The SEO Framework - Version 2.8.2

Version Description

In the 2.8.0 update WordPress 4.3 and PHP 5.2 support have been dropped for better code quality.

Download this release

Release Info

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

Code changes from version 2.7.3 to 2.8.2

Files changed (69) hide show
  1. autodescription.php +66 -54
  2. inc/classes/admin-init.class.php +142 -83
  3. inc/classes/{adminpages.class.php → admin-pages.class.php} +178 -169
  4. inc/classes/{transients.class.php → cache.class.php} +422 -137
  5. inc/classes/compat.class.php +69 -70
  6. inc/classes/core.class.php +310 -133
  7. inc/classes/debug.class.php +417 -219
  8. inc/classes/deprecated.class.php +505 -0
  9. inc/classes/detect.class.php +112 -191
  10. inc/classes/{doingitright.class.php → doing-it-right.class.php} +169 -162
  11. inc/classes/feed.class.php +22 -34
  12. inc/classes/generate-description.class.php +264 -209
  13. inc/classes/generate-image.class.php +244 -105
  14. inc/classes/generate-ldjson.class.php +110 -79
  15. inc/classes/generate-title.class.php +207 -208
  16. inc/classes/generate-url.class.php +301 -623
  17. inc/classes/generate.class.php +122 -37
  18. inc/classes/init.class.php +389 -116
  19. inc/classes/inpost.class.php +72 -444
  20. inc/classes/load.class.php +263 -0
  21. inc/classes/metaboxes.class.php +157 -167
  22. inc/classes/{postdata.class.php → post-data.class.php} +184 -93
  23. inc/classes/query.class.php +93 -114
  24. inc/classes/render.class.php +133 -125
  25. inc/classes/sanitize.class.php +411 -251
  26. inc/classes/search.class.php +0 -183
  27. inc/classes/{siteoptions.class.php → site-options.class.php} +110 -71
  28. inc/classes/sitemaps.class.php +402 -291
  29. inc/classes/{termdata.class.php → term-data.class.php} +79 -108
  30. inc/{functions/compat.php → compat/php-mbstring.php} +4 -152
  31. inc/compat/plugin-bbpress.php +35 -0
  32. inc/compat/plugin-donncha-dm.php +65 -0
  33. inc/compat/plugin-qtranslatex.php +100 -0
  34. inc/compat/plugin-ultimatemember.php +47 -0
  35. inc/compat/plugin-wpml.php +203 -0
  36. inc/compat/plugin-wpmudev-dm.php +122 -0
  37. inc/compat/theme-genesis.php +71 -0
  38. inc/deprecated/deprecated.class.php +0 -905
  39. inc/{deprecated → functions}/deprecated.php +2 -2
  40. inc/functions/optionsapi.php +17 -4
  41. inc/functions/plugin-test-server.php +113 -0
  42. inc/functions/upgrade.php +12 -14
  43. inc/interfaces/debug.interface.php +106 -0
  44. inc/views/debug/output.php +42 -19
  45. inc/views/inpost/index.php +8 -0
  46. inc/views/inpost/seo-settings.php +423 -0
  47. inc/views/metaboxes/description-metabox.php +16 -16
  48. inc/views/metaboxes/general-metabox.php +192 -0
  49. inc/views/metaboxes/homepage-metabox.php +101 -72
  50. inc/views/metaboxes/knowledge-metabox.php +0 -230
  51. inc/views/metaboxes/schema-metabox.php +256 -57
  52. inc/views/metaboxes/sitemaps-metabox.php +114 -47
  53. inc/views/metaboxes/social-metabox.php +84 -80
  54. inc/views/metaboxes/title-metabox.php +21 -21
  55. inc/views/sitemap/index.php +6 -0
  56. inc/views/sitemap/xsl-stylesheet.php +249 -0
  57. language/autodescription.pot +750 -464
  58. lib/css/autodescription-rtl.min.css +0 -1
  59. lib/css/autodescription.min.css +0 -1
  60. lib/css/{autodescription-rtl.css → tsf-rtl.css} +66 -9
  61. lib/css/tsf-rtl.min.css +1 -0
  62. lib/css/{autodescription.css → tsf.css} +68 -11
  63. lib/css/tsf.min.css +1 -0
  64. lib/js/autodescription.js +0 -1408
  65. lib/js/autodescription.min.js +0 -25
  66. lib/js/tsf.externs.js +277 -0
  67. lib/js/tsf.externs.protected.js +412 -0
  68. lib/js/tsf.js +2011 -0
  69. lib/js/tsf.min.js +17 -0
autodescription.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
  /**
3
  * Plugin Name: The SEO Framework
4
- * Plugin URI: https://wordpress.org/plugins/autodescription/
5
  * Description: An automated, advanced, accessible, unbranded and extremely fast SEO solution for any WordPress website.
6
- * Version: 2.7.3
7
  * Author: Sybre Waaijer
8
  * Author URI: https://cyberwire.nl/
9
  * License: GPLv3
@@ -33,11 +33,11 @@ defined( 'ABSPATH' ) or die;
33
  //* Debug. Not to be used on production websites as it dumps and/or disables all kinds of stuff everywhere.
34
  //add_action( 'plugins_loaded', function() { if ( is_super_admin() ) {
35
  //if ( is_admin() ) {
36
- // define( 'THE_SEO_FRAMEWORK_DEBUG', true );
37
- // define( 'THE_SEO_FRAMEWORK_DEBUG_HIDDEN', true );
38
- // define( 'THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS', true );
39
- // update_option( 'the_seo_framework_upgraded_db_version', '0' );
40
- // add_filter( 'the_seo_framework_use_object_cache', '__return_false' );
41
  //}
42
  //}},0);
43
 
@@ -46,13 +46,13 @@ defined( 'ABSPATH' ) or die;
46
  * Not many caching plugins use CDN in dashboard. What a shame. Firefox does cache.
47
  * @since 1.0.0
48
  */
49
- define( 'THE_SEO_FRAMEWORK_VERSION', '2.7.3' );
50
 
51
  /**
52
- * Plugin Database version for lightweight version comparing.
53
  * @since 2.7.0
54
  */
55
- define( 'THE_SEO_FRAMEWORK_DB_VERSION', '2701' );
56
 
57
  /**
58
  * Plugin options filter.
@@ -108,74 +108,86 @@ define( 'THE_SEO_FRAMEWORK_PLUGIN_BASE_FILE', __FILE__ );
108
  * The plugin views map absolute path.
109
  * @since 2.7.0
110
  */
111
- define( 'THE_SEO_FRAMEWORK_DIR_PATH_VIEWS', THE_SEO_FRAMEWORK_DIR_PATH . 'inc/views/' );
112
 
113
  /**
114
  * The plugin class map absolute path.
115
  * @since 2.2.9
116
  */
117
- define( 'THE_SEO_FRAMEWORK_DIR_PATH_CLASS', THE_SEO_FRAMEWORK_DIR_PATH . 'inc/classes/' );
118
 
119
  /**
120
- * The plugin function map absolute path.
121
- * @since 2.2.9
122
  */
123
- define( 'THE_SEO_FRAMEWORK_DIR_PATH_FUNCT', THE_SEO_FRAMEWORK_DIR_PATH . 'inc/functions/' );
124
 
125
- add_action( 'plugins_loaded', 'the_seo_framework_locale_init', 10 );
126
  /**
127
- * Plugin locale 'autodescription'
128
- * File located in plugin folder autodescription/language/
129
- * @since 1.0.0
130
  */
131
- function the_seo_framework_locale_init() {
132
- load_plugin_textdomain( 'autodescription', false, basename( dirname( __FILE__ ) ) . '/language/' );
133
- }
134
 
135
  /**
136
- * Load plugin files.
137
- * @since 1.0.0
138
- * @uses THE_SEO_FRAMEWORK_DIR_PATH
139
  */
140
- require_once( THE_SEO_FRAMEWORK_DIR_PATH . 'load.class.php' );
141
 
142
- //* Load deprecated functions.
143
- require_once( THE_SEO_FRAMEWORK_DIR_PATH . 'inc/deprecated/deprecated.php' );
144
-
145
- register_activation_hook( THE_SEO_FRAMEWORK_PLUGIN_BASE_FILE, 'the_seo_framework_flush_rewrite_rules_activation' );
146
  /**
147
- * Add and Flush rewrite rules on plugin activation.
148
  *
149
- * @since 2.6.6
150
- * @since 2.7.1: 1. Now no longer reinitializes global $wp_rewrite.
151
- * 2. Now always listens to the preconditions of the sitemap addition.
152
- * 3. Now flushes the rules on shutdown.
153
- * @access private
154
  */
155
- function the_seo_framework_flush_rewrite_rules_activation() {
156
-
157
- $the_seo_framework = the_seo_framework();
158
-
159
- if ( isset( $the_seo_framework ) ) {
160
- $the_seo_framework->rewrite_rule_sitemap();
161
- add_action( 'shutdown', 'flush_rewrite_rules' );
162
  }
163
  }
164
 
165
- register_deactivation_hook( THE_SEO_FRAMEWORK_PLUGIN_BASE_FILE, 'the_seo_framework_flush_rewrite_rules_deactivation' );
166
  /**
167
- * Flush rewrite rules on plugin deactivation.
168
  *
169
- * @since 2.6.6
170
- * @since 2.7.1: 1. Now no longer reinitializes global $wp_rewrite.
171
- * 2. Now flushes the rules on shutdown.
172
- * @access private
173
- * @global object $wp_rewrite
174
  */
175
- function the_seo_framework_flush_rewrite_rules_deactivation() {
176
- global $wp_rewrite;
177
 
178
- unset( $wp_rewrite->extra_rules_top['sitemap\.xml$'] );
 
179
 
180
- add_action( 'shutdown', 'flush_rewrite_rules' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  }
1
  <?php
2
  /**
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 any WordPress website.
6
+ * Version: 2.8.2
7
  * Author: Sybre Waaijer
8
  * Author URI: https://cyberwire.nl/
9
  * License: GPLv3
33
  //* Debug. Not to be used on production websites as it dumps and/or disables all kinds of stuff everywhere.
34
  //add_action( 'plugins_loaded', function() { if ( is_super_admin() ) {
35
  //if ( is_admin() ) {
36
+ //define( 'THE_SEO_FRAMEWORK_DEBUG', true );
37
+ //define( 'THE_SEO_FRAMEWORK_DEBUG_HIDDEN', true );
38
+ //define( 'THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS', true );
39
+ //update_option( 'the_seo_framework_upgraded_db_version', '0' );
40
+ //add_filter( 'the_seo_framework_use_object_cache', '__return_false' );
41
  //}
42
  //}},0);
43
 
46
  * Not many caching plugins use CDN in dashboard. What a shame. Firefox does cache.
47
  * @since 1.0.0
48
  */
49
+ define( 'THE_SEO_FRAMEWORK_VERSION', '2.8.2' );
50
 
51
  /**
52
+ * Plugin Database version for lightweight version upgrade comparing.
53
  * @since 2.7.0
54
  */
55
+ define( 'THE_SEO_FRAMEWORK_DB_VERSION', '2804' );
56
 
57
  /**
58
  * Plugin options filter.
108
  * The plugin views map absolute path.
109
  * @since 2.7.0
110
  */
111
+ define( 'THE_SEO_FRAMEWORK_DIR_PATH_VIEWS', THE_SEO_FRAMEWORK_DIR_PATH . 'inc' . DIRECTORY_SEPARATOR . 'views' . DIRECTORY_SEPARATOR );
112
 
113
  /**
114
  * The plugin class map absolute path.
115
  * @since 2.2.9
116
  */
117
+ define( 'THE_SEO_FRAMEWORK_DIR_PATH_CLASS', THE_SEO_FRAMEWORK_DIR_PATH . 'inc' . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR );
118
 
119
  /**
120
+ * The plugin interface map absolute path.
121
+ * @since 2.8.0
122
  */
123
+ define( 'THE_SEO_FRAMEWORK_DIR_PATH_INTERFACE', THE_SEO_FRAMEWORK_DIR_PATH . 'inc' . DIRECTORY_SEPARATOR . 'interfaces' . DIRECTORY_SEPARATOR );
124
 
 
125
  /**
126
+ * The plugin function map absolute path.
127
+ * @since 2.2.9
 
128
  */
129
+ define( 'THE_SEO_FRAMEWORK_DIR_PATH_FUNCT', THE_SEO_FRAMEWORK_DIR_PATH . 'inc' . DIRECTORY_SEPARATOR . 'functions' . DIRECTORY_SEPARATOR );
 
 
130
 
131
  /**
132
+ * The plugin function map absolute path.
133
+ * @since 2.8.0
 
134
  */
135
+ define( 'THE_SEO_FRAMEWORK_DIR_PATH_COMPAT', THE_SEO_FRAMEWORK_DIR_PATH . 'inc' . DIRECTORY_SEPARATOR . 'compat' . DIRECTORY_SEPARATOR );
136
 
137
+ the_seo_framework_pre_load();
 
 
 
138
  /**
139
+ * Determines whether we can "just" load the plugin, or require verification beforehand.
140
  *
141
+ * @since 2.8.0
 
 
 
 
142
  */
143
+ function the_seo_framework_pre_load() {
144
+ if ( get_site_option( 'the_seo_framework_tested_upgrade_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION ) {
145
+ the_seo_framework_load_base_files();
146
+ } else {
147
+ the_seo_framework_test_server();
 
 
148
  }
149
  }
150
 
 
151
  /**
152
+ * Tests plugin upgrade.
153
  *
154
+ * @since 2.8.0
 
 
 
 
155
  */
156
+ function the_seo_framework_test_server() {
 
157
 
158
+ //* Load on init action (manual FTP upload) or after plugin has been upgraded.
159
+ require_once( THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'plugin-test-server.php' );
160
 
161
+ if ( get_site_option( 'the_seo_framework_tested_upgrade_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION )
162
+ the_seo_framework_load_base_files();
163
+ }
164
+
165
+ /**
166
+ * Loads plugin base files.
167
+ *
168
+ * @since 2.8.0
169
+ */
170
+ function the_seo_framework_load_base_files() {
171
+ /**
172
+ * Load plugin files.
173
+ *
174
+ * @since 1.0.0
175
+ * @uses THE_SEO_FRAMEWORK_DIR_PATH
176
+ */
177
+ require_once( THE_SEO_FRAMEWORK_DIR_PATH . 'load.php' );
178
+
179
+ /**
180
+ * Load deprecated functions.
181
+ *
182
+ * @since 2.7.0
183
+ * @uses THE_SEO_FRAMEWORK_DIR_PATH_FUNCT
184
+ */
185
+ require_once( THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'deprecated.php' );
186
+
187
+ /**
188
+ * Load API files.
189
+ * @since 2.1.6
190
+ * @uses THE_SEO_FRAMEWORK_DIR_PATH_FUNCT
191
+ */
192
+ require_once( THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'optionsapi.php' );
193
  }
inc/classes/admin-init.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,17 +23,15 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Admin_Init
23
  *
24
  * Initializes the plugin for the wp-admin screens.
25
  * Enqueues CSS and Javascript.
26
  *
27
- * @since 2.1.6
28
  */
29
- class AutoDescription_Admin_Init extends AutoDescription_Init {
30
 
31
  /**
32
  * The page base file.
@@ -41,44 +46,27 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
41
  * JavaScript name identifier to be used with enqueuing.
42
  *
43
  * @since 2.5.2.2
 
44
  *
45
  * @var string JavaScript name identifier.
46
  */
47
- public $js_name = 'autodescription';
48
 
49
  /**
50
  * CSS script name identifier to be used with enqueuing.
51
  *
52
  * @since 2.6.0
 
53
  *
54
  * @var string CSS name identifier.
55
  */
56
- public $css_name = 'autodescription';
57
-
58
- /**
59
- * Unserializing instances of this class is forbidden.
60
- */
61
- private function __wakeup() { }
62
-
63
- /**
64
- * Handle unapproachable invoked methods.
65
- */
66
- public function __call( $name, $arguments ) {
67
- parent::__call( $name, $arguments );
68
- }
69
 
70
  /**
71
  * Constructor. Loads parent constructor, registers script names and adds actions.
72
  */
73
- public function __construct() {
74
  parent::__construct();
75
-
76
- //* Enqueues admin scripts.
77
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ), 0, 1 );
78
-
79
- //* Admin AJAX for counter options.
80
- add_action( 'wp_ajax_the_seo_framework_update_counter', array( $this, 'wp_ajax_update_counter_type' ) );
81
-
82
  }
83
 
84
  /**
@@ -98,6 +86,10 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
98
  'term.php',
99
  );
100
 
 
 
 
 
101
  /**
102
  * Check hook first.
103
  * @since 2.3.9
@@ -116,6 +108,8 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
116
  * Registers admin scripts and styles.
117
  *
118
  * @since 2.6.0
 
 
119
  */
120
  public function init_admin_scripts( $direct = false ) {
121
 
@@ -123,10 +117,9 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
123
  $this->enqueue_admin_css( $this->page_base_file );
124
  $this->enqueue_admin_javascript( $this->page_base_file );
125
  } else {
126
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_css' ), 1 );
127
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_javascript' ), 1 );
128
  }
129
-
130
  }
131
 
132
  /**
@@ -142,18 +135,24 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
142
  * Put hook and js name in class vars.
143
  * @since 2.5.2.2
144
  */
145
- $this->page_base_file = $this->page_base_file ? $this->page_base_file : $hook;
146
 
147
  //* Register the script.
148
- $this->register_admin_javascript();
 
 
 
149
 
150
- wp_enqueue_script( $this->js_name );
 
 
 
151
 
152
  /**
153
  * Localize JavaScript.
154
  * @since 2.5.2.2
155
  */
156
- add_action( 'admin_footer', array( $this, 'localize_admin_javascript' ) );
157
 
158
  }
159
 
@@ -164,7 +163,7 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
164
  * @staticvar bool $registered : Prevents Re-registering of the style.
165
  * @access private
166
  */
167
- public function register_admin_javascript() {
168
 
169
  static $registered = null;
170
 
@@ -173,7 +172,7 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
173
 
174
  $suffix = $this->script_debug ? '' : '.min';
175
 
176
- wp_register_script( $this->js_name, THE_SEO_FRAMEWORK_DIR_URL . "lib/js/autodescription{$suffix}.js", array( 'jquery' ), THE_SEO_FRAMEWORK_VERSION, true );
177
 
178
  $registered = true;
179
 
@@ -186,7 +185,7 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
186
  * @staticvar bool $localized : Prevents Re-registering of the l10n.
187
  * @access private
188
  */
189
- public function localize_admin_javascript() {
190
 
191
  static $localized = null;
192
 
@@ -195,7 +194,7 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
195
 
196
  $strings = $this->get_javascript_l10n();
197
 
198
- wp_localize_script( $this->js_name, 'autodescriptionL10n', $strings );
199
 
200
  $localized = true;
201
 
@@ -207,16 +206,15 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
207
  * @since 2.6.0
208
  * @staticvar array $strings : The l10n strings.
209
  * @since 2.7.0 Added AJAX nonce: 'autodescription-ajax-nonce'
 
 
 
 
210
  *
211
  * @return array $strings The l10n strings.
212
  */
213
  protected function get_javascript_l10n() {
214
 
215
- static $strings = null;
216
-
217
- if ( isset( $strings ) )
218
- return $strings;
219
-
220
  $blog_name = $this->get_blogname();
221
  $description = $this->get_blogdescription();
222
  $title = '';
@@ -237,7 +235,6 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
237
  $title_separator = $this->get_separator( 'title' );
238
  $description_separator = $this->get_separator( 'description' );
239
 
240
- $isrtl = (bool) is_rtl();
241
  $ishome = false;
242
 
243
  if ( isset( $this->page_base_file ) && $this->page_base_file ) {
@@ -273,16 +270,14 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
273
  }
274
  } elseif ( $this->is_archive() ) {
275
  //* Category or Tag.
276
- global $current_screen;
277
-
278
- if ( isset( $current_screen->taxonomy ) ) {
279
 
280
  $term_id = $this->get_admin_term_id();
281
 
282
  if ( $term_id ) {
283
  $generated_doctitle_args = array(
284
  'term_id' => $term_id,
285
- 'taxonomy' => $current_screen->taxonomy,
286
  'notagline' => true,
287
  'get_custom_field' => false,
288
  );
@@ -301,47 +296,85 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
301
  // We're on our SEO settings pages.
302
  if ( $this->has_page_on_front() ) {
303
  // Home is a page.
304
- $inpost_title = $this->get_custom_field( '_genesis_title', get_option( 'page_on_front' ) );
305
  } else {
306
  // Home is a blog.
307
  $inpost_title = '';
308
  }
309
- $title = $inpost_title ? $inpost_title : $blog_name;
310
- $additions = $home_tagline ? $home_tagline : $description;
311
  }
312
 
313
- $nonce = wp_create_nonce( 'autodescription-ajax-nonce' );
314
-
315
- return $strings = array(
316
- 'saveAlert' => esc_html__( 'The changes you made will be lost if you navigate away from this page.', 'autodescription' ),
317
- 'confirmReset' => esc_html__( 'Are you sure you want to reset all SEO settings to their defaults?', 'autodescription' ),
318
- 'siteTitle' => esc_html( $title ),
319
- 'titleAdditions' => esc_html( $additions ),
320
- 'blogDescription' => esc_html( $description ),
321
- 'titleTagline' => $tagline,
322
- 'titleSeparator' => esc_html( $title_separator ),
323
- 'titleLocation' => esc_html( $title_location ),
324
- 'descriptionSeparator' => esc_html( $description_separator ),
325
- 'isRTL' => $isrtl,
326
- 'isHome' => $ishome,
327
- 'counterType' => absint( $counter_type ),
328
- 'good' => esc_html( $good ),
329
- 'okay' => esc_html( $okay ),
330
- 'bad' => esc_html( $bad ),
331
- 'unknown' => esc_html( $unknown ),
332
  'nonce' => $nonce,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  );
334
  }
335
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  /**
337
  * CSS for the AutoDescription Bar
338
  *
339
  * @since 2.1.9
340
  *
341
  * @param $hook the current page
342
- *
343
- * @todo get_network_option
344
- * @priority low 3.0.0
345
  */
346
  public function enqueue_admin_css( $hook ) {
347
 
@@ -349,12 +382,16 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
349
  * Put hook and js name in class vars.
350
  * @since 2.5.2.2
351
  */
352
- $this->page_base_file = $this->page_base_file ? $this->page_base_file : $hook;
353
 
354
  //* Register the script.
355
  $this->register_admin_css();
356
 
357
- wp_enqueue_style( $this->css_name );
 
 
 
 
358
 
359
  }
360
 
@@ -372,12 +409,31 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
372
  if ( isset( $registered ) )
373
  return;
374
 
375
- $rtl = is_rtl() ? '-rtl' : '';
376
  $suffix = $this->script_debug ? '' : '.min';
377
  $registered = true;
378
 
379
- wp_register_style( $this->css_name, THE_SEO_FRAMEWORK_DIR_URL . "lib/css/autodescription{$rtl}{$suffix}.css", array(), THE_SEO_FRAMEWORK_VERSION, 'all' );
 
 
 
 
 
 
 
 
 
 
 
 
380
 
 
 
 
 
 
 
 
381
  }
382
 
383
  /**
@@ -396,16 +452,16 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
396
  if ( empty( $page ) )
397
  return;
398
 
399
- $url = html_entity_decode( menu_page_url( $page, 0 ) );
400
 
401
  foreach ( $query_args as $key => $value ) {
402
  if ( empty( $key ) || empty( $value ) )
403
  unset( $query_args[ $key ] );
404
  }
405
 
406
- $url = add_query_arg( $query_args, $url );
407
 
408
- wp_safe_redirect( esc_url_raw( $url ), 302 );
409
  exit;
410
  }
411
 
@@ -420,17 +476,17 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
420
  if ( $this->is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
421
 
422
  //* If current user isn't allowed to edit posts, don't do anything and kill PHP.
423
- if ( ! current_user_can( 'publish_posts' ) )
424
  exit;
425
 
426
- check_ajax_referer( 'autodescription-ajax-nonce', 'nonce' );
427
 
428
  /**
429
  * Count up, reset to 0 if needed. We have 4 options: 0, 1, 2, 3
430
  * $_POST['val'] already contains updated number.
431
  */
432
  $value = isset( $_POST['val'] ) ? intval( $_POST['val'] ) : $this->get_user_option( 0, 'counter_type', 3 ) + 1;
433
- $value = absint( $value );
434
 
435
  if ( $value > 3 )
436
  $value = 0;
@@ -443,6 +499,9 @@ class AutoDescription_Admin_Init extends AutoDescription_Init {
443
  'value' => $value,
444
  );
445
 
 
 
 
446
  //* Encode and echo results. Requires JSON decode within JS.
447
  echo json_encode( $results );
448
 
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Admin_Init
28
  *
29
  * Initializes the plugin for the wp-admin screens.
30
  * Enqueues CSS and Javascript.
31
  *
32
+ * @since 2.8.0
33
  */
34
+ class Admin_Init extends Init {
35
 
36
  /**
37
  * The page base file.
46
  * JavaScript name identifier to be used with enqueuing.
47
  *
48
  * @since 2.5.2.2
49
+ * @since 2.8.0 Renamed
50
  *
51
  * @var string JavaScript name identifier.
52
  */
53
+ public $js_name = 'tsf';
54
 
55
  /**
56
  * CSS script name identifier to be used with enqueuing.
57
  *
58
  * @since 2.6.0
59
+ * @since 2.8.0 Renamed
60
  *
61
  * @var string CSS name identifier.
62
  */
63
+ public $css_name = 'tsf';
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
  /**
66
  * Constructor. Loads parent constructor, registers script names and adds actions.
67
  */
68
+ protected function __construct() {
69
  parent::__construct();
 
 
 
 
 
 
 
70
  }
71
 
72
  /**
86
  'term.php',
87
  );
88
 
89
+ if ( ! $this->is_option_checked( 'display_seo_bar_tables' ) ) {
90
+ $enqueue_hooks = array_diff( $enqueue_hooks, array( 'edit.php', 'edit-tags.php' ) );
91
+ }
92
+
93
  /**
94
  * Check hook first.
95
  * @since 2.3.9
108
  * Registers admin scripts and styles.
109
  *
110
  * @since 2.6.0
111
+ *
112
+ * @param bool $direct Whether to directly include the files, or let the action handler do it.
113
  */
114
  public function init_admin_scripts( $direct = false ) {
115
 
117
  $this->enqueue_admin_css( $this->page_base_file );
118
  $this->enqueue_admin_javascript( $this->page_base_file );
119
  } else {
120
+ \add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_css' ), 1 );
121
+ \add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_javascript' ), 1 );
122
  }
 
123
  }
124
 
125
  /**
135
  * Put hook and js name in class vars.
136
  * @since 2.5.2.2
137
  */
138
+ $this->page_base_file = $this->page_base_file ?: $hook;
139
 
140
  //* Register the script.
141
+ $this->_register_admin_javascript();
142
+
143
+ if ( $this->is_post_edit() || $this->is_seo_settings_page() )
144
+ \wp_enqueue_media();
145
 
146
+ if ( $this->is_seo_settings_page() )
147
+ \wp_enqueue_script( 'wp-color-picker' );
148
+
149
+ \wp_enqueue_script( $this->js_name );
150
 
151
  /**
152
  * Localize JavaScript.
153
  * @since 2.5.2.2
154
  */
155
+ \add_action( 'admin_footer', array( $this, '_localize_admin_javascript' ) );
156
 
157
  }
158
 
163
  * @staticvar bool $registered : Prevents Re-registering of the style.
164
  * @access private
165
  */
166
+ public function _register_admin_javascript() {
167
 
168
  static $registered = null;
169
 
172
 
173
  $suffix = $this->script_debug ? '' : '.min';
174
 
175
+ \wp_register_script( $this->js_name, THE_SEO_FRAMEWORK_DIR_URL . "lib/js/{$this->js_name}{$suffix}.js", array( 'jquery' ), THE_SEO_FRAMEWORK_VERSION, true );
176
 
177
  $registered = true;
178
 
185
  * @staticvar bool $localized : Prevents Re-registering of the l10n.
186
  * @access private
187
  */
188
+ public function _localize_admin_javascript() {
189
 
190
  static $localized = null;
191
 
194
 
195
  $strings = $this->get_javascript_l10n();
196
 
197
+ \wp_localize_script( $this->js_name, "{$this->js_name}L10n", $strings );
198
 
199
  $localized = true;
200
 
206
  * @since 2.6.0
207
  * @staticvar array $strings : The l10n strings.
208
  * @since 2.7.0 Added AJAX nonce: 'autodescription-ajax-nonce'
209
+ * @since 2.8.0 1. Added input detection: 'hasInput'
210
+ * 2. Reworked output.
211
+ * 3. Removed unused caching.
212
+ * 4. Added dynamic output control.
213
  *
214
  * @return array $strings The l10n strings.
215
  */
216
  protected function get_javascript_l10n() {
217
 
 
 
 
 
 
218
  $blog_name = $this->get_blogname();
219
  $description = $this->get_blogdescription();
220
  $title = '';
235
  $title_separator = $this->get_separator( 'title' );
236
  $description_separator = $this->get_separator( 'description' );
237
 
 
238
  $ishome = false;
239
 
240
  if ( isset( $this->page_base_file ) && $this->page_base_file ) {
270
  }
271
  } elseif ( $this->is_archive() ) {
272
  //* Category or Tag.
273
+ if ( isset( $GLOBALS['current_screen']->taxonomy ) ) {
 
 
274
 
275
  $term_id = $this->get_admin_term_id();
276
 
277
  if ( $term_id ) {
278
  $generated_doctitle_args = array(
279
  'term_id' => $term_id,
280
+ 'taxonomy' => $GLOBALS['current_screen']->taxonomy,
281
  'notagline' => true,
282
  'get_custom_field' => false,
283
  );
296
  // We're on our SEO settings pages.
297
  if ( $this->has_page_on_front() ) {
298
  // Home is a page.
299
+ $inpost_title = $this->get_custom_field( '_genesis_title', \get_option( 'page_on_front' ) );
300
  } else {
301
  // Home is a blog.
302
  $inpost_title = '';
303
  }
304
+ $title = $inpost_title ?: $blog_name;
305
+ $additions = $home_tagline ?: $description;
306
  }
307
 
308
+ $nonce = \wp_create_nonce( 'autodescription-ajax-nonce' );
309
+
310
+ return array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  'nonce' => $nonce,
312
+ 'i18n' => array(
313
+ 'saveAlert' => \esc_html__( 'The changes you made will be lost if you navigate away from this page.', 'autodescription' ),
314
+ 'confirmReset' => \esc_html__( 'Are you sure you want to reset all SEO settings to their defaults?', 'autodescription' ),
315
+ 'good' => \esc_html( $good ),
316
+ 'okay' => \esc_html( $okay ),
317
+ 'bad' => \esc_html( $bad ),
318
+ 'unknown' => \esc_html( $unknown ),
319
+ ),
320
+ 'states' => array(
321
+ 'isRTL' => (bool) \is_rtl(),
322
+ 'isHome' => $ishome,
323
+ 'hasInput' => $this->is_term_edit() || $this->is_post_edit() || $this->is_seo_settings_page(),
324
+ 'counterType' => \absint( $counter_type ),
325
+ 'titleTagline' => $tagline,
326
+ ),
327
+ 'params' => array(
328
+ 'siteTitle' => \esc_html( \wp_kses_decode_entities( $title ) ),
329
+ 'titleAdditions' => \esc_html( \wp_kses_decode_entities( $additions ) ),
330
+ 'blogDescription' => \esc_html( \wp_kses_decode_entities( $description ) ),
331
+ 'titleSeparator' => \esc_html( $title_separator ),
332
+ 'descriptionSeparator' => \esc_html( $description_separator ),
333
+ 'titleLocation' => \esc_html( $title_location ),
334
+ ),
335
+ 'other' => $this->additional_js_l10n( null, array(), true ),
336
  );
337
  }
338
 
339
+ /**
340
+ * Maintains and Returns additional JS l10n.
341
+ *
342
+ * They are put under object 'tsfemL10n.other.$key.[ $val ]'.
343
+ *
344
+ * @since 2.8.0
345
+ * @staticvar object $strings The cached strings object.
346
+ *
347
+ * @param null|string $key The object key. Requires escape.
348
+ * @param null|array $val The object val. Requires escape.
349
+ * @param bool $get Whether to return the cached strings.
350
+ * @param bool $escape Whether to escape the input.
351
+ * @return object Early when $get is true
352
+ */
353
+ public function additional_js_l10n( $key = null, array $val = array(), $get = false, $escape = true ) {
354
+
355
+ static $strings = null;
356
+
357
+ if ( null === $strings )
358
+ $strings = new \stdClass();
359
+
360
+ if ( $get )
361
+ return $strings;
362
+
363
+ if ( $escape ) {
364
+ $key = \esc_attr( $key );
365
+ $val = \map_deep( $val, 'esc_attr' );
366
+ }
367
+
368
+ if ( $key )
369
+ $strings->$key = $val;
370
+ }
371
+
372
  /**
373
  * CSS for the AutoDescription Bar
374
  *
375
  * @since 2.1.9
376
  *
377
  * @param $hook the current page
 
 
 
378
  */
379
  public function enqueue_admin_css( $hook ) {
380
 
382
  * Put hook and js name in class vars.
383
  * @since 2.5.2.2
384
  */
385
+ $this->page_base_file = $this->page_base_file ?: $hook;
386
 
387
  //* Register the script.
388
  $this->register_admin_css();
389
 
390
+ if ( $this->is_seo_settings_page() ) {
391
+ \wp_enqueue_style( 'wp-color-picker' );
392
+ }
393
+
394
+ \wp_enqueue_style( $this->css_name );
395
 
396
  }
397
 
409
  if ( isset( $registered ) )
410
  return;
411
 
412
+ $rtl = \is_rtl() ? '-rtl' : '';
413
  $suffix = $this->script_debug ? '' : '.min';
414
  $registered = true;
415
 
416
+ \wp_register_style( $this->css_name, THE_SEO_FRAMEWORK_DIR_URL . "lib/css/{$this->css_name}{$rtl}{$suffix}.css", array(), THE_SEO_FRAMEWORK_VERSION, 'all' );
417
+
418
+ }
419
+
420
+ /**
421
+ * Adds removable query args to WordPress query arg handler.
422
+ *
423
+ * @since 2.8.0
424
+ *
425
+ * @param array $removable_query_args
426
+ * @return array $removable_query_args The adjusted removable query args.
427
+ */
428
+ public function add_removable_query_args( $removable_query_args = array() ) {
429
 
430
+ if ( ! is_array( $removable_query_args ) )
431
+ return $removable_query_args;
432
+
433
+ $removable_query_args[] = 'tsf-settings-reset';
434
+ $removable_query_args[] = 'tsf-settings-updated';
435
+
436
+ return $removable_query_args;
437
  }
438
 
439
  /**
452
  if ( empty( $page ) )
453
  return;
454
 
455
+ $url = html_entity_decode( \menu_page_url( $page, false ) );
456
 
457
  foreach ( $query_args as $key => $value ) {
458
  if ( empty( $key ) || empty( $value ) )
459
  unset( $query_args[ $key ] );
460
  }
461
 
462
+ $url = \add_query_arg( $query_args, $url );
463
 
464
+ \wp_safe_redirect( \esc_url_raw( $url ), 302 );
465
  exit;
466
  }
467
 
476
  if ( $this->is_admin() && defined( 'DOING_AJAX' ) && DOING_AJAX ) {
477
 
478
  //* If current user isn't allowed to edit posts, don't do anything and kill PHP.
479
+ if ( ! \current_user_can( 'publish_posts' ) )
480
  exit;
481
 
482
+ \check_ajax_referer( 'autodescription-ajax-nonce', 'nonce' );
483
 
484
  /**
485
  * Count up, reset to 0 if needed. We have 4 options: 0, 1, 2, 3
486
  * $_POST['val'] already contains updated number.
487
  */
488
  $value = isset( $_POST['val'] ) ? intval( $_POST['val'] ) : $this->get_user_option( 0, 'counter_type', 3 ) + 1;
489
+ $value = \absint( $value );
490
 
491
  if ( $value > 3 )
492
  $value = 0;
499
  'value' => $value,
500
  );
501
 
502
+ //* Remove output buffer.
503
+ $this->clean_reponse_header();
504
+
505
  //* Encode and echo results. Requires JSON decode within JS.
506
  echo json_encode( $results );
507
 
inc/classes/{adminpages.class.php → admin-pages.class.php} RENAMED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,16 +23,14 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Siteoptions
23
  *
24
- * Renders admin pages content for AutoDescription.
25
  *
26
- * @since 2.2.2
27
  */
28
- class AutoDescription_Adminpages extends AutoDescription_Inpost {
29
 
30
  /**
31
  * Page Defaults.
@@ -54,57 +59,11 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
54
  */
55
  public $load_options;
56
 
57
- /**
58
- * Unserializing instances of this class is forbidden.
59
- */
60
- private function __wakeup() { }
61
-
62
- /**
63
- * Handle unapproachable invoked methods.
64
- */
65
- public function __call( $name, $arguments ) {
66
- parent::__call( $name, $arguments );
67
- }
68
-
69
  /**
70
  * Constructor. Loads parent constructor, does actions and sets up variables.
71
  */
72
- public function __construct() {
73
  parent::__construct();
74
-
75
- /**
76
- * Applies filters the_seo_framework_load_options : Boolean Allows the options page to be removed
77
- * @since 2.2.2
78
- */
79
- $this->load_options = (bool) apply_filters( 'the_seo_framework_load_options', true );
80
-
81
- add_action( 'init', array( $this, 'init_admin_actions' ), 0 );
82
- }
83
-
84
- /**
85
- * Initializes Admin Menu actions.
86
- *
87
- * @since 2.7.0
88
- */
89
- public function init_admin_actions() {
90
-
91
- if ( $this->load_options && $this->is_admin() ) {
92
- // Enqueue i18n defaults.
93
- add_action( 'admin_init', array( $this, 'enqueue_page_defaults' ), 1 );
94
-
95
- // Add menu links and register $this->seo_settings_page_hook
96
- add_action( 'admin_menu', array( $this, 'add_menu_link' ) );
97
-
98
- //* Load the page content
99
- add_action( 'admin_init', array( $this, 'settings_init' ) );
100
-
101
- // Set up notices
102
- add_action( 'admin_notices', array( $this, 'notices' ) );
103
-
104
- // Load nessecary assets
105
- add_action( 'admin_init', array( $this, 'load_assets' ) );
106
- }
107
-
108
  }
109
 
110
  /**
@@ -117,18 +76,17 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
117
  */
118
  public function enqueue_page_defaults() {
119
 
120
- $this->page_defaults = (array) apply_filters(
121
  'the_seo_framework_admin_page_defaults',
122
  array(
123
- 'save_button_text' => esc_html__( 'Save Settings', 'autodescription' ),
124
- 'reset_button_text' => esc_html__( 'Reset Settings', 'autodescription' ),
125
- 'saved_notice_text' => esc_html__( 'Settings are saved.', 'autodescription' ),
126
- 'reset_notice_text' => esc_html__( 'Settings are reset.', 'autodescription' ),
127
- 'error_notice_text' => esc_html__( 'Error saving settings.', 'autodescription' ),
128
- 'plugin_update_text' => esc_html__( 'New SEO Settings have been updated.', 'autodescription' ),
129
  )
130
  );
131
-
132
  }
133
 
134
  /**
@@ -141,8 +99,8 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
141
  public function add_menu_link() {
142
 
143
  $menu = array(
144
- 'page_title' => esc_html__( 'SEO Settings', 'autodescription' ),
145
- 'menu_title' => esc_html__( 'SEO', 'autodescription' ),
146
  'capability' => $this->settings_capability(),
147
  'menu_slug' => $this->seo_settings_page_slug,
148
  'callback' => array( $this, 'admin' ),
@@ -150,7 +108,7 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
150
  'position' => '90.9001',
151
  );
152
 
153
- $this->seo_settings_page_hook = add_menu_page(
154
  $menu['page_title'],
155
  $menu['menu_title'],
156
  $menu['capability'],
@@ -164,7 +122,7 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
164
  * Simply copy the previous, but rename the submenu entry.
165
  * The function add_submenu_page() takes care of the duplications.
166
  */
167
- add_submenu_page(
168
  $menu['menu_slug'],
169
  $menu['page_title'],
170
  $menu['page_title'],
@@ -174,10 +132,10 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
174
  );
175
 
176
  //* Enqueue styles
177
- add_action( 'admin_print_styles-' . $this->seo_settings_page_hook, array( $this, 'enqueue_admin_css' ), 11 );
178
 
179
  //* Enqueue scripts
180
- add_action( 'admin_print_scripts-' . $this->seo_settings_page_hook, array( $this, 'enqueue_admin_javascript' ), 11 );
181
 
182
  }
183
 
@@ -185,48 +143,49 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
185
  * Initialize the settings page.
186
  *
187
  * @since 2.2.2
 
188
  */
189
  public function settings_init() {
190
 
191
- add_action( $this->seo_settings_page_hook . '_settings_page_boxes', array( $this, 'do_metaboxes' ) );
192
- add_action( 'load-' . $this->seo_settings_page_hook, array( $this, 'metaboxes' ) );
 
193
 
 
 
 
194
  }
195
 
196
  /**
197
  * Echo out the do_metaboxes() and wrapping markup.
198
  *
199
  * @since 2.2.2
200
- *
201
- * @global array $wp_meta_boxes Holds all metaboxes data.
202
  */
203
  public function do_metaboxes() {
204
- global $wp_meta_boxes;
205
-
206
  ?>
207
  <div class="metabox-holder columns-2">
208
  <div class="postbox-container-1">
209
  <?php
210
- do_action( 'the_seo_framework_before_siteadmin_metaboxes', $this->seo_settings_page_hook );
211
 
212
- do_meta_boxes( $this->seo_settings_page_hook, 'main', null );
213
 
214
- if ( isset( $wp_meta_boxes[ $this->seo_settings_page_hook ]['main_extra'] ) )
215
- do_meta_boxes( $this->seo_settings_page_hook, 'main_extra', null );
216
 
217
- do_action( 'the_seo_framework_after_siteadmin_metaboxes', $this->seo_settings_page_hook );
218
  ?>
219
  </div>
220
  <div class="postbox-container-2">
221
  <?php
222
- do_action( 'the_seo_framework_before_siteadmin_metaboxes_side', $this->seo_settings_page_hook );
223
 
224
  /**
225
  * @TODO fill this in
226
  * @priority low 2.9.0
227
  */
228
 
229
- do_action( 'the_seo_framework_after_siteadmin_metaboxes_side', $this->seo_settings_page_hook );
230
  ?>
231
  </div>
232
  </div>
@@ -238,16 +197,16 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
238
  *
239
  * @since 2.2.2
240
  *
241
- * @see $this->title_metabox() Callback for Title Settings box.
242
- * @see $this->description_metabox() Callback for Description Settings box.
243
- * @see $this->robots_metabox() Callback for Robots Settings box.
244
- * @see $this->homepage_metabox() Callback for Home Page Settings box.
245
- * @see $this->social_metabox() Callback for Social Settings box.
246
- * @see $this->knowledge_metabox() Callback for Knowledge Graph Settings box.
247
- * @see $this->schema_metabox() Callback for Schema Settings box.
248
- * @see $this->webmaster_metabox() Callback for Webmaster Settings box.
249
- * @see $this->sitemaps_metabox() Callback for Sitemap Settings box.
250
- * @see $this->feed_metabox() Callback for Feed Settings box.
251
  */
252
  public function metaboxes() {
253
 
@@ -256,23 +215,35 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
256
  * Set any to false if you wish the meta box to be removed.
257
  *
258
  * @since 2.2.4
 
259
  */
260
- $title = (bool) apply_filters( 'the_seo_framework_title_metabox', true );
261
- $description = (bool) apply_filters( 'the_seo_framework_description_metabox', true );
262
- $robots = (bool) apply_filters( 'the_seo_framework_robots_metabox', true );
263
- $home = (bool) apply_filters( 'the_seo_framework_home_metabox', true );
264
- $social = (bool) apply_filters( 'the_seo_framework_social_metabox', true );
265
- $knowledge = (bool) apply_filters( 'the_seo_framework_knowledge_metabox', true );
266
- $schema = (bool) apply_filters( 'the_seo_framework_schema_metabox', true );
267
- $webmaster = (bool) apply_filters( 'the_seo_framework_webmaster_metabox', true );
268
- $sitemap = (bool) apply_filters( 'the_seo_framework_sitemap_metabox', true );
269
- $feed = (bool) apply_filters( 'the_seo_framework_feed_metabox', true );
 
 
 
 
 
 
 
 
 
 
 
270
 
271
  //* Title Meta Box
272
  if ( $title )
273
- add_meta_box(
274
  'autodescription-title-settings',
275
- esc_html__( 'Title Settings', 'autodescription' ),
276
  array( $this, 'title_metabox' ),
277
  $this->seo_settings_page_hook,
278
  'main',
@@ -281,9 +252,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
281
 
282
  //* Description Meta Box
283
  if ( $description )
284
- add_meta_box(
285
  'autodescription-description-settings',
286
- esc_html__( 'Description Meta Settings', 'autodescription' ),
287
  array( $this, 'description_metabox' ),
288
  $this->seo_settings_page_hook,
289
  'main',
@@ -292,9 +263,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
292
 
293
  //* Home Page Meta Box
294
  if ( $home )
295
- add_meta_box(
296
  'autodescription-homepage-settings',
297
- esc_html__( 'Home Page Settings', 'autodescription' ),
298
  array( $this, 'homepage_metabox' ),
299
  $this->seo_settings_page_hook,
300
  'main',
@@ -303,31 +274,20 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
303
 
304
  //* Social Meta Box
305
  if ( $social )
306
- add_meta_box(
307
  'autodescription-social-settings',
308
- esc_html__( 'Social Meta Settings', 'autodescription' ),
309
  array( $this, 'social_metabox' ),
310
  $this->seo_settings_page_hook,
311
  'main',
312
  array()
313
  );
314
 
315
- //* Knowledge Graph Meta Box
316
- if ( $knowledge )
317
- add_meta_box(
318
- 'autodescription-knowledgegraph-settings',
319
- esc_html__( 'Knowledge Graph Settings', 'autodescription' ),
320
- array( $this, 'knowledge_metabox' ),
321
- $this->seo_settings_page_hook,
322
- 'main',
323
- array()
324
- );
325
-
326
  //* Title Meta Box
327
  if ( $schema )
328
- add_meta_box(
329
  'autodescription-schema-settings',
330
- esc_html__( 'Schema Settings', 'autodescription' ),
331
  array( $this, 'schema_metabox' ),
332
  $this->seo_settings_page_hook,
333
  'main',
@@ -336,9 +296,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
336
 
337
  //* Robots Meta Box
338
  if ( $robots )
339
- add_meta_box(
340
  'autodescription-robots-settings',
341
- esc_html__( 'Robots Meta Settings', 'autodescription' ),
342
  array( $this, 'robots_metabox' ),
343
  $this->seo_settings_page_hook,
344
  'main',
@@ -347,9 +307,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
347
 
348
  //* Webmaster Meta Box
349
  if ( $webmaster )
350
- add_meta_box(
351
  'autodescription-webmaster-settings',
352
- esc_html__( 'Webmaster Meta Settings', 'autodescription' ),
353
  array( $this, 'webmaster_metabox' ),
354
  $this->seo_settings_page_hook,
355
  'main',
@@ -358,9 +318,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
358
 
359
  //* Sitemaps Meta Box
360
  if ( $sitemap )
361
- add_meta_box(
362
  'autodescription-sitemap-settings',
363
- esc_html__( 'Sitemap Settings', 'autodescription' ),
364
  array( $this, 'sitemaps_metabox' ),
365
  $this->seo_settings_page_hook,
366
  'main',
@@ -369,15 +329,14 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
369
 
370
  //* Feed Meta Box
371
  if ( $feed )
372
- add_meta_box(
373
  'autodescription-feed-settings',
374
- esc_html__( 'Feed Settings', 'autodescription' ),
375
  array( $this, 'feed_metabox' ),
376
  $this->seo_settings_page_hook,
377
  'main',
378
  array()
379
  );
380
-
381
  }
382
 
383
  /**
@@ -392,26 +351,26 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
392
  <div class="wrap tsf-metaboxes">
393
  <form method="post" action="options.php">
394
 
395
- <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
396
- <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
397
- <?php settings_fields( $this->settings_field ); ?>
398
 
399
  <div class="tsf-top-wrap">
400
- <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
401
  <p class="tsf-top-buttons">
402
  <?php
403
- submit_button( $this->page_defaults['save_button_text'], 'primary', 'submit', false, array( 'id' => '' ) );
404
- submit_button( $this->page_defaults['reset_button_text'], 'secondary autodescription-js-confirm-reset', $this->get_field_name( 'reset' ), false, array( 'id' => '' ) );
405
  ?>
406
  </p>
407
  </div>
408
 
409
- <?php do_action( "{$this->seo_settings_page_hook}_settings_page_boxes", $this->seo_settings_page_hook ); ?>
410
 
411
  <div class="tsf-bottom-buttons">
412
  <?php
413
- submit_button( $this->page_defaults['save_button_text'], 'primary', 'submit', false, array( 'id' => '' ) );
414
- submit_button( $this->page_defaults['reset_button_text'], 'secondary autodescription-js-confirm-reset', $this->get_field_name( 'reset' ), false, array( 'id' => '' ) );
415
  ?>
416
  </div>
417
  </form>
@@ -419,11 +378,11 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
419
  <?php // Add postbox listeners ?>
420
  <script type="text/javascript">
421
  //<![CDATA[
422
- jQuery(document).ready( function ($) {
423
  // close postboxes that should be closed
424
  $('.if-js-closed').removeClass('if-js-closed').addClass('closed');
425
  // postboxes setup
426
- postboxes.add_postbox_toggles('<?php echo esc_js( $this->seo_settings_page_hook ); ?>');
427
  });
428
  //]]>
429
  </script>
@@ -443,15 +402,20 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
443
  if ( false === $this->is_seo_settings_page( true ) )
444
  return;
445
 
446
- if ( isset( $_REQUEST['settings-updated'] ) && 'true' === $_REQUEST['settings-updated'] )
 
 
 
 
 
447
  $this->do_dismissible_notice( $this->page_defaults['saved_notice_text'], 'updated' );
448
- elseif ( isset( $_REQUEST['reset'] ) && 'true' === $_REQUEST['reset'] )
449
  $this->do_dismissible_notice( $this->page_defaults['reset_notice_text'], 'warning' );
450
- elseif ( isset( $_REQUEST['error'] ) && 'true' === $_REQUEST['error'] )
451
  $this->do_dismissible_notice( $this->page_defaults['error_notice_text'], 'error' );
452
- elseif ( isset( $_REQUEST['seo-updated'] ) && 'true' === $_REQUEST['seo-updated'] )
453
  $this->do_dismissible_notice( $this->page_defaults['plugin_update_text'], 'updated' );
454
-
455
  }
456
 
457
  /**
@@ -478,7 +442,7 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
478
  * @param string $name Field name base
479
  */
480
  public function field_name( $name ) {
481
- echo esc_attr( $this->get_field_name( $name ) );
482
  }
483
 
484
  /**
@@ -506,7 +470,7 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
506
  public function field_id( $id, $echo = true ) {
507
 
508
  if ( $echo ) {
509
- echo esc_attr( $this->get_field_id( $id ) );
510
  } else {
511
  return $this->get_field_id( $id );
512
  }
@@ -535,7 +499,7 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
535
  * @param string $key Field key
536
  */
537
  public function field_value( $key ) {
538
- echo esc_attr( $this->get_field_value( $key ) );
539
  }
540
 
541
  /**
@@ -550,12 +514,13 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
550
  public function wrap_fields( $input = '', $echo = false ) {
551
 
552
  if ( is_array( $input ) )
553
- $input = implode( "\r\n", $input );
554
 
555
  if ( $echo ) {
556
- echo '<div class="tsf-fields">' . "\r\n" . $input . "\r\n" . '</div>';
 
557
  } else {
558
- return '<div class="tsf-fields">' . "\r\n" . $input . "\r\n" . '</div>';
559
  }
560
  }
561
 
@@ -573,8 +538,10 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
573
  */
574
  public function make_checkbox( $field_id = '', $label = '', $description = '', $escape = true ) {
575
 
576
- $description = $escape ? esc_html( $description ) : $description;
577
- $label = $escape ? esc_html( $label ) : $label;
 
 
578
 
579
  $description = $description ? '<p class="description tsf-option-spacer">' . $description . '</p>' : '';
580
 
@@ -586,7 +553,7 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
586
  . 'id="' . $this->get_field_id( $field_id ) . '" '
587
  . $this->get_is_conditional_checked( $field_id ) . ' '
588
  . 'value="1" '
589
- . checked( $this->get_field_value( $field_id ), true, false ) .
590
  ' />'
591
  . $label
592
  . '</label>'
@@ -597,6 +564,48 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
597
  return $output;
598
  }
599
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
  /**
601
  * Return a wrapped question mark.
602
  *
@@ -610,9 +619,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
610
  public function make_info( $description = '', $link = '', $echo = true ) {
611
 
612
  if ( $link ) {
613
- $output = '<a href="' . esc_url( $link ) . '" target="_blank" title="' . esc_attr( $description ) . '">[?]</a>';
614
  } else {
615
- $output = '<span title="' . esc_attr( $description ) . '">[?]</span>';
616
  }
617
 
618
  if ( $echo ) {
@@ -630,7 +639,7 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
630
  */
631
  public function load_assets() {
632
  //* Hook scripts method
633
- add_action( "load-{$this->seo_settings_page_hook}", array( $this, 'metabox_scripts' ) );
634
  }
635
 
636
  /**
@@ -639,9 +648,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
639
  * @since 2.2.2
640
  */
641
  public function metabox_scripts() {
642
- wp_enqueue_script( 'common' );
643
- wp_enqueue_script( 'wp-lists' );
644
- wp_enqueue_script( 'postbox' );
645
  }
646
 
647
  /**
@@ -668,9 +677,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
668
 
669
  if ( $echo ) {
670
  if ( $wrap ) {
671
- printf( 'class="%s"', esc_attr( $class ) );
672
  } else {
673
- echo esc_attr( $class );
674
  }
675
  } else {
676
  if ( $wrap )
@@ -702,9 +711,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
702
 
703
  if ( $echo ) {
704
  if ( $wrap ) {
705
- printf( 'class="%s"', esc_attr( $class ) );
706
  } else {
707
- echo esc_attr( $class );
708
  }
709
  } else {
710
  if ( $wrap )
@@ -757,9 +766,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
757
 
758
  if ( $echo ) {
759
  if ( $wrap ) {
760
- printf( 'class="%s"', esc_attr( $class ) );
761
  } else {
762
- echo esc_attr( $class );
763
  }
764
  } else {
765
  if ( $wrap )
@@ -795,9 +804,9 @@ class AutoDescription_Adminpages extends AutoDescription_Inpost {
795
 
796
  if ( $echo ) {
797
  if ( $wrap ) {
798
- echo sprintf( 'class="%s"', esc_attr( $class ) );
799
  } else {
800
- echo esc_attr( $class );
801
  }
802
  } else {
803
  if ( $wrap )
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Site_Options
28
  *
29
+ * Renders admin pages content for this plugin.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Admin_Pages extends Inpost {
34
 
35
  /**
36
  * Page Defaults.
59
  */
60
  public $load_options;
61
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  /**
63
  * Constructor. Loads parent constructor, does actions and sets up variables.
64
  */
65
+ protected function __construct() {
66
  parent::__construct();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
 
69
  /**
76
  */
77
  public function enqueue_page_defaults() {
78
 
79
+ $this->page_defaults = (array) \apply_filters(
80
  'the_seo_framework_admin_page_defaults',
81
  array(
82
+ 'save_button_text' => \esc_html__( 'Save Settings', 'autodescription' ),
83
+ 'reset_button_text' => \esc_html__( 'Reset Settings', 'autodescription' ),
84
+ 'saved_notice_text' => \esc_html__( 'Settings are saved.', 'autodescription' ),
85
+ 'reset_notice_text' => \esc_html__( 'Settings are reset.', 'autodescription' ),
86
+ 'error_notice_text' => \esc_html__( 'Error saving settings.', 'autodescription' ),
87
+ 'plugin_update_text' => \esc_html__( 'New SEO Settings have been updated.', 'autodescription' ),
88
  )
89
  );
 
90
  }
91
 
92
  /**
99
  public function add_menu_link() {
100
 
101
  $menu = array(
102
+ 'page_title' => \esc_html__( 'SEO Settings', 'autodescription' ),
103
+ 'menu_title' => \esc_html__( 'SEO', 'autodescription' ),
104
  'capability' => $this->settings_capability(),
105
  'menu_slug' => $this->seo_settings_page_slug,
106
  'callback' => array( $this, 'admin' ),
108
  'position' => '90.9001',
109
  );
110
 
111
+ $this->seo_settings_page_hook = \add_menu_page(
112
  $menu['page_title'],
113
  $menu['menu_title'],
114
  $menu['capability'],
122
  * Simply copy the previous, but rename the submenu entry.
123
  * The function add_submenu_page() takes care of the duplications.
124
  */
125
+ \add_submenu_page(
126
  $menu['menu_slug'],
127
  $menu['page_title'],
128
  $menu['page_title'],
132
  );
133
 
134
  //* Enqueue styles
135
+ \add_action( 'admin_print_styles-' . $this->seo_settings_page_hook, array( $this, 'enqueue_admin_css' ), 11 );
136
 
137
  //* Enqueue scripts
138
+ \add_action( 'admin_print_scripts-' . $this->seo_settings_page_hook, array( $this, 'enqueue_admin_javascript' ), 11 );
139
 
140
  }
141
 
143
  * Initialize the settings page.
144
  *
145
  * @since 2.2.2
146
+ * @since 2.8.0 Handled settings POST initialization.
147
  */
148
  public function settings_init() {
149
 
150
+ //* Handle post-update actions. Must be initialized on admin_init and is initalized on options.php.
151
+ if ( 'options.php' === $GLOBALS['pagenow'] )
152
+ $this->handle_update_post();
153
 
154
+ //* Output metaboxes.
155
+ \add_action( $this->seo_settings_page_hook . '_settings_page_boxes', array( $this, 'do_metaboxes' ) );
156
+ \add_action( 'load-' . $this->seo_settings_page_hook, array( $this, 'metaboxes' ) );
157
  }
158
 
159
  /**
160
  * Echo out the do_metaboxes() and wrapping markup.
161
  *
162
  * @since 2.2.2
 
 
163
  */
164
  public function do_metaboxes() {
 
 
165
  ?>
166
  <div class="metabox-holder columns-2">
167
  <div class="postbox-container-1">
168
  <?php
169
+ \do_action( 'the_seo_framework_before_siteadmin_metaboxes', $this->seo_settings_page_hook );
170
 
171
+ \do_meta_boxes( $this->seo_settings_page_hook, 'main', null );
172
 
173
+ if ( isset( $GLOBALS['wp_meta_boxes'][ $this->seo_settings_page_hook ]['main_extra'] ) )
174
+ \do_meta_boxes( $this->seo_settings_page_hook, 'main_extra', null );
175
 
176
+ \do_action( 'the_seo_framework_after_siteadmin_metaboxes', $this->seo_settings_page_hook );
177
  ?>
178
  </div>
179
  <div class="postbox-container-2">
180
  <?php
181
+ \do_action( 'the_seo_framework_before_siteadmin_metaboxes_side', $this->seo_settings_page_hook );
182
 
183
  /**
184
  * @TODO fill this in
185
  * @priority low 2.9.0
186
  */
187
 
188
+ \do_action( 'the_seo_framework_after_siteadmin_metaboxes_side', $this->seo_settings_page_hook );
189
  ?>
190
  </div>
191
  </div>
197
  *
198
  * @since 2.2.2
199
  *
200
+ * @see $this->general_metabox() Callback for General Settings box.
201
+ * @see $this->title_metabox() Callback for Title Settings box.
202
+ * @see $this->description_metabox() Callback for Description Settings box.
203
+ * @see $this->robots_metabox() Callback for Robots Settings box.
204
+ * @see $this->homepage_metabox() Callback for Home Page Settings box.
205
+ * @see $this->social_metabox() Callback for Social Settings box.
206
+ * @see $this->schema_metabox() Callback for Schema Settings box.
207
+ * @see $this->webmaster_metabox() Callback for Webmaster Settings box.
208
+ * @see $this->sitemaps_metabox() Callback for Sitemap Settings box.
209
+ * @see $this->feed_metabox() Callback for Feed Settings box.
210
  */
211
  public function metaboxes() {
212
 
215
  * Set any to false if you wish the meta box to be removed.
216
  *
217
  * @since 2.2.4
218
+ * @since 2.8.0: Added `the_seo_framework_general_metabox` filter.
219
  */
220
+ $general = (bool) \apply_filters( 'the_seo_framework_general_metabox', true );
221
+ $title = (bool) \apply_filters( 'the_seo_framework_title_metabox', true );
222
+ $description = (bool) \apply_filters( 'the_seo_framework_description_metabox', true );
223
+ $robots = (bool) \apply_filters( 'the_seo_framework_robots_metabox', true );
224
+ $home = (bool) \apply_filters( 'the_seo_framework_home_metabox', true );
225
+ $social = (bool) \apply_filters( 'the_seo_framework_social_metabox', true );
226
+ $schema = (bool) \apply_filters( 'the_seo_framework_schema_metabox', true );
227
+ $webmaster = (bool) \apply_filters( 'the_seo_framework_webmaster_metabox', true );
228
+ $sitemap = (bool) \apply_filters( 'the_seo_framework_sitemap_metabox', true );
229
+ $feed = (bool) \apply_filters( 'the_seo_framework_feed_metabox', true );
230
+
231
+ //* Title Meta Box
232
+ if ( $general )
233
+ \add_meta_box(
234
+ 'autodescription-general-settings',
235
+ \esc_html__( 'General Settings', 'autodescription' ),
236
+ array( $this, 'general_metabox' ),
237
+ $this->seo_settings_page_hook,
238
+ 'main',
239
+ array()
240
+ );
241
 
242
  //* Title Meta Box
243
  if ( $title )
244
+ \add_meta_box(
245
  'autodescription-title-settings',
246
+ \esc_html__( 'Title Settings', 'autodescription' ),
247
  array( $this, 'title_metabox' ),
248
  $this->seo_settings_page_hook,
249
  'main',
252
 
253
  //* Description Meta Box
254
  if ( $description )
255
+ \add_meta_box(
256
  'autodescription-description-settings',
257
+ \esc_html__( 'Description Meta Settings', 'autodescription' ),
258
  array( $this, 'description_metabox' ),
259
  $this->seo_settings_page_hook,
260
  'main',
263
 
264
  //* Home Page Meta Box
265
  if ( $home )
266
+ \add_meta_box(
267
  'autodescription-homepage-settings',
268
+ \esc_html__( 'Home Page Settings', 'autodescription' ),
269
  array( $this, 'homepage_metabox' ),
270
  $this->seo_settings_page_hook,
271
  'main',
274
 
275
  //* Social Meta Box
276
  if ( $social )
277
+ \add_meta_box(
278
  'autodescription-social-settings',
279
+ \esc_html__( 'Social Meta Settings', 'autodescription' ),
280
  array( $this, 'social_metabox' ),
281
  $this->seo_settings_page_hook,
282
  'main',
283
  array()
284
  );
285
 
 
 
 
 
 
 
 
 
 
 
 
286
  //* Title Meta Box
287
  if ( $schema )
288
+ \add_meta_box(
289
  'autodescription-schema-settings',
290
+ \esc_html__( 'Schema Settings', 'autodescription' ),
291
  array( $this, 'schema_metabox' ),
292
  $this->seo_settings_page_hook,
293
  'main',
296
 
297
  //* Robots Meta Box
298
  if ( $robots )
299
+ \add_meta_box(
300
  'autodescription-robots-settings',
301
+ \esc_html__( 'Robots Meta Settings', 'autodescription' ),
302
  array( $this, 'robots_metabox' ),
303
  $this->seo_settings_page_hook,
304
  'main',
307
 
308
  //* Webmaster Meta Box
309
  if ( $webmaster )
310
+ \add_meta_box(
311
  'autodescription-webmaster-settings',
312
+ \esc_html__( 'Webmaster Meta Settings', 'autodescription' ),
313
  array( $this, 'webmaster_metabox' ),
314
  $this->seo_settings_page_hook,
315
  'main',
318
 
319
  //* Sitemaps Meta Box
320
  if ( $sitemap )
321
+ \add_meta_box(
322
  'autodescription-sitemap-settings',
323
+ \esc_html__( 'Sitemap Settings', 'autodescription' ),
324
  array( $this, 'sitemaps_metabox' ),
325
  $this->seo_settings_page_hook,
326
  'main',
329
 
330
  //* Feed Meta Box
331
  if ( $feed )
332
+ \add_meta_box(
333
  'autodescription-feed-settings',
334
+ \esc_html__( 'Feed Settings', 'autodescription' ),
335
  array( $this, 'feed_metabox' ),
336
  $this->seo_settings_page_hook,
337
  'main',
338
  array()
339
  );
 
340
  }
341
 
342
  /**
351
  <div class="wrap tsf-metaboxes">
352
  <form method="post" action="options.php">
353
 
354
+ <?php \wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
355
+ <?php \wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
356
+ <?php \settings_fields( $this->settings_field ); ?>
357
 
358
  <div class="tsf-top-wrap">
359
+ <h1><?php echo \esc_html( \get_admin_page_title() ); ?></h1>
360
  <p class="tsf-top-buttons">
361
  <?php
362
+ \submit_button( $this->page_defaults['save_button_text'], 'primary', 'submit', false, array( 'id' => '' ) );
363
+ \submit_button( $this->page_defaults['reset_button_text'], 'secondary tsf-js-confirm-reset', $this->get_field_name( 'tsf-settings-reset' ), false, array( 'id' => '' ) );
364
  ?>
365
  </p>
366
  </div>
367
 
368
+ <?php \do_action( "{$this->seo_settings_page_hook}_settings_page_boxes", $this->seo_settings_page_hook ); ?>
369
 
370
  <div class="tsf-bottom-buttons">
371
  <?php
372
+ \submit_button( $this->page_defaults['save_button_text'], 'primary', 'submit', false, array( 'id' => '' ) );
373
+ \submit_button( $this->page_defaults['reset_button_text'], 'secondary tsf-js-confirm-reset', $this->get_field_name( 'tsf-settings-reset' ), false, array( 'id' => '' ) );
374
  ?>
375
  </div>
376
  </form>
378
  <?php // Add postbox listeners ?>
379
  <script type="text/javascript">
380
  //<![CDATA[
381
+ jQuery(document).ready( function($) {
382
  // close postboxes that should be closed
383
  $('.if-js-closed').removeClass('if-js-closed').addClass('closed');
384
  // postboxes setup
385
+ postboxes.add_postbox_toggles('<?php echo \esc_js( $this->seo_settings_page_hook ); ?>');
386
  });
387
  //]]>
388
  </script>
402
  if ( false === $this->is_seo_settings_page( true ) )
403
  return;
404
 
405
+ $request = isset( $_REQUEST ) ? $_REQUEST : null;
406
+
407
+ if ( null === $request )
408
+ return;
409
+
410
+ if ( isset( $request['settings-updated'] ) && 'true' === $request['settings-updated'] ) :
411
  $this->do_dismissible_notice( $this->page_defaults['saved_notice_text'], 'updated' );
412
+ elseif ( isset( $request['tsf-settings-reset'] ) && 'true' === $request['tsf-settings-reset'] ) :
413
  $this->do_dismissible_notice( $this->page_defaults['reset_notice_text'], 'warning' );
414
+ elseif ( isset( $request['error'] ) && 'true' === $request['error'] ) :
415
  $this->do_dismissible_notice( $this->page_defaults['error_notice_text'], 'error' );
416
+ elseif ( isset( $request['tsf-settings-updated'] ) && 'true' === $request['tsf-settings-updated'] ) :
417
  $this->do_dismissible_notice( $this->page_defaults['plugin_update_text'], 'updated' );
418
+ endif;
419
  }
420
 
421
  /**
442
  * @param string $name Field name base
443
  */
444
  public function field_name( $name ) {
445
+ echo \esc_attr( $this->get_field_name( $name ) );
446
  }
447
 
448
  /**
470
  public function field_id( $id, $echo = true ) {
471
 
472
  if ( $echo ) {
473
+ echo \esc_attr( $this->get_field_id( $id ) );
474
  } else {
475
  return $this->get_field_id( $id );
476
  }
499
  * @param string $key Field key
500
  */
501
  public function field_value( $key ) {
502
+ echo \esc_attr( $this->get_field_value( $key ) );
503
  }
504
 
505
  /**
514
  public function wrap_fields( $input = '', $echo = false ) {
515
 
516
  if ( is_array( $input ) )
517
+ $input = implode( PHP_EOL, $input );
518
 
519
  if ( $echo ) {
520
+ //* Already escaped.
521
+ echo '<div class="tsf-fields">' . $input . '</div>';
522
  } else {
523
+ return '<div class="tsf-fields">' . $input . '</div>';
524
  }
525
  }
526
 
538
  */
539
  public function make_checkbox( $field_id = '', $label = '', $description = '', $escape = true ) {
540
 
541
+ if ( $escape ) {
542
+ $description = \esc_html( $description );
543
+ $label = \esc_html( $label );
544
+ }
545
 
546
  $description = $description ? '<p class="description tsf-option-spacer">' . $description . '</p>' : '';
547
 
553
  . 'id="' . $this->get_field_id( $field_id ) . '" '
554
  . $this->get_is_conditional_checked( $field_id ) . ' '
555
  . 'value="1" '
556
+ . \checked( $this->get_field_value( $field_id ), true, false ) .
557
  ' />'
558
  . $label
559
  . '</label>'
564
  return $output;
565
  }
566
 
567
+ /**
568
+ * Return a text field wrapper.
569
+ *
570
+ * @since 2.8.0
571
+ * @ignore Unused.
572
+ * @access private
573
+ *
574
+ * @param string $field_id The option ID. Must be within the Autodescription settings.
575
+ * @param string $label The checkbox description label.
576
+ * @param string $description Addition description to place beneath the checkbox.
577
+ * @param string $placeholder The text field placeholder.
578
+ * @param bool $escape Whether to escape the label and description.
579
+ * @return HTML text field output.
580
+ */
581
+ public function make_textfield( $field_id = '', $label = '', $description = '', $placeholder = '', $escape = true ) {
582
+
583
+ if ( $escape ) {
584
+ $description = \esc_html( $description );
585
+ $label = \esc_html( $label );
586
+ $placeholder = \esc_attr( $placeholder );
587
+ }
588
+
589
+ $description = $description ? '<p class="description tsf-option-spacer">' . $description . '</p>' : '';
590
+
591
+ $output = '<p>'
592
+ . '<label for="' . $this->field_id( $field_id ) . '" class="tsf-toblock">'
593
+ . '<strong>' . $label . '</strong>'
594
+ . '</label>'
595
+ . '</p>'
596
+ . '<p>'
597
+ . '<input type="text" name="' . $this->field_name( $field_id ) . '"'
598
+ . ' class="large-text" id="' . $this->field_id( $field_id ) . '"'
599
+ . ' placeholder="' . $placeholder . '"'
600
+ . ' value="' . $this->get_field_value( $field_id ) . '"'
601
+ . ' />'
602
+ . '</p>'
603
+ . $description
604
+ ;
605
+
606
+ return $output;
607
+ }
608
+
609
  /**
610
  * Return a wrapped question mark.
611
  *
619
  public function make_info( $description = '', $link = '', $echo = true ) {
620
 
621
  if ( $link ) {
622
+ $output = '<a href="' . \esc_url( $link ) . '" target="_blank" title="' . \esc_attr( $description ) . '">[?]</a>';
623
  } else {
624
+ $output = '<span title="' . \esc_attr( $description ) . '">[?]</span>';
625
  }
626
 
627
  if ( $echo ) {
639
  */
640
  public function load_assets() {
641
  //* Hook scripts method
642
+ \add_action( "load-{$this->seo_settings_page_hook}", array( $this, 'metabox_scripts' ) );
643
  }
644
 
645
  /**
648
  * @since 2.2.2
649
  */
650
  public function metabox_scripts() {
651
+ \wp_enqueue_script( 'common' );
652
+ \wp_enqueue_script( 'wp-lists' );
653
+ \wp_enqueue_script( 'postbox' );
654
  }
655
 
656
  /**
677
 
678
  if ( $echo ) {
679
  if ( $wrap ) {
680
+ printf( 'class="%s"', \esc_attr( $class ) );
681
  } else {
682
+ echo \esc_attr( $class );
683
  }
684
  } else {
685
  if ( $wrap )
711
 
712
  if ( $echo ) {
713
  if ( $wrap ) {
714
+ printf( 'class="%s"', \esc_attr( $class ) );
715
  } else {
716
+ echo \esc_attr( $class );
717
  }
718
  } else {
719
  if ( $wrap )
766
 
767
  if ( $echo ) {
768
  if ( $wrap ) {
769
+ printf( 'class="%s"', \esc_attr( $class ) );
770
  } else {
771
+ echo \esc_attr( $class );
772
  }
773
  } else {
774
  if ( $wrap )
804
 
805
  if ( $echo ) {
806
  if ( $wrap ) {
807
+ printf( 'class="%s"', \esc_attr( $class ) );
808
  } else {
809
+ echo \esc_attr( $class );
810
  }
811
  } else {
812
  if ( $wrap )
inc/classes/{transients.class.php → cache.class.php} RENAMED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,16 +23,14 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Transients
23
  *
24
  * Generates, stores and deletes common transients.
25
  *
26
- * @since 2.3.3
27
  */
28
- class AutoDescription_Transients extends AutoDescription_Sitemaps {
29
 
30
  /**
31
  * The sitemap transient name.
@@ -64,52 +69,283 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
64
  protected $theme_doing_it_right_transient;
65
 
66
  /**
67
- * Unserializing instances of this class is forbidden.
68
  */
69
- private function __wakeup() { }
 
 
 
 
 
70
 
71
  /**
72
- * Handle unapproachable invoked methods.
 
 
 
 
 
73
  */
74
- public function __call( $name, $arguments ) {
75
- parent::__call( $name, $arguments );
76
  }
77
 
78
  /**
79
- * Constructor, load parent constructor and set up caches.
 
 
 
 
80
  */
81
- public function __construct() {
82
- parent::__construct();
83
-
84
- // Setup Transient names
85
- add_action( 'plugins_loaded', array( $this, 'setup_transient_names' ), 10 );
86
 
87
- /**
88
- * Delete Sitemap and Description transients on post publish/delete.
89
- * @see WP Core wp_transition_post_status()
90
- */
91
- add_action( 'publish_post', array( $this, 'delete_transients_post' ) );
92
- add_action( 'publish_page', array( $this, 'delete_transients_post' ) );
93
- add_action( 'deleted_post', array( $this, 'delete_transients_post' ) );
94
- add_action( 'deleted_page', array( $this, 'delete_transients_post' ) );
95
- add_action( 'post_updated', array( $this, 'delete_transients_post' ) );
96
- add_action( 'page_updated', array( $this, 'delete_transients_post' ) );
97
 
98
- add_action( 'profile_update', array( $this, 'delete_transients_author' ) );
 
 
99
 
100
- add_action( 'edit_term', array( $this, 'delete_auto_description_transients_term' ), 10, 3 );
101
- add_action( 'delete_term', array( $this, 'delete_auto_description_transients_term' ), 10, 4 );
102
 
103
  //* Delete Sitemap transient on permalink structure change.
104
- add_action( 'load-options-permalink.php', array( $this, 'delete_sitemap_transient_permalink_updated' ), 20 );
105
 
106
  //* Deletes front page description transient on Tagline change.
107
- add_action( 'update_option_blogdescription', array( $this, 'delete_auto_description_frontpage_transient' ), 10, 1 );
108
 
109
- //* Delete doing it wrong transient after theme switch.
110
- add_action( 'after_switch_theme', array( $this, 'delete_theme_dir_transient' ), 10, 0 );
111
- add_action( 'upgrader_process_complete', array( $this, 'delete_theme_dir_transient' ), 10, 2 );
 
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  }
114
 
115
  /**
@@ -123,42 +359,79 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
123
  * @since 2.6.0
124
  *
125
  * @param string $transient Transient name. Expected to not be SQL-escaped.
126
- *
127
  * @return mixed|bool Value of the transient. False on failure or non existing transient.
128
  */
129
  public function get_transient( $transient ) {
130
 
131
  if ( $this->the_seo_framework_use_transients )
132
- return get_transient( $transient );
133
 
134
  return false;
135
  }
136
 
137
  /**
138
- * Set the value of the transient..
139
  *
140
- * Prevents setting of transients when they're disabled.
141
- * @see $this->the_seo_framework_use_transients
142
  *
143
- * @since 2.6.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  *
145
- * @param string $transient Transient name. Expected to not be SQL-escaped.
146
- * @param string $value Transient value. Expected to not be SQL-escaped.
147
- * @param int $expiration Optional Transient expiration date, optional. Expected to not be SQL-escaped.
 
 
 
 
148
  */
149
- public function set_transient( $transient, $value, $expiration = '' ) {
150
 
151
- if ( $this->the_seo_framework_use_transients )
152
- set_transient( $transient, $value, $expiration );
153
 
 
154
  }
155
 
156
  /**
157
- * Setup vars for general site transients.
158
  *
159
- * @global int $blog_id
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  *
161
  * @since 2.3.3
 
 
 
 
162
  */
163
  public function setup_transient_names() {
164
  global $blog_id;
@@ -167,23 +440,29 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
167
  * When the caching mechanism changes. Change this value.
168
  * Use hex. e.g. 0, 1, 2, 9, a, b
169
  */
170
- $revision = '0';
 
171
 
172
- $this->sitemap_transient = 'tsf_sitemap_' . (string) $revision . '_' . (string) $blog_id;
173
- $this->theme_doing_it_right_transient = 'tsf_tdir_' . (string) $revision . '_' . (string) $blog_id;
174
  }
175
 
176
  /**
177
  * Setup vars for transients which require $page_id.
178
  *
179
  * @since 2.3.3
 
180
  *
181
  * @param int|string|bool $page_id the Taxonomy or Post ID. If false it will generate for the blog page.
182
  * @param string $taxonomy The taxonomy name.
183
- * @param strgin $type The Post Type
 
184
  */
185
  public function setup_auto_description_transient( $page_id, $taxonomy = '', $type = null ) {
186
 
 
 
 
187
  $cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
188
 
189
  /**
@@ -192,7 +471,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
192
  *
193
  * @since 2.3.4
194
  */
195
- $revision = '1';
196
 
197
  $additions = $this->add_description_additions( $page_id, $taxonomy );
198
 
@@ -208,13 +487,18 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
208
  * Setup vars for transients which require $page_id.
209
  *
210
  * @since 2.3.3
 
211
  *
212
  * @param int|string|bool $page_id the Taxonomy or Post ID. If false it will generate for the blog page.
213
  * @param string $taxonomy The taxonomy name.
214
  * @param string|null $type The post type.
 
215
  */
216
  public function setup_ld_json_transient( $page_id, $taxonomy = '', $type = null ) {
217
 
 
 
 
218
  $cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
219
 
220
  /**
@@ -222,7 +506,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
222
  *
223
  * Use hex. e.g. 0, 1, 2, 9, a, b
224
  */
225
- $revision = '1';
226
 
227
  /**
228
  * Change key based on options.
@@ -250,7 +534,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
250
  */
251
  public function generate_cache_key( $page_id, $taxonomy = '', $type = null ) {
252
 
253
- $page_id = $page_id ? $page_id : $this->get_the_real_ID();
254
 
255
  if ( isset( $type ) ) {
256
  if ( 'author' === $type ) {
@@ -260,8 +544,8 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
260
  //* Front/HomePage.
261
  return $this->add_cache_key_suffix( $this->generate_front_page_cache_key() );
262
  } else {
263
- $this->_doing_it_wrong( __METHOD__, esc_html__( 'Third parameter must be a known type.', 'autodescription' ), '2.6.5' );
264
- return $this->add_cache_key_suffix( esc_sql( $type . '_' . $page_id . '_' . $taxonomy ) );
265
  }
266
  }
267
 
@@ -296,7 +580,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
296
  $query = '';
297
 
298
  if ( function_exists( 'get_search_query' ) ) {
299
- $search_query = get_search_query();
300
 
301
  if ( $search_query )
302
  $query = str_replace( ' ', '', $search_query );
@@ -305,15 +589,19 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
305
  if ( mb_strlen( $query ) > 10 )
306
  $query = mb_substr( $query, 0, 10 );
307
 
308
- $query = esc_sql( $query );
309
  }
310
 
 
 
 
 
311
  $the_id = $page_id . '_s_' . $query;
312
  } elseif ( $this->is_archive() ) {
313
  if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
314
 
315
  if ( empty( $t ) ) {
316
- $o = get_queried_object();
317
 
318
  if ( isset( $o->taxonomy ) )
319
  $t = $o->taxonomy;
@@ -327,18 +615,18 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
327
  } elseif ( $this->is_author() ) {
328
  $the_id = 'author_' . $page_id;
329
  } elseif ( $this->is_date() ) {
330
- $post = get_post();
331
 
332
  if ( $post && isset( $post->post_date ) ) {
333
  $date = $post->post_date;
334
 
335
  if ( $this->is_year() ) {
336
- $the_id .= 'year_' . mysql2date( 'y', $date, false );
337
  } elseif ( $this->is_month() ) {
338
- $the_id .= 'month_' . mysql2date( 'm_y', $date, false );
339
  } elseif ( $this->is_day() ) {
340
  //* Day. The correct notation.
341
- $the_id .= 'day_' . mysql2date( 'd_m_y', $date, false );
342
  }
343
  } else {
344
  //* Get seconds since UNIX Epoch. This is a failsafe.
@@ -361,13 +649,13 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
361
  //* Other taxonomial archives.
362
 
363
  if ( empty( $t ) ) {
364
- $post_type = get_query_var( 'post_type' );
365
 
366
  if ( is_array( $post_type ) )
367
  reset( $post_type );
368
 
369
  if ( $post_type )
370
- $post_type_obj = get_post_type_object( $post_type );
371
 
372
  if ( isset( $post_type_obj->labels->name ) )
373
  $t = $post_type_obj->labels->name;
@@ -375,7 +663,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
375
 
376
  //* Still empty? Try this.
377
  if ( empty( $t ) )
378
- $t = get_query_var( 'taxonomy' );
379
 
380
  $the_id = $this->generate_taxonomial_cache_key( $page_id, $t );
381
 
@@ -402,13 +690,19 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
402
  * Adds cache key suffix based on blog id and locale.
403
  *
404
  * @since 2.7.0
 
 
 
405
  *
406
  * @return string the cache key.
407
  */
408
- protected function add_cache_key_suffix( $key ) {
409
  global $blog_id;
410
 
411
- $locale = strtolower( get_locale() );
 
 
 
412
 
413
  return $key . '_' . $blog_id . '_' . $locale;
414
  }
@@ -417,7 +711,6 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
417
  * Returns the front page partial transient key.
418
  *
419
  * @param string $type
420
- *
421
  * @return string the front page transient key.
422
  */
423
  public function generate_front_page_cache_key( $type = '' ) {
@@ -429,7 +722,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
429
  $type = 'blog';
430
  }
431
  } else {
432
- $type = esc_sql( $type );
433
  }
434
 
435
  return $the_id = 'h' . $type . '_' . $this->get_the_front_page_ID();
@@ -466,7 +759,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
466
  if ( mb_strlen( $taxonomy ) >= 5 ) {
467
  $the_id = mb_substr( $taxonomy, 0, 5 );
468
  } else {
469
- $the_id = esc_sql( $taxonomy );
470
  }
471
  }
472
 
@@ -477,73 +770,76 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
477
  }
478
 
479
  /**
480
- * Delete transient on post save.
481
  *
482
- * @since 2.2.9
483
  *
484
- * @param int $post_id The Post ID that has been updated.
485
- * @return bool|null True when sitemap is flushed. False on revision. Null
486
- * when sitemaps are deactivated.
487
  */
488
- public function delete_transients_post( $post_id ) {
489
-
490
- $this->delete_auto_description_transient( $post_id );
491
- $this->delete_ld_json_transient( $post_id );
492
-
493
- if ( $this->is_option_checked( 'sitemaps_output' ) ) {
494
-
495
- //* Don't flush sitemap on revision.
496
- if ( wp_is_post_revision( $post_id ) )
497
- return false;
498
 
499
- $this->delete_sitemap_transient();
500
 
501
- return true;
502
- }
503
  }
504
 
505
  /**
506
- * Delete transient on profile save.
507
  *
508
- * @since 2.6.4
 
509
  *
510
- * @param int $user_id The User ID that has been updated.
 
511
  */
512
- public function delete_transients_author( $user_id ) {
513
- $this->delete_auto_description_transient( $user_id, 'author', 'author' );
 
 
 
 
 
 
 
 
 
 
 
 
 
514
  }
515
 
516
  /**
517
  * Delete transient on term save/deletion.
518
  *
 
 
519
  * @param int $term_id The Term ID
520
  * @param int $tt_id The Term Taxonomy ID.
521
  * @param string $taxonomy The Taxonomy type.
522
  * @param mixed $deleted_term Copy of the already-deleted term. Unused.
523
- *
524
- * @since 2.3.3
525
  */
526
  public function delete_auto_description_transients_term( $term_id, $tt_id, $taxonomy, $deleted_term = '' ) {
527
 
528
- $term_id = $term_id ? $term_id : $tt_id;
529
 
530
- $this->delete_auto_description_transient( $term_id, $taxonomy );
531
  }
532
 
533
  /**
534
  * Checks whether the permalink structure is updated.
535
  *
536
  * @since 2.3.0
537
- * @since 2.7.0 Added admin referer check.
538
  *
539
  * @return bool Whether if sitemap transient is deleted.
540
  */
541
  public function delete_sitemap_transient_permalink_updated() {
542
 
543
  if ( isset( $_POST['permalink_structure'] ) || isset( $_POST['category_base'] ) ) {
544
- check_admin_referer( 'update-permalink' );
545
 
546
- return $this->delete_sitemap_transient();
 
547
  }
548
 
549
  return false;
@@ -554,16 +850,23 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
554
  * Also ping search engines.
555
  *
556
  * @since 2.2.9
 
 
 
557
  *
558
- * @return bool true
559
  */
560
  public function delete_sitemap_transient() {
561
 
562
- delete_transient( $this->sitemap_transient );
563
 
 
 
 
 
564
  $this->ping_searchengines();
565
 
566
- return true;
567
  }
568
 
569
  /**
@@ -571,6 +874,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
571
  * Returns old option, since that's passed for sanitation within WP Core.
572
  *
573
  * @since 2.3.3
 
574
  *
575
  * @param string $old_option The previous blog description option.
576
  * @return string Previous option.
@@ -579,7 +883,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
579
 
580
  $this->setup_auto_description_transient( $this->get_the_front_page_ID(), '', 'frontpage' );
581
 
582
- delete_transient( $this->auto_description_transient );
583
 
584
  return $old_option;
585
  }
@@ -588,6 +892,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
588
  * Delete transient for the automatic description on requests.
589
  *
590
  * @since 2.3.3
 
591
  *
592
  * @param mixed $page_id The page ID or identifier.
593
  * @param string $taxonomy The tt name.
@@ -598,7 +903,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
598
 
599
  $this->setup_auto_description_transient( $page_id, $taxonomy, $type );
600
 
601
- delete_transient( $this->auto_description_transient );
602
 
603
  return true;
604
  }
@@ -607,6 +912,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
607
  * Delete transient for the LD+Json scripts on requests.
608
  *
609
  * @since 2.4.2
 
610
  *
611
  * @param mixed $page_id The page ID or identifier.
612
  * @param string $taxonomy The tt name.
@@ -620,7 +926,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
620
  if ( ! isset( $flushed ) ) {
621
  $this->setup_ld_json_transient( $page_id, $taxonomy, $type );
622
 
623
- delete_transient( $this->ld_json_transient );
624
 
625
  $flushed = 'Oh behave!';
626
 
@@ -634,7 +940,9 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
634
  * Delete transient for the Theme doing it Right bool on special requests.
635
  *
636
  * @since 2.5.2
637
- * @since 2.7.0
 
 
638
  *
639
  * @param string|object $value The theme directory stylesheet location, or either WP_Theme/WP_Upgrader instance.
640
  * @param array|object|null $options If set, the update options array or the Old theme WP_Theme instance.
@@ -647,7 +955,7 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
647
  return false;
648
  }
649
 
650
- delete_transient( $this->theme_doing_it_right_transient );
651
 
652
  return true;
653
  }
@@ -656,43 +964,20 @@ class AutoDescription_Transients extends AutoDescription_Sitemaps {
656
  * Sets transient for Theme doing it Right.
657
  *
658
  * @since 2.5.2
659
- * @since 2.7.0 Will always set "doing it wrong" transient, even if it was "doing it right" earlier.
660
  *
661
- * @NOTE: Ignores transient debug constant.
662
  *
663
  * @param bool $doing_it_right
664
  */
665
  public function set_theme_dir_transient( $dir = null ) {
666
 
667
- if ( is_bool( $dir ) && ( false === $dir || false === get_transient( $this->theme_doing_it_right_transient ) ) ) {
668
 
669
  //* Convert $dir to string 1 or 0 as transients can be false on failure.
670
  $dir = $dir ? '1' : '0';
671
 
672
- set_transient( $this->theme_doing_it_right_transient, $dir, 0 );
673
  }
674
-
675
- }
676
-
677
- /**
678
- * Flushes the home page LD+Json transient.
679
- *
680
- * @since 2.6.0
681
- * @staticvar bool $flushed Prevents second flush.
682
- *
683
- * @return bool Whether it's flushed on current call.
684
- */
685
- public function delete_front_ld_json_transient() {
686
-
687
- static $flushed = null;
688
-
689
- if ( isset( $flushed ) )
690
- return false;
691
-
692
- $front_id = $this->get_the_front_page_ID();
693
-
694
- $this->delete_ld_json_transient( $front_id, '', 'frontpage' );
695
-
696
- return $flushed = true;
697
  }
698
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Cache
28
  *
29
  * Generates, stores and deletes common transients.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Cache extends Sitemaps {
34
 
35
  /**
36
  * The sitemap transient name.
69
  protected $theme_doing_it_right_transient;
70
 
71
  /**
72
+ * Constructor, load parent constructor and set up caches.
73
  */
74
+ protected function __construct() {
75
+ parent::__construct();
76
+
77
+ //* Setup Transient names
78
+ add_action( 'plugins_loaded', array( $this, 'setup_transient_names' ), 10 );
79
+ }
80
 
81
  /**
82
+ * Determines whether object cache is being used.
83
+ *
84
+ * @since 2.8.0
85
+ * @see $this->use_object_cache
86
+ *
87
+ * @return bool
88
  */
89
+ protected function use_object_cache() {
90
+ return \wp_using_ext_object_cache() && $this->is_option_checked( 'cache_object' );
91
  }
92
 
93
  /**
94
+ * Initializes admin caching actions.
95
+ *
96
+ * @since 2.8.0
97
+ * @action init priority 1
98
+ * @see $this->init_admin_actions();
99
  */
100
+ public function init_admin_caching_actions() {
 
 
 
 
101
 
102
+ $this->init_post_cache_actions();
 
 
 
 
 
 
 
 
 
103
 
104
+ //* Deletes term description transient.
105
+ \add_action( 'edit_term', array( $this, 'delete_auto_description_transients_term' ), 10, 3 );
106
+ \add_action( 'delete_term', array( $this, 'delete_auto_description_transients_term' ), 10, 4 );
107
 
108
+ //* Deletes author transient.
109
+ \add_action( 'profile_update', array( $this, 'delete_author_cache' ) );
110
 
111
  //* Delete Sitemap transient on permalink structure change.
112
+ \add_action( 'load-options-permalink.php', array( $this, 'delete_sitemap_transient_permalink_updated' ), 20 );
113
 
114
  //* Deletes front page description transient on Tagline change.
115
+ \add_action( 'update_option_blogdescription', array( $this, 'delete_auto_description_frontpage_transient' ), 10, 1 );
116
 
117
+ //* Delete doing it wrong transient after theme switch or plugin upgrade.
118
+ \add_action( 'after_switch_theme', array( $this, 'delete_theme_dir_transient' ), 10, 0 );
119
+ \add_action( 'upgrader_process_complete', array( $this, 'delete_theme_dir_transient' ), 10, 2 );
120
+ }
121
 
122
+ /**
123
+ * Deletes Sitemap and Description transients on post publish/delete.
124
+ *
125
+ * @see WP Core wp_transition_post_status()
126
+ * @since 2.8.2
127
+ * @staticvar bool $run
128
+ * @action init priority 1
129
+ * @see $this->init_admin_actions();
130
+ * @see $this->init_cron_actions();
131
+ *
132
+ * @return void Early if already called.
133
+ */
134
+ public function init_post_cache_actions() {
135
+
136
+ static $run = false;
137
+
138
+ if ( $run )
139
+ return;
140
+
141
+ //* Can-be cron actions.
142
+ \add_action( 'publish_post', array( $this, 'delete_post_cache' ) );
143
+ \add_action( 'publish_page', array( $this, 'delete_post_cache' ) );
144
+
145
+ //* Other actions.
146
+ \add_action( 'deleted_post', array( $this, 'delete_post_cache' ) );
147
+ \add_action( 'deleted_page', array( $this, 'delete_post_cache' ) );
148
+ \add_action( 'post_updated', array( $this, 'delete_post_cache' ) );
149
+ \add_action( 'page_updated', array( $this, 'delete_post_cache' ) );
150
+
151
+ $run = true;
152
+ }
153
+
154
+ /**
155
+ * Flushes front-page and global transients that can be affected by options.
156
+ *
157
+ * @since 2.8.0
158
+ */
159
+ public function delete_main_cache() {
160
+ $this->delete_cache( 'front' );
161
+ $this->delete_cache( 'sitemap' );
162
+ $this->delete_cache( 'robots' );
163
+ }
164
+
165
+ /**
166
+ * Delete transient on post save.
167
+ *
168
+ * @since 2.8.0
169
+ *
170
+ * @param int $post_id The Post ID that has been updated.
171
+ * @return bool True on success, false on failure.
172
+ */
173
+ public function delete_post_cache( $post_id ) {
174
+
175
+ $success = array();
176
+
177
+ $success[] = $this->delete_cache( 'post', $post_id );
178
+
179
+ if ( $this->is_option_checked( 'sitemaps_output' ) ) {
180
+ //* Don't flush sitemap on revision.
181
+ if ( ! \wp_is_post_revision( $post_id ) )
182
+ $success[] = $this->delete_cache( 'sitemap' );
183
+ }
184
+
185
+ return ! in_array( false, $success, true );
186
+ }
187
+
188
+ /**
189
+ * Deletes cache on profile save.
190
+ *
191
+ * @since 2.8.0
192
+ *
193
+ * @param int $user_id The User ID that has been updated.
194
+ */
195
+ public function delete_author_cache( $user_id ) {
196
+ return $this->delete_cache( 'author', $user_id );
197
+ }
198
+
199
+ /**
200
+ * Handles all kinds of cache for removal.
201
+ * Main cache deletion function handler.
202
+ *
203
+ * @since 2.8.0
204
+ *
205
+ * @param string $type The type
206
+ * @param int $id The post, page or TT ID. Defaults to $this->get_the_real_ID().
207
+ * @param array $args Additional arguments. They can overwrite $type and $id.
208
+ * @return bool true on success, false on failure.
209
+ */
210
+ public function delete_cache( $type, $id = 0, array $args = array() ) {
211
+
212
+ $this->parse_delete_cache_keys( $type, $id, $args );
213
+
214
+ switch ( $type ) :
215
+ case 'front' :
216
+ $front_id = $this->get_the_front_page_ID();
217
+
218
+ $this->setup_auto_description_transient( $front_id, '', 'frontpage' );
219
+
220
+ $this->object_cache_delete( $this->get_meta_output_cache_key( $this->get_the_front_page_ID() ) );
221
+ $this->is_option_checked( 'cache_meta_schema' ) and $this->delete_ld_json_transient( $front_id, '', 'frontpage' );
222
+ $this->is_option_checked( 'cache_meta_description' ) and delete_transient( $this->auto_description_transient );
223
+ break;
224
+
225
+ case 'post' :
226
+ $this->object_cache_delete( $this->get_meta_output_cache_key( $id ) );
227
+ $this->delete_auto_description_transient( $id );
228
+ $this->delete_ld_json_transient( $id );
229
+ return true;
230
+ break;
231
+
232
+ //* Careful, this can only run on archive pages. For now.
233
+ case 'term' :
234
+ $this->object_cache_delete( $this->get_meta_output_cache_key( $id ) );
235
+ $this->delete_auto_description_transient( $id, $args['term'] );
236
+ $this->delete_ld_json_transient( $id, $args['term'] );
237
+ return true;
238
+ break;
239
+
240
+ case 'author' :
241
+ $this->object_cache_delete( $this->get_meta_output_cache_key( $id ) );
242
+ $this->delete_auto_description_transient( $id, 'author', 'author' );
243
+ return true;
244
+ break;
245
+
246
+ case 'sitemap' :
247
+ return $this->delete_sitemap_transient();
248
+ break;
249
+
250
+ case 'robots' :
251
+ return $this->object_cache_delete( $this->get_robots_txt_cache_key() );
252
+ break;
253
+
254
+ case 'detection' :
255
+ return $this->delete_theme_dir_transient();
256
+ break;
257
+
258
+ //* Flush all transients.
259
+ case 'transientflush' :
260
+ /**
261
+ * Applies filters 'the_seo_framework_allow_transient_flush' : boolean
262
+ * @since 2.8.0
263
+ * WARNING: Experimental and untested. Use at own risk.
264
+ */
265
+ if ( \apply_filters( 'the_seo_framework_allow_transient_flush', false ) ) {
266
+ if ( ! \wp_using_ext_object_cache() ) {
267
+ //* Delete WordPress set transients.
268
+ if ( $GLOBALS['wpdb']->delete( $wpdb->options, array( 'option_name' => '%_transient_timeout_tsf_%' ) ) )
269
+ if ( $GLOBALS['wpdb']->delete( $wpdb->options, array( 'option_name' => '%_transient_tsf_%' ) ) )
270
+ return true;
271
+ }
272
+ }
273
+ break;
274
+
275
+ /**
276
+ * Flush whole object cache group.
277
+ * Set here for external functions to use. It works because of magic methods.
278
+ */
279
+ case 'objectflush' :
280
+ if ( $this->use_object_cache ) {
281
+ if ( isset( $GLOBALS['wp_object_cache']->cache['the_seo_framework'] ) ) {
282
+ $_cache = $GLOBALS['wp_object_cache']->cache;
283
+ unset( $_cache['the_seo_framework'] );
284
+ $GLOBALS['wp_object_cache']->cache = $_cache;
285
+ return true;
286
+ }
287
+ }
288
+ break;
289
+
290
+ default :
291
+ break;
292
+ endswitch;
293
+
294
+ return false;
295
+ }
296
+
297
+ /**
298
+ * Parses input keys for method delete_cache.
299
+ *
300
+ * @since 2.8.0
301
+ *
302
+ * @param string $type The cache type. Passed by reference.
303
+ * @param int $id The post, page or TT ID. Defaults to $this->get_the_real_ID(). Passed by reference.
304
+ * @param array $args Additional arguments. They can overwrite $type and $id. Passed by reference.
305
+ */
306
+ protected function parse_delete_cache_keys( &$type, &$id, &$args ) {
307
+
308
+ $id = $id ?: $this->get_the_real_ID();
309
+
310
+ $defaults = array(
311
+ 'type' => $type,
312
+ 'id' => $id,
313
+ 'term' => '',
314
+ );
315
+
316
+ /**
317
+ * Applies filters 'the_seo_framework_delete_cache_args' : array
318
+ * Careful: might infinitely loop method delete_cache() if not done strictly.
319
+ *
320
+ * @since 2.8.0
321
+ *
322
+ * @param array $args
323
+ * @param string $type
324
+ * @param int $id
325
+ */
326
+ $args = (array) \apply_filters( 'the_seo_framework_delete_cache_args', $args, $type, $id );
327
+ $args = \wp_parse_args( $args, $defaults );
328
+
329
+ $type = $args['type'];
330
+ $id = $args['id'];
331
+ }
332
+
333
+ /**
334
+ * Set the value of the transient.
335
+ *
336
+ * Prevents setting of transients when they're disabled.
337
+ * @see $this->the_seo_framework_use_transients
338
+ *
339
+ * @since 2.6.0
340
+ *
341
+ * @param string $transient Transient name. Expected to not be SQL-escaped.
342
+ * @param string $value Transient value. Expected to not be SQL-escaped.
343
+ * @param int $expiration Optional Transient expiration date, optional. Expected to not be SQL-escaped.
344
+ */
345
+ public function set_transient( $transient, $value, $expiration = '' ) {
346
+
347
+ if ( $this->the_seo_framework_use_transients )
348
+ \set_transient( $transient, $value, $expiration );
349
  }
350
 
351
  /**
359
  * @since 2.6.0
360
  *
361
  * @param string $transient Transient name. Expected to not be SQL-escaped.
 
362
  * @return mixed|bool Value of the transient. False on failure or non existing transient.
363
  */
364
  public function get_transient( $transient ) {
365
 
366
  if ( $this->the_seo_framework_use_transients )
367
+ return \get_transient( $transient );
368
 
369
  return false;
370
  }
371
 
372
  /**
373
+ * Object cache set wrapper.
374
  *
375
+ * @since 2.4.3
 
376
  *
377
+ * @param string $key The Object cache key.
378
+ * @param mixed $data The Object cache data.
379
+ * @param int $expire The Object cache expire time.
380
+ * @param string $group The Object cache group.
381
+ * @return bool true on set, false when disabled.
382
+ */
383
+ public function object_cache_set( $key, $data, $expire = 0, $group = 'the_seo_framework' ) {
384
+
385
+ if ( $this->use_object_cache )
386
+ return \wp_cache_set( $key, $data, $group, $expire );
387
+
388
+ return false;
389
+ }
390
+
391
+ /**
392
+ * Object cache get wrapper.
393
  *
394
+ * @since 2.4.3
395
+ *
396
+ * @param string $key The Object cache key.
397
+ * @param string $group The Object cache group.
398
+ * @param bool $force Whether to force an update of the local cache.
399
+ * @param bool $found Whether the key was found in the cache. Disambiguates a return of false, a storable value. Passed by reference.
400
+ * @return mixed wp_cache_get if object caching is allowed. False otherwise.
401
  */
402
+ public function object_cache_get( $key, $group = 'the_seo_framework', $force = false, &$found = null ) {
403
 
404
+ if ( $this->use_object_cache )
405
+ return \wp_cache_get( $key, $group, $force, $found );
406
 
407
+ return false;
408
  }
409
 
410
  /**
411
+ * Object cache delete wrapper.
412
  *
413
+ * @since 2.8.0
414
+ *
415
+ * @param string $key The Object cache key.
416
+ * @param string $group The Object cache group.
417
+ * @return mixed wp_cache_delete if object caching is allowed. False otherwise.
418
+ */
419
+ public function object_cache_delete( $key, $group = 'the_seo_framework' ) {
420
+
421
+ if ( $this->use_object_cache )
422
+ return \wp_cache_delete( $key, $group );
423
+
424
+ return false;
425
+ }
426
+
427
+ /**
428
+ * Setup vars for general site transients.
429
  *
430
  * @since 2.3.3
431
+ * @since 2.8.0:
432
+ * 1. Added locale suffix.
433
+ * 2. Added check for option 'cache_sitemap'.
434
+ * @global int $blog_id
435
  */
436
  public function setup_transient_names() {
437
  global $blog_id;
440
  * When the caching mechanism changes. Change this value.
441
  * Use hex. e.g. 0, 1, 2, 9, a, b
442
  */
443
+ $sitemap_revision = '2';
444
+ $theme_dir_revision = '0';
445
 
446
+ $this->sitemap_transient = $this->is_option_checked( 'cache_sitemap' ) ? $this->add_cache_key_suffix( 'tsf_sitemap_' . $sitemap_revision ) : '';
447
+ $this->theme_doing_it_right_transient = 'tsf_tdir_' . $theme_dir_revision . '_' . $blog_id;
448
  }
449
 
450
  /**
451
  * Setup vars for transients which require $page_id.
452
  *
453
  * @since 2.3.3
454
+ * @since 2.8.0: Now listens to option 'cache_meta_description'.
455
  *
456
  * @param int|string|bool $page_id the Taxonomy or Post ID. If false it will generate for the blog page.
457
  * @param string $taxonomy The taxonomy name.
458
+ * @param string $type The Post Type
459
+ * @return void Early if caching is disabled.
460
  */
461
  public function setup_auto_description_transient( $page_id, $taxonomy = '', $type = null ) {
462
 
463
+ if ( false === $this->is_option_checked( 'cache_meta_description' ) )
464
+ return;
465
+
466
  $cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
467
 
468
  /**
471
  *
472
  * @since 2.3.4
473
  */
474
+ $revision = '2';
475
 
476
  $additions = $this->add_description_additions( $page_id, $taxonomy );
477
 
487
  * Setup vars for transients which require $page_id.
488
  *
489
  * @since 2.3.3
490
+ * @since 2.8.0: Now listens to option 'cache_meta_schema'.
491
  *
492
  * @param int|string|bool $page_id the Taxonomy or Post ID. If false it will generate for the blog page.
493
  * @param string $taxonomy The taxonomy name.
494
  * @param string|null $type The post type.
495
+ * @return void Early if caching is disabled.
496
  */
497
  public function setup_ld_json_transient( $page_id, $taxonomy = '', $type = null ) {
498
 
499
+ if ( false === $this->is_option_checked( 'cache_meta_schema' ) )
500
+ return;
501
+
502
  $cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
503
 
504
  /**
506
  *
507
  * Use hex. e.g. 0, 1, 2, 9, a, b
508
  */
509
+ $revision = '3';
510
 
511
  /**
512
  * Change key based on options.
534
  */
535
  public function generate_cache_key( $page_id, $taxonomy = '', $type = null ) {
536
 
537
+ $page_id = $page_id ?: $this->get_the_real_ID();
538
 
539
  if ( isset( $type ) ) {
540
  if ( 'author' === $type ) {
544
  //* Front/HomePage.
545
  return $this->add_cache_key_suffix( $this->generate_front_page_cache_key() );
546
  } else {
547
+ $this->_doing_it_wrong( __METHOD__, 'Third parameter must be a known type.', '2.6.5' );
548
+ return $this->add_cache_key_suffix( \esc_sql( $type . '_' . $page_id . '_' . $taxonomy ) );
549
  }
550
  }
551
 
580
  $query = '';
581
 
582
  if ( function_exists( 'get_search_query' ) ) {
583
+ $search_query = \get_search_query();
584
 
585
  if ( $search_query )
586
  $query = str_replace( ' ', '', $search_query );
589
  if ( mb_strlen( $query ) > 10 )
590
  $query = mb_substr( $query, 0, 10 );
591
 
592
+ $query = \esc_sql( $query );
593
  }
594
 
595
+ //* Temporarily disable caches to prevent database spam.
596
+ $this->the_seo_framework_use_transients = false;
597
+ $this->use_object_cache = false;
598
+
599
  $the_id = $page_id . '_s_' . $query;
600
  } elseif ( $this->is_archive() ) {
601
  if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
602
 
603
  if ( empty( $t ) ) {
604
+ $o = \get_queried_object();
605
 
606
  if ( isset( $o->taxonomy ) )
607
  $t = $o->taxonomy;
615
  } elseif ( $this->is_author() ) {
616
  $the_id = 'author_' . $page_id;
617
  } elseif ( $this->is_date() ) {
618
+ $post = \get_post();
619
 
620
  if ( $post && isset( $post->post_date ) ) {
621
  $date = $post->post_date;
622
 
623
  if ( $this->is_year() ) {
624
+ $the_id .= 'year_' . \mysql2date( 'y', $date, false );
625
  } elseif ( $this->is_month() ) {
626
+ $the_id .= 'month_' . \mysql2date( 'm_y', $date, false );
627
  } elseif ( $this->is_day() ) {
628
  //* Day. The correct notation.
629
+ $the_id .= 'day_' . \mysql2date( 'd_m_y', $date, false );
630
  }
631
  } else {
632
  //* Get seconds since UNIX Epoch. This is a failsafe.
649
  //* Other taxonomial archives.
650
 
651
  if ( empty( $t ) ) {
652
+ $post_type = \get_query_var( 'post_type' );
653
 
654
  if ( is_array( $post_type ) )
655
  reset( $post_type );
656
 
657
  if ( $post_type )
658
+ $post_type_obj = \get_post_type_object( $post_type );
659
 
660
  if ( isset( $post_type_obj->labels->name ) )
661
  $t = $post_type_obj->labels->name;
663
 
664
  //* Still empty? Try this.
665
  if ( empty( $t ) )
666
+ $t = \get_query_var( 'taxonomy' );
667
 
668
  $the_id = $this->generate_taxonomial_cache_key( $page_id, $t );
669
 
690
  * Adds cache key suffix based on blog id and locale.
691
  *
692
  * @since 2.7.0
693
+ * @since 2.8.0 $locale is now static.
694
+ * $key may now be empty.
695
+ * @staticvar string $locale
696
  *
697
  * @return string the cache key.
698
  */
699
+ protected function add_cache_key_suffix( $key = '' ) {
700
  global $blog_id;
701
 
702
+ static $locale = null;
703
+
704
+ if ( is_null( $locale ) )
705
+ $locale = strtolower( \get_locale() );
706
 
707
  return $key . '_' . $blog_id . '_' . $locale;
708
  }
711
  * Returns the front page partial transient key.
712
  *
713
  * @param string $type
 
714
  * @return string the front page transient key.
715
  */
716
  public function generate_front_page_cache_key( $type = '' ) {
722
  $type = 'blog';
723
  }
724
  } else {
725
+ $type = \esc_sql( $type );
726
  }
727
 
728
  return $the_id = 'h' . $type . '_' . $this->get_the_front_page_ID();
759
  if ( mb_strlen( $taxonomy ) >= 5 ) {
760
  $the_id = mb_substr( $taxonomy, 0, 5 );
761
  } else {
762
+ $the_id = \esc_sql( $taxonomy );
763
  }
764
  }
765
 
770
  }
771
 
772
  /**
773
+ * Returns the robots.txt object cache key.
774
  *
775
+ * @since 2.8.0
776
  *
777
+ * @return string The robots_txt cache key.
 
 
778
  */
779
+ public function get_robots_txt_cache_key() {
 
 
 
 
 
 
 
 
 
780
 
781
+ $revision = '1';
782
 
783
+ return $cache_key = 'robots_txt_output_' . $revision . $GLOBALS['blog_id'];
 
784
  }
785
 
786
  /**
787
+ * Returns the TSF meta output Object cache key.
788
  *
789
+ * @since 2.8.0
790
+ * @uses THE_SEO_FRAMEWORK_DB_VERSION as cache key buster.
791
  *
792
+ * @param int $id The ID. Defaults to $this->get_the_real_ID();
793
+ * @return string The TSF meta output cache key.
794
  */
795
+ public function get_meta_output_cache_key( $id = 0 ) {
796
+ /**
797
+ * Cache key buster.
798
+ * Busts cache on each new db version.
799
+ */
800
+ $key = $this->generate_cache_key( $id ) . '_' . THE_SEO_FRAMEWORK_DB_VERSION;
801
+
802
+ /**
803
+ * Give each paged pages/archives a different cache key.
804
+ * @since 2.2.6
805
+ */
806
+ $page = (string) $this->page();
807
+ $paged = (string) $this->paged();
808
+
809
+ return $cache_key = 'seo_framework_output_' . $key . '_' . $paged . '_' . $page;
810
  }
811
 
812
  /**
813
  * Delete transient on term save/deletion.
814
  *
815
+ * @since 2.3.3
816
+ *
817
  * @param int $term_id The Term ID
818
  * @param int $tt_id The Term Taxonomy ID.
819
  * @param string $taxonomy The Taxonomy type.
820
  * @param mixed $deleted_term Copy of the already-deleted term. Unused.
 
 
821
  */
822
  public function delete_auto_description_transients_term( $term_id, $tt_id, $taxonomy, $deleted_term = '' ) {
823
 
824
+ $term_id = $term_id ?: $tt_id;
825
 
826
+ $this->delete_cache( 'term', $term_id, array( 'term' => $taxonomy ) );
827
  }
828
 
829
  /**
830
  * Checks whether the permalink structure is updated.
831
  *
832
  * @since 2.3.0
833
+ * @since 2.7.0 : Added admin referer check.
834
  *
835
  * @return bool Whether if sitemap transient is deleted.
836
  */
837
  public function delete_sitemap_transient_permalink_updated() {
838
 
839
  if ( isset( $_POST['permalink_structure'] ) || isset( $_POST['category_base'] ) ) {
 
840
 
841
+ if ( check_admin_referer( 'update-permalink' ) )
842
+ return $this->delete_cache( 'sitemap' );
843
  }
844
 
845
  return false;
850
  * Also ping search engines.
851
  *
852
  * @since 2.2.9
853
+ * @since 2.8.0 : Mow listens to option 'cache_sitemap' before deleting transient.
854
+ * @since 2.8.2 : Added cache to prevent duplicated flushes.
855
+ * @staticvar bool $run
856
  *
857
+ * @return bool True on success, false on failure.
858
  */
859
  public function delete_sitemap_transient() {
860
 
861
+ static $run = false;
862
 
863
+ if ( $run )
864
+ return false;
865
+
866
+ $this->is_option_checked( 'cache_sitemap' ) and \delete_transient( $this->sitemap_transient );
867
  $this->ping_searchengines();
868
 
869
+ return $run = true;
870
  }
871
 
872
  /**
874
  * Returns old option, since that's passed for sanitation within WP Core.
875
  *
876
  * @since 2.3.3
877
+ * @since 2.8.0 : Now listens to option 'cache_meta_description' before deleting transient.
878
  *
879
  * @param string $old_option The previous blog description option.
880
  * @return string Previous option.
883
 
884
  $this->setup_auto_description_transient( $this->get_the_front_page_ID(), '', 'frontpage' );
885
 
886
+ $this->is_option_checked( 'cache_meta_description' ) and \delete_transient( $this->auto_description_transient );
887
 
888
  return $old_option;
889
  }
892
  * Delete transient for the automatic description on requests.
893
  *
894
  * @since 2.3.3
895
+ * @since 2.8.0 : Now listens to option 'cache_meta_description' before deleting transient.
896
  *
897
  * @param mixed $page_id The page ID or identifier.
898
  * @param string $taxonomy The tt name.
903
 
904
  $this->setup_auto_description_transient( $page_id, $taxonomy, $type );
905
 
906
+ $this->is_option_checked( 'cache_meta_description' ) and \delete_transient( $this->auto_description_transient );
907
 
908
  return true;
909
  }
912
  * Delete transient for the LD+Json scripts on requests.
913
  *
914
  * @since 2.4.2
915
+ * @since 2.8.0 : Now listens to option 'cache_meta_schema' before deleting transient.
916
  *
917
  * @param mixed $page_id The page ID or identifier.
918
  * @param string $taxonomy The tt name.
926
  if ( ! isset( $flushed ) ) {
927
  $this->setup_ld_json_transient( $page_id, $taxonomy, $type );
928
 
929
+ $this->is_option_checked( 'cache_meta_schema' ) and \delete_transient( $this->ld_json_transient );
930
 
931
  $flushed = 'Oh behave!';
932
 
940
  * Delete transient for the Theme doing it Right bool on special requests.
941
  *
942
  * @since 2.5.2
943
+ * @since 2.7.0 : ???
944
+ *
945
+ * @NOTE: Ignores transient debug constant and options.
946
  *
947
  * @param string|object $value The theme directory stylesheet location, or either WP_Theme/WP_Upgrader instance.
948
  * @param array|object|null $options If set, the update options array or the Old theme WP_Theme instance.
955
  return false;
956
  }
957
 
958
+ \delete_transient( $this->theme_doing_it_right_transient );
959
 
960
  return true;
961
  }
964
  * Sets transient for Theme doing it Right.
965
  *
966
  * @since 2.5.2
967
+ * @since 2.7.0 : Will always set "doing it wrong" transient, even if it was "doing it right" earlier.
968
  *
969
+ * @NOTE: Ignores transient debug constant and options.
970
  *
971
  * @param bool $doing_it_right
972
  */
973
  public function set_theme_dir_transient( $dir = null ) {
974
 
975
+ if ( is_bool( $dir ) && ( false === $dir || false === \get_transient( $this->theme_doing_it_right_transient ) ) ) {
976
 
977
  //* Convert $dir to string 1 or 0 as transients can be false on failure.
978
  $dir = $dir ? '1' : '0';
979
 
980
+ \set_transient( $this->theme_doing_it_right_transient, $dir, 0 );
981
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
982
  }
983
  }
inc/classes/compat.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,95 +23,103 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Compat
23
  *
24
  * Adds theme/plugin compatibility.
25
  *
26
- * @since 2.6.0
27
  */
28
- class AutoDescription_Compat extends AutoDescription_Debug {
29
-
30
- /**
31
- * Unserializing instances of this class is forbidden.
32
- */
33
- private function __wakeup() { }
34
-
35
- /**
36
- * Handle unapproachable invoked methods.
37
- */
38
- public function __call( $name, $arguments ) {
39
- parent::__call( $name, $arguments );
40
- }
41
 
42
  /**
43
  * Constructor, load parent constructor
44
  */
45
- public function __construct() {
46
  parent::__construct();
47
 
48
- //* Genesis compat.
49
- add_action( 'init', array( $this, 'genesis_compat' ) );
50
- add_filter( 'genesis_detect_seo_plugins', array( $this, 'no_more_genesis_seo' ), 10 );
51
-
52
- //* Headway compat.
53
- add_filter( 'headway_seo_disabled', '__return_true' );
54
 
55
  //* Jetpack compat.
56
- add_action( 'init', array( $this, 'jetpack_compat' ) );
57
-
58
- //* BuddyPress compat.
59
- add_action( 'init', array( $this, 'buddypress_compat' ) );
60
 
 
 
61
  }
62
 
63
  /**
64
- * Adds Genesis SEO compatibility.
 
 
65
  *
66
- * @since 2.6.0
67
- * @access private
68
  */
69
- public function genesis_compat() {
70
 
71
- //* Nothing to do on admin.
72
- if ( $this->is_admin() )
73
- return;
74
 
75
- //* Reverse the removal of head attributes, this shouldn't affect SEO.
76
- remove_filter( 'genesis_attr_head', 'genesis_attributes_empty_class' );
77
- add_filter( 'genesis_attr_head', 'genesis_attributes_head' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
 
 
 
 
 
 
 
 
 
79
  }
80
 
81
  /**
82
- * Removes the Genesis SEO meta boxes on the SEO Settings page
83
  *
84
- * @since 2.2.4
85
  * @access private
 
86
  *
87
- * @param array $plugins, overwritten as this filter will fire the
88
- * detection, regardless of other SEO plugins.
89
- * @return array Plugins to detect.
90
  */
91
- public function no_more_genesis_seo( $plugins ) {
 
 
92
 
93
- $plugins = array(
94
- 'classes' => array(
95
- 'The_SEO_Framework_Load',
96
- ),
97
- 'functions' => array(),
98
- 'constants' => array(),
99
- );
100
 
101
- return $plugins;
102
  }
103
 
104
  /**
105
  * Adds compatibility with various JetPack modules.
106
  *
107
- * Recently, JetPack made sure this filter doesn't run when The SEO Framework
108
  * is active as they've added their own compatibility check towards this plugin.
109
  * Let's wait until everyone has updated before removing this.
110
  *
@@ -115,23 +130,7 @@ class AutoDescription_Compat extends AutoDescription_Debug {
115
 
116
  if ( $this->use_og_tags() ) {
117
  //* Disable Jetpack Publicize's Open Graph.
118
- add_filter( 'jetpack_enable_open_graph', '__return_false', 99 );
119
  }
120
  }
121
-
122
- /**
123
- * Removes canonical URL from BuddyPress. Regardless of The SEO Framework settings.
124
- *
125
- * @since 2.7.0
126
- * @access private
127
- */
128
- public function buddypress_compat() {
129
-
130
- //* Nothing to do on admin.
131
- if ( $this->is_admin() )
132
- return;
133
-
134
- remove_action( 'wp_head', '_bp_maybe_remove_rel_canonical', 8 );
135
-
136
- }
137
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Compat
28
  *
29
  * Adds theme/plugin compatibility.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Compat extends Core {
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  /**
36
  * Constructor, load parent constructor
37
  */
38
+ protected function __construct() {
39
  parent::__construct();
40
 
41
+ //* Disable Headway SEO.
42
+ \add_filter( 'headway_seo_disabled', '__return_true' );
 
 
 
 
43
 
44
  //* Jetpack compat.
45
+ \add_action( 'init', array( $this, 'jetpack_compat' ) );
 
 
 
46
 
47
+ //* BuddyPress front-end compat.
48
+ \remove_action( 'wp_head', '_bp_maybe_remove_rel_canonical', 8 );
49
  }
50
 
51
  /**
52
+ * Requires compatibility files which are needed early or on every page.
53
+ * Mostly requires premium plugins/themes, so we check actual PHP instances,
54
+ * rather than common paths. As they can require manual FTP upload.
55
  *
56
+ * @since 2.8.0
 
57
  */
58
+ protected function load_early_compat_files() {
59
 
60
+ if ( ! extension_loaded( 'mbstring' ) ) {
61
+ $this->_include_compat( 'mbstring', 'php' );
62
+ }
63
 
64
+ if ( $this->is_theme( 'genesis' ) ) {
65
+ //* Genesis Framework
66
+ $this->_include_compat( 'genesis', 'theme' );
67
+ }
68
+
69
+ if ( defined( 'DOMAIN_MAPPING' ) ) {
70
+ if ( $this->detect_plugin( array( 'functions' => array( 'redirect_to_mapped_domain' ) ) ) ) {
71
+ //* Donncha domain mapping.
72
+ $this->_include_compat( 'donncha-dm', 'plugin' );
73
+ } elseif ( $this->detect_plugin( array( 'functions' => array( 'domainmap_launch' ) ) ) ) {
74
+ //* WPMUdev domain mapping.
75
+ $this->_include_compat( 'wpmudev-dm', 'plugin' );
76
+ }
77
+ }
78
+
79
+ if ( $this->detect_plugin( array( 'constants' => array( 'ICL_LANGUAGE_CODE' ) ) ) ) {
80
+ //* WPML
81
+ $this->_include_compat( 'wpml', 'plugin' );
82
+ } elseif ( $this->detect_plugin( array( 'constants' => array( 'QTX_VERSION' ) ) ) ) {
83
+ //* qTranslate X
84
+ $this->_include_compat( 'qtranslatex', 'plugin' );
85
+ }
86
 
87
+ if ( $this->detect_plugin( array( 'globals' => array( 'ultimatemember' ) ) ) ) {
88
+ //* Ultimate Member
89
+ $this->_include_compat( 'ultimatemember', 'plugin' );
90
+ }
91
+
92
+ if ( $this->detect_plugin( array( 'functions' => array( 'bbpress' ) ) ) ) {
93
+ //* bbPress
94
+ $this->_include_compat( 'bbpress', 'plugin' );
95
+ }
96
  }
97
 
98
  /**
99
+ * Includes compatibility files.
100
  *
101
+ * @since 2.8.0
102
  * @access private
103
+ * @staticvar array $included Maintains cache of whether files have been loaded.
104
  *
105
+ * @param string $what The vendor/plugin/theme name for the compatibilty.
106
+ * @param string $type The compatibility type. Be it 'plugin' or 'theme'.
107
+ * @return bool True on success, false on failure. Files are expected not to return any values.
108
  */
109
+ public function _include_compat( $what, $type = 'plugin' ) {
110
+
111
+ static $included = array();
112
 
113
+ isset( $included[ $what ][ $type ] )
114
+ or $included[ $what ][ $type ] = (bool) require_once( THE_SEO_FRAMEWORK_DIR_PATH_COMPAT . $type . '-' . $what . '.php' );
 
 
 
 
 
115
 
116
+ return $included[ $what ][ $type ];
117
  }
118
 
119
  /**
120
  * Adds compatibility with various JetPack modules.
121
  *
122
+ * Recently, JetPack (4.0) made sure this filter doesn't run when The SEO Framework
123
  * is active as they've added their own compatibility check towards this plugin.
124
  * Let's wait until everyone has updated before removing this.
125
  *
130
 
131
  if ( $this->use_og_tags() ) {
132
  //* Disable Jetpack Publicize's Open Graph.
133
+ \add_filter( 'jetpack_enable_open_graph', '__return_false', 99 );
134
  }
135
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  }
inc/classes/core.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,37 +23,60 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Core
23
  *
24
  * Initializes the plugin & Holds plugin core functions.
25
  *
26
- * @since 2.6.0
27
  */
28
- class AutoDescription_Core {
29
 
30
  /**
31
- * Unserializing instances of this class is forbidden.
32
  */
33
- private function __wakeup() { }
34
 
35
  /**
36
- * Cloning of this class is forbidden.
37
  */
38
- private function __clone() { }
39
 
40
  /**
41
- * __get() deprecation handler.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  * @since 2.7.0
43
- * @return mixed $var The object variable.
 
 
44
  */
45
- public function __get( $name ) {
46
 
47
  switch ( $name ) :
48
  case 'pagehook' :
49
- $this->_deprecated_function( 'the_seo_framework()->' . esc_html( $name ), '2.7.0', 'the_seo_framework()->seo_settings_page_hook' );
50
  return $this->seo_settings_page_hook;
51
  break;
52
 
@@ -54,17 +84,29 @@ class AutoDescription_Core {
54
  break;
55
  endswitch;
56
 
57
- //* Invoke default error.
58
  return $this->$name;
59
  }
60
 
61
  /**
62
- * Handle unapproachable invoked methods.
 
 
 
63
  * @return void
64
  */
65
- public function __call( $name, $arguments ) {
66
- $_this = the_seo_framework();
67
- $_this->_inaccessible_p_or_m( 'the_seo_framework()->' . esc_html( $name ) . '()' );
 
 
 
 
 
 
 
 
 
68
  return;
69
  }
70
 
@@ -72,22 +114,45 @@ class AutoDescription_Core {
72
  * Constructor. Loads actions and filters.
73
  * Latest Class. Doesn't have parent.
74
  */
75
- public function __construct() {
76
 
77
- add_action( 'current_screen', array( $this, 'post_type_support' ), 0 );
78
 
79
- /**
80
- * Add plugin links to the plugin activation page.
81
- * @since 2.2.8
82
- */
83
- add_filter( 'plugin_action_links_' . THE_SEO_FRAMEWORK_PLUGIN_BASENAME, array( $this, 'plugin_action_links' ), 10, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
 
 
 
 
 
 
85
  }
86
 
87
  /**
88
  * Fetches files based on input to reduce memory overhead.
89
  * Passes on input vars.
90
  *
 
 
 
91
  * @param string $view The file name.
92
  * @param array $args The arguments to be supplied within the file name.
93
  * Each array key is converted to a variable with its value attached.
@@ -95,7 +160,7 @@ class AutoDescription_Core {
95
  *
96
  * @credits Akismet For some code.
97
  */
98
- protected function get_view( $view, array $args = array(), $instance = 'main' ) {
99
 
100
  foreach ( $args as $key => $val )
101
  $$key = $val;
@@ -108,6 +173,8 @@ class AutoDescription_Core {
108
  /**
109
  * Fetches view instance for switch.
110
  *
 
 
111
  * @param string $base The instance basename (namespace).
112
  * @param string $instance The instance suffix to call back upon.
113
  * @return string The file instance case.
@@ -120,12 +187,11 @@ class AutoDescription_Core {
120
  * Proportionate dimensions based on Width and Height.
121
  * AKA Aspect Ratio.
122
  *
 
 
123
  * @param int $i The dimension to resize.
124
  * @param int $r1 The deminsion that determines the ratio.
125
  * @param int $r2 The dimension to proportionate to.
126
- *
127
- * @since 2.6.0
128
- *
129
  * @return int The proportional dimension, rounded.
130
  */
131
  public function proportionate_dimensions( $i, $r1, $r2 ) {
@@ -140,9 +206,6 @@ class AutoDescription_Core {
140
  /**
141
  * Adds post type support for The SEO Framework.
142
  *
143
- * Applies filters the_seo_framework_supported_post_types : The supported post types.
144
- * @since 2.3.1
145
- *
146
  * @since 2.1.6
147
  */
148
  public function post_type_support() {
@@ -157,12 +220,16 @@ class AutoDescription_Core {
157
  'jetpack-portfolio',
158
  );
159
 
160
- $post_types = (array) apply_filters( 'the_seo_framework_supported_post_types', $defaults );
 
 
 
 
161
 
162
- $types = wp_parse_args( $defaults, $post_types );
163
 
164
  foreach ( $types as $type )
165
- add_post_type_support( $type, array( 'autodescription-meta' ) );
166
 
167
  }
168
 
@@ -178,9 +245,9 @@ class AutoDescription_Core {
178
  $tsf_links = array();
179
 
180
  if ( $this->load_options )
181
- $tsf_links['settings'] = '<a href="' . esc_url( admin_url( 'admin.php?page=' . $this->seo_settings_page_slug ) ) . '">' . esc_html__( 'SEO Settings', 'autodescription' ) . '</a>';
182
 
183
- $tsf_links['home'] = '<a href="' . esc_url( 'https://theseoframework.com/' ) . '" target="_blank">' . esc_html_x( 'Plugin Home', 'As in: The Plugin Home Page', 'autodescription' ) . '</a>';
184
 
185
  return array_merge( $tsf_links, $links );
186
  }
@@ -199,7 +266,7 @@ class AutoDescription_Core {
199
  if ( isset( $front_id ) )
200
  return $front_id;
201
 
202
- return $front_id = $this->has_page_on_front() ? (int) get_option( 'page_on_front' ) : 0;
203
  }
204
 
205
  /**
@@ -220,7 +287,7 @@ class AutoDescription_Core {
220
  return '';
221
 
222
  if ( $escape )
223
- $message = esc_html( $message );
224
 
225
  //* Make sure the scripts are loaded.
226
  $this->init_admin_scripts( true );
@@ -230,8 +297,8 @@ class AutoDescription_Core {
230
 
231
  $a11y = $a11y ? 'tsf-show-icon' : '';
232
 
233
- $notice = '<div class="notice ' . esc_attr( $type ) . ' tsf-notice ' . $a11y . '"><p>';
234
- $notice .= '<a class="hide-if-no-js tsf-dismiss" title="' . esc_attr__( 'Dismiss', 'AutoDescription' ) . '"></a>';
235
  $notice .= '<strong>' . $message . '</strong>';
236
  $notice .= '</p></div>';
237
 
@@ -249,7 +316,7 @@ class AutoDescription_Core {
249
  * @param bool $escape Whether to escape the whole output.
250
  */
251
  public function do_dismissible_notice( $message = '', $type = 'updated', $a11y = true, $escape = true ) {
252
- echo $this->generate_dismissible_notice( $message, $type, $a11y, $escape );
253
  }
254
 
255
  /**
@@ -262,7 +329,7 @@ class AutoDescription_Core {
262
  * @return string Content wrapped in code tags.
263
  */
264
  public function code_wrap( $content ) {
265
- return $this->code_wrap_noesc( esc_html( $content ) );
266
  }
267
 
268
  /**
@@ -289,7 +356,7 @@ class AutoDescription_Core {
289
  * @return string Content wrapped int he description wrap.
290
  */
291
  public function description( $content, $block = true ) {
292
- $this->description_noesc( esc_html( $content ), $block );
293
  }
294
 
295
  /**
@@ -302,47 +369,10 @@ class AutoDescription_Core {
302
  * @return string Content wrapped int he description wrap.
303
  */
304
  public function description_noesc( $content, $block = true ) {
 
305
  $output = '<span class="description">' . $content . '</span>';
306
  echo $block ? '<p>' . $output . '</p>' : $output;
307
- }
308
-
309
- /**
310
- * Return custom field post meta data.
311
- *
312
- * Return only the first value of custom field. Return false if field is
313
- * blank or not set.
314
- *
315
- * @since 2.0.0
316
- * @staticvar array $field_cache
317
- *
318
- * @param string $field Custom field key.
319
- * @param int $post_id The post ID
320
- * @return string|boolean Return value or false on failure.
321
- */
322
- public function get_custom_field( $field, $post_id = null ) {
323
 
324
- //* If field is falsy, get_post_meta() will return an array.
325
- if ( ! $field )
326
- return false;
327
-
328
- static $field_cache = array();
329
-
330
- if ( isset( $field_cache[ $field ][ $post_id ] ) )
331
- return $field_cache[ $field ][ $post_id ];
332
-
333
- if ( empty( $post_id ) )
334
- $post_id = $this->get_the_real_ID();
335
-
336
- $custom_field = get_post_meta( $post_id, $field, true );
337
-
338
- //* If custom field is empty, empty cache..
339
- if ( empty( $custom_field ) )
340
- $field_cache[ $field ][ $post_id ] = '';
341
-
342
- //* Render custom field, slashes stripped, sanitized if string
343
- $field_cache[ $field ][ $post_id ] = is_array( $custom_field ) ? stripslashes_deep( $custom_field ) : stripslashes( wp_kses_decode_entities( $custom_field ) );
344
-
345
- return $field_cache[ $field ][ $post_id ];
346
  }
347
 
348
  /**
@@ -365,7 +395,7 @@ class AutoDescription_Core {
365
  return $language;
366
 
367
  //* Language shorttag to be used in Google help pages.
368
- $language = esc_html_x( 'en', 'e.g. en for English, nl for Dutch, fi for Finish, de for German', 'autodescription' );
369
 
370
  return $language;
371
  }
@@ -389,45 +419,7 @@ class AutoDescription_Core {
389
  * Applies filters the_seo_framework_allow_external_redirect : bool
390
  * @since 2.1.0
391
  */
392
- return $allowed = (bool) apply_filters( 'the_seo_framework_allow_external_redirect', true );
393
- }
394
-
395
- /**
396
- * Object cache set wrapper.
397
- *
398
- * @since 2.4.3
399
- *
400
- * @param string $key The Object cache key.
401
- * @param mixed $data The Object cache data.
402
- * @param int $expire The Object cache expire time.
403
- * @param string $group The Object cache group.
404
- * @return bool true on set, false when disabled.
405
- */
406
- public function object_cache_set( $key, $data, $expire = 0, $group = 'the_seo_framework' ) {
407
-
408
- if ( $this->use_object_cache )
409
- return wp_cache_set( $key, $data, $group, $expire );
410
-
411
- return false;
412
- }
413
-
414
- /**
415
- * Object cache get wrapper.
416
- *
417
- * @since 2.4.3
418
- *
419
- * @param string $key The Object cache key.
420
- * @param string $group The Object cache group.
421
- * @param bool $force Whether to force an update of the local cache.
422
- * @param bool $found Whether the key was found in the cache. Disambiguates a return of false, a storable value.
423
- * @return mixed wp_cache_get if object caching is allowed. False otherwise.
424
- */
425
- public function object_cache_get( $key, $group = 'the_seo_framework', $force = false, &$found = null ) {
426
-
427
- if ( $this->use_object_cache )
428
- return wp_cache_get( $key, $group, $force, $found );
429
-
430
- return false;
431
  }
432
 
433
  /**
@@ -479,7 +471,7 @@ class AutoDescription_Core {
479
  if ( isset( $cache ) )
480
  return $cache;
481
 
482
- if ( '1' === get_option( 'blog_public' ) )
483
  return $cache = true;
484
 
485
  return $cache = false;
@@ -534,7 +526,7 @@ class AutoDescription_Core {
534
  * @return string The minimum required capability for SEO Settings.
535
  */
536
  public function settings_capability() {
537
- return (string) apply_filters( 'the_seo_framework_settings_capability', 'manage_options' );
538
  }
539
 
540
  /**
@@ -549,9 +541,9 @@ class AutoDescription_Core {
549
  if ( $this->load_options ) {
550
  //* Options are allowed to be loaded.
551
 
552
- $url = html_entity_decode( menu_page_url( $this->seo_settings_page_slug, 0 ) );
553
 
554
- return esc_url( $url );
555
  }
556
 
557
  return '';
@@ -569,13 +561,13 @@ class AutoDescription_Core {
569
  */
570
  public function get_timezone_string( $guess = false ) {
571
 
572
- $tzstring = get_option( 'timezone_string' );
573
 
574
  if ( false !== strpos( $tzstring, 'Etc/GMT' ) )
575
  $tzstring = '';
576
 
577
  if ( $guess && empty( $tzstring ) ) {
578
- $offset = get_option( 'gmt_offset' );
579
  $tzstring = $this->get_tzstring_from_offset( $offset );
580
  }
581
 
@@ -685,13 +677,12 @@ class AutoDescription_Core {
685
 
686
  $words_too_many = array();
687
 
688
- if ( is_array( $words ) ) {
689
-
690
  /**
691
  * Applies filters 'the_seo_framework_bother_me_desc_length' : int Min Character length to bother you with.
692
  * @since 2.6.0
693
  */
694
- $bother_me_length = (int) apply_filters( 'the_seo_framework_bother_me_desc_length', $bother_length );
695
 
696
  $word_count = array_count_values( $words );
697
 
@@ -709,7 +700,7 @@ class AutoDescription_Core {
709
  }
710
 
711
  if ( $run ) {
712
- //* The encoded word is longer or equal to the bother lenght.
713
 
714
  $word_len = mb_strlen( $word );
715
 
@@ -721,8 +712,194 @@ class AutoDescription_Core {
721
  }
722
  }
723
  }
724
- }
725
 
726
  return $words_too_many;
727
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
728
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Core
28
  *
29
  * Initializes the plugin & Holds plugin core functions.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Core {
34
 
35
  /**
36
+ * Unserializing instances of this object is forbidden.
37
  */
38
+ final protected function __wakeup() { }
39
 
40
  /**
41
+ * Cloning of this object is forbidden.
42
  */
43
+ final protected function __clone() { }
44
 
45
  /**
46
+ * Handles unapproachable invoked properties.
47
+ * Makes sure deprecated properties are still overwritten.
48
+ * If property never existed, default PHP behavior is invoked.
49
+ *
50
+ * @since 2.8.0
51
+ *
52
+ * @param string $name The property name.
53
+ * @param mixed $value The property value.
54
+ */
55
+ final public function __set( $name, $value ) {
56
+ /**
57
+ * For now, no deprecation is being handled; as no properties are deprecated.
58
+ */
59
+ $this->_deprecated_function( 'the_seo_framework()->' . \esc_html( $name ), 'unknown' );
60
+
61
+ //* Invoke default behavior.
62
+ $this->$name = $value;
63
+ }
64
+
65
+ /**
66
+ * Handles unapproachable invoked properties.
67
+ * Makes sure deprecated properties are still accessible.
68
+ * If property never existed, default PHP behavior is invoked.
69
+ *
70
  * @since 2.7.0
71
+ *
72
+ * @param string $name The property name.
73
+ * @return mixed $var The property value.
74
  */
75
+ final public function __get( $name ) {
76
 
77
  switch ( $name ) :
78
  case 'pagehook' :
79
+ $this->_deprecated_function( 'the_seo_framework()->' . \esc_html( $name ), '2.7.0', 'the_seo_framework()->seo_settings_page_hook' );
80
  return $this->seo_settings_page_hook;
81
  break;
82
 
84
  break;
85
  endswitch;
86
 
87
+ //* Invoke default behavior.
88
  return $this->$name;
89
  }
90
 
91
  /**
92
+ * Handles unapproachable invoked methods.
93
+ *
94
+ * @param string $name The method name.
95
+ * @param array $arguments The method arguments.
96
  * @return void
97
  */
98
+ final public function __call( $name, $arguments ) {
99
+
100
+ static $depr_class = null;
101
+
102
+ if ( is_null( $depr_class ) )
103
+ $depr_class = new Deprecated;
104
+
105
+ if ( is_callable( array( $depr_class, $name ) ) ) {
106
+ return call_user_func_array( array( $depr_class, $name ), $arguments );
107
+ }
108
+
109
+ \the_seo_framework()->_inaccessible_p_or_m( 'the_seo_framework()->' . \esc_html( $name ) . '()' );
110
  return;
111
  }
112
 
114
  * Constructor. Loads actions and filters.
115
  * Latest Class. Doesn't have parent.
116
  */
117
+ protected function __construct() {
118
 
119
+ \add_action( 'current_screen', array( $this, 'post_type_support' ), 0 );
120
 
121
+ if ( $this->the_seo_framework_debug ) {
122
+
123
+ $debug_instance = \The_SEO_Framework\Debug::get_instance();
124
+
125
+ \add_action( 'the_seo_framework_do_before_output', array( $debug_instance, 'set_debug_query_output_cache' ) );
126
+ \add_action( 'admin_footer', array( $debug_instance, 'debug_screens' ) );
127
+ \add_action( 'admin_footer', array( $debug_instance, 'debug_output' ) );
128
+ \add_action( 'wp_footer', array( $debug_instance, 'debug_output' ) );
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Destroys output buffer, if any. To be used with AJAX and XML to clear any PHP errors or dumps.
134
+ *
135
+ * @since 2.8.0
136
+ *
137
+ * @return bool True on clear. False otherwise.
138
+ */
139
+ protected function clean_reponse_header() {
140
 
141
+ if ( ob_get_level() && ob_get_contents() ) {
142
+ ob_clean();
143
+ return true;
144
+ }
145
+
146
+ return false;
147
  }
148
 
149
  /**
150
  * Fetches files based on input to reduce memory overhead.
151
  * Passes on input vars.
152
  *
153
+ * @since 2.7.0
154
+ * @access private
155
+ *
156
  * @param string $view The file name.
157
  * @param array $args The arguments to be supplied within the file name.
158
  * Each array key is converted to a variable with its value attached.
160
  *
161
  * @credits Akismet For some code.
162
  */
163
+ public function get_view( $view, array $args = array(), $instance = 'main' ) {
164
 
165
  foreach ( $args as $key => $val )
166
  $$key = $val;
173
  /**
174
  * Fetches view instance for switch.
175
  *
176
+ * @since 2.7.0
177
+ *
178
  * @param string $base The instance basename (namespace).
179
  * @param string $instance The instance suffix to call back upon.
180
  * @return string The file instance case.
187
  * Proportionate dimensions based on Width and Height.
188
  * AKA Aspect Ratio.
189
  *
190
+ * @since 2.6.0
191
+ *
192
  * @param int $i The dimension to resize.
193
  * @param int $r1 The deminsion that determines the ratio.
194
  * @param int $r2 The dimension to proportionate to.
 
 
 
195
  * @return int The proportional dimension, rounded.
196
  */
197
  public function proportionate_dimensions( $i, $r1, $r2 ) {
206
  /**
207
  * Adds post type support for The SEO Framework.
208
  *
 
 
 
209
  * @since 2.1.6
210
  */
211
  public function post_type_support() {
220
  'jetpack-portfolio',
221
  );
222
 
223
+ /*
224
+ * Applies filters the_seo_framework_supported_post_types : Array The supported post types.
225
+ * @since 2.3.1
226
+ */
227
+ $post_types = (array) \apply_filters( 'the_seo_framework_supported_post_types', $defaults );
228
 
229
+ $types = \wp_parse_args( $defaults, $post_types );
230
 
231
  foreach ( $types as $type )
232
+ \add_post_type_support( $type, array( 'autodescription-meta' ) );
233
 
234
  }
235
 
245
  $tsf_links = array();
246
 
247
  if ( $this->load_options )
248
+ $tsf_links['settings'] = '<a href="' . \esc_url( \admin_url( 'admin.php?page=' . $this->seo_settings_page_slug ) ) . '">' . \esc_html__( 'SEO Settings', 'autodescription' ) . '</a>';
249
 
250
+ $tsf_links['home'] = '<a href="' . \esc_url( 'https://theseoframework.com/' ) . '" target="_blank">' . \esc_html_x( 'Plugin Home', 'As in: The Plugin Home Page', 'autodescription' ) . '</a>';
251
 
252
  return array_merge( $tsf_links, $links );
253
  }
266
  if ( isset( $front_id ) )
267
  return $front_id;
268
 
269
+ return $front_id = $this->has_page_on_front() ? (int) \get_option( 'page_on_front' ) : 0;
270
  }
271
 
272
  /**
287
  return '';
288
 
289
  if ( $escape )
290
+ $message = \esc_html( $message );
291
 
292
  //* Make sure the scripts are loaded.
293
  $this->init_admin_scripts( true );
297
 
298
  $a11y = $a11y ? 'tsf-show-icon' : '';
299
 
300
+ $notice = '<div class="notice ' . \esc_attr( $type ) . ' tsf-notice ' . $a11y . '"><p>';
301
+ $notice .= '<a class="hide-if-no-js tsf-dismiss" title="' . \esc_attr__( 'Dismiss', 'AutoDescription' ) . '"></a>';
302
  $notice .= '<strong>' . $message . '</strong>';
303
  $notice .= '</p></div>';
304
 
316
  * @param bool $escape Whether to escape the whole output.
317
  */
318
  public function do_dismissible_notice( $message = '', $type = 'updated', $a11y = true, $escape = true ) {
319
+ echo $this->generate_dismissible_notice( $message, $type, (bool) $a11y, (bool) $escape );
320
  }
321
 
322
  /**
329
  * @return string Content wrapped in code tags.
330
  */
331
  public function code_wrap( $content ) {
332
+ return $this->code_wrap_noesc( \esc_html( $content ) );
333
  }
334
 
335
  /**
356
  * @return string Content wrapped int he description wrap.
357
  */
358
  public function description( $content, $block = true ) {
359
+ $this->description_noesc( \esc_html( $content ), $block );
360
  }
361
 
362
  /**
369
  * @return string Content wrapped int he description wrap.
370
  */
371
  public function description_noesc( $content, $block = true ) {
372
+
373
  $output = '<span class="description">' . $content . '</span>';
374
  echo $block ? '<p>' . $output . '</p>' : $output;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
  }
377
 
378
  /**
395
  return $language;
396
 
397
  //* Language shorttag to be used in Google help pages.
398
+ $language = \esc_html_x( 'en', 'e.g. en for English, nl for Dutch, fi for Finish, de for German', 'autodescription' );
399
 
400
  return $language;
401
  }
419
  * Applies filters the_seo_framework_allow_external_redirect : bool
420
  * @since 2.1.0
421
  */
422
+ return $allowed = (bool) \apply_filters( 'the_seo_framework_allow_external_redirect', true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
  }
424
 
425
  /**
471
  if ( isset( $cache ) )
472
  return $cache;
473
 
474
+ if ( '1' === \get_option( 'blog_public' ) )
475
  return $cache = true;
476
 
477
  return $cache = false;
526
  * @return string The minimum required capability for SEO Settings.
527
  */
528
  public function settings_capability() {
529
+ return (string) \apply_filters( 'the_seo_framework_settings_capability', 'manage_options' );
530
  }
531
 
532
  /**
541
  if ( $this->load_options ) {
542
  //* Options are allowed to be loaded.
543
 
544
+ $url = html_entity_decode( \menu_page_url( $this->seo_settings_page_slug, false ) );
545
 
546
+ return \esc_url( $url );
547
  }
548
 
549
  return '';
561
  */
562
  public function get_timezone_string( $guess = false ) {
563
 
564
+ $tzstring = \get_option( 'timezone_string' );
565
 
566
  if ( false !== strpos( $tzstring, 'Etc/GMT' ) )
567
  $tzstring = '';
568
 
569
  if ( $guess && empty( $tzstring ) ) {
570
+ $offset = \get_option( 'gmt_offset' );
571
  $tzstring = $this->get_tzstring_from_offset( $offset );
572
  }
573
 
677
 
678
  $words_too_many = array();
679
 
680
+ if ( is_array( $words ) ) :
 
681
  /**
682
  * Applies filters 'the_seo_framework_bother_me_desc_length' : int Min Character length to bother you with.
683
  * @since 2.6.0
684
  */
685
+ $bother_me_length = (int) \apply_filters( 'the_seo_framework_bother_me_desc_length', $bother_length );
686
 
687
  $word_count = array_count_values( $words );
688
 
700
  }
701
 
702
  if ( $run ) {
703
+ //* The encoded word is longer or equal to the bother length.
704
 
705
  $word_len = mb_strlen( $word );
706
 
712
  }
713
  }
714
  }
715
+ endif;
716
 
717
  return $words_too_many;
718
  }
719
+
720
+ /**
721
+ * Calculates the relative font color according to the background.
722
+ *
723
+ * @since 2.8.0
724
+ *
725
+ * @param string $hex The 3 to 6 character RGB hex. '#' prefix is supported.
726
+ * @return string The hexadecimal RGB relative font color, without '#' prefix.
727
+ */
728
+ public function get_relatitve_fontcolor( $hex = '' ) {
729
+
730
+ $hex = ltrim( $hex, '#' );
731
+
732
+ //* #rgb = #rrggbb
733
+ if ( 3 === strlen( $hex ) )
734
+ $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
735
+
736
+ $hex = str_split( $hex, 2 );
737
+
738
+ //* Convert to numerical values.
739
+ $r = hexdec( $hex[0] );
740
+ $g = hexdec( $hex[1] );
741
+ $b = hexdec( $hex[2] );
742
+
743
+ //* Convert to sRGB for relative luminance.
744
+ $sr = 0.2125 * $r;
745
+ $sg = 0.7154 * $g;
746
+ $sb = 0.0721 * $b;
747
+ $rel_lum = 1 - ( $sr + $sg + $sb ) / 255;
748
+
749
+ //* Convert to relative intvals between 1 and 0 for L from HSL
750
+ /*
751
+ $rr = $r / 255;
752
+ $rg = $g / 255;
753
+ $rb = $b / 255;
754
+ $luminance = ( min( $rr, $rg, $rb ) + max( $rr, $rg, $rb ) ) / 2;
755
+ */
756
+
757
+ //* Get perceptive luminance (greyscale) according to W3C.
758
+ $gr = 0.2989 * $r;
759
+ $gg = 0.5870 * $g;
760
+ $gb = 0.1140 * $b;
761
+ $per_lum = 1 - ( $gr + $gg + $gb ) / 255;
762
+
763
+ //* Invert colors if they hit luminance boundaries.
764
+ if ( $rel_lum < 0.5 ) {
765
+ //* Build dark. Add softness.
766
+ $gr = $gr * $per_lum / 8 / 0.2989 + 8 * 0.2989;
767
+ $gg = $gg * $per_lum / 8 / 0.5870 + 8 * 0.5870;
768
+ $gb = $gb * $per_lum / 8 / 0.1140 + 8 * 0.1140;
769
+ } else {
770
+ //* Build light. Add (subtract) softness.
771
+ $gr = 255 - $gr * $per_lum / 8 * 0.2989 - 8 * 0.2989;
772
+ $gg = 255 - $gg * $per_lum / 8 * 0.5870 - 8 * 0.5870;
773
+ $gb = 255 - $gb * $per_lum / 8 * 0.1140 - 8 * 0.1140;
774
+ }
775
+
776
+ //* Complete hexvals.
777
+ $retr = str_pad( dechex( $gr ), 2, '0', STR_PAD_LEFT );
778
+ $retg = str_pad( dechex( $gg ), 2, '0', STR_PAD_LEFT );
779
+ $retb = str_pad( dechex( $gb ), 2, '0', STR_PAD_LEFT );
780
+
781
+ return $retr . $retg . $retb;
782
+ }
783
+
784
+ /**
785
+ * Converts markdown text into HMTL.
786
+ * Does not support list or block elements. Only inline statements.
787
+ *
788
+ * Note: This code has been rightfully stolen from the Extension Manager plugin (sorry Sybre!).
789
+ *
790
+ * @since 2.8.0
791
+ * @link https://wordpress.org/plugins/about/readme.txt
792
+ *
793
+ * @param string $text The text that might contain markdown. Expected to be escaped.
794
+ * @param array $convert The markdown style types wished to be converted.
795
+ * If left empty, it will convert all.
796
+ * @return string The markdown converted text.
797
+ */
798
+ public function convert_markdown( $text, $convert = array() ) {
799
+
800
+ preprocess : {
801
+ $text = str_replace( "\r\n", "\n", $text );
802
+ $text = str_replace( "\t", ' ', $text );
803
+ $text = trim( $text );
804
+ }
805
+
806
+ if ( '' === $text )
807
+ return '';
808
+
809
+ /**
810
+ * The conversion list's keys are per reference only.
811
+ */
812
+ $conversions = array(
813
+ '**' => 'strong',
814
+ '*' => 'em',
815
+ '`' => 'code',
816
+ '[]()' => 'a',
817
+ '======' => 'h6',
818
+ '=====' => 'h5',
819
+ '====' => 'h4',
820
+ '===' => 'h3',
821
+ '==' => 'h2',
822
+ '=' => 'h1',
823
+ );
824
+
825
+ $md_types = empty( $convert ) ? $conversions : array_intersect( $conversions, $convert );
826
+
827
+ foreach ( $md_types as $type ) :
828
+ switch ( $type ) :
829
+ case 'strong' :
830
+ //* Considers word boundary. @TODO consider removing this?
831
+ $count = preg_match_all( '/(?:\*{2})\b([^\*{2}]+)(?:\*{2})/', $text, $matches, PREG_PATTERN_ORDER );
832
+
833
+ for ( $i = 0; $i < $count; $i++ ) {
834
+ $text = str_replace(
835
+ $matches[0][ $i ],
836
+ sprintf( '<strong>%s</strong>', \esc_html( $matches[1][ $i ] ) ),
837
+ $text
838
+ );
839
+ }
840
+ break;
841
+
842
+ case 'em' :
843
+ $count = preg_match_all( '/(?:\*{1})([^\*{1}]+)(?:\*{1})/', $text, $matches, PREG_PATTERN_ORDER );
844
+
845
+ for ( $i = 0; $i < $count; $i++ ) {
846
+ $text = str_replace(
847
+ $matches[0][ $i ],
848
+ sprintf( '<em>%s</em>', \esc_html( $matches[1][ $i ] ) ),
849
+ $text
850
+ );
851
+ }
852
+ break;
853
+
854
+ case 'code' :
855
+ $count = preg_match_all( '/(?:`{1})([^`{1}]+)(?:`{1})/', $text, $matches, PREG_PATTERN_ORDER );
856
+
857
+ for ( $i = 0; $i < $count; $i++ ) {
858
+ $text = str_replace(
859
+ $matches[0][ $i ],
860
+ sprintf( '<code>%s</code>', \esc_html( $matches[1][ $i ] ) ),
861
+ $text
862
+ );
863
+ }
864
+ break;
865
+
866
+ case 'h6' :
867
+ case 'h5' :
868
+ case 'h4' :
869
+ case 'h3' :
870
+ case 'h2' :
871
+ case 'h1' :
872
+ $amount = filter_var( $type, FILTER_SANITIZE_NUMBER_INT );
873
+ //* Considers word non-boundary. @TODO consider removing this?
874
+ $expression = "/(?:={{$amount}})\B([^={{$amount}}]+?)\B(?:={{$amount}})/";
875
+ $count = preg_match_all( $expression, $text, $matches, PREG_PATTERN_ORDER );
876
+
877
+ for ( $i = 0; $i < $count; $i++ ) {
878
+ $text = str_replace(
879
+ $matches[0][ $i ],
880
+ sprintf( '<%1$s>%2$s</%1$s>', \esc_attr( $type ), \esc_html( $matches[1][ $i ] ) ),
881
+ $text
882
+ );
883
+ }
884
+ break;
885
+
886
+ case 'a' :
887
+ $count = preg_match_all( '/(?:(?:\[{1})([^\]{1}]+)(?:\]{1})(?:\({1})([^\)\(]+)(?:\){1}))/', $text, $matches, PREG_PATTERN_ORDER );
888
+
889
+ for ( $i = 0; $i < $count; $i++ ) {
890
+ $text = str_replace(
891
+ $matches[0][ $i ],
892
+ sprintf( '<a href="%s" rel="nofollow">%s</a>', \esc_url( $matches[2][ $i ] ), \esc_html( $matches[1][ $i ] ) ),
893
+ $text
894
+ );
895
+ }
896
+ break;
897
+
898
+ default :
899
+ break;
900
+ endswitch;
901
+ endforeach;
902
+
903
+ return $text;
904
+ }
905
  }
inc/classes/debug.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,16 +23,14 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Debug
23
  *
24
  * Holds plugin debug functions.
25
  *
26
- * @since 2.6.0
27
  */
28
- class AutoDescription_Debug extends AutoDescription_Core {
29
 
30
  /**
31
  * Enqueue the debug output.
@@ -41,34 +46,92 @@ class AutoDescription_Debug extends AutoDescription_Core {
41
  *
42
  * @since 2.6.5
43
  *
44
- * @var bool Whether to continue adding to AutoDescription_Debug::debug_output
45
- * within AutoDescription_Debug::debug_init().
46
  */
47
  protected $add_debug_output = true;
48
 
49
  /**
50
- * Unserializing instances of this class is forbidden.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  */
52
- private function __wakeup() { }
53
 
54
  /**
55
- * Handle unapproachable invoked methods.
 
 
 
 
 
 
 
 
56
  */
57
- public function __call( $name, $arguments ) {
58
- parent::__call( $name, $arguments );
 
 
 
 
 
 
 
 
59
  }
60
 
61
  /**
62
- * Constructor, load parent constructor and add actions.
 
 
 
 
63
  */
64
- public function __construct() {
65
- parent::__construct();
66
 
67
- if ( $this->the_seo_framework_debug ) {
68
- add_action( 'admin_footer', array( $this, 'debug_screens' ) );
69
- add_action( 'admin_footer', array( $this, 'debug_output' ) );
70
- add_action( 'wp_footer', array( $this, 'debug_output' ) );
71
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
 
74
  /**
@@ -79,11 +142,13 @@ class AutoDescription_Debug extends AutoDescription_Core {
79
  * The current behavior is to trigger a user error if WP_DEBUG is true.
80
  *
81
  * @since 2.6.0
 
82
  * @access private
83
  *
84
- * @param string $function The function that was called.
85
- * @param string $version The version of WordPress that deprecated the function.
86
- * @param string $replacement Optional. The function that should have been called. Default null.
 
87
  */
88
  public function _deprecated_function( $function, $version, $replacement = null ) {
89
  /**
@@ -95,7 +160,7 @@ class AutoDescription_Debug extends AutoDescription_Core {
95
  * @param string $replacement The function that should have been called.
96
  * @param string $version The version of WordPress that deprecated the function.
97
  */
98
- do_action( 'deprecated_function_run', $function, $replacement, $version );
99
 
100
  /**
101
  * Filter whether to trigger an error for deprecated functions.
@@ -104,22 +169,29 @@ class AutoDescription_Debug extends AutoDescription_Core {
104
  *
105
  * @param bool $trigger Whether to trigger the error for deprecated functions. Default true.
106
  */
107
- if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
108
 
109
  set_error_handler( array( $this, 'error_handler_deprecated' ) );
110
 
111
- if ( function_exists( '__' ) ) {
112
- if ( isset( $replacement ) )
113
- /* translators: 1: Function name, 2: Plugin Version notification, 3: Replacement function */
114
- trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since version %2$s of The SEO Framework! Use %3$s instead.', 'autodescription' ), $function, $version, $replacement ) );
115
- else
116
- /* translators: 1: Function name, 2: Plugin Version notification */
117
- trigger_error( sprintf( __( '%1$s is <strong>deprecated</strong> since version %2$s of The SEO Framework with no alternative available.', 'autodescription' ), $function, $version ) );
 
 
 
118
  } else {
119
- if ( isset( $replacement ) )
120
- trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s of The SEO Framework! Use %3$s instead.', $function, $version, $replacement ) );
121
- else
122
- trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s of The SEO Framework with no alternative available.', $function, $version ) );
 
 
 
 
123
  }
124
 
125
  restore_error_handler();
@@ -134,13 +206,14 @@ class AutoDescription_Debug extends AutoDescription_Core {
134
  * The current behavior is to trigger a user error if WP_DEBUG is true.
135
  *
136
  * @since 2.6.0
 
137
  * @access private
138
  *
139
  * @param string $function The function that was called.
140
  * @param string $message A message explaining what has been done incorrectly.
141
  * @param string $version The version of WordPress where the message was added.
142
  */
143
- public function _doing_it_wrong( $function, $message, $version ) {
144
  /**
145
  * Fires when the given function is being used incorrectly.
146
  *
@@ -150,7 +223,7 @@ class AutoDescription_Debug extends AutoDescription_Core {
150
  * @param string $message A message explaining what has been done incorrectly.
151
  * @param string $version The version of WordPress where the message was added.
152
  */
153
- do_action( 'doing_it_wrong_run', $function, $message, $version );
154
 
155
  /**
156
  * Filter whether to trigger an error for _doing_it_wrong() calls.
@@ -159,26 +232,21 @@ class AutoDescription_Debug extends AutoDescription_Core {
159
  *
160
  * @param bool $trigger Whether to trigger the error for _doing_it_wrong() calls. Default true.
161
  */
162
- if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) {
163
 
164
  set_error_handler( array( $this, 'error_handler_doing_it_wrong' ) );
165
 
166
- if ( function_exists( '__' ) ) {
167
- $version = is_null( $version ) ? '' : sprintf( __( '(This message was added in version %s of The SEO Framework.)' ), $version );
168
- /* translators: %s: Codex URL */
169
- $message .= ' ' . sprintf( __( 'Please see <a href="%s">Debugging in WordPress</a> for more information.', 'autodescription' ),
170
- __( 'https://codex.wordpress.org/Debugging_in_WordPress', 'autodescription' )
171
- );
172
- /* translators: 1: Function name, 2: Message, 3: Plugin Version notification */
173
- trigger_error( sprintf( __( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s', 'autodescription' ), $function, $message, $version ) );
174
- } else {
175
- $version = is_null( $version ) ? '' : sprintf( '(This message was added in version %s of The SEO Framework.)', $version );
176
- $message .= ' ' . sprintf( 'Please see <a href="%s">Debugging in WordPress</a> for more information.',
177
- 'https://codex.wordpress.org/Debugging_in_WordPress'
178
- );
179
-
180
- trigger_error( sprintf( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s', $function, $message, $version ) );
181
- }
182
 
183
  restore_error_handler();
184
  }
@@ -186,14 +254,16 @@ class AutoDescription_Debug extends AutoDescription_Core {
186
 
187
  /**
188
  * Mark a property or method inaccessible when it has been used.
189
-
190
  * The current behavior is to trigger a user error if WP_DEBUG is true.
191
  *
192
  * @since 2.7.0
 
 
193
  * @access private
 
194
  *
195
- * @param string $p_or_m The Property or Method.
196
- * @param string $message A message explaining what has been done incorrectly.
197
  */
198
  public function _inaccessible_p_or_m( $p_or_m, $message = '' ) {
199
 
@@ -205,25 +275,21 @@ class AutoDescription_Debug extends AutoDescription_Core {
205
  * @param string $p_or_m The Property or Method.
206
  * @param string $message A message explaining what has been done incorrectly.
207
  */
208
- do_action( 'the_seo_framework_inaccessible_p_or_m_run', $p_or_m, $message );
209
 
210
  /**
211
- * Filter whether to trigger an error for _doing_it_wrong() calls.
212
- *
213
- * @since 3.1.0
214
- *
215
- * @param bool $trigger Whether to trigger the error for _doing_it_wrong() calls. Default true.
216
- */
217
- if ( WP_DEBUG && apply_filters( 'the_seo_framework_inaccessible_p_or_m_trigger_error', true ) ) {
218
 
219
  set_error_handler( array( $this, 'error_handler_inaccessible_call' ) );
220
 
221
- if ( function_exists( '__' ) ) {
222
- /* translators: 1: Method or Property name, 2: Message */
223
- trigger_error( sprintf( __( '%1$s is not <strong>accessible</strong>. %2$s', 'autodescription' ), $p_or_m, $message ) );
224
- } else {
225
- trigger_error( sprintf( '%s is not <strong>accessible</strong>. %s', $p_or_m, $message ) );
226
- }
227
 
228
  restore_error_handler();
229
  }
@@ -243,17 +309,21 @@ class AutoDescription_Debug extends AutoDescription_Core {
243
  protected function error_handler_deprecated( $code, $message ) {
244
 
245
  //* Only do so if E_USER_NOTICE is pased.
246
- if ( $code >= 1024 && isset( $message ) ) {
247
 
248
  $backtrace = debug_backtrace();
249
  /**
250
- * 0 = This function. 1 = Debug function. 2 = Error trigger. 3 = Deprecated call.
 
251
  */
252
- $error = $backtrace[3];
 
 
 
 
253
 
254
  $this->error_handler( $error, $message );
255
  }
256
-
257
  }
258
 
259
  /**
@@ -270,24 +340,23 @@ class AutoDescription_Debug extends AutoDescription_Core {
270
  protected function error_handler_doing_it_wrong( $code, $message ) {
271
 
272
  //* Only do so if E_USER_NOTICE is pased.
273
- if ( $code >= 1024 && isset( $message ) ) {
274
 
275
  $backtrace = debug_backtrace();
276
  /**
277
- * 0 = This function. 1 = Debug function. 2 = Error trigger.
278
  */
279
- $error = $backtrace[2];
280
 
281
  $this->error_handler( $error, $message );
282
  }
283
-
284
  }
285
 
286
  /**
287
  * The SEO Framework error handler.
288
  *
289
  * Only handles notices.
290
- * @see E_USER_NOTICE
291
  *
292
  * @since 2.6.0
293
  *
@@ -296,63 +365,108 @@ class AutoDescription_Debug extends AutoDescription_Core {
296
  */
297
  protected function error_handler_inaccessible_call( $code, $message ) {
298
 
299
- if ( $code >= 1024 && isset( $message ) ) {
 
300
 
301
  $backtrace = debug_backtrace();
 
302
  /**
303
- * 0 = This function. 1 = Debug function. 2 = debug function. 3-29 = 26 classes loop, 30 = user call.
304
  */
305
- $error = $backtrace[30];
306
 
307
- $this->error_handler( $error, $message );
308
  }
309
-
310
  }
311
 
312
  /**
313
  * Echos error.
314
  *
315
  * @since 2.6.0
 
316
  *
317
  * @param array $error The Error location and file.
318
- * @param string $message The error message.
 
319
  */
320
- protected function error_handler( $error, $message ) {
321
 
322
  $file = isset( $error['file'] ) ? $error['file'] : '';
323
  $line = isset( $error['line'] ) ? $error['line'] : '';
324
 
325
  if ( isset( $message ) ) {
326
- echo "\r\n" . '<strong>Notice:</strong> ' . $message;
327
- echo $file ? ' In ' . $file : '';
328
- echo $line ? ' on line ' . $line : '';
329
- echo ".<br>\r\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  }
331
  }
332
 
333
  /**
334
- * Echos found screens in the admin footer when debugging is enabled.
335
  *
336
  * @since 2.5.2
337
- * @uses bool $this->the_seo_framework_debug
338
  * @access private
339
- * @global object $current_screen
340
  */
341
  public function debug_screens() {
342
  global $current_screen;
343
 
344
  $this->debug_init( __METHOD__, false, '', get_defined_vars() );
345
-
346
  }
347
 
348
  /**
349
  * Echos debug output.
350
  *
351
  * @since 2.6.0
 
352
  * @access private
353
  */
354
  public function debug_output() {
355
- $this->get_view( 'debug/output' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
356
  }
357
 
358
  /**
@@ -370,11 +484,11 @@ class AutoDescription_Debug extends AutoDescription_Core {
370
 
371
  if ( $this->the_seo_framework_debug ) {
372
 
373
- $output .= "\r\n";
374
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<span class="code highlight">';
375
 
376
  if ( is_null( $values ) ) {
377
- $output .= $this->debug_value_wrapper( "Debug message: Value isn't set." ) . "\r\n";
378
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</span>';
379
 
380
  return $output;
@@ -405,18 +519,18 @@ class AutoDescription_Debug extends AutoDescription_Core {
405
  if ( '' === $value ) {
406
  $output .= $this->debug_key_wrapper( $key ) . ' => ';
407
  $output .= $this->debug_value_wrapper( "''" );
408
- $output .= "\r\n";
409
  } elseif ( is_string( $value ) || is_int( $value ) ) {
410
  $output .= $this->debug_key_wrapper( $key ) . ' => ';
411
  $output .= $this->debug_value_wrapper( $value );
412
- $output .= "\r\n";
413
  } elseif ( is_bool( $value ) ) {
414
  $output .= $this->debug_key_wrapper( $key ) . ' => ';
415
  $output .= $this->debug_value_wrapper( $value ? 'true' : 'false' );
416
- $output .= "\r\n";
417
  } elseif ( is_array( $value ) ) {
418
  $output .= $this->debug_key_wrapper( $key ) . ' => ';
419
- $output .= "Array[\r\n";
420
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<p style="margin:0;padding-left:12px">';
421
  foreach ( $value as $k => $v ) {
422
  $output .= "\t\t\t";
@@ -437,7 +551,7 @@ class AutoDescription_Debug extends AutoDescription_Core {
437
  $output .= $this->debug_value_wrapper( $v );
438
  }
439
  $output .= ',';
440
- $output .= "\r\n";
441
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<br>';
442
  }
443
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</p>';
@@ -445,7 +559,7 @@ class AutoDescription_Debug extends AutoDescription_Core {
445
  } else {
446
  $output .= $this->debug_key_wrapper( $key ) . ' => ';
447
  $output .= $this->debug_value_wrapper( $value );
448
- $output .= "\r\n";
449
  }
450
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<br>';
451
  }
@@ -465,7 +579,7 @@ class AutoDescription_Debug extends AutoDescription_Core {
465
  }
466
 
467
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</span>';
468
- $output .= "\r\n";
469
  }
470
 
471
  return $output;
@@ -485,9 +599,9 @@ class AutoDescription_Debug extends AutoDescription_Core {
485
  public function debug_key_wrapper( $key, $ignore = false ) {
486
 
487
  if ( $ignore || false === $this->the_seo_framework_debug_hidden )
488
- return '<font color="chucknorris">' . esc_attr( $key ) . '</font>';
489
 
490
- return esc_attr( $key );
491
  }
492
 
493
  /**
@@ -510,16 +624,15 @@ class AutoDescription_Debug extends AutoDescription_Core {
510
  return html_entity_decode( $value );
511
 
512
  if ( $ignore || false === $this->the_seo_framework_debug_hidden )
513
- return '<span class="wp-ui-notification">' . esc_attr( trim( $value ) ) . '</span>';
514
 
515
- return esc_attr( $value );
516
  }
517
 
518
  /**
519
  * Debug init. Simplified way of debugging a function, only works in admin.
520
  *
521
  * @since 2.6.0
522
- *
523
  * @access private
524
  *
525
  * @param string $method The function name.
@@ -528,7 +641,7 @@ class AutoDescription_Debug extends AutoDescription_Core {
528
  * @param mixed function args.
529
  * @return void early if debugging is disabled or when storing cache values.
530
  */
531
- protected function debug_init( $method, $store, $debug_key ) {
532
 
533
  if ( false === $this->the_seo_framework_debug || false === $this->add_debug_output )
534
  return;
@@ -542,13 +655,16 @@ class AutoDescription_Debug extends AutoDescription_Core {
542
  static $hold_args = array();
543
 
544
  $args = array_slice( func_get_args(), 3 );
 
 
 
545
  $key = $method . '_' . $debug_key;
546
 
547
  if ( $store ) {
548
  $this->profile( false, false, 'time', $key ) . ' seconds';
549
  $this->profile( false, false, 'memory', $key ) . ' bytes';
550
 
551
- unset( $args[0]['debug_key'] );
552
 
553
  $cached_args[ $method ] = $args;
554
  $hold_args[ $method ] = $args;
@@ -565,13 +681,10 @@ class AutoDescription_Debug extends AutoDescription_Core {
565
  $loop++;
566
  $debug_key = '[Debug key: ' . $loop . ' - ' . $method . ']';
567
 
568
- if ( $this->is_admin() && 'admin_footer' !== current_action() ) {
569
- echo "\r\n";
570
- echo $this->the_seo_framework_debug_hidden ? esc_html( $debug_key ) . ' action. ' : '<p>' . esc_html( $debug_key ) . '</p>';
571
- }
572
 
573
- $output .= "\r\n";
574
- $output .= $this->the_seo_framework_debug_hidden ? esc_html( $debug_key ) . ' output. ' : '<h3>' . esc_html( $debug_key ) . '</h3>';
575
 
576
  if ( isset( $cached_args[ $method ] ) ) {
577
  $args[] = array(
@@ -589,45 +702,45 @@ class AutoDescription_Debug extends AutoDescription_Core {
589
  }
590
 
591
  if ( $args ) {
 
592
 
593
- $output .= $method . '( ';
594
-
595
- if ( isset( $hold_args[ $method ][0] ) ) {
596
- if ( is_array( $hold_args[ $method ][0] ) ) {
597
- foreach ( $hold_args[ $method ][0] as $var => $a ) {
598
- $output .= gettype( $a ) . ' $' . $var . ', ';
599
  }
600
  }
601
- $output = rtrim( $output, ', ' );
602
  $hold_args[ $method ] = null;
603
  }
604
 
605
- $output .= ' )';
606
- $output .= $this->the_seo_framework_debug_hidden ? "\r\n" : "<br>\r\n";
607
 
608
  foreach ( $args as $num => $a ) {
609
  if ( is_array( $a ) ) {
610
  foreach ( $a as $k => $v ) {
611
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<div style="padding-left:12px">';
612
- $output .= "\t" . (string) $k . ': ';
613
- $output .= $this->the_seo_framework_debug_hidden ? "\r\n" : '<br><div style="padding-left:12px">' . "\r\n";
614
- $output .= "\t " . gettype( $v ) . ': [';
615
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<div style="padding-left:12px">';
616
  $output .= "\t\t" . $this->get_debug_information( $v );
617
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</div>';
618
- $output .= "\t " . ']' . "\r\n";
619
- $output .= $this->the_seo_framework_debug_hidden ? '' : '</div>';
620
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</div>';
621
  }
622
  } else {
623
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<div style="padding-left:12px">';
624
- $output .= "\t" . (string) $num . ': ';
625
- $output .= $this->the_seo_framework_debug_hidden ? "\r\n" : "<br>\r\n";
626
- $output .= "\t " . gettype( $a ) . ': [';
627
- $output .= $this->the_seo_framework_debug_hidden ? '' : '<div style="padding-left:12px">';
628
- $output .= "\t\t" . $this->get_debug_information( $a );
629
- $output .= $this->the_seo_framework_debug_hidden ? '' : "</div><br>\r\n";
630
- $output .= "\t " . ']' . "\r\n";
 
631
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</div>';
632
  }
633
  }
@@ -635,7 +748,6 @@ class AutoDescription_Debug extends AutoDescription_Core {
635
  }
636
 
637
  if ( $output ) {
638
-
639
  static $odd = false;
640
  if ( $odd ) {
641
  $bg = 'f1f1f1';
@@ -706,22 +818,21 @@ class AutoDescription_Debug extends AutoDescription_Core {
706
  }
707
 
708
  //* Convert to string and echo if not returned yet.
709
- echo (string) "\r\n" . $difference_time . "s\r\n";
710
- echo (string) ( $difference_memory / 1024 ) . "kiB\r\n";
711
  } else {
712
  if ( false === $echo ) {
713
  //* Return early if not allowed to echo.
714
  if ( 'time' === $what )
715
  return number_format( $plugin_time[ $key ], 5 );
716
 
717
- return $plugin_memory[$key];
718
  }
719
 
720
  //* Convert to string and echo if not returned yet.
721
- echo (string) "\r\n" . $plugin_time[ $key ] . "s\r\n";
722
- echo (string) ( $plugin_memory[ $key ] / 1024 ) . "kiB\r\n";
723
  }
724
-
725
  }
726
 
727
  /**
@@ -746,6 +857,20 @@ class AutoDescription_Debug extends AutoDescription_Core {
746
  return $output;
747
  }
748
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
749
  /**
750
  * Wraps header output in front-end code.
751
  * This won't consider hiding the output.
@@ -754,13 +879,15 @@ class AutoDescription_Debug extends AutoDescription_Core {
754
  *
755
  * @return string Wrapped SEO meta tags output.
756
  */
757
- protected function debug_header_output() {
758
 
759
- if ( $this->is_admin() && ! $this->is_term_edit() && ! $this->is_post_edit() && ! $this->is_seo_settings_page( true ) )
 
 
760
  return;
761
 
762
- if ( $this->is_seo_settings_page( true ) )
763
- add_filter( 'the_seo_framework_current_object_id', array( $this, 'get_the_front_page_ID' ) );
764
 
765
  //* Start timer.
766
  $this->timer( true );
@@ -768,38 +895,37 @@ class AutoDescription_Debug extends AutoDescription_Core {
768
  //* Don't register this output.
769
  $this->add_debug_output = false;
770
 
771
- $output = $this->the_description()
772
- . $this->og_image()
773
- . $this->og_locale()
774
- . $this->og_type()
775
- . $this->og_title()
776
- . $this->og_description()
777
- . $this->og_url()
778
- . $this->og_sitename()
779
- . $this->facebook_publisher()
780
- . $this->facebook_author()
781
- . $this->facebook_app_id()
782
- . $this->article_published_time()
783
- . $this->article_modified_time()
784
- . $this->twitter_card()
785
- . $this->twitter_site()
786
- . $this->twitter_creator()
787
- . $this->twitter_title()
788
- . $this->twitter_description()
789
- . $this->twitter_image()
790
- . $this->shortlink()
791
- . $this->canonical()
792
- . $this->paged_urls()
793
- . $this->ld_json()
794
- . $this->google_site_output()
795
- . $this->bing_site_output()
796
- . $this->yandex_site_output()
797
- . $this->pint_site_output()
798
- ;
799
 
800
  $timer = '<div style="display:inline-block;width:100%;padding:20px;border-bottom:1px solid #ccc;">Generated in: ' . number_format( $this->timer(), 5 ) . ' seconds</div>' ;
801
 
802
- $title = $this->is_admin() ? 'Expected SEO Output' : 'Current SEO Output';
803
  $title = '<div style="display:inline-block;width:100%;padding:20px;margin:0 auto;border-bottom:1px solid #ccc;"><h2 style="color:#ddd;font-size:22px;padding:0;margin:0">' . $title . '</h2></div>';
804
 
805
  //* Escape it, replace EOL with breaks, and style everything between quotes (which are ending with space).
@@ -809,59 +935,125 @@ class AutoDescription_Debug extends AutoDescription_Core {
809
  $output = '<div style="display:inline-block;width:100%;padding:20px;font-family:Consolas,Monaco,monospace;font-size:14px;">' . $output . '</div>';
810
  $output = '<div style="display:block;width:100%;background:#23282D;color:#ddd;border-bottom:1px solid #ccc">' . $title . $timer . $output . '</div>';
811
 
 
 
812
  return $output;
813
  }
814
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
815
  /**
816
  * Wraps query status booleans in human-readable code.
817
  *
818
  * @since 2.6.6
 
 
819
  *
 
820
  * @return string Wrapped Query State debug output.
821
  */
822
- protected function debug_query_output() {
823
 
824
  //* Start timer.
825
  $this->timer( true );
826
 
827
- //* Don't register this output.
828
  $this->add_debug_output = false;
829
 
830
  global $multipage, $numpages;
831
 
 
 
832
  //* Only get true/false values.
833
- $is_404 = $this->is_404();
834
- $is_admin = $this->is_admin();
835
- $is_attachment = $this->is_attachment();
836
- $is_archive = $this->is_archive();
837
- $is_term_edit = $this->is_term_edit();
838
- $is_post_edit = $this->is_post_edit();
839
- $is_wp_lists_edit = $this->is_wp_lists_edit();
840
- $is_wp_lists_edit = $this->is_wp_lists_edit();
841
- $is_author = $this->is_author();
842
- $is_blog_page = $this->is_blog_page();
843
- $is_category = $this->is_category();
844
- $is_date = $this->is_date();
845
- $is_day = $this->is_day();
846
- $is_feed = $this->is_feed();
847
- $is_front_page = $this->is_front_page();
848
- $is_home = $this->is_home();
849
- $is_month = $this->is_month();
850
- $is_page = $this->is_page();
851
- $page = $this->page();
852
- $paged = $this->paged();
853
- $is_preview = $this->is_preview();
854
- $is_search = $this->is_search();
855
- $is_single = $this->is_single();
856
- $is_singular = $this->is_singular();
857
- $is_static_frontpage = $this->is_static_frontpage();
858
- $is_tag = $this->is_tag();
859
- $is_tax = $this->is_tax();
860
- $is_ultimate_member_user_page = $this->is_ultimate_member_user_page();
861
- $is_wc_shop = $this->is_wc_shop();
862
- $is_wc_product = $this->is_wc_product();
863
- $is_year = $this->is_year();
864
- $is_seo_settings_page = $this->is_seo_settings_page( true );
 
 
865
 
866
  //* Get all above vars, split them in two (true and false) and sort them by key names.
867
  $vars = get_defined_vars();
@@ -870,7 +1062,7 @@ class AutoDescription_Debug extends AutoDescription_Core {
870
  ksort( $current );
871
  ksort( $not_current );
872
 
873
- $timer = '<div style="display:inline-block;width:100%;padding:20px;border-bottom:1px solid #666;">Generated in: ' . number_format( $this->timer(), 5 ) . ' seconds</div>' ;
874
 
875
  $output = '';
876
  foreach ( $current as $name => $value ) {
@@ -879,11 +1071,11 @@ class AutoDescription_Debug extends AutoDescription_Core {
879
  if ( is_bool( $value ) ) {
880
  $value = $value ? 'true' : 'false';
881
  } else {
882
- $value = esc_attr( var_export( $value, true ) );
883
  }
884
 
885
  $value = $this->the_seo_framework_debug_hidden ? $type . ' ' . $value : '<font color="harrisonford">' . $type . ' ' . $value . '</font>';
886
- $out = $name . ' => ' . $value;
887
  $output .= $this->the_seo_framework_debug_hidden ? $out . PHP_EOL : '<span style="background:#dadada">' . $out . '</span>' . PHP_EOL;
888
  }
889
 
@@ -893,15 +1085,19 @@ class AutoDescription_Debug extends AutoDescription_Core {
893
  if ( is_bool( $value ) ) {
894
  $value = $value ? 'true' : 'false';
895
  } else {
896
- $value = esc_attr( var_export( $value, true ) );
897
  }
898
 
899
  $value = $this->the_seo_framework_debug_hidden ? $type . ' ' . $value : '<font color="harrisonford">' . $type . ' ' . $value . '</font>';
900
- $out = $name . ' => ' . $value;
901
  $output .= $out . PHP_EOL;
902
  }
903
 
904
- $title = $this->is_admin() ? 'Current WordPress Screen + Expected WordPress Query' : 'Current WordPress Query';
 
 
 
 
905
  $title = '<div style="display:inline-block;width:100%;padding:20px;margin:0 auto;border-bottom:1px solid #666;"><h2 style="color:#222;font-size:22px;padding:0;margin:0">' . $title . '</h2></div>';
906
 
907
  $output = $this->the_seo_framework_debug_hidden ? $output : str_replace( PHP_EOL, '<br>' . PHP_EOL, $output );
@@ -909,6 +1105,8 @@ class AutoDescription_Debug extends AutoDescription_Core {
909
  $output = '<div style="display:inline-block;width:100%;padding:20px;font-family:Consolas,Monaco,monospace;font-size:14px;">' . $output . '</div>';
910
  $output = '<div style="display:block;width:100%;background:#fafafa;color:#333;border-bottom:1px solid #666">' . $title . $timer . $output . '</div>';
911
 
 
 
912
  return $output;
913
  }
914
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Singleton class The_SEO_Framework\Debug
28
  *
29
  * Holds plugin debug functions.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ final class Debug implements Debug_Interface {
34
 
35
  /**
36
  * Enqueue the debug output.
46
  *
47
  * @since 2.6.5
48
  *
49
+ * @var bool Whether to continue adding to The_SEO_Framework_Debug::debug_output
50
+ * within The_SEO_Framework_Debug::debug_init().
51
  */
52
  protected $add_debug_output = true;
53
 
54
  /**
55
+ * The object instance.
56
+ *
57
+ * @since 2.8.0
58
+ *
59
+ * @var object|null This object instance.
60
+ */
61
+ private static $instance = null;
62
+
63
+ /**
64
+ * Cached debug/profile properties.
65
+ *
66
+ * @since 2.8.0
67
+ *
68
+ * @var bool Whether debug is enabled.
69
+ * @var bool Whether debug is hidden in HTMl.
70
+ */
71
+ public $the_seo_framework_debug = false;
72
+ public $the_seo_framework_debug_hidden = false;
73
+
74
+ /**
75
+ * Unserializing instances of this object is forbidden.
76
+ */
77
+ final protected function __wakeup() { }
78
+
79
+ /**
80
+ * Cloning of this object is forbidden.
81
  */
82
+ final protected function __clone() { }
83
 
84
  /**
85
+ * Constructor.
86
+ */
87
+ final protected function __construct() {}
88
+
89
+ /**
90
+ * Sets the class instance.
91
+ *
92
+ * @since 2.8.0
93
+ * @access private
94
  */
95
+ public static function set_instance( $debug = null, $hidden = null ) {
96
+
97
+ if ( is_null( static::$instance ) ) {
98
+ static::$instance = new static();
99
+ }
100
+
101
+ if ( isset( $debug ) ) {
102
+ static::$instance->the_seo_framework_debug = (bool) $debug;
103
+ static::$instance->the_seo_framework_debug_hidden = (bool) $hidden;
104
+ }
105
  }
106
 
107
  /**
108
+ * Gets the class instance. It's set when it's null.
109
+ *
110
+ * @since 2.8.0
111
+ *
112
+ * @return object The current instance.
113
  */
114
+ public static function get_instance() {
 
115
 
116
+ if ( is_null( static::$instance ) ) {
117
+ static::set_instance();
 
 
118
  }
119
+
120
+ return static::$instance;
121
+ }
122
+
123
+ /**
124
+ * Mark a filter as deprecated and inform when it has been used.
125
+ *
126
+ * @since 2.8.0
127
+ * @see @this->_deprecated_function().
128
+ *
129
+ * @param string $filter The function that was called.
130
+ * @param string $version The version of WordPress that deprecated the function.
131
+ * @param string $replacement Optional. The function that should have been called. Default null.
132
+ */
133
+ public function _deprecated_filter( $filter, $version, $replacement = null ) {
134
+ $this->_deprecated_function( 'Filter ' . $filter, $version, $replacement );
135
  }
136
 
137
  /**
142
  * The current behavior is to trigger a user error if WP_DEBUG is true.
143
  *
144
  * @since 2.6.0
145
+ * @since 2.8.0 Now escapes all input, except for $replacement.
146
  * @access private
147
  *
148
+ * @param string $function The function that was called.
149
+ * @param string $version The version of WordPress that deprecated the function.
150
+ * @param string $replacement Optional. The function that should have been called. Default null.
151
+ * Expected to be escaped.
152
  */
153
  public function _deprecated_function( $function, $version, $replacement = null ) {
154
  /**
160
  * @param string $replacement The function that should have been called.
161
  * @param string $version The version of WordPress that deprecated the function.
162
  */
163
+ \do_action( 'deprecated_function_run', $function, $replacement, $version );
164
 
165
  /**
166
  * Filter whether to trigger an error for deprecated functions.
169
  *
170
  * @param bool $trigger Whether to trigger the error for deprecated functions. Default true.
171
  */
172
+ if ( WP_DEBUG && \apply_filters( 'deprecated_function_trigger_error', true ) ) {
173
 
174
  set_error_handler( array( $this, 'error_handler_deprecated' ) );
175
 
176
+ if ( isset( $replacement ) ) {
177
+ trigger_error(
178
+ /* translators: 1: Function name, 2: 'Deprecated', 3: Plugin Version notification, 4: Replacement function */
179
+ sprintf( \esc_html__( '%1$s is %2$s since version %3$s of The SEO Framework! Use %4$s instead.', 'autodescription' ),
180
+ \esc_html( $function ),
181
+ '<strong>' . \esc_html__( 'deprecated', 'autodescription' ) . '</strong>',
182
+ \esc_html( $version ),
183
+ $replacement
184
+ )
185
+ );
186
  } else {
187
+ trigger_error(
188
+ /* translators: 1: Function name, 2: 'Deprecated', 3: Plugin Version notification */
189
+ sprintf( \esc_html__( '%1$s is %2$s since version %3$s of The SEO Framework with no alternative available.', 'autodescription' ),
190
+ \esc_html( $function ),
191
+ '<strong>' . \esc_html__( 'deprecated', 'autodescription' ) . '</strong>',
192
+ \esc_html( $version )
193
+ )
194
+ );
195
  }
196
 
197
  restore_error_handler();
206
  * The current behavior is to trigger a user error if WP_DEBUG is true.
207
  *
208
  * @since 2.6.0
209
+ * @since 2.8.0 Now escapes all input, except for $message.
210
  * @access private
211
  *
212
  * @param string $function The function that was called.
213
  * @param string $message A message explaining what has been done incorrectly.
214
  * @param string $version The version of WordPress where the message was added.
215
  */
216
+ public function _doing_it_wrong( $function, $message, $version = null ) {
217
  /**
218
  * Fires when the given function is being used incorrectly.
219
  *
223
  * @param string $message A message explaining what has been done incorrectly.
224
  * @param string $version The version of WordPress where the message was added.
225
  */
226
+ \do_action( 'doing_it_wrong_run', $function, $message, $version );
227
 
228
  /**
229
  * Filter whether to trigger an error for _doing_it_wrong() calls.
232
  *
233
  * @param bool $trigger Whether to trigger the error for _doing_it_wrong() calls. Default true.
234
  */
235
+ if ( WP_DEBUG && \apply_filters( 'doing_it_wrong_trigger_error', true ) ) {
236
 
237
  set_error_handler( array( $this, 'error_handler_doing_it_wrong' ) );
238
 
239
+ $version = empty( $version ) ? '' : sprintf( \__( '(This message was added in version %s of The SEO Framework.)' ), $version );
240
+ trigger_error(
241
+ /* translators: 1: Function name, 2: 'Incorrectly', 3: Error message 4: Plugin Version notification */
242
+ sprintf( \esc_html__( '%1$s was called %2$s. %3$s %4$s', 'autodescription' ),
243
+ \esc_html( $function ),
244
+ '<strong>' . \esc_html__( 'incorrectly', 'autodescription' ) . '</strong>',
245
+ //* Expected to be escaped.
246
+ $message,
247
+ \esc_html( $version )
248
+ )
249
+ );
 
 
 
 
 
250
 
251
  restore_error_handler();
252
  }
254
 
255
  /**
256
  * Mark a property or method inaccessible when it has been used.
 
257
  * The current behavior is to trigger a user error if WP_DEBUG is true.
258
  *
259
  * @since 2.7.0
260
+ * @since 2.8.0 1. Now escapes all parameters.
261
+ * 2. Removed check for gettext.
262
  * @access private
263
+ * @todo Escape translation string.
264
  *
265
+ * @param string $p_or_m The Property or Method.
266
+ * @param string $message A message explaining what has been done incorrectly.
267
  */
268
  public function _inaccessible_p_or_m( $p_or_m, $message = '' ) {
269
 
275
  * @param string $p_or_m The Property or Method.
276
  * @param string $message A message explaining what has been done incorrectly.
277
  */
278
+ \do_action( 'the_seo_framework_inaccessible_p_or_m_run', $p_or_m, $message );
279
 
280
  /**
281
+ * Filter whether to trigger an error for _doing_it_wrong() calls.
282
+ *
283
+ * @since 3.1.0
284
+ *
285
+ * @param bool $trigger Whether to trigger the error for _doing_it_wrong() calls. Default true.
286
+ */
287
+ if ( WP_DEBUG && \apply_filters( 'the_seo_framework_inaccessible_p_or_m_trigger_error', true ) ) {
288
 
289
  set_error_handler( array( $this, 'error_handler_inaccessible_call' ) );
290
 
291
+ /* translators: 1: Method or Property name, 2: Message */
292
+ trigger_error( sprintf( \esc_html__( '%1$s is not accessible. %2$s', 'autodescription' ), '<code>' . \esc_html( $p_or_m ) . '</code>', \esc_html( $message ) ), E_USER_ERROR );
 
 
 
 
293
 
294
  restore_error_handler();
295
  }
309
  protected function error_handler_deprecated( $code, $message ) {
310
 
311
  //* Only do so if E_USER_NOTICE is pased.
312
+ if ( 1024 === $code && isset( $message ) ) {
313
 
314
  $backtrace = debug_backtrace();
315
  /**
316
+ * 0 = This function. 1 = Debug function. 2 = Error trigger. 3 = Deprecated Class, 4 = Deprecated Method, 5 = Magic Method, 6 = Deprecated call.
317
+ * 0 = This function. 1 = Debug function. 2 = Error trigger. 3 = Deprecated Class, 4 = Deprecated Filter, 5 = Deprecated call.
318
  */
319
+ if ( 'Filter ' === substr( $message, 0, 7 ) ) {
320
+ $error = $backtrace[5];
321
+ } else {
322
+ $error = $backtrace[6];
323
+ }
324
 
325
  $this->error_handler( $error, $message );
326
  }
 
327
  }
328
 
329
  /**
340
  protected function error_handler_doing_it_wrong( $code, $message ) {
341
 
342
  //* Only do so if E_USER_NOTICE is pased.
343
+ if ( 1024 === $code && isset( $message ) ) {
344
 
345
  $backtrace = debug_backtrace();
346
  /**
347
+ * 0 = This function. 1 = Debug function. 2 = magic methods, 3 = Error trigger.
348
  */
349
+ $error = $backtrace[3];
350
 
351
  $this->error_handler( $error, $message );
352
  }
 
353
  }
354
 
355
  /**
356
  * The SEO Framework error handler.
357
  *
358
  * Only handles notices.
359
+ * @see E_USER_ERROR
360
  *
361
  * @since 2.6.0
362
  *
365
  */
366
  protected function error_handler_inaccessible_call( $code, $message ) {
367
 
368
+ //* Only do so if E_USER_ERROR is pased.
369
+ if ( 256 === $code && isset( $message ) ) {
370
 
371
  $backtrace = debug_backtrace();
372
+
373
  /**
374
+ * 0 = This function. 1-3 = Debug functions. 4-5 = magic methods, 6 = user call.
375
  */
376
+ $error = $backtrace[6];
377
 
378
+ $this->error_handler( $error, $message, $code );
379
  }
 
380
  }
381
 
382
  /**
383
  * Echos error.
384
  *
385
  * @since 2.6.0
386
+ * @since 2.8.0 added $code parameter
387
  *
388
  * @param array $error The Error location and file.
389
+ * @param string $message The error message. Expected to be escaped.
390
+ * @param int $code The error handler code.
391
  */
392
+ protected function error_handler( $error, $message, $code = E_USER_NOTICE ) {
393
 
394
  $file = isset( $error['file'] ) ? $error['file'] : '';
395
  $line = isset( $error['line'] ) ? $error['line'] : '';
396
 
397
  if ( isset( $message ) ) {
398
+ switch ( $code ) :
399
+ case E_USER_ERROR :
400
+ $type = 'Error';
401
+ break;
402
+
403
+ case E_USER_WARNING :
404
+ $type = 'Warning';
405
+ break;
406
+
407
+ case E_USER_NOTICE :
408
+ default :
409
+ $type = 'Notice';
410
+ break;
411
+ endswitch;
412
+
413
+ //* Already escaped.
414
+ echo sprintf( '<span><strong>%s:</strong> ', $type ) . $message;
415
+ echo $file ? ' In ' . \esc_html( $file ) : '';
416
+ echo $line ? ' on line ' . \esc_html( $line ) : '';
417
+ echo '.</span><br>' . PHP_EOL;
418
  }
419
  }
420
 
421
  /**
422
+ * Adds found screens in the admin footer when debugging is enabled.
423
  *
424
  * @since 2.5.2
 
425
  * @access private
426
+ * @global object $current_screen This object is passed through get_defined_vars().
427
  */
428
  public function debug_screens() {
429
  global $current_screen;
430
 
431
  $this->debug_init( __METHOD__, false, '', get_defined_vars() );
 
432
  }
433
 
434
  /**
435
  * Echos debug output.
436
  *
437
  * @since 2.6.0
438
+ * @since 2.8.0 is now static.
439
  * @access private
440
  */
441
  public function debug_output() {
442
+ \the_seo_framework()->get_view( 'debug/output', array( 'debug_output' => $this->debug_output ) );
443
+ }
444
+
445
+ /**
446
+ * Determines if there's debug output.
447
+ *
448
+ * @since 2.8.0
449
+ * @access private
450
+ *
451
+ * @return bool True if there's output.
452
+ */
453
+ public static function has_debug_output() {
454
+ $instance = static::get_instance();
455
+ return (bool) $instance->debug_output;
456
+ }
457
+
458
+ /**
459
+ * Outputs the debug_output property.
460
+ *
461
+ * @since 2.8.0
462
+ * @access private
463
+ */
464
+ public static function _output_debug() {
465
+
466
+ $instance = static::get_instance();
467
+ //* Already escaped.
468
+ echo $instance->debug_output;
469
+
470
  }
471
 
472
  /**
484
 
485
  if ( $this->the_seo_framework_debug ) {
486
 
487
+ $output .= PHP_EOL;
488
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<span class="code highlight">';
489
 
490
  if ( is_null( $values ) ) {
491
+ $output .= $this->debug_value_wrapper( 'null' ) . PHP_EOL;
492
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</span>';
493
 
494
  return $output;
519
  if ( '' === $value ) {
520
  $output .= $this->debug_key_wrapper( $key ) . ' => ';
521
  $output .= $this->debug_value_wrapper( "''" );
522
+ $output .= PHP_EOL;
523
  } elseif ( is_string( $value ) || is_int( $value ) ) {
524
  $output .= $this->debug_key_wrapper( $key ) . ' => ';
525
  $output .= $this->debug_value_wrapper( $value );
526
+ $output .= PHP_EOL;
527
  } elseif ( is_bool( $value ) ) {
528
  $output .= $this->debug_key_wrapper( $key ) . ' => ';
529
  $output .= $this->debug_value_wrapper( $value ? 'true' : 'false' );
530
+ $output .= PHP_EOL;
531
  } elseif ( is_array( $value ) ) {
532
  $output .= $this->debug_key_wrapper( $key ) . ' => ';
533
+ $output .= 'Array[' . PHP_EOL;
534
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<p style="margin:0;padding-left:12px">';
535
  foreach ( $value as $k => $v ) {
536
  $output .= "\t\t\t";
551
  $output .= $this->debug_value_wrapper( $v );
552
  }
553
  $output .= ',';
554
+ $output .= PHP_EOL;
555
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<br>';
556
  }
557
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</p>';
559
  } else {
560
  $output .= $this->debug_key_wrapper( $key ) . ' => ';
561
  $output .= $this->debug_value_wrapper( $value );
562
+ $output .= PHP_EOL;
563
  }
564
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<br>';
565
  }
579
  }
580
 
581
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</span>';
582
+ $output .= PHP_EOL;
583
  }
584
 
585
  return $output;
599
  public function debug_key_wrapper( $key, $ignore = false ) {
600
 
601
  if ( $ignore || false === $this->the_seo_framework_debug_hidden )
602
+ return '<font color="chucknorris">' . \esc_attr( $key ) . '</font>';
603
 
604
+ return \esc_attr( $key );
605
  }
606
 
607
  /**
624
  return html_entity_decode( $value );
625
 
626
  if ( $ignore || false === $this->the_seo_framework_debug_hidden )
627
+ return '<span class="wp-ui-notification">' . \esc_attr( trim( $value ) ) . '</span>';
628
 
629
+ return \esc_attr( $value );
630
  }
631
 
632
  /**
633
  * Debug init. Simplified way of debugging a function, only works in admin.
634
  *
635
  * @since 2.6.0
 
636
  * @access private
637
  *
638
  * @param string $method The function name.
641
  * @param mixed function args.
642
  * @return void early if debugging is disabled or when storing cache values.
643
  */
644
+ public function debug_init( $method, $store, $debug_key ) {
645
 
646
  if ( false === $this->the_seo_framework_debug || false === $this->add_debug_output )
647
  return;
655
  static $hold_args = array();
656
 
657
  $args = array_slice( func_get_args(), 3 );
658
+ //* Shift array.
659
+ isset( $args[0][0] ) and $args = $args[0][0];
660
+
661
  $key = $method . '_' . $debug_key;
662
 
663
  if ( $store ) {
664
  $this->profile( false, false, 'time', $key ) . ' seconds';
665
  $this->profile( false, false, 'memory', $key ) . ' bytes';
666
 
667
+ unset( $args['debug_key'] );
668
 
669
  $cached_args[ $method ] = $args;
670
  $hold_args[ $method ] = $args;
681
  $loop++;
682
  $debug_key = '[Debug key: ' . $loop . ' - ' . $method . ']';
683
 
684
+ if ( \the_seo_framework()->is_admin() && 'admin_footer' !== \current_action() )
685
+ echo $this->the_seo_framework_debug_hidden ? \esc_html( PHP_EOL . $debug_key ) . ' action. ' : '<p>' . \esc_html( $debug_key ) . '</p>';
 
 
686
 
687
+ $output .= $this->the_seo_framework_debug_hidden ? \esc_html( PHP_EOL . $debug_key ) . ' output. ' : '<h3>' . \esc_html( $debug_key ) . '</h3>';
 
688
 
689
  if ( isset( $cached_args[ $method ] ) ) {
690
  $args[] = array(
702
  }
703
 
704
  if ( $args ) {
705
+ $output .= $method . '(';
706
 
707
+ if ( isset( $hold_args[ $method ] ) ) {
708
+ if ( is_array( $hold_args[ $method ] ) ) {
709
+ foreach ( $hold_args[ $method ] as $var => $a ) {
710
+ $output .= ' ' . gettype( $a ) . ' $' . $var . ',';
 
 
711
  }
712
  }
713
+ $output = rtrim( $output, ', ' ) . ' ';
714
  $hold_args[ $method ] = null;
715
  }
716
 
717
+ $output .= ')';
718
+ $output .= $this->the_seo_framework_debug_hidden ? PHP_EOL : '<br>' . PHP_EOL;
719
 
720
  foreach ( $args as $num => $a ) {
721
  if ( is_array( $a ) ) {
722
  foreach ( $a as $k => $v ) {
723
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<div style="padding-left:12px">';
724
+ $output .= $this->the_seo_framework_debug_hidden ? "\t" . (string) $k . ': {{{' : "\t" . '<font color="fredwilliamson">' . (string) $k . '</font>: {{{';
725
+ $output .= $this->the_seo_framework_debug_hidden ? PHP_EOL : '<br><div style="padding-left:12px">' . PHP_EOL;
726
+ $output .= "\t " . gettype( $v ) . ': {';
727
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<div style="padding-left:12px">';
728
  $output .= "\t\t" . $this->get_debug_information( $v );
729
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</div>';
730
+ $output .= "\t " . '}' . PHP_EOL;
731
+ $output .= $this->the_seo_framework_debug_hidden ? '}}}' : '<br>}}}</div>';
732
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</div>';
733
  }
734
  } else {
735
  $output .= $this->the_seo_framework_debug_hidden ? '' : '<div style="padding-left:12px">';
736
+ $output .= $this->the_seo_framework_debug_hidden ? "\t" . (string) $num . ': {{{' : "\t" . '<font color="peterweller">' . (string) $num . '</font>: {{{';
737
+ $output .= $this->the_seo_framework_debug_hidden ? PHP_EOL : '<br><div style="padding-left:12px">' . PHP_EOL;
738
+ $output .= "\t " . gettype( $a ) . ': {';
739
+ $output .= $this->the_seo_framework_debug_hidden ? '' : '<div style="padding-left:12px">';
740
+ $output .= "\t\t" . $this->get_debug_information( $a );
741
+ $output .= $this->the_seo_framework_debug_hidden ? '' : '</div>' . PHP_EOL;
742
+ $output .= "\t " . '}' . PHP_EOL;
743
+ $output .= $this->the_seo_framework_debug_hidden ? '}}}' : '<br>}}}</div>';
744
  $output .= $this->the_seo_framework_debug_hidden ? '' : '</div>';
745
  }
746
  }
748
  }
749
 
750
  if ( $output ) {
 
751
  static $odd = false;
752
  if ( $odd ) {
753
  $bg = 'f1f1f1';
818
  }
819
 
820
  //* Convert to string and echo if not returned yet.
821
+ echo \esc_html( PHP_EOL . $difference_time . 's' . PHP_EOL );
822
+ echo \esc_html( ( $difference_memory / 1024 ) . 'kiB' . PHP_EOL );
823
  } else {
824
  if ( false === $echo ) {
825
  //* Return early if not allowed to echo.
826
  if ( 'time' === $what )
827
  return number_format( $plugin_time[ $key ], 5 );
828
 
829
+ return $plugin_memory[ $key ];
830
  }
831
 
832
  //* Convert to string and echo if not returned yet.
833
+ echo \esc_html( PHP_EOL . $plugin_time[ $key ] . 's' . PHP_EOL );
834
+ echo \esc_html( ( $plugin_memory[ $key ] / 1024 ) . 'kiB' . PHP_EOL );
835
  }
 
836
  }
837
 
838
  /**
857
  return $output;
858
  }
859
 
860
+ /**
861
+ * Outputs the debug header.
862
+ *
863
+ * @since 2.8.0
864
+ * @access private
865
+ */
866
+ public static function _output_debug_header() {
867
+
868
+ $instance = static::get_instance();
869
+ //* Already escaped.
870
+ echo $instance->get_debug_header_output();
871
+
872
+ }
873
+
874
  /**
875
  * Wraps header output in front-end code.
876
  * This won't consider hiding the output.
879
  *
880
  * @return string Wrapped SEO meta tags output.
881
  */
882
+ protected function get_debug_header_output() {
883
 
884
+ $tsf = \the_seo_framework();
885
+
886
+ if ( $tsf->is_admin() && ! $tsf->is_term_edit() && ! $tsf->is_post_edit() && ! $tsf->is_seo_settings_page( true ) )
887
  return;
888
 
889
+ if ( $tsf->is_seo_settings_page( true ) )
890
+ \add_filter( 'the_seo_framework_current_object_id', array( $tsf, 'get_the_front_page_ID' ) );
891
 
892
  //* Start timer.
893
  $this->timer( true );
895
  //* Don't register this output.
896
  $this->add_debug_output = false;
897
 
898
+ $output = $tsf->the_description()
899
+ . $tsf->og_image()
900
+ . $tsf->og_locale()
901
+ . $tsf->og_type()
902
+ . $tsf->og_title()
903
+ . $tsf->og_description()
904
+ . $tsf->og_url()
905
+ . $tsf->og_sitename()
906
+ . $tsf->facebook_publisher()
907
+ . $tsf->facebook_author()
908
+ . $tsf->facebook_app_id()
909
+ . $tsf->article_published_time()
910
+ . $tsf->article_modified_time()
911
+ . $tsf->twitter_card()
912
+ . $tsf->twitter_site()
913
+ . $tsf->twitter_creator()
914
+ . $tsf->twitter_title()
915
+ . $tsf->twitter_description()
916
+ . $tsf->twitter_image()
917
+ . $tsf->shortlink()
918
+ . $tsf->canonical()
919
+ . $tsf->paged_urls()
920
+ . $tsf->ld_json()
921
+ . $tsf->google_site_output()
922
+ . $tsf->bing_site_output()
923
+ . $tsf->yandex_site_output()
924
+ . $tsf->pint_site_output();
 
925
 
926
  $timer = '<div style="display:inline-block;width:100%;padding:20px;border-bottom:1px solid #ccc;">Generated in: ' . number_format( $this->timer(), 5 ) . ' seconds</div>' ;
927
 
928
+ $title = $tsf->is_admin() ? 'Expected SEO Output' : 'Current SEO Output';
929
  $title = '<div style="display:inline-block;width:100%;padding:20px;margin:0 auto;border-bottom:1px solid #ccc;"><h2 style="color:#ddd;font-size:22px;padding:0;margin:0">' . $title . '</h2></div>';
930
 
931
  //* Escape it, replace EOL with breaks, and style everything between quotes (which are ending with space).
935
  $output = '<div style="display:inline-block;width:100%;padding:20px;font-family:Consolas,Monaco,monospace;font-size:14px;">' . $output . '</div>';
936
  $output = '<div style="display:block;width:100%;background:#23282D;color:#ddd;border-bottom:1px solid #ccc">' . $title . $timer . $output . '</div>';
937
 
938
+ $this->add_debug_output = true;
939
+
940
  return $output;
941
  }
942
 
943
+ /**
944
+ * Outputs debug query.
945
+ *
946
+ * @since 2.8.0
947
+ * @access private
948
+ */
949
+ public static function _output_debug_query() {
950
+
951
+ $instance = static::$instance;
952
+ //* Already escaped.
953
+ echo $instance->get_debug_query_output();
954
+
955
+ }
956
+
957
+ /**
958
+ * Outputs debug query from cache.
959
+ *
960
+ * @since 2.8.0
961
+ * @access private
962
+ */
963
+ public static function _output_debug_query_from_cache() {
964
+
965
+ $instance = static::$instance;
966
+ //* Already escaped.
967
+ echo $instance->get_debug_query_output_from_cache();
968
+
969
+ }
970
+
971
+ /**
972
+ * Sets debug query cache.
973
+ *
974
+ * @since 2.8.0
975
+ * @access private
976
+ */
977
+ public function set_debug_query_output_cache() {
978
+ $this->get_debug_query_output_from_cache();
979
+ }
980
+
981
+ /**
982
+ * Wraps query status booleans in human-readable code.
983
+ *
984
+ * @since 2.6.6
985
+ * @global bool $multipage
986
+ * @global int $numpages
987
+ *
988
+ * @return string Wrapped Query State debug output.
989
+ */
990
+ protected function get_debug_query_output_from_cache() {
991
+
992
+ static $cache = null;
993
+
994
+ if ( isset( $cache ) )
995
+ return $cache;
996
+
997
+ return $cache = $this->get_debug_query_output( 'yup' );
998
+ }
999
+
1000
  /**
1001
  * Wraps query status booleans in human-readable code.
1002
  *
1003
  * @since 2.6.6
1004
+ * @global bool $multipage
1005
+ * @global int $numpages
1006
  *
1007
+ * @param string $cache_version 'Yes/no'
1008
  * @return string Wrapped Query State debug output.
1009
  */
1010
+ protected function get_debug_query_output( $cache_version = 'nope' ) {
1011
 
1012
  //* Start timer.
1013
  $this->timer( true );
1014
 
1015
+ //* Don't register duplicated output invoked in this method.
1016
  $this->add_debug_output = false;
1017
 
1018
  global $multipage, $numpages;
1019
 
1020
+ $tsf = \the_seo_framework();
1021
+
1022
  //* Only get true/false values.
1023
+ $is_404 = $tsf->is_404();
1024
+ $is_admin = $tsf->is_admin();
1025
+ $is_attachment = $tsf->is_attachment();
1026
+ $is_archive = $tsf->is_archive();
1027
+ $is_term_edit = $tsf->is_term_edit();
1028
+ $is_post_edit = $tsf->is_post_edit();
1029
+ $is_wp_lists_edit = $tsf->is_wp_lists_edit();
1030
+ $is_wp_lists_edit = $tsf->is_wp_lists_edit();
1031
+ $is_author = $tsf->is_author();
1032
+ $is_blog_page = $tsf->is_blog_page();
1033
+ $is_category = $tsf->is_category();
1034
+ $is_date = $tsf->is_date();
1035
+ $is_day = $tsf->is_day();
1036
+ $is_feed = $tsf->is_feed();
1037
+ $is_front_page = $tsf->is_front_page();
1038
+ $is_home = $tsf->is_home();
1039
+ $is_month = $tsf->is_month();
1040
+ $is_page = $tsf->is_page();
1041
+ $page = $tsf->page();
1042
+ $paged = $tsf->paged();
1043
+ $is_preview = $tsf->is_preview();
1044
+ $is_search = $tsf->is_search();
1045
+ $is_single = $tsf->is_single();
1046
+ $is_singular = $tsf->is_singular();
1047
+ $is_static_frontpage = $tsf->is_static_frontpage();
1048
+ $is_tag = $tsf->is_tag();
1049
+ $is_tax = $tsf->is_tax();
1050
+ $is_wc_shop = $tsf->is_wc_shop();
1051
+ $is_wc_product = $tsf->is_wc_product();
1052
+ $is_year = $tsf->is_year();
1053
+ $is_seo_settings_page = $tsf->is_seo_settings_page( true );
1054
+
1055
+ //* Don't debug the class object.
1056
+ unset( $tsf );
1057
 
1058
  //* Get all above vars, split them in two (true and false) and sort them by key names.
1059
  $vars = get_defined_vars();
1062
  ksort( $current );
1063
  ksort( $not_current );
1064
 
1065
+ $timer = '<div style="display:inline-block;width:100%;padding:20px;border-bottom:1px solid #666;">Generated in: ' . number_format( $this->timer(), 5 ) . ' seconds</div>';
1066
 
1067
  $output = '';
1068
  foreach ( $current as $name => $value ) {
1071
  if ( is_bool( $value ) ) {
1072
  $value = $value ? 'true' : 'false';
1073
  } else {
1074
+ $value = \esc_attr( var_export( $value, true ) );
1075
  }
1076
 
1077
  $value = $this->the_seo_framework_debug_hidden ? $type . ' ' . $value : '<font color="harrisonford">' . $type . ' ' . $value . '</font>';
1078
+ $out = \esc_html( $name ) . ' => ' . $value;
1079
  $output .= $this->the_seo_framework_debug_hidden ? $out . PHP_EOL : '<span style="background:#dadada">' . $out . '</span>' . PHP_EOL;
1080
  }
1081
 
1085
  if ( is_bool( $value ) ) {
1086
  $value = $value ? 'true' : 'false';
1087
  } else {
1088
+ $value = \esc_attr( var_export( $value, true ) );
1089
  }
1090
 
1091
  $value = $this->the_seo_framework_debug_hidden ? $type . ' ' . $value : '<font color="harrisonford">' . $type . ' ' . $value . '</font>';
1092
+ $out = \esc_html( $name ) . ' => ' . $value;
1093
  $output .= $out . PHP_EOL;
1094
  }
1095
 
1096
+ if ( 'yes' === $cache_version || 'yup' === $cache_version ) {
1097
+ $title = 'WordPress Query at Meta Generation';
1098
+ } else {
1099
+ $title = \the_seo_framework()->is_admin() ? 'Current WordPress Screen + Expected WordPress Query' : 'Current WordPress Query';
1100
+ }
1101
  $title = '<div style="display:inline-block;width:100%;padding:20px;margin:0 auto;border-bottom:1px solid #666;"><h2 style="color:#222;font-size:22px;padding:0;margin:0">' . $title . '</h2></div>';
1102
 
1103
  $output = $this->the_seo_framework_debug_hidden ? $output : str_replace( PHP_EOL, '<br>' . PHP_EOL, $output );
1105
  $output = '<div style="display:inline-block;width:100%;padding:20px;font-family:Consolas,Monaco,monospace;font-size:14px;">' . $output . '</div>';
1106
  $output = '<div style="display:block;width:100%;background:#fafafa;color:#333;border-bottom:1px solid #666">' . $title . $timer . $output . '</div>';
1107
 
1108
+ $this->add_debug_output = true;
1109
+
1110
  return $output;
1111
  }
1112
  }
inc/classes/deprecated.class.php ADDED
@@ -0,0 +1,505 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes\Deprecated
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
+ /**
10
+ * The SEO Framework plugin
11
+ * Copyright (C) 2015 - 2016 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
15
+ * by the Free Software Foundation.
16
+ *
17
+ * This program is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
+ */
25
+
26
+ defined( 'ABSPATH' ) or die;
27
+
28
+ /**
29
+ * Class The_SEO_Framework\Deprecated
30
+ *
31
+ * Contains all deprecated functions.
32
+ *
33
+ * @since 2.8.0
34
+ */
35
+ final class Deprecated {
36
+
37
+ /**
38
+ * Constructor. Does nothing.
39
+ */
40
+ public function __construct() { }
41
+
42
+ /**
43
+ * HomePage Metabox General Tab Output.
44
+ *
45
+ * @since 2.6.0
46
+ * @see $this->homepage_metabox() Callback for HomePage Settings box.
47
+ *
48
+ * @deprecated
49
+ * @since 2.7.0
50
+ */
51
+ public function homepage_metabox_general() {
52
+ \the_seo_framework()->_deprecated_function( 'The_SEO_Framework_Metaboxes::' . __FUNCTION__, '2.7.0', 'The_SEO_Framework_Metaboxes::homepage_metabox_general_tab()' );
53
+ \the_seo_framework()->get_view( 'metaboxes/homepage-metabox', array(), 'general' );
54
+ }
55
+
56
+ /**
57
+ * HomePage Metabox Additions Tab Output.
58
+ *
59
+ * @since 2.6.0
60
+ * @see $this->homepage_metabox() Callback for HomePage Settings box.
61
+ *
62
+ * @deprecated
63
+ * @since 2.7.0
64
+ */
65
+ public function homepage_metabox_additions() {
66
+ \the_seo_framework()->_deprecated_function( 'The_SEO_Framework_Metaboxes::' . __FUNCTION__, '2.7.0', 'The_SEO_Framework_Metaboxes::homepage_metabox_additions_tab()' );
67
+ \the_seo_framework()->get_view( 'metaboxes/homepage-metabox', array(), 'additions' );
68
+ }
69
+
70
+ /**
71
+ * HomePage Metabox Robots Tab Output
72
+ *
73
+ * @since 2.6.0
74
+ * @see $this->homepage_metabox() Callback for HomePage Settings box.
75
+ *
76
+ * @deprecated
77
+ * @since 2.7.0
78
+ */
79
+ public function homepage_metabox_robots() {
80
+ \the_seo_framework()->_deprecated_function( 'The_SEO_Framework_Metaboxes::' . __FUNCTION__, '2.7.0', 'The_SEO_Framework_Metaboxes::homepage_metabox_robots_tab()' );
81
+ \the_seo_framework()->get_view( 'metaboxes/homepage-metabox', array(), 'robots' );
82
+ }
83
+
84
+ /**
85
+ * Delete transient for the automatic description for blog on save request.
86
+ * Returns old option, since that's passed for sanitation within WP Core.
87
+ *
88
+ * @since 2.3.3
89
+ *
90
+ * @deprecated
91
+ * @since 2.7.0
92
+ *
93
+ * @param string $old_option The previous blog description option.
94
+ * @return string Previous option.
95
+ */
96
+ public function delete_auto_description_blog_transient( $old_option ) {
97
+
98
+ \the_seo_framework()->_deprecated_function( 'The_SEO_Framework_Transients::' . __FUNCTION__, '2.7.0', 'The_SEO_Framework_Transients::delete_auto_description_frontpage_transient()' );
99
+
100
+ \the_seo_framework()->delete_auto_description_transient( the_seo_framework()->get_the_front_page_ID(), '', 'frontpage' );
101
+
102
+ return $old_option;
103
+ }
104
+
105
+ /**
106
+ * Add term meta data into options table of the term.
107
+ * Adds separated database options for terms, as the terms table doesn't allow for addition.
108
+ *
109
+ * Applies filters array the_seo_framework_term_meta_defaults : Array of default term SEO options
110
+ * Applies filters mixed the_seo_framework_term_meta_{field} : Override filter for specifics.
111
+ * Applies filters array the_seo_framework_term_meta : Override output for term or taxonomy.
112
+ *
113
+ * @since 2.1.8
114
+ *
115
+ * @deprecated silently.
116
+ * @since WordPress 4.4.0
117
+ * @since The SEO Framework 2.7.0
118
+ * @since 2.8.0: Deprecated visually.
119
+ *
120
+ * @param object $term Database row object.
121
+ * @param string $taxonomy Taxonomy name that $term is part of.
122
+ * @return object $term Database row object.
123
+ */
124
+ public function get_term_filter( $term, $taxonomy ) {
125
+
126
+ \the_seo_framework()->_deprecated_function( 'The_SEO_Framework_Transients::' . __FUNCTION__, '2.7.0', 'WordPress Core "get_term_meta()"' );
127
+
128
+ return false;
129
+ }
130
+
131
+ /**
132
+ * Adds The SEO Framework term meta data to functions that return multiple terms.
133
+ *
134
+ * @since 2.0.0
135
+ *
136
+ * @deprecated silently.
137
+ * @since WordPress 4.4.0
138
+ * @since The SEO Framework 2.7.0
139
+ * @since 2.8.0: Deprecated visually.
140
+ *
141
+ * @param array $terms Database row objects.
142
+ * @param string $taxonomy Taxonomy name that $terms are part of.
143
+ * @return array $terms Database row objects.
144
+ */
145
+ public function get_terms_filter( array $terms, $taxonomy ) {
146
+
147
+ \the_seo_framework()->_deprecated_function( 'The_SEO_Framework_Transients::' . __FUNCTION__, '2.7.0', 'WordPress Core "get_term_meta()"' );
148
+
149
+ return false;
150
+ }
151
+
152
+ /**
153
+ * Save taxonomy meta data.
154
+ * Fires when a user edits and saves a taxonomy.
155
+ *
156
+ * @since 2.1.8
157
+ *
158
+ * @deprecated silently.
159
+ * @since WordPress 4.4.0
160
+ * @since The SEO Framework 2.7.0
161
+ * @since 2.8.0: Deprecated visually.
162
+ *
163
+ * @param integer $term_id Term ID.
164
+ * @param integer $tt_id Term Taxonomy ID.
165
+ * @return void Early on AJAX call.
166
+ */
167
+ public function taxonomy_seo_save( $term_id, $tt_id ) {
168
+
169
+ \the_seo_framework()->_deprecated_function( 'The_SEO_Framework_Transients::' . __FUNCTION__, '2.7.0', 'WordPress Core "update_term_meta()"' );
170
+
171
+ return false;
172
+ }
173
+
174
+ /**
175
+ * Delete term meta data.
176
+ * Fires when a user deletes a term.
177
+ *
178
+ * @since 2.1.8
179
+ *
180
+ * @deprecated silently.
181
+ * @since WordPress 4.4.0
182
+ * @since The SEO Framework 2.7.0
183
+ * @since 2.8.0: Deprecated visually.
184
+ *
185
+ * @param integer $term_id Term ID.
186
+ * @param integer $tt_id Taxonomy Term ID.
187
+ */
188
+ public function term_meta_delete( $term_id, $tt_id ) {
189
+
190
+ \the_seo_framework()->_deprecated_function( 'The_SEO_Framework_Transients::' . __FUNCTION__, '2.7.0', 'WordPress Core "delete_term_meta()"' );
191
+
192
+ return false;
193
+ }
194
+
195
+ /**
196
+ * Faster way of doing an in_array search compared to default PHP behavior.
197
+ * @NOTE only to show improvement with large arrays. Might slow down with small arrays.
198
+ * @NOTE can't do type checks. Always assume the comparing value is a string.
199
+ *
200
+ * @since 2.5.2
201
+ * @since 2.7.0 Deprecated.
202
+ * @deprecated
203
+ *
204
+ * @param string|array $needle The needle(s) to search for
205
+ * @param array $array The single dimensional array to search in.
206
+ * @return bool true if value is in array.
207
+ */
208
+ public function in_array( $needle, $array, $strict = true ) {
209
+
210
+ \the_seo_framework()->_deprecated_function( 'The_SEO_Framework_Core::' . __FUNCTION__, '2.7.0', 'in_array()' );
211
+
212
+ $array = array_flip( $array );
213
+
214
+ if ( is_string( $needle ) ) {
215
+ if ( isset( $array[ $needle ] ) )
216
+ return true;
217
+ } elseif ( is_array( $needle ) ) {
218
+ foreach ( $needle as $str ) {
219
+ if ( isset( $array[ $str ] ) )
220
+ return true;
221
+ }
222
+ }
223
+
224
+ return false;
225
+ }
226
+
227
+ /**
228
+ * Fetches posts with exclude_local_search option on
229
+ *
230
+ * @since 2.1.7
231
+ * @since 2.7.0 Deprecated.
232
+ * @deprecated
233
+ *
234
+ * @return array Excluded Post IDs
235
+ */
236
+ public function exclude_search_ids() {
237
+
238
+ \the_seo_framework()->_deprecated_function( 'The_SEO_Framework_Search::' . __FUNCTION__, '2.7.0', 'the_seo_framework()->get_excluded_search_ids()' );
239
+
240
+ return $this->get_excluded_search_ids();
241
+ }
242
+
243
+ /**
244
+ * Fetches posts with exclude_local_search option on.
245
+ *
246
+ * @since 2.1.7
247
+ * @since 2.7.0 No longer used for performance reasons.
248
+ * @uses $this->exclude_search_ids()
249
+ * @deprecated
250
+ * @since 2.8.0
251
+ *
252
+ * @param array $query The possible search query.
253
+ * @return void Early if no search query is found.
254
+ */
255
+ public function search_filter( $query ) {
256
+
257
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->search_filter()', '2.8.0' );
258
+
259
+ // Don't exclude pages in wp-admin.
260
+ if ( $query->is_search && false === \the_seo_framework()->is_admin() ) {
261
+
262
+ $q = $query->query;
263
+ //* Only interact with an actual Search Query.
264
+ if ( false === isset( $q['s'] ) )
265
+ return;
266
+
267
+ //* Get excluded IDs.
268
+ $protected_posts = $this->get_excluded_search_ids();
269
+ if ( $protected_posts ) {
270
+ $get = $query->get( 'post__not_in' );
271
+
272
+ //* Merge user defined query.
273
+ if ( is_array( $get ) && ! empty( $get ) )
274
+ $protected_posts = array_merge( $protected_posts, $get );
275
+
276
+ $query->set( 'post__not_in', $protected_posts );
277
+ }
278
+
279
+ // Parse all ID's, even beyond the first page.
280
+ $query->set( 'no_found_rows', false );
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Fetches posts with exclude_local_search option on
286
+ *
287
+ * @since 2.7.0
288
+ * @since 2.7.0 No longer used.
289
+ * @global int $blog_id
290
+ * @deprecated
291
+ *
292
+ * @return array Excluded Post IDs
293
+ */
294
+ public function get_excluded_search_ids() {
295
+
296
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->get_excluded_search_ids()', '2.7.0' );
297
+
298
+ global $blog_id;
299
+
300
+ $cache_key = 'exclude_search_ids_' . $blog_id . '_' . \get_locale();
301
+
302
+ $post_ids = \the_seo_framework()->object_cache_get( $cache_key );
303
+ if ( false === $post_ids ) {
304
+ $post_ids = array();
305
+
306
+ $args = array(
307
+ 'post_type' => 'any',
308
+ 'numberposts' => -1,
309
+ 'posts_per_page' => -1,
310
+ 'order' => 'DESC',
311
+ 'post_status' => 'publish',
312
+ 'meta_key' => 'exclude_local_search',
313
+ 'meta_value' => 1,
314
+ 'meta_compare' => '=',
315
+ 'cache_results' => true,
316
+ 'suppress_filters' => false,
317
+ );
318
+ $get_posts = new \WP_Query;
319
+ $excluded_posts = $get_posts->query( $args );
320
+ unset( $get_posts );
321
+
322
+ if ( $excluded_posts )
323
+ $post_ids = \wp_list_pluck( $excluded_posts, 'ID' );
324
+
325
+ \the_seo_framework()->object_cache_set( $cache_key, $post_ids, 86400 );
326
+ }
327
+
328
+ // return an array of exclude post IDs
329
+ return $post_ids;
330
+ }
331
+
332
+ /**
333
+ * Registers option sanitation filter
334
+ *
335
+ * @since 2.2.2
336
+ * @since 2.7.0 : No longer used internally.
337
+ * @since 2.8.0 : Deprecated
338
+ * @deprecated
339
+ *
340
+ * @param string $filter The filter to call (see The_SEO_Framework_Site_Options::$available_filters for options)
341
+ * @param string $option The WordPress option name
342
+ * @param string|array $suboption Optional. The suboption or suboptions you want to filter
343
+ * @return true on completion.
344
+ */
345
+ public function autodescription_add_option_filter( $filter, $option, $suboption = null ) {
346
+
347
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->add_option_filter()', '2.8.0' );
348
+
349
+ return \the_seo_framework()->add_option_filter( $filter, $option, $suboption );
350
+ }
351
+
352
+ /**
353
+ * Register each of the settings with a sanitization filter type.
354
+ *
355
+ * @since 2.2.2
356
+ * @since 2.8.0 Deprecated.
357
+ * @uses method add_filter() Assign filter to array of settings.
358
+ * @see The_SEO_Framework_Sanitize::add_filter() Add sanitization filters to options.
359
+ */
360
+ public function sanitizer_filters() {
361
+
362
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->sanitizer_filters()', '2.8.0', 'the_seo_framework()->init_sanitizer_filters()' );
363
+
364
+ \the_seo_framework()->init_sanitizer_filters();
365
+ }
366
+
367
+ /**
368
+ * Fetches site icon brought in WordPress 4.3.0
369
+ *
370
+ * @since 2.2.1
371
+ * @since 2.8.0: Deprecated.
372
+ * @deprecated
373
+ *
374
+ * @param string $size The icon size, accepts 'full' and pixel values.
375
+ * @param bool $set_og_dimensions Whether to set size for OG image. Always falls back to the current post ID.
376
+ * @return string URL site icon, not escaped.
377
+ */
378
+ public function site_icon( $size = 'full', $set_og_dimensions = false ) {
379
+
380
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->site_icon()', '2.8.0', 'the_seo_framework()->get_site_icon()' );
381
+
382
+ return the_seo_framework()->get_site_icon( $size, $set_og_dimensions );
383
+ }
384
+
385
+ /**
386
+ * Delete transient on post save.
387
+ *
388
+ * @since 2.2.9
389
+ * @since 2.8.0 : Deprecated
390
+ * @deprecated
391
+ *
392
+ * @param int $post_id The Post ID that has been updated.
393
+ * @return bool|null True when sitemap is flushed. False on revision. Null
394
+ * when sitemaps are deactivated.
395
+ */
396
+ public function delete_transients_post( $post_id ) {
397
+
398
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->delete_transients_post()', '2.8.0', 'the_seo_framework()->delete_post_cache()' );
399
+
400
+ return \the_seo_framework()->delete_post_cache( $post_id );
401
+ }
402
+
403
+ /**
404
+ * Delete transient on profile save.
405
+ *
406
+ * @since 2.6.4
407
+ * @since 2.8.0 : Deprecated
408
+ * @deprecated
409
+ *
410
+ * @param int $user_id The User ID that has been updated.
411
+ */
412
+ public function delete_transients_author( $user_id ) {
413
+
414
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->delete_transients_author()', '2.8.0', 'the_seo_framework()->delete_author_cache()' );
415
+
416
+ return \the_seo_framework()->delete_author_cache( $user_id );
417
+ }
418
+
419
+ /**
420
+ * Flushes the home page LD+Json transient.
421
+ *
422
+ * @since 2.6.0
423
+ * @since 2.8.0 deprecated.
424
+ * @staticvar bool $flushed Prevents second flush.
425
+ * @deprecated
426
+ *
427
+ * @return bool Whether it's flushed on current call.
428
+ */
429
+ public function delete_front_ld_json_transient() {
430
+
431
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->delete_front_ld_json_transient()', '2.8.0', 'the_seo_framework()->delete_cache( \'front\' )' );
432
+
433
+ static $flushed = null;
434
+
435
+ if ( isset( $flushed ) )
436
+ return false;
437
+
438
+ if ( ! \the_seo_framework()->is_option_checked( 'cache_meta_schema' ) )
439
+ return $flushed = false;
440
+
441
+ $front_id = \the_seo_framework()->get_the_front_page_ID();
442
+
443
+ \the_seo_framework()->delete_ld_json_transient( $front_id, '', 'frontpage' );
444
+
445
+ return $flushed = true;
446
+ }
447
+
448
+ /**
449
+ * Determines whether we can use the new WordPress core term meta functionality.
450
+ *
451
+ * @since 2.7.0
452
+ * @since 2.8.0: Deprecated. WordPress 4.4+ is now required.
453
+ * @staticvar bool $cache
454
+ * @deprecated
455
+ *
456
+ * @return bool True when WordPress is at version 4.4 or higher and has an
457
+ * accordingly upgraded database.
458
+ */
459
+ public function can_get_term_meta() {
460
+
461
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->can_get_term_meta()', '2.8.0' );
462
+
463
+ static $cache = null;
464
+
465
+ if ( isset( $cache ) )
466
+ return $cache;
467
+
468
+ return $cache = \get_option( 'db_version' ) >= 34370 && \get_option( 'the_seo_framework_upgraded_db_version' ) >= '2700' && \the_seo_framework()->wp_version( '4.3.999', '>' );
469
+ }
470
+
471
+ /**
472
+ * Fetches term metadata array for the inpost term metabox.
473
+ *
474
+ * @since 2.7.0
475
+ * @since 2.8.0: Deprecated. WordPress 4.4+ is now required.
476
+ * @deprecated
477
+ *
478
+ * @param object $term The TT object. Must be assigned.
479
+ * @return array The SEO Framework TT data.
480
+ */
481
+ protected function get_old_term_data( $term ) {
482
+
483
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->get_old_term_data()', '2.8.0' );
484
+
485
+ $data = array();
486
+
487
+ $data['title'] = isset( $term->admeta['doctitle'] ) ? $term->admeta['doctitle'] : '';
488
+ $data['description'] = isset( $term->admeta['description'] ) ? $term->admeta['description'] : '';
489
+ $data['noindex'] = isset( $term->admeta['noindex'] ) ? $term->admeta['noindex'] : '';
490
+ $data['nofollow'] = isset( $term->admeta['nofollow'] ) ? $term->admeta['nofollow'] : '';
491
+ $data['noarchive'] = isset( $term->admeta['noarchive'] ) ? $term->admeta['noarchive'] : '';
492
+ $flag = isset( $term->admeta['saved_flag'] ) ? (bool) $term->admeta['saved_flag'] : false;
493
+
494
+ //* Genesis data fetch. This will override our options with Genesis options on save.
495
+ if ( false === $flag && isset( $term->meta ) ) {
496
+ $data['title'] = empty( $data['title'] ) && isset( $term->meta['doctitle'] ) ? $term->meta['doctitle'] : $data['noindex'];
497
+ $data['description'] = empty( $data['description'] ) && isset( $term->meta['description'] ) ? $term->meta['description'] : $data['description'];
498
+ $data['noindex'] = empty( $data['noindex'] ) && isset( $term->meta['noindex'] ) ? $term->meta['noindex'] : $data['noindex'];
499
+ $data['nofollow'] = empty( $data['nofollow'] ) && isset( $term->meta['nofollow'] ) ? $term->meta['nofollow'] : $data['nofollow'];
500
+ $data['noarchive'] = empty( $data['noarchive'] ) && isset( $term->meta['noarchive'] ) ? $term->meta['noarchive'] : $data['noarchive'];
501
+ }
502
+
503
+ return $data;
504
+ }
505
+ }
inc/classes/detect.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -19,30 +26,18 @@
19
  defined( 'ABSPATH' ) or die;
20
 
21
  /**
22
- * Class AutoDescription_Detect
23
  *
24
  * Detects other plugins and themes
25
  *
26
- * @since 2.1.6
27
  */
28
- class AutoDescription_Detect extends AutoDescription_Render {
29
-
30
- /**
31
- * Unserializing instances of this class is forbidden.
32
- */
33
- private function __wakeup() { }
34
-
35
- /**
36
- * Handle unapproachable invoked methods.
37
- */
38
- public function __call( $name, $arguments ) {
39
- parent::__call( $name, $arguments );
40
- }
41
 
42
  /**
43
  * Constructor, load parent constructor
44
  */
45
- public function __construct() {
46
  parent::__construct();
47
  }
48
 
@@ -62,12 +57,12 @@ class AutoDescription_Detect extends AutoDescription_Render {
62
  if ( isset( $active_plugins ) )
63
  return $active_plugins;
64
 
65
- $active_plugins = (array) get_option( 'active_plugins', array() );
66
 
67
- if ( is_multisite() ) {
68
  // Due to legacy code, active_sitewide_plugins stores them in the keys,
69
  // whereas active_plugins stores them in the values.
70
- $network_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
71
  if ( $network_plugins ) {
72
  $active_plugins = array_merge( $active_plugins, $network_plugins );
73
  }
@@ -81,7 +76,6 @@ class AutoDescription_Detect extends AutoDescription_Render {
81
  /**
82
  * Filterable list of conflicting plugins.
83
  *
84
- * Applies filters 'the_seo_framework_conflicting_plugins' : array
85
  * @since 2.6.0
86
  * @credits JetPack for most code.
87
  *
@@ -103,49 +97,38 @@ class AutoDescription_Detect extends AutoDescription_Render {
103
  'Google XML Sitemaps for qTranslate' => 'google-xml-sitemaps-v3-for-qtranslate/sitemap.php',
104
  'XML Sitemap & Google News feeds' => 'xml-sitemap-feed/xml-sitemap.php',
105
  'Google Sitemap by BestWebSoft' => 'google-sitemap-plugin/google-sitemap-plugin.php',
106
- 'Yoast SEO' => 'wordpress-seo/wp-seo.php',
107
- 'Yoast SEO Premium' => 'wordpress-seo-premium/wp-seo-premium.php',
108
- 'All in One SEO Pack' => 'all-in-one-seo-pack/all_in_one_seo_pack.php',
109
- 'Sitemap' => 'sitemap/sitemap.php',
110
  'Simple Wp Sitemap' => 'simple-wp-sitemap/simple-wp-sitemap.php',
111
  'Simple Sitemap' => 'simple-sitemap/simple-sitemap.php',
112
  'XML Sitemaps' => 'xml-sitemaps/xml-sitemaps.php',
113
  ),
114
  'open_graph' => array(
115
- '2 Click Social Media Buttons' => '2-click-socialmedia-buttons/2-click-socialmedia-buttons.php',
116
  'Add Link to Facebook' => 'add-link-to-facebook/add-link-to-facebook.php',
117
- 'Add Meta Tags' => 'add-meta-tags/add-meta-tags.php',
118
- 'Facebook' => 'facebook/facebook.php',
119
  'Facebook AWD All in one' => 'facebook-awd/AWD_facebook.php',
120
  'Facebook Featured Image & OG Meta Tags' => 'facebook-featured-image-and-open-graph-meta-tags/fb-featured-image.php',
121
  'Facebook Meta Tags' => 'facebook-meta-tags/facebook-metatags.php',
122
  'Facebook Open Graph Meta Tags for WordPress' => 'wonderm00ns-simple-facebook-open-graph-tags/wonderm00n-open-graph.php',
123
- 'Facebook Revised Open Graph Meta Tag' => 'facebook-revised-open-graph-meta-tag/index.php',
124
  'Facebook Thumb Fixer' => 'facebook-thumb-fixer/_facebook-thumb-fixer.php',
125
  'Fedmichs Facebook Open Graph Meta' => 'facebook-and-digg-thumbnail-generator/facebook-and-digg-thumbnail-generator.php',
126
  'Header and Footer' => 'header-footer/plugin.php',
127
- 'Network Publisher' => 'network-publisher/networkpub.php',
128
  'NextGEN Facebook OG' => 'nextgen-facebook/nextgen-facebook.php',
129
  'NextScripts SNAP' => 'social-networks-auto-poster-facebook-twitter-g/NextScripts_SNAP.php',
130
  'Open Graph' => 'opengraph/opengraph.php',
131
  'Open Graph Protocol Framework' => 'open-graph-protocol-framework/open-graph-protocol-framework.php',
132
- 'Shareaholic' => 'sexybookmarks/sexy-bookmarks.php',
133
  'Shareaholic2' => 'shareaholic/sexy-bookmarks.php',
134
- 'SharePress' => 'sharepress/sharepress.php',
135
  'Social Sharing Toolkit' => 'social-sharing-toolkit/social_sharing_toolkit.php',
136
- 'Tweet, Like, Google +1 and Share' => 'only-tweet-like-share-and-google-1/tweet-like-plusone.php',
137
  'WordPress Social Sharing Optimization' => 'wpsso/wpsso.php',
138
  'WP Facebook Open Graph protocol' => 'wp-facebook-open-graph-protocol/wp-facebook-ogp.php',
139
  ),
140
  'twitter_card' => array(
141
  'Twitter' => 'twitter/twitter.php',
142
- 'Eewee Twitter Card' => 'eewee-twitter-card/index.php',
143
- 'Twitter Cards' => 'twitter-cards/twitter-cards.php',
144
- 'Twitter Cards Meta' => 'twitter-cards-meta/twitter-cards-meta.php',
145
  ),
146
  );
147
 
148
- return (array) apply_filters( 'the_seo_framework_conflicting_plugins', $conflicting_plugins );
 
 
 
 
149
  }
150
 
151
  /**
@@ -161,7 +144,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
161
  $conflicting_plugins = $this->conflicting_plugins();
162
 
163
  if ( isset( $conflicting_plugins[ $type ] ) )
164
- return (array) apply_filters( 'the_seo_framework_conflicting_plugins_type', $conflicting_plugins[ $type ], $type );
165
 
166
  return array();
167
  }
@@ -169,17 +152,30 @@ class AutoDescription_Detect extends AutoDescription_Render {
169
  /**
170
  * Detect active plugin by constant, class or function existence.
171
  *
 
 
172
  * @since 1.3.0
 
 
173
  *
174
  * @param array $plugins Array of array for constants, classes and / or functions to check for plugin existence.
175
  * @return boolean True if plugin exists or false if plugin constant, class or function not detected.
176
  */
177
  public function detect_plugin( $plugins ) {
178
 
179
- //* Check for classes
180
- if ( isset( $plugins['classes'] ) ) {
181
- foreach ( $plugins['classes'] as $name ) {
182
- if ( class_exists( $name ) ) {
 
 
 
 
 
 
 
 
 
183
  return true;
184
  break;
185
  }
@@ -196,10 +192,10 @@ class AutoDescription_Detect extends AutoDescription_Render {
196
  }
197
  }
198
 
199
- //* Check for constants
200
- if ( isset( $plugins['constants'] ) ) {
201
- foreach ( $plugins['constants'] as $name ) {
202
- if ( defined( $name ) ) {
203
  return true;
204
  break;
205
  }
@@ -313,7 +309,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
313
  if ( empty( $themes ) )
314
  return false;
315
 
316
- $wp_get_theme = wp_get_theme();
317
 
318
  $theme_parent = strtolower( $wp_get_theme->get( 'Template' ) );
319
  $theme_name = strtolower( $wp_get_theme->get( 'Name' ) );
@@ -339,9 +335,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
339
  * Determines if other SEO plugins are active.
340
  *
341
  * @since 1.3.0
342
- *
343
- * Applies filters 'the_seo_framework_seo_plugin_detected' : bool
344
- * @since 2.6.1
345
  *
346
  * @return bool SEO plugin detected.
347
  */
@@ -349,11 +343,6 @@ class AutoDescription_Detect extends AutoDescription_Render {
349
 
350
  static $detected = null;
351
 
352
- if ( isset( $detected ) )
353
- return $detected;
354
-
355
- //* Old style filter.
356
- $detected = $this->detect_seo_plugins_old();
357
  if ( isset( $detected ) )
358
  return $detected;
359
 
@@ -364,7 +353,11 @@ class AutoDescription_Detect extends AutoDescription_Render {
364
 
365
  foreach ( $conflicting_plugins as $plugin ) {
366
  if ( in_array( $plugin, $active_plugins, true ) ) {
367
- $detected = apply_filters( 'the_seo_framework_seo_plugin_detected', true );
 
 
 
 
368
  break;
369
  }
370
  }
@@ -377,9 +370,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
377
  * Determines if other Open Graph or SEO plugins are active.
378
  *
379
  * @since 1.3.0
380
- *
381
- * Applies filters 'the_seo_framework_og_plugin_detected' : bool
382
- * @since 2.6.1
383
  *
384
  * @return bool True if OG or SEO plugin detected.
385
  */
@@ -391,13 +382,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
391
  return $detected;
392
 
393
  //* Detect SEO plugins beforehand.
394
- $detected = $this->detect_seo_plugins();
395
- if ( $detected )
396
- return $detected;
397
-
398
- //* Old style filter. Emits warning if used.
399
- $detected = $this->has_og_plugin();
400
- if ( isset( $detected ) )
401
  return $detected;
402
 
403
  $active_plugins = $this->active_plugins();
@@ -407,7 +392,11 @@ class AutoDescription_Detect extends AutoDescription_Render {
407
 
408
  foreach ( $conflicting_plugins as $plugin ) {
409
  if ( in_array( $plugin, $active_plugins, true ) ) {
410
- $detected = apply_filters( 'the_seo_framework_og_plugin_detected', true );
 
 
 
 
411
  break;
412
  }
413
  }
@@ -432,8 +421,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
432
  return $detected;
433
 
434
  //* Detect SEO plugins beforehand.
435
- $detected = $this->detect_seo_plugins();
436
- if ( $detected )
437
  return $detected;
438
 
439
  $active_plugins = $this->active_plugins();
@@ -443,7 +431,11 @@ class AutoDescription_Detect extends AutoDescription_Render {
443
 
444
  foreach ( $conflicting_plugins as $plugin ) {
445
  if ( in_array( $plugin, $active_plugins, true ) ) {
446
- $detected = apply_filters( 'the_seo_framework_twittercard_plugin_detected', true );
 
 
 
 
447
  break;
448
  }
449
  }
@@ -465,7 +457,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
465
  * Applies filters 'the_seo_framework_ldjson_plugin_detected' : boolean
466
  * @since 2.6.5
467
  */
468
- return (bool) apply_filters( 'the_seo_framework_ldjson_plugin_detected', false );
469
  }
470
 
471
  /**
@@ -483,6 +475,10 @@ class AutoDescription_Detect extends AutoDescription_Render {
483
  if ( isset( $detected ) )
484
  return $detected;
485
 
 
 
 
 
486
  $active_plugins = $this->active_plugins();
487
 
488
  if ( ! empty( $active_plugins ) ) {
@@ -490,7 +486,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
490
 
491
  foreach ( $conflicting_plugins as $plugin ) {
492
  if ( in_array( $plugin, $active_plugins, true ) ) {
493
- $detected = apply_filters( 'the_seo_framework_sitemap_plugin_detected', true );
494
  break;
495
  }
496
  }
@@ -503,24 +499,28 @@ class AutoDescription_Detect extends AutoDescription_Render {
503
  * Determines whether to add a line within robots based by plugin detection, or sitemap output option.
504
  *
505
  * @since 2.6.0
 
506
  *
 
507
  * @return bool True when no conflicting plugins are detected or when The SEO Framework's Sitemaps are output.
508
  */
509
- public function can_do_sitemap_robots() {
510
 
511
  $plugins = array(
512
  'functions' => array(
513
- 'jetpack_sitemap_initialize' // Jetpack
514
  ),
515
  );
516
 
517
  if ( $this->detect_plugin( $plugins ) )
518
  return false;
519
 
520
- if ( $this->is_option_checked( 'sitemaps_output' ) )
521
- return true;
 
 
522
 
523
- return false;
524
  }
525
 
526
  /**
@@ -538,7 +538,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
538
  if ( isset( $has_robots ) )
539
  return $has_robots;
540
 
541
- $path = get_home_path() . 'robots.txt';
542
 
543
  return $has_robots = file_exists( $path );
544
  }
@@ -558,7 +558,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
558
  if ( isset( $has_map ) )
559
  return $has_map;
560
 
561
- $path = get_home_path() . 'sitemap.xml';
562
 
563
  return $has_map = file_exists( $path );
564
  }
@@ -573,7 +573,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
573
  *
574
  * @param string $version the three part version to compare to WordPress
575
  * @param string $compare the comparing operator, default "$version >= Current WP Version"
576
- * @return bool wp version is "compare" to
577
  */
578
  public function wp_version( $version = '4.3.0', $compare = '>=' ) {
579
 
@@ -587,7 +587,10 @@ class AutoDescription_Detect extends AutoDescription_Render {
587
 
588
  $wp_version = $GLOBALS['wp_version'];
589
 
590
- // Add a .0 if WP outputs something like 4.3 instead of 4.3.0
 
 
 
591
  if ( 3 === strlen( $wp_version ) )
592
  $wp_version = $wp_version . '.0';
593
 
@@ -611,12 +614,12 @@ class AutoDescription_Detect extends AutoDescription_Render {
611
  if ( ! $use_cache ) {
612
  //* Don't use cache.
613
 
614
- if ( is_string( $features ) && ( current_theme_supports( $features ) ) )
615
  return true;
616
 
617
  if ( is_array( $features ) ) {
618
  foreach ( $features as $feature ) {
619
- if ( current_theme_supports( $feature ) ) {
620
  return true;
621
  break;
622
  }
@@ -648,14 +651,14 @@ class AutoDescription_Detect extends AutoDescription_Render {
648
 
649
  //* Setup cache values
650
  if ( is_string( $features ) ) {
651
- if ( current_theme_supports( $features ) ) {
652
  return $cache[ $features ] = true;
653
  } else {
654
  return $cache[ $features ] = false;
655
  }
656
  } elseif ( is_array( $features ) ) {
657
  foreach ( $features as $feature ) {
658
- if ( current_theme_supports( $feature ) ) {
659
  return $cache[ $feature ] = true;
660
  break;
661
  } else {
@@ -758,91 +761,18 @@ class AutoDescription_Detect extends AutoDescription_Render {
758
 
759
  //* Echo the HTML comment.
760
  if ( $output )
761
- echo '<!-- Title diw: "' . esc_html( $title_output ) . '" : "' . esc_html( $sep_output ) . '" : "' . esc_html( $seplocation_output ) . '" -->' . "\r\n";
762
 
763
  return;
764
  }
765
 
766
- /**
767
- * Detects WPMUdev Domain Mapping plugin.
768
- *
769
- * @since 2.3.0
770
- * @staticvar bool $active
771
- *
772
- * @return bool
773
- */
774
- public function is_domainmapping_active() {
775
-
776
- static $active = null;
777
-
778
- if ( isset( $active ) )
779
- return $active;
780
-
781
- return $active = $this->detect_plugin( array( 'classes' => array( 'domain_map' ) ) );
782
- }
783
-
784
- /**
785
- * Detects Donncha Domain Mapping plugin.
786
- *
787
- * @since 2.4.0
788
- * @staticvar bool $active
789
- *
790
- * @return bool
791
- */
792
- public function is_donncha_domainmapping_active() {
793
-
794
- static $active = null;
795
-
796
- if ( isset( $active ) )
797
- return $active;
798
-
799
- return $active = $this->detect_plugin( array( 'functions' => array( 'redirect_to_mapped_domain' ) ) );
800
- }
801
-
802
- /**
803
- * Detects WPML plugin.
804
- *
805
- * @since 2.6.0
806
- * @staticvar bool $active
807
- *
808
- * @return bool
809
- */
810
- public function is_wpml_active() {
811
-
812
- static $active = null;
813
-
814
- if ( isset( $active ) )
815
- return $active;
816
-
817
- return $active = $this->detect_plugin( array( 'constants' => array( 'ICL_LANGUAGE_CODE' ) ) );
818
- }
819
-
820
- /**
821
- * Detect qTranslate X plugin.
822
- *
823
- * @since 2.6.0
824
- * @staticvar bool $active
825
- *
826
- * @return bool
827
- */
828
- public function is_qtranslate_active() {
829
-
830
- static $active = null;
831
-
832
- if ( isset( $active ) )
833
- return $active;
834
-
835
- return $active = $this->detect_plugin( array( 'constants' => array( 'QTX_VERSION' ) ) );
836
- }
837
-
838
  /**
839
  * Detect if the current screen type is a page or taxonomy.
840
  *
841
- * @param string $type the Screen type
842
  * @staticvar array $is_page
843
- *
844
  * @since 2.3.1
845
  *
 
846
  * @return bool true if post type is a page or post
847
  */
848
  public function is_post_type_page( $type ) {
@@ -852,7 +782,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
852
  if ( isset( $is_page[ $type ] ) )
853
  return $is_page[ $type ];
854
 
855
- $post_page = (array) get_post_types( array( 'public' => true ) );
856
 
857
  foreach ( $post_page as $screen ) {
858
  if ( $type === $screen ) {
@@ -868,13 +798,11 @@ class AutoDescription_Detect extends AutoDescription_Render {
868
  * Detect WordPress language.
869
  * Considers en_UK, en_US, en, etc.
870
  *
871
- * @param string $locale Required, the locale.
872
- * @param bool $use_cache Set to false to bypass the cache.
873
- *
874
- * @staticvar array $locale
875
- *
876
  * @since 2.6.0
 
877
  *
 
 
878
  * @return bool Whether the locale is in the WordPress locale.
879
  */
880
  public function check_wp_locale( $locale = '', $use_cache = true ) {
@@ -882,15 +810,15 @@ class AutoDescription_Detect extends AutoDescription_Render {
882
  if ( empty( $locale ) )
883
  return false;
884
 
885
- if ( true !== $use_cache )
886
- return false !== strpos( get_locale(), $locale );
887
 
888
  static $cache = array();
889
 
890
  if ( isset( $cache[ $locale ] ) )
891
  return $cache[ $locale ];
892
 
893
- return $cache[ $locale ] = false !== strpos( get_locale(), $locale );
894
  }
895
 
896
  /**
@@ -904,7 +832,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
904
  public function post_type_supports_inpost( $post_type = null ) {
905
 
906
  if ( isset( $post_type ) && $post_type ) {
907
- $supports = (array) apply_filters( 'the_seo_framework_custom_post_type_support',
908
  array(
909
  'title',
910
  'editor',
@@ -912,7 +840,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
912
  );
913
 
914
  foreach ( $supports as $support ) {
915
- if ( ! post_type_supports( $post_type, $support ) ) {
916
  return false;
917
  break;
918
  }
@@ -930,9 +858,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
930
  * Doesn't work on admin_init.
931
  *
932
  * @since 2.3.9
933
- * @staticvar string $post_type
934
  * @staticvar bool $supported
935
- * @staticvar array $post_page
936
  *
937
  * @param string $post_type The current post type.
938
  * @return bool true of post type is supported.
@@ -955,7 +881,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
955
  *
956
  * @since 2.3.5
957
  */
958
- if ( post_type_supports( $post_type, 'autodescription-meta' ) || $this->post_type_supports_inpost( $post_type ) )
959
  return $supported[ $post_type ] = true;
960
 
961
  return $supported[ $post_type ] = false;
@@ -964,12 +890,11 @@ class AutoDescription_Detect extends AutoDescription_Render {
964
  /**
965
  * Checks (current) Post Type for if this plugin may use it.
966
  *
967
- * @param bool $public Whether to only get Public Post types.
968
- * @param string $post_type Optional. The post type to check.
969
- *
970
  * @since 2.6.0
971
  * @staticvar string $cache
972
  *
 
 
973
  * @return bool|string The Allowed Post Type.
974
  */
975
  public function get_supported_post_type( $public = true, $post_type = '' ) {
@@ -991,7 +916,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
991
  if ( isset( $cache[ $public ][ $post_type ] ) )
992
  return $cache[ $public ][ $post_type ];
993
 
994
- $object = get_post_type_object( $post_type );
995
 
996
  //* Check if rewrite is enabled. Bypass builtin post types.
997
  if ( isset( $object->_builtin ) && false === $object->_builtin )
@@ -1010,7 +935,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
1010
  * @param string $post_type The supported post type. Is boolean false if not supported.
1011
  * @param string $post_type_evaluated The evaluated post type.
1012
  */
1013
- $post_type = (string) apply_filters( 'the_seo_framework_supported_post_type', $post_type, $post_type_evaluated );
1014
 
1015
  //* No supported post type has been found.
1016
  if ( empty( $post_type ) )
@@ -1034,7 +959,7 @@ class AutoDescription_Detect extends AutoDescription_Render {
1034
  if ( isset( $dir ) )
1035
  return $dir;
1036
 
1037
- $transient = get_transient( $this->theme_doing_it_right_transient );
1038
 
1039
  if ( '0' === $transient )
1040
  return $dir = false;
@@ -1090,26 +1015,22 @@ class AutoDescription_Detect extends AutoDescription_Render {
1090
  if ( isset( $pof ) )
1091
  return $pof;
1092
 
1093
- return $pof = 'page' === get_option( 'show_on_front' );
1094
  }
1095
 
1096
-
1097
  /**
1098
- * Determines whether we can use the new WordPress core term meta functionality.
 
1099
  *
1100
- * @since 2.7.0
1101
- * @staticvar bool $cache
1102
  *
1103
- * @return bool True when WordPress is at version 4.4 or higher and has an
1104
- * accordingly upgraded database.
1105
  */
1106
- public function can_get_term_meta() {
1107
 
1108
  static $cache = null;
1109
 
1110
- if ( isset( $cache ) )
1111
- return $cache;
1112
-
1113
- return $cache = get_option( 'db_version' ) >= 34370 && get_option( 'the_seo_framework_upgraded_db_version' ) >= '2700' && $this->wp_version( '4.4' );
1114
  }
1115
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
26
  defined( 'ABSPATH' ) or die;
27
 
28
  /**
29
+ * Class The_SEO_Framework\Detect
30
  *
31
  * Detects other plugins and themes
32
  *
33
+ * @since 2.8.0
34
  */
35
+ class Detect extends Render {
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  /**
38
  * Constructor, load parent constructor
39
  */
40
+ protected function __construct() {
41
  parent::__construct();
42
  }
43
 
57
  if ( isset( $active_plugins ) )
58
  return $active_plugins;
59
 
60
+ $active_plugins = (array) \get_option( 'active_plugins', array() );
61
 
62
+ if ( \is_multisite() ) {
63
  // Due to legacy code, active_sitewide_plugins stores them in the keys,
64
  // whereas active_plugins stores them in the values.
65
+ $network_plugins = array_keys( \get_site_option( 'active_sitewide_plugins', array() ) );
66
  if ( $network_plugins ) {
67
  $active_plugins = array_merge( $active_plugins, $network_plugins );
68
  }
76
  /**
77
  * Filterable list of conflicting plugins.
78
  *
 
79
  * @since 2.6.0
80
  * @credits JetPack for most code.
81
  *
97
  'Google XML Sitemaps for qTranslate' => 'google-xml-sitemaps-v3-for-qtranslate/sitemap.php',
98
  'XML Sitemap & Google News feeds' => 'xml-sitemap-feed/xml-sitemap.php',
99
  'Google Sitemap by BestWebSoft' => 'google-sitemap-plugin/google-sitemap-plugin.php',
 
 
 
 
100
  'Simple Wp Sitemap' => 'simple-wp-sitemap/simple-wp-sitemap.php',
101
  'Simple Sitemap' => 'simple-sitemap/simple-sitemap.php',
102
  'XML Sitemaps' => 'xml-sitemaps/xml-sitemaps.php',
103
  ),
104
  'open_graph' => array(
 
105
  'Add Link to Facebook' => 'add-link-to-facebook/add-link-to-facebook.php',
 
 
106
  'Facebook AWD All in one' => 'facebook-awd/AWD_facebook.php',
107
  'Facebook Featured Image & OG Meta Tags' => 'facebook-featured-image-and-open-graph-meta-tags/fb-featured-image.php',
108
  'Facebook Meta Tags' => 'facebook-meta-tags/facebook-metatags.php',
109
  'Facebook Open Graph Meta Tags for WordPress' => 'wonderm00ns-simple-facebook-open-graph-tags/wonderm00n-open-graph.php',
 
110
  'Facebook Thumb Fixer' => 'facebook-thumb-fixer/_facebook-thumb-fixer.php',
111
  'Fedmichs Facebook Open Graph Meta' => 'facebook-and-digg-thumbnail-generator/facebook-and-digg-thumbnail-generator.php',
112
  'Header and Footer' => 'header-footer/plugin.php',
 
113
  'NextGEN Facebook OG' => 'nextgen-facebook/nextgen-facebook.php',
114
  'NextScripts SNAP' => 'social-networks-auto-poster-facebook-twitter-g/NextScripts_SNAP.php',
115
  'Open Graph' => 'opengraph/opengraph.php',
116
  'Open Graph Protocol Framework' => 'open-graph-protocol-framework/open-graph-protocol-framework.php',
 
117
  'Shareaholic2' => 'shareaholic/sexy-bookmarks.php',
 
118
  'Social Sharing Toolkit' => 'social-sharing-toolkit/social_sharing_toolkit.php',
 
119
  'WordPress Social Sharing Optimization' => 'wpsso/wpsso.php',
120
  'WP Facebook Open Graph protocol' => 'wp-facebook-open-graph-protocol/wp-facebook-ogp.php',
121
  ),
122
  'twitter_card' => array(
123
  'Twitter' => 'twitter/twitter.php',
 
 
 
124
  ),
125
  );
126
 
127
+ /**
128
+ * Applies filters 'the_seo_framework_conflicting_plugins' : array
129
+ * @since 2.6.0
130
+ */
131
+ return (array) \apply_filters( 'the_seo_framework_conflicting_plugins', $conflicting_plugins );
132
  }
133
 
134
  /**
144
  $conflicting_plugins = $this->conflicting_plugins();
145
 
146
  if ( isset( $conflicting_plugins[ $type ] ) )
147
+ return (array) \apply_filters( 'the_seo_framework_conflicting_plugins_type', $conflicting_plugins[ $type ], $type );
148
 
149
  return array();
150
  }
152
  /**
153
  * Detect active plugin by constant, class or function existence.
154
  *
155
+ * Note: Class check is 3 times as slow as defined check. Function check is 2 times as slow.
156
+ *
157
  * @since 1.3.0
158
+ * @since 2.8.0 : 1. Can now check for globals.
159
+ * 2. Switched order from FAST to SLOW.
160
  *
161
  * @param array $plugins Array of array for constants, classes and / or functions to check for plugin existence.
162
  * @return boolean True if plugin exists or false if plugin constant, class or function not detected.
163
  */
164
  public function detect_plugin( $plugins ) {
165
 
166
+ if ( isset( $plugins['globals'] ) ) {
167
+ foreach ( $plugins['globals'] as $name ) {
168
+ if ( isset( $GLOBALS[ $name ] ) ) {
169
+ return true;
170
+ break;
171
+ }
172
+ }
173
+ }
174
+
175
+ //* Check for constants
176
+ if ( isset( $plugins['constants'] ) ) {
177
+ foreach ( $plugins['constants'] as $name ) {
178
+ if ( defined( $name ) ) {
179
  return true;
180
  break;
181
  }
192
  }
193
  }
194
 
195
+ //* Check for classes
196
+ if ( isset( $plugins['classes'] ) ) {
197
+ foreach ( $plugins['classes'] as $name ) {
198
+ if ( class_exists( $name ) ) {
199
  return true;
200
  break;
201
  }
309
  if ( empty( $themes ) )
310
  return false;
311
 
312
+ $wp_get_theme = \wp_get_theme();
313
 
314
  $theme_parent = strtolower( $wp_get_theme->get( 'Template' ) );
315
  $theme_name = strtolower( $wp_get_theme->get( 'Name' ) );
335
  * Determines if other SEO plugins are active.
336
  *
337
  * @since 1.3.0
338
+ * @since 2.6.0 Uses new style detection.
 
 
339
  *
340
  * @return bool SEO plugin detected.
341
  */
343
 
344
  static $detected = null;
345
 
 
 
 
 
 
346
  if ( isset( $detected ) )
347
  return $detected;
348
 
353
 
354
  foreach ( $conflicting_plugins as $plugin ) {
355
  if ( in_array( $plugin, $active_plugins, true ) ) {
356
+ /**
357
+ * Applies filters 'the_seo_framework_seo_plugin_detected' : boolean
358
+ * @since 2.6.1
359
+ */
360
+ $detected = \apply_filters( 'the_seo_framework_seo_plugin_detected', true );
361
  break;
362
  }
363
  }
370
  * Determines if other Open Graph or SEO plugins are active.
371
  *
372
  * @since 1.3.0
373
+ * @since 2.8.0: No longer checks for old style filter.
 
 
374
  *
375
  * @return bool True if OG or SEO plugin detected.
376
  */
382
  return $detected;
383
 
384
  //* Detect SEO plugins beforehand.
385
+ if ( $detected = $this->detect_seo_plugins() )
 
 
 
 
 
 
386
  return $detected;
387
 
388
  $active_plugins = $this->active_plugins();
392
 
393
  foreach ( $conflicting_plugins as $plugin ) {
394
  if ( in_array( $plugin, $active_plugins, true ) ) {
395
+ /**
396
+ * Applies filters 'the_seo_framework_og_plugin_detected' : boolean
397
+ * @since 2.6.1
398
+ */
399
+ $detected = \apply_filters( 'the_seo_framework_og_plugin_detected', true );
400
  break;
401
  }
402
  }
421
  return $detected;
422
 
423
  //* Detect SEO plugins beforehand.
424
+ if ( $detected = $this->detect_seo_plugins() )
 
425
  return $detected;
426
 
427
  $active_plugins = $this->active_plugins();
431
 
432
  foreach ( $conflicting_plugins as $plugin ) {
433
  if ( in_array( $plugin, $active_plugins, true ) ) {
434
+ /**
435
+ * Applies filters 'the_seo_framework_twittercard_plugin_detected' : boolean
436
+ * @since 2.6.1
437
+ */
438
+ $detected = \apply_filters( 'the_seo_framework_twittercard_plugin_detected', true );
439
  break;
440
  }
441
  }
457
  * Applies filters 'the_seo_framework_ldjson_plugin_detected' : boolean
458
  * @since 2.6.5
459
  */
460
+ return (bool) \apply_filters( 'the_seo_framework_ldjson_plugin_detected', false );
461
  }
462
 
463
  /**
475
  if ( isset( $detected ) )
476
  return $detected;
477
 
478
+ //* Detect SEO plugins beforehand.
479
+ if ( $detected = $this->detect_seo_plugins() )
480
+ return $detected;
481
+
482
  $active_plugins = $this->active_plugins();
483
 
484
  if ( ! empty( $active_plugins ) ) {
486
 
487
  foreach ( $conflicting_plugins as $plugin ) {
488
  if ( in_array( $plugin, $active_plugins, true ) ) {
489
+ $detected = \apply_filters( 'the_seo_framework_sitemap_plugin_detected', true );
490
  break;
491
  }
492
  }
499
  * Determines whether to add a line within robots based by plugin detection, or sitemap output option.
500
  *
501
  * @since 2.6.0
502
+ * @since 2.8.0 Added check_option parameter.
503
  *
504
+ * @param bool $check_option Whether to check for sitemap option.
505
  * @return bool True when no conflicting plugins are detected or when The SEO Framework's Sitemaps are output.
506
  */
507
+ public function can_do_sitemap_robots( $check_option = true ) {
508
 
509
  $plugins = array(
510
  'functions' => array(
511
+ 'jetpack_sitemap_initialize', // Jetpack
512
  ),
513
  );
514
 
515
  if ( $this->detect_plugin( $plugins ) )
516
  return false;
517
 
518
+ if ( $check_option ) {
519
+ if ( ! $this->is_option_checked( 'sitemaps_output' ) )
520
+ return false;
521
+ }
522
 
523
+ return true;
524
  }
525
 
526
  /**
538
  if ( isset( $has_robots ) )
539
  return $has_robots;
540
 
541
+ $path = \get_home_path() . 'robots.txt';
542
 
543
  return $has_robots = file_exists( $path );
544
  }
558
  if ( isset( $has_map ) )
559
  return $has_map;
560
 
561
+ $path = \get_home_path() . 'sitemap.xml';
562
 
563
  return $has_map = file_exists( $path );
564
  }
573
  *
574
  * @param string $version the three part version to compare to WordPress
575
  * @param string $compare the comparing operator, default "$version >= Current WP Version"
576
+ * @return bool True if the WordPress version comparison passes.
577
  */
578
  public function wp_version( $version = '4.3.0', $compare = '>=' ) {
579
 
587
 
588
  $wp_version = $GLOBALS['wp_version'];
589
 
590
+ /**
591
+ * Add a .0 if WP outputs something like 4.3 instead of 4.3.0
592
+ * Does not consider 4.10.x, but that's OK with the way WP handles updates.
593
+ */
594
  if ( 3 === strlen( $wp_version ) )
595
  $wp_version = $wp_version . '.0';
596
 
614
  if ( ! $use_cache ) {
615
  //* Don't use cache.
616
 
617
+ if ( is_string( $features ) && ( \current_theme_supports( $features ) ) )
618
  return true;
619
 
620
  if ( is_array( $features ) ) {
621
  foreach ( $features as $feature ) {
622
+ if ( \current_theme_supports( $feature ) ) {
623
  return true;
624
  break;
625
  }
651
 
652
  //* Setup cache values
653
  if ( is_string( $features ) ) {
654
+ if ( \current_theme_supports( $features ) ) {
655
  return $cache[ $features ] = true;
656
  } else {
657
  return $cache[ $features ] = false;
658
  }
659
  } elseif ( is_array( $features ) ) {
660
  foreach ( $features as $feature ) {
661
+ if ( \current_theme_supports( $feature ) ) {
662
  return $cache[ $feature ] = true;
663
  break;
664
  } else {
761
 
762
  //* Echo the HTML comment.
763
  if ( $output )
764
+ echo '<!-- Title diw: "' . \esc_html( $title_output ) . '" : "' . \esc_html( $sep_output ) . '" : "' . \esc_html( $seplocation_output ) . '" -->' . "\r\n";
765
 
766
  return;
767
  }
768
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
769
  /**
770
  * Detect if the current screen type is a page or taxonomy.
771
  *
 
772
  * @staticvar array $is_page
 
773
  * @since 2.3.1
774
  *
775
+ * @param string $type the Screen type
776
  * @return bool true if post type is a page or post
777
  */
778
  public function is_post_type_page( $type ) {
782
  if ( isset( $is_page[ $type ] ) )
783
  return $is_page[ $type ];
784
 
785
+ $post_page = (array) \get_post_types( array( 'public' => true ) );
786
 
787
  foreach ( $post_page as $screen ) {
788
  if ( $type === $screen ) {
798
  * Detect WordPress language.
799
  * Considers en_UK, en_US, en, etc.
800
  *
 
 
 
 
 
801
  * @since 2.6.0
802
+ * @staticvar array $locale
803
  *
804
+ * @param string $locale Required, the locale.
805
+ * @param bool $use_cache Set to false to bypass the cache.
806
  * @return bool Whether the locale is in the WordPress locale.
807
  */
808
  public function check_wp_locale( $locale = '', $use_cache = true ) {
810
  if ( empty( $locale ) )
811
  return false;
812
 
813
+ if ( ! $use_cache )
814
+ return is_int( strpos( \get_locale(), $locale ) );
815
 
816
  static $cache = array();
817
 
818
  if ( isset( $cache[ $locale ] ) )
819
  return $cache[ $locale ];
820
 
821
+ return $cache[ $locale ] = is_int( strpos( \get_locale(), $locale ) );
822
  }
823
 
824
  /**
832
  public function post_type_supports_inpost( $post_type = null ) {
833
 
834
  if ( isset( $post_type ) && $post_type ) {
835
+ $supports = (array) \apply_filters( 'the_seo_framework_custom_post_type_support',
836
  array(
837
  'title',
838
  'editor',
840
  );
841
 
842
  foreach ( $supports as $support ) {
843
+ if ( ! \post_type_supports( $post_type, $support ) ) {
844
  return false;
845
  break;
846
  }
858
  * Doesn't work on admin_init.
859
  *
860
  * @since 2.3.9
 
861
  * @staticvar bool $supported
 
862
  *
863
  * @param string $post_type The current post type.
864
  * @return bool true of post type is supported.
881
  *
882
  * @since 2.3.5
883
  */
884
+ if ( \post_type_supports( $post_type, 'autodescription-meta' ) || $this->post_type_supports_inpost( $post_type ) )
885
  return $supported[ $post_type ] = true;
886
 
887
  return $supported[ $post_type ] = false;
890
  /**
891
  * Checks (current) Post Type for if this plugin may use it.
892
  *
 
 
 
893
  * @since 2.6.0
894
  * @staticvar string $cache
895
  *
896
+ * @param bool $public Whether to only get Public Post types.
897
+ * @param string $post_type Optional. The post type to check.
898
  * @return bool|string The Allowed Post Type.
899
  */
900
  public function get_supported_post_type( $public = true, $post_type = '' ) {
916
  if ( isset( $cache[ $public ][ $post_type ] ) )
917
  return $cache[ $public ][ $post_type ];
918
 
919
+ $object = \get_post_type_object( $post_type );
920
 
921
  //* Check if rewrite is enabled. Bypass builtin post types.
922
  if ( isset( $object->_builtin ) && false === $object->_builtin )
935
  * @param string $post_type The supported post type. Is boolean false if not supported.
936
  * @param string $post_type_evaluated The evaluated post type.
937
  */
938
+ $post_type = (string) \apply_filters( 'the_seo_framework_supported_post_type', $post_type, $post_type_evaluated );
939
 
940
  //* No supported post type has been found.
941
  if ( empty( $post_type ) )
959
  if ( isset( $dir ) )
960
  return $dir;
961
 
962
+ $transient = \get_transient( $this->theme_doing_it_right_transient );
963
 
964
  if ( '0' === $transient )
965
  return $dir = false;
1015
  if ( isset( $pof ) )
1016
  return $pof;
1017
 
1018
+ return $pof = 'page' === \get_option( 'show_on_front' );
1019
  }
1020
 
 
1021
  /**
1022
+ * Determines if the current theme supports the custom logo addition.
1023
+ * Also checks WP version.
1024
  *
1025
+ * @since 2.8.0
1026
+ * @staticvar $bool $cache
1027
  *
1028
+ * @return bool
 
1029
  */
1030
+ public function can_use_logo() {
1031
 
1032
  static $cache = null;
1033
 
1034
+ return isset( $cache ) ? $cache : $this->wp_version( '4.5.0', '>=' ) && \current_theme_supports( 'custom-logo' );
 
 
 
1035
  }
1036
  }
inc/classes/{doingitright.class.php → doing-it-right.class.php} RENAMED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,45 +23,22 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_DoingItRight
23
  *
24
  * Adds data in a column to edit.php and edit-tags.php
25
  * Shows you if you're doing the SEO right.
26
  *
27
- * @since 2.1.9
28
  */
29
- class AutoDescription_DoingItRight extends AutoDescription_Search {
30
-
31
- /**
32
- * Unserializing instances of this class is forbidden.
33
- */
34
- private function __wakeup() { }
35
-
36
- /**
37
- * Handle unapproachable invoked methods.
38
- */
39
- public function __call( $name, $arguments ) {
40
- parent::__call( $name, $arguments );
41
- }
42
 
43
  /**
44
  * Constructor, load parent constructor.
45
  * Initalizes columns and load post states.
46
  */
47
- public function __construct() {
48
  parent::__construct();
49
-
50
- //* Initialize post states.
51
- add_action( 'current_screen', array( $this, 'post_state' ) );
52
-
53
- //* Ajax handlers for columns.
54
- add_action( 'wp_ajax_add-tag', array( $this, 'init_columns_ajax' ), -1 );
55
- //* Initialize columns.
56
- add_action( 'current_screen', array( $this, 'init_columns' ) );
57
-
58
  }
59
 
60
  /**
@@ -68,18 +52,15 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
68
 
69
  //* Only load on singular pages.
70
  if ( $this->is_singular() ) {
71
-
72
  /**
73
  * Applies filters `the_seo_framework_allow_states` : boolean Whether to allow post states output.
74
  * @since 2.1.0
75
  */
76
- $allow_states = (bool) apply_filters( 'the_seo_framework_allow_states', true );
77
 
78
  if ( $allow_states )
79
- add_filter( 'display_post_states', array( $this, 'add_post_state' ), 10, 2 );
80
-
81
  }
82
-
83
  }
84
 
85
  /**
@@ -98,7 +79,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
98
  $searchexclude = (bool) $this->get_custom_field( 'exclude_local_search', $post_id );
99
 
100
  if ( $searchexclude )
101
- $states[] = esc_html__( 'No Search', 'autodescription' );
102
  }
103
 
104
  return $states;
@@ -114,15 +95,14 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
114
  /**
115
  * Securely check the referrer, instead of leaving holes everywhere.
116
  */
117
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'add-tag', '_wpnonce_add-tag', false ) ) {
118
 
119
  $taxonomy = ! empty( $_POST['taxonomy'] ) ? $_POST['taxonomy'] : 'post_tag';
120
- $tax = get_taxonomy( $taxonomy );
121
 
122
- if ( current_user_can( $tax->cap->edit_terms ) )
123
  $this->init_columns( '', true );
124
  }
125
-
126
  }
127
 
128
  /**
@@ -137,55 +117,50 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
137
  */
138
  public function init_columns( $screen = '', $doing_ajax = false ) {
139
 
140
- $show_seo_column = (bool) apply_filters( 'the_seo_framework_show_seo_column', true );
141
 
142
- if ( $doing_ajax )
143
  $post_type = isset( $_POST['post_type'] ) ? $_POST['post_type'] : '';
144
- else
145
  $post_type = isset( $screen->post_type ) ? $screen->post_type : '';
 
146
 
147
  if ( $show_seo_column && $this->post_type_supports_custom_seo( $post_type ) ) {
148
-
149
  if ( $doing_ajax ) {
150
 
151
  $id = isset( $_POST['screen'] ) ? $_POST['screen'] : false;
152
  $taxonomy = isset( $_POST['taxonomy'] ) ? $_POST['taxonomy'] : false;
153
 
154
  if ( $taxonomy && $id ) {
155
- add_filter( 'manage_' . $id . '_columns', array( $this, 'add_column' ), 1 );
156
- add_action( 'manage_' . $taxonomy . '_custom_column', array( $this, 'seo_bar_ajax' ), 1, 3 );
157
  }
158
  } else {
159
-
160
  $id = isset( $screen->id ) ? $screen->id : '';
161
 
162
- if ( '' !== $id ) {
163
-
164
- if ( $this->is_wp_lists_edit() ) {
165
- add_filter( 'manage_' . $id . '_columns', array( $this, 'add_column' ), 10, 1 );
166
 
167
- $taxonomy = isset( $screen->taxonomy ) ? $screen->taxonomy : '';
168
 
169
- if ( $taxonomy )
170
- add_action( 'manage_' . $taxonomy . '_custom_column', array( $this, 'seo_bar' ), 1, 3 );
171
 
172
- /**
173
- * Always load pages and posts.
174
- * Many CPT plugins rely on these.
175
- */
176
- add_action( 'manage_posts_custom_column', array( $this, 'seo_bar' ), 1, 3 );
177
- add_action( 'manage_pages_custom_column', array( $this, 'seo_bar' ), 1, 3 );
178
- }
179
  }
180
  }
181
  }
182
-
183
  }
184
 
185
  /**
186
  * Adds SEO column on edit(-tags).php
187
  *
188
- * Also determines where the column should be placed. Prefered before comments, then data, then tags.
189
  * If neither found, it will add the column to the end.
190
  *
191
  * @since 2.1.9
@@ -205,14 +180,20 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
205
  'posts',
206
  'date',
207
  'tags',
208
- 'bbp_topic_freshness',
209
- 'bbp_forum_freshness',
210
- 'bbp_reply_created',
211
  );
212
 
 
 
 
 
 
 
 
 
 
213
  foreach ( $order_keys as $key ) {
214
  //* Put value in $offset, if not false, break loop.
215
- if ( false !== ( $offset = array_search( $key, $column_keys ) ) )
216
  break;
217
  }
218
 
@@ -251,10 +232,10 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
251
  static $type = null;
252
 
253
  if ( ! isset( $type ) ) {
254
- $type = get_post_type( $post_id );
255
 
256
  if ( false === $type || '' !== $tax_id ) {
257
- $screen = (object) get_current_screen();
258
 
259
  if ( isset( $screen->taxonomy ) )
260
  $type = $screen->taxonomy;
@@ -271,7 +252,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
271
  }
272
 
273
  if ( 'tsf-seo-bar-wrap' === $column )
274
- echo $this->post_status( $post_id, $type, true );
275
 
276
  }
277
 
@@ -280,9 +261,9 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
280
  *
281
  * @since 2.1.9
282
  *
283
- * @param string $column the current column : If it's a taxonomy, this is empty
284
- * @param int $post_id the post id : If it's a taxonomy, this is the column name
285
- * @param string $tax_id this is empty : If it's a taxonomy, this is the taxonomy id
286
  */
287
  public function seo_bar_ajax( $column, $post_id, $tax_id = '' ) {
288
 
@@ -299,13 +280,12 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
299
  }
300
 
301
  if ( 'tsf-seo-bar-wrap' === $column ) {
302
- $context = esc_html__( 'Refresh to see the SEO Bar status.', 'autodescription' );
303
 
304
  $ajax_id = $column . $post_id;
305
 
306
- echo $this->post_status_special( $context, '?', 'unknown', $is_term, $ajax_id );
307
  }
308
-
309
  }
310
 
311
  /**
@@ -317,9 +297,10 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
317
  * @param string $symbol The single-character symbol.
318
  * @param string $class The SEO block color code. : 'bad', 'okay', 'good', 'unknown'.
319
  * @param int|null $ajax_id The unique Ajax ID to generate a small on-hover script for this ID. May be Arbitrary.
320
- * @return string The special block with wrap.
 
321
  */
322
- protected function post_status_special( $context, $symbol = '?', $color = 'unknown', $is_term = '', $ajax_id = null ) {
323
 
324
  $classes = $this->get_the_seo_bar_classes();
325
 
@@ -334,7 +315,14 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
334
  if ( empty( $is_term ) )
335
  $is_term = $this->is_archive();
336
 
337
- return $this->get_the_seo_bar_wrap( $block, $is_term, $ajax_id );
 
 
 
 
 
 
 
338
  }
339
 
340
  /**
@@ -343,13 +331,14 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
343
  * @since 2.1.9
344
  * @staticvar string $post_i18n The post type slug.
345
  * @staticvar bool $is_term If we're dealing with TT pages.
 
346
  *
347
  * @param int $post_id The Post ID or taxonomy ID.
348
  * @param string $type Is fetched on edit.php, inpost, taxonomies, etc.
349
- * @param bool $html return the status in html or string.
350
- * @return string $content the post SEO status
351
  */
352
- public function post_status( $post_id = '', $type = 'inpost', $html = true ) {
353
 
354
  $content = '';
355
 
@@ -357,12 +346,10 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
357
  if ( empty( $post_id ) )
358
  $post_id = $this->get_the_real_ID();
359
 
360
- //* Only run when post ID is found.
361
- if ( isset( $post_id ) && $post_id ) {
362
-
363
  //* Fetch Post Type.
364
- if ( 'inpost' === $type || '' === $type )
365
- $type = get_post_type( $post_id );
366
 
367
  //* No need to re-evalute these.
368
  static $post_i18n = null;
@@ -377,11 +364,11 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
377
 
378
  //* Setup i18n values for posts and pages.
379
  if ( 'post' === $type ) {
380
- $post_i18n = __( 'Post', 'autodescription' );
381
  $is_term = false;
382
  $term = false;
383
  } elseif ( 'page' === $type ) {
384
- $post_i18n = __( 'Page', 'autodescription' );
385
  $is_term = false;
386
  $term = false;
387
  } else {
@@ -420,14 +407,21 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
420
  );
421
 
422
  if ( $is_term ) {
423
- return $this->the_seo_bar_term( $args );
424
  } else {
425
- return $this->the_seo_bar_page( $args );
426
  }
427
  } else {
428
- $context = esc_attr__( 'Failed to fetch post ID.', 'autodescription' );
429
 
430
- return $this->post_status_special( $context, '!', 'bad' );
 
 
 
 
 
 
 
431
  }
432
  }
433
 
@@ -480,14 +474,14 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
480
  $width = $is_term ? ' ' . $classes['100%'] : '';
481
  $pill = $this->pill_the_seo_bar() ? ' ' . $classes['pill'] : '';
482
 
483
- $class = esc_attr( 'tsf-seo-bar clearfix' . $width . $pill );
484
  }
485
 
486
  if ( isset( $ajax_id ) ) {
487
  //* Ajax handler.
488
- $script = '<script>jQuery("#' . esc_js( $ajax_id ) . '").on( "hover click", autodescription.statusBarHover );</script>';
489
 
490
- return sprintf( '<span class="%s" id="%s"><span class="tsf-seo-bar-inner-wrap">%s</span></span>', $class, esc_attr( $ajax_id ), $content ) . $script;
491
  }
492
 
493
  return sprintf( '<span class="%s"><span class="tsf-seo-bar-inner-wrap">%s</span></span>', $class, $content );
@@ -795,7 +789,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
795
  $but_and = $title_length_warning['but'] ? $but_i18n : $and_i18n;
796
 
797
  /* translators: %s = But or And */
798
- $notice .= '<br>' . sprintf( esc_attr__( '%s the Title contains the Blogname multiple times.', 'autodescription' ), $but_and );
799
  $class = $classes['bad'];
800
  }
801
 
@@ -827,13 +821,13 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
827
 
828
  //* Fetch data
829
  $data = $this->the_seo_bar_data( $args );
830
- $description = $data['description'];
831
- $description_is_from_custom_field = $data['description_is_from_custom_field'];
832
 
833
  //* Fetch i18n and put in vars
834
  $i18n = $this->get_the_seo_bar_i18n();
835
- $description_short = $i18n['description_short'];
836
- $generated_short = $i18n['generated_short'];
837
 
838
  //* Description length. Convert &#8230; to a single character as well.
839
  $desc_len = mb_strlen( html_entity_decode( $description ) );
@@ -966,7 +960,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
966
  $desc_value = ctype_upper( $desc_value ) ? $desc_value : ucfirst( $desc_value );
967
 
968
  /* translators: 1: Word, 2: Occurences */
969
- $notice .= sprintf( esc_attr__( '%1$s is used %2$d times.', 'autodescription' ), '<span>' . $desc_value . '</span>', $desc_count );
970
 
971
  //* Don't add break at last occurence.
972
  $notice .= $i === $count ? '' : '<br>';
@@ -1010,7 +1004,8 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1010
  $and_i18n = $i18n['and'];
1011
  $ind_notice = $i18n['index'];
1012
 
1013
- $ind_notice .= ' ' . sprintf( esc_attr__( '%s is being indexed.', 'autodescription' ), $post_i18n );
 
1014
  $ind_class = $good;
1015
 
1016
  /**
@@ -1019,7 +1014,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1019
  * @since 2.2.2
1020
  */
1021
  if ( $this->is_option_checked( 'site_noindex' ) ) {
1022
- $ind_notice .= '<br>' . esc_attr__( "But you've disabled indexing for the whole site.", 'autodescription' );
1023
  $ind_class = $unknown;
1024
  $ind_but = true;
1025
  }
@@ -1043,17 +1038,29 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1043
  $label = $this->get_the_term_name( $term, false );
1044
 
1045
  /* translators: 1: But or And, 2: Current taxonomy term plural label */
1046
- $ind_notice .= '<br>' . sprintf( esc_attr__( '%1$s indexing for %2$s have been disabled.', 'autodescription' ), $but_and, $label );
1047
  $ind_class = $unknown;
1048
  $ind_but = true;
1049
  }
1050
  }
1051
 
 
 
 
 
 
 
 
 
 
 
 
 
1052
  //* Adds notice for WordPress blog public indexing.
1053
  if ( false === $this->is_blog_public() ) {
1054
  $but_and = isset( $ind_but ) ? $and_i18n : $but_i18n;
1055
  /* translators: %s = But or And */
1056
- $ind_notice .= '<br>' . sprintf( esc_attr__( "%s the blog isn't set to public. This means WordPress discourages indexing.", 'autodescription' ), $but_and );
1057
  $ind_class = $bad;
1058
  $ind_but = true;
1059
  }
@@ -1067,7 +1074,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1067
  $but_and = isset( $ind_but ) ? $and_i18n : $but_i18n;
1068
 
1069
  /* translators: %s = But or And */
1070
- $ind_notice .= '<br>' . sprintf( esc_attr__( '%s there are no posts in this term; therefore, indexing has been disabled.', 'autodescription' ), $but_and );
1071
  //* Don't make it unknown if it's not good.
1072
  $ind_class = $ind_class !== $good ? $ind_class : $unknown;
1073
  }
@@ -1151,13 +1158,13 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1151
  $follow_short = $i18n['follow_short'];
1152
 
1153
  if ( $nofollow ) {
1154
- $fol_notice = $follow_i18n . ' ' . sprintf( esc_attr__( "%s links aren't being followed.", 'autodescription' ), $post_i18n );
1155
  $fol_class = $unknown;
1156
  $fol_but = true;
1157
 
1158
  $followed = false;
1159
  } else {
1160
- $fol_notice = $follow_i18n . ' ' . sprintf( esc_attr__( '%s links are being followed.', 'autodescription' ), $post_i18n );
1161
  $fol_class = $good;
1162
  }
1163
 
@@ -1169,7 +1176,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1169
  if ( $this->is_option_checked( 'site_nofollow' ) ) {
1170
  $but_and = isset( $fol_but ) ? $and_i18n : $but_i18n;
1171
  /* translators: %s = But or And */
1172
- $fol_notice .= '<br>' . sprintf( esc_attr__( "%s you've disabled the following of links for the whole site.", 'autodescription' ), $but_and );
1173
  $fol_class = $unknown;
1174
  $fol_but = true;
1175
 
@@ -1195,7 +1202,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1195
  $label = $this->get_the_term_name( $term, false );
1196
 
1197
  /* translators: 1: But or And, 2: Current taxonomy term plural label */
1198
- $fol_notice .= '<br>' . sprintf( esc_attr__( '%1$s following for %2$s have been disabled.', 'autodescription' ), $but_and, $label );
1199
  $fol_class = $unknown;
1200
 
1201
  $followed = false;
@@ -1203,11 +1210,11 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1203
  }
1204
 
1205
  if ( false === $this->is_blog_public() ) {
1206
- //* Make it "and" if following has not been disabled otherwise.
1207
  $but_and = $followed || ! isset( $fol_but ) ? $and_i18n : $but_i18n;
1208
 
1209
  /* translators: %s = But or And */
1210
- $fol_notice .= '<br>' . sprintf( esc_attr__( "%s the blog isn't set to public. This means WordPress allows the links to be followed regardless.", 'autodescription' ), $but_and );
1211
  $fol_class = $followed ? $fol_class : $okay;
1212
  $fol_but = true;
1213
 
@@ -1259,12 +1266,12 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1259
  $archive_short = $i18n['archive_short'];
1260
 
1261
  if ( $noarchive ) {
1262
- $arc_notice = $archive_i18n . ' ' . sprintf( esc_attr__( "Search Engine aren't allowed to archive this %s.", 'autodescription' ), $post_low );
1263
  $arc_class = $unknown;
1264
  $archived = false;
1265
  $arc_but = true;
1266
  } else {
1267
- $arc_notice = $archive_i18n . ' ' . sprintf( esc_attr__( 'Search Engine are allowed to archive this %s.', 'autodescription' ), $post_low );
1268
  $arc_class = $good;
1269
  }
1270
 
@@ -1276,7 +1283,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1276
  if ( $this->is_option_checked( 'site_noarchive' ) ) {
1277
  $but_and = isset( $arc_but ) ? $and_i18n : $but_i18n;
1278
 
1279
- $arc_notice .= '<br>' . sprintf( esc_attr__( "But you've disabled archiving for the whole site.", 'autodescription' ), $but_and );
1280
  $arc_class = $unknown;
1281
  $arc_but = true;
1282
 
@@ -1302,7 +1309,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1302
  $label = $this->get_the_term_name( $term, false );
1303
 
1304
  /* translators: 1: But or And, 2: Current taxonomy term plural label */
1305
- $arc_notice .= '<br>' . sprintf( esc_attr__( '%1$s archiving for %2$s have been disabled.', 'autodescription' ), $but_and, $label );
1306
  $arc_class = $unknown;
1307
  $arc_but = true;
1308
 
@@ -1311,11 +1318,11 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1311
  }
1312
 
1313
  if ( false === $this->is_blog_public() ) {
1314
- //* Make it "and" if archiving has not been disabled otherwise.
1315
  $but_and = $archived || ! isset( $arc_but ) ? $and_i18n : $but_i18n;
1316
 
1317
  /* translators: %s = But or And */
1318
- $arc_notice .= '<br>' . sprintf( esc_attr__( "%s the blog isn't set to public. This means WordPress allows the blog to be archived regardless.", 'autodescription' ), $but_and );
1319
  $arc_but = true;
1320
 
1321
  $arc_class = $archived ? $arc_class : $okay;
@@ -1361,7 +1368,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1361
  $redirect_i18n = $i18n['redirect'];
1362
  $redirect_short = $i18n['redirect_short'];
1363
 
1364
- $red_notice = $redirect_i18n . ' ' . sprintf( esc_attr__( "%s isn't being redirected.", 'autodescription' ), $post );
1365
  $red_class = $classes['good'];
1366
 
1367
  $red_wrap_args = array(
@@ -1403,10 +1410,10 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1403
  if ( $redirect && $noindex ) {
1404
  //* Redirect and noindex found, why bother showing SEO info?
1405
 
1406
- $red_notice = $i18n['redirect'] . ' ' . sprintf( esc_attr__( '%s is being redirected. This means no SEO values have to be set.', 'autodescription' ), $post );
1407
  $red_class = $classes['unknown'];
1408
 
1409
- $noi_notice = $i18n['index'] . ' ' . sprintf( esc_attr__( '%s is not being indexed. This means no SEO values have to be set.', 'autodescription' ), $post );
1410
  $noi_class = $classes['unknown'];
1411
 
1412
  $red_wrap_args = array(
@@ -1432,7 +1439,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1432
  } elseif ( $redirect && false === $noindex ) {
1433
  //* Redirect found, why bother showing SEO info?
1434
 
1435
- $red_notice = $i18n['redirect'] . ' ' . sprintf( esc_attr__( '%s is being redirected. This means no SEO values have to be set.', 'autodescription' ), $post );
1436
  $red_class = $classes['unknown'];
1437
 
1438
  $red_wrap_args = array(
@@ -1448,7 +1455,7 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1448
  } elseif ( $noindex && false === $redirect ) {
1449
  //* Noindex found, why bother showing SEO info?
1450
 
1451
- $noi_notice = $i18n['index'] . ' ' . sprintf( esc_attr__( '%s is not being indexed. This means no SEO values have to be set.', 'autodescription' ), $post );
1452
  $noi_class = $classes['unknown'];
1453
 
1454
  $noi_wrap_args = array(
@@ -1524,25 +1531,25 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1524
  */
1525
  public function get_the_seo_bar_classes() {
1526
  return array(
1527
- 'bad' => 'tsf-seo-bar-bad',
1528
- 'okay' => 'tsf-seo-bar-okay',
1529
- 'good' => 'tsf-seo-bar-good',
1530
- 'unknown' => 'tsf-seo-bar-unknown',
1531
 
1532
  'pill' => 'pill',
1533
 
1534
- '100%' => 'tsf-100',
1535
- '60%' => 'tsf-60',
1536
- '50%' => 'tsf-50',
1537
- '40%' => 'tsf-40',
1538
- '33%' => 'tsf-33',
1539
- '25%' => 'tsf-25',
1540
- '25%' => 'tsf-25',
1541
- '20%' => 'tsf-20',
1542
- '16%' => 'tsf-16',
1543
  '12.5%' => 'tsf-12-5',
1544
- '11%' => 'ad-11',
1545
- '10%' => 'tsf-10',
1546
  );
1547
  }
1548
 
@@ -1562,31 +1569,31 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1562
  return $i18n;
1563
 
1564
  return $i18n = array(
1565
- 'title' => esc_attr__( 'Title:', 'autodescription' ),
1566
- 'description' => esc_attr__( 'Description:', 'autodescription' ),
1567
- 'index' => esc_attr__( 'Index:', 'autodescription' ),
1568
- 'follow' => esc_attr__( 'Follow:', 'autodescription' ),
1569
- 'archive' => esc_attr__( 'Archive:', 'autodescription' ),
1570
- 'redirect' => esc_attr__( 'Redirect:', 'autodescription' ),
1571
-
1572
- 'generated' => esc_attr__( 'Generated: Automatically generated.', 'autodescription' ),
1573
-
1574
- 'generated_short' => esc_html_x( 'G', 'Generated', 'autodescription' ),
1575
- 'title_short' => esc_html_x( 'T', 'Title', 'autodescription' ),
1576
- 'description_short' => esc_html_x( 'D', 'Description', 'autodescription' ),
1577
- 'index_short' => esc_html_x( 'I', 'no-Index', 'autodescription' ),
1578
- 'follow_short' => esc_html_x( 'F', 'no-Follow', 'autodescription' ),
1579
- 'archive_short' => esc_html_x( 'A', 'no-Archive', 'autodescription' ),
1580
- 'redirect_short' => esc_html_x( 'R', 'Redirect', 'autodescription' ),
1581
-
1582
- 'but' => esc_attr_x( 'But', 'But there are...', 'autodescription' ),
1583
- 'and' => esc_attr_x( 'And', 'And there are...', 'autodescription' ),
1584
-
1585
- 'length_far_too_short' => ' ' . esc_attr__( 'Length is far too short.', 'autodescription' ),
1586
- 'length_too_short' => ' ' . esc_attr__( 'Length is too short.', 'autodescription' ),
1587
- 'length_too_long' => ' ' . esc_attr__( 'Length is too long.', 'autodescription' ),
1588
- 'length_far_too_long' => ' ' . esc_attr__( 'Length is far too long.', 'autodescription' ),
1589
- 'length_good' => ' ' . esc_attr__( 'Length is good.', 'autodescription' ),
1590
  );
1591
  }
1592
 
@@ -1607,6 +1614,6 @@ class AutoDescription_DoingItRight extends AutoDescription_Search {
1607
  if ( isset( $cache ) )
1608
  return $cache;
1609
 
1610
- return $cache = (bool) apply_filters( 'the_seo_framework_seo_bar_pill', false );
1611
  }
1612
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Doing_It_Right
28
  *
29
  * Adds data in a column to edit.php and edit-tags.php
30
  * Shows you if you're doing the SEO right.
31
  *
32
+ * @since 2.8.0
33
  */
34
+ class Doing_It_Right extends Generate_Ldjson {
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  /**
37
  * Constructor, load parent constructor.
38
  * Initalizes columns and load post states.
39
  */
40
+ protected function __construct() {
41
  parent::__construct();
 
 
 
 
 
 
 
 
 
42
  }
43
 
44
  /**
52
 
53
  //* Only load on singular pages.
54
  if ( $this->is_singular() ) {
 
55
  /**
56
  * Applies filters `the_seo_framework_allow_states` : boolean Whether to allow post states output.
57
  * @since 2.1.0
58
  */
59
+ $allow_states = (bool) \apply_filters( 'the_seo_framework_allow_states', true );
60
 
61
  if ( $allow_states )
62
+ \add_filter( 'display_post_states', array( $this, 'add_post_state' ), 10, 2 );
 
63
  }
 
64
  }
65
 
66
  /**
79
  $searchexclude = (bool) $this->get_custom_field( 'exclude_local_search', $post_id );
80
 
81
  if ( $searchexclude )
82
+ $states[] = \esc_html__( 'No Search', 'autodescription' );
83
  }
84
 
85
  return $states;
95
  /**
96
  * Securely check the referrer, instead of leaving holes everywhere.
97
  */
98
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX && \check_ajax_referer( 'add-tag', '_wpnonce_add-tag', false ) ) {
99
 
100
  $taxonomy = ! empty( $_POST['taxonomy'] ) ? $_POST['taxonomy'] : 'post_tag';
101
+ $tax = \get_taxonomy( $taxonomy );
102
 
103
+ if ( \current_user_can( $tax->cap->edit_terms ) )
104
  $this->init_columns( '', true );
105
  }
 
106
  }
107
 
108
  /**
117
  */
118
  public function init_columns( $screen = '', $doing_ajax = false ) {
119
 
120
+ $show_seo_column = (bool) \apply_filters( 'the_seo_framework_show_seo_column', true );
121
 
122
+ if ( $doing_ajax ) {
123
  $post_type = isset( $_POST['post_type'] ) ? $_POST['post_type'] : '';
124
+ } else {
125
  $post_type = isset( $screen->post_type ) ? $screen->post_type : '';
126
+ }
127
 
128
  if ( $show_seo_column && $this->post_type_supports_custom_seo( $post_type ) ) {
 
129
  if ( $doing_ajax ) {
130
 
131
  $id = isset( $_POST['screen'] ) ? $_POST['screen'] : false;
132
  $taxonomy = isset( $_POST['taxonomy'] ) ? $_POST['taxonomy'] : false;
133
 
134
  if ( $taxonomy && $id ) {
135
+ \add_filter( 'manage_' . $id . '_columns', array( $this, 'add_column' ), 1 );
136
+ \add_action( 'manage_' . $taxonomy . '_custom_column', array( $this, 'seo_bar_ajax' ), 1, 3 );
137
  }
138
  } else {
 
139
  $id = isset( $screen->id ) ? $screen->id : '';
140
 
141
+ if ( '' !== $id && $this->is_wp_lists_edit() ) {
142
+ \add_filter( 'manage_' . $id . '_columns', array( $this, 'add_column' ), 10, 1 );
 
 
143
 
144
+ $taxonomy = isset( $screen->taxonomy ) ? $screen->taxonomy : '';
145
 
146
+ if ( $taxonomy )
147
+ \add_action( 'manage_' . $taxonomy . '_custom_column', array( $this, 'seo_bar' ), 1, 3 );
148
 
149
+ /**
150
+ * Always load pages and posts.
151
+ * Many CPT plugins rely on these.
152
+ */
153
+ \add_action( 'manage_posts_custom_column', array( $this, 'seo_bar' ), 1, 3 );
154
+ \add_action( 'manage_pages_custom_column', array( $this, 'seo_bar' ), 1, 3 );
 
155
  }
156
  }
157
  }
 
158
  }
159
 
160
  /**
161
  * Adds SEO column on edit(-tags).php
162
  *
163
+ * Also determines where the column should be placed. Preferred before comments, then data, then tags.
164
  * If neither found, it will add the column to the end.
165
  *
166
  * @since 2.1.9
180
  'posts',
181
  'date',
182
  'tags',
 
 
 
183
  );
184
 
185
+ /**
186
+ * Applies filters 'the_seo_framework_seo_column_keys_order' : array
187
+ *
188
+ * @since 2.8.0
189
+ *
190
+ * @param array $order_keys
191
+ */
192
+ $order_keys = (array) \apply_filters( 'the_seo_framework_seo_column_keys_order', $order_keys );
193
+
194
  foreach ( $order_keys as $key ) {
195
  //* Put value in $offset, if not false, break loop.
196
+ if ( false !== ( $offset = array_search( $key, $column_keys, true ) ) )
197
  break;
198
  }
199
 
232
  static $type = null;
233
 
234
  if ( ! isset( $type ) ) {
235
+ $type = \get_post_type( $post_id );
236
 
237
  if ( false === $type || '' !== $tax_id ) {
238
+ $screen = (object) \get_current_screen();
239
 
240
  if ( isset( $screen->taxonomy ) )
241
  $type = $screen->taxonomy;
252
  }
253
 
254
  if ( 'tsf-seo-bar-wrap' === $column )
255
+ $this->post_status( $post_id, $type, true );
256
 
257
  }
258
 
261
  *
262
  * @since 2.1.9
263
  *
264
+ * @param string $column the current column : If it's a taxonomy, this is empty
265
+ * @param int $post_id the post id : If it's a taxonomy, this is the column name
266
+ * @param string $tax_id this is empty : If it's a taxonomy, this is the taxonomy id
267
  */
268
  public function seo_bar_ajax( $column, $post_id, $tax_id = '' ) {
269
 
280
  }
281
 
282
  if ( 'tsf-seo-bar-wrap' === $column ) {
283
+ $context = \esc_html__( 'Refresh to see the SEO Bar status.', 'autodescription' );
284
 
285
  $ajax_id = $column . $post_id;
286
 
287
+ $this->post_status_special( $context, '?', 'unknown', $is_term, $ajax_id, true );
288
  }
 
289
  }
290
 
291
  /**
297
  * @param string $symbol The single-character symbol.
298
  * @param string $class The SEO block color code. : 'bad', 'okay', 'good', 'unknown'.
299
  * @param int|null $ajax_id The unique Ajax ID to generate a small on-hover script for this ID. May be Arbitrary.
300
+ * @param bool $echo Whether to echo the output.
301
+ * @return string|void The special block with wrap. Void if $echo is true.
302
  */
303
+ protected function post_status_special( $context, $symbol = '?', $color = 'unknown', $is_term = '', $ajax_id = null, $echo = false ) {
304
 
305
  $classes = $this->get_the_seo_bar_classes();
306
 
315
  if ( empty( $is_term ) )
316
  $is_term = $this->is_archive();
317
 
318
+ $bar = $this->get_the_seo_bar_wrap( $block, $is_term, $ajax_id );
319
+
320
+ if ( $echo ) {
321
+ //* Already escaped.
322
+ echo $bar;
323
+ } else {
324
+ return $bar;
325
+ }
326
  }
327
 
328
  /**
331
  * @since 2.1.9
332
  * @staticvar string $post_i18n The post type slug.
333
  * @staticvar bool $is_term If we're dealing with TT pages.
334
+ * @since 2.8.0 Third parameter `$echo` has been put into effect.
335
  *
336
  * @param int $post_id The Post ID or taxonomy ID.
337
  * @param string $type Is fetched on edit.php, inpost, taxonomies, etc.
338
+ * @param bool $echo Whether to echo the value. Does not eliminate return.
339
+ * @return string|void $content The post SEO status. Void if $echo is true.
340
  */
341
+ public function post_status( $post_id = '', $type = 'inpost', $echo = false ) {
342
 
343
  $content = '';
344
 
346
  if ( empty( $post_id ) )
347
  $post_id = $this->get_the_real_ID();
348
 
349
+ if ( $post_id ) {
 
 
350
  //* Fetch Post Type.
351
+ if ( 'inpost' === $type || empty( $type ) )
352
+ $type = \get_post_type( $post_id );
353
 
354
  //* No need to re-evalute these.
355
  static $post_i18n = null;
364
 
365
  //* Setup i18n values for posts and pages.
366
  if ( 'post' === $type ) {
367
+ $post_i18n = \__( 'Post', 'autodescription' );
368
  $is_term = false;
369
  $term = false;
370
  } elseif ( 'page' === $type ) {
371
+ $post_i18n = \__( 'Page', 'autodescription' );
372
  $is_term = false;
373
  $term = false;
374
  } else {
407
  );
408
 
409
  if ( $is_term ) {
410
+ $bar = $this->the_seo_bar_term( $args );
411
  } else {
412
+ $bar = $this->the_seo_bar_page( $args );
413
  }
414
  } else {
415
+ $context = \esc_attr__( 'Failed to fetch post ID.', 'autodescription' );
416
 
417
+ $bar = $this->post_status_special( $context, '!', 'bad' );
418
+ }
419
+
420
+ //* Already escaped.
421
+ if ( $echo ) {
422
+ echo $bar;
423
+ } else {
424
+ return $bar;
425
  }
426
  }
427
 
474
  $width = $is_term ? ' ' . $classes['100%'] : '';
475
  $pill = $this->pill_the_seo_bar() ? ' ' . $classes['pill'] : '';
476
 
477
+ $class = \esc_attr( 'tsf-seo-bar clearfix' . $width . $pill );
478
  }
479
 
480
  if ( isset( $ajax_id ) ) {
481
  //* Ajax handler.
482
+ $script = '<script>jQuery("#' . \esc_js( $ajax_id ) . '").on( "hover click", tsf.statusBarHover );</script>';
483
 
484
+ return sprintf( '<span class="%s" id="%s"><span class="tsf-seo-bar-inner-wrap">%s</span></span>', $class, \esc_attr( $ajax_id ), $content ) . $script;
485
  }
486
 
487
  return sprintf( '<span class="%s"><span class="tsf-seo-bar-inner-wrap">%s</span></span>', $class, $content );
789
  $but_and = $title_length_warning['but'] ? $but_i18n : $and_i18n;
790
 
791
  /* translators: %s = But or And */
792
+ $notice .= '<br>' . sprintf( \esc_attr__( '%s the Title contains the Blogname multiple times.', 'autodescription' ), $but_and );
793
  $class = $classes['bad'];
794
  }
795
 
821
 
822
  //* Fetch data
823
  $data = $this->the_seo_bar_data( $args );
824
+ $description = $data['description'];
825
+ $description_is_from_custom_field = $data['description_is_from_custom_field'];
826
 
827
  //* Fetch i18n and put in vars
828
  $i18n = $this->get_the_seo_bar_i18n();
829
+ $description_short = $i18n['description_short'];
830
+ $generated_short = $i18n['generated_short'];
831
 
832
  //* Description length. Convert &#8230; to a single character as well.
833
  $desc_len = mb_strlen( html_entity_decode( $description ) );
960
  $desc_value = ctype_upper( $desc_value ) ? $desc_value : ucfirst( $desc_value );
961
 
962
  /* translators: 1: Word, 2: Occurences */
963
+ $notice .= sprintf( \esc_attr__( '%1$s is used %2$d times.', 'autodescription' ), '<span>' . $desc_value . '</span>', $desc_count );
964
 
965
  //* Don't add break at last occurence.
966
  $notice .= $i === $count ? '' : '<br>';
1004
  $and_i18n = $i18n['and'];
1005
  $ind_notice = $i18n['index'];
1006
 
1007
+ /* Translators: %s = Post / Page / Category, etc. */
1008
+ $ind_notice .= ' ' . sprintf( \esc_attr__( '%s is being indexed.', 'autodescription' ), $post_i18n );
1009
  $ind_class = $good;
1010
 
1011
  /**
1014
  * @since 2.2.2
1015
  */
1016
  if ( $this->is_option_checked( 'site_noindex' ) ) {
1017
+ $ind_notice .= '<br>' . \esc_attr__( "But you've discouraged indexing for the whole site.", 'autodescription' );
1018
  $ind_class = $unknown;
1019
  $ind_but = true;
1020
  }
1038
  $label = $this->get_the_term_name( $term, false );
1039
 
1040
  /* translators: 1: But or And, 2: Current taxonomy term plural label */
1041
+ $ind_notice .= '<br>' . sprintf( \esc_attr__( '%1$s indexing for %2$s have been discouraged.', 'autodescription' ), $but_and, $label );
1042
  $ind_class = $unknown;
1043
  $ind_but = true;
1044
  }
1045
  }
1046
 
1047
+ /**
1048
+ * Adds post protection notice
1049
+ * @since 2.8.0
1050
+ */
1051
+ if ( ! $is_term && $this->is_protected( $args['post_id'] ) ) {
1052
+ $but_and = isset( $ind_but ) ? $and_i18n : $but_i18n;
1053
+ /* translators: 1 = But or And, 1 = Post/Page */
1054
+ $ind_notice .= '<br>' . sprintf( \esc_attr__( '%1$s the %2$s is protected from public visibility. This means indexing is discouraged.', 'autodescription' ), $but_and, $post_i18n );
1055
+ $ind_class = $unknown;
1056
+ $ind_but = true;
1057
+ }
1058
+
1059
  //* Adds notice for WordPress blog public indexing.
1060
  if ( false === $this->is_blog_public() ) {
1061
  $but_and = isset( $ind_but ) ? $and_i18n : $but_i18n;
1062
  /* translators: %s = But or And */
1063
+ $ind_notice .= '<br>' . sprintf( \esc_attr__( "%s the blog isn't set to public. This means WordPress discourages indexing.", 'autodescription' ), $but_and );
1064
  $ind_class = $bad;
1065
  $ind_but = true;
1066
  }
1074
  $but_and = isset( $ind_but ) ? $and_i18n : $but_i18n;
1075
 
1076
  /* translators: %s = But or And */
1077
+ $ind_notice .= '<br>' . sprintf( \esc_attr__( '%s there are no posts in this term; therefore, indexing has been discouraged.', 'autodescription' ), $but_and );
1078
  //* Don't make it unknown if it's not good.
1079
  $ind_class = $ind_class !== $good ? $ind_class : $unknown;
1080
  }
1158
  $follow_short = $i18n['follow_short'];
1159
 
1160
  if ( $nofollow ) {
1161
+ $fol_notice = $follow_i18n . ' ' . sprintf( \esc_attr__( "%s links aren't being followed.", 'autodescription' ), $post_i18n );
1162
  $fol_class = $unknown;
1163
  $fol_but = true;
1164
 
1165
  $followed = false;
1166
  } else {
1167
+ $fol_notice = $follow_i18n . ' ' . sprintf( \esc_attr__( '%s links are being followed.', 'autodescription' ), $post_i18n );
1168
  $fol_class = $good;
1169
  }
1170
 
1176
  if ( $this->is_option_checked( 'site_nofollow' ) ) {
1177
  $but_and = isset( $fol_but ) ? $and_i18n : $but_i18n;
1178
  /* translators: %s = But or And */
1179
+ $fol_notice .= '<br>' . sprintf( \esc_attr__( "%s you've discouraged the following of links for the whole site.", 'autodescription' ), $but_and );
1180
  $fol_class = $unknown;
1181
  $fol_but = true;
1182
 
1202
  $label = $this->get_the_term_name( $term, false );
1203
 
1204
  /* translators: 1: But or And, 2: Current taxonomy term plural label */
1205
+ $fol_notice .= '<br>' . sprintf( \esc_attr__( '%1$s following for %2$s have been discouraged.', 'autodescription' ), $but_and, $label );
1206
  $fol_class = $unknown;
1207
 
1208
  $followed = false;
1210
  }
1211
 
1212
  if ( false === $this->is_blog_public() ) {
1213
+ //* Make it "and" if following has not been discouraged otherwise.
1214
  $but_and = $followed || ! isset( $fol_but ) ? $and_i18n : $but_i18n;
1215
 
1216
  /* translators: %s = But or And */
1217
+ $fol_notice .= '<br>' . sprintf( \esc_attr__( "%s the blog isn't set to public. This means WordPress allows the links to be followed regardless.", 'autodescription' ), $but_and );
1218
  $fol_class = $followed ? $fol_class : $okay;
1219
  $fol_but = true;
1220
 
1266
  $archive_short = $i18n['archive_short'];
1267
 
1268
  if ( $noarchive ) {
1269
+ $arc_notice = $archive_i18n . ' ' . sprintf( \esc_attr__( "Search Engines aren't allowed to archive this %s.", 'autodescription' ), $post_low );
1270
  $arc_class = $unknown;
1271
  $archived = false;
1272
  $arc_but = true;
1273
  } else {
1274
+ $arc_notice = $archive_i18n . ' ' . sprintf( \esc_attr__( 'Search Engines are allowed to archive this %s.', 'autodescription' ), $post_low );
1275
  $arc_class = $good;
1276
  }
1277
 
1283
  if ( $this->is_option_checked( 'site_noarchive' ) ) {
1284
  $but_and = isset( $arc_but ) ? $and_i18n : $but_i18n;
1285
 
1286
+ $arc_notice .= '<br>' . sprintf( \esc_attr__( "But you've discouraged archiving for the whole site.", 'autodescription' ), $but_and );
1287
  $arc_class = $unknown;
1288
  $arc_but = true;
1289
 
1309
  $label = $this->get_the_term_name( $term, false );
1310
 
1311
  /* translators: 1: But or And, 2: Current taxonomy term plural label */
1312
+ $arc_notice .= '<br>' . sprintf( \esc_attr__( '%1$s archiving for %2$s have been discouraged.', 'autodescription' ), $but_and, $label );
1313
  $arc_class = $unknown;
1314
  $arc_but = true;
1315
 
1318
  }
1319
 
1320
  if ( false === $this->is_blog_public() ) {
1321
+ //* Make it "and" if archiving has not been discouraged otherwise.
1322
  $but_and = $archived || ! isset( $arc_but ) ? $and_i18n : $but_i18n;
1323
 
1324
  /* translators: %s = But or And */
1325
+ $arc_notice .= '<br>' . sprintf( \esc_attr__( "%s the blog isn't set to public. This means WordPress allows the blog to be archived regardless.", 'autodescription' ), $but_and );
1326
  $arc_but = true;
1327
 
1328
  $arc_class = $archived ? $arc_class : $okay;
1368
  $redirect_i18n = $i18n['redirect'];
1369
  $redirect_short = $i18n['redirect_short'];
1370
 
1371
+ $red_notice = $redirect_i18n . ' ' . sprintf( \esc_attr__( "%s isn't being redirected.", 'autodescription' ), $post );
1372
  $red_class = $classes['good'];
1373
 
1374
  $red_wrap_args = array(
1410
  if ( $redirect && $noindex ) {
1411
  //* Redirect and noindex found, why bother showing SEO info?
1412
 
1413
+ $red_notice = $i18n['redirect'] . ' ' . sprintf( \esc_attr__( '%s is being redirected. This means no SEO values have to be set.', 'autodescription' ), $post );
1414
  $red_class = $classes['unknown'];
1415
 
1416
+ $noi_notice = $i18n['index'] . ' ' . sprintf( \esc_attr__( '%s is not being indexed. This means no SEO values have to be set.', 'autodescription' ), $post );
1417
  $noi_class = $classes['unknown'];
1418
 
1419
  $red_wrap_args = array(
1439
  } elseif ( $redirect && false === $noindex ) {
1440
  //* Redirect found, why bother showing SEO info?
1441
 
1442
+ $red_notice = $i18n['redirect'] . ' ' . sprintf( \esc_attr__( '%s is being redirected. This means no SEO values have to be set.', 'autodescription' ), $post );
1443
  $red_class = $classes['unknown'];
1444
 
1445
  $red_wrap_args = array(
1455
  } elseif ( $noindex && false === $redirect ) {
1456
  //* Noindex found, why bother showing SEO info?
1457
 
1458
+ $noi_notice = $i18n['index'] . ' ' . sprintf( \esc_attr__( '%s is not being indexed. This means no SEO values have to be set.', 'autodescription' ), $post );
1459
  $noi_class = $classes['unknown'];
1460
 
1461
  $noi_wrap_args = array(
1531
  */
1532
  public function get_the_seo_bar_classes() {
1533
  return array(
1534
+ 'bad' => 'tsf-seo-bar-bad',
1535
+ 'okay' => 'tsf-seo-bar-okay',
1536
+ 'good' => 'tsf-seo-bar-good',
1537
+ 'unknown' => 'tsf-seo-bar-unknown',
1538
 
1539
  'pill' => 'pill',
1540
 
1541
+ '100%' => 'tsf-100',
1542
+ '60%' => 'tsf-60',
1543
+ '50%' => 'tsf-50',
1544
+ '40%' => 'tsf-40',
1545
+ '33%' => 'tsf-33',
1546
+ '25%' => 'tsf-25',
1547
+ '25%' => 'tsf-25',
1548
+ '20%' => 'tsf-20',
1549
+ '16%' => 'tsf-16',
1550
  '12.5%' => 'tsf-12-5',
1551
+ '11%' => 'ad-11',
1552
+ '10%' => 'tsf-10',
1553
  );
1554
  }
1555
 
1569
  return $i18n;
1570
 
1571
  return $i18n = array(
1572
+ 'title' => \esc_attr__( 'Title:', 'autodescription' ),
1573
+ 'description' => \esc_attr__( 'Description:', 'autodescription' ),
1574
+ 'index' => \esc_attr__( 'Index:', 'autodescription' ),
1575
+ 'follow' => \esc_attr__( 'Follow:', 'autodescription' ),
1576
+ 'archive' => \esc_attr__( 'Archive:', 'autodescription' ),
1577
+ 'redirect' => \esc_attr__( 'Redirect:', 'autodescription' ),
1578
+
1579
+ 'generated' => \esc_attr__( 'Generated: Automatically generated.', 'autodescription' ),
1580
+
1581
+ 'generated_short' => \esc_html_x( 'G', 'Generated', 'autodescription' ),
1582
+ 'title_short' => \esc_html_x( 'T', 'Title', 'autodescription' ),
1583
+ 'description_short' => \esc_html_x( 'D', 'Description', 'autodescription' ),
1584
+ 'index_short' => \esc_html_x( 'I', 'no-Index', 'autodescription' ),
1585
+ 'follow_short' => \esc_html_x( 'F', 'no-Follow', 'autodescription' ),
1586
+ 'archive_short' => \esc_html_x( 'A', 'no-Archive', 'autodescription' ),
1587
+ 'redirect_short' => \esc_html_x( 'R', 'Redirect', 'autodescription' ),
1588
+
1589
+ 'but' => \esc_attr_x( 'But', 'But there are...', 'autodescription' ),
1590
+ 'and' => \esc_attr_x( 'And', 'And there are...', 'autodescription' ),
1591
+
1592
+ 'length_far_too_short' => ' ' . \esc_attr__( 'Length is far too short.', 'autodescription' ),
1593
+ 'length_too_short' => ' ' . \esc_attr__( 'Length is too short.', 'autodescription' ),
1594
+ 'length_too_long' => ' ' . \esc_attr__( 'Length is too long.', 'autodescription' ),
1595
+ 'length_far_too_long' => ' ' . \esc_attr__( 'Length is far too long.', 'autodescription' ),
1596
+ 'length_good' => ' ' . \esc_attr__( 'Length is good.', 'autodescription' ),
1597
  );
1598
  }
1599
 
1614
  if ( isset( $cache ) )
1615
  return $cache;
1616
 
1617
+ return $cache = (bool) \apply_filters( 'the_seo_framework_seo_bar_pill', false );
1618
  }
1619
  }
inc/classes/feed.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,37 +23,21 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Feed
23
  *
24
  * Influences WordPress feeds.
25
  * "Report Cybr for Feeding." - General EUW League of Legends player.
26
  *
27
- * @since 2.5.2
28
  */
29
- class AutoDescription_Feed extends AutoDescription_Transients {
30
-
31
- /**
32
- * Unserializing instances of this class is forbidden.
33
- */
34
- private function __wakeup() { }
35
-
36
- /**
37
- * Handle unapproachable invoked methods.
38
- */
39
- public function __call( $name, $arguments ) {
40
- parent::__call( $name, $arguments );
41
- }
42
 
43
  /**
44
  * Constructor, load parent constructor and run functions.
45
  */
46
- public function __construct() {
47
  parent::__construct();
48
-
49
- add_action( 'template_redirect', array( $this, 'init_feed' ) );
50
  }
51
 
52
  /**
@@ -56,14 +47,11 @@ class AutoDescription_Feed extends AutoDescription_Transients {
56
  */
57
  public function init_feed() {
58
 
59
- if ( false === $this->is_feed() )
60
- return;
61
-
62
- add_filter( 'the_content_feed', array( $this, 'the_content_feed' ), 10, 2 );
63
 
64
  //* Only add the feed link to the excerpt if we're only building excerpts.
65
  if ( $this->rss_uses_excerpt() )
66
- add_filter( 'the_excerpt_rss', array( $this, 'the_content_feed' ), 10, 1 );
67
 
68
  }
69
 
@@ -75,7 +63,7 @@ class AutoDescription_Feed extends AutoDescription_Transients {
75
  * @return bool
76
  */
77
  public function rss_uses_excerpt() {
78
- return (bool) get_option( 'rss_use_excerpt' );
79
  }
80
 
81
  /**
@@ -88,7 +76,7 @@ class AutoDescription_Feed extends AutoDescription_Transients {
88
  */
89
  public function the_content_feed( $content, $feed_type = null ) {
90
 
91
- if ( $content ) {
92
 
93
  /**
94
  * Don't alter already-excerpts or descriptions.
@@ -96,14 +84,14 @@ class AutoDescription_Feed extends AutoDescription_Transients {
96
  */
97
  if ( isset( $feed_type ) && $this->get_option( 'excerpt_the_feed' ) ) {
98
  //* Strip all code and lines.
99
- $excerpt = $this->get_excerpt_by_id( $content );
100
 
101
  $excerpt_len = (int) mb_strlen( $excerpt );
102
  /**
103
  * Applies filters the_seo_framework_max_content_feed_length : The max excerpt length.
104
  * @since 2.5.2
105
  */
106
- $max_len = (int) apply_filters( 'the_seo_framework_max_content_feed_length', 400 );
107
 
108
  //* Generate excerpt.
109
  $excerpt = $this->trim_excerpt( $excerpt, $excerpt_len, $max_len );
@@ -128,7 +116,7 @@ class AutoDescription_Feed extends AutoDescription_Transients {
128
  $excerpt = str_replace( $h2_content, '', $excerpt, $count );
129
 
130
  //* Wrap h2 content in h2 tags.
131
- $h2_output = '<h2>' . $h2_content . "</h2>\r\n";
132
  }
133
  }
134
 
@@ -137,17 +125,17 @@ class AutoDescription_Feed extends AutoDescription_Transients {
137
 
138
  if ( $this->get_option( 'source_the_feed' ) ) {
139
 
140
- //* Fetch permalink and add it to the content.
141
  $permalink = $this->the_url();
142
 
143
  /**
144
  * Applies filters 'the_seo_framework_feed_source_link' : string
145
  * @since 2.6.0
146
  */
147
- $source_i18n = (string) apply_filters( 'the_seo_framework_feed_source_link_text', _x( 'Source', 'The content source', 'autodescription' ) );
148
- $content .= "\r\n" . '<p><a href="' . $permalink . '" rel="external nofollow">' . $source_i18n . '</a></p>';
149
  }
150
- }
151
 
152
  return $content;
153
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Feed
28
  *
29
  * Influences WordPress feeds.
30
  * "Report Cybr for Feeding." - General EUW League of Legends player.
31
  *
32
+ * @since 2.8.0
33
  */
34
+ class Feed extends Cache {
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  /**
37
  * Constructor, load parent constructor and run functions.
38
  */
39
+ protected function __construct() {
40
  parent::__construct();
 
 
41
  }
42
 
43
  /**
47
  */
48
  public function init_feed() {
49
 
50
+ \add_filter( 'the_content_feed', array( $this, 'the_content_feed' ), 10, 2 );
 
 
 
51
 
52
  //* Only add the feed link to the excerpt if we're only building excerpts.
53
  if ( $this->rss_uses_excerpt() )
54
+ \add_filter( 'the_excerpt_rss', array( $this, 'the_content_feed' ), 10, 1 );
55
 
56
  }
57
 
63
  * @return bool
64
  */
65
  public function rss_uses_excerpt() {
66
+ return (bool) \get_option( 'rss_use_excerpt' );
67
  }
68
 
69
  /**
76
  */
77
  public function the_content_feed( $content, $feed_type = null ) {
78
 
79
+ if ( $content ) :
80
 
81
  /**
82
  * Don't alter already-excerpts or descriptions.
84
  */
85
  if ( isset( $feed_type ) && $this->get_option( 'excerpt_the_feed' ) ) {
86
  //* Strip all code and lines.
87
+ $excerpt = $this->s_excerpt_raw( $content, false );
88
 
89
  $excerpt_len = (int) mb_strlen( $excerpt );
90
  /**
91
  * Applies filters the_seo_framework_max_content_feed_length : The max excerpt length.
92
  * @since 2.5.2
93
  */
94
+ $max_len = (int) \apply_filters( 'the_seo_framework_max_content_feed_length', 400 );
95
 
96
  //* Generate excerpt.
97
  $excerpt = $this->trim_excerpt( $excerpt, $excerpt_len, $max_len );
116
  $excerpt = str_replace( $h2_content, '', $excerpt, $count );
117
 
118
  //* Wrap h2 content in h2 tags.
119
+ $h2_output = '<h2>' . $h2_content . '</h2>' . PHP_EOL;
120
  }
121
  }
122
 
125
 
126
  if ( $this->get_option( 'source_the_feed' ) ) {
127
 
128
+ //* Fetch permalink and add it to the content. Already escaped.
129
  $permalink = $this->the_url();
130
 
131
  /**
132
  * Applies filters 'the_seo_framework_feed_source_link' : string
133
  * @since 2.6.0
134
  */
135
+ $source_i18n = (string) apply_filters( 'the_seo_framework_feed_source_link_text', \_x( 'Source', 'The content source', 'autodescription' ) );
136
+ $content .= PHP_EOL . '<p><a href="' . $permalink . '" rel="external nofollow">' . \esc_html( $source_i18n ) . '</a></p>';
137
  }
138
+ endif;
139
 
140
  return $content;
141
  }
inc/classes/generate-description.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,42 +23,19 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Generate_Description
23
  *
24
  * Generates Description SEO data based on content.
25
  *
26
- * @since 2.6.0
27
  */
28
- class AutoDescription_Generate_Description extends AutoDescription_Generate {
29
-
30
- /**
31
- * Determines whether we're parsing the manual content Excerpt for the automated description.
32
- *
33
- * @since 2.6.0
34
- *
35
- * @var bool Using manual excerpt.
36
- */
37
- protected $using_manual_excerpt = false;
38
-
39
- /**
40
- * Unserializing instances of this class is forbidden.
41
- */
42
- private function __wakeup() { }
43
-
44
- /**
45
- * Handle unapproachable invoked methods.
46
- */
47
- public function __call( $name, $arguments ) {
48
- parent::__call( $name, $arguments );
49
- }
50
 
51
  /**
52
  * Constructor, loads parent constructor.
53
  */
54
- public function __construct() {
55
  parent::__construct();
56
  }
57
 
@@ -87,42 +71,17 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
87
  }
88
 
89
  //* Still no description found? Create an auto description based on content.
90
- if ( empty( $description ) || ! is_scalar( $description ) )
91
  $description = $this->generate_description_from_id( $args, false );
92
 
93
  /**
94
  * Applies filters 'the_seo_framework_do_shortcodes_in_description' : Boolean
95
  * @since 2.6.6
96
  */
97
- if ( apply_filters( 'the_seo_framework_do_shortcodes_in_description', false ) )
98
- $description = do_shortcode( $description );
99
 
100
- /**
101
- * Sanitize.
102
- * @since 2.3.4 Beautifies too.
103
- */
104
- $description = $this->escape_description( $description );
105
-
106
- return $description;
107
- }
108
-
109
- /**
110
- * Escapes and beautifies description.
111
- *
112
- * @since 2.5.2
113
- *
114
- * @param string $description The description to escape and beautify.
115
- * @return string Escaped and beautified description.
116
- */
117
- public function escape_description( $description = '' ) {
118
-
119
- $description = wptexturize( $description );
120
- $description = convert_chars( $description );
121
- $description = esc_html( $description );
122
- $description = capital_P_dangit( $description );
123
- $description = trim( $description );
124
-
125
- return $description;
126
  }
127
 
128
  /**
@@ -130,14 +89,6 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
130
  *
131
  * @since 2.5.0
132
  *
133
- * @applies filters the_seo_framework_description_args : {
134
- * @param int $id the term or page id.
135
- * @param string $taxonomy taxonomy name.
136
- * @param bool $is_home We're generating for the home page.
137
- * @param bool $get_custom_field Do not fetch custom title when false.
138
- * @param bool $social Generate Social Description when true.
139
- * }
140
- *
141
  * @param array $args required The passed arguments.
142
  * @param array $defaults The default arguments.
143
  * @param bool $get_defaults Return the default arguments. Ignoring $args.
@@ -148,14 +99,28 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
148
  //* Passing back the defaults reduces the memory usage.
149
  if ( empty( $defaults ) ) {
150
  $defaults = array(
151
- 'id' => $this->get_the_real_ID(),
152
- 'taxonomy' => '',
153
- 'is_home' => false,
154
- 'get_custom_field' => true,
155
- 'social' => false,
156
  );
157
 
158
- $defaults = (array) apply_filters( 'the_seo_framework_description_args', $defaults, $args );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  }
160
 
161
  //* Return early if it's only a default args request.
@@ -163,11 +128,11 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
163
  return $defaults;
164
 
165
  //* Array merge doesn't support sanitation. We're simply type casting here.
166
- $args['id'] = isset( $args['id'] ) ? (int) $args['id'] : $defaults['id'];
167
- $args['taxonomy'] = isset( $args['taxonomy'] ) ? (string) $args['taxonomy'] : $defaults['taxonomy'];
168
- $args['is_home'] = isset( $args['is_home'] ) ? (bool) $args['is_home'] : $defaults['is_home'];
169
- $args['get_custom_field'] = isset( $args['get_custom_field'] ) ? (bool) $args['get_custom_field'] : $defaults['get_custom_field'];
170
- $args['social'] = isset( $args['social'] ) ? (bool) $args['social'] : $defaults['social'];
171
 
172
  return $args;
173
  }
@@ -241,7 +206,6 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
241
  * Fetches HomePage Description from custom field.
242
  *
243
  * @since 2.6.0
244
- * @access protected
245
  * Use $this->description_from_custom_field() instead.
246
  *
247
  * @param array $args Description args.
@@ -252,8 +216,7 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
252
  $description = '';
253
 
254
  if ( $args['is_home'] || $this->is_front_page() || ( empty( $args['taxonomy'] ) && $this->is_static_frontpage( $args['id'] ) ) ) {
255
- $homedesc = $this->get_option( 'homepage_description' );
256
- $description = $homedesc ? $homedesc : '';
257
  }
258
 
259
  return $description;
@@ -263,7 +226,6 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
263
  * Fetches Singular Description from custom field.
264
  *
265
  * @since 2.6.0
266
- * @access protected
267
  * Use $this->description_from_custom_field() instead.
268
  *
269
  * @param int $id The page ID.
@@ -274,8 +236,7 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
274
  $description = '';
275
 
276
  if ( $this->is_singular( $id ) ) {
277
- $custom_desc = $this->get_custom_field( '_genesis_description', $id );
278
- $description = $custom_desc ? $custom_desc : $description;
279
  }
280
 
281
  return $description;
@@ -285,7 +246,6 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
285
  * Fetch Archive Description from custom field.
286
  *
287
  * @since 2.6.0
288
- * @access protected
289
  * Use $this->description_from_custom_field() instead.
290
  *
291
  * @param array $args
@@ -325,15 +285,15 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
325
  */
326
  public function generate_description_from_id( $args = array(), $escape = true ) {
327
 
328
- if ( $this->the_seo_framework_debug ) $this->debug_init( __METHOD__, true, $debug_key = microtime( true ), get_defined_vars() );
329
 
330
  /**
331
  * Applies filters bool 'the_seo_framework_enable_auto_description' : Enable or disable the description.
332
  *
333
  * @since 2.5.0
334
  */
335
- $autodescription = (bool) apply_filters( 'the_seo_framework_enable_auto_description', true );
336
- if ( false === $autodescription )
337
  return '';
338
 
339
  $description = $this->generate_the_description( $args, false );
@@ -341,7 +301,7 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
341
  if ( $escape )
342
  $description = $this->escape_description( $description );
343
 
344
- if ( $this->the_seo_framework_debug ) $this->debug_init( __METHOD__, false, $debug_key, array( 'description' => $description, 'transient_key' => $this->auto_description_transient ) );
345
 
346
  return (string) $description;
347
  }
@@ -350,7 +310,8 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
350
  * Generates description from content.
351
  *
352
  * @since 2.6.0
353
- * @staticvar string $title
 
354
  *
355
  * @param array $args description args : {
356
  * @param int $id the term or page id.
@@ -360,6 +321,7 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
360
  * @param bool $social Generate Social Description when true.
361
  * }
362
  * @param bool $escape Whether to escape the description.
 
363
  * @return string The description.
364
  */
365
  protected function generate_the_description( $args, $escape = true ) {
@@ -374,66 +336,54 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
374
  if ( $args['is_home'] || $this->is_front_page() || $this->is_static_frontpage( $args['id'] ) )
375
  return $this->generate_home_page_description( $args['get_custom_field'], $escape );
376
 
377
- $term = $this->fetch_the_term( $args['id'] );
378
-
379
- $title = '';
380
- $on = '';
381
- $blogname = '';
382
- $sep = '';
383
-
384
- //* Whether the post ID has a manual excerpt.
385
- if ( empty( $term ) && has_excerpt( $args['id'] ) ) {
386
- $this->using_manual_excerpt = true;
387
- } else {
388
- $title_on_blogname = $this->generate_description_additions( $args['id'], $term, false );
389
- $title = $title_on_blogname['title'];
390
- $on = $title_on_blogname['on'];
391
- $blogname = $title_on_blogname['blogname'];
392
- $sep = $title_on_blogname['sep'];
393
- }
394
 
395
  /**
396
  * Setup transient.
397
  */
398
- $this->setup_auto_description_transient( $args['id'], $args['taxonomy'] );
 
 
399
 
400
  /**
401
- * Cache the generated description within a transient.
402
- * @since 2.3.3
403
- * @since 2.3.4 Put inside a different function.
404
  */
405
- $excerpt = $this->get_transient( $this->auto_description_transient );
406
  if ( false === $excerpt ) {
 
407
 
408
  /**
409
- * Get max char length.
410
- * Default to 200 when $args['social'] as there are no additions.
 
411
  */
412
- $additions = trim( $title . " $on " . $blogname );
413
- //* If there are additions, add a trailing space.
414
- if ( $additions )
415
- $additions .= ' ';
416
-
417
- $max_char_length_normal = 155 - mb_strlen( html_entity_decode( $additions ) );
418
- $max_char_length_social = 200;
419
-
420
- //* Generate Excerpts.
421
- $excerpt_normal = $this->generate_excerpt( $args['id'], $term, $max_char_length_normal );
422
- $excerpt_social = $this->generate_excerpt( $args['id'], $term, $max_char_length_social );
423
-
424
- //* Put in array to be accessed later.
425
- $excerpt = array(
426
- 'normal' => $excerpt_normal,
427
- 'social' => $excerpt_social,
428
- );
429
 
430
- /**
431
- * Transient expiration: 1 week.
432
- * Keep the description for at most 1 week.
433
- */
434
- $expiration = WEEK_IN_SECONDS;
435
 
436
- $this->set_transient( $this->auto_description_transient, $excerpt, $expiration );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
  }
438
 
439
  /**
@@ -443,42 +393,120 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
443
  * @since 2.5.0
444
  */
445
  if ( $args['social'] ) {
446
- if ( $excerpt['social'] ) {
447
- $description = $excerpt['social'];
448
- } else {
449
- //* No social description if nothing is found.
450
- $description = '';
451
- }
452
  } else {
 
 
 
 
 
 
453
 
454
- if ( empty( $excerpt['normal'] ) ) {
455
- //* Fetch additions ignoring options.
456
- $title_on_blogname = $this->generate_description_additions( $args['id'], $term, true );
457
- $title = $title_on_blogname['title'];
458
- $on = $title_on_blogname['on'];
459
- $blogname = $title_on_blogname['blogname'];
460
- $sep = $title_on_blogname['sep'];
461
- }
462
-
463
- /* translators: 1: Title, 2: on, 3: Blogname */
464
- $title_on_blogname = trim( sprintf( _x( '%1$s %2$s %3$s', '1: Title, 2: on, 3: Blogname', 'autodescription' ), $title, $on, $blogname ) );
465
 
466
- if ( $excerpt['normal'] ) {
467
- /* translators: 1: Title, 2: Separator, 3: Excerpt */
468
- $description = sprintf( _x( '%1$s %2$s %3$s', '1: Title, 2: Separator, 3: Excerpt', 'autodescription' ), $title_on_blogname, $sep, $excerpt['normal'] );
469
  } else {
 
 
 
470
  //* We still add the additions when no excerpt has been found.
471
  // i.e. home page or empty/shortcode filled page.
472
- $description = $title_on_blogname;
473
  }
474
  }
475
 
476
- if ( $escape )
477
  $description = $this->escape_description( $description );
 
 
 
478
 
479
  return $description;
480
  }
481
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
482
  /**
483
  * Generates the home page description.
484
  *
@@ -545,7 +573,7 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
545
  * }
546
  * @since 2.6.0
547
  */
548
- $filter = apply_filters( 'the_seo_framework_add_description_additions', true, $id, $term );
549
  $option = $this->get_option( 'description_additions' );
550
 
551
  return $option && $filter;
@@ -567,7 +595,29 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
567
  if ( isset( $sep ) )
568
  return $sep;
569
 
570
- return $sep = (string) apply_filters( 'the_seo_framework_description_separator', $this->get_separator( 'description', false ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
571
  }
572
 
573
  /**
@@ -594,15 +644,16 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
594
 
595
  if ( $ignore || $this->add_description_additions( $id, $term ) ) {
596
 
597
- if ( ! isset( $title[ $id ] ) )
598
- $title[ $id ] = $this->generate_description_title( $id, $term, $ignore );
 
599
 
600
  if ( $ignore || $this->is_option_checked( 'description_blogname' ) ) {
601
 
602
  static $on = null;
603
  if ( is_null( $on ) ) {
604
  /* translators: Front-end output. */
605
- $on = _x( 'on', 'Placement. e.g. Post Title "on" Blog Name', 'autodescription' );
606
  }
607
 
608
  //* Already cached.
@@ -644,10 +695,9 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
644
  if ( '' === $id )
645
  $id = $this->get_the_real_ID();
646
 
647
- if ( $page_on_front || $this->is_static_frontpage( $id ) ) {
648
- $tagline = $this->get_option( 'homepage_title_tagline' );
649
- $title = $tagline ? $tagline : $this->get_blogdescription();
650
- } else {
651
  /**
652
  * No need to parse these when generating social description.
653
  *
@@ -665,7 +715,7 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
665
  * @priority medium 2.8.0+
666
  */
667
  /* translators: Front-end output. */
668
- $title = __( 'Latest posts:', 'autodescription' ) . ' ' . $title;
669
  } elseif ( $term && isset( $term->term_id ) ) {
670
  //* We're on a taxonomy now.
671
 
@@ -682,7 +732,7 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
682
  //* We're on a page now.
683
  $title = $this->title( '', '', '', array( 'term_id' => $id, 'notagline' => true, 'description_title' => true, 'escape' => false ) );
684
  }
685
- }
686
 
687
  /**
688
  * Use Untitled on empty titles.
@@ -699,14 +749,16 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
699
  * @NOTE Supply calculated $max_char_length to reflect actual output.
700
  *
701
  * @since 2.3.4
 
702
  * @staticvar array $excerpt_cache Holds the excerpt
703
  * @staticvar array $excerptlength_cache Holds the excerpt length
704
  *
705
  * @param int|string $page_id required : The Page ID
706
  * @param object|null $term The Taxonomy Term.
707
  * @param int $max_char_length The maximum excerpt char length.
 
708
  */
709
- public function generate_excerpt( $page_id, $term = '', $max_char_length = 154 ) {
710
 
711
  static $excerpt_cache = array();
712
  static $excerptlength_cache = array();
@@ -717,12 +769,12 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
717
  if ( ! isset( $excerpt_cache[ $page_id ][ $term_id ] ) ) {
718
  if ( $this->is_singular( $page_id ) ) {
719
  //* We're on the blog page now.
720
- $excerpt = $this->get_excerpt_by_id( '', $page_id );
721
  } elseif ( $term_id ) {
722
  //* We're on a taxonomy now. Fetch excerpt from latest term post.
723
- $excerpt = empty( $term->description ) ? $this->get_excerpt_by_id( '', '', $page_id ) : $this->s_description( $term->description );
724
  } elseif ( $this->is_author() ) {
725
- $excerpt = $this->s_description( get_the_author_meta( 'description', (int) get_query_var( 'author' ) ) );
726
  } else {
727
  $excerpt = '';
728
  }
@@ -762,61 +814,64 @@ class AutoDescription_Generate_Description extends AutoDescription_Generate {
762
  */
763
  public function trim_excerpt( $excerpt, $excerpt_length, $max_char_length ) {
764
 
765
- if ( $excerpt_length > $max_char_length ) {
 
766
 
767
- //* Cut string to fit $max_char_length.
768
- $sub_ex = mb_substr( $excerpt, 0, $max_char_length );
769
- $sub_ex = trim( html_entity_decode( $sub_ex ) );
770
 
771
- //* Split words in array separated by delimiter.
772
- $ex_words = explode( ' ', $sub_ex );
773
 
774
- //* Count to total words in the excerpt.
775
- $ex_total = count( $ex_words );
776
 
777
- //* Slice the complete excerpt and count the amount of words.
778
- $extra_ex_words = explode( ' ', trim( $excerpt ), $ex_total + 1 );
779
- $extra_ex_total = count( $extra_ex_words ) - 1;
780
- unset( $extra_ex_words[ $extra_ex_total ] );
781
 
782
- //* Calculate if last word exceeds.
783
- if ( $extra_ex_total >= $ex_total ) {
784
- $ex_cut = mb_strlen( $ex_words[ $ex_total - 1 ] );
785
 
786
- if ( $extra_ex_total > $ex_total ) {
787
- /**
788
- * There are more words in the trimmed excerpt than the compared total excerpt.
789
- * Remove the exceeding word.
790
- */
 
 
 
 
 
 
 
 
 
 
791
  $excerpt = mb_substr( $sub_ex, 0, - $ex_cut );
792
  } else {
793
- /**
794
- * The amount of words are the same in the comparison.
795
- * Calculate if the chacterers are exceeding.
796
- */
797
- $ex_extra_cut = mb_strlen( $extra_ex_words[ $extra_ex_total - 1 ] );
798
-
799
- if ( $ex_extra_cut > $ex_cut ) {
800
- //* Final word is falling off. Remove it.
801
- $excerpt = mb_substr( $sub_ex, 0, - $ex_cut );
802
- } else {
803
- //* We're all good here, continue.
804
- $excerpt = $sub_ex;
805
- }
806
  }
807
  }
 
808
 
809
- //* Remove trailing/leading comma's and spaces.
810
- $excerpt = trim( $excerpt, ' ,' );
811
 
812
- //* Fetch last character.
813
- $last_char = substr( $excerpt, -1 );
814
 
 
 
 
815
  $stops = array( '.', '?', '!' );
816
  //* Add three dots if there's no full stop at the end of the excerpt.
817
  if ( ! in_array( $last_char, $stops, true ) )
818
  $excerpt .= '...';
819
-
820
  }
821
 
822
  return trim( $excerpt );
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Generate_Description
28
  *
29
  * Generates Description SEO data based on content.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Generate_Description extends Generate {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  /**
36
  * Constructor, loads parent constructor.
37
  */
38
+ protected function __construct() {
39
  parent::__construct();
40
  }
41
 
71
  }
72
 
73
  //* Still no description found? Create an auto description based on content.
74
+ if ( empty( $description ) || false === is_scalar( $description ) )
75
  $description = $this->generate_description_from_id( $args, false );
76
 
77
  /**
78
  * Applies filters 'the_seo_framework_do_shortcodes_in_description' : Boolean
79
  * @since 2.6.6
80
  */
81
+ if ( \apply_filters( 'the_seo_framework_do_shortcodes_in_description', false ) )
82
+ $description = \do_shortcode( $description );
83
 
84
+ return $this->escape_description( $description );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  }
86
 
87
  /**
89
  *
90
  * @since 2.5.0
91
  *
 
 
 
 
 
 
 
 
92
  * @param array $args required The passed arguments.
93
  * @param array $defaults The default arguments.
94
  * @param bool $get_defaults Return the default arguments. Ignoring $args.
99
  //* Passing back the defaults reduces the memory usage.
100
  if ( empty( $defaults ) ) {
101
  $defaults = array(
102
+ 'id' => $this->get_the_real_ID(),
103
+ 'taxonomy' => '',
104
+ 'is_home' => false,
105
+ 'get_custom_field' => true,
106
+ 'social' => false,
107
  );
108
 
109
+ /**
110
+ * Applies filters 'the_seo_framework_description_args' : array {
111
+ * @param int $id the term or page id.
112
+ * @param string $taxonomy taxonomy name.
113
+ * @param bool $is_home We're generating for the home page.
114
+ * @param bool $get_custom_field Do not fetch custom title when false.
115
+ * @param bool $social Generate Social Description when true.
116
+ * }
117
+ *
118
+ * @since 2.5.0
119
+ *
120
+ * @param array $defaults The description defaults.
121
+ * @param array $args The input args.
122
+ */
123
+ $defaults = (array) \apply_filters( 'the_seo_framework_description_args', $defaults, $args );
124
  }
125
 
126
  //* Return early if it's only a default args request.
128
  return $defaults;
129
 
130
  //* Array merge doesn't support sanitation. We're simply type casting here.
131
+ $args['id'] = isset( $args['id'] ) ? (int) $args['id'] : $defaults['id'];
132
+ $args['taxonomy'] = isset( $args['taxonomy'] ) ? (string) $args['taxonomy'] : $defaults['taxonomy'];
133
+ $args['is_home'] = isset( $args['is_home'] ) ? (bool) $args['is_home'] : $defaults['is_home'];
134
+ $args['get_custom_field'] = isset( $args['get_custom_field'] ) ? (bool) $args['get_custom_field'] : $defaults['get_custom_field'];
135
+ $args['social'] = isset( $args['social'] ) ? (bool) $args['social'] : $defaults['social'];
136
 
137
  return $args;
138
  }
206
  * Fetches HomePage Description from custom field.
207
  *
208
  * @since 2.6.0
 
209
  * Use $this->description_from_custom_field() instead.
210
  *
211
  * @param array $args Description args.
216
  $description = '';
217
 
218
  if ( $args['is_home'] || $this->is_front_page() || ( empty( $args['taxonomy'] ) && $this->is_static_frontpage( $args['id'] ) ) ) {
219
+ $description = $this->get_option( 'homepage_description' ) ?: '';
 
220
  }
221
 
222
  return $description;
226
  * Fetches Singular Description from custom field.
227
  *
228
  * @since 2.6.0
 
229
  * Use $this->description_from_custom_field() instead.
230
  *
231
  * @param int $id The page ID.
236
  $description = '';
237
 
238
  if ( $this->is_singular( $id ) ) {
239
+ $description = $this->get_custom_field( '_genesis_description', $id ) ?: '';
 
240
  }
241
 
242
  return $description;
246
  * Fetch Archive Description from custom field.
247
  *
248
  * @since 2.6.0
 
249
  * Use $this->description_from_custom_field() instead.
250
  *
251
  * @param array $args
285
  */
286
  public function generate_description_from_id( $args = array(), $escape = true ) {
287
 
288
+ $this->the_seo_framework_debug and $this->debug_init( __METHOD__, true, $debug_key = microtime( true ), get_defined_vars() );
289
 
290
  /**
291
  * Applies filters bool 'the_seo_framework_enable_auto_description' : Enable or disable the description.
292
  *
293
  * @since 2.5.0
294
  */
295
+ $autodescription = (bool) \apply_filters( 'the_seo_framework_enable_auto_description', true );
296
+ if ( false === $autodescription || $this->is_protected( $args['id'] ) )
297
  return '';
298
 
299
  $description = $this->generate_the_description( $args, false );
301
  if ( $escape )
302
  $description = $this->escape_description( $description );
303
 
304
+ $this->the_seo_framework_debug and $this->debug_init( __METHOD__, false, $debug_key, array( 'description' => $description, 'transient_key' => $this->auto_description_transient ) );
305
 
306
  return (string) $description;
307
  }
310
  * Generates description from content.
311
  *
312
  * @since 2.6.0
313
+ * @since 2.8.0 : The output is always trimmed if $escape is false.
314
+ * : The cache will no longer be maintained on previews or search.
315
  *
316
  * @param array $args description args : {
317
  * @param int $id the term or page id.
321
  * @param bool $social Generate Social Description when true.
322
  * }
323
  * @param bool $escape Whether to escape the description.
324
+ * NOTE: When this is false, be sure to trim the output.
325
  * @return string The description.
326
  */
327
  protected function generate_the_description( $args, $escape = true ) {
336
  if ( $args['is_home'] || $this->is_front_page() || $this->is_static_frontpage( $args['id'] ) )
337
  return $this->generate_home_page_description( $args['get_custom_field'], $escape );
338
 
339
+ /**
340
+ * Determines whether to prevent caching of transients.
341
+ * @since 2.8.0
342
+ */
343
+ $nocache = ( ! $this->is_admin() && $this->is_search() ) || $this->is_preview();
344
+ $use_cache = ! $nocache && $this->is_option_checked( 'cache_meta_description' );
 
 
 
 
 
 
 
 
 
 
 
345
 
346
  /**
347
  * Setup transient.
348
  */
349
+ $use_cache and $this->setup_auto_description_transient( $args['id'], $args['taxonomy'] );
350
+
351
+ $term = $this->fetch_the_term( $args['id'] );
352
 
353
  /**
354
+ * @since 2.8.0: Added check for option 'cache_meta_description'.
 
 
355
  */
356
+ $excerpt = $use_cache ? $this->get_transient( $this->auto_description_transient ) : false;
357
  if ( false === $excerpt ) {
358
+ $excerpt = array();
359
 
360
  /**
361
+ * @since 2.8.0:
362
+ * 1. Added check for option 'cache_meta_description' and search/preview.
363
+ * 2. Moved generation functions in two different methods.
364
  */
365
+ if ( $use_cache ) {
366
+ $excerpt_normal = $this->get_description_excerpt_normal( $args['id'], $term );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
 
368
+ $excerpt['normal'] = $excerpt_normal['excerpt'];
369
+ $excerpt['trim'] = $excerpt_normal['trim'];
370
+ $excerpt['social'] = $this->get_description_excerpt_social( $args['id'], $term );
 
 
371
 
372
+ /**
373
+ * Transient expiration: 1 week.
374
+ * Keep the description for at most 1 week.
375
+ */
376
+ $expiration = WEEK_IN_SECONDS;
377
+
378
+ $this->set_transient( $this->auto_description_transient, $excerpt, $expiration );
379
+ } elseif ( $args['social'] ) {
380
+ $excerpt['social'] = $this->get_description_excerpt_social( $args['id'], $term );
381
+ } else {
382
+ $excerpt_normal = $this->get_description_excerpt_normal( $args['id'], $term );
383
+
384
+ $excerpt['normal'] = $excerpt_normal['excerpt'];
385
+ $excerpt['trim'] = $excerpt_normal['trim'];
386
+ }
387
  }
388
 
389
  /**
393
  * @since 2.5.0
394
  */
395
  if ( $args['social'] ) {
396
+ //* No social description if nothing is found.
397
+ $description = $excerpt['social'] ? $excerpt['social'] : '';
 
 
 
 
398
  } else {
399
+ if ( $excerpt['normal'] ) {
400
+ if ( $excerpt['trim'] ) {
401
+ $description = $excerpt['normal'];
402
+ } else {
403
+ if ( $term || ! \has_excerpt( $args['id'] ) ) {
404
+ $additions = $this->generate_description_additions( $args['id'], $term, false );
405
 
406
+ $title_on_blogname = $this->get_title_on_blogname( $additions );
407
+ $sep = $additions['sep'];
408
+ } else {
409
+ $title_on_blogname = $sep = '';
410
+ }
 
 
 
 
 
 
411
 
412
+ /* translators: 1: Title, 2: Separator, 3: Excerpt */
413
+ $description = sprintf( \_x( '%1$s %2$s %3$s', '1: Title, 2: Separator, 3: Excerpt', 'autodescription' ), $title_on_blogname, $sep, $excerpt['normal'] );
414
+ }
415
  } else {
416
+ //* Fetch additions ignoring options.
417
+ $additions = $this->generate_description_additions( $args['id'], $term, true );
418
+
419
  //* We still add the additions when no excerpt has been found.
420
  // i.e. home page or empty/shortcode filled page.
421
+ $description = $this->get_title_on_blogname( $additions );
422
  }
423
  }
424
 
425
+ if ( $escape ) {
426
  $description = $this->escape_description( $description );
427
+ } else {
428
+ $description = trim( $description );
429
+ }
430
 
431
  return $description;
432
  }
433
 
434
+ /**
435
+ * Returns the generated description excerpt array for the normal description tag.
436
+ *
437
+ * @since 2.8.0
438
+ *
439
+ * @param int $id The post/term ID.
440
+ * @param bool|object The term object.
441
+ * @return array {
442
+ * 'excerpt' => string The excerpt. Unescaped.
443
+ * 'trim' => bool Whether to trim the additions.
444
+ * }
445
+ */
446
+ public function get_description_excerpt_normal( $id = 0, $term = false ) {
447
+
448
+ $title = '';
449
+ $on = '';
450
+ $blogname = '';
451
+ $sep = '';
452
+
453
+ if ( $term || ! \has_excerpt( $id ) ) {
454
+ $title_on_blogname = $this->generate_description_additions( $id, $term, false );
455
+ $title = $title_on_blogname['title'];
456
+ $on = $title_on_blogname['on'];
457
+ $blogname = $title_on_blogname['blogname'];
458
+ $sep = $title_on_blogname['sep'];
459
+ }
460
+
461
+ $additions = trim( "$title $on $blogname" );
462
+ //* If there are additions, add a trailing space.
463
+ if ( $additions )
464
+ $additions .= ' ';
465
+
466
+ $additions_length = $additions ? mb_strlen( html_entity_decode( $additions ) ) : 0;
467
+ /**
468
+ * Determine if the title is far too long (72+, rather than 75 in the Title guidelines).
469
+ * If this is the case, trim the "title on blogname" part from the description.
470
+ * @since 2.8.0
471
+ */
472
+ if ( $additions_length > 71 ) {
473
+ $max_char_length = 155;
474
+ $trim = true;
475
+ } else {
476
+ $max_char_length = 155 - $additions_length;
477
+ $trim = false;
478
+ }
479
+
480
+ $excerpt_normal = $this->generate_excerpt( $id, $term, $max_char_length );
481
+
482
+ /**
483
+ * Put in array to be accessed later.
484
+ * @since 2.8.0 Added trim value.
485
+ */
486
+ return array(
487
+ 'excerpt' => $excerpt_normal,
488
+ 'trim' => $trim,
489
+ );
490
+ }
491
+
492
+ /**
493
+ * Returns the generated description excerpt for the social description tag.
494
+ *
495
+ * @since 2.8.0
496
+ *
497
+ * @param int $id The post/term ID.
498
+ * @param bool|object The term object.
499
+ * @return string The social description excerpt. Unescaped.
500
+ */
501
+ public function get_description_excerpt_social( $id = 0, $term = false ) {
502
+
503
+ $max_char_length = 200;
504
+
505
+ $excerpt_social = $this->generate_excerpt( $id, $term, $max_char_length );
506
+
507
+ return $excerpt_social;
508
+ }
509
+
510
  /**
511
  * Generates the home page description.
512
  *
573
  * }
574
  * @since 2.6.0
575
  */
576
+ $filter = \apply_filters( 'the_seo_framework_add_description_additions', true, $id, $term );
577
  $option = $this->get_option( 'description_additions' );
578
 
579
  return $option && $filter;
595
  if ( isset( $sep ) )
596
  return $sep;
597
 
598
+ return $sep = (string) \apply_filters( 'the_seo_framework_description_separator', $this->get_separator( 'description', false ) );
599
+ }
600
+
601
+ /**
602
+ * Returns translation string for "Title on Blogname".
603
+ *
604
+ * @since 2.8.0
605
+ * @see $this->generate_description_additions()
606
+ *
607
+ * @param array $additions The description additions.
608
+ * @return string The description additions.
609
+ */
610
+ protected function get_title_on_blogname( $additions ) {
611
+
612
+ if ( empty( $additions ) )
613
+ return '';
614
+
615
+ $title = $additions['title'];
616
+ $on = $additions['on'];
617
+ $blogname = $additions['blogname'];
618
+
619
+ /* translators: 1: Title, 2: on, 3: Blogname */
620
+ return trim( sprintf( \_x( '%1$s %2$s %3$s', '1: Title, 2: on, 3: Blogname', 'autodescription' ), $title, $on, $blogname ) );
621
  }
622
 
623
  /**
644
 
645
  if ( $ignore || $this->add_description_additions( $id, $term ) ) {
646
 
647
+ if ( ! isset( $title[ $id ] ) ) {
648
+ $title[ $id ] = $this->generate_description_title( $id, $term, $this->is_front_page( $id ) );
649
+ }
650
 
651
  if ( $ignore || $this->is_option_checked( 'description_blogname' ) ) {
652
 
653
  static $on = null;
654
  if ( is_null( $on ) ) {
655
  /* translators: Front-end output. */
656
+ $on = \_x( 'on', 'Placement. e.g. Post Title "on" Blog Name', 'autodescription' );
657
  }
658
 
659
  //* Already cached.
695
  if ( '' === $id )
696
  $id = $this->get_the_real_ID();
697
 
698
+ if ( $page_on_front || $this->is_static_frontpage( $id ) ) :
699
+ $title = $this->get_option( 'homepage_title_tagline' ) ?: $this->get_blogdescription();
700
+ else :
 
701
  /**
702
  * No need to parse these when generating social description.
703
  *
715
  * @priority medium 2.8.0+
716
  */
717
  /* translators: Front-end output. */
718
+ $title = \__( 'Latest posts:', 'autodescription' ) . ' ' . $title;
719
  } elseif ( $term && isset( $term->term_id ) ) {
720
  //* We're on a taxonomy now.
721
 
732
  //* We're on a page now.
733
  $title = $this->title( '', '', '', array( 'term_id' => $id, 'notagline' => true, 'description_title' => true, 'escape' => false ) );
734
  }
735
+ endif;
736
 
737
  /**
738
  * Use Untitled on empty titles.
749
  * @NOTE Supply calculated $max_char_length to reflect actual output.
750
  *
751
  * @since 2.3.4
752
+ * @since 2.8.2 Now no longer escapes excerpt by accident in processing, preventing "too short" output.
753
  * @staticvar array $excerpt_cache Holds the excerpt
754
  * @staticvar array $excerptlength_cache Holds the excerpt length
755
  *
756
  * @param int|string $page_id required : The Page ID
757
  * @param object|null $term The Taxonomy Term.
758
  * @param int $max_char_length The maximum excerpt char length.
759
+ * @return string $excerpt The excerpt, not escaped.
760
  */
761
+ public function generate_excerpt( $page_id, $term = '', $max_char_length = 155 ) {
762
 
763
  static $excerpt_cache = array();
764
  static $excerptlength_cache = array();
769
  if ( ! isset( $excerpt_cache[ $page_id ][ $term_id ] ) ) {
770
  if ( $this->is_singular( $page_id ) ) {
771
  //* We're on the blog page now.
772
+ $excerpt = $this->get_excerpt_by_id( '', $page_id, '', false );
773
  } elseif ( $term_id ) {
774
  //* We're on a taxonomy now. Fetch excerpt from latest term post.
775
+ $excerpt = empty( $term->description ) ? $this->get_excerpt_by_id( '', '', $page_id, false ) : $this->s_description_raw( $term->description );
776
  } elseif ( $this->is_author() ) {
777
+ $excerpt = $this->s_description_raw( \get_the_author_meta( 'description', (int) \get_query_var( 'author' ) ) );
778
  } else {
779
  $excerpt = '';
780
  }
814
  */
815
  public function trim_excerpt( $excerpt, $excerpt_length, $max_char_length ) {
816
 
817
+ if ( $excerpt_length <= $max_char_length )
818
+ return trim( $excerpt );
819
 
820
+ //* Cut string to fit $max_char_length.
821
+ $sub_ex = mb_substr( $excerpt, 0, $max_char_length );
822
+ $sub_ex = trim( html_entity_decode( $sub_ex ) );
823
 
824
+ //* Split words in array separated by delimiter.
825
+ $ex_words = explode( ' ', $sub_ex );
826
 
827
+ //* Count to total words in the excerpt.
828
+ $ex_total = count( $ex_words );
829
 
830
+ //* Slice the complete excerpt and count the amount of words.
831
+ $extra_ex_words = explode( ' ', trim( $excerpt ), $ex_total + 1 );
832
+ $extra_ex_total = count( $extra_ex_words ) - 1;
833
+ unset( $extra_ex_words[ $extra_ex_total ] );
834
 
835
+ //* Calculate if last word exceeds.
836
+ if ( $extra_ex_total >= $ex_total ) {
837
+ $ex_cut = mb_strlen( $ex_words[ $ex_total - 1 ] );
838
 
839
+ if ( $extra_ex_total > $ex_total ) {
840
+ /**
841
+ * There are more words in the trimmed excerpt than the compared total excerpt.
842
+ * Remove the exceeding word.
843
+ */
844
+ $excerpt = mb_substr( $sub_ex, 0, - $ex_cut );
845
+ } else {
846
+ /**
847
+ * The amount of words are the same in the comparison.
848
+ * Calculate if the chacterers are exceeding.
849
+ */
850
+ $ex_extra_cut = mb_strlen( $extra_ex_words[ $extra_ex_total - 1 ] );
851
+
852
+ if ( $ex_extra_cut > $ex_cut ) {
853
+ //* Final word is falling off. Remove it.
854
  $excerpt = mb_substr( $sub_ex, 0, - $ex_cut );
855
  } else {
856
+ //* We're all good here, continue.
857
+ $excerpt = $sub_ex;
 
 
 
 
 
 
 
 
 
 
 
858
  }
859
  }
860
+ }
861
 
862
+ //* Remove trailing/leading commas and spaces.
863
+ $excerpt = trim( $excerpt, ' ,' );
864
 
865
+ //* Fetch last character.
866
+ $last_char = substr( $excerpt, -1 );
867
 
868
+ if ( ';' === $last_char ) {
869
+ $excerpt = rtrim( $excerpt, ' ,.?!;' ) . '.';
870
+ } else {
871
  $stops = array( '.', '?', '!' );
872
  //* Add three dots if there's no full stop at the end of the excerpt.
873
  if ( ! in_array( $last_char, $stops, true ) )
874
  $excerpt .= '...';
 
875
  }
876
 
877
  return trim( $excerpt );
inc/classes/generate-image.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,16 +23,14 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Generate_Image
23
  *
24
  * Generates Image SEO data based on content.
25
  *
26
- * @since 2.6.0
27
  */
28
- class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
29
 
30
  /**
31
  * Holds the image dimensions, if found.
@@ -36,30 +41,23 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
36
  */
37
  public $image_dimensions = array();
38
 
39
- /**
40
- * Unserializing instances of this class is forbidden.
41
- */
42
- private function __wakeup() { }
43
-
44
- /**
45
- * Handle unapproachable invoked methods.
46
- */
47
- public function __call( $name, $arguments ) {
48
- parent::__call( $name, $arguments );
49
- }
50
-
51
  /**
52
  * Constructor, loads parent constructor.
53
  */
54
- public function __construct() {
55
  parent::__construct();
56
  }
57
 
58
  /**
59
  * Fetches og:image URL.
60
  *
61
- * @since 2.5.2 Applies filters string the_seo_framework_og_image_after_featured
62
- * @since 2.5.2 Applies filters string the_seo_framework_og_image_after_header
 
 
 
 
 
63
  *
64
  * @todo listen to attached images within post.
65
  * @todo set archive and front page image listener, now it simply fail on some calls.
@@ -72,49 +70,86 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
72
  */
73
  public function get_image( $post_id = '', $args = array(), $escape = true ) {
74
 
75
- if ( empty( $post_id ) )
76
- $post_id = $this->get_the_real_ID();
77
-
78
- if ( empty( $post_id ) )
79
- return '';
80
-
81
  /**
82
  * Backwards compat with parse args.
83
  * @since 2.5.0
84
  */
85
  if ( ! isset( $args['post_id'] ) )
86
- $args['post_id'] = $post_id;
87
 
88
  $args = $this->reparse_image_args( $args );
89
 
90
  //* 0. Image from argument.
91
- $image = $args['image'];
 
 
 
92
 
93
  //* Check if there are no disallowed arguments.
94
  $all_allowed = empty( $args['disallowed'] );
95
 
96
- //* 1. Fetch image from featured
97
- if ( empty( $image ) && ( $all_allowed || ! in_array( 'featured', $args['disallowed'], true ) ) )
98
- $image = $this->get_image_from_post_thumbnail( $args );
 
 
 
99
 
100
- //* 2. Fetch image from fallback filter 1
101
- if ( empty( $image ) )
102
- $image = (string) apply_filters( 'the_seo_framework_og_image_after_featured', '', $args['post_id'] );
 
 
 
103
 
104
- //* 3. Fallback: Get header image if exists
105
- if ( empty( $image ) && ( $all_allowed || ! in_array( 'header', $args['disallowed'], true ) ) && current_theme_supports( 'custom-header', 'default-image' ) )
106
- $image = $this->get_header_image( true );
 
 
107
 
108
- //* 4. Fetch image from fallback filter 2
109
- if ( empty( $image ) )
110
- $image = (string) apply_filters( 'the_seo_framework_og_image_after_header', '', $args['post_id'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
- //* 5. Get the WP 4.3.0 Site Icon
113
- if ( empty( $image ) && ( $all_allowed || ! in_array( 'icon', $args['disallowed'], true ) ) )
114
- $image = $this->site_icon( 'full', true );
115
 
116
  if ( $escape && $image )
117
- return esc_url( $image );
118
 
119
  return $image;
120
  }
@@ -124,19 +159,6 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
124
  *
125
  * @since 2.5.0
126
  *
127
- * @since 2.0.1 Applies filters the_seo_framework_og_image_args : {
128
- * @param string $image The image url
129
- * @param mixed $size The image size
130
- * @param bool $icon Fetch Image icon
131
- * @param array $attr Image attributes
132
- * @param array $disallowed Disallowed image types : {
133
- * array (
134
- * string 'featured'
135
- * string 'header'
136
- * string 'icon'
137
- * )
138
- * }
139
- * }
140
  * The image set in the filter will always be used as fallback
141
  *
142
  * @param array $args required The passed arguments.
@@ -149,15 +171,35 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
149
  //* Passing back the defaults reduces the memory usage.
150
  if ( empty( $defaults ) ) {
151
  $defaults = array(
152
- 'post_id' => $this->get_the_real_ID(),
153
- 'image' => '',
154
- 'size' => 'full',
155
- 'icon' => false,
156
- 'attr' => array(),
157
  'disallowed' => array(),
158
  );
159
 
160
- $defaults = (array) apply_filters( 'the_seo_framework_og_image_args', $defaults, $args );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
 
163
  //* Return early if it's only a default args request.
@@ -165,12 +207,12 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
165
  return $defaults;
166
 
167
  //* Array merge doesn't support sanitation. We're simply type casting here.
168
- $args['post_id'] = isset( $args['post_id'] ) ? (int) $args['post_id'] : $defaults['post_id'];
169
- $args['image'] = isset( $args['image'] ) ? (string) $args['image'] : $defaults['image'];
170
- $args['size'] = isset( $args['size'] ) ? $args['size'] : $defaults['size']; // Mixed.
171
- $args['icon'] = isset( $args['icon'] ) ? (bool) $args['icon'] : $defaults['icon'];
172
- $args['attr'] = isset( $args['attr'] ) ? (array) $args['attr'] : $defaults['attr'];
173
- $args['disallowed'] = isset( $args['disallowed'] ) ? (array) $args['disallowed'] : $defaults['disallowed'];
174
 
175
  return $args;
176
  }
@@ -202,6 +244,72 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
202
  return $args;
203
  }
204
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  /**
206
  * Fetches image from post thumbnail.
207
  * Resizes the image between 1500px if bigger. Then it saves the image and
@@ -220,7 +328,7 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
220
  if ( ! isset( $args['post_id'] ) )
221
  $args['post_id'] = $this->get_the_real_ID();
222
 
223
- $id = get_post_thumbnail_id( $args['post_id'] );
224
 
225
  $args['get_the_real_ID'] = true;
226
 
@@ -233,7 +341,7 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
233
  * Fetches images id's from WooCommerce gallery
234
  *
235
  * @since 2.5.0
236
- * @staticvar array $ids The image ids
237
  *
238
  * @param array $args Image arguments.
239
  * @return array The image URL's.
@@ -249,10 +357,10 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
249
 
250
  $post_id = $this->get_the_real_ID();
251
 
252
- if ( metadata_exists( 'post', $post_id, '_product_image_gallery' ) ) {
253
- $product_image_gallery = get_post_meta( $post_id, '_product_image_gallery', true );
254
 
255
- $attachment_ids = array_filter( explode( ',', $product_image_gallery ) );
256
  }
257
 
258
  return $ids = $attachment_ids;
@@ -262,7 +370,8 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
262
  * Parses OG image to correct size.
263
  *
264
  * @since 2.5.0
265
- * @staticvar string $called Checks if image ID has already been fetched (to prevent duplicate output on WooCommerce).
 
266
  *
267
  * @todo create formula to fetch transient.
268
  * @priority high 2.7.0
@@ -277,23 +386,17 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
277
  if ( ! isset( $id ) || empty( $id ) )
278
  return;
279
 
280
- static $called = array();
281
-
282
- //* Don't parse image twice. Return empty on second run.
283
- if ( isset( $called[ $id ] ) )
284
- return '';
285
-
286
  if ( empty( $args ) )
287
  $args = $this->reparse_image_args( $args );
288
 
289
- $src = wp_get_attachment_image_src( $id, $args['size'], $args['icon'], $args['attr'] );
290
 
291
  $i = $src[0]; // Source URL
292
  $w = $src[1]; // Width
293
  $h = $src[2]; // Height
294
 
295
- //* Prefered 1500px, resize it
296
- if ( $w > 1500 || $h > 1500 ) {
297
 
298
  if ( $w === $h ) {
299
  //* Square
@@ -308,10 +411,8 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
308
  }
309
 
310
  //* Get path of image and load it into the wp_get_image_editor
311
- $i_file_path = get_attached_file( $id );
312
-
313
- $i_file_old_name = basename( get_attached_file( $id ) );
314
- $i_file_ext = pathinfo( $i_file_path, PATHINFO_EXTENSION );
315
 
316
  if ( $i_file_ext ) {
317
  $i_file_dir_name = pathinfo( $i_file_path, PATHINFO_DIRNAME );
@@ -325,8 +426,8 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
325
  $new_image_dirfile = $i_file_dir_name . $i_file_file_name . '-' . $w . 'x' . $h . '.' . $i_file_ext;
326
 
327
  //* Generate image URL.
328
- $upload_dir = wp_upload_dir();
329
- $upload_url = $upload_dir['baseurl'];
330
  $upload_basedir = $upload_dir['basedir'];
331
 
332
  //* We've got our image path.
@@ -336,9 +437,9 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
336
  // Generate file if it doesn't exists yet.
337
  if ( ! file_exists( $new_image_dirfile ) ) {
338
 
339
- $image_editor = wp_get_image_editor( $i_file_path );
340
 
341
- if ( ! is_wp_error( $image_editor ) ) {
342
  $image_editor->resize( $w, $h, false );
343
  $image_editor->set_quality( 82 ); // Let's save some bandwidth, Facebook compresses it even further anyway.
344
  $image_editor->save( $new_image_dirfile );
@@ -348,35 +449,35 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
348
  }
349
  }
350
  }
351
- }
352
 
353
  //* Whether to use the post ID (Post Thumbnail) or input ID (ID was known beforehand)
354
  $usage_id = isset( $args['get_the_real_ID'] ) && $args['get_the_real_ID'] ? $this->get_the_real_ID() : $id;
355
 
356
  $this->image_dimensions = $this->image_dimensions + array( $usage_id => array( 'width' => $w, 'height' => $h ) );
357
 
358
- return $called[ $id ] = $i;
359
  }
360
 
361
  /**
362
- * Fetches site icon brought in WordPress 4.3.0
363
  *
364
- * @since 2.2.1
365
  *
366
- * @param string $size The icon size, accepts 'full' and pixel values.
367
  * @param bool $set_og_dimensions Whether to set size for OG image. Always falls back to the current post ID.
368
  * @return string URL site icon, not escaped.
369
  */
370
- public function site_icon( $size = 'full', $set_og_dimensions = false ) {
371
 
372
  $icon = '';
373
 
374
  if ( 'full' === $size ) {
375
- $site_icon_id = get_option( 'site_icon' );
376
 
377
  if ( $site_icon_id ) {
378
  $url_data = '';
379
- $url_data = wp_get_attachment_image_src( $site_icon_id, $size );
380
 
381
  $icon = $url_data ? $url_data[0] : '';
382
 
@@ -387,14 +488,52 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
387
  $this->image_dimensions = $this->image_dimensions + array( $this->get_the_real_ID() => array( 'width' => $w, 'height' => $h ) );
388
  }
389
  }
390
- } elseif ( is_int( $size ) && function_exists( 'has_site_icon' ) && $this->wp_version( '4.3', '>=' ) ) {
 
 
 
 
391
  //* Also applies (MultiSite) filters.
392
- $icon = get_site_icon_url( $size );
393
  }
394
 
395
  return $icon;
396
  }
397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
398
  /**
399
  * Returns header image URL.
400
  * Also sets image dimensions. Falls back to current post ID for index.
@@ -406,12 +545,12 @@ class AutoDescription_Generate_Image extends AutoDescription_Generate_Url {
406
  */
407
  public function get_header_image( $set_og_dimensions = false ) {
408
 
409
- $image = get_header_image();
410
 
411
  if ( $set_og_dimensions && $image ) {
412
 
413
- $w = (int) get_theme_support( 'custom-header', 'width' );
414
- $h = (int) get_theme_support( 'custom-header', 'height' );
415
 
416
  if ( $w && $h )
417
  $this->image_dimensions = $this->image_dimensions + array( $this->get_the_real_ID() => array( 'width' => $w, 'height' => $h ) );
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Generate_Image
28
  *
29
  * Generates Image SEO data based on content.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Generate_Image extends Generate_Url {
34
 
35
  /**
36
  * Holds the image dimensions, if found.
41
  */
42
  public $image_dimensions = array();
43
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  /**
45
  * Constructor, loads parent constructor.
46
  */
47
+ protected function __construct() {
48
  parent::__construct();
49
  }
50
 
51
  /**
52
  * Fetches og:image URL.
53
  *
54
+ * @since 2.2.2
55
+ * @since 2.2.8 : Added theme icon detection.
56
+ * @since 2.5.2 : Added args filters.
57
+ * @since 2.8.0 : 1. Added theme logo detection.
58
+ * 2. Added inpost image selection detection.
59
+ * @since 2.8.2 : 1. Now returns something on post ID 0.
60
+ * 2. Added SEO settings fallback image selection detection.
61
  *
62
  * @todo listen to attached images within post.
63
  * @todo set archive and front page image listener, now it simply fail on some calls.
70
  */
71
  public function get_image( $post_id = '', $args = array(), $escape = true ) {
72
 
 
 
 
 
 
 
73
  /**
74
  * Backwards compat with parse args.
75
  * @since 2.5.0
76
  */
77
  if ( ! isset( $args['post_id'] ) )
78
+ $args['post_id'] = $post_id ?: ( $this->is_singular() ? $this->get_the_real_ID() : 0 );
79
 
80
  $args = $this->reparse_image_args( $args );
81
 
82
  //* 0. Image from argument.
83
+ pre_0 : {
84
+ if ( $image = $args['image'] )
85
+ goto end;
86
+ }
87
 
88
  //* Check if there are no disallowed arguments.
89
  $all_allowed = empty( $args['disallowed'] );
90
 
91
+ if ( $args['post_id'] ) {
92
+ //* 1. Fetch image from SEO meta upload.
93
+ if ( $all_allowed || false === in_array( 'postmeta', $args['disallowed'], true ) ) {
94
+ if ( $image = $this->get_social_image_url_from_post_meta( $args['post_id'], true ) )
95
+ goto end;
96
+ }
97
 
98
+ //* 2. Fetch image from featured
99
+ if ( $all_allowed || false === in_array( 'featured', $args['disallowed'], true ) ) {
100
+ if ( $image = $this->get_image_from_post_thumbnail( $args ) )
101
+ goto end;
102
+ }
103
+ }
104
 
105
+ //* 3. Fetch image from SEO settings
106
+ if ( $all_allowed || false === in_array( 'option', $args['disallowed'], true ) ) {
107
+ if ( $image = $this->get_social_image_url_from_seo_settings( true ) )
108
+ goto end;
109
+ }
110
 
111
+ //* 4. Fetch image from fallback filter 1
112
+ /**
113
+ * Applies filters 'the_seo_framework_og_image_after_featured' : string
114
+ * @since 2.5.2
115
+ */
116
+ fallback_1 : {
117
+ if ( $image = (string) \apply_filters( 'the_seo_framework_og_image_after_featured', '', $args['post_id'] ) )
118
+ goto end;
119
+ }
120
+
121
+ //* 5. Fallback: Get header image if exists
122
+ if ( ( $all_allowed || false === in_array( 'header', $args['disallowed'], true ) ) && \current_theme_supports( 'custom-header', 'default-image' ) ) {
123
+ if ( $image = $this->get_header_image( true ) )
124
+ goto end;
125
+ }
126
+
127
+ //* 6. Fetch image from fallback filter 2
128
+ /**
129
+ * Applies filters 'the_seo_framework_og_image_after_header' : string
130
+ * @since 2.5.2
131
+ */
132
+ fallback_2 : {
133
+ if ( $image = (string) \apply_filters( 'the_seo_framework_og_image_after_header', '', $args['post_id'] ) )
134
+ goto end;
135
+ }
136
+
137
+ //* 7. Get the WP 4.5 Site Logo
138
+ if ( ( $all_allowed || false === in_array( 'logo', $args['disallowed'], true ) ) && $this->can_use_logo() ) {
139
+ if ( $image = $this->get_site_logo( true ) )
140
+ goto end;
141
+ }
142
+
143
+ //* 8. Get the WP 4.3 Site Icon
144
+ if ( $all_allowed || false === in_array( 'icon', $args['disallowed'], true ) ) {
145
+ if ( $image = $this->get_site_icon( 'full', true ) )
146
+ goto end;
147
+ }
148
 
149
+ end :;
 
 
150
 
151
  if ( $escape && $image )
152
+ return \esc_url( $image );
153
 
154
  return $image;
155
  }
159
  *
160
  * @since 2.5.0
161
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  * The image set in the filter will always be used as fallback
163
  *
164
  * @param array $args required The passed arguments.
171
  //* Passing back the defaults reduces the memory usage.
172
  if ( empty( $defaults ) ) {
173
  $defaults = array(
174
+ 'post_id' => $this->get_the_real_ID(),
175
+ 'image' => '',
176
+ 'size' => 'full',
177
+ 'icon' => false,
178
+ 'attr' => array(),
179
  'disallowed' => array(),
180
  );
181
 
182
+ /**
183
+ * Applies filters the_seo_framework_og_image_args : {
184
+ * @param string $image The image url
185
+ * @param mixed $size The image size
186
+ * @param bool $icon Fetch Image icon
187
+ * @param array $attr Image attributes
188
+ * @param array $disallowed Disallowed image types : {
189
+ * array (
190
+ * string 'featured'
191
+ * string 'header'
192
+ * string 'icon'
193
+ * )
194
+ * }
195
+ * }
196
+ *
197
+ * @since 2.0.1
198
+ *
199
+ * @param array $defaults The image defaults.
200
+ * @param array $args The input args.
201
+ */
202
+ $defaults = (array) \apply_filters( 'the_seo_framework_og_image_args', $defaults, $args );
203
  }
204
 
205
  //* Return early if it's only a default args request.
207
  return $defaults;
208
 
209
  //* Array merge doesn't support sanitation. We're simply type casting here.
210
+ $args['post_id'] = isset( $args['post_id'] ) ? (int) $args['post_id'] : $defaults['post_id'];
211
+ $args['image'] = isset( $args['image'] ) ? (string) $args['image'] : $defaults['image'];
212
+ $args['size'] = isset( $args['size'] ) ? $args['size'] : $defaults['size']; // Mixed.
213
+ $args['icon'] = isset( $args['icon'] ) ? (bool) $args['icon'] : $defaults['icon'];
214
+ $args['attr'] = isset( $args['attr'] ) ? (array) $args['attr'] : $defaults['attr'];
215
+ $args['disallowed'] = isset( $args['disallowed'] ) ? (array) $args['disallowed'] : $defaults['disallowed'];
216
 
217
  return $args;
218
  }
244
  return $args;
245
  }
246
 
247
+ /**
248
+ * Returns unescaped URL from post ID input.
249
+ *
250
+ * @since 2.8.0
251
+ * @uses $this->image_dimensions
252
+ *
253
+ * @param int $id The post ID.
254
+ * @param bool $set_og_dimensions Whether to set open graph and twitter dimensions.
255
+ * @return string The unescaped social image URL.
256
+ */
257
+ public function get_social_image_url_from_post_meta( $id = 0, $set_og_dimensions = false ) {
258
+
259
+ if ( empty( $id ) )
260
+ $id = $this->get_the_real_ID();
261
+
262
+ $src = $this->get_custom_field( '_social_image_url', $id );
263
+
264
+ if ( ! $src )
265
+ return '';
266
+
267
+ //* Calculate image sizes.
268
+ if ( $img_id = $this->get_custom_field( '_social_image_id', $id ) ) {
269
+ $_src = \wp_get_attachment_image_src( $img_id, 'full' );
270
+
271
+ $i = $_src[0]; // Source URL
272
+ $w = $_src[1]; // Width
273
+ $h = $_src[2]; // Height
274
+
275
+ if ( \esc_url( $this->set_preferred_url_scheme( $i ) ) === \esc_url( $this->set_preferred_url_scheme( $src ) ) )
276
+ $this->image_dimensions = $this->image_dimensions + array( $id => array( 'width' => $w, 'height' => $h ) );
277
+ }
278
+
279
+ return $src;
280
+ }
281
+
282
+ /**
283
+ * Returns unescaped URL from options input.
284
+ *
285
+ * @since 2.8.2
286
+ * @uses $this->image_dimensions
287
+ *
288
+ * @param bool $set_og_dimensions Whether to set open graph and twitter dimensions.
289
+ * @return string The unescaped social image fallback URL.
290
+ */
291
+ public function get_social_image_url_from_seo_settings( $set_og_dimensions = false ) {
292
+
293
+ $src = $this->get_option( 'social_image_fb_url' );
294
+
295
+ if ( ! $src )
296
+ return '';
297
+
298
+ //* Calculate image sizes.
299
+ if ( $img_id = $this->get_option( 'social_image_fb_id' ) ) {
300
+ $_src = \wp_get_attachment_image_src( $img_id, 'full' );
301
+
302
+ $i = $_src[0]; // Source URL
303
+ $w = $_src[1]; // Width
304
+ $h = $_src[2]; // Height
305
+
306
+ if ( \esc_url( $this->set_preferred_url_scheme( $i ) ) === \esc_url( $this->set_preferred_url_scheme( $src ) ) )
307
+ $this->image_dimensions = $this->image_dimensions + array( $this->get_the_real_ID() => array( 'width' => $w, 'height' => $h ) );
308
+ }
309
+
310
+ return $src;
311
+ }
312
+
313
  /**
314
  * Fetches image from post thumbnail.
315
  * Resizes the image between 1500px if bigger. Then it saves the image and
328
  if ( ! isset( $args['post_id'] ) )
329
  $args['post_id'] = $this->get_the_real_ID();
330
 
331
+ $id = \get_post_thumbnail_id( $args['post_id'] );
332
 
333
  $args['get_the_real_ID'] = true;
334
 
341
  * Fetches images id's from WooCommerce gallery
342
  *
343
  * @since 2.5.0
344
+ * @staticvar array $ids The image IDs
345
  *
346
  * @param array $args Image arguments.
347
  * @return array The image URL's.
357
 
358
  $post_id = $this->get_the_real_ID();
359
 
360
+ if ( \metadata_exists( 'post', $post_id, '_product_image_gallery' ) ) {
361
+ $product_image_gallery = \get_post_meta( $post_id, '_product_image_gallery', true );
362
 
363
+ $attachment_ids = array_map( 'absint', array_filter( explode( ',', $product_image_gallery ) ) );
364
  }
365
 
366
  return $ids = $attachment_ids;
370
  * Parses OG image to correct size.
371
  *
372
  * @since 2.5.0
373
+ * @since 2.8.0 : 1. Removed staticvar.
374
+ * 2. Now adds ID call to OG image called listener.
375
  *
376
  * @todo create formula to fetch transient.
377
  * @priority high 2.7.0
386
  if ( ! isset( $id ) || empty( $id ) )
387
  return;
388
 
 
 
 
 
 
 
389
  if ( empty( $args ) )
390
  $args = $this->reparse_image_args( $args );
391
 
392
+ $src = \wp_get_attachment_image_src( $id, $args['size'], $args['icon'], $args['attr'] );
393
 
394
  $i = $src[0]; // Source URL
395
  $w = $src[1]; // Width
396
  $h = $src[2]; // Height
397
 
398
+ //* Preferred 1500px, resize it
399
+ if ( $w > 1500 || $h > 1500 ) :
400
 
401
  if ( $w === $h ) {
402
  //* Square
411
  }
412
 
413
  //* Get path of image and load it into the wp_get_image_editor
414
+ $i_file_path = \get_attached_file( $id );
415
+ $i_file_ext = pathinfo( $i_file_path, PATHINFO_EXTENSION );
 
 
416
 
417
  if ( $i_file_ext ) {
418
  $i_file_dir_name = pathinfo( $i_file_path, PATHINFO_DIRNAME );
426
  $new_image_dirfile = $i_file_dir_name . $i_file_file_name . '-' . $w . 'x' . $h . '.' . $i_file_ext;
427
 
428
  //* Generate image URL.
429
+ $upload_dir = \wp_upload_dir();
430
+ $upload_url = $upload_dir['baseurl'];
431
  $upload_basedir = $upload_dir['basedir'];
432
 
433
  //* We've got our image path.
437
  // Generate file if it doesn't exists yet.
438
  if ( ! file_exists( $new_image_dirfile ) ) {
439
 
440
+ $image_editor = \wp_get_image_editor( $i_file_path );
441
 
442
+ if ( ! \is_wp_error( $image_editor ) ) {
443
  $image_editor->resize( $w, $h, false );
444
  $image_editor->set_quality( 82 ); // Let's save some bandwidth, Facebook compresses it even further anyway.
445
  $image_editor->save( $new_image_dirfile );
449
  }
450
  }
451
  }
452
+ endif;
453
 
454
  //* Whether to use the post ID (Post Thumbnail) or input ID (ID was known beforehand)
455
  $usage_id = isset( $args['get_the_real_ID'] ) && $args['get_the_real_ID'] ? $this->get_the_real_ID() : $id;
456
 
457
  $this->image_dimensions = $this->image_dimensions + array( $usage_id => array( 'width' => $w, 'height' => $h ) );
458
 
459
+ return $i;
460
  }
461
 
462
  /**
463
+ * Fetches site icon brought in WordPress 4.3
464
  *
465
+ * @since 2.8.0
466
  *
467
+ * @param string|int $size The icon size, accepts 'full' and pixel values.
468
  * @param bool $set_og_dimensions Whether to set size for OG image. Always falls back to the current post ID.
469
  * @return string URL site icon, not escaped.
470
  */
471
+ public function get_site_icon( $size = 'full', $set_og_dimensions = false ) {
472
 
473
  $icon = '';
474
 
475
  if ( 'full' === $size ) {
476
+ $site_icon_id = \get_option( 'site_icon' );
477
 
478
  if ( $site_icon_id ) {
479
  $url_data = '';
480
+ $url_data = \wp_get_attachment_image_src( $site_icon_id, $size );
481
 
482
  $icon = $url_data ? $url_data[0] : '';
483
 
488
  $this->image_dimensions = $this->image_dimensions + array( $this->get_the_real_ID() => array( 'width' => $w, 'height' => $h ) );
489
  }
490
  }
491
+ } elseif ( is_int( $size ) && function_exists( 'has_site_icon' ) ) {
492
+ //* Above 512 defaults to full. Loop back.
493
+ if ( $size > 512 )
494
+ return $this->get_site_icon( 'full', $set_og_dimensions );
495
+
496
  //* Also applies (MultiSite) filters.
497
+ $icon = \get_site_icon_url( $size );
498
  }
499
 
500
  return $icon;
501
  }
502
 
503
+ /**
504
+ * Fetches site logo brought in WordPress 4.5
505
+ *
506
+ * @since 2.8.0
507
+ *
508
+ * @param bool $set_og_dimensions Whether to set size for OG image. Always falls back to the current post ID.
509
+ * @return string URL site logo, not escaped.
510
+ */
511
+ public function get_site_logo( $set_og_dimensions = false ) {
512
+
513
+ if ( false === $this->can_use_logo() )
514
+ return '';
515
+
516
+ $logo = '';
517
+
518
+ $site_logo_id = \get_theme_mod( 'custom_logo' );
519
+
520
+ if ( $site_logo_id ) {
521
+ $url_data = '';
522
+ $url_data = \wp_get_attachment_image_src( $site_logo_id, 'full' );
523
+
524
+ $logo = $url_data ? $url_data[0] : '';
525
+
526
+ if ( $set_og_dimensions && $logo ) {
527
+ $w = $url_data[1];
528
+ $h = $url_data[2];
529
+
530
+ $this->image_dimensions = $this->image_dimensions + array( $this->get_the_real_ID() => array( 'width' => $w, 'height' => $h ) );
531
+ }
532
+ }
533
+
534
+ return $logo;
535
+ }
536
+
537
  /**
538
  * Returns header image URL.
539
  * Also sets image dimensions. Falls back to current post ID for index.
545
  */
546
  public function get_header_image( $set_og_dimensions = false ) {
547
 
548
+ $image = \get_header_image();
549
 
550
  if ( $set_og_dimensions && $image ) {
551
 
552
+ $w = (int) \get_theme_support( 'custom-header', 'width' );
553
+ $h = (int) \get_theme_support( 'custom-header', 'height' );
554
 
555
  if ( $w && $h )
556
  $this->image_dimensions = $this->image_dimensions + array( $this->get_the_real_ID() => array( 'width' => $w, 'height' => $h ) );
inc/classes/generate-ldjson.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,34 +23,19 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Generate
23
  *
24
  * Generates SEO data based on content
25
- * Returns strings/arrays
26
  *
27
- * @since 2.6.0
28
  */
29
- class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
30
-
31
- /**
32
- * Unserializing instances of this class is forbidden.
33
- */
34
- private function __wakeup() { }
35
-
36
- /**
37
- * Handle unapproachable invoked methods.
38
- */
39
- public function __call( $name, $arguments ) {
40
- parent::__call( $name, $arguments );
41
- }
42
 
43
  /**
44
  * Constructor, load parent constructor
45
  */
46
- public function __construct() {
47
  parent::__construct();
48
  }
49
 
@@ -63,7 +55,9 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
63
 
64
  if ( $this->the_seo_framework_debug ) $this->debug_init( __METHOD__, false, $debug_key = microtime( true ), array( 'LD Json transient' => $this->ld_json_transient, 'Output from transient' => false !== $this->get_transient( $this->ld_json_transient ) ) );
65
 
66
- $output = $this->get_transient( $this->ld_json_transient );
 
 
67
  if ( false === $output ) {
68
 
69
  $output = '';
@@ -88,17 +82,21 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
88
  $breadcrumbhelper = $this->ld_json_breadcrumbs();
89
 
90
  //* No wrapper, is done within script generator.
91
- if ( $breadcrumbhelper )
92
  $output .= $breadcrumbhelper;
 
 
93
  }
94
 
95
- /**
96
- * Transient expiration: 1 week.
97
- * Keep the script for at most 1 week.
98
- */
99
- $expiration = WEEK_IN_SECONDS;
 
100
 
101
- $this->set_transient( $this->ld_json_transient, $output, $expiration );
 
102
  }
103
 
104
  /**
@@ -259,9 +257,9 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
259
  * @param int $id The page, post, product or term ID.
260
  * @param bool $singular Whether the ID is singular.
261
  */
262
- $image = apply_filters( 'the_seo_framework_ld_json_breadcrumb_image', $image, $id, $singular );
263
 
264
- return $images[ $id ][ $singular ] = json_encode( esc_url_raw( $image ) );
265
  }
266
 
267
  /**
@@ -287,7 +285,7 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
287
  * @since 2.7.0
288
  * @param string $search_url The default WordPress search URL without query parameters.
289
  */
290
- $search_url = (string) apply_filters( 'the_seo_framework_ld_json_search_url', $this->the_home_url_from_cache( true ) . '?s=' );
291
 
292
  // Remove trailing quote and add it back.
293
  $target = mb_substr( json_encode( $search_url ), 0, -1 ) . '{search_term_string}"';
@@ -347,13 +345,25 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
347
  $cat_type = 'product_cat';
348
 
349
  //* Test categories.
350
- $r = is_object_in_term( $post_id, $cat_type, '' );
 
 
 
 
 
 
 
 
 
 
 
 
 
351
 
352
- if ( ! $r || is_wp_error( $r ) )
353
  return '';
354
 
355
- $cats = get_the_terms( $post_id, $cat_type );
356
- $cats = wp_list_pluck( $cats, 'parent', 'term_id' );
357
  asort( $cats, SORT_NUMERIC );
358
 
359
  $assigned_ids = array();
@@ -363,17 +373,22 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
363
 
364
  //* Fetch cats children id's, if any.
365
  foreach ( $cats as $term_id => $parent_id ) {
 
 
 
 
366
  //* Store to filter unused Cat ID's from the post.
367
  $assigned_ids[] = $term_id;
368
 
369
  // Check if they have kittens.
370
- $children = get_term_children( $term_id, $cat_type );
371
- $ancestors = get_ancestors( $term_id, $cat_type );
372
 
373
  //* Save children id's as kittens.
374
  $kittens[ $term_id ] = $children;
375
  $parents[ $term_id ] = $ancestors;
376
  }
 
377
 
378
  foreach ( $kittens as $kit_id => $child_id ) {
379
  foreach ( $child_id as $ckey => $cid ) {
@@ -449,8 +464,21 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
449
  /**
450
  * Sort by number of id's. Provides a cleaner layout, better Search Engine understanding and more consistent cache.
451
  */
452
- if ( count( $trees ) > 1 )
453
- array_multisort( array_map( 'count', $trees ), SORT_DESC, $trees );
 
 
 
 
 
 
 
 
 
 
 
 
 
454
 
455
  $context = $this->schema_context();
456
  $context_type = $this->schema_breadcrumblist();
@@ -485,12 +513,13 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
485
  } else {
486
  $pos = $position + 2;
487
 
488
- $cat = get_term_by( 'id', $child_id, $cat_type, OBJECT, 'raw' );
489
  $data = $this->get_term_data( $cat, $child_id );
490
 
491
  $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'is_term' => true, 'term' => $cat ) ) );
492
 
493
- $cat_name = empty( $data['doctitle'] ) ? $cat->name : $data['doctitle'];
 
494
  $name = json_encode( $cat_name );
495
 
496
  $image = $this->schema_image( $child_id );
@@ -528,12 +557,13 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
528
  $image = $this->schema_image( $tree_ids );
529
 
530
  //* $tree_ids is a single ID here.
531
- $cat = get_term_by( 'id', $tree_ids, $cat_type, OBJECT, 'raw' );
532
  $data = $this->get_term_data( $cat, $tree_ids );
533
 
534
  $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'is_term' => true, 'external' => true, 'term' => $cat ) ) );
535
 
536
- $cat_name = empty( $data['doctitle'] ) ? $cat->name : $data['doctitle'];
 
537
  $name = json_encode( $cat_name );
538
 
539
  $items .= sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s,"image":%s}},', $item_type, (string) $pos, $id, $name, $image );
@@ -567,9 +597,9 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
567
  $page_id = $this->get_the_real_ID();
568
 
569
  //* Get ancestors.
570
- $parents = get_post_ancestors( $page_id );
571
 
572
- if ( $parents ) {
573
 
574
  $context = $this->schema_context();
575
  $context_type = $this->schema_breadcrumblist();
@@ -584,8 +614,7 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
584
 
585
  $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'id' => $parent_id ) ) );
586
 
587
- $custom_field_name = $this->get_custom_field( '_genesis_title', $parent_id );
588
- $parent_name = $custom_field_name ? $custom_field_name : $this->title( '', '', '', array( 'term_id' => $parent_id, 'meta' => true, 'get_custom_field' => false, 'placeholder' => true, 'notagline' => true, 'description_title' => true ) );
589
 
590
  $name = json_encode( $parent_name );
591
  $image = $this->schema_image( $parent_id );
@@ -609,7 +638,7 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
609
  $breadcrumbhelper = sprintf( '{"@context":%s,"@type":%s,"itemListElement":[%s]}', $context, $context_type, $items );
610
  $output = '<script type="application/ld+json">' . $breadcrumbhelper . '</script>' . "\r\n";
611
  }
612
- }
613
 
614
  return $output;
615
  }
@@ -644,8 +673,7 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
644
  } elseif ( $this->has_page_on_front() ) {
645
  $home_id = (int) get_option( 'page_on_front' );
646
 
647
- $custom_name = $this->get_custom_field( '_genesis_title', $home_id );
648
- $custom_name = $custom_name ? $custom_name : $this->get_blogname();
649
  } else {
650
  $custom_name = $this->get_blogname();
651
  }
@@ -667,18 +695,15 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
667
  /**
668
  * Return current page item for LD Json Breadcrumbs.
669
  *
670
- * @staticvar string $last_item.
671
- *
672
  * @since 2.4.2
673
- *
674
- * @param string $item_type the breadcrumb item type.
675
- * @param int $pos Last known position.
676
- * @param int $post_id The current Post ID
677
- *
678
  * @staticvar string $type The breadcrumb item type.
679
  * @staticvar string $id The current post/page/archive url.
680
  * @staticvar string $name The current post/page/archive title.
681
  *
 
 
 
682
  * @return string Last Breadcrumb item
683
  */
684
  public function ld_json_breadcrumb_last( $item_type = null, $pos = null, $post_id = null ) {
@@ -712,8 +737,7 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
712
  $id = json_encode( $this->the_url_from_cache() );
713
 
714
  if ( ! isset( $name ) ) {
715
- $custom_field = $this->get_custom_field( '_genesis_title', $post_id );
716
- $name = $custom_field ? $custom_field : $this->title( '', '', '', array( 'term_id' => $post_id, 'placeholder' => true, 'meta' => true, 'notagline' => true, 'description_title' => true ) );
717
  $name = json_encode( $name );
718
  }
719
 
@@ -745,19 +769,20 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
745
  * @return string The LD+Json breadcrumb.
746
  */
747
  public function make_breadcrumb( $item, $comma = true ) {
 
748
  $comma = $comma ? ',' : '';
 
749
  return sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s,"image":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $item['image'], $comma );
750
  }
751
 
752
  /**
753
- * Build breadcrumb trees.
754
  *
755
  * @since 2.6.0
756
  *
757
- * @param array The breadcrumb trees, with the key as parent.
758
  * @param array $previous_tree A previous set tree to compare to, if set.
759
- *
760
- * @return trees in order.
761
  */
762
  protected function build_breadcrumb_trees( $kittens, array $previous_tree = array() ) {
763
 
@@ -775,10 +800,10 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
775
  //* Nested categories.
776
  $add = array();
777
 
778
- foreach ( $kitten as $kit => $kat ) {
779
  //* Only add if non-existent in $trees.
780
- if ( ! in_array( $kat, $trees, true ) )
781
- $add[] = $kat;
782
  }
783
 
784
  //* Put children in right order.
@@ -810,24 +835,25 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
810
  * Forgot to add this.
811
  * @since 2.4.3
812
  */
813
- $knowledge_name = $this->get_option( 'knowledge_name' );
814
- $knowledge_name = $knowledge_name ? $knowledge_name : $this->get_blogname();
815
 
816
  $context = $this->schema_context();
817
  $type = json_encode( ucfirst( $knowledge_type ) );
818
  $name = json_encode( $knowledge_name );
819
- $url = json_encode( esc_url( home_url( '/' ) ) );
820
 
821
  $logo = '';
822
 
823
  if ( $this->get_option( 'knowledge_logo' ) && 'organization' === $knowledge_type ) {
824
- $icon = $this->site_icon();
 
 
825
 
826
- if ( $icon ) {
827
- $logourl = esc_url_raw( $icon );
828
 
829
  //* Add trailing comma
830
- $logo = '"logo":' . json_encode( $logourl ) . ',';
831
  }
832
  }
833
 
@@ -836,7 +862,7 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
836
  * @since ???
837
  * @todo Document.
838
  */
839
- $options = (array) apply_filters( 'the_seo_framework_json_options', array(
840
  'knowledge_facebook',
841
  'knowledge_twitter',
842
  'knowledge_gplus',
@@ -865,8 +891,13 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
865
  $sameurls = rtrim( $sameurls, $comma );
866
  $json = '';
867
 
868
- if ( $sameurls )
869
- $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s,%s"sameAs":[%s]}', $context, $type, $name, $url, $logo, $sameurls );
 
 
 
 
 
870
 
871
  $output = '';
872
  if ( $json )
@@ -920,7 +951,7 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
920
  * Applies filters the_seo_framework_json_breadcrumb_output
921
  * @since 2.4.2
922
  */
923
- $filter = (bool) apply_filters( 'the_seo_framework_json_breadcrumb_output', true );
924
  $option = $this->is_option_checked( 'ld_json_breadcrumbs' );
925
 
926
  return $cache = $filter && $option;
@@ -945,7 +976,7 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
945
  * Applies filters the_seo_framework_json_sitename_output
946
  * @since 2.6.0
947
  */
948
- $filter = (bool) apply_filters( 'the_seo_framework_json_sitename_output', true );
949
  $option = $this->is_option_checked( 'ld_json_sitename' );
950
 
951
  return $cache = $filter && $option;
@@ -970,7 +1001,7 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
970
  * Applies filters 'the_seo_framework_json_search_output'
971
  * @since 2.3.9
972
  */
973
- $filter = (bool) apply_filters( 'the_seo_framework_json_search_output', true );
974
  $option = $this->is_option_checked( 'ld_json_searchbox' );
975
 
976
  return $cache = $filter && $option;
@@ -995,7 +1026,7 @@ class AutoDescription_Generate_Ldjson extends AutoDescription_Generate_Image {
995
  * Applies filters 'the_seo_framework_json_search_output'
996
  * @since 2.6.5
997
  */
998
- $filter = (bool) apply_filters( 'the_seo_framework_json_knowledge_output', true );
999
  $option = $this->is_option_checked( 'knowledge_output' );
1000
 
1001
  return $cache = $filter && $option;
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Generate_Ldjson
28
  *
29
  * Generates SEO data based on content
 
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Generate_Ldjson extends Generate_Image {
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  /**
36
  * Constructor, load parent constructor
37
  */
38
+ protected function __construct() {
39
  parent::__construct();
40
  }
41
 
55
 
56
  if ( $this->the_seo_framework_debug ) $this->debug_init( __METHOD__, false, $debug_key = microtime( true ), array( 'LD Json transient' => $this->ld_json_transient, 'Output from transient' => false !== $this->get_transient( $this->ld_json_transient ) ) );
57
 
58
+ $use_cache = $this->is_option_checked( 'cache_meta_schema' );
59
+
60
+ $output = $use_cache ? $this->get_transient( $this->ld_json_transient ) : false;
61
  if ( false === $output ) {
62
 
63
  $output = '';
82
  $breadcrumbhelper = $this->ld_json_breadcrumbs();
83
 
84
  //* No wrapper, is done within script generator.
85
+ if ( $breadcrumbhelper ) {
86
  $output .= $breadcrumbhelper;
87
+ $output .= $this->ld_json_name();
88
+ }
89
  }
90
 
91
+ if ( $use_cache ) {
92
+ /**
93
+ * Transient expiration: 1 week.
94
+ * Keep the script for at most 1 week.
95
+ */
96
+ $expiration = WEEK_IN_SECONDS;
97
 
98
+ $this->set_transient( $this->ld_json_transient, $output, $expiration );
99
+ }
100
  }
101
 
102
  /**
257
  * @param int $id The page, post, product or term ID.
258
  * @param bool $singular Whether the ID is singular.
259
  */
260
+ $image = \apply_filters( 'the_seo_framework_ld_json_breadcrumb_image', $image, $id, $singular );
261
 
262
+ return $images[ $id ][ $singular ] = json_encode( \esc_url_raw( $image ) );
263
  }
264
 
265
  /**
285
  * @since 2.7.0
286
  * @param string $search_url The default WordPress search URL without query parameters.
287
  */
288
+ $search_url = (string) \apply_filters( 'the_seo_framework_ld_json_search_url', $this->the_home_url_from_cache( true ) . '?s=' );
289
 
290
  // Remove trailing quote and add it back.
291
  $target = mb_substr( json_encode( $search_url ), 0, -1 ) . '{search_term_string}"';
345
  $cat_type = 'product_cat';
346
 
347
  //* Test categories.
348
+ $r = \is_object_in_term( $post_id, $cat_type, '' );
349
+
350
+ if ( ! $r || \is_wp_error( $r ) )
351
+ return '';
352
+
353
+ /**
354
+ * Applies filter 'the_seo_framework_ld_json_breadcrumb_terms' : array
355
+ * @since 2.8.0
356
+ *
357
+ * @param array $cats The LD+Json terms that are being used
358
+ * @param int $post_id The current Post ID.
359
+ * @param string $cat_type The current taxonomy (either category or product_cat).
360
+ */
361
+ $cats = (array) \apply_filters_ref_array( 'the_seo_framework_ld_json_breadcrumb_terms', array( \get_the_terms( $post_id, $cat_type ), $post_id, $cat_type ) );
362
 
363
+ if ( empty( $cats ) )
364
  return '';
365
 
366
+ $cats = \wp_list_pluck( $cats, 'parent', 'term_id' );
 
367
  asort( $cats, SORT_NUMERIC );
368
 
369
  $assigned_ids = array();
373
 
374
  //* Fetch cats children id's, if any.
375
  foreach ( $cats as $term_id => $parent_id ) {
376
+ //* Warning: This makes database calls...
377
+ if ( ! \term_exists( $term_id, $cat_type, $parent_id ) )
378
+ continue;
379
+
380
  //* Store to filter unused Cat ID's from the post.
381
  $assigned_ids[] = $term_id;
382
 
383
  // Check if they have kittens.
384
+ $children = \get_term_children( $term_id, $cat_type );
385
+ $ancestors = \get_ancestors( $term_id, $cat_type );
386
 
387
  //* Save children id's as kittens.
388
  $kittens[ $term_id ] = $children;
389
  $parents[ $term_id ] = $ancestors;
390
  }
391
+ unset( $cats );
392
 
393
  foreach ( $kittens as $kit_id => $child_id ) {
394
  foreach ( $child_id as $ckey => $cid ) {
464
  /**
465
  * Sort by number of id's. Provides a cleaner layout, better Search Engine understanding and more consistent cache.
466
  */
467
+ if ( count( $trees ) > 1 ) {
468
+ /**
469
+ * Applies filter 'the_seo_framework_breadcrumb_post_sorting_callback' : string|array
470
+ * @since 2.8.0
471
+ *
472
+ * @param mixed $function The method or function callback. Default false.
473
+ * @param array $trees The current tree list.
474
+ */
475
+ $callback_filter = \apply_filters_ref_array( 'the_seo_framework_breadcrumb_post_sorting_callback', array( false, $trees ) );
476
+ if ( $callback_filter ) {
477
+ $trees = $this->call_function( $callback_filter, '2.8.0', $trees );
478
+ } else {
479
+ array_multisort( array_map( 'count', $trees ), SORT_DESC, SORT_REGULAR, $trees );
480
+ }
481
+ }
482
 
483
  $context = $this->schema_context();
484
  $context_type = $this->schema_breadcrumblist();
513
  } else {
514
  $pos = $position + 2;
515
 
516
+ $cat = \get_term_by( 'id', $child_id, $cat_type, OBJECT, 'raw' );
517
  $data = $this->get_term_data( $cat, $child_id );
518
 
519
  $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'is_term' => true, 'term' => $cat ) ) );
520
 
521
+ //* Note: WordPress Core translation.
522
+ $cat_name = empty( $data['doctitle'] ) ? ( empty( $cat->name ) ? __( 'Uncategorized' ) : $cat->name ) : $data['doctitle'];
523
  $name = json_encode( $cat_name );
524
 
525
  $image = $this->schema_image( $child_id );
557
  $image = $this->schema_image( $tree_ids );
558
 
559
  //* $tree_ids is a single ID here.
560
+ $cat = \get_term_by( 'id', $tree_ids, $cat_type, OBJECT, 'raw' );
561
  $data = $this->get_term_data( $cat, $tree_ids );
562
 
563
  $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'is_term' => true, 'external' => true, 'term' => $cat ) ) );
564
 
565
+ //* Note: WordPress Core translation.
566
+ $cat_name = empty( $data['doctitle'] ) ? ( empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name ) : $data['doctitle'];
567
  $name = json_encode( $cat_name );
568
 
569
  $items .= sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s,"image":%s}},', $item_type, (string) $pos, $id, $name, $image );
597
  $page_id = $this->get_the_real_ID();
598
 
599
  //* Get ancestors.
600
+ $parents = \get_post_ancestors( $page_id );
601
 
602
+ if ( $parents ) :
603
 
604
  $context = $this->schema_context();
605
  $context_type = $this->schema_breadcrumblist();
614
 
615
  $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'id' => $parent_id ) ) );
616
 
617
+ $parent_name = $this->get_custom_field( '_genesis_title', $parent_id ) ?: $this->title( '', '', '', array( 'term_id' => $parent_id, 'meta' => true, 'get_custom_field' => false, 'placeholder' => true, 'notagline' => true, 'description_title' => true ) );
 
618
 
619
  $name = json_encode( $parent_name );
620
  $image = $this->schema_image( $parent_id );
638
  $breadcrumbhelper = sprintf( '{"@context":%s,"@type":%s,"itemListElement":[%s]}', $context, $context_type, $items );
639
  $output = '<script type="application/ld+json">' . $breadcrumbhelper . '</script>' . "\r\n";
640
  }
641
+ endif;
642
 
643
  return $output;
644
  }
673
  } elseif ( $this->has_page_on_front() ) {
674
  $home_id = (int) get_option( 'page_on_front' );
675
 
676
+ $custom_name = $this->get_custom_field( '_genesis_title', $home_id ) ?: $this->get_blogname();
 
677
  } else {
678
  $custom_name = $this->get_blogname();
679
  }
695
  /**
696
  * Return current page item for LD Json Breadcrumbs.
697
  *
 
 
698
  * @since 2.4.2
699
+ * @staticvar string $last_item.
 
 
 
 
700
  * @staticvar string $type The breadcrumb item type.
701
  * @staticvar string $id The current post/page/archive url.
702
  * @staticvar string $name The current post/page/archive title.
703
  *
704
+ * @param string $item_type the breadcrumb item type.
705
+ * @param int $pos Last known position.
706
+ * @param int $post_id The current Post ID
707
  * @return string Last Breadcrumb item
708
  */
709
  public function ld_json_breadcrumb_last( $item_type = null, $pos = null, $post_id = null ) {
737
  $id = json_encode( $this->the_url_from_cache() );
738
 
739
  if ( ! isset( $name ) ) {
740
+ $name = $this->get_custom_field( '_genesis_title', $post_id ) ?: $this->title( '', '', '', array( 'term_id' => $post_id, 'placeholder' => true, 'meta' => true, 'notagline' => true, 'description_title' => true ) );
 
741
  $name = json_encode( $name );
742
  }
743
 
769
  * @return string The LD+Json breadcrumb.
770
  */
771
  public function make_breadcrumb( $item, $comma = true ) {
772
+
773
  $comma = $comma ? ',' : '';
774
+
775
  return sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s,"image":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $item['image'], $comma );
776
  }
777
 
778
  /**
779
+ * Builds breadcrumb trees.
780
  *
781
  * @since 2.6.0
782
  *
783
+ * @param array $kittens The breadcrumb trees, with the key as parent.
784
  * @param array $previous_tree A previous set tree to compare to, if set.
785
+ * @return array Trees in order.
 
786
  */
787
  protected function build_breadcrumb_trees( $kittens, array $previous_tree = array() ) {
788
 
800
  //* Nested categories.
801
  $add = array();
802
 
803
+ foreach ( $kitten as $kit_id => $child_id ) {
804
  //* Only add if non-existent in $trees.
805
+ if ( ! in_array( $child_id, $trees, true ) )
806
+ $add[] = $child_id;
807
  }
808
 
809
  //* Put children in right order.
835
  * Forgot to add this.
836
  * @since 2.4.3
837
  */
838
+ $knowledge_name = $this->get_option( 'knowledge_name' ) ?: $this->get_blogname();
 
839
 
840
  $context = $this->schema_context();
841
  $type = json_encode( ucfirst( $knowledge_type ) );
842
  $name = json_encode( $knowledge_name );
843
+ $url = json_encode( \esc_url( \home_url( '/' ) ) );
844
 
845
  $logo = '';
846
 
847
  if ( $this->get_option( 'knowledge_logo' ) && 'organization' === $knowledge_type ) {
848
+ $_logo = $this->get_site_logo();
849
+ if ( ! $_logo )
850
+ $_logo = $this->get_site_icon();
851
 
852
+ if ( $_logo ) {
853
+ $logourl = \esc_url_raw( $_logo );
854
 
855
  //* Add trailing comma
856
+ $logo = '"logo":' . json_encode( $logourl );
857
  }
858
  }
859
 
862
  * @since ???
863
  * @todo Document.
864
  */
865
+ $options = (array) \apply_filters( 'the_seo_framework_json_options', array(
866
  'knowledge_facebook',
867
  'knowledge_twitter',
868
  'knowledge_gplus',
891
  $sameurls = rtrim( $sameurls, $comma );
892
  $json = '';
893
 
894
+ $logo = $logo ? ',' . $logo : '';
895
+
896
+ if ( $sameurls ) {
897
+ $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s%s,"sameAs":[%s]}', $context, $type, $name, $url, $logo, $sameurls );
898
+ } else {
899
+ $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s%s}', $context, $type, $name, $url, $logo );
900
+ }
901
 
902
  $output = '';
903
  if ( $json )
951
  * Applies filters the_seo_framework_json_breadcrumb_output
952
  * @since 2.4.2
953
  */
954
+ $filter = (bool) \apply_filters( 'the_seo_framework_json_breadcrumb_output', true );
955
  $option = $this->is_option_checked( 'ld_json_breadcrumbs' );
956
 
957
  return $cache = $filter && $option;
976
  * Applies filters the_seo_framework_json_sitename_output
977
  * @since 2.6.0
978
  */
979
+ $filter = (bool) \apply_filters( 'the_seo_framework_json_sitename_output', true );
980
  $option = $this->is_option_checked( 'ld_json_sitename' );
981
 
982
  return $cache = $filter && $option;
1001
  * Applies filters 'the_seo_framework_json_search_output'
1002
  * @since 2.3.9
1003
  */
1004
+ $filter = (bool) \apply_filters( 'the_seo_framework_json_search_output', true );
1005
  $option = $this->is_option_checked( 'ld_json_searchbox' );
1006
 
1007
  return $cache = $filter && $option;
1026
  * Applies filters 'the_seo_framework_json_search_output'
1027
  * @since 2.6.5
1028
  */
1029
+ $filter = (bool) \apply_filters( 'the_seo_framework_json_knowledge_output', true );
1030
  $option = $this->is_option_checked( 'knowledge_output' );
1031
 
1032
  return $cache = $filter && $option;
inc/classes/generate-title.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -19,30 +26,18 @@
19
  defined( 'ABSPATH' ) or die;
20
 
21
  /**
22
- * Class AutoDescription_Generate_Title
23
  *
24
  * Generates title SEO data based on content.
25
  *
26
- * @since 2.6.0
27
  */
28
- class AutoDescription_Generate_Title extends AutoDescription_Generate_Description {
29
-
30
- /**
31
- * Unserializing instances of this class is forbidden.
32
- */
33
- private function __wakeup() { }
34
-
35
- /**
36
- * Handle unapproachable invoked methods.
37
- */
38
- public function __call( $name, $arguments ) {
39
- parent::__call( $name, $arguments );
40
- }
41
 
42
  /**
43
  * Constructor, load parent constructor
44
  */
45
- public function __construct() {
46
  parent::__construct();
47
  }
48
 
@@ -99,7 +94,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
99
  //* Set doing it wrong parameters.
100
  $this->set_tell_title_doing_it_wrong( $title, $sep, $seplocation, false );
101
  //* And echo them.
102
- add_action( 'wp_footer', array( $this, 'tell_title_doing_it_wrong' ), 20 );
103
 
104
  //* Notify cache.
105
  $this->title_doing_it_wrong = true;
@@ -128,43 +123,11 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
128
  return $this->build_title( $title = '', $seplocation, $args );
129
  }
130
 
131
- /**
132
- * Escapes and beautifies title.
133
- *
134
- * @since 2.5.2
135
- *
136
- * @param string $title The title to escape and beautify.
137
- * @param bool $trim Whether to trim the title from whitespaces.
138
- * @return string Escaped and beautified title.
139
- */
140
- public function escape_title( $title = '', $trim = true ) {
141
-
142
- $title = wptexturize( $title );
143
- $title = convert_chars( $title );
144
- $title = esc_html( $title );
145
- $title = capital_P_dangit( $title );
146
- $title = $trim ? trim( $title ) : $title;
147
-
148
- return $title;
149
- }
150
-
151
  /**
152
  * Parse and sanitize title args.
153
  *
154
  * @since 2.4.0
155
  *
156
- * @since 2.5.0:
157
- * Applies filters the_seo_framework_title_args : {
158
- * @param int term_id The Taxonomy Term ID when taxonomy is also filled in. Else post ID.
159
- * @param string taxonomy The Taxonomy name.
160
- * @param bool page_on_front Page on front condition for example generation.
161
- * @param bool notagline Generate title without tagline.
162
- * @param bool meta Ignore doing_it_wrong. Used in og:title/twitter:title
163
- * @param bool get_custom_field Do not fetch custom title when false.
164
- * @param bool description_title Fetch title for description.
165
- * @param bool is_front_page Fetch front page title.
166
- * }
167
- *
168
  * @param array $args required The passed arguments.
169
  * @param array $defaults The default arguments.
170
  * @param bool $get_defaults Return the default arguments. Ignoring $args.
@@ -175,18 +138,35 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
175
  //* Passing back the defaults reduces the memory usage.
176
  if ( empty( $defaults ) ) {
177
  $defaults = array(
178
- 'term_id' => $this->get_the_real_ID(),
179
- 'taxonomy' => '',
180
- 'page_on_front' => false,
181
- 'notagline' => false,
182
- 'meta' => false,
183
- 'get_custom_field' => true,
184
- 'description_title' => false,
185
- 'is_front_page' => false,
186
- 'escape' => true,
187
  );
188
 
189
- $defaults = (array) apply_filters( 'the_seo_framework_title_args', $defaults, $args );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  }
191
 
192
  //* Return early if it's only a default args request.
@@ -194,15 +174,15 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
194
  return $defaults;
195
 
196
  //* Array merge doesn't support sanitation. We're simply type casting here.
197
- $args['term_id'] = isset( $args['term_id'] ) ? (int) $args['term_id'] : $defaults['term_id'];
198
- $args['taxonomy'] = isset( $args['taxonomy'] ) ? (string) $args['taxonomy'] : $defaults['taxonomy'];
199
- $args['page_on_front'] = isset( $args['page_on_front'] ) ? (bool) $args['page_on_front'] : $defaults['page_on_front'];
200
- $args['notagline'] = isset( $args['notagline'] ) ? (bool) $args['notagline'] : $defaults['notagline'];
201
- $args['meta'] = isset( $args['meta'] ) ? (bool) $args['meta'] : $defaults['meta'];
202
- $args['get_custom_field'] = isset( $args['get_custom_field'] ) ? (bool) $args['get_custom_field'] : $defaults['get_custom_field'];
203
- $args['description_title'] = isset( $args['description_title'] ) ? (bool) $args['description_title'] : $defaults['description_title'];
204
- $args['is_front_page'] = isset( $args['is_front_page'] ) ? (bool) $args['is_front_page'] : $defaults['is_front_page'];
205
- $args['escape'] = isset( $args['escape'] ) ? (bool) $args['escape'] : $defaults['escape'];
206
 
207
  return $args;
208
  }
@@ -271,9 +251,9 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
271
  * @since 2.6.0
272
  *
273
  * @param array $args : accepted args : {
274
- * @param int term_id The Taxonomy Term ID
275
- * @param bool placeholder Generate placeholder, ignoring options.
276
- * @param bool page_on_front Page on front condition for example generation
277
  * }
278
  * @return string Title without tagline.
279
  */
@@ -281,7 +261,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
281
 
282
  $title = '';
283
 
284
- //* Fetch title from custom fields.
285
  if ( $args['get_custom_field'] )
286
  $title = $this->get_custom_field_title( $title, $args['term_id'], $args['taxonomy'] );
287
 
@@ -344,13 +324,11 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
344
  $blogname = $this->get_blogname();
345
 
346
  /**
347
- * Don't add/replace separator when false.
348
- *
349
- * @applies filters the_seo_framework_doingitwrong_add_sep
350
- *
351
  * @since 2.4.2
352
  */
353
- $add_sep = (bool) apply_filters( 'the_seo_framework_doingitwrong_add_sep', true );
354
 
355
  $sep_replace = false;
356
  //* Maybe remove separator.
@@ -384,13 +362,11 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
384
  *
385
  * A separator is at least 2 long (space + separator).
386
  *
387
- * @param string $sep_to_replace Already confirmed to contain the old sep string.
388
  *
389
- * Now also considers seplocation.
390
- * @since 2.4.1
391
  */
392
  if ( $sep_to_replace ) {
393
-
394
  $sep_to_replace_length = mb_strlen( $sep_to_replace );
395
 
396
  if ( 'right' === $seplocation ) {
@@ -524,8 +500,8 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
524
  * Applies filters 'the_seo_framework_do_shortcodes_in_title' : Boolean
525
  * @since 2.6.6
526
  */
527
- if ( apply_filters( 'the_seo_framework_do_shortcodes_in_title', false ) )
528
- $title = do_shortcode( $title );
529
 
530
  if ( $args['escape'] )
531
  $title = $this->escape_title( $title );
@@ -535,32 +511,11 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
535
  return $title;
536
  }
537
 
538
- /**
539
- * Fetches title from special fields, like other plugins with special queries.
540
- * Used before and has priority over custom fields.
541
- * Front end only.
542
- *
543
- * @since 2.5.2
544
- *
545
- * @return string $title Title from Special Field.
546
- */
547
- public function title_from_special_fields() {
548
-
549
- $title = '';
550
-
551
- if ( false === $this->is_admin() ) {
552
- if ( $this->is_ultimate_member_user_page() && um_is_core_page( 'user' ) && um_get_requested_user() ) {
553
- $title = um_user( 'display_name' );
554
- }
555
- }
556
-
557
- return $title;
558
- }
559
-
560
  /**
561
  * Generate the title based on query conditions.
562
  *
563
  * @since 2.3.4
 
564
  * @staticvar array $cache : contains $title strings.
565
  *
566
  * @param array $args The Title Args.
@@ -575,18 +530,24 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
575
  $id = $args['term_id'];
576
  $taxonomy = $args['taxonomy'];
577
 
578
- static $cache = array();
 
 
 
579
 
580
- if ( isset( $cache[ $id ][ $taxonomy ] ) )
581
- $title = $cache[ $id ][ $taxonomy ];
 
582
 
583
  if ( empty( $title ) ) {
584
 
585
- if ( $this->is_archive() ) {
 
 
586
  if ( ( $id && $taxonomy ) || $this->is_category() || $this->is_tag() || $this->is_tax() ) {
587
  $title = $this->title_for_terms( $args, false );
588
  } else {
589
- $term = get_queried_object();
590
  /**
591
  * Get all other archive titles
592
  * @since 2.5.2
@@ -611,7 +572,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
611
  if ( $escape )
612
  $title = $this->escape_title( $title, false );
613
 
614
- return $title;
615
  }
616
 
617
  /**
@@ -664,12 +625,29 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
664
  $blogname = $this->escape_title( $blogname, false );
665
  }
666
 
667
- return array(
668
  'title' => $title,
669
  'blogname' => $blogname,
670
  'add_tagline' => $add_tagline,
671
  'seplocation' => $seplocation,
672
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
  }
674
 
675
  /**
@@ -692,18 +670,29 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
692
  * Get blogname title based on option
693
  * @since 2.2.2
694
  */
695
- if ( $get_option ) {
696
- $home_title_option = $this->get_option( 'homepage_title' ) ? $this->get_option( 'homepage_title' ) : $home_title;
697
- $home_title = $home_title_option ? $home_title_option : $home_title;
698
- }
699
 
700
  /**
701
  * Fetch from Home Page InPost SEO Box if available.
702
  * Only from page on front.
703
  */
704
  if ( $get_custom_field && empty( $home_title ) && $this->has_page_on_front() ) {
705
- $custom_field = $this->get_custom_field( '_genesis_title', $this->get_the_front_page_ID() );
706
- $home_title = $custom_field ? $custom_field : $this->get_blogname();
 
 
 
 
 
 
 
 
 
 
 
 
 
707
  } else {
708
  $home_title = $home_title ? $home_title : $this->get_blogname();
709
  }
@@ -731,11 +720,11 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
731
  $term = null;
732
 
733
  if ( $args['term_id'] && $args['taxonomy'] )
734
- $term = get_term( $args['term_id'], $args['taxonomy'], OBJECT, 'raw' );
735
 
736
  if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
737
  if ( ! isset( $term ) && $this->is_tax() )
738
- $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
739
 
740
  if ( ! isset( $term ) )
741
  $term = $this->fetch_the_term( $args['term_id'] );
@@ -776,13 +765,13 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
776
  */
777
  if ( $this->is_singular() ) {
778
  //* Get title from custom field, empty it if it's not there to override the default title
779
- $title = $this->get_custom_field( '_genesis_title', $id ) ? $this->get_custom_field( '_genesis_title', $id ) : $title;
780
  } elseif ( $this->is_blog_page( $id ) ) {
781
  //* Posts page title.
782
- $title = $this->get_custom_field( '_genesis_title', $id ) ? $this->get_custom_field( '_genesis_title', $id ) : get_the_title( $id );
783
  } elseif ( $this->is_archive() || ( $id && $taxonomy ) ) {
784
  //* Get the custom title for terms.
785
- $term = get_term( $id, $taxonomy, OBJECT, 'raw' );
786
  $data = $this->get_term_data( $term, $id );
787
 
788
  $title = empty( $data['doctitle'] ) ? $title : $data['doctitle'];
@@ -795,29 +784,29 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
795
  }
796
 
797
  /**
798
- * Get the archive Title, including filter. Also works in admin.
799
  * @NOTE Taken from WordPress core. Altered to work in the Admin area.
800
  *
801
  * @since 2.6.0
802
  *
803
  * @param object $term The Term object.
804
  * @param array $args The Title arguments.
805
- * @return string The Archive Title.
806
  */
807
  public function get_the_real_archive_title( $term = null, $args = array() ) {
808
 
809
  if ( empty( $term ) )
810
- $term = get_queried_object();
811
 
812
  /**
813
- * Applies filters the_seo_framework_the_archive_title : {
814
- * @param string empty short circuit the function.
815
- * @param object $term The Term object.
816
- * }
817
  *
818
  * @since 2.6.0
 
 
 
819
  */
820
- $title = (string) apply_filters( 'the_seo_framework_the_archive_title', '', $term );
821
 
822
  if ( $title )
823
  return $title;
@@ -830,59 +819,59 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
830
  if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
831
  $title = $this->single_term_title( '', false, $term );
832
  /* translators: Front-end output. 1: Taxonomy singular name, 2: Current taxonomy term */
833
- $title = $use_prefix ? sprintf( __( '%1$s: %2$s', 'autodescription' ), $this->get_the_term_name( $term ), $title ) : $title;
834
  } elseif ( $this->is_author() ) {
835
- $title = get_the_author();
836
  /* translators: Front-end output. */
837
- $title = $use_prefix ? sprintf( __( 'Author: %s', 'autodescription' ), $title ) : $title;
838
  } elseif ( $this->is_date() ) {
839
  if ( $this->is_year() ) {
840
  /* translators: Front-end output. */
841
- $title = get_the_date( _x( 'Y', 'yearly archives date format', 'autodescription' ) );
842
  /* translators: Front-end output. */
843
- $title = $use_prefix ? sprintf( __( 'Year: %s', 'autodescription' ), $title ) : $title;
844
  } elseif ( $this->is_month() ) {
845
  /* translators: Front-end output. */
846
- $title = get_the_date( _x( 'F Y', 'monthly archives date format', 'autodescription' ) );
847
  /* translators: Front-end output. */
848
- $title = $use_prefix ? sprintf( __( 'Month: %s', 'autodescription' ), $title ) : $title;
849
  } elseif ( $this->is_day() ) {
850
  /* translators: Front-end output. */
851
- $title = get_the_date( _x( 'F j, Y', 'daily archives date format', 'autodescription' ) );
852
  /* translators: Front-end output. */
853
- $title = $use_prefix ? sprintf( __( 'Day: %s', 'autodescription' ), $title ) : $title;
854
  }
855
  } elseif ( $this->is_tax( 'post_format' ) ) {
856
- if ( is_tax( 'post_format', 'post-format-aside' ) ) {
857
  /* translators: Front-end output. */
858
- $title = _x( 'Asides', 'post format archive title', 'autodescription' );
859
  } elseif ( $this->is_tax( 'post_format', 'post-format-gallery' ) ) {
860
  /* translators: Front-end output. */
861
- $title = _x( 'Galleries', 'post format archive title', 'autodescription' );
862
  } elseif ( $this->is_tax( 'post_format', 'post-format-image' ) ) {
863
  /* translators: Front-end output. */
864
- $title = _x( 'Images', 'post format archive title', 'autodescription' );
865
  } elseif ( $this->is_tax( 'post_format', 'post-format-video' ) ) {
866
  /* translators: Front-end output. */
867
- $title = _x( 'Videos', 'post format archive title', 'autodescription' );
868
  } elseif ( $this->is_tax( 'post_format', 'post-format-quote' ) ) {
869
  /* translators: Front-end output. */
870
- $title = _x( 'Quotes', 'post format archive title', 'autodescription' );
871
  } elseif ( $this->is_tax( 'post_format', 'post-format-link' ) ) {
872
  /* translators: Front-end output. */
873
- $title = _x( 'Links', 'post format archive title', 'autodescription' );
874
  } elseif ( $this->is_tax( 'post_format', 'post-format-status' ) ) {
875
  /* translators: Front-end output. */
876
- $title = _x( 'Statuses', 'post format archive title', 'autodescription' );
877
  } elseif ( $this->is_tax( 'post_format', 'post-format-audio' ) ) {
878
  /* translators: Front-end output. */
879
- $title = _x( 'Audio', 'post format archive title', 'autodescription' );
880
  } elseif ( $this->is_tax( 'post_format', 'post-format-chat' ) ) {
881
  /* translators: Front-end output. */
882
- $title = _x( 'Chats', 'post format archive title', 'autodescription' );
883
  }
884
- } elseif ( is_post_type_archive() ) {
885
- $title = post_type_archive_title( '', false );
886
  /* translators: Front-end output. */
887
  $title = $use_prefix ? sprintf( __( 'Archives: %s' ), $title ) : $title;
888
  } elseif ( isset( $term ) ) {
@@ -890,28 +879,28 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
890
 
891
  if ( $use_prefix ) {
892
  /* translators: Front-end output. 1: Taxonomy singular name, 2: Current taxonomy term */
893
- $title = sprintf( __( '%1$s: %2$s', 'autodescription' ), $this->get_the_term_name( $term, true, false ), $title );
894
  }
895
  } else {
896
  /* translators: Front-end output. */
897
- $title = __( 'Archives', 'autodescription' );
898
  }
899
 
900
  return $title;
901
  }
902
 
903
  /**
904
- * Fetch single term title.
905
  * @NOTE Taken from WordPress core. Altered to work in the Admin area.
906
  *
907
  * @since 2.6.0
908
  *
909
- * @return string.
910
  */
911
  public function single_term_title( $prefix = '', $display = true, $term = null ) {
912
 
913
  if ( is_null( $term ) )
914
- $term = get_queried_object();
915
 
916
  if ( ! $term )
917
  return;
@@ -925,7 +914,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
925
  *
926
  * @param string $term_name Category name for archive being displayed.
927
  */
928
- $term_name = apply_filters( 'single_cat_title', $term->name );
929
  } elseif ( $this->is_tag() ) {
930
  /**
931
  * Filter the tag archive page title.
@@ -934,7 +923,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
934
  *
935
  * @param string $term_name Tag name for archive being displayed.
936
  */
937
- $term_name = apply_filters( 'single_tag_title', $term->name );
938
  } elseif ( $this->is_tax() || $this->is_admin() ) {
939
  /**
940
  * Filter the custom taxonomy archive page title.
@@ -943,7 +932,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
943
  *
944
  * @param string $term_name Term name for archive being displayed.
945
  */
946
- $term_name = apply_filters( 'single_term_title', $term->name );
947
  } else {
948
  return '';
949
  }
@@ -953,10 +942,11 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
953
  if ( empty( $term_name ) )
954
  $term_name = $this->untitled();
955
 
956
- if ( $display )
957
- echo esc_attr( $prefix . $term_name );
958
- else
959
  return $prefix . $term_name;
 
960
  }
961
 
962
  /**
@@ -971,16 +961,21 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
971
  */
972
  public function get_custom_field_title( $title = '', $id = '', $taxonomy = '' ) {
973
 
974
- $title_special = '';
975
-
976
- if ( $this->is_singular() )
977
- $title_special = $this->title_from_special_fields();
978
-
979
- if ( $title_special ) {
980
- $title = $title_special;
 
 
 
 
 
 
981
  } else {
982
- $title_from_custom_field = $this->title_from_custom_field( $title, false, $id, $taxonomy );
983
- $title = $title_from_custom_field ? $title_from_custom_field : $title;
984
  }
985
 
986
  return $title;
@@ -991,11 +986,11 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
991
  *
992
  * @since 2.6.0
993
  *
994
- * @return string Untitled.
995
  */
996
  public function untitled() {
997
  /* translators: Front-end output. */
998
- return __( 'Untitled', 'autodescription' );
999
  }
1000
 
1001
  /**
@@ -1012,7 +1007,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
1012
  if ( $this->is_archive() )
1013
  return $title;
1014
 
1015
- $post = get_post( $id, OBJECT );
1016
 
1017
  return $title = isset( $post->post_title ) ? $post->post_title : $title;
1018
  }
@@ -1030,9 +1025,9 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
1030
 
1031
  if ( $this->is_search() ) {
1032
  /* translators: Front-end output. */
1033
- $search_title = (string) apply_filters( 'the_seo_framework_search_title', __( 'Search results for:', 'autodescription' ) );
1034
 
1035
- return $search_title . ' ' . trim( get_search_query( $escape ) );
1036
  }
1037
 
1038
  return $title;
@@ -1052,7 +1047,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
1052
  public function get_the_404_title( $title = '' ) {
1053
 
1054
  if ( $this->is_404() )
1055
- return (string) apply_filters( 'the_seo_framework_404_title', '404' );
1056
 
1057
  return $title;
1058
  }
@@ -1075,7 +1070,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
1075
  if ( isset( $sep ) )
1076
  return $sep;
1077
 
1078
- return $sep = (string) apply_filters( 'the_seo_framework_title_separator', $this->get_separator( 'title', false ) );
1079
  }
1080
 
1081
  /**
@@ -1102,9 +1097,9 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
1102
 
1103
  if ( empty( $seplocation ) || 'right' !== $seplocation || 'left' !== $seplocation ) {
1104
  if ( $home ) {
1105
- return $cache[ $seplocation ][ $home ] = (string) apply_filters( 'the_seo_framework_title_seplocation_front', $this->get_option( 'home_title_location' ) );
1106
  } else {
1107
- return $cache[ $seplocation ][ $home ] = (string) apply_filters( 'the_seo_framework_title_seplocation', $this->get_option( 'title_location' ) );
1108
  }
1109
  }
1110
 
@@ -1142,7 +1137,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
1142
  return $add;
1143
 
1144
  if ( $this->can_manipulate_title() )
1145
- if ( $this->is_option_checked( 'title_rem_additions' ) || false === (bool) apply_filters( 'the_seo_framework_add_blogname_to_title', true ) )
1146
  return $add = false;
1147
 
1148
  return $add = true;
@@ -1180,35 +1175,39 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
1180
  * Adds title protection prefixes.
1181
  *
1182
  * @since 2.6.0
 
1183
  *
1184
  * @param $title The current Title.
1185
  * @param $id The page ID.
1186
  * @return string $title with possible affixes.
1187
  */
1188
- public function add_title_protection( $title, $id ) {
1189
 
1190
- /**
1191
- * From WordPress core get_the_title.
1192
- * Bypasses get_post() function object which causes conflict with some themes and plugins.
1193
- *
1194
- * Also bypasses the_title filters.
1195
- * And now also works in admin. It gives you a true representation of its output.
1196
- *
1197
- * @since 2.4.1
1198
- *
1199
- * @applies filters WordPress core 'protected_title_format' : string
1200
- * @applies filters WordPress core 'private_title_format' : string
1201
- */
1202
- $post = get_post( $id, OBJECT );
1203
-
1204
- if ( isset( $post->post_password ) && '' !== $post->post_password ) {
1205
- /* translators: Front-end output */
1206
- $protected_title_format = (string) apply_filters( 'protected_title_format', __( 'Protected: %s', 'autodescription' ), $post );
1207
- $title = sprintf( $protected_title_format, $title );
1208
- } elseif ( isset( $post->post_status ) && 'private' === $post->post_status ) {
1209
- /* translators: Front-end output */
1210
- $private_title_format = (string) apply_filters( 'private_title_format', __( 'Private: %s', 'autodescription' ), $post );
1211
- $title = sprintf( $private_title_format, $title );
 
 
 
1212
  }
1213
 
1214
  return $title;
@@ -1275,7 +1274,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
1275
  *
1276
  * @since 2.6.0
1277
  */
1278
- $filter = (bool) apply_filters( 'the_seo_framework_use_archive_title_prefix', true, $term );
1279
  $option = ! $this->get_option( 'title_rem_prefixes' );
1280
 
1281
  return $cache = $option && $filter;
@@ -1301,7 +1300,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
1301
  * @param array $args
1302
  * @param bool $escape
1303
  */
1304
- $title = (string) apply_filters( 'the_seo_framework_pre_add_title', $title, $args, $escape );
1305
 
1306
  if ( $escape )
1307
  $title = $this->escape_title( $title );
@@ -1329,7 +1328,7 @@ class AutoDescription_Generate_Title extends AutoDescription_Generate_Descriptio
1329
  * @param array $args
1330
  * @param bool $escape
1331
  */
1332
- $title = (string) apply_filters( 'the_seo_framework_pro_add_title', $title, $args, $escape );
1333
 
1334
  if ( $escape )
1335
  $title = $this->escape_title( $title );
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
26
  defined( 'ABSPATH' ) or die;
27
 
28
  /**
29
+ * Class The_SEO_Framework\Generate_Title
30
  *
31
  * Generates title SEO data based on content.
32
  *
33
+ * @since 2.8.0
34
  */
35
+ class Generate_Title extends Generate_Description {
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  /**
38
  * Constructor, load parent constructor
39
  */
40
+ protected function __construct() {
41
  parent::__construct();
42
  }
43
 
94
  //* Set doing it wrong parameters.
95
  $this->set_tell_title_doing_it_wrong( $title, $sep, $seplocation, false );
96
  //* And echo them.
97
+ \add_action( 'wp_footer', array( $this, 'tell_title_doing_it_wrong' ), 20 );
98
 
99
  //* Notify cache.
100
  $this->title_doing_it_wrong = true;
123
  return $this->build_title( $title = '', $seplocation, $args );
124
  }
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  /**
127
  * Parse and sanitize title args.
128
  *
129
  * @since 2.4.0
130
  *
 
 
 
 
 
 
 
 
 
 
 
 
131
  * @param array $args required The passed arguments.
132
  * @param array $defaults The default arguments.
133
  * @param bool $get_defaults Return the default arguments. Ignoring $args.
138
  //* Passing back the defaults reduces the memory usage.
139
  if ( empty( $defaults ) ) {
140
  $defaults = array(
141
+ 'term_id' => $this->get_the_real_ID(),
142
+ 'taxonomy' => '',
143
+ 'page_on_front' => false,
144
+ 'notagline' => false,
145
+ 'meta' => false,
146
+ 'get_custom_field' => true,
147
+ 'description_title' => false,
148
+ 'is_front_page' => false,
149
+ 'escape' => true,
150
  );
151
 
152
+ /**
153
+ * Applies filters the_seo_framework_title_args : {
154
+ * @param int term_id The Taxonomy Term ID when taxonomy is also filled in. Else post ID.
155
+ * @param string taxonomy The Taxonomy name.
156
+ * @param bool page_on_front Page on front condition for example generation.
157
+ * @param bool notagline Generate title without tagline.
158
+ * @param bool meta Ignore doing_it_wrong. Used in og:title/twitter:title
159
+ * @param bool get_custom_field Do not fetch custom title when false.
160
+ * @param bool description_title Fetch title for description.
161
+ * @param bool is_front_page Fetch front page title.
162
+ * }
163
+ *
164
+ * @since 2.5.0
165
+ *
166
+ * @param array $defaults The title defaults.
167
+ * @param array $args The input args.
168
+ */
169
+ $defaults = (array) \apply_filters( 'the_seo_framework_title_args', $defaults, $args );
170
  }
171
 
172
  //* Return early if it's only a default args request.
174
  return $defaults;
175
 
176
  //* Array merge doesn't support sanitation. We're simply type casting here.
177
+ $args['term_id'] = isset( $args['term_id'] ) ? (int) $args['term_id'] : $defaults['term_id'];
178
+ $args['taxonomy'] = isset( $args['taxonomy'] ) ? (string) $args['taxonomy'] : $defaults['taxonomy'];
179
+ $args['page_on_front'] = isset( $args['page_on_front'] ) ? (bool) $args['page_on_front'] : $defaults['page_on_front'];
180
+ $args['notagline'] = isset( $args['notagline'] ) ? (bool) $args['notagline'] : $defaults['notagline'];
181
+ $args['meta'] = isset( $args['meta'] ) ? (bool) $args['meta'] : $defaults['meta'];
182
+ $args['get_custom_field'] = isset( $args['get_custom_field'] ) ? (bool) $args['get_custom_field'] : $defaults['get_custom_field'];
183
+ $args['description_title'] = isset( $args['description_title'] ) ? (bool) $args['description_title'] : $defaults['description_title'];
184
+ $args['is_front_page'] = isset( $args['is_front_page'] ) ? (bool) $args['is_front_page'] : $defaults['is_front_page'];
185
+ $args['escape'] = isset( $args['escape'] ) ? (bool) $args['escape'] : $defaults['escape'];
186
 
187
  return $args;
188
  }
251
  * @since 2.6.0
252
  *
253
  * @param array $args : accepted args : {
254
+ * @param int $term_id The Taxonomy Term ID
255
+ * @param bool $placeholder Generate placeholder, ignoring options.
256
+ * @param bool $page_on_front Page on front condition for example generation
257
  * }
258
  * @return string Title without tagline.
259
  */
261
 
262
  $title = '';
263
 
264
+ //* Fetch title from custom fields or filter.
265
  if ( $args['get_custom_field'] )
266
  $title = $this->get_custom_field_title( $title, $args['term_id'], $args['taxonomy'] );
267
 
324
  $blogname = $this->get_blogname();
325
 
326
  /**
327
+ * Applies filters 'the_seo_framework_doingitwrong_add_sep' : bool
328
+ * Determines additions of separator.
 
 
329
  * @since 2.4.2
330
  */
331
+ $add_sep = (bool) \apply_filters( 'the_seo_framework_doingitwrong_add_sep', true );
332
 
333
  $sep_replace = false;
334
  //* Maybe remove separator.
362
  *
363
  * A separator is at least 2 long (space + separator).
364
  *
365
+ * @since 2.4.1 Now also considers seplocation.
366
  *
367
+ * @param string $sep_to_replace Already confirmed to contain the old sep string.
 
368
  */
369
  if ( $sep_to_replace ) {
 
370
  $sep_to_replace_length = mb_strlen( $sep_to_replace );
371
 
372
  if ( 'right' === $seplocation ) {
500
  * Applies filters 'the_seo_framework_do_shortcodes_in_title' : Boolean
501
  * @since 2.6.6
502
  */
503
+ if ( \apply_filters( 'the_seo_framework_do_shortcodes_in_title', false ) )
504
+ $title = \do_shortcode( $title );
505
 
506
  if ( $args['escape'] )
507
  $title = $this->escape_title( $title );
511
  return $title;
512
  }
513
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
514
  /**
515
  * Generate the title based on query conditions.
516
  *
517
  * @since 2.3.4
518
+ * @since 2.8.0 : Cache now works.
519
  * @staticvar array $cache : contains $title strings.
520
  *
521
  * @param array $args The Title Args.
530
  $id = $args['term_id'];
531
  $taxonomy = $args['taxonomy'];
532
 
533
+ if ( $this->is_admin() ) {
534
+ $cache = array();
535
+ } else {
536
+ static $cache = array();
537
 
538
+ if ( isset( $cache[ $id ][ $taxonomy ] ) )
539
+ $title = $cache[ $id ][ $taxonomy ];
540
+ }
541
 
542
  if ( empty( $title ) ) {
543
 
544
+ if ( $args['page_on_front'] ) {
545
+ $title = $this->title_for_home( '', $args['get_custom_field'], false, true );
546
+ } elseif ( $this->is_archive() ) {
547
  if ( ( $id && $taxonomy ) || $this->is_category() || $this->is_tag() || $this->is_tax() ) {
548
  $title = $this->title_for_terms( $args, false );
549
  } else {
550
+ $term = \get_queried_object();
551
  /**
552
  * Get all other archive titles
553
  * @since 2.5.2
572
  if ( $escape )
573
  $title = $this->escape_title( $title, false );
574
 
575
+ return $cache[ $id ][ $taxonomy ] = $title;
576
  }
577
 
578
  /**
625
  $blogname = $this->escape_title( $blogname, false );
626
  }
627
 
628
+ $defaults = array(
629
  'title' => $title,
630
  'blogname' => $blogname,
631
  'add_tagline' => $add_tagline,
632
  'seplocation' => $seplocation,
633
  );
634
+
635
+ /**
636
+ * Applies filters 'the_seo_framework_home_title_args' : array {
637
+ * @param string $title : NOTE: This is the blogname
638
+ * @param string $blogname : NOTE: This is the tagline.
639
+ * @param bool $add_tagline
640
+ * @param string $seplocation : 'left' or 'right'
641
+ * }
642
+ *
643
+ * @since 2.8.0
644
+ *
645
+ * @param array $args
646
+ * @param array $defaults
647
+ */
648
+ $args = (array) \apply_filters( 'the_seo_framework_home_title_args', array(), $defaults );
649
+
650
+ return \wp_parse_args( $args, $defaults );
651
  }
652
 
653
  /**
670
  * Get blogname title based on option
671
  * @since 2.2.2
672
  */
673
+ if ( $get_option )
674
+ $home_title = $this->get_option( 'homepage_title' ) ?: $home_title;
 
 
675
 
676
  /**
677
  * Fetch from Home Page InPost SEO Box if available.
678
  * Only from page on front.
679
  */
680
  if ( $get_custom_field && empty( $home_title ) && $this->has_page_on_front() ) {
681
+
682
+ /**
683
+ * Applies filters 'the_seo_framework_custom_field_home_title' : string
684
+ * @see filter 'the_seo_framework_custom_field_title'
685
+ *
686
+ * @since 2.8.0
687
+ *
688
+ * @param string $title The special title.
689
+ */
690
+ if ( $filter_title = (string) \apply_filters( 'the_seo_framework_custom_field_home_title', '' ) ) {
691
+ $home_title = $filter_title;
692
+ } else {
693
+ $custom_field = $this->get_custom_field( '_genesis_title', $this->get_the_front_page_ID() );
694
+ $home_title = $custom_field ? $custom_field : $this->get_blogname();
695
+ }
696
  } else {
697
  $home_title = $home_title ? $home_title : $this->get_blogname();
698
  }
720
  $term = null;
721
 
722
  if ( $args['term_id'] && $args['taxonomy'] )
723
+ $term = \get_term( $args['term_id'], $args['taxonomy'], OBJECT, 'raw' );
724
 
725
  if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
726
  if ( ! isset( $term ) && $this->is_tax() )
727
+ $term = \get_term_by( 'slug', \get_query_var( 'term' ), \get_query_var( 'taxonomy' ) );
728
 
729
  if ( ! isset( $term ) )
730
  $term = $this->fetch_the_term( $args['term_id'] );
765
  */
766
  if ( $this->is_singular() ) {
767
  //* Get title from custom field, empty it if it's not there to override the default title
768
+ $title = $this->get_custom_field( '_genesis_title', $id ) ?: $title;
769
  } elseif ( $this->is_blog_page( $id ) ) {
770
  //* Posts page title.
771
+ $title = $this->get_custom_field( '_genesis_title', $id ) ?: \get_the_title( $id );
772
  } elseif ( $this->is_archive() || ( $id && $taxonomy ) ) {
773
  //* Get the custom title for terms.
774
+ $term = \get_term( $id, $taxonomy, OBJECT, 'raw' );
775
  $data = $this->get_term_data( $term, $id );
776
 
777
  $title = empty( $data['doctitle'] ) ? $title : $data['doctitle'];
784
  }
785
 
786
  /**
787
+ * Gets the archive Title, including filter. Also works in admin.
788
  * @NOTE Taken from WordPress core. Altered to work in the Admin area.
789
  *
790
  * @since 2.6.0
791
  *
792
  * @param object $term The Term object.
793
  * @param array $args The Title arguments.
794
+ * @return string The Archive Title, not escaped.
795
  */
796
  public function get_the_real_archive_title( $term = null, $args = array() ) {
797
 
798
  if ( empty( $term ) )
799
+ $term = \get_queried_object();
800
 
801
  /**
802
+ * Applies filters 'the_seo_framework_the_archive_title' : string
 
 
 
803
  *
804
  * @since 2.6.0
805
+ *
806
+ * @param string $title The short circuit title.
807
+ * @param object $term The Term object.
808
  */
809
+ $title = (string) \apply_filters( 'the_seo_framework_the_archive_title', '', $term );
810
 
811
  if ( $title )
812
  return $title;
819
  if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
820
  $title = $this->single_term_title( '', false, $term );
821
  /* translators: Front-end output. 1: Taxonomy singular name, 2: Current taxonomy term */
822
+ $title = $use_prefix ? sprintf( \__( '%1$s: %2$s', 'autodescription' ), $this->get_the_term_name( $term ), $title ) : $title;
823
  } elseif ( $this->is_author() ) {
824
+ $title = \get_the_author();
825
  /* translators: Front-end output. */
826
+ $title = $use_prefix ? sprintf( \__( 'Author: %s', 'autodescription' ), $title ) : $title;
827
  } elseif ( $this->is_date() ) {
828
  if ( $this->is_year() ) {
829
  /* translators: Front-end output. */
830
+ $title = \get_the_date( \_x( 'Y', 'yearly archives date format', 'autodescription' ) );
831
  /* translators: Front-end output. */
832
+ $title = $use_prefix ? sprintf( \__( 'Year: %s', 'autodescription' ), $title ) : $title;
833
  } elseif ( $this->is_month() ) {
834
  /* translators: Front-end output. */
835
+ $title = \get_the_date( \_x( 'F Y', 'monthly archives date format', 'autodescription' ) );
836
  /* translators: Front-end output. */
837
+ $title = $use_prefix ? sprintf( \__( 'Month: %s', 'autodescription' ), $title ) : $title;
838
  } elseif ( $this->is_day() ) {
839
  /* translators: Front-end output. */
840
+ $title = \get_the_date( \_x( 'F j, Y', 'daily archives date format', 'autodescription' ) );
841
  /* translators: Front-end output. */
842
+ $title = $use_prefix ? sprintf( \__( 'Day: %s', 'autodescription' ), $title ) : $title;
843
  }
844
  } elseif ( $this->is_tax( 'post_format' ) ) {
845
+ if ( \is_tax( 'post_format', 'post-format-aside' ) ) {
846
  /* translators: Front-end output. */
847
+ $title = \_x( 'Asides', 'post format archive title', 'autodescription' );
848
  } elseif ( $this->is_tax( 'post_format', 'post-format-gallery' ) ) {
849
  /* translators: Front-end output. */
850
+ $title = \_x( 'Galleries', 'post format archive title', 'autodescription' );
851
  } elseif ( $this->is_tax( 'post_format', 'post-format-image' ) ) {
852
  /* translators: Front-end output. */
853
+ $title = \_x( 'Images', 'post format archive title', 'autodescription' );
854
  } elseif ( $this->is_tax( 'post_format', 'post-format-video' ) ) {
855
  /* translators: Front-end output. */
856
+ $title = \_x( 'Videos', 'post format archive title', 'autodescription' );
857
  } elseif ( $this->is_tax( 'post_format', 'post-format-quote' ) ) {
858
  /* translators: Front-end output. */
859
+ $title = \_x( 'Quotes', 'post format archive title', 'autodescription' );
860
  } elseif ( $this->is_tax( 'post_format', 'post-format-link' ) ) {
861
  /* translators: Front-end output. */
862
+ $title = \_x( 'Links', 'post format archive title', 'autodescription' );
863
  } elseif ( $this->is_tax( 'post_format', 'post-format-status' ) ) {
864
  /* translators: Front-end output. */
865
+ $title = \_x( 'Statuses', 'post format archive title', 'autodescription' );
866
  } elseif ( $this->is_tax( 'post_format', 'post-format-audio' ) ) {
867
  /* translators: Front-end output. */
868
+ $title = \_x( 'Audio', 'post format archive title', 'autodescription' );
869
  } elseif ( $this->is_tax( 'post_format', 'post-format-chat' ) ) {
870
  /* translators: Front-end output. */
871
+ $title = \_x( 'Chats', 'post format archive title', 'autodescription' );
872
  }
873
+ } elseif ( \is_post_type_archive() ) {
874
+ $title = \post_type_archive_title( '', false );
875
  /* translators: Front-end output. */
876
  $title = $use_prefix ? sprintf( __( 'Archives: %s' ), $title ) : $title;
877
  } elseif ( isset( $term ) ) {
879
 
880
  if ( $use_prefix ) {
881
  /* translators: Front-end output. 1: Taxonomy singular name, 2: Current taxonomy term */
882
+ $title = sprintf( __( '%1$s: %2$s', 'autodescription' ), $this->get_the_term_name( $term, true, false ), $title );
883
  }
884
  } else {
885
  /* translators: Front-end output. */
886
+ $title = \__( 'Archives', 'autodescription' );
887
  }
888
 
889
  return $title;
890
  }
891
 
892
  /**
893
+ * Fetches single term title.
894
  * @NOTE Taken from WordPress core. Altered to work in the Admin area.
895
  *
896
  * @since 2.6.0
897
  *
898
+ * @return string Single term title.
899
  */
900
  public function single_term_title( $prefix = '', $display = true, $term = null ) {
901
 
902
  if ( is_null( $term ) )
903
+ $term = \get_queried_object();
904
 
905
  if ( ! $term )
906
  return;
914
  *
915
  * @param string $term_name Category name for archive being displayed.
916
  */
917
+ $term_name = \apply_filters( 'single_cat_title', $term->name );
918
  } elseif ( $this->is_tag() ) {
919
  /**
920
  * Filter the tag archive page title.
923
  *
924
  * @param string $term_name Tag name for archive being displayed.
925
  */
926
+ $term_name = \apply_filters( 'single_tag_title', $term->name );
927
  } elseif ( $this->is_tax() || $this->is_admin() ) {
928
  /**
929
  * Filter the custom taxonomy archive page title.
932
  *
933
  * @param string $term_name Term name for archive being displayed.
934
  */
935
+ $term_name = \apply_filters( 'single_term_title', $term->name );
936
  } else {
937
  return '';
938
  }
942
  if ( empty( $term_name ) )
943
  $term_name = $this->untitled();
944
 
945
+ if ( $display ) {
946
+ echo \esc_attr( $prefix . $term_name );
947
+ } else {
948
  return $prefix . $term_name;
949
+ }
950
  }
951
 
952
  /**
961
  */
962
  public function get_custom_field_title( $title = '', $id = '', $taxonomy = '' ) {
963
 
964
+ /**
965
+ * Applies filters 'the_seo_framework_custom_field_title' : string
966
+ * NOTE: This does NOT filter the title for the HOMEpage.
967
+ * @see filter 'the_seo_framework_custom_field_home_title'
968
+ *
969
+ * @since 2.8.0
970
+ *
971
+ * @param string $title The special title.
972
+ * @param int $id The post or TT ID.
973
+ * @param string $taxonomy the TT name.
974
+ */
975
+ if ( $filter_title = (string) \apply_filters( 'the_seo_framework_custom_field_title', '', $id, $taxonomy ) ) {
976
+ $title = $filter_title;
977
  } else {
978
+ $title = $this->title_from_custom_field( $title, false, $id, $taxonomy ) ?: $title;
 
979
  }
980
 
981
  return $title;
986
  *
987
  * @since 2.6.0
988
  *
989
+ * @return string Untitled. Not escaped.
990
  */
991
  public function untitled() {
992
  /* translators: Front-end output. */
993
+ return \__( 'Untitled', 'autodescription' );
994
  }
995
 
996
  /**
1007
  if ( $this->is_archive() )
1008
  return $title;
1009
 
1010
+ $post = \get_post( $id, OBJECT );
1011
 
1012
  return $title = isset( $post->post_title ) ? $post->post_title : $title;
1013
  }
1025
 
1026
  if ( $this->is_search() ) {
1027
  /* translators: Front-end output. */
1028
+ $search_title = (string) \apply_filters( 'the_seo_framework_search_title', __( 'Search results for:', 'autodescription' ) );
1029
 
1030
+ return $search_title . ' ' . trim( \get_search_query( $escape ) );
1031
  }
1032
 
1033
  return $title;
1047
  public function get_the_404_title( $title = '' ) {
1048
 
1049
  if ( $this->is_404() )
1050
+ return (string) \apply_filters( 'the_seo_framework_404_title', '404' );
1051
 
1052
  return $title;
1053
  }
1070
  if ( isset( $sep ) )
1071
  return $sep;
1072
 
1073
+ return $sep = (string) \apply_filters( 'the_seo_framework_title_separator', $this->get_separator( 'title', false ) );
1074
  }
1075
 
1076
  /**
1097
 
1098
  if ( empty( $seplocation ) || 'right' !== $seplocation || 'left' !== $seplocation ) {
1099
  if ( $home ) {
1100
+ return $cache[ $seplocation ][ $home ] = (string) \apply_filters( 'the_seo_framework_title_seplocation_front', $this->get_option( 'home_title_location' ) );
1101
  } else {
1102
+ return $cache[ $seplocation ][ $home ] = (string) \apply_filters( 'the_seo_framework_title_seplocation', $this->get_option( 'title_location' ) );
1103
  }
1104
  }
1105
 
1137
  return $add;
1138
 
1139
  if ( $this->can_manipulate_title() )
1140
+ if ( $this->is_option_checked( 'title_rem_additions' ) || false === (bool) \apply_filters( 'the_seo_framework_add_blogname_to_title', true ) )
1141
  return $add = false;
1142
 
1143
  return $add = true;
1175
  * Adds title protection prefixes.
1176
  *
1177
  * @since 2.6.0
1178
+ * @since 2.8.0 Now first checks if is singular.
1179
  *
1180
  * @param $title The current Title.
1181
  * @param $id The page ID.
1182
  * @return string $title with possible affixes.
1183
  */
1184
+ public function add_title_protection( $title, $id = 0 ) {
1185
 
1186
+ if ( $this->is_singular() ) {
1187
+ /**
1188
+ * This is from WordPress core get_the_title().
1189
+ *
1190
+ * Bypasses get_post() function object which causes conflict with some themes and plugins.
1191
+ * Also bypasses 'the_title' filters.
1192
+ *
1193
+ * And now also works in admin. It gives you a true representation of its output.
1194
+ *
1195
+ * @since 2.4.1
1196
+ * Applies filters WordPress core 'protected_title_format' : string The protected title format.
1197
+ * Applies filters WordPress core 'private_title_format' : string The private title format.
1198
+ */
1199
+
1200
+ $post = \get_post( $id, OBJECT );
1201
+
1202
+ if ( isset( $post->post_password ) && '' !== $post->post_password ) {
1203
+ /* translators: Front-end output */
1204
+ $protected_title_format = (string) \apply_filters( 'protected_title_format', \__( 'Protected: %s', 'autodescription' ), $post );
1205
+ $title = sprintf( $protected_title_format, $title );
1206
+ } elseif ( isset( $post->post_status ) && 'private' === $post->post_status ) {
1207
+ /* translators: Front-end output */
1208
+ $private_title_format = (string) \apply_filters( 'private_title_format', \__( 'Private: %s', 'autodescription' ), $post );
1209
+ $title = sprintf( $private_title_format, $title );
1210
+ }
1211
  }
1212
 
1213
  return $title;
1274
  *
1275
  * @since 2.6.0
1276
  */
1277
+ $filter = (bool) \apply_filters( 'the_seo_framework_use_archive_title_prefix', true, $term );
1278
  $option = ! $this->get_option( 'title_rem_prefixes' );
1279
 
1280
  return $cache = $option && $filter;
1300
  * @param array $args
1301
  * @param bool $escape
1302
  */
1303
+ $title = (string) \apply_filters( 'the_seo_framework_pre_add_title', $title, $args, $escape );
1304
 
1305
  if ( $escape )
1306
  $title = $this->escape_title( $title );
1328
  * @param array $args
1329
  * @param bool $escape
1330
  */
1331
+ $title = (string) \apply_filters( 'the_seo_framework_pro_add_title', $title, $args, $escape );
1332
 
1333
  if ( $escape )
1334
  $title = $this->escape_title( $title );
inc/classes/generate-url.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,60 +23,50 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Generate_Url
23
  *
24
  * Generates URL and permalink SEO data based on content.
25
  *
26
- * @since 2.6.0
27
  */
28
- class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
29
 
30
  /**
31
  * Whether to slash the url or not. Used when query vars are in url.
32
  *
33
  * @since 2.6.0
 
34
  *
35
  * @var bool Whether to slash the url.
36
  */
37
- protected $url_slashit;
38
 
39
  /**
40
  * Holds current HTTP host.
41
  *
42
  * @since 2.6.5
 
43
  *
44
  * @var string The current HTTP host.
45
  */
46
- protected $current_host;
47
-
48
- /**
49
- * Unserializing instances of this class is forbidden.
50
- */
51
- private function __wakeup() { }
52
-
53
- /**
54
- * Handle unapproachable invoked methods.
55
- */
56
- public function __call( $name, $arguments ) {
57
- parent::__call( $name, $arguments );
58
- }
59
 
60
  /**
61
  * Constructor, load parent constructor and set up variables.
62
  */
63
- public function __construct() {
64
  parent::__construct();
65
  }
66
 
67
  /**
68
  * Creates canonical URL.
69
  *
70
- * @param string $url the url
 
 
71
  *
72
- * @since 2.4.2
73
  * @param array $args : accepted args : {
74
  * @param bool $paged Return current page URL without pagination if false
75
  * @param bool $paged_plural Whether to add pagination for the second or later page.
@@ -82,14 +79,11 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
82
  * @param bool $forceslash Fetch home URL and slash it, always.
83
  * @param int $id The Page or Term ID.
84
  * }
85
- *
86
- * @since 2.0.0
87
- *
88
  * @return string Escape url.
89
  */
90
  public function the_url( $url = '', $args = array() ) {
91
 
92
- if ( $this->the_seo_framework_debug && false === $this->doing_sitemap ) $this->debug_init( __METHOD__, true, $debug_key = microtime( true ), get_defined_vars() );
93
 
94
  $args = $this->reparse_url_args( $args );
95
 
@@ -98,7 +92,7 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
98
  * @since 2.5.2
99
  */
100
  if ( $this->is_feed() )
101
- $url = get_permalink();
102
 
103
  //* Reset cache.
104
  $this->url_slashit = true;
@@ -107,16 +101,11 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
107
 
108
  $path = '';
109
  $scheme = '';
110
-
111
- /**
112
- * Trailing slash the post, or not.
113
- * @since 2.2.4
114
- */
115
  $slashit = true;
116
 
117
- if ( ! $args['home'] && empty( $url ) ) {
118
  /**
119
- * Get url from options
120
  * @since 2.2.9
121
  */
122
  if ( $args['get_custom_field'] && $this->is_singular() ) {
@@ -125,7 +114,7 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
125
  if ( $custom_url ) {
126
  $url = $custom_url;
127
  $this->url_slashit = false;
128
- $parsed_url = wp_parse_url( $custom_url );
129
  $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : 'http';
130
  }
131
  }
@@ -134,25 +123,32 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
134
  $path = $this->generate_url_path( $args );
135
  }
136
 
137
- //* Translate the URL, when possible.
138
- $path = $this->get_translation_path( $path, $args['id'], $args['external'] );
 
 
 
 
 
 
 
 
139
 
140
- //* Domain Mapping canonical URL
141
- if ( empty( $url ) ) {
142
- $wpmu_url = $this->the_url_wpmudev_domainmap( $path, true );
143
- if ( $wpmu_url && is_array( $wpmu_url ) ) {
144
- $url = $wpmu_url[0];
145
- $scheme = $wpmu_url[1];
146
- }
147
- }
 
 
 
148
 
149
- //* Domain Mapping canonical URL
150
- if ( empty( $url ) ) {
151
- $dm_url = $this->the_url_donncha_domainmap( $path, true );
152
- if ( $dm_url && is_array( $dm_url ) ) {
153
- $url = $dm_url[0];
154
- $scheme = $dm_url[1];
155
- }
156
  }
157
 
158
  //* Non-domainmap URL
@@ -161,38 +157,31 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
161
  $this->unset_current_subdomain();
162
 
163
  $url = $this->add_url_host( $path );
164
- $scheme = is_ssl() ? 'https' : 'http';
165
 
166
  $url = $this->add_url_subdomain( $url );
167
  }
168
 
169
- //* URL has been given manually or $args['home'] is true.
170
- if ( ! isset( $scheme ) )
171
- $scheme = is_ssl() ? 'https' : 'http';
172
 
173
  $url = $this->set_url_scheme( $url, $scheme );
174
 
175
  if ( $this->url_slashit ) {
176
- /**
177
- * Slash it only if $slashit is true
178
- * @since 2.2.4
179
- */
180
- if ( $slashit && ! $args['forceslash'] )
181
- $url = user_trailingslashit( $url );
182
-
183
- //* Be careful with the default permalink structure.
184
- if ( $args['forceslash'] )
185
- $url = trailingslashit( $url );
186
  }
187
 
188
  if ( $this->pretty_permalinks ) {
189
- $url = esc_url( $url );
190
  } else {
191
  //* Keep the &'s more readable.
192
- $url = esc_url_raw( $url );
193
  }
194
 
195
- if ( $this->the_seo_framework_debug && false === $this->doing_sitemap ) $this->debug_init( __METHOD__, false, $debug_key, array( 'url_output' => $url ) );
196
 
197
  return $url;
198
  }
@@ -201,19 +190,6 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
201
  * Parse and sanitize url args.
202
  *
203
  * @since 2.4.2
204
- * @since 2.5.0:
205
- * @applies filters the_seo_framework_url_args : {
206
- * @param bool $paged Return current page URL without pagination if false
207
- * @param bool $paged_plural Whether to add pagination for the second or later page.
208
- * @param bool $from_option Get the canonical uri option
209
- * @param object $post The Post Object.
210
- * @param bool $external Whether to fetch the current WP Request or get the permalink by Post Object.
211
- * @param bool $is_term Fetch url for term.
212
- * @param object $term The term object.
213
- * @param bool $home Fetch home URL.
214
- * @param bool $forceslash Fetch home URL and slash it, always.
215
- * @param int $id The Page or Term ID.
216
- * }
217
  *
218
  * @param array $args required The passed arguments.
219
  * @param array $defaults The default arguments.
@@ -225,19 +201,38 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
225
  //* Passing back the defaults reduces the memory usage.
226
  if ( empty( $defaults ) ) {
227
  $defaults = array(
228
- 'paged' => false,
229
- 'paged_plural' => true,
230
- 'get_custom_field' => true,
231
- 'external' => false,
232
- 'is_term' => false,
233
- 'post' => null,
234
- 'term' => null,
235
- 'home' => false,
236
- 'forceslash' => false,
237
- 'id' => $this->get_the_real_ID(),
238
  );
239
 
240
- $defaults = (array) apply_filters( 'the_seo_framework_url_args', $defaults, $args );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  }
242
 
243
  //* Return early if it's only a default args request.
@@ -245,17 +240,17 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
245
  return $defaults;
246
 
247
  //* Array merge doesn't support sanitation. We're simply type casting here.
248
- $args['paged'] = isset( $args['paged'] ) ? (bool) $args['paged'] : $defaults['paged'];
249
- $args['paged_plural'] = isset( $args['paged_plural'] ) ? (bool) $args['paged_plural'] : $defaults['paged_plural'];
250
- $args['get_custom_field'] = isset( $args['get_custom_field'] ) ? (bool) $args['get_custom_field'] : $defaults['get_custom_field'];
251
- $args['external'] = isset( $args['external'] ) ? (bool) $args['external'] : $defaults['external'];
252
- $args['is_term'] = isset( $args['is_term'] ) ? (bool) $args['is_term'] : $defaults['is_term'];
253
- $args['get_custom_field'] = isset( $args['get_custom_field'] ) ? (bool) $args['get_custom_field'] : $defaults['get_custom_field'];
254
- $args['post'] = isset( $args['post'] ) ? (object) $args['post'] : $defaults['post'];
255
- $args['term'] = isset( $args['term'] ) ? (object) $args['term'] : $defaults['term'];
256
- $args['home'] = isset( $args['home'] ) ? (bool) $args['home'] : $defaults['home'];
257
- $args['forceslash'] = isset( $args['forceslash'] ) ? (bool) $args['forceslash'] : $defaults['forceslash'];
258
- $args['id'] = isset( $args['id'] ) ? (int) $args['id'] : $defaults['id'];
259
 
260
  return $args;
261
  }
@@ -291,7 +286,6 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
291
  * Generate URL from arguments.
292
  *
293
  * @since 2.6.0
294
- * @global object $wp
295
  * @NOTE: Handles full path, including home directory.
296
  *
297
  * @param array $args the URL args.
@@ -301,27 +295,26 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
301
 
302
  $args = $this->reparse_url_args( $args );
303
 
304
- if ( $this->is_archive() || $args['is_term'] ) {
305
 
306
  $term = $args['term'];
307
 
308
  //* Term or Taxonomy.
309
  if ( ! isset( $term ) )
310
- $term = get_queried_object();
311
 
312
  if ( isset( $term->taxonomy ) ) {
313
  //* Registered Terms and Taxonomies.
314
  $path = $this->get_relative_term_url( $term, $args );
315
- } elseif ( ! $args['external'] ) {
316
  //* Everything else.
317
- global $wp;
318
- $path = trailingslashit( get_option( 'home' ) ) . $wp->request;
319
  $path = $this->set_url_scheme( $path, 'relative' );
320
  } else {
321
  //* Nothing to see here...
322
  $path = '';
323
  }
324
- } else {
325
 
326
  /**
327
  * Reworked to use the $args['id'] check based on get_the_real_ID.
@@ -329,8 +322,8 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
329
  */
330
  $post_id = isset( $args['post']->ID ) ? $args['post']->ID : $args['id'];
331
 
332
- if ( $this->pretty_permalinks && $post_id && $this->is_singular() ) {
333
- $post = get_post( $post_id );
334
 
335
  //* Don't slash draft links.
336
  if ( isset( $post->post_status ) && ( 'auto-draft' === $post->post_status || 'draft' === $post->post_status ) )
@@ -338,20 +331,17 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
338
  }
339
 
340
  $path = $this->build_singular_relative_url( $post_id, $args );
341
- }
342
-
343
- if ( isset( $path ) )
344
- return $path;
345
 
346
- return '';
347
  }
348
 
349
  /**
350
  * Generates relative URL for the Homepage and Singular Posts.
351
  *
352
  * @since 2.6.5
353
- * @global object $wp
354
  * @NOTE: Handles full path, including home directory.
 
355
  *
356
  * @param int $post_id The ID.
357
  * @param array $args The URL arguments.
@@ -359,53 +349,54 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
359
  */
360
  public function build_singular_relative_url( $post_id = null, $args = array() ) {
361
 
362
- if ( ! isset( $post_id ) ) {
363
  //* We can't fetch the post ID when there's an external request.
364
- if ( $args['external'] )
365
- return '';
366
-
367
- $post_id = $this->get_the_real_ID();
 
368
  }
369
 
370
  $args = $this->reparse_url_args( $args );
371
 
372
  if ( $args['external'] || ! $this->is_front_page() ) {
373
- $url = get_permalink( $post_id );
374
  } elseif ( $this->is_front_page() ) {
375
- $url = get_home_url();
376
  } elseif ( ! $args['external'] ) {
377
- global $wp;
378
-
379
- if ( isset( $wp->request ) )
380
- $url = trailingslashit( get_option( 'home' ) ) . $wp->request;
381
  }
382
 
383
  //* No permalink found.
384
  if ( ! isset( $url ) )
385
  return '';
386
 
387
- $paged = $this->is_singular() ? $this->page() : $this->paged();
388
- $paged = $this->maybe_get_paged( $paged, $args['paged'], $args['paged_plural'] );
 
 
 
 
389
 
390
  if ( $paged ) {
391
  if ( $this->pretty_permalinks ) {
392
  if ( $this->is_singular() ) {
393
- $url = trailingslashit( $url ) . $paged;
394
  } else {
395
- $url = trailingslashit( $url ) . 'page/' . $paged;
396
  }
397
  } else {
398
  if ( $this->is_singular() ) {
399
- $url = add_query_arg( 'page', $paged, $url );
400
  } else {
401
- $url = add_query_arg( 'paged', $paged, $url );
402
  }
403
  }
404
  }
405
 
406
- $path = $this->set_url_scheme( $url, 'relative' );
407
-
408
- return $path;
409
  }
410
 
411
  /**
@@ -421,248 +412,11 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
421
  */
422
  public function add_url_host( $path = '' ) {
423
 
424
- $host = $this->current_host ? $this->current_host : $this->get_home_host();
425
 
426
  $scheme = $host ? 'http://' : '';
427
 
428
- return $url = $scheme . trailingslashit( $host ) . ltrim( $path, ' \\/' );
429
- }
430
-
431
- /**
432
- * Generates relative URL for current post_ID for translation plugins.
433
- *
434
- * @since 2.6.0
435
- * @global object $post
436
- * @NOTE: Handles full path, including home directory.
437
- *
438
- * @param string $path the current URL path.
439
- * @param int $post_id The post ID.
440
- * @param bool $external Whether the request for URL generation is external.
441
- * @return relative Post or Page url.
442
- */
443
- public function get_translation_path( $path = '', $post_id = null, $external = false ) {
444
-
445
- if ( is_object( $post_id ) )
446
- $post_id = isset( $post_id->ID ) ? $post_id->ID : $this->get_the_real_ID();
447
-
448
- if ( is_null( $post_id ) )
449
- $post_id = $this->get_the_real_ID();
450
-
451
- //* WPML support.
452
- if ( $this->is_wpml_active() )
453
- $path = $this->get_relative_wmpl_url( $path, $post_id );
454
-
455
- //* qTranslate X support. Can't work externally as we can't fetch the post's current language.
456
- if ( ! $external && $this->is_qtranslate_active() )
457
- $path = $this->get_relative_qtranslate_url( $path, $post_id );
458
-
459
- return $path;
460
- }
461
-
462
- /**
463
- * Generates qtranslate URL.
464
- *
465
- * @since 2.6.0
466
- * @staticvar int $q_config_mode
467
- * @global array $q_config
468
- * @NOTE: Handles full path, including home directory.
469
- *
470
- * @param string $path The current path.
471
- * @param int $post_id The Post ID. Unused until qTranslate provides external URL forgery.
472
- */
473
- public function get_relative_qtranslate_url( $path = '', $post_id = '' ) {
474
-
475
- //* Reset cache.
476
- $this->url_slashit = true;
477
- $this->unset_current_subdomain();
478
-
479
- static $q_config_mode = null;
480
-
481
- if ( ! isset( $q_config ) ) {
482
- global $q_config;
483
- $q_config_mode = $q_config['url_mode'];
484
- }
485
-
486
- //* If false, change canonical URL for every page.
487
- $hide = isset( $q_config['hide_default_language'] ) ? $q_config['hide_default_language'] : true;
488
-
489
- $current_lang = isset( $q_config['language'] ) ? $q_config['language'] : false;
490
- $default_lang = isset( $q_config['default_language'] ) ? $q_config['default_language'] : false;
491
-
492
- //* Don't to anything on default language when path is hidden.
493
- if ( $hide && $current_lang === $default_lang )
494
- return $path;
495
-
496
- switch ( $q_config_mode ) {
497
- case '1' :
498
- //* Negotiation type query var.
499
-
500
- //* Don't slash it further.
501
- $this->url_slashit = false;
502
-
503
- /**
504
- * Path must have trailing slash for pagination permalinks to work.
505
- * So we remove the query string and add it back with slash.
506
- */
507
- if ( strpos( $path, '?lang=' . $current_lang ) !== false )
508
- $path = str_replace( '?lang=' . $current_lang, '', $path );
509
-
510
- return user_trailingslashit( $path ) . '?lang=' . $current_lang;
511
- break;
512
-
513
- case '2' :
514
- //* Subdirectory
515
- if ( 0 === strpos( $path, '/' . $current_lang . '/' ) )
516
- return $path;
517
- else
518
- return $path = trailingslashit( $current_lang ) . ltrim( $path, ' \\/' );
519
- break;
520
-
521
- case '3' :
522
- //* Notify cache of subdomain addition.
523
- $this->set_current_subdomain( $current_lang );
524
-
525
- //* No need to alter the path.
526
- return $path;
527
- break;
528
-
529
- default :
530
- return $path;
531
- break;
532
- }
533
-
534
- return $path;
535
- }
536
-
537
- /**
538
- * Generate relative WPML url.
539
- *
540
- * @since 2.4.3
541
- * @staticvar bool $gli_exists
542
- * @staticvar string $default_lang
543
- * @global object $sitepress
544
- * @NOTE: Handles full path, including home directory.
545
- *
546
- * @param string $path The current path.
547
- * @param int $post_id The Post ID.
548
- * @return relative path for WPML urls.
549
- */
550
- public function get_relative_wmpl_url( $path = '', $post_id = '' ) {
551
- global $sitepress;
552
-
553
- //* Reset cache.
554
- $this->url_slashit = true;
555
- $this->unset_current_subdomain();
556
-
557
- if ( ! isset( $sitepress ) )
558
- return $path;
559
-
560
- static $gli_exists = null;
561
- if ( is_null( $gli_exists ) )
562
- $gli_exists = function_exists( 'wpml_get_language_information' );
563
-
564
- if ( ! $gli_exists )
565
- return $path;
566
-
567
- if ( empty( $post_id ) )
568
- $post_id = $this->get_the_real_ID();
569
-
570
- //* Cache default language.
571
- static $default_lang = null;
572
- if ( is_null( $default_lang ) )
573
- $default_lang = $sitepress->get_default_language();
574
-
575
- /**
576
- * Applies filters wpml_post_language_details : array|wp_error
577
- *
578
- * ... Somehow WPML thought this would be great and understandable.
579
- * This should be put inside a callable function.
580
- * @since 2.6.0
581
- */
582
- $lang_info = apply_filters( 'wpml_post_language_details', null, $post_id );
583
-
584
- if ( is_wp_error( $lang_info ) ) {
585
- //* Terms and Taxonomies.
586
- $lang_info = array();
587
-
588
- //* Cache the code.
589
- static $lang_code = null;
590
- if ( is_null( $lang_code ) && defined( 'ICL_LANGUAGE_CODE' ) )
591
- $lang_code = ICL_LANGUAGE_CODE;
592
-
593
- $lang_info['language_code'] = $lang_code;
594
- }
595
-
596
- //* If filter isn't used, bail.
597
- if ( ! isset( $lang_info['language_code'] ) )
598
- return $path;
599
-
600
- $current_lang = $lang_info['language_code'];
601
-
602
- //* No need to alter URL if we're on default lang.
603
- if ( $current_lang === $default_lang )
604
- return $path;
605
-
606
- //* Cache negotiation type.
607
- static $negotiation_type = null;
608
- if ( ! isset( $negotiation_type ) )
609
- $negotiation_type = $sitepress->get_setting( 'language_negotiation_type' );
610
-
611
- switch ( $negotiation_type ) {
612
-
613
- case '1' :
614
- //* Subdirectory
615
-
616
- /**
617
- * Might not always work.
618
- * @TODO Fix.
619
- * @priority OMG WTF BBQ
620
- */
621
- $contains_path = strpos( $path, '/' . $current_lang . '/' );
622
- if ( false !== $contains_path && 0 === $contains_path ) {
623
- return $path;
624
- } else {
625
- return $path = trailingslashit( $current_lang ) . ltrim( $path, ' \\/' );
626
- }
627
- break;
628
-
629
- case '2' :
630
- //* Custom domain.
631
-
632
- $langsettings = $sitepress->get_setting( 'language_domains' );
633
- $current_lang_setting = isset( $langsettings[ $current_lang ] ) ? $langsettings[ $current_lang ] : '';
634
-
635
- if ( empty( $current_lang_setting ) )
636
- return $path;
637
-
638
- $current_lang_setting = $this->make_fully_qualified_url( $current_lang_setting );
639
- $parsed = wp_parse_url( $current_lang_setting );
640
-
641
- $this->current_host = isset( $parsed['host'] ) ? $parsed['host'] : '';
642
- $current_path = isset( $parsed['path'] ) ? trailingslashit( $parsed['path'] ) : '';
643
-
644
- return $current_path . $path;
645
- break;
646
-
647
- case '3' :
648
- //* Negotiation type query var.
649
-
650
- //* Don't slash it further.
651
- $this->url_slashit = false;
652
-
653
- /**
654
- * Path must have trailing slash for pagination permalinks to work.
655
- * So we remove the query string and add it back with slash.
656
- */
657
- if ( false !== strpos( $path, '?lang=' . $current_lang ) )
658
- $path = str_replace( '?lang=' . $current_lang, '', $path );
659
-
660
- return user_trailingslashit( $path ) . '?lang=' . $current_lang;
661
- break;
662
-
663
- }
664
-
665
- return $path;
666
  }
667
 
668
  /**
@@ -701,17 +455,17 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
701
  return '';
702
 
703
  if ( is_null( $term ) )
704
- $term = get_queried_object();
705
 
706
  $taxonomy = $term->taxonomy;
707
  $path = $wp_rewrite->get_extra_permastruct( $taxonomy );
708
 
709
  $slug = $term->slug;
710
- $t = get_taxonomy( $taxonomy );
711
 
712
  $paged = $this->maybe_get_paged( $this->paged(), $args['paged'], $args['paged_plural'] );
713
 
714
- if ( empty( $path ) ) {
715
  //* Default permalink structure.
716
 
717
  if ( 'category' === $taxonomy ) {
@@ -728,7 +482,7 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
728
  //* Don't slash it.
729
  $this->url_slashit = false;
730
 
731
- } else {
732
  if ( $t->rewrite['hierarchical'] ) {
733
  $hierarchical_slugs = array();
734
  $ancestors = get_ancestors( $term->term_id, $taxonomy, 'taxonomy' );
@@ -747,37 +501,91 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
747
  }
748
 
749
  if ( $paged )
750
- $path = trailingslashit( $path ) . 'page/' . $paged;
751
 
752
- $path = user_trailingslashit( $path, 'category' );
753
- }
754
 
755
  //* Add plausible domain subdirectories.
756
- $url = trailingslashit( get_option( 'home' ) ) . ltrim( $path, ' \\/' );
757
  $path = $this->set_url_scheme( $url, 'relative' );
758
 
759
  return $path;
760
  }
761
 
762
  /**
763
- * Set url scheme.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
764
  * WordPress core function, without filter.
765
  *
 
 
766
  * @param string $url Absolute url that includes a scheme.
767
  * @param string $scheme optional. Scheme to give $url. Currently 'http', 'https', 'login', 'login_post', 'admin', or 'relative'.
768
  * @param bool $use_filter Whether to parse filters.
769
- *
770
- * @since 2.4.2
771
  * @return string url with chosen scheme.
772
  */
773
  public function set_url_scheme( $url, $scheme = null, $use_filter = true ) {
774
 
775
- if ( ! isset( $scheme ) ) {
776
- $scheme = is_ssl() ? 'https' : 'http';
777
  } elseif ( 'admin' === $scheme || 'login' === $scheme || 'login_post' === $scheme || 'rpc' === $scheme ) {
778
- $scheme = is_ssl() || force_ssl_admin() ? 'https' : 'http';
779
  } elseif ( 'http' !== $scheme && 'https' !== $scheme && 'relative' !== $scheme ) {
780
- $scheme = is_ssl() ? 'https' : 'http';
781
  }
782
 
783
  $url = $this->make_fully_qualified_url( $url );
@@ -822,15 +630,14 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
822
  * @param string $current_scheme the current used scheme.
823
  *
824
  * @since 2.4.2
 
825
  */
826
- $scheme_settings = apply_filters( 'the_seo_framework_canonical_force_scheme', null, $current_scheme );
827
-
828
- /**
829
- * @TODO add options metabox.
830
- * @priority medium 2.6.5+
831
- */
832
 
833
  if ( isset( $scheme_settings ) ) {
 
 
 
834
  if ( 'https' === $scheme_settings || 'http' === $scheme_settings || 'relative' === $scheme_settings ) {
835
  $url = $this->set_url_scheme( $url, $scheme_settings, false );
836
  } elseif ( ! $scheme_settings ) {
@@ -844,242 +651,112 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
844
  }
845
 
846
  /**
847
- * Creates a full canonical URL when WPMUdev Domain Mapping is active from path.
848
  *
849
- * @since 2.3.0
850
- * @since 2.4.0 Added $get_scheme parameter.
851
  *
852
- * @param string $path The post relative path.
853
- * @param bool $get_scheme Output array with scheme.
854
- * @return string|array|void The unescaped URL, the scheme
855
  */
856
- public function the_url_wpmudev_domainmap( $path, $get_scheme = false ) {
857
 
858
- if ( false === $this->is_domainmapping_active() )
859
  return '';
860
 
861
- global $wpdb, $blog_id;
862
-
863
- /**
864
- * Cache revisions. Hexadecimal.
865
- * @since 2.6.0
866
- */
867
- $revision = '1';
868
-
869
- $cache_key = 'wpmudev_mapped_domain_' . $revision . '_' . $blog_id;
870
-
871
- //* Check if the domain is mapped. Store in object cache.
872
- $mapped_domain = $this->object_cache_get( $cache_key );
873
- if ( false === $mapped_domain ) {
874
-
875
- $mapped_domains = $wpdb->get_results( $wpdb->prepare( "SELECT id, domain, is_primary, scheme FROM {$wpdb->base_prefix}domain_mapping WHERE blog_id = %d", $blog_id ), OBJECT );
876
 
877
- $primary_key = 0;
878
- $domain_ids = array();
879
 
880
- foreach ( $mapped_domains as $key => $domain ) {
881
- if ( isset( $domain->is_primary ) && '1' === $domain->is_primary ) {
882
- $primary_key = $key;
883
 
884
- //* We've found the primary key, break loop.
885
- break;
 
886
  } else {
887
- //* Save IDs.
888
- if ( isset( $domain->id ) && $domain->id )
889
- $domain_ids[ $key ] = $domain->id;
890
  }
891
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
892
 
893
- if ( 0 === $primary_key && ! empty( $domain_ids ) ) {
894
- //* No primary ID has been found. Get the one with the lowest ID, which has been added first.
895
- $primary_key = array_keys( $domain_ids, min( $domain_ids ), true );
896
- $primary_key = reset( $primary_key );
897
- }
898
-
899
- //* Set 0, as we check for false to begin with.
900
- $mapped_domain = isset( $mapped_domains[ $primary_key ] ) ? $mapped_domains[ $primary_key ] : 0;
901
-
902
- $this->object_cache_set( $cache_key, $mapped_domain, 3600 );
903
- }
904
-
905
- if ( $mapped_domain ) {
906
 
907
- $domain = isset( $mapped_domain->domain ) ? $mapped_domain->domain : '0';
908
- $scheme = isset( $mapped_domain->scheme ) ? $mapped_domain->scheme : '';
909
 
910
- //* Fallback to is_ssl if no scheme has been found.
911
- if ( '' === $scheme )
912
- $scheme = is_ssl() ? '1' : '0';
913
 
914
- if ( '1' === $scheme ) {
915
- $scheme_full = 'https://';
916
- $scheme = 'https';
917
- } else {
918
- $scheme_full = 'http://';
919
- $scheme = 'http';
920
  }
921
-
922
- //* Put it all together.
923
- $url = trailingslashit( $scheme_full . $domain ) . ltrim( $path, ' \\/' );
924
-
925
- if ( $get_scheme )
926
- return array( $url, $scheme );
927
- else
928
- return $url;
929
  }
930
 
931
- return '';
932
- }
933
-
934
- /**
935
- * Try to get an canonical URL when Donncha Domain Mapping is active.
936
- *
937
- * @since 2.4.0
938
- *
939
- * @param string $path The post relative path.
940
- * @param bool $get_scheme Output array with scheme.
941
- * @return string|array|void The unescaped URL, the scheme
942
- */
943
- public function the_url_donncha_domainmap( $path, $get_scheme = false ) {
944
-
945
- if ( false === $this->is_donncha_domainmapping_active() )
946
  return '';
947
 
948
- global $current_blog;
949
-
950
- $scheme = is_ssl() ? 'https' : 'http';
951
- $url = function_exists( 'domain_mapping_siteurl' ) ? domain_mapping_siteurl( false ) : false;
952
-
953
- $request_uri = '';
954
-
955
- if ( $url && untrailingslashit( $scheme . '://' . $current_blog->domain . $current_blog->path ) !== $url ) {
956
- if ( ( defined( 'VHOST' ) && 'yes' !== VHOST ) || ( defined( 'SUBDOMAIN_INSTALL' ) && false === SUBDOMAIN_INSTALL ) )
957
- $request_uri = str_replace( $current_blog->path, '/', $_SERVER['REQUEST_URI'] );
958
 
959
- $url = trailingslashit( $url . $request_uri ) . ltrim( $path, '\\/ ' );
 
960
 
961
- if ( $get_scheme ) {
962
- return array( $url, $scheme );
 
 
963
  } else {
964
- return $url;
965
  }
966
- }
967
 
968
- return '';
969
- }
970
-
971
- /**
972
- * Generates shortlink URL.
973
- *
974
- * @since 2.2.2
975
- * @global object $wp_query
976
- *
977
- * @param int $post_id The post ID.
978
- * @return string|null Escaped site Shortlink URL.
979
- */
980
- public function get_shortlink( $post_id = 0 ) {
981
-
982
- if ( $this->get_option( 'shortlink_tag' ) ) {
983
-
984
- $path = null;
985
-
986
- if ( false === $this->is_front_page() ) {
987
- if ( $this->is_singular( $post_id ) ) {
988
- if ( 0 === $post_id )
989
- $post_id = $this->get_the_real_ID();
990
-
991
- if ( $post_id ) {
992
- if ( $this->is_static_frontpage( $post_id ) ) {
993
- $path = '';
994
- } else {
995
- //* This will be converted to '?p' later.
996
- $path = '?page_id=' . $post_id;
997
- }
998
- }
999
- } elseif ( $this->is_archive() ) {
1000
- if ( $this->is_category() ) {
1001
- $id = get_queried_object_id();
1002
- $path = '?cat=' . $id;
1003
- } elseif ( $this->is_tag() ) {
1004
- $id = get_queried_object_id();
1005
- $path = '?post_tag=' . $id;
1006
- } elseif ( $this->is_date() ) {
1007
- global $wp_query;
1008
-
1009
- $query = $wp_query->query;
1010
- $var = '';
1011
-
1012
- $first = true;
1013
- foreach ( $query as $key => $val ) {
1014
- $var .= $first ? '?' : '&';
1015
- $var .= $key . '=' . $val;
1016
- $first = false;
1017
- }
1018
-
1019
- $path = $var;
1020
- } elseif ( $this->is_author() ) {
1021
- $id = get_queried_object_id();
1022
- $path = '?author=' . $id;
1023
- } elseif ( $this->is_tax() ) {
1024
- //* Generate shortlink for object type and slug.
1025
- $object = get_queried_object();
1026
-
1027
- $t = isset( $object->taxonomy ) ? urlencode( $object->taxonomy ) : '';
1028
-
1029
- if ( $t ) {
1030
- $slug = isset( $object->slug ) ? urlencode( $object->slug ) : '';
1031
-
1032
- if ( $slug )
1033
- $path = '?' . $t . '=' . $slug;
1034
- }
1035
- }
1036
- }
1037
  }
 
1038
 
1039
- if ( isset( $path ) ) {
1040
- //* Path always has something. So we can safely use .='&' instead of add_query_arg().
1041
-
1042
- if ( 0 === $post_id )
1043
- $post_id = $this->get_the_real_ID();
1044
-
1045
- $url = $this->the_url_from_cache( '', $post_id, false, false, false );
1046
- $query = parse_url( $url, PHP_URL_QUERY );
1047
-
1048
- $additions = '';
1049
- if ( isset( $query ) ) {
1050
- if ( false !== strpos( $query, '&' ) ) {
1051
- $query = explode( '&', $query );
1052
- } else {
1053
- $query = array( $query );
1054
- }
1055
-
1056
- foreach ( $query as $arg ) {
1057
- if ( false === strpos( $path, $arg ) )
1058
- $additions .= '&' . $arg;
1059
- }
1060
- }
1061
-
1062
- //* We used 'page_id' to determine duplicates. Now we can convert it to a shorter form.
1063
- $path = str_replace( 'page_id=', 'p=', $path );
1064
-
1065
- if ( $this->is_archive() || $this->is_home() ) {
1066
- $paged = $this->maybe_get_paged( $this->paged(), false, true );
1067
- if ( $paged )
1068
- $path .= '&paged=' . $paged;
1069
- } else {
1070
- $page = $this->maybe_get_paged( $this->page(), false, true );
1071
- if ( $page )
1072
- $path .= '&page=' . $page;
1073
- }
1074
-
1075
- $home_url = $this->the_home_url_from_cache( true );
1076
- $url = $home_url . $path . $additions;
1077
 
1078
- return esc_url_raw( $url );
1079
- }
 
 
 
 
 
 
1080
  }
1081
 
1082
- return '';
 
 
 
1083
  }
1084
 
1085
  /**
@@ -1137,35 +814,35 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
1137
  if ( $paged < 1 )
1138
  $paged = 1;
1139
 
1140
- $prev = get_pagenum_link( $paged, false );
1141
  } elseif ( 'next' === $prev_next && $paged < $GLOBALS['wp_query']->max_num_pages ) {
1142
 
1143
  if ( ! $paged )
1144
  $paged = 1;
1145
  $paged = intval( $paged ) + 1;
1146
 
1147
- $next = get_pagenum_link( $paged, false );
1148
  }
1149
  }
1150
  }
1151
 
1152
  if ( $prev )
1153
- return esc_url_raw( $prev );
1154
 
1155
  if ( $next )
1156
- return esc_url_raw( $next );
1157
 
1158
  return '';
1159
  }
1160
 
1161
  /**
1162
- * Return the special URL of a paged post.
1163
  *
1164
  * Taken from _wp_link_page() in WordPress core, but instead of anchor markup, just return the URL.
1165
  * Also adds WPMUdev Domain Mapping support and is optimized for speed.
1166
  *
1167
- * @uses $this->the_url_from_cache();
1168
  * @since 2.2.4
 
1169
  *
1170
  * @param int $i The page number to generate the URL from.
1171
  * @param int $post_id The post ID
@@ -1179,10 +856,10 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
1179
  if ( empty( $post_id ) )
1180
  $post_id = $this->get_the_real_ID();
1181
 
1182
- if ( 1 === $i ) {
1183
  $url = $this->the_url_from_cache( '', $post_id, false, $from_option, false );
1184
- } else {
1185
- $post = get_post( $post_id );
1186
 
1187
  $urlfromcache = $this->the_url_from_cache( '', $post_id, false, $from_option, false );
1188
 
@@ -1214,23 +891,23 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
1214
  if ( isset( $query_arg ) )
1215
  $urlfromcache = $urlfromcache . '?' . $query_arg;
1216
 
1217
- $url = add_query_arg( 'page', $i, $urlfromcache );
1218
  } elseif ( $this->is_static_frontpage( $post_id ) ) {
1219
  global $wp_rewrite;
1220
 
1221
- $url = trailingslashit( $urlfromcache ) . user_trailingslashit( $wp_rewrite->pagination_base . '/' . $i, 'single_paged' );
1222
 
1223
  //* Add back query arg if removed.
1224
  if ( isset( $query_arg ) )
1225
  $url = $url . '?' . $query_arg;
1226
  } else {
1227
- $url = trailingslashit( $urlfromcache ) . user_trailingslashit( $i, 'single_paged' );
1228
 
1229
  //* Add back query arg if removed.
1230
  if ( isset( $query_arg ) )
1231
  $url = $url . '?' . $query_arg;
1232
  }
1233
- }
1234
 
1235
  return $url;
1236
  }
@@ -1249,7 +926,7 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
1249
 
1250
  //* Add subdomain, if set.
1251
  if ( $subdomain = $this->get_current_subdomain() ) {
1252
- $parsed_url = wp_parse_url( $url );
1253
  $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : 'http';
1254
  $url = str_replace( $scheme . '://', '', $url );
1255
 
@@ -1275,7 +952,7 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
1275
  static $subdomain = null;
1276
 
1277
  if ( isset( $set ) )
1278
- $subdomain = esc_html( $set );
1279
 
1280
  if ( $unset )
1281
  unset( $subdomain );
@@ -1360,10 +1037,11 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
1360
  */
1361
  public function make_fully_qualified_url( $url ) {
1362
 
1363
- if ( '//' === substr( $url, 0, 2 ) )
1364
  $url = 'http:' . $url;
1365
- elseif ( 'http' !== substr( $url, 0, 4 ) )
1366
  $url = 'http://' . $url;
 
1367
 
1368
  return $url;
1369
  }
@@ -1384,7 +1062,7 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
1384
  if ( isset( $cache ) )
1385
  return $cache;
1386
 
1387
- $parsed_url = wp_parse_url( get_option( 'home' ) );
1388
 
1389
  $host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : '';
1390
 
@@ -1408,7 +1086,7 @@ class AutoDescription_Generate_Url extends AutoDescription_Generate_Title {
1408
 
1409
  $path = '';
1410
 
1411
- $parsed_url = wp_parse_url( get_option( 'home' ) );
1412
 
1413
  if ( ! empty( $parsed_url['path'] ) && $path = ltrim( $parsed_url['path'], ' \\/' ) )
1414
  $path = '/' . $path;
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Generate_Url
28
  *
29
  * Generates URL and permalink SEO data based on content.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Generate_Url extends Generate_Title {
34
 
35
  /**
36
  * Whether to slash the url or not. Used when query vars are in url.
37
  *
38
  * @since 2.6.0
39
+ * @since 2.8.0 : Made public.
40
  *
41
  * @var bool Whether to slash the url.
42
  */
43
+ public $url_slashit;
44
 
45
  /**
46
  * Holds current HTTP host.
47
  *
48
  * @since 2.6.5
49
+ * @since 2.8.0 : Made public.
50
  *
51
  * @var string The current HTTP host.
52
  */
53
+ public $current_host;
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  /**
56
  * Constructor, load parent constructor and set up variables.
57
  */
58
+ protected function __construct() {
59
  parent::__construct();
60
  }
61
 
62
  /**
63
  * Creates canonical URL.
64
  *
65
+ * @since 2.0.0
66
+ * @since 2.4.2 : Refactored arguments
67
+ * @since 2.8.0 : No longer tolerates $id as Post object.
68
  *
69
+ * @param string $url the url
70
  * @param array $args : accepted args : {
71
  * @param bool $paged Return current page URL without pagination if false
72
  * @param bool $paged_plural Whether to add pagination for the second or later page.
79
  * @param bool $forceslash Fetch home URL and slash it, always.
80
  * @param int $id The Page or Term ID.
81
  * }
 
 
 
82
  * @return string Escape url.
83
  */
84
  public function the_url( $url = '', $args = array() ) {
85
 
86
+ $this->the_seo_framework_debug && false === $this->doing_sitemap and $this->debug_init( __METHOD__, true, $debug_key = microtime( true ), get_defined_vars() );
87
 
88
  $args = $this->reparse_url_args( $args );
89
 
92
  * @since 2.5.2
93
  */
94
  if ( $this->is_feed() )
95
+ $url = \get_permalink();
96
 
97
  //* Reset cache.
98
  $this->url_slashit = true;
101
 
102
  $path = '';
103
  $scheme = '';
 
 
 
 
 
104
  $slashit = true;
105
 
106
+ if ( false === $args['home'] && empty( $url ) ) {
107
  /**
108
+ * Get URL from options.
109
  * @since 2.2.9
110
  */
111
  if ( $args['get_custom_field'] && $this->is_singular() ) {
114
  if ( $custom_url ) {
115
  $url = $custom_url;
116
  $this->url_slashit = false;
117
+ $parsed_url = \wp_parse_url( $custom_url );
118
  $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : 'http';
119
  }
120
  }
123
  $path = $this->generate_url_path( $args );
124
  }
125
 
126
+ /**
127
+ * Applies filters 'the_seo_framework_url_path' : array
128
+ *
129
+ * @since 2.8.0
130
+ *
131
+ * @param string $path the URL path.
132
+ * @param int $id The current post, page or term ID.
133
+ * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
134
+ */
135
+ $path = (string) \apply_filters( 'the_seo_framework_url_path', $path, $args['id'], $args['external'] );
136
 
137
+ /**
138
+ * Applies filters 'the_seo_framework_sanitize_redirect_url' : array
139
+ *
140
+ * @since 2.8.0
141
+ *
142
+ * @param array : { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
143
+ * @param string $path the URL path.
144
+ * @param int $id The current post, page or term ID.
145
+ * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
146
+ */
147
+ $filter = (array) \apply_filters( 'the_seo_framework_url_output_args', array(), $path, $args['id'], $args['external'] );
148
 
149
+ if ( $filter ) {
150
+ $url = $filter['url'];
151
+ $scheme = $filter['scheme'];
 
 
 
 
152
  }
153
 
154
  //* Non-domainmap URL
157
  $this->unset_current_subdomain();
158
 
159
  $url = $this->add_url_host( $path );
160
+ $scheme = $this->is_ssl() ? 'https' : 'http';
161
 
162
  $url = $this->add_url_subdomain( $url );
163
  }
164
 
165
+ $scheme = $scheme ?: $this->get_prefered_scheme();
 
 
166
 
167
  $url = $this->set_url_scheme( $url, $scheme );
168
 
169
  if ( $this->url_slashit ) {
170
+ if ( $args['forceslash'] ) {
171
+ $url = \trailingslashit( $url );
172
+ } elseif ( $slashit ) {
173
+ $url = \user_trailingslashit( $url );
174
+ }
 
 
 
 
 
175
  }
176
 
177
  if ( $this->pretty_permalinks ) {
178
+ $url = \esc_url( $url );
179
  } else {
180
  //* Keep the &'s more readable.
181
+ $url = \esc_url_raw( $url );
182
  }
183
 
184
+ $this->the_seo_framework_debug && false === $this->doing_sitemap and $this->debug_init( __METHOD__, false, $debug_key, array( 'url_output' => $url ) );
185
 
186
  return $url;
187
  }
190
  * Parse and sanitize url args.
191
  *
192
  * @since 2.4.2
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  *
194
  * @param array $args required The passed arguments.
195
  * @param array $defaults The default arguments.
201
  //* Passing back the defaults reduces the memory usage.
202
  if ( empty( $defaults ) ) {
203
  $defaults = array(
204
+ 'paged' => false,
205
+ 'paged_plural' => true,
206
+ 'get_custom_field' => true,
207
+ 'external' => false,
208
+ 'is_term' => false,
209
+ 'post' => null,
210
+ 'term' => null,
211
+ 'home' => false,
212
+ 'forceslash' => false,
213
+ 'id' => $this->get_the_real_ID(),
214
  );
215
 
216
+ /**
217
+ * @applies filters the_seo_framework_url_args : {
218
+ * @param bool $paged Return current page URL without pagination if false
219
+ * @param bool $paged_plural Whether to add pagination for the second or later page.
220
+ * @param bool $from_option Get the canonical uri option
221
+ * @param object $post The Post Object.
222
+ * @param bool $external Whether to fetch the current WP Request or get the permalink by Post Object.
223
+ * @param bool $is_term Fetch url for term.
224
+ * @param object $term The term object.
225
+ * @param bool $home Fetch home URL.
226
+ * @param bool $forceslash Fetch home URL and slash it, always.
227
+ * @param int $id The Page or Term ID.
228
+ * }
229
+ *
230
+ * @since 2.5.0
231
+ *
232
+ * @param array $defaults The url defaults.
233
+ * @param array $args The input args.
234
+ */
235
+ $defaults = (array) \apply_filters( 'the_seo_framework_url_args', $defaults, $args );
236
  }
237
 
238
  //* Return early if it's only a default args request.
240
  return $defaults;
241
 
242
  //* Array merge doesn't support sanitation. We're simply type casting here.
243
+ $args['paged'] = isset( $args['paged'] ) ? (bool) $args['paged'] : $defaults['paged'];
244
+ $args['paged_plural'] = isset( $args['paged_plural'] ) ? (bool) $args['paged_plural'] : $defaults['paged_plural'];
245
+ $args['get_custom_field'] = isset( $args['get_custom_field'] ) ? (bool) $args['get_custom_field'] : $defaults['get_custom_field'];
246
+ $args['external'] = isset( $args['external'] ) ? (bool) $args['external'] : $defaults['external'];
247
+ $args['is_term'] = isset( $args['is_term'] ) ? (bool) $args['is_term'] : $defaults['is_term'];
248
+ $args['get_custom_field'] = isset( $args['get_custom_field'] ) ? (bool) $args['get_custom_field'] : $defaults['get_custom_field'];
249
+ $args['post'] = isset( $args['post'] ) ? (object) $args['post'] : $defaults['post'];
250
+ $args['term'] = isset( $args['term'] ) ? (object) $args['term'] : $defaults['term'];
251
+ $args['home'] = isset( $args['home'] ) ? (bool) $args['home'] : $defaults['home'];
252
+ $args['forceslash'] = isset( $args['forceslash'] ) ? (bool) $args['forceslash'] : $defaults['forceslash'];
253
+ $args['id'] = isset( $args['id'] ) ? (int) $args['id'] : $defaults['id'];
254
 
255
  return $args;
256
  }
286
  * Generate URL from arguments.
287
  *
288
  * @since 2.6.0
 
289
  * @NOTE: Handles full path, including home directory.
290
  *
291
  * @param array $args the URL args.
295
 
296
  $args = $this->reparse_url_args( $args );
297
 
298
+ if ( $this->is_archive() || $args['is_term'] ) :
299
 
300
  $term = $args['term'];
301
 
302
  //* Term or Taxonomy.
303
  if ( ! isset( $term ) )
304
+ $term = \get_queried_object();
305
 
306
  if ( isset( $term->taxonomy ) ) {
307
  //* Registered Terms and Taxonomies.
308
  $path = $this->get_relative_term_url( $term, $args );
309
+ } elseif ( ! $args['external'] && isset( $GLOBALS['wp']->request ) ) {
310
  //* Everything else.
311
+ $path = \trailingslashit( \get_option( 'home' ) ) . $GLOBALS['wp']->request;
 
312
  $path = $this->set_url_scheme( $path, 'relative' );
313
  } else {
314
  //* Nothing to see here...
315
  $path = '';
316
  }
317
+ else :
318
 
319
  /**
320
  * Reworked to use the $args['id'] check based on get_the_real_ID.
322
  */
323
  $post_id = isset( $args['post']->ID ) ? $args['post']->ID : $args['id'];
324
 
325
+ if ( $this->pretty_permalinks && $post_id && $this->is_singular( $post_id ) ) {
326
+ $post = \get_post( $post_id );
327
 
328
  //* Don't slash draft links.
329
  if ( isset( $post->post_status ) && ( 'auto-draft' === $post->post_status || 'draft' === $post->post_status ) )
331
  }
332
 
333
  $path = $this->build_singular_relative_url( $post_id, $args );
334
+ endif;
 
 
 
335
 
336
+ return $path;
337
  }
338
 
339
  /**
340
  * Generates relative URL for the Homepage and Singular Posts.
341
  *
342
  * @since 2.6.5
 
343
  * @NOTE: Handles full path, including home directory.
344
+ * @since 2.8.0: Continues on empty post ID. Handles it as HomePage.
345
  *
346
  * @param int $post_id The ID.
347
  * @param array $args The URL arguments.
349
  */
350
  public function build_singular_relative_url( $post_id = null, $args = array() ) {
351
 
352
+ if ( empty( $post_id ) ) {
353
  //* We can't fetch the post ID when there's an external request.
354
+ if ( $args['external'] ) {
355
+ $post_id = 0;
356
+ } else {
357
+ $post_id = $this->get_the_real_ID();
358
+ }
359
  }
360
 
361
  $args = $this->reparse_url_args( $args );
362
 
363
  if ( $args['external'] || ! $this->is_front_page() ) {
364
+ $url = \get_permalink( $post_id );
365
  } elseif ( $this->is_front_page() ) {
366
+ $url = \get_home_url();
367
  } elseif ( ! $args['external'] ) {
368
+ if ( isset( $GLOBALS['wp']->request ) )
369
+ $url = \trailingslashit( \get_option( 'home' ) ) . $GLOBALS['wp']->request;
 
 
370
  }
371
 
372
  //* No permalink found.
373
  if ( ! isset( $url ) )
374
  return '';
375
 
376
+ $paged = false;
377
+
378
+ if ( false === $args['external'] ) {
379
+ $paged = $this->is_singular() ? $this->page() : $this->paged();
380
+ $paged = $this->maybe_get_paged( $paged, $args['paged'], $args['paged_plural'] );
381
+ }
382
 
383
  if ( $paged ) {
384
  if ( $this->pretty_permalinks ) {
385
  if ( $this->is_singular() ) {
386
+ $url = \trailingslashit( $url ) . $paged;
387
  } else {
388
+ $url = \trailingslashit( $url ) . 'page/' . $paged;
389
  }
390
  } else {
391
  if ( $this->is_singular() ) {
392
+ $url = \add_query_arg( 'page', $paged, $url );
393
  } else {
394
+ $url = \add_query_arg( 'paged', $paged, $url );
395
  }
396
  }
397
  }
398
 
399
+ return $this->set_url_scheme( $url, 'relative' );
 
 
400
  }
401
 
402
  /**
412
  */
413
  public function add_url_host( $path = '' ) {
414
 
415
+ $host = $this->current_host ?: $this->get_home_host();
416
 
417
  $scheme = $host ? 'http://' : '';
418
 
419
+ return $url = $scheme . \trailingslashit( $host ) . ltrim( $path, ' \\/' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  }
421
 
422
  /**
455
  return '';
456
 
457
  if ( is_null( $term ) )
458
+ $term = \get_queried_object();
459
 
460
  $taxonomy = $term->taxonomy;
461
  $path = $wp_rewrite->get_extra_permastruct( $taxonomy );
462
 
463
  $slug = $term->slug;
464
+ $t = \get_taxonomy( $taxonomy );
465
 
466
  $paged = $this->maybe_get_paged( $this->paged(), $args['paged'], $args['paged_plural'] );
467
 
468
+ if ( empty( $path ) ) :
469
  //* Default permalink structure.
470
 
471
  if ( 'category' === $taxonomy ) {
482
  //* Don't slash it.
483
  $this->url_slashit = false;
484
 
485
+ else :
486
  if ( $t->rewrite['hierarchical'] ) {
487
  $hierarchical_slugs = array();
488
  $ancestors = get_ancestors( $term->term_id, $taxonomy, 'taxonomy' );
501
  }
502
 
503
  if ( $paged )
504
+ $path = \trailingslashit( $path ) . 'page/' . $paged;
505
 
506
+ $path = \user_trailingslashit( $path, 'category' );
507
+ endif;
508
 
509
  //* Add plausible domain subdirectories.
510
+ $url = \trailingslashit( get_option( 'home' ) ) . ltrim( $path, ' \\/' );
511
  $path = $this->set_url_scheme( $url, 'relative' );
512
 
513
  return $path;
514
  }
515
 
516
  /**
517
+ * Returns preferred $url scheme.
518
+ * Can be automatically be detected.
519
+ *
520
+ * @since 2.8.0
521
+ * @staticvar string $scheme
522
+ *
523
+ * @return string The preferred URl scheme.
524
+ */
525
+ public function get_prefered_scheme() {
526
+
527
+ static $scheme;
528
+
529
+ if ( isset( $scheme ) )
530
+ return $scheme;
531
+
532
+ switch ( $this->get_option( 'canonical_scheme' ) ) :
533
+ case 'https' :
534
+ $scheme = 'https';
535
+ break;
536
+
537
+ case 'http' :
538
+ $scheme = 'http';
539
+ break;
540
+
541
+ case 'automatic' :
542
+ default :
543
+ $scheme = $this->is_ssl() ? 'https' : 'http';
544
+ break;
545
+ endswitch;
546
+
547
+ /**
548
+ * Applies filters 'the_seo_framework_preferred_url_scheme' : string
549
+ *
550
+ * @since 2.8.0
551
+ *
552
+ * @param string $scheme The current URL scheme.
553
+ */
554
+ return $scheme = (string) apply_filters( 'the_seo_framework_preferred_url_scheme', $scheme );
555
+ }
556
+
557
+ /**
558
+ * Sets URL to preferred URL scheme.
559
+ * Does not sanitize output.
560
+ *
561
+ * @since 2.8.0
562
+ *
563
+ * @param string $url The URL to set scheme for.
564
+ * @return string The URL with the preferred scheme.
565
+ */
566
+ public function set_preferred_url_scheme( $url ) {
567
+ return $this->set_url_scheme( $url, $this->get_prefered_scheme(), false );
568
+ }
569
+
570
+ /**
571
+ * Sets URL scheme for input URL.
572
  * WordPress core function, without filter.
573
  *
574
+ * @since 2.4.2
575
+ *
576
  * @param string $url Absolute url that includes a scheme.
577
  * @param string $scheme optional. Scheme to give $url. Currently 'http', 'https', 'login', 'login_post', 'admin', or 'relative'.
578
  * @param bool $use_filter Whether to parse filters.
 
 
579
  * @return string url with chosen scheme.
580
  */
581
  public function set_url_scheme( $url, $scheme = null, $use_filter = true ) {
582
 
583
+ if ( empty( $scheme ) ) {
584
+ $scheme = $this->is_ssl() ? 'https' : 'http';
585
  } elseif ( 'admin' === $scheme || 'login' === $scheme || 'login_post' === $scheme || 'rpc' === $scheme ) {
586
+ $scheme = $this->is_ssl() || \force_ssl_admin() ? 'https' : 'http';
587
  } elseif ( 'http' !== $scheme && 'https' !== $scheme && 'relative' !== $scheme ) {
588
+ $scheme = $this->is_ssl() ? 'https' : 'http';
589
  }
590
 
591
  $url = $this->make_fully_qualified_url( $url );
630
  * @param string $current_scheme the current used scheme.
631
  *
632
  * @since 2.4.2
633
+ * @since 2.8.0 Deprecated.
634
  */
635
+ $scheme_settings = \apply_filters( 'the_seo_framework_canonical_force_scheme', null, $current_scheme );
 
 
 
 
 
636
 
637
  if ( isset( $scheme_settings ) ) {
638
+
639
+ $this->_deprecated_filter( 'the_seo_framework_canonical_force_scheme', '2.8.0', 'the_seo_framework_preferred_url_scheme' );
640
+
641
  if ( 'https' === $scheme_settings || 'http' === $scheme_settings || 'relative' === $scheme_settings ) {
642
  $url = $this->set_url_scheme( $url, $scheme_settings, false );
643
  } elseif ( ! $scheme_settings ) {
651
  }
652
 
653
  /**
654
+ * Generates shortlink URL.
655
  *
656
+ * @since 2.2.2
 
657
  *
658
+ * @param int $post_id The post ID.
659
+ * @return string|null Escaped site Shortlink URL.
 
660
  */
661
+ public function get_shortlink( $post_id = 0 ) {
662
 
663
+ if ( ! $this->get_option( 'shortlink_tag' ) )
664
  return '';
665
 
666
+ if ( $this->is_front_page() )
667
+ return '';
 
 
 
 
 
 
 
 
 
 
 
 
 
668
 
669
+ $path = '';
 
670
 
671
+ if ( $this->is_singular( $post_id ) ) {
672
+ if ( 0 === $post_id )
673
+ $post_id = $this->get_the_real_ID();
674
 
675
+ if ( $post_id ) {
676
+ if ( $this->is_static_frontpage( $post_id ) ) {
677
+ $path = '';
678
  } else {
679
+ //* This will be converted to '?p' later.
680
+ $path = '?page_id=' . $post_id;
 
681
  }
682
  }
683
+ } elseif ( $this->is_archive() ) {
684
+ if ( $this->is_category() ) {
685
+ $id = \get_queried_object_id();
686
+ $path = '?cat=' . $id;
687
+ } elseif ( $this->is_tag() ) {
688
+ $id = \get_queried_object_id();
689
+ $path = '?post_tag=' . $id;
690
+ } elseif ( $this->is_date() && isset( $GLOBALS['wp_query']->query ) ) {
691
+ $query = $GLOBALS['wp_query']->query;
692
+ $var = '';
693
+
694
+ $first = true;
695
+ foreach ( $query as $key => $val ) {
696
+ $var .= $first ? '?' : '&';
697
+ $var .= $key . '=' . $val;
698
+ $first = false;
699
+ }
700
 
701
+ $path = $var;
702
+ } elseif ( $this->is_author() ) {
703
+ $id = \get_queried_object_id();
704
+ $path = '?author=' . $id;
705
+ } elseif ( $this->is_tax() ) {
706
+ //* Generate shortlink for object type and slug.
707
+ $object = \get_queried_object();
 
 
 
 
 
 
708
 
709
+ $t = isset( $object->taxonomy ) ? urlencode( $object->taxonomy ) : '';
 
710
 
711
+ if ( $t ) {
712
+ $slug = isset( $object->slug ) ? urlencode( $object->slug ) : '';
 
713
 
714
+ if ( $slug )
715
+ $path = '?' . $t . '=' . $slug;
716
+ }
 
 
 
717
  }
 
 
 
 
 
 
 
 
718
  }
719
 
720
+ if ( empty( $path ) )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
721
  return '';
722
 
723
+ if ( 0 === $post_id )
724
+ $post_id = $this->get_the_real_ID();
 
 
 
 
 
 
 
 
725
 
726
+ $url = $this->the_url_from_cache( '', $post_id, false, false, false );
727
+ $query = parse_url( $url, PHP_URL_QUERY );
728
 
729
+ $additions = '';
730
+ if ( isset( $query ) ) {
731
+ if ( false !== strpos( $query, '&' ) ) {
732
+ $query = explode( '&', $query );
733
  } else {
734
+ $query = array( $query );
735
  }
 
736
 
737
+ foreach ( $query as $arg ) {
738
+ if ( false === strpos( $path, $arg ) )
739
+ $additions .= '&' . $arg;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
740
  }
741
+ }
742
 
743
+ //* We used 'page_id' to determine duplicates. Now we can convert it to a shorter form.
744
+ $path = str_replace( 'page_id=', 'p=', $path );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
745
 
746
+ if ( $this->is_archive() || $this->is_home() ) {
747
+ $paged = $this->maybe_get_paged( $this->paged(), false, true );
748
+ if ( $paged )
749
+ $path .= '&paged=' . $paged;
750
+ } else {
751
+ $page = $this->maybe_get_paged( $this->page(), false, true );
752
+ if ( $page )
753
+ $path .= '&page=' . $page;
754
  }
755
 
756
+ $home_url = $this->the_home_url_from_cache( true );
757
+ $url = $home_url . $path . $additions;
758
+
759
+ return \esc_url_raw( $url );
760
  }
761
 
762
  /**
814
  if ( $paged < 1 )
815
  $paged = 1;
816
 
817
+ $prev = \get_pagenum_link( $paged, false );
818
  } elseif ( 'next' === $prev_next && $paged < $GLOBALS['wp_query']->max_num_pages ) {
819
 
820
  if ( ! $paged )
821
  $paged = 1;
822
  $paged = intval( $paged ) + 1;
823
 
824
+ $next = \get_pagenum_link( $paged, false );
825
  }
826
  }
827
  }
828
 
829
  if ( $prev )
830
+ return $this->set_preferred_url_scheme( \esc_url_raw( $prev ) );
831
 
832
  if ( $next )
833
+ return $this->set_preferred_url_scheme( \esc_url_raw( $next ) );
834
 
835
  return '';
836
  }
837
 
838
  /**
839
+ * Returns the special URL of a paged post.
840
  *
841
  * Taken from _wp_link_page() in WordPress core, but instead of anchor markup, just return the URL.
842
  * Also adds WPMUdev Domain Mapping support and is optimized for speed.
843
  *
 
844
  * @since 2.2.4
845
+ * @uses $this->the_url_from_cache();
846
  *
847
  * @param int $i The page number to generate the URL from.
848
  * @param int $post_id The post ID
856
  if ( empty( $post_id ) )
857
  $post_id = $this->get_the_real_ID();
858
 
859
+ if ( 1 === $i ) :
860
  $url = $this->the_url_from_cache( '', $post_id, false, $from_option, false );
861
+ else :
862
+ $post = \get_post( $post_id );
863
 
864
  $urlfromcache = $this->the_url_from_cache( '', $post_id, false, $from_option, false );
865
 
891
  if ( isset( $query_arg ) )
892
  $urlfromcache = $urlfromcache . '?' . $query_arg;
893
 
894
+ $url = \add_query_arg( 'page', $i, $urlfromcache );
895
  } elseif ( $this->is_static_frontpage( $post_id ) ) {
896
  global $wp_rewrite;
897
 
898
+ $url = \trailingslashit( $urlfromcache ) . \user_trailingslashit( $wp_rewrite->pagination_base . '/' . $i, 'single_paged' );
899
 
900
  //* Add back query arg if removed.
901
  if ( isset( $query_arg ) )
902
  $url = $url . '?' . $query_arg;
903
  } else {
904
+ $url = \trailingslashit( $urlfromcache ) . \user_trailingslashit( $i, 'single_paged' );
905
 
906
  //* Add back query arg if removed.
907
  if ( isset( $query_arg ) )
908
  $url = $url . '?' . $query_arg;
909
  }
910
+ endif;
911
 
912
  return $url;
913
  }
926
 
927
  //* Add subdomain, if set.
928
  if ( $subdomain = $this->get_current_subdomain() ) {
929
+ $parsed_url = \wp_parse_url( $url );
930
  $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : 'http';
931
  $url = str_replace( $scheme . '://', '', $url );
932
 
952
  static $subdomain = null;
953
 
954
  if ( isset( $set ) )
955
+ $subdomain = \esc_html( $set );
956
 
957
  if ( $unset )
958
  unset( $subdomain );
1037
  */
1038
  public function make_fully_qualified_url( $url ) {
1039
 
1040
+ if ( '//' === substr( $url, 0, 2 ) ) {
1041
  $url = 'http:' . $url;
1042
+ } elseif ( 'http' !== substr( $url, 0, 4 ) ) {
1043
  $url = 'http://' . $url;
1044
+ }
1045
 
1046
  return $url;
1047
  }
1062
  if ( isset( $cache ) )
1063
  return $cache;
1064
 
1065
+ $parsed_url = \wp_parse_url( \get_option( 'home' ) );
1066
 
1067
  $host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : '';
1068
 
1086
 
1087
  $path = '';
1088
 
1089
+ $parsed_url = \wp_parse_url( \get_option( 'home' ) );
1090
 
1091
  if ( ! empty( $parsed_url['path'] ) && $path = ltrim( $parsed_url['path'], ' \\/' ) )
1092
  $path = '/' . $path;
inc/classes/generate.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,33 +23,19 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Generate
23
  *
24
  * Generates general SEO data based on content.
25
  *
26
- * @since 2.1.6
27
  */
28
- class AutoDescription_Generate extends AutoDescription_TermData {
29
-
30
- /**
31
- * Unserializing instances of this class is forbidden.
32
- */
33
- private function __wakeup() { }
34
-
35
- /**
36
- * Handle unapproachable invoked methods.
37
- */
38
- public function __call( $name, $arguments ) {
39
- parent::__call( $name, $arguments );
40
- }
41
 
42
  /**
43
  * Constructor, load parent constructor
44
  */
45
- public function __construct() {
46
  parent::__construct();
47
  }
48
 
@@ -50,9 +43,9 @@ class AutoDescription_Generate extends AutoDescription_TermData {
50
  * Output the `index`, `follow`, `noodp`, `noydir`, `noarchive` robots meta code in array
51
  *
52
  * @since 2.2.2
53
- *
54
- * @uses genesis_get_seo_option() Get SEO setting value.
55
- * @uses genesis_get_custom_field() Get custom field value.
56
  *
57
  * @global object $wp_query
58
  *
@@ -146,13 +139,17 @@ class AutoDescription_Generate extends AutoDescription_TermData {
146
  $meta['noindex'] = empty( $meta['noindex'] ) && $this->get_custom_field( '_genesis_noindex' ) ? 'noindex' : $meta['noindex'];
147
  $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->get_custom_field( '_genesis_nofollow' ) ? 'nofollow' : $meta['nofollow'];
148
  $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->get_custom_field( '_genesis_noarchive' ) ? 'noarchive' : $meta['noarchive'];
 
 
 
 
149
  }
150
 
151
  /**
152
  * Applies filters the_seo_framework_robots_meta_array : array
153
  * @since 2.6.0
154
  */
155
- $meta = (array) apply_filters( 'the_seo_framework_robots_meta_array', $meta );
156
 
157
  //* Strip empty array items
158
  $meta = array_filter( $meta );
@@ -163,13 +160,13 @@ class AutoDescription_Generate extends AutoDescription_TermData {
163
  /**
164
  * Returns cached and parsed separator option.
165
  *
166
- * @param string $type The separator type. Used to fetch option.
167
- * @param bool $escape Escape the separator.
168
- *
169
  * @staticvar array $sepcache The separator cache.
170
  * @staticvar array $sep_esc The escaped separator cache.
171
  *
172
- * @since 2.3.9
 
 
173
  */
174
  public function get_separator( $type = 'title', $escape = true ) {
175
 
@@ -203,7 +200,7 @@ class AutoDescription_Generate extends AutoDescription_TermData {
203
  }
204
 
205
  if ( $escape ) {
206
- return $sep_esc[ $type ][ $escape ] = esc_html( $sepcache[ $type ] );
207
  } else {
208
  return $sep_esc[ $type ][ $escape ] = $sepcache[ $type ];
209
  }
@@ -212,9 +209,9 @@ class AutoDescription_Generate extends AutoDescription_TermData {
212
  /**
213
  * Fetches blogname.
214
  *
 
215
  * @staticvar string $blogname
216
  *
217
- * @since 2.5.2
218
  * @return string $blogname The trimmed and sanitized blogname.
219
  */
220
  public function get_blogname() {
@@ -224,15 +221,15 @@ class AutoDescription_Generate extends AutoDescription_TermData {
224
  if ( isset( $blogname ) )
225
  return $blogname;
226
 
227
- return $blogname = trim( get_bloginfo( 'name', 'display' ) );
228
  }
229
 
230
  /**
231
  * Fetch blog description.
232
  *
 
233
  * @staticvar string $description
234
  *
235
- * @since 2.5.2
236
  * @return string $blogname The trimmed and sanitized blog description.
237
  */
238
  public function get_blogdescription() {
@@ -242,25 +239,24 @@ class AutoDescription_Generate extends AutoDescription_TermData {
242
  if ( isset( $description ) )
243
  return $description;
244
 
245
- $description = trim( get_bloginfo( 'description', 'display' ) );
246
 
247
- return $description = $description ? $description : $this->untitled();
248
  }
249
 
250
  /**
251
  * Matches WordPress locales.
252
  * If not matched, it will calculate a locale.
253
  *
254
- * @param $match the locale to match. Defaults to WordPress locale.
255
- *
256
  * @since 2.5.2
257
  *
 
258
  * @return string Facebook acceptable OG locale.
259
  */
260
  public function fetch_locale( $match = '' ) {
261
 
262
  if ( empty( $match ) )
263
- $match = get_locale();
264
 
265
  $match_len = strlen( $match );
266
  $valid_locales = (array) $this->fb_locales();
@@ -290,7 +286,7 @@ class AutoDescription_Generate extends AutoDescription_TermData {
290
  $locale_keys = (array) $this->language_keys();
291
 
292
  //* No need to do for each loop. Just match the keys.
293
- if ( $key = array_search( $match, $locale_keys ) ) {
294
  //* Fetch the corresponding value from key within the language array.
295
  return $valid_locales[ $key ];
296
  }
@@ -323,15 +319,104 @@ class AutoDescription_Generate extends AutoDescription_TermData {
323
  return $type;
324
  }
325
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  /**
327
  * Generates the Twitter Card type. When there's an image found, it will
328
  * take the said option. Otherwise, it will fall back to 'summary'.
329
  *
330
  * @since 2.7.0
 
331
  *
332
  * @return string The Twitter Card type.
333
  */
334
  public function generate_twitter_card_type() {
335
- return $this->get_image_from_cache() ? $this->get_option( 'twitter_card' ) : 'summary';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  }
337
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Generate
28
  *
29
  * Generates general SEO data based on content.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Generate extends Term_Data {
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  /**
36
  * Constructor, load parent constructor
37
  */
38
+ protected function __construct() {
39
  parent::__construct();
40
  }
41
 
43
  * Output the `index`, `follow`, `noodp`, `noydir`, `noarchive` robots meta code in array
44
  *
45
  * @since 2.2.2
46
+ * @since 2.2.4 Added robots SEO settings check.
47
+ * @since 2.2.8 Added check for empty archives.
48
+ * @since 2.8.0 Added check for protected/private posts.
49
  *
50
  * @global object $wp_query
51
  *
139
  $meta['noindex'] = empty( $meta['noindex'] ) && $this->get_custom_field( '_genesis_noindex' ) ? 'noindex' : $meta['noindex'];
140
  $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->get_custom_field( '_genesis_nofollow' ) ? 'nofollow' : $meta['nofollow'];
141
  $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->get_custom_field( '_genesis_noarchive' ) ? 'noarchive' : $meta['noarchive'];
142
+
143
+ if ( $this->is_protected( $this->get_the_real_ID() ) ) {
144
+ $meta['noindex'] = 'noindex';
145
+ }
146
  }
147
 
148
  /**
149
  * Applies filters the_seo_framework_robots_meta_array : array
150
  * @since 2.6.0
151
  */
152
+ $meta = (array) \apply_filters( 'the_seo_framework_robots_meta_array', $meta );
153
 
154
  //* Strip empty array items
155
  $meta = array_filter( $meta );
160
  /**
161
  * Returns cached and parsed separator option.
162
  *
163
+ * @since 2.3.9
 
 
164
  * @staticvar array $sepcache The separator cache.
165
  * @staticvar array $sep_esc The escaped separator cache.
166
  *
167
+ * @param string $type The separator type. Used to fetch option.
168
+ * @param bool $escape Escape the separator.
169
+ * @return string The separator.
170
  */
171
  public function get_separator( $type = 'title', $escape = true ) {
172
 
200
  }
201
 
202
  if ( $escape ) {
203
+ return $sep_esc[ $type ][ $escape ] = \esc_html( $sepcache[ $type ] );
204
  } else {
205
  return $sep_esc[ $type ][ $escape ] = $sepcache[ $type ];
206
  }
209
  /**
210
  * Fetches blogname.
211
  *
212
+ * @since 2.5.2
213
  * @staticvar string $blogname
214
  *
 
215
  * @return string $blogname The trimmed and sanitized blogname.
216
  */
217
  public function get_blogname() {
221
  if ( isset( $blogname ) )
222
  return $blogname;
223
 
224
+ return $blogname = trim( \get_bloginfo( 'name', 'display' ) );
225
  }
226
 
227
  /**
228
  * Fetch blog description.
229
  *
230
+ * @since 2.5.2
231
  * @staticvar string $description
232
  *
 
233
  * @return string $blogname The trimmed and sanitized blog description.
234
  */
235
  public function get_blogdescription() {
239
  if ( isset( $description ) )
240
  return $description;
241
 
242
+ $description = trim( \get_bloginfo( 'description', 'display' ) );
243
 
244
+ return $description = $description ?: $this->untitled();
245
  }
246
 
247
  /**
248
  * Matches WordPress locales.
249
  * If not matched, it will calculate a locale.
250
  *
 
 
251
  * @since 2.5.2
252
  *
253
+ * @param $match the locale to match. Defaults to WordPress locale.
254
  * @return string Facebook acceptable OG locale.
255
  */
256
  public function fetch_locale( $match = '' ) {
257
 
258
  if ( empty( $match ) )
259
+ $match = \get_locale();
260
 
261
  $match_len = strlen( $match );
262
  $valid_locales = (array) $this->fb_locales();
286
  $locale_keys = (array) $this->language_keys();
287
 
288
  //* No need to do for each loop. Just match the keys.
289
+ if ( $key = array_search( $match, $locale_keys, true ) ) {
290
  //* Fetch the corresponding value from key within the language array.
291
  return $valid_locales[ $key ];
292
  }
319
  return $type;
320
  }
321
 
322
+ /**
323
+ * Returns OG Type
324
+ *
325
+ * @since 2.8.0
326
+ * @staticvar string $type
327
+ *
328
+ * @return string
329
+ */
330
+ public function get_og_type() {
331
+
332
+ static $type = null;
333
+
334
+ if ( isset( $type ) )
335
+ return $type;
336
+
337
+ /**
338
+ * Applies filters 'the_seo_framework_ogtype_output' : string
339
+ * @since 2.3.0
340
+ * @since 2.7.0 Added output within filter.
341
+ */
342
+ return $type = (string) \apply_filters( 'the_seo_framework_ogtype_output', $this->generate_og_type(), $this->get_the_real_ID() );
343
+ }
344
+
345
  /**
346
  * Generates the Twitter Card type. When there's an image found, it will
347
  * take the said option. Otherwise, it will fall back to 'summary'.
348
  *
349
  * @since 2.7.0
350
+ * @since 2.8.2 : Now considers description output.
351
  *
352
  * @return string The Twitter Card type.
353
  */
354
  public function generate_twitter_card_type() {
355
+
356
+ if ( $this->get_image_from_cache() ) {
357
+
358
+ $option = $this->get_option( 'twitter_card' );
359
+
360
+ //* Photo will always work with an image.
361
+ if ( 'photo' === $option )
362
+ return 'photo';
363
+
364
+ //* Only output 'summary' or 'summary_large_image' if there's a description.
365
+ if ( $this->description_from_cache( true ) )
366
+ return trim( \esc_attr( $option ) );
367
+
368
+ //* Output photo otherwise.
369
+ return 'photo';
370
+ }
371
+
372
+ if ( $this->description_from_cache( true ) )
373
+ return 'summary';
374
+
375
+ return '';
376
+ }
377
+
378
+ /**
379
+ * List of title separators.
380
+ *
381
+ * @since 2.6.0
382
+ *
383
+ * @todo add filter.
384
+ * @todo check if filter can propagate within all functions.
385
+ *
386
+ * @return array Title separators.
387
+ */
388
+ public function get_separator_list() {
389
+ return array(
390
+ 'pipe' => '|',
391
+ 'dash' => '-',
392
+ 'ndash' => '&ndash;',
393
+ 'mdash' => '&mdash;',
394
+ 'bull' => '&bull;',
395
+ 'middot' => '&middot;',
396
+ 'lsaquo' => '&lsaquo;',
397
+ 'rsaquo' => '&rsaquo;',
398
+ 'frasl' => '&frasl;',
399
+ 'laquo' => '&laquo;',
400
+ 'raquo' => '&raquo;',
401
+ 'le' => '&le;',
402
+ 'ge' => '&ge;',
403
+ 'lt' => '&lt;',
404
+ 'gt' => '&gt;',
405
+ );
406
+ }
407
+
408
+ /**
409
+ * Returns array of Twitter Card Types
410
+ *
411
+ * @since 2.6.0
412
+ *
413
+ * @return array Twitter Card types.
414
+ */
415
+ public function get_twitter_card_types() {
416
+ return array(
417
+ 'summary' => 'summary',
418
+ 'summary_large_image' => 'summary-large-image',
419
+ 'photo' => 'photo',
420
+ );
421
  }
422
  }
inc/classes/init.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,16 +23,14 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Init
23
  *
24
  * Outputs all data in front-end header
25
  *
26
- * @since 2.1.6
27
  */
28
- class AutoDescription_Init extends AutoDescription_Query {
29
 
30
  /**
31
  * Allow object caching through a filter.
@@ -36,76 +41,224 @@ class AutoDescription_Init extends AutoDescription_Query {
36
  */
37
  protected $use_object_cache = true;
38
 
39
- /**
40
- * Unserializing instances of this class is forbidden.
41
- */
42
- private function __wakeup() { }
43
-
44
- /**
45
- * Handle unapproachable invoked methods.
46
- */
47
- public function __call( $name, $arguments ) {
48
- parent::__call( $name, $arguments );
49
- }
50
-
51
  /**
52
  * Constructor. Initializes actions and loads parent constructor.
53
  */
54
- public function __construct() {
55
  parent::__construct();
56
 
57
- add_action( 'init', array( $this, 'autodescription_run' ), 1 );
58
- add_action( 'template_redirect', array( $this, 'custom_field_redirect' ) );
 
 
 
59
 
60
  /**
61
  * Applies filters 'the_seo_framework_use_object_cache' : bool
62
  * @since 2.4.3
 
63
  */
64
- $this->use_object_cache = (bool) apply_filters( 'the_seo_framework_use_object_cache', true );
65
 
 
 
 
 
 
 
66
  }
67
 
68
  /**
69
  * Runs the plugin on the front-end.
70
  *
71
  * @since 1.0.0
 
 
72
  */
73
  public function autodescription_run() {
 
 
74
 
75
- /**
76
- * Don't run in admin.
77
- * Don't do anything on preview either.
78
- * @since 2.2.4
79
- */
80
- if ( $this->is_admin() || $this->is_preview() )
 
 
 
81
  return;
82
 
83
- $this->init_actions();
84
- $this->init_filters();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  }
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  /**
89
  * Initializes front-end actions.
 
90
  *
91
  * @since 2.5.2
92
  */
93
- protected function init_actions() {
 
 
94
 
95
  //* Remove canonical header tag from WP
96
- remove_action( 'wp_head', 'rel_canonical' );
 
97
  //* Remove shortlink.
98
- remove_action( 'wp_head', 'wp_shortlink_wp_head' );
 
99
  //* Remove adjecent rel tags.
100
- remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head' );
 
101
  //* Earlier removal of the generator tag. Doesn't require filter.
102
- remove_action( 'wp_head', 'wp_generator' );
103
 
104
- if ( $this->is_theme( 'genesis' ) ) {
105
- add_action( 'genesis_meta', array( $this, 'html_output' ), 5 );
106
- } else {
107
- add_action( 'wp_head', array( $this, 'html_output' ), 1 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  }
 
 
 
 
 
 
 
109
  }
110
 
111
  /**
@@ -113,30 +266,30 @@ class AutoDescription_Init extends AutoDescription_Query {
113
  *
114
  * @since 2.5.2
115
  */
116
- protected function init_filters() {
 
 
 
117
 
118
  //* Removes all pre_get_document_title filters.
119
- remove_all_filters( 'pre_get_document_title', false );
120
 
121
  //* New WordPress 4.4.0 filter. Hurray! It's also much faster :)
122
- add_filter( 'pre_get_document_title', array( $this, 'title_from_cache' ), 10 );
123
  //* Override AnsPress Theme Title
124
- add_filter( 'ap_title', array( $this, 'title_from_cache' ), 99, 1 );
125
- //* Override bbPress title
126
- add_filter( 'bbp_title', array( $this, 'title_from_cache' ), 99, 3 );
127
  //* Override Woo Themes Title
128
- add_filter( 'woo_title', array( $this, 'title_from_cache' ), 99 );
129
 
130
  /**
131
  * Applies filters 'the_seo_framework_manipulate_title' : boolean
132
  * Disables the title tag manipulation on old themes.
133
  * @since 2.4.1
134
  */
135
- if ( (bool) apply_filters( 'the_seo_framework_manipulate_title', true ) ) {
136
  //* Override WordPress Title
137
- add_filter( 'wp_title', array( $this, 'title_from_cache' ), 9, 3 );
138
  }
139
-
140
  }
141
 
142
  /**
@@ -157,23 +310,28 @@ class AutoDescription_Init extends AutoDescription_Query {
157
  $functions = array();
158
 
159
  /**
 
 
160
  * Applies filters 'the_seo_framework_before_output' : array after functions output
161
  * Applies filters 'the_seo_framework_after_output' : array after functions output
 
 
 
 
162
  */
163
  $filter_tag = $before ? 'the_seo_framework_before_output' : 'the_seo_framework_after_output';
164
- $filter = (array) apply_filters( $filter_tag, $functions );
165
 
166
- $functions = wp_parse_args( $args, $filter );
167
 
168
- if ( $functions && is_array( $functions ) ) {
169
- foreach ( $functions as $function ) {
170
  $arguments = isset( $function['args'] ) ? $function['args'] : '';
171
 
172
  if ( isset( $function['callback'] ) )
173
  $output .= $this->call_function( $function['callback'], '2.2.6', $arguments );
174
-
175
- }
176
- }
177
 
178
  return $output;
179
  }
@@ -182,10 +340,11 @@ class AutoDescription_Init extends AutoDescription_Query {
182
  * Echos the header meta and scripts.
183
  *
184
  * @since 1.0.0
 
185
  */
186
  public function html_output() {
187
 
188
- do_action( 'the_seo_framework_do_before_output' );
189
 
190
  /**
191
  * Start the timer here. I know it doesn't calculate the initiation of
@@ -194,43 +353,30 @@ class AutoDescription_Init extends AutoDescription_Query {
194
  * This function takes the most time anyway.
195
  */
196
  $init_start = microtime( true );
197
- $memory_start = $this->the_seo_framework_debug ? $this->profile( false, false, 'memory', 'html_output' ) : 0;
198
 
199
- /**
200
- * Cache key buster
201
- * Hexadecimal revision, e.g. 0, 1, 2, e, f,
202
- *
203
- * @busted to '2' @version 2.5.2.1
204
- */
205
- $revision = '2';
206
- $the_id = $this->get_the_real_ID();
207
- $key = $this->generate_cache_key( $the_id ) . $revision;
208
-
209
- /**
210
- * Give each paged pages/archives a different cache key.
211
- * @since 2.2.6
212
- */
213
- $page = (string) $this->page();
214
- $paged = (string) $this->paged();
215
-
216
- $cache_key = 'seo_framework_output_' . $key . '_' . $paged . '_' . $page;
217
 
218
- $output = $this->object_cache_get( $cache_key );
219
- if ( false === $output ) {
220
 
221
  $robots = $this->robots();
222
 
223
  /**
224
  * Applies filters 'the_seo_framework_pre' : string
225
- * Adds content before the output.
226
  * @since 2.6.0
227
  */
228
- $before = (string) apply_filters( 'the_seo_framework_pre', '' );
229
 
230
  $before_actions = $this->header_actions( '', true );
231
 
232
  //* Limit processing on 404 or search
233
- if ( $this->is_404() || $this->is_search() ) {
234
  $output = $this->og_locale()
235
  . $this->og_type()
236
  . $this->og_title()
@@ -240,9 +386,8 @@ class AutoDescription_Init extends AutoDescription_Query {
240
  . $this->google_site_output()
241
  . $this->bing_site_output()
242
  . $this->yandex_site_output()
243
- . $this->pint_site_output()
244
- ;
245
- } else {
246
  $output = $this->the_description()
247
  . $this->og_image()
248
  . $this->og_locale()
@@ -269,63 +414,62 @@ class AutoDescription_Init extends AutoDescription_Query {
269
  . $this->google_site_output()
270
  . $this->bing_site_output()
271
  . $this->yandex_site_output()
272
- . $this->pint_site_output()
273
- ;
274
- }
275
 
276
  $after_actions = $this->header_actions( '', false );
277
 
278
  /**
279
  * Applies filters 'the_seo_framework_pro' : string
280
- * Adds content before the output.
281
  * @since 2.6.0
282
  */
283
- $after = (string) apply_filters( 'the_seo_framework_pro', '' );
284
 
285
  /**
286
  * Applies filters 'the_seo_framework_generator_tag' : String generator tag content.
287
  * @since 2.0.1
288
  * @see https://wordpress.org/plugins/generator-the-seo-framework/ For an alternative.
289
  */
290
- $generator = (string) apply_filters( 'the_seo_framework_generator_tag', '' );
291
 
292
- if ( '' !== $generator )
293
- $generator = '<meta name="generator" content="' . esc_attr( $generator ) . '" />' . "\r\n";
294
 
295
  $output = $robots . $before . $before_actions . $output . $after_actions . $after . $generator;
296
 
297
- $this->object_cache_set( $cache_key, $output, 86400 );
298
- }
299
 
300
  /**
301
  * Applies filters 'the_seo_framework_indicator' : Boolean
302
  * Whether to show the indicator in HTML.
303
  * @since 2.0.0
304
  */
305
- $indicator = (bool) apply_filters( 'the_seo_framework_indicator', true );
306
 
307
  $indicatorbefore = '';
308
  $indicatorafter = '';
309
 
310
- if ( $indicator ) {
311
 
312
  /**
313
  * Applies filters 'the_seo_framework_indicator_timing' : Boolean
314
  * Whether to show the hidden generation time in HTML.
315
  * @since 2.4.0
316
  */
317
- $timer = (bool) apply_filters( 'the_seo_framework_indicator_timing', true );
318
 
319
  /**
320
  * Applies filters 'sybre_waaijer_<3' : Boolean
321
  * Whether to show the hidden author name in HTML.
322
  * @since 2.4.0
323
  */
324
- $sybre = (bool) apply_filters( 'sybre_waaijer_<3', true );
325
 
326
- $start = esc_html__( 'Start The Seo Framework', 'autodescription' );
327
- $end = esc_html__( 'End The Seo Framework', 'autodescription' );
328
- $me = $sybre ? ' ' . esc_html__( 'by Sybre Waaijer', 'autodescription' ) : '';
329
 
330
  $indicatorbefore = '<!-- ' . $start . $me . ' -->' . "\r\n";
331
 
@@ -334,54 +478,183 @@ class AutoDescription_Init extends AutoDescription_Query {
334
  * @since 2.4.0
335
  */
336
  if ( $timer ) {
337
- $memory = $this->the_seo_framework_debug ? ' | ' . number_format( $this->profile( false, true, 'memory', 'html_output' ) / 1024, 2 ) . ' kiB' : '';
338
- $indicatorafter = '<!-- ' . $end . $me . ' | ' . number_format( microtime( true ) - $init_start, 5 ) . 's' . $memory . ' -->' . "\r\n";
339
  } else {
340
  $indicatorafter = '<!-- ' . $end . $me . ' -->' . "\r\n";
341
  }
342
- }
343
 
344
  $output = "\r\n" . $indicatorbefore . $output . $indicatorafter . "\r\n";
345
 
346
- do_action( 'the_seo_framework_do_after_output' );
347
-
348
  //* Already escaped.
349
  echo $output;
350
 
 
 
351
  }
352
 
353
  /**
354
  * Redirects singular page to an alternate URL.
355
  *
356
  * @since 2.0.9
 
357
  *
358
  * @return void early on non-singular pages.
359
  */
360
  public function custom_field_redirect() {
361
 
362
- //* Prevent redirect from options on uneditable pages.
363
- if ( false === $this->is_singular() || $this->is_admin() )
364
- return;
365
 
366
- $url = $this->get_custom_field( 'redirect' );
367
 
368
- if ( $url ) {
 
 
 
 
369
 
370
- $allow_external = $this->allow_external_redirect();
371
- $scheme = null;
372
 
373
  if ( false === $allow_external ) {
374
  $url = $this->set_url_scheme( $url, 'relative' );
375
  $url = $this->add_url_host( $url );
376
- $scheme = is_ssl() ? 'https' : 'http';
377
 
378
- wp_safe_redirect( esc_url_raw( $url, array( $scheme ) ), 301 );
379
  exit;
380
  }
381
 
382
- //* @TODO set scheme filter, adjustable through (multisite) extensions?
383
- wp_redirect( esc_url_raw( $url ), 301 );
384
  exit;
385
  }
386
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Init
28
  *
29
  * Outputs all data in front-end header
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Init extends Query {
34
 
35
  /**
36
  * Allow object caching through a filter.
41
  */
42
  protected $use_object_cache = true;
43
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  /**
45
  * Constructor. Initializes actions and loads parent constructor.
46
  */
47
+ protected function __construct() {
48
  parent::__construct();
49
 
50
+ /**
51
+ * Applies filters 'the_seo_framework_load_options' : Boolean Allows the options page to be removed
52
+ * @since 2.2.2
53
+ */
54
+ $this->load_options = (bool) \apply_filters( 'the_seo_framework_load_options', true );
55
 
56
  /**
57
  * Applies filters 'the_seo_framework_use_object_cache' : bool
58
  * @since 2.4.3
59
+ * @since 2.8.0 : Uses method $this->use_object_cache() as default.
60
  */
61
+ $this->use_object_cache = (bool) \apply_filters( 'the_seo_framework_use_object_cache', $this->use_object_cache() );
62
 
63
+ //* Determines Whether we're using pretty permalinks.
64
+ $this->pretty_permalinks = '' !== $this->permalink_structure();
65
+
66
+ \add_action( 'init', array( $this, 'init_the_seo_framework' ), 0 );
67
+
68
+ $this->load_early_compat_files();
69
  }
70
 
71
  /**
72
  * Runs the plugin on the front-end.
73
  *
74
  * @since 1.0.0
75
+ * @since 2.8.0 Silently deprecated. Displaying legacy roots.
76
+ * @deprecated
77
  */
78
  public function autodescription_run() {
79
+ $this->init_the_seo_framework();
80
+ }
81
 
82
+ /**
83
+ * Initializes the plugin actions and filters.
84
+ *
85
+ * @since 2.8.0
86
+ */
87
+ public function init_the_seo_framework() {
88
+
89
+ //* Don't initialize cache or cause other issues on preview.
90
+ if ( $this->is_preview() )
91
  return;
92
 
93
+ \do_action( 'the_seo_framework_init' );
94
+
95
+ $this->init_global_actions();
96
+ $this->init_global_filters();
97
+
98
+ if ( $this->is_admin() ) {
99
+ $this->init_admin_actions();
100
+ } else {
101
+ $this->init_front_end_actions();
102
+ $this->init_front_end_filters();
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Initializes the plugin front- and back-end actions.
108
+ *
109
+ * @since 2.8.0
110
+ */
111
+ public function init_global_actions() {
112
+
113
+ if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
114
+ $this->init_cron_actions();
115
+ }
116
+
117
+ //* Add query strings for sitemap rewrite.
118
+ \add_action( 'init', array( $this, 'rewrite_rule_sitemap' ), 1 );
119
+
120
+ //* Enqueue sitemap rewrite flush
121
+ \add_action( 'shutdown', array( $this, 'maybe_flush_rewrite' ), 999 );
122
+ }
123
+
124
+ /**
125
+ * Initializes the plugin front- and back-end filters.
126
+ *
127
+ * @since 2.8.0
128
+ */
129
+ public function init_global_filters() {
130
+
131
+ //* Add query strings for sitemap rewrite.
132
+ \add_filter( 'query_vars', array( $this, 'enqueue_sitemap_query_vars' ), 1, 1 );
133
+ }
134
+
135
+ /**
136
+ * Initializes cron actions.
137
+ *
138
+ * @since 2.8.0
139
+ */
140
+ public function init_cron_actions() {
141
+
142
+ //* Flush post cache.
143
+ $this->init_post_cache_actions();
144
 
145
  }
146
 
147
+ /**
148
+ * Initializes Admin Menu actions.
149
+ *
150
+ * @since 2.7.0
151
+ */
152
+ public function init_admin_actions() {
153
+
154
+ \do_action( 'the_seo_framework_admin_init' );
155
+
156
+ //* Initialize caching actions.
157
+ $this->init_admin_caching_actions();
158
+
159
+ //* Save post data.
160
+ \add_action( 'save_post', array( $this, 'inpost_seo_save' ), 1, 2 );
161
+
162
+ //* Enqueues admin scripts.
163
+ \add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ), 0, 1 );
164
+
165
+ //* Add plugin links to the plugin activation page.
166
+ \add_filter( 'plugin_action_links_' . THE_SEO_FRAMEWORK_PLUGIN_BASENAME, array( $this, 'plugin_action_links' ), 10, 2 );
167
+
168
+ //* Initialize post states.
169
+ \add_action( 'current_screen', array( $this, 'post_state' ) );
170
+
171
+ if ( $this->is_option_checked( 'display_seo_bar_tables' ) ) {
172
+ //* Initialize columns.
173
+ \add_action( 'current_screen', array( $this, 'init_columns' ) );
174
+
175
+ //* Ajax handlers for columns.
176
+ \add_action( 'wp_ajax_add-tag', array( $this, 'init_columns_ajax' ), -1 );
177
+ }
178
+
179
+ if ( $this->load_options ) {
180
+ // Enqueue i18n defaults.
181
+ \add_action( 'admin_init', array( $this, 'enqueue_page_defaults' ), 1 );
182
+
183
+ //* Set up site settings and save/reset them
184
+ \add_action( 'admin_init', array( $this, 'register_settings' ), 5 );
185
+
186
+ //* Load the SEO admin page content and handlers.
187
+ \add_action( 'admin_init', array( $this, 'settings_init' ), 10 );
188
+
189
+ //* Update site options at plugin update.
190
+ \add_action( 'admin_init', array( $this, 'site_updated_plugin_option' ), 30 );
191
+
192
+ //* Enqueue Inpost meta boxes.
193
+ \add_action( 'add_meta_boxes', array( $this, 'add_inpost_seo_box_init' ), 5 );
194
+
195
+ //* Enqueue Taxonomy meta output.
196
+ \add_action( 'current_screen', array( $this, 'add_taxonomy_seo_box_init' ), 10 );
197
+
198
+ // Add menu links and register $this->seo_settings_page_hook
199
+ \add_action( 'admin_menu', array( $this, 'add_menu_link' ) );
200
+
201
+ // Set up notices
202
+ \add_action( 'admin_notices', array( $this, 'notices' ) );
203
+
204
+ // Load nessecary assets
205
+ \add_action( 'admin_init', array( $this, 'load_assets' ) );
206
+
207
+ //* Admin AJAX for counter options.
208
+ \add_action( 'wp_ajax_the_seo_framework_update_counter', array( $this, 'wp_ajax_update_counter_type' ) );
209
+
210
+ \add_filter( 'removable_query_args', array( $this, 'add_removable_query_args' ) );
211
+ }
212
+ }
213
+
214
  /**
215
  * Initializes front-end actions.
216
+ * Disregards other SEO plugins, the meta output does look at detection.
217
  *
218
  * @since 2.5.2
219
  */
220
+ protected function init_front_end_actions() {
221
+
222
+ \do_action( 'the_seo_framework_front_init' );
223
 
224
  //* Remove canonical header tag from WP
225
+ \remove_action( 'wp_head', 'rel_canonical' );
226
+
227
  //* Remove shortlink.
228
+ \remove_action( 'wp_head', 'wp_shortlink_wp_head' );
229
+
230
  //* Remove adjecent rel tags.
231
+ \remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head' );
232
+
233
  //* Earlier removal of the generator tag. Doesn't require filter.
234
+ \remove_action( 'wp_head', 'wp_generator' );
235
 
236
+ /**
237
+ * @since 2.7.0 Changed priority from 999 to 9999.
238
+ * Now uses another method. Was: 'search_filter'.
239
+ */
240
+ \add_action( 'pre_get_posts', array( $this, 'adjust_search_filter' ), 9999, 1 );
241
+
242
+ /**
243
+ * Outputs sitemap or stylesheet on request.
244
+ *
245
+ * Adding a higher priority will cause a trailing slash to be added.
246
+ * We need to be in front of the queue to prevent this from happening.
247
+ */
248
+ \add_action( 'template_redirect', array( $this, 'maybe_output_sitemap' ), 1 );
249
+ \add_action( 'template_redirect', array( $this, 'maybe_output_sitemap_stylesheet' ), 1 );
250
+
251
+ if ( $this->is_singular() ) {
252
+ //* Initialize 301 redirects.
253
+ \add_action( 'template_redirect', array( $this, 'custom_field_redirect' ) );
254
  }
255
+
256
+ if ( $this->is_feed() ) {
257
+ //* Initialize feed alteration.
258
+ \add_action( 'template_redirect', array( $this, 'init_feed' ) );
259
+ }
260
+
261
+ \add_action( 'wp_head', array( $this, 'html_output' ), 1 );
262
  }
263
 
264
  /**
266
  *
267
  * @since 2.5.2
268
  */
269
+ protected function init_front_end_filters() {
270
+
271
+ //* Edit the robots.txt file
272
+ \add_filter( 'robots_txt', array( $this, 'robots_txt' ), 10, 2 );
273
 
274
  //* Removes all pre_get_document_title filters.
275
+ \remove_all_filters( 'pre_get_document_title', false );
276
 
277
  //* New WordPress 4.4.0 filter. Hurray! It's also much faster :)
278
+ \add_filter( 'pre_get_document_title', array( $this, 'title_from_cache' ), 10 );
279
  //* Override AnsPress Theme Title
280
+ \add_filter( 'ap_title', array( $this, 'title_from_cache' ), 99, 1 );
 
 
281
  //* Override Woo Themes Title
282
+ \add_filter( 'woo_title', array( $this, 'title_from_cache' ), 99 );
283
 
284
  /**
285
  * Applies filters 'the_seo_framework_manipulate_title' : boolean
286
  * Disables the title tag manipulation on old themes.
287
  * @since 2.4.1
288
  */
289
+ if ( (bool) \apply_filters( 'the_seo_framework_manipulate_title', true ) ) {
290
  //* Override WordPress Title
291
+ \add_filter( 'wp_title', array( $this, 'title_from_cache' ), 9, 3 );
292
  }
 
293
  }
294
 
295
  /**
310
  $functions = array();
311
 
312
  /**
313
+ * @since 2.2.6
314
+ *
315
  * Applies filters 'the_seo_framework_before_output' : array after functions output
316
  * Applies filters 'the_seo_framework_after_output' : array after functions output
317
+ * @param array $functions {
318
+ * 'callback' => string|array The function to call.
319
+ * 'args' => scalar|array Arguments. When array, each key is a new argument.
320
+ * }
321
  */
322
  $filter_tag = $before ? 'the_seo_framework_before_output' : 'the_seo_framework_after_output';
323
+ $filter = (array) \apply_filters( $filter_tag, $functions );
324
 
325
+ $functions = \wp_parse_args( $args, $filter );
326
 
327
+ if ( $functions && is_array( $functions ) ) :
328
+ foreach ( $functions as $function ) :
329
  $arguments = isset( $function['args'] ) ? $function['args'] : '';
330
 
331
  if ( isset( $function['callback'] ) )
332
  $output .= $this->call_function( $function['callback'], '2.2.6', $arguments );
333
+ endforeach;
334
+ endif;
 
335
 
336
  return $output;
337
  }
340
  * Echos the header meta and scripts.
341
  *
342
  * @since 1.0.0
343
+ * @since 2.8.0 Cache is busted on each new release.
344
  */
345
  public function html_output() {
346
 
347
+ \do_action( 'the_seo_framework_do_before_output' );
348
 
349
  /**
350
  * Start the timer here. I know it doesn't calculate the initiation of
353
  * This function takes the most time anyway.
354
  */
355
  $init_start = microtime( true );
 
356
 
357
+ if ( $this->use_object_cache ) {
358
+ $cache_key = $this->get_meta_output_cache_key();
359
+ $output = $this->object_cache_get( $cache_key );
360
+ } else {
361
+ $cache_key = '';
362
+ $output = false;
363
+ }
 
 
 
 
 
 
 
 
 
 
 
364
 
365
+ if ( false === $output ) :
 
366
 
367
  $robots = $this->robots();
368
 
369
  /**
370
  * Applies filters 'the_seo_framework_pre' : string
371
+ * Adds content before the output and caches it through Object caching.
372
  * @since 2.6.0
373
  */
374
+ $before = (string) \apply_filters( 'the_seo_framework_pre', '' );
375
 
376
  $before_actions = $this->header_actions( '', true );
377
 
378
  //* Limit processing on 404 or search
379
+ if ( $this->is_404() || $this->is_search() ) :
380
  $output = $this->og_locale()
381
  . $this->og_type()
382
  . $this->og_title()
386
  . $this->google_site_output()
387
  . $this->bing_site_output()
388
  . $this->yandex_site_output()
389
+ . $this->pint_site_output();
390
+ else :
 
391
  $output = $this->the_description()
392
  . $this->og_image()
393
  . $this->og_locale()
414
  . $this->google_site_output()
415
  . $this->bing_site_output()
416
  . $this->yandex_site_output()
417
+ . $this->pint_site_output();
418
+ endif;
 
419
 
420
  $after_actions = $this->header_actions( '', false );
421
 
422
  /**
423
  * Applies filters 'the_seo_framework_pro' : string
424
+ * Adds content after the output and caches it through Object caching.
425
  * @since 2.6.0
426
  */
427
+ $after = (string) \apply_filters( 'the_seo_framework_pro', '' );
428
 
429
  /**
430
  * Applies filters 'the_seo_framework_generator_tag' : String generator tag content.
431
  * @since 2.0.1
432
  * @see https://wordpress.org/plugins/generator-the-seo-framework/ For an alternative.
433
  */
434
+ $generator = (string) \apply_filters( 'the_seo_framework_generator_tag', '' );
435
 
436
+ if ( $generator )
437
+ $generator = '<meta name="generator" content="' . \esc_attr( $generator ) . '" />' . "\r\n";
438
 
439
  $output = $robots . $before . $before_actions . $output . $after_actions . $after . $generator;
440
 
441
+ $this->use_object_cache and $this->object_cache_set( $cache_key, $output, 86400 );
442
+ endif;
443
 
444
  /**
445
  * Applies filters 'the_seo_framework_indicator' : Boolean
446
  * Whether to show the indicator in HTML.
447
  * @since 2.0.0
448
  */
449
+ $indicator = (bool) \apply_filters( 'the_seo_framework_indicator', true );
450
 
451
  $indicatorbefore = '';
452
  $indicatorafter = '';
453
 
454
+ if ( $indicator ) :
455
 
456
  /**
457
  * Applies filters 'the_seo_framework_indicator_timing' : Boolean
458
  * Whether to show the hidden generation time in HTML.
459
  * @since 2.4.0
460
  */
461
+ $timer = (bool) \apply_filters( 'the_seo_framework_indicator_timing', true );
462
 
463
  /**
464
  * Applies filters 'sybre_waaijer_<3' : Boolean
465
  * Whether to show the hidden author name in HTML.
466
  * @since 2.4.0
467
  */
468
+ $sybre = (bool) \apply_filters( 'sybre_waaijer_<3', true );
469
 
470
+ $start = \esc_html__( 'Start The Seo Framework', 'autodescription' );
471
+ $end = \esc_html__( 'End The Seo Framework', 'autodescription' );
472
+ $me = $sybre ? ' ' . \esc_html__( 'by Sybre Waaijer', 'autodescription' ) : '';
473
 
474
  $indicatorbefore = '<!-- ' . $start . $me . ' -->' . "\r\n";
475
 
478
  * @since 2.4.0
479
  */
480
  if ( $timer ) {
481
+ $indicatorafter = '<!-- ' . $end . $me . ' | ' . number_format( microtime( true ) - $init_start, 5 ) . 's' . ' -->' . "\r\n";
 
482
  } else {
483
  $indicatorafter = '<!-- ' . $end . $me . ' -->' . "\r\n";
484
  }
485
+ endif;
486
 
487
  $output = "\r\n" . $indicatorbefore . $output . $indicatorafter . "\r\n";
488
 
 
 
489
  //* Already escaped.
490
  echo $output;
491
 
492
+ \do_action( 'the_seo_framework_do_after_output' );
493
+
494
  }
495
 
496
  /**
497
  * Redirects singular page to an alternate URL.
498
  *
499
  * @since 2.0.9
500
+ * @since 2.8.0 Redirect status code is now filterable.
501
  *
502
  * @return void early on non-singular pages.
503
  */
504
  public function custom_field_redirect() {
505
 
506
+ if ( $url = $this->get_custom_field( 'redirect' ) ) {
 
 
507
 
508
+ $allow_external = $this->allow_external_redirect();
509
 
510
+ /**
511
+ * Applies filters 'the_seo_framework_redirect_status_code' : Absolute integer.
512
+ * @since 2.8.0
513
+ */
514
+ $redirect_type = absint( apply_filters( 'the_seo_framework_redirect_status_code', 301 ) );
515
 
516
+ if ( $redirect_type > 399 || $redirect_type < 300 )
517
+ $this->_doing_it_wrong( __METHOD__, 'You should use 3xx HTTP Status Codes. Recommended 301 and 302.', '2.8.0' );
518
 
519
  if ( false === $allow_external ) {
520
  $url = $this->set_url_scheme( $url, 'relative' );
521
  $url = $this->add_url_host( $url );
522
+ $scheme = $this->is_ssl() ? 'https' : 'http';
523
 
524
+ \wp_safe_redirect( \esc_url_raw( $url, array( $scheme ) ), $redirect_type );
525
  exit;
526
  }
527
 
528
+ \wp_redirect( \esc_url_raw( $url ), $redirect_type );
 
529
  exit;
530
  }
531
  }
532
+
533
+ /**
534
+ * Edits the robots.txt output.
535
+ * Requires not to have a robots.txt file in the root directory.
536
+ *
537
+ * @since 2.2.9
538
+ * @uses robots_txt filter located at WP core
539
+ *
540
+ * @param string $robots_txt The current robots_txt output.
541
+ * @param string $public The blog_public option value.
542
+ * @return string Robots.txt output.
543
+ */
544
+ public function robots_txt( $robots_txt = '', $public = '' ) {
545
+
546
+ /**
547
+ * Don't do anything if the blog isn't public
548
+ */
549
+ if ( '0' === $public )
550
+ return $robots_txt;
551
+
552
+ if ( $this->use_object_cache ) {
553
+ $cache_key = $this->get_robots_txt_cache_key();
554
+ $output = $this->object_cache_get( $cache_key );
555
+ } else {
556
+ $output = false;
557
+ }
558
+
559
+ if ( false === $output ) :
560
+ $output = '';
561
+
562
+ /**
563
+ * Apply filters the_seo_framework_robots_txt_pre & the_seo_framework_robots_txt_pro : string
564
+ * Adds custom cacheable lines.
565
+ * Don't forget to add line breaks ( "\r\n" || PHP_EOL )
566
+ *
567
+ * @since 2.5.0
568
+ */
569
+ $pre = (string) \apply_filters( 'the_seo_framework_robots_txt_pre', '' );
570
+ $pro = (string) \apply_filters( 'the_seo_framework_robots_txt_pro', '' );
571
+
572
+ $site_url = \wp_parse_url( \site_url() );
573
+ $path = ( ! empty( $site_url['path'] ) ) ? $site_url['path'] : '';
574
+
575
+ $output .= $pre;
576
+ //* Output defaults
577
+ $output .= "User-agent: *\r\n";
578
+ $output .= "Disallow: $path/wp-admin/\r\n";
579
+ $output .= "Allow: $path/wp-admin/admin-ajax.php\r\n";
580
+
581
+ /**
582
+ * Prevents query indexing
583
+ * @since 2.2.9
584
+ *
585
+ * Applies filters the_seo_framework_robots_disallow_queries : Whether to allow queries for robots.
586
+ * @since 2.5.0
587
+ */
588
+ if ( \apply_filters( 'the_seo_framework_robots_disallow_queries', false ) ) {
589
+ $home_url = \wp_parse_url( rtrim( $this->the_home_url_from_cache(), ' /\\' ) );
590
+ $home_path = ( ! empty( $home_url['path'] ) ) ? $home_url['path'] : '';
591
+ $output .= "Disallow: $home_path/*?*\r\n";
592
+ }
593
+
594
+ $output .= $pro;
595
+
596
+ if ( $this->get_option( 'sitemaps_robots' ) && $this->can_do_sitemap_robots() ) {
597
+ //* Add whitespace before sitemap.
598
+ $output .= "\r\n";
599
+
600
+ //* Add sitemap full url
601
+ $output .= 'Sitemap: ' . $this->the_home_url_from_cache( true ) . "sitemap.xml\r\n";
602
+ }
603
+
604
+ $this->use_object_cache and $this->object_cache_set( $cache_key, $output, 86400 );
605
+ endif;
606
+
607
+ /**
608
+ * Completely override robots with output.
609
+ * @since 2.5.0
610
+ */
611
+ $robots_txt = $output;
612
+
613
+ return $robots_txt;
614
+ }
615
+
616
+ /**
617
+ * Excludes posts from search with certain metadata.
618
+ * For now, it only looks at 'exclude_local_search'. If it exists, the post or
619
+ * page will be excluded from the local Search Results.
620
+ *
621
+ * @since 2.7.0
622
+ *
623
+ * @param array $query The possible search query.
624
+ * @return void Early if no search query is found.
625
+ */
626
+ public function adjust_search_filter( $query ) {
627
+
628
+ // Don't exclude pages in wp-admin.
629
+ if ( $query->is_search && false === $this->is_admin() ) {
630
+
631
+ $q = $query->query;
632
+ //* Only interact with an actual Search Query.
633
+ if ( false === isset( $q['s'] ) )
634
+ return;
635
+
636
+ $meta_query = $query->get( 'meta_query' );
637
+
638
+ //* Convert to array. Unset it if it's empty.
639
+ if ( false === is_array( $meta_query ) )
640
+ $meta_query = $meta_query ? (array) $meta_query : array();
641
+
642
+ /**
643
+ * Exclude posts with exclude_local_search option on.
644
+ *
645
+ * Query is faster when the global relation is not set. Defaults to AND.
646
+ * Query is faster when no value is set. Defaults to 'IS NULL' because
647
+ * of 'compare'. Having no effect whatsoever as it's an exclusion.
648
+ */
649
+ $meta_query[] = array(
650
+ array(
651
+ 'key' => 'exclude_local_search',
652
+ 'type' => 'NUMERIC',
653
+ 'compare' => 'NOT EXISTS',
654
+ ),
655
+ );
656
+
657
+ $query->set( 'meta_query', $meta_query );
658
+ }
659
+ }
660
  }
inc/classes/inpost.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,16 +23,14 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Inpost
23
  *
24
  * Outputs Taxonomy, Post and Page meta boxes
25
  *
26
- * @since 2.2.2
27
  */
28
- class AutoDescription_Inpost extends AutoDescription_DoingItRight {
29
 
30
  /**
31
  * Add inpost SEO Bar through a filter.
@@ -54,33 +59,15 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
54
  */
55
  public $inpost_nonce_field;
56
 
57
- /**
58
- * Unserializing instances of this class is forbidden.
59
- */
60
- private function __wakeup() { }
61
-
62
- /**
63
- * Handle unapproachable invoked methods.
64
- */
65
- public function __call( $name, $arguments ) {
66
- parent::__call( $name, $arguments );
67
- }
68
-
69
  /**
70
  * Constructor, load parent constructor
71
  */
72
- public function __construct() {
73
  parent::__construct();
74
 
75
  $this->inpost_nonce_name = 'the_seo_framework_inpost_seo_settings';
76
  $this->inpost_nonce_field = 'the_seo_framework_inpost';
77
 
78
- //* Enqueue Inpost meta boxes.
79
- add_action( 'add_meta_boxes', array( $this, 'add_inpost_seo_box_init' ), 5 );
80
-
81
- //* Enqueue Taxonomy meta output.
82
- add_action( 'current_screen', array( $this, 'add_taxonomy_seo_box_init' ), 10 );
83
-
84
  /**
85
  * Applies filters bool|string the_seo_framework_inpost_seo_bar :
86
  * Whether to output the SEO bar within the inpost SEO Settings metabox.
@@ -89,7 +76,7 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
89
  * : bool false No output.
90
  * @since 2.5.2
91
  */
92
- $this->inpost_seo_bar = apply_filters( 'the_seo_framework_inpost_seo_bar', false );
93
 
94
  }
95
 
@@ -107,10 +94,10 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
107
  * Applies filters the_seo_framework_seobox_output : bool
108
  * @since 2.0.0
109
  */
110
- $show_seobox = (bool) apply_filters( 'the_seo_framework_seobox_output', true );
111
 
112
  if ( $show_seobox )
113
- add_action( 'add_meta_boxes', array( $this, 'add_inpost_seo_box' ), 10, 1 );
114
 
115
  }
116
 
@@ -120,10 +107,11 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
120
  * @since 2.1.8
121
  * @since 2.6.0 Can no longer run outside of the term edit scope.
122
  * @since 2.6.0 Can no longer run when another SEO plugin is active.
 
123
  */
124
  public function add_taxonomy_seo_box_init() {
125
 
126
- if ( $this->detect_seo_plugins() || ! $this->is_term_edit() )
127
  return;
128
 
129
  /**
@@ -132,12 +120,12 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
132
  *
133
  * @since 2.6.0
134
  */
135
- $priority = (int) apply_filters( 'the_seo_framework_term_metabox_priority', 0 );
136
 
137
  //* Add taxonomy meta boxes
138
- foreach ( get_taxonomies( array( 'public' => true ) ) as $tax_name )
139
- add_action( $tax_name . '_edit_form', array( $this, 'pre_seo_box' ), $priority, 2 );
140
-
141
  }
142
 
143
  /**
@@ -155,7 +143,7 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
155
  */
156
  if ( $this->post_type_supports_custom_seo( $post_type ) ) {
157
 
158
- $post = get_post_type_object( $post_type );
159
 
160
  if ( is_object( $post ) ) {
161
  $labels = isset( $post->labels ) ? $post->labels : '';
@@ -172,34 +160,31 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
172
  * @TODO solve note.
173
  * @priority medium 2.7.0
174
  */
175
- $id = (string) apply_filters( 'the_seo_framework_metabox_id', 'tsf-inpost-box' );
176
  $context = 'normal';
177
 
178
  /**
179
  * High priority, this box is seen right below the post/page edit screen.
180
  * Applies filters 'the_seo_framework_metabox_priority' : string
181
- * Accepts 'high', 'default', 'low'
182
  * @since 2.6.0
 
183
  */
184
- $priority = (string) apply_filters( 'the_seo_framework_metabox_priority', 'high' );
185
 
186
- add_meta_box( $id, sprintf( __( '%s SEO Settings', 'autodescription' ), $title ), array( $this, 'pre_seo_box' ), $post_type, $context, $priority, $args );
187
  }
188
  }
189
  }
190
-
191
  }
192
 
193
  /**
194
- * Determines which arguments should be used
195
  *
196
  * @since 2.1.8
197
- *
198
- * @used by add_inpost_seo_box
199
  *
200
  * @param $object the page/post/taxonomy object
201
  * @param $args the page/post arguments or taxonomy slug.
202
- *
203
  * @return string Inpost SEO box.
204
  */
205
  public function pre_seo_box( $object, $args ) {
@@ -215,8 +200,7 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
215
  return $this->inpost_seo_box( $object, (array) $args );
216
  }
217
  } else {
218
- //* Note: Passes object.
219
- // Empty the arguments, if any.
220
  return $this->inpost_seo_box( $object, $args = '' );
221
  }
222
 
@@ -228,15 +212,10 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
228
  *
229
  * @since 2.0.0
230
  * @access private
231
- *
232
- * @param array $post The post object
233
  *
234
  * @param object $object the page/post/taxonomy object
235
  * @param array $args the page/post arguments or taxonomy slug
236
- *
237
- * @uses $this->get_custom_field() Get custom field value.
238
- *
239
- * Note: Passed through object $object by reference
240
  */
241
  public function inpost_seo_box( $object, $args ) {
242
 
@@ -252,9 +231,9 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
252
  //* The kind of page we're on.
253
  $page = $args_split[1];
254
 
255
- // Only add nonce on post/page edit screen
256
  if ( 'is_post_page' === $page ) {
257
- wp_nonce_field( $this->inpost_nonce_field, $this->inpost_nonce_name );
258
  } else {
259
  // This shouldn't happen.
260
  return;
@@ -270,7 +249,7 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
270
 
271
  if ( empty( $type ) ) {
272
  // Fallback to Page as it is generic.
273
- $type = __( 'Page', 'autodescription' );
274
  }
275
 
276
  $is_term = true;
@@ -280,9 +259,8 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
280
  if ( $is_term ) {
281
  $this->tt_inpost_box( $type, $object );
282
  } else {
283
- $this->page_inpost_box( $type );
284
  }
285
-
286
  }
287
 
288
  /**
@@ -295,165 +273,9 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
295
  * @param object $object The TT object.
296
  */
297
  public function tt_inpost_box( $type, $object ) {
298
-
299
- do_action( 'the_seo_framework_pre_tt_inpost_box' );
300
-
301
- //* Get the language the Google page should assume.
302
- $language = $this->google_language();
303
-
304
- //* Fetch Term ID and taxonomy.
305
- $term_id = $object->term_id;
306
- $taxonomy = $object->taxonomy;
307
-
308
- $data = $this->get_term_data( $object, $term_id );
309
-
310
- $title = isset( $data['doctitle'] ) ? $data['doctitle'] : '';
311
- $description = isset( $data['description'] ) ? $data['description'] : '';
312
- $noindex = isset( $data['noindex'] ) ? $data['noindex'] : '';
313
- $nofollow = isset( $data['nofollow'] ) ? $data['nofollow'] : '';
314
- $noarchive = isset( $data['noarchive'] ) ? $data['noarchive'] : '';
315
-
316
- $generated_doctitle_args = array(
317
- 'term_id' => $term_id,
318
- 'taxonomy' => $taxonomy,
319
- 'placeholder' => true,
320
- 'get_custom_field' => false,
321
- );
322
-
323
- $generated_description_args = array(
324
- 'id' => $term_id,
325
- 'taxonomy' => $taxonomy,
326
- 'get_custom_field' => false,
327
- );
328
-
329
- //* Generate title and description.
330
- $generated_doctitle = $this->title( '', '', '', $generated_doctitle_args );
331
- $generated_description = $this->generate_description( '', $generated_description_args );
332
-
333
- $blog_name = $this->get_blogname();
334
- $add_additions = $this->add_title_additions();
335
-
336
- /**
337
- * Separator doesn't matter. Since html_entity_decode is used.
338
- * Order doesn't matter either. Since it's just used for length calculation.
339
- *
340
- * @since 2.3.4
341
- */
342
- $doc_pre_rem = $add_additions ? $title . ' | ' . $blog_name : $title;
343
- $title_len = $title ? $doc_pre_rem : $generated_doctitle;
344
- $description_len = $description ? $description : $generated_description;
345
-
346
- /**
347
- * Convert to what Google outputs.
348
- *
349
- * This will convert e.g. &raquo; to a single length character.
350
- * @since 2.3.4
351
- */
352
- $tit_len_parsed = html_entity_decode( $title_len );
353
- $desc_len_parsed = html_entity_decode( $description_len );
354
-
355
- /**
356
- * Generate static placeholder for when title or description is emptied
357
- *
358
- * @since 2.2.4
359
- */
360
- $title_placeholder = $generated_doctitle;
361
- $description_placeholder = $generated_description;
362
-
363
- ?>
364
- <h3><?php printf( esc_html__( '%s SEO Settings', 'autodescription' ), $type ); ?></h3>
365
-
366
- <table class="form-table">
367
- <tbody>
368
-
369
- <?php if ( 'above' === $this->inpost_seo_bar ) : ?>
370
- <tr>
371
- <th scope="row" valign="top"><?php esc_html_e( 'Doing it Right', 'autodescription' ); ?></th>
372
- <td>
373
- <?php echo $this->post_status( $term_id, $taxonomy, true ); ?>
374
- </td>
375
- </tr>
376
- <?php endif; ?>
377
-
378
- <tr class="form-field">
379
- <th scope="row" valign="top">
380
- <label for="autodescription-meta[doctitle]">
381
- <strong><?php printf( esc_html__( '%s Title', 'autodescription' ), $type ); ?></strong>
382
- <a href="https://support.google.com/webmasters/answer/35624?hl=<?php echo $language; ?>#3" target="_blank" title="<?php esc_html_e( 'Recommended Length: 50 to 55 characters', 'autodescription' ) ?>">[?]</a>
383
- </label>
384
- </th>
385
- <td>
386
- <div id="tsf-title-wrap">
387
- <input name="autodescription-meta[doctitle]" id="autodescription-meta[doctitle]" type="text" placeholder="<?php echo $title_placeholder ?>" value="<?php echo esc_attr( $title ); ?>" size="40" />
388
- <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
389
- </div>
390
- <p class="description tsf-counter">
391
- <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="autodescription-meta[doctitle]_chars">'. mb_strlen( $tit_len_parsed ) .'</span>' ); ?>
392
- <span class="hide-if-no-js tsf-ajax"></span>
393
- </p>
394
- </td>
395
- </tr>
396
-
397
- <tr class="form-field">
398
- <th scope="row" valign="top">
399
- <label for="autodescription-meta[description]">
400
- <strong><?php printf( esc_html__( '%s Meta Description', 'autodescription' ), $type ); ?></strong>
401
- <a href="https://support.google.com/webmasters/answer/35624?hl=<?php echo $language; ?>#1" target="_blank" title="<?php esc_html_e( 'Recommended Length: 145 to 155 characters', 'autodescription' ) ?>">[?]</a>
402
- </label>
403
- </th>
404
- <td>
405
- <textarea name="autodescription-meta[description]" id="autodescription-meta[description]" placeholder="<?php echo $description_placeholder ?>" rows="5" cols="50" class="large-text"><?php echo esc_html( $description ); ?></textarea>
406
- <p class="description tsf-counter">
407
- <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="autodescription-meta[description]_chars">'. mb_strlen( $desc_len_parsed ) .'</span>' ); ?>
408
- <span class="hide-if-no-js tsf-ajax"></span>
409
- </p>
410
- </td>
411
- </tr>
412
-
413
- <tr>
414
- <th scope="row" valign="top"><?php esc_html_e( 'Robots Meta Settings', 'autodescription' ); ?></th>
415
- <td>
416
- <label for="autodescription-meta[noindex]"><input name="autodescription-meta[noindex]" id="autodescription-meta[noindex]" type="checkbox" value="1" <?php checked( $noindex ); ?> />
417
- <?php printf( esc_html__( 'Apply %s to this term?', 'autodescription' ), $this->code_wrap( 'noindex' ) ); ?>
418
- <a href="https://support.google.com/webmasters/answer/93710?hl=<?php echo $language; ?>" target="_blank" title="<?php printf( esc_html__( 'Tell Search Engines not to show this page in their search results', 'autodescription' ) ) ?>">[?]</a>
419
- </label>
420
-
421
- <br>
422
-
423
- <label for="autodescription-meta[nofollow]"><input name="autodescription-meta[nofollow]" id="autodescription-meta[nofollow]" type="checkbox" value="1" <?php checked( $nofollow ); ?> />
424
- <?php printf( esc_html__( 'Apply %s to this term?', 'autodescription' ), $this->code_wrap( 'nofollow' ) ); ?>
425
- <a href="https://support.google.com/webmasters/answer/96569?hl=<?php echo $language; ?>" target="_blank" title="<?php printf( esc_html__( 'Tell Search Engines not to follow links on this page', 'autodescription' ) ) ?>">[?]</a>
426
- </label>
427
-
428
- <br>
429
-
430
- <label for="autodescription-meta[noarchive]"><input name="autodescription-meta[noarchive]" id="autodescription-meta[noarchive]" type="checkbox" value="1" <?php checked( $noarchive ); ?> />
431
- <?php printf( esc_html__( 'Apply %s to this term?', 'autodescription' ), $this->code_wrap( 'noarchive' ) ); ?>
432
- <a href="https://support.google.com/webmasters/answer/79812?hl=<?php echo $language; ?>" target="_blank" title="<?php printf( esc_html__( 'Tell Search Engines not to save a cached copy of this page', 'autodescription' ) ) ?>">[?]</a>
433
- </label>
434
-
435
- <?php // Saved flag, if set then it won't fetch for Genesis meta anymore ?>
436
- <label class="hidden" for="autodescription-meta[saved_flag]">
437
- <input name="autodescription-meta[saved_flag]" id="autodescription-meta[saved_flag]" type="checkbox" value="1" checked='checked' />
438
- </label>
439
- </td>
440
- </tr>
441
-
442
- <?php if ( 'below' === $this->inpost_seo_bar ) : ?>
443
- <tr>
444
- <th scope="row" valign="top"><?php esc_html_e( 'Doing it Right', 'autodescription' ); ?></th>
445
- <td>
446
- <?php echo $this->post_status( $term_id, $taxonomy, true ); ?>
447
- </td>
448
- </tr>
449
- <?php endif; ?>
450
-
451
- </tbody>
452
- </table>
453
- <?php
454
-
455
- do_action( 'the_seo_framework_pro_tt_inpost_box' );
456
-
457
  }
458
 
459
  /**
@@ -464,241 +286,47 @@ class AutoDescription_Inpost extends AutoDescription_DoingItRight {
464
  *
465
  * @param string $type The post type name.
466
  */
467
- public function page_inpost_box( $type ) {
468
-
469
- do_action( 'the_seo_framework_pre_page_inpost_box' );
470
-
471
- //* Get the language the Google page should assume.
472
- $language = $this->google_language();
473
-
474
- $post_id = $this->get_the_real_ID();
475
- $is_static_frontpage = $this->is_static_frontpage( $post_id );
476
-
477
- $title = $this->get_custom_field( '_genesis_title', $post_id );
478
-
479
- /**
480
- * Generate static placeholder for when title or description is emptied
481
- *
482
- * @since 2.2.4
483
- *
484
- * Fetch description from Home Page SEO Settings placeholder if it exists.
485
- * @since 2.2.5
486
- *
487
- * Generate description for Posts Page if selected in customizer.
488
- * @since 2.2.8
489
- */
490
- if ( $is_static_frontpage ) {
491
- //* Front page.
492
- $generated_doctitle_args = array(
493
- 'page_on_front' => true,
494
- 'placeholder' => true,
495
- 'meta' => true,
496
- 'get_custom_field' => false,
497
- );
498
-
499
- $generated_description_args = array(
500
- 'id' => $post_id,
501
- 'is_home' => true,
502
- 'get_custom_field' => true,
503
- );
504
- } elseif ( $this->is_blog_page( $post_id ) ) {
505
- //* Page for posts.
506
- $generated_doctitle_args = array(
507
- 'placeholder' => true,
508
- 'meta' => true,
509
- 'get_custom_field' => false,
510
- );
511
-
512
- $generated_description_args = array(
513
- 'id' => $post_id,
514
- 'page_for_posts' => true,
515
- );
516
- } else {
517
- $generated_doctitle_args = array(
518
- 'placeholder' => true,
519
- 'meta' => true,
520
- 'get_custom_field' => false,
521
- );
522
-
523
- $generated_description_args = array(
524
- 'id' => $post_id,
525
- );
526
- }
527
- $generated_doctitle = $this->title( '', '', '', $generated_doctitle_args );
528
- $generated_description = $this->generate_description_from_id( $generated_description_args );
529
 
530
- /**
531
- * Special check for home page.
532
- *
533
- * @since 2.3.4
534
- */
535
- if ( $is_static_frontpage ) {
536
- if ( $this->get_option( 'homepage_tagline' ) )
537
- $tit_len_pre = $title ? $title . " | " . $this->get_blogdescription() : $generated_doctitle;
538
- else
539
- $tit_len_pre = $title ? $title : $generated_doctitle;
540
- } else {
541
- /**
542
- * Separator doesn't matter. Since html_entity_decode is used.
543
- * Order doesn't matter either. Since it's just used for length calculation.
544
- *
545
- * @since 2.3.4
546
- */
547
- if ( $this->add_title_additions() )
548
- $tit_len_pre = $title ? $title . " | " . $this->get_blogname() : $generated_doctitle;
549
- else
550
- $tit_len_pre = $title ? $title : $generated_doctitle;
551
- }
552
 
553
- //* Fetch description from option.
554
- $description = $this->get_custom_field( '_genesis_description' );
555
 
556
- /**
557
- * Calculate current description length
558
- *
559
- * Reworked.
560
- * @since 2.3.4
561
- */
562
- if ( $is_static_frontpage ) {
563
- //* The homepage description takes precedence.
564
- $homepage_description = $this->get_option( 'homepage_description' );
565
-
566
- if ( $description )
567
- $desc_len_pre = $homepage_description ? $homepage_description : $description;
568
- else
569
- $desc_len_pre = $homepage_description ? $homepage_description : $generated_description;
570
- } else {
571
- $desc_len_pre = $description ? $description : $generated_description;
572
- }
573
 
574
- /**
575
- * Convert to what Google outputs.
576
- *
577
- * This will convert e.g. &raquo; to a single length character.
578
- * @since 2.3.4
579
- */
580
- $tit_len_parsed = html_entity_decode( $tit_len_pre );
581
- $desc_len_parsed = html_entity_decode( $desc_len_pre );
 
582
 
583
- /**
584
- * Generate static placeholder for when title or description is emptied
585
- *
586
- * Now within aptly named vars.
587
- * @since 2.3.4
588
- */
589
- $doctitle_placeholder = $generated_doctitle;
590
- $description_placeholder = $generated_description;
591
-
592
- //* Fetch Canonical URL.
593
- $canonical = $this->get_custom_field( '_genesis_canonical_uri' );
594
- //* Fetch Canonical URL Placeholder.
595
- $canonical_placeholder = $this->the_url_from_cache( '', $post_id, false, false );
596
-
597
- ?>
598
- <?php if ( 'above' === $this->inpost_seo_bar ) : ?>
599
- <p>
600
- <strong><?php esc_html_e( 'Doing it Right', 'autodescription' ); ?></strong>
601
- <div><?php echo $this->post_status( $post_id, 'inpost', true ); ?></div>
602
- </p>
603
- <?php endif; ?>
604
-
605
- <p>
606
- <label for="autodescription_title"><strong><?php printf( esc_html__( 'Custom %s Title', 'autodescription' ), $type ); ?></strong>
607
- <a href="https://support.google.com/webmasters/answer/35624?hl=<?php echo $language; ?>#3" target="_blank" title="<?php esc_html_e( 'Recommended Length: 50 to 55 characters', 'autodescription' ); ?>">[?]</a>
608
- <span class="description tsf-counter">
609
- <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="autodescription_title_chars">'. mb_strlen( $tit_len_parsed ) .'</span>' ); ?>
610
- <span class="hide-if-no-js tsf-ajax"></span>
611
- </span>
612
- </label>
613
- </p>
614
- <p>
615
- <div id="tsf-title-wrap">
616
- <input class="large-text" type="text" name="autodescription[_genesis_title]" id="autodescription_title" placeholder="<?php echo $doctitle_placeholder ?>" value="<?php echo esc_attr( $this->get_custom_field( '_genesis_title' ) ); ?>" />
617
- <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
618
- </div>
619
- </p>
620
-
621
- <p>
622
- <label for="autodescription_description">
623
- <strong><?php printf( esc_html__( 'Custom %s Description', 'autodescription' ), $type ); ?></strong>
624
- <a href="https://support.google.com/webmasters/answer/35624?hl=<?php echo $language; ?>#1" target="_blank" title="<?php esc_html_e( 'Recommended Length: 145 to 155 characters', 'autodescription' ); ?>">[?]</a>
625
- <span class="description tsf-counter">
626
- <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="autodescription_description_chars">'. mb_strlen( $desc_len_parsed ) .'</span>' ); ?>
627
- <span class="hide-if-no-js tsf-ajax"></span>
628
- </span>
629
- </label>
630
- </p>
631
- <p>
632
- <textarea class="large-text" name="autodescription[_genesis_description]" id="autodescription_description" placeholder="<?php echo $description_placeholder ?>" rows="4" cols="4"><?php echo esc_textarea( $this->get_custom_field( '_genesis_description' ) ); ?></textarea>
633
- </p>
634
-
635
- <p>
636
- <label for="autodescription_canonical">
637
- <strong><?php esc_html_e( 'Custom Canonical URL', 'autodescription' ); ?></strong>
638
- <a href="https://support.google.com/webmasters/answer/139066?hl=<?php echo $language; ?>" target="_blank" title="<?php printf( esc_html__( 'Preferred %s URL location', 'autodescription' ), $type ); ?>">[?]</a>
639
- </label>
640
- </p>
641
- <p>
642
- <input class="large-text" type="text" name="autodescription[_genesis_canonical_uri]" id="autodescription_canonical" placeholder="<?php echo $canonical_placeholder ?>" value="<?php echo esc_url( $this->get_custom_field( '_genesis_canonical_uri' ) ); ?>" />
643
- </p>
644
-
645
- <p><strong><?php esc_html_e( 'Robots Meta Settings', 'autodescription' ); ?></strong></p>
646
- <p>
647
- <label for="autodescription_noindex"><input type="checkbox" name="autodescription[_genesis_noindex]" id="autodescription_noindex" value="1" <?php checked( $this->get_custom_field( '_genesis_noindex' ) ); ?> />
648
- <?php
649
- /* translators: 1: Option, 2: Post or Page */
650
- printf( esc_html__( 'Apply %1$s to this %2$s', 'autodescription' ), $this->code_wrap( 'noindex' ), $type );
651
- ?>
652
- <a href="https://support.google.com/webmasters/answer/93710?hl=<?php echo $language; ?>" target="_blank" title="<?php printf( esc_html__( 'Tell Search Engines not to show this %s in their search results', 'autodescription' ), $type ); ?>">[?]</a>
653
- </label>
654
-
655
- <br>
656
-
657
- <label for="autodescription_nofollow"><input type="checkbox" name="autodescription[_genesis_nofollow]" id="autodescription_nofollow" value="1" <?php checked( $this->get_custom_field( '_genesis_nofollow' ) ); ?> />
658
- <?php
659
- /* translators: 1: Option, 2: Post or Page */
660
- printf( esc_html__( 'Apply %1$s to this %2$s', 'autodescription' ), $this->code_wrap( 'nofollow' ), $type );
661
- ?>
662
- <a href="https://support.google.com/webmasters/answer/96569?hl=<?php echo $language; ?>" target="_blank" title="<?php printf( esc_html__( 'Tell Search Engines not to follow links on this %s', 'autodescription' ), $type ); ?>">[?]</a>
663
- </label>
664
-
665
- <br>
666
-
667
- <label for="autodescription_noarchive"><input type="checkbox" name="autodescription[_genesis_noarchive]" id="autodescription_noarchive" value="1" <?php checked( $this->get_custom_field( '_genesis_noarchive' ) ); ?> />
668
- <?php
669
- /* translators: 1: Option, 2: Post or Page */
670
- printf( esc_html__( 'Apply %1$s to this %2$s', 'autodescription' ), $this->code_wrap( 'noarchive' ), $type );
671
- ?>
672
- <a href="https://support.google.com/webmasters/answer/79812?hl=<?php echo $language; ?>" target="_blank" title="<?php printf( esc_html__( 'Tell Search Engines not to save a cached copy of this %s', 'autodescription' ), $type ); ?>">[?]</a>
673
- </label>
674
- </p>
675
-
676
- <p><strong><?php esc_html_e( 'Local Search Settings', 'autodescription' ); ?></strong></p>
677
- <p>
678
- <label for="autodescription_exclude_local_search"><input type="checkbox" name="autodescription[exclude_local_search]" id="autodescription_exclude_local_search" value="1" <?php checked( $this->get_custom_field( 'exclude_local_search' ) ); ?> />
679
- <?php printf( esc_html__( 'Exclude this %s from local search', 'autodescription' ), $type ); ?>
680
- <span title="<?php printf( esc_html__( 'This excludes this %s from local on-site search results', 'autodescription' ), $type ); ?>">[?]</span>
681
- </label>
682
- </p>
683
-
684
- <p>
685
- <label for="autodescription_redirect">
686
- <strong><?php esc_html_e( 'Custom 301 Redirect URL', 'autodescription' ); ?></strong>
687
- <a href="https://support.google.com/webmasters/answer/93633?hl=<?php echo $language; ?>" target="_blank" title="<?php esc_html_e( 'This will force visitors to go to another URL', 'autodescription' ); ?>">[?]</a>
688
- </label>
689
- </p>
690
- <p>
691
- <input class="large-text" type="text" name="autodescription[redirect]" id="genesis_redirect" value="<?php echo esc_url( $this->get_custom_field( 'redirect' ) ); ?>" />
692
- </p>
693
-
694
- <?php if ( 'below' === $this->inpost_seo_bar ) : ?>
695
- <p>
696
- <strong><?php esc_html_e( 'Doing it Right', 'autodescription' ); ?></strong>
697
- <div><?php echo $this->post_status( $post_id, 'inpost', true ); ?></div>
698
- </p>
699
- <?php endif;
700
-
701
- do_action( 'the_seo_framework_pro_page_inpost_box' );
702
 
 
703
  }
704
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Inpost
28
  *
29
  * Outputs Taxonomy, Post and Page meta boxes
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Inpost extends Doing_It_Right {
34
 
35
  /**
36
  * Add inpost SEO Bar through a filter.
59
  */
60
  public $inpost_nonce_field;
61
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  /**
63
  * Constructor, load parent constructor
64
  */
65
+ protected function __construct() {
66
  parent::__construct();
67
 
68
  $this->inpost_nonce_name = 'the_seo_framework_inpost_seo_settings';
69
  $this->inpost_nonce_field = 'the_seo_framework_inpost';
70
 
 
 
 
 
 
 
71
  /**
72
  * Applies filters bool|string the_seo_framework_inpost_seo_bar :
73
  * Whether to output the SEO bar within the inpost SEO Settings metabox.
76
  * : bool false No output.
77
  * @since 2.5.2
78
  */
79
+ $this->inpost_seo_bar = \apply_filters( 'the_seo_framework_inpost_seo_bar', false );
80
 
81
  }
82
 
94
  * Applies filters the_seo_framework_seobox_output : bool
95
  * @since 2.0.0
96
  */
97
+ $show_seobox = (bool) \apply_filters( 'the_seo_framework_seobox_output', true );
98
 
99
  if ( $show_seobox )
100
+ \add_action( 'add_meta_boxes', array( $this, 'add_inpost_seo_box' ), 10, 1 );
101
 
102
  }
103
 
107
  * @since 2.1.8
108
  * @since 2.6.0 Can no longer run outside of the term edit scope.
109
  * @since 2.6.0 Can no longer run when another SEO plugin is active.
110
+ * @since 2.8.0 Added show_ui argument for public taxonomy detection.
111
  */
112
  public function add_taxonomy_seo_box_init() {
113
 
114
+ if ( $this->detect_seo_plugins() || false === $this->is_term_edit() )
115
  return;
116
 
117
  /**
120
  *
121
  * @since 2.6.0
122
  */
123
+ $priority = (int) \apply_filters( 'the_seo_framework_term_metabox_priority', 0 );
124
 
125
  //* Add taxonomy meta boxes
126
+ foreach ( \get_taxonomies( array( 'public' => true, 'show_ui' => true ) ) as $tax_name ) {
127
+ \add_action( $tax_name . '_edit_form', array( $this, 'pre_seo_box' ), $priority, 2 );
128
+ }
129
  }
130
 
131
  /**
143
  */
144
  if ( $this->post_type_supports_custom_seo( $post_type ) ) {
145
 
146
+ $post = \get_post_type_object( $post_type );
147
 
148
  if ( is_object( $post ) ) {
149
  $labels = isset( $post->labels ) ? $post->labels : '';
160
  * @TODO solve note.
161
  * @priority medium 2.7.0
162
  */
163
+ $id = (string) \apply_filters( 'the_seo_framework_metabox_id', 'tsf-inpost-box' );
164
  $context = 'normal';
165
 
166
  /**
167
  * High priority, this box is seen right below the post/page edit screen.
168
  * Applies filters 'the_seo_framework_metabox_priority' : string
 
169
  * @since 2.6.0
170
+ * @param string $default Accepts 'high', 'default', 'low'
171
  */
172
+ $priority = (string) \apply_filters( 'the_seo_framework_metabox_priority', 'high' );
173
 
174
+ \add_meta_box( $id, sprintf( \__( '%s SEO Settings', 'autodescription' ), $title ), array( $this, 'pre_seo_box' ), $post_type, $context, $priority, $args );
175
  }
176
  }
177
  }
 
178
  }
179
 
180
  /**
181
+ * Determines post type and outputs SEO box.
182
  *
183
  * @since 2.1.8
184
+ * @access private
 
185
  *
186
  * @param $object the page/post/taxonomy object
187
  * @param $args the page/post arguments or taxonomy slug.
 
188
  * @return string Inpost SEO box.
189
  */
190
  public function pre_seo_box( $object, $args ) {
200
  return $this->inpost_seo_box( $object, (array) $args );
201
  }
202
  } else {
203
+ //* Empty the arguments, if any.
 
204
  return $this->inpost_seo_box( $object, $args = '' );
205
  }
206
 
212
  *
213
  * @since 2.0.0
214
  * @access private
215
+ * @uses $this->get_custom_field() Get custom field value.
 
216
  *
217
  * @param object $object the page/post/taxonomy object
218
  * @param array $args the page/post arguments or taxonomy slug
 
 
 
 
219
  */
220
  public function inpost_seo_box( $object, $args ) {
221
 
231
  //* The kind of page we're on.
232
  $page = $args_split[1];
233
 
234
+ //* Only add nonce on post/page edit screen. Nonce for terms are handled in core.
235
  if ( 'is_post_page' === $page ) {
236
+ \wp_nonce_field( $this->inpost_nonce_field, $this->inpost_nonce_name );
237
  } else {
238
  // This shouldn't happen.
239
  return;
249
 
250
  if ( empty( $type ) ) {
251
  // Fallback to Page as it is generic.
252
+ $type = \__( 'Page', 'autodescription' );
253
  }
254
 
255
  $is_term = true;
259
  if ( $is_term ) {
260
  $this->tt_inpost_box( $type, $object );
261
  } else {
262
+ $this->singular_inpost_box( $type );
263
  }
 
264
  }
265
 
266
  /**
273
  * @param object $object The TT object.
274
  */
275
  public function tt_inpost_box( $type, $object ) {
276
+ \do_action( 'the_seo_framework_pre_tt_inpost_box' );
277
+ $this->get_view( 'inpost/seo-settings', get_defined_vars(), 'term' );
278
+ \do_action( 'the_seo_framework_pro_tt_inpost_box' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  }
280
 
281
  /**
286
  *
287
  * @param string $type The post type name.
288
  */
289
+ public function singular_inpost_box( $type ) {
290
+ \do_action( 'the_seo_framework_pre_page_inpost_box' );
291
+ $this->get_view( 'inpost/seo-settings', get_defined_vars(), 'singular' );
292
+ \do_action( 'the_seo_framework_pro_page_inpost_box' );
293
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
 
295
+ /**
296
+ * Returns social image uploader form button.
297
+ * Also registers additional i18n strings for JS.
298
+ *
299
+ * @since 2.8.0
300
+ * @todo optimize? Sanitation and translations are duplicated -> microseconds...
301
+ *
302
+ * @param string $input_id Required. The HTML input id to pass URL into.
303
+ * @return string The image uploader button.
304
+ */
305
+ public function get_social_image_uploader_form( $input_id ) {
 
 
 
 
 
 
 
 
 
 
 
306
 
307
+ if ( ! $input_id )
308
+ return '';
309
 
310
+ $content = sprintf( '<a href="%1$s" class="tsf-set-social-image button button-primary button-small" title="%2$s" id="%3$s-select" data-inputid="%3$s">%4$s</a>',
311
+ \esc_url( \get_upload_iframe_src( 'image', $this->get_the_real_ID() ) ),
312
+ \esc_attr__( 'Select social image', 'autodescription' ),
313
+ \esc_attr( $input_id ),
314
+ \esc_html__( 'Select Image', 'autodescription' )
315
+ );
 
 
 
 
 
 
 
 
 
 
 
316
 
317
+ $button_labels = array(
318
+ 'select' => \esc_attr__( 'Select Image', 'autodescription' ),
319
+ 'select_title' => \esc_attr__( 'Select social image', 'autodescription' ),
320
+ 'change' => \esc_attr__( 'Change Image', 'autodescription' ),
321
+ 'remove' => \esc_attr__( 'Remove Image', 'autodescription' ),
322
+ 'remove_title' => \esc_attr__( 'Remove selected social image', 'autodescription' ),
323
+ 'frame_title' => \esc_attr__( 'Select Social Image', 'autodescription' ),
324
+ 'frame_button' => \esc_attr__( 'Use this image', 'autodescription' ),
325
+ );
326
 
327
+ //* Already escaped. Turn off escaping.
328
+ $this->additional_js_l10n( \esc_attr( $input_id ), $button_labels, false, false );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
 
330
+ return $content;
331
  }
332
  }
inc/classes/load.class.php ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
+ /**
10
+ * The SEO Framework plugin
11
+ * Copyright (C) 2015 - 2016 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
15
+ * by the Free Software Foundation.
16
+ *
17
+ * This program is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
+ */
25
+
26
+ /**
27
+ * Facade final class The_SEO_Framework\Load
28
+ *
29
+ * Extending upon parent classes.
30
+ *
31
+ * @since 2.8.0
32
+ * @uses interface Debug_Interface
33
+ */
34
+ final class Load extends Feed implements Debug_Interface {
35
+
36
+ /**
37
+ * Cached debug/profile properties. Initialized on plugins_loaded priority 5.
38
+ *
39
+ * @since 2.2.9
40
+ *
41
+ * @var bool Whether debug is enabled.
42
+ * @var bool Whether debug is hidden in HTMl.
43
+ * @var bool Whether transients are enabled.
44
+ * @var bool Whether script debugging is enabled.
45
+ */
46
+ public $the_seo_framework_debug = false;
47
+ public $the_seo_framework_debug_hidden = false;
48
+ public $the_seo_framework_use_transients = true;
49
+ public $script_debug = false;
50
+
51
+ /**
52
+ * Constructor, setup debug vars and then load parent constructor.
53
+ *
54
+ * @staticvar int $count Prevents duplicated constructor loading.
55
+ * @return null If called twice or more.
56
+ */
57
+ public function __construct() {
58
+
59
+ static $count = 0;
60
+
61
+ if ( $count > 0 ) {
62
+ return null;
63
+ }
64
+
65
+ $count++;
66
+
67
+ //* Setup debug vars before initializing parents.
68
+ $this->init_debug_vars();
69
+
70
+ parent::__construct();
71
+ }
72
+
73
+ /**
74
+ * Initializes public debug variables for the class to use.
75
+ *
76
+ * @since 2.6.0
77
+ */
78
+ public function init_debug_vars() {
79
+
80
+ $this->the_seo_framework_debug = defined( 'THE_SEO_FRAMEWORK_DEBUG' ) && THE_SEO_FRAMEWORK_DEBUG ? true : $this->the_seo_framework_debug;
81
+ if ( $this->the_seo_framework_debug ) {
82
+ //* No need to set these to true if no debugging is enabled.
83
+ $this->the_seo_framework_debug_hidden = defined( 'THE_SEO_FRAMEWORK_DEBUG_HIDDEN' ) && THE_SEO_FRAMEWORK_DEBUG_HIDDEN ? true : $this->the_seo_framework_debug_hidden;
84
+
85
+ $instance = \The_SEO_Framework\Debug::set_instance( $this->the_seo_framework_debug, $this->the_seo_framework_debug_hidden );
86
+ }
87
+
88
+ $this->the_seo_framework_use_transients = defined( 'THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS' ) && THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS ? false : $this->the_seo_framework_use_transients;
89
+
90
+ //* WP Core definition.
91
+ $this->script_debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? true : $this->script_debug;
92
+
93
+ }
94
+
95
+ /**
96
+ * Wrapper for function calling through parameters. The golden nugget.
97
+ *
98
+ * @since 2.2.2
99
+ * @access private
100
+ * @NOTE _doing_it_wrong notices go towards the callback. Unless this
101
+ * function is used wrongfully. Then the notice is about this function.
102
+ *
103
+ * @param array|string $callback the method array or function string.
104
+ * @param string $version the version of The SEO Framework the function is used.
105
+ * @param array|string $args The arguments passed to the function.
106
+ * @return mixed $output The function called.
107
+ */
108
+ public function call_function( $callback, $version = '', $args = array() ) {
109
+
110
+ $output = '';
111
+
112
+ /**
113
+ * Convert string/object to array
114
+ */
115
+ if ( is_object( $callback ) ) {
116
+ $function = array( $callback, '' );
117
+ } else {
118
+ $function = (array) $callback;
119
+ }
120
+
121
+ /**
122
+ * Convert string/object to array
123
+ */
124
+ if ( is_object( $args ) ) {
125
+ $args = array( $args, '' );
126
+ } else {
127
+ $args = (array) $args;
128
+ }
129
+
130
+ $class = reset( $function );
131
+ $method = next( $function );
132
+
133
+ /**
134
+ * Fetch method/function
135
+ */
136
+ if ( ( is_object( $class ) || is_string( $class ) ) && $class && is_string( $method ) && $method ) {
137
+ if ( get_class( $this ) === get_class( $class ) ) {
138
+ if ( method_exists( $this, $method ) ) {
139
+ if ( empty( $args ) ) {
140
+ // In-Object calling.
141
+ $output = call_user_func( array( $this, $method ) );
142
+ } else {
143
+ // In-Object calling.
144
+ $output = call_user_func_array( array( $this, $method ), $args );
145
+ }
146
+ } else {
147
+ $this->_inaccessible_p_or_m( \esc_html( get_class( $class ) . '->' . $method . '()' ), 'Class or Method not found.', \esc_html( $version ) );
148
+ }
149
+ } else {
150
+ if ( method_exists( $class, $method ) ) {
151
+ if ( empty( $args ) ) {
152
+ $output = call_user_func( array( $class, $method ) );
153
+ } else {
154
+ $output = call_user_func_array( array( $class, $method ), $args );
155
+ }
156
+ } else {
157
+ $this->_inaccessible_p_or_m( \esc_html( get_class( $class ) . '::' . $method . '()' ), 'Class or Method not found.', \esc_html( $version ) );
158
+ }
159
+ }
160
+ } elseif ( is_string( $class ) && $class ) {
161
+ //* Class is function.
162
+ $func = $class;
163
+
164
+ if ( empty( $args ) ) {
165
+ $output = call_user_func( $func );
166
+ } else {
167
+ $output = call_user_func_array( $func, $args );
168
+ }
169
+ } else {
170
+ $this->_doing_it_wrong( __METHOD__, 'Function needs to be called as a string.', \esc_html( $version ) );
171
+ }
172
+
173
+ return $output;
174
+ }
175
+
176
+ /**
177
+ * Mark a filter as deprecated and inform when it has been used.
178
+ *
179
+ * @since 2.8.0
180
+ * @see $this->_deprecated_function().
181
+ * @access private
182
+ *
183
+ * @param string $filter The function that was called.
184
+ * @param string $version The version of WordPress that deprecated the function.
185
+ * @param string $replacement Optional. The function that should have been called. Default null.
186
+ */
187
+ public function _deprecated_filter( $filter, $version, $replacement = null ) {
188
+ $instance = \The_SEO_Framework\Debug::get_instance();
189
+ $instance->_deprecated_filter( $filter, $version, $replacement );
190
+ }
191
+
192
+ /**
193
+ * Mark a function as deprecated and inform when it has been used.
194
+ * Taken from WordPress core, but added extra parameters and linguistic alterations.
195
+ * The current behavior is to trigger a user error if WP_DEBUG is true.
196
+ *
197
+ * @since 2.6.0
198
+ * @access private
199
+ *
200
+ * @param string $function The function that was called.
201
+ * @param string $version The version of WordPress that deprecated the function.
202
+ * @param string $replacement Optional. The function that should have been called. Default null.
203
+ */
204
+ public function _deprecated_function( $function, $version, $replacement = null ) {
205
+ $instance = \The_SEO_Framework\Debug::get_instance();
206
+ $instance->_deprecated_function( $function, $version, $replacement );
207
+ }
208
+
209
+ /**
210
+ * Mark a function as deprecated and inform when it has been used.
211
+ * Taken from WordPress core, but added extra parameters and linguistic alterations.
212
+ * The current behavior is to trigger a user error if WP_DEBUG is true.
213
+ *
214
+ * @since 2.6.0
215
+ * @access private
216
+ *
217
+ * @param string $function The function that was called.
218
+ * @param string $message A message explaining what has been done incorrectly.
219
+ * @param string $version The version of WordPress where the message was added.
220
+ */
221
+ public function _doing_it_wrong( $function, $message, $version = null ) {
222
+ $instance = \The_SEO_Framework\Debug::get_instance();
223
+ $instance->_doing_it_wrong( $function, $message, $version );
224
+ }
225
+
226
+ /**
227
+ * Mark a property or method inaccessible when it has been used.
228
+
229
+ * The current behavior is to trigger a user error if WP_DEBUG is true.
230
+ *
231
+ * @since 2.7.0
232
+ * @access private
233
+ *
234
+ * @param string $p_or_m The Property or Method.
235
+ * @param string $message A message explaining what has been done incorrectly.
236
+ */
237
+ public function _inaccessible_p_or_m( $p_or_m, $message = '' ) {
238
+ $instance = \The_SEO_Framework\Debug::get_instance();
239
+ $instance->_inaccessible_p_or_m( $p_or_m, $message );
240
+ }
241
+ /**
242
+ * Debug init. Simplified way of debugging a function, only works in admin.
243
+ *
244
+ * @since 2.6.0
245
+ * @access private
246
+ *
247
+ * @param string $method The function name.
248
+ * @param bool $store Whether to store the output in cache for next run to pick up on.
249
+ * @param double $debug_key Use $debug_key as variable, it's reserved.
250
+ * @param mixed function args.
251
+ * @return void early if debugging is disabled or when storing cache values.
252
+ */
253
+ public function debug_init( $method, $store, $debug_key = null ) {
254
+
255
+ $instance = \The_SEO_Framework\Debug::get_instance();
256
+
257
+ if ( func_num_args() >= 4 ) {
258
+ $instance->debug_init( $method, $store, $debug_key, array_slice( func_get_args(), 3 ) );
259
+ } else {
260
+ $instance->debug_init( $method, $store, $debug_key );
261
+ }
262
+ }
263
+ }
inc/classes/metaboxes.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,85 +23,31 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Metaboxes
23
  *
24
  * Outputs Network and Site SEO settings meta boxes
25
  *
26
- * @since 2.2.2
27
  */
28
- class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
29
-
30
- /**
31
- * Unserializing instances of this class is forbidden.
32
- */
33
- private function __wakeup() { }
34
-
35
- /**
36
- * Handle unapproachable invoked methods.
37
- */
38
- public function __call( $name, $arguments ) {
39
- parent::__call( $name, $arguments );
40
- }
41
 
42
  /**
43
  * Constructor, load parent constructor.
44
  */
45
- public function __construct() {
46
  parent::__construct();
47
  }
48
 
49
  /**
50
- * List of title separators.
51
- *
52
- * @since 2.6.0
53
- *
54
- * @todo add filter.
55
- * @todo check if filter can propagate within all functions.
56
  *
57
- * @return array Title separators.
58
- */
59
- public function get_separator_list() {
60
- return array(
61
- 'pipe' => '|',
62
- 'dash' => '-',
63
- 'ndash' => '&ndash;',
64
- 'mdash' => '&mdash;',
65
- 'bull' => '&bull;',
66
- 'middot' => '&middot;',
67
- 'lsaquo' => '&lsaquo;',
68
- 'rsaquo' => '&rsaquo;',
69
- 'frasl' => '&frasl;',
70
- 'laquo' => '&laquo;',
71
- 'raquo' => '&raquo;',
72
- 'le' => '&le;',
73
- 'ge' => '&ge;',
74
- 'lt' => '&lt;',
75
- 'gt' => '&gt;',
76
- );
77
- }
78
-
79
- /**
80
- * Returns array of Twitter Card Types
81
  *
 
82
  * @since 2.6.0
83
  *
84
- * @return array Twitter Card types.
85
- */
86
- public function get_twitter_card_types() {
87
- return array(
88
- 'summary' => 'summary',
89
- 'summary_large_image' => 'summary-large-image',
90
- 'photo' => 'photo',
91
- );
92
- }
93
-
94
- /**
95
- * Setting nav tab wrappers.
96
- * Outputs Tabs and settings content.
97
- *
98
  * @param string $id The Nav Tab ID
99
  * @param array $tabs the tab content {
100
  * $tabs = tab ID key = array(
@@ -106,11 +59,6 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
106
  * }
107
  * @param string $version the The SEO Framework version for debugging. May be emptied.
108
  * @param bool $use_tabs Whether to output tabs, only works when $tabs only has one count.
109
- *
110
- * @since 2.3.6
111
- *
112
- * @refactored
113
- * @since 2.6.0
114
  */
115
  public function nav_tab_wrapper( $id, $tabs = array(), $version = '2.3.6', $use_tabs = true ) {
116
 
@@ -118,39 +66,40 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
118
  $use_tabs = $use_tabs && count( $tabs ) > 1;
119
 
120
  /**
121
- * Start navigation.
122
  *
123
  * Don't output navigation if $use_tabs is false and the amount of tabs is 1 or lower.
124
  */
125
- if ( $use_tabs ) {
126
-
127
- ?><div class="tsf-nav-tab-wrapper hide-if-no-js" id="<?php echo esc_attr( $id . '-tabs-wrapper' ); ?>"><?php
 
128
  $count = 1;
129
- foreach ( $tabs as $tab => $value ) {
130
-
131
  $dashicon = isset( $value['dashicon'] ) ? $value['dashicon'] : '';
132
  $name = isset( $value['name'] ) ? $value['name'] : '';
133
 
134
  $checked = 1 === $count ? 'checked' : '';
135
- $the_id = esc_attr( $id . '-tab-' . $tab );
136
- $the_name = esc_attr( $id . '-tabs' );
137
-
138
- $label_class = $checked ? ' tsf-active-tab' : ''; // maybe
139
 
 
140
  ?>
141
  <div class="tsf-tab">
142
- <input type="radio" class="tsf-tabs-radio" id="<?php echo $the_id ?>" name="<?php echo $the_name ?>" <?php echo $checked ?>>
143
  <label for="<?php echo $the_id; ?>" class="tsf-nav-tab">
144
- <?php echo $dashicon ? '<span class="dashicons dashicons-' . esc_attr( $dashicon ) . ' tsf-dashicons-tabs"></span>' : ''; ?>
145
- <?php echo $name ? '<span class="tsf-nav-desktop">' . esc_attr( $name ) . '</span>' : ''; ?>
146
  </label>
147
  </div>
148
  <?php
149
 
150
  $count++;
151
- }
152
- ?></div><?php
153
- }
 
 
154
 
155
  /**
156
  * Start Content.
@@ -158,7 +107,7 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
158
  * The content is relative to the navigation, and uses CSS to become visible.
159
  */
160
  $count = 1;
161
- foreach ( $tabs as $tab => $value ) {
162
 
163
  $the_id = $id . '-tab-' . $tab . '-content';
164
  $the_name = $id . '-tabs-content';
@@ -166,51 +115,106 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
166
  //* Current tab for JS.
167
  $current = 1 === $count ? ' tsf-active-tab-content' : '';
168
 
169
- ?><div class="tsf-tabs-content <?php echo esc_attr( $the_name . $current ); ?>" id="<?php echo esc_attr( $the_id ); ?>" ><?php
 
 
170
  //* No-JS tabs.
171
- if ( $use_tabs ) {
172
  $dashicon = isset( $value['dashicon'] ) ? $value['dashicon'] : '';
173
  $name = isset( $value['name'] ) ? $value['name'] : '';
174
 
175
  ?>
176
- <div class="hide-if-js seoframework-content-no-js">
177
  <div class="tsf-tab tsf-tab-no-js">
178
  <span class="tsf-nav-tab tsf-active-tab">
179
- <?php echo $dashicon ? '<span class="dashicons dashicons-' . esc_attr( $dashicon ) . ' tsf-dashicons-tabs"></span>' : ''; ?>
180
- <?php echo $name ? '<span>' . esc_attr( $name ) . '</span>' : ''; ?>
181
  </span>
182
  </div>
183
  </div>
184
  <?php
185
- }
186
 
187
  $callback = isset( $value['callback'] ) ? $value['callback'] : '';
188
 
189
- if ( $callback ) {
190
  $params = isset( $value['args'] ) ? $value['args'] : '';
191
  $output = $this->call_function( $callback, $version, $params );
192
  echo $output;
193
- }
194
- ?></div><?php
 
 
195
 
196
  $count++;
197
- }
 
198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  }
200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  /**
202
  * Title meta box on the Site SEO Settings page.
203
  *
204
  * @since 2.2.2
205
- * @see $this->title_metabox() Callback for Title Settings box.
206
  *
207
  * @param object|null $post The current post object.
208
  * @param array $args The metabox arguments.
209
  */
210
  public function title_metabox( $post = null, $args = array() ) {
211
- do_action( 'the_seo_framework_title_metabox_before' );
212
  $this->get_view( 'metaboxes/title-metabox', $args );
213
- do_action( 'the_seo_framework_title_metabox_after' );
214
  }
215
 
216
  /**
@@ -263,9 +267,9 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
263
  * @param array $args The metabox arguments.
264
  */
265
  public function description_metabox( $post = null, $args = array() ) {
266
- do_action( 'the_seo_framework_description_metabox_before' );
267
  $this->get_view( 'metaboxes/description-metabox', $args );
268
- do_action( 'the_seo_framework_description_metabox_after' );
269
  }
270
 
271
  /**
@@ -297,9 +301,9 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
297
  * @param array $args The metabox arguments.
298
  */
299
  public function robots_metabox( $post = null, $args = array() ) {
300
- do_action( 'the_seo_framework_robots_metabox_before' );
301
  $this->get_view( 'metaboxes/robots-metabox', $args );
302
- do_action( 'the_seo_framework_robots_metabox_after' );
303
  }
304
 
305
  /**
@@ -338,9 +342,9 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
338
  * @param array $args The navigation tabs args.
339
  */
340
  public function homepage_metabox( $post = null, $args = array() ) {
341
- do_action( 'the_seo_framework_homepage_metabox_before' );
342
  $this->get_view( 'metaboxes/homepage-metabox', $args );
343
- do_action( 'the_seo_framework_homepage_metabox_after' );
344
  }
345
 
346
  /**
@@ -382,9 +386,9 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
382
  * @param array $args the social tabs arguments.
383
  */
384
  public function social_metabox( $post = null, $args = array() ) {
385
- do_action( 'the_seo_framework_social_metabox_before' );
386
  $this->get_view( 'metaboxes/social-metabox', $args );
387
- do_action( 'the_seo_framework_social_metabox_after' );
388
  }
389
 
390
  /**
@@ -428,16 +432,6 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
428
  $this->get_view( 'metaboxes/social-metabox', array(), 'postdates' );
429
  }
430
 
431
- /**
432
- * Social Metabox Relationships Tab output.
433
- *
434
- * @since 2.2.4
435
- * @see $this->social_metabox() Callback for Social Settings box.
436
- */
437
- public function social_metabox_relationships_tab() {
438
- $this->get_view( 'metaboxes/social-metabox', array(), 'relationships' );
439
- }
440
-
441
  /**
442
  * Webmaster meta box on the Site SEO Settings page.
443
  *
@@ -447,53 +441,9 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
447
  * @param array $args the social tabs arguments.
448
  */
449
  public function webmaster_metabox( $post = null, $args = array() ) {
450
- do_action( 'the_seo_framework_webmaster_metabox_before' );
451
  $this->get_view( 'metaboxes/webmaster-metabox', $args );
452
- do_action( 'the_seo_framework_webmaster_metabox_after' );
453
- }
454
-
455
- /**
456
- * Knowlegde Graph metabox on the Site SEO Settings page.
457
- *
458
- * @since 2.2.8
459
- *
460
- * @param object|null $post The current post object.
461
- * @param array $args the social tabs arguments.
462
- */
463
- public function knowledge_metabox( $post = null, $args = array() ) {
464
- do_action( 'the_seo_framework_knowledge_metabox_before' );
465
- $this->get_view( 'metaboxes/knowledge-metabox', $args );
466
- do_action( 'the_seo_framework_knowledge_metabox_after' );
467
- }
468
-
469
- /**
470
- * Knowledge Graph Metabox General Tab output.
471
- *
472
- * @since 2.2.8
473
- * @see $this->knowledge_metabox() Callback for Knowledge Graph Settings box.
474
- */
475
- public function knowledge_metabox_general_tab() {
476
- $this->get_view( 'metaboxes/knowledge-metabox', array(), 'general' );
477
- }
478
-
479
- /**
480
- * Knowledge Graph Metabox About Tab output.
481
- *
482
- * @since 2.2.8
483
- * @see $this->knowledge_metabox() Callback for Knowledge Graph Settings box.
484
- */
485
- public function knowledge_metabox_about_tab() {
486
- $this->get_view( 'metaboxes/knowledge-metabox', array(), 'about' );
487
- }
488
-
489
- /**
490
- * Knowledge Graph Metabox Social Tab output.
491
- *
492
- * @since 2.2.8
493
- * @see $this->knowledge_metabox() Callback for Knowledge Graph Settings box.
494
- */
495
- public function knowledge_metabox_social_tab() {
496
- $this->get_view( 'metaboxes/knowledge-metabox', array(), 'social' );
497
  }
498
 
499
  /**
@@ -506,9 +456,9 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
506
  * @param array $args the social tabs arguments.
507
  */
508
  public function sitemaps_metabox( $post = null, $args = array() ) {
509
- do_action( 'the_seo_framework_sitemaps_metabox_before' );
510
  $this->get_view( 'metaboxes/sitemaps-metabox', $args );
511
- do_action( 'the_seo_framework_sitemaps_metabox_after' );
512
  }
513
 
514
  /**
@@ -551,6 +501,16 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
551
  $this->get_view( 'metaboxes/sitemaps-metabox', array(), 'notify' );
552
  }
553
 
 
 
 
 
 
 
 
 
 
 
554
  /**
555
  * Feed Metabox on the Site SEO Settings page.
556
  *
@@ -560,9 +520,9 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
560
  * @param array $args the social tabs arguments.
561
  */
562
  public function feed_metabox( $post = null, $args = array() ) {
563
- do_action( 'the_seo_framework_feed_metabox_before' );
564
  $this->get_view( 'metaboxes/feed-metabox', $args );
565
- do_action( 'the_seo_framework_feed_metabox_after' );
566
  }
567
 
568
  /**
@@ -574,8 +534,38 @@ class AutoDescription_Metaboxes extends AutoDescription_Siteoptions {
574
  * @param array $args the social tabs arguments.
575
  */
576
  public function schema_metabox( $post = null, $args = array() ) {
577
- do_action( 'the_seo_framework_schema_metabox_before' );
578
  $this->get_view( 'metaboxes/schema-metabox', $args );
579
- do_action( 'the_seo_framework_schema_metabox_after' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
  }
581
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Metaboxes
28
  *
29
  * Outputs Network and Site SEO settings meta boxes
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Metaboxes extends Site_Options {
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  /**
36
  * Constructor, load parent constructor.
37
  */
38
+ protected function __construct() {
39
  parent::__construct();
40
  }
41
 
42
  /**
43
+ * Setting nav tab wrappers.
44
+ * Outputs Tabs and settings content.
 
 
 
 
45
  *
46
+ * @since 2.3.6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  *
48
+ * @refactored
49
  * @since 2.6.0
50
  *
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  * @param string $id The Nav Tab ID
52
  * @param array $tabs the tab content {
53
  * $tabs = tab ID key = array(
59
  * }
60
  * @param string $version the The SEO Framework version for debugging. May be emptied.
61
  * @param bool $use_tabs Whether to output tabs, only works when $tabs only has one count.
 
 
 
 
 
62
  */
63
  public function nav_tab_wrapper( $id, $tabs = array(), $version = '2.3.6', $use_tabs = true ) {
64
 
66
  $use_tabs = $use_tabs && count( $tabs ) > 1;
67
 
68
  /**
69
+ * Start navigational tabs.
70
  *
71
  * Don't output navigation if $use_tabs is false and the amount of tabs is 1 or lower.
72
  */
73
+ if ( $use_tabs ) :
74
+ ?>
75
+ <div class="tsf-nav-tab-wrapper hide-if-no-js" id="<?php echo \esc_attr( $id . '-tabs-wrapper' ); ?>">
76
+ <?php
77
  $count = 1;
78
+ foreach ( $tabs as $tab => $value ) :
 
79
  $dashicon = isset( $value['dashicon'] ) ? $value['dashicon'] : '';
80
  $name = isset( $value['name'] ) ? $value['name'] : '';
81
 
82
  $checked = 1 === $count ? 'checked' : '';
83
+ $the_id = \esc_attr( $id . '-tab-' . $tab );
84
+ $the_name = \esc_attr( $id . '-tabs' );
 
 
85
 
86
+ //* All output below is escaped.
87
  ?>
88
  <div class="tsf-tab">
89
+ <input type="radio" class="tsf-tabs-radio" id="<?php echo $the_id; ?>" name="<?php echo $the_name; ?>" <?php echo $checked; ?>>
90
  <label for="<?php echo $the_id; ?>" class="tsf-nav-tab">
91
+ <?php echo $dashicon ? '<span class="dashicons dashicons-' . \esc_attr( $dashicon ) . ' tsf-dashicons-tabs"></span>' : ''; ?>
92
+ <?php echo $name ? '<span class="tsf-nav-desktop">' . \esc_attr( $name ) . '</span>' : ''; ?>
93
  </label>
94
  </div>
95
  <?php
96
 
97
  $count++;
98
+ endforeach;
99
+ ?>
100
+ </div>
101
+ <?php
102
+ endif;
103
 
104
  /**
105
  * Start Content.
107
  * The content is relative to the navigation, and uses CSS to become visible.
108
  */
109
  $count = 1;
110
+ foreach ( $tabs as $tab => $value ) :
111
 
112
  $the_id = $id . '-tab-' . $tab . '-content';
113
  $the_name = $id . '-tabs-content';
115
  //* Current tab for JS.
116
  $current = 1 === $count ? ' tsf-active-tab-content' : '';
117
 
118
+ ?>
119
+ <div class="tsf-tabs-content <?php echo \esc_attr( $the_name . $current ); ?>" id="<?php echo \esc_attr( $the_id ); ?>" >
120
+ <?php
121
  //* No-JS tabs.
122
+ if ( $use_tabs ) :
123
  $dashicon = isset( $value['dashicon'] ) ? $value['dashicon'] : '';
124
  $name = isset( $value['name'] ) ? $value['name'] : '';
125
 
126
  ?>
127
+ <div class="hide-if-js tsf-content-no-js">
128
  <div class="tsf-tab tsf-tab-no-js">
129
  <span class="tsf-nav-tab tsf-active-tab">
130
+ <?php echo $dashicon ? '<span class="dashicons dashicons-' . \esc_attr( $dashicon ) . ' tsf-dashicons-tabs"></span>' : ''; ?>
131
+ <?php echo $name ? '<span>' . \esc_attr( $name ) . '</span>' : ''; ?>
132
  </span>
133
  </div>
134
  </div>
135
  <?php
136
+ endif;
137
 
138
  $callback = isset( $value['callback'] ) ? $value['callback'] : '';
139
 
140
+ if ( $callback ) :
141
  $params = isset( $value['args'] ) ? $value['args'] : '';
142
  $output = $this->call_function( $callback, $version, $params );
143
  echo $output;
144
+ endif;
145
+ ?>
146
+ </div>
147
+ <?php
148
 
149
  $count++;
150
+ endforeach;
151
+ }
152
 
153
+ /**
154
+ * Outputs General Settings meta box on the Site SEO Settings page.
155
+ *
156
+ * @since 2.8.0
157
+ *
158
+ * @param object|null $post The current post object.
159
+ * @param array $args The metabox arguments.
160
+ */
161
+ public function general_metabox( $post = null, $args = array() ) {
162
+ \do_action( 'the_seo_framework_general_metabox_before' );
163
+ $this->get_view( 'metaboxes/general-metabox', $args );
164
+ \do_action( 'the_seo_framework_general_metabox_after' );
165
+ }
166
+
167
+ /**
168
+ * Outputs General Settings meta box general tab.
169
+ *
170
+ * @since 2.8.0
171
+ * @see $this->general_metabox() : Callback for General Settings box.
172
+ */
173
+ public function general_metabox_general_tab() {
174
+ $this->get_view( 'metaboxes/general-metabox', array(), 'general' );
175
  }
176
 
177
+ /**
178
+ * Outputs General Settings meta box layout tab.
179
+ *
180
+ * @since 2.8.0
181
+ * @see $this->general_metabox() : Callback for General Settings box.
182
+ */
183
+ public function general_metabox_layout_tab() {
184
+ $this->get_view( 'metaboxes/general-metabox', array(), 'layout' );
185
+ }
186
+
187
+ /**
188
+ * Outputs General Settings meta box performance tab.
189
+ *
190
+ * @since 2.8.0
191
+ * @see $this->general_metabox() : Callback for General Settings box.
192
+ */
193
+ public function general_metabox_performance_tab() {
194
+ $this->get_view( 'metaboxes/general-metabox', array(), 'performance' );
195
+ }
196
+
197
+ /**
198
+ * Outputs General Settings meta box canonical tab.
199
+ *
200
+ * @since 2.8.0
201
+ * @see $this->general_metabox() : Callback for General Settings box.
202
+ */
203
+ public function general_metabox_canonical_tab() {
204
+ $this->get_view( 'metaboxes/general-metabox', array(), 'canonical' );
205
+ }
206
  /**
207
  * Title meta box on the Site SEO Settings page.
208
  *
209
  * @since 2.2.2
 
210
  *
211
  * @param object|null $post The current post object.
212
  * @param array $args The metabox arguments.
213
  */
214
  public function title_metabox( $post = null, $args = array() ) {
215
+ \do_action( 'the_seo_framework_title_metabox_before' );
216
  $this->get_view( 'metaboxes/title-metabox', $args );
217
+ \do_action( 'the_seo_framework_title_metabox_after' );
218
  }
219
 
220
  /**
267
  * @param array $args The metabox arguments.
268
  */
269
  public function description_metabox( $post = null, $args = array() ) {
270
+ \do_action( 'the_seo_framework_description_metabox_before' );
271
  $this->get_view( 'metaboxes/description-metabox', $args );
272
+ \do_action( 'the_seo_framework_description_metabox_after' );
273
  }
274
 
275
  /**
301
  * @param array $args The metabox arguments.
302
  */
303
  public function robots_metabox( $post = null, $args = array() ) {
304
+ \do_action( 'the_seo_framework_robots_metabox_before' );
305
  $this->get_view( 'metaboxes/robots-metabox', $args );
306
+ \do_action( 'the_seo_framework_robots_metabox_after' );
307
  }
308
 
309
  /**
342
  * @param array $args The navigation tabs args.
343
  */
344
  public function homepage_metabox( $post = null, $args = array() ) {
345
+ \do_action( 'the_seo_framework_homepage_metabox_before' );
346
  $this->get_view( 'metaboxes/homepage-metabox', $args );
347
+ \do_action( 'the_seo_framework_homepage_metabox_after' );
348
  }
349
 
350
  /**
386
  * @param array $args the social tabs arguments.
387
  */
388
  public function social_metabox( $post = null, $args = array() ) {
389
+ \do_action( 'the_seo_framework_social_metabox_before' );
390
  $this->get_view( 'metaboxes/social-metabox', $args );
391
+ \do_action( 'the_seo_framework_social_metabox_after' );
392
  }
393
 
394
  /**
432
  $this->get_view( 'metaboxes/social-metabox', array(), 'postdates' );
433
  }
434
 
 
 
 
 
 
 
 
 
 
 
435
  /**
436
  * Webmaster meta box on the Site SEO Settings page.
437
  *
441
  * @param array $args the social tabs arguments.
442
  */
443
  public function webmaster_metabox( $post = null, $args = array() ) {
444
+ \do_action( 'the_seo_framework_webmaster_metabox_before' );
445
  $this->get_view( 'metaboxes/webmaster-metabox', $args );
446
+ \do_action( 'the_seo_framework_webmaster_metabox_after' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  }
448
 
449
  /**
456
  * @param array $args the social tabs arguments.
457
  */
458
  public function sitemaps_metabox( $post = null, $args = array() ) {
459
+ \do_action( 'the_seo_framework_sitemaps_metabox_before' );
460
  $this->get_view( 'metaboxes/sitemaps-metabox', $args );
461
+ \do_action( 'the_seo_framework_sitemaps_metabox_after' );
462
  }
463
 
464
  /**
501
  $this->get_view( 'metaboxes/sitemaps-metabox', array(), 'notify' );
502
  }
503
 
504
+ /**
505
+ * Sitemaps Metabox Style Tab output.
506
+ *
507
+ * @since 2.8.0
508
+ * @see $this->sitemaps_metabox() Callback for Sitemaps Settings box.
509
+ */
510
+ public function sitemaps_metabox_style_tab() {
511
+ $this->get_view( 'metaboxes/sitemaps-metabox', array(), 'style' );
512
+ }
513
+
514
  /**
515
  * Feed Metabox on the Site SEO Settings page.
516
  *
520
  * @param array $args the social tabs arguments.
521
  */
522
  public function feed_metabox( $post = null, $args = array() ) {
523
+ \do_action( 'the_seo_framework_feed_metabox_before' );
524
  $this->get_view( 'metaboxes/feed-metabox', $args );
525
+ \do_action( 'the_seo_framework_feed_metabox_after' );
526
  }
527
 
528
  /**
534
  * @param array $args the social tabs arguments.
535
  */
536
  public function schema_metabox( $post = null, $args = array() ) {
537
+ \do_action( 'the_seo_framework_schema_metabox_before' );
538
  $this->get_view( 'metaboxes/schema-metabox', $args );
539
+ \do_action( 'the_seo_framework_schema_metabox_after' );
540
+ }
541
+
542
+ /**
543
+ * Schema Metabox General Tab output.
544
+ *
545
+ * @since 2.8.0
546
+ * @see $this->schema_metabox() Callback for Schema.org Settings box.
547
+ */
548
+ public function schema_metabox_general_tab() {
549
+ $this->get_view( 'metaboxes/schema-metabox', array(), 'general' );
550
+ }
551
+
552
+ /**
553
+ * Schema Metabox Structure Tab output.
554
+ *
555
+ * @since 2.8.0
556
+ * @see $this->schema_metabox() Callback for Schema.org Settings box.
557
+ */
558
+ public function schema_metabox_structure_tab() {
559
+ $this->get_view( 'metaboxes/schema-metabox', array(), 'structure' );
560
+ }
561
+
562
+ /**
563
+ * Schema Metabox PResence Tab output.
564
+ *
565
+ * @since 2.8.0
566
+ * @see $this->schema_metabox() Callback for Schema.org Settings box.
567
+ */
568
+ public function schema_metabox_presence_tab() {
569
+ $this->get_view( 'metaboxes/schema-metabox', array(), 'presence' );
570
  }
571
  }
inc/classes/{postdata.class.php → post-data.class.php} RENAMED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,87 +23,141 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_PostData
23
  *
24
  * Holds Post data.
25
  *
26
  * @since 2.1.6
27
  */
28
- class AutoDescription_PostData extends AutoDescription_Detect {
29
-
30
- /**
31
- * Unserializing instances of this class is forbidden.
32
- */
33
- private function __wakeup() { }
34
 
35
  /**
36
- * Handle unapproachable invoked methods.
37
  */
38
- public function __call( $name, $arguments ) {
39
- parent::__call( $name, $arguments );
40
  }
41
 
42
  /**
43
- * Constructor, load parent constructor
 
 
 
 
 
 
 
 
 
 
44
  */
45
- public function __construct() {
46
- parent::__construct();
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
- add_action( 'save_post', array( $this, 'inpost_seo_save' ), 1, 2 );
 
 
 
 
 
 
 
49
  }
50
 
51
  /**
52
  * Save the SEO settings when we save a post or page.
53
  * Some values get sanitized, the rest are pulled from identically named subkeys in the $_POST['autodescription'] array.
54
  *
55
- * @uses $this->save_custom_fields() Perform checks and saves post meta / custom field data to a post or page.
56
- *
57
  * @since 2.0.0
 
58
  *
59
- * @param integer $post_id Post ID.
60
- * @param stdClass $post Post object.
61
  * @return mixed Returns post id if permissions incorrect, null if doing autosave, ajax or future post, false if update
62
  * or delete failed, and true on success.
63
  */
64
  public function inpost_seo_save( $post_id, $post ) {
65
 
66
- if ( ! isset( $_POST['autodescription'] ) )
 
67
  return;
68
 
69
  /**
70
  * Merge user submitted options with fallback defaults
71
  * Passes through nonce at the end of the function.
72
  */
73
- $data = wp_parse_args( $_POST['autodescription'], array(
74
  '_genesis_title' => '',
75
  '_genesis_description' => '',
76
  '_genesis_canonical_uri' => '',
77
  'redirect' => '',
 
 
78
  '_genesis_noindex' => 0,
79
  '_genesis_nofollow' => 0,
80
  '_genesis_noarchive' => 0,
81
  'exclude_local_search' => 0,
82
  ) );
83
 
84
- foreach ( (array) $data as $key => $value ) {
85
- //* Sanitize the title
86
- if ( '_genesis_title' === $key )
87
- $data[ $key ] = trim( strip_tags( $value ) );
88
-
89
- //* Sanitize the description
90
- if ( '_genesis_description' === $key )
91
- $data[ $key ] = $this->s_description( $value );
92
-
93
- //* Sanitize the URL. Make sure it's an absolute URL
94
- if ( 'redirect' === $key )
95
- $data[ $key ] = $this->s_redirect_url( $value );
96
-
97
- }
98
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  $this->save_custom_fields( $data, $this->inpost_nonce_field, $this->inpost_nonce_name, $post );
 
100
  }
101
 
102
  /**
@@ -126,7 +187,12 @@ class AutoDescription_PostData extends AutoDescription_Detect {
126
  if ( ! isset( $_POST[ $nonce_name ] ) || ! wp_verify_nonce( $_POST[ $nonce_name ], $nonce_action ) )
127
  return;
128
 
129
- //* Don't try to save the data under autosave, ajax, or future post.
 
 
 
 
 
130
  if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
131
  return;
132
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
@@ -135,38 +201,43 @@ class AutoDescription_PostData extends AutoDescription_Detect {
135
  return;
136
 
137
  //* Grab the post object
138
- $post = get_post( $post );
139
 
140
- //* Don't save if WP is creating a revision (same as DOING_AUTOSAVE?)
141
- if ( 'revision' === get_post_type( $post ) )
 
 
 
142
  return;
143
 
144
  //* Check that the user is allowed to edit the post
145
- if ( ! current_user_can( 'edit_post', $post->ID ) )
146
  return;
147
 
148
  //* Cycle through $data, insert value or delete field
149
  foreach ( (array) $data as $field => $value ) {
150
  //* Save $value, or delete if the $value is empty
151
- if ( $value )
152
- update_post_meta( $post->ID, $field, $value );
153
- else
154
- delete_post_meta( $post->ID, $field );
 
155
  }
156
-
157
  }
158
 
159
  /**
160
  * Fetches or parses the excerpt of the post.
161
  *
162
  * @since 1.0.0
 
163
  *
164
  * @param string $excerpt the Excerpt.
165
  * @param int $the_id The Post ID.
166
  * @param int $tt_id The Taxonomy Term ID.
 
167
  * @return string The escaped Excerpt.
168
  */
169
- public function get_excerpt_by_id( $excerpt = '', $the_id = '', $tt_id = '' ) {
170
 
171
  if ( empty( $excerpt ) )
172
  $excerpt = $this->fetch_excerpt( $the_id, $tt_id );
@@ -175,17 +246,10 @@ class AutoDescription_PostData extends AutoDescription_Detect {
175
  if ( '' === $excerpt )
176
  return '';
177
 
178
- /**
179
- * Applies filters 'the_seo_framework_allow_excerpt_shortcode_tags' : boolean
180
- * @since 2.6.6.1
181
- */
182
- if ( apply_filters( 'the_seo_framework_allow_excerpt_shortcode_tags', false ) && false === $this->is_feed() ) {
183
- $excerpt = wp_strip_all_tags( $excerpt );
184
- } else {
185
- $excerpt = wp_strip_all_tags( strip_shortcodes( $excerpt ) );
186
- }
187
 
188
- return $this->s_description( $excerpt );
189
  }
190
 
191
  /**
@@ -214,8 +278,7 @@ class AutoDescription_PostData extends AutoDescription_Detect {
214
  if ( ! empty( $post->post_excerpt ) ) {
215
  $excerpt = $post->post_excerpt;
216
  } elseif ( isset( $post->post_content ) ) {
217
- $uses_builder = $this->uses_page_builder( $post->ID );
218
- $excerpt = $uses_builder ? '' : $post->post_content;
219
  } else {
220
  $excerpt = '';
221
  }
@@ -251,38 +314,38 @@ class AutoDescription_PostData extends AutoDescription_Detect {
251
  if ( '' !== $the_id ) {
252
  if ( $this->is_blog_page( $the_id ) ) {
253
  $args = array(
254
- 'posts_per_page' => 1,
255
- 'offset' => 0,
256
- 'category' => '',
257
- 'category_name' => '',
258
- 'orderby' => 'date',
259
- 'order' => 'DESC',
260
- 'post_type' => 'post',
261
- 'post_status' => 'publish',
262
- 'cache_results' => false,
263
  );
264
 
265
- $post = get_posts( $args );
266
  } else {
267
- $post = get_post( $the_id );
268
  }
269
  } elseif ( '' !== $tt_id ) {
270
  /**
271
  * @since 2.3.3 Match the descriptions in admin as on the front end.
272
  */
273
  $args = array(
274
- 'posts_per_page' => 1,
275
- 'offset' => 0,
276
- 'category' => $tt_id,
277
- 'category_name' => '',
278
- 'post_type' => 'post',
279
- 'post_status' => 'publish',
280
- 'cache_results' => false,
281
  );
282
 
283
- $post = get_posts( $args );
284
  } else {
285
- $post = get_post( $the_id );
286
  }
287
 
288
  /**
@@ -303,7 +366,7 @@ class AutoDescription_PostData extends AutoDescription_Detect {
303
  * @since 2.6.6
304
  */
305
  if ( ARRAY_A === $output || ARRAY_N === $output ) {
306
- $_post = WP_Post::get_instance( $post );
307
  $post = $_post->to_array();
308
 
309
  if ( ARRAY_N === $output )
@@ -321,6 +384,8 @@ class AutoDescription_PostData extends AutoDescription_Detect {
321
  * @global object $wpdb
322
  * @global int $blog_id
323
  *
 
 
324
  * @return int Latest Post ID.
325
  */
326
  public function get_latest_post_id() {
@@ -337,12 +402,12 @@ class AutoDescription_PostData extends AutoDescription_Detect {
337
  $page_id = $this->object_cache_get( $latest_posts_key );
338
  if ( false === $page_id ) {
339
 
340
- // Prepare array
341
- $post_type = esc_sql( array( 'post', 'page' ) );
342
  $post_type_in_string = "'" . implode( "','", $post_type ) . "'";
343
 
344
- // Prepare array
345
- $post_status = esc_sql( array( 'publish', 'future', 'pending' ) );
346
  $post_status_in_string = "'" . implode( "','", $post_status ) . "'";
347
 
348
  $sql = $wpdb->prepare(
@@ -375,9 +440,9 @@ class AutoDescription_PostData extends AutoDescription_Detect {
375
  */
376
  public function get_post_content( $id = 0 ) {
377
 
378
- $id = $id ? $id : $this->get_the_real_ID();
379
 
380
- $content = get_post_field( 'post_content', $id );
381
 
382
  if ( is_string( $content ) )
383
  return $content;
@@ -402,7 +467,7 @@ class AutoDescription_PostData extends AutoDescription_Detect {
402
  */
403
  public function uses_page_builder( $post_id ) {
404
 
405
- $meta = get_post_meta( $post_id );
406
 
407
  /**
408
  * Applies filters 'the_seo_framework_detect_page_builder' : boolean
@@ -413,7 +478,7 @@ class AutoDescription_PostData extends AutoDescription_Detect {
413
  * @param int $post_id The current Post ID.
414
  * @param array $meta The current post meta.
415
  */
416
- $detected = (bool) apply_filters( 'the_seo_framework_detect_page_builder', false, $post_id, $meta );
417
 
418
  if ( $detected )
419
  return true;
@@ -421,18 +486,44 @@ class AutoDescription_PostData extends AutoDescription_Detect {
421
  if ( empty( $meta ) )
422
  return false;
423
 
424
- if ( isset( $meta['_et_pb_use_builder'][0] ) && 'on' === $meta['_et_pb_use_builder'][0] && defined( 'ET_BUILDER_VERSION' ) )
425
  //* Divi Builder by Elegant Themes
426
  return true;
427
- elseif ( isset( $meta['_wpb_vc_js_status'][0] ) && 'true' === $meta['_wpb_vc_js_status'][0] && defined( 'WPB_VC_VERSION' ) )
428
  //* Visual Composer by WPBakery
429
  return true;
430
- elseif ( isset( $meta['panels_data'][0] ) && '' !== $meta['panels_data'][0] && defined( 'SITEORIGIN_PANELS_VERSION' ) )
431
  //* Page Builder by SiteOrigin
432
  return true;
433
- elseif ( isset( $meta['_fl_builder_enabled'][0] ) && '1' === $meta['_fl_builder_enabled'][0] && defined( 'FL_BUILDER_VERSION' ) )
434
  //* Beaver Builder by Fastline Media
435
  return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
436
 
437
  return false;
438
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Post_Data
28
  *
29
  * Holds Post data.
30
  *
31
  * @since 2.1.6
32
  */
33
+ class Post_Data extends Detect {
 
 
 
 
 
34
 
35
  /**
36
+ * Constructor, load parent constructor
37
  */
38
+ protected function __construct() {
39
+ parent::__construct();
40
  }
41
 
42
  /**
43
+ * Return custom field post meta data.
44
+ *
45
+ * Return only the first value of custom field. Return false if field is
46
+ * blank or not set.
47
+ *
48
+ * @since 2.0.0
49
+ * @staticvar array $field_cache
50
+ *
51
+ * @param string $field Custom field key.
52
+ * @param int $post_id The post ID
53
+ * @return string|boolean Return value or false on failure.
54
  */
55
+ public function get_custom_field( $field, $post_id = null ) {
56
+
57
+ //* If field is falsy, get_post_meta() will return an array.
58
+ if ( ! $field )
59
+ return false;
60
+
61
+ static $field_cache = array();
62
+
63
+ if ( isset( $field_cache[ $field ][ $post_id ] ) )
64
+ return $field_cache[ $field ][ $post_id ];
65
+
66
+ if ( empty( $post_id ) )
67
+ $post_id = $this->get_the_real_ID();
68
+
69
+ $custom_field = \get_post_meta( $post_id, $field, true );
70
 
71
+ //* If custom field is empty, empty cache..
72
+ if ( empty( $custom_field ) )
73
+ $field_cache[ $field ][ $post_id ] = '';
74
+
75
+ //* Render custom field, slashes stripped, sanitized if string
76
+ $field_cache[ $field ][ $post_id ] = is_array( $custom_field ) ? \stripslashes_deep( $custom_field ) : stripslashes( $custom_field );
77
+
78
+ return $field_cache[ $field ][ $post_id ];
79
  }
80
 
81
  /**
82
  * Save the SEO settings when we save a post or page.
83
  * Some values get sanitized, the rest are pulled from identically named subkeys in the $_POST['autodescription'] array.
84
  *
 
 
85
  * @since 2.0.0
86
+ * @uses $this->save_custom_fields() : Perform security checks and saves post meta / custom field data to a post or page.
87
  *
88
+ * @param integer $post_id Post ID.
89
+ * @param object $post Post object.
90
  * @return mixed Returns post id if permissions incorrect, null if doing autosave, ajax or future post, false if update
91
  * or delete failed, and true on success.
92
  */
93
  public function inpost_seo_save( $post_id, $post ) {
94
 
95
+ //* Nonce is done at the end of this function.
96
+ if ( empty( $_POST['autodescription'] ) )
97
  return;
98
 
99
  /**
100
  * Merge user submitted options with fallback defaults
101
  * Passes through nonce at the end of the function.
102
  */
103
+ $data = \wp_parse_args( $_POST['autodescription'], array(
104
  '_genesis_title' => '',
105
  '_genesis_description' => '',
106
  '_genesis_canonical_uri' => '',
107
  'redirect' => '',
108
+ '_social_image_url' => '',
109
+ '_social_image_id' => 0,
110
  '_genesis_noindex' => 0,
111
  '_genesis_nofollow' => 0,
112
  '_genesis_noarchive' => 0,
113
  'exclude_local_search' => 0,
114
  ) );
115
 
116
+ foreach ( (array) $data as $key => $value ) :
117
+ switch ( $key ) :
118
+ case '_genesis_title' :
119
+ $data[ $key ] = $this->s_title_raw( $value );
120
+ continue 2;
121
+
122
+ case '_genesis_description' :
123
+ $data[ $key ] = $this->s_description_raw( $value );
124
+ continue 2;
125
+
126
+ case '_genesis_canonical_uri' :
127
+ case '_social_image_url' :
128
+ /**
129
+ * Remove unwanted query parameters. They're allowed by Google, but very much rather not.
130
+ * Also, they will only cause bugs.
131
+ * Query parameters are also only used when no pretty permalinks are used. Which is bad.
132
+ */
133
+ $data[ $key ] = $this->s_url( $value );
134
+ continue 2;
135
+
136
+ case '_social_image_id' :
137
+ //* Bound to _social_image_url.
138
+ $data[ $key ] = $data['_social_image_url'] ? $this->s_absint( $value ) : 0;
139
+ continue 2;
140
+
141
+ case 'redirect' :
142
+ //* Let's keep this as the output really is.
143
+ $data[ $key ] = $this->s_redirect_url( $value );
144
+ continue 2;
145
+
146
+ case '_genesis_noindex' :
147
+ case '_genesis_nofollow' :
148
+ case '_genesis_noarchive' :
149
+ case 'exclude_local_search' :
150
+ $data[ $key ] = $this->s_one_zero( $value );
151
+ continue 2;
152
+
153
+ default :
154
+ break;
155
+ endswitch;
156
+ endforeach;
157
+
158
+ //* Perform nonce and save fields.
159
  $this->save_custom_fields( $data, $this->inpost_nonce_field, $this->inpost_nonce_name, $post );
160
+
161
  }
162
 
163
  /**
187
  if ( ! isset( $_POST[ $nonce_name ] ) || ! wp_verify_nonce( $_POST[ $nonce_name ], $nonce_action ) )
188
  return;
189
 
190
+ /**
191
+ * Don't try to save the data under autosave, ajax, or future post.
192
+ * @TODO find a way to maintain revisions:
193
+ * @link https://github.com/sybrew/the-seo-framework/issues/48
194
+ * @link https://johnblackbourn.com/post-meta-revisions-wordpress
195
+ */
196
  if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
197
  return;
198
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
201
  return;
202
 
203
  //* Grab the post object
204
+ $post = \get_post( $post );
205
 
206
+ /**
207
+ * Don't save if WP is creating a revision (same as DOING_AUTOSAVE?)
208
+ * @todo @see wp_is_post_revision(), which also returns the post revision ID...
209
+ */
210
+ if ( 'revision' === \get_post_type( $post ) )
211
  return;
212
 
213
  //* Check that the user is allowed to edit the post
214
+ if ( ! \current_user_can( 'edit_post', $post->ID ) )
215
  return;
216
 
217
  //* Cycle through $data, insert value or delete field
218
  foreach ( (array) $data as $field => $value ) {
219
  //* Save $value, or delete if the $value is empty
220
+ if ( $value ) {
221
+ \update_post_meta( $post->ID, $field, $value );
222
+ } else {
223
+ \delete_post_meta( $post->ID, $field );
224
+ }
225
  }
 
226
  }
227
 
228
  /**
229
  * Fetches or parses the excerpt of the post.
230
  *
231
  * @since 1.0.0
232
+ * @since 2.8.2 : Added 4th parameter for escaping.
233
  *
234
  * @param string $excerpt the Excerpt.
235
  * @param int $the_id The Post ID.
236
  * @param int $tt_id The Taxonomy Term ID.
237
+ * @param int $tt_id The Taxonomy Term ID.
238
  * @return string The escaped Excerpt.
239
  */
240
+ public function get_excerpt_by_id( $excerpt = '', $the_id = '', $tt_id = '', $escape = true ) {
241
 
242
  if ( empty( $excerpt ) )
243
  $excerpt = $this->fetch_excerpt( $the_id, $tt_id );
246
  if ( '' === $excerpt )
247
  return '';
248
 
249
+ if ( $escape )
250
+ return $this->s_excerpt( $excerpt );
 
 
 
 
 
 
 
251
 
252
+ return $this->s_excerpt_raw( $excerpt );
253
  }
254
 
255
  /**
278
  if ( ! empty( $post->post_excerpt ) ) {
279
  $excerpt = $post->post_excerpt;
280
  } elseif ( isset( $post->post_content ) ) {
281
+ $excerpt = $this->uses_page_builder( $post->ID ) ? '' : $post->post_content;
 
282
  } else {
283
  $excerpt = '';
284
  }
314
  if ( '' !== $the_id ) {
315
  if ( $this->is_blog_page( $the_id ) ) {
316
  $args = array(
317
+ 'posts_per_page' => 1,
318
+ 'offset' => 0,
319
+ 'category' => '',
320
+ 'category_name' => '',
321
+ 'orderby' => 'date',
322
+ 'order' => 'DESC',
323
+ 'post_type' => 'post',
324
+ 'post_status' => 'publish',
325
+ 'cache_results' => false,
326
  );
327
 
328
+ $post = \get_posts( $args );
329
  } else {
330
+ $post = \get_post( $the_id );
331
  }
332
  } elseif ( '' !== $tt_id ) {
333
  /**
334
  * @since 2.3.3 Match the descriptions in admin as on the front end.
335
  */
336
  $args = array(
337
+ 'posts_per_page' => 1,
338
+ 'offset' => 0,
339
+ 'category' => $tt_id,
340
+ 'category_name' => '',
341
+ 'post_type' => 'post',
342
+ 'post_status' => 'publish',
343
+ 'cache_results' => false,
344
  );
345
 
346
+ $post = \get_posts( $args );
347
  } else {
348
+ $post = \get_post( $the_id );
349
  }
350
 
351
  /**
366
  * @since 2.6.6
367
  */
368
  if ( ARRAY_A === $output || ARRAY_N === $output ) {
369
+ $_post = \WP_Post::get_instance( $post );
370
  $post = $_post->to_array();
371
 
372
  if ( ARRAY_N === $output )
384
  * @global object $wpdb
385
  * @global int $blog_id
386
  *
387
+ * @TODO use get_post() or WP_Query.
388
+ *
389
  * @return int Latest Post ID.
390
  */
391
  public function get_latest_post_id() {
402
  $page_id = $this->object_cache_get( $latest_posts_key );
403
  if ( false === $page_id ) {
404
 
405
+ //* Prepare array
406
+ $post_type = \esc_sql( array( 'post', 'page' ) );
407
  $post_type_in_string = "'" . implode( "','", $post_type ) . "'";
408
 
409
+ //* Prepare array
410
+ $post_status = \esc_sql( array( 'publish', 'future', 'pending' ) );
411
  $post_status_in_string = "'" . implode( "','", $post_status ) . "'";
412
 
413
  $sql = $wpdb->prepare(
440
  */
441
  public function get_post_content( $id = 0 ) {
442
 
443
+ $id = $id ?: $this->get_the_real_ID();
444
 
445
+ $content = \get_post_field( 'post_content', $id );
446
 
447
  if ( is_string( $content ) )
448
  return $content;
467
  */
468
  public function uses_page_builder( $post_id ) {
469
 
470
+ $meta = \get_post_meta( $post_id );
471
 
472
  /**
473
  * Applies filters 'the_seo_framework_detect_page_builder' : boolean
478
  * @param int $post_id The current Post ID.
479
  * @param array $meta The current post meta.
480
  */
481
+ $detected = (bool) \apply_filters( 'the_seo_framework_detect_page_builder', false, $post_id, $meta );
482
 
483
  if ( $detected )
484
  return true;
486
  if ( empty( $meta ) )
487
  return false;
488
 
489
+ if ( isset( $meta['_et_pb_use_builder'][0] ) && 'on' === $meta['_et_pb_use_builder'][0] && defined( 'ET_BUILDER_VERSION' ) ) :
490
  //* Divi Builder by Elegant Themes
491
  return true;
492
+ elseif ( isset( $meta['_wpb_vc_js_status'][0] ) && 'true' === $meta['_wpb_vc_js_status'][0] && defined( 'WPB_VC_VERSION' ) ) :
493
  //* Visual Composer by WPBakery
494
  return true;
495
+ elseif ( isset( $meta['panels_data'][0] ) && '' !== $meta['panels_data'][0] && defined( 'SITEORIGIN_PANELS_VERSION' ) ) :
496
  //* Page Builder by SiteOrigin
497
  return true;
498
+ elseif ( isset( $meta['_fl_builder_enabled'][0] ) && '1' === $meta['_fl_builder_enabled'][0] && defined( 'FL_BUILDER_VERSION' ) ) :
499
  //* Beaver Builder by Fastline Media
500
  return true;
501
+ endif;
502
+
503
+ return false;
504
+ }
505
+
506
+ /**
507
+ * Determines if the current post is protected or private.
508
+ * Only works on singular pages.
509
+ *
510
+ * @since 2.8.0
511
+ *
512
+ * @param int|object The post ID or WP Post object.
513
+ * @return bool True if private, false otherwise.
514
+ */
515
+ public function is_protected( $id = 0 ) {
516
+
517
+ if ( false === $this->is_singular() )
518
+ return false;
519
+
520
+ $post = \get_post( $id, OBJECT );
521
+
522
+ if ( isset( $post->post_password ) && '' !== $post->post_password ) {
523
+ return true;
524
+ } elseif ( isset( $post->post_status ) && 'private' === $post->post_status ) {
525
+ return true;
526
+ }
527
 
528
  return false;
529
  }
inc/classes/query.class.php CHANGED
@@ -1,11 +1,18 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
5
  *
6
  * This program is free software: you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 or later as
8
- * published by the Free Software Foundation.
9
  *
10
  * This program is distributed in the hope that it will be useful,
11
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,36 +23,19 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Query
23
  *
24
  * Caches and organizes the WP Query.
25
- * Functions are (somewhat) in alphabetical order!
26
- *
27
- * @since 2.6.0
28
  *
29
- * @license GPLv2+ <http://www.gnu.org/licenses/gpl-2.0.html>
30
  */
31
- class AutoDescription_Query extends AutoDescription_Compat {
32
-
33
- /**
34
- * Unserializing instances of this class is forbidden.
35
- */
36
- private function __wakeup() { }
37
-
38
- /**
39
- * Handle unapproachable invoked methods.
40
- */
41
- public function __call( $name, $arguments ) {
42
- parent::__call( $name, $arguments );
43
- }
44
 
45
  /**
46
  * Constructor. Load parent constructor.
47
  */
48
- public function __construct() {
49
  parent::__construct();
50
  }
51
 
@@ -55,7 +45,6 @@ class AutoDescription_Query extends AutoDescription_Compat {
55
  * @since 2.6.1
56
  * @access private
57
  * @staticvar bool $cache : Always true if set.
58
- *
59
  * @global object $wp_query
60
  * @global object|null $current_screen
61
  *
@@ -103,7 +92,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
103
 
104
  if ( empty( $id ) ) {
105
  //* This catches most ID's. Even Post IDs.
106
- $id = get_queried_object_id();
107
  }
108
 
109
  /**
@@ -112,11 +101,11 @@ class AutoDescription_Query extends AutoDescription_Compat {
112
  *
113
  * @param int $id
114
  * @param bool Whether the globals WP_Query or current_screen are set.
115
- * @see AutoDescription_Query::can_cache_query()
116
  *
117
  * @since 2.6.2
118
  */
119
- return $id = (int) apply_filters( 'the_seo_framework_current_object_id', $id, $can_cache );
120
  }
121
 
122
  /**
@@ -124,16 +113,11 @@ class AutoDescription_Query extends AutoDescription_Compat {
124
  * Alters while in the loop. Therefore, this can't be cached and must be called within the loop.
125
  *
126
  * @since 2.7.0
 
127
  */
128
  public function get_the_real_admin_ID() {
129
 
130
- /**
131
- * This is get_the_ID() with WordPress 3.9 compatibility.
132
- * @todo convert to get_the_ID()
133
- * @priority OMGWTFBBQ 2.7.x (I warned you.)
134
- */
135
- $post = get_post();
136
- $id = empty( $post ) ? 0 : $post->ID;
137
 
138
  //* Current term ID (outside loop).
139
  if ( empty( $id ) && $this->is_archive_admin() )
@@ -161,10 +145,10 @@ class AutoDescription_Query extends AutoDescription_Compat {
161
 
162
  if ( $this->is_wc_shop() ) {
163
  //* WooCommerce Shop
164
- $id = get_option( 'woocommerce_shop_page_id' );
165
- } elseif ( function_exists( 'get_question_id' ) && did_action( 'template_redirect' ) ) {
166
  //* AnsPress
167
- $id = get_question_id();
168
  }
169
 
170
  /**
@@ -174,7 +158,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
174
  */
175
  $this->set_query_cache(
176
  __METHOD__,
177
- $id = (int) apply_filters( 'the_seo_framework_real_id', $id )
178
  );
179
 
180
  return $id;
@@ -184,7 +168,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
184
  * Fetches the Term ID on admin pages.
185
  *
186
  * @since 2.6.0
187
- * @since 2.6.6 Moved from class AutoDescription_TermData.
188
  *
189
  * @return int Term ID.
190
  */
@@ -212,7 +196,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
212
 
213
  $this->set_query_cache(
214
  __METHOD__,
215
- $term_id = intval( $term_id ) ? absint( $term_id ) : 0
216
  );
217
 
218
  return $term_id;
@@ -226,7 +210,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
226
  * @return bool
227
  */
228
  public function is_404() {
229
- return is_404();
230
  }
231
 
232
  /**
@@ -237,7 +221,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
237
  * @return bool
238
  */
239
  public function is_admin() {
240
- return is_admin();
241
  }
242
 
243
  /**
@@ -251,14 +235,14 @@ class AutoDescription_Query extends AutoDescription_Compat {
251
  public function is_attachment( $attachment = '' ) {
252
 
253
  if ( empty( $attachment ) )
254
- return is_attachment();
255
 
256
  if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $attachment ) )
257
  return $cache;
258
 
259
  $this->set_query_cache(
260
  __METHOD__,
261
- $is_attachment = is_attachment( $attachment ),
262
  $attachment
263
  );
264
 
@@ -278,7 +262,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
278
  if ( $this->is_admin() )
279
  return $this->is_archive_admin();
280
 
281
- if ( is_archive() && false === $this->is_singular() )
282
  return true;
283
 
284
  if ( $this->can_cache_query() && false === $this->is_singular() ) {
@@ -314,7 +298,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
314
  * @since 2.6.0
315
  * @global object $current_screen
316
  *
317
- * @return bool We're on Term Edit screen.
318
  */
319
  public function is_term_edit() {
320
 
@@ -389,14 +373,14 @@ class AutoDescription_Query extends AutoDescription_Compat {
389
  public function is_author( $author = '' ) {
390
 
391
  if ( empty( $author ) )
392
- return is_author();
393
 
394
  if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $author ) )
395
  return $cache;
396
 
397
  $this->set_query_cache(
398
  __METHOD__,
399
- $is_author = is_author( $author ),
400
  $author
401
  );
402
 
@@ -421,13 +405,14 @@ class AutoDescription_Query extends AutoDescription_Compat {
421
 
422
  $is_blog_page = false;
423
 
424
- $pfp = (int) get_option( 'page_for_posts' );
425
 
426
  if ( $this->has_page_on_front() ) {
427
- if ( $id === $pfp && false === is_archive() )
428
  $is_blog_page = true;
429
- elseif ( is_home() )
430
  $is_blog_page = true;
 
431
  }
432
 
433
  $this->set_query_cache(
@@ -458,7 +443,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
458
 
459
  $this->set_query_cache(
460
  __METHOD__,
461
- $is_category = is_category( $category ),
462
  $category
463
  );
464
 
@@ -487,10 +472,11 @@ class AutoDescription_Query extends AutoDescription_Compat {
487
  $tax = $current_screen->taxonomy;
488
  $len = strlen( $tax );
489
 
490
- if ( $len >= 8 && false !== strrpos( $tax, 'category', -8 ) )
491
  $is_category = true;
492
- elseif ( $len >= 3 && false !== strrpos( $tax, 'cat', -3 ) )
493
  $is_category = true;
 
494
  }
495
 
496
  $this->set_query_cache(
@@ -509,7 +495,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
509
  * @return bool
510
  */
511
  public function is_date() {
512
- return is_date();
513
  }
514
 
515
  /**
@@ -521,7 +507,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
521
  * @return bool
522
  */
523
  public function is_day() {
524
- return is_day();
525
  }
526
 
527
  /**
@@ -533,7 +519,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
533
  * @return bool
534
  */
535
  public function is_feed( $feeds = '' ) {
536
- return is_feed( $feeds );
537
  }
538
 
539
  /**
@@ -553,12 +539,12 @@ class AutoDescription_Query extends AutoDescription_Compat {
553
 
554
  $is_front_page = false;
555
 
556
- if ( is_front_page() && empty( $id ) )
557
  $is_front_page = true;
558
 
559
- //* Elegant Themes Support.
560
  if ( false === $is_front_page && empty( $id ) && $this->is_home() ) {
561
- $sof = get_option( 'show_on_front' );
562
 
563
  if ( 'page' !== $sof && 'posts' !== $sof )
564
  $is_front_page = true;
@@ -566,13 +552,15 @@ class AutoDescription_Query extends AutoDescription_Compat {
566
 
567
  //* Compare against $id
568
  if ( false === $is_front_page && $id ) {
569
- $sof = get_option( 'show_on_front' );
570
 
571
- if ( 'page' === $sof && (int) get_option( 'page_on_front' ) === $id )
572
  $is_front_page = true;
573
 
574
- if ( 'posts' === $sof && (int) get_option( 'page_for_posts' ) === $id )
575
  $is_front_page = true;
 
 
576
  }
577
 
578
  $this->set_query_cache(
@@ -593,7 +581,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
593
  * @return bool
594
  */
595
  public function is_home() {
596
- return is_home();
597
  }
598
 
599
  /**
@@ -604,7 +592,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
604
  * @return bool
605
  */
606
  public function is_month() {
607
- return is_month();
608
  }
609
 
610
  /**
@@ -624,14 +612,14 @@ class AutoDescription_Query extends AutoDescription_Compat {
624
  return $this->is_page_admin();
625
 
626
  if ( empty( $page ) )
627
- return is_page();
628
 
629
  if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $page ) )
630
  return $cache;
631
 
632
  $this->set_query_cache(
633
  __METHOD__,
634
- $is_page = is_page( $page ),
635
  $page
636
  );
637
 
@@ -665,7 +653,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
665
  * @return bool
666
  */
667
  public function is_preview() {
668
- return is_preview();
669
  }
670
 
671
  /**
@@ -677,7 +665,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
677
  * @return bool
678
  */
679
  public function is_search() {
680
- return is_search();
681
  }
682
 
683
  /**
@@ -686,7 +674,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
686
  *
687
  * @since 2.6.0
688
  * @staticvar bool $cache
689
- * @uses AutoDescription_Query::is_single_admin()
690
  *
691
  * @param int|string|array $post Optional. Post ID, title, slug, or array of such. Default empty.
692
  * @return bool
@@ -697,14 +685,14 @@ class AutoDescription_Query extends AutoDescription_Compat {
697
  return $this->is_single_admin();
698
 
699
  if ( empty( $post ) )
700
- return is_single();
701
 
702
  if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $post ) )
703
  return $cache;
704
 
705
  $this->set_query_cache(
706
  __METHOD__,
707
- $is_single = is_single( $post ),
708
  $post
709
  );
710
 
@@ -716,7 +704,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
716
  *
717
  * @since 2.6.0
718
  * @global object $current_screen
719
- * @see AutoDescription_Query::is_single()
720
  *
721
  * @return bool
722
  */
@@ -734,9 +722,9 @@ class AutoDescription_Query extends AutoDescription_Compat {
734
  * Replaces and expands default WordPress is_singular().
735
  *
736
  * @since 2.5.2
737
- * @uses AutoDescription_Query::is_singular_admin()
738
- * @uses AutoDescription_Query::is_blog_page()
739
- * @uses AutoDescription_Query::is_wc_shop()
740
  * @access private
741
  *
742
  * @param string|array $post_types Optional. Post type or array of post types. Default empty string.
@@ -757,7 +745,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
757
  if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $post_types ) )
758
  return $cache;
759
 
760
- if ( ! $is_singular = is_singular( $post_types ) ) {
761
  $id = isset( $id ) ? $id : $this->get_the_real_ID();
762
 
763
  //* Check for somewhat singulars. We need this to adjust Meta data filled in Posts.
@@ -804,8 +792,8 @@ class AutoDescription_Query extends AutoDescription_Compat {
804
  if ( empty( $id ) )
805
  $id = $this->get_the_real_ID();
806
 
807
- if ( 'page' === get_option( 'show_on_front' ) )
808
- return (int) get_option( 'page_on_front' ) === $id;
809
 
810
  return false;
811
  }
@@ -831,7 +819,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
831
 
832
  $this->set_query_cache(
833
  __METHOD__,
834
- $is_tag = is_tag( $tag ),
835
  $tag
836
  );
837
 
@@ -884,35 +872,13 @@ class AutoDescription_Query extends AutoDescription_Compat {
884
 
885
  $this->set_query_cache(
886
  __METHOD__,
887
- $is_tax = is_tax( $taxonomy, $term ),
888
  $taxonomy, $term
889
  );
890
 
891
  return $is_tax;
892
  }
893
 
894
- /**
895
- * Determines if the page is a Ulimate Member's plugin User page.
896
- * Checks for function availability: um_user, um_is_core_page, um_get_requested_user
897
- *
898
- * @since 2.5.2
899
- * @uses $this->can_i_use()
900
- *
901
- * @return bool Whether we're on a Ultimate Member page.
902
- */
903
- public function is_ultimate_member_user_page() {
904
-
905
- if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
906
- return $cache;
907
-
908
- $this->set_query_cache(
909
- __METHOD__,
910
- $is_um_user_page = $this->can_i_use( array( 'functions' => array( 'um_user', 'um_is_core_page', 'um_get_requested_user' ) ), false )
911
- );
912
-
913
- return $is_um_user_page;
914
- }
915
-
916
  /**
917
  * Determines if the page is the WooCommerce plugin Shop page.
918
  *
@@ -928,7 +894,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
928
 
929
  $this->set_query_cache(
930
  __METHOD__,
931
- $is_shop = false === $this->is_admin() && function_exists( 'is_shop' ) && is_shop()
932
  );
933
 
934
  return $is_shop;
@@ -948,7 +914,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
948
 
949
  $this->set_query_cache(
950
  __METHOD__,
951
- $is_product = false === $this->is_admin() && function_exists( 'is_product' ) && is_product()
952
  );
953
 
954
  return $is_product;
@@ -962,7 +928,22 @@ class AutoDescription_Query extends AutoDescription_Compat {
962
  * @return bool
963
  */
964
  public function is_year() {
965
- return is_year();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
966
  }
967
 
968
  /**
@@ -1014,7 +995,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
1014
  if ( $page_hook === $pagehook )
1015
  return true;
1016
  } elseif ( $this->is_admin() && $pageslug ) {
1017
- if ( isset( $_GET['page'] ) && $pageslug === $_GET['page'] )
1018
  return true;
1019
  }
1020
 
@@ -1034,7 +1015,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
1034
  if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1035
  return $cache;
1036
 
1037
- $page = $this->is_multipage() ? get_query_var( 'page' ) : 1;
1038
 
1039
  $this->set_query_cache(
1040
  __METHOD__,
@@ -1088,7 +1069,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
1088
  * of `<!-- nextpage -->` tags..
1089
  * @param WP_Post $post Current post object.
1090
  */
1091
- $_pages = apply_filters( 'content_pagination', $_pages, $post );
1092
 
1093
  $numpages = count( $_pages );
1094
 
@@ -1114,7 +1095,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
1114
  if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1115
  return $cache;
1116
 
1117
- $paged = get_query_var( 'paged' );
1118
 
1119
  $this->set_query_cache(
1120
  __METHOD__,
@@ -1185,8 +1166,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
1185
  * Object cache handler for the query class.
1186
  *
1187
  * @since 2.7.0
1188
- * @since 2.7.2: Put func_get_args() in a variable for PHP5.2 support.
1189
- * @see AutoDescription_Query::get_query_cache()
1190
  *
1191
  * @param string $key The key to set.
1192
  * @param mixed $value_to_set If null, no cache will be set.
@@ -1198,8 +1178,7 @@ class AutoDescription_Query extends AutoDescription_Compat {
1198
  */
1199
  public function set_query_cache( $key, $value_to_set ) {
1200
  if ( func_num_args() > 2 ) {
1201
- $a = func_get_args();
1202
- return $this->get_query_cache( $key, $value_to_set, array_slice( $a, 2 ) );
1203
  } else {
1204
  return $this->get_query_cache( $key, $value_to_set );
1205
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 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
15
+ * by the Free Software Foundation.
16
  *
17
  * This program is distributed in the hope that it will be useful,
18
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Query
28
  *
29
  * Caches and organizes the WP Query.
 
 
 
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Query extends Compat {
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  /**
36
  * Constructor. Load parent constructor.
37
  */
38
+ protected function __construct() {
39
  parent::__construct();
40
  }
41
 
45
  * @since 2.6.1
46
  * @access private
47
  * @staticvar bool $cache : Always true if set.
 
48
  * @global object $wp_query
49
  * @global object|null $current_screen
50
  *
92
 
93
  if ( empty( $id ) ) {
94
  //* This catches most ID's. Even Post IDs.
95
+ $id = \get_queried_object_id();
96
  }
97
 
98
  /**
101
  *
102
  * @param int $id
103
  * @param bool Whether the globals WP_Query or current_screen are set.
104
+ * @see The_SEO_Framework_Query::can_cache_query()
105
  *
106
  * @since 2.6.2
107
  */
108
+ return $id = (int) \apply_filters( 'the_seo_framework_current_object_id', $id, $can_cache );
109
  }
110
 
111
  /**
113
  * Alters while in the loop. Therefore, this can't be cached and must be called within the loop.
114
  *
115
  * @since 2.7.0
116
+ * @since 2.8.0 Removed WP 3.9 compat
117
  */
118
  public function get_the_real_admin_ID() {
119
 
120
+ $id = \get_the_ID();
 
 
 
 
 
 
121
 
122
  //* Current term ID (outside loop).
123
  if ( empty( $id ) && $this->is_archive_admin() )
145
 
146
  if ( $this->is_wc_shop() ) {
147
  //* WooCommerce Shop
148
+ $id = \get_option( 'woocommerce_shop_page_id' );
149
+ } elseif ( function_exists( 'get_question_id' ) && \did_action( 'template_redirect' ) ) {
150
  //* AnsPress
151
+ $id = \get_question_id();
152
  }
153
 
154
  /**
158
  */
159
  $this->set_query_cache(
160
  __METHOD__,
161
+ $id = (int) \apply_filters( 'the_seo_framework_real_id', $id )
162
  );
163
 
164
  return $id;
168
  * Fetches the Term ID on admin pages.
169
  *
170
  * @since 2.6.0
171
+ * @since 2.6.6 Moved from class The_SEO_Framework_Term_Data.
172
  *
173
  * @return int Term ID.
174
  */
196
 
197
  $this->set_query_cache(
198
  __METHOD__,
199
+ $term_id = intval( $term_id ) ? \absint( $term_id ) : 0
200
  );
201
 
202
  return $term_id;
210
  * @return bool
211
  */
212
  public function is_404() {
213
+ return \is_404();
214
  }
215
 
216
  /**
221
  * @return bool
222
  */
223
  public function is_admin() {
224
+ return \is_admin();
225
  }
226
 
227
  /**
235
  public function is_attachment( $attachment = '' ) {
236
 
237
  if ( empty( $attachment ) )
238
+ return \is_attachment();
239
 
240
  if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $attachment ) )
241
  return $cache;
242
 
243
  $this->set_query_cache(
244
  __METHOD__,
245
+ $is_attachment = \is_attachment( $attachment ),
246
  $attachment
247
  );
248
 
262
  if ( $this->is_admin() )
263
  return $this->is_archive_admin();
264
 
265
+ if ( \is_archive() && false === $this->is_singular() )
266
  return true;
267
 
268
  if ( $this->can_cache_query() && false === $this->is_singular() ) {
298
  * @since 2.6.0
299
  * @global object $current_screen
300
  *
301
+ * @return bool True if on Term Edit screen. False otherwise.
302
  */
303
  public function is_term_edit() {
304
 
373
  public function is_author( $author = '' ) {
374
 
375
  if ( empty( $author ) )
376
+ return \is_author();
377
 
378
  if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $author ) )
379
  return $cache;
380
 
381
  $this->set_query_cache(
382
  __METHOD__,
383
+ $is_author = \is_author( $author ),
384
  $author
385
  );
386
 
405
 
406
  $is_blog_page = false;
407
 
408
+ $pfp = (int) \get_option( 'page_for_posts' );
409
 
410
  if ( $this->has_page_on_front() ) {
411
+ if ( $id === $pfp && false === \is_archive() ) {
412
  $is_blog_page = true;
413
+ } elseif ( \is_home() ) {
414
  $is_blog_page = true;
415
+ }
416
  }
417
 
418
  $this->set_query_cache(
443
 
444
  $this->set_query_cache(
445
  __METHOD__,
446
+ $is_category = \is_category( $category ),
447
  $category
448
  );
449
 
472
  $tax = $current_screen->taxonomy;
473
  $len = strlen( $tax );
474
 
475
+ if ( $len >= 8 && false !== strrpos( $tax, 'category', -8 ) ) {
476
  $is_category = true;
477
+ } elseif ( $len >= 3 && false !== strrpos( $tax, 'cat', -3 ) ) {
478
  $is_category = true;
479
+ }
480
  }
481
 
482
  $this->set_query_cache(
495
  * @return bool
496
  */
497
  public function is_date() {
498
+ return \is_date();
499
  }
500
 
501
  /**
507
  * @return bool
508
  */
509
  public function is_day() {
510
+ return \is_day();
511
  }
512
 
513
  /**
519
  * @return bool
520
  */
521
  public function is_feed( $feeds = '' ) {
522
+ return \is_feed( $feeds );
523
  }
524
 
525
  /**
539
 
540
  $is_front_page = false;
541
 
542
+ if ( \is_front_page() && empty( $id ) )
543
  $is_front_page = true;
544
 
545
+ //* Elegant Themes Support. Yay.
546
  if ( false === $is_front_page && empty( $id ) && $this->is_home() ) {
547
+ $sof = \get_option( 'show_on_front' );
548
 
549
  if ( 'page' !== $sof && 'posts' !== $sof )
550
  $is_front_page = true;
552
 
553
  //* Compare against $id
554
  if ( false === $is_front_page && $id ) {
555
+ $sof = \get_option( 'show_on_front' );
556
 
557
+ if ( 'page' === $sof && (int) \get_option( 'page_on_front' ) === $id )
558
  $is_front_page = true;
559
 
560
+ if ( 'posts' === $sof && (int) \get_option( 'page_for_posts' ) === $id )
561
  $is_front_page = true;
562
+ } elseif ( empty( $id ) && $this->is_seo_settings_page() ) {
563
+ $is_front_page = true;
564
  }
565
 
566
  $this->set_query_cache(
581
  * @return bool
582
  */
583
  public function is_home() {
584
+ return \is_home();
585
  }
586
 
587
  /**
592
  * @return bool
593
  */
594
  public function is_month() {
595
+ return \is_month();
596
  }
597
 
598
  /**
612
  return $this->is_page_admin();
613
 
614
  if ( empty( $page ) )
615
+ return \is_page();
616
 
617
  if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $page ) )
618
  return $cache;
619
 
620
  $this->set_query_cache(
621
  __METHOD__,
622
+ $is_page = \is_page( $page ),
623
  $page
624
  );
625
 
653
  * @return bool
654
  */
655
  public function is_preview() {
656
+ return \is_preview();
657
  }
658
 
659
  /**
665
  * @return bool
666
  */
667
  public function is_search() {
668
+ return \is_search();
669
  }
670
 
671
  /**
674
  *
675
  * @since 2.6.0
676
  * @staticvar bool $cache
677
+ * @uses The_SEO_Framework_Query::is_single_admin()
678
  *
679
  * @param int|string|array $post Optional. Post ID, title, slug, or array of such. Default empty.
680
  * @return bool
685
  return $this->is_single_admin();
686
 
687
  if ( empty( $post ) )
688
+ return \is_single();
689
 
690
  if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $post ) )
691
  return $cache;
692
 
693
  $this->set_query_cache(
694
  __METHOD__,
695
+ $is_single = \is_single( $post ),
696
  $post
697
  );
698
 
704
  *
705
  * @since 2.6.0
706
  * @global object $current_screen
707
+ * @see The_SEO_Framework_Query::is_single()
708
  *
709
  * @return bool
710
  */
722
  * Replaces and expands default WordPress is_singular().
723
  *
724
  * @since 2.5.2
725
+ * @uses The_SEO_Framework_Query::is_singular_admin()
726
+ * @uses The_SEO_Framework_Query::is_blog_page()
727
+ * @uses The_SEO_Framework_Query::is_wc_shop()
728
  * @access private
729
  *
730
  * @param string|array $post_types Optional. Post type or array of post types. Default empty string.
745
  if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $post_types ) )
746
  return $cache;
747
 
748
+ if ( ! $is_singular = \is_singular( $post_types ) ) {
749
  $id = isset( $id ) ? $id : $this->get_the_real_ID();
750
 
751
  //* Check for somewhat singulars. We need this to adjust Meta data filled in Posts.
792
  if ( empty( $id ) )
793
  $id = $this->get_the_real_ID();
794
 
795
+ if ( 'page' === \get_option( 'show_on_front' ) )
796
+ return (int) \get_option( 'page_on_front' ) === $id;
797
 
798
  return false;
799
  }
819
 
820
  $this->set_query_cache(
821
  __METHOD__,
822
+ $is_tag = \is_tag( $tag ),
823
  $tag
824
  );
825
 
872
 
873
  $this->set_query_cache(
874
  __METHOD__,
875
+ $is_tax = \is_tax( $taxonomy, $term ),
876
  $taxonomy, $term
877
  );
878
 
879
  return $is_tax;
880
  }
881
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
882
  /**
883
  * Determines if the page is the WooCommerce plugin Shop page.
884
  *
894
 
895
  $this->set_query_cache(
896
  __METHOD__,
897
+ $is_shop = false === $this->is_admin() && function_exists( 'is_shop' ) && \is_shop()
898
  );
899
 
900
  return $is_shop;
914
 
915
  $this->set_query_cache(
916
  __METHOD__,
917
+ $is_product = false === $this->is_admin() && function_exists( 'is_product' ) && \is_product()
918
  );
919
 
920
  return $is_product;
928
  * @return bool
929
  */
930
  public function is_year() {
931
+ return \is_year();
932
+ }
933
+
934
+ /**
935
+ * Determines if SSL is used.
936
+ *
937
+ * @since 2.8.0
938
+ * @staticvar bool $cache
939
+ *
940
+ * @return bool True if SSL, false otherwise.
941
+ */
942
+ public function is_ssl() {
943
+
944
+ static $cache = null;
945
+
946
+ return isset( $cache ) ? $cache : $cache = \is_ssl();
947
  }
948
 
949
  /**
995
  if ( $page_hook === $pagehook )
996
  return true;
997
  } elseif ( $this->is_admin() && $pageslug ) {
998
+ if ( ! empty( $_GET['page'] ) && $pageslug === $_GET['page'] )
999
  return true;
1000
  }
1001
 
1015
  if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1016
  return $cache;
1017
 
1018
+ $page = $this->is_multipage() ? \get_query_var( 'page' ) : 1;
1019
 
1020
  $this->set_query_cache(
1021
  __METHOD__,
1069
  * of `<!-- nextpage -->` tags..
1070
  * @param WP_Post $post Current post object.
1071
  */
1072
+ $_pages = \apply_filters( 'content_pagination', $_pages, $post );
1073
 
1074
  $numpages = count( $_pages );
1075
 
1095
  if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1096
  return $cache;
1097
 
1098
+ $paged = \get_query_var( 'paged' );
1099
 
1100
  $this->set_query_cache(
1101
  __METHOD__,
1166
  * Object cache handler for the query class.
1167
  *
1168
  * @since 2.7.0
1169
+ * @see The_SEO_Framework_Query::get_query_cache()
 
1170
  *
1171
  * @param string $key The key to set.
1172
  * @param mixed $value_to_set If null, no cache will be set.
1178
  */
1179
  public function set_query_cache( $key, $value_to_set ) {
1180
  if ( func_num_args() > 2 ) {
1181
+ return $this->get_query_cache( $key, $value_to_set, array_slice( func_get_args(), 2 ) );
 
1182
  } else {
1183
  return $this->get_query_cache( $key, $value_to_set );
1184
  }
inc/classes/render.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,17 +23,14 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Render
23
  *
24
- * Puts all data into HTML valid strings
25
- * Returns strings
26
  *
27
- * @since 2.1.6
28
  */
29
- class AutoDescription_Render extends AutoDescription_Admin_Init {
30
 
31
  /**
32
  * Theme title doing it wrong boolean.
@@ -37,22 +41,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
37
  */
38
  protected $title_doing_it_wrong = null;
39
 
40
- /**
41
- * Unserializing instances of this class is forbidden.
42
- */
43
- private function __wakeup() { }
44
-
45
- /**
46
- * Handle unapproachable invoked methods.
47
- */
48
- public function __call( $name, $arguments ) {
49
- parent::__call( $name, $arguments );
50
- }
51
-
52
  /**
53
  * Constructor, load parent constructor
54
  */
55
- public function __construct() {
56
  parent::__construct();
57
  }
58
 
@@ -60,9 +52,9 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
60
  * Cache description in static variable
61
  * Must be called inside the loop
62
  *
 
63
  * @staticvar array $description_cache
64
  *
65
- * @since 2.2.2
66
  * @return string The description
67
  */
68
  public function description_from_cache( $social = false ) {
@@ -79,15 +71,14 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
79
  * Cache current URL in static variable
80
  * Must be called inside the loop
81
  *
 
 
 
82
  * @param string $url the url
83
  * @param int $post_id the page id, if empty it will fetch the requested ID, else the page uri
84
  * @param bool $paged Return current page URL with pagination
85
  * @param bool $from_option Get the canonical uri option
86
  * @param bool $paged_plural Whether to allow pagination on second or later pages.
87
- *
88
- * @staticvar array $url_cache
89
- *
90
- * @since 2.2.2
91
  * @return string The url
92
  */
93
  public function the_url_from_cache( $url = '', $post_id = null, $paged = false, $from_option = true, $paged_plural = true ) {
@@ -106,11 +97,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
106
  /**
107
  * Cache home URL in static variable
108
  *
109
- * @param bool $force_slash Force slash
110
- *
111
  * @staticvar array $url_cache
112
  *
113
- * @since 2.5.0
114
  * @return string The url
115
  */
116
  public function the_home_url_from_cache( $force_slash = false ) {
@@ -127,14 +117,14 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
127
  * Cache current Title in static variable
128
  * Must be called inside the loop
129
  *
 
 
 
 
130
  * @param string $title The Title to return
131
  * @param string $sep The Title sepeartor
132
  * @param string $seplocation The Title sepeartor location ( accepts 'left' or 'right' )
133
  * @param bool $meta Ignore theme doing it wrong.
134
- *
135
- * @staticvar array $title_cache
136
- *
137
- * @since 2.2.2
138
  * @return string The title
139
  */
140
  public function title_from_cache( $title = '', $sep = '', $seplocation = '', $meta = false ) {
@@ -151,7 +141,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
151
  static $seplocation_param_cache = null;
152
 
153
  if ( ! isset( $setup_cache ) ) {
154
- if ( doing_filter( 'pre_get_document_title' ) || doing_filter( 'wp_title' ) ) {
155
  $title_param_cache = $title;
156
  $sep_param_cache = $sep;
157
  $seplocation_param_cache = $seplocation;
@@ -160,11 +150,6 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
160
  }
161
  }
162
 
163
- /**
164
- * If the theme is doing it right, override parameters to speed things up.
165
- *
166
- * @since 2.4.0
167
- */
168
  if ( isset( $this->title_doing_it_wrong ) && false === $this->title_doing_it_wrong ) {
169
  $title = $title_param_cache;
170
  $sep = $sep_param_cache;
@@ -184,35 +169,41 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
184
  * Caches current Image URL in static variable.
185
  * Must be called inside the loop.
186
  *
187
- * @staticvar string $image_cache
188
- *
189
  * @since 2.2.2
190
  * @since 2.7.0 $get_id parameter has been added.
 
191
  *
192
  * @return string The image URL.
193
  */
194
  public function get_image_from_cache() {
195
 
196
- static $image_cache = null;
197
 
198
- if ( isset( $image_cache ) )
199
- return $image_cache;
200
 
201
- $post_id = $this->get_the_real_ID();
 
 
 
 
 
 
 
 
202
 
203
- $image_cache = $this->get_image( $post_id );
204
 
205
- return $image_cache;
206
  }
207
 
208
  /**
209
  * Renders the description meta tag.
210
  *
 
211
  * @uses $this->description_from_cache()
212
  * @uses $this->detect_seo_plugins()
213
  *
214
- * @since 1.3.0
215
- *
216
  * @return string The description meta tag.
217
  */
218
  public function the_description() {
@@ -223,12 +214,12 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
223
  /**
224
  * Applies filters 'the_seo_framework_description_output' : string
225
  * @since 2.3.0
226
- * @since 2.7.0 Added output within filter.
227
  */
228
- $description = (string) apply_filters( 'the_seo_framework_description_output', $this->description_from_cache(), $this->get_the_real_ID() );
229
 
230
  if ( $description )
231
- return '<meta name="description" content="' . esc_attr( $description ) . '" />' . "\r\n";
232
 
233
  return '';
234
  }
@@ -236,8 +227,8 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
236
  /**
237
  * Renders og:description meta tag
238
  *
239
- * @uses $this->description_from_cache()
240
  * @since 1.3.0
 
241
  *
242
  * @return string The Open Graph description meta tag.
243
  */
@@ -251,10 +242,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
251
  * @since 2.3.0
252
  * @since 2.7.0 Added output within filter.
253
  */
254
- $description = (string) apply_filters( 'the_seo_framework_ogdescription_output', $this->description_from_cache( true ), $this->get_the_real_ID() );
255
 
256
  if ( $description )
257
- return '<meta property="og:description" content="' . esc_attr( $description ) . '" />' . "\r\n";
258
 
259
  return '';
260
  }
@@ -276,10 +267,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
276
  * @since 2.3.0
277
  * @since 2.7.0 Added output within filter.
278
  */
279
- $locale = (string) apply_filters( 'the_seo_framework_oglocale_output', $this->fetch_locale(), $this->get_the_real_ID() );
280
 
281
  if ( $locale )
282
- return '<meta property="og:locale" content="' . esc_attr( $locale ) . '" />' . "\r\n";
283
 
284
  return '';
285
  }
@@ -302,10 +293,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
302
  * @since 2.3.0
303
  * @since 2.7.0 Added output within filter.
304
  */
305
- $title = (string) apply_filters( 'the_seo_framework_ogtitle_output', $this->title_from_cache( '', '', '', true ), $this->get_the_real_ID() );
306
 
307
  if ( $title )
308
- return '<meta property="og:title" content="' . esc_attr( $title ) . '" />' . "\r\n";
309
 
310
  return '';
311
  }
@@ -322,15 +313,8 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
322
  if ( ! $this->use_og_tags() )
323
  return '';
324
 
325
- /**
326
- * Applies filters 'the_seo_framework_ogtype_output' : string
327
- * @since 2.3.0
328
- * @since 2.7.0 Added output within filter.
329
- */
330
- $type = (string) apply_filters( 'the_seo_framework_ogtype_output', $this->generate_og_type(), $this->get_the_real_ID() );
331
-
332
- if ( $type )
333
- return '<meta property="og:type" content="' . esc_attr( $type ) . '" />' . "\r\n";
334
 
335
  return '';
336
  }
@@ -338,11 +322,9 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
338
  /**
339
  * Renders Open Graph image meta tag.
340
  *
341
- * @param string $image url for image
342
- *
343
  * @since 1.3.0
344
- * @since 2.6.0 Added WooCommerce gallery images.
345
- * @since 2.7.0 Added image dimensions if found.
346
  *
347
  * @return string The Open Graph image meta tag.
348
  */
@@ -362,7 +344,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
362
  * @todo Place in listener cache.
363
  * @priority medium 2.8.0+
364
  */
365
- $image = apply_filters( 'the_seo_framework_ogimage_output', $this->get_image_from_cache(), $id = $this->get_the_real_ID() );
366
 
367
  /**
368
  * Now returns empty string on false.
@@ -377,12 +359,12 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
377
  * Always output
378
  * @since 2.1.1
379
  */
380
- $output = '<meta property="og:image" content="' . esc_attr( $image ) . '" />' . "\r\n";
381
 
382
  if ( $image ) {
383
  if ( ! empty( $this->image_dimensions[ $id ]['width'] ) && ! empty( $this->image_dimensions[ $id ]['height'] ) ) {
384
- $output .= '<meta property="og:image:width" content="' . esc_attr( $this->image_dimensions[ $id ]['width'] ) . '" />' . "\r\n";
385
- $output .= '<meta property="og:image:height" content="' . esc_attr( $this->image_dimensions[ $id ]['height'] ) . '" />' . "\r\n";
386
  }
387
  }
388
 
@@ -396,7 +378,8 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
396
  * Renders WooCommerce Product Gallery OG images.
397
  *
398
  * @since 2.6.0
399
- * @since 2.7.0 Added image dimensions if found.
 
400
  *
401
  * @return string The rendered OG Image.
402
  */
@@ -409,16 +392,25 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
409
  $images = $this->get_image_from_woocommerce_gallery();
410
 
411
  if ( $images && is_array( $images ) ) {
 
 
 
 
 
412
  foreach ( $images as $id ) {
 
 
 
 
413
  //* Parse 1500px url.
414
  $img = $this->parse_og_image( $id );
415
 
416
  if ( $img ) {
417
- $output .= '<meta property="og:image" content="' . esc_attr( $img ) . '" />' . "\r\n";
418
 
419
  if ( ! empty( $this->image_dimensions[ $id ]['width'] ) && ! empty( $this->image_dimensions[ $id ]['height'] ) ) {
420
- $output .= '<meta property="og:image:width" content="' . esc_attr( $this->image_dimensions[ $id ]['width'] ) . '" />' . "\r\n";
421
- $output .= '<meta property="og:image:height" content="' . esc_attr( $this->image_dimensions[ $id ]['height'] ) . '" />' . "\r\n";
422
  }
423
  }
424
  }
@@ -445,10 +437,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
445
  * @since 2.3.0
446
  * @since 2.7.0 Added output within filter.
447
  */
448
- $sitename = (string) apply_filters( 'the_seo_framework_ogsitename_output', get_bloginfo( 'name' ), $this->get_the_real_ID() );
449
 
450
  if ( $sitename )
451
- return '<meta property="og:site_name" content="' . esc_attr( $sitename ) . '" />' . "\r\n";
452
 
453
  return '';
454
  }
@@ -486,10 +478,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
486
  * @since 2.3.0
487
  * @since 2.7.0 Added output within filter.
488
  */
489
- $card = (string) apply_filters( 'the_seo_framework_twittercard_output', $this->generate_twitter_card_type(), $this->get_the_real_ID() );
490
 
491
  if ( $card )
492
- return '<meta name="twitter:card" content="' . esc_attr( $card ) . '" />' . "\r\n";
493
 
494
  return '';
495
  }
@@ -511,10 +503,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
511
  * @since 2.3.0
512
  * @since 2.7.0 Added output within filter.
513
  */
514
- $site = (string) apply_filters( 'the_seo_framework_twittersite_output', $this->get_option( 'twitter_site' ), $this->get_the_real_ID() );
515
 
516
  if ( $site )
517
- return '<meta name="twitter:site" content="' . esc_attr( $site ) . '" />' . "\r\n";
518
 
519
  return '';
520
  }
@@ -537,7 +529,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
537
  * @since 2.3.0
538
  * @since 2.7.0 Added output within filter.
539
  */
540
- $creator = (string) apply_filters( 'the_seo_framework_twittercreator_output', $this->get_option( 'twitter_creator' ), $this->get_the_real_ID() );
541
 
542
  if ( $creator ) {
543
  /**
@@ -545,9 +537,9 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
545
  * Per Twitter requirements.
546
  */
547
  if ( $this->get_option( 'twitter_site' ) ) {
548
- return '<meta name="twitter:site:id" content="' . esc_attr( $creator ) . '" />' . "\r\n";
549
  } else {
550
- return '<meta name="twitter:creator" content="' . esc_attr( $creator ) . '" />' . "\r\n";
551
  }
552
  }
553
 
@@ -572,10 +564,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
572
  * @since 2.3.0
573
  * @since 2.7.0 Added output within filter.
574
  */
575
- $title = (string) apply_filters( 'the_seo_framework_twittertitle_output', $this->title_from_cache( '', '', '', true ), $this->get_the_real_ID() );
576
 
577
  if ( $title )
578
- return '<meta name="twitter:title" content="' . esc_attr( $title ) . '" />' . "\r\n";
579
 
580
  return '';
581
  }
@@ -598,10 +590,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
598
  * @since 2.3.0
599
  * @since 2.7.0 Added output within filter.
600
  */
601
- $description = (string) apply_filters( 'the_seo_framework_twitterdescription_output', $this->description_from_cache( true ), $this->get_the_real_ID() );
602
 
603
  if ( $description )
604
- return '<meta name="twitter:description" content="' . esc_attr( $description ) . '" />' . "\r\n";
605
 
606
  return '';
607
  }
@@ -623,16 +615,16 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
623
  * @since 2.3.0
624
  * @since 2.7.0 Added output within filter.
625
  */
626
- $image = (string) apply_filters( 'the_seo_framework_twitterimage_output', $this->get_image_from_cache(), $id = $this->get_the_real_ID() );
627
 
628
  $output = '';
629
 
630
  if ( $image ) {
631
- $output = '<meta name="twitter:image" content="' . esc_attr( $image ) . '" />' . "\r\n";
632
 
633
  if ( ! empty( $this->image_dimensions[ $id ]['width'] ) && ! empty( $this->image_dimensions[ $id ]['height'] ) ) {
634
- $output .= '<meta name="twitter:image:width" content="' . esc_attr( $this->image_dimensions[ $id ]['width'] ) . '" />' . "\r\n";
635
- $output .= '<meta name="twitter:image:height" content="' . esc_attr( $this->image_dimensions[ $id ]['height'] ) . '" />' . "\r\n";
636
  }
637
  }
638
 
@@ -643,6 +635,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
643
  * Renders Facebook Author meta tag.
644
  *
645
  * @since 2.2.2
 
646
  *
647
  * @return string The Facebook Author meta tag.
648
  */
@@ -651,15 +644,18 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
651
  if ( ! $this->use_facebook_tags() )
652
  return '';
653
 
 
 
 
654
  /**
655
  * Applies filters 'the_seo_framework_facebookauthor_output' : string
656
  * @since 2.3.0
657
  * @since 2.7.0 Added output within filter.
658
  */
659
- $author = (string) apply_filters( 'the_seo_framework_facebookauthor_output', $this->get_option( 'facebook_author' ), $this->get_the_real_ID() );
660
 
661
  if ( $author )
662
- return '<meta property="article:author" content="' . esc_attr( esc_url_raw( $author ) ) . '" />' . "\r\n";
663
 
664
  return '';
665
  }
@@ -681,10 +677,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
681
  * @since 2.3.0
682
  * @since 2.7.0 Added output within filter.
683
  */
684
- $publisher = (string) apply_filters( 'the_seo_framework_facebookpublisher_output', $this->get_option( 'facebook_publisher' ), $this->get_the_real_ID() );
685
 
686
  if ( $publisher )
687
- return '<meta property="article:publisher" content="' . esc_attr( esc_url_raw( $publisher ) ) . '" />' . "\r\n";
688
 
689
  return '';
690
  }
@@ -706,10 +702,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
706
  * @since 2.3.0
707
  * @since 2.7.0 Added output within filter.
708
  */
709
- $app_id = (string) apply_filters( 'the_seo_framework_facebookappid_output', $this->get_option( 'facebook_appid' ), $this->get_the_real_ID() );
710
 
711
  if ( $app_id )
712
- return '<meta property="fb:app_id" content="' . esc_attr( $app_id ) . '" />' . "\r\n";
713
 
714
  return '';
715
  }
@@ -718,6 +714,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
718
  * Renders Article Publishing Time meta tag.
719
  *
720
  * @since 2.2.2
 
721
  *
722
  * @return string The Article Publishing Time meta tag.
723
  */
@@ -727,6 +724,9 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
727
  if ( false === $this->is_singular() )
728
  return '';
729
 
 
 
 
730
  if ( $this->is_front_page() ) {
731
  //* If it's the frontpage, but the option is disabled, don't do anything.
732
  if ( ! $this->get_option( 'home_publish_time' ) )
@@ -748,10 +748,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
748
  * @since 2.3.0
749
  * @since 2.7.0 Added output within filter.
750
  */
751
- $time = (string) apply_filters( 'the_seo_framework_publishedtime_output', get_the_date( 'Y-m-d', $id ), $id );
752
 
753
  if ( $time )
754
- return '<meta property="article:published_time" content="' . esc_attr( $time ) . '" />' . "\r\n";
755
 
756
  return '';
757
  }
@@ -762,15 +762,19 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
762
  *
763
  * @since 2.2.2
764
  * @since 2.7.0 Listens to $this->get_the_real_ID() instead of WordPress Core ID determination.
 
765
  *
766
  * @return string The Article Modified Time meta tag, and optionally the Open Graph Updated Time.
767
  */
768
  public function article_modified_time() {
769
 
770
- // Don't do anything if it's not a page or post, or if both options are disabled
771
  if ( false === $this->is_singular() )
772
  return '';
773
 
 
 
 
774
  if ( $this->is_front_page() ) {
775
  //* If it's the frontpage, but the option is disabled, don't do anything.
776
  if ( ! $this->get_option( 'home_modify_time' ) )
@@ -792,13 +796,13 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
792
  * @since 2.3.0
793
  * @since 2.7.0 Added output within filter.
794
  */
795
- $time = (string) apply_filters( 'the_seo_framework_modifiedtime_output', get_post_modified_time( 'Y-m-d', false, $id, false ), $id );
796
 
797
  if ( $time ) {
798
- $output = '<meta property="article:modified_time" content="' . esc_attr( $time ) . '" />' . "\r\n";
799
 
800
  if ( $this->use_og_tags() )
801
- $output .= '<meta property="og:updated_time" content="' . esc_attr( $time ) . '" />' . "\r\n";
802
 
803
  return $output;
804
  }
@@ -823,8 +827,8 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
823
  * @deprecated
824
  * @since 2.7.0
825
  */
826
- if ( ! apply_filters( 'the_seo_framework_output_canonical', true, $this->get_the_real_ID() ) ) {
827
- $this->_deprecated_function( 'filter the_seo_framework_output_canonical', '2.7.0', "add_filter( 'the_seo_framework_rel_canonical_output', '__return_empty_string' );" );
828
  return '';
829
  }
830
 
@@ -832,7 +836,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
832
  * Applies filters 'the_seo_framework_rel_canonical_output' : Change canonical URL output.
833
  * @since 2.6.5
834
  */
835
- $url = (string) apply_filters( 'the_seo_framework_rel_canonical_output', $this->the_url_from_cache(), $this->get_the_real_ID() );
836
 
837
  /**
838
  * @since 2.7.0 Listens to the second filter.
@@ -861,7 +865,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
861
  * Applies filters 'the_seo_framework_ldjson_scripts' : string
862
  * @since 2.6.0
863
  */
864
- $json = (string) apply_filters( 'the_seo_framework_ldjson_scripts', $this->render_ld_json_scripts(), $this->get_the_real_ID() );
865
 
866
  return $json;
867
  }
@@ -879,10 +883,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
879
  * Applies filters 'the_seo_framework_googlesite_output' : string
880
  * @since 2.6.0
881
  */
882
- $code = (string) apply_filters( 'the_seo_framework_googlesite_output', $this->get_option( 'google_verification' ), $this->get_the_real_ID() );
883
 
884
  if ( $code )
885
- return '<meta name="google-site-verification" content="' . esc_attr( $code ) . '" />' . "\r\n";
886
 
887
  return '';
888
  }
@@ -900,10 +904,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
900
  * Applies filters 'the_seo_framework_bingsite_output' : string
901
  * @since 2.6.0
902
  */
903
- $code = (string) apply_filters( 'the_seo_framework_bingsite_output', $this->get_option( 'bing_verification' ), $this->get_the_real_ID() );
904
 
905
  if ( $code )
906
- return '<meta name="msvalidate.01" content="' . esc_attr( $code ) . '" />' . "\r\n";
907
 
908
  return '';
909
  }
@@ -921,10 +925,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
921
  * Applies filters 'the_seo_framework_yandexsite_output' : string
922
  * @since 2.6.0
923
  */
924
- $code = (string) apply_filters( 'the_seo_framework_yandexsite_output', $this->get_option( 'yandex_verification' ), $this->get_the_real_ID() );
925
 
926
  if ( $code )
927
- return '<meta name="yandex-verification" content="' . esc_attr( $code ) . '" />' . "\r\n";
928
 
929
  return '';
930
  }
@@ -942,10 +946,10 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
942
  * Applies filters 'the_seo_framework_pintsite_output' : string
943
  * @since 2.6.0
944
  */
945
- $code = (string) apply_filters( 'the_seo_framework_pintsite_output', $this->get_option( 'pint_verification' ), $this->get_the_real_ID() );
946
 
947
  if ( $code )
948
- return '<meta name="p:domain_verify" content="' . esc_attr( $code ) . '" />' . "\r\n";
949
 
950
  return '';
951
  }
@@ -968,7 +972,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
968
  * Applies filters 'the_seo_framework_robots_meta' : array
969
  * @since 2.6.0
970
  */
971
- $meta = (array) apply_filters( 'the_seo_framework_robots_meta', $this->robots_meta(), $this->get_the_real_ID() );
972
 
973
  if ( empty( $meta ) )
974
  return '';
@@ -990,7 +994,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
990
  * Applies filters 'the_seo_framework_shortlink_output' : string
991
  * @since 2.6.0
992
  */
993
- $url = (string) apply_filters( 'the_seo_framework_shortlink_output', $this->get_shortlink(), $this->get_the_real_ID() );
994
 
995
  if ( $url )
996
  return sprintf( '<link rel="shortlink" href="%s" />' . "\r\n", $url );
@@ -1014,13 +1018,13 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
1014
  * Applies filters 'the_seo_framework_paged_url_output' : array
1015
  * @since 2.6.0
1016
  */
1017
- $next = (string) apply_filters( 'the_seo_framework_paged_url_output_next', $this->get_paged_url( 'next' ), $id );
1018
 
1019
  /**
1020
  * Applies filters 'the_seo_framework_paged_url_output' : array
1021
  * @since 2.6.0
1022
  */
1023
- $prev = (string) apply_filters( 'the_seo_framework_paged_url_output_prev', $this->get_paged_url( 'prev' ), $id );
1024
 
1025
  $output = '';
1026
 
@@ -1073,6 +1077,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
1073
  * Determines whether we can use Twitter tags.
1074
  *
1075
  * @since 2.6.0
 
1076
  * @staticvar bool $cache
1077
  *
1078
  * @return bool
@@ -1084,7 +1089,7 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
1084
  if ( isset( $cache ) )
1085
  return $cache;
1086
 
1087
- return $cache = $this->is_option_checked( 'twitter_tags' ) && false === $this->detect_twitter_card_plugin();
1088
  }
1089
 
1090
  /**
@@ -1092,11 +1097,14 @@ class AutoDescription_Render extends AutoDescription_Admin_Init {
1092
  *
1093
  * @since 2.6.0
1094
  * @staticvar bool $cache
 
1095
  *
1096
  * @return bool
1097
  */
1098
  public function use_googleplus_tags() {
1099
 
 
 
1100
  static $cache = null;
1101
 
1102
  if ( isset( $cache ) )
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Render
28
  *
29
+ * Puts all data into HTML valid meta tags.
 
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Render extends Admin_Init {
34
 
35
  /**
36
  * Theme title doing it wrong boolean.
41
  */
42
  protected $title_doing_it_wrong = null;
43
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  /**
45
  * Constructor, load parent constructor
46
  */
47
+ protected function __construct() {
48
  parent::__construct();
49
  }
50
 
52
  * Cache description in static variable
53
  * Must be called inside the loop
54
  *
55
+ * @since 2.2.2
56
  * @staticvar array $description_cache
57
  *
 
58
  * @return string The description
59
  */
60
  public function description_from_cache( $social = false ) {
71
  * Cache current URL in static variable
72
  * Must be called inside the loop
73
  *
74
+ * @since 2.2.2
75
+ * @staticvar array $url_cache
76
+ *
77
  * @param string $url the url
78
  * @param int $post_id the page id, if empty it will fetch the requested ID, else the page uri
79
  * @param bool $paged Return current page URL with pagination
80
  * @param bool $from_option Get the canonical uri option
81
  * @param bool $paged_plural Whether to allow pagination on second or later pages.
 
 
 
 
82
  * @return string The url
83
  */
84
  public function the_url_from_cache( $url = '', $post_id = null, $paged = false, $from_option = true, $paged_plural = true ) {
97
  /**
98
  * Cache home URL in static variable
99
  *
100
+ * @since 2.5.0
 
101
  * @staticvar array $url_cache
102
  *
103
+ * @param bool $force_slash Force slash
104
  * @return string The url
105
  */
106
  public function the_home_url_from_cache( $force_slash = false ) {
117
  * Cache current Title in static variable
118
  * Must be called inside the loop
119
  *
120
+ * @since 2.2.2
121
+ * @since 2.4.0 : If the theme is doing it right, override cache parameters to speed things up.
122
+ * @staticvar array $title_cache
123
+ *
124
  * @param string $title The Title to return
125
  * @param string $sep The Title sepeartor
126
  * @param string $seplocation The Title sepeartor location ( accepts 'left' or 'right' )
127
  * @param bool $meta Ignore theme doing it wrong.
 
 
 
 
128
  * @return string The title
129
  */
130
  public function title_from_cache( $title = '', $sep = '', $seplocation = '', $meta = false ) {
141
  static $seplocation_param_cache = null;
142
 
143
  if ( ! isset( $setup_cache ) ) {
144
+ if ( \doing_filter( 'pre_get_document_title' ) || \doing_filter( 'wp_title' ) ) {
145
  $title_param_cache = $title;
146
  $sep_param_cache = $sep;
147
  $seplocation_param_cache = $seplocation;
150
  }
151
  }
152
 
 
 
 
 
 
153
  if ( isset( $this->title_doing_it_wrong ) && false === $this->title_doing_it_wrong ) {
154
  $title = $title_param_cache;
155
  $sep = $sep_param_cache;
169
  * Caches current Image URL in static variable.
170
  * Must be called inside the loop.
171
  *
 
 
172
  * @since 2.2.2
173
  * @since 2.7.0 $get_id parameter has been added.
174
+ * @staticvar string $cache
175
  *
176
  * @return string The image URL.
177
  */
178
  public function get_image_from_cache() {
179
 
180
+ static $cache = null;
181
 
182
+ return isset( $cache ) ? $cache : $cache = $this->get_image( $this->get_the_real_ID() );
183
+ }
184
 
185
+ /**
186
+ * Returns the current Twitter card type.
187
+ *
188
+ * @since 2.8.2
189
+ * @staticvar string $cache
190
+ *
191
+ * @return string The cached Twitter card.
192
+ */
193
+ public function get_current_twitter_card_type() {
194
 
195
+ static $cache = null;
196
 
197
+ return isset( $cache ) ? $cache : $cache = $this->generate_twitter_card_type();
198
  }
199
 
200
  /**
201
  * Renders the description meta tag.
202
  *
203
+ * @since 1.3.0
204
  * @uses $this->description_from_cache()
205
  * @uses $this->detect_seo_plugins()
206
  *
 
 
207
  * @return string The description meta tag.
208
  */
209
  public function the_description() {
214
  /**
215
  * Applies filters 'the_seo_framework_description_output' : string
216
  * @since 2.3.0
217
+ * @since 2.7.0 : Added output within filter.
218
  */
219
+ $description = (string) \apply_filters( 'the_seo_framework_description_output', $this->description_from_cache(), $this->get_the_real_ID() );
220
 
221
  if ( $description )
222
+ return '<meta name="description" content="' . \esc_attr( $description ) . '" />' . "\r\n";
223
 
224
  return '';
225
  }
227
  /**
228
  * Renders og:description meta tag
229
  *
 
230
  * @since 1.3.0
231
+ * @uses $this->description_from_cache()
232
  *
233
  * @return string The Open Graph description meta tag.
234
  */
242
  * @since 2.3.0
243
  * @since 2.7.0 Added output within filter.
244
  */
245
+ $description = (string) \apply_filters( 'the_seo_framework_ogdescription_output', $this->description_from_cache( true ), $this->get_the_real_ID() );
246
 
247
  if ( $description )
248
+ return '<meta property="og:description" content="' . \esc_attr( $description ) . '" />' . "\r\n";
249
 
250
  return '';
251
  }
267
  * @since 2.3.0
268
  * @since 2.7.0 Added output within filter.
269
  */
270
+ $locale = (string) \apply_filters( 'the_seo_framework_oglocale_output', $this->fetch_locale(), $this->get_the_real_ID() );
271
 
272
  if ( $locale )
273
+ return '<meta property="og:locale" content="' . \esc_attr( $locale ) . '" />' . "\r\n";
274
 
275
  return '';
276
  }
293
  * @since 2.3.0
294
  * @since 2.7.0 Added output within filter.
295
  */
296
+ $title = (string) \apply_filters( 'the_seo_framework_ogtitle_output', $this->title_from_cache( '', '', '', true ), $this->get_the_real_ID() );
297
 
298
  if ( $title )
299
+ return '<meta property="og:title" content="' . \esc_attr( $title ) . '" />' . "\r\n";
300
 
301
  return '';
302
  }
313
  if ( ! $this->use_og_tags() )
314
  return '';
315
 
316
+ if ( $type = $this->get_og_type() )
317
+ return '<meta property="og:type" content="' . \esc_attr( $type ) . '" />' . "\r\n";
 
 
 
 
 
 
 
318
 
319
  return '';
320
  }
322
  /**
323
  * Renders Open Graph image meta tag.
324
  *
 
 
325
  * @since 1.3.0
326
+ * @since 2.6.0 : Added WooCommerce gallery images.
327
+ * @since 2.7.0 : Added image dimensions if found.
328
  *
329
  * @return string The Open Graph image meta tag.
330
  */
344
  * @todo Place in listener cache.
345
  * @priority medium 2.8.0+
346
  */
347
+ $image = \apply_filters( 'the_seo_framework_ogimage_output', $this->get_image_from_cache(), $id = $this->get_the_real_ID() );
348
 
349
  /**
350
  * Now returns empty string on false.
359
  * Always output
360
  * @since 2.1.1
361
  */
362
+ $output = '<meta property="og:image" content="' . \esc_attr( $image ) . '" />' . "\r\n";
363
 
364
  if ( $image ) {
365
  if ( ! empty( $this->image_dimensions[ $id ]['width'] ) && ! empty( $this->image_dimensions[ $id ]['height'] ) ) {
366
+ $output .= '<meta property="og:image:width" content="' . \esc_attr( $this->image_dimensions[ $id ]['width'] ) . '" />' . "\r\n";
367
+ $output .= '<meta property="og:image:height" content="' . \esc_attr( $this->image_dimensions[ $id ]['height'] ) . '" />' . "\r\n";
368
  }
369
  }
370
 
378
  * Renders WooCommerce Product Gallery OG images.
379
  *
380
  * @since 2.6.0
381
+ * @since 2.7.0 : Added image dimensions if found.
382
+ * @since 2.8.0 : Checks for featured ID internally, rather than using a far-off cache.
383
  *
384
  * @return string The rendered OG Image.
385
  */
392
  $images = $this->get_image_from_woocommerce_gallery();
393
 
394
  if ( $images && is_array( $images ) ) {
395
+
396
+ $post_id = $this->get_the_real_ID();
397
+ $post_manual_og = $this->get_custom_field( '_social_image_id', $post_id );
398
+ $featured_id = $post_manual_og ? (int) $post_manual_og : (int) \get_post_thumbnail_id( $post_id );
399
+
400
  foreach ( $images as $id ) {
401
+
402
+ if ( $id === $featured_id )
403
+ continue;
404
+
405
  //* Parse 1500px url.
406
  $img = $this->parse_og_image( $id );
407
 
408
  if ( $img ) {
409
+ $output .= '<meta property="og:image" content="' . \esc_attr( $img ) . '" />' . "\r\n";
410
 
411
  if ( ! empty( $this->image_dimensions[ $id ]['width'] ) && ! empty( $this->image_dimensions[ $id ]['height'] ) ) {
412
+ $output .= '<meta property="og:image:width" content="' . \esc_attr( $this->image_dimensions[ $id ]['width'] ) . '" />' . "\r\n";
413
+ $output .= '<meta property="og:image:height" content="' . \esc_attr( $this->image_dimensions[ $id ]['height'] ) . '" />' . "\r\n";
414
  }
415
  }
416
  }
437
  * @since 2.3.0
438
  * @since 2.7.0 Added output within filter.
439
  */
440
+ $sitename = (string) \apply_filters( 'the_seo_framework_ogsitename_output', \get_bloginfo( 'name' ), $this->get_the_real_ID() );
441
 
442
  if ( $sitename )
443
+ return '<meta property="og:site_name" content="' . \esc_attr( $sitename ) . '" />' . "\r\n";
444
 
445
  return '';
446
  }
478
  * @since 2.3.0
479
  * @since 2.7.0 Added output within filter.
480
  */
481
+ $card = (string) \apply_filters( 'the_seo_framework_twittercard_output', $this->get_current_twitter_card_type(), $this->get_the_real_ID() );
482
 
483
  if ( $card )
484
+ return '<meta name="twitter:card" content="' . \esc_attr( $card ) . '" />' . "\r\n";
485
 
486
  return '';
487
  }
503
  * @since 2.3.0
504
  * @since 2.7.0 Added output within filter.
505
  */
506
+ $site = (string) \apply_filters( 'the_seo_framework_twittersite_output', $this->get_option( 'twitter_site' ), $this->get_the_real_ID() );
507
 
508
  if ( $site )
509
+ return '<meta name="twitter:site" content="' . \esc_attr( $site ) . '" />' . "\r\n";
510
 
511
  return '';
512
  }
529
  * @since 2.3.0
530
  * @since 2.7.0 Added output within filter.
531
  */
532
+ $creator = (string) \apply_filters( 'the_seo_framework_twittercreator_output', $this->get_option( 'twitter_creator' ), $this->get_the_real_ID() );
533
 
534
  if ( $creator ) {
535
  /**
537
  * Per Twitter requirements.
538
  */
539
  if ( $this->get_option( 'twitter_site' ) ) {
540
+ return '<meta name="twitter:site:id" content="' . \esc_attr( $creator ) . '" />' . "\r\n";
541
  } else {
542
+ return '<meta name="twitter:creator" content="' . \esc_attr( $creator ) . '" />' . "\r\n";
543
  }
544
  }
545
 
564
  * @since 2.3.0
565
  * @since 2.7.0 Added output within filter.
566
  */
567
+ $title = (string) \apply_filters( 'the_seo_framework_twittertitle_output', $this->title_from_cache( '', '', '', true ), $this->get_the_real_ID() );
568
 
569
  if ( $title )
570
+ return '<meta name="twitter:title" content="' . \esc_attr( $title ) . '" />' . "\r\n";
571
 
572
  return '';
573
  }
590
  * @since 2.3.0
591
  * @since 2.7.0 Added output within filter.
592
  */
593
+ $description = (string) \apply_filters( 'the_seo_framework_twitterdescription_output', $this->description_from_cache( true ), $this->get_the_real_ID() );
594
 
595
  if ( $description )
596
+ return '<meta name="twitter:description" content="' . \esc_attr( $description ) . '" />' . "\r\n";
597
 
598
  return '';
599
  }
615
  * @since 2.3.0
616
  * @since 2.7.0 Added output within filter.
617
  */
618
+ $image = (string) \apply_filters( 'the_seo_framework_twitterimage_output', $this->get_image_from_cache(), $id = $this->get_the_real_ID() );
619
 
620
  $output = '';
621
 
622
  if ( $image ) {
623
+ $output = '<meta name="twitter:image" content="' . \esc_attr( $image ) . '" />' . "\r\n";
624
 
625
  if ( ! empty( $this->image_dimensions[ $id ]['width'] ) && ! empty( $this->image_dimensions[ $id ]['height'] ) ) {
626
+ $output .= '<meta name="twitter:image:width" content="' . \esc_attr( $this->image_dimensions[ $id ]['width'] ) . '" />' . "\r\n";
627
+ $output .= '<meta name="twitter:image:height" content="' . \esc_attr( $this->image_dimensions[ $id ]['height'] ) . '" />' . "\r\n";
628
  }
629
  }
630
 
635
  * Renders Facebook Author meta tag.
636
  *
637
  * @since 2.2.2
638
+ * @since 2.8.0 : Return empty on og:type 'website' or 'product'
639
  *
640
  * @return string The Facebook Author meta tag.
641
  */
644
  if ( ! $this->use_facebook_tags() )
645
  return '';
646
 
647
+ if ( in_array( $this->get_og_type(), array( 'website', 'product' ), true ) )
648
+ return '';
649
+
650
  /**
651
  * Applies filters 'the_seo_framework_facebookauthor_output' : string
652
  * @since 2.3.0
653
  * @since 2.7.0 Added output within filter.
654
  */
655
+ $author = (string) \apply_filters( 'the_seo_framework_facebookauthor_output', $this->get_option( 'facebook_author' ), $this->get_the_real_ID() );
656
 
657
  if ( $author )
658
+ return '<meta property="article:author" content="' . \esc_attr( \esc_url_raw( $author ) ) . '" />' . "\r\n";
659
 
660
  return '';
661
  }
677
  * @since 2.3.0
678
  * @since 2.7.0 Added output within filter.
679
  */
680
+ $publisher = (string) \apply_filters( 'the_seo_framework_facebookpublisher_output', $this->get_option( 'facebook_publisher' ), $this->get_the_real_ID() );
681
 
682
  if ( $publisher )
683
+ return '<meta property="article:publisher" content="' . \esc_attr( \esc_url_raw( $publisher ) ) . '" />' . "\r\n";
684
 
685
  return '';
686
  }
702
  * @since 2.3.0
703
  * @since 2.7.0 Added output within filter.
704
  */
705
+ $app_id = (string) \apply_filters( 'the_seo_framework_facebookappid_output', $this->get_option( 'facebook_appid' ), $this->get_the_real_ID() );
706
 
707
  if ( $app_id )
708
+ return '<meta property="fb:app_id" content="' . \esc_attr( $app_id ) . '" />' . "\r\n";
709
 
710
  return '';
711
  }
714
  * Renders Article Publishing Time meta tag.
715
  *
716
  * @since 2.2.2
717
+ * @since 2.8.0 Returns empty on product pages.
718
  *
719
  * @return string The Article Publishing Time meta tag.
720
  */
724
  if ( false === $this->is_singular() )
725
  return '';
726
 
727
+ if ( 'product' === $this->get_og_type() )
728
+ return '';
729
+
730
  if ( $this->is_front_page() ) {
731
  //* If it's the frontpage, but the option is disabled, don't do anything.
732
  if ( ! $this->get_option( 'home_publish_time' ) )
748
  * @since 2.3.0
749
  * @since 2.7.0 Added output within filter.
750
  */
751
+ $time = (string) \apply_filters( 'the_seo_framework_publishedtime_output', \get_the_date( 'Y-m-d', $id ), $id );
752
 
753
  if ( $time )
754
+ return '<meta property="article:published_time" content="' . \esc_attr( $time ) . '" />' . "\r\n";
755
 
756
  return '';
757
  }
762
  *
763
  * @since 2.2.2
764
  * @since 2.7.0 Listens to $this->get_the_real_ID() instead of WordPress Core ID determination.
765
+ * @since 2.8.0 Returns empty on product pages.
766
  *
767
  * @return string The Article Modified Time meta tag, and optionally the Open Graph Updated Time.
768
  */
769
  public function article_modified_time() {
770
 
771
+ // Don't do anything if it's not a page or post.
772
  if ( false === $this->is_singular() )
773
  return '';
774
 
775
+ if ( 'product' === $this->get_og_type() )
776
+ return '';
777
+
778
  if ( $this->is_front_page() ) {
779
  //* If it's the frontpage, but the option is disabled, don't do anything.
780
  if ( ! $this->get_option( 'home_modify_time' ) )
796
  * @since 2.3.0
797
  * @since 2.7.0 Added output within filter.
798
  */
799
+ $time = (string) \apply_filters( 'the_seo_framework_modifiedtime_output', \get_post_modified_time( 'Y-m-d', false, $id, false ), $id );
800
 
801
  if ( $time ) {
802
+ $output = '<meta property="article:modified_time" content="' . \esc_attr( $time ) . '" />' . "\r\n";
803
 
804
  if ( $this->use_og_tags() )
805
+ $output .= '<meta property="og:updated_time" content="' . \esc_attr( $time ) . '" />' . "\r\n";
806
 
807
  return $output;
808
  }
827
  * @deprecated
828
  * @since 2.7.0
829
  */
830
+ if ( true !== \apply_filters( 'the_seo_framework_output_canonical', true, $this->get_the_real_ID() ) ) {
831
+ $this->_deprecated_filter( 'the_seo_framework_output_canonical', '2.7.0', "add_filter( 'the_seo_framework_rel_canonical_output', '__return_empty_string' );" );
832
  return '';
833
  }
834
 
836
  * Applies filters 'the_seo_framework_rel_canonical_output' : Change canonical URL output.
837
  * @since 2.6.5
838
  */
839
+ $url = (string) \apply_filters( 'the_seo_framework_rel_canonical_output', $this->the_url_from_cache(), $this->get_the_real_ID() );
840
 
841
  /**
842
  * @since 2.7.0 Listens to the second filter.
865
  * Applies filters 'the_seo_framework_ldjson_scripts' : string
866
  * @since 2.6.0
867
  */
868
+ $json = (string) \apply_filters( 'the_seo_framework_ldjson_scripts', $this->render_ld_json_scripts(), $this->get_the_real_ID() );
869
 
870
  return $json;
871
  }
883
  * Applies filters 'the_seo_framework_googlesite_output' : string
884
  * @since 2.6.0
885
  */
886
+ $code = (string) \apply_filters( 'the_seo_framework_googlesite_output', $this->get_option( 'google_verification' ), $this->get_the_real_ID() );
887
 
888
  if ( $code )
889
+ return '<meta name="google-site-verification" content="' . \esc_attr( $code ) . '" />' . "\r\n";
890
 
891
  return '';
892
  }
904
  * Applies filters 'the_seo_framework_bingsite_output' : string
905
  * @since 2.6.0
906
  */
907
+ $code = (string) \apply_filters( 'the_seo_framework_bingsite_output', $this->get_option( 'bing_verification' ), $this->get_the_real_ID() );
908
 
909
  if ( $code )
910
+ return '<meta name="msvalidate.01" content="' . \esc_attr( $code ) . '" />' . "\r\n";
911
 
912
  return '';
913
  }
925
  * Applies filters 'the_seo_framework_yandexsite_output' : string
926
  * @since 2.6.0
927
  */
928
+ $code = (string) \apply_filters( 'the_seo_framework_yandexsite_output', $this->get_option( 'yandex_verification' ), $this->get_the_real_ID() );
929
 
930
  if ( $code )
931
+ return '<meta name="yandex-verification" content="' . \esc_attr( $code ) . '" />' . "\r\n";
932
 
933
  return '';
934
  }
946
  * Applies filters 'the_seo_framework_pintsite_output' : string
947
  * @since 2.6.0
948
  */
949
+ $code = (string) \apply_filters( 'the_seo_framework_pintsite_output', $this->get_option( 'pint_verification' ), $this->get_the_real_ID() );
950
 
951
  if ( $code )
952
+ return '<meta name="p:domain_verify" content="' . \esc_attr( $code ) . '" />' . "\r\n";
953
 
954
  return '';
955
  }
972
  * Applies filters 'the_seo_framework_robots_meta' : array
973
  * @since 2.6.0
974
  */
975
+ $meta = (array) \apply_filters( 'the_seo_framework_robots_meta', $this->robots_meta(), $this->get_the_real_ID() );
976
 
977
  if ( empty( $meta ) )
978
  return '';
994
  * Applies filters 'the_seo_framework_shortlink_output' : string
995
  * @since 2.6.0
996
  */
997
+ $url = (string) \apply_filters( 'the_seo_framework_shortlink_output', $this->get_shortlink(), $this->get_the_real_ID() );
998
 
999
  if ( $url )
1000
  return sprintf( '<link rel="shortlink" href="%s" />' . "\r\n", $url );
1018
  * Applies filters 'the_seo_framework_paged_url_output' : array
1019
  * @since 2.6.0
1020
  */
1021
+ $next = (string) \apply_filters( 'the_seo_framework_paged_url_output_next', $this->get_paged_url( 'next' ), $id );
1022
 
1023
  /**
1024
  * Applies filters 'the_seo_framework_paged_url_output' : array
1025
  * @since 2.6.0
1026
  */
1027
+ $prev = (string) \apply_filters( 'the_seo_framework_paged_url_output_prev', $this->get_paged_url( 'prev' ), $id );
1028
 
1029
  $output = '';
1030
 
1077
  * Determines whether we can use Twitter tags.
1078
  *
1079
  * @since 2.6.0
1080
+ * @since 2.8.2 : Now also considers Twitter card type output.
1081
  * @staticvar bool $cache
1082
  *
1083
  * @return bool
1089
  if ( isset( $cache ) )
1090
  return $cache;
1091
 
1092
+ return $cache = $this->is_option_checked( 'twitter_tags' ) && false === $this->detect_twitter_card_plugin() && $this->get_current_twitter_card_type();
1093
  }
1094
 
1095
  /**
1097
  *
1098
  * @since 2.6.0
1099
  * @staticvar bool $cache
1100
+ * @NOTE: not used.
1101
  *
1102
  * @return bool
1103
  */
1104
  public function use_googleplus_tags() {
1105
 
1106
+ return false;
1107
+
1108
  static $cache = null;
1109
 
1110
  if ( isset( $cache ) )
inc/classes/sanitize.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,40 +23,20 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Sanitize
23
  *
24
- * Sanitizes strings/arrays within the plugin.
25
  *
26
- * @since 2.2.4
27
  */
28
- class AutoDescription_Sanitize extends AutoDescription_Adminpages {
29
-
30
- /**
31
- * Unserializing instances of this class is forbidden.
32
- */
33
- private function __wakeup() { }
34
-
35
- /**
36
- * Handle unapproachable invoked methods.
37
- */
38
- public function __call( $name, $arguments ) {
39
- parent::__call( $name, $arguments );
40
- }
41
 
42
  /**
43
  * Constructor, load parent constructor
44
  */
45
- public function __construct() {
46
  parent::__construct();
47
-
48
- /**
49
- * Sanitizes Site options
50
- * @see siteoptions.class.php
51
- */
52
- add_action( 'admin_init', array( $this, 'sanitizer_filters' ) );
53
  }
54
 
55
  /**
@@ -84,19 +71,20 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
84
  if ( empty( $_POST ) || ! isset( $_POST[ THE_SEO_FRAMEWORK_SITE_OPTIONS ] ) || ! is_array( $_POST[ THE_SEO_FRAMEWORK_SITE_OPTIONS ] ) )
85
  return $validated = false;
86
 
87
- check_admin_referer( $this->settings_field . '-options' );
 
88
 
89
  return $validated = true;
90
  }
91
 
92
  /**
93
- * Register each of the settings with a sanitization filter type.
94
  *
95
- * @since 2.2.2
96
- * @uses autodescription_add_option_filter() Assign filter to array of settings.
97
- * @see AutoDescription_Sanitize::add_filter() Add sanitization filters to options.
98
  */
99
- public function sanitizer_filters() {
100
 
101
  //* Verify update nonce.
102
  if ( false === $this->verify_seo_settings_nonce() )
@@ -105,7 +93,22 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
105
  //* Update hidden options.
106
  $this->update_hidden_options_to_default();
107
 
108
- $this->add_filter(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  's_title_separator',
110
  $this->settings_field,
111
  array(
@@ -113,7 +116,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
113
  )
114
  );
115
 
116
- $this->add_filter(
117
  's_description_separator',
118
  $this->settings_field,
119
  array(
@@ -121,27 +124,38 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
121
  )
122
  );
123
 
124
- $this->add_filter(
125
  's_description',
126
  $this->settings_field,
 
 
 
 
 
 
127
  array(
128
  'homepage_description',
129
- 'description_custom',
130
  )
131
  );
132
 
133
- $this->add_filter(
134
  's_title',
135
  $this->settings_field,
 
 
 
 
 
 
 
 
136
  array(
137
  'homepage_title',
138
  'homepage_title_tagline',
139
-
140
- 'knowledge_name',
141
  )
142
  );
143
 
144
- $this->add_filter(
145
  's_knowledge_type',
146
  $this->settings_field,
147
  array(
@@ -149,7 +163,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
149
  )
150
  );
151
 
152
- $this->add_filter(
153
  's_left_right',
154
  $this->settings_field,
155
  array(
@@ -157,7 +171,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
157
  )
158
  );
159
 
160
- $this->add_filter(
161
  's_left_right_home',
162
  $this->settings_field,
163
  array(
@@ -165,7 +179,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
165
  )
166
  );
167
 
168
- $this->add_filter(
169
  's_one_zero',
170
  $this->settings_field,
171
  array(
@@ -220,7 +234,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
220
  'og_tags',
221
  'facebook_tags',
222
  'twitter_tags',
223
- 'googleplus_tags',
224
 
225
  'knowledge_output',
226
 
@@ -238,7 +252,6 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
238
 
239
  'knowledge_logo',
240
 
241
- 'sitemaps_robots',
242
  'ping_google',
243
  'ping_bing',
244
  'ping_yandex',
@@ -249,29 +262,35 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
249
  'ld_json_searchbox',
250
  'ld_json_sitename',
251
  'ld_json_breadcrumbs',
 
 
 
 
 
 
 
252
  )
253
  );
254
 
255
- $this->add_filter(
256
  's_absint',
257
  $this->settings_field,
258
  array(
259
- // 'home_author', @TODO
260
  )
261
  );
262
 
263
- $this->add_filter(
264
  's_no_html',
265
  $this->settings_field,
266
- array(
267
- )
268
  );
269
 
270
  /**
271
  * @todo create content="code" stripper
272
  * @priority low 2.9.0+
273
  */
274
- $this->add_filter(
275
  's_no_html_space',
276
  $this->settings_field,
277
  array(
@@ -284,7 +303,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
284
  )
285
  );
286
 
287
- $this->add_filter(
288
  's_url',
289
  $this->settings_field,
290
  array(
@@ -303,15 +322,16 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
303
  )
304
  );
305
 
306
- $this->add_filter(
307
  's_url_query',
308
  $this->settings_field,
309
  array(
310
  'knowledge_linkedin',
 
311
  )
312
  );
313
 
314
- $this->add_filter(
315
  's_twitter_name',
316
  $this->settings_field,
317
  array(
@@ -320,7 +340,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
320
  )
321
  );
322
 
323
- $this->add_filter(
324
  's_twitter_card',
325
  $this->settings_field,
326
  array(
@@ -328,41 +348,14 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
328
  )
329
  );
330
 
331
- //* Special action filter.
332
- $this->add_filter(
333
- 's_one_zero_flush_rewrite',
334
- $this->settings_field,
335
- array(
336
- 'sitemaps_output',
337
- )
338
- );
339
-
340
- //* Special action filter.
341
- $this->add_filter(
342
- 's_one_zero_flush_sitemap',
343
  $this->settings_field,
344
  array(
345
- 'sitemaps_modified',
346
- 'sitemap_timestamps',
347
  )
348
  );
349
-
350
- }
351
-
352
- /**
353
- * Registers option sanitation filter
354
- *
355
- * @since 2.2.2
356
- * @since 2.7.0 : No longer used internally.
357
- *
358
- * @param string $filter The filter to call (see AutoDescription_Siteoptions::$available_filters for options)
359
- * @param string $option The WordPress option name
360
- * @param string|array $suboption Optional. The suboption or suboptions you want to filter
361
- *
362
- * @return true
363
- */
364
- public function autodescription_add_option_filter( $filter, $option, $suboption = null ) {
365
- return $this->add_filter( $filter, $option, $suboption );
366
  }
367
 
368
  /**
@@ -374,17 +367,18 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
374
  *
375
  * @since 2.2.2
376
  * @since 2.7.0: Uses external caching function.
 
377
  *
378
  * @param string $filter Sanitization filter type
379
  * @param string $option Option key
380
  * @param array|string $suboption Optional. Suboption key
381
  * @return boolean Returns true when complete
382
  */
383
- public function add_filter( $filter, $option, $suboption = null ) {
384
 
385
  $this->set_option_filter( $filter, $option, $suboption );
386
 
387
- add_filter( 'sanitize_option_' . $option, array( $this, 'sanitize' ), 10, 2 );
388
 
389
  return true;
390
  }
@@ -403,7 +397,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
403
  * @param string $option Option key
404
  * @param array|string $suboption Optional. Suboption key
405
  * @param bool $get Whether to retrieve cache.
406
- * @return boolean Returns true when complete
407
  */
408
  protected function set_option_filter( $filter, $option, $suboption = null, $get = false ) {
409
 
@@ -454,10 +448,10 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
454
  return $new_value;
455
  } elseif ( is_string( $filters[ $option ] ) ) {
456
  //* Single option value
457
- return $this->do_filter( $filters[ $option ], $new_value, get_option( $option ) );
458
  } elseif ( is_array( $filters[ $option ] ) ) {
459
  //* Array of suboption values to loop through
460
- $old_value = get_option( $option );
461
  foreach ( $filters[ $option ] as $suboption => $filter ) {
462
  $old_value[ $suboption ] = isset( $old_value[ $suboption ] ) ? $old_value[ $suboption ] : '';
463
  $new_value[ $suboption ] = isset( $new_value[ $suboption ] ) ? $new_value[ $suboption ] : '';
@@ -480,8 +474,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
480
  * @param string $filter Sanitization filter type
481
  * @param string $new_value New value
482
  * @param string $old_value Previous value
483
- * @return mixed Returns filtered value, or submitted value if value is
484
- * unfiltered.
485
  */
486
  protected function do_filter( $filter, $new_value, $old_value ) {
487
 
@@ -509,24 +502,24 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
509
  protected function get_available_filters() {
510
 
511
  $default_filters = array(
512
- 's_left_right' => array( $this, 's_left_right' ),
513
- 's_left_right_home' => array( $this, 's_left_right_home' ),
514
- 's_title_separator' => array( $this, 's_title_separator' ),
515
- 's_description_separator' => array( $this, 's_description_separator' ),
516
- 's_description' => array( $this, 's_description' ),
517
- 's_title' => array( $this, 's_title' ),
518
- 's_knowledge_type' => array( $this, 's_knowledge_type' ),
519
- 's_one_zero' => array( $this, 's_one_zero' ),
520
- 's_one_zero_flush_rewrite' => array( $this, 's_one_zero_flush_rewrite' ),
521
- 's_one_zero_flush_sitemap' => array( $this, 's_one_zero_flush_sitemap' ),
522
- 's_no_html' => array( $this, 's_no_html' ),
523
- 's_no_html_space' => array( $this, 's_no_html_space' ),
524
- 's_absint' => array( $this, 's_absint' ),
525
- 's_safe_html' => array( $this, 's_safe_html' ),
526
- 's_url' => array( $this, 's_url' ),
527
- 's_url_query' => array( $this, 's_url_query' ),
528
- 's_twitter_name' => array( $this, 's_twitter_name' ),
529
- 's_twitter_card' => array( $this, 's_twitter_card' ),
530
  );
531
 
532
  /**
@@ -538,7 +531,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
538
  * @param array $default_filters Array with keys of sanitization types,
539
  * and values of the filter function name as a callback
540
  */
541
- return (array) apply_filters( 'the_seo_framework_available_sanitizer_filters', $default_filters );
542
  }
543
 
544
  /**
@@ -549,7 +542,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
549
  * @param mixed $new_value Should be identical to any of the $this->get_separator_list() values
550
  * @return string Title separator option
551
  */
552
- protected function s_title_separator( $new_value ) {
553
 
554
  $title_separator = $this->get_separator_list();
555
 
@@ -562,7 +555,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
562
 
563
  //* Fallback to default if empty.
564
  if ( empty( $previous ) )
565
- $previous = $this->get_default_option( 'title_seperator' );
566
 
567
  return (string) $previous;
568
  }
@@ -571,11 +564,12 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
571
  * Returns the description separator value string.
572
  *
573
  * @since 2.2.2
 
574
  *
575
  * @param mixed $new_value Should be identical to any of the $this->description_separator values
576
  * @return string Description separator option
577
  */
578
- protected function s_description_separator( $new_value ) {
579
 
580
  //* Use the same as title_separator
581
  $description_separator = $this->get_separator_list();
@@ -595,19 +589,78 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
595
  }
596
 
597
  /**
598
- * Returns a one-line sanitized description
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
599
  *
600
  * @since 2.5.0
601
- * @since 2.6.6 Removes duplicated spaces.
 
 
 
 
602
  *
603
  * @param string $new_value The Description.
604
  * @return string One line sanitized description.
605
  */
606
- protected function s_description( $new_value ) {
607
 
608
- $description = str_replace( array( "\r\n", "\r", "\n" ), "\n", $new_value );
 
609
 
610
- $lines = explode( "\n", $description );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
611
  $new_lines = array();
612
 
613
  //* Remove line breaks
@@ -617,43 +670,157 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
617
  $new_lines[] = trim( $line ) . ' ';
618
  }
619
 
620
- $description = trim( implode( $new_lines ) );
 
 
 
 
 
 
 
 
 
 
 
 
621
 
622
  $i = 0;
623
  //* Run twice at most, to catch uneven multiple spaces.
624
  do {
625
- $description = str_replace( ' ', ' ', $description );
626
  $i++;
627
- } while ( strpos( $description, ' ' ) && $i <= 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
628
 
629
- return (string) strip_tags( $description );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
630
  }
631
 
632
  /**
633
  * Returns a sanitized and trimmed title.
634
  *
635
  * @since 2.5.2
 
636
  *
637
- * @param string $new_value The Title.
638
  * @return string Sanitized and trimmed title.
639
  */
640
- protected function s_title( $new_value ) {
641
 
642
- $title = esc_html( $new_value );
643
- $title = trim( $title );
644
 
645
- return (string) strip_tags( $title );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
  }
647
 
648
  /**
649
  * Returns the knowledge type value string.
650
  *
651
  * @since 2.2.8
 
652
  *
653
  * @param mixed $new_value Should be identical to any of the $person_organization values.
654
  * @return string title Knowledge type option
655
  */
656
- protected function s_knowledge_type( $new_value ) {
657
 
658
  if ( 'person' === $new_value || 'organization' === $new_value )
659
  return (string) $new_value;
@@ -667,11 +834,12 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
667
  * Returns left or right, for the separator location.
668
  *
669
  * @since 2.2.2
 
670
  *
671
  * @param mixed $new_value Should ideally be a string 'left' or 'right' passed in.
672
  * @return string left or right
673
  */
674
- protected function s_left_right( $new_value ) {
675
 
676
  if ( 'left' === $new_value || 'right' === $new_value )
677
  return (string) $new_value;
@@ -689,11 +857,12 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
689
  * Returns left or right, for the home separator location.
690
  *
691
  * @since 2.5.2
 
692
  *
693
  * @param mixed $new_value Should ideally be a string 'left' or 'right' passed in.
694
  * @return string left or right
695
  */
696
- protected function s_left_right_home( $new_value ) {
697
 
698
  if ( 'left' === $new_value || 'right' === $new_value )
699
  return (string) $new_value;
@@ -713,63 +882,12 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
713
  * Uses double casting. First, we cast to bool, then to integer.
714
  *
715
  * @since 2.2.2
 
716
  *
717
  * @param mixed $new_value Should ideally be a 1 or 0 integer passed in.
718
  * @return integer 1 or 0.
719
  */
720
- protected function s_one_zero( $new_value ) {
721
- return (int) (bool) $new_value;
722
- }
723
-
724
- /**
725
- * Returns a 1 or 0, for all truthy / falsy values.
726
- *
727
- * Uses double casting. First, we cast to bool, then to integer.
728
- *
729
- * Also flushes rewrite rules.
730
- *
731
- * @since 2.2.9
732
- *
733
- * @param mixed $new_value Should ideally be a 1 or 0 integer passed in.
734
- * @return integer 1 or 0.
735
- */
736
- protected function s_one_zero_flush_rewrite( $new_value ) {
737
-
738
- /**
739
- * Don't call functions anymore. Although it was after admin_init.
740
- * It was too early for some plugins.
741
- *
742
- * @since 2.3.0
743
- */
744
- if ( $new_value ) {
745
- $this->enqueue_rewrite_activate( true );
746
- } else {
747
- $this->enqueue_rewrite_deactivate( true );
748
- }
749
-
750
- return (int) (bool) $new_value;
751
- }
752
-
753
- /**
754
- * Returns a 1 or 0, for all truthy / falsy values.
755
- * Uses double casting. First, we cast to bool, then to integer.
756
- * Also flushes the sitemap.
757
- *
758
- * @since 2.2.9
759
- * @staticvar bool $flushed
760
- *
761
- * @param mixed $new_value Should ideally be a 1 or 0 integer passed in.
762
- * @return integer 1 or 0.
763
- */
764
- protected function s_one_zero_flush_sitemap( $new_value ) {
765
-
766
- static $flushed = null;
767
-
768
- if ( ! isset( $flushed ) )
769
- $this->delete_sitemap_transient();
770
-
771
- $flushed = true;
772
-
773
  return (int) (bool) $new_value;
774
  }
775
 
@@ -777,23 +895,25 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
777
  * Returns a positive integer value.
778
  *
779
  * @since 2.2.2
 
780
  *
781
  * @param mixed $new_value Should ideally be a positive integer.
782
  * @return integer Positive integer.
783
  */
784
- protected function s_absint( $new_value ) {
785
- return absint( $new_value );
786
  }
787
 
788
  /**
789
  * Removes HTML tags from string.
790
  *
791
  * @since 2.2.2
 
792
  *
793
  * @param string $new_value String, possibly with HTML in it.
794
  * @return string String without HTML in it.
795
  */
796
- protected function s_no_html( $new_value ) {
797
  return strip_tags( $new_value );
798
  }
799
 
@@ -801,73 +921,74 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
801
  * Removes HTML tags and line breaks from string.
802
  *
803
  * @since 2.5.2
 
804
  *
805
  * @param string $new_value String, possibly with HTML and spaces in it.
806
  * @return string String without HTML and breaks in it.
807
  */
808
- protected function s_no_html_space( $new_value ) {
809
  return str_replace( ' ', '', strip_tags( $new_value ) );
810
  }
811
 
812
  /**
813
- * Makes URLs safe
814
  *
815
  * @since 2.2.2
 
816
  *
817
  * @param string $new_value String, a URL, possibly unsafe.
 
818
  * @return string String a safe URL without Query Arguments.
819
  */
820
- protected function s_url( $new_value ) {
821
-
822
- $this->delete_front_ld_json_transient();
823
 
824
  /**
825
  * If queries have been tokenized, take the value before the query args.
826
  * Otherwise it's empty, so take the current value.
827
  */
828
  $no_query_url = strtok( $new_value, '?' );
829
- $url = $no_query_url ? $no_query_url : $new_value;
830
 
831
- return esc_url_raw( $url );
832
  }
833
 
834
  /**
835
  * Makes URLs safe and removes query args.
836
  *
837
  * @since 2.2.8
 
838
  *
839
  * @param string $new_value String, a URL, possibly unsafe.
840
  * @return string String a safe URL with Query Arguments.
841
  */
842
- protected function s_url_query( $new_value ) {
843
-
844
- $this->delete_front_ld_json_transient();
845
-
846
- return esc_url_raw( $new_value );
847
  }
848
 
849
  /**
850
  * Makes Email Addresses safe, via sanitize_email()
851
  *
852
  * @since 2.2.2
 
853
  *
854
  * @param string $new_value String, an email address, possibly unsafe.
855
  * @return string String a safe email address
856
  */
857
- protected function s_email_address( $new_value ) {
858
- return sanitize_email( $new_value );
859
  }
860
 
861
  /**
862
  * Removes unsafe HTML tags, via wp_kses_post().
863
  *
864
  * @since 2.2.2
 
865
  *
866
  * @param string $new_value String with potentially unsafe HTML in it.
867
  * @return string String with only safe HTML in it
868
  */
869
- protected function s_safe_html( $new_value ) {
870
- return wp_kses_post( $new_value );
871
  }
872
 
873
  /**
@@ -875,11 +996,12 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
875
  * Parses URL to path and adds @ if URL is given.
876
  *
877
  * @since 2.2.2
 
878
  *
879
  * @param string $new_value String with potentially wrong Twitter username.
880
  * @return string String with 'correct' Twitter username
881
  */
882
- protected function s_twitter_name( $new_value ) {
883
 
884
  if ( empty( $new_value ) )
885
  return (string) $new_value;
@@ -887,7 +1009,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
887
  $profile = trim( strip_tags( $new_value ) );
888
 
889
  if ( 'http' === substr( $profile, 0, 4 ) ) {
890
- $parsed_url = wp_parse_url( $profile );
891
  $path = isset( $parsed_url['path'] ) ? str_replace( '/', '', $parsed_url['path'] ) : '';
892
  $profile = $path ? '@' . $path : '';
893
 
@@ -906,11 +1028,12 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
906
  * Falls back to previous value if empty. If previous value is empty if will go to default.
907
  *
908
  * @since 2.5.2
 
909
  *
910
  * @param string $new_value String with potentially wrong option value.
911
  * @return string Sanitized twitter card type.
912
  */
913
- protected function s_twitter_card( $new_value ) {
914
 
915
  //* Fetch Twitter card array.
916
  $card = $this->get_twitter_card_types();
@@ -935,27 +1058,29 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
935
  * beginning, so it isn't a true relative link, but from the web root base.
936
  *
937
  * @since 2.6.5
 
938
  *
939
  * @param string $url Full Path URL or relative URL.
940
  * @return string Abolute path.
941
  */
942
- protected function s_relative_url( $url ) {
943
  return ltrim( preg_replace( '|^(https?:)?//[^/]+(/.*)|i', '$2', $url ), ' \//' );
944
  }
945
 
946
  /**
947
- * Sanitize the Redirect URL
948
  *
949
  * @since 2.2.4
 
950
  *
951
  * @param string $new_value String with potentially unwanted redirect URL.
952
  * @return string The Sanitized Redirect URL
953
  */
954
- protected function s_redirect_url( $new_value ) {
955
 
956
  $url = strip_tags( $new_value );
957
 
958
- if ( $url ) {
959
 
960
  $allow_external = $this->allow_external_redirect();
961
 
@@ -966,50 +1091,38 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
966
  if ( ! $allow_external )
967
  $url = $this->s_relative_url( $url );
968
 
969
- //* Find a path.
970
- if ( _wp_can_use_pcre_u() ) {
971
- //* URL pattern excluding path.
972
- $pattern = '/'
973
- . '((((http)(s)?)?)\:)?' // 1: maybe http: https:
974
- . '(\/\/)?' // 2: maybe slash slash
975
- . '((www.)?)' // 3: maybe www.
976
- . '(.*\.[a-zA-Z0-9]*)' // 4: any legal domain with tld
977
- . '(?:\/)?' // 5: trailing slash
978
- . '/'
979
- ;
980
-
981
- $is_path = ! preg_match( $pattern, $url );
982
- } else {
983
- $parsed_url = wp_parse_url( $url );
984
- $is_path = ! isset( $parsed_url['host'] ) && isset( $parsed_url['path'] );
985
- }
986
 
987
  //* If link is relative, make it full again
988
- if ( $is_path ) {
989
 
990
  //* The url is a relative path
991
  $path = $url;
992
 
993
- //* Try WPMUdev Domain Mapping.
994
- $wpmu_url = $this->the_url_wpmudev_domainmap( $path, true );
995
- if ( $wpmu_url && is_array( $wpmu_url ) ) {
996
- $url = $wpmu_url[0];
997
- $scheme = $wpmu_url[1];
998
- }
999
-
1000
- //* Try Donncha Domain Mapping.
1001
- if ( ! isset( $scheme ) ) {
1002
- $dm_url = $this->the_url_donncha_domainmap( $path, true );
1003
- if ( $dm_url && is_array( $dm_url ) ) {
1004
- $url = $dm_url[0];
1005
- $scheme = $dm_url[1];
1006
- }
1007
- }
1008
-
1009
- //* Everything else.
1010
- if ( ! isset( $scheme ) ) {
1011
  $url = $this->the_home_url_from_cache( true ) . ltrim( $path, ' /' );
1012
- $scheme = is_ssl() ? 'https' : 'http';
1013
  }
1014
 
1015
  //* When nothing is found, fall back on WP defaults (is_ssl).
@@ -1017,13 +1130,13 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
1017
 
1018
  $url = $this->set_url_scheme( $url, $scheme );
1019
  }
1020
- }
1021
 
1022
  /**
1023
  * Applies filters the_seo_framework_301_noqueries : bool remove query args from 301
1024
  * @since 2.5.0
1025
  */
1026
- $noqueries = (bool) apply_filters( 'the_seo_framework_301_noqueries', true );
1027
 
1028
  /**
1029
  * Remove queries from the URL
@@ -1035,7 +1148,7 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
1035
  /**
1036
  * Remove query args
1037
  *
1038
- * @see AutoDescription_Sanitize::s_url
1039
  * @since 2.2.4
1040
  */
1041
  $new_value = $this->s_url( $url );
@@ -1043,10 +1156,57 @@ class AutoDescription_Sanitize extends AutoDescription_Adminpages {
1043
  /**
1044
  * Allow query string parameters. XSS safe.
1045
  */
1046
- $new_value = esc_url_raw( $url );
1047
  }
1048
 
1049
  //* Save url
1050
  return $new_value;
1051
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1052
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Sanitize
28
  *
29
+ * Sanitizes input within the plugin.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Sanitize extends Admin_Pages {
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  /**
36
  * Constructor, load parent constructor
37
  */
38
+ protected function __construct() {
39
  parent::__construct();
 
 
 
 
 
 
40
  }
41
 
42
  /**
71
  if ( empty( $_POST ) || ! isset( $_POST[ THE_SEO_FRAMEWORK_SITE_OPTIONS ] ) || ! is_array( $_POST[ THE_SEO_FRAMEWORK_SITE_OPTIONS ] ) )
72
  return $validated = false;
73
 
74
+ //* This is also handled in /wp-admin/options.php. Nevertheless, one might register outside of scope.
75
+ \check_admin_referer( $this->settings_field . '-options' );
76
 
77
  return $validated = true;
78
  }
79
 
80
  /**
81
+ * Handles settings field update POST actions.
82
  *
83
+ * @since 2.8.0
84
+ *
85
+ * @return void Early if nonce failed.
86
  */
87
+ public function handle_update_post() {
88
 
89
  //* Verify update nonce.
90
  if ( false === $this->verify_seo_settings_nonce() )
93
  //* Update hidden options.
94
  $this->update_hidden_options_to_default();
95
 
96
+ $this->init_sanitizer_filters();
97
+
98
+ //* Flush transients after options have changed.
99
+ \add_action( "update_option_{$this->settings_field}", array( $this, 'delete_main_cache' ) );
100
+ \add_action( "update_option_{$this->settings_field}", array( $this, 'reinitialize_rewrite' ), 11 );
101
+ }
102
+
103
+ /**
104
+ * Register each of the settings with a sanitization filter type.
105
+ *
106
+ * @since 2.8.0
107
+ * @uses method add_option_filter() Assign filter to array of settings.
108
+ */
109
+ public function init_sanitizer_filters() {
110
+
111
+ $this->add_option_filter(
112
  's_title_separator',
113
  $this->settings_field,
114
  array(
116
  )
117
  );
118
 
119
+ $this->add_option_filter(
120
  's_description_separator',
121
  $this->settings_field,
122
  array(
124
  )
125
  );
126
 
127
+ $this->add_option_filter(
128
  's_description',
129
  $this->settings_field,
130
+ array()
131
+ );
132
+
133
+ $this->add_option_filter(
134
+ 's_description_raw',
135
+ $this->settings_field,
136
  array(
137
  'homepage_description',
 
138
  )
139
  );
140
 
141
+ $this->add_option_filter(
142
  's_title',
143
  $this->settings_field,
144
+ array(
145
+ 'knowledge_name',
146
+ )
147
+ );
148
+
149
+ $this->add_option_filter(
150
+ 's_title_raw',
151
+ $this->settings_field,
152
  array(
153
  'homepage_title',
154
  'homepage_title_tagline',
 
 
155
  )
156
  );
157
 
158
+ $this->add_option_filter(
159
  's_knowledge_type',
160
  $this->settings_field,
161
  array(
163
  )
164
  );
165
 
166
+ $this->add_option_filter(
167
  's_left_right',
168
  $this->settings_field,
169
  array(
171
  )
172
  );
173
 
174
+ $this->add_option_filter(
175
  's_left_right_home',
176
  $this->settings_field,
177
  array(
179
  )
180
  );
181
 
182
+ $this->add_option_filter(
183
  's_one_zero',
184
  $this->settings_field,
185
  array(
234
  'og_tags',
235
  'facebook_tags',
236
  'twitter_tags',
237
+ // 'googleplus_tags',
238
 
239
  'knowledge_output',
240
 
252
 
253
  'knowledge_logo',
254
 
 
255
  'ping_google',
256
  'ping_bing',
257
  'ping_yandex',
262
  'ld_json_searchbox',
263
  'ld_json_sitename',
264
  'ld_json_breadcrumbs',
265
+
266
+ 'sitemaps_output',
267
+ 'sitemaps_robots',
268
+ 'sitemaps_modified',
269
+ 'sitemap_timestamps',
270
+ 'sitemap_styles',
271
+ 'sitemap_logo',
272
  )
273
  );
274
 
275
+ $this->add_option_filter(
276
  's_absint',
277
  $this->settings_field,
278
  array(
279
+ 'social_image_fb_id',
280
  )
281
  );
282
 
283
+ $this->add_option_filter(
284
  's_no_html',
285
  $this->settings_field,
286
+ array()
 
287
  );
288
 
289
  /**
290
  * @todo create content="code" stripper
291
  * @priority low 2.9.0+
292
  */
293
+ $this->add_option_filter(
294
  's_no_html_space',
295
  $this->settings_field,
296
  array(
303
  )
304
  );
305
 
306
+ $this->add_option_filter(
307
  's_url',
308
  $this->settings_field,
309
  array(
322
  )
323
  );
324
 
325
+ $this->add_option_filter(
326
  's_url_query',
327
  $this->settings_field,
328
  array(
329
  'knowledge_linkedin',
330
+ 'social_image_fb_url',
331
  )
332
  );
333
 
334
+ $this->add_option_filter(
335
  's_twitter_name',
336
  $this->settings_field,
337
  array(
340
  )
341
  );
342
 
343
+ $this->add_option_filter(
344
  's_twitter_card',
345
  $this->settings_field,
346
  array(
348
  )
349
  );
350
 
351
+ $this->add_option_filter(
352
+ 's_color_hex',
 
 
 
 
 
 
 
 
 
 
353
  $this->settings_field,
354
  array(
355
+ 'sitemap_color_main',
356
+ 'sitemap_color_accent',
357
  )
358
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
359
  }
360
 
361
  /**
367
  *
368
  * @since 2.2.2
369
  * @since 2.7.0: Uses external caching function.
370
+ * @since 2.8.0 Renamed.
371
  *
372
  * @param string $filter Sanitization filter type
373
  * @param string $option Option key
374
  * @param array|string $suboption Optional. Suboption key
375
  * @return boolean Returns true when complete
376
  */
377
+ public function add_option_filter( $filter, $option, $suboption = null ) {
378
 
379
  $this->set_option_filter( $filter, $option, $suboption );
380
 
381
+ \add_filter( 'sanitize_option_' . $option, array( $this, 'sanitize' ), 10, 2 );
382
 
383
  return true;
384
  }
397
  * @param string $option Option key
398
  * @param array|string $suboption Optional. Suboption key
399
  * @param bool $get Whether to retrieve cache.
400
+ * @return array When $get is true, it will return the option filters.
401
  */
402
  protected function set_option_filter( $filter, $option, $suboption = null, $get = false ) {
403
 
448
  return $new_value;
449
  } elseif ( is_string( $filters[ $option ] ) ) {
450
  //* Single option value
451
+ return $this->do_filter( $filters[ $option ], $new_value, \get_option( $option ) );
452
  } elseif ( is_array( $filters[ $option ] ) ) {
453
  //* Array of suboption values to loop through
454
+ $old_value = \get_option( $option );
455
  foreach ( $filters[ $option ] as $suboption => $filter ) {
456
  $old_value[ $suboption ] = isset( $old_value[ $suboption ] ) ? $old_value[ $suboption ] : '';
457
  $new_value[ $suboption ] = isset( $new_value[ $suboption ] ) ? $new_value[ $suboption ] : '';
474
  * @param string $filter Sanitization filter type
475
  * @param string $new_value New value
476
  * @param string $old_value Previous value
477
+ * @return mixed Returns filtered value, or submitted value if value is unfiltered.
 
478
  */
479
  protected function do_filter( $filter, $new_value, $old_value ) {
480
 
502
  protected function get_available_filters() {
503
 
504
  $default_filters = array(
505
+ 's_left_right' => array( $this, 's_left_right' ),
506
+ 's_left_right_home' => array( $this, 's_left_right_home' ),
507
+ 's_title_separator' => array( $this, 's_title_separator' ),
508
+ 's_description_separator' => array( $this, 's_description_separator' ),
509
+ 's_description' => array( $this, 's_description' ),
510
+ 's_description_raw' => array( $this, 's_description_raw' ),
511
+ 's_title' => array( $this, 's_title' ),
512
+ 's_title_raw' => array( $this, 's_title_raw' ),
513
+ 's_knowledge_type' => array( $this, 's_knowledge_type' ),
514
+ 's_one_zero' => array( $this, 's_one_zero' ),
515
+ 's_no_html' => array( $this, 's_no_html' ),
516
+ 's_no_html_space' => array( $this, 's_no_html_space' ),
517
+ 's_absint' => array( $this, 's_absint' ),
518
+ 's_safe_html' => array( $this, 's_safe_html' ),
519
+ 's_url' => array( $this, 's_url' ),
520
+ 's_url_query' => array( $this, 's_url_query' ),
521
+ 's_twitter_name' => array( $this, 's_twitter_name' ),
522
+ 's_twitter_card' => array( $this, 's_twitter_card' ),
523
  );
524
 
525
  /**
531
  * @param array $default_filters Array with keys of sanitization types,
532
  * and values of the filter function name as a callback
533
  */
534
+ return (array) \apply_filters( 'the_seo_framework_available_sanitizer_filters', $default_filters );
535
  }
536
 
537
  /**
542
  * @param mixed $new_value Should be identical to any of the $this->get_separator_list() values
543
  * @return string Title separator option
544
  */
545
+ public function s_title_separator( $new_value ) {
546
 
547
  $title_separator = $this->get_separator_list();
548
 
555
 
556
  //* Fallback to default if empty.
557
  if ( empty( $previous ) )
558
+ $previous = $this->get_default_option( 'title_seperator' ); // NOTE: Typo
559
 
560
  return (string) $previous;
561
  }
564
  * Returns the description separator value string.
565
  *
566
  * @since 2.2.2
567
+ * @since 2.8.0 Method is now public.
568
  *
569
  * @param mixed $new_value Should be identical to any of the $this->description_separator values
570
  * @return string Description separator option
571
  */
572
+ public function s_description_separator( $new_value ) {
573
 
574
  //* Use the same as title_separator
575
  $description_separator = $this->get_separator_list();
589
  }
590
 
591
  /**
592
+ * Escapes and beautifies description.
593
+ *
594
+ * @since 2.5.2
595
+ *
596
+ * @param string $description The description to escape and beautify.
597
+ * @return string Escaped and beautified description.
598
+ */
599
+ public function escape_description( $description = '' ) {
600
+
601
+ $description = \wptexturize( $description );
602
+ $description = \convert_chars( $description );
603
+ $description = \esc_html( $description );
604
+ $description = \capital_P_dangit( $description );
605
+ $description = trim( $description );
606
+
607
+ return $description;
608
+ }
609
+
610
+ /**
611
+ * Returns an one-line sanitized description and escapes it.
612
  *
613
  * @since 2.5.0
614
+ * @since 2.6.6 : Removes duplicated spaces.
615
+ * @since 2.8.0 : Method is now public.
616
+ * @since 2.8.2 : Added extra sanitation.
617
+ * @uses $this->s_description_raw().
618
+ * @uses $this->escape_description().
619
  *
620
  * @param string $new_value The Description.
621
  * @return string One line sanitized description.
622
  */
623
+ public function s_description( $new_value ) {
624
 
625
+ $new_value = $this->s_description_raw( $new_value );
626
+ $new_value = $this->escape_description( $new_value );
627
 
628
+ return $new_value;
629
+ }
630
+
631
+ /**
632
+ * Returns an one-line sanitized description without nbsp and tabs.
633
+ * Does NOT escape.
634
+ *
635
+ * @since 2.8.2
636
+ *
637
+ * @param string $new_value The Description.
638
+ * @return string One line sanitized description.
639
+ */
640
+ public function s_description_raw( $new_value ) {
641
+
642
+ $new_value = $this->s_singleline( $new_value );
643
+ $new_value = $this->s_nbsp( $new_value );
644
+ $new_value = $this->s_tabs( $new_value );
645
+ $new_value = $this->s_bsol( $new_value );
646
+ $new_value = $this->s_dupe_space( $new_value );
647
+
648
+ return $new_value;
649
+ }
650
+
651
+ /**
652
+ * Converts multilines to single lines.
653
+ *
654
+ * @since 2.8.2
655
+ *
656
+ * @param string $new_value The input value with possible multiline.
657
+ * @return string The input string without multiple lines.
658
+ */
659
+ public function s_singleline( $new_value ) {
660
+
661
+ $new_value = str_replace( array( "\r\n", "\r", "\n" ), "\n", $new_value );
662
+
663
+ $lines = explode( "\n", $new_value );
664
  $new_lines = array();
665
 
666
  //* Remove line breaks
670
  $new_lines[] = trim( $line ) . ' ';
671
  }
672
 
673
+ return trim( implode( $new_lines ) );
674
+ }
675
+
676
+ /**
677
+ * Removes duplicated spaces from the input value.
678
+ *
679
+ * @since 2.8.2
680
+ * @see $this->s_nsbp() For converting other spaces prior to using this method.
681
+ *
682
+ * @param string $new_value The input value with possible multispaces.
683
+ * @return string The input string without duplicated spaces.
684
+ */
685
+ public function s_dupe_space( $new_value ) {
686
 
687
  $i = 0;
688
  //* Run twice at most, to catch uneven multiple spaces.
689
  do {
690
+ $new_value = str_replace( ' ', ' ', $new_value );
691
  $i++;
692
+ } while ( $i <= 2 && strpos( $new_value, ' ' ) );
693
+
694
+ return $new_value;
695
+ }
696
+
697
+ /**
698
+ * Removes tabs and replaces it with spaces.
699
+ *
700
+ * @since 2.8.2
701
+ * @see $this->s_dupe_space() For removing duplicates spaces.
702
+ *
703
+ * @param string $new_value The input value with possible tabs.
704
+ * @return string The input string without tabs.
705
+ */
706
+ public function s_tabs( $new_value ) {
707
+ return str_replace( "\t", ' ', $new_value );
708
+ }
709
+
710
+ /**
711
+ * Sanitizes input excerpt.
712
+ *
713
+ * @since 2.8.0
714
+ * @since 2.8.2 : 1. Added allow_shortcodes parameter.
715
+ * 2. Added escape parameter
716
+ *
717
+ * @param string $excerpt the Excerpt.
718
+ * @param bool $allow_shortcodes Whether to maintain shortcodes from excerpt.
719
+ * @param bool $escape Whether to escape the excerpt.
720
+ * @return string The escaped Excerpt.
721
+ */
722
+ public function s_excerpt( $excerpt = '', $allow_shortcodes = true, $escape = true ) {
723
+
724
+ //* No need to parse an empty excerpt.
725
+ if ( '' === $excerpt )
726
+ return '';
727
+
728
+ /**
729
+ * Applies filters 'the_seo_framework_allow_excerpt_shortcode_tags' : boolean
730
+ * @since 2.6.6.1
731
+ */
732
+ if ( $allow_shortcodes && \apply_filters( 'the_seo_framework_allow_excerpt_shortcode_tags', false ) ) {
733
+ $excerpt = \wp_strip_all_tags( $excerpt );
734
+ } else {
735
+ $excerpt = \wp_strip_all_tags( \strip_shortcodes( $excerpt ) );
736
+ }
737
 
738
+ if ( $escape )
739
+ return $this->s_description( $excerpt );
740
+
741
+ return $this->s_description_raw( $excerpt );
742
+ }
743
+
744
+ /**
745
+ * Cleans input excerpt. Does NOT escape excerpt for output.
746
+ *
747
+ * @since 2.8.2
748
+ * @see $this->s_excerpt - This is basically a copy without sanitation.
749
+ *
750
+ * @param string $excerpt the Excerpt.
751
+ * @param bool $allow_shortcodes Whether to maintain shortcodes from excerpt.
752
+ * @return string The unescaped Excerpt.
753
+ */
754
+ public function s_excerpt_raw( $excerpt = '', $allow_shortcodes = true ) {
755
+ return $this->s_excerpt( $excerpt, $allow_shortcodes, false );
756
+ }
757
+
758
+ /**
759
+ * Escapes and beautifies title.
760
+ *
761
+ * @since 2.5.2
762
+ *
763
+ * @param string $title The title to escape and beautify.
764
+ * @param bool $trim Whether to trim the title from whitespaces.
765
+ * @return string Escaped and beautified title.
766
+ */
767
+ public function escape_title( $title = '', $trim = true ) {
768
+
769
+ $title = \wptexturize( $title );
770
+ $title = \convert_chars( $title );
771
+ $title = \esc_html( $title );
772
+ $title = \capital_P_dangit( $title );
773
+ $title = $trim ? trim( $title ) : $title;
774
+
775
+ return $title;
776
  }
777
 
778
  /**
779
  * Returns a sanitized and trimmed title.
780
  *
781
  * @since 2.5.2
782
+ * @since 2.8.0 Method is now public.
783
  *
784
+ * @param string $new_value The input Title.
785
  * @return string Sanitized and trimmed title.
786
  */
787
+ public function s_title( $new_value ) {
788
 
789
+ $new_value = $this->s_title_raw( $new_value );
790
+ $new_value = $this->escape_title( $new_value );
791
 
792
+ return $new_value;
793
+ }
794
+
795
+ /**
796
+ * Sanitizes input title as output.
797
+ *
798
+ * @since 2.8.2
799
+ *
800
+ * @param string $new_value The input Title.
801
+ * @return string Sanitized, beautified and trimmed title.
802
+ */
803
+ public function s_title_raw( $new_value ) {
804
+
805
+ $new_value = $this->s_singleline( $new_value );
806
+ $new_value = $this->s_nbsp( $new_value );
807
+ $new_value = $this->s_tabs( $new_value );
808
+ $new_value = $this->s_bsol( $new_value );
809
+ $new_value = $this->s_dupe_space( $new_value );
810
+
811
+ return (string) $new_value;
812
  }
813
 
814
  /**
815
  * Returns the knowledge type value string.
816
  *
817
  * @since 2.2.8
818
+ * @since 2.8.0 Method is now public.
819
  *
820
  * @param mixed $new_value Should be identical to any of the $person_organization values.
821
  * @return string title Knowledge type option
822
  */
823
+ public function s_knowledge_type( $new_value ) {
824
 
825
  if ( 'person' === $new_value || 'organization' === $new_value )
826
  return (string) $new_value;
834
  * Returns left or right, for the separator location.
835
  *
836
  * @since 2.2.2
837
+ * @since 2.8.0 Method is now public.
838
  *
839
  * @param mixed $new_value Should ideally be a string 'left' or 'right' passed in.
840
  * @return string left or right
841
  */
842
+ public function s_left_right( $new_value ) {
843
 
844
  if ( 'left' === $new_value || 'right' === $new_value )
845
  return (string) $new_value;
857
  * Returns left or right, for the home separator location.
858
  *
859
  * @since 2.5.2
860
+ * @since 2.8.0 Method is now public.
861
  *
862
  * @param mixed $new_value Should ideally be a string 'left' or 'right' passed in.
863
  * @return string left or right
864
  */
865
+ public function s_left_right_home( $new_value ) {
866
 
867
  if ( 'left' === $new_value || 'right' === $new_value )
868
  return (string) $new_value;
882
  * Uses double casting. First, we cast to bool, then to integer.
883
  *
884
  * @since 2.2.2
885
+ * @since 2.8.0 Method is now public.
886
  *
887
  * @param mixed $new_value Should ideally be a 1 or 0 integer passed in.
888
  * @return integer 1 or 0.
889
  */
890
+ public function s_one_zero( $new_value ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
891
  return (int) (bool) $new_value;
892
  }
893
 
895
  * Returns a positive integer value.
896
  *
897
  * @since 2.2.2
898
+ * @since 2.8.0 Method is now public.
899
  *
900
  * @param mixed $new_value Should ideally be a positive integer.
901
  * @return integer Positive integer.
902
  */
903
+ public function s_absint( $new_value ) {
904
+ return \absint( $new_value );
905
  }
906
 
907
  /**
908
  * Removes HTML tags from string.
909
  *
910
  * @since 2.2.2
911
+ * @since 2.8.0 Method is now public.
912
  *
913
  * @param string $new_value String, possibly with HTML in it.
914
  * @return string String without HTML in it.
915
  */
916
+ public function s_no_html( $new_value ) {
917
  return strip_tags( $new_value );
918
  }
919
 
921
  * Removes HTML tags and line breaks from string.
922
  *
923
  * @since 2.5.2
924
+ * @since 2.8.0 Method is now public.
925
  *
926
  * @param string $new_value String, possibly with HTML and spaces in it.
927
  * @return string String without HTML and breaks in it.
928
  */
929
+ public function s_no_html_space( $new_value ) {
930
  return str_replace( ' ', '', strip_tags( $new_value ) );
931
  }
932
 
933
  /**
934
+ * Makes URLs safe.
935
  *
936
  * @since 2.2.2
937
+ * @since 2.8.0 Method is now public.
938
  *
939
  * @param string $new_value String, a URL, possibly unsafe.
940
+ * @param boolean/sphaghetti $flush Whether to flush to transient.
941
  * @return string String a safe URL without Query Arguments.
942
  */
943
+ public function s_url( $new_value ) {
 
 
944
 
945
  /**
946
  * If queries have been tokenized, take the value before the query args.
947
  * Otherwise it's empty, so take the current value.
948
  */
949
  $no_query_url = strtok( $new_value, '?' );
950
+ $url = $no_query_url ?: $new_value;
951
 
952
+ return \esc_url_raw( $url );
953
  }
954
 
955
  /**
956
  * Makes URLs safe and removes query args.
957
  *
958
  * @since 2.2.8
959
+ * @since 2.8.0 Method is now public.
960
  *
961
  * @param string $new_value String, a URL, possibly unsafe.
962
  * @return string String a safe URL with Query Arguments.
963
  */
964
+ public function s_url_query( $new_value ) {
965
+ return \esc_url_raw( $new_value );
 
 
 
966
  }
967
 
968
  /**
969
  * Makes Email Addresses safe, via sanitize_email()
970
  *
971
  * @since 2.2.2
972
+ * @since 2.8.0 Method is now public.
973
  *
974
  * @param string $new_value String, an email address, possibly unsafe.
975
  * @return string String a safe email address
976
  */
977
+ public function s_email_address( $new_value ) {
978
+ return \sanitize_email( $new_value );
979
  }
980
 
981
  /**
982
  * Removes unsafe HTML tags, via wp_kses_post().
983
  *
984
  * @since 2.2.2
985
+ * @since 2.8.0 Method is now public.
986
  *
987
  * @param string $new_value String with potentially unsafe HTML in it.
988
  * @return string String with only safe HTML in it
989
  */
990
+ public function s_safe_html( $new_value ) {
991
+ return \wp_kses_post( $new_value );
992
  }
993
 
994
  /**
996
  * Parses URL to path and adds @ if URL is given.
997
  *
998
  * @since 2.2.2
999
+ * @since 2.8.0 Method is now public.
1000
  *
1001
  * @param string $new_value String with potentially wrong Twitter username.
1002
  * @return string String with 'correct' Twitter username
1003
  */
1004
+ public function s_twitter_name( $new_value ) {
1005
 
1006
  if ( empty( $new_value ) )
1007
  return (string) $new_value;
1009
  $profile = trim( strip_tags( $new_value ) );
1010
 
1011
  if ( 'http' === substr( $profile, 0, 4 ) ) {
1012
+ $parsed_url = \wp_parse_url( $profile );
1013
  $path = isset( $parsed_url['path'] ) ? str_replace( '/', '', $parsed_url['path'] ) : '';
1014
  $profile = $path ? '@' . $path : '';
1015
 
1028
  * Falls back to previous value if empty. If previous value is empty if will go to default.
1029
  *
1030
  * @since 2.5.2
1031
+ * @since 2.8.0 Method is now public.
1032
  *
1033
  * @param string $new_value String with potentially wrong option value.
1034
  * @return string Sanitized twitter card type.
1035
  */
1036
+ public function s_twitter_card( $new_value ) {
1037
 
1038
  //* Fetch Twitter card array.
1039
  $card = $this->get_twitter_card_types();
1058
  * beginning, so it isn't a true relative link, but from the web root base.
1059
  *
1060
  * @since 2.6.5
1061
+ * @since 2.8.0 Method is now public.
1062
  *
1063
  * @param string $url Full Path URL or relative URL.
1064
  * @return string Abolute path.
1065
  */
1066
+ public function s_relative_url( $url ) {
1067
  return ltrim( preg_replace( '|^(https?:)?//[^/]+(/.*)|i', '$2', $url ), ' \//' );
1068
  }
1069
 
1070
  /**
1071
+ * Sanitizes the Redirect URL
1072
  *
1073
  * @since 2.2.4
1074
+ * @since 2.8.0 Method is now public.
1075
  *
1076
  * @param string $new_value String with potentially unwanted redirect URL.
1077
  * @return string The Sanitized Redirect URL
1078
  */
1079
+ public function s_redirect_url( $new_value ) {
1080
 
1081
  $url = strip_tags( $new_value );
1082
 
1083
+ if ( $url ) :
1084
 
1085
  $allow_external = $this->allow_external_redirect();
1086
 
1091
  if ( ! $allow_external )
1092
  $url = $this->s_relative_url( $url );
1093
 
1094
+ //* URL pattern excluding path.
1095
+ $pattern = '/'
1096
+ . '((((http)(s)?)?)\:)?' // 1: maybe http: https:
1097
+ . '(\/\/)?' // 2: maybe slash slash
1098
+ . '((www.)?)' // 3: maybe www.
1099
+ . '(.*\.[a-zA-Z0-9]*)' // 4: any legal domain with tld
1100
+ . '(?:\/)?' // 5: trailing slash
1101
+ . '/'
1102
+ ;
 
 
 
 
 
 
 
 
1103
 
1104
  //* If link is relative, make it full again
1105
+ if ( ! preg_match( $pattern, $url ) ) {
1106
 
1107
  //* The url is a relative path
1108
  $path = $url;
1109
 
1110
+ /**
1111
+ * Applies filters 'the_seo_framework_sanitize_redirect_url' : array
1112
+ *
1113
+ * @since 2.8.0
1114
+ *
1115
+ * @param array : { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
1116
+ * @param string $path the URL path.
1117
+ */
1118
+ $filter = (array) \apply_filters( 'the_seo_framework_sanitize_redirect_args', array(), $path );
1119
+
1120
+ if ( $filter ) {
1121
+ $url = $filter['url'];
1122
+ $scheme = $filter['scheme'];
1123
+ } else {
 
 
 
 
1124
  $url = $this->the_home_url_from_cache( true ) . ltrim( $path, ' /' );
1125
+ $scheme = $this->is_ssl() ? 'https' : 'http';
1126
  }
1127
 
1128
  //* When nothing is found, fall back on WP defaults (is_ssl).
1130
 
1131
  $url = $this->set_url_scheme( $url, $scheme );
1132
  }
1133
+ endif;
1134
 
1135
  /**
1136
  * Applies filters the_seo_framework_301_noqueries : bool remove query args from 301
1137
  * @since 2.5.0
1138
  */
1139
+ $noqueries = (bool) \apply_filters( 'the_seo_framework_301_noqueries', true );
1140
 
1141
  /**
1142
  * Remove queries from the URL
1148
  /**
1149
  * Remove query args
1150
  *
1151
+ * @see The_SEO_Framework_Sanitize::s_url
1152
  * @since 2.2.4
1153
  */
1154
  $new_value = $this->s_url( $url );
1156
  /**
1157
  * Allow query string parameters. XSS safe.
1158
  */
1159
+ $new_value = \esc_url_raw( $url );
1160
  }
1161
 
1162
  //* Save url
1163
  return $new_value;
1164
  }
1165
+
1166
+ /**
1167
+ * Sanitizes color hexadecimals.
1168
+ *
1169
+ * @since 2.8.0
1170
+ *
1171
+ * @param string $new_value String with potentially unwanted hex values.
1172
+ * @return string The sanitized color hex.
1173
+ */
1174
+ public function s_color_hex( $new_value ) {
1175
+
1176
+ $color = trim( $new_value, '# ' );
1177
+
1178
+ if ( '' === $color )
1179
+ return '';
1180
+
1181
+ $color = $color;
1182
+
1183
+ if ( preg_match( '|^([A-Fa-f0-9]{3}){1,2}$|', $color ) )
1184
+ return $color;
1185
+
1186
+ return '';
1187
+ }
1188
+
1189
+ /**
1190
+ * Replaces non-break spaces with regular spaces.
1191
+ *
1192
+ * @since 2.8.2
1193
+ *
1194
+ * @param string $new_value String with potentially unwanted nbsp values.
1195
+ * @return string A spacy string.
1196
+ */
1197
+ public function s_nbsp( $new_value ) {
1198
+ return str_replace( array( '%c2%a0', '&nbsp;' ), ' ', $new_value );
1199
+ }
1200
+
1201
+ /**
1202
+ * Replaces backslash with entity backslash.
1203
+ *
1204
+ * @since 2.8.2
1205
+ *
1206
+ * @param string $new_value String with potentially unwanted \ values.
1207
+ * @return string A string with safe HTML encoded backslashes.
1208
+ */
1209
+ public function s_bsol( $new_value ) {
1210
+ return str_replace( '\\', '&#92;', stripslashes( $new_value ) );
1211
+ }
1212
  }
inc/classes/search.class.php DELETED
@@ -1,183 +0,0 @@
1
- <?php
2
- /**
3
- * The SEO Framework plugin
4
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
5
- *
6
- * This program is free software: you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 3 as published
8
- * by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- defined( 'ABSPATH' ) or die;
20
-
21
- /**
22
- * Class AutoDescription_Search
23
- *
24
- * Excludes pages from search based on options
25
- *
26
- * @since 2.1.6
27
- */
28
- class AutoDescription_Search extends AutoDescription_Generate_Ldjson {
29
-
30
- /**
31
- * Unserializing instances of this class is forbidden.
32
- */
33
- private function __wakeup() { }
34
-
35
- /**
36
- * Handle unapproachable invoked methods.
37
- */
38
- public function __call( $name, $arguments ) {
39
- parent::__call( $name, $arguments );
40
- }
41
-
42
- /**
43
- * Constructor, loads parent constructor and adds filters.
44
- */
45
- public function __construct() {
46
- parent::__construct();
47
-
48
- /**
49
- * @since 2.1.7
50
- * @since 2.7.0 Changed priority from 999 to 9999.
51
- * Now uses another method. Was: 'search_filter'.
52
- */
53
- add_action( 'pre_get_posts', array( $this, 'adjust_search_filter' ), 9999, 1 );
54
- }
55
-
56
- /**
57
- * Excludes posts from search with certain metadata.
58
- * For now, it only looks at 'exclude_local_search'. If it exists, the post or
59
- * page will be excluded from the local Search Results.
60
- *
61
- * @since 2.7.0
62
- *
63
- * @param array $query The possible search query.
64
- * @return void Early if no search query is found.
65
- */
66
- public function adjust_search_filter( $query ) {
67
-
68
- // Don't exclude pages in wp-admin.
69
- if ( $query->is_search && false === $this->is_admin() ) {
70
-
71
- $q = $query->query;
72
- //* Only interact with an actual Search Query.
73
- if ( false === isset( $q['s'] ) )
74
- return;
75
-
76
- $meta_query = $query->get( 'meta_query' );
77
-
78
- //* Convert to array. Unset it if it's empty.
79
- if ( false === is_array( $meta_query ) )
80
- $meta_query = $meta_query ? (array) $meta_query : array();
81
-
82
- /**
83
- * Exclude posts with exclude_local_search option on.
84
- *
85
- * Query is faster when the global relation is not set. Defaults to AND.
86
- * Query is faster when secondary relation is set. Defaults to AND.
87
- * Looks for CHAR value, while it's an integer/char in when unserialized.
88
- */
89
- $meta_query[] = array(
90
- array(
91
- 'key' => 'exclude_local_search',
92
- 'value' => '1',
93
- 'type' => 'CHAR',
94
- 'compare' => 'NOT EXISTS',
95
- 'relation' => 'AND',
96
- ),
97
- );
98
-
99
- $query->set( 'meta_query', $meta_query );
100
- }
101
- }
102
-
103
- /**
104
- * Fetches posts with exclude_local_search option on.
105
- *
106
- * @since 2.1.7
107
- * @since 2.7.0 No longer used for performance reasons.
108
- * @uses $this->exclude_search_ids()
109
- *
110
- * @param array $query The possible search query.
111
- * @return void Early if no search query is found.
112
- */
113
- public function search_filter( $query ) {
114
-
115
- // Don't exclude pages in wp-admin.
116
- if ( $query->is_search && false === $this->is_admin() ) {
117
-
118
- $q = $query->query;
119
- //* Only interact with an actual Search Query.
120
- if ( false === isset( $q['s'] ) )
121
- return;
122
-
123
- //* Get excluded IDs.
124
- $protected_posts = $this->get_excluded_search_ids();
125
- if ( $protected_posts ) {
126
- $get = $query->get( 'post__not_in' );
127
-
128
- //* Merge user defined query.
129
- if ( is_array( $get ) && ! empty( $get ) )
130
- $protected_posts = array_merge( $protected_posts, $get );
131
-
132
- $query->set( 'post__not_in', $protected_posts );
133
- }
134
-
135
- // Parse all ID's, even beyond the first page.
136
- $query->set( 'no_found_rows', false );
137
- }
138
- }
139
-
140
- /**
141
- * Fetches posts with exclude_local_search option on
142
- *
143
- * @since 2.7.0
144
- * @since 2.7.0 No longer used.
145
- * @global int $blog_id
146
- *
147
- * @return array Excluded Post IDs
148
- */
149
- public function get_excluded_search_ids() {
150
- global $blog_id;
151
-
152
- $cache_key = 'exclude_search_ids_' . $blog_id . '_' . get_locale();
153
-
154
- $post_ids = $this->object_cache_get( $cache_key );
155
- if ( false === $post_ids ) {
156
- $post_ids = array();
157
-
158
- $args = array(
159
- 'post_type' => 'any',
160
- 'numberposts' => -1,
161
- 'posts_per_page' => -1,
162
- 'order' => 'DESC',
163
- 'post_status' => 'publish',
164
- 'meta_key' => 'exclude_local_search',
165
- 'meta_value' => 1,
166
- 'meta_compare' => '=',
167
- 'cache_results' => true,
168
- 'suppress_filters' => false,
169
- );
170
- $get_posts = new WP_Query;
171
- $excluded_posts = $get_posts->query( $args );
172
- unset( $get_posts );
173
-
174
- if ( $excluded_posts )
175
- $post_ids = wp_list_pluck( $excluded_posts, 'ID' );
176
-
177
- $this->object_cache_set( $cache_key, $post_ids, 86400 );
178
- }
179
-
180
- // return an array of exclude post IDs
181
- return $post_ids;
182
- }
183
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/classes/{siteoptions.class.php → site-options.class.php} RENAMED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,16 +23,14 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Siteoptions
23
  *
24
- * Holds Site Options for the plugin.
25
  *
26
- * @since 2.2.2
27
  */
28
- class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
29
 
30
  /**
31
  * Site Settings field.
@@ -55,34 +60,16 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
55
  */
56
  protected $o_plugin_updated;
57
 
58
- /**
59
- * Unserializing instances of this class is forbidden.
60
- */
61
- private function __wakeup() { }
62
-
63
- /**
64
- * Handle unapproachable invoked methods.
65
- */
66
- public function __call( $name, $arguments ) {
67
- parent::__call( $name, $arguments );
68
- }
69
-
70
  /**
71
  * Constructor, load parent constructor and set up cachable variables.
72
  */
73
- public function __construct() {
74
  parent::__construct();
75
 
76
  $this->settings_field = THE_SEO_FRAMEWORK_SITE_OPTIONS;
77
  $this->o_plugin_updated = 'updated_' . THE_SEO_FRAMEWORK_DB_VERSION;
78
  $this->seo_settings_page_slug = 'theseoframework-settings';
79
 
80
- //* Set up site settings and save/reset them
81
- add_action( 'admin_init', array( $this, 'register_settings' ), 5 );
82
-
83
- //* Update site options at plugin update.
84
- add_action( 'admin_init', array( $this, 'site_updated_plugin_option' ), 30 );
85
-
86
  }
87
 
88
  /**
@@ -98,7 +85,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
98
  * Switch when RTL is active;
99
  * @since 2.5.0
100
  */
101
- if ( is_rtl() ) {
102
  $titleloc = 'left';
103
  $h_titleloc = 'right';
104
  } else {
@@ -117,6 +104,19 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
117
  * @since 2.2.7
118
  */
119
  return array(
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  // Title.
121
  'title_seperator' => 'pipe', // Title separator (note: TYPO), dropdown
122
  'title_location' => $titleloc, // Title separation location
@@ -127,7 +127,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
127
  'description_separator' => 'pipe', // Description separator, dropdown
128
  'description_additions' => 1, // "Title on Blogname" within Description
129
  'description_blogname' => 1, // "on Blogname" within Description
130
- 'description_custom' => '', // Custom prefix
131
 
132
  // Robots directory.
133
  'noodp' => 1, // Site noopd robots settings
@@ -206,7 +206,11 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
206
  'og_tags' => 1, // Output of Open Graph meta tags
207
  'facebook_tags' => 1, // Output the Facebook meta tags
208
  'twitter_tags' => 1, // Output the Twitter meta tags
209
- 'googleplus_tags' => 1, // Output the Google+ meta tags
 
 
 
 
210
 
211
  // Webmasters.
212
  'google_verification' => '', // Google Verification Code
@@ -242,6 +246,10 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
242
  'ping_google' => 1, // Ping Google
243
  'ping_bing' => 1, // Ping Bing
244
  'ping_yandex' => 1, // Ping Yandex
 
 
 
 
245
 
246
  // Feed.
247
  'excerpt_the_feed' => 1, // Generate feed Excerpts
@@ -275,6 +283,14 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
275
  * Only used within the SEO Settings page.
276
  */
277
  return array(
 
 
 
 
 
 
 
 
278
  'title_rem_additions' => 1, // Title remove additions.
279
  'title_rem_prefixes' => 0, // Title remove prefixes.
280
 
@@ -335,7 +351,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
335
  'og_tags' => 0, // Output of Open Graph meta tags
336
  'facebook_tags' => 0, // Output the Facebook meta tags
337
  'twitter_tags' => 0, // Output the Twitter meta tags
338
- 'googleplus_tags' => 0, // Output the Google+ meta tags
339
 
340
  'knowledge_output' => 0, // Default for outputing the Knowledge SEO.
341
  'knowledge_logo' => 0, // Fetch logo from WP Favicon
@@ -346,6 +362,8 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
346
  'ping_google' => 0, // Ping Google
347
  'ping_bing' => 0, // Ping Bing
348
  'ping_yandex' => 0, // Ping Yandex
 
 
349
 
350
  'excerpt_the_feed' => 0, // Generate feed Excerpts
351
  'source_the_feed' => 0, // Add backlink at the end of the feed
@@ -396,14 +414,14 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
396
  return;
397
 
398
  //* If current user isn't allowed to update options, don't do anything.
399
- if ( ! current_user_can( $this->settings_capability() ) )
400
  return;
401
 
402
  /**
403
  * Applies filters 'the_seo_framework_update_options_at_update' : bool
404
  * @since 2.6.0
405
  */
406
- if ( ! apply_filters( 'the_seo_framework_update_options_at_update', true ) )
407
  return;
408
 
409
  $updated = false;
@@ -428,7 +446,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
428
  }
429
 
430
  //* Updated the options. Check for updated flag and see if settings pages are loaded.
431
- if ( update_option( $this->settings_field, $options ) && $updated && $this->load_options )
432
  $this->pre_output_site_updated_plugin_notice();
433
 
434
  }
@@ -443,8 +461,8 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
443
 
444
  if ( $this->is_seo_settings_page( false ) ) {
445
  //* Redirect to current page if on options page to correct option values. Once.
446
- if ( ! isset( $_REQUEST['seo-updated'] ) || 'true' !== $_REQUEST['seo-updated'] )
447
- $this->admin_redirect( $this->seo_settings_page_slug, array( 'seo-updated' => 'true' ) );
448
 
449
  //* Notice has already been sent.
450
  return;
@@ -454,7 +472,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
454
  $this->init_admin_scripts();
455
 
456
  //* Output notice.
457
- add_action( 'admin_notices', array( $this, 'site_updated_plugin_notice' ) );
458
 
459
  }
460
 
@@ -468,8 +486,8 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
468
  public function site_updated_plugin_notice() {
469
 
470
  $settings_url = $this->seo_settings_page_url();
471
- $link = sprintf( '<a href="%s" title="%s" target="_self">%s</a>', $settings_url, esc_attr__( 'SEO Settings', 'autodescription' ), esc_html__( 'here', 'autodescription' ) );
472
- $go_to_page = sprintf( esc_html_x( 'View the new options %s.', '%s = here', 'autodescription' ), $link );
473
 
474
  $notice = $this->page_defaults['plugin_update_text'] . ' ' . $go_to_page;
475
 
@@ -517,7 +535,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
517
  * Applies filters 'the_seo_framework_get_options' : boolean
518
  * @since 2.0.0
519
  */
520
- return $cache[ $setting ] = apply_filters( 'the_seo_framework_get_options', get_option( $setting ), $setting );
521
  }
522
 
523
  /**
@@ -527,6 +545,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
527
  * second DB interaction.
528
  *
529
  * @since 2.0.0
 
530
  * @staticvar array $settings_cache
531
  * @staticvar array $options_cache
532
  * @thanks StudioPress (http://www.studiopress.com/) for some code.
@@ -540,12 +559,12 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
540
 
541
  //* If we need to bypass the cache
542
  if ( ! $use_cache ) {
543
- $options = get_option( $setting );
544
 
545
  if ( ! is_array( $options ) || ! array_key_exists( $key, $options ) )
546
  return '';
547
 
548
- return is_array( $options[ $key ] ) ? stripslashes_deep( $options[ $key ] ) : stripslashes( wp_kses_decode_entities( $options[ $key ] ) );
549
  }
550
 
551
  //* Setup caches
@@ -564,7 +583,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
564
  $options_cache[ $setting ][ $key ] = '';
565
  } else {
566
  //* Option has not been previously been cached, so cache now
567
- $options_cache[ $setting ][ $key ] = is_array( $options[ $key ] ) ? stripslashes_deep( $options[ $key ] ) : stripslashes( wp_kses_decode_entities( $options[ $key ] ) );
568
  }
569
 
570
  return $options_cache[ $setting ][ $key ];
@@ -605,18 +624,19 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
605
  *
606
  * @since 2.2.7
607
  *
608
- * Applies filters the_seo_framework_default_site_options : The default site options array.
609
- *
610
  * @param array $args Additional default options to filter.
611
- *
612
  * @return array The SEO Framework Options
613
  */
614
  protected function default_site_options( $args = array() ) {
615
- return wp_parse_args(
 
 
 
 
616
  $args,
617
- apply_filters(
618
  'the_seo_framework_default_site_options',
619
- wp_parse_args(
620
  $args,
621
  $this->get_default_site_options()
622
  )
@@ -627,18 +647,19 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
627
  /**
628
  * Return the Warned site options. Options which should be 'avoided' return true.
629
  *
630
- * @since 2.3.4
631
- * Applies filters 'the_seo_framework_warned_site_options' : array The warned site options array.
632
- *
633
  * @param array $args Additional warned options to filter.
634
  * @return array The SEO Framework Warned Options
635
  */
636
  protected function warned_site_options( $args = array() ) {
637
- return wp_parse_args(
 
 
 
 
638
  $args,
639
- apply_filters(
640
  'the_seo_framework_warned_site_options',
641
- wp_parse_args(
642
  $args,
643
  $this->get_warned_site_options()
644
  )
@@ -652,7 +673,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
652
  * @since 2.2.2
653
  * @thanks StudioPress (http://www.studiopress.com/) for some code.
654
  *
655
- * @return void
656
  */
657
  public function register_settings() {
658
 
@@ -660,16 +681,16 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
660
  if ( empty( $this->settings_field ) )
661
  return;
662
 
663
- register_setting( $this->settings_field, $this->settings_field );
664
- add_option( $this->settings_field, $this->default_site_options() );
665
 
666
  //* If this page isn't the SEO Settings page, there's no need to check for a reset.
667
  if ( false === $this->is_seo_settings_page( false ) )
668
  return;
669
 
670
- if ( $this->get_option( 'reset', $this->settings_field ) ) {
671
- if ( update_option( $this->settings_field, $this->default_site_options() ) ) {
672
- $this->admin_redirect( $this->seo_settings_page_slug, array( 'reset' => 'true' ) );
673
  exit;
674
  } else {
675
  $this->admin_redirect( $this->seo_settings_page_slug, array( 'error' => 'true' ) );
@@ -683,25 +704,36 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
683
  *
684
  * @since 2.7.0
685
  *
686
- * @param string|array $new The new setting(s).
 
 
 
 
 
 
 
687
  * @param string $settings_field The Settings Field to update. Defaults
688
- * to The SEO Framework settings field.
 
689
  */
690
  public function update_settings( $new = '', $settings_field = '' ) {
691
 
692
- if ( empty( $settings_field ) )
693
  $settings_field = $this->settings_field;
 
 
694
 
695
- $old = get_option( $settings_field );
696
- $settings = wp_parse_args( $new, $old );
697
 
698
- return update_option( $settings_field, $settings );
699
  }
700
 
701
  /**
702
  * Get the default of any of the The SEO Framework settings.
703
  *
704
  * @since 2.2.4
 
705
  * @staticvar array $defaults_cache
706
  * @uses $this->settings_field
707
  * @uses $this->default_site_options()
@@ -728,7 +760,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
728
  if ( ! is_array( $defaults ) || ! array_key_exists( $key, $defaults ) )
729
  return -1;
730
 
731
- return is_array( $defaults[ $key ] ) ? stripslashes_deep( $defaults[ $key ] ) : stripslashes( wp_kses_decode_entities( $defaults[ $key ] ) );
732
  }
733
 
734
  static $defaults_cache = array();
@@ -844,7 +876,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
844
  if ( isset( $user_id ) )
845
  return $user_id;
846
 
847
- $user = wp_get_current_user();
848
 
849
  return $user_id = $user->exists() ? (int) $user->ID : 0;
850
  }
@@ -853,6 +885,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
853
  * Fetches The SEO Framework usermeta.
854
  *
855
  * @since 2.7.0
 
856
  * @staticvar array $usermeta_cache
857
  *
858
  * @param int $user_id The user ID.
@@ -863,20 +896,21 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
863
  public function get_user_meta( $user_id, $key = THE_SEO_FRAMEWORK_USER_OPTIONS, $use_cache = true ) {
864
 
865
  if ( false === $use_cache )
866
- return get_user_meta( $user_id, $key, true );
867
 
868
  static $usermeta_cache = array();
869
 
870
  if ( isset( $usermeta_cache[ $user_id ][ $key ] ) )
871
  return $usermeta_cache[ $user_id ][ $key ];
872
 
873
- return $usermeta_cache[ $user_id ][ $key ] = get_user_meta( $user_id, $key, true );
874
  }
875
 
876
  /**
877
  * Updates user SEO option.
878
  *
879
  * @since 2.7.0
 
880
  *
881
  * @param int $user_id The user ID.
882
  * @param string $option The user's SEO metadata option.
@@ -896,9 +930,14 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
896
 
897
  $meta = $this->get_user_meta( $user_id, THE_SEO_FRAMEWORK_USER_OPTIONS, false );
898
 
 
 
 
 
 
899
  $meta[ $option ] = $value;
900
 
901
- return update_user_meta( $user_id, THE_SEO_FRAMEWORK_USER_OPTIONS, $meta );
902
  }
903
 
904
  /**
@@ -1062,7 +1101,7 @@ class AutoDescription_Siteoptions extends AutoDescription_Sanitize {
1062
  * @since 2.5.2
1063
  * @see https://www.facebook.com/translations/FacebookLocales.xml
1064
  *
1065
- * @return array Valid Facebook locales
1066
  */
1067
  public function language_keys() {
1068
  return array(
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Site_Options
28
  *
29
+ * Handles Site Options for the plugin.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Site_Options extends Sanitize {
34
 
35
  /**
36
  * Site Settings field.
60
  */
61
  protected $o_plugin_updated;
62
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  /**
64
  * Constructor, load parent constructor and set up cachable variables.
65
  */
66
+ protected function __construct() {
67
  parent::__construct();
68
 
69
  $this->settings_field = THE_SEO_FRAMEWORK_SITE_OPTIONS;
70
  $this->o_plugin_updated = 'updated_' . THE_SEO_FRAMEWORK_DB_VERSION;
71
  $this->seo_settings_page_slug = 'theseoframework-settings';
72
 
 
 
 
 
 
 
73
  }
74
 
75
  /**
85
  * Switch when RTL is active;
86
  * @since 2.5.0
87
  */
88
+ if ( \is_rtl() ) {
89
  $titleloc = 'left';
90
  $h_titleloc = 'right';
91
  } else {
104
  * @since 2.2.7
105
  */
106
  return array(
107
+ // General. Performance.
108
+ 'cache_meta_description' => 1, // Description transient cache.
109
+ 'cache_meta_schema' => 1, // Schema.org transient cache.
110
+ 'cache_sitemap' => 1, // Sitemap transient cache.
111
+ 'cache_object' => 1, // Object caching.
112
+
113
+ // General. Layout.
114
+ 'display_seo_bar_tables' => 1, // SEO Bar post-list tables.
115
+ 'display_seo_bar_metabox' => 0, // SEO Bar post SEO Settings.
116
+
117
+ // General. Canonical.
118
+ 'canonical_scheme' => 'automatic', // Canonical URL scheme.
119
+
120
  // Title.
121
  'title_seperator' => 'pipe', // Title separator (note: TYPO), dropdown
122
  'title_location' => $titleloc, // Title separation location
127
  'description_separator' => 'pipe', // Description separator, dropdown
128
  'description_additions' => 1, // "Title on Blogname" within Description
129
  'description_blogname' => 1, // "on Blogname" within Description
130
+ // 'description_custom' => '', // Custom prefix
131
 
132
  // Robots directory.
133
  'noodp' => 1, // Site noopd robots settings
206
  'og_tags' => 1, // Output of Open Graph meta tags
207
  'facebook_tags' => 1, // Output the Facebook meta tags
208
  'twitter_tags' => 1, // Output the Twitter meta tags
209
+ // 'googleplus_tags' => 1, // Output the Google+ meta tags
210
+
211
+ // Social FallBack images
212
+ 'social_image_fb_url' => '',
213
+ 'social_image_fb_id' => 0,
214
 
215
  // Webmasters.
216
  'google_verification' => '', // Google Verification Code
246
  'ping_google' => 1, // Ping Google
247
  'ping_bing' => 1, // Ping Bing
248
  'ping_yandex' => 1, // Ping Yandex
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
283
  * Only used within the SEO Settings page.
284
  */
285
  return array(
286
+ 'cache_meta_description' => 0, // Description transient cache.
287
+ 'cache_meta_schema' => 0, // Schema.org transient cache.
288
+ 'cache_sitemap' => 0, // Sitemap transient cache.
289
+ 'cache_object' => 0, // Object caching.
290
+
291
+ 'display_seo_bar_tables' => 0, // SEO Bar post-list tables.
292
+ 'display_seo_bar_metabox' => 0, // SEO Bar post SEO Settings.
293
+
294
  'title_rem_additions' => 1, // Title remove additions.
295
  'title_rem_prefixes' => 0, // Title remove prefixes.
296
 
351
  'og_tags' => 0, // Output of Open Graph meta tags
352
  'facebook_tags' => 0, // Output the Facebook meta tags
353
  'twitter_tags' => 0, // Output the Twitter meta tags
354
+ // 'googleplus_tags' => 0, // Output the Google+ meta tags
355
 
356
  'knowledge_output' => 0, // Default for outputing the Knowledge SEO.
357
  'knowledge_logo' => 0, // Fetch logo from WP Favicon
362
  'ping_google' => 0, // Ping Google
363
  'ping_bing' => 0, // Ping Bing
364
  'ping_yandex' => 0, // Ping Yandex
365
+ 'sitemap_styles' => 0, // Whether to style the sitemap
366
+ 'sitemap_logo' => 0, // Whether to add a logo to the sitemap
367
 
368
  'excerpt_the_feed' => 0, // Generate feed Excerpts
369
  'source_the_feed' => 0, // Add backlink at the end of the feed
414
  return;
415
 
416
  //* If current user isn't allowed to update options, don't do anything.
417
+ if ( ! \current_user_can( $this->settings_capability() ) )
418
  return;
419
 
420
  /**
421
  * Applies filters 'the_seo_framework_update_options_at_update' : bool
422
  * @since 2.6.0
423
  */
424
+ if ( ! \apply_filters( 'the_seo_framework_update_options_at_update', true ) )
425
  return;
426
 
427
  $updated = false;
446
  }
447
 
448
  //* Updated the options. Check for updated flag and see if settings pages are loaded.
449
+ if ( \update_option( $this->settings_field, $options ) && $updated && $this->load_options )
450
  $this->pre_output_site_updated_plugin_notice();
451
 
452
  }
461
 
462
  if ( $this->is_seo_settings_page( false ) ) {
463
  //* Redirect to current page if on options page to correct option values. Once.
464
+ if ( ! isset( $_REQUEST['tsf-settings-updated'] ) || 'true' !== $_REQUEST['tsf-settings-updated'] )
465
+ $this->admin_redirect( $this->seo_settings_page_slug, array( 'tsf-settings-updated' => 'true' ) );
466
 
467
  //* Notice has already been sent.
468
  return;
472
  $this->init_admin_scripts();
473
 
474
  //* Output notice.
475
+ \add_action( 'admin_notices', array( $this, 'site_updated_plugin_notice' ) );
476
 
477
  }
478
 
486
  public function site_updated_plugin_notice() {
487
 
488
  $settings_url = $this->seo_settings_page_url();
489
+ $link = sprintf( '<a href="%s" title="%s" target="_self">%s</a>', $settings_url, \esc_attr__( 'SEO Settings', 'autodescription' ), \esc_html__( 'here', 'autodescription' ) );
490
+ $go_to_page = sprintf( \esc_html_x( 'View the new options %s.', '%s = here', 'autodescription' ), $link );
491
 
492
  $notice = $this->page_defaults['plugin_update_text'] . ' ' . $go_to_page;
493
 
535
  * Applies filters 'the_seo_framework_get_options' : boolean
536
  * @since 2.0.0
537
  */
538
+ return $cache[ $setting ] = \apply_filters( 'the_seo_framework_get_options', \get_option( $setting ), $setting );
539
  }
540
 
541
  /**
545
  * second DB interaction.
546
  *
547
  * @since 2.0.0
548
+ * @since 2.8.2 : No longer decodes entities on request.
549
  * @staticvar array $settings_cache
550
  * @staticvar array $options_cache
551
  * @thanks StudioPress (http://www.studiopress.com/) for some code.
559
 
560
  //* If we need to bypass the cache
561
  if ( ! $use_cache ) {
562
+ $options = \get_option( $setting );
563
 
564
  if ( ! is_array( $options ) || ! array_key_exists( $key, $options ) )
565
  return '';
566
 
567
+ return is_array( $options[ $key ] ) ? \stripslashes_deep( $options[ $key ] ) : stripslashes( $options[ $key ] );
568
  }
569
 
570
  //* Setup caches
583
  $options_cache[ $setting ][ $key ] = '';
584
  } else {
585
  //* Option has not been previously been cached, so cache now
586
+ $options_cache[ $setting ][ $key ] = is_array( $options[ $key ] ) ? \stripslashes_deep( $options[ $key ] ) : stripslashes( $options[ $key ] );
587
  }
588
 
589
  return $options_cache[ $setting ][ $key ];
624
  *
625
  * @since 2.2.7
626
  *
 
 
627
  * @param array $args Additional default options to filter.
 
628
  * @return array The SEO Framework Options
629
  */
630
  protected function default_site_options( $args = array() ) {
631
+ /**
632
+ * Applies filters the_seo_framework_default_site_options : array
633
+ * @since 2.2.7
634
+ */
635
+ return \wp_parse_args(
636
  $args,
637
+ \apply_filters(
638
  'the_seo_framework_default_site_options',
639
+ \wp_parse_args(
640
  $args,
641
  $this->get_default_site_options()
642
  )
647
  /**
648
  * Return the Warned site options. Options which should be 'avoided' return true.
649
  *
 
 
 
650
  * @param array $args Additional warned options to filter.
651
  * @return array The SEO Framework Warned Options
652
  */
653
  protected function warned_site_options( $args = array() ) {
654
+ /**
655
+ * Applies filters the_seo_framework_warned_site_options : array
656
+ * @since 2.3.4
657
+ */
658
+ return \wp_parse_args(
659
  $args,
660
+ \apply_filters(
661
  'the_seo_framework_warned_site_options',
662
+ \wp_parse_args(
663
  $args,
664
  $this->get_warned_site_options()
665
  )
673
  * @since 2.2.2
674
  * @thanks StudioPress (http://www.studiopress.com/) for some code.
675
  *
676
+ * @return void Early if settings can't be registered.
677
  */
678
  public function register_settings() {
679
 
681
  if ( empty( $this->settings_field ) )
682
  return;
683
 
684
+ \register_setting( $this->settings_field, $this->settings_field );
685
+ \add_option( $this->settings_field, $this->default_site_options() );
686
 
687
  //* If this page isn't the SEO Settings page, there's no need to check for a reset.
688
  if ( false === $this->is_seo_settings_page( false ) )
689
  return;
690
 
691
+ if ( $this->get_option( 'tsf-settings-reset', $this->settings_field ) ) {
692
+ if ( \update_option( $this->settings_field, $this->default_site_options() ) ) {
693
+ $this->admin_redirect( $this->seo_settings_page_slug, array( 'tsf-settings-reset' => 'true' ) );
694
  exit;
695
  } else {
696
  $this->admin_redirect( $this->seo_settings_page_slug, array( 'error' => 'true' ) );
704
  *
705
  * @since 2.7.0
706
  *
707
+ * @param string|array $new_option {
708
+ * if string: The string will act as a key for a new empty string option, e.g. : {
709
+ * 'sitemap_index' becomes ['sitemap_index' => '']
710
+ * }
711
+ * if array: The option name(s) and value(s), e.g. : {
712
+ * ['sitemap_index' => 1]
713
+ * }
714
+ * }
715
  * @param string $settings_field The Settings Field to update. Defaults
716
+ * to The SEO Framework settings field.
717
+ * @return bool True on success. False on failure.
718
  */
719
  public function update_settings( $new = '', $settings_field = '' ) {
720
 
721
+ if ( empty( $settings_field ) ) {
722
  $settings_field = $this->settings_field;
723
+ $this->init_sanitizer_filters();
724
+ }
725
 
726
+ $old = \get_option( $settings_field );
727
+ $settings = \wp_parse_args( $new, $old );
728
 
729
+ return \update_option( $settings_field, $settings );
730
  }
731
 
732
  /**
733
  * Get the default of any of the The SEO Framework settings.
734
  *
735
  * @since 2.2.4
736
+ * @since 2.8.2 : No longer decodes entities on request.
737
  * @staticvar array $defaults_cache
738
  * @uses $this->settings_field
739
  * @uses $this->default_site_options()
760
  if ( ! is_array( $defaults ) || ! array_key_exists( $key, $defaults ) )
761
  return -1;
762
 
763
+ return is_array( $defaults[ $key ] ) ? \stripslashes_deep( $defaults[ $key ] ) : stripslashes( $defaults[ $key ] );
764
  }
765
 
766
  static $defaults_cache = array();
876
  if ( isset( $user_id ) )
877
  return $user_id;
878
 
879
+ $user = \wp_get_current_user();
880
 
881
  return $user_id = $user->exists() ? (int) $user->ID : 0;
882
  }
885
  * Fetches The SEO Framework usermeta.
886
  *
887
  * @since 2.7.0
888
+ * @since 2.8.0 Always returns array, even if no value is assigned.
889
  * @staticvar array $usermeta_cache
890
  *
891
  * @param int $user_id The user ID.
896
  public function get_user_meta( $user_id, $key = THE_SEO_FRAMEWORK_USER_OPTIONS, $use_cache = true ) {
897
 
898
  if ( false === $use_cache )
899
+ return ( $meta = \get_user_meta( $user_id, $key, true ) ) && is_array( $meta ) ? $meta : array();
900
 
901
  static $usermeta_cache = array();
902
 
903
  if ( isset( $usermeta_cache[ $user_id ][ $key ] ) )
904
  return $usermeta_cache[ $user_id ][ $key ];
905
 
906
+ return $usermeta_cache[ $user_id ][ $key ] = ( $meta = \get_user_meta( $user_id, $key, true ) ) && is_array( $meta ) ? $meta : array();
907
  }
908
 
909
  /**
910
  * Updates user SEO option.
911
  *
912
  * @since 2.7.0
913
+ * @since 2.8.0 New users now get a new array assigned.
914
  *
915
  * @param int $user_id The user ID.
916
  * @param string $option The user's SEO metadata option.
930
 
931
  $meta = $this->get_user_meta( $user_id, THE_SEO_FRAMEWORK_USER_OPTIONS, false );
932
 
933
+ /**
934
+ * @since 2.8.0 initializes new array on empty values.
935
+ */
936
+ is_array( $meta ) or $meta = array();
937
+
938
  $meta[ $option ] = $value;
939
 
940
+ return \update_user_meta( $user_id, THE_SEO_FRAMEWORK_USER_OPTIONS, $meta );
941
  }
942
 
943
  /**
1101
  * @since 2.5.2
1102
  * @see https://www.facebook.com/translations/FacebookLocales.xml
1103
  *
1104
+ * @return array Valid Facebook locale keys
1105
  */
1106
  public function language_keys() {
1107
  return array(
inc/classes/sitemaps.class.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,16 +23,14 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_Search
23
  *
24
- * Generates sitemap and outputs it.
25
  *
26
- * @since 2.2.9
27
  */
28
- class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
29
 
30
  /**
31
  * Maximum number of posts that show up in the sitemap.xml page.
@@ -54,51 +59,18 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
54
  */
55
  protected $doing_sitemap = false;
56
 
57
- /**
58
- * Unserializing instances of this class is forbidden.
59
- */
60
- private function __wakeup() { }
61
-
62
- /**
63
- * Handle unapproachable invoked methods.
64
- */
65
- public function __call( $name, $arguments ) {
66
- parent::__call( $name, $arguments );
67
- }
68
-
69
  /**
70
  * Constructor, load parent constructor and set up caches.
71
  */
72
- public function __construct() {
73
  parent::__construct();
74
-
75
- //* Whether we're using pretty permalinks.
76
- $this->pretty_permalinks = '' !== $this->permalink_structure();
77
-
78
- /**
79
- * Add query strings to rewrite
80
- */
81
- add_action( 'init', array( $this, 'rewrite_rule_sitemap' ), 1 );
82
- add_filter( 'query_vars', array( $this, 'enqueue_sitemap_query_vars' ), 1 );
83
-
84
- /**
85
- * Adding a higher priority will cause a trailing slash to be added.
86
- * We need to be in front of the queue to prevent this from happening.
87
- */
88
- add_action( 'template_redirect', array( $this, 'maybe_output_sitemap' ), 1 );
89
-
90
- //* Edit the robots.txt file
91
- add_filter( 'robots_txt', array( $this, 'robots_txt' ), 10, 2 );
92
-
93
- //* Enqueue rewrite flush
94
- add_action( 'shutdown', array( $this, 'maybe_flush_rewrite' ), 999 );
95
  }
96
 
97
  /**
98
- * Whether we can output sitemap or not based on options.
99
  *
100
- * @staticvar bool $cache
101
  * @since 2.6.0
 
102
  *
103
  * @return bool
104
  */
@@ -137,31 +109,33 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
137
  if ( $this->detect_sitemap_plugin() )
138
  return;
139
 
140
- add_rewrite_rule( 'sitemap\.xml$', 'index.php?the_seo_framework_sitemap=xml', 'top' );
 
141
  }
142
  }
143
 
144
  /**
145
- * Register the_seo_framework_sitemap to wp_query
146
- *
147
- * @param array vars The WP_Query vars
148
  *
149
  * @since 2.2.9
 
 
 
150
  */
151
  public function enqueue_sitemap_query_vars( $vars ) {
152
 
153
- if ( $this->can_run_sitemap() )
154
  $vars[] = 'the_seo_framework_sitemap';
 
155
 
156
  return $vars;
157
  }
158
 
159
  /**
160
- * Maybe Output sitemap.xml 'file' and header.
 
161
  *
162
  * @since 2.2.9
163
- *
164
- * @return void|header+string SiteMap XML file.
165
  */
166
  public function maybe_output_sitemap() {
167
 
@@ -177,38 +151,60 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
177
  /**
178
  * Applies filters 'the_seo_framework_sitemap_post_limit' : int
179
  * @since 2.2.9
 
180
  */
181
- $this->max_posts = (int) apply_filters( 'the_seo_framework_sitemap_post_limit', 700 );
182
 
183
  /**
184
  * Set at least 2000 variables free.
185
  * Freeing 0.15MB on a clean WordPress installation.
186
  * @since 2.6.0
187
  */
188
- $this->clean_up_globals();
189
 
190
  $this->output_sitemap();
191
  }
192
  }
 
 
 
 
 
 
 
 
193
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  }
195
 
196
  /**
197
- * Destroy unused $GLOBALS.
198
  *
199
  * @since 2.6.0
 
200
  *
201
  * @param bool $get_freed_memory Whether to return the freed memory in bytes.
202
  * @return int $freed_memory
203
  */
204
- protected function clean_up_globals( $get_freed_memory = false ) {
205
 
206
  static $freed_memory = null;
207
 
208
  if ( $get_freed_memory )
209
  return $freed_memory;
210
 
211
- if ( $this->the_seo_framework_debug ) $memory = memory_get_usage();
212
 
213
  $remove = array(
214
  'wp_filter' => array(
@@ -238,83 +234,195 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
238
  }
239
  }
240
 
241
- if ( $this->the_seo_framework_debug ) $freed_memory = $memory - memory_get_usage();
242
 
243
  }
244
 
245
  /**
246
- * Output sitemap.xml 'file' and header.
247
  *
248
  * @since 2.2.9
249
  */
250
  protected function output_sitemap() {
251
 
 
 
 
252
  if ( ! headers_sent() )
253
  header( 'Content-type: text/xml; charset=utf-8' );
254
 
255
- //* Remove output, if any.
256
- if ( ob_get_level() > 0 ) {
257
- if ( ob_get_contents() )
258
- ob_clean();
259
- }
260
-
261
  //* Fetch sitemap content and add trailing line. Already escaped internally.
262
- echo $this->get_sitemap_content() . "\r\n";
 
263
 
264
  // We're done now.
265
- die();
266
  }
267
 
268
  /**
269
  * Output sitemap.xml content from transient.
270
  *
271
- * @since 2.2.9
272
  *
273
  * @return string Sitemap XML contents.
274
  */
275
- protected function get_sitemap_content() {
276
 
277
- if ( $this->the_seo_framework_debug ) $timer_start = microtime( true );
278
 
279
  /**
280
  * Re-use the variable, eliminating database requests
281
  * @since 2.4.0
282
  */
283
- $sitemap_content = $this->get_transient( $this->sitemap_transient );
284
 
285
- if ( false === $sitemap_content ) {
286
- $cached_content = "\r\n<!-- " . __( 'Sitemap is generated for this view', 'autodescription' ) . ' -->';
287
- } else {
288
- $cached_content = "\r\n<!-- " . __( 'Sitemap is served from cache', 'autodescription' ) . ' -->';
 
 
 
 
 
 
289
  }
290
 
291
- $content = '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n";
292
- $content .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\r\n";
293
- $content .= $this->setup_sitemap( $sitemap_content );
294
- $content .= '</urlset>';
295
 
296
- $content .= $cached_content;
 
 
 
 
297
 
298
  /**
299
  * Output debug info.
300
  * @since 2.3.7
301
  */
302
  if ( $this->the_seo_framework_debug ) {
303
- $content .= "\r\n<!-- Site estimated peak usage: " . ( memory_get_peak_usage() / 1024 / 1024 ) . ' MB -->';
304
- $content .= "\r\n<!-- System estimated peak usage: " . ( memory_get_peak_usage( true ) / 1024 / 1024 ) . ' MB -->';
305
- $content .= "\r\n<!-- Freed memory prior to generation: " . $this->clean_up_globals( true ) / 1024 . ' kB -->';
306
- $content .= "\r\n<!-- Sitemap generation time: " . ( number_format( microtime( true ) - $timer_start, 6 ) ) . ' seconds -->';
307
  }
 
308
 
309
- return $content;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  }
311
 
312
  /**
313
- * Create sitemap.xml content transient.
314
  *
315
- * @param string|bool $content required The sitemap transient content.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
316
  *
317
  * @since 2.6.0
 
 
 
318
  */
319
  public function setup_sitemap( $sitemap_content ) {
320
 
@@ -337,20 +445,24 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
337
  /**
338
  * Generate sitemap.xml content.
339
  *
340
- * @param bool $secure Only process when param is given.
341
- *
342
  * @since 2.2.9
 
 
 
343
  */
344
  protected function generate_sitemap() {
345
 
 
 
346
  $content = '';
347
 
348
  /**
349
  * Applies filters the_seo_framework_sitemap_exclude_ids : array of id's
350
  *
351
  * @since 2.5.2
 
352
  */
353
- $excluded = (array) apply_filters( 'the_seo_framework_sitemap_exclude_ids', array() );
354
 
355
  if ( empty( $excluded ) ) {
356
  $excluded = '';
@@ -366,9 +478,9 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
366
  * Applies filters the_seo_framework_sitemap_posts_count : int max posts
367
  * Applies filters the_seo_framework_sitemap_custom_posts_count : int max posts
368
  */
369
- $totalpages = (int) apply_filters( 'the_seo_framework_sitemap_pages_count', $this->max_posts );
370
- $totalposts = (int) apply_filters( 'the_seo_framework_sitemap_posts_count', $this->max_posts );
371
- $total_cpt_posts = (int) apply_filters( 'the_seo_framework_sitemap_custom_posts_count', $this->max_posts );
372
 
373
  $latest_pages = array();
374
  $latest_posts = array();
@@ -392,7 +504,7 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
392
  } else {
393
  $page_lastmod = $this->is_option_checked( 'page_modify_time' );
394
  $post_lastmod = $this->is_option_checked( 'post_modify_time' );
395
- $home_lastmod = $page_lastmod ? $page_lastmod : $this->is_option_checked( 'home_modify_time' );
396
  }
397
 
398
  /**
@@ -400,41 +512,59 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
400
  *
401
  * Applies filter the_seo_framework_sitemap_timestamp : bool
402
  */
403
- $timestamp = (bool) apply_filters( 'the_seo_framework_sitemap_timestamp', true );
404
 
405
  if ( $timestamp )
406
- $content .= '<!-- ' . __( 'Sitemap is generated on', 'autodescription' ) . ' ' . current_time( 'Y-m-d H:i:s' ) . ' -->' . "\r\n";
 
 
 
 
407
 
408
  if ( $totalpages ) {
409
  //* Ascend by the date for normal pages. Older pages get to the top of the list.
410
- $args = array(
411
- 'numberposts' => $totalpages,
412
- 'posts_per_page' => $totalpages,
413
- 'post_type' => 'page',
414
- 'orderby' => 'date',
415
- 'order' => 'ASC',
416
- 'post_status' => 'publish',
417
- 'cache_results' => false,
418
- 'suppress_filters' => true,
 
419
  );
420
- $get_posts = new WP_Query;
421
- $latest_pages = $get_posts->query( $args );
422
- unset( $get_posts );
 
 
 
 
 
 
 
 
 
 
423
  }
424
  $latest_pages_amount = (int) count( $latest_pages );
425
 
426
- if ( $latest_pages_amount > 0 ) {
427
 
428
- $id_on_front = $this->has_page_on_front() ? (int) get_option( 'page_on_front' ) : (int) get_option( 'page_for_posts' );
429
 
430
  /**
431
  * This can be heavy.
432
  */
433
- foreach ( $latest_pages as $page ) {
434
- if ( isset( $page->ID ) ) {
 
 
 
435
  $page_id = $page->ID;
436
 
437
- if ( '' === $excluded || ! isset( $excluded[ $page_id ] ) ) {
438
 
439
  //* Fetch the noindex option, per page.
440
  $indexed = ! $this->get_custom_field( '_genesis_noindex', $page_id );
@@ -466,33 +596,43 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
466
  $content .= "\t</url>\r\n";
467
  }
468
  }
469
- }
470
- }
471
 
472
  //* Free memory.
473
  unset( $latest_pages );
474
- }
475
 
476
  if ( $totalposts ) {
477
  //* Descend by the date for posts. The latest posts get to the top of the list after pages.
478
- $args = array(
479
- 'numberposts' => $totalposts,
480
- 'posts_per_page' => $totalposts,
481
- 'post_type' => 'post',
482
- 'orderby' => 'date',
483
- 'order' => 'DESC',
484
- 'post_status' => 'publish',
485
- 'cache_results' => false,
486
- 'suppress_filters' => true,
 
487
  );
488
- $get_posts = new WP_Query;
489
- $latest_posts = $get_posts->query( $args );
490
- unset( $get_posts );
 
 
 
 
 
 
 
 
 
 
491
  }
492
  $latest_posts_amount = (int) count( $latest_posts );
493
 
494
- if ( $latest_posts_amount > 0 ) {
495
-
496
  /**
497
  * Setting up priorities, with pages always being important.
498
  *
@@ -520,11 +660,14 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
520
  /**
521
  * This can be heavy.
522
  */
523
- foreach ( $latest_posts as $post ) {
524
- if ( isset( $post->ID ) ) {
 
 
 
525
  $post_id = $post->ID;
526
 
527
- if ( '' === $excluded || ! isset( $excluded[ $post_id ] ) ) {
528
 
529
  //* Fetch the noindex option, per page.
530
  $indexed = ! $this->get_custom_field( '_genesis_noindex', $post_id );
@@ -554,21 +697,21 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
554
  $priority = $priority <= (int) 0 ? (int) 0 : (float) $priority;
555
  }
556
  }
557
- }
558
- }
559
 
560
  //* Free memory.
561
  unset( $latest_posts );
562
- }
563
 
564
- if ( $total_cpt_posts ) {
565
- $post_page = (array) get_post_types( array( 'public' => true ) );
566
 
567
  /**
568
  * Applies filters Array the_seo_framework_sitemap_exclude_cpt : Excludes these CPT
569
  * @since 2.5.0
570
  */
571
- $excluded_cpt = (array) apply_filters( 'the_seo_framework_sitemap_exclude_cpt', array() );
572
 
573
  $not_cpt = array( 'post', 'page', 'attachment' );
574
 
@@ -584,24 +727,35 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
584
 
585
  if ( $cpt ) {
586
  //* Descend by the date for CPTs. The latest posts get to the top of the list after pages.
587
- $args = array(
588
- 'numberposts' => $total_cpt_posts,
589
- 'posts_per_page' => $total_cpt_posts,
590
- 'post_type' => $cpt,
591
- 'orderby' => 'date',
592
- 'order' => 'DESC',
593
- 'post_status' => 'publish',
594
- 'cache_results' => false,
595
- 'suppress_filters' => true,
 
596
  );
597
- $get_posts = new WP_Query;
598
- $latest_cpt_posts = $get_posts->query( $args );
599
- unset( $get_posts );
 
 
 
 
 
 
 
 
 
 
600
  }
601
- }
602
  $latest_cpt_posts_amount = (int) count( $latest_cpt_posts );
603
 
604
- if ( $latest_cpt_posts_amount > 0 ) {
605
 
606
  /**
607
  * Setting up priorities, with pages always being important.
@@ -623,11 +777,14 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
623
  /**
624
  * This can be heavy.
625
  */
626
- foreach ( $latest_cpt_posts as $ctp_post ) {
627
- if ( isset( $ctp_post->ID ) ) {
 
 
 
628
  $cpt_id = $ctp_post->ID;
629
 
630
- if ( '' === $excluded || ! isset( $excluded[ $cpt_id ] ) ) {
631
 
632
  //* Fetch the noindex option, per page.
633
  $indexed = ! $this->get_custom_field( '_genesis_noindex', $cpt_id );
@@ -658,12 +815,12 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
658
  $priority_cpt = $priority_cpt <= (int) 0 ? (int) 0 : (float) $priority_cpt;
659
  }
660
  }
661
- }
662
- }
663
 
664
  //* Free memory.
665
  unset( $latest_cpt_posts );
666
- }
667
 
668
  /**
669
  * Applies filters the_seo_framework_sitemap_additional_urls : {
@@ -675,12 +832,12 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
675
  *
676
  * @since 2.5.2
677
  */
678
- $custom_urls = (array) apply_filters( 'the_seo_framework_sitemap_additional_urls', array() );
679
 
680
  if ( $custom_urls ) {
681
 
682
  //* Force ent2ncr to run, regardless of filters.
683
- remove_all_filters( 'pre_ent2ncr', false );
684
 
685
  foreach ( $custom_urls as $url => $args ) {
686
 
@@ -691,10 +848,10 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
691
 
692
  $content .= "\t<url>\r\n";
693
  //* No need to use static vars
694
- $content .= "\t\t<loc>" . ent2ncr( esc_url_raw( $url ) ) . "</loc>\r\n";
695
 
696
  if ( isset( $args['lastmod'] ) && $args['lastmod'] ) {
697
- $content .= "\t\t<lastmod>" . mysql2date( $timestamp_format, $args['lastmod'], false ) . "</lastmod>\r\n";
698
  }
699
 
700
  if ( isset( $args['priority'] ) && $args['priority'] ) {
@@ -712,7 +869,7 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
712
  * Applies filters the_seo_framework_sitemap_extend : string
713
  * @since 2.5.2
714
  */
715
- $extend = (string) apply_filters( 'the_seo_framework_sitemap_extend', '' );
716
 
717
  if ( $extend )
718
  $content .= "\t" . $extend . "\r\n";
@@ -727,50 +884,47 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
727
  * Ping search engines on post publish.
728
  *
729
  * @since 2.2.9
 
 
 
730
  */
731
  public function ping_searchengines() {
732
 
733
- /**
734
- * Don't ping if the blog isn't public.
735
- * @since 2.3.1
736
- */
737
- if ( false === $this->is_option_checked( 'site_noindex' ) && $this->is_blog_public() ) {
738
- global $blog_id;
739
 
740
- $blog_id = (string) $blog_id;
741
 
742
- $transient = 'tsf_throttle_ping_' . $blog_id;
743
 
744
- //* NOTE: Use legacy get_transient to prevent ping spam.
745
- if ( false === get_transient( $transient ) ) {
746
- //* Transient doesn't exist yet.
747
 
748
- if ( $this->is_option_checked( 'ping_google' ) )
749
- $this->ping_google();
750
 
751
- if ( $this->is_option_checked( 'ping_bing' ) )
752
- $this->ping_bing();
753
 
754
- if ( $this->is_option_checked( 'ping_yandex' ) )
755
- $this->ping_yandex();
756
 
757
- // Sorry, I couldn't help myself.
758
- $throttle = 'Bert and Ernie are weird.';
759
 
760
- /**
761
- * Limit the pinging to a maximum of 1 per hour.
762
- * Transient expiration. 1 hour.
763
- *
764
- * Applies filters the_seo_framework_sitemap_throttle_s
765
- * @since 2.5.1
766
- */
767
- $expiration = (int) apply_filters( 'the_seo_framework_sitemap_throttle_s', HOUR_IN_SECONDS );
768
 
769
- //* @NOTE: Using legacy set_transient to prevent ping spam.
770
- set_transient( $transient, $throttle, $expiration );
771
- }
772
  }
773
-
774
  }
775
 
776
  /**
@@ -779,10 +933,8 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
779
  * @since 2.2.9
780
  */
781
  public function ping_google() {
782
-
783
  $pingurl = 'http://www.google.com/webmasters/sitemaps/ping?sitemap=' . urlencode( $this->the_home_url_from_cache( true ) . 'sitemap.xml' );
784
- wp_safe_remote_get( $pingurl, array( 'timeout' => 3 ) );
785
-
786
  }
787
 
788
  /**
@@ -791,10 +943,8 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
791
  * @since 2.2.9
792
  */
793
  public function ping_bing() {
794
-
795
  $pingurl = 'http://www.bing.com/webmaster/ping.aspx?siteMap=' . urlencode( $this->the_home_url_from_cache( true ) . 'sitemap.xml' );
796
- wp_safe_remote_get( $pingurl, array( 'timeout' => 3 ) );
797
-
798
  }
799
 
800
  /**
@@ -803,109 +953,39 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
803
  * @since 2.6.0
804
  */
805
  public function ping_yandex() {
806
-
807
  $pingurl = 'http://blogs.yandex.ru/pings/?status=success&url=' . urlencode( $this->the_home_url_from_cache( true ) . 'sitemap.xml' );
808
- wp_safe_remote_get( $pingurl, array( 'timeout' => 3 ) );
809
-
810
- }
811
-
812
- /**
813
- * Edits the robots.txt output
814
- *
815
- * Requires not to have a robots.txt file in the root directory
816
- *
817
- * @uses robots_txt filter located at WP core
818
- *
819
- * @since 2.2.9
820
- *
821
- * @global int $blog_id;
822
- *
823
- * @todo maybe combine with noindex/noarchive/(nofollow) -> only when object caching?
824
- */
825
- public function robots_txt( $robots_txt = '', $public = '' ) {
826
- global $blog_id;
827
-
828
- /**
829
- * Don't do anything if the blog isn't public
830
- */
831
- if ( '0' === $public )
832
- return $robots_txt;
833
-
834
- $revision = '1';
835
-
836
- $cache_key = 'robots_txt_output_' . $revision . $blog_id;
837
-
838
- $output = $this->object_cache_get( $cache_key );
839
- if ( false === $output ) {
840
- $output = '';
841
-
842
- /**
843
- * Apply filters the_seo_framework_robots_txt_pre & the_seo_framework_robots_txt_pro
844
- * : Add custom cacheable lines.
845
- * : Don't forget to add line breaks ( "\r\n" | PHP_EOL )
846
- *
847
- * @since 2.5.0
848
- */
849
- $pre = (string) apply_filters( 'the_seo_framework_robots_txt_pre', '' );
850
- $pro = (string) apply_filters( 'the_seo_framework_robots_txt_pro', '' );
851
-
852
- $site_url = wp_parse_url( site_url() );
853
- $path = ( ! empty( $site_url['path'] ) ) ? $site_url['path'] : '';
854
-
855
- $output .= $pre;
856
- //* Output defaults
857
- $output .= "User-agent: *\r\n";
858
- $output .= "Disallow: $path/wp-admin/\r\n";
859
- $output .= "Allow: $path/wp-admin/admin-ajax.php\r\n";
860
-
861
- /**
862
- * Prevents query indexing
863
- * @since 2.2.9
864
- *
865
- * Applies filters the_seo_framework_robots_disallow_queries : Whether to allow queries for robots.
866
- * @since 2.5.0
867
- */
868
- if ( apply_filters( 'the_seo_framework_robots_disallow_queries', false ) ) {
869
- $home_url = wp_parse_url( rtrim( $this->the_home_url_from_cache(), ' /\\' ) );
870
- $home_path = ( ! empty( $home_url['path'] ) ) ? $home_url['path'] : '';
871
- $output .= "Disallow: $home_path/*?*\r\n";
872
- }
873
-
874
- $output .= $pro;
875
-
876
- if ( $this->get_option( 'sitemaps_robots' ) && $this->can_do_sitemap_robots() ) {
877
- //* Add whitespace before sitemap.
878
- $output .= "\r\n";
879
-
880
- //* Add sitemap full url
881
- $output .= 'Sitemap: ' . $this->the_home_url_from_cache( true ) . "sitemap.xml\r\n";
882
- }
883
-
884
- $this->object_cache_set( $cache_key, $output, 86400 );
885
- }
886
-
887
- /**
888
- * Completely override robots with output.
889
- * @since 2.5.0
890
- */
891
- $robots_txt = $output;
892
-
893
- return $robots_txt;
894
  }
895
 
896
  /**
897
  * Initialize and flush rewrite rules.
898
  *
899
  * @since 2.6.0
 
900
  * @access private
 
901
  */
902
  public function flush_rewrite_rules() {
903
  global $wp_rewrite;
904
 
905
  $this->rewrite_rule_sitemap();
906
 
907
- $wp_rewrite->init();
908
- $wp_rewrite->flush_rules( true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
909
  }
910
 
911
  /**
@@ -1006,13 +1086,11 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
1006
  * @access private
1007
  */
1008
  public function flush_rewrite_rules_activation() {
1009
- global $wp_rewrite;
1010
 
1011
  //* This function is called statically.
1012
  $this->rewrite_rule_sitemap( true );
1013
 
1014
- $wp_rewrite->init();
1015
- $wp_rewrite->flush_rules( true );
1016
 
1017
  }
1018
 
@@ -1021,6 +1099,7 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
1021
  *
1022
  * @since 2.6.6.1
1023
  * @access private
 
1024
  */
1025
  public function flush_rewrite_rules_deactivation() {
1026
  global $wp_rewrite;
@@ -1032,4 +1111,36 @@ class AutoDescription_Sitemaps extends AutoDescription_Metaboxes {
1032
  $wp_rewrite->flush_rules( true );
1033
 
1034
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1035
  }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Sitemaps
28
  *
29
+ * Handles sitemap output.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Sitemaps extends Metaboxes {
34
 
35
  /**
36
  * Maximum number of posts that show up in the sitemap.xml page.
59
  */
60
  protected $doing_sitemap = false;
61
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  /**
63
  * Constructor, load parent constructor and set up caches.
64
  */
65
+ protected function __construct() {
66
  parent::__construct();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
 
69
  /**
70
+ * Determines whether we can output sitemap or not based on options.
71
  *
 
72
  * @since 2.6.0
73
+ * @staticvar bool $cache
74
  *
75
  * @return bool
76
  */
109
  if ( $this->detect_sitemap_plugin() )
110
  return;
111
 
112
+ \add_rewrite_rule( 'sitemap\.xml$', 'index.php?the_seo_framework_sitemap=xml', 'top' );
113
+ \add_rewrite_rule( 'sitemap\.xsl$', 'index.php?the_seo_framework_sitemap=xsl', 'top' );
114
  }
115
  }
116
 
117
  /**
118
+ * Registers the_seo_framework_sitemap to WP_Query.
 
 
119
  *
120
  * @since 2.2.9
121
+ *
122
+ * @param array $vars The WP_Query variables.
123
+ * @return array $vars The adjusted vars.
124
  */
125
  public function enqueue_sitemap_query_vars( $vars ) {
126
 
127
+ if ( $this->can_run_sitemap() ) {
128
  $vars[] = 'the_seo_framework_sitemap';
129
+ }
130
 
131
  return $vars;
132
  }
133
 
134
  /**
135
+ * Outputs sitemap.xml 'file' and header on sitemap query.
136
+ * Also cleans up globals and sets up variables.
137
  *
138
  * @since 2.2.9
 
 
139
  */
140
  public function maybe_output_sitemap() {
141
 
151
  /**
152
  * Applies filters 'the_seo_framework_sitemap_post_limit' : int
153
  * @since 2.2.9
154
+ * @since 2.8.0 Increased to 1200 from 700.
155
  */
156
+ $this->max_posts = (int) \apply_filters( 'the_seo_framework_sitemap_post_limit', 1200 );
157
 
158
  /**
159
  * Set at least 2000 variables free.
160
  * Freeing 0.15MB on a clean WordPress installation.
161
  * @since 2.6.0
162
  */
163
+ $this->clean_up_globals_for_sitemap();
164
 
165
  $this->output_sitemap();
166
  }
167
  }
168
+ }
169
+
170
+ /**
171
+ * Outputs sitemap.xsl 'file' and header on sitemap stylesheet query.
172
+ *
173
+ * @since 2.2.9
174
+ */
175
+ public function maybe_output_sitemap_stylesheet() {
176
 
177
+ if ( $this->can_run_sitemap() ) {
178
+ global $wp_query;
179
+
180
+ if ( isset( $wp_query->query_vars['the_seo_framework_sitemap'] ) && 'xsl' === $wp_query->query_vars['the_seo_framework_sitemap'] ) {
181
+ // Don't let WordPress think this is 404.
182
+ $wp_query->is_404 = false;
183
+
184
+ $this->doing_sitemap = true;
185
+
186
+ $this->output_sitemap_xsl_stylesheet();
187
+ }
188
+ }
189
  }
190
 
191
  /**
192
+ * Destroys unused $GLOBALS. To be used prior to outputting sitemap.
193
  *
194
  * @since 2.6.0
195
+ * @since 2.8.0 Renamed from clean_up_globals().
196
  *
197
  * @param bool $get_freed_memory Whether to return the freed memory in bytes.
198
  * @return int $freed_memory
199
  */
200
+ protected function clean_up_globals_for_sitemap( $get_freed_memory = false ) {
201
 
202
  static $freed_memory = null;
203
 
204
  if ( $get_freed_memory )
205
  return $freed_memory;
206
 
207
+ $this->the_seo_framework_debug and $memory = memory_get_usage();
208
 
209
  $remove = array(
210
  'wp_filter' => array(
234
  }
235
  }
236
 
237
+ $this->the_seo_framework_debug and $freed_memory = $memory - memory_get_usage();
238
 
239
  }
240
 
241
  /**
242
+ * Outputs sitemap.xml 'file' and header.
243
  *
244
  * @since 2.2.9
245
  */
246
  protected function output_sitemap() {
247
 
248
+ //* Remove output, if any.
249
+ $this->clean_reponse_header();
250
+
251
  if ( ! headers_sent() )
252
  header( 'Content-type: text/xml; charset=utf-8' );
253
 
 
 
 
 
 
 
254
  //* Fetch sitemap content and add trailing line. Already escaped internally.
255
+ $this->output_sitemap_content();
256
+ echo "\r\n";
257
 
258
  // We're done now.
259
+ exit;
260
  }
261
 
262
  /**
263
  * Output sitemap.xml content from transient.
264
  *
265
+ * @since 2.8.0
266
  *
267
  * @return string Sitemap XML contents.
268
  */
269
+ protected function output_sitemap_content() {
270
 
271
+ $this->the_seo_framework_debug and $timer_start = microtime( true );
272
 
273
  /**
274
  * Re-use the variable, eliminating database requests
275
  * @since 2.4.0
276
  */
277
+ $sitemap_content = $this->is_option_checked( 'cache_sitemap' ) ? $this->get_transient( $this->sitemap_transient ) : false;
278
 
279
+ echo '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n";
280
+ echo $this->get_sitemap_xsl_stylesheet_tag();
281
+
282
+ /**
283
+ * Output debug prior output.
284
+ * @since 2.8.0
285
+ */
286
+ if ( $this->the_seo_framework_debug ) {
287
+ echo '<!-- Site estimated peak usage prior to generation: ' . number_format( memory_get_peak_usage() / 1024 / 1024, 3 ) . ' MB -->' . "\r\n";
288
+ echo '<!-- System estimated peak usage prior to generation: ' . number_format( memory_get_peak_usage( true ) / 1024 / 1024, 3 ) . ' MB -->' . "\r\n";
289
  }
290
 
291
+ echo $this->get_sitemap_urlset_open_tag();
292
+ echo $this->setup_sitemap( $sitemap_content );
293
+ echo $this->get_sitemap_urlset_close_tag();
 
294
 
295
+ if ( false === $sitemap_content ) {
296
+ echo "\r\n" . '<!-- ' . \esc_html__( 'Sitemap is generated for this view', 'autodescription' ) . ' -->';
297
+ } else {
298
+ echo "\r\n" . '<!-- ' . \esc_html__( 'Sitemap is served from cache', 'autodescription' ) . ' -->';
299
+ }
300
 
301
  /**
302
  * Output debug info.
303
  * @since 2.3.7
304
  */
305
  if ( $this->the_seo_framework_debug ) {
306
+ echo "\r\n" . '<!-- Site estimated peak usage: ' . number_format( memory_get_peak_usage() / 1024 / 1024, 3 ) . ' MB -->';
307
+ echo "\r\n" . '<!-- System estimated peak usage: ' . number_format( memory_get_peak_usage( true ) / 1024 / 1024, 3 ) . ' MB -->';
308
+ echo "\r\n" . '<!-- Freed memory prior to generation: ' . number_format( $this->clean_up_globals( true ) / 1024, 3 ) . ' kB -->';
309
+ echo "\r\n" . '<!-- Sitemap generation time: ' . ( number_format( microtime( true ) - $timer_start, 6 ) ) . ' seconds -->';
310
  }
311
+ }
312
 
313
+ /**
314
+ * Returns the opening tag for the sitemap URLset.
315
+ *
316
+ * @since 2.8.0
317
+ *
318
+ * @return string The sitemap URLset opening tag.
319
+ */
320
+ public function get_sitemap_urlset_open_tag() {
321
+
322
+ $schemas = array(
323
+ 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9',
324
+ 'xmlns:xhtml' => 'http://www.w3.org/1999/xhtml',
325
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
326
+ 'xsi:schemaLocation' => array(
327
+ 'http://www.sitemaps.org/schemas/sitemap/0.9',
328
+ 'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd',
329
+ ),
330
+ );
331
+
332
+ /**
333
+ * Applies filters 'the_seo_framework_sitemap_schemas' : array
334
+ * @since 2.8.0
335
+ * @param array $schems The schema list. URLs are expected to be escaped.
336
+ */
337
+ $schemas = (array) \apply_filters( 'the_seo_framework_sitemap_schemas', $schemas );
338
+
339
+ $urlset = '<urlset';
340
+ foreach ( $schemas as $type => $values ) {
341
+ $urlset .= ' ' . $type . '="';
342
+ if ( is_array( $values ) ) {
343
+ $urlset .= implode( ' ', $values );
344
+ } else {
345
+ $urlset .= $values;
346
+ }
347
+ $urlset .= '"';
348
+ }
349
+ $urlset .= '>';
350
+
351
+ return $urlset . "\r\n";
352
  }
353
 
354
  /**
355
+ * Returns the closing tag for the sitemap URLset.
356
  *
357
+ * @since 2.8.0
358
+ *
359
+ * @return string The sitemap URLset closing tag.
360
+ */
361
+ public function get_sitemap_urlset_close_tag() {
362
+ return '</urlset>';
363
+ }
364
+
365
+ /**
366
+ * Returns stylesheet XSL location tag.
367
+ *
368
+ * @since 2.8.0
369
+ *
370
+ * @return string The sitemap XSL location tag.
371
+ */
372
+ public function get_sitemap_xsl_stylesheet_tag() {
373
+
374
+ if ( $this->is_option_checked( 'sitemap_styles' ) )
375
+ return sprintf( '<?xml-stylesheet type="text/xsl" href="%s"?>', \esc_url( $this->get_sitemap_xsl_url() ) ) . "\r\n";
376
+
377
+ return '';
378
+ }
379
+
380
+ /**
381
+ * Returns the stylesheet XSL location URL.
382
+ *
383
+ * @since 2.8.0
384
+ *
385
+ * @return string URL location of the XSL stylesheet. Unescaped.
386
+ */
387
+ public function get_sitemap_xsl_url() {
388
+ global $wp_rewrite;
389
+
390
+ if ( $wp_rewrite->using_index_permalinks() ) {
391
+ $xsl = \home_url( '/index.php/sitemap.xsl' );
392
+ } elseif ( $wp_rewrite->using_permalinks() ) {
393
+ $xsl = \home_url( '/sitemap.xsl' );
394
+ } else {
395
+ $xsl = \home_url( '/?the_seo_framework_sitemap-xsl=true' );
396
+ }
397
+
398
+ return $xsl;
399
+ }
400
+
401
+ /**
402
+ * Sitemap XSL stylesheet output.
403
+ *
404
+ * @since 2.8.0
405
+ */
406
+ public function output_sitemap_xsl_stylesheet() {
407
+
408
+ $this->clean_reponse_header();
409
+
410
+ if ( ! headers_sent() ) {
411
+ header( 'Content-type: text/xsl; charset=utf-8' );
412
+ header( 'Cache-Control: max-age=1800' );
413
+ }
414
+
415
+ $this->get_view( 'sitemap/xsl-stylesheet' );
416
+ exit;
417
+ }
418
+
419
+ /**
420
+ * Create sitemap.xml content transient.
421
  *
422
  * @since 2.6.0
423
+ *
424
+ * @param string|bool $content required The sitemap transient content.
425
+ * @return string The sitemap content.
426
  */
427
  public function setup_sitemap( $sitemap_content ) {
428
 
445
  /**
446
  * Generate sitemap.xml content.
447
  *
 
 
448
  * @since 2.2.9
449
+ * @since 2.8.0 Now adjusts memory limit when possible.
450
+ *
451
+ * @return string The sitemap content.
452
  */
453
  protected function generate_sitemap() {
454
 
455
+ \wp_is_ini_value_changeable( 'memory_limit' ) and @ini_set( 'memory_limit', WP_MAX_MEMORY_LIMIT );
456
+
457
  $content = '';
458
 
459
  /**
460
  * Applies filters the_seo_framework_sitemap_exclude_ids : array of id's
461
  *
462
  * @since 2.5.2
463
+ * @since 2.8.0 : No longer accepts '0' as entry.
464
  */
465
+ $excluded = (array) \apply_filters( 'the_seo_framework_sitemap_exclude_ids', array() );
466
 
467
  if ( empty( $excluded ) ) {
468
  $excluded = '';
478
  * Applies filters the_seo_framework_sitemap_posts_count : int max posts
479
  * Applies filters the_seo_framework_sitemap_custom_posts_count : int max posts
480
  */
481
+ $totalpages = (int) \apply_filters( 'the_seo_framework_sitemap_pages_count', $this->max_posts );
482
+ $totalposts = (int) \apply_filters( 'the_seo_framework_sitemap_posts_count', $this->max_posts );
483
+ $total_cpt_posts = (int) \apply_filters( 'the_seo_framework_sitemap_custom_posts_count', $this->max_posts );
484
 
485
  $latest_pages = array();
486
  $latest_posts = array();
504
  } else {
505
  $page_lastmod = $this->is_option_checked( 'page_modify_time' );
506
  $post_lastmod = $this->is_option_checked( 'post_modify_time' );
507
+ $home_lastmod = $page_lastmod ?: $this->is_option_checked( 'home_modify_time' );
508
  }
509
 
510
  /**
512
  *
513
  * Applies filter the_seo_framework_sitemap_timestamp : bool
514
  */
515
+ $timestamp = (bool) \apply_filters( 'the_seo_framework_sitemap_timestamp', true );
516
 
517
  if ( $timestamp )
518
+ $content .= '<!-- ' . \esc_html__( 'Sitemap is generated on', 'autodescription' ) . ' ' . \current_time( 'Y-m-d H:i:s' ) . ' -->' . "\r\n";
519
+
520
+ $wp_query = new \WP_Query;
521
+ $wp_query->init();
522
+ $query = $wp_query->query = $wp_query->query_vars = array();
523
 
524
  if ( $totalpages ) {
525
  //* Ascend by the date for normal pages. Older pages get to the top of the list.
526
+ $defaults = array(
527
+ 'posts_per_page' => $totalpages,
528
+ 'post_type' => 'page',
529
+ 'orderby' => 'date',
530
+ 'order' => 'ASC',
531
+ 'post_status' => 'publish',
532
+ 'fields' => 'ids',
533
+ 'cache_results' => false,
534
+ 'suppress_filters' => true,
535
+ 'no_found_rows' => true,
536
  );
537
+
538
+ /**
539
+ * Applies filters 'the_seo_framework_sitemap_pages_query_args' : array
540
+ *
541
+ * @since 2.8.0
542
+ *
543
+ * @param array $args The new query arguments.
544
+ * @param array $defaults The default query arguments
545
+ */
546
+ $args = \apply_filters( 'the_seo_framework_sitemap_pages_query_args', array(), $defaults );
547
+
548
+ $wp_query->query = $wp_query->query_vars = \wp_parse_args( $args, $defaults );
549
+ $latest_pages = $wp_query->get_posts();
550
  }
551
  $latest_pages_amount = (int) count( $latest_pages );
552
 
553
+ if ( $latest_pages_amount > 0 ) :
554
 
555
+ $id_on_front = $this->has_page_on_front() ? (int) \get_option( 'page_on_front' ) : (int) \get_option( 'page_for_posts' );
556
 
557
  /**
558
  * This can be heavy.
559
  */
560
+ foreach ( $latest_pages as $page_id ) :
561
+
562
+ $page = \get_post( $page_id );
563
+
564
+ if ( isset( $page->ID ) ) :
565
  $page_id = $page->ID;
566
 
567
+ if ( '' === $excluded || empty( $excluded[ $page_id ] ) ) {
568
 
569
  //* Fetch the noindex option, per page.
570
  $indexed = ! $this->get_custom_field( '_genesis_noindex', $page_id );
596
  $content .= "\t</url>\r\n";
597
  }
598
  }
599
+ endif;
600
+ endforeach;
601
 
602
  //* Free memory.
603
  unset( $latest_pages );
604
+ endif;
605
 
606
  if ( $totalposts ) {
607
  //* Descend by the date for posts. The latest posts get to the top of the list after pages.
608
+ $defaults = array(
609
+ 'posts_per_page' => $totalposts,
610
+ 'post_type' => 'post',
611
+ 'orderby' => 'date',
612
+ 'order' => 'DESC',
613
+ 'post_status' => 'publish',
614
+ 'fields' => 'ids',
615
+ 'cache_results' => false,
616
+ 'suppress_filters' => true,
617
+ 'no_found_rows' => true,
618
  );
619
+
620
+ /**
621
+ * Applies filters 'the_seo_framework_sitemap_posts_query_args' : array
622
+ *
623
+ * @since 2.8.0
624
+ *
625
+ * @param array $args The new query arguments.
626
+ * @param array $defaults The default query arguments
627
+ */
628
+ $args = \apply_filters( 'the_seo_framework_sitemap_posts_query_args', array(), $defaults );
629
+
630
+ $wp_query->query = $wp_query->query_vars = \wp_parse_args( $args, $defaults );
631
+ $latest_posts = $wp_query->get_posts();
632
  }
633
  $latest_posts_amount = (int) count( $latest_posts );
634
 
635
+ if ( $latest_posts_amount > 0 ) :
 
636
  /**
637
  * Setting up priorities, with pages always being important.
638
  *
660
  /**
661
  * This can be heavy.
662
  */
663
+ foreach ( $latest_posts as $post_id ) :
664
+
665
+ $post = \get_post( $post_id );
666
+
667
+ if ( isset( $post->ID ) ) :
668
  $post_id = $post->ID;
669
 
670
+ if ( '' === $excluded || empty( $excluded[ $post_id ] ) ) {
671
 
672
  //* Fetch the noindex option, per page.
673
  $indexed = ! $this->get_custom_field( '_genesis_noindex', $post_id );
697
  $priority = $priority <= (int) 0 ? (int) 0 : (float) $priority;
698
  }
699
  }
700
+ endif;
701
+ endforeach;
702
 
703
  //* Free memory.
704
  unset( $latest_posts );
705
+ endif;
706
 
707
+ if ( $total_cpt_posts ) :
708
+ $post_page = (array) \get_post_types( array( 'public' => true ) );
709
 
710
  /**
711
  * Applies filters Array the_seo_framework_sitemap_exclude_cpt : Excludes these CPT
712
  * @since 2.5.0
713
  */
714
+ $excluded_cpt = (array) \apply_filters( 'the_seo_framework_sitemap_exclude_cpt', array() );
715
 
716
  $not_cpt = array( 'post', 'page', 'attachment' );
717
 
727
 
728
  if ( $cpt ) {
729
  //* Descend by the date for CPTs. The latest posts get to the top of the list after pages.
730
+ $defaults = array(
731
+ 'posts_per_page' => $total_cpt_posts,
732
+ 'post_type' => $cpt,
733
+ 'orderby' => 'date',
734
+ 'order' => 'DESC',
735
+ 'post_status' => 'publish',
736
+ 'fields' => 'ids',
737
+ 'cache_results' => false,
738
+ 'suppress_filters' => true,
739
+ 'no_found_rows' => true,
740
  );
741
+
742
+ /**
743
+ * Applies filters 'the_seo_framework_sitemap_posts_query_args' : array
744
+ *
745
+ * @since 2.8.0
746
+ *
747
+ * @param array $args The new query arguments.
748
+ * @param array $defaults The default query arguments
749
+ */
750
+ $args = \apply_filters( 'the_seo_framework_sitemap_cpt_query_args', array(), $defaults );
751
+
752
+ $wp_query->query = $wp_query->query_vars = \wp_parse_args( $args, $defaults );
753
+ $latest_cpt_posts = $wp_query->get_posts();
754
  }
755
+ endif;
756
  $latest_cpt_posts_amount = (int) count( $latest_cpt_posts );
757
 
758
+ if ( $latest_cpt_posts_amount > 0 ) :
759
 
760
  /**
761
  * Setting up priorities, with pages always being important.
777
  /**
778
  * This can be heavy.
779
  */
780
+ foreach ( $latest_cpt_posts as $ctp_post_id ) :
781
+
782
+ $ctp_post = \get_post( $ctp_post_id );
783
+
784
+ if ( isset( $ctp_post->ID ) ) :
785
  $cpt_id = $ctp_post->ID;
786
 
787
+ if ( '' === $excluded || empty( $excluded[ $cpt_id ] ) ) {
788
 
789
  //* Fetch the noindex option, per page.
790
  $indexed = ! $this->get_custom_field( '_genesis_noindex', $cpt_id );
815
  $priority_cpt = $priority_cpt <= (int) 0 ? (int) 0 : (float) $priority_cpt;
816
  }
817
  }
818
+ endif;
819
+ endforeach;
820
 
821
  //* Free memory.
822
  unset( $latest_cpt_posts );
823
+ endif;
824
 
825
  /**
826
  * Applies filters the_seo_framework_sitemap_additional_urls : {
832
  *
833
  * @since 2.5.2
834
  */
835
+ $custom_urls = (array) \apply_filters( 'the_seo_framework_sitemap_additional_urls', array() );
836
 
837
  if ( $custom_urls ) {
838
 
839
  //* Force ent2ncr to run, regardless of filters.
840
+ \remove_all_filters( 'pre_ent2ncr', false );
841
 
842
  foreach ( $custom_urls as $url => $args ) {
843
 
848
 
849
  $content .= "\t<url>\r\n";
850
  //* No need to use static vars
851
+ $content .= "\t\t<loc>" . \ent2ncr( \esc_url_raw( $url ) ) . "</loc>\r\n";
852
 
853
  if ( isset( $args['lastmod'] ) && $args['lastmod'] ) {
854
+ $content .= "\t\t<lastmod>" . \mysql2date( $timestamp_format, $args['lastmod'], false ) . "</lastmod>\r\n";
855
  }
856
 
857
  if ( isset( $args['priority'] ) && $args['priority'] ) {
869
  * Applies filters the_seo_framework_sitemap_extend : string
870
  * @since 2.5.2
871
  */
872
+ $extend = (string) \apply_filters( 'the_seo_framework_sitemap_extend', '' );
873
 
874
  if ( $extend )
875
  $content .= "\t" . $extend . "\r\n";
884
  * Ping search engines on post publish.
885
  *
886
  * @since 2.2.9
887
+ * @global int $blog_id
888
+ *
889
+ * @return void Early if blog is not public.
890
  */
891
  public function ping_searchengines() {
892
 
893
+ if ( $this->is_option_checked( 'site_noindex' ) || $this->is_blog_public() )
894
+ return;
 
 
 
 
895
 
896
+ $blog_id = (string) $GLOBALS['blog_id'];
897
 
898
+ $transient = 'tsf_throttle_ping_' . $blog_id;
899
 
900
+ //* NOTE: Use legacy get_transient to prevent ping spam.
901
+ if ( false === \get_transient( $transient ) ) {
902
+ //* Transient doesn't exist yet.
903
 
904
+ if ( $this->is_option_checked( 'ping_google' ) )
905
+ $this->ping_google();
906
 
907
+ if ( $this->is_option_checked( 'ping_bing' ) )
908
+ $this->ping_bing();
909
 
910
+ if ( $this->is_option_checked( 'ping_yandex' ) )
911
+ $this->ping_yandex();
912
 
913
+ // Sorry, I couldn't help myself.
914
+ $throttle = 'Bert and Ernie are weird.';
915
 
916
+ /**
917
+ * Limit the pinging to a maximum of 1 per hour.
918
+ * Transient expiration. 1 hour.
919
+ *
920
+ * Applies filters the_seo_framework_sitemap_throttle_s
921
+ * @since 2.5.1
922
+ */
923
+ $expiration = (int) \apply_filters( 'the_seo_framework_sitemap_throttle_s', HOUR_IN_SECONDS );
924
 
925
+ //* @NOTE: Using legacy set_transient to prevent ping spam.
926
+ \set_transient( $transient, $throttle, $expiration );
 
927
  }
 
928
  }
929
 
930
  /**
933
  * @since 2.2.9
934
  */
935
  public function ping_google() {
 
936
  $pingurl = 'http://www.google.com/webmasters/sitemaps/ping?sitemap=' . urlencode( $this->the_home_url_from_cache( true ) . 'sitemap.xml' );
937
+ \wp_safe_remote_get( $pingurl, array( 'timeout' => 3 ) );
 
938
  }
939
 
940
  /**
943
  * @since 2.2.9
944
  */
945
  public function ping_bing() {
 
946
  $pingurl = 'http://www.bing.com/webmaster/ping.aspx?siteMap=' . urlencode( $this->the_home_url_from_cache( true ) . 'sitemap.xml' );
947
+ \wp_safe_remote_get( $pingurl, array( 'timeout' => 3 ) );
 
948
  }
949
 
950
  /**
953
  * @since 2.6.0
954
  */
955
  public function ping_yandex() {
 
956
  $pingurl = 'http://blogs.yandex.ru/pings/?status=success&url=' . urlencode( $this->the_home_url_from_cache( true ) . 'sitemap.xml' );
957
+ \wp_safe_remote_get( $pingurl, array( 'timeout' => 3 ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
958
  }
959
 
960
  /**
961
  * Initialize and flush rewrite rules.
962
  *
963
  * @since 2.6.0
964
+ * @since 2.8.0 : Deprecated?
965
  * @access private
966
+ * @deprecated silently.
967
  */
968
  public function flush_rewrite_rules() {
969
  global $wp_rewrite;
970
 
971
  $this->rewrite_rule_sitemap();
972
 
973
+ \flush_rewrite_rules();
974
+ }
975
+
976
+ /**
977
+ * Enqueues rewrite rules flush.
978
+ *
979
+ * @since 2.8.0
980
+ */
981
+ public function reinitialize_rewrite() {
982
+
983
+ if ( $this->get_option( 'sitemaps_output', false ) ) {
984
+ $this->rewrite_rule_sitemap();
985
+ $this->enqueue_rewrite_activate( true );
986
+ } else {
987
+ $this->enqueue_rewrite_deactivate( true );
988
+ }
989
  }
990
 
991
  /**
1086
  * @access private
1087
  */
1088
  public function flush_rewrite_rules_activation() {
 
1089
 
1090
  //* This function is called statically.
1091
  $this->rewrite_rule_sitemap( true );
1092
 
1093
+ \flush_rewrite_rules();
 
1094
 
1095
  }
1096
 
1099
  *
1100
  * @since 2.6.6.1
1101
  * @access private
1102
+ * @global object $wp_rewrite
1103
  */
1104
  public function flush_rewrite_rules_deactivation() {
1105
  global $wp_rewrite;
1111
  $wp_rewrite->flush_rules( true );
1112
 
1113
  }
1114
+
1115
+ /**
1116
+ * Returns sitemap color scheme.
1117
+ *
1118
+ * @since 2.8.0
1119
+ *
1120
+ * @param bool $get_defaults Whether to get the default colors.
1121
+ * @return array The sitemap colors.
1122
+ */
1123
+ public function get_sitemap_colors( $get_defaults = false ) {
1124
+
1125
+ if ( $get_defaults ) {
1126
+ $retval = array(
1127
+ 'main' => '#333',
1128
+ 'accent' => '#00cd98',
1129
+ );
1130
+ } else {
1131
+ $main = $this->s_color_hex( $this->get_option( 'sitemap_color_main' ) );
1132
+ $accent = $this->s_color_hex( $this->get_option( 'sitemap_color_accent' ) );
1133
+
1134
+ $options = array(
1135
+ 'main' => $main ? '#' . $main : '',
1136
+ 'accent' => $accent ? '#' . $accent : '',
1137
+ );
1138
+
1139
+ $options = array_filter( $options );
1140
+
1141
+ $retval = array_merge( $this->get_sitemap_colors( true ), $options );
1142
+ }
1143
+
1144
+ return $retval;
1145
+ }
1146
  }
inc/classes/{termdata.class.php → term-data.class.php} RENAMED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
  * The SEO Framework plugin
4
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
@@ -16,33 +23,19 @@
16
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
  */
18
 
19
- defined( 'ABSPATH' ) or die;
20
-
21
  /**
22
- * Class AutoDescription_TermData
23
  *
24
  * Holds Term and Taxonomy data.
25
  *
26
- * @since 2.6.0
27
  */
28
- class AutoDescription_TermData extends AutoDescription_PostData {
29
-
30
- /**
31
- * Unserializing instances of this class is forbidden.
32
- */
33
- private function __wakeup() { }
34
-
35
- /**
36
- * Handle unapproachable invoked methods.
37
- */
38
- public function __call( $name, $arguments ) {
39
- parent::__call( $name, $arguments );
40
- }
41
 
42
  /**
43
  * Constructor, load parent constructor.
44
  */
45
- public function __construct() {
46
  parent::__construct();
47
 
48
  //* Initialize term meta filters and actions.
@@ -55,19 +48,10 @@ class AutoDescription_TermData extends AutoDescription_PostData {
55
  * @since 2.7.0
56
  */
57
  public function initialize_term_meta() {
58
-
59
- if ( $this->can_get_term_meta() ) {
60
- add_action( 'edit_term', array( $this, 'update_term_meta' ), 10, 2 );
61
- add_action( 'delete_term', array( $this, 'delete_term_meta' ), 10, 2 );
62
- } else {
63
- //* Old style term meta data through loop injections.
64
- add_filter( 'get_term', array( $this, 'get_term_filter' ), 10, 2 );
65
- add_filter( 'get_terms', array( $this, 'get_terms_filter' ), 10, 2 );
66
-
67
- add_action( 'edit_term', array( $this, 'taxonomy_seo_save' ), 10, 2 );
68
- add_action( 'delete_term', array( $this, 'term_meta_delete' ), 10, 2 );
69
  }
70
-
71
  }
72
 
73
  /**
@@ -75,6 +59,7 @@ class AutoDescription_TermData extends AutoDescription_PostData {
75
  * Returns Genesis 2.3.0+ data if no term meta data is set.
76
  *
77
  * @since 2.7.0
 
78
  * @staticvar array $cache
79
  *
80
  * @param int $term_id The Term ID.
@@ -92,24 +77,23 @@ class AutoDescription_TermData extends AutoDescription_PostData {
92
  $cache = array();
93
  }
94
 
95
- $data = get_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, true );
96
 
97
  //* Evaluate merely by presence.
98
  if ( isset( $data['saved_flag'] ) )
99
  return $cache[ $term_id ] = $data;
100
 
101
- if ( $this->is_theme( 'genesis' ) ) {
102
- $data = array();
103
- $data['doctitle'] = get_term_meta( $term_id, 'doctitle', true );
104
- $data['description'] = get_term_meta( $term_id, 'description', true );
105
- $data['noindex'] = get_term_meta( $term_id, 'noindex', true );
106
- $data['nofollow'] = get_term_meta( $term_id, 'nofollow', true );
107
- $data['noarchive'] = get_term_meta( $term_id, 'noarchive', true );
108
-
109
- return $cache[ $term_id ] = $data;
110
- }
111
-
112
- return $cache[ $term_id ] = array();
113
  }
114
 
115
  /**
@@ -123,13 +107,13 @@ class AutoDescription_TermData extends AutoDescription_PostData {
123
  * @return array The Term Metadata default options.
124
  */
125
  public function get_term_meta_defaults() {
126
- return (array) apply_filters( 'the_seo_framework_term_meta_defaults', array(
127
- 'doctitle' => '',
128
- 'description' => '',
129
- 'noindex' => 0,
130
- 'nofollow' => 0,
131
- 'noarchive' => 0,
132
- 'saved_flag' => 0, // Don't touch, used to prevent data conflict with Genesis.
133
  ) );
134
  }
135
 
@@ -149,12 +133,33 @@ class AutoDescription_TermData extends AutoDescription_PostData {
149
  return;
150
 
151
  //* Check again against ambiguous injection.
152
- if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'update-tag_' . $term_id ) ) {
153
-
154
- $data = isset( $_POST['autodescription-meta'] ) ? (array) map_deep( $_POST['autodescription-meta'], 'esc_attr' ) : array();
155
- $data = wp_parse_args( $data, $this->get_term_meta_defaults() );
156
-
157
- update_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, $data );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  }
159
  }
160
 
@@ -170,7 +175,7 @@ class AutoDescription_TermData extends AutoDescription_PostData {
170
  public function delete_term_meta( $term_id, $tt_id ) {
171
 
172
  //* If this results in an empty data string, all data has already been removed by WP core.
173
- $data = get_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, true );
174
 
175
  if ( is_array( $data ) ) {
176
  foreach ( $this->get_term_meta_defaults() as $key => $value ) {
@@ -178,11 +183,11 @@ class AutoDescription_TermData extends AutoDescription_PostData {
178
  }
179
  }
180
 
181
- if ( empty( $data ) )
182
- delete_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS );
183
- else
184
- update_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, $data );
185
-
186
  }
187
 
188
  /**
@@ -202,48 +207,13 @@ class AutoDescription_TermData extends AutoDescription_PostData {
202
  if ( is_null( $term ) )
203
  $term = $this->fetch_the_term( $term_id );
204
 
205
- if ( isset( $term->term_id ) ) {
206
- if ( $this->can_get_term_meta() )
207
- return $this->get_term_meta( $term->term_id );
208
- else
209
- return $this->get_old_term_data( $term );
210
- }
211
 
212
  //* Return null if no term can be set.
213
  return null;
214
  }
215
 
216
- /**
217
- * Fetches term metadata array for the inpost term metabox.
218
- *
219
- * @since 2.7.0
220
- *
221
- * @param object $term The TT object. Must be assigned.
222
- * @return array The SEO Framework TT data.
223
- */
224
- protected function get_old_term_data( $term ) {
225
-
226
- $data = array();
227
-
228
- $data['title'] = isset( $term->admeta['doctitle'] ) ? $term->admeta['doctitle'] : '';
229
- $data['description'] = isset( $term->admeta['description'] ) ? $term->admeta['description'] : '';
230
- $data['noindex'] = isset( $term->admeta['noindex'] ) ? $term->admeta['noindex'] : '';
231
- $data['nofollow'] = isset( $term->admeta['nofollow'] ) ? $term->admeta['nofollow'] : '';
232
- $data['noarchive'] = isset( $term->admeta['noarchive'] ) ? $term->admeta['noarchive'] : '';
233
- $flag = isset( $term->admeta['saved_flag'] ) ? (bool) $term->admeta['saved_flag'] : false;
234
-
235
- //* Genesis data fetch. This will override our options with Genesis options on save.
236
- if ( false === $flag && isset( $term->meta ) ) {
237
- $data['title'] = empty( $data['title'] ) && isset( $term->meta['doctitle'] ) ? $term->meta['doctitle'] : $data['noindex'];
238
- $data['description'] = empty( $data['description'] ) && isset( $term->meta['description'] ) ? $term->meta['description'] : $data['description'];
239
- $data['noindex'] = empty( $data['noindex'] ) && isset( $term->meta['noindex'] ) ? $term->meta['noindex'] : $data['noindex'];
240
- $data['nofollow'] = empty( $data['nofollow'] ) && isset( $term->meta['nofollow'] ) ? $term->meta['nofollow'] : $data['nofollow'];
241
- $data['noarchive'] = empty( $data['noarchive'] ) && isset( $term->meta['noarchive'] ) ? $term->meta['noarchive'] : $data['noarchive'];
242
- }
243
-
244
- return $data;
245
- }
246
-
247
  /**
248
  * Try to fetch a term if none can be found.
249
  *
@@ -251,7 +221,7 @@ class AutoDescription_TermData extends AutoDescription_PostData {
251
  * @access private
252
  *
253
  * @param int $id The possible taxonomy Term ID.
254
- * @return null|object The Term object.
255
  */
256
  public function fetch_the_term( $id = '' ) {
257
 
@@ -269,13 +239,14 @@ class AutoDescription_TermData extends AutoDescription_PostData {
269
 
270
  if ( isset( $current_screen->taxonomy ) ) {
271
  $term_id = $id ? $id : $this->get_admin_term_id();
272
- $term[ $id ] = get_term_by( 'id', $term_id, $current_screen->taxonomy );
273
  }
274
  } else {
275
- if ( $this->is_category() || $this->is_tag() )
276
- $term[ $id ] = get_queried_object();
277
- elseif ( $this->is_tax() )
278
- $term[ $id ] = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
 
279
  }
280
 
281
  if ( isset( $term[ $id ] ) )
@@ -300,7 +271,7 @@ class AutoDescription_TermData extends AutoDescription_PostData {
300
  if ( isset( $labels ) )
301
  return $labels;
302
 
303
- $tax_object = get_taxonomy( $tax_type );
304
 
305
  if ( is_object( $tax_object ) )
306
  return $labels = (object) $tax_object->labels;
@@ -356,9 +327,9 @@ class AutoDescription_TermData extends AutoDescription_PostData {
356
  if ( $fallback ) {
357
  //* Fallback to Page as it is generic.
358
  if ( $singular )
359
- return $term_name[ $singular ] = esc_html__( 'Page', 'autodescription' );
360
 
361
- return $term_name[ $singular ] = esc_html__( 'Pages', 'autodescription' );
362
  }
363
 
364
  return $term_name[ $singular ] = '';
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
  /**
10
  * The SEO Framework plugin
11
  * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
23
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
  */
25
 
 
 
26
  /**
27
+ * Class The_SEO_Framework\Term_Data
28
  *
29
  * Holds Term and Taxonomy data.
30
  *
31
+ * @since 2.8.0
32
  */
33
+ class Term_Data extends Post_Data {
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  /**
36
  * Constructor, load parent constructor.
37
  */
38
+ protected function __construct() {
39
  parent::__construct();
40
 
41
  //* Initialize term meta filters and actions.
48
  * @since 2.7.0
49
  */
50
  public function initialize_term_meta() {
51
+ if ( $this->is_admin() ) {
52
+ \add_action( 'edit_term', array( $this, 'update_term_meta' ), 10, 2 );
53
+ \add_action( 'delete_term', array( $this, 'delete_term_meta' ), 10, 2 );
 
 
 
 
 
 
 
 
54
  }
 
55
  }
56
 
57
  /**
59
  * Returns Genesis 2.3.0+ data if no term meta data is set.
60
  *
61
  * @since 2.7.0
62
+ * @since 2.8.0 : Added filter.
63
  * @staticvar array $cache
64
  *
65
  * @param int $term_id The Term ID.
77
  $cache = array();
78
  }
79
 
80
+ $data = \get_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, true );
81
 
82
  //* Evaluate merely by presence.
83
  if ( isset( $data['saved_flag'] ) )
84
  return $cache[ $term_id ] = $data;
85
 
86
+ /**
87
+ * Applies filters 'the_seo_framework_get_term_meta'
88
+ *
89
+ * @since 2.8.0
90
+ *
91
+ * @param array $data The term data.
92
+ * @param int $term_id The current Term ID.
93
+ */
94
+ $data = \apply_filters( 'the_seo_framework_get_term_meta', array(), $term_id );
95
+
96
+ return $cache[ $term_id ] = $data;
 
97
  }
98
 
99
  /**
107
  * @return array The Term Metadata default options.
108
  */
109
  public function get_term_meta_defaults() {
110
+ return (array) \apply_filters( 'the_seo_framework_term_meta_defaults', array(
111
+ 'doctitle' => '',
112
+ 'description' => '',
113
+ 'noindex' => 0,
114
+ 'nofollow' => 0,
115
+ 'noarchive' => 0,
116
+ 'saved_flag' => 0, // Don't touch, used to prevent data conflict with Genesis.
117
  ) );
118
  }
119
 
133
  return;
134
 
135
  //* Check again against ambiguous injection.
136
+ if ( isset( $_POST['_wpnonce'] ) && \wp_verify_nonce( $_POST['_wpnonce'], 'update-tag_' . $term_id ) ) {
137
+ $data = isset( $_POST['autodescription-meta'] ) ? (array) $_POST['autodescription-meta'] : array();
138
+ $data = \wp_parse_args( $data, $this->get_term_meta_defaults() );
139
+
140
+ foreach ( (array) $data as $key => $value ) :
141
+ switch ( $key ) :
142
+ case 'doctitle' :
143
+ $data[ $key ] = $this->s_title_raw( $value );
144
+ continue 2;
145
+
146
+ case 'description' :
147
+ $data[ $key ] = $this->s_description_raw( $value );
148
+ continue 2;
149
+
150
+ case 'noindex' :
151
+ case 'nofollow' :
152
+ case 'noarchive' :
153
+ case 'saved_flag' :
154
+ $data[ $key ] = $this->s_one_zero( $value );
155
+ continue 2;
156
+
157
+ default :
158
+ break;
159
+ endswitch;
160
+ endforeach;
161
+
162
+ \update_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, $data );
163
  }
164
  }
165
 
175
  public function delete_term_meta( $term_id, $tt_id ) {
176
 
177
  //* If this results in an empty data string, all data has already been removed by WP core.
178
+ $data = \get_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, true );
179
 
180
  if ( is_array( $data ) ) {
181
  foreach ( $this->get_term_meta_defaults() as $key => $value ) {
183
  }
184
  }
185
 
186
+ if ( empty( $data ) ) {
187
+ \delete_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS );
188
+ } else {
189
+ \update_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, $data );
190
+ }
191
  }
192
 
193
  /**
207
  if ( is_null( $term ) )
208
  $term = $this->fetch_the_term( $term_id );
209
 
210
+ if ( isset( $term->term_id ) )
211
+ return $this->get_term_meta( $term->term_id );
 
 
 
 
212
 
213
  //* Return null if no term can be set.
214
  return null;
215
  }
216
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  /**
218
  * Try to fetch a term if none can be found.
219
  *
221
  * @access private
222
  *
223
  * @param int $id The possible taxonomy Term ID.
224
+ * @return false|object The Term object.
225
  */
226
  public function fetch_the_term( $id = '' ) {
227
 
239
 
240
  if ( isset( $current_screen->taxonomy ) ) {
241
  $term_id = $id ? $id : $this->get_admin_term_id();
242
+ $term[ $id ] = \get_term_by( 'id', $term_id, $current_screen->taxonomy );
243
  }
244
  } else {
245
+ if ( $this->is_category() || $this->is_tag() ) {
246
+ $term[ $id ] = \get_queried_object();
247
+ } elseif ( $this->is_tax() ) {
248
+ $term[ $id ] = \get_term_by( 'slug', \get_query_var( 'term' ), \get_query_var( 'taxonomy' ) );
249
+ }
250
  }
251
 
252
  if ( isset( $term[ $id ] ) )
271
  if ( isset( $labels ) )
272
  return $labels;
273
 
274
+ $tax_object = \get_taxonomy( $tax_type );
275
 
276
  if ( is_object( $tax_object ) )
277
  return $labels = (object) $tax_object->labels;
327
  if ( $fallback ) {
328
  //* Fallback to Page as it is generic.
329
  if ( $singular )
330
+ return $term_name[ $singular ] = \esc_html__( 'Page', 'autodescription' );
331
 
332
+ return $term_name[ $singular ] = \esc_html__( 'Pages', 'autodescription' );
333
  }
334
 
335
  return $term_name[ $singular ] = '';
inc/{functions/compat.php → compat/php-mbstring.php} RENAMED
@@ -1,108 +1,9 @@
1
  <?php
2
-
3
- defined( 'ABSPATH' ) or die;
4
-
5
- /**
6
- * Returns whether PCRE/u (PCRE_UTF8 modifier) is available for use.
7
- *
8
- * @ignore
9
- * @since WordPress 4.2.2
10
- * @access private
11
- *
12
- * @staticvar string $utf8_pcre
13
- *
14
- * @param bool $set - Used for testing only
15
- * null : default - get PCRE/u capability
16
- * false : Used for testing - return false for future calls to this function
17
- * 'reset': Used for testing - restore default behavior of this function
18
- *
19
- * WordPress core function.
20
- * Implemented in this plugin for compatibility with older WordPress versions.
21
- * @since 2.3.5
22
- */
23
- if ( ! function_exists( '_wp_can_use_pcre_u' ) ) :
24
- function _wp_can_use_pcre_u( $set = null ) {
25
- static $utf8_pcre = 'reset';
26
-
27
- if ( null !== $set ) {
28
- $utf8_pcre = $set;
29
- }
30
-
31
- if ( 'reset' === $utf8_pcre ) {
32
- $utf8_pcre = @preg_match( '/^./u', 'a' );
33
- }
34
-
35
- return $utf8_pcre;
36
- }
37
- endif;
38
-
39
  /**
40
- * Extended charset support
41
- *
42
- * @uses strlen
43
- * @return mb_strlen
44
- *
45
- * @since 1.3.0 The SEO Framework
46
- * @since 4.2.0 WordPress Core
47
- *
48
  */
49
- if ( ! function_exists( 'mb_strlen' ) ) :
50
- function mb_strlen( $str, $encoding = null ) {
51
- return _mb_strlen( $str, $encoding );
52
- }
53
- endif;
54
-
55
- /*
56
- * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit.
57
- * For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence.
58
- * The behavior of this function for invalid inputs is undefined.
59
- */
60
- if ( ! function_exists( '_mb_strlen' ) ) :
61
- function _mb_strlen( $str, $encoding = null ) {
62
- if ( null === $encoding ) {
63
- $encoding = get_option( 'blog_charset' );
64
- }
65
 
66
- // The solution below works only for UTF-8,
67
- // so in case of a different charset just use built-in strlen()
68
- if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) {
69
- return strlen( $str );
70
- }
71
-
72
- if ( _wp_can_use_pcre_u() ) {
73
- // Use the regex unicode support to separate the UTF-8 characters into an array
74
- preg_match_all( '/./us', $str, $match );
75
- return count( $match[0] );
76
- }
77
-
78
- $regex = '/(?:
79
- [\x00-\x7F] # single-byte sequences 0xxxxxxx
80
- | [\xC2-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx
81
- | \xE0[\xA0-\xBF][\x80-\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2
82
- | [\xE1-\xEC][\x80-\xBF]{2}
83
- | \xED[\x80-\x9F][\x80-\xBF]
84
- | [\xEE-\xEF][\x80-\xBF]{2}
85
- | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3
86
- | [\xF1-\xF3][\x80-\xBF]{3}
87
- | \xF4[\x80-\x8F][\x80-\xBF]{2}
88
- )/x';
89
-
90
- $count = 1; // Start at 1 instead of 0 since the first thing we do is decrement
91
- do {
92
- // We had some string left over from the last round, but we counted it in that last round.
93
- $count--;
94
-
95
- // Split by UTF-8 character, limit to 1000 characters (last array element will contain the rest of the string)
96
- $pieces = preg_split( $regex, $str, 1000 );
97
-
98
- // Increment
99
- $count += count( $pieces );
100
- } while ( $str = array_pop( $pieces ) ); // If there's anything left over, repeat the loop.
101
-
102
- // Fencepost: preg_split() always returns one extra item in the array
103
- return --$count;
104
- }
105
- endif;
106
 
107
  /**
108
  * Extended charset support
@@ -126,7 +27,7 @@ endif;
126
  /**
127
  * Compat function to mimic mb_strpos().
128
  *
129
- * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit.
130
  * For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence.
131
  * The behavior of this function for invalid inputs is PHP compliant.
132
  *
@@ -151,7 +52,7 @@ if ( ! function_exists( '_mb_strpos' ) ) :
151
  // The solution below works only for UTF-8,
152
  // So in case of a different charset just use built-in strpos()
153
  if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) {
154
- return $offset === 0 ? strpos( $haystack, $needle ) : strpos( $haystack, $needle, $offset );
155
  }
156
 
157
  $haystack_len = mb_strlen( $haystack );
@@ -291,52 +192,3 @@ if ( ! function_exists( '_mb_strpos' ) ) :
291
  }
292
  }
293
  endif;
294
-
295
- /**
296
- * A wrapper for PHP's parse_url() function that handles edgecases in < PHP 5.4.7
297
- *
298
- * PHP 5.4.7 expanded parse_url()'s ability to handle non-absolute url's, including
299
- * schemeless and relative url's with :// in the path, this works around those
300
- * limitations providing a standard output on PHP 5.2~5.4+.
301
- *
302
- * Error suppression is used as prior to PHP 5.3.3, an E_WARNING would be generated
303
- * when URL parsing failed.
304
- *
305
- * @since 2.7.0 The SEO Framework
306
- * @since 4.4.0 WordPress Core
307
- *
308
- * @param string $url The URL to parse.
309
- * @return bool|array False on failure; Array of URL components on success;
310
- * See parse_url()'s return values.
311
- */
312
- if ( ! function_exists( 'wp_parse_url' ) ) :
313
- function wp_parse_url( $url ) {
314
- $parts = @parse_url( $url );
315
- if ( ! $parts ) {
316
- // < PHP 5.4.7 compat, trouble with relative paths including a scheme break in the path
317
- if ( '/' === $url[0] && false !== strpos( $url, '://' ) ) {
318
- // Since we know it's a relative path, prefix with a scheme/host placeholder and try again
319
- if ( ! $parts = @parse_url( 'placeholder://placeholder' . $url ) ) {
320
- return $parts;
321
- }
322
- // Remove the placeholder values
323
- unset( $parts['scheme'], $parts['host'] );
324
- } else {
325
- return $parts;
326
- }
327
- }
328
-
329
- // < PHP 5.4.7 compat, doesn't detect schemeless URL's host field
330
- if ( '//' === substr( $url, 0, 2 ) && ! isset( $parts['host'] ) ) {
331
- $path_parts = explode( '/', substr( $parts['path'], 2 ), 2 );
332
- $parts['host'] = $path_parts[0];
333
- if ( isset( $path_parts[1] ) ) {
334
- $parts['path'] = '/' . $path_parts[1];
335
- } else {
336
- unset( $parts['path'] );
337
- }
338
- }
339
-
340
- return $parts;
341
- }
342
- endif;
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /**
3
+ * @package The_SEO_Framework\Compat\PHP\mbstring
 
 
 
 
 
 
 
4
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
+ defined( 'ABSPATH' ) or die;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  /**
9
  * Extended charset support
27
  /**
28
  * Compat function to mimic mb_strpos().
29
  *
30
+ * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit.
31
  * For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence.
32
  * The behavior of this function for invalid inputs is PHP compliant.
33
  *
52
  // The solution below works only for UTF-8,
53
  // So in case of a different charset just use built-in strpos()
54
  if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) {
55
+ return 0 === $offset ? strpos( $haystack, $needle ) : strpos( $haystack, $needle, $offset );
56
  }
57
 
58
  $haystack_len = mb_strlen( $haystack );
192
  }
193
  }
194
  endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/compat/plugin-bbpress.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Compat\Plugin\bbPress
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) and $_this = \the_seo_framework_class() and $this instanceof $_this or die;
8
+
9
+ /**
10
+ * Override wp_title's bbPress title with the one generated by The SEO Framework.
11
+ *
12
+ * @since 2.3.5
13
+ */
14
+ \add_filter( 'bbp_title', array( $this, 'title_from_cache' ), 99, 3 );
15
+
16
+ \add_filter( 'the_seo_framework_seo_column_keys_order', __NAMESPACE__ . '\\_bbpress_filter_order_keys' );
17
+ /**
18
+ * Filters the order keys for The SEO Bar.
19
+ *
20
+ * @since 2.8.0
21
+ * @access private
22
+ *
23
+ * @param array $current_keys The current column keys TSF looks for.
24
+ * @return array Expanded keyset.
25
+ */
26
+ function _bbpress_filter_order_keys( $current_keys = array() ) {
27
+
28
+ $new_keys = array(
29
+ 'bbp_topic_freshness',
30
+ 'bbp_forum_freshness',
31
+ 'bbp_reply_created',
32
+ );
33
+
34
+ return array_merge( $current_keys, $new_keys );
35
+ }
inc/compat/plugin-donncha-dm.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Compat\Plugin\Donncha-dm
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) and $_this = \the_seo_framework_class() and $this instanceof $_this or die;
8
+
9
+ \add_filter( 'the_seo_framework_sanitize_redirect_args', __NAMESPACE__ . '\\_donncha_domainmap_sanitize_redirect_url', 10, 2 );
10
+ \add_filter( 'the_seo_framework_url_output_args', __NAMESPACE__ . '\\_donncha_domainmap_sanitize_redirect_url', 10, 2 );
11
+ /**
12
+ * Filters the sanitation URL.
13
+ *
14
+ * @since 2.8.0
15
+ * @access private
16
+ *
17
+ * @param array : { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
18
+ * @param string $path the URL path.
19
+ * @param int $id The current post, page or term ID.
20
+ * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
21
+ */
22
+ function _donncha_domainmap_sanitize_redirect_url( $args = array(), $path = '' ) {
23
+
24
+ $args = \The_SEO_Framework\_donncha_domainmap_get_url( $path, true );
25
+
26
+ return array(
27
+ 'url' => $args[0],
28
+ 'scheme' => $args[1],
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Try to get an canonical URL when Donncha Domain Mapping is active.
34
+ *
35
+ * @since 2.4.0
36
+ * @global object $current_blog
37
+ * @access private
38
+ *
39
+ * @param string $path The post relative path.
40
+ * @param bool $get_scheme Output array with scheme.
41
+ * @return string|array|void The unescaped URL, the scheme
42
+ */
43
+ function _donncha_domainmap_get_url( $path, $get_scheme = false ) {
44
+ global $current_blog;
45
+
46
+ $scheme = \the_seo_framework()->is_ssl() ? 'https' : 'http';
47
+ $url = function_exists( 'domain_mapping_siteurl' ) ? \domain_mapping_siteurl( false ) : false;
48
+
49
+ $request_uri = '';
50
+
51
+ if ( $url && \untrailingslashit( $scheme . '://' . $current_blog->domain . $current_blog->path ) !== $url ) {
52
+ if ( ( defined( 'VHOST' ) && 'yes' !== VHOST ) || ( defined( 'SUBDOMAIN_INSTALL' ) && false === SUBDOMAIN_INSTALL ) )
53
+ $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? str_replace( $current_blog->path, '/', $_SERVER['REQUEST_URI'] ) : '';
54
+
55
+ $url = \trailingslashit( $url . $request_uri ) . ltrim( $path, ' \\/' );
56
+
57
+ if ( $get_scheme ) {
58
+ return array( $url, $scheme );
59
+ } else {
60
+ return $url;
61
+ }
62
+ }
63
+
64
+ return '';
65
+ }
inc/compat/plugin-qtranslatex.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Compat\Plugin\qTranslateX
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) and $_this = \the_seo_framework_class() and $this instanceof $_this or die;
8
+
9
+ \add_filter( 'the_seo_framework_url_path', __NAMESPACE__ . '\\_qtranslatex_filter_url_path', 10, 3 );
10
+ /**
11
+ * Filters the canonical URL path.
12
+ *
13
+ * @since 2.8.0
14
+ * @access private
15
+ *
16
+ * @param string $path the URL path.
17
+ * @param int $id The current post, page or term ID.
18
+ * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
19
+ * @return string The URL path.
20
+ */
21
+ function _qtranslatex_filter_url_path( $path = '', $id = 0, $external = false ) {
22
+ return \The_SEO_Framework\_qtranslate_get_relative_url( $path, $id );
23
+ }
24
+
25
+ /**
26
+ * Generates qtranslate URL from path.
27
+ *
28
+ * @since 2.6.0
29
+ * @since 2.8.0 Moved to compat file and renamed.
30
+ * @staticvar int $q_config_mode
31
+ * @global array $q_config
32
+ * @NOTE: Handles full path, including home directory.
33
+ * @access private
34
+ *
35
+ * @param string $path The current path.
36
+ * @param int $post_id The Post ID. Unused until qTranslate provides external URL forgery.
37
+ */
38
+ function _qtranslate_get_relative_url( $path = '', $post_id = '' ) {
39
+
40
+ //* Reset cache.
41
+ \the_seo_framework()->url_slashit = true;
42
+ \the_seo_framework()->unset_current_subdomain();
43
+
44
+ static $q_config_mode = null;
45
+
46
+ if ( ! isset( $q_config ) ) {
47
+ global $q_config;
48
+ $q_config_mode = $q_config['url_mode'];
49
+ }
50
+
51
+ //* If false, change canonical URL for every page.
52
+ $hide = isset( $q_config['hide_default_language'] ) ? $q_config['hide_default_language'] : true;
53
+
54
+ $current_lang = isset( $q_config['language'] ) ? $q_config['language'] : false;
55
+ $default_lang = isset( $q_config['default_language'] ) ? $q_config['default_language'] : false;
56
+
57
+ //* Don't to anything on default language when path is hidden.
58
+ if ( $hide && $current_lang === $default_lang )
59
+ return $path;
60
+
61
+ switch ( $q_config_mode ) :
62
+ case '1' :
63
+ //* Negotiation type query var.
64
+
65
+ //* Don't slash it further.
66
+ \the_seo_framework()->url_slashit = false;
67
+
68
+ /**
69
+ * Path must have trailing slash for pagination permalinks to work.
70
+ * So we remove the query string and add it back with slash.
71
+ */
72
+ if ( strpos( $path, '?lang=' . $current_lang ) !== false )
73
+ $path = str_replace( '?lang=' . $current_lang, '', $path );
74
+
75
+ return \user_trailingslashit( $path ) . '?lang=' . $current_lang;
76
+ break;
77
+
78
+ case '2' :
79
+ //* Subdirectory
80
+ if ( 0 === strpos( trailingslashit( $path ), '/' . $current_lang . '/' ) ) {
81
+ return $path;
82
+ } else {
83
+ return $path = \trailingslashit( $current_lang ) . ltrim( $path, ' \\/' );
84
+ }
85
+ break;
86
+
87
+ case '3' :
88
+ //* Notify cache of subdomain addition.
89
+ \the_seo_framework()->set_current_subdomain( $current_lang );
90
+
91
+ //* No need to alter the path.
92
+ return $path;
93
+ break;
94
+
95
+ default :
96
+ break;
97
+ endswitch;
98
+
99
+ return $path;
100
+ }
inc/compat/plugin-ultimatemember.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Compat\Plugin\UltimateMember
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) and $_this = \the_seo_framework_class() and $this instanceof $_this or die;
8
+
9
+ /**
10
+ * Determines if the user detection functions are available.
11
+ * Checks for: um_user, um_is_core_page, um_get_requested_user
12
+ *
13
+ * @since 2.8.0
14
+ * @staticvar bool $cache
15
+ *
16
+ * @return bool Whether functions can be used.
17
+ */
18
+ function _um_user_functions_available() {
19
+
20
+ static $cache = null;
21
+
22
+ return isset( $cache ) ? $cache : $cache = \the_seo_framework()->can_i_use(
23
+ array( 'functions' => array( 'um_user', 'um_is_core_page', 'um_get_requested_user' ) ),
24
+ false
25
+ );
26
+ }
27
+
28
+ \add_filter( 'the_seo_framework_custom_field_title', __NAMESPACE__ . '\\_um_filter_custom_field_title', 10, 3 );
29
+ /**
30
+ * Filters the custom title.
31
+ *
32
+ * @since 2.8.0
33
+ * @access private
34
+ *
35
+ * @param string $title The special title.
36
+ * @param int $id The post or TT ID.
37
+ * @param string $axonomy the TT name.
38
+ * @return string The user title.
39
+ */
40
+ function _um_filter_custom_field_title( $title = '', $id = '', $taxonomy = '' ) {
41
+
42
+ if ( \The_SEO_Framework\_um_user_functions_available() && \um_is_core_page( 'user' ) && \um_get_requested_user() ) {
43
+ $title = \um_user( 'display_name' );
44
+ }
45
+
46
+ return $title;
47
+ }
inc/compat/plugin-wpml.php ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Compat\Plugin\WPML
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) and $_this = \the_seo_framework_class() and $this instanceof $_this or die;
8
+
9
+ /**
10
+ * Warns homepage global title and description about recieving input.
11
+ *
12
+ * @since 1.0.0
13
+ */
14
+ \add_filter( 'the_seo_framework_warn_homepage_global_title', '__return_true' );
15
+ \add_filter( 'the_seo_framework_warn_homepage_global_description', '__return_true' );
16
+
17
+ \add_filter( 'the_seo_framework_url_path', __NAMESPACE__ . '\\_wpml_filter_url_path', 10, 3 );
18
+ /**
19
+ * Filters the canonical URL path.
20
+ *
21
+ * @since 2.8.0
22
+ * @access private
23
+ *
24
+ * @param string $path the URL path.
25
+ * @param int $id The current post, page or term ID.
26
+ * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
27
+ * @return string The URL path.
28
+ */
29
+ function _wpml_filter_url_path( $path = '', $id = 0, $external = false ) {
30
+ return \The_SEO_Framework\_wmpl_get_relative_url( $path, $id );
31
+ }
32
+
33
+ /**
34
+ * Generate relative WPML url.
35
+ *
36
+ * @since 2.4.3
37
+ * @staticvar bool $gli_exists
38
+ * @staticvar string $default_lang
39
+ * @global object $sitepress
40
+ * @NOTE: Handles full path, including home directory.
41
+ * @access private
42
+ *
43
+ * @param string $path The current path.
44
+ * @param int $post_id The Post ID.
45
+ * @return relative path for WPML urls.
46
+ */
47
+ function _wmpl_get_relative_url( $path = '', $post_id = '' ) {
48
+ global $sitepress;
49
+
50
+ //* Reset cache.
51
+ \the_seo_framework()->url_slashit = true;
52
+ \the_seo_framework()->unset_current_subdomain();
53
+
54
+ if ( ! isset( $sitepress ) )
55
+ return $path;
56
+
57
+ static $gli_exists = null;
58
+ if ( is_null( $gli_exists ) )
59
+ $gli_exists = function_exists( 'wpml_get_language_information' );
60
+
61
+ if ( false === $gli_exists )
62
+ return $path;
63
+
64
+ if ( empty( $post_id ) )
65
+ $post_id = \the_seo_framework()->get_the_real_ID();
66
+
67
+ //* Cache default language.
68
+ static $default_lang = null;
69
+ if ( is_null( $default_lang ) )
70
+ $default_lang = $sitepress->get_default_language();
71
+
72
+ /**
73
+ * Applies filters wpml_post_language_details : array|wp_error
74
+ *
75
+ * ... Somehow WPML thought this would be great and understandable.
76
+ * This should be put inside a callable function.
77
+ * @since 2.6.0
78
+ */
79
+ $lang_info = \apply_filters( 'wpml_post_language_details', null, $post_id );
80
+
81
+ if ( \is_wp_error( $lang_info ) ) {
82
+ //* Terms and Taxonomies.
83
+ $lang_info = array();
84
+
85
+ //* Cache the code.
86
+ static $lang_code = null;
87
+ if ( is_null( $lang_code ) && defined( 'ICL_LANGUAGE_CODE' ) )
88
+ $lang_code = ICL_LANGUAGE_CODE;
89
+
90
+ $lang_info['language_code'] = $lang_code;
91
+ }
92
+
93
+ //* If filter isn't used, bail.
94
+ if ( false === isset( $lang_info['language_code'] ) )
95
+ return $path;
96
+
97
+ $current_lang = $lang_info['language_code'];
98
+
99
+ //* No need to alter URL if we're on default lang.
100
+ if ( $current_lang === $default_lang )
101
+ return $path;
102
+
103
+ //* Cache negotiation type.
104
+ static $negotiation_type = null;
105
+ if ( is_null( $negotiation_type ) )
106
+ $negotiation_type = $sitepress->get_setting( 'language_negotiation_type' );
107
+
108
+ switch ( $negotiation_type ) :
109
+ case '1' :
110
+ //* Subdirectory
111
+
112
+ $t_path = \trailingslashit( $path );
113
+
114
+ if ( 0 === strpos( $t_path, '/' . $current_lang . '/' ) ) {
115
+ //* Link is already good.
116
+ return $path;
117
+ } elseif ( 0 === strpos( $t_path, '/' . $default_lang . '/' ) ) {
118
+ //* Link contains default lang. Strip.
119
+ $t_path = substr( $t_path, strlen( '/' . $default_lang ) );
120
+
121
+ if ( 0 === strpos( $t_path, '/' . $current_lang . '/' ) ) {
122
+ //* New link contains current lang correctly.
123
+ return \user_trailingslashit( $t_path );
124
+ } else {
125
+ return $path = \trailingslashit( $current_lang ) . ltrim( \user_trailingslashit( $t_path ), ' \\/' );
126
+ }
127
+ }
128
+
129
+ return $path = \trailingslashit( $current_lang ) . ltrim( \user_trailingslashit( $path ), ' \\/' );
130
+ break;
131
+
132
+ case '2' :
133
+ //* Custom domain.
134
+
135
+ $langsettings = $sitepress->get_setting( 'language_domains' );
136
+ $current_lang_setting = isset( $langsettings[ $current_lang ] ) ? $langsettings[ $current_lang ] : '';
137
+
138
+ if ( empty( $current_lang_setting ) )
139
+ return $path;
140
+
141
+ $current_lang_setting = \the_seo_framework()->make_fully_qualified_url( $current_lang_setting );
142
+ $parsed = \wp_parse_url( $current_lang_setting );
143
+
144
+ \the_seo_framework()->current_host = isset( $parsed['host'] ) ? $parsed['host'] : '';
145
+ $current_path = isset( $parsed['path'] ) ? \trailingslashit( $parsed['path'] ) : '';
146
+
147
+ return $current_path . $path;
148
+ break;
149
+
150
+ case '3' :
151
+ //* Negotiation type query var.
152
+
153
+ //* Don't slash it further.
154
+ \the_seo_framework()->url_slashit = false;
155
+
156
+ /**
157
+ * Path must have trailing slash for pagination permalinks to work.
158
+ * So we remove the query string and add it back with slash.
159
+ */
160
+ if ( false !== strpos( $path, '?lang=' . $current_lang ) )
161
+ $path = str_replace( '?lang=' . $current_lang, '', $path );
162
+
163
+ return \user_trailingslashit( $path ) . '?lang=' . $current_lang;
164
+ break;
165
+
166
+ default :
167
+ break;
168
+ endswitch;
169
+
170
+ return $path;
171
+ }
172
+
173
+ \add_action( 'current_screen', __NAMESPACE__ . '\\_wpml_do_current_screen_action' );
174
+ /**
175
+ * Adds WPML filters only on SEO plugin page.
176
+ *
177
+ * @since 2.8.0
178
+ * @access private
179
+ *
180
+ * @param object $current_screen
181
+ */
182
+ function _wpml_do_current_screen_action( $current_screen = '' ) {
183
+
184
+ if ( \the_seo_framework()->is_seo_settings_page() ) {
185
+ \add_filter( 'wpml_admin_language_switcher_items', __NAMESPACE__ . '\\_wpml_remove_all_languages' );
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Removes "All languages" option from WPML admin switcher.
191
+ *
192
+ * @since 2.8.0
193
+ * @access private
194
+ *
195
+ * @param array $languages_links
196
+ * @return array
197
+ */
198
+ function _wpml_remove_all_languages( $languages_links = array() ) {
199
+
200
+ unset( $languages_links['all'] );
201
+
202
+ return $languages_links;
203
+ }
inc/compat/plugin-wpmudev-dm.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Compat\Plugin\WPMUDev-dm
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) and $_this = \the_seo_framework_class() and $this instanceof $_this or die;
8
+
9
+ \add_filter( 'the_seo_framework_sanitize_redirect_args', __NAMESPACE__ . '\\_wpmudev_sanitize_redirect_url', 10, 2 );
10
+ \add_filter( 'the_seo_framework_url_output_args', __NAMESPACE__ . '\\_wpmudev_sanitize_redirect_url', 10, 2 );
11
+ /**
12
+ * Filters the sanitation URL.
13
+ *
14
+ * @since 2.8.0
15
+ * @access private
16
+ *
17
+ * @param array : { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
18
+ * @param string $path the URL path.
19
+ * @param int $id The current post, page or term ID.
20
+ * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
21
+ */
22
+ function _wpmudev_sanitize_redirect_url( $args = array(), $path = '' ) {
23
+
24
+ $args = \The_SEO_Framework\_wpmudev_domainmap_get_url( $path, true );
25
+
26
+ return array(
27
+ 'url' => $args[0],
28
+ 'scheme' => $args[1],
29
+ );
30
+ }
31
+
32
+ /**
33
+ * Creates a full canonical URL when WPMUdev Domain Mapping is active from path.
34
+ *
35
+ * @since 2.3.0
36
+ * @since 2.4.0 Added $get_scheme parameter.
37
+ * @since 2.8.0 Moved to compat file.
38
+ * @global object $wpdb
39
+ * @global int $blog_id
40
+ * @access private
41
+ *
42
+ * @param string $path The post relative path.
43
+ * @param bool $get_scheme Output array with scheme.
44
+ * @return string|array|void The unescaped URL, the scheme
45
+ */
46
+ function _wpmudev_domainmap_get_url( $path, $get_scheme = false ) {
47
+ global $wpdb, $blog_id;
48
+
49
+ /**
50
+ * Cache revisions. Hexadecimal.
51
+ * @since 2.6.0
52
+ */
53
+ $revision = '1';
54
+
55
+ $cache_key = 'wpmudev_mapped_domain_' . $revision . '_' . $blog_id;
56
+
57
+ //* Check if the domain is mapped. Store in object cache.
58
+ $mapped_domain = \the_seo_framework()->object_cache_get( $cache_key );
59
+ if ( false === $mapped_domain ) :
60
+ $mapped_domains = $wpdb->get_results(
61
+ $wpdb->prepare(
62
+ "SELECT id, domain, is_primary, scheme FROM {$wpdb->base_prefix}domain_mapping WHERE blog_id = %d", $blog_id
63
+ ), OBJECT
64
+ );
65
+
66
+ $primary_key = 0;
67
+ $domain_ids = array();
68
+
69
+ foreach ( $mapped_domains as $key => $domain ) :
70
+ if ( isset( $domain->is_primary ) && '1' === $domain->is_primary ) {
71
+ $primary_key = $key;
72
+
73
+ //* We've found the primary key, break loop.
74
+ break;
75
+ } else {
76
+ //* Save IDs.
77
+ if ( isset( $domain->id ) && $domain->id )
78
+ $domain_ids[ $key ] = $domain->id;
79
+ }
80
+ endforeach;
81
+
82
+ if ( 0 === $primary_key && ! empty( $domain_ids ) ) {
83
+ //* No primary ID has been found. Get the one with the lowest ID, which has been added first.
84
+ $primary_key = array_keys( $domain_ids, min( $domain_ids ), true );
85
+ $primary_key = reset( $primary_key );
86
+ }
87
+
88
+ //* Set 0, as we check for false to begin with.
89
+ $mapped_domain = isset( $mapped_domains[ $primary_key ] ) ? $mapped_domains[ $primary_key ] : 0;
90
+
91
+ \the_seo_framework()->object_cache_set( $cache_key, $mapped_domain, 3600 );
92
+ endif;
93
+
94
+ if ( $mapped_domain ) :
95
+
96
+ $domain = isset( $mapped_domain->domain ) ? $mapped_domain->domain : '0';
97
+ $scheme = isset( $mapped_domain->scheme ) ? $mapped_domain->scheme : '';
98
+
99
+ //* Fallback to is_ssl if no scheme has been found.
100
+ if ( '' === $scheme )
101
+ $scheme = \the_seo_framework()->is_ssl() ? '1' : '0';
102
+
103
+ if ( '1' === $scheme ) {
104
+ $scheme_full = 'https://';
105
+ $scheme = 'https';
106
+ } else {
107
+ $scheme_full = 'http://';
108
+ $scheme = 'http';
109
+ }
110
+
111
+ //* Put it all together.
112
+ $url = \trailingslashit( $scheme_full . $domain ) . ltrim( $path, ' \\/' );
113
+
114
+ if ( $get_scheme ) {
115
+ return array( $url, $scheme );
116
+ } else {
117
+ return $url;
118
+ }
119
+ endif;
120
+
121
+ return '';
122
+ }
inc/compat/theme-genesis.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Compat\Theme\Genesis
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) and $_this = \the_seo_framework_class() and $this instanceof $_this or die;
8
+
9
+ //* Disable Genesis SEO.
10
+ \add_filter( 'genesis_detect_seo_plugins', __NAMESPACE__ . '\\_disable_genesis_seo', 10, 1 );
11
+ /**
12
+ * Removes the Genesis SEO meta boxes on the SEO Settings page
13
+ *
14
+ * @since 2.8.0
15
+ * @access private
16
+ *
17
+ * @param array $plugins, overwritten as this filter will fire the
18
+ * detection, regardless of other SEO plugins.
19
+ * @return array Plugins to detect.
20
+ */
21
+ function _disable_genesis_seo( $plugins ) {
22
+
23
+ $plugins = array(
24
+ 'classes' => array(
25
+ '\The_SEO_Framework\\Load',
26
+ ),
27
+ 'functions' => array(
28
+ 'the_seo_framework',
29
+ ),
30
+ 'constants' => array(
31
+ 'THE_SEO_FRAMEWORK_VERSION',
32
+ ),
33
+ );
34
+
35
+ return $plugins;
36
+ }
37
+
38
+ \add_action( 'init', __NAMESPACE__ . '\\_genesis_add_head_attributes' );
39
+ /**
40
+ * Adds Genesis SEO compatibility.
41
+ *
42
+ * @since 2.6.0
43
+ * @since 2.8.0 Moved to compat file and renamed.
44
+ * @access private
45
+ */
46
+ function _genesis_add_head_attributes() {
47
+ //* Reverse the removal of head attributes, this shouldn't affect SEO.
48
+ \remove_filter( 'genesis_attr_head', 'genesis_attributes_empty_class' );
49
+ \add_filter( 'genesis_attr_head', 'genesis_attributes_head' );
50
+ }
51
+
52
+ \add_filter( 'the_seo_framework_get_term_meta', __NAMESPACE__ . '\\_genesis_get_term_meta', 10, 2 );
53
+ /**
54
+ * Returns Genesis term meta.
55
+ *
56
+ * @since 2.8.0
57
+ *
58
+ * @param array $data The current term meta.
59
+ * @param int $term_id The current term ID.
60
+ * @return array The Genesis Term meta.
61
+ */
62
+ function _genesis_get_term_meta( $data = array(), $term_id = 0 ) {
63
+
64
+ $data['doctitle'] = \get_term_meta( $term_id, 'doctitle', true );
65
+ $data['description'] = \get_term_meta( $term_id, 'description', true );
66
+ $data['noindex'] = \get_term_meta( $term_id, 'noindex', true );
67
+ $data['nofollow'] = \get_term_meta( $term_id, 'nofollow', true );
68
+ $data['noarchive'] = \get_term_meta( $term_id, 'noarchive', true );
69
+
70
+ return $data;
71
+ }
inc/deprecated/deprecated.class.php DELETED
@@ -1,905 +0,0 @@
1
- <?php
2
- /**
3
- * The SEO Framework plugin
4
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
5
- *
6
- * This program is free software: you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 3 as published
8
- * by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
- */
18
-
19
- defined( 'ABSPATH' ) or die;
20
-
21
- /**
22
- * Deprecation class.
23
- * Contains all deprecated functions. Is autoloaded.
24
- *
25
- * @since 2.3.4
26
- */
27
- class The_SEO_Framework_Deprecated extends AutoDescription_Feed {
28
-
29
- /**
30
- * Unserializing instances of this class is forbidden.
31
- */
32
- private function __wakeup() { }
33
-
34
- /**
35
- * Handle unapproachable invoked methods.
36
- */
37
- public function __call( $name, $arguments ) {
38
- parent::__call( $name, $arguments );
39
- }
40
-
41
- /**
42
- * Constructor. Loads parent constructor.
43
- */
44
- public function __construct() {
45
- parent::__construct();
46
- }
47
-
48
- /**
49
- * Helper function for allowed post/page screens where this plugin is active.
50
- *
51
- * @param array $screens The allowed screens
52
- *
53
- * @since 2.1.9
54
- *
55
- * Applies filters the_seo_framework_supported_screens : The supported administration
56
- * screens where css and javascript files are loaded.
57
- *
58
- * @param array $args the custom supported screens.
59
- *
60
- * @deprecated
61
- * @since 2.5.2
62
- *
63
- * @return array $screens
64
- */
65
- protected function supported_screens( $args = array() ) {
66
- $this->_deprecated_function( 'AutoDescription_Admin_Init::' . __FUNCTION__, '2.5.2' );
67
-
68
- /**
69
- * Instead of supporting page ID's, we support the Page base now.
70
- *
71
- * @since 2.3.3
72
- */
73
- $defaults = array(
74
- 'edit',
75
- 'post',
76
- 'edit-tags',
77
- );
78
-
79
- $screens = (array) apply_filters( 'the_seo_framework_supported_screens', $defaults, $args );
80
- $screens = wp_parse_args( $args, $screens );
81
-
82
- return $screens;
83
- }
84
-
85
- /**
86
- * Add doing it wrong html code in the footer.
87
- *
88
- * @since 2.2.5
89
- *
90
- * @deprecated
91
- * @since 2.5.2.1
92
- */
93
- public function title_doing_it_wrong() {
94
- $this->_deprecated_function( 'AutoDescription_Detect::' . __FUNCTION__, '2.5.2.1', 'AutoDescription_Detect::tell_title_doing_it_wrong()' );
95
-
96
- return;
97
- }
98
-
99
- /**
100
- * Checks a theme's support for a given feature
101
- *
102
- * @since 2.2.5
103
- *
104
- * @global array $_wp_theme_features
105
- *
106
- * @param string $feature the feature being checked
107
- * @return bool
108
- *
109
- * Taken from WP Core, but it now returns true on title-tag support.
110
- *
111
- * @deprecated
112
- * @since 2.6.0
113
- */
114
- public function current_theme_supports( $feature ) {
115
- $this->_deprecated_function( 'AutoDescription_Detect::' . __FUNCTION__, '2.6.0', 'current_theme_supports()' );
116
-
117
- return current_theme_supports();
118
- }
119
-
120
- /**
121
- * Echo debug values.
122
- *
123
- * @param mixed $values What to be output.
124
- *
125
- * @since 2.3.4
126
- *
127
- * @deprecated
128
- * @since 2.6.0
129
- */
130
- public function echo_debug_information( $values ) {
131
- $this->_deprecated_function( 'AutoDescription_Debug::' . __FUNCTION__, '2.6.0', 'AutoDescription_Debug::get_debug_information()' );
132
-
133
- echo $this->get_debug_information( $values );
134
-
135
- }
136
-
137
- /**
138
- * Get the archive Title.
139
- *
140
- * WordPress core function @since 4.1.0
141
- *
142
- * @since 2.3.6
143
- *
144
- * @deprecated
145
- * @since 2.6.0
146
- */
147
- public function get_the_archive_title() {
148
- $this->_deprecated_function( 'AutoDescription_Generate_Description::' . __FUNCTION__, '2.6.0', 'AutoDescription_Generate_Title::get_the_real_archive_title()' );
149
-
150
- return $this->get_the_real_archive_title();
151
- }
152
-
153
- /**
154
- * Adds the SEO Bar.
155
- *
156
- * @param string $column the current column : If it's a taxonomy, this is empty
157
- * @param int $post_id the post id : If it's a taxonomy, this is the column name
158
- * @param string $tax_id this is empty : If it's a taxonomy, this is the taxonomy id
159
- *
160
- * @param string $status the status in html
161
- *
162
- * @staticvar string $type_cache
163
- * @staticvar string $column_cache
164
- *
165
- * @since 2.1.9
166
- *
167
- * @deprecated
168
- * @since 2.6.0
169
- */
170
- public function seo_column( $column, $post_id, $tax_id = '' ) {
171
- $this->_deprecated_function( 'AutoDescription_DoingItRight::' . __FUNCTION__, '2.6.0', 'AutoDescription_DoingItRight::seo_bar()' );
172
-
173
- return $this->seo_bar( $column, $post_id, $tax_id );
174
- }
175
-
176
- /**
177
- * Ping Yahoo
178
- *
179
- * @since 2.2.9
180
- * @deprecated
181
- * @since 2.6.0
182
- */
183
- public function ping_yahoo() {
184
- $this->_deprecated_function( 'AutoDescription_Sitemaps::' . __FUNCTION__, '2.6.0', 'AutoDescription_Sitemaps::ping_bing()' );
185
-
186
- $this->ping_bing();
187
- }
188
-
189
- /**
190
- * Create sitemap.xml content transient.
191
- *
192
- * @param string|bool $content required The sitemap transient content.
193
- *
194
- * @since 2.2.9
195
- * @deprecated
196
- * @since 2.6.0
197
- */
198
- public function setup_sitemap_transient( $sitemap_content ) {
199
- $this->_deprecated_function( 'AutoDescription_Sitemaps::' . __FUNCTION__, '2.6.0', 'AutoDescription_Sitemaps::setup_sitemap()' );
200
-
201
- return $this->setup_sitemap( $sitemap_content );
202
- }
203
-
204
- /**
205
- * Detect WordPress language.
206
- * Considers en_UK, en_US, etc.
207
- *
208
- * @param string $str Required, the locale.
209
- * @param bool $use_cache Set to false to bypass the cache.
210
- *
211
- * @staticvar array $locale
212
- * @staticvar string $get_locale
213
- *
214
- * @since 2.3.8
215
- * @deprecated
216
- * @since 2.6.0
217
- *
218
- * @return bool
219
- */
220
- public function is_locale( $str, $use_cache = true ) {
221
- $this->_deprecated_function( 'AutoDescription_Detect::' . __FUNCTION__, '2.6.0', 'AutoDescription_Detect::check_wp_locale()' );
222
-
223
- return $this->check_wp_locale( $str, $use_cache );
224
- }
225
-
226
- /**
227
- * Build the title based on input, without tagline.
228
- * Note: Not escaped.
229
- *
230
- * @param string $title The Title to return
231
- * @param array $args : accepted args : {
232
- * @param int term_id The Taxonomy Term ID
233
- * @param bool placeholder Generate placeholder, ignoring options.
234
- * @param bool page_on_front Page on front condition for example generation
235
- * }
236
- *
237
- * @since 2.4.0
238
- * @deprecated
239
- * @since 2.6.0
240
- *
241
- * @return string Title without tagline.
242
- */
243
- public function get_placeholder_title( $title = '', $args = array() ) {
244
- $this->_deprecated_function( 'AutoDescription_Generate_Title::' . __FUNCTION__, '2.6.0', 'AutoDescription_Generate_Title::title()` with the argument $args[\'notagline\']' );
245
-
246
- $args['notagline'] = true;
247
- return $this->title( $title, '', '', $args );
248
- }
249
-
250
- /**
251
- * Initializes default settings very early at the after_setup_theme hook.
252
- * Admin only.
253
- *
254
- * @since 2.5.0
255
- * @deprecated
256
- * @since 2.6.0
257
- *
258
- * @return void
259
- */
260
- public function initialize_defaults_admin() {
261
- $this->_deprecated_function( 'AutoDescription_Siteoptions::' . __FUNCTION__, '2.6.0' );
262
- return;
263
- }
264
-
265
- /**
266
- * Initializes default settings very early at the after_setup_theme hook
267
- * Therefore supports is_rtl().
268
- *
269
- * @since 2.5.0
270
- * @deprecated
271
- * @since 2.6.0
272
- *
273
- * @return void
274
- */
275
- public function initialize_defaults() {
276
- $this->_deprecated_function( 'AutoDescription_Siteoptions::' . __FUNCTION__, '2.6.0' );
277
- return;
278
- }
279
-
280
- /**
281
- * Old style method for detecting SEO plugins.
282
- *
283
- * @since 2.6.1
284
- * @access private
285
- *
286
- * @deprecated
287
- * @since 2.6.1
288
- *
289
- * @return bool
290
- *
291
- * @thanks StudioPress (http://www.studiopress.com/) for some code.
292
- */
293
- public function detect_seo_plugins_old() {
294
-
295
- /**
296
- * Applies filters 'the_seo_framework_detect_seo_plugins' : array
297
- * @deprecated
298
- * @since 2.6.1
299
- *
300
- * Use this filter to adjust plugin tests.
301
- */
302
- $plugins_check = apply_filters(
303
- 'the_seo_framework_detect_seo_plugins',
304
- //* Add to this array to add new plugin checks.
305
- null
306
- );
307
-
308
- if ( isset( $plugins_check ) ) {
309
- $this->_deprecated_function( 'the_seo_framework_detect_seo_plugins', '2.6.1', 'the_seo_framework_conflicting_plugins' );
310
- return $this->detect_plugin( $plugins_check );
311
- }
312
-
313
- return null;
314
- }
315
-
316
-
317
- /**
318
- * Detects if plugins outputting og:type exists
319
- *
320
- * @note isn't used in $this->og_image() Because og:image may be output multiple times.
321
- *
322
- * @uses $this->detect_plugin()
323
- *
324
- * @since 1.3.0
325
- * @return bool OG plugin detected.
326
- *
327
- * @staticvar bool $has_plugin
328
- * @since 2.2.5
329
- *
330
- * @deprecated
331
- * @since 2.6.1
332
- *
333
- * @return bool $has_plugin one of the plugins has been found.
334
- */
335
- public function has_og_plugin() {
336
-
337
- /**
338
- * Applies filters 'the_seo_framework_detect_og_plugins' : array
339
- * @since 2.6.1
340
- * @deprecated
341
- * @since 2.6.1 (same patch)
342
- *
343
- * Use this filter to adjust plugin tests.
344
- */
345
- $plugins_check = apply_filters(
346
- 'the_seo_framework_detect_og_plugins',
347
- //* Add to this array to add new plugin checks.
348
- null
349
- );
350
-
351
- if ( isset( $plugins_check ) ) {
352
- $this->_deprecated_function( 'the_seo_framework_detect_og_plugins', '2.6.1', 'the_seo_framework_conflicting_plugins' );
353
- return $this->detect_plugin( $plugins_check );
354
- }
355
-
356
- return null;
357
- }
358
-
359
- /**
360
- * Detecs sitemap plugins
361
- *
362
- * @since 2.1.0
363
- * @staticvar bool $detected
364
- *
365
- * @deprecated
366
- * @since 2.6.1
367
- *
368
- * @return bool
369
- */
370
- public function has_sitemap_plugin() {
371
- $this->_deprecated_function( 'AutoDescription_Detect::' . __FUNCTION__, '2.6.1', 'AutoDescription_Detect::detect_sitemap_plugin' );
372
-
373
- return $this->detect_sitemap_plugin();
374
- }
375
-
376
- /**
377
- * Returns Post Type from current screen.
378
- *
379
- * @param bool $public Whether to only get Public Post types.
380
- *
381
- * @since 2.6.0
382
- *
383
- * @deprecated
384
- * @since 2.6.1
385
- *
386
- * @return bool|string The Post Type
387
- */
388
- public function get_current_post_type( $public = true ) {
389
-
390
- $this->_deprecated_function( 'AutoDescription_Detect::' . __FUNCTION__, '2.6.2', 'AutoDescription_Detect::get_supported_post_type' );
391
-
392
- static $post_type = null;
393
-
394
- //* Detect post type if empty or not set.
395
- if ( is_null( $post_type ) || empty( $post_type ) ) {
396
- global $current_screen;
397
-
398
- if ( isset( $current_screen->post_type ) ) {
399
-
400
- static $post_page = array();
401
-
402
- $args = $public ? array( 'public' => true ) : array();
403
-
404
- if ( ! isset( $post_page[$public] ) )
405
- $post_page[$public] = (array) get_post_types( $args );
406
-
407
- //* Smart var. This elemenates the need for a foreach loop, reducing resource usage.
408
- $post_type = isset( $post_page[$public][ $current_screen->post_type ] ) ? $current_screen->post_type : '';
409
- }
410
- }
411
-
412
- //* No post type has been found.
413
- if ( empty( $post_type ) )
414
- return false;
415
-
416
- return $post_type;
417
- }
418
-
419
- /**
420
- * Add the WPMUdev Domain Mapping rules again. And flush them on init.
421
- * Domain Mapping bugfix.
422
- *
423
- * @param bool $options_saved : If we're in admin and the sanitiation function runs.
424
- * @param bool $flush_now : Whether to flush directly on call if not yet flushed. Only when $options_saved is false.
425
- *
426
- * Runs a flush and updates the site option to "true".
427
- * When the site option is set to true, it not flush again on init.
428
- *
429
- * If $options_saved is true, it will not check for the init action hook and continue,
430
- * So it will flush the next time on init.
431
- *
432
- * @since 2.3.0
433
- * @access private
434
- *
435
- * @deprecated
436
- * @since 2.6.3
437
- */
438
- public function wpmudev_domainmap_flush_fix( $options_saved = false, $flush_now = true ) {
439
-
440
- $this->_deprecated_function( 'AutoDescription_Sitemaps::' . __FUNCTION__, '2.6.2' );
441
-
442
- if ( $this->pretty_permalinks && $this->is_domainmapping_active() ) {
443
- if ( $options_saved || 'init' === current_action() ) {
444
-
445
- if ( class_exists( 'Domainmap_Module_Cdsso' ) && defined( 'Domainmap_Module_Cdsso::SSO_ENDPOINT' ) ) {
446
- add_rewrite_endpoint( Domainmap_Module_Cdsso::SSO_ENDPOINT, EP_ALL );
447
-
448
- $name = 'tsf_wpmudev_dm_fix';
449
- $option = (array) get_site_option( $name, array() );
450
- $key = get_current_blog_id();
451
- $value = $this->o_plugin_updated;
452
-
453
- if ( $options_saved ) {
454
- //* Reset the flush on option change.
455
- if ( isset( $option[$key] ) && $value === $option[$key] ) {
456
- $option[$key] = false;
457
- update_site_option( $name, $option );
458
- }
459
- } else {
460
- if ( ! isset( $option[$key] ) || false === $option[$key] ) {
461
- //* Prevent flushing multiple times.
462
- $option[$key] = $value;
463
- update_site_option( $name, $option );
464
-
465
- //* Now flush
466
- if ( $flush_now )
467
- $this->flush_rewrite_rules();
468
- else
469
- $this->enqueue_rewrite_flush_other( true );
470
- }
471
- }
472
- }
473
- }
474
- }
475
-
476
- }
477
-
478
- /**
479
- * Generates relative URL for current post_ID.
480
- *
481
- * @param int|object $post The post object or ID.
482
- * @param bool $external Whether to fetch the WP Request or get the permalink by Post Object.
483
- * @param int $depr Deprecated The post ID.
484
- *
485
- * @since 2.3.0
486
- *
487
- * @deprecated
488
- * @since 2.6.5
489
- *
490
- * @global object $wp
491
- *
492
- * @return relative Post or Page url.
493
- */
494
- public function get_relative_url( $post = null, $external = false, $depr = null ) {
495
-
496
- $this->_deprecated_function( 'AutoDescription_Generate_Url::' . __FUNCTION__, '2.6.5', 'AutoDescription_Generate_Url::build_singular_relative_url()' );
497
-
498
- if ( isset( $depr ) ) {
499
- $post_id = $depr;
500
- } else {
501
- if ( is_object( $post ) ) {
502
- if ( isset( $post->ID ) )
503
- $post_id = $post->ID;
504
- } elseif ( is_scalar( $post ) ) {
505
- $post_id = (int) $post;
506
- }
507
- }
508
-
509
- if ( ! isset( $post_id ) ) {
510
- if ( ! $external )
511
- $post_id = $this->get_the_real_ID();
512
- else
513
- return '';
514
- }
515
-
516
- if ( $external || ! $this->is_home() ) {
517
- $permalink = get_permalink( $post_id );
518
- } elseif ( ! $external ) {
519
- global $wp;
520
-
521
- if ( isset( $wp->request ) )
522
- $permalink = $wp->request;
523
- }
524
-
525
- //* No permalink found.
526
- if ( ! isset( $permalink ) )
527
- return '';
528
-
529
- $path = $this->set_url_scheme( $permalink, 'relative' );
530
-
531
- return $path;
532
- }
533
- /**
534
- * Creates canonical url for the default permalink structure.
535
- *
536
- * @param object|int $post The post object or ID.
537
- * @param bool $paged Whether to add pagination for all types.
538
- * @param bool $paged_plural Whether to add pagination for the second or later page.
539
- *
540
- * @since 2.3.0
541
- *
542
- * @deprecated
543
- * @since 2.6.5
544
- *
545
- * @return string The URL path.
546
- */
547
- public function the_url_path_default_permalink_structure( $post = null, $paged = false, $paged_plural = true ) {
548
-
549
- $this->_deprecated_function( 'AutoDescription_Generate_Url::' . __FUNCTION__, '2.6.5' , 'AutoDescription_Generate_Url::build_singular_relative_url()' );
550
-
551
- //* Don't slash it.
552
- $this->url_slashit = false;
553
-
554
- if ( false === $this->is_singular() ) {
555
- //* We're on a taxonomy
556
- $object = get_queried_object();
557
-
558
- if ( is_object( $object ) ) {
559
- if ( $this->is_category() ) {
560
- $path = '?cat=' . $object->term_id;
561
- } elseif ( $this->is_tag() ) {
562
- $path = '?tag=' . $object->name;
563
- } elseif ( $this->is_date() ) {
564
- global $wp_query;
565
-
566
- $query = $wp_query->query;
567
-
568
- $year = $query->year;
569
- $month = $query->monthnum ? '&monthnum=' . $query->monthnum : '';
570
- $day = $query->day ? '&day=' . $query->day : '';
571
-
572
- $path = '?year=' . $year . $month . $day;
573
- } elseif ( $this->is_author() ) {
574
- $path = '?author=' . $object->author_name;
575
- } elseif ( $this->is_tax() ) {
576
- $path = '?taxonomy=' . $object->taxonomy . '&term=' . $object->slug;
577
- } elseif ( isset( $object->query_var ) && $object->query_var ) {
578
- $path = '?' . $object->query_var . '=' . $object->slug;
579
- } else {
580
- $path = '?p=' . $object->ID;
581
- }
582
-
583
- $paged = $this->maybe_get_paged( $this->paged(), $paged, $paged_plural );
584
- if ( $paged )
585
- $path .= '&paged=' . $paged;
586
- }
587
-
588
- }
589
-
590
- if ( ! isset( $path ) ) {
591
-
592
- if ( isset( $post ) ) {
593
- if ( is_object( $post ) && isset( $post->ID ) ) {
594
- $id = $post->ID;
595
- } elseif ( is_scalar( $post ) ) {
596
- $id = $post;
597
- }
598
- }
599
-
600
- if ( ! isset( $id ) )
601
- $id = $this->get_the_real_ID();
602
-
603
- $path = '?p=' . $id;
604
-
605
- $page = $this->maybe_get_paged( $this->page(), $paged, $paged_plural );
606
- if ( $page )
607
- $path .= '&page=' . $page;
608
- }
609
-
610
- return $path;
611
- }
612
-
613
- /**
614
- * Doing it Wrong The SEO Framework version wrapper.
615
- *
616
- * @since 2.3.0
617
- *
618
- * @deprecated
619
- * @since 2.6.6
620
- *
621
- * @return string The SEO Framework version.
622
- */
623
- public function the_seo_framework_version( $version = '' ) {
624
-
625
- $this->_deprecated_function( 'AutoDescription_Load::' . __FUNCTION__, '2.6.6' );
626
-
627
- $output = $version ? sprintf( __( '%s of The SEO Framework', 'autodescription' ), esc_attr( $version ) ) : '';
628
-
629
- return $output;
630
- }
631
-
632
-
633
- /**
634
- * HomePage Metabox General Tab Output.
635
- *
636
- * @since 2.6.0
637
- * @see $this->homepage_metabox() Callback for HomePage Settings box.
638
- *
639
- * @deprecated
640
- * @since 2.7.0
641
- */
642
- public function homepage_metabox_general() {
643
- $this->_deprecated_function( 'AutoDescription_Metaboxes::' . __FUNCTION__, '2.7.0', 'AutoDescription_Metaboxes::homepage_metabox_general_tab()' );
644
- $this->get_view( 'metaboxes/homepage-metabox', array(), 'general' );
645
- }
646
-
647
- /**
648
- * HomePage Metabox Additions Tab Output.
649
- *
650
- * @since 2.6.0
651
- * @see $this->homepage_metabox() Callback for HomePage Settings box.
652
- *
653
- * @deprecated
654
- * @since 2.7.0
655
- */
656
- public function homepage_metabox_additions() {
657
- $this->_deprecated_function( 'AutoDescription_Metaboxes::' . __FUNCTION__, '2.7.0', 'AutoDescription_Metaboxes::homepage_metabox_additions_tab()' );
658
- $this->get_view( 'metaboxes/homepage-metabox', array(), 'additions' );
659
- }
660
-
661
- /**
662
- * HomePage Metabox Robots Tab Output
663
- *
664
- * @since 2.6.0
665
- * @see $this->homepage_metabox() Callback for HomePage Settings box.
666
- *
667
- * @deprecated
668
- * @since 2.7.0
669
- */
670
- public function homepage_metabox_robots() {
671
- $this->_deprecated_function( 'AutoDescription_Metaboxes::' . __FUNCTION__, '2.7.0', 'AutoDescription_Metaboxes::homepage_metabox_robots_tab()' );
672
- $this->get_view( 'metaboxes/homepage-metabox', array(), 'robots' );
673
- }
674
-
675
- /**
676
- * Delete transient for the automatic description for blog on save request.
677
- * Returns old option, since that's passed for sanitation within WP Core.
678
- *
679
- * @since 2.3.3
680
- *
681
- * @deprecated
682
- * @since 2.7.0
683
- *
684
- * @param string $old_option The previous blog description option.
685
- * @return string Previous option.
686
- */
687
- public function delete_auto_description_blog_transient( $old_option ) {
688
-
689
- $this->_deprecated_function( 'AutoDescription_Transients::' . __FUNCTION__, '2.7.0', 'AutoDescription_Transients::delete_auto_description_frontpage_transient()' );
690
-
691
- $this->setup_auto_description_transient( $this->get_the_front_page_ID(), '', 'frontpage' );
692
-
693
- delete_transient( $this->auto_description_transient );
694
-
695
- return $old_option;
696
- }
697
-
698
- /**
699
- * Add term meta data into options table of the term.
700
- * Adds separated database options for terms, as the terms table doesn't allow for addition.
701
- *
702
- * Applies filters array the_seo_framework_term_meta_defaults : Array of default term SEO options
703
- * Applies filters mixed the_seo_framework_term_meta_{field} : Override filter for specifics.
704
- * Applies filters array the_seo_framework_term_meta : Override output for term or taxonomy.
705
- *
706
- * @since 2.1.8
707
- *
708
- * @deprecated silently.
709
- * @since WordPress 4.4.0
710
- * @since The SEO Framework 2.7.0
711
- *
712
- * @param object $term Database row object.
713
- * @param string $taxonomy Taxonomy name that $term is part of.
714
- * @return object $term Database row object.
715
- */
716
- public function get_term_filter( $term, $taxonomy ) {
717
-
718
- //* Do nothing, if $term is not an object.
719
- if ( ! is_object( $term ) )
720
- return $term;
721
-
722
- /**
723
- * No need to process this data outside of the Terms' scope.
724
- * @since 2.6.0
725
- */
726
- if ( false === is_admin() && false === is_archive() )
727
- return $term;
728
-
729
- /**
730
- * No need to process this after the data has already been output.
731
- * @since 2.6.0
732
- */
733
- if ( did_action( 'the_seo_framework_do_after_output' ) )
734
- return $term;
735
-
736
- /**
737
- * Do nothing if called in the context of creating a term via an Ajax call to prevent data conflict.
738
- * @since 2.1.8
739
- *
740
- * @since 2.6.0 delay did_action call as it's a heavy array call.
741
- */
742
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX && did_action( 'wp_ajax_add-tag' ) )
743
- return $term;
744
-
745
- $db = get_option( 'autodescription-term-meta' );
746
- $term_meta = isset( $db[$term->term_id] ) ? $db[$term->term_id] : array();
747
-
748
- $term->admeta = wp_parse_args( $term_meta, $this->get_term_meta_defaults() );
749
-
750
- //* Sanitize term meta
751
- foreach ( $term->admeta as $field => $value ) {
752
-
753
- /**
754
- * Trim and sanitize the title beforehand.
755
- * @since 2.5.0
756
- */
757
- if ( 'doctitle' === $field )
758
- $value = trim( strip_tags( $value ) );
759
-
760
- /**
761
- * Trim and sanitize the description beforehand.
762
- * @since 2.5.0
763
- */
764
- if ( 'description' === $field )
765
- $value = $this->s_description( $value );
766
-
767
- /**
768
- * @param object $term The Term object.
769
- * @param string $taxonomy The Taxonomy name.
770
- */
771
- $term->admeta[$field] = (string) apply_filters( "the_seo_framework_term_meta_{$field}", stripslashes( wp_kses_decode_entities( $value ) ), $term, $taxonomy );
772
- }
773
-
774
- /**
775
- * @param object $term The Term object.
776
- * @param array $taxonomy The Taxonomy name.
777
- */
778
- $term->admeta = (array) apply_filters( 'the_seo_framework_term_meta', $term->admeta, $term, $taxonomy );
779
-
780
- return $term;
781
- }
782
-
783
- /**
784
- * Adds The SEO Framework term meta data to functions that return multiple terms.
785
- *
786
- * @since 2.0.0
787
- *
788
- * @deprecated silently.
789
- * @since WordPress 4.4.0
790
- * @since The SEO Framework 2.7.0
791
- *
792
- * @param array $terms Database row objects.
793
- * @param string $taxonomy Taxonomy name that $terms are part of.
794
- * @return array $terms Database row objects.
795
- */
796
- public function get_terms_filter( array $terms, $taxonomy ) {
797
-
798
- foreach ( $terms as $term )
799
- $term = $this->get_term_filter( $term, $taxonomy );
800
-
801
- return $terms;
802
- }
803
-
804
- /**
805
- * Save taxonomy meta data.
806
- * Fires when a user edits and saves a taxonomy.
807
- *
808
- * @since 2.1.8
809
- *
810
- * @deprecated silently.
811
- * @since WordPress 4.4.0
812
- * @since The SEO Framework 2.7.0
813
- *
814
- * @param integer $term_id Term ID.
815
- * @param integer $tt_id Term Taxonomy ID.
816
- * @return void Early on AJAX call.
817
- */
818
- public function taxonomy_seo_save( $term_id, $tt_id ) {
819
-
820
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
821
- return;
822
-
823
- $term_meta = (array) get_option( 'autodescription-term-meta' );
824
-
825
- $term_meta[$term_id] = isset( $_POST['autodescription-meta'] ) ? (array) $_POST['autodescription-meta'] : array();
826
-
827
- //* Pass through wp_kses if not super admin.
828
- if ( ! current_user_can( 'unfiltered_html' ) && isset( $term_meta[$term_id]['archive_description'] ) )
829
- $term_meta[$term_id]['archive_description'] = wp_kses( $term_meta[$term_id]['archive_description'] );
830
-
831
- update_option( 'autodescription-term-meta', $term_meta );
832
-
833
- }
834
-
835
- /**
836
- * Delete term meta data.
837
- * Fires when a user deletes a term.
838
- *
839
- * @since 2.1.8
840
- *
841
- * @deprecated silently.
842
- * @since WordPress 4.4.0
843
- * @since The SEO Framework 2.7.0
844
- *
845
- * @param integer $term_id Term ID.
846
- * @param integer $tt_id Taxonomy Term ID.
847
- */
848
- public function term_meta_delete( $term_id, $tt_id ) {
849
-
850
- $term_meta = (array) get_option( 'autodescription-term-meta' );
851
-
852
- unset( $term_meta[$term_id] );
853
-
854
- update_option( 'autodescription-term-meta', (array) $term_meta );
855
-
856
- }
857
-
858
- /**
859
- * Faster way of doing an in_array search compared to default PHP behavior.
860
- * @NOTE only to show improvement with large arrays. Might slow down with small arrays.
861
- * @NOTE can't do type checks. Always assume the comparing value is a string.
862
- *
863
- * @since 2.5.2
864
- * @deprecated
865
- * @since 2.7.0
866
- *
867
- * @param string|array $needle The needle(s) to search for
868
- * @param array $array The single dimensional array to search in.
869
- * @return bool true if value is in array.
870
- */
871
- public function in_array( $needle, $array ) {
872
-
873
- $this->_deprecated_function( 'AutoDescription_Core::' . __FUNCTION__, '2.7.0', 'in_array()' );
874
-
875
- $array = array_flip( $array );
876
-
877
- if ( is_string( $needle ) ) {
878
- if ( isset( $array[ $needle ] ) )
879
- return true;
880
- } elseif ( is_array( $needle ) ) {
881
- foreach ( $needle as $str ) {
882
- if ( isset( $array[ $str ] ) )
883
- return true;
884
- }
885
- }
886
-
887
- return false;
888
- }
889
-
890
- /**
891
- * Fetches posts with exclude_local_search option on
892
- *
893
- * @since 2.1.7
894
- * @since 2.7.0 Deprecated.
895
- * @deprecated
896
- *
897
- * @return array Excluded Post IDs
898
- */
899
- public function exclude_search_ids() {
900
-
901
- $this->_deprecated_function( 'AutoDescription_Search::' . __FUNCTION__, '2.7.0', 'AutoDescription_Search::get_excluded_search_ids()' );
902
-
903
- return $this->get_excluded_search_ids();
904
- }
905
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/{deprecated → functions}/deprecated.php RENAMED
@@ -22,7 +22,7 @@ defined( 'ABSPATH' ) or die;
22
  * This file contains most functions that have been deprecated.
23
  *
24
  * @since 2.1.6
25
- * @since 2.3.5 Emptied. (~2.5 months later )
26
  * @since 2.6.2 Emptied. (~6 months later)
27
  */
28
 
@@ -86,7 +86,7 @@ function tsf_wp_version( $version = '4.3.0', $compare = '>=' ) {
86
  $theseoframework = the_seo_framework();
87
 
88
  if ( isset( $theseoframework ) ) {
89
- $theseoframework->_deprecated_function( __FUNCTION__, '2.7.0', 'AutoDescription_Detect::wp_version()' );
90
  return $theseoframework->wp_version( $version, $compare );
91
  }
92
 
22
  * This file contains most functions that have been deprecated.
23
  *
24
  * @since 2.1.6
25
+ * @since 2.3.5 Emptied. (~2.5 months later)
26
  * @since 2.6.2 Emptied. (~6 months later)
27
  */
28
 
86
  $theseoframework = the_seo_framework();
87
 
88
  if ( isset( $theseoframework ) ) {
89
+ $theseoframework->_deprecated_function( __FUNCTION__, '2.7.0', 'the_seo_framework()->wp_version()' );
90
  return $theseoframework->wp_version( $version, $compare );
91
  }
92
 
inc/functions/optionsapi.php CHANGED
@@ -35,7 +35,7 @@ defined( 'ABSPATH' ) or die;
35
  * @return object The SEO Framework Facade class.
36
  */
37
  function the_seo_framework() {
38
- return the_seo_framework_init();
39
  }
40
 
41
  /**
@@ -45,8 +45,9 @@ function the_seo_framework() {
45
  * will fail to load views.
46
  *
47
  * @since 2.7.0
 
48
  *
49
- * @return string The SEO Framework class name.
50
  */
51
  function the_seo_framework_class() {
52
 
@@ -55,6 +56,9 @@ function the_seo_framework_class() {
55
  if ( isset( $class ) )
56
  return $class;
57
 
 
 
 
58
  return $class = get_class( the_seo_framework() );
59
  }
60
 
@@ -66,7 +70,7 @@ function the_seo_framework_class() {
66
  * @return bool true if SEO framework is active
67
  */
68
  function the_seo_framework_active() {
69
- return the_seo_framework_load();
70
  }
71
 
72
  /**
@@ -137,12 +141,13 @@ function the_seo_framework_options_pagehook() {
137
  * Fetch an option from The SEO Framework.
138
  *
139
  * @since 2.7.0
 
140
  *
141
  * @param string $key Option name.
142
  * @param boolean $use_cache Optional. Whether to use the cache value or not. Defaults to true.
143
  * @return mixed The option value.
144
  */
145
- function the_seo_framework_get_option() {
146
 
147
  $theseoframework = the_seo_framework();
148
 
@@ -228,6 +233,14 @@ function the_seo_framework_is_settings_page() {
228
  *
229
  * @since 2.7.0
230
  *
 
 
 
 
 
 
 
 
231
  * @return bool True on success. False on failure.
232
  */
233
  function the_seo_framework_update_option( $new_option ) {
35
  * @return object The SEO Framework Facade class.
36
  */
37
  function the_seo_framework() {
38
+ return \The_SEO_Framework\_init();
39
  }
40
 
41
  /**
45
  * will fail to load views.
46
  *
47
  * @since 2.7.0
48
+ * @since 2.8.0: Added did_action and current_action check.
49
  *
50
+ * @return string|bool The SEO Framework class name. False if The SEO Framework isn't loaded.
51
  */
52
  function the_seo_framework_class() {
53
 
56
  if ( isset( $class ) )
57
  return $class;
58
 
59
+ if ( ! ( did_action( 'plugins_loaded' ) || current_action( 'plugins_loaded' ) ) )
60
+ return false;
61
+
62
  return $class = get_class( the_seo_framework() );
63
  }
64
 
70
  * @return bool true if SEO framework is active
71
  */
72
  function the_seo_framework_active() {
73
+ return \The_SEO_Framework\_can_load();
74
  }
75
 
76
  /**
141
  * Fetch an option from The SEO Framework.
142
  *
143
  * @since 2.7.0
144
+ * @since 2.8.0 Now works as intended, by including the required parameters.
145
  *
146
  * @param string $key Option name.
147
  * @param boolean $use_cache Optional. Whether to use the cache value or not. Defaults to true.
148
  * @return mixed The option value.
149
  */
150
+ function the_seo_framework_get_option( $key, $use_cache = true ) {
151
 
152
  $theseoframework = the_seo_framework();
153
 
233
  *
234
  * @since 2.7.0
235
  *
236
+ * @param string|array $new_option {
237
+ * if string: The string will act as a key for a new empty string option, e.g. : {
238
+ * 'sitemap_index' becomes ['sitemap_index' => '']
239
+ * }
240
+ * if array: The option name(s) and value(s), e.g. : {
241
+ * ['sitemap_index' => 1]
242
+ * }
243
+ * }
244
  * @return bool True on success. False on failure.
245
  */
246
  function the_seo_framework_update_option( $new_option ) {
inc/functions/plugin-test-server.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The SEO Framework plugin
4
+ * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License version 3 as published
8
+ * by the Free Software Foundation.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ defined( 'THE_SEO_FRAMEWORK_PLUGIN_BASENAME' ) or die;
20
+
21
+ /**
22
+ * This file holds functions for testing the plugin after upgrade.
23
+ * This file will only be called ONCE if the required version option is lower
24
+ * compared to The SEO Framework version constant.
25
+ *
26
+ * @since 2.8.0
27
+ * @access private
28
+ */
29
+
30
+ the_seo_framework_test_server_phase();
31
+ /**
32
+ * Tests plugin upgrade.
33
+ *
34
+ * @since 2.8.0
35
+ * @access private
36
+ * @link http://php.net/eol.php
37
+ * @link https://codex.wordpress.org/WordPress_Versions
38
+ */
39
+ function the_seo_framework_test_server_phase() {
40
+
41
+ $requirements = array(
42
+ 'php' => '50300',
43
+ 'wp' => '35700',
44
+ );
45
+
46
+ ! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < $requirements['php'] and $test = 1
47
+ or $GLOBALS['wp_db_version'] < $requirements['wp'] and $test = 2
48
+ or $test = true;
49
+
50
+ //* All good.
51
+ if ( true === $test ) {
52
+ update_site_option( 'the_seo_framework_tested_upgrade_version', THE_SEO_FRAMEWORK_DB_VERSION );
53
+ return;
54
+ }
55
+
56
+ if ( is_multisite() ) {
57
+ $plugins = get_site_option( 'active_sitewide_plugins' );
58
+ $network_mode = isset( $plugins[ THE_SEO_FRAMEWORK_PLUGIN_BASENAME ] );
59
+ } else {
60
+ $network_mode = false;
61
+ }
62
+
63
+ if ( ! function_exists( 'deactivate_plugins' ) )
64
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
65
+
66
+ $admin = is_admin();
67
+ $silent = ! $admin;
68
+
69
+ //* Not good. Deactivate plugin.
70
+ deactivate_plugins( THE_SEO_FRAMEWORK_PLUGIN_BASENAME, $silent, $network_mode );
71
+
72
+ //* Don't die on front-end.
73
+ if ( ! $admin )
74
+ return;
75
+
76
+ switch ( $test ) :
77
+ case 0 :
78
+ case 1 :
79
+ //* PHP requirements not met, always count up to encourage best standards.
80
+ $requirement = 'PHP 5.3.0 or later';
81
+ $issue = 'PHP version';
82
+ $version = phpversion();
83
+ $subtitle = 'Server Requirements';
84
+ break;
85
+
86
+ case 2 :
87
+ //* WordPress requirements not met.
88
+ $requirement = 'WordPress 4.4 or later';
89
+ $issue = 'WordPress version';
90
+ $version = $GLOBALS['wp_version'];
91
+ $subtitle = 'WordPress Requirements';
92
+ break;
93
+
94
+ default :
95
+ wp_die();
96
+ endswitch;
97
+
98
+ //* network_admin_url() falls back to admin_url() on single. But networks can enable single too.
99
+ $pluginspage = $network_mode ? network_admin_url( 'plugins.php' ) : admin_url( 'plugins.php' );
100
+
101
+ //* Let's have some fun with teapots.
102
+ $response = floor( time() / DAY_IN_SECONDS ) === floor( strtotime( 'first day of April ' . date( 'Y' ) ) / DAY_IN_SECONDS ) ? 418 : 500;
103
+
104
+ wp_die(
105
+ sprintf(
106
+ '<p><strong>The SEO Framework</strong> requires <em>%s</em>. Sorry about that!<br>Your %s is: <code>%s</code></p>
107
+ <p>Do you want to <strong><a onclick="window.history.back()" href="%s">go back</a></strong>?</p>',
108
+ esc_html( $requirement ), esc_html( $issue ), esc_html( $version ), esc_url( $pluginspage )
109
+ ),
110
+ sprintf( 'The SEO Framework &laquo; %s', esc_attr( $subtitle ) ),
111
+ array( 'response' => intval( $response ) )
112
+ );
113
+ }
inc/functions/upgrade.php CHANGED
@@ -37,7 +37,6 @@ add_action( 'admin_init', 'the_seo_framework_do_upgrade', 20 );
37
  * Only works on WordPress 4.4 and later to ensure and force maximum compatibility.
38
  *
39
  * @since 2.7.0
40
- * @global int $wp_db_version
41
  *
42
  * @thanks StudioPress for some code.
43
  */
@@ -49,17 +48,18 @@ function the_seo_framework_do_upgrade() {
49
  if ( ! the_seo_framework()->wp_version( '4.4', '>=' ) )
50
  return;
51
 
52
- global $wp_db_version;
53
-
54
  //* If the WordPress Database hasn't been upgraded yet, make the user upgrade first.
55
- if ( (int) get_option( 'db_version' ) !== $wp_db_version ) {
56
- wp_safe_redirect( admin_url( 'upgrade.php?_wp_http_referer=' . urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
57
  exit;
58
  }
59
 
60
  if ( get_option( 'the_seo_framework_upgraded_db_version' ) < '2701' )
61
  the_seo_framework_do_upgrade_2701();
62
 
 
 
 
63
  do_action( 'the_seo_framework_upgraded' );
64
  }
65
 
@@ -92,19 +92,17 @@ function the_seo_framework_do_upgrade_2701() {
92
  }
93
 
94
  /**
95
- * Removes term metadata for version 2800
 
96
  *
97
  * @since 2.8.0
98
- * @TODO planned.
99
  */
100
- function the_seo_framework_do_upgrade_2800() {
101
 
102
- //* Delete old values from database. Removes backwards compatibility.
103
- // delete_option( 'autodescription-term-meta' );
104
 
105
- //* Set this as upgrade notice:
106
- // = 2.8.0 =
107
- // This version deletes all old style metadata values. This removes backwards term meta data compatibility with The SEO Framework 2.6.5.2 or lower.
108
 
109
- // update_option( 'the_seo_framework_upgraded_db_version', '2800' );
110
  }
37
  * Only works on WordPress 4.4 and later to ensure and force maximum compatibility.
38
  *
39
  * @since 2.7.0
 
40
  *
41
  * @thanks StudioPress for some code.
42
  */
48
  if ( ! the_seo_framework()->wp_version( '4.4', '>=' ) )
49
  return;
50
 
 
 
51
  //* If the WordPress Database hasn't been upgraded yet, make the user upgrade first.
52
+ if ( (int) get_option( 'db_version' ) !== (int) $GLOBALS['wp_db_version'] ) {
53
+ wp_safe_redirect( admin_url( 'upgrade.php?_wp_http_referer=' . rawurlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
54
  exit;
55
  }
56
 
57
  if ( get_option( 'the_seo_framework_upgraded_db_version' ) < '2701' )
58
  the_seo_framework_do_upgrade_2701();
59
 
60
+ if ( get_option( 'the_seo_framework_upgraded_db_version' ) < '2802' )
61
+ the_seo_framework_do_upgrade_2802();
62
+
63
  do_action( 'the_seo_framework_upgraded' );
64
  }
65
 
92
  }
93
 
94
  /**
95
+ * Removes term metadata for version 2802.
96
+ * Reinitializes rewrite data for for sitemap stylesheet.
97
  *
98
  * @since 2.8.0
 
99
  */
100
+ function the_seo_framework_do_upgrade_2802() {
101
 
102
+ the_seo_framework()->reinitialize_rewrite();
 
103
 
104
+ //* Delete old values from database. Removes backwards compatibility.
105
+ delete_option( 'autodescription-term-meta' );
 
106
 
107
+ update_option( 'the_seo_framework_upgraded_db_version', '2802' );
108
  }
inc/interfaces/debug.interface.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Classes
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'ABSPATH' ) or die;
8
+
9
+ /**
10
+ * The SEO Framework plugin
11
+ * Copyright (C) 2015 - 2016 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
15
+ * by the Free Software Foundation.
16
+ *
17
+ * This program is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
+ */
25
+
26
+ /**
27
+ * Interface The_SEO_Framework\Debug_Interface
28
+ *
29
+ * Sets public debug functions.
30
+ *
31
+ * @since 2.8.0
32
+ */
33
+ interface Debug_Interface {
34
+
35
+ /**
36
+ * Mark a filter as deprecated and inform when it has been used.
37
+ *
38
+ * @since 2.8.0
39
+ * @access private
40
+ * @see @this->_deprecated_function().
41
+ *
42
+ * @param string $filter The function that was called.
43
+ * @param string $version The version of WordPress that deprecated the function.
44
+ * @param string $replacement Optional. The function that should have been called. Default null.
45
+ */
46
+ public function _deprecated_filter( $filter, $version, $replacement = null );
47
+
48
+ /**
49
+ * Mark a function as deprecated and inform when it has been used.
50
+ *
51
+ * Taken from WordPress core, but added extra parameters and linguistic alterations.
52
+ *
53
+ * The current behavior is to trigger a user error if WP_DEBUG is true.
54
+ *
55
+ * @since 2.6.0
56
+ * @access private
57
+ *
58
+ * @param string $function The function that was called.
59
+ * @param string $version The version of WordPress that deprecated the function.
60
+ * @param string $replacement Optional. The function that should have been called. Default null.
61
+ */
62
+ public function _deprecated_function( $function, $version, $replacement = null );
63
+
64
+ /**
65
+ * Mark a function as deprecated and inform when it has been used.
66
+ *
67
+ * Taken from WordPress core, but added extra parameters and linguistic alterations.
68
+ *
69
+ * The current behavior is to trigger a user error if WP_DEBUG is true.
70
+ *
71
+ * @since 2.6.0
72
+ * @access private
73
+ *
74
+ * @param string $function The function that was called.
75
+ * @param string $message A message explaining what has been done incorrectly.
76
+ * @param string $version The version of WordPress where the message was added.
77
+ */
78
+ public function _doing_it_wrong( $function, $message, $version );
79
+
80
+ /**
81
+ * Mark a property or method inaccessible when it has been used.
82
+
83
+ * The current behavior is to trigger a user error if WP_DEBUG is true.
84
+ *
85
+ * @since 2.7.0
86
+ * @access private
87
+ *
88
+ * @param string $p_or_m The Property or Method.
89
+ * @param string $message A message explaining what has been done incorrectly.
90
+ */
91
+ public function _inaccessible_p_or_m( $p_or_m, $message = '' );
92
+
93
+ /**
94
+ * Debug init. Simplified way of debugging a function, only works in admin.
95
+ *
96
+ * @since 2.6.0
97
+ * @access private
98
+ *
99
+ * @param string $method The function name.
100
+ * @param bool $store Whether to store the output in cache for next run to pick up on.
101
+ * @param double $debug_key Use $debug_key as variable, it's reserved.
102
+ * @param mixed function args.
103
+ * @return void early if debugging is disabled or when storing cache values.
104
+ */
105
+ public function debug_init( $method, $store, $debug_key );
106
+ }
inc/views/debug/output.php CHANGED
@@ -1,11 +1,16 @@
1
  <?php
 
 
 
2
 
3
  defined( 'ABSPATH' ) and $_this = the_seo_framework_class() and $this instanceof $_this or die;
4
 
5
- if ( $this->debug_output ) {
6
- if ( $this->the_seo_framework_debug_hidden ) {
7
- echo "\r\n<!--\r\n:: THE SEO FRAMEWORK DEBUG :: \r\n" . $this->debug_output . "\r\n:: / THE SEO FRAMEWORK DEBUG ::\r\n-->\r\n";
8
- } else {
 
 
9
 
10
  $id = $this->get_the_real_ID();
11
  $mdash = ' &mdash; ';
@@ -19,21 +24,25 @@ if ( $this->debug_output ) {
19
  if ( $this->is_admin() ) {
20
  ?>
21
  <div style="color:#444;font-family:Georgio,sans-serif;font-size:14px;clear:both;float:left;position:relative;width:calc( 100% - 200px );min-height:700px;padding:0;margin:20px 20px 40px 180px;overflow:hidden;border:1px solid #ccc;border-radius:3px;line-height:18px">
22
- <h3 style="font-size:14px;padding:0 12px;margin:0;line-height:39px;border-bottom:2px solid #aaa;position:absolute;z-index:1;width:100%;right:0;left:0;top:0;background:#fff;border-radius:3px 3px 0 0;height:39px;">
23
  SEO Debug Information
24
  <?php
25
  if ( $this->is_post_edit() || $this->is_term_edit() ) :
26
  echo ' :: ';
27
- echo 'Type: ' . esc_html( $type );
28
- echo $mdash . 'ID: ' . esc_html( $id );
29
- echo $mdash . 'Cache key: ' . esc_html( $cache_key );
 
 
30
  endif;
31
  ?>
32
  </h3>
33
  <div style="position:absolute;bottom:0;right:0;left:0;top:39px;margin:0;padding:0;background:#fff;border-radius:3px;overflow-x:hidden;z-index:9001">
34
- <?php echo $this->debug_header_output(); ?>
35
- <?php echo $this->debug_query_output(); ?>
36
- <?php echo $this->debug_output; ?>
 
 
37
  </div>
38
  </div>
39
  <?php
@@ -41,22 +50,36 @@ if ( $this->debug_output ) {
41
  ?>
42
  <style type="text/css">.wp-ui-notification{color:#fff;background-color:#d54e21}.code.highlight{font-family:Consolas,Monaco,monospace;font-size:14px;}.theseoframework-debug h3{font-size:18px;margin:18px 0}</style>
43
  <div class="theseoframework-debug" style="color:#444;font-family:Georgio,sans-serif;font-size:14px;clear:both;float:left;position:relative;width:calc( 100% - 80px );min-height:700px;padding:0;margin:40px;overflow:hidden;border:1px solid #ccc;border-radius:3px;line-height:18px">
44
- <h3 style="font-size:14px;padding:0 12px;margin:0;line-height:39px;border-bottom:2px solid #aaa;position:absolute;z-index:1;width:100%;right:0;left:0;top:0;background:#fff;border-radius:3px 3px 0 0;height:39px">
45
  SEO Debug Information
46
  <?php
47
  echo ' :: ';
48
  echo 'Type: ' . esc_html( $type );
49
- echo $mdash . 'ID: ' . esc_html( $id );
50
- echo $mdash . 'Cache key: ' . esc_html( $cache_key );
 
 
51
  ?>
52
  </h3>
53
  <div style="position:absolute;bottom:0;right:0;left:0;top:39px;margin:0;padding:0;background:#fff;border-radius:3px;overflow-x:hidden;z-index:9001">
54
- <?php echo $this->debug_header_output(); ?>
55
- <?php echo $this->debug_query_output(); ?>
56
- <?php echo $this->debug_output; ?>
 
 
 
 
 
 
 
 
 
 
 
 
57
  </div>
58
  </div>
59
  <?php
60
  }
61
- }
62
- }
1
  <?php
2
+ /**
3
+ * @package The_SEO_Framework\Views\Debug
4
+ */
5
 
6
  defined( 'ABSPATH' ) and $_this = the_seo_framework_class() and $this instanceof $_this or die;
7
 
8
+ if ( The_SEO_Framework\Debug::has_debug_output() ) :
9
+ if ( $this->the_seo_framework_debug_hidden ) :
10
+ echo "\r\n<!--\r\n:: THE SEO FRAMEWORK DEBUG :: \r\n";
11
+ The_SEO_Framework\Debug::_output_debug();
12
+ echo "\r\n:: / THE SEO FRAMEWORK DEBUG ::\r\n-->\r\n";
13
+ else :
14
 
15
  $id = $this->get_the_real_ID();
16
  $mdash = ' &mdash; ';
24
  if ( $this->is_admin() ) {
25
  ?>
26
  <div style="color:#444;font-family:Georgio,sans-serif;font-size:14px;clear:both;float:left;position:relative;width:calc( 100% - 200px );min-height:700px;padding:0;margin:20px 20px 40px 180px;overflow:hidden;border:1px solid #ccc;border-radius:3px;line-height:18px">
27
+ <h3 style="font-size:14px;padding:0 12px;margin:0;line-height:39px;border-bottom:2px solid #aaa;position:absolute;z-index:9002;width:100%;right:0;left:0;top:0;background:#fff;border-radius:3px 3px 0 0;height:39px;">
28
  SEO Debug Information
29
  <?php
30
  if ( $this->is_post_edit() || $this->is_term_edit() ) :
31
  echo ' :: ';
32
+ echo esc_html( 'Type: ' . $type );
33
+ echo esc_html( $mdash . 'ID: ' . $id );
34
+ echo esc_html( $mdash . 'Cache key: ' . $cache_key );
35
+ echo esc_html( $mdash . 'Plugin version: ' . THE_SEO_FRAMEWORK_VERSION );
36
+ echo esc_html( $mdash . 'Plugin DB version: c' . get_option( 'the_seo_framework_upgraded_db_version' ) . ' | e' . THE_SEO_FRAMEWORK_DB_VERSION );
37
  endif;
38
  ?>
39
  </h3>
40
  <div style="position:absolute;bottom:0;right:0;left:0;top:39px;margin:0;padding:0;background:#fff;border-radius:3px;overflow-x:hidden;z-index:9001">
41
+ <?php
42
+ The_SEO_Framework\Debug::_output_debug_header();
43
+ The_SEO_Framework\Debug::_output_debug_query();
44
+ The_SEO_Framework\Debug::_output_debug();
45
+ ?>
46
  </div>
47
  </div>
48
  <?php
50
  ?>
51
  <style type="text/css">.wp-ui-notification{color:#fff;background-color:#d54e21}.code.highlight{font-family:Consolas,Monaco,monospace;font-size:14px;}.theseoframework-debug h3{font-size:18px;margin:18px 0}</style>
52
  <div class="theseoframework-debug" style="color:#444;font-family:Georgio,sans-serif;font-size:14px;clear:both;float:left;position:relative;width:calc( 100% - 80px );min-height:700px;padding:0;margin:40px;overflow:hidden;border:1px solid #ccc;border-radius:3px;line-height:18px">
53
+ <h3 style="font-size:14px;padding:0 12px;margin:0;line-height:39px;border-bottom:2px solid #aaa;position:absolute;z-index:9002;width:100%;right:0;left:0;top:0;background:#fff;border-radius:3px 3px 0 0;height:39px">
54
  SEO Debug Information
55
  <?php
56
  echo ' :: ';
57
  echo 'Type: ' . esc_html( $type );
58
+ echo esc_html( $mdash . 'ID: ' . $id );
59
+ echo esc_html( $mdash . 'Cache key: ' . $cache_key );
60
+ echo esc_html( $mdash . 'Plugin version: ' . THE_SEO_FRAMEWORK_VERSION );
61
+ echo esc_html( $mdash . 'Plugin DB version: c' . get_option( 'the_seo_framework_upgraded_db_version' ) . ' | e' . THE_SEO_FRAMEWORK_DB_VERSION );
62
  ?>
63
  </h3>
64
  <div style="position:absolute;bottom:0;right:0;left:0;top:39px;margin:0;padding:0;background:#fff;border-radius:3px;overflow-x:hidden;z-index:9001">
65
+ <?php
66
+ The_SEO_Framework\Debug::_output_debug_header();
67
+ ?>
68
+ <div style="width:50%;float:left;">
69
+ <?php
70
+ The_SEO_Framework\Debug::_output_debug_query_from_cache();
71
+ ?>
72
+ </div><div style="width:50%;float:right;">
73
+ <?php
74
+ The_SEO_Framework\Debug::_output_debug_query();
75
+ ?>
76
+ </div>
77
+ <?php
78
+ The_SEO_Framework\Debug::_output_debug();
79
+ ?>
80
  </div>
81
  </div>
82
  <?php
83
  }
84
+ endif;
85
+ endif;
inc/views/inpost/index.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * When power leads men towards arrogance, poetry reminds him of his limitations.
4
+ * When power narrows the areas of man’s concern, poetry reminds him of the richness and diversity of existence.
5
+ * When power corrupts, poetry cleanses.
6
+ *
7
+ * - John F. Kennedy
8
+ */
inc/views/inpost/seo-settings.php ADDED
@@ -0,0 +1,423 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Views\Inpost
4
+ */
5
+
6
+ defined( 'ABSPATH' ) and $_this = the_seo_framework_class() and $this instanceof $_this or die;
7
+
8
+ //* Fetch the required instance within this file.
9
+ $instance = $this->get_view_instance( 'the_seo_framework_settings_type', $instance );
10
+
11
+ //* Get the language the Google page should assume.
12
+ $language = $this->google_language();
13
+
14
+ switch ( $instance ) :
15
+ case 'the_seo_framework_settings_type_singular' :
16
+ $post_id = $this->get_the_real_ID();
17
+ $is_static_frontpage = $this->is_static_frontpage( $post_id );
18
+
19
+ $title = $this->get_custom_field( '_genesis_title', $post_id );
20
+
21
+ /**
22
+ * Generate static placeholder
23
+ */
24
+ if ( $is_static_frontpage ) {
25
+ //* Front page.
26
+ $generated_doctitle_args = array(
27
+ 'page_on_front' => true,
28
+ 'placeholder' => true,
29
+ 'meta' => true,
30
+ 'get_custom_field' => false,
31
+ );
32
+
33
+ $generated_description_args = array(
34
+ 'id' => $post_id,
35
+ 'is_home' => true,
36
+ 'get_custom_field' => true,
37
+ );
38
+ } elseif ( $this->is_blog_page( $post_id ) ) {
39
+ //* Page for posts.
40
+ $generated_doctitle_args = array(
41
+ 'placeholder' => true,
42
+ 'meta' => true,
43
+ 'get_custom_field' => false,
44
+ );
45
+
46
+ $generated_description_args = array(
47
+ 'id' => $post_id,
48
+ 'page_for_posts' => true,
49
+ );
50
+ } else {
51
+ $generated_doctitle_args = array(
52
+ 'placeholder' => true,
53
+ 'meta' => true,
54
+ 'get_custom_field' => false,
55
+ );
56
+
57
+ $generated_description_args = array(
58
+ 'id' => $post_id,
59
+ );
60
+ }
61
+ $generated_doctitle = $this->title( '', '', '', $generated_doctitle_args );
62
+ $generated_description = $this->generate_description_from_id( $generated_description_args );
63
+
64
+ /**
65
+ * Special check for home page.
66
+ *
67
+ * @since 2.3.4
68
+ */
69
+ if ( $is_static_frontpage ) {
70
+ if ( $this->get_option( 'homepage_tagline' ) ) {
71
+ $tit_len_pre = $title ? $title . ' | ' . $this->get_blogdescription() : $generated_doctitle;
72
+ } else {
73
+ $tit_len_pre = $title ?: $generated_doctitle;
74
+ }
75
+ } else {
76
+ /**
77
+ * Separator doesn't matter. Since html_entity_decode is used.
78
+ * Order doesn't matter either. Since it's just used for length calculation.
79
+ *
80
+ * @since 2.3.4
81
+ */
82
+ if ( $this->add_title_additions() ) {
83
+ $tit_len_pre = $title ? $title . ' | ' . $this->get_blogname() : $generated_doctitle;
84
+ } else {
85
+ $tit_len_pre = $title ?: $generated_doctitle;
86
+ }
87
+ }
88
+
89
+ //* Fetch description from option.
90
+ $description = $this->get_custom_field( '_genesis_description' );
91
+
92
+ /**
93
+ * Calculate current description length
94
+ *
95
+ * Reworked.
96
+ * @since 2.3.4
97
+ */
98
+ if ( $is_static_frontpage ) {
99
+ //* The homepage description takes precedence.
100
+ if ( $description ) {
101
+ $desc_len_pre = $this->get_option( 'homepage_description' ) ?: $description;
102
+ } else {
103
+ $desc_len_pre = $this->get_option( 'homepage_description' ) ?: $generated_description;
104
+ }
105
+ } else {
106
+ $desc_len_pre = $description ?: $generated_description;
107
+ }
108
+
109
+ /**
110
+ * Convert to what Google outputs.
111
+ *
112
+ * This will convert e.g. &raquo; to a single length character.
113
+ * @since 2.3.4
114
+ */
115
+ $tit_len_parsed = html_entity_decode( $tit_len_pre );
116
+ $desc_len_parsed = html_entity_decode( $desc_len_pre );
117
+
118
+ /**
119
+ * Generate static placeholder for when title or description is emptied
120
+ *
121
+ * Now within aptly named vars.
122
+ * @since 2.3.4
123
+ */
124
+ $doctitle_placeholder = $generated_doctitle;
125
+ $description_placeholder = $generated_description;
126
+
127
+ //* Fetch Canonical URL.
128
+ $canonical = $this->get_custom_field( '_genesis_canonical_uri' );
129
+ //* Fetch Canonical URL Placeholder.
130
+ $canonical_placeholder = $this->the_url_from_cache( '', $post_id, false, false );
131
+
132
+ //* Fetch image placeholder.
133
+ $image_placeholder = $this->get_image( $post_id, array( 'disallowed' => array( 'postmeta' ) ), false );
134
+
135
+ ?>
136
+ <?php if ( 'above' === $this->inpost_seo_bar || $this->is_option_checked( 'display_seo_bar_metabox' ) ) : ?>
137
+ <p>
138
+ <strong><?php esc_html_e( 'Doing it Right', 'autodescription' ); ?></strong>
139
+ <div>
140
+ <?php $this->post_status( $post_id, 'inpost', true ); ?>
141
+ </div>
142
+ </p>
143
+ <?php endif; ?>
144
+
145
+ <p>
146
+ <label for="autodescription_title"><strong><?php printf( esc_html__( 'Custom %s Title', 'autodescription' ), esc_html( $type ) ); ?></strong>
147
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#3' ); ?>" target="_blank" title="<?php esc_attr_e( 'Recommended Length: 50 to 55 characters', 'autodescription' ); ?>">[?]</a>
148
+ <span class="description tsf-counter">
149
+ <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="autodescription_title_chars">' . (int) mb_strlen( $tit_len_parsed ) . '</span>' ); ?>
150
+ <span class="hide-if-no-js tsf-ajax"></span>
151
+ </span>
152
+ </label>
153
+ </p>
154
+ <p>
155
+ <div id="tsf-title-wrap">
156
+ <input class="large-text" type="text" name="autodescription[_genesis_title]" id="autodescription_title" placeholder="<?php echo esc_attr( $doctitle_placeholder ); ?>" value="<?php echo esc_attr( $this->get_custom_field( '_genesis_title' ) ); ?>" />
157
+ <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
158
+ </div>
159
+ </p>
160
+
161
+ <p>
162
+ <label for="autodescription_description">
163
+ <strong><?php printf( esc_html__( 'Custom %s Description', 'autodescription' ), esc_html( $type ) ); ?></strong>
164
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#1' ); ?>" target="_blank" title="<?php esc_attr_e( 'Recommended Length: 145 to 155 characters', 'autodescription' ); ?>">[?]</a>
165
+ <span class="description tsf-counter">
166
+ <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="autodescription_description_chars">' . (int) mb_strlen( $desc_len_parsed ) . '</span>' ); ?>
167
+ <span class="hide-if-no-js tsf-ajax"></span>
168
+ </span>
169
+ </label>
170
+ </p>
171
+ <p>
172
+ <textarea class="large-text" name="autodescription[_genesis_description]" id="autodescription_description" placeholder="<?php echo esc_attr( $description_placeholder ); ?>" rows="4" cols="4"><?php echo esc_attr( $this->get_custom_field( '_genesis_description' ) ); ?></textarea>
173
+ </p>
174
+
175
+ <p>
176
+ <label for="autodescription_socialimage">
177
+ <strong><?php esc_html_e( 'Custom Social Image URL', 'autodescription' ); ?></strong>
178
+ <a href="<?php echo esc_url( 'https://developers.facebook.com/docs/sharing/best-practices#images' ); ?>" target="_blank" title="<?php printf( esc_attr__( 'Preferred %s Social Image URL location', 'autodescription' ), esc_attr( $type ) ); ?>">[?]</a>
179
+ </label>
180
+ </p>
181
+ <p class="hide-if-no-js">
182
+ <?php
183
+ //* Already escaped.
184
+ echo $this->get_social_image_uploader_form( 'autodescription_socialimage' );
185
+ ?>
186
+ </p>
187
+ <p>
188
+ <input class="large-text" type="text" name="autodescription[_social_image_url]" id="autodescription_socialimage-url" placeholder="<?php echo esc_url( $image_placeholder ); ?>" value="<?php echo esc_url( $this->get_custom_field( '_social_image_url' ) ); ?>" />
189
+ <?php
190
+ /**
191
+ * Insert form element only if JS is active. If JS is inactive, then this will cause it to be emptied on $_POST
192
+ * @TODO use disabled and jQuery.removeprop( 'disabled' )?
193
+ */
194
+ ?>
195
+ <script>
196
+ document.getElementById( 'autodescription_socialimage-url' ).insertAdjacentHTML( 'afterend', '<input type="hidden" name="autodescription[_social_image_id]" id="autodescription_socialimage-id" value="<?php echo absint( $this->get_custom_field( '_social_image_id' ) ); ?>" />' );
197
+ </script>
198
+ </p>
199
+
200
+ <p>
201
+ <label for="autodescription_canonical">
202
+ <strong><?php esc_html_e( 'Custom Canonical URL', 'autodescription' ); ?></strong>
203
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/139066?hl=' . $language ); ?>" target="_blank" title="<?php printf( esc_attr__( 'Preferred %s URL location', 'autodescription' ), esc_attr( $type ) ); ?>">[?]</a>
204
+ </label>
205
+ </p>
206
+ <p>
207
+ <input class="large-text" type="text" name="autodescription[_genesis_canonical_uri]" id="autodescription_canonical" placeholder="<?php echo esc_url( $canonical_placeholder ); ?>" value="<?php echo esc_url( $this->get_custom_field( '_genesis_canonical_uri' ) ); ?>" />
208
+ </p>
209
+
210
+ <p><strong><?php esc_html_e( 'Robots Meta Settings', 'autodescription' ); ?></strong></p>
211
+ <p>
212
+ <label for="autodescription_noindex"><input type="checkbox" name="autodescription[_genesis_noindex]" id="autodescription_noindex" value="1" <?php checked( $this->get_custom_field( '_genesis_noindex' ) ); ?> />
213
+ <?php
214
+ /* translators: 1: Option, 2: Post or Page */
215
+ printf( esc_html__( 'Apply %1$s to this %2$s', 'autodescription' ), $this->code_wrap( 'noindex' ), esc_html( $type ) );
216
+ ?>
217
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/93710?hl=' . $language ); ?>" target="_blank" title="<?php printf( esc_attr__( 'Tell Search Engines not to show this %s in their search results', 'autodescription' ), esc_attr( $type ) ); ?>">[?]</a>
218
+ </label>
219
+
220
+ <br>
221
+
222
+ <label for="autodescription_nofollow"><input type="checkbox" name="autodescription[_genesis_nofollow]" id="autodescription_nofollow" value="1" <?php checked( $this->get_custom_field( '_genesis_nofollow' ) ); ?> />
223
+ <?php
224
+ /* translators: 1: Option, 2: Post or Page */
225
+ printf( esc_html__( 'Apply %1$s to this %2$s', 'autodescription' ), $this->code_wrap( 'nofollow' ), esc_html( $type ) );
226
+ ?>
227
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/96569?hl=' . $language ); ?>" target="_blank" title="<?php printf( esc_attr__( 'Tell Search Engines not to follow links on this %s', 'autodescription' ), esc_attr( $type ) ); ?>">[?]</a>
228
+ </label>
229
+
230
+ <br>
231
+
232
+ <label for="autodescription_noarchive"><input type="checkbox" name="autodescription[_genesis_noarchive]" id="autodescription_noarchive" value="1" <?php checked( $this->get_custom_field( '_genesis_noarchive' ) ); ?> />
233
+ <?php
234
+ /* translators: 1: Option, 2: Post or Page */
235
+ printf( esc_html__( 'Apply %1$s to this %2$s', 'autodescription' ), $this->code_wrap( 'noarchive' ), esc_html( $type ) );
236
+ ?>
237
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/79812?hl=' . $language ); ?>" target="_blank" title="<?php printf( esc_attr__( 'Tell Search Engines not to save a cached copy of this %s', 'autodescription' ), esc_attr( $type ) ); ?>">[?]</a>
238
+ </label>
239
+ </p>
240
+
241
+ <p><strong><?php esc_html_e( 'Local Search Settings', 'autodescription' ); ?></strong></p>
242
+ <p>
243
+ <label for="autodescription_exclude_local_search"><input type="checkbox" name="autodescription[exclude_local_search]" id="autodescription_exclude_local_search" value="1" <?php checked( $this->get_custom_field( 'exclude_local_search' ) ); ?> />
244
+ <?php printf( esc_html__( 'Exclude this %s from local search', 'autodescription' ), esc_html( $type ) ); ?>
245
+ <span title="<?php printf( esc_attr__( 'This excludes this %s from local on-site search results', 'autodescription' ), esc_attr( $type ) ); ?>">[?]</span>
246
+ </label>
247
+ </p>
248
+
249
+ <p>
250
+ <label for="autodescription_redirect">
251
+ <strong><?php esc_html_e( 'Custom 301 Redirect URL', 'autodescription' ); ?></strong>
252
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/93633?hl=' . $language ); ?>" target="_blank" title="<?php esc_attr_e( 'This will force visitors to go to another URL', 'autodescription' ); ?>">[?]</a>
253
+ </label>
254
+ </p>
255
+ <p>
256
+ <input class="large-text" type="text" name="autodescription[redirect]" id="genesis_redirect" value="<?php echo esc_url( $this->get_custom_field( 'redirect' ) ); ?>" />
257
+ </p>
258
+
259
+ <?php if ( 'below' === $this->inpost_seo_bar ) : ?>
260
+ <p>
261
+ <strong><?php esc_html_e( 'Doing it Right', 'autodescription' ); ?></strong>
262
+ <div>
263
+ <?php $this->post_status( $post_id, 'inpost', true ); ?>
264
+ </div>
265
+ </p>
266
+ <?php endif;
267
+ break;
268
+
269
+ case 'the_seo_framework_settings_type_term' :
270
+
271
+ //* Fetch Term ID and taxonomy.
272
+ $term_id = $object->term_id;
273
+ $taxonomy = $object->taxonomy;
274
+
275
+ $data = $this->get_term_data( $object, $term_id );
276
+
277
+ $title = isset( $data['doctitle'] ) ? $data['doctitle'] : '';
278
+ $description = isset( $data['description'] ) ? $data['description'] : '';
279
+ $noindex = isset( $data['noindex'] ) ? $data['noindex'] : '';
280
+ $nofollow = isset( $data['nofollow'] ) ? $data['nofollow'] : '';
281
+ $noarchive = isset( $data['noarchive'] ) ? $data['noarchive'] : '';
282
+
283
+ $generated_doctitle_args = array(
284
+ 'term_id' => $term_id,
285
+ 'taxonomy' => $taxonomy,
286
+ 'placeholder' => true,
287
+ 'get_custom_field' => false,
288
+ );
289
+
290
+ $generated_description_args = array(
291
+ 'id' => $term_id,
292
+ 'taxonomy' => $taxonomy,
293
+ 'get_custom_field' => false,
294
+ );
295
+
296
+ //* Generate title and description.
297
+ $generated_doctitle = $this->title( '', '', '', $generated_doctitle_args );
298
+ $generated_description = $this->generate_description( '', $generated_description_args );
299
+
300
+ $blog_name = $this->get_blogname();
301
+ $add_additions = $this->add_title_additions();
302
+
303
+ /**
304
+ * Separator doesn't matter. Since html_entity_decode is used.
305
+ * Order doesn't matter either. Since it's just used for length calculation.
306
+ *
307
+ * @since 2.3.4
308
+ */
309
+ $doc_pre_rem = $add_additions ? $title . ' | ' . $blog_name : $title;
310
+ $title_len = $title ? $doc_pre_rem : $generated_doctitle;
311
+ $description_len = $description ?: $generated_description;
312
+
313
+ /**
314
+ * Convert to what Google outputs.
315
+ *
316
+ * This will convert e.g. &raquo; to a single length character.
317
+ * @since 2.3.4
318
+ */
319
+ $tit_len_parsed = html_entity_decode( $title_len );
320
+ $desc_len_parsed = html_entity_decode( $description_len );
321
+
322
+ /**
323
+ * Generate static placeholder for when title or description is emptied
324
+ *
325
+ * @since 2.2.4
326
+ */
327
+ $title_placeholder = $generated_doctitle;
328
+ $description_placeholder = $generated_description;
329
+
330
+ ?>
331
+ <h3><?php printf( esc_html__( '%s SEO Settings', 'autodescription' ), esc_html( $type ) ); ?></h3>
332
+
333
+ <table class="form-table">
334
+ <tbody>
335
+ <?php if ( 'above' === $this->inpost_seo_bar || $this->is_option_checked( 'display_seo_bar_metabox' ) ) : ?>
336
+ <tr>
337
+ <th scope="row" valign="top"><?php esc_html_e( 'Doing it Right', 'autodescription' ); ?></th>
338
+ <td>
339
+ <?php $this->post_status( $term_id, $taxonomy, true ); ?>
340
+ </td>
341
+ </tr>
342
+ <?php endif; ?>
343
+
344
+ <tr class="form-field">
345
+ <th scope="row" valign="top">
346
+ <label for="autodescription-meta[doctitle]">
347
+ <strong><?php printf( esc_html__( '%s Title', 'autodescription' ), esc_html( $type ) ); ?></strong>
348
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#3' ); ?>" target="_blank" title="<?php esc_attr_e( 'Recommended Length: 50 to 55 characters', 'autodescription' ); ?>">[?]</a>
349
+ </label>
350
+ </th>
351
+ <td>
352
+ <div id="tsf-title-wrap">
353
+ <input name="autodescription-meta[doctitle]" id="autodescription-meta[doctitle]" type="text" placeholder="<?php echo esc_attr( $title_placeholder ) ?>" value="<?php echo esc_attr( $title ); ?>" size="40" />
354
+ <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
355
+ </div>
356
+ <p class="description tsf-counter">
357
+ <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="autodescription-meta[doctitle]_chars">' . esc_html( mb_strlen( $tit_len_parsed ) ) . '</span>' ); ?>
358
+ <span class="hide-if-no-js tsf-ajax"></span>
359
+ </p>
360
+ </td>
361
+ </tr>
362
+
363
+ <tr class="form-field">
364
+ <th scope="row" valign="top">
365
+ <label for="autodescription-meta[description]">
366
+ <strong><?php printf( esc_html__( '%s Meta Description', 'autodescription' ), esc_html( $type ) ); ?></strong>
367
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#1' ); ?>" target="_blank" title="<?php esc_attr_e( 'Recommended Length: 145 to 155 characters', 'autodescription' ); ?>">[?]</a>
368
+ </label>
369
+ </th>
370
+ <td>
371
+ <textarea name="autodescription-meta[description]" id="autodescription-meta[description]" placeholder="<?php echo esc_attr( $description_placeholder ); ?>" rows="5" cols="50" class="large-text"><?php echo esc_html( $description ); ?></textarea>
372
+ <p class="description tsf-counter">
373
+ <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="autodescription-meta[description]_chars">' . esc_html( mb_strlen( $desc_len_parsed ) ) . '</span>' ); ?>
374
+ <span class="hide-if-no-js tsf-ajax"></span>
375
+ </p>
376
+ </td>
377
+ </tr>
378
+
379
+ <tr>
380
+ <th scope="row" valign="top"><?php esc_html_e( 'Robots Meta Settings', 'autodescription' ); ?></th>
381
+ <td>
382
+ <label for="autodescription-meta[noindex]"><input name="autodescription-meta[noindex]" id="autodescription-meta[noindex]" type="checkbox" value="1" <?php checked( $noindex ); ?> />
383
+ <?php printf( esc_html__( 'Apply %s to this term?', 'autodescription' ), $this->code_wrap( 'noindex' ) ); ?>
384
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/93710?hl=' . $language ); ?>" target="_blank" title="<?php printf( esc_attr__( 'Tell Search Engines not to show this page in their search results', 'autodescription' ) ); ?>">[?]</a>
385
+ </label>
386
+
387
+ <br>
388
+
389
+ <label for="autodescription-meta[nofollow]"><input name="autodescription-meta[nofollow]" id="autodescription-meta[nofollow]" type="checkbox" value="1" <?php checked( $nofollow ); ?> />
390
+ <?php printf( esc_html__( 'Apply %s to this term?', 'autodescription' ), $this->code_wrap( 'nofollow' ) ); ?>
391
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/96569?hl=' . $language ); ?>" target="_blank" title="<?php printf( esc_attr__( 'Tell Search Engines not to follow links on this page', 'autodescription' ) ); ?>">[?]</a>
392
+ </label>
393
+
394
+ <br>
395
+
396
+ <label for="autodescription-meta[noarchive]"><input name="autodescription-meta[noarchive]" id="autodescription-meta[noarchive]" type="checkbox" value="1" <?php checked( $noarchive ); ?> />
397
+ <?php printf( esc_html__( 'Apply %s to this term?', 'autodescription' ), $this->code_wrap( 'noarchive' ) ); ?>
398
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/79812?hl=' . $language ); ?>" target="_blank" title="<?php printf( esc_attr__( 'Tell Search Engines not to save a cached copy of this page', 'autodescription' ) ); ?>">[?]</a>
399
+ </label>
400
+
401
+ <?php // Saved flag, if set then it won't fetch for Genesis meta anymore ?>
402
+ <label class="hidden" for="autodescription-meta[saved_flag]">
403
+ <input name="autodescription-meta[saved_flag]" id="autodescription-meta[saved_flag]" type="checkbox" value="1" checked='checked' />
404
+ </label>
405
+ </td>
406
+ </tr>
407
+
408
+ <?php if ( 'below' === $this->inpost_seo_bar ) : ?>
409
+ <tr>
410
+ <th scope="row" valign="top"><?php esc_html_e( 'Doing it Right', 'autodescription' ); ?></th>
411
+ <td>
412
+ <?php $this->post_status( $term_id, $taxonomy, true ); ?>
413
+ </td>
414
+ </tr>
415
+ <?php endif; ?>
416
+ </tbody>
417
+ </table>
418
+ <?php
419
+ break;
420
+
421
+ default :
422
+ break;
423
+ endswitch;
inc/views/metaboxes/description-metabox.php CHANGED
@@ -19,7 +19,7 @@ switch ( $instance ) :
19
  $excerpt = $this->escape_description( __( 'This is an example description...', 'autodescription' ) );
20
 
21
  //* Put it together.
22
- $example = '<span id="tsf-description-additions-js">'
23
  . $page_title
24
  . '<span id="tsf-on-blogname-js">' . " $on " . $blogname . '</span>'
25
  . '<span id="autodescription-descsep-js">' . " $sep " . '</span>'
@@ -55,23 +55,23 @@ switch ( $instance ) :
55
  * @since 2.6.0
56
  *
57
  * @param array $default_tabs { 'id' = The identifier =>
58
- * array(
59
- * 'name' => The name
60
- * 'callback' => The callback function, use array for method calling (accepts $this, but isn't used here for optimization purposes)
61
- * 'dashicon' => Desired dashicon
62
- * )
63
  * }
64
  */
65
  $default_tabs = array(
66
  'general' => array(
67
- 'name' => esc_html__( 'General', 'autodescription' ),
68
- 'callback' => array( $this, 'description_metabox_general_tab' ),
69
- 'dashicon' => 'admin-generic',
70
  ),
71
  'additions' => array(
72
- 'name' => esc_html__( 'Additions', 'autodescription' ),
73
- 'callback' => array( $this, 'description_metabox_additions_tab' ),
74
- 'dashicon' => 'plus',
75
  ),
76
  );
77
 
@@ -95,15 +95,15 @@ switch ( $instance ) :
95
  $sep_option = $this->get_option( 'description_separator' );
96
  $sep_option = $sep_option ? $sep_option : 'pipe';
97
 
98
- $recommended = ' class="tsf-recommended" title="' . esc_attr__( 'Recommended', 'autodescription' ) . '"';
99
-
100
  ?>
101
  <fieldset>
102
  <legend><h4><?php esc_html_e( 'Description Excerpt Separator', 'autodescription' ); ?></h4></legend>
103
  <p id="tsf-description-separator" class="tsf-fields">
104
  <?php foreach ( $description_separator as $name => $html ) { ?>
105
- <input type="radio" name="<?php $this->field_name( 'description_separator' ); ?>" id="<?php $this->field_id( 'description_separator' . $name ); ?>" value="<?php echo $name ?>" <?php checked( $sep_option, $name ); ?> />
106
- <label for="<?php $this->field_id( 'description_separator' . $name ); ?>" <?php echo ( 'pipe' === $name || 'dash' === $name ) ? $recommended : ''; ?>><?php echo $html ?></label>
 
 
107
  <?php } ?>
108
  </p>
109
  <span class="description"><?php esc_html_e( 'If the Automated Description consists of two parts (title and excerpt), then the separator will go in-between them.', 'autodescription' ); ?></span>
19
  $excerpt = $this->escape_description( __( 'This is an example description...', 'autodescription' ) );
20
 
21
  //* Put it together.
22
+ $example = '<span id="tsf-description-additions-js">'
23
  . $page_title
24
  . '<span id="tsf-on-blogname-js">' . " $on " . $blogname . '</span>'
25
  . '<span id="autodescription-descsep-js">' . " $sep " . '</span>'
55
  * @since 2.6.0
56
  *
57
  * @param array $default_tabs { 'id' = The identifier =>
58
+ * array(
59
+ * 'name' => The name
60
+ * 'callback' => The callback function, use array for method calling
61
+ * 'dashicon' => Desired dashicon
62
+ * )
63
  * }
64
  */
65
  $default_tabs = array(
66
  'general' => array(
67
+ 'name' => esc_html__( 'General', 'autodescription' ),
68
+ 'callback' => array( $this, 'description_metabox_general_tab' ),
69
+ 'dashicon' => 'admin-generic',
70
  ),
71
  'additions' => array(
72
+ 'name' => esc_html__( 'Additions', 'autodescription' ),
73
+ 'callback' => array( $this, 'description_metabox_additions_tab' ),
74
+ 'dashicon' => 'plus',
75
  ),
76
  );
77
 
95
  $sep_option = $this->get_option( 'description_separator' );
96
  $sep_option = $sep_option ? $sep_option : 'pipe';
97
 
 
 
98
  ?>
99
  <fieldset>
100
  <legend><h4><?php esc_html_e( 'Description Excerpt Separator', 'autodescription' ); ?></h4></legend>
101
  <p id="tsf-description-separator" class="tsf-fields">
102
  <?php foreach ( $description_separator as $name => $html ) { ?>
103
+ <input type="radio" name="<?php $this->field_name( 'description_separator' ); ?>" id="<?php $this->field_id( 'description_separator' . $name ); ?>" value="<?php echo esc_attr( $name ); ?>" <?php checked( $sep_option, $name ); ?> />
104
+ <label for="<?php $this->field_id( 'description_separator' . $name ); ?>">
105
+ <?php echo $html; ?>
106
+ </label>
107
  <?php } ?>
108
  </p>
109
  <span class="description"><?php esc_html_e( 'If the Automated Description consists of two parts (title and excerpt), then the separator will go in-between them.', 'autodescription' ); ?></span>
inc/views/metaboxes/general-metabox.php ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) and $_this = the_seo_framework_class() and $this instanceof $_this or die;
4
+
5
+ //* Fetch the required instance within this file.
6
+ $instance = $this->get_view_instance( 'the_seo_framework_general_metabox', $instance );
7
+
8
+ switch ( $instance ) :
9
+ case 'the_seo_framework_general_metabox_main' :
10
+
11
+ $default_tabs = array(
12
+ // 'general' => array(
13
+ // 'name' => __( 'General', 'autodescription' ),
14
+ // 'callback' => array( $this, 'general_metabox_general_tab' ),
15
+ // 'dashicon' => 'admin-generic',
16
+ // ),
17
+ 'performance' => array(
18
+ 'name' => __( 'Performance', 'autodescription' ),
19
+ 'callback' => array( $this, 'general_metabox_performance_tab' ),
20
+ 'dashicon' => 'performance',
21
+ ),
22
+ 'layout' => array(
23
+ 'name' => __( 'Layout', 'autodescription' ),
24
+ 'callback' => array( $this, 'general_metabox_layout_tab' ),
25
+ 'dashicon' => 'screenoptions',
26
+ ),
27
+ 'canonical' => array(
28
+ 'name' => __( 'Canonical', 'autodescription' ),
29
+ 'callback' => array( $this, 'general_metabox_canonical_tab' ),
30
+ 'dashicon' => 'external',
31
+ ),
32
+ );
33
+
34
+ /**
35
+ * Applies filters `the_seo_framework_general_settings_tabs` : Array
36
+ * Used to extend or minimize General Settings tabs
37
+ * @since 2.8.0
38
+ */
39
+ $defaults = (array) apply_filters( 'the_seo_framework_general_settings_tabs', $default_tabs, $args );
40
+
41
+ $tabs = wp_parse_args( $args, $defaults );
42
+
43
+ $this->nav_tab_wrapper( 'general', $tabs, '2.8.0' );
44
+ break;
45
+
46
+ case 'the_seo_framework_general_metabox_general' :
47
+ echo 'Nothing to see here yet.';
48
+ break;
49
+
50
+ case 'the_seo_framework_general_metabox_performance' :
51
+
52
+ ?><h4><?php esc_html_e( 'Performance Settings', 'autodescription' ); ?></h4><?php
53
+ $this->description( __( 'In order to improve performance, generated SEO output can be stored in the database as transient cache.', 'autodescription' ) );
54
+ $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' ) );
55
+
56
+ ?>
57
+ <hr>
58
+
59
+ <h4><?php esc_html_e( 'Transient Cache Settings', 'autodescription' ); ?></h4>
60
+ <?php
61
+ $this->wrap_fields(
62
+ array(
63
+ $this->make_checkbox(
64
+ 'cache_meta_description',
65
+ esc_html__( 'Enable automated description output cache?', 'autodescription' )
66
+ . ' ' . $this->make_info( __( 'Description generation can use a lot of server resources when it reads the page content.', 'autodescription' ), '', false ),
67
+ '',
68
+ false
69
+ ),
70
+ $this->make_checkbox(
71
+ 'cache_meta_schema',
72
+ esc_html__( 'Enable automated Schema output cache?', 'autodescription' )
73
+ . ' ' . $this->make_info( __( 'Schema.org output generally makes multiple calls to the database.', 'autodescription' ), '', false ),
74
+ '',
75
+ false
76
+ ),
77
+ $this->make_checkbox(
78
+ 'cache_sitemap',
79
+ esc_html__( 'Enable sitemap generation cache?', 'autodescription' )
80
+ . ' ' . $this->make_info( __( 'Generating the sitemap can use a lot of server resources.', 'autodescription' ), '', false ),
81
+ '',
82
+ false
83
+ ),
84
+ ),
85
+ true
86
+ );
87
+
88
+ if ( wp_using_ext_object_cache() ) :
89
+ ?>
90
+ <hr>
91
+
92
+ <h4><?php esc_html_e( 'Object Cache Settings', 'autodescription' ); ?></h4>
93
+ <?php
94
+
95
+ $this->wrap_fields(
96
+ $this->make_checkbox(
97
+ 'cache_object',
98
+ esc_html__( 'Enable object cache?', 'autodescription' )
99
+ . ' ' . $this->make_info( __( 'Object cache generally works faster than transient cache', 'autodescription' ), '', false ),
100
+ esc_html__( 'An object cache handler has been detected. If you enable this option, you might wish to disable description and Schema transient caching.', 'autodescription' ),
101
+ false
102
+ ),
103
+ true
104
+ );
105
+ endif;
106
+ break;
107
+
108
+ case 'the_seo_framework_general_metabox_layout' :
109
+ ?><h4><?php esc_html_e( 'Administrative Layout Settings', 'autodescription' ); ?></h4><?php
110
+ $this->description( __( 'SEO hints can be visually displayed throughout the dashboard.', 'autodescription' ) );
111
+
112
+ ?>
113
+ <hr>
114
+
115
+ <h4><?php esc_html_e( 'SEO Bar Settings', 'autodescription' ); ?></h4>
116
+ <?php
117
+ $this->wrap_fields(
118
+ array(
119
+ $this->make_checkbox(
120
+ 'display_seo_bar_tables',
121
+ esc_html__( 'Display the SEO Bar in overview tables?', 'autodescription' ),
122
+ '',
123
+ false
124
+ ),
125
+ $this->make_checkbox(
126
+ 'display_seo_bar_metabox',
127
+ esc_html__( 'Display the SEO Bar in the SEO Settings metabox?', 'autodescription' ),
128
+ '',
129
+ false
130
+ ),
131
+ ),
132
+ true
133
+ );
134
+ break;
135
+
136
+ case 'the_seo_framework_general_metabox_canonical' :
137
+
138
+ ?><h4><?php esc_html_e( 'Canonical URL Settings', 'autodescription' ); ?></h4><?php
139
+ $this->description( __( 'The canonical URL meta tag urges Search Engines to go to the outputted URL.', 'autodescription' ) );
140
+ $this->description( __( 'If the canonical URL meta tag represents the visited page, then the Search Engine will crawl the visited page. Otherwise, the Search Engine might go to the outputted URL.', 'autodescription' ) );
141
+ $this->description( __( 'Only adjust these options if you are aware of its SEO effects.', 'autodescription' ) );
142
+ ?>
143
+ <hr>
144
+
145
+ <p>
146
+ <h4><?php esc_html_e( 'Scheme Settings', 'autodescription' ); ?></h4>
147
+ <?php
148
+ $this->description( __( 'If your website is accessible on both HTTP as HTTPS, set this to HTTPS in order to prevent duplicate content.', 'autodescription' ) );
149
+ $this->description( __( 'Otherwise, automatic detection is recommended.', 'autodescription' ) );
150
+ ?>
151
+ <label for="<?php $this->field_id( 'canonical_scheme' ); ?>"><?php echo esc_html_x( 'Preferred canonical URL scheme:', '= Detect Automatically, HTTPS, HTTP', 'autodescription' ); ?></label>
152
+ <select name="<?php $this->field_name( 'canonical_scheme' ); ?>" id="<?php $this->field_id( 'canonical_scheme' ); ?>">
153
+ <?php
154
+ $scheme_types = (array) apply_filters(
155
+ 'the_seo_framework_canonical_scheme_types',
156
+ array(
157
+ 'automatic' => __( 'Detect automatically', 'autodescription' ),
158
+ 'http' => 'HTTP',
159
+ 'https' => 'HTTPS',
160
+ )
161
+ );
162
+ foreach ( $scheme_types as $value => $name )
163
+ echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->get_field_value( 'canonical_scheme' ), esc_attr( $value ), false ) . '>' . esc_html( $name ) . '</option>' . "\n";
164
+ ?>
165
+ </select>
166
+ </p>
167
+
168
+ <hr>
169
+
170
+ <h4><?php esc_html_e( 'Link Relationship Settings', 'autodescription' ); ?></h4><?php
171
+ $this->description( __( 'Some Search Engines look for relations between the content of your pages. If you have multiple pages for a single Post or Page, or have archives indexed, this option will help Search Engines look for the right page to display in the Search Results.', 'autodescription' ) );
172
+ $this->description( __( "It's recommended to turn this option on for better SEO consistency and to prevent duplicate content errors.", 'autodescription' ) );
173
+
174
+ /* translators: %s = <code>rel</code> */
175
+ $prev_next_posts_label = sprintf( esc_html__( 'Add %s link tags to Posts and Pages?', 'autodescription' ), $this->code_wrap( 'rel' ) );
176
+ $prev_next_posts_checkbox = $this->make_checkbox( 'prev_next_posts', $prev_next_posts_label, '', false );
177
+
178
+ /* translators: %s = <code>rel</code> */
179
+ $prev_next_archives_label = sprintf( esc_html__( 'Add %s link tags to Archives?', 'autodescription' ), $this->code_wrap( 'rel' ) );
180
+ $prev_next_archives_checkbox = $this->make_checkbox( 'prev_next_archives', $prev_next_archives_label, '', false );
181
+
182
+ /* translators: %s = <code>rel</code> */
183
+ $prev_next_frontpage_label = sprintf( esc_html__( 'Add %s link tags to the Home Page?', 'autodescription' ), $this->code_wrap( 'rel' ) );
184
+ $prev_next_frontpage_checkbox = $this->make_checkbox( 'prev_next_frontpage', $prev_next_frontpage_label, '', false );
185
+
186
+ //* Echo checkboxes.
187
+ $this->wrap_fields( $prev_next_posts_checkbox . $prev_next_archives_checkbox . $prev_next_frontpage_checkbox, true );
188
+ break;
189
+
190
+ default :
191
+ break;
192
+ endswitch;
inc/views/metaboxes/homepage-metabox.php CHANGED
@@ -10,7 +10,9 @@ switch ( $instance ) :
10
 
11
  $this->description( __( 'These settings will take precedence over the settings set within the Home Page edit screen, if any.', 'autodescription' ) );
12
 
13
- ?><hr><?php
 
 
14
 
15
  /**
16
  * Parse tabs content.
@@ -18,28 +20,28 @@ switch ( $instance ) :
18
  * @since 2.6.0
19
  *
20
  * @param array $default_tabs { 'id' = The identifier =>
21
- * array(
22
- * 'name' => The name
23
- * 'callback' => The callback function, use array for method calling (accepts $this, but isn't used here for optimization purposes)
24
- * 'dashicon' => Desired dashicon
25
- * )
26
  * }
27
  */
28
  $default_tabs = array(
29
  'general' => array(
30
- 'name' => __( 'General', 'autodescription' ),
31
- 'callback' => array( $this, 'homepage_metabox_general_tab' ),
32
- 'dashicon' => 'admin-generic',
33
  ),
34
  'additions' => array(
35
- 'name' => __( 'Additions', 'autodescription' ),
36
- 'callback' => array( $this, 'homepage_metabox_additions_tab' ),
37
- 'dashicon' => 'plus',
38
  ),
39
  'robots' => array(
40
- 'name' => __( 'Robots', 'autodescription' ),
41
- 'callback' => array( $this, 'homepage_metabox_robots_tab' ),
42
- 'dashicon' => 'visibility',
43
  ),
44
  );
45
 
@@ -59,53 +61,23 @@ switch ( $instance ) :
59
 
60
  $language = $this->google_language();
61
 
62
- $page_on_front = $this->has_page_on_front();
63
- $home_description_frompost = false;
64
-
65
- $description_from_post_message = '';
66
- $title_from_post_message = '';
67
 
68
  $title_i18n = esc_html__( 'Title', 'autodescription' );
69
  $description_i18n = esc_html__( 'Description', 'autodescription' );
70
  $home_page_i18n = esc_html__( 'Home Page', 'autodescription' );
71
 
72
  $home_id = $this->get_the_front_page_ID();
73
- $home_title = $this->escape_title( $this->get_option( 'homepage_title' ) );
74
- $blog_description = $this->get_blogdescription();
75
-
76
- /**
77
- * Home Page Tagline settings.
78
- * @since 2.3.8
79
- *
80
- * @param string $home_tagline The tagline option.
81
- * @param string $home_tagline_placeholder The option placeholder. Always defaults to description.
82
- * @param string|void $home_tagline_value The tagline input value.
83
- * @param string $blog_description Override blog description with option if applicable.
84
- */
85
- $home_tagline = $this->get_field_value( 'homepage_title_tagline' );
86
- $home_tagline_placeholder = $blog_description;
87
- $home_tagline_value = $home_tagline ? $home_tagline : '';
88
- $blog_description = $home_tagline_value ? $home_tagline_value : $blog_description;
89
 
90
  /**
91
  * Create a placeholder for when there's no custom HomePage title found.
92
  * @since 2.2.4
93
  */
94
  $home_title_args = $this->generate_home_title( true, '', '', true, false );
95
- if ( $this->home_page_add_title_tagline() )
96
  $home_title_placeholder = $this->process_title_additions( $home_title_args['blogname'], $home_title_args['title'], $home_title_args['seplocation'] );
97
- else
98
  $home_title_placeholder = $home_title_args['title'];
99
-
100
- /**
101
- * If the home title is fetched from the post, notify about that instead.
102
- * @since 2.2.4
103
- *
104
- * Nesting often used translations
105
- */
106
- if ( empty( $home_title ) && $page_on_front && $this->get_custom_field( '_genesis_title', $home_id ) ) {
107
- /* translators: 1: Option, 2: Page SEO Settings, 3: Home Page */
108
- $title_from_post_message = sprintf( __( 'Note: The %1$s is fetched from the %2$s on the %3$s.', 'autodescription' ), $title_i18n, __( 'Page SEO Settings', 'autodescription' ), $home_page_i18n );
109
  }
110
 
111
  /**
@@ -113,7 +85,7 @@ switch ( $instance ) :
113
  *
114
  * @since 2.3.4
115
  */
116
- if ( $home_title ) {
117
  $home_title_args = $this->generate_home_title();
118
  $tit_len_pre = $this->process_title_additions( $home_title_args['title'], $home_title_args['blogname'], $home_title_args['seplocation'] );
119
  } else {
@@ -121,10 +93,7 @@ switch ( $instance ) :
121
  }
122
 
123
  //* Fetch the description from the home page.
124
- $frompost_description = $page_on_front ? $this->get_custom_field( '_genesis_description', $home_id ) : '';
125
-
126
- //* Fetch the HomePage Description option.
127
- $home_description = $this->get_field_value( 'homepage_description' );
128
 
129
  /**
130
  * Create a placeholder.
@@ -136,7 +105,7 @@ switch ( $instance ) :
136
  $description_args = array(
137
  'id' => $home_id,
138
  'is_home' => true,
139
- 'get_custom_field' => false
140
  );
141
 
142
  $description_placeholder = $this->generate_description( '', $description_args );
@@ -146,12 +115,16 @@ switch ( $instance ) :
146
  * Checks if the home is blog, the Home Page Metabox description and
147
  * the frompost description.
148
  * @since 2.3.4
 
 
149
  */
150
- if ( empty( $home_description ) && $page_on_front && $frompost_description )
151
  $home_description_frompost = true;
 
 
 
152
 
153
  /**
154
- *
155
  * If the HomePage Description empty, it will check for the InPost
156
  * Description set on the Home Page. And it will set the InPost
157
  * Description as placeholder.
@@ -167,7 +140,7 @@ switch ( $instance ) :
167
  $description_from_post_message = sprintf( __( 'Note: The %1$s is fetched from the %2$s on the %3$s.', 'autodescription' ), $description_i18n, $page_seo_settings_i18n, $home_page_i18n );
168
  }
169
 
170
- $desc_len_pre = $home_description ? $home_description : $description_placeholder;
171
 
172
  /**
173
  * Convert to what Google outputs.
@@ -176,7 +149,7 @@ switch ( $instance ) :
176
  * @since 2.3.4
177
  */
178
  $tit_len = html_entity_decode( $this->escape_title( $tit_len_pre ) );
179
- $desc_len = html_entity_decode( $this->escape_title( $desc_len_pre ) );
180
 
181
  ?>
182
  <p>
@@ -185,7 +158,7 @@ switch ( $instance ) :
185
  </label>
186
  </p>
187
  <p>
188
- <input type="text" name="<?php $this->field_name( 'homepage_title_tagline' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_title_tagline' ); ?>" placeholder="<?php echo $home_tagline_placeholder ?>" value="<?php echo esc_attr( $home_tagline_value ); ?>" />
189
  </p>
190
 
191
  <hr>
@@ -195,18 +168,48 @@ switch ( $instance ) :
195
  <strong><?php printf( esc_html__( 'Custom %s Title', 'autodescription' ), $home_page_i18n ); ?></strong>
196
  <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#3' ); ?>" target="_blank" title="<?php esc_attr_e( 'Recommended Length: 50 to 55 characters', 'autodescription' ) ?>">[?]</a>
197
  <span class="description tsf-counter">
198
- <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="' . $this->field_id( 'homepage_title', false ) . '_chars">'. mb_strlen( $tit_len ) .'</span>' ); ?>
199
  <span class="hide-if-no-js tsf-ajax"></span>
200
  </span>
201
  </label>
202
  </p>
203
  <p id="tsf-title-wrap">
204
- <input type="text" name="<?php $this->field_name( 'homepage_title' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_title' ); ?>" placeholder="<?php echo esc_attr( $home_title_placeholder ); ?>" value="<?php echo esc_attr( $home_title ); ?>" />
205
  <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
206
  </p>
207
  <?php
208
- if ( $title_from_post_message ) {
209
- $this->description( $title_from_post_message );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  }
211
  ?>
212
  <hr>
@@ -214,21 +217,39 @@ switch ( $instance ) :
214
  <p>
215
  <label for="<?php $this->field_id( 'homepage_description' ); ?>" class="tsf-toblock">
216
  <strong><?php printf( esc_html__( 'Custom %s Description', 'autodescription' ), $home_page_i18n ); ?></strong>
217
- <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#1' ); ?>" target="_blank" title="<?php _e( 'Recommended Length: 145 to 155 characters', 'autodescription' ) ?>">[?]</a>
218
  <span class="description tsf-counter">
219
- <?php printf( __( 'Characters Used: %s', 'autodescription' ), '<span id="' . $this->field_id( 'homepage_description', false ) . '_chars">'. mb_strlen( $desc_len ) .'</span>' ); ?>
220
  <span class="hide-if-no-js tsf-ajax"></span>
221
  </span>
222
  </label>
223
  </p>
224
  <p>
225
- <textarea name="<?php $this->field_name( 'homepage_description' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_description' ); ?>" rows="3" cols="70" placeholder="<?php echo $description_placeholder ?>"><?php echo esc_textarea( $home_description ); ?></textarea>
226
  </p>
227
  <?php
228
  $this->description( __( 'The meta description can be used to determine the text used under the title on Search Engine results pages.', 'autodescription' ) );
229
 
230
  if ( $description_from_post_message ) {
231
- echo '<p class="description">' . esc_html( $description_from_post_message ) . '</p>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  }
233
  break;
234
 
@@ -240,8 +261,8 @@ switch ( $instance ) :
240
  $blogname = $title_args['blogname'];
241
  $sep = $this->get_separator( 'title' );
242
 
243
- $example_left = '<em><span class="custom-title-js">' . $title . '</span><span class="tsf-custom-blogname-js"><span class="autodescription-sep-js"> ' . $sep . ' </span><span class="tsf-custom-tagline-js">' . $blogname . '</span></span></span></em>';
244
- $example_right = '<em><span class="tsf-custom-blogname-js"><span class="tsf-custom-tagline-js">' . $blogname . '</span><span class="autodescription-sep-js"> ' . $sep . ' </span></span><span class="custom-title-js">' . $title . '</span></em>';
245
 
246
  $home_page_i18n = esc_html__( 'Home Page', 'autodescription' );
247
 
@@ -255,14 +276,20 @@ switch ( $instance ) :
255
  <input type="radio" name="<?php $this->field_name( 'home_title_location' ); ?>" id="<?php $this->field_id( 'home_title_location_left' ); ?>" value="left" <?php checked( $this->get_field_value( 'home_title_location' ), 'left' ); ?> />
256
  <label for="<?php $this->field_id( 'home_title_location_left' ); ?>">
257
  <span><?php esc_html_e( 'Left:', 'autodescription' ); ?></span>
258
- <?php echo ( $example_left ) ? $this->code_wrap_noesc( $example_left ) : ''; ?>
 
 
 
259
  </label>
260
  </span>
261
  <span class="tsf-toblock">
262
  <input type="radio" name="<?php $this->field_name( 'home_title_location' ); ?>" id="<?php $this->field_id( 'home_title_location_right' ); ?>" value="right" <?php checked( $this->get_field_value( 'home_title_location' ), 'right' ); ?> />
263
  <label for="<?php $this->field_id( 'home_title_location_right' ); ?>">
264
  <span><?php esc_html_e( 'Right:', 'autodescription' ); ?></span>
265
- <?php echo $example_right ? $this->code_wrap_noesc( $example_right ) : ''; ?>
 
 
 
266
  </label>
267
  </span>
268
  </p>
@@ -302,7 +329,9 @@ switch ( $instance ) :
302
  $checked_home = ' - <a href="' . esc_url( admin_url( 'post.php?post=' . $home_id . '&action=edit#tsf-inpost-box' ) ) . '" target="_blank" class="attention" title="' . esc_attr__( 'View Home Page Settings', 'autodescription' ) . '" >' . esc_html__( 'Checked in Page', 'autodescription' ) . '</a>';
303
  }
304
 
305
- ?><h4><?php esc_html_e( 'Home Page Robots Meta Settings', 'autodescription' ); ?></h4><?php
 
 
306
 
307
  $noindex_note = $noindex_post ? $checked_home : '';
308
  $nofollow_note = $nofollow_post ? $checked_home : '';
10
 
11
  $this->description( __( 'These settings will take precedence over the settings set within the Home Page edit screen, if any.', 'autodescription' ) );
12
 
13
+ ?>
14
+ <hr>
15
+ <?php
16
 
17
  /**
18
  * Parse tabs content.
20
  * @since 2.6.0
21
  *
22
  * @param array $default_tabs { 'id' = The identifier =>
23
+ * array(
24
+ * 'name' => The name
25
+ * 'callback' => The callback function, use array for method calling
26
+ * 'dashicon' => Desired dashicon
27
+ * )
28
  * }
29
  */
30
  $default_tabs = array(
31
  'general' => array(
32
+ 'name' => __( 'General', 'autodescription' ),
33
+ 'callback' => array( $this, 'homepage_metabox_general_tab' ),
34
+ 'dashicon' => 'admin-generic',
35
  ),
36
  'additions' => array(
37
+ 'name' => __( 'Additions', 'autodescription' ),
38
+ 'callback' => array( $this, 'homepage_metabox_additions_tab' ),
39
+ 'dashicon' => 'plus',
40
  ),
41
  'robots' => array(
42
+ 'name' => __( 'Robots', 'autodescription' ),
43
+ 'callback' => array( $this, 'homepage_metabox_robots_tab' ),
44
+ 'dashicon' => 'visibility',
45
  ),
46
  );
47
 
61
 
62
  $language = $this->google_language();
63
 
64
+ $description_from_post_message = $title_from_post_message = '';
 
 
 
 
65
 
66
  $title_i18n = esc_html__( 'Title', 'autodescription' );
67
  $description_i18n = esc_html__( 'Description', 'autodescription' );
68
  $home_page_i18n = esc_html__( 'Home Page', 'autodescription' );
69
 
70
  $home_id = $this->get_the_front_page_ID();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
  /**
73
  * Create a placeholder for when there's no custom HomePage title found.
74
  * @since 2.2.4
75
  */
76
  $home_title_args = $this->generate_home_title( true, '', '', true, false );
77
+ if ( $this->home_page_add_title_tagline() ) {
78
  $home_title_placeholder = $this->process_title_additions( $home_title_args['blogname'], $home_title_args['title'], $home_title_args['seplocation'] );
79
+ } else {
80
  $home_title_placeholder = $home_title_args['title'];
 
 
 
 
 
 
 
 
 
 
81
  }
82
 
83
  /**
85
  *
86
  * @since 2.3.4
87
  */
88
+ if ( $this->get_option( 'homepage_title' ) ) {
89
  $home_title_args = $this->generate_home_title();
90
  $tit_len_pre = $this->process_title_additions( $home_title_args['title'], $home_title_args['blogname'], $home_title_args['seplocation'] );
91
  } else {
93
  }
94
 
95
  //* Fetch the description from the home page.
96
+ $frompost_description = $this->has_page_on_front() ? $this->get_custom_field( '_genesis_description', $home_id ) : '';
 
 
 
97
 
98
  /**
99
  * Create a placeholder.
105
  $description_args = array(
106
  'id' => $home_id,
107
  'is_home' => true,
108
+ 'get_custom_field' => false,
109
  );
110
 
111
  $description_placeholder = $this->generate_description( '', $description_args );
115
  * Checks if the home is blog, the Home Page Metabox description and
116
  * the frompost description.
117
  * @since 2.3.4
118
+ *
119
+ * @TODO make function.
120
  */
121
+ if ( ! $this->get_field_value( 'homepage_description' ) && $this->has_page_on_front() && $frompost_description ) {
122
  $home_description_frompost = true;
123
+ } else {
124
+ $home_description_frompost = false;
125
+ }
126
 
127
  /**
 
128
  * If the HomePage Description empty, it will check for the InPost
129
  * Description set on the Home Page. And it will set the InPost
130
  * Description as placeholder.
140
  $description_from_post_message = sprintf( __( 'Note: The %1$s is fetched from the %2$s on the %3$s.', 'autodescription' ), $description_i18n, $page_seo_settings_i18n, $home_page_i18n );
141
  }
142
 
143
+ $desc_len_pre = $this->get_field_value( 'homepage_description' ) ?: $description_placeholder;
144
 
145
  /**
146
  * Convert to what Google outputs.
149
  * @since 2.3.4
150
  */
151
  $tit_len = html_entity_decode( $this->escape_title( $tit_len_pre ) );
152
+ $desc_len = html_entity_decode( $this->escape_description( $desc_len_pre ) );
153
 
154
  ?>
155
  <p>
158
  </label>
159
  </p>
160
  <p>
161
+ <input type="text" name="<?php $this->field_name( 'homepage_title_tagline' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_title_tagline' ); ?>" placeholder="<?php echo esc_attr( $this->escape_title( $this->get_blogdescription() ) ); ?>" value="<?php echo esc_attr( $this->get_field_value( 'homepage_title_tagline' ) ); ?>" />
162
  </p>
163
 
164
  <hr>
168
  <strong><?php printf( esc_html__( 'Custom %s Title', 'autodescription' ), $home_page_i18n ); ?></strong>
169
  <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#3' ); ?>" target="_blank" title="<?php esc_attr_e( 'Recommended Length: 50 to 55 characters', 'autodescription' ) ?>">[?]</a>
170
  <span class="description tsf-counter">
171
+ <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="' . esc_attr( $this->field_id( 'homepage_title', false ) ) . '_chars">' . (int) mb_strlen( $tit_len ) . '</span>' ); ?>
172
  <span class="hide-if-no-js tsf-ajax"></span>
173
  </span>
174
  </label>
175
  </p>
176
  <p id="tsf-title-wrap">
177
+ <input type="text" name="<?php $this->field_name( 'homepage_title' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_title' ); ?>" placeholder="<?php echo esc_attr( $home_title_placeholder ); ?>" value="<?php echo esc_attr( $this->get_field_value( 'homepage_title' ) ); ?>" />
178
  <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
179
  </p>
180
  <?php
181
+ /**
182
+ * If the home title is fetched from the post, notify about that instead.
183
+ * @since 2.2.4
184
+ *
185
+ * Nesting often used translations
186
+ */
187
+ if ( $this->has_page_on_front() && ! $this->get_option( 'homepage_title' ) && $this->get_custom_field( '_genesis_title', $home_id ) ) {
188
+ /* translators: 1: Option, 2: Page SEO Settings, 3: Home Page */
189
+ $this->description( sprintf( esc_html__( 'Note: The %1$s is fetched from the %2$s on the %3$s.', 'autodescription' ),
190
+ esc_html( $title_i18n ),
191
+ esc_html__( 'Page SEO Settings', 'autodescription' ),
192
+ esc_html( $home_page_i18n )
193
+ ) );
194
+ }
195
+
196
+ /**
197
+ * Applies filters 'the_seo_framework_warn_homepage_global_title' : bool
198
+ *
199
+ * @since 2.8.0
200
+ */
201
+ if ( apply_filters( 'the_seo_framework_warn_homepage_global_title', false ) && $this->has_page_on_front() ) {
202
+ printf( '<p class="attention">%s</p>',
203
+ //* Markdown escapes.
204
+ $this->convert_markdown(
205
+ sprintf(
206
+ /* translators: %s = Home page URL markdown */
207
+ esc_html__( 'A plugin has been detected that suggests to maintain this option on the [Home Page](%s).', 'autodescription' ),
208
+ esc_url( admin_url( 'post.php?post=' . $home_id . '&action=edit#tsf-inpost-box' ) )
209
+ ),
210
+ array( 'a' )
211
+ )
212
+ );
213
  }
214
  ?>
215
  <hr>
217
  <p>
218
  <label for="<?php $this->field_id( 'homepage_description' ); ?>" class="tsf-toblock">
219
  <strong><?php printf( esc_html__( 'Custom %s Description', 'autodescription' ), $home_page_i18n ); ?></strong>
220
+ <a href="<?php echo esc_url( 'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#1' ); ?>" target="_blank" title="<?php esc_attr_e( 'Recommended Length: 145 to 155 characters', 'autodescription' ) ?>">[?]</a>
221
  <span class="description tsf-counter">
222
+ <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="' . esc_attr( $this->field_id( 'homepage_description', false ) ) . '_chars">' . (int) mb_strlen( $desc_len ) . '</span>' ); ?>
223
  <span class="hide-if-no-js tsf-ajax"></span>
224
  </span>
225
  </label>
226
  </p>
227
  <p>
228
+ <textarea name="<?php $this->field_name( 'homepage_description' ); ?>" class="large-text" id="<?php $this->field_id( 'homepage_description' ); ?>" rows="3" cols="70" placeholder="<?php echo esc_attr( $description_placeholder ); ?>"><?php echo esc_attr( $this->get_field_value( 'homepage_description' ) ); ?></textarea>
229
  </p>
230
  <?php
231
  $this->description( __( 'The meta description can be used to determine the text used under the title on Search Engine results pages.', 'autodescription' ) );
232
 
233
  if ( $description_from_post_message ) {
234
+ $this->description( $description_from_post_message );
235
+ }
236
+
237
+ /**
238
+ * Applies filters 'the_seo_framework_warn_homepage_global_description' : bool
239
+ *
240
+ * @since 2.8.0
241
+ */
242
+ if ( apply_filters( 'the_seo_framework_warn_homepage_global_description', false ) && $this->has_page_on_front() ) {
243
+ printf( '<p class="attention">%s</p>',
244
+ $this->convert_markdown(
245
+ sprintf(
246
+ /* translators: %s = Home page URL markdown */
247
+ esc_html__( 'A plugin has been detected that suggests to maintain this option on the [Home Page](%s).', 'autodescription' ),
248
+ esc_url( admin_url( 'post.php?post=' . $home_id . '&action=edit#tsf-inpost-box' ) )
249
+ ),
250
+ array( 'a' )
251
+ )
252
+ );
253
  }
254
  break;
255
 
261
  $blogname = $title_args['blogname'];
262
  $sep = $this->get_separator( 'title' );
263
 
264
+ $example_left = '<em><span class="tsf-custom-title-js">' . $title . '</span><span class="tsf-custom-blogname-js"><span class="tsf-sep-js"> ' . $sep . ' </span><span class="tsf-custom-tagline-js">' . $blogname . '</span></span></span></em>';
265
+ $example_right = '<em><span class="tsf-custom-blogname-js"><span class="tsf-custom-tagline-js">' . $blogname . '</span><span class="tsf-sep-js"> ' . $sep . ' </span></span><span class="tsf-custom-title-js">' . $title . '</span></em>';
266
 
267
  $home_page_i18n = esc_html__( 'Home Page', 'autodescription' );
268
 
276
  <input type="radio" name="<?php $this->field_name( 'home_title_location' ); ?>" id="<?php $this->field_id( 'home_title_location_left' ); ?>" value="left" <?php checked( $this->get_field_value( 'home_title_location' ), 'left' ); ?> />
277
  <label for="<?php $this->field_id( 'home_title_location_left' ); ?>">
278
  <span><?php esc_html_e( 'Left:', 'autodescription' ); ?></span>
279
+ <?php
280
+ //* Already escaped.
281
+ echo $this->code_wrap_noesc( $example_left );
282
+ ?>
283
  </label>
284
  </span>
285
  <span class="tsf-toblock">
286
  <input type="radio" name="<?php $this->field_name( 'home_title_location' ); ?>" id="<?php $this->field_id( 'home_title_location_right' ); ?>" value="right" <?php checked( $this->get_field_value( 'home_title_location' ), 'right' ); ?> />
287
  <label for="<?php $this->field_id( 'home_title_location_right' ); ?>">
288
  <span><?php esc_html_e( 'Right:', 'autodescription' ); ?></span>
289
+ <?php
290
+ //* Already escaped.
291
+ echo $this->code_wrap_noesc( $example_right );
292
+ ?>
293
  </label>
294
  </span>
295
  </p>
329
  $checked_home = ' - <a href="' . esc_url( admin_url( 'post.php?post=' . $home_id . '&action=edit#tsf-inpost-box' ) ) . '" target="_blank" class="attention" title="' . esc_attr__( 'View Home Page Settings', 'autodescription' ) . '" >' . esc_html__( 'Checked in Page', 'autodescription' ) . '</a>';
330
  }
331
 
332
+ ?>
333
+ <h4><?php esc_html_e( 'Home Page Robots Meta Settings', 'autodescription' ); ?></h4>
334
+ <?php
335
 
336
  $noindex_note = $noindex_post ? $checked_home : '';
337
  $nofollow_note = $nofollow_post ? $checked_home : '';
inc/views/metaboxes/knowledge-metabox.php DELETED
@@ -1,230 +0,0 @@
1
- <?php
2
-
3
- defined( 'ABSPATH' ) and $_this = the_seo_framework_class() and $this instanceof $_this or die;
4
-
5
- //* Fetch the required instance within this file.
6
- $instance = $this->get_view_instance( 'the_seo_framework_knowledge_metabox', $instance );
7
-
8
- switch ( $instance ) :
9
- case 'the_seo_framework_knowledge_metabox_main' :
10
-
11
- /**
12
- * Parse tabs content.
13
- *
14
- * @since 2.2.8
15
- *
16
- * @param array $default_tabs { 'id' = The identifier =>
17
- * array(
18
- * 'name' => The name
19
- * 'callback' => The callback function, use array for method calling (accepts $this, but isn't used here for optimization purposes)
20
- * 'dashicon' => Desired dashicon
21
- * )
22
- * }
23
- */
24
- $default_tabs = array(
25
- 'general' => array(
26
- 'name' => __( 'General', 'autodescription' ),
27
- 'callback' => array( $this, 'knowledge_metabox_general_tab' ),
28
- 'dashicon' => 'admin-generic',
29
- ),
30
- 'website' => array(
31
- 'name' => __( 'Website', 'autodescription' ),
32
- 'callback' => array( $this, 'knowledge_metabox_about_tab' ),
33
- 'dashicon' => 'admin-home',
34
- ),
35
- 'social' => array(
36
- 'name' => 'Social Sites',
37
- 'callback' => array( $this, 'knowledge_metabox_social_tab' ),
38
- 'dashicon' => 'networking',
39
- ),
40
- );
41
-
42
- /**
43
- * Applies filter knowledgegraph_settings_tabs : Array see $default_tabs
44
- * @since 2.2.8
45
- * Used to extend Knowledge Graph tabs
46
- */
47
- $defaults = (array) apply_filters( 'the_seo_framework_knowledgegraph_settings_tabs', $default_tabs, $args );
48
-
49
- $tabs = wp_parse_args( $args, $defaults );
50
-
51
- $this->nav_tab_wrapper( 'knowledge', $tabs, '2.2.8' );
52
- break;
53
-
54
- case 'the_seo_framework_knowledge_metabox_general' :
55
-
56
- ?><h4><?php esc_html_e( 'Knowledge Graph Settings', 'autodescription' ); ?></h4><?php
57
- $this->description( __( "The Knowledge Graph lets Google and other Search Engines know where to find you or your organization and its relevant content.", 'autodescription' ) );
58
- $this->description( __( "Google is becoming more of an 'Answer Engine' than a 'Search Engine'. Setting up these options could have a positive impact on the SEO value of your website.", 'autodescription' ) );
59
-
60
- //* Echo checkbox.
61
- $this->wrap_fields(
62
- $this->make_checkbox(
63
- 'knowledge_output',
64
- __( 'Output Knowledge tags?', 'autodescription' ),
65
- '',
66
- true
67
- ), true
68
- );
69
-
70
- if ( $this->wp_version( '4.2.999', '>=' ) ) :
71
- ?>
72
- <hr>
73
-
74
- <h4><?php esc_html_e( 'Website logo', 'autodescription' ); ?></h4>
75
- <?php
76
- //* Echo checkbox.
77
- $this->wrap_fields(
78
- $this->make_checkbox(
79
- 'knowledge_logo',
80
- __( 'Use the Favicon from Customizer as the Organization Logo?', 'autodescription' ),
81
- __( 'This option only has an effect when this site represents an Organization. If left disabled, Search Engines will look elsewhere for a logo, if it exists and is assigned as a logo.', 'autodescription' ),
82
- true
83
- ), true
84
- );
85
- endif;
86
- break;
87
-
88
- case 'the_seo_framework_knowledge_metabox_about' :
89
-
90
- $blogname = $this->get_blogname();
91
-
92
- ?><h4><?php esc_html_e( 'About this website', 'autodescription' ); ?></h4><?php
93
- $this->description( __( 'Who or what is your website about?', 'autodescription' ) );
94
-
95
- ?>
96
- <hr>
97
-
98
- <p>
99
- <label for="<?php $this->field_id( 'knowledge_type' ); ?>"><?php echo esc_html_x( 'This website represents:', '...Organization or Person.', 'autodescription' ); ?></label>
100
- <select name="<?php $this->field_name( 'knowledge_type' ); ?>" id="<?php $this->field_id( 'knowledge_type' ); ?>">
101
- <?php
102
- $knowledge_type = (array) apply_filters(
103
- 'the_seo_framework_knowledge_types',
104
- array(
105
- 'organization' => __( 'An Organization', 'autodescription' ),
106
- 'person' => __( 'A Person', 'autodescription' ),
107
- )
108
- );
109
- foreach ( $knowledge_type as $value => $name )
110
- echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->get_field_value( 'knowledge_type' ), esc_attr( $value ), false ) . '>' . esc_html( $name ) . '</option>' . "\n";
111
- ?>
112
- </select>
113
- </p>
114
-
115
- <hr>
116
-
117
- <p>
118
- <label for="<?php $this->field_id( 'knowledge_name' ); ?>">
119
- <strong><?php esc_html_e( 'The organization or personal name', 'autodescription' ); ?></strong>
120
- </label>
121
- </p>
122
- <p>
123
- <input type="text" name="<?php $this->field_name( 'knowledge_name' ); ?>" class="large-text" id="<?php $this->field_id( 'knowledge_name' ); ?>" placeholder="<?php echo esc_attr( $blogname ) ?>" value="<?php echo esc_attr( $this->get_field_value( 'knowledge_name' ) ); ?>" />
124
- </p>
125
- <?php
126
- break;
127
-
128
- case 'the_seo_framework_knowledge_metabox_social' :
129
-
130
- ?><h4><?php esc_html_e( 'Social Pages connected to this website', 'autodescription' ); ?></h4><?php
131
- $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' ) );
132
- $this->description( __( 'Add the link that leads directly to the social page of this website.', 'autodescription' ) );
133
-
134
- ?><hr><?php
135
-
136
- $connectedi18n = _x( 'RelatedProfile', 'No spaces. E.g. https://facebook.com/RelatedProfile', 'autodescription' );
137
- $profile18n = _x( 'Profile', 'Social Profile', 'autodescription' );
138
-
139
- /**
140
- * @todo maybe genericons?
141
- */
142
-
143
- $socialsites = array(
144
- 'facebook' => array(
145
- 'option' => 'knowledge_facebook',
146
- 'dashicon' => 'dashicons-facebook',
147
- 'desc' => 'Facebook ' . __( 'Page', 'autodescription' ),
148
- 'placeholder' => 'http://www.facebook.com/' . $connectedi18n,
149
- 'examplelink' => esc_url( 'https://facebook.com/me' ),
150
- ),
151
- 'twitter' => array(
152
- 'option' => 'knowledge_twitter',
153
- 'dashicon' => 'dashicons-twitter',
154
- 'desc' => 'Twitter ' . $profile18n,
155
- 'placeholder' => 'http://www.twitter.com/' . $connectedi18n,
156
- 'examplelink' => esc_url( 'https://twitter.com/home' ), // No example link available.
157
- ),
158
- 'gplus' => array(
159
- 'option' => 'knowledge_gplus',
160
- 'dashicon' => 'dashicons-googleplus',
161
- 'desc' => 'Google+ ' . $profile18n,
162
- 'placeholder' => 'https://plus.google.com/' . $connectedi18n,
163
- 'examplelink' => esc_url( 'https://plus.google.com/me' ),
164
- ),
165
- 'instagram' => array(
166
- 'option' => 'knowledge_instagram',
167
- 'dashicon' => 'genericon-instagram',
168
- 'desc' => 'Instagram ' . $profile18n,
169
- 'placeholder' => 'http://instagram.com/' . $connectedi18n,
170
- 'examplelink' => esc_url( 'https://instagram.com/' ), // No example link available.
171
- ),
172
- 'youtube' => array(
173
- 'option' => 'knowledge_youtube',
174
- 'dashicon' => 'genericon-youtube',
175
- 'desc' => 'Youtube ' . $profile18n,
176
- 'placeholder' => 'http://www.youtube.com/' . $connectedi18n,
177
- 'examplelink' => esc_url( 'https://www.youtube.com/user/%2f' ), // Yes a double slash.
178
- ),
179
- 'linkedin' => array(
180
- 'option' => 'knowledge_linkedin',
181
- 'dashicon' => 'genericon-linkedin-alt',
182
- 'desc' => 'LinkedIn ' . $profile18n . ' ID',
183
- 'placeholder' => 'http://www.linkedin.com/profile/view?id=' . $connectedi18n,
184
- 'examplelink' => esc_url( 'https://www.linkedin.com/profile/view' ), // This generates a query arg. We should allow that.
185
- ),
186
- 'pinterest' => array(
187
- 'option' => 'knowledge_pinterest',
188
- 'dashicon' => 'genericon-pinterest-alt',
189
- 'desc' => 'Pinterest ' . $profile18n,
190
- 'placeholder' => 'https://www.pinterest.com/' . $connectedi18n . '/',
191
- 'examplelink' => esc_url( 'https://www.pinterest.com/me/' ),
192
- ),
193
- 'soundcloud' => array(
194
- 'option' => 'knowledge_soundcloud',
195
- 'dashicon' => 'genericon-cloud', // I know, it's not the real one. D:
196
- 'desc' => 'SoundCloud ' . $profile18n,
197
- 'placeholder' => 'https://soundcloud.com/' . $connectedi18n,
198
- 'examplelink' => esc_url( 'https://soundcloud.com/you' ),
199
- ),
200
- 'tumblr' => array(
201
- 'option' => 'knowledge_tumblr',
202
- 'dashicon' => 'genericon-tumblr',
203
- 'desc' => 'Tumblr ' . __( 'Blog', 'autodescription' ),
204
- 'placeholder' => 'https://tumblr.com/blog/' . $connectedi18n,
205
- 'examplelink' => esc_url( 'https://www.tumblr.com/dashboard' ), // No example link available.
206
- ),
207
- );
208
-
209
- foreach ( $socialsites as $key => $value ) {
210
- ?>
211
- <p>
212
- <label for="<?php $this->field_id( $value['option'] ); ?>">
213
- <strong><?php echo esc_html( $value['desc'] ); ?></strong>
214
- <?php
215
- if ( $value['examplelink'] ) {
216
- ?><a href="<?php echo esc_url( $value['examplelink'] ); ?>" target="_blank">[?]</a><?php
217
- }
218
- ?>
219
- </label>
220
- </p>
221
- <p>
222
- <input type="text" name="<?php $this->field_name( $value['option'] ); ?>" class="large-text" id="<?php $this->field_id( $value['option'] ); ?>" placeholder="<?php echo esc_attr( $value['placeholder'] ) ?>" value="<?php echo esc_attr( $this->get_field_value( $value['option'] ) ); ?>" />
223
- </p>
224
- <?php
225
- }
226
- break;
227
-
228
- default :
229
- break;
230
- endswitch;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/views/metaboxes/schema-metabox.php CHANGED
@@ -8,78 +8,277 @@ $instance = $this->get_view_instance( 'the_seo_framework_schema_metabox', $insta
8
  switch ( $instance ) :
9
  case 'the_seo_framework_schema_metabox_main' :
10
 
11
- ?><h4><?php esc_html_e( 'Schema.org Output Settings', 'autodescription' ); ?></h4><?php
 
 
12
 
13
  if ( $this->has_json_ld_plugin() ) :
14
  $this->description( __( 'Another Schema.org plugin has been detected.', 'autodescription' ) );
15
  else :
16
  $this->description( __( 'The Schema.org markup is a standard way of annotating structured data for Search Engines. This markup is represented within hidden scripts throughout the website.', 'autodescription' ) );
17
  $this->description( __( 'When your web pages include structured data markup, Search Engines can use that data to index your content better, present it more prominently in Search Results, and use it in several different applications.', 'autodescription' ) );
 
18
 
19
- ?>
20
- <hr>
21
-
22
- <?php /* translators: https://developers.google.com/search/docs/data-types/sitelinks-searchbox */ ?>
23
- <h4><?php echo esc_html( _x( 'Sitelinks Searchbox', 'Product name', 'autodescription' ) ); ?></h4><?php
24
- $this->description( __( 'When Search users search for your brand name, the following option allows them to search through your website directly from the Search Results.', 'autodescription' ) );
25
-
26
- $info = $this->make_info(
27
- _x( 'Sitelinks Searchbox', 'Product name', 'autodescription' ),
28
- 'https://developers.google.com/search/docs/data-types/sitelinks-searchbox',
29
- false
30
- );
31
- $this->wrap_fields(
32
- $this->make_checkbox(
33
- 'ld_json_searchbox',
34
- esc_html_x( 'Enable Sitelinks Searchbox?', 'Product name', 'autodescription' ) . ' ' . $info,
35
- '',
36
- false
 
 
 
 
 
 
 
 
 
 
37
  ),
38
- true
39
  );
40
 
41
- ?>
42
- <hr>
 
 
 
 
43
 
44
- <h4><?php esc_html_e( 'Site Name', 'autodescription' ); ?></h4><?php
45
- $this->description( __( "When using breadcrumbs, the first entry is by default your website's address. Using the following option will convert it to the Site Name.", 'autodescription' ) );
46
 
47
- $info = $this->make_info(
48
- __( 'Include your Site Name in Search Results', 'autodescription' ),
49
- 'https://developers.google.com/search/docs/data-types/sitename',
50
- false
51
- );
52
- $this->wrap_fields(
53
- $this->make_checkbox(
54
- 'ld_json_sitename',
55
- esc_html__( 'Convert URL to Site Name?', 'autodescription' ) . ' ' . $info,
56
- sprintf( esc_html__( 'The Site Name is: %s', 'autodescription' ), $this->code_wrap( $this->get_blogname() ) ),
57
- false
58
- ),
59
- true
60
- );
61
 
62
- ?>
63
- <hr>
64
 
65
- <h4><?php esc_html_e( 'Breadcrumbs', 'autodescription' ); ?></h4><?php
66
- $this->description( __( "Breadcrumb trails indicate the page's position in the site hierarchy. Using the following option will show the hierarchy within the Search Results when available.", 'autodescription' ) );
67
 
68
- $info = $this->make_info(
69
- __( 'About Breadcrumbs', 'autodescription' ),
70
- 'https://developers.google.com/search/docs/data-types/breadcrumbs',
71
- false
72
- );
73
- $this->wrap_fields(
74
- $this->make_checkbox(
75
- 'ld_json_breadcrumbs',
76
- esc_html__( 'Enable Breadcrumbs?', 'autodescription' ) . ' ' . $info,
77
- esc_html__( 'Multiple trails can be outputted. The longest trail is prioritized.', 'autodescription' ),
78
- false
79
- ),
80
- true
81
- );
82
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  break;
84
 
85
  default :
8
  switch ( $instance ) :
9
  case 'the_seo_framework_schema_metabox_main' :
10
 
11
+ ?>
12
+ <h4><?php esc_html_e( 'Schema.org Output Settings', 'autodescription' ); ?></h4>
13
+ <?php
14
 
15
  if ( $this->has_json_ld_plugin() ) :
16
  $this->description( __( 'Another Schema.org plugin has been detected.', 'autodescription' ) );
17
  else :
18
  $this->description( __( 'The Schema.org markup is a standard way of annotating structured data for Search Engines. This markup is represented within hidden scripts throughout the website.', 'autodescription' ) );
19
  $this->description( __( 'When your web pages include structured data markup, Search Engines can use that data to index your content better, present it more prominently in Search Results, and use it in several different applications.', 'autodescription' ) );
20
+ $this->description( __( 'This is also known as the "Knowledge Graph" and "Structured Data", which is under heavy active development by several Search Engines. Therefore, the usage of the outputted markup is not guaranteed.', 'autodescription' ) );
21
 
22
+ /**
23
+ * Parse tabs content.
24
+ *
25
+ * @since 2.8.0
26
+ *
27
+ * @param array $default_tabs { 'id' = The identifier =>
28
+ * array(
29
+ * 'name' => The name
30
+ * 'callback' => The callback function, use array for method calling
31
+ * 'dashicon' => Desired dashicon
32
+ * )
33
+ * }
34
+ */
35
+ $default_tabs = array(
36
+ 'general' => array(
37
+ 'name' => __( 'General', 'autodescription' ),
38
+ 'callback' => array( $this, 'schema_metabox_general_tab' ),
39
+ 'dashicon' => 'admin-generic',
40
+ ),
41
+ 'structure' => array(
42
+ 'name' => __( 'Structure', 'autodescription' ),
43
+ 'callback' => array( $this, 'schema_metabox_structure_tab' ),
44
+ 'dashicon' => 'admin-multisite',
45
+ ),
46
+ 'presence' => array(
47
+ 'name' => __( 'Presence', 'autodescription' ),
48
+ 'callback' => array( $this, 'schema_metabox_presence_tab' ),
49
+ 'dashicon' => 'networking',
50
  ),
 
51
  );
52
 
53
+ /**
54
+ * Applies filter 'the_seo_framework_schema_settings_tabs' : Array
55
+ * @since 2.8.0
56
+ * Used to extend Schema settings tabs
57
+ */
58
+ $defaults = (array) apply_filters( 'the_seo_framework_schema_settings_tabs', $default_tabs, $args );
59
 
60
+ $tabs = wp_parse_args( $args, $defaults );
 
61
 
62
+ $this->nav_tab_wrapper( 'schema', $tabs, '2.8.0' );
63
+ endif;
64
+ break;
 
 
 
 
 
 
 
 
 
 
 
65
 
66
+ case 'the_seo_framework_schema_metabox_general' :
 
67
 
68
+ ?>
69
+ <h4><?php esc_html_e( 'About this website', 'autodescription' ); ?></h4>
70
 
71
+ <p>
72
+ <label for="<?php $this->field_id( 'knowledge_type' ); ?>"><?php echo esc_html_x( 'This website represents:', '...Organization or Person.', 'autodescription' ); ?></label>
73
+ <select name="<?php $this->field_name( 'knowledge_type' ); ?>" id="<?php $this->field_id( 'knowledge_type' ); ?>">
74
+ <?php
75
+ $knowledge_type = (array) apply_filters(
76
+ 'the_seo_framework_knowledge_types',
77
+ array(
78
+ 'organization' => __( 'An Organization', 'autodescription' ),
79
+ 'person' => __( 'A Person', 'autodescription' ),
80
+ )
81
+ );
82
+ foreach ( $knowledge_type as $value => $name ) {
83
+ echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->get_field_value( 'knowledge_type' ), esc_attr( $value ), false ) . '>' . esc_html( $name ) . '</option>' . "\n";
84
+ }
85
+ ?>
86
+ </select>
87
+ </p>
88
+
89
+ <p>
90
+ <label for="<?php $this->field_id( 'knowledge_name' ); ?>">
91
+ <strong><?php esc_html_e( 'The organization or personal name', 'autodescription' ); ?></strong>
92
+ </label>
93
+ </p>
94
+ <p>
95
+ <input type="text" name="<?php $this->field_name( 'knowledge_name' ); ?>" class="large-text" id="<?php $this->field_id( 'knowledge_name' ); ?>" placeholder="<?php echo esc_attr( $this->get_blogname() ) ?>" value="<?php echo esc_attr( $this->get_field_value( 'knowledge_name' ) ); ?>" />
96
+ </p>
97
+ <?php
98
+ break;
99
+
100
+ case 'the_seo_framework_schema_metabox_structure' :
101
+
102
+ ?><h4><?php esc_html_e( 'Site Structure Options', 'autodescription' ); ?></h4><?php
103
+ $this->description( __( 'The site structure Schema.org output allows Search Engines to gain knowledge on how your website is built.', 'autodescription' ) );
104
+ $this->description( __( "For example, Search Engines display your pages' URLs when listed in the Search Results. These options allow you to enhance those URLs output.", 'autodescription' ) );
105
+
106
+ ?>
107
+ <hr>
108
+
109
+ <h4><?php esc_html_e( 'Breadcrumbs', 'autodescription' ); ?></h4><?php
110
+ $this->description( __( "Breadcrumb trails indicate the page's position in the site hierarchy. Using the following option will show the hierarchy within the Search Results when available.", 'autodescription' ) );
111
+
112
+ $info = $this->make_info( __( 'About Breadcrumbs', 'autodescription' ), 'https://developers.google.com/search/docs/data-types/breadcrumbs', false );
113
+ $this->wrap_fields( $this->make_checkbox(
114
+ 'ld_json_breadcrumbs',
115
+ esc_html__( 'Enable Breadcrumbs?', 'autodescription' ) . ' ' . $info,
116
+ esc_html__( 'Multiple trails can be outputted. The longest trail is prioritized.', 'autodescription' ),
117
+ false
118
+ ), true );
119
+
120
+ ?>
121
+ <hr>
122
+
123
+ <h4><?php esc_html_e( 'Site Name', 'autodescription' ); ?></h4>
124
+ <?php
125
+ $this->description( __( "When using breadcrumbs, the first entry is by default your website's address. Using the following option will convert it to the Site Name.", 'autodescription' ) );
126
+
127
+ $info = $this->make_info(
128
+ __( 'Include your Site Name in Search Results', 'autodescription' ),
129
+ 'https://developers.google.com/search/docs/data-types/sitename',
130
+ false
131
+ );
132
+ $this->wrap_fields( $this->make_checkbox(
133
+ 'ld_json_sitename',
134
+ esc_html__( 'Convert URL to Site Name?', 'autodescription' ) . ' ' . $info,
135
+ sprintf( esc_html__( 'The Site Name is: %s', 'autodescription' ), $this->code_wrap( $this->get_blogname() ) ),
136
+ false
137
+ ), true );
138
+
139
+ ?>
140
+ <hr>
141
+ <?php
142
+
143
+ /* translators: https://developers.google.com/search/docs/data-types/sitelinks-searchbox */
144
+ ?><h4><?php echo esc_html( _x( 'Sitelinks Searchbox', 'Product name', 'autodescription' ) ); ?></h4><?php
145
+ $this->description( __( 'When Search users search for your brand name, the following option allows them to search through this website directly from the Search Results.', 'autodescription' ) );
146
+
147
+ $info = $this->make_info( _x( 'Sitelinks Searchbox', 'Product name', 'autodescription' ), 'https://developers.google.com/search/docs/data-types/sitelinks-searchbox', false );
148
+ $this->wrap_fields( $this->make_checkbox(
149
+ 'ld_json_searchbox',
150
+ esc_html_x( 'Enable Sitelinks Searchbox?', 'Product name', 'autodescription' ) . ' ' . $info,
151
+ '',
152
+ false
153
+ ), true );
154
+ break;
155
+
156
+ case 'the_seo_framework_schema_metabox_presence' :
157
+
158
+ ?><h4><?php esc_html_e( 'Authorized Presence Options', 'autodescription' ); ?></h4><?php
159
+ $this->description( __( 'The authorized presence Schema.org output helps Search Engine users find ways to interact with this website.', 'autodescription' ) );
160
+
161
+ $info = $this->make_info( __( 'About Authorized Presence', 'autodescription' ), 'https://developers.google.com/search/docs/guides/enhance-site#add-your-sites-name-logo-and-social-links', false );
162
+ //* Echo checkbox.
163
+ $this->wrap_fields( $this->make_checkbox(
164
+ 'knowledge_output',
165
+ esc_html__( 'Output Authorized Presence?', 'autodescription' ) . ' ' . $info,
166
+ '',
167
+ false
168
+ ), true );
169
+
170
+ ?>
171
+ <hr>
172
+
173
+ <h4><?php esc_html_e( 'Website logo', 'autodescription' ); ?></h4>
174
+ <?php
175
+ //* @TODO @priority OMGWTFBBQ 2.8.0 this logo MUST prefer "Site Icon". State that.
176
+ // if ( $this->theme_supports_site_icon() )
177
+ // $this->description( __( 'If your theme supports', 'autodescription' ) );
178
+ $info = $this->make_info( __( 'About Organization Logo', 'autodescription' ), 'https://developers.google.com/search/docs/data-types/logo', false );
179
+ $this->wrap_fields( $this->make_checkbox(
180
+ 'knowledge_logo',
181
+ esc_html__( 'Use the Favicon from Customizer as the Organization Logo?', 'autodescription' ) . ' ' . $info,
182
+ esc_html__( 'This option only has an effect when this site represents an Organization. If left disabled, Search Engines will look elsewhere for a logo, if it exists and is assigned as a logo.', 'autodescription' ),
183
+ false
184
+ ), true );
185
+
186
+ ?>
187
+ <hr>
188
+
189
+ <h4><?php esc_html_e( 'Social Pages connected to this website', 'autodescription' ); ?></h4><?php
190
+ $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' ) );
191
+ $this->description( __( 'Add the link that leads directly to the social page of this website.', 'autodescription' ) );
192
+
193
+ $connectedi18n = _x( 'RelatedProfile', 'No spaces. E.g. https://facebook.com/RelatedProfile', 'autodescription' );
194
+ $profile18n = _x( 'Profile', 'Social Profile', 'autodescription' );
195
+
196
+ /**
197
+ * @todo maybe genericons?
198
+ */
199
+ $socialsites = array(
200
+ 'facebook' => array(
201
+ 'option' => 'knowledge_facebook',
202
+ 'dashicon' => 'dashicons-facebook',
203
+ 'desc' => 'Facebook ' . __( 'Page', 'autodescription' ),
204
+ 'placeholder' => 'http://www.facebook.com/' . $connectedi18n,
205
+ 'examplelink' => esc_url( 'https://facebook.com/me' ),
206
+ ),
207
+ 'twitter' => array(
208
+ 'option' => 'knowledge_twitter',
209
+ 'dashicon' => 'dashicons-twitter',
210
+ 'desc' => 'Twitter ' . $profile18n,
211
+ 'placeholder' => 'http://www.twitter.com/' . $connectedi18n,
212
+ 'examplelink' => esc_url( 'https://twitter.com/home' ), // No example link available.
213
+ ),
214
+ 'gplus' => array(
215
+ 'option' => 'knowledge_gplus',
216
+ 'dashicon' => 'dashicons-googleplus',
217
+ 'desc' => 'Google+ ' . $profile18n,
218
+ 'placeholder' => 'https://plus.google.com/' . $connectedi18n,
219
+ 'examplelink' => esc_url( 'https://plus.google.com/me' ),
220
+ ),
221
+ 'instagram' => array(
222
+ 'option' => 'knowledge_instagram',
223
+ 'dashicon' => 'genericon-instagram',
224
+ 'desc' => 'Instagram ' . $profile18n,
225
+ 'placeholder' => 'http://instagram.com/' . $connectedi18n,
226
+ 'examplelink' => esc_url( 'https://instagram.com/' ), // No example link available.
227
+ ),
228
+ 'youtube' => array(
229
+ 'option' => 'knowledge_youtube',
230
+ 'dashicon' => 'genericon-youtube',
231
+ 'desc' => 'Youtube ' . $profile18n,
232
+ 'placeholder' => 'http://www.youtube.com/' . $connectedi18n,
233
+ 'examplelink' => esc_url( 'https://www.youtube.com/user/%2f' ), // Yes a double slash.
234
+ ),
235
+ 'linkedin' => array(
236
+ 'option' => 'knowledge_linkedin',
237
+ 'dashicon' => 'genericon-linkedin-alt',
238
+ 'desc' => 'LinkedIn ' . $profile18n . ' ID',
239
+ 'placeholder' => 'http://www.linkedin.com/profile/view?id=' . $connectedi18n,
240
+ 'examplelink' => esc_url( 'https://www.linkedin.com/profile/view' ), // This generates a query arg. We should allow that.
241
+ ),
242
+ 'pinterest' => array(
243
+ 'option' => 'knowledge_pinterest',
244
+ 'dashicon' => 'genericon-pinterest-alt',
245
+ 'desc' => 'Pinterest ' . $profile18n,
246
+ 'placeholder' => 'https://www.pinterest.com/' . $connectedi18n . '/',
247
+ 'examplelink' => esc_url( 'https://www.pinterest.com/me/' ),
248
+ ),
249
+ 'soundcloud' => array(
250
+ 'option' => 'knowledge_soundcloud',
251
+ 'dashicon' => 'genericon-cloud', // I know, it's not the real one. D:
252
+ 'desc' => 'SoundCloud ' . $profile18n,
253
+ 'placeholder' => 'https://soundcloud.com/' . $connectedi18n,
254
+ 'examplelink' => esc_url( 'https://soundcloud.com/you' ),
255
+ ),
256
+ 'tumblr' => array(
257
+ 'option' => 'knowledge_tumblr',
258
+ 'dashicon' => 'genericon-tumblr',
259
+ 'desc' => 'Tumblr ' . __( 'Blog', 'autodescription' ),
260
+ 'placeholder' => 'https://tumblr.com/blog/' . $connectedi18n,
261
+ 'examplelink' => esc_url( 'https://www.tumblr.com/dashboard' ), // No example link available.
262
+ ),
263
+ );
264
+
265
+ foreach ( $socialsites as $key => $value ) {
266
+ ?>
267
+ <p>
268
+ <label for="<?php $this->field_id( $value['option'] ); ?>">
269
+ <strong><?php echo esc_html( $value['desc'] ); ?></strong>
270
+ <?php
271
+ if ( $value['examplelink'] ) {
272
+ ?><a href="<?php echo esc_url( $value['examplelink'] ); ?>" target="_blank">[?]</a><?php
273
+ }
274
+ ?>
275
+ </label>
276
+ </p>
277
+ <p>
278
+ <input type="text" name="<?php $this->field_name( $value['option'] ); ?>" class="large-text" id="<?php $this->field_id( $value['option'] ); ?>" placeholder="<?php echo esc_attr( $value['placeholder'] ) ?>" value="<?php echo esc_attr( $this->get_field_value( $value['option'] ) ); ?>" />
279
+ </p>
280
+ <?php
281
+ }
282
  break;
283
 
284
  default :
inc/views/metaboxes/sitemaps-metabox.php CHANGED
@@ -8,7 +8,7 @@ $instance = $this->get_view_instance( 'the_seo_framework_sitemaps_metabox', $ins
8
  switch ( $instance ) :
9
  case 'the_seo_framework_sitemaps_metabox_main' :
10
 
11
- if ( ! $this->pretty_permalinks ) {
12
 
13
  $permalink_settings_url = admin_url( 'options-permalink.php' );
14
  $here = '<a href="' . esc_url( $permalink_settings_url ) . '" target="_blank" title="' . esc_attr__( 'Permalink Settings', 'autodescription' ) . '">' . esc_html_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
@@ -18,41 +18,46 @@ switch ( $instance ) :
18
  ?><hr><?php
19
  $this->description_noesc( sprintf( esc_html_x( "Change your Permalink Settings %s (Recommended: 'postname').", '%s = here', 'autodescription' ), $here ) );
20
 
21
- } else {
22
 
23
  /**
24
  * Parse tabs content
25
  *
26
  * @param array $default_tabs { 'id' = The identifier =>
27
- * array(
28
- * 'name' => The name
29
- * 'callback' => The callback function, use array for method calling (accepts $this, but isn't used here for optimization purposes)
30
- * 'dashicon' => Desired dashicon
31
- * )
32
  * }
33
  *
34
  * @since 2.2.9
35
  */
36
  $default_tabs = array(
37
  'general' => array(
38
- 'name' => __( 'General', 'autodescription' ),
39
- 'callback' => array( $this, 'sitemaps_metabox_general_tab' ),
40
- 'dashicon' => 'admin-generic',
41
  ),
42
  'robots' => array(
43
- 'name' => 'Robots.txt',
44
- 'callback' => array( $this, 'sitemaps_metabox_robots_tab' ),
45
- 'dashicon' => 'share-alt2',
46
  ),
47
  'timestamps' => array(
48
- 'name' => __( 'Timestamps', 'autodescription' ),
49
- 'callback' => array( $this, 'sitemaps_metabox_timestamps_tab' ),
50
- 'dashicon' => 'backup',
51
  ),
52
  'notify' => array(
53
- 'name' => _x( 'Ping', 'Ping or notify Search Engine', 'autodescription' ),
54
- 'callback' => array( $this, 'sitemaps_metabox_notify_tab' ),
55
- 'dashicon' => 'megaphone',
 
 
 
 
 
56
  ),
57
  );
58
 
@@ -66,7 +71,7 @@ switch ( $instance ) :
66
  $tabs = wp_parse_args( $args, $defaults );
67
  $use_tabs = true;
68
 
69
- $sitemap_plugin = $this->detect_sitemap_plugin();
70
  $sitemap_detected = $this->has_sitemap_xml();
71
  $robots_detected = $this->has_robots_txt();
72
 
@@ -74,25 +79,14 @@ switch ( $instance ) :
74
  * Remove the timestamps and notify submenus
75
  * @since 2.5.2
76
  */
77
- if ( $sitemap_plugin || $sitemap_detected ) {
78
  unset( $tabs['timestamps'] );
79
  unset( $tabs['notify'] );
80
  }
81
 
82
- /**
83
- * Remove the robots submenu
84
- * @since 2.5.2
85
- */
86
- if ( $robots_detected ) {
87
- unset( $tabs['robots'] );
88
- }
89
-
90
- if ( $robots_detected && ( $sitemap_plugin || $sitemap_detected ) )
91
- $use_tabs = false;
92
 
93
- $this->nav_tab_wrapper( 'sitemaps', $tabs, '2.2.8', $use_tabs );
94
-
95
- }
96
  break;
97
 
98
  case 'the_seo_framework_sitemaps_metabox_general' :
@@ -103,13 +97,15 @@ switch ( $instance ) :
103
  $has_sitemap_plugin = $this->detect_sitemap_plugin();
104
  $sitemap_detected = $this->has_sitemap_xml();
105
 
106
- ?><h4><?php esc_html_e( 'Sitemap Integration Settings', 'autodescription' ); ?></h4><?php
 
 
107
 
108
- if ( $has_sitemap_plugin ) {
109
  $this->description( __( 'Another active sitemap plugin has been detected. This means that the sitemap functionality has been replaced.', 'autodescription' ) );
110
- } elseif ( $sitemap_detected ) {
111
  $this->description( __( 'A sitemap has been detected in the root folder of your website. This means that the sitemap functionality has no effect.', 'autodescription' ) );
112
- } else {
113
  $this->description( __( 'The Sitemap is an XML file that lists pages and posts for your website along with optional metadata about each post or page. This helps Search Engines crawl your website more easily.', 'autodescription' ) );
114
  $this->description( __( 'The optional metadata include the post and page modified time and a page priority indication, which is automated.', 'autodescription' ) );
115
 
@@ -128,9 +124,9 @@ switch ( $instance ) :
128
  true
129
  ), true
130
  );
131
- }
132
 
133
- if ( ! ( $has_sitemap_plugin || $sitemap_detected ) && $this->get_option( 'sitemaps_output' ) ) {
134
  $here = '<a href="' . esc_url( $sitemap_url ) . '" target="_blank" title="' . esc_attr__( 'View sitemap', 'autodescription' ) . '">' . esc_attr_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
135
  $this->description_noesc( sprintf( _x( 'The sitemap can be found %s.', '%s = here', 'autodescription' ), $here ) );
136
  }
@@ -142,9 +138,13 @@ switch ( $instance ) :
142
  $robots_url = trailingslashit( $site_url ) . 'robots.txt';
143
  $here = '<a href="' . esc_url( $robots_url ) . '" target="_blank" title="' . esc_attr__( 'View robots.txt', 'autodescription' ) . '">' . esc_html_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
144
 
145
- ?><h4><?php esc_html_e( 'Robots.txt Settings', 'autodescription' ); ?></h4><?php
 
 
146
 
147
- if ( $this->can_do_sitemap_robots() ) :
 
 
148
  $this->description( __( 'The robots.txt file is the first thing Search Engines look for. If you add the sitemap location in the robots.txt file, then Search Engines will look for and index the sitemap.', 'autodescription' ) );
149
  $this->description( __( 'If you do not add the sitemap location to the robots.txt file, you will need to notify Search Engines manually through the Webmaster Console provided by the Search Engines.', 'autodescription' ) );
150
 
@@ -158,9 +158,9 @@ switch ( $instance ) :
158
  $this->wrap_fields(
159
  $this->make_checkbox(
160
  'sitemaps_robots',
161
- __( 'Add sitemap location in robots?', 'autodescription' ),
162
  '',
163
- true
164
  ), true
165
  );
166
  else :
@@ -244,9 +244,9 @@ switch ( $instance ) :
244
  <?php
245
 
246
  $engines = array(
247
- 'ping_google' => 'Google',
248
- 'ping_bing' => 'Bing',
249
- 'ping_yandex' => 'Yandex',
250
  );
251
 
252
  $ping_checkbox = '';
@@ -260,6 +260,73 @@ switch ( $instance ) :
260
  $this->wrap_fields( $ping_checkbox, true );
261
  break;
262
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  default :
264
  break;
265
  endswitch;
8
  switch ( $instance ) :
9
  case 'the_seo_framework_sitemaps_metabox_main' :
10
 
11
+ if ( ! $this->pretty_permalinks ) :
12
 
13
  $permalink_settings_url = admin_url( 'options-permalink.php' );
14
  $here = '<a href="' . esc_url( $permalink_settings_url ) . '" target="_blank" title="' . esc_attr__( 'Permalink Settings', 'autodescription' ) . '">' . esc_html_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
18
  ?><hr><?php
19
  $this->description_noesc( sprintf( esc_html_x( "Change your Permalink Settings %s (Recommended: 'postname').", '%s = here', 'autodescription' ), $here ) );
20
 
21
+ else :
22
 
23
  /**
24
  * Parse tabs content
25
  *
26
  * @param array $default_tabs { 'id' = The identifier =>
27
+ * array(
28
+ * 'name' => The name
29
+ * 'callback' => The callback function, use array for method calling
30
+ * 'dashicon' => Desired dashicon
31
+ * )
32
  * }
33
  *
34
  * @since 2.2.9
35
  */
36
  $default_tabs = array(
37
  'general' => array(
38
+ 'name' => __( 'General', 'autodescription' ),
39
+ 'callback' => array( $this, 'sitemaps_metabox_general_tab' ),
40
+ 'dashicon' => 'admin-generic',
41
  ),
42
  'robots' => array(
43
+ 'name' => 'Robots.txt',
44
+ 'callback' => array( $this, 'sitemaps_metabox_robots_tab' ),
45
+ 'dashicon' => 'share-alt2',
46
  ),
47
  'timestamps' => array(
48
+ 'name' => __( 'Timestamps', 'autodescription' ),
49
+ 'callback' => array( $this, 'sitemaps_metabox_timestamps_tab' ),
50
+ 'dashicon' => 'backup',
51
  ),
52
  'notify' => array(
53
+ 'name' => _x( 'Ping', 'Ping or notify Search Engine', 'autodescription' ),
54
+ 'callback' => array( $this, 'sitemaps_metabox_notify_tab' ),
55
+ 'dashicon' => 'megaphone',
56
+ ),
57
+ 'style' => array(
58
+ 'name' => __( 'Style', 'autodescription' ),
59
+ 'callback' => array( $this, 'sitemaps_metabox_style_tab' ),
60
+ 'dashicon' => 'art',
61
  ),
62
  );
63
 
71
  $tabs = wp_parse_args( $args, $defaults );
72
  $use_tabs = true;
73
 
74
+ $has_sitemap_plugin = $this->detect_sitemap_plugin();
75
  $sitemap_detected = $this->has_sitemap_xml();
76
  $robots_detected = $this->has_robots_txt();
77
 
79
  * Remove the timestamps and notify submenus
80
  * @since 2.5.2
81
  */
82
+ if ( $has_sitemap_plugin || $sitemap_detected ) {
83
  unset( $tabs['timestamps'] );
84
  unset( $tabs['notify'] );
85
  }
86
 
87
+ $this->nav_tab_wrapper( 'sitemaps', $tabs, '2.2.8' );
 
 
 
 
 
 
 
 
 
88
 
89
+ endif;
 
 
90
  break;
91
 
92
  case 'the_seo_framework_sitemaps_metabox_general' :
97
  $has_sitemap_plugin = $this->detect_sitemap_plugin();
98
  $sitemap_detected = $this->has_sitemap_xml();
99
 
100
+ ?>
101
+ <h4><?php esc_html_e( 'Sitemap Integration Settings', 'autodescription' ); ?></h4>
102
+ <?php
103
 
104
+ if ( $has_sitemap_plugin ) :
105
  $this->description( __( 'Another active sitemap plugin has been detected. This means that the sitemap functionality has been replaced.', 'autodescription' ) );
106
+ elseif ( $sitemap_detected ) :
107
  $this->description( __( 'A sitemap has been detected in the root folder of your website. This means that the sitemap functionality has no effect.', 'autodescription' ) );
108
+ else :
109
  $this->description( __( 'The Sitemap is an XML file that lists pages and posts for your website along with optional metadata about each post or page. This helps Search Engines crawl your website more easily.', 'autodescription' ) );
110
  $this->description( __( 'The optional metadata include the post and page modified time and a page priority indication, which is automated.', 'autodescription' ) );
111
 
124
  true
125
  ), true
126
  );
127
+ endif;
128
 
129
+ if ( ! $has_sitemap_plugin && ( $this->get_option( 'sitemaps_output' ) || $sitemap_detected ) ) {
130
  $here = '<a href="' . esc_url( $sitemap_url ) . '" target="_blank" title="' . esc_attr__( 'View sitemap', 'autodescription' ) . '">' . esc_attr_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
131
  $this->description_noesc( sprintf( _x( 'The sitemap can be found %s.', '%s = here', 'autodescription' ), $here ) );
132
  }
138
  $robots_url = trailingslashit( $site_url ) . 'robots.txt';
139
  $here = '<a href="' . esc_url( $robots_url ) . '" target="_blank" title="' . esc_attr__( 'View robots.txt', 'autodescription' ) . '">' . esc_html_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
140
 
141
+ ?>
142
+ <h4><?php esc_html_e( 'Robots.txt Settings', 'autodescription' ); ?></h4>
143
+ <?php
144
 
145
+ if ( $this->has_robots_txt() ) :
146
+ $this->description( __( 'A robots.txt file has been detected in the root folder of your website; therefore no settings are able to alter its output.', 'autodescription' ) );
147
+ elseif ( $this->can_do_sitemap_robots( false ) ) :
148
  $this->description( __( 'The robots.txt file is the first thing Search Engines look for. If you add the sitemap location in the robots.txt file, then Search Engines will look for and index the sitemap.', 'autodescription' ) );
149
  $this->description( __( 'If you do not add the sitemap location to the robots.txt file, you will need to notify Search Engines manually through the Webmaster Console provided by the Search Engines.', 'autodescription' ) );
150
 
158
  $this->wrap_fields(
159
  $this->make_checkbox(
160
  'sitemaps_robots',
161
+ esc_html__( 'Add sitemap location in robots?', 'autodescription' ) . ' ' . $this->make_info( __( 'This only has effect if the sitemap is active', 'autodescription' ), '', false ),
162
  '',
163
+ false
164
  ), true
165
  );
166
  else :
244
  <?php
245
 
246
  $engines = array(
247
+ 'ping_google' => 'Google',
248
+ 'ping_bing' => 'Bing',
249
+ 'ping_yandex' => 'Yandex',
250
  );
251
 
252
  $ping_checkbox = '';
260
  $this->wrap_fields( $ping_checkbox, true );
261
  break;
262
 
263
+ case 'the_seo_framework_sitemaps_metabox_style' :
264
+
265
+ ?>
266
+ <h4><?php esc_html_e( 'Sitemap Styling Settings', 'autodescription' ); ?></h4>
267
+ <?php
268
+
269
+ $this->description( __( 'You can style the sitemap to give it a more personal look. Styling the sitemap has no SEO value whatsoever.', 'autodescription' ) );
270
+
271
+ ?>
272
+ <hr>
273
+
274
+ <h4><?php esc_html_e( 'Enable styling', 'autodescription' ); ?></h4>
275
+ <?php
276
+
277
+ //* Echo checkboxes.
278
+ $this->wrap_fields(
279
+ $this->make_checkbox(
280
+ 'sitemap_styles',
281
+ esc_html__( 'Style Sitemap?', 'autodescription' ) . ' ' . $this->make_info( __( 'This makes the sitemap more readable for humans', 'autodescription' ), '', false ),
282
+ '',
283
+ false
284
+ ), true
285
+ );
286
+
287
+ ?>
288
+ <hr>
289
+
290
+ <h4><?php esc_html_e( 'Style configuration', 'autodescription' ); ?></h4>
291
+ <?php
292
+
293
+ if ( $this->can_use_logo() ) :
294
+ //* Echo checkbox.
295
+ $this->wrap_fields(
296
+ $this->make_checkbox(
297
+ 'sitemap_logo',
298
+ esc_html__( 'Add site logo?', 'autodescription' ) . ' ' . $this->make_info( __( 'The logo is set in Customizer', 'autodescription' ), '', false ),
299
+ '',
300
+ false
301
+ ), true
302
+ );
303
+ endif;
304
+
305
+ $current_colors = $this->get_sitemap_colors();
306
+ $default_colors = $this->get_sitemap_colors( true );
307
+
308
+ ?>
309
+ <p>
310
+ <label for="<?php $this->field_id( 'sitemap_color_main' ); ?>">
311
+ <strong><?php esc_html_e( 'Sitemap header background color', 'autodescription' ); ?></strong>
312
+ </label>
313
+ </p>
314
+ <p>
315
+ <input type="text" name="<?php $this->field_name( 'sitemap_color_main' ); ?>" class="tsf-color-picker" id="<?php $this->field_id( 'sitemap_color_main' ); ?>" placeholder="<?php echo esc_attr( $default_colors['main'] ); ?>" value="<?php echo esc_attr( $current_colors['main'] ); ?>" data-tsf-default-color="<?php echo esc_attr( $default_colors['main'] ); ?>" />
316
+ </p>
317
+
318
+ <p>
319
+ <label for="<?php $this->field_id( 'sitemap_color_accent' ); ?>">
320
+ <strong><?php esc_html_e( 'Sitemap title and lines color', 'autodescription' ); ?></strong>
321
+ </label>
322
+ </p>
323
+ <p>
324
+ <input type="text" name="<?php $this->field_name( 'sitemap_color_accent' ); ?>" class="tsf-color-picker" id="<?php $this->field_id( 'sitemap_color_accent' ); ?>" placeholder="<?php echo esc_attr( $default_colors['accent'] ); ?>" value="<?php echo esc_attr( $current_colors['accent'] ); ?>" data-tsf-default-color="<?php echo esc_attr( $default_colors['accent'] ); ?>" />
325
+ </p>
326
+ <?php
327
+
328
+ break;
329
+
330
  default :
331
  break;
332
  endswitch;
inc/views/metaboxes/social-metabox.php CHANGED
@@ -13,38 +13,33 @@ switch ( $instance ) :
13
  * @since 2.2.2
14
  *
15
  * @param array $default_tabs { 'id' = The identifier =>
16
- * array(
17
- * 'name' => The name
18
- * 'callback' => The callback function, use array for method calling (accepts $this, but isn't used here for optimization purposes)
19
- * 'dashicon' => Desired dashicon
20
- * )
21
  * }
22
  */
23
  $default_tabs = array(
24
  'general' => array(
25
- 'name' => __( 'General', 'autodescription' ),
26
- 'callback' => array( $this, 'social_metabox_general_tab' ),
27
- 'dashicon' => 'admin-generic',
28
  ),
29
  'facebook' => array(
30
- 'name' => 'Facebook',
31
- 'callback' => array( $this, 'social_metabox_facebook_tab' ),
32
- 'dashicon' => 'facebook-alt',
33
  ),
34
  'twitter' => array(
35
- 'name' => 'Twitter',
36
- 'callback' => array( $this, 'social_metabox_twitter_tab' ),
37
- 'dashicon' => 'twitter',
38
  ),
39
  'postdates' => array(
40
- 'name' => __( 'Post Dates', 'autodescription' ),
41
- 'callback' => array( $this, 'social_metabox_postdates_tab' ),
42
- 'dashicon' => 'backup',
43
- ),
44
- 'relationships' => array(
45
- 'name' => __( 'Link Relationships', 'autodescription' ),
46
- 'callback' => array( $this, 'social_metabox_relationships_tab' ),
47
- 'dashicon' => 'leftright',
48
  ),
49
  );
50
 
@@ -62,28 +57,14 @@ switch ( $instance ) :
62
 
63
  case 'the_seo_framework_social_metabox_general' :
64
 
65
- ?><h4><?php esc_html_e( 'Site Shortlink Settings', 'autodescription' ); ?></h4><?php
66
- $this->description( __( 'The shortlink tag might have some use for 3rd party service discoverability, but it has little to no SEO value whatsoever.', 'autodescription' ) );
67
-
68
- //* Echo checkboxes.
69
- $this->wrap_fields(
70
- $this->make_checkbox(
71
- 'shortlink_tag',
72
- __( 'Output shortlink tag?', 'autodescription' ),
73
- '',
74
- true
75
- ),
76
- true
77
- );
78
-
79
  ?>
80
- <hr>
81
-
82
  <h4><?php esc_html_e( 'Social Meta Tags Settings', 'autodescription' ); ?></h4>
83
  <?php
84
  $this->description( __( 'Output various meta tags for social site integration, among other 3rd party services.', 'autodescription' ) );
85
 
86
- ?><hr><?php
 
 
87
 
88
  //* Echo Open Graph Tags checkboxes.
89
  $this->wrap_fields(
@@ -99,8 +80,6 @@ switch ( $instance ) :
99
  if ( $this->detect_og_plugin() )
100
  $this->description( __( 'Note: Another Open Graph plugin has been detected.', 'autodescription' ) );
101
 
102
- ?><hr><?php
103
-
104
  //* Echo Facebook Tags checkbox.
105
  $this->wrap_fields(
106
  $this->make_checkbox(
@@ -112,8 +91,6 @@ switch ( $instance ) :
112
  true
113
  );
114
 
115
- ?><hr><?php
116
-
117
  //* Echo Twitter Tags checkboxes.
118
  $this->wrap_fields(
119
  $this->make_checkbox(
@@ -125,9 +102,60 @@ switch ( $instance ) :
125
  true
126
  );
127
 
128
- if ( $this->detect_twitter_card_plugin() ) {
129
  $this->description( __( 'Note: Another Twitter Card plugin has been detected.', 'autodescription' ) );
130
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  break;
132
 
133
  case 'the_seo_framework_social_metabox_facebook' :
@@ -202,17 +230,17 @@ switch ( $instance ) :
202
 
203
  <p class="tsf-fields">
204
  <?php
205
- foreach ( $twitter_card as $type => $name ) {
206
- ?>
207
- <span class="tsf-toblock">
208
- <input type="radio" name="<?php $this->field_name( 'twitter_card' ); ?>" id="<?php $this->field_id( 'twitter_card_' . $type ); ?>" value="<?php echo esc_attr( $type ); ?>" <?php checked( $this->get_field_value( 'twitter_card' ), $type ); ?> />
209
- <label for="<?php $this->field_id( 'twitter_card_' . $type ); ?>">
210
- <span><?php echo $this->code_wrap( $name ); ?></span>
211
- <a class="description" href="<?php echo esc_url( 'https://dev.twitter.com/cards/types/' . $name ); ?>" target="_blank" title="Twitter Card <?php echo esc_attr( $name ) . ' ' . esc_attr__( 'Example', 'autodescription' ); ?>"><?php esc_html_e( 'Example', 'autodescription' ); ?></a>
212
- </label>
213
- </span>
214
- <?php
215
- }
216
  ?>
217
  </p>
218
  </fieldset>
@@ -294,30 +322,6 @@ switch ( $instance ) :
294
  $this->wrap_fields( $home_publish_time_checkbox . $home_modify_time_checkbox, true );
295
  break;
296
 
297
- case 'the_seo_framework_social_metabox_relationships' :
298
-
299
- ?><h4><?php esc_html_e( 'Link Relationship Settings', 'autodescription' ); ?></h4><?php
300
- $this->description( __( 'Some Search Engines look for relations between the content of your pages. If you have multiple pages for a single Post or Page, or have archives indexed, this option will help Search Engines look for the right page to display in the Search Results.', 'autodescription' ) );
301
- $this->description( __( "It's recommended to turn this option on for better SEO consistency and to prevent duplicate content errors.", 'autodescription' ) );
302
-
303
- ?><hr><?php
304
-
305
- /* translators: %s = <code>rel</code> */
306
- $prev_next_posts_label = sprintf( esc_html__( 'Add %s link tags to Posts and Pages?', 'autodescription' ), $this->code_wrap( 'rel' ) );
307
- $prev_next_posts_checkbox = $this->make_checkbox( 'prev_next_posts', $prev_next_posts_label, '', false );
308
-
309
- /* translators: %s = <code>rel</code> */
310
- $prev_next_archives_label = sprintf( esc_html__( 'Add %s link tags to Archives?', 'autodescription' ), $this->code_wrap( 'rel' ) );
311
- $prev_next_archives_checkbox = $this->make_checkbox( 'prev_next_archives', $prev_next_archives_label, '', false );
312
-
313
- /* translators: %s = <code>rel</code> */
314
- $prev_next_frontpage_label = sprintf( esc_html__( 'Add %s link tags to the Home Page?', 'autodescription' ), $this->code_wrap( 'rel' ) );
315
- $prev_next_frontpage_checkbox = $this->make_checkbox( 'prev_next_frontpage', $prev_next_frontpage_label, '', false );
316
-
317
- //* Echo checkboxes.
318
- $this->wrap_fields( $prev_next_posts_checkbox . $prev_next_archives_checkbox . $prev_next_frontpage_checkbox, true );
319
- break;
320
-
321
  default :
322
  break;
323
  endswitch;
13
  * @since 2.2.2
14
  *
15
  * @param array $default_tabs { 'id' = The identifier =>
16
+ * array(
17
+ * 'name' => The name
18
+ * 'callback' => The callback function, use array for method calling
19
+ * 'dashicon' => Desired dashicon
20
+ * )
21
  * }
22
  */
23
  $default_tabs = array(
24
  'general' => array(
25
+ 'name' => __( 'General', 'autodescription' ),
26
+ 'callback' => array( $this, 'social_metabox_general_tab' ),
27
+ 'dashicon' => 'admin-generic',
28
  ),
29
  'facebook' => array(
30
+ 'name' => 'Facebook',
31
+ 'callback' => array( $this, 'social_metabox_facebook_tab' ),
32
+ 'dashicon' => 'facebook-alt',
33
  ),
34
  'twitter' => array(
35
+ 'name' => 'Twitter',
36
+ 'callback' => array( $this, 'social_metabox_twitter_tab' ),
37
+ 'dashicon' => 'twitter',
38
  ),
39
  'postdates' => array(
40
+ 'name' => __( 'Post Dates', 'autodescription' ),
41
+ 'callback' => array( $this, 'social_metabox_postdates_tab' ),
42
+ 'dashicon' => 'backup',
 
 
 
 
 
43
  ),
44
  );
45
 
57
 
58
  case 'the_seo_framework_social_metabox_general' :
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  ?>
 
 
61
  <h4><?php esc_html_e( 'Social Meta Tags Settings', 'autodescription' ); ?></h4>
62
  <?php
63
  $this->description( __( 'Output various meta tags for social site integration, among other 3rd party services.', 'autodescription' ) );
64
 
65
+ ?>
66
+ <hr>
67
+ <?php
68
 
69
  //* Echo Open Graph Tags checkboxes.
70
  $this->wrap_fields(
80
  if ( $this->detect_og_plugin() )
81
  $this->description( __( 'Note: Another Open Graph plugin has been detected.', 'autodescription' ) );
82
 
 
 
83
  //* Echo Facebook Tags checkbox.
84
  $this->wrap_fields(
85
  $this->make_checkbox(
91
  true
92
  );
93
 
 
 
94
  //* Echo Twitter Tags checkboxes.
95
  $this->wrap_fields(
96
  $this->make_checkbox(
102
  true
103
  );
104
 
105
+ if ( $this->detect_twitter_card_plugin() )
106
  $this->description( __( 'Note: Another Twitter Card plugin has been detected.', 'autodescription' ) );
107
+
108
+ ?>
109
+ <hr>
110
+
111
+ <h4><?php esc_html_e( 'Social Image Settings', 'autodescription' ); ?></h4>
112
+ <?php
113
+ $this->description( __( 'A social image can be displayed when your website is shared. They are a great way to grab attention.', 'autodescription' ) );
114
+
115
+ $image_placeholder = $this->get_image( 0, array( 'disallowed' => array( 'postmeta', 'featured' ) ), false );
116
+
117
+ ?>
118
+ <p>
119
+ <label for="tsf_fb_socialimage">
120
+ <strong><?php esc_html_e( 'Social Image Fallback URL', 'autodescription' ); ?></strong>
121
+ <a href="<?php echo esc_url( 'https://developers.facebook.com/docs/sharing/best-practices#images' ); ?>" target="_blank" title="<?php echo esc_attr__( 'Preferred Social Image fallback URL location', 'autodescription' ); ?>">[?]</a>
122
+ </label>
123
+ </p>
124
+ <p class="hide-if-no-js">
125
+ <?php
126
+ //* Already escaped.
127
+ echo $this->get_social_image_uploader_form( 'tsf_fb_socialimage' );
128
+ ?>
129
+ </p>
130
+ <p>
131
+ <input class="large-text" type="text" name="<?php $this->field_name( 'social_image_fb_url' ); ?>" id="tsf_fb_socialimage-url" placeholder="<?php echo esc_url( $image_placeholder ); ?>" value="<?php echo esc_url( $this->get_field_value( 'social_image_fb_url' ) ); ?>" />
132
+ <?php
133
+ /**
134
+ * Insert form element only if JS is active. If JS is inactive, then this will cause it to be emptied on $_POST
135
+ * @TODO use disabled and jQuery.removeprop( 'disabled' )?
136
+ */
137
+ ?>
138
+ <script>
139
+ document.getElementById( 'tsf_fb_socialimage-url' ).insertAdjacentHTML( 'afterend', '<input type="hidden" name="<?php $this->field_name( 'social_image_fb_id' ); ?>" id="tsf_fb_socialimage-id" value="<?php echo absint( $this->get_field_value( 'social_image_fb_id' ) ); ?>" />' );
140
+ </script>
141
+ </p>
142
+
143
+ <hr>
144
+
145
+ <h4><?php esc_html_e( 'Site Shortlink Settings', 'autodescription' ); ?></h4>
146
+ <?php
147
+ $this->description( __( 'The shortlink tag might have some use for 3rd party service discoverability, but it has little to no SEO value whatsoever.', 'autodescription' ) );
148
+
149
+ //* Echo checkboxes.
150
+ $this->wrap_fields(
151
+ $this->make_checkbox(
152
+ 'shortlink_tag',
153
+ __( 'Output shortlink tag?', 'autodescription' ),
154
+ '',
155
+ true
156
+ ),
157
+ true
158
+ );
159
  break;
160
 
161
  case 'the_seo_framework_social_metabox_facebook' :
230
 
231
  <p class="tsf-fields">
232
  <?php
233
+ foreach ( $twitter_card as $type => $name ) {
234
+ ?>
235
+ <span class="tsf-toblock">
236
+ <input type="radio" name="<?php $this->field_name( 'twitter_card' ); ?>" id="<?php $this->field_id( 'twitter_card_' . $type ); ?>" value="<?php echo esc_attr( $type ); ?>" <?php checked( $this->get_field_value( 'twitter_card' ), $type ); ?> />
237
+ <label for="<?php $this->field_id( 'twitter_card_' . $type ); ?>">
238
+ <span><?php echo $this->code_wrap( $name ); ?></span>
239
+ <a class="description" href="<?php echo esc_url( 'https://dev.twitter.com/cards/types/' . $name ); ?>" target="_blank" title="Twitter Card <?php echo esc_attr( $name ) . ' ' . esc_attr__( 'Example', 'autodescription' ); ?>"><?php esc_html_e( 'Example', 'autodescription' ); ?></a>
240
+ </label>
241
+ </span>
242
+ <?php
243
+ }
244
  ?>
245
  </p>
246
  </fieldset>
322
  $this->wrap_fields( $home_publish_time_checkbox . $home_modify_time_checkbox, true );
323
  break;
324
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  default :
326
  break;
327
  endswitch;
inc/views/metaboxes/title-metabox.php CHANGED
@@ -20,8 +20,8 @@ switch ( $instance ) :
20
  $blogname = $this->get_blogname();
21
  $sep = $this->get_separator( 'title' );
22
 
23
- $additions_left = '<span class="tsf-title-additions-js">' . $blogname . '<span class="autodescription-sep-js">' . " $sep " . '</span></span>';
24
- $additions_right = '<span class="tsf-title-additions-js"><span class="autodescription-sep-js">' . " $sep " . '</span>' . $blogname . '</span>';
25
 
26
  $example_left = '<em>' . $additions_left . $title . '</em>';
27
  $example_right = '<em>' . $title . $additions_right . '</em>';
@@ -49,37 +49,37 @@ switch ( $instance ) :
49
  * @since 2.2.2
50
  *
51
  * @param array $default_tabs { 'id' = The identifier =>
52
- * array(
53
- * 'name' => The name
54
- * 'callback' => The callback function, use array for method calling (accepts $this, but isn't used here for optimization purposes)
55
- * 'dashicon' => Desired dashicon
56
- * )
57
  * }
58
  */
59
  $default_tabs = array(
60
  'general' => array(
61
- 'name' => __( 'General', 'autodescription' ),
62
- 'callback' => array( $this, 'title_metabox_general_tab' ),
63
- 'dashicon' => 'admin-generic',
64
  ),
65
  'additions' => array(
66
- 'name' => __( 'Additions', 'autodescription' ),
67
- 'callback' => array( $this, 'title_metabox_additions_tab' ),
68
- 'dashicon' => 'plus',
69
- 'args' => array(
70
  'examples' => array(
71
- 'left' => $example_left,
72
  'right' => $example_right,
73
  ),
74
  ),
75
  ),
76
  'prefixes' => array(
77
- 'name' => __( 'Prefixes', 'autodescription' ),
78
- 'callback' => array( $this, 'title_metabox_prefixes_tab' ),
79
- 'dashicon' => 'plus-alt',
80
- 'args' => array(
81
  'additions' => array(
82
- 'left' => $additions_left,
83
  'right' => $additions_right,
84
  ),
85
  'showleft' => $showleft,
@@ -205,7 +205,7 @@ switch ( $instance ) :
205
 
206
  //* If cat is found, it will return its name. Otherwise it's an empty string.
207
  $cat_name = get_cat_name( $cat );
208
- $cat_name = $cat_name ? $cat_name : __( 'Example Category', 'autodescription' );
209
 
210
  $display_prefix = $this->is_option_checked( 'title_rem_prefixes' ) ? 'none' : 'inline';
211
  $title = '<span class="tsf-title-prefix-example" style="display:' . $display_prefix . '">' . esc_html( $label ) . ': </span>' . esc_html( $cat_name );
20
  $blogname = $this->get_blogname();
21
  $sep = $this->get_separator( 'title' );
22
 
23
+ $additions_left = '<span class="tsf-title-additions-js">' . $blogname . '<span class="tsf-sep-js">' . " $sep " . '</span></span>';
24
+ $additions_right = '<span class="tsf-title-additions-js"><span class="tsf-sep-js">' . " $sep " . '</span>' . $blogname . '</span>';
25
 
26
  $example_left = '<em>' . $additions_left . $title . '</em>';
27
  $example_right = '<em>' . $title . $additions_right . '</em>';
49
  * @since 2.2.2
50
  *
51
  * @param array $default_tabs { 'id' = The identifier =>
52
+ * array(
53
+ * 'name' => The name
54
+ * 'callback' => The callback function, use array for method calling
55
+ * 'dashicon' => Desired dashicon
56
+ * )
57
  * }
58
  */
59
  $default_tabs = array(
60
  'general' => array(
61
+ 'name' => __( 'General', 'autodescription' ),
62
+ 'callback' => array( $this, 'title_metabox_general_tab' ),
63
+ 'dashicon' => 'admin-generic',
64
  ),
65
  'additions' => array(
66
+ 'name' => __( 'Additions', 'autodescription' ),
67
+ 'callback' => array( $this, 'title_metabox_additions_tab' ),
68
+ 'dashicon' => 'plus',
69
+ 'args' => array(
70
  'examples' => array(
71
+ 'left' => $example_left,
72
  'right' => $example_right,
73
  ),
74
  ),
75
  ),
76
  'prefixes' => array(
77
+ 'name' => __( 'Prefixes', 'autodescription' ),
78
+ 'callback' => array( $this, 'title_metabox_prefixes_tab' ),
79
+ 'dashicon' => 'plus-alt',
80
+ 'args' => array(
81
  'additions' => array(
82
+ 'left' => $additions_left,
83
  'right' => $additions_right,
84
  ),
85
  'showleft' => $showleft,
205
 
206
  //* If cat is found, it will return its name. Otherwise it's an empty string.
207
  $cat_name = get_cat_name( $cat );
208
+ $cat_name = $cat_name ?: __( 'Example Category', 'autodescription' );
209
 
210
  $display_prefix = $this->is_option_checked( 'title_rem_prefixes' ) ? 'none' : 'inline';
211
  $title = '<span class="tsf-title-prefix-example" style="display:' . $display_prefix . '">' . esc_html( $label ) . ': </span>' . esc_html( $cat_name );
inc/views/sitemap/index.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Man cannot discover new oceans, unless he has the courage to lose sight of the shore.
4
+ *
5
+ * - Andre Gide
6
+ */
inc/views/sitemap/xsl-stylesheet.php ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Views\Sitemap
4
+ */
5
+
6
+ defined( 'ABSPATH' ) and $_this = the_seo_framework_class() and $this instanceof $_this or die;
7
+
8
+ $title = __( 'XML Sitemap', 'autodescription' );
9
+ if ( $this->add_title_additions() )
10
+ $title = $this->process_title_additions( $title, $this->get_blogname(), $this->get_title_seplocation( '', false ) );
11
+
12
+ if ( $this->is_option_checked( 'sitemap_logo' ) ) {
13
+
14
+ $logo = $this->can_use_logo() ? wp_get_attachment_image_src( get_theme_mod( 'custom_logo' ), array( 29, 29 ) ) : array();
15
+ /**
16
+ * Applies filters 'the_seo_framework_sitemap_logo' : array
17
+ * @since 2.8.0
18
+ */
19
+ $logo = (array) apply_filters( 'the_seo_framework_sitemap_logo', $logo );
20
+
21
+ if ( ! empty( $logo[0] ) ) {
22
+ $logo = sprintf( '<img src="%s" width="%s" height="%s" />', esc_url( $logo[0] ), esc_attr( $logo[1] ), esc_attr( $logo[2] ) );
23
+ } else {
24
+ $logo = '';
25
+ }
26
+ } else {
27
+ $logo = '';
28
+ }
29
+
30
+ $colors = $this->get_sitemap_colors();
31
+
32
+ /**
33
+ * Applies filters 'the_seo_framework_sitemap_color_main' : string
34
+ * @since 2.8.0
35
+ */
36
+ $sitemap_color_main = '#' . $this->s_color_hex( (string) apply_filters( 'the_seo_framework_sitemap_color_accent', $colors['main'] ) );
37
+
38
+ /**
39
+ * Applies filters 'the_seo_framework_sitemap_color_accent' : string
40
+ * @since 2.8.0
41
+ */
42
+ $sitemap_color_accent = '#' . $this->s_color_hex( (string) apply_filters( 'the_seo_framework_sitemap_color_main', $colors['accent'] ) );
43
+
44
+ /**
45
+ * Applies filters 'the_seo_framework_sitemap_relative_font_color' : string
46
+ * @since 2.8.0
47
+ */
48
+ $relative_font_color = '#' . $this->s_color_hex( (string) apply_filters( 'the_seo_framework_sitemap_relative_font_color', $this->get_relatitve_fontcolor( $sitemap_color_main ) ) );
49
+
50
+ /**
51
+ * Applies filters 'the_seo_framework_indicator_sitemap' : boolean
52
+ * @since 2.8.0
53
+ */
54
+ $indicator = (bool) apply_filters( 'the_seo_framework_indicator_sitemap', true );
55
+
56
+ $xml = '<?xml version="1.0" encoding="UTF-8"?>
57
+ <xsl:stylesheet version="2.0"
58
+ xmlns:html="http://www.w3.org/TR/REC-html40"
59
+ xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
60
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
61
+ <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
62
+ <xsl:template match="/">
63
+ <html xmlns="http://www.w3.org/1999/xhtml">
64
+ <head>
65
+ <title>' . esc_html( ent2ncr( $title ) ) . '</title>
66
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
67
+ <style type="text/css">
68
+ body {
69
+ font-size: 14px;
70
+ font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
71
+ margin: 0;
72
+ }
73
+ a {
74
+ color: #05809e;
75
+ text-decoration: none;
76
+ }
77
+ h1 {
78
+ font-size: 24px;
79
+ font-family: Verdana,Geneva,sans-serif;
80
+ font-weight: normal;
81
+ margin: 0;
82
+ color: ' . $sitemap_color_accent . ';
83
+ }
84
+ h1 img {
85
+ vertical-align: bottom;
86
+ margin-right: 14px;
87
+ }
88
+ #description {
89
+ background-color: ' . $sitemap_color_main . ';
90
+ border-bottom: 7px solid ' . $sitemap_color_accent . ';
91
+ color: ' . $relative_font_color . ';
92
+ padding: 30px 30px 20px;
93
+ }
94
+ #description a {
95
+ color: ' . $relative_font_color . ';
96
+ }
97
+ #content {
98
+ padding: 10px 30px 30px;
99
+ background: #fff;
100
+ }
101
+ a:hover {
102
+ border-bottom: 1px solid;
103
+ }
104
+ table {
105
+ min-width: 600px;
106
+ border-spacing: 0;
107
+ }
108
+ th, td {
109
+ font-size: 12px;
110
+ border: 0px solid;
111
+ padding: 10px 15px;
112
+ }
113
+ th {
114
+ text-align: left;
115
+ border-bottom: 1px solid ' . $sitemap_color_accent . ';
116
+ }
117
+ .odd {
118
+ background-color: #eaeaea;
119
+ }
120
+ #footer {
121
+ margin: 20px 30px;
122
+ font-size: 12px;
123
+ color: #999;
124
+ }
125
+ #footer a {
126
+ color: inherit;
127
+ }
128
+ #description a, #footer a {
129
+ border-bottom: 1px solid;
130
+ }
131
+ #description a:hover, #footer a:hover {
132
+ border-bottom: none;
133
+ }
134
+ </style>
135
+ </head>
136
+ <body>
137
+ <div id="description">
138
+ <a href="' . esc_url( ent2ncr( get_home_url() ) ) . '"><h1>' .
139
+ ent2ncr( $logo ) .
140
+ esc_html( ent2ncr( $this->get_blogname() . ' &mdash; ' . __( 'XML Sitemap', 'autodescription' ) ) ) . '</h1></a>
141
+ <p>' .
142
+ wp_kses(
143
+ ent2ncr(
144
+ $this->convert_markdown(
145
+ /* translators: URLs are in Markdown. */
146
+ __( 'This is a generated XML Sitemap, meant to be consumed by search engines like [Google](https://www.google.com/) or [Bing](https://www.bing.com/).', 'autodescription' ),
147
+ array( 'a' )
148
+ )
149
+ ),
150
+ array(
151
+ 'a' => array(
152
+ 'href' => true,
153
+ 'rel' => true,
154
+ ),
155
+ )
156
+ ) . '</p>
157
+ <p>' .
158
+ wp_kses(
159
+ ent2ncr(
160
+ $this->convert_markdown(
161
+ /* translators: URLs are in Markdown. */
162
+ __( 'You can find more information on XML sitemaps at [sitemaps.org](https://www.sitemaps.org/).', 'autodescription' ),
163
+ array( 'a' )
164
+ )
165
+ ),
166
+ array(
167
+ 'a' => array(
168
+ 'href' => true,
169
+ 'rel' => true,
170
+ ),
171
+ )
172
+ ) . '</p>
173
+ </div>
174
+ <div id="content">
175
+ <table>
176
+ <tr>
177
+ <th>' . esc_html( ent2ncr( __( 'URL', 'autodescription' ) ) ) . '</th>';
178
+
179
+ if ( $this->is_option_checked( 'sitemaps_modified' ) ) :
180
+ $xml .= '
181
+ <th>' . esc_html( ent2ncr( __( 'Last Updated', 'autodescription' ) ) ) . '</th>';
182
+ endif;
183
+
184
+ $xml .= '
185
+ <th>' . esc_html( ent2ncr( __( 'Priority', 'autodescription' ) ) ) . '</th>
186
+ </tr>
187
+ <xsl:variable name="lower" select="\'abcdefghijklmnopqrstuvwxyz\'"/>
188
+ <xsl:variable name="upper" select="\'ABCDEFGHIJKLMNOPQRSTUVWXYZ\'"/>
189
+ <xsl:for-each select="sitemap:urlset/sitemap:url">
190
+ <tr>
191
+ <xsl:choose>
192
+ <xsl:when test="position() mod 2 != 1">
193
+ <xsl:attribute name="class">odd</xsl:attribute>
194
+ </xsl:when>
195
+ </xsl:choose>
196
+ <td>
197
+ <xsl:variable name="itemURL">
198
+ <xsl:value-of select="sitemap:loc"/>
199
+ </xsl:variable>
200
+ <a href="{$itemURL}">
201
+ <xsl:value-of select="sitemap:loc"/>
202
+ </a>
203
+ </td>';
204
+
205
+ if ( $this->is_option_checked( 'sitemaps_modified' ) ) :
206
+ $xml .= '
207
+ <td>
208
+ <xsl:value-of select="concat(substring(sitemap:lastmod,0,11),concat(\' \', substring(sitemap:lastmod,12,5)))"/>
209
+ </td>';
210
+ endif;
211
+
212
+ $xml .= '
213
+ <td>
214
+ <xsl:value-of select="substring(sitemap:priority,0,4)"/>
215
+ </td>
216
+ </tr>
217
+ </xsl:for-each>
218
+ </table>
219
+ </div>
220
+ <div id="footer">';
221
+
222
+ if ( $indicator ) :
223
+ $xml .= '
224
+ <p>' .
225
+ wp_kses(
226
+ ent2ncr(
227
+ $this->convert_markdown(
228
+ /* translators: URLs are in Markdown. */
229
+ __( 'Generated by [The SEO Framework](https://wordpress.org/plugins/autodescription/)', 'autodescription' ),
230
+ array( 'a' )
231
+ )
232
+ ),
233
+ array(
234
+ 'a' => array(
235
+ 'href' => true,
236
+ 'rel' => true,
237
+ ),
238
+ )
239
+ ) . '</p>';
240
+ endif;
241
+
242
+ $xml .= '
243
+ </div>
244
+ </body>
245
+ </html>
246
+ </xsl:template>
247
+ </xsl:stylesheet>';
248
+
249
+ echo $xml;
language/autodescription.pot CHANGED
@@ -1,408 +1,415 @@
1
- # Copyright (C) 2016 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 2.7.0\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/autodescription\n"
7
- "POT-Creation-Date: 2016-09-09 18:15:47+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: 2016-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
- #: inc/classes/admin-init.class.php:232
16
  msgid "Good"
17
  msgstr ""
18
 
19
- #: inc/classes/admin-init.class.php:233
20
  msgid "Okay"
21
  msgstr ""
22
 
23
- #: inc/classes/admin-init.class.php:234
24
  msgid "Bad"
25
  msgstr ""
26
 
27
- #: inc/classes/admin-init.class.php:235
28
  msgid "Unknown"
29
  msgstr ""
30
 
31
- #: inc/classes/admin-init.class.php:316
32
  msgid "The changes you made will be lost if you navigate away from this page."
33
  msgstr ""
34
 
35
- #: inc/classes/admin-init.class.php:317
36
  msgid "Are you sure you want to reset all SEO settings to their defaults?"
37
  msgstr ""
38
 
39
- #: inc/classes/adminpages.class.php:123
40
  msgid "Save Settings"
41
  msgstr ""
42
 
43
- #: inc/classes/adminpages.class.php:124
44
  msgid "Reset Settings"
45
  msgstr ""
46
 
47
- #: inc/classes/adminpages.class.php:125
48
  msgid "Settings are saved."
49
  msgstr ""
50
 
51
- #: inc/classes/adminpages.class.php:126
52
  msgid "Settings are reset."
53
  msgstr ""
54
 
55
- #: inc/classes/adminpages.class.php:127
56
  msgid "Error saving settings."
57
  msgstr ""
58
 
59
- #: inc/classes/adminpages.class.php:128
60
  msgid "New SEO Settings have been updated."
61
  msgstr ""
62
 
63
- #: inc/classes/adminpages.class.php:144 inc/classes/core.class.php:181
64
- #: inc/classes/siteoptions.class.php:471
65
  msgid "SEO Settings"
66
  msgstr ""
67
 
68
- #: inc/classes/adminpages.class.php:145
69
  msgid "SEO"
70
  msgstr ""
71
 
72
- #: inc/classes/adminpages.class.php:275
 
 
 
 
73
  msgid "Title Settings"
74
  msgstr ""
75
 
76
- #: inc/classes/adminpages.class.php:286
77
  msgid "Description Meta Settings"
78
  msgstr ""
79
 
80
- #: inc/classes/adminpages.class.php:297
81
  msgid "Home Page Settings"
82
  msgstr ""
83
 
84
- #: inc/classes/adminpages.class.php:308
85
  msgid "Social Meta Settings"
86
  msgstr ""
87
 
88
- #: inc/classes/adminpages.class.php:319
89
- #: inc/views/metaboxes/knowledge-metabox.php:56
90
- msgid "Knowledge Graph Settings"
91
- msgstr ""
92
-
93
- #: inc/classes/adminpages.class.php:330
94
  msgid "Schema Settings"
95
  msgstr ""
96
 
97
- #: inc/classes/adminpages.class.php:341 inc/classes/inpost.class.php:414
98
- #: inc/classes/inpost.class.php:645
99
  msgid "Robots Meta Settings"
100
  msgstr ""
101
 
102
- #: inc/classes/adminpages.class.php:352
103
  msgid "Webmaster Meta Settings"
104
  msgstr ""
105
 
106
- #: inc/classes/adminpages.class.php:363
107
  msgid "Sitemap Settings"
108
  msgstr ""
109
 
110
- #: inc/classes/adminpages.class.php:374
111
  msgid "Feed Settings"
112
  msgstr ""
113
 
114
- #: inc/classes/core.class.php:183
115
  msgctxt "As in: The Plugin Home Page"
116
  msgid "Plugin Home"
117
  msgstr ""
118
 
119
- #: inc/classes/core.class.php:234
120
  msgid "Dismiss"
121
  msgstr ""
122
 
123
- #: inc/classes/core.class.php:368
124
  msgctxt "e.g. en for English, nl for Dutch, fi for Finish, de for German"
125
  msgid "en"
126
  msgstr ""
127
 
128
- #. translators: 1: Function name, 2: Plugin Version notification, 3:
129
- #. Replacement function
 
 
 
 
130
 
131
- #: inc/classes/debug.class.php:114
132
- msgid "%1$s is <strong>deprecated</strong> since version %2$s of The SEO Framework! Use %3$s instead."
133
  msgstr ""
134
 
135
- #. translators: 1: Function name, 2: Plugin Version notification
 
136
 
137
- #: inc/classes/debug.class.php:117
138
- msgid "%1$s is <strong>deprecated</strong> since version %2$s of The SEO Framework with no alternative available."
139
  msgstr ""
140
 
141
- #: inc/classes/debug.class.php:167
142
  msgid "(This message was added in version %s of The SEO Framework.)"
143
  msgstr ""
144
 
145
- #. translators: %s: Codex URL
 
146
 
147
- #: inc/classes/debug.class.php:169
148
- msgid "Please see <a href=\"%s\">Debugging in WordPress</a> for more information."
149
  msgstr ""
150
 
151
- #: inc/classes/debug.class.php:170
152
- msgid "https://codex.wordpress.org/Debugging_in_WordPress"
153
- msgstr ""
154
-
155
- #. translators: 1: Function name, 2: Message, 3: Plugin Version notification
156
-
157
- #: inc/classes/debug.class.php:173
158
- msgid "%1$s was called <strong>incorrectly</strong>. %2$s %3$s"
159
  msgstr ""
160
 
161
  #. translators: 1: Method or Property name, 2: Message
162
 
163
- #: inc/classes/debug.class.php:223
164
- msgid "%1$s is not <strong>accessible</strong>. %2$s"
165
  msgstr ""
166
 
167
- #: inc/classes/doingitright.class.php:101
168
  msgid "No Search"
169
  msgstr ""
170
 
171
- #: inc/classes/doingitright.class.php:302
172
  msgid "Refresh to see the SEO Bar status."
173
  msgstr ""
174
 
175
- #: inc/classes/doingitright.class.php:380
176
  msgid "Post"
177
  msgstr ""
178
 
179
- #: inc/classes/doingitright.class.php:384 inc/classes/inpost.class.php:273
180
- #: inc/classes/termdata.class.php:359
181
- #: inc/views/metaboxes/knowledge-metabox.php:147
182
  msgid "Page"
183
  msgstr ""
184
 
185
- #: inc/classes/doingitright.class.php:428
186
  msgid "Failed to fetch post ID."
187
  msgstr ""
188
 
189
  #. translators: %s = But or And
190
 
191
- #: inc/classes/doingitright.class.php:798
192
  msgid "%s the Title contains the Blogname multiple times."
193
  msgstr ""
194
 
195
  #. translators: 1: Word, 2: Occurences
196
 
197
- #: inc/classes/doingitright.class.php:969
198
  msgid "%1$s is used %2$d times."
199
  msgstr ""
200
 
201
- #: inc/classes/doingitright.class.php:1013
 
 
202
  msgid "%s is being indexed."
203
  msgstr ""
204
 
205
- #: inc/classes/doingitright.class.php:1022
206
- msgid "But you've disabled indexing for the whole site."
207
  msgstr ""
208
 
209
  #. translators: 1: But or And, 2: Current taxonomy term plural label
210
 
211
- #: inc/classes/doingitright.class.php:1046
212
- msgid "%1$s indexing for %2$s have been disabled."
 
 
 
 
 
 
213
  msgstr ""
214
 
215
  #. translators: %s = But or And
216
 
217
- #: inc/classes/doingitright.class.php:1056
218
  msgid "%s the blog isn't set to public. This means WordPress discourages indexing."
219
  msgstr ""
220
 
221
  #. translators: %s = But or And
222
 
223
- #: inc/classes/doingitright.class.php:1070
224
- msgid "%s there are no posts in this term; therefore, indexing has been disabled."
225
  msgstr ""
226
 
227
- #: inc/classes/doingitright.class.php:1154
228
  msgid "%s links aren't being followed."
229
  msgstr ""
230
 
231
- #: inc/classes/doingitright.class.php:1160
232
  msgid "%s links are being followed."
233
  msgstr ""
234
 
235
  #. translators: %s = But or And
236
 
237
- #: inc/classes/doingitright.class.php:1172
238
- msgid "%s you've disabled the following of links for the whole site."
239
  msgstr ""
240
 
241
  #. translators: 1: But or And, 2: Current taxonomy term plural label
242
 
243
- #: inc/classes/doingitright.class.php:1198
244
- msgid "%1$s following for %2$s have been disabled."
245
  msgstr ""
246
 
247
  #. translators: %s = But or And
248
 
249
- #: inc/classes/doingitright.class.php:1210
250
  msgid "%s the blog isn't set to public. This means WordPress allows the links to be followed regardless."
251
  msgstr ""
252
 
253
- #: inc/classes/doingitright.class.php:1262
254
- msgid "Search Engine aren't allowed to archive this %s."
255
  msgstr ""
256
 
257
- #: inc/classes/doingitright.class.php:1267
258
- msgid "Search Engine are allowed to archive this %s."
259
  msgstr ""
260
 
261
- #: inc/classes/doingitright.class.php:1279
262
- msgid "But you've disabled archiving for the whole site."
263
  msgstr ""
264
 
265
  #. translators: 1: But or And, 2: Current taxonomy term plural label
266
 
267
- #: inc/classes/doingitright.class.php:1305
268
- msgid "%1$s archiving for %2$s have been disabled."
269
  msgstr ""
270
 
271
  #. translators: %s = But or And
272
 
273
- #: inc/classes/doingitright.class.php:1318
274
  msgid "%s the blog isn't set to public. This means WordPress allows the blog to be archived regardless."
275
  msgstr ""
276
 
277
- #: inc/classes/doingitright.class.php:1364
278
  msgid "%s isn't being redirected."
279
  msgstr ""
280
 
281
- #: inc/classes/doingitright.class.php:1406
282
- #: inc/classes/doingitright.class.php:1435
283
  msgid "%s is being redirected. This means no SEO values have to be set."
284
  msgstr ""
285
 
286
- #: inc/classes/doingitright.class.php:1409
287
- #: inc/classes/doingitright.class.php:1451
288
  msgid "%s is not being indexed. This means no SEO values have to be set."
289
  msgstr ""
290
 
291
- #: inc/classes/doingitright.class.php:1565
292
  msgid "Title:"
293
  msgstr ""
294
 
295
- #: inc/classes/doingitright.class.php:1566
296
  msgid "Description:"
297
  msgstr ""
298
 
299
- #: inc/classes/doingitright.class.php:1567
300
  msgid "Index:"
301
  msgstr ""
302
 
303
- #: inc/classes/doingitright.class.php:1568
304
  msgid "Follow:"
305
  msgstr ""
306
 
307
- #: inc/classes/doingitright.class.php:1569
308
  msgid "Archive:"
309
  msgstr ""
310
 
311
- #: inc/classes/doingitright.class.php:1570
312
  msgid "Redirect:"
313
  msgstr ""
314
 
315
- #: inc/classes/doingitright.class.php:1572
316
  msgid "Generated: Automatically generated."
317
  msgstr ""
318
 
319
- #: inc/classes/doingitright.class.php:1574
320
  msgctxt "Generated"
321
  msgid "G"
322
  msgstr ""
323
 
324
- #: inc/classes/doingitright.class.php:1575
325
  msgctxt "Title"
326
  msgid "T"
327
  msgstr ""
328
 
329
- #: inc/classes/doingitright.class.php:1576
330
  msgctxt "Description"
331
  msgid "D"
332
  msgstr ""
333
 
334
- #: inc/classes/doingitright.class.php:1577
335
  msgctxt "no-Index"
336
  msgid "I"
337
  msgstr ""
338
 
339
- #: inc/classes/doingitright.class.php:1578
340
  msgctxt "no-Follow"
341
  msgid "F"
342
  msgstr ""
343
 
344
- #: inc/classes/doingitright.class.php:1579
345
  msgctxt "no-Archive"
346
  msgid "A"
347
  msgstr ""
348
 
349
- #: inc/classes/doingitright.class.php:1580
350
  msgctxt "Redirect"
351
  msgid "R"
352
  msgstr ""
353
 
354
- #: inc/classes/doingitright.class.php:1582
355
  msgctxt "But there are..."
356
  msgid "But"
357
  msgstr ""
358
 
359
- #: inc/classes/doingitright.class.php:1583
360
  msgctxt "And there are..."
361
  msgid "And"
362
  msgstr ""
363
 
364
- #: inc/classes/doingitright.class.php:1585
365
  msgid "Length is far too short."
366
  msgstr ""
367
 
368
- #: inc/classes/doingitright.class.php:1586
369
  msgid "Length is too short."
370
  msgstr ""
371
 
372
- #: inc/classes/doingitright.class.php:1587
373
  msgid "Length is too long."
374
  msgstr ""
375
 
376
- #: inc/classes/doingitright.class.php:1588
377
  msgid "Length is far too long."
378
  msgstr ""
379
 
380
- #: inc/classes/doingitright.class.php:1589
381
  msgid "Length is good."
382
  msgstr ""
383
 
384
- #: inc/classes/feed.class.php:147
385
  msgctxt "The content source"
386
  msgid "Source"
387
  msgstr ""
388
 
389
- #. translators: 1: Title, 2: on, 3: Blogname
390
 
391
- #: inc/classes/generate-description.class.php:464
392
- msgctxt "1: Title, 2: on, 3: Blogname"
393
  msgid "%1$s %2$s %3$s"
394
  msgstr ""
395
 
396
- #. translators: 1: Title, 2: Separator, 3: Excerpt
397
 
398
- #: inc/classes/generate-description.class.php:468
399
- msgctxt "1: Title, 2: Separator, 3: Excerpt"
400
  msgid "%1$s %2$s %3$s"
401
  msgstr ""
402
 
403
  #. translators: Front-end output.
404
 
405
- #: inc/classes/generate-description.class.php:605
406
  #: inc/views/metaboxes/description-metabox.php:18
407
  msgctxt "Placement. e.g. Post Title \"on\" Blog Name"
408
  msgid "on"
@@ -410,323 +417,356 @@ msgstr ""
410
 
411
  #. translators: Front-end output.
412
 
413
- #: inc/classes/generate-description.class.php:668
414
  msgid "Latest posts:"
415
  msgstr ""
416
 
 
 
 
 
 
417
  #. translators: Front-end output. 1: Taxonomy singular name, 2: Current
418
  #. taxonomy term
419
 
420
- #: inc/classes/generate-title.class.php:833
421
- #: inc/classes/generate-title.class.php:893
422
  msgid "%1$s: %2$s"
423
  msgstr ""
424
 
425
  #. translators: Front-end output.
426
 
427
- #: inc/classes/generate-title.class.php:837
428
  msgid "Author: %s"
429
  msgstr ""
430
 
431
  #. translators: Front-end output.
432
 
433
- #: inc/classes/generate-title.class.php:841
434
  msgctxt "yearly archives date format"
435
  msgid "Y"
436
  msgstr ""
437
 
438
  #. translators: Front-end output.
439
 
440
- #: inc/classes/generate-title.class.php:843
441
  msgid "Year: %s"
442
  msgstr ""
443
 
444
  #. translators: Front-end output.
445
 
446
- #: inc/classes/generate-title.class.php:846
447
  msgctxt "monthly archives date format"
448
  msgid "F Y"
449
  msgstr ""
450
 
451
  #. translators: Front-end output.
452
 
453
- #: inc/classes/generate-title.class.php:848
454
  msgid "Month: %s"
455
  msgstr ""
456
 
457
  #. translators: Front-end output.
458
 
459
- #: inc/classes/generate-title.class.php:851
460
  msgctxt "daily archives date format"
461
  msgid "F j, Y"
462
  msgstr ""
463
 
464
  #. translators: Front-end output.
465
 
466
- #: inc/classes/generate-title.class.php:853
467
  msgid "Day: %s"
468
  msgstr ""
469
 
470
  #. translators: Front-end output.
471
 
472
- #: inc/classes/generate-title.class.php:858
473
  msgctxt "post format archive title"
474
  msgid "Asides"
475
  msgstr ""
476
 
477
  #. translators: Front-end output.
478
 
479
- #: inc/classes/generate-title.class.php:861
480
  msgctxt "post format archive title"
481
  msgid "Galleries"
482
  msgstr ""
483
 
484
  #. translators: Front-end output.
485
 
486
- #: inc/classes/generate-title.class.php:864
487
  msgctxt "post format archive title"
488
  msgid "Images"
489
  msgstr ""
490
 
491
  #. translators: Front-end output.
492
 
493
- #: inc/classes/generate-title.class.php:867
494
  msgctxt "post format archive title"
495
  msgid "Videos"
496
  msgstr ""
497
 
498
  #. translators: Front-end output.
499
 
500
- #: inc/classes/generate-title.class.php:870
501
  msgctxt "post format archive title"
502
  msgid "Quotes"
503
  msgstr ""
504
 
505
  #. translators: Front-end output.
506
 
507
- #: inc/classes/generate-title.class.php:873
508
  msgctxt "post format archive title"
509
  msgid "Links"
510
  msgstr ""
511
 
512
  #. translators: Front-end output.
513
 
514
- #: inc/classes/generate-title.class.php:876
515
  msgctxt "post format archive title"
516
  msgid "Statuses"
517
  msgstr ""
518
 
519
  #. translators: Front-end output.
520
 
521
- #: inc/classes/generate-title.class.php:879
522
  msgctxt "post format archive title"
523
  msgid "Audio"
524
  msgstr ""
525
 
526
  #. translators: Front-end output.
527
 
528
- #: inc/classes/generate-title.class.php:882
529
  msgctxt "post format archive title"
530
  msgid "Chats"
531
  msgstr ""
532
 
533
  #. translators: Front-end output.
534
 
535
- #: inc/classes/generate-title.class.php:887
536
  msgid "Archives: %s"
537
  msgstr ""
538
 
539
  #. translators: Front-end output.
540
 
541
- #: inc/classes/generate-title.class.php:897
542
  msgid "Archives"
543
  msgstr ""
544
 
545
  #. translators: Front-end output.
546
 
547
- #: inc/classes/generate-title.class.php:998
548
  msgid "Untitled"
549
  msgstr ""
550
 
551
  #. translators: Front-end output.
552
 
553
- #: inc/classes/generate-title.class.php:1033
554
  msgid "Search results for:"
555
  msgstr ""
556
 
557
  #. translators: Front-end output
558
 
559
- #: inc/classes/generate-title.class.php:1206
560
  msgid "Protected: %s"
561
  msgstr ""
562
 
563
  #. translators: Front-end output
564
 
565
- #: inc/classes/generate-title.class.php:1210
566
  msgid "Private: %s"
567
  msgstr ""
568
 
569
  #. translators: Front-end output.
570
 
571
- #: inc/classes/generate-title.class.php:1242
572
  msgid "Page %s"
573
  msgstr ""
574
 
575
- #: inc/classes/init.class.php:326
576
  msgid "Start The Seo Framework"
577
  msgstr ""
578
 
579
- #: inc/classes/init.class.php:327
580
  msgid "End The Seo Framework"
581
  msgstr ""
582
 
583
- #: inc/classes/init.class.php:328
584
  msgid "by Sybre Waaijer"
585
  msgstr ""
586
 
587
- #: inc/classes/inpost.class.php:186 inc/classes/inpost.class.php:364
588
  msgid "%s SEO Settings"
589
  msgstr ""
590
 
591
- #: inc/classes/inpost.class.php:371 inc/classes/inpost.class.php:444
592
- #: inc/classes/inpost.class.php:600 inc/classes/inpost.class.php:696
593
- msgid "Doing it Right"
594
  msgstr ""
595
 
596
- #: inc/classes/inpost.class.php:381
597
- msgid "%s Title"
598
  msgstr ""
599
 
600
- #: inc/classes/inpost.class.php:382 inc/classes/inpost.class.php:607
601
- #: inc/views/metaboxes/homepage-metabox.php:196
602
- msgid "Recommended Length: 50 to 55 characters"
603
  msgstr ""
604
 
605
- #: inc/classes/inpost.class.php:391 inc/classes/inpost.class.php:407
606
- #: inc/classes/inpost.class.php:609 inc/classes/inpost.class.php:626
607
- #: inc/views/metaboxes/homepage-metabox.php:198
608
- #: inc/views/metaboxes/homepage-metabox.php:219
609
- msgid "Characters Used: %s"
610
  msgstr ""
611
 
612
- #: inc/classes/inpost.class.php:400
613
- msgid "%s Meta Description"
614
  msgstr ""
615
 
616
- #: inc/classes/inpost.class.php:401 inc/classes/inpost.class.php:624
617
- #: inc/views/metaboxes/homepage-metabox.php:217
618
- msgid "Recommended Length: 145 to 155 characters"
619
  msgstr ""
620
 
621
- #: inc/classes/inpost.class.php:417 inc/classes/inpost.class.php:424
622
- #: inc/classes/inpost.class.php:431
623
- msgid "Apply %s to this term?"
624
  msgstr ""
625
 
626
- #: inc/classes/inpost.class.php:418
627
- #: inc/views/metaboxes/homepage-metabox.php:316
628
- msgid "Tell Search Engines not to show this page in their search results"
629
  msgstr ""
630
 
631
- #: inc/classes/inpost.class.php:425
632
- #: inc/views/metaboxes/homepage-metabox.php:326
633
- msgid "Tell Search Engines not to follow links on this page"
634
  msgstr ""
635
 
636
- #: inc/classes/inpost.class.php:432
637
- #: inc/views/metaboxes/homepage-metabox.php:336
638
- msgid "Tell Search Engines not to save a cached copy of this page"
 
 
 
639
  msgstr ""
640
 
641
- #: inc/classes/inpost.class.php:606
642
- #: inc/views/metaboxes/homepage-metabox.php:195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
643
  msgid "Custom %s Title"
644
  msgstr ""
645
 
646
- #: inc/classes/inpost.class.php:623
647
- #: inc/views/metaboxes/homepage-metabox.php:216
 
 
 
 
 
 
 
 
 
 
 
 
648
  msgid "Custom %s Description"
649
  msgstr ""
650
 
651
- #: inc/classes/inpost.class.php:637
 
 
 
 
 
 
 
 
 
 
 
 
 
652
  msgid "Custom Canonical URL"
653
  msgstr ""
654
 
655
- #: inc/classes/inpost.class.php:638
656
  msgid "Preferred %s URL location"
657
  msgstr ""
658
 
659
  #. translators: 1: Option, 2: Post or Page
660
 
661
- #: inc/classes/inpost.class.php:650 inc/classes/inpost.class.php:660
662
- #: inc/classes/inpost.class.php:670
663
  msgid "Apply %1$s to this %2$s"
664
  msgstr ""
665
 
666
- #: inc/classes/inpost.class.php:652
667
  msgid "Tell Search Engines not to show this %s in their search results"
668
  msgstr ""
669
 
670
- #: inc/classes/inpost.class.php:662
671
  msgid "Tell Search Engines not to follow links on this %s"
672
  msgstr ""
673
 
674
- #: inc/classes/inpost.class.php:672
675
  msgid "Tell Search Engines not to save a cached copy of this %s"
676
  msgstr ""
677
 
678
- #: inc/classes/inpost.class.php:676
679
  msgid "Local Search Settings"
680
  msgstr ""
681
 
682
- #: inc/classes/inpost.class.php:679
683
  msgid "Exclude this %s from local search"
684
  msgstr ""
685
 
686
- #: inc/classes/inpost.class.php:680
687
  msgid "This excludes this %s from local on-site search results"
688
  msgstr ""
689
 
690
- #: inc/classes/inpost.class.php:686
691
  msgid "Custom 301 Redirect URL"
692
  msgstr ""
693
 
694
- #: inc/classes/inpost.class.php:687
695
  msgid "This will force visitors to go to another URL"
696
  msgstr ""
697
 
698
- #: inc/classes/sitemaps.class.php:287
699
- msgid "Sitemap is generated for this view"
700
- msgstr ""
701
-
702
- #: inc/classes/sitemaps.class.php:289
703
- msgid "Sitemap is served from cache"
704
- msgstr ""
705
-
706
- #: inc/classes/sitemaps.class.php:407
707
- msgid "Sitemap is generated on"
708
  msgstr ""
709
 
710
- #: inc/classes/siteoptions.class.php:471
711
- msgid "here"
712
  msgstr ""
713
 
714
- #: inc/classes/siteoptions.class.php:472
715
- msgctxt "%s = here"
716
- msgid "View the new options %s."
717
  msgstr ""
718
 
719
- #: inc/classes/termdata.class.php:361
720
- #: inc/views/metaboxes/social-metabox.php:248
721
- msgid "Pages"
722
  msgstr ""
723
 
724
- #: inc/classes/transients.class.php:263
725
- msgid "Third parameter must be a known type."
 
726
  msgstr ""
727
 
728
- #: inc/deprecated/deprecated.class.php:627
729
- msgid "%s of The SEO Framework"
 
730
  msgstr ""
731
 
732
  #: inc/views/metaboxes/description-metabox.php:17
@@ -742,7 +782,7 @@ msgid "Automated Description Settings"
742
  msgstr ""
743
 
744
  #: inc/views/metaboxes/description-metabox.php:42
745
- #: inc/views/metaboxes/homepage-metabox.php:228
746
  msgid "The meta description can be used to determine the text used under the title on Search Engine results pages."
747
  msgstr ""
748
 
@@ -751,9 +791,9 @@ msgid "Example Automated Description Output"
751
  msgstr ""
752
 
753
  #: inc/views/metaboxes/description-metabox.php:67
754
- #: inc/views/metaboxes/homepage-metabox.php:30
755
- #: inc/views/metaboxes/knowledge-metabox.php:26
756
  #: inc/views/metaboxes/robots-metabox.php:57
 
757
  #: inc/views/metaboxes/sitemaps-metabox.php:38
758
  #: inc/views/metaboxes/social-metabox.php:25
759
  #: inc/views/metaboxes/title-metabox.php:61
@@ -761,17 +801,12 @@ msgid "General"
761
  msgstr ""
762
 
763
  #: inc/views/metaboxes/description-metabox.php:72
764
- #: inc/views/metaboxes/homepage-metabox.php:35
765
  #: inc/views/metaboxes/title-metabox.php:66
766
  msgid "Additions"
767
  msgstr ""
768
 
769
- #: inc/views/metaboxes/description-metabox.php:98
770
- #: inc/views/metaboxes/title-metabox.php:105
771
- msgid "Recommended"
772
- msgstr ""
773
-
774
- #: inc/views/metaboxes/description-metabox.php:102
775
  msgid "Description Excerpt Separator"
776
  msgstr ""
777
 
@@ -866,189 +901,272 @@ msgctxt "%s = here"
866
  msgid "The feed can be found %s."
867
  msgstr ""
868
 
869
- #: inc/views/metaboxes/homepage-metabox.php:11
870
- msgid "These settings will take precedence over the settings set within the Home Page edit screen, if any."
871
  msgstr ""
872
 
873
- #: inc/views/metaboxes/homepage-metabox.php:40
874
- msgid "Robots"
875
  msgstr ""
876
 
877
- #: inc/views/metaboxes/homepage-metabox.php:68
878
- msgid "Title"
879
  msgstr ""
880
 
881
- #: inc/views/metaboxes/homepage-metabox.php:69
882
- msgid "Description"
883
  msgstr ""
884
 
885
- #: inc/views/metaboxes/homepage-metabox.php:70
886
- #: inc/views/metaboxes/homepage-metabox.php:246
887
- #: inc/views/metaboxes/homepage-metabox.php:285
888
- #: inc/views/metaboxes/social-metabox.php:250
889
- #: inc/views/metaboxes/social-metabox.php:281
890
- msgid "Home Page"
891
  msgstr ""
892
 
893
- #. translators: 1: Option, 2: Page SEO Settings, 3: Home Page
 
 
894
 
895
- #: inc/views/metaboxes/homepage-metabox.php:108
896
- #: inc/views/metaboxes/homepage-metabox.php:167
897
- msgid "Note: The %1$s is fetched from the %2$s on the %3$s."
898
  msgstr ""
899
 
900
- #: inc/views/metaboxes/homepage-metabox.php:108
901
- #: inc/views/metaboxes/homepage-metabox.php:165
902
- msgid "Page SEO Settings"
903
  msgstr ""
904
 
905
- #: inc/views/metaboxes/homepage-metabox.php:184
906
- msgid "Custom %s Title Tagline"
907
  msgstr ""
908
 
909
- #: inc/views/metaboxes/homepage-metabox.php:250
910
- #: inc/views/metaboxes/title-metabox.php:132
911
- msgid "Document Title Additions Location"
912
  msgstr ""
913
 
914
- #: inc/views/metaboxes/homepage-metabox.php:251
915
- #: inc/views/metaboxes/title-metabox.php:134
916
- msgid "Determines which side the added title text will go on."
917
  msgstr ""
918
 
919
- #: inc/views/metaboxes/homepage-metabox.php:257
920
- #: inc/views/metaboxes/title-metabox.php:140
921
- msgid "Left:"
922
  msgstr ""
923
 
924
- #: inc/views/metaboxes/homepage-metabox.php:264
925
- #: inc/views/metaboxes/title-metabox.php:147
926
- msgid "Right:"
927
  msgstr ""
928
 
929
- #: inc/views/metaboxes/homepage-metabox.php:272
930
- msgid "%s Tagline"
931
  msgstr ""
932
 
933
- #: inc/views/metaboxes/homepage-metabox.php:276
934
- msgid "Add site description (tagline) to the Title on the %s?"
935
  msgstr ""
936
 
937
- #: inc/views/metaboxes/homepage-metabox.php:302
938
- msgid "View Home Page Settings"
939
  msgstr ""
940
 
941
- #: inc/views/metaboxes/homepage-metabox.php:302
942
- msgid "Checked in Page"
943
  msgstr ""
944
 
945
- #: inc/views/metaboxes/homepage-metabox.php:305
946
- msgid "Home Page Robots Meta Settings"
947
  msgstr ""
948
 
949
- #. translators: 1: Option, 2: Location
 
 
950
 
951
- #: inc/views/metaboxes/homepage-metabox.php:313
952
- #: inc/views/metaboxes/homepage-metabox.php:323
953
- #: inc/views/metaboxes/homepage-metabox.php:333
954
- msgid "Apply %1$s to the %2$s?"
955
  msgstr ""
956
 
957
- #: inc/views/metaboxes/homepage-metabox.php:368
958
- msgid "Note: If any of these options are unchecked, but are checked on the Home Page, they will be outputted regardless."
959
  msgstr ""
960
 
961
- #: inc/views/metaboxes/homepage-metabox.php:374
962
- msgid "Home Page Pagination Robots Settings"
963
  msgstr ""
964
 
965
- #: inc/views/metaboxes/homepage-metabox.php:375
966
- msgid "If your Home Page is paginated and outputs content that's also found elsewhere on the website, enabling this option might prevent duplicate content."
967
  msgstr ""
968
 
969
- #. translators: 1: Option, 2: Location
 
 
970
 
971
- #: inc/views/metaboxes/homepage-metabox.php:383
972
- msgid "Apply %1$s to every second or later page on the %2$s?"
973
  msgstr ""
974
 
975
- #: inc/views/metaboxes/knowledge-metabox.php:31
976
- msgid "Website"
977
  msgstr ""
978
 
979
- #: inc/views/metaboxes/knowledge-metabox.php:57
980
- msgid "The Knowledge Graph lets Google and other Search Engines know where to find you or your organization and its relevant content."
981
  msgstr ""
982
 
983
- #: inc/views/metaboxes/knowledge-metabox.php:58
984
- msgid "Google is becoming more of an 'Answer Engine' than a 'Search Engine'. Setting up these options could have a positive impact on the SEO value of your website."
985
  msgstr ""
986
 
987
- #: inc/views/metaboxes/knowledge-metabox.php:64
988
- msgid "Output Knowledge tags?"
989
  msgstr ""
990
 
991
- #: inc/views/metaboxes/knowledge-metabox.php:74
992
- msgid "Website logo"
 
993
  msgstr ""
994
 
995
- #: inc/views/metaboxes/knowledge-metabox.php:80
996
- msgid "Use the Favicon from Customizer as the Organization Logo?"
997
  msgstr ""
998
 
999
- #: inc/views/metaboxes/knowledge-metabox.php:81
1000
- msgid "This option only has an effect when this site represents an Organization. If left disabled, Search Engines will look elsewhere for a logo, if it exists and is assigned as a logo."
1001
  msgstr ""
1002
 
1003
- #: inc/views/metaboxes/knowledge-metabox.php:92
1004
- msgid "About this website"
1005
  msgstr ""
1006
 
1007
- #: inc/views/metaboxes/knowledge-metabox.php:93
1008
- msgid "Who or what is your website about?"
1009
  msgstr ""
1010
 
1011
- #: inc/views/metaboxes/knowledge-metabox.php:99
1012
- msgctxt "...Organization or Person."
1013
- msgid "This website represents:"
 
1014
  msgstr ""
1015
 
1016
- #: inc/views/metaboxes/knowledge-metabox.php:105
1017
- msgid "An Organization"
 
 
1018
  msgstr ""
1019
 
1020
- #: inc/views/metaboxes/knowledge-metabox.php:106
1021
- msgid "A Person"
 
 
1022
  msgstr ""
1023
 
1024
- #: inc/views/metaboxes/knowledge-metabox.php:119
1025
- msgid "The organization or personal name"
1026
  msgstr ""
1027
 
1028
- #: inc/views/metaboxes/knowledge-metabox.php:130
1029
- msgid "Social Pages connected to this website"
1030
  msgstr ""
1031
 
1032
- #: inc/views/metaboxes/knowledge-metabox.php:131
1033
- 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."
1034
  msgstr ""
1035
 
1036
- #: inc/views/metaboxes/knowledge-metabox.php:132
1037
- msgid "Add the link that leads directly to the social page of this website."
1038
  msgstr ""
1039
 
1040
- #: inc/views/metaboxes/knowledge-metabox.php:136
1041
- msgctxt "No spaces. E.g. https://facebook.com/RelatedProfile"
1042
- msgid "RelatedProfile"
 
 
 
1043
  msgstr ""
1044
 
1045
- #: inc/views/metaboxes/knowledge-metabox.php:137
1046
- msgctxt "Social Profile"
1047
- msgid "Profile"
1048
  msgstr ""
1049
 
1050
- #: inc/views/metaboxes/knowledge-metabox.php:203
1051
- msgid "Blog"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1052
  msgstr ""
1053
 
1054
  #: inc/views/metaboxes/robots-metabox.php:13
@@ -1162,78 +1280,181 @@ msgstr ""
1162
  msgid "Apply %1$s to %2$s Archives?"
1163
  msgstr ""
1164
 
1165
- #: inc/views/metaboxes/schema-metabox.php:11
1166
  msgid "Schema.org Output Settings"
1167
  msgstr ""
1168
 
1169
- #: inc/views/metaboxes/schema-metabox.php:14
1170
  msgid "Another Schema.org plugin has been detected."
1171
  msgstr ""
1172
 
1173
- #: inc/views/metaboxes/schema-metabox.php:16
1174
  msgid "The Schema.org markup is a standard way of annotating structured data for Search Engines. This markup is represented within hidden scripts throughout the website."
1175
  msgstr ""
1176
 
1177
- #: inc/views/metaboxes/schema-metabox.php:17
1178
  msgid "When your web pages include structured data markup, Search Engines can use that data to index your content better, present it more prominently in Search Results, and use it in several different applications."
1179
  msgstr ""
1180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1181
  #. translators:
1182
  #. https:developers.google.com/search/docs/data-types/sitelinks-searchbox
1183
 
1184
- #: inc/views/metaboxes/schema-metabox.php:23
1185
- #: inc/views/metaboxes/schema-metabox.php:27
1186
  msgctxt "Product name"
1187
  msgid "Sitelinks Searchbox"
1188
  msgstr ""
1189
 
1190
- #: inc/views/metaboxes/schema-metabox.php:24
1191
- msgid "When Search users search for your brand name, the following option allows them to search through your website directly from the Search Results."
1192
  msgstr ""
1193
 
1194
- #: inc/views/metaboxes/schema-metabox.php:34
1195
  msgctxt "Product name"
1196
  msgid "Enable Sitelinks Searchbox?"
1197
  msgstr ""
1198
 
1199
- #: inc/views/metaboxes/schema-metabox.php:44
1200
- msgid "Site Name"
1201
  msgstr ""
1202
 
1203
- #: inc/views/metaboxes/schema-metabox.php:45
1204
- msgid "When using breadcrumbs, the first entry is by default your website's address. Using the following option will convert it to the Site Name."
1205
  msgstr ""
1206
 
1207
- #: inc/views/metaboxes/schema-metabox.php:48
1208
- msgid "Include your Site Name in Search Results"
1209
  msgstr ""
1210
 
1211
- #: inc/views/metaboxes/schema-metabox.php:55
1212
- msgid "Convert URL to Site Name?"
1213
  msgstr ""
1214
 
1215
- #: inc/views/metaboxes/schema-metabox.php:56
1216
- msgid "The Site Name is: %s"
1217
  msgstr ""
1218
 
1219
- #: inc/views/metaboxes/schema-metabox.php:65
1220
- msgid "Breadcrumbs"
1221
  msgstr ""
1222
 
1223
- #: inc/views/metaboxes/schema-metabox.php:66
1224
- msgid "Breadcrumb trails indicate the page's position in the site hierarchy. Using the following option will show the hierarchy within the Search Results when available."
1225
  msgstr ""
1226
 
1227
- #: inc/views/metaboxes/schema-metabox.php:69
1228
- msgid "About Breadcrumbs"
1229
  msgstr ""
1230
 
1231
- #: inc/views/metaboxes/schema-metabox.php:76
1232
- msgid "Enable Breadcrumbs?"
1233
  msgstr ""
1234
 
1235
- #: inc/views/metaboxes/schema-metabox.php:77
1236
- msgid "Multiple trails can be outputted. The longest trail is prioritized."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1237
  msgstr ""
1238
 
1239
  #: inc/views/metaboxes/sitemaps-metabox.php:14
@@ -1241,8 +1462,8 @@ msgid "Permalink Settings"
1241
  msgstr ""
1242
 
1243
  #: inc/views/metaboxes/sitemaps-metabox.php:14
1244
- #: inc/views/metaboxes/sitemaps-metabox.php:134
1245
- #: inc/views/metaboxes/sitemaps-metabox.php:143
1246
  msgctxt "The sitemap can be found %s."
1247
  msgid "here"
1248
  msgstr ""
@@ -1269,51 +1490,59 @@ msgctxt "Ping or notify Search Engine"
1269
  msgid "Ping"
1270
  msgstr ""
1271
 
1272
- #: inc/views/metaboxes/sitemaps-metabox.php:106
 
 
 
 
1273
  msgid "Sitemap Integration Settings"
1274
  msgstr ""
1275
 
1276
- #: inc/views/metaboxes/sitemaps-metabox.php:109
1277
  msgid "Another active sitemap plugin has been detected. This means that the sitemap functionality has been replaced."
1278
  msgstr ""
1279
 
1280
- #: inc/views/metaboxes/sitemaps-metabox.php:111
1281
  msgid "A sitemap has been detected in the root folder of your website. This means that the sitemap functionality has no effect."
1282
  msgstr ""
1283
 
1284
- #: inc/views/metaboxes/sitemaps-metabox.php:113
1285
  msgid "The Sitemap is an XML file that lists pages and posts for your website along with optional metadata about each post or page. This helps Search Engines crawl your website more easily."
1286
  msgstr ""
1287
 
1288
- #: inc/views/metaboxes/sitemaps-metabox.php:114
1289
  msgid "The optional metadata include the post and page modified time and a page priority indication, which is automated."
1290
  msgstr ""
1291
 
1292
- #: inc/views/metaboxes/sitemaps-metabox.php:119
1293
  msgid "Sitemap Output"
1294
  msgstr ""
1295
 
1296
- #: inc/views/metaboxes/sitemaps-metabox.php:126
1297
  msgid "Output Sitemap?"
1298
  msgstr ""
1299
 
1300
- #: inc/views/metaboxes/sitemaps-metabox.php:134
1301
  msgid "View sitemap"
1302
  msgstr ""
1303
 
1304
- #: inc/views/metaboxes/sitemaps-metabox.php:135
1305
  msgctxt "%s = here"
1306
  msgid "The sitemap can be found %s."
1307
  msgstr ""
1308
 
1309
- #: inc/views/metaboxes/sitemaps-metabox.php:143
1310
  msgid "View robots.txt"
1311
  msgstr ""
1312
 
1313
- #: inc/views/metaboxes/sitemaps-metabox.php:145
1314
  msgid "Robots.txt Settings"
1315
  msgstr ""
1316
 
 
 
 
 
1317
  #: inc/views/metaboxes/sitemaps-metabox.php:148
1318
  msgid "The robots.txt file is the first thing Search Engines look for. If you add the sitemap location in the robots.txt file, then Search Engines will look for and index the sitemap."
1319
  msgstr ""
@@ -1330,6 +1559,10 @@ msgstr ""
1330
  msgid "Add sitemap location in robots?"
1331
  msgstr ""
1332
 
 
 
 
 
1333
  #: inc/views/metaboxes/sitemaps-metabox.php:167
1334
  msgid "Another robots.txt sitemap Location addition has been detected."
1335
  msgstr ""
@@ -1395,217 +1628,239 @@ msgstr ""
1395
  msgid "Notify %s about sitemap changes?"
1396
  msgstr ""
1397
 
1398
- #: inc/views/metaboxes/social-metabox.php:40
1399
- msgid "Post Dates"
1400
  msgstr ""
1401
 
1402
- #: inc/views/metaboxes/social-metabox.php:45
1403
- msgid "Link Relationships"
1404
  msgstr ""
1405
 
1406
- #: inc/views/metaboxes/social-metabox.php:65
1407
- msgid "Site Shortlink Settings"
1408
  msgstr ""
1409
 
1410
- #: inc/views/metaboxes/social-metabox.php:66
1411
- msgid "The shortlink tag might have some use for 3rd party service discoverability, but it has little to no SEO value whatsoever."
1412
  msgstr ""
1413
 
1414
- #: inc/views/metaboxes/social-metabox.php:72
1415
- msgid "Output shortlink tag?"
 
 
 
 
1416
  msgstr ""
1417
 
1418
- #: inc/views/metaboxes/social-metabox.php:82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1419
  msgid "Social Meta Tags Settings"
1420
  msgstr ""
1421
 
1422
- #: inc/views/metaboxes/social-metabox.php:84
1423
  msgid "Output various meta tags for social site integration, among other 3rd party services."
1424
  msgstr ""
1425
 
1426
- #: inc/views/metaboxes/social-metabox.php:92
1427
  msgid "Output Open Graph meta tags?"
1428
  msgstr ""
1429
 
1430
- #: inc/views/metaboxes/social-metabox.php:93
1431
  msgid "Facebook, Twitter, Pinterest and many other social sites make use of these tags."
1432
  msgstr ""
1433
 
1434
- #: inc/views/metaboxes/social-metabox.php:100
1435
  msgid "Note: Another Open Graph plugin has been detected."
1436
  msgstr ""
1437
 
1438
- #: inc/views/metaboxes/social-metabox.php:108
1439
  msgid "Output Facebook meta tags?"
1440
  msgstr ""
1441
 
1442
- #: inc/views/metaboxes/social-metabox.php:109
1443
- #: inc/views/metaboxes/social-metabox.php:122
1444
  msgid "Output various tags targetted at %s."
1445
  msgstr ""
1446
 
1447
- #: inc/views/metaboxes/social-metabox.php:121
1448
  msgid "Output Twitter meta tags?"
1449
  msgstr ""
1450
 
1451
- #: inc/views/metaboxes/social-metabox.php:129
1452
  msgid "Note: Another Twitter Card plugin has been detected."
1453
  msgstr ""
1454
 
1455
- #: inc/views/metaboxes/social-metabox.php:136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1456
  msgctxt "Example Facebook Personal URL"
1457
  msgid "http://www.facebook.com/YourPersonalProfile"
1458
  msgstr ""
1459
 
1460
- #: inc/views/metaboxes/social-metabox.php:139
1461
  msgctxt "Example Verified Facebook Business URL"
1462
  msgid "http://www.facebook.com/YourVerifiedBusinessProfile"
1463
  msgstr ""
1464
 
1465
- #: inc/views/metaboxes/social-metabox.php:144
1466
  msgid "Default Facebook Integration Settings"
1467
  msgstr ""
1468
 
1469
- #: inc/views/metaboxes/social-metabox.php:145
1470
  msgid "Facebook post sharing works mostly through Open Graph. However, you can also link your Business and Personal Facebook pages, among various other options."
1471
  msgstr ""
1472
 
1473
- #: inc/views/metaboxes/social-metabox.php:146
1474
  msgid "When these options are filled in, Facebook might link your Facebook profile to be followed and liked when your post or page is shared."
1475
  msgstr ""
1476
 
1477
- #: inc/views/metaboxes/social-metabox.php:153
1478
  msgid "Article Author Facebook URL"
1479
  msgstr ""
1480
 
1481
- #: inc/views/metaboxes/social-metabox.php:154
1482
  msgid "Your Facebook Profile"
1483
  msgstr ""
1484
 
1485
- #: inc/views/metaboxes/social-metabox.php:163
1486
  msgid "Article Publisher Facebook URL"
1487
  msgstr ""
1488
 
1489
- #: inc/views/metaboxes/social-metabox.php:164
1490
  msgid "To use this, you need to be a verified business"
1491
  msgstr ""
1492
 
1493
- #: inc/views/metaboxes/social-metabox.php:173
1494
  msgid "Facebook App ID"
1495
  msgstr ""
1496
 
1497
- #: inc/views/metaboxes/social-metabox.php:174
1498
  msgid "Get Facebook App ID"
1499
  msgstr ""
1500
 
1501
- #: inc/views/metaboxes/social-metabox.php:186
1502
  msgctxt "Twitter @username"
1503
  msgid "@your-site-username"
1504
  msgstr ""
1505
 
1506
- #: inc/views/metaboxes/social-metabox.php:189
1507
  msgctxt "Twitter @username"
1508
  msgid "@your-personal-username"
1509
  msgstr ""
1510
 
1511
- #: inc/views/metaboxes/social-metabox.php:193
1512
  msgid "Default Twitter Integration Settings"
1513
  msgstr ""
1514
 
1515
- #: inc/views/metaboxes/social-metabox.php:194
1516
  msgid "Twitter post sharing works mostly through Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options."
1517
  msgstr ""
1518
 
1519
- #: inc/views/metaboxes/social-metabox.php:200
1520
  msgid "Twitter Card Type"
1521
  msgstr ""
1522
 
1523
- #: inc/views/metaboxes/social-metabox.php:201
1524
  msgid "What kind of Twitter card would you like to use? It will default to %s if no image is found."
1525
  msgstr ""
1526
 
1527
- #: inc/views/metaboxes/social-metabox.php:211
1528
  msgid "Example"
1529
  msgstr ""
1530
 
1531
- #: inc/views/metaboxes/social-metabox.php:222
1532
  msgid "When the following options are filled in, Twitter might link your Twitter Site or Personal Profile when your post or page is shared."
1533
  msgstr ""
1534
 
1535
- #: inc/views/metaboxes/social-metabox.php:226
1536
  msgid "Your Website's Twitter Profile"
1537
  msgstr ""
1538
 
1539
- #: inc/views/metaboxes/social-metabox.php:227
1540
- #: inc/views/metaboxes/social-metabox.php:237
1541
  msgid "Find your @username"
1542
  msgstr ""
1543
 
1544
- #: inc/views/metaboxes/social-metabox.php:236
1545
  msgid "Your Personal Twitter Profile"
1546
  msgstr ""
1547
 
1548
- #: inc/views/metaboxes/social-metabox.php:249
1549
  msgid "Posts"
1550
  msgstr ""
1551
 
1552
- #: inc/views/metaboxes/social-metabox.php:252
1553
  msgid "Post Date Settings"
1554
  msgstr ""
1555
 
1556
- #: inc/views/metaboxes/social-metabox.php:253
1557
  msgid "Some Search Engines output the publishing date and modified date next to the search results. These help Search Engines find new content and could impact the SEO value."
1558
  msgstr ""
1559
 
1560
- #: inc/views/metaboxes/social-metabox.php:254
1561
  msgid "It's recommended on posts, but it's not recommended on pages unless you modify or create new pages frequently."
1562
  msgstr ""
1563
 
1564
  #. translators: 1: Option, 2: Post Type
1565
 
1566
- #: inc/views/metaboxes/social-metabox.php:257
1567
- #: inc/views/metaboxes/social-metabox.php:261
1568
- #: inc/views/metaboxes/social-metabox.php:268
1569
- #: inc/views/metaboxes/social-metabox.php:272
1570
- #: inc/views/metaboxes/social-metabox.php:286
1571
- #: inc/views/metaboxes/social-metabox.php:290
1572
  msgid "Add %1$s to %2$s?"
1573
  msgstr ""
1574
 
1575
- #: inc/views/metaboxes/social-metabox.php:283
1576
  msgid "Because you only publish the Home Page once, Search Engines might think your website is outdated. This can be prevented by disabling the following options."
1577
  msgstr ""
1578
 
1579
- #: inc/views/metaboxes/social-metabox.php:299
1580
- msgid "Link Relationship Settings"
1581
- msgstr ""
1582
-
1583
- #: inc/views/metaboxes/social-metabox.php:300
1584
- msgid "Some Search Engines look for relations between the content of your pages. If you have multiple pages for a single Post or Page, or have archives indexed, this option will help Search Engines look for the right page to display in the Search Results."
1585
- msgstr ""
1586
-
1587
- #: inc/views/metaboxes/social-metabox.php:301
1588
- msgid "It's recommended to turn this option on for better SEO consistency and to prevent duplicate content errors."
1589
- msgstr ""
1590
-
1591
- #. translators: %s = <code>rel</code>
1592
-
1593
- #: inc/views/metaboxes/social-metabox.php:306
1594
- msgid "Add %s link tags to Posts and Pages?"
1595
- msgstr ""
1596
-
1597
- #. translators: %s = <code>rel</code>
1598
-
1599
- #: inc/views/metaboxes/social-metabox.php:310
1600
- msgid "Add %s link tags to Archives?"
1601
- msgstr ""
1602
-
1603
- #. translators: %s = <code>rel</code>
1604
-
1605
- #: inc/views/metaboxes/social-metabox.php:314
1606
- msgid "Add %s link tags to the Home Page?"
1607
- msgstr ""
1608
-
1609
  #: inc/views/metaboxes/title-metabox.php:17
1610
  msgid "Example Post Title"
1611
  msgstr ""
@@ -1626,6 +1881,10 @@ msgstr ""
1626
  msgid "Prefixes"
1627
  msgstr ""
1628
 
 
 
 
 
1629
  #: inc/views/metaboxes/title-metabox.php:109
1630
  msgid "Document Title Separator"
1631
  msgstr ""
@@ -1726,19 +1985,46 @@ msgstr ""
1726
  msgid "Get the Pinterest Verification Code"
1727
  msgstr ""
1728
 
1729
- #: load.class.php:245 load.class.php:255 load.class.php:267
1730
- msgid "Class or Method not found."
 
1731
  msgstr ""
1732
 
1733
- #: load.class.php:279
1734
- msgid "Function needs to be called as a string."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1735
  msgstr ""
1736
  #. Plugin Name of the plugin/theme
1737
  msgid "The SEO Framework"
1738
  msgstr ""
1739
 
1740
  #. Plugin URI of the plugin/theme
1741
- msgid "https://wordpress.org/plugins/autodescription/"
1742
  msgstr ""
1743
 
1744
  #. Description of the plugin/theme
1
+ # Copyright (C) 2017 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 2.8.2-RC2\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/autodescription\n"
7
+ "POT-Creation-Date: 2017-01-27 08:25:27+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: 2017-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
+ #: inc/classes/admin-init.class.php:230
16
  msgid "Good"
17
  msgstr ""
18
 
19
+ #: inc/classes/admin-init.class.php:231
20
  msgid "Okay"
21
  msgstr ""
22
 
23
+ #: inc/classes/admin-init.class.php:232
24
  msgid "Bad"
25
  msgstr ""
26
 
27
+ #: inc/classes/admin-init.class.php:233
28
  msgid "Unknown"
29
  msgstr ""
30
 
31
+ #: inc/classes/admin-init.class.php:313
32
  msgid "The changes you made will be lost if you navigate away from this page."
33
  msgstr ""
34
 
35
+ #: inc/classes/admin-init.class.php:314
36
  msgid "Are you sure you want to reset all SEO settings to their defaults?"
37
  msgstr ""
38
 
39
+ #: inc/classes/admin-pages.class.php:82
40
  msgid "Save Settings"
41
  msgstr ""
42
 
43
+ #: inc/classes/admin-pages.class.php:83
44
  msgid "Reset Settings"
45
  msgstr ""
46
 
47
+ #: inc/classes/admin-pages.class.php:84
48
  msgid "Settings are saved."
49
  msgstr ""
50
 
51
+ #: inc/classes/admin-pages.class.php:85
52
  msgid "Settings are reset."
53
  msgstr ""
54
 
55
+ #: inc/classes/admin-pages.class.php:86
56
  msgid "Error saving settings."
57
  msgstr ""
58
 
59
+ #: inc/classes/admin-pages.class.php:87
60
  msgid "New SEO Settings have been updated."
61
  msgstr ""
62
 
63
+ #: inc/classes/admin-pages.class.php:102 inc/classes/core.class.php:248
64
+ #: inc/classes/site-options.class.php:489
65
  msgid "SEO Settings"
66
  msgstr ""
67
 
68
+ #: inc/classes/admin-pages.class.php:103
69
  msgid "SEO"
70
  msgstr ""
71
 
72
+ #: inc/classes/admin-pages.class.php:235
73
+ msgid "General Settings"
74
+ msgstr ""
75
+
76
+ #: inc/classes/admin-pages.class.php:246
77
  msgid "Title Settings"
78
  msgstr ""
79
 
80
+ #: inc/classes/admin-pages.class.php:257
81
  msgid "Description Meta Settings"
82
  msgstr ""
83
 
84
+ #: inc/classes/admin-pages.class.php:268
85
  msgid "Home Page Settings"
86
  msgstr ""
87
 
88
+ #: inc/classes/admin-pages.class.php:279
89
  msgid "Social Meta Settings"
90
  msgstr ""
91
 
92
+ #: inc/classes/admin-pages.class.php:290
 
 
 
 
 
93
  msgid "Schema Settings"
94
  msgstr ""
95
 
96
+ #: inc/classes/admin-pages.class.php:301 inc/views/inpost/seo-settings.php:210
97
+ #: inc/views/inpost/seo-settings.php:380
98
  msgid "Robots Meta Settings"
99
  msgstr ""
100
 
101
+ #: inc/classes/admin-pages.class.php:312
102
  msgid "Webmaster Meta Settings"
103
  msgstr ""
104
 
105
+ #: inc/classes/admin-pages.class.php:323
106
  msgid "Sitemap Settings"
107
  msgstr ""
108
 
109
+ #: inc/classes/admin-pages.class.php:334
110
  msgid "Feed Settings"
111
  msgstr ""
112
 
113
+ #: inc/classes/core.class.php:250
114
  msgctxt "As in: The Plugin Home Page"
115
  msgid "Plugin Home"
116
  msgstr ""
117
 
118
+ #: inc/classes/core.class.php:301
119
  msgid "Dismiss"
120
  msgstr ""
121
 
122
+ #: inc/classes/core.class.php:398
123
  msgctxt "e.g. en for English, nl for Dutch, fi for Finish, de for German"
124
  msgid "en"
125
  msgstr ""
126
 
127
+ #. translators: 1: Function name, 2: 'Deprecated', 3: Plugin Version
128
+ #. notification, 4: Replacement function
129
+
130
+ #: inc/classes/debug.class.php:179
131
+ msgid "%1$s is %2$s since version %3$s of The SEO Framework! Use %4$s instead."
132
+ msgstr ""
133
 
134
+ #: inc/classes/debug.class.php:181 inc/classes/debug.class.php:191
135
+ msgid "deprecated"
136
  msgstr ""
137
 
138
+ #. translators: 1: Function name, 2: 'Deprecated', 3: Plugin Version
139
+ #. notification
140
 
141
+ #: inc/classes/debug.class.php:189
142
+ msgid "%1$s is %2$s since version %3$s of The SEO Framework with no alternative available."
143
  msgstr ""
144
 
145
+ #: inc/classes/debug.class.php:239
146
  msgid "(This message was added in version %s of The SEO Framework.)"
147
  msgstr ""
148
 
149
+ #. translators: 1: Function name, 2: 'Incorrectly', 3: Error message 4: Plugin
150
+ #. Version notification
151
 
152
+ #: inc/classes/debug.class.php:242
153
+ msgid "%1$s was called %2$s. %3$s %4$s"
154
  msgstr ""
155
 
156
+ #: inc/classes/debug.class.php:244
157
+ msgid "incorrectly"
 
 
 
 
 
 
158
  msgstr ""
159
 
160
  #. translators: 1: Method or Property name, 2: Message
161
 
162
+ #: inc/classes/debug.class.php:292
163
+ msgid "%1$s is not accessible. %2$s"
164
  msgstr ""
165
 
166
+ #: inc/classes/doing-it-right.class.php:82
167
  msgid "No Search"
168
  msgstr ""
169
 
170
+ #: inc/classes/doing-it-right.class.php:283
171
  msgid "Refresh to see the SEO Bar status."
172
  msgstr ""
173
 
174
+ #: inc/classes/doing-it-right.class.php:367
175
  msgid "Post"
176
  msgstr ""
177
 
178
+ #: inc/classes/doing-it-right.class.php:371 inc/classes/inpost.class.php:252
179
+ #: inc/classes/term-data.class.php:330
180
+ #: inc/views/metaboxes/schema-metabox.php:203
181
  msgid "Page"
182
  msgstr ""
183
 
184
+ #: inc/classes/doing-it-right.class.php:415
185
  msgid "Failed to fetch post ID."
186
  msgstr ""
187
 
188
  #. translators: %s = But or And
189
 
190
+ #: inc/classes/doing-it-right.class.php:792
191
  msgid "%s the Title contains the Blogname multiple times."
192
  msgstr ""
193
 
194
  #. translators: 1: Word, 2: Occurences
195
 
196
+ #: inc/classes/doing-it-right.class.php:963
197
  msgid "%1$s is used %2$d times."
198
  msgstr ""
199
 
200
+ #. Translators: %s = Post / Page / Category, etc.
201
+
202
+ #: inc/classes/doing-it-right.class.php:1008
203
  msgid "%s is being indexed."
204
  msgstr ""
205
 
206
+ #: inc/classes/doing-it-right.class.php:1017
207
+ msgid "But you've discouraged indexing for the whole site."
208
  msgstr ""
209
 
210
  #. translators: 1: But or And, 2: Current taxonomy term plural label
211
 
212
+ #: inc/classes/doing-it-right.class.php:1041
213
+ msgid "%1$s indexing for %2$s have been discouraged."
214
+ msgstr ""
215
+
216
+ #. translators: 1 = But or And, 1 = Post/Page
217
+
218
+ #: inc/classes/doing-it-right.class.php:1054
219
+ msgid "%1$s the %2$s is protected from public visibility. This means indexing is discouraged."
220
  msgstr ""
221
 
222
  #. translators: %s = But or And
223
 
224
+ #: inc/classes/doing-it-right.class.php:1063
225
  msgid "%s the blog isn't set to public. This means WordPress discourages indexing."
226
  msgstr ""
227
 
228
  #. translators: %s = But or And
229
 
230
+ #: inc/classes/doing-it-right.class.php:1077
231
+ msgid "%s there are no posts in this term; therefore, indexing has been discouraged."
232
  msgstr ""
233
 
234
+ #: inc/classes/doing-it-right.class.php:1161
235
  msgid "%s links aren't being followed."
236
  msgstr ""
237
 
238
+ #: inc/classes/doing-it-right.class.php:1167
239
  msgid "%s links are being followed."
240
  msgstr ""
241
 
242
  #. translators: %s = But or And
243
 
244
+ #: inc/classes/doing-it-right.class.php:1179
245
+ msgid "%s you've discouraged the following of links for the whole site."
246
  msgstr ""
247
 
248
  #. translators: 1: But or And, 2: Current taxonomy term plural label
249
 
250
+ #: inc/classes/doing-it-right.class.php:1205
251
+ msgid "%1$s following for %2$s have been discouraged."
252
  msgstr ""
253
 
254
  #. translators: %s = But or And
255
 
256
+ #: inc/classes/doing-it-right.class.php:1217
257
  msgid "%s the blog isn't set to public. This means WordPress allows the links to be followed regardless."
258
  msgstr ""
259
 
260
+ #: inc/classes/doing-it-right.class.php:1269
261
+ msgid "Search Engines aren't allowed to archive this %s."
262
  msgstr ""
263
 
264
+ #: inc/classes/doing-it-right.class.php:1274
265
+ msgid "Search Engines are allowed to archive this %s."
266
  msgstr ""
267
 
268
+ #: inc/classes/doing-it-right.class.php:1286
269
+ msgid "But you've discouraged archiving for the whole site."
270
  msgstr ""
271
 
272
  #. translators: 1: But or And, 2: Current taxonomy term plural label
273
 
274
+ #: inc/classes/doing-it-right.class.php:1312
275
+ msgid "%1$s archiving for %2$s have been discouraged."
276
  msgstr ""
277
 
278
  #. translators: %s = But or And
279
 
280
+ #: inc/classes/doing-it-right.class.php:1325
281
  msgid "%s the blog isn't set to public. This means WordPress allows the blog to be archived regardless."
282
  msgstr ""
283
 
284
+ #: inc/classes/doing-it-right.class.php:1371
285
  msgid "%s isn't being redirected."
286
  msgstr ""
287
 
288
+ #: inc/classes/doing-it-right.class.php:1413
289
+ #: inc/classes/doing-it-right.class.php:1442
290
  msgid "%s is being redirected. This means no SEO values have to be set."
291
  msgstr ""
292
 
293
+ #: inc/classes/doing-it-right.class.php:1416
294
+ #: inc/classes/doing-it-right.class.php:1458
295
  msgid "%s is not being indexed. This means no SEO values have to be set."
296
  msgstr ""
297
 
298
+ #: inc/classes/doing-it-right.class.php:1572
299
  msgid "Title:"
300
  msgstr ""
301
 
302
+ #: inc/classes/doing-it-right.class.php:1573
303
  msgid "Description:"
304
  msgstr ""
305
 
306
+ #: inc/classes/doing-it-right.class.php:1574
307
  msgid "Index:"
308
  msgstr ""
309
 
310
+ #: inc/classes/doing-it-right.class.php:1575
311
  msgid "Follow:"
312
  msgstr ""
313
 
314
+ #: inc/classes/doing-it-right.class.php:1576
315
  msgid "Archive:"
316
  msgstr ""
317
 
318
+ #: inc/classes/doing-it-right.class.php:1577
319
  msgid "Redirect:"
320
  msgstr ""
321
 
322
+ #: inc/classes/doing-it-right.class.php:1579
323
  msgid "Generated: Automatically generated."
324
  msgstr ""
325
 
326
+ #: inc/classes/doing-it-right.class.php:1581
327
  msgctxt "Generated"
328
  msgid "G"
329
  msgstr ""
330
 
331
+ #: inc/classes/doing-it-right.class.php:1582
332
  msgctxt "Title"
333
  msgid "T"
334
  msgstr ""
335
 
336
+ #: inc/classes/doing-it-right.class.php:1583
337
  msgctxt "Description"
338
  msgid "D"
339
  msgstr ""
340
 
341
+ #: inc/classes/doing-it-right.class.php:1584
342
  msgctxt "no-Index"
343
  msgid "I"
344
  msgstr ""
345
 
346
+ #: inc/classes/doing-it-right.class.php:1585
347
  msgctxt "no-Follow"
348
  msgid "F"
349
  msgstr ""
350
 
351
+ #: inc/classes/doing-it-right.class.php:1586
352
  msgctxt "no-Archive"
353
  msgid "A"
354
  msgstr ""
355
 
356
+ #: inc/classes/doing-it-right.class.php:1587
357
  msgctxt "Redirect"
358
  msgid "R"
359
  msgstr ""
360
 
361
+ #: inc/classes/doing-it-right.class.php:1589
362
  msgctxt "But there are..."
363
  msgid "But"
364
  msgstr ""
365
 
366
+ #: inc/classes/doing-it-right.class.php:1590
367
  msgctxt "And there are..."
368
  msgid "And"
369
  msgstr ""
370
 
371
+ #: inc/classes/doing-it-right.class.php:1592
372
  msgid "Length is far too short."
373
  msgstr ""
374
 
375
+ #: inc/classes/doing-it-right.class.php:1593
376
  msgid "Length is too short."
377
  msgstr ""
378
 
379
+ #: inc/classes/doing-it-right.class.php:1594
380
  msgid "Length is too long."
381
  msgstr ""
382
 
383
+ #: inc/classes/doing-it-right.class.php:1595
384
  msgid "Length is far too long."
385
  msgstr ""
386
 
387
+ #: inc/classes/doing-it-right.class.php:1596
388
  msgid "Length is good."
389
  msgstr ""
390
 
391
+ #: inc/classes/feed.class.php:135
392
  msgctxt "The content source"
393
  msgid "Source"
394
  msgstr ""
395
 
396
+ #. translators: 1: Title, 2: Separator, 3: Excerpt
397
 
398
+ #: inc/classes/generate-description.class.php:413
399
+ msgctxt "1: Title, 2: Separator, 3: Excerpt"
400
  msgid "%1$s %2$s %3$s"
401
  msgstr ""
402
 
403
+ #. translators: 1: Title, 2: on, 3: Blogname
404
 
405
+ #: inc/classes/generate-description.class.php:620
406
+ msgctxt "1: Title, 2: on, 3: Blogname"
407
  msgid "%1$s %2$s %3$s"
408
  msgstr ""
409
 
410
  #. translators: Front-end output.
411
 
412
+ #: inc/classes/generate-description.class.php:655
413
  #: inc/views/metaboxes/description-metabox.php:18
414
  msgctxt "Placement. e.g. Post Title \"on\" Blog Name"
415
  msgid "on"
417
 
418
  #. translators: Front-end output.
419
 
420
+ #: inc/classes/generate-description.class.php:717
421
  msgid "Latest posts:"
422
  msgstr ""
423
 
424
+ #: inc/classes/generate-ldjson.class.php:520
425
+ #: inc/classes/generate-ldjson.class.php:564
426
+ msgid "Uncategorized"
427
+ msgstr ""
428
+
429
  #. translators: Front-end output. 1: Taxonomy singular name, 2: Current
430
  #. taxonomy term
431
 
432
+ #: inc/classes/generate-title.class.php:822
433
+ #: inc/classes/generate-title.class.php:882
434
  msgid "%1$s: %2$s"
435
  msgstr ""
436
 
437
  #. translators: Front-end output.
438
 
439
+ #: inc/classes/generate-title.class.php:826
440
  msgid "Author: %s"
441
  msgstr ""
442
 
443
  #. translators: Front-end output.
444
 
445
+ #: inc/classes/generate-title.class.php:830
446
  msgctxt "yearly archives date format"
447
  msgid "Y"
448
  msgstr ""
449
 
450
  #. translators: Front-end output.
451
 
452
+ #: inc/classes/generate-title.class.php:832
453
  msgid "Year: %s"
454
  msgstr ""
455
 
456
  #. translators: Front-end output.
457
 
458
+ #: inc/classes/generate-title.class.php:835
459
  msgctxt "monthly archives date format"
460
  msgid "F Y"
461
  msgstr ""
462
 
463
  #. translators: Front-end output.
464
 
465
+ #: inc/classes/generate-title.class.php:837
466
  msgid "Month: %s"
467
  msgstr ""
468
 
469
  #. translators: Front-end output.
470
 
471
+ #: inc/classes/generate-title.class.php:840
472
  msgctxt "daily archives date format"
473
  msgid "F j, Y"
474
  msgstr ""
475
 
476
  #. translators: Front-end output.
477
 
478
+ #: inc/classes/generate-title.class.php:842
479
  msgid "Day: %s"
480
  msgstr ""
481
 
482
  #. translators: Front-end output.
483
 
484
+ #: inc/classes/generate-title.class.php:847
485
  msgctxt "post format archive title"
486
  msgid "Asides"
487
  msgstr ""
488
 
489
  #. translators: Front-end output.
490
 
491
+ #: inc/classes/generate-title.class.php:850
492
  msgctxt "post format archive title"
493
  msgid "Galleries"
494
  msgstr ""
495
 
496
  #. translators: Front-end output.
497
 
498
+ #: inc/classes/generate-title.class.php:853
499
  msgctxt "post format archive title"
500
  msgid "Images"
501
  msgstr ""
502
 
503
  #. translators: Front-end output.
504
 
505
+ #: inc/classes/generate-title.class.php:856
506
  msgctxt "post format archive title"
507
  msgid "Videos"
508
  msgstr ""
509
 
510
  #. translators: Front-end output.
511
 
512
+ #: inc/classes/generate-title.class.php:859
513
  msgctxt "post format archive title"
514
  msgid "Quotes"
515
  msgstr ""
516
 
517
  #. translators: Front-end output.
518
 
519
+ #: inc/classes/generate-title.class.php:862
520
  msgctxt "post format archive title"
521
  msgid "Links"
522
  msgstr ""
523
 
524
  #. translators: Front-end output.
525
 
526
+ #: inc/classes/generate-title.class.php:865
527
  msgctxt "post format archive title"
528
  msgid "Statuses"
529
  msgstr ""
530
 
531
  #. translators: Front-end output.
532
 
533
+ #: inc/classes/generate-title.class.php:868
534
  msgctxt "post format archive title"
535
  msgid "Audio"
536
  msgstr ""
537
 
538
  #. translators: Front-end output.
539
 
540
+ #: inc/classes/generate-title.class.php:871
541
  msgctxt "post format archive title"
542
  msgid "Chats"
543
  msgstr ""
544
 
545
  #. translators: Front-end output.
546
 
547
+ #: inc/classes/generate-title.class.php:876
548
  msgid "Archives: %s"
549
  msgstr ""
550
 
551
  #. translators: Front-end output.
552
 
553
+ #: inc/classes/generate-title.class.php:886
554
  msgid "Archives"
555
  msgstr ""
556
 
557
  #. translators: Front-end output.
558
 
559
+ #: inc/classes/generate-title.class.php:993
560
  msgid "Untitled"
561
  msgstr ""
562
 
563
  #. translators: Front-end output.
564
 
565
+ #: inc/classes/generate-title.class.php:1028
566
  msgid "Search results for:"
567
  msgstr ""
568
 
569
  #. translators: Front-end output
570
 
571
+ #: inc/classes/generate-title.class.php:1204
572
  msgid "Protected: %s"
573
  msgstr ""
574
 
575
  #. translators: Front-end output
576
 
577
+ #: inc/classes/generate-title.class.php:1208
578
  msgid "Private: %s"
579
  msgstr ""
580
 
581
  #. translators: Front-end output.
582
 
583
+ #: inc/classes/generate-title.class.php:1241
584
  msgid "Page %s"
585
  msgstr ""
586
 
587
+ #: inc/classes/init.class.php:470
588
  msgid "Start The Seo Framework"
589
  msgstr ""
590
 
591
+ #: inc/classes/init.class.php:471
592
  msgid "End The Seo Framework"
593
  msgstr ""
594
 
595
+ #: inc/classes/init.class.php:472
596
  msgid "by Sybre Waaijer"
597
  msgstr ""
598
 
599
+ #: inc/classes/inpost.class.php:174 inc/views/inpost/seo-settings.php:331
600
  msgid "%s SEO Settings"
601
  msgstr ""
602
 
603
+ #: inc/classes/inpost.class.php:312 inc/classes/inpost.class.php:319
604
+ msgid "Select social image"
 
605
  msgstr ""
606
 
607
+ #: inc/classes/inpost.class.php:314 inc/classes/inpost.class.php:318
608
+ msgid "Select Image"
609
  msgstr ""
610
 
611
+ #: inc/classes/inpost.class.php:320
612
+ msgid "Change Image"
 
613
  msgstr ""
614
 
615
+ #: inc/classes/inpost.class.php:321
616
+ msgid "Remove Image"
 
 
 
617
  msgstr ""
618
 
619
+ #: inc/classes/inpost.class.php:322
620
+ msgid "Remove selected social image"
621
  msgstr ""
622
 
623
+ #: inc/classes/inpost.class.php:323
624
+ msgid "Select Social Image"
 
625
  msgstr ""
626
 
627
+ #: inc/classes/inpost.class.php:324
628
+ msgid "Use this image"
 
629
  msgstr ""
630
 
631
+ #: inc/classes/site-options.class.php:489
632
+ msgid "here"
 
633
  msgstr ""
634
 
635
+ #: inc/classes/site-options.class.php:490
636
+ msgctxt "%s = here"
637
+ msgid "View the new options %s."
638
  msgstr ""
639
 
640
+ #: inc/classes/sitemaps.class.php:296
641
+ msgid "Sitemap is generated for this view"
642
+ msgstr ""
643
+
644
+ #: inc/classes/sitemaps.class.php:298
645
+ msgid "Sitemap is served from cache"
646
  msgstr ""
647
 
648
+ #: inc/classes/sitemaps.class.php:518
649
+ msgid "Sitemap is generated on"
650
+ msgstr ""
651
+
652
+ #: inc/classes/term-data.class.php:332
653
+ #: inc/views/metaboxes/social-metabox.php:276
654
+ msgid "Pages"
655
+ msgstr ""
656
+
657
+ #: inc/views/inpost/seo-settings.php:138 inc/views/inpost/seo-settings.php:261
658
+ #: inc/views/inpost/seo-settings.php:337 inc/views/inpost/seo-settings.php:410
659
+ msgid "Doing it Right"
660
+ msgstr ""
661
+
662
+ #: inc/views/inpost/seo-settings.php:146
663
+ #: inc/views/metaboxes/homepage-metabox.php:168
664
  msgid "Custom %s Title"
665
  msgstr ""
666
 
667
+ #: inc/views/inpost/seo-settings.php:147 inc/views/inpost/seo-settings.php:348
668
+ #: inc/views/metaboxes/homepage-metabox.php:169
669
+ msgid "Recommended Length: 50 to 55 characters"
670
+ msgstr ""
671
+
672
+ #: inc/views/inpost/seo-settings.php:149 inc/views/inpost/seo-settings.php:166
673
+ #: inc/views/inpost/seo-settings.php:357 inc/views/inpost/seo-settings.php:373
674
+ #: inc/views/metaboxes/homepage-metabox.php:171
675
+ #: inc/views/metaboxes/homepage-metabox.php:222
676
+ msgid "Characters Used: %s"
677
+ msgstr ""
678
+
679
+ #: inc/views/inpost/seo-settings.php:163
680
+ #: inc/views/metaboxes/homepage-metabox.php:219
681
  msgid "Custom %s Description"
682
  msgstr ""
683
 
684
+ #: inc/views/inpost/seo-settings.php:164 inc/views/inpost/seo-settings.php:367
685
+ #: inc/views/metaboxes/homepage-metabox.php:220
686
+ msgid "Recommended Length: 145 to 155 characters"
687
+ msgstr ""
688
+
689
+ #: inc/views/inpost/seo-settings.php:177
690
+ msgid "Custom Social Image URL"
691
+ msgstr ""
692
+
693
+ #: inc/views/inpost/seo-settings.php:178
694
+ msgid "Preferred %s Social Image URL location"
695
+ msgstr ""
696
+
697
+ #: inc/views/inpost/seo-settings.php:202
698
  msgid "Custom Canonical URL"
699
  msgstr ""
700
 
701
+ #: inc/views/inpost/seo-settings.php:203
702
  msgid "Preferred %s URL location"
703
  msgstr ""
704
 
705
  #. translators: 1: Option, 2: Post or Page
706
 
707
+ #: inc/views/inpost/seo-settings.php:215 inc/views/inpost/seo-settings.php:225
708
+ #: inc/views/inpost/seo-settings.php:235
709
  msgid "Apply %1$s to this %2$s"
710
  msgstr ""
711
 
712
+ #: inc/views/inpost/seo-settings.php:217
713
  msgid "Tell Search Engines not to show this %s in their search results"
714
  msgstr ""
715
 
716
+ #: inc/views/inpost/seo-settings.php:227
717
  msgid "Tell Search Engines not to follow links on this %s"
718
  msgstr ""
719
 
720
+ #: inc/views/inpost/seo-settings.php:237
721
  msgid "Tell Search Engines not to save a cached copy of this %s"
722
  msgstr ""
723
 
724
+ #: inc/views/inpost/seo-settings.php:241
725
  msgid "Local Search Settings"
726
  msgstr ""
727
 
728
+ #: inc/views/inpost/seo-settings.php:244
729
  msgid "Exclude this %s from local search"
730
  msgstr ""
731
 
732
+ #: inc/views/inpost/seo-settings.php:245
733
  msgid "This excludes this %s from local on-site search results"
734
  msgstr ""
735
 
736
+ #: inc/views/inpost/seo-settings.php:251
737
  msgid "Custom 301 Redirect URL"
738
  msgstr ""
739
 
740
+ #: inc/views/inpost/seo-settings.php:252
741
  msgid "This will force visitors to go to another URL"
742
  msgstr ""
743
 
744
+ #: inc/views/inpost/seo-settings.php:347
745
+ msgid "%s Title"
 
 
 
 
 
 
 
 
746
  msgstr ""
747
 
748
+ #: inc/views/inpost/seo-settings.php:366
749
+ msgid "%s Meta Description"
750
  msgstr ""
751
 
752
+ #: inc/views/inpost/seo-settings.php:383 inc/views/inpost/seo-settings.php:390
753
+ #: inc/views/inpost/seo-settings.php:397
754
+ msgid "Apply %s to this term?"
755
  msgstr ""
756
 
757
+ #: inc/views/inpost/seo-settings.php:384
758
+ #: inc/views/metaboxes/homepage-metabox.php:345
759
+ msgid "Tell Search Engines not to show this page in their search results"
760
  msgstr ""
761
 
762
+ #: inc/views/inpost/seo-settings.php:391
763
+ #: inc/views/metaboxes/homepage-metabox.php:355
764
+ msgid "Tell Search Engines not to follow links on this page"
765
  msgstr ""
766
 
767
+ #: inc/views/inpost/seo-settings.php:398
768
+ #: inc/views/metaboxes/homepage-metabox.php:365
769
+ msgid "Tell Search Engines not to save a cached copy of this page"
770
  msgstr ""
771
 
772
  #: inc/views/metaboxes/description-metabox.php:17
782
  msgstr ""
783
 
784
  #: inc/views/metaboxes/description-metabox.php:42
785
+ #: inc/views/metaboxes/homepage-metabox.php:231
786
  msgid "The meta description can be used to determine the text used under the title on Search Engine results pages."
787
  msgstr ""
788
 
791
  msgstr ""
792
 
793
  #: inc/views/metaboxes/description-metabox.php:67
794
+ #: inc/views/metaboxes/homepage-metabox.php:32
 
795
  #: inc/views/metaboxes/robots-metabox.php:57
796
+ #: inc/views/metaboxes/schema-metabox.php:37
797
  #: inc/views/metaboxes/sitemaps-metabox.php:38
798
  #: inc/views/metaboxes/social-metabox.php:25
799
  #: inc/views/metaboxes/title-metabox.php:61
801
  msgstr ""
802
 
803
  #: inc/views/metaboxes/description-metabox.php:72
804
+ #: inc/views/metaboxes/homepage-metabox.php:37
805
  #: inc/views/metaboxes/title-metabox.php:66
806
  msgid "Additions"
807
  msgstr ""
808
 
809
+ #: inc/views/metaboxes/description-metabox.php:100
 
 
 
 
 
810
  msgid "Description Excerpt Separator"
811
  msgstr ""
812
 
901
  msgid "The feed can be found %s."
902
  msgstr ""
903
 
904
+ #: inc/views/metaboxes/general-metabox.php:18
905
+ msgid "Performance"
906
  msgstr ""
907
 
908
+ #: inc/views/metaboxes/general-metabox.php:23
909
+ msgid "Layout"
910
  msgstr ""
911
 
912
+ #: inc/views/metaboxes/general-metabox.php:28
913
+ msgid "Canonical"
914
  msgstr ""
915
 
916
+ #: inc/views/metaboxes/general-metabox.php:52
917
+ msgid "Performance Settings"
918
  msgstr ""
919
 
920
+ #: inc/views/metaboxes/general-metabox.php:53
921
+ msgid "In order to improve performance, generated SEO output can be stored in the database as transient cache."
 
 
 
 
922
  msgstr ""
923
 
924
+ #: inc/views/metaboxes/general-metabox.php:54
925
+ msgid "If your website has thousands of pages, or if other forms of caching are used, you might wish to adjust these options."
926
+ msgstr ""
927
 
928
+ #: inc/views/metaboxes/general-metabox.php:59
929
+ msgid "Transient Cache Settings"
 
930
  msgstr ""
931
 
932
+ #: inc/views/metaboxes/general-metabox.php:65
933
+ msgid "Enable automated description output cache?"
 
934
  msgstr ""
935
 
936
+ #: inc/views/metaboxes/general-metabox.php:66
937
+ msgid "Description generation can use a lot of server resources when it reads the page content."
938
  msgstr ""
939
 
940
+ #: inc/views/metaboxes/general-metabox.php:72
941
+ msgid "Enable automated Schema output cache?"
 
942
  msgstr ""
943
 
944
+ #: inc/views/metaboxes/general-metabox.php:73
945
+ msgid "Schema.org output generally makes multiple calls to the database."
 
946
  msgstr ""
947
 
948
+ #: inc/views/metaboxes/general-metabox.php:79
949
+ msgid "Enable sitemap generation cache?"
 
950
  msgstr ""
951
 
952
+ #: inc/views/metaboxes/general-metabox.php:80
953
+ msgid "Generating the sitemap can use a lot of server resources."
 
954
  msgstr ""
955
 
956
+ #: inc/views/metaboxes/general-metabox.php:92
957
+ msgid "Object Cache Settings"
958
  msgstr ""
959
 
960
+ #: inc/views/metaboxes/general-metabox.php:98
961
+ msgid "Enable object cache?"
962
  msgstr ""
963
 
964
+ #: inc/views/metaboxes/general-metabox.php:99
965
+ msgid "Object cache generally works faster than transient cache"
966
  msgstr ""
967
 
968
+ #: inc/views/metaboxes/general-metabox.php:100
969
+ msgid "An object cache handler has been detected. If you enable this option, you might wish to disable description and Schema transient caching."
970
  msgstr ""
971
 
972
+ #: inc/views/metaboxes/general-metabox.php:109
973
+ msgid "Administrative Layout Settings"
974
  msgstr ""
975
 
976
+ #: inc/views/metaboxes/general-metabox.php:110
977
+ msgid "SEO hints can be visually displayed throughout the dashboard."
978
+ msgstr ""
979
 
980
+ #: inc/views/metaboxes/general-metabox.php:115
981
+ msgid "SEO Bar Settings"
 
 
982
  msgstr ""
983
 
984
+ #: inc/views/metaboxes/general-metabox.php:121
985
+ msgid "Display the SEO Bar in overview tables?"
986
  msgstr ""
987
 
988
+ #: inc/views/metaboxes/general-metabox.php:127
989
+ msgid "Display the SEO Bar in the SEO Settings metabox?"
990
  msgstr ""
991
 
992
+ #: inc/views/metaboxes/general-metabox.php:138
993
+ msgid "Canonical URL Settings"
994
  msgstr ""
995
 
996
+ #: inc/views/metaboxes/general-metabox.php:139
997
+ msgid "The canonical URL meta tag urges Search Engines to go to the outputted URL."
998
+ msgstr ""
999
 
1000
+ #: inc/views/metaboxes/general-metabox.php:140
1001
+ msgid "If the canonical URL meta tag represents the visited page, then the Search Engine will crawl the visited page. Otherwise, the Search Engine might go to the outputted URL."
1002
  msgstr ""
1003
 
1004
+ #: inc/views/metaboxes/general-metabox.php:141
1005
+ msgid "Only adjust these options if you are aware of its SEO effects."
1006
  msgstr ""
1007
 
1008
+ #: inc/views/metaboxes/general-metabox.php:146
1009
+ msgid "Scheme Settings"
1010
  msgstr ""
1011
 
1012
+ #: inc/views/metaboxes/general-metabox.php:148
1013
+ msgid "If your website is accessible on both HTTP as HTTPS, set this to HTTPS in order to prevent duplicate content."
1014
  msgstr ""
1015
 
1016
+ #: inc/views/metaboxes/general-metabox.php:149
1017
+ msgid "Otherwise, automatic detection is recommended."
1018
  msgstr ""
1019
 
1020
+ #: inc/views/metaboxes/general-metabox.php:151
1021
+ msgctxt "= Detect Automatically, HTTPS, HTTP"
1022
+ msgid "Preferred canonical URL scheme:"
1023
  msgstr ""
1024
 
1025
+ #: inc/views/metaboxes/general-metabox.php:157
1026
+ msgid "Detect automatically"
1027
  msgstr ""
1028
 
1029
+ #: inc/views/metaboxes/general-metabox.php:170
1030
+ msgid "Link Relationship Settings"
1031
  msgstr ""
1032
 
1033
+ #: inc/views/metaboxes/general-metabox.php:171
1034
+ msgid "Some Search Engines look for relations between the content of your pages. If you have multiple pages for a single Post or Page, or have archives indexed, this option will help Search Engines look for the right page to display in the Search Results."
1035
  msgstr ""
1036
 
1037
+ #: inc/views/metaboxes/general-metabox.php:172
1038
+ msgid "It's recommended to turn this option on for better SEO consistency and to prevent duplicate content errors."
1039
  msgstr ""
1040
 
1041
+ #. translators: %s = <code>rel</code>
1042
+
1043
+ #: inc/views/metaboxes/general-metabox.php:175
1044
+ msgid "Add %s link tags to Posts and Pages?"
1045
  msgstr ""
1046
 
1047
+ #. translators: %s = <code>rel</code>
1048
+
1049
+ #: inc/views/metaboxes/general-metabox.php:179
1050
+ msgid "Add %s link tags to Archives?"
1051
  msgstr ""
1052
 
1053
+ #. translators: %s = <code>rel</code>
1054
+
1055
+ #: inc/views/metaboxes/general-metabox.php:183
1056
+ msgid "Add %s link tags to the Home Page?"
1057
  msgstr ""
1058
 
1059
+ #: inc/views/metaboxes/homepage-metabox.php:11
1060
+ msgid "These settings will take precedence over the settings set within the Home Page edit screen, if any."
1061
  msgstr ""
1062
 
1063
+ #: inc/views/metaboxes/homepage-metabox.php:42
1064
+ msgid "Robots"
1065
  msgstr ""
1066
 
1067
+ #: inc/views/metaboxes/homepage-metabox.php:66
1068
+ msgid "Title"
1069
  msgstr ""
1070
 
1071
+ #: inc/views/metaboxes/homepage-metabox.php:67
1072
+ msgid "Description"
1073
  msgstr ""
1074
 
1075
+ #: inc/views/metaboxes/homepage-metabox.php:68
1076
+ #: inc/views/metaboxes/homepage-metabox.php:267
1077
+ #: inc/views/metaboxes/homepage-metabox.php:312
1078
+ #: inc/views/metaboxes/social-metabox.php:278
1079
+ #: inc/views/metaboxes/social-metabox.php:309
1080
+ msgid "Home Page"
1081
  msgstr ""
1082
 
1083
+ #: inc/views/metaboxes/homepage-metabox.php:138
1084
+ #: inc/views/metaboxes/homepage-metabox.php:191
1085
+ msgid "Page SEO Settings"
1086
  msgstr ""
1087
 
1088
+ #. translators: 1: Option, 2: Page SEO Settings, 3: Home Page
1089
+
1090
+ #: inc/views/metaboxes/homepage-metabox.php:140
1091
+ #: inc/views/metaboxes/homepage-metabox.php:189
1092
+ msgid "Note: The %1$s is fetched from the %2$s on the %3$s."
1093
+ msgstr ""
1094
+
1095
+ #: inc/views/metaboxes/homepage-metabox.php:157
1096
+ msgid "Custom %s Title Tagline"
1097
+ msgstr ""
1098
+
1099
+ #. translators: %s = Home page URL markdown
1100
+
1101
+ #: inc/views/metaboxes/homepage-metabox.php:207
1102
+ #: inc/views/metaboxes/homepage-metabox.php:247
1103
+ msgid "A plugin has been detected that suggests to maintain this option on the [Home Page](%s)."
1104
+ msgstr ""
1105
+
1106
+ #: inc/views/metaboxes/homepage-metabox.php:271
1107
+ #: inc/views/metaboxes/title-metabox.php:132
1108
+ msgid "Document Title Additions Location"
1109
+ msgstr ""
1110
+
1111
+ #: inc/views/metaboxes/homepage-metabox.php:272
1112
+ #: inc/views/metaboxes/title-metabox.php:134
1113
+ msgid "Determines which side the added title text will go on."
1114
+ msgstr ""
1115
+
1116
+ #: inc/views/metaboxes/homepage-metabox.php:278
1117
+ #: inc/views/metaboxes/title-metabox.php:140
1118
+ msgid "Left:"
1119
+ msgstr ""
1120
+
1121
+ #: inc/views/metaboxes/homepage-metabox.php:288
1122
+ #: inc/views/metaboxes/title-metabox.php:147
1123
+ msgid "Right:"
1124
+ msgstr ""
1125
+
1126
+ #: inc/views/metaboxes/homepage-metabox.php:299
1127
+ msgid "%s Tagline"
1128
+ msgstr ""
1129
+
1130
+ #: inc/views/metaboxes/homepage-metabox.php:303
1131
+ msgid "Add site description (tagline) to the Title on the %s?"
1132
+ msgstr ""
1133
+
1134
+ #: inc/views/metaboxes/homepage-metabox.php:329
1135
+ msgid "View Home Page Settings"
1136
+ msgstr ""
1137
+
1138
+ #: inc/views/metaboxes/homepage-metabox.php:329
1139
+ msgid "Checked in Page"
1140
+ msgstr ""
1141
+
1142
+ #: inc/views/metaboxes/homepage-metabox.php:333
1143
+ msgid "Home Page Robots Meta Settings"
1144
+ msgstr ""
1145
+
1146
+ #. translators: 1: Option, 2: Location
1147
+
1148
+ #: inc/views/metaboxes/homepage-metabox.php:342
1149
+ #: inc/views/metaboxes/homepage-metabox.php:352
1150
+ #: inc/views/metaboxes/homepage-metabox.php:362
1151
+ msgid "Apply %1$s to the %2$s?"
1152
+ msgstr ""
1153
+
1154
+ #: inc/views/metaboxes/homepage-metabox.php:397
1155
+ msgid "Note: If any of these options are unchecked, but are checked on the Home Page, they will be outputted regardless."
1156
+ msgstr ""
1157
+
1158
+ #: inc/views/metaboxes/homepage-metabox.php:403
1159
+ msgid "Home Page Pagination Robots Settings"
1160
+ msgstr ""
1161
+
1162
+ #: inc/views/metaboxes/homepage-metabox.php:404
1163
+ msgid "If your Home Page is paginated and outputs content that's also found elsewhere on the website, enabling this option might prevent duplicate content."
1164
+ msgstr ""
1165
+
1166
+ #. translators: 1: Option, 2: Location
1167
+
1168
+ #: inc/views/metaboxes/homepage-metabox.php:412
1169
+ msgid "Apply %1$s to every second or later page on the %2$s?"
1170
  msgstr ""
1171
 
1172
  #: inc/views/metaboxes/robots-metabox.php:13
1280
  msgid "Apply %1$s to %2$s Archives?"
1281
  msgstr ""
1282
 
1283
+ #: inc/views/metaboxes/schema-metabox.php:12
1284
  msgid "Schema.org Output Settings"
1285
  msgstr ""
1286
 
1287
+ #: inc/views/metaboxes/schema-metabox.php:16
1288
  msgid "Another Schema.org plugin has been detected."
1289
  msgstr ""
1290
 
1291
+ #: inc/views/metaboxes/schema-metabox.php:18
1292
  msgid "The Schema.org markup is a standard way of annotating structured data for Search Engines. This markup is represented within hidden scripts throughout the website."
1293
  msgstr ""
1294
 
1295
+ #: inc/views/metaboxes/schema-metabox.php:19
1296
  msgid "When your web pages include structured data markup, Search Engines can use that data to index your content better, present it more prominently in Search Results, and use it in several different applications."
1297
  msgstr ""
1298
 
1299
+ #: inc/views/metaboxes/schema-metabox.php:20
1300
+ msgid "This is also known as the \"Knowledge Graph\" and \"Structured Data\", which is under heavy active development by several Search Engines. Therefore, the usage of the outputted markup is not guaranteed."
1301
+ msgstr ""
1302
+
1303
+ #: inc/views/metaboxes/schema-metabox.php:42
1304
+ msgid "Structure"
1305
+ msgstr ""
1306
+
1307
+ #: inc/views/metaboxes/schema-metabox.php:47
1308
+ msgid "Presence"
1309
+ msgstr ""
1310
+
1311
+ #: inc/views/metaboxes/schema-metabox.php:69
1312
+ msgid "About this website"
1313
+ msgstr ""
1314
+
1315
+ #: inc/views/metaboxes/schema-metabox.php:72
1316
+ msgctxt "...Organization or Person."
1317
+ msgid "This website represents:"
1318
+ msgstr ""
1319
+
1320
+ #: inc/views/metaboxes/schema-metabox.php:78
1321
+ msgid "An Organization"
1322
+ msgstr ""
1323
+
1324
+ #: inc/views/metaboxes/schema-metabox.php:79
1325
+ msgid "A Person"
1326
+ msgstr ""
1327
+
1328
+ #: inc/views/metaboxes/schema-metabox.php:91
1329
+ msgid "The organization or personal name"
1330
+ msgstr ""
1331
+
1332
+ #: inc/views/metaboxes/schema-metabox.php:102
1333
+ msgid "Site Structure Options"
1334
+ msgstr ""
1335
+
1336
+ #: inc/views/metaboxes/schema-metabox.php:103
1337
+ msgid "The site structure Schema.org output allows Search Engines to gain knowledge on how your website is built."
1338
+ msgstr ""
1339
+
1340
+ #: inc/views/metaboxes/schema-metabox.php:104
1341
+ msgid "For example, Search Engines display your pages' URLs when listed in the Search Results. These options allow you to enhance those URLs output."
1342
+ msgstr ""
1343
+
1344
+ #: inc/views/metaboxes/schema-metabox.php:109
1345
+ msgid "Breadcrumbs"
1346
+ msgstr ""
1347
+
1348
+ #: inc/views/metaboxes/schema-metabox.php:110
1349
+ msgid "Breadcrumb trails indicate the page's position in the site hierarchy. Using the following option will show the hierarchy within the Search Results when available."
1350
+ msgstr ""
1351
+
1352
+ #: inc/views/metaboxes/schema-metabox.php:112
1353
+ msgid "About Breadcrumbs"
1354
+ msgstr ""
1355
+
1356
+ #: inc/views/metaboxes/schema-metabox.php:115
1357
+ msgid "Enable Breadcrumbs?"
1358
+ msgstr ""
1359
+
1360
+ #: inc/views/metaboxes/schema-metabox.php:116
1361
+ msgid "Multiple trails can be outputted. The longest trail is prioritized."
1362
+ msgstr ""
1363
+
1364
+ #: inc/views/metaboxes/schema-metabox.php:123
1365
+ msgid "Site Name"
1366
+ msgstr ""
1367
+
1368
+ #: inc/views/metaboxes/schema-metabox.php:125
1369
+ msgid "When using breadcrumbs, the first entry is by default your website's address. Using the following option will convert it to the Site Name."
1370
+ msgstr ""
1371
+
1372
+ #: inc/views/metaboxes/schema-metabox.php:128
1373
+ msgid "Include your Site Name in Search Results"
1374
+ msgstr ""
1375
+
1376
+ #: inc/views/metaboxes/schema-metabox.php:134
1377
+ msgid "Convert URL to Site Name?"
1378
+ msgstr ""
1379
+
1380
+ #: inc/views/metaboxes/schema-metabox.php:135
1381
+ msgid "The Site Name is: %s"
1382
+ msgstr ""
1383
+
1384
  #. translators:
1385
  #. https:developers.google.com/search/docs/data-types/sitelinks-searchbox
1386
 
1387
+ #: inc/views/metaboxes/schema-metabox.php:144
1388
+ #: inc/views/metaboxes/schema-metabox.php:147
1389
  msgctxt "Product name"
1390
  msgid "Sitelinks Searchbox"
1391
  msgstr ""
1392
 
1393
+ #: inc/views/metaboxes/schema-metabox.php:145
1394
+ msgid "When Search users search for your brand name, the following option allows them to search through this website directly from the Search Results."
1395
  msgstr ""
1396
 
1397
+ #: inc/views/metaboxes/schema-metabox.php:150
1398
  msgctxt "Product name"
1399
  msgid "Enable Sitelinks Searchbox?"
1400
  msgstr ""
1401
 
1402
+ #: inc/views/metaboxes/schema-metabox.php:158
1403
+ msgid "Authorized Presence Options"
1404
  msgstr ""
1405
 
1406
+ #: inc/views/metaboxes/schema-metabox.php:159
1407
+ msgid "The authorized presence Schema.org output helps Search Engine users find ways to interact with this website."
1408
  msgstr ""
1409
 
1410
+ #: inc/views/metaboxes/schema-metabox.php:161
1411
+ msgid "About Authorized Presence"
1412
  msgstr ""
1413
 
1414
+ #: inc/views/metaboxes/schema-metabox.php:165
1415
+ msgid "Output Authorized Presence?"
1416
  msgstr ""
1417
 
1418
+ #: inc/views/metaboxes/schema-metabox.php:173
1419
+ msgid "Website logo"
1420
  msgstr ""
1421
 
1422
+ #: inc/views/metaboxes/schema-metabox.php:178
1423
+ msgid "About Organization Logo"
1424
  msgstr ""
1425
 
1426
+ #: inc/views/metaboxes/schema-metabox.php:181
1427
+ msgid "Use the Favicon from Customizer as the Organization Logo?"
1428
  msgstr ""
1429
 
1430
+ #: inc/views/metaboxes/schema-metabox.php:182
1431
+ msgid "This option only has an effect when this site represents an Organization. If left disabled, Search Engines will look elsewhere for a logo, if it exists and is assigned as a logo."
1432
  msgstr ""
1433
 
1434
+ #: inc/views/metaboxes/schema-metabox.php:189
1435
+ msgid "Social Pages connected to this website"
1436
  msgstr ""
1437
 
1438
+ #: inc/views/metaboxes/schema-metabox.php:190
1439
+ 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."
1440
+ msgstr ""
1441
+
1442
+ #: inc/views/metaboxes/schema-metabox.php:191
1443
+ msgid "Add the link that leads directly to the social page of this website."
1444
+ msgstr ""
1445
+
1446
+ #: inc/views/metaboxes/schema-metabox.php:193
1447
+ msgctxt "No spaces. E.g. https://facebook.com/RelatedProfile"
1448
+ msgid "RelatedProfile"
1449
+ msgstr ""
1450
+
1451
+ #: inc/views/metaboxes/schema-metabox.php:194
1452
+ msgctxt "Social Profile"
1453
+ msgid "Profile"
1454
+ msgstr ""
1455
+
1456
+ #: inc/views/metaboxes/schema-metabox.php:259
1457
+ msgid "Blog"
1458
  msgstr ""
1459
 
1460
  #: inc/views/metaboxes/sitemaps-metabox.php:14
1462
  msgstr ""
1463
 
1464
  #: inc/views/metaboxes/sitemaps-metabox.php:14
1465
+ #: inc/views/metaboxes/sitemaps-metabox.php:130
1466
+ #: inc/views/metaboxes/sitemaps-metabox.php:139
1467
  msgctxt "The sitemap can be found %s."
1468
  msgid "here"
1469
  msgstr ""
1490
  msgid "Ping"
1491
  msgstr ""
1492
 
1493
+ #: inc/views/metaboxes/sitemaps-metabox.php:58
1494
+ msgid "Style"
1495
+ msgstr ""
1496
+
1497
+ #: inc/views/metaboxes/sitemaps-metabox.php:101
1498
  msgid "Sitemap Integration Settings"
1499
  msgstr ""
1500
 
1501
+ #: inc/views/metaboxes/sitemaps-metabox.php:105
1502
  msgid "Another active sitemap plugin has been detected. This means that the sitemap functionality has been replaced."
1503
  msgstr ""
1504
 
1505
+ #: inc/views/metaboxes/sitemaps-metabox.php:107
1506
  msgid "A sitemap has been detected in the root folder of your website. This means that the sitemap functionality has no effect."
1507
  msgstr ""
1508
 
1509
+ #: inc/views/metaboxes/sitemaps-metabox.php:109
1510
  msgid "The Sitemap is an XML file that lists pages and posts for your website along with optional metadata about each post or page. This helps Search Engines crawl your website more easily."
1511
  msgstr ""
1512
 
1513
+ #: inc/views/metaboxes/sitemaps-metabox.php:110
1514
  msgid "The optional metadata include the post and page modified time and a page priority indication, which is automated."
1515
  msgstr ""
1516
 
1517
+ #: inc/views/metaboxes/sitemaps-metabox.php:115
1518
  msgid "Sitemap Output"
1519
  msgstr ""
1520
 
1521
+ #: inc/views/metaboxes/sitemaps-metabox.php:122
1522
  msgid "Output Sitemap?"
1523
  msgstr ""
1524
 
1525
+ #: inc/views/metaboxes/sitemaps-metabox.php:130
1526
  msgid "View sitemap"
1527
  msgstr ""
1528
 
1529
+ #: inc/views/metaboxes/sitemaps-metabox.php:131
1530
  msgctxt "%s = here"
1531
  msgid "The sitemap can be found %s."
1532
  msgstr ""
1533
 
1534
+ #: inc/views/metaboxes/sitemaps-metabox.php:139
1535
  msgid "View robots.txt"
1536
  msgstr ""
1537
 
1538
+ #: inc/views/metaboxes/sitemaps-metabox.php:142
1539
  msgid "Robots.txt Settings"
1540
  msgstr ""
1541
 
1542
+ #: inc/views/metaboxes/sitemaps-metabox.php:146
1543
+ msgid "A robots.txt file has been detected in the root folder of your website; therefore no settings are able to alter its output."
1544
+ msgstr ""
1545
+
1546
  #: inc/views/metaboxes/sitemaps-metabox.php:148
1547
  msgid "The robots.txt file is the first thing Search Engines look for. If you add the sitemap location in the robots.txt file, then Search Engines will look for and index the sitemap."
1548
  msgstr ""
1559
  msgid "Add sitemap location in robots?"
1560
  msgstr ""
1561
 
1562
+ #: inc/views/metaboxes/sitemaps-metabox.php:161
1563
+ msgid "This only has effect if the sitemap is active"
1564
+ msgstr ""
1565
+
1566
  #: inc/views/metaboxes/sitemaps-metabox.php:167
1567
  msgid "Another robots.txt sitemap Location addition has been detected."
1568
  msgstr ""
1628
  msgid "Notify %s about sitemap changes?"
1629
  msgstr ""
1630
 
1631
+ #: inc/views/metaboxes/sitemaps-metabox.php:266
1632
+ msgid "Sitemap Styling Settings"
1633
  msgstr ""
1634
 
1635
+ #: inc/views/metaboxes/sitemaps-metabox.php:269
1636
+ msgid "You can style the sitemap to give it a more personal look. Styling the sitemap has no SEO value whatsoever."
1637
  msgstr ""
1638
 
1639
+ #: inc/views/metaboxes/sitemaps-metabox.php:274
1640
+ msgid "Enable styling"
1641
  msgstr ""
1642
 
1643
+ #: inc/views/metaboxes/sitemaps-metabox.php:281
1644
+ msgid "Style Sitemap?"
1645
  msgstr ""
1646
 
1647
+ #: inc/views/metaboxes/sitemaps-metabox.php:281
1648
+ msgid "This makes the sitemap more readable for humans"
1649
+ msgstr ""
1650
+
1651
+ #: inc/views/metaboxes/sitemaps-metabox.php:290
1652
+ msgid "Style configuration"
1653
  msgstr ""
1654
 
1655
+ #: inc/views/metaboxes/sitemaps-metabox.php:298
1656
+ msgid "Add site logo?"
1657
+ msgstr ""
1658
+
1659
+ #: inc/views/metaboxes/sitemaps-metabox.php:298
1660
+ msgid "The logo is set in Customizer"
1661
+ msgstr ""
1662
+
1663
+ #: inc/views/metaboxes/sitemaps-metabox.php:311
1664
+ msgid "Sitemap header background color"
1665
+ msgstr ""
1666
+
1667
+ #: inc/views/metaboxes/sitemaps-metabox.php:320
1668
+ msgid "Sitemap title and lines color"
1669
+ msgstr ""
1670
+
1671
+ #: inc/views/metaboxes/social-metabox.php:40
1672
+ msgid "Post Dates"
1673
+ msgstr ""
1674
+
1675
+ #: inc/views/metaboxes/social-metabox.php:61
1676
  msgid "Social Meta Tags Settings"
1677
  msgstr ""
1678
 
1679
+ #: inc/views/metaboxes/social-metabox.php:63
1680
  msgid "Output various meta tags for social site integration, among other 3rd party services."
1681
  msgstr ""
1682
 
1683
+ #: inc/views/metaboxes/social-metabox.php:73
1684
  msgid "Output Open Graph meta tags?"
1685
  msgstr ""
1686
 
1687
+ #: inc/views/metaboxes/social-metabox.php:74
1688
  msgid "Facebook, Twitter, Pinterest and many other social sites make use of these tags."
1689
  msgstr ""
1690
 
1691
+ #: inc/views/metaboxes/social-metabox.php:81
1692
  msgid "Note: Another Open Graph plugin has been detected."
1693
  msgstr ""
1694
 
1695
+ #: inc/views/metaboxes/social-metabox.php:87
1696
  msgid "Output Facebook meta tags?"
1697
  msgstr ""
1698
 
1699
+ #: inc/views/metaboxes/social-metabox.php:88
1700
+ #: inc/views/metaboxes/social-metabox.php:99
1701
  msgid "Output various tags targetted at %s."
1702
  msgstr ""
1703
 
1704
+ #: inc/views/metaboxes/social-metabox.php:98
1705
  msgid "Output Twitter meta tags?"
1706
  msgstr ""
1707
 
1708
+ #: inc/views/metaboxes/social-metabox.php:106
1709
  msgid "Note: Another Twitter Card plugin has been detected."
1710
  msgstr ""
1711
 
1712
+ #: inc/views/metaboxes/social-metabox.php:111
1713
+ msgid "Social Image Settings"
1714
+ msgstr ""
1715
+
1716
+ #: inc/views/metaboxes/social-metabox.php:113
1717
+ msgid "A social image can be displayed when your website is shared. They are a great way to grab attention."
1718
+ msgstr ""
1719
+
1720
+ #: inc/views/metaboxes/social-metabox.php:120
1721
+ msgid "Social Image Fallback URL"
1722
+ msgstr ""
1723
+
1724
+ #: inc/views/metaboxes/social-metabox.php:121
1725
+ msgid "Preferred Social Image fallback URL location"
1726
+ msgstr ""
1727
+
1728
+ #: inc/views/metaboxes/social-metabox.php:145
1729
+ msgid "Site Shortlink Settings"
1730
+ msgstr ""
1731
+
1732
+ #: inc/views/metaboxes/social-metabox.php:147
1733
+ msgid "The shortlink tag might have some use for 3rd party service discoverability, but it has little to no SEO value whatsoever."
1734
+ msgstr ""
1735
+
1736
+ #: inc/views/metaboxes/social-metabox.php:153
1737
+ msgid "Output shortlink tag?"
1738
+ msgstr ""
1739
+
1740
+ #: inc/views/metaboxes/social-metabox.php:164
1741
  msgctxt "Example Facebook Personal URL"
1742
  msgid "http://www.facebook.com/YourPersonalProfile"
1743
  msgstr ""
1744
 
1745
+ #: inc/views/metaboxes/social-metabox.php:167
1746
  msgctxt "Example Verified Facebook Business URL"
1747
  msgid "http://www.facebook.com/YourVerifiedBusinessProfile"
1748
  msgstr ""
1749
 
1750
+ #: inc/views/metaboxes/social-metabox.php:172
1751
  msgid "Default Facebook Integration Settings"
1752
  msgstr ""
1753
 
1754
+ #: inc/views/metaboxes/social-metabox.php:173
1755
  msgid "Facebook post sharing works mostly through Open Graph. However, you can also link your Business and Personal Facebook pages, among various other options."
1756
  msgstr ""
1757
 
1758
+ #: inc/views/metaboxes/social-metabox.php:174
1759
  msgid "When these options are filled in, Facebook might link your Facebook profile to be followed and liked when your post or page is shared."
1760
  msgstr ""
1761
 
1762
+ #: inc/views/metaboxes/social-metabox.php:181
1763
  msgid "Article Author Facebook URL"
1764
  msgstr ""
1765
 
1766
+ #: inc/views/metaboxes/social-metabox.php:182
1767
  msgid "Your Facebook Profile"
1768
  msgstr ""
1769
 
1770
+ #: inc/views/metaboxes/social-metabox.php:191
1771
  msgid "Article Publisher Facebook URL"
1772
  msgstr ""
1773
 
1774
+ #: inc/views/metaboxes/social-metabox.php:192
1775
  msgid "To use this, you need to be a verified business"
1776
  msgstr ""
1777
 
1778
+ #: inc/views/metaboxes/social-metabox.php:201
1779
  msgid "Facebook App ID"
1780
  msgstr ""
1781
 
1782
+ #: inc/views/metaboxes/social-metabox.php:202
1783
  msgid "Get Facebook App ID"
1784
  msgstr ""
1785
 
1786
+ #: inc/views/metaboxes/social-metabox.php:214
1787
  msgctxt "Twitter @username"
1788
  msgid "@your-site-username"
1789
  msgstr ""
1790
 
1791
+ #: inc/views/metaboxes/social-metabox.php:217
1792
  msgctxt "Twitter @username"
1793
  msgid "@your-personal-username"
1794
  msgstr ""
1795
 
1796
+ #: inc/views/metaboxes/social-metabox.php:221
1797
  msgid "Default Twitter Integration Settings"
1798
  msgstr ""
1799
 
1800
+ #: inc/views/metaboxes/social-metabox.php:222
1801
  msgid "Twitter post sharing works mostly through Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options."
1802
  msgstr ""
1803
 
1804
+ #: inc/views/metaboxes/social-metabox.php:228
1805
  msgid "Twitter Card Type"
1806
  msgstr ""
1807
 
1808
+ #: inc/views/metaboxes/social-metabox.php:229
1809
  msgid "What kind of Twitter card would you like to use? It will default to %s if no image is found."
1810
  msgstr ""
1811
 
1812
+ #: inc/views/metaboxes/social-metabox.php:239
1813
  msgid "Example"
1814
  msgstr ""
1815
 
1816
+ #: inc/views/metaboxes/social-metabox.php:250
1817
  msgid "When the following options are filled in, Twitter might link your Twitter Site or Personal Profile when your post or page is shared."
1818
  msgstr ""
1819
 
1820
+ #: inc/views/metaboxes/social-metabox.php:254
1821
  msgid "Your Website's Twitter Profile"
1822
  msgstr ""
1823
 
1824
+ #: inc/views/metaboxes/social-metabox.php:255
1825
+ #: inc/views/metaboxes/social-metabox.php:265
1826
  msgid "Find your @username"
1827
  msgstr ""
1828
 
1829
+ #: inc/views/metaboxes/social-metabox.php:264
1830
  msgid "Your Personal Twitter Profile"
1831
  msgstr ""
1832
 
1833
+ #: inc/views/metaboxes/social-metabox.php:277
1834
  msgid "Posts"
1835
  msgstr ""
1836
 
1837
+ #: inc/views/metaboxes/social-metabox.php:280
1838
  msgid "Post Date Settings"
1839
  msgstr ""
1840
 
1841
+ #: inc/views/metaboxes/social-metabox.php:281
1842
  msgid "Some Search Engines output the publishing date and modified date next to the search results. These help Search Engines find new content and could impact the SEO value."
1843
  msgstr ""
1844
 
1845
+ #: inc/views/metaboxes/social-metabox.php:282
1846
  msgid "It's recommended on posts, but it's not recommended on pages unless you modify or create new pages frequently."
1847
  msgstr ""
1848
 
1849
  #. translators: 1: Option, 2: Post Type
1850
 
1851
+ #: inc/views/metaboxes/social-metabox.php:285
1852
+ #: inc/views/metaboxes/social-metabox.php:289
1853
+ #: inc/views/metaboxes/social-metabox.php:296
1854
+ #: inc/views/metaboxes/social-metabox.php:300
1855
+ #: inc/views/metaboxes/social-metabox.php:314
1856
+ #: inc/views/metaboxes/social-metabox.php:318
1857
  msgid "Add %1$s to %2$s?"
1858
  msgstr ""
1859
 
1860
+ #: inc/views/metaboxes/social-metabox.php:311
1861
  msgid "Because you only publish the Home Page once, Search Engines might think your website is outdated. This can be prevented by disabling the following options."
1862
  msgstr ""
1863
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1864
  #: inc/views/metaboxes/title-metabox.php:17
1865
  msgid "Example Post Title"
1866
  msgstr ""
1881
  msgid "Prefixes"
1882
  msgstr ""
1883
 
1884
+ #: inc/views/metaboxes/title-metabox.php:105
1885
+ msgid "Recommended"
1886
+ msgstr ""
1887
+
1888
  #: inc/views/metaboxes/title-metabox.php:109
1889
  msgid "Document Title Separator"
1890
  msgstr ""
1985
  msgid "Get the Pinterest Verification Code"
1986
  msgstr ""
1987
 
1988
+ #: inc/views/sitemap/xsl-stylesheet.php:8
1989
+ #: inc/views/sitemap/xsl-stylesheet.php:140
1990
+ msgid "XML Sitemap"
1991
  msgstr ""
1992
 
1993
+ #. translators: URLs are in Markdown.
1994
+
1995
+ #: inc/views/sitemap/xsl-stylesheet.php:146
1996
+ msgid "This is a generated XML Sitemap, meant to be consumed by search engines like [Google](https://www.google.com/) or [Bing](https://www.bing.com/)."
1997
+ msgstr ""
1998
+
1999
+ #. translators: URLs are in Markdown.
2000
+
2001
+ #: inc/views/sitemap/xsl-stylesheet.php:162
2002
+ msgid "You can find more information on XML sitemaps at [sitemaps.org](https://www.sitemaps.org/)."
2003
+ msgstr ""
2004
+
2005
+ #: inc/views/sitemap/xsl-stylesheet.php:177
2006
+ msgid "URL"
2007
+ msgstr ""
2008
+
2009
+ #: inc/views/sitemap/xsl-stylesheet.php:181
2010
+ msgid "Last Updated"
2011
+ msgstr ""
2012
+
2013
+ #: inc/views/sitemap/xsl-stylesheet.php:185
2014
+ msgid "Priority"
2015
+ msgstr ""
2016
+
2017
+ #. translators: URLs are in Markdown.
2018
+
2019
+ #: inc/views/sitemap/xsl-stylesheet.php:229
2020
+ msgid "Generated by [The SEO Framework](https://wordpress.org/plugins/autodescription/)"
2021
  msgstr ""
2022
  #. Plugin Name of the plugin/theme
2023
  msgid "The SEO Framework"
2024
  msgstr ""
2025
 
2026
  #. Plugin URI of the plugin/theme
2027
+ msgid "https://theseoframework.com/"
2028
  msgstr ""
2029
 
2030
  #. Description of the plugin/theme
lib/css/autodescription-rtl.min.css DELETED
@@ -1 +0,0 @@
1
- .tsf-metaboxes .tsf-top-buttons,.tsf-metaboxes .tsf-top-wrap>h1,.tsf-metaboxes .tsf-top-wrap>h2{float:left}.tsf-notice{position:relative;clear:both}.tsf-notice.tsf-show-icon p:before{content:'';margin-left:12px;background:0 0;display:inline-block;font:400 14px/16px dashicons;speak:none;height:16px;text-align:center;vertical-align:middle;width:16px;line-height:14px;-webkit-font-smoothing:antialiased}.error.tsf-notice.tsf-show-icon p:before{color:#dd3811;content:"\f534"}.notice-warning.tsf-notice.tsf-show-icon p:before{color:#ffa01b;content:"\f227"}.updated.tsf-notice.tsf-show-icon p:before{color:#0cc34b;font-size:16px;content:"\f147"}a.tsf-dismiss{position:absolute;top:0;left:1px;border:none;margin:0;padding:9px;background:0 0;color:#b4b9be;cursor:pointer;text-decoration:none}a.tsf-dismiss:before{background:0 0;content:"\f153";display:block;font:400 16px/20px dashicons;speak:none;height:20px;text-align:center;width:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a.tsf-dismiss:hover{color:#c00}table.wp-list-table .column-name{width:15%}table.wp-list-table .column-icl_translations,table.wp-list-table .column-is_in_stock,table.wp-list-table .column-price,table.wp-list-table .column-sku{width:8%}.tsf-seo-bar a{text-decoration:none;font-size:13px}#tsf-title-wrap{position:relative;display:block;padding:0;height:auto;width:auto}#tsf-title-offset{visibility:hidden;height:0;display:inline-block;position:absolute;right:0;color:transparent;white-space:pre}#tsf-title-placeholder{position:absolute;color:#777;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;top:0;left:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.tsf-counter{font-weight:600;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}span.tsf-count-bad{color:#dd3811}span.tsf-count-okay{color:#ffa700}span.tsf-count-good{color:#0cc34b}span.tsf-counter-one{color:#fff;border-radius:58px;padding:0 1px;min-width:29px;display:inline-block;text-align:center;vertical-align:baseline}span.tsf-counter-one.tsf-count-bad{background-color:#dd3811}span.tsf-counter-one.tsf-count-okay{background-color:#ffa700}span.tsf-counter-one.tsf-count-good{background-color:#0cc34b}#tsf-seo-bar-wrap{width:18%}th:last-of-type#tsf-seo-bar-wrap{width:160px}span.tsf-seo-bar{display:block;width:95%;max-width:220px;border-radius:0;padding:3px;text-shadow:0 0 3px rgba(0,0,0,.3)}span.tsf-seo-bar.tsf-100{width:100%}span.tsf-seo-bar-inner-wrap{display:table;width:100%;border-radius:0;margin:0 auto;border-collapse:separate;border-spacing:0;vertical-align:middle;position:relative}span.tsf-seo-bar-section-wrap{display:table-cell;border-collapse:collapse}.tsf-seo-bar-inner-wrap a{display:table;width:100%;color:#fff;text-align:center;cursor:help;height:100%;min-width:12px;vertical-align:top;line-height:1.625em;box-shadow:2px 0 0 -1px rgba(0,0,0,.1) inset,-2px 0 0 -1px rgba(0,0,0,.1) inset}span.tsf-seo-bar.pill,span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap{border-radius:30px}span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a{box-shadow:2px 6px 3px -2px rgba(255,255,255,.2) inset,-2px -6px 3px -2px rgba(41,41,41,.2) inset,0 0 1px rgba(41,41,41,.6)}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type a{border-top-left-radius:30px;border-bottom-left-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type a{border-top-right-radius:30px;border-bottom-right-radius:30px}.tsf-100{width:100%}.tsf-60{width:60%}.tsf-50{width:50%}.tsf-40{width:40%}.tsf-33{width:33.333%}.tsf-25{width:25%}.tsf-20{width:20%}.tsf-16{width:16.666%}.tsf-12-5{width:12.5%}.ad-11{width:11.333%}.tsf-10{width:10%}.tsf-seo-bar-bad{background-color:#dd3811}.tsf-seo-bar-okay{background-color:#ffa700}.tsf-seo-bar-good{background-color:#0cc34b}.tsf-seo-bar-unknown{background-color:#007bd2}span.tsf-seo-bar .tsf-explanation-desc{position:absolute;width:auto;min-width:90%;max-width:220px;font-weight:600;background:#007bd2;padding:8px 12px;color:#fdfdfd;border-radius:0;z-index:900142;box-shadow:0 0 2px rgba(0,0,0,.6);left:0;right:0;text-align:left}span.tsf-seo-bar .tsf-explanation-desc span{text-decoration:underline}span.tsf-seo-bar .tsf-explanation-desc div{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-top:12px solid #007bd2;position:absolute;bottom:-8px;z-index:9999999;left:0}.tsf-seo-bar-wrap.column-tsf-seo-bar-temp{overflow:initial!important;min-width:160px}#col-container,#col-right{overflow:initial}.tsf-metaboxes{box-sizing:border-box;max-width:690px;padding-bottom:20px}.tsf-metaboxes .tsf-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-metaboxes .metabox-holder{clear:both}.tsf-metaboxes .tsf-bottom-buttons{text-align:left}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}.tsf-metaboxes #tsf-description-separator,.tsf-metaboxes #tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}.tsf-metaboxes #tsf-description-separator input,.tsf-metaboxes #tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #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-metaboxes #tsf-description-separator label.tsf-recommended,.tsf-metaboxes #tsf-title-separator label.tsf-recommended{border:1px solid #0cc34b;box-shadow:-1px -1px 1px #0cc34b inset}.tsf-metaboxes #tsf-description-separator input:hover+label,.tsf-metaboxes #tsf-description-separator label:hover,.tsf-metaboxes #tsf-title-separator input:hover+label,.tsf-metaboxes #tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}.tsf-metaboxes #tsf-description-separator input:checked+label,.tsf-metaboxes #tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}.tsf-metaboxes #tsf-home-title-location,.tsf-metaboxes #tsf-title-location{display:block}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span,.tsf-metaboxes #tsf-twitter-cards label span{display:inline-block;min-width:60px;vertical-align:baseline}.tsf-metaboxes #tsf-twitter-cards label span{min-width:150px}.tsf-metaboxes #tsf-home-title-location label .autodescription-sep-js,.tsf-metaboxes #tsf-home-title-location label span.custom-title-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,.tsf-metaboxes #tsf-title-location label .autodescription-sep-js{display:inline;min-width:0;white-space:pre}.tsf-metaboxes .tsf-nav-tab-wrapper,.tsf-metaboxes .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-metaboxes .tsf-nav-tab{float:right;border:1px solid #ccc;margin-right:.5em;margin-bottom:-1px;padding:5px 14px;font-size:12px;line-height:16px;background:#f1f1f1;color:#555;font-weight:600}.tsf-metaboxes .tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}.tsf-metaboxes .tsf-tabs-radio{display:none;width:0;height:0;position:absolute;left:-9001px}.tsf-metaboxes .tsf-active-tab,.tsf-metaboxes .tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-metaboxes .tsf-tabs-content{margin:1.33em auto 0}.tsf-metaboxes .seoframework-content-no-js{margin:1.33em auto}body.js .tsf-metaboxes .tsf-tabs-content{display:none}body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content{display:block}.tsf-metaboxes .tsf-default-selected{border-color:#1c9d38}.tsf-metaboxes .tsf-default-selected:checked:before{color:#1c9d38}.tsf-metaboxes .tsf-warning-selected{border-color:#dd3811}.tsf-metaboxes .tsf-warning-selected:checked:before{color:#dd3811}.tsf-fields{font-size:13px;line-height:1.5;margin:1em 0}.tsf-fields .tsf-toblock{display:block;width:100%;margin-bottom:4px}.tsf-fields p.description{margin:7px 0 5px;color:#666}.tsf-option-spacer{margin:1em 0}.tsf-counter .tsf-ajax{margin-right:3px}.tsf-ajax:before{display:inline-block;line-height:1;font-family:dashicons;font-style:normal;font-weight:400;font-size:1.225em;vertical-align:middle;content:""}.tsf-ajax.tsf-loading:before{content:"\f463";color:#007bd2;-webkit-animation:tsf-spin 1.5s linear infinite;-moz-animation:tsf-spin 1.5s linear infinite;-o-animation:tsf-spin 1.5s linear infinite;animation:tsf-spin 1.5s linear infinite}.tsf-ajax.tsf-error:before{content:"\f158";color:#dd3811}.tsf-ajax.tsf-success:before{content:"\f147";color:#0cc34b}@-webkit-keyframes tsf-spin{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes tsf-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media screen and (max-width:782px){.tsf-inpost-box p.tsf-fields,.tsf-metaboxes p.tsf-fields{line-height:2.8}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span{min-width:40px}}@media screen and (max-width:642px){.tsf-metaboxes span.tsf-nav-desktop{display:none}}@media screen and (max-width:510px){span.tsf-seo-bar.tsf-100{width:inherit}}@-moz-document url-prefix(){.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{margin:3px 1px}@media only screen and (min-width:768px){.widefat tr td.column-title:nth-child(2):nth-last-child(n+6),.widefat tr td.title:nth-child(2):nth-last-child(n+6),.widefat tr th.column-title:nth-child(2):nth-last-child(n+6),.widefat tr th.title:nth-child(2):nth-last-child(n+6){min-width:1em;width:25%;max-width:100%;white-space:unset}}.tsf-metaboxes .tsf-default-selected{box-shadow:0 0 2px 0 #1c9d38}.tsf-metaboxes .tsf-warning-selected{box-shadow:0 0 2px 0 #dd3811}.tsf-metaboxes legend h4{margin:2px 0}}
 
lib/css/autodescription.min.css DELETED
@@ -1 +0,0 @@
1
- .tsf-notice{position:relative;clear:both}.tsf-notice.tsf-show-icon p:before{content:'';margin-right:12px;background:0 0;display:inline-block;font:400 14px/16px dashicons;speak:none;height:16px;text-align:center;vertical-align:middle;width:16px;line-height:14px;-webkit-font-smoothing:antialiased}.error.tsf-notice.tsf-show-icon p:before{color:#dd3811;content:"\f534"}.notice-warning.tsf-notice.tsf-show-icon p:before{color:#ffa01b;content:"\f227"}.updated.tsf-notice.tsf-show-icon p:before{color:#0cc34b;font-size:16px;content:"\f147"}a.tsf-dismiss{position:absolute;top:0;right:1px;border:none;margin:0;padding:9px;background:0 0;color:#b4b9be;cursor:pointer;text-decoration:none}a.tsf-dismiss:before{background:0 0;content:"\f153";display:block;font:400 16px/20px dashicons;speak:none;height:20px;text-align:center;width:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a.tsf-dismiss:hover{color:#c00}table.wp-list-table .column-name{width:15%}table.wp-list-table .column-icl_translations,table.wp-list-table .column-is_in_stock,table.wp-list-table .column-price,table.wp-list-table .column-sku{width:8%}.tsf-seo-bar a{text-decoration:none;font-size:13px}#tsf-title-wrap{position:relative;display:block;padding:0;height:auto;width:auto}#tsf-title-offset{visibility:hidden;height:0;display:inline-block;position:absolute;left:0;color:transparent;white-space:pre}#tsf-title-placeholder{position:absolute;color:#777;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;top:0;left:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.tsf-counter{font-weight:600;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}span.tsf-count-bad{color:#dd3811}span.tsf-count-okay{color:#ffa700}span.tsf-count-good{color:#0cc34b}span.tsf-counter-one{color:#fff;border-radius:58px;padding:0 1px;min-width:29px;display:inline-block;text-align:center;vertical-align:baseline}span.tsf-counter-one.tsf-count-bad{background-color:#dd3811}span.tsf-counter-one.tsf-count-okay{background-color:#ffa700}span.tsf-counter-one.tsf-count-good{background-color:#0cc34b}#tsf-seo-bar-wrap{width:18%}th:last-of-type#tsf-seo-bar-wrap{width:160px}span.tsf-seo-bar{display:block;width:95%;max-width:220px;border-radius:0;padding:3px;text-shadow:0 0 3px rgba(0,0,0,.3)}span.tsf-seo-bar.tsf-100{width:100%}span.tsf-seo-bar-inner-wrap{display:table;width:100%;border-radius:0;margin:0 auto;border-collapse:separate;border-spacing:0;vertical-align:middle;position:relative}span.tsf-seo-bar-section-wrap{display:table-cell;border-collapse:collapse}.tsf-seo-bar-inner-wrap a{display:table;width:100%;color:#fff;text-align:center;cursor:help;height:100%;min-width:12px;vertical-align:top;line-height:1.625em;box-shadow:2px 0 0 -1px rgba(0,0,0,.1) inset,-2px 0 0 -1px rgba(0,0,0,.1) inset}span.tsf-seo-bar.pill,span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap{border-radius:30px}span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a{box-shadow:2px 6px 3px -2px rgba(255,255,255,.2) inset,-2px -6px 3px -2px rgba(41,41,41,.2) inset,0 0 1px rgba(41,41,41,.6)}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type a{border-top-left-radius:30px;border-bottom-left-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type a{border-top-right-radius:30px;border-bottom-right-radius:30px}.tsf-100{width:100%}.tsf-60{width:60%}.tsf-50{width:50%}.tsf-40{width:40%}.tsf-33{width:33.333%}.tsf-25{width:25%}.tsf-20{width:20%}.tsf-16{width:16.666%}.tsf-12-5{width:12.5%}.ad-11{width:11.333%}.tsf-10{width:10%}.tsf-seo-bar-bad{background-color:#dd3811}.tsf-seo-bar-okay{background-color:#ffa700}.tsf-seo-bar-good{background-color:#0cc34b}.tsf-seo-bar-unknown{background-color:#007bd2}span.tsf-seo-bar .tsf-explanation-desc{position:absolute;width:auto;min-width:90%;max-width:220px;font-weight:600;background:#007bd2;padding:8px 12px;color:#fdfdfd;border-radius:0;z-index:900142;box-shadow:0 0 2px rgba(0,0,0,.6);left:0;right:0;text-align:left}span.tsf-seo-bar .tsf-explanation-desc span{text-decoration:underline}span.tsf-seo-bar .tsf-explanation-desc div{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-top:12px solid #007bd2;position:absolute;bottom:-8px;z-index:9999999;left:0}.tsf-seo-bar-wrap.column-tsf-seo-bar-temp{overflow:initial!important;min-width:160px}#col-container,#col-right{overflow:initial}.tsf-metaboxes{box-sizing:border-box;max-width:690px;padding-bottom:20px}.tsf-metaboxes .tsf-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-metaboxes .tsf-top-wrap>h1,.tsf-metaboxes .tsf-top-wrap>h2{float:left}.tsf-metaboxes .metabox-holder{clear:both}.tsf-metaboxes .tsf-top-buttons{float:right}.tsf-metaboxes .tsf-bottom-buttons{text-align:right}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}.tsf-metaboxes #tsf-description-separator,.tsf-metaboxes #tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}.tsf-metaboxes #tsf-description-separator input,.tsf-metaboxes #tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #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-metaboxes #tsf-description-separator label.tsf-recommended,.tsf-metaboxes #tsf-title-separator label.tsf-recommended{border:1px solid #0cc34b;box-shadow:-1px -1px 1px #0cc34b inset}.tsf-metaboxes #tsf-description-separator input:hover+label,.tsf-metaboxes #tsf-description-separator label:hover,.tsf-metaboxes #tsf-title-separator input:hover+label,.tsf-metaboxes #tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}.tsf-metaboxes #tsf-description-separator input:checked+label,.tsf-metaboxes #tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}.tsf-metaboxes #tsf-home-title-location,.tsf-metaboxes #tsf-title-location{display:block}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span,.tsf-metaboxes #tsf-twitter-cards label span{display:inline-block;min-width:60px;vertical-align:baseline}.tsf-metaboxes #tsf-twitter-cards label span{min-width:150px}.tsf-metaboxes #tsf-home-title-location label .autodescription-sep-js,.tsf-metaboxes #tsf-home-title-location label span.custom-title-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,.tsf-metaboxes #tsf-title-location label .autodescription-sep-js{display:inline;min-width:0;white-space:pre}.tsf-metaboxes .tsf-nav-tab-wrapper,.tsf-metaboxes .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-metaboxes .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}.tsf-metaboxes .tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}.tsf-metaboxes .tsf-tabs-radio{display:none;width:0;height:0;position:absolute;left:-9001px}.tsf-metaboxes .tsf-active-tab,.tsf-metaboxes .tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-metaboxes .tsf-tabs-content{margin:1.33em auto 0}.tsf-metaboxes .seoframework-content-no-js{margin:1.33em auto}body.js .tsf-metaboxes .tsf-tabs-content{display:none}body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content{display:block}.tsf-metaboxes .tsf-default-selected{border-color:#1c9d38}.tsf-metaboxes .tsf-default-selected:checked:before{color:#1c9d38}.tsf-metaboxes .tsf-warning-selected{border-color:#dd3811}.tsf-metaboxes .tsf-warning-selected:checked:before{color:#dd3811}.tsf-fields{font-size:13px;line-height:1.5;margin:1em 0}.tsf-fields .tsf-toblock{display:block;width:100%;margin-bottom:4px}.tsf-fields p.description{margin:7px 0 5px;color:#666}.tsf-option-spacer{margin:1em 0}.tsf-counter .tsf-ajax{margin-left:3px}.tsf-ajax:before{display:inline-block;line-height:1;font-family:dashicons;font-style:normal;font-weight:400;font-size:1.225em;vertical-align:middle;content:""}.tsf-ajax.tsf-loading:before{content:"\f463";color:#007bd2;-webkit-animation:tsf-spin 1.5s linear infinite;-moz-animation:tsf-spin 1.5s linear infinite;-o-animation:tsf-spin 1.5s linear infinite;animation:tsf-spin 1.5s linear infinite}.tsf-ajax.tsf-error:before{content:"\f158";color:#dd3811}.tsf-ajax.tsf-success:before{content:"\f147";color:#0cc34b}@-webkit-keyframes tsf-spin{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes tsf-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media screen and (max-width:782px){.tsf-inpost-box p.tsf-fields,.tsf-metaboxes p.tsf-fields{line-height:2.8}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span{min-width:40px}}@media screen and (max-width:642px){.tsf-metaboxes span.tsf-nav-desktop{display:none}}@media screen and (max-width:510px){span.tsf-seo-bar.tsf-100{width:inherit}}@-moz-document url-prefix(){.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{margin:3px 1px}@media only screen and (min-width:768px){.widefat tr td.column-title:nth-child(2):nth-last-child(n+6),.widefat tr td.title:nth-child(2):nth-last-child(n+6),.widefat tr th.column-title:nth-child(2):nth-last-child(n+6),.widefat tr th.title:nth-child(2):nth-last-child(n+6){min-width:1em;width:25%;max-width:100%;white-space:unset}}.tsf-metaboxes .tsf-default-selected{box-shadow:0 0 2px 0 #1c9d38}.tsf-metaboxes .tsf-warning-selected{box-shadow:0 0 2px 0 #dd3811}.tsf-metaboxes legend h4{margin:2px 0}}
 
lib/css/{autodescription-rtl.css → tsf-rtl.css} RENAMED
@@ -79,7 +79,8 @@ table.wp-list-table .column-name {
79
  table.wp-list-table .column-is_in_stock,
80
  table.wp-list-table .column-sku,
81
  table.wp-list-table .column-price,
82
- table.wp-list-table .column-icl_translations {
 
83
  width: 8%;
84
  }
85
 
@@ -94,6 +95,7 @@ table.wp-list-table .column-icl_translations {
94
  padding: 0;
95
  height: auto;
96
  width: auto;
 
97
  }
98
 
99
  #tsf-title-offset {
@@ -146,10 +148,9 @@ span.tsf-count-good {
146
 
147
  span.tsf-counter-one {
148
  color: #fff;
149
- padding: 3px;
150
- border-radius: 58px;
151
- padding: 0 1px;
152
- min-width: 29px;
153
  display: inline-block;
154
  text-align: center;
155
  vertical-align: baseline;
@@ -457,11 +458,11 @@ span.tsf-seo-bar .tsf-explanation-desc div {
457
  min-width: 150px;
458
  }
459
 
460
- .tsf-metaboxes #tsf-home-title-location label span.custom-title-js,
461
  .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,
462
  .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,
463
- .tsf-metaboxes #tsf-title-location label .autodescription-sep-js,
464
- .tsf-metaboxes #tsf-home-title-location label .autodescription-sep-js {
465
  display: inline;
466
  min-width: 0;
467
  white-space: pre;
@@ -520,7 +521,7 @@ span.tsf-seo-bar .tsf-explanation-desc div {
520
  margin: 1.33em auto 0;
521
  }
522
 
523
- .tsf-metaboxes .seoframework-content-no-js {
524
  margin: 1.33em auto;
525
  }
526
 
@@ -607,6 +608,58 @@ body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content {
607
  color: #0cc34b;
608
  }
609
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
610
  @-webkit-keyframes tsf-spin {
611
  0% {
612
  -webkit-transform: rotate( 0deg );
@@ -635,6 +688,10 @@ body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content {
635
  .tsf-metaboxes #tsf-home-title-location label span {
636
  min-width: 40px;
637
  }
 
 
 
 
638
  }
639
 
640
  @media screen and (max-width: 642px) {
79
  table.wp-list-table .column-is_in_stock,
80
  table.wp-list-table .column-sku,
81
  table.wp-list-table .column-price,
82
+ table.wp-list-table .column-icl_translations,
83
+ th.column-tsf-seo-bar-wrap ~ th {
84
  width: 8%;
85
  }
86
 
95
  padding: 0;
96
  height: auto;
97
  width: auto;
98
+ overflow: hidden;
99
  }
100
 
101
  #tsf-title-offset {
148
 
149
  span.tsf-counter-one {
150
  color: #fff;
151
+ border-radius: 4em;
152
+ padding: 0 0.5em;
153
+ min-width: 2em;
 
154
  display: inline-block;
155
  text-align: center;
156
  vertical-align: baseline;
458
  min-width: 150px;
459
  }
460
 
461
+ .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-title-js,
462
  .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,
463
  .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,
464
+ .tsf-metaboxes #tsf-title-location label .tsf-sep-js,
465
+ .tsf-metaboxes #tsf-home-title-location label .tsf-sep-js {
466
  display: inline;
467
  min-width: 0;
468
  white-space: pre;
521
  margin: 1.33em auto 0;
522
  }
523
 
524
+ .tsf-metaboxes .tsf-content-no-js {
525
  margin: 1.33em auto;
526
  }
527
 
608
  color: #0cc34b;
609
  }
610
 
611
+ a.tsf-set-social-image.button {
612
+ margin-left: 7px;
613
+ }
614
+
615
+ #tsf-inpost-box input[type="text"]::-webkit-input-placeholder,
616
+ #tsf-inpost-box textarea::-webkit-input-placeholder,
617
+ .tsf-metaboxes input[type="text"]::-webkit-input-placeholder,
618
+ .tsf-metaboxes textarea::-webkit-input-placeholder {
619
+ -webkit-transition: all 0.33s ease-in;
620
+ -o-transition: all 0.33s ease-in;
621
+ transition: all 0.33s ease-in;
622
+ }
623
+
624
+ #tsf-inpost-box input[type="text"]::-moz-placeholder,
625
+ #tsf-inpost-box textarea::-moz-placeholder,
626
+ .tsf-metaboxes input[type="text"]::-moz-placeholder,
627
+ .tsf-metaboxes textarea::-moz-placeholder {
628
+ -moz-transition: all 0.33s ease-in;
629
+ transition: all 0.33s ease-in;
630
+ }
631
+
632
+ #tsf-inpost-box input[type="text"]:-ms-input-placeholder,
633
+ #tsf-inpost-box textarea:-ms-input-placeholder,
634
+ .tsf-metaboxes input[type="text"]:-ms-input-placeholder,
635
+ .tsf-metaboxes textarea:-ms-input-placeholder {
636
+ transition: all 0.33s ease-in;
637
+ }
638
+
639
+ #tsf-inpost-box input[type="text"]:focus::-webkit-input-placeholder,
640
+ #tsf-inpost-box textarea:focus::-webkit-input-placeholder,
641
+ .tsf-metaboxes input[type="text"]:focus::-webkit-input-placeholder,
642
+ .tsf-metaboxes textarea:focus::-webkit-input-placeholder {
643
+ color: transparent;
644
+ text-shadow: 0 0 1px rgba(114, 119, 124, 0.75);
645
+ }
646
+
647
+ #tsf-inpost-box input[type="text"]:focus::-moz-placeholder,
648
+ #tsf-inpost-box textarea:focus::-moz-placeholder,
649
+ .tsf-metaboxes input[type="text"]:focus::-moz-placeholder,
650
+ .tsf-metaboxe textarea:focus::-moz-placeholder {
651
+ color: transparent;
652
+ text-shadow: 0 0 1px rgba(114, 119, 124, 0.75);
653
+ }
654
+
655
+ #tsf-inpost-box input[type="text"]:focus:-ms-input-placeholder,
656
+ #tsf-inpost-box textarea:focus:-ms-input-placeholder,
657
+ .tsf-metaboxes input[type="text"]:focus:-ms-input-placeholder,
658
+ .tsf-metaboxes textarea:focus:-ms-input-placeholder {
659
+ color: transparent;
660
+ text-shadow: 0 0 1px rgba(114, 119, 124, 0.75);
661
+ }
662
+
663
  @-webkit-keyframes tsf-spin {
664
  0% {
665
  -webkit-transform: rotate( 0deg );
688
  .tsf-metaboxes #tsf-home-title-location label span {
689
  min-width: 40px;
690
  }
691
+
692
+ .wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden) {
693
+ overflow: initial !important;
694
+ }
695
  }
696
 
697
  @media screen and (max-width: 642px) {
lib/css/tsf-rtl.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .tsf-metaboxes .tsf-top-buttons,.tsf-metaboxes .tsf-top-wrap>h1,.tsf-metaboxes .tsf-top-wrap>h2{float:left}.tsf-notice{position:relative;clear:both}.tsf-notice.tsf-show-icon p:before{content:'';margin-left:12px;background:0 0;display:inline-block;font:400 14px/16px dashicons;speak:none;height:16px;text-align:center;vertical-align:middle;width:16px;line-height:14px;-webkit-font-smoothing:antialiased}.error.tsf-notice.tsf-show-icon p:before{color:#dd3811;content:"\f534"}.notice-warning.tsf-notice.tsf-show-icon p:before{color:#ffa01b;content:"\f227"}.updated.tsf-notice.tsf-show-icon p:before{color:#0cc34b;font-size:16px;content:"\f147"}a.tsf-dismiss{position:absolute;top:0;left:1px;border:none;margin:0;padding:9px;background:0 0;color:#b4b9be;cursor:pointer;text-decoration:none}a.tsf-dismiss:before{background:0 0;content:"\f153";display:block;font:400 16px/20px dashicons;speak:none;height:20px;text-align:center;width:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a.tsf-dismiss:hover{color:#c00}table.wp-list-table .column-name{width:15%}table.wp-list-table .column-icl_translations,table.wp-list-table .column-is_in_stock,table.wp-list-table .column-price,table.wp-list-table .column-sku,th.column-tsf-seo-bar-wrap~th{width:8%}.tsf-seo-bar a{text-decoration:none;font-size:13px}#tsf-title-wrap{position:relative;display:block;padding:0;height:auto;width:auto;overflow:hidden}#tsf-title-offset{visibility:hidden;height:0;display:inline-block;position:absolute;right:0;color:transparent;white-space:pre}#tsf-title-placeholder{position:absolute;color:#777;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;top:0;left:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.tsf-counter{font-weight:600;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}span.tsf-count-bad{color:#dd3811}span.tsf-count-okay{color:#ffa700}span.tsf-count-good{color:#0cc34b}span.tsf-counter-one{color:#fff;border-radius:4em;padding:0 .5em;min-width:2em;display:inline-block;text-align:center;vertical-align:baseline}span.tsf-counter-one.tsf-count-bad{background-color:#dd3811}span.tsf-counter-one.tsf-count-okay{background-color:#ffa700}span.tsf-counter-one.tsf-count-good{background-color:#0cc34b}#tsf-seo-bar-wrap{width:18%}th:last-of-type#tsf-seo-bar-wrap{width:160px}span.tsf-seo-bar{display:block;width:95%;max-width:220px;border-radius:0;padding:3px;text-shadow:0 0 3px rgba(0,0,0,.3)}span.tsf-seo-bar.tsf-100{width:100%}span.tsf-seo-bar-inner-wrap{display:table;width:100%;border-radius:0;margin:0 auto;border-collapse:separate;border-spacing:0;vertical-align:middle;position:relative}span.tsf-seo-bar-section-wrap{display:table-cell;border-collapse:collapse}.tsf-seo-bar-inner-wrap a{display:table;width:100%;color:#fff;text-align:center;cursor:help;height:100%;min-width:12px;vertical-align:top;line-height:1.625em;box-shadow:2px 0 0 -1px rgba(0,0,0,.1) inset,-2px 0 0 -1px rgba(0,0,0,.1) inset}span.tsf-seo-bar.pill,span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap{border-radius:30px}span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a{box-shadow:2px 6px 3px -2px rgba(255,255,255,.2) inset,-2px -6px 3px -2px rgba(41,41,41,.2) inset,0 0 1px rgba(41,41,41,.6)}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type a{border-top-left-radius:30px;border-bottom-left-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type a{border-top-right-radius:30px;border-bottom-right-radius:30px}.tsf-100{width:100%}.tsf-60{width:60%}.tsf-50{width:50%}.tsf-40{width:40%}.tsf-33{width:33.333%}.tsf-25{width:25%}.tsf-20{width:20%}.tsf-16{width:16.666%}.tsf-12-5{width:12.5%}.ad-11{width:11.333%}.tsf-10{width:10%}.tsf-seo-bar-bad{background-color:#dd3811}.tsf-seo-bar-okay{background-color:#ffa700}.tsf-seo-bar-good{background-color:#0cc34b}.tsf-seo-bar-unknown{background-color:#007bd2}span.tsf-seo-bar .tsf-explanation-desc{position:absolute;width:auto;min-width:90%;max-width:220px;font-weight:600;background:#007bd2;padding:8px 12px;color:#fdfdfd;border-radius:0;z-index:900142;box-shadow:0 0 2px rgba(0,0,0,.6);left:0;right:0;text-align:left}span.tsf-seo-bar .tsf-explanation-desc span{text-decoration:underline}span.tsf-seo-bar .tsf-explanation-desc div{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-top:12px solid #007bd2;position:absolute;bottom:-8px;z-index:9999999;left:0}.tsf-seo-bar-wrap.column-tsf-seo-bar-temp{overflow:initial!important;min-width:160px}#col-container,#col-right{overflow:initial}.tsf-metaboxes{box-sizing:border-box;max-width:690px;padding-bottom:20px}.tsf-metaboxes .tsf-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-metaboxes .metabox-holder{clear:both}.tsf-metaboxes .tsf-bottom-buttons{text-align:left}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}.tsf-metaboxes #tsf-description-separator,.tsf-metaboxes #tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}.tsf-metaboxes #tsf-description-separator input,.tsf-metaboxes #tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #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-metaboxes #tsf-description-separator label.tsf-recommended,.tsf-metaboxes #tsf-title-separator label.tsf-recommended{border:1px solid #0cc34b;box-shadow:-1px -1px 1px #0cc34b inset}.tsf-metaboxes #tsf-description-separator input:hover+label,.tsf-metaboxes #tsf-description-separator label:hover,.tsf-metaboxes #tsf-title-separator input:hover+label,.tsf-metaboxes #tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}.tsf-metaboxes #tsf-description-separator input:checked+label,.tsf-metaboxes #tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}.tsf-metaboxes #tsf-home-title-location,.tsf-metaboxes #tsf-title-location{display:block}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span,.tsf-metaboxes #tsf-twitter-cards label span{display:inline-block;min-width:60px;vertical-align:baseline}.tsf-metaboxes #tsf-twitter-cards label span{min-width:150px}.tsf-metaboxes #tsf-home-title-location label .tsf-sep-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-title-js,.tsf-metaboxes #tsf-title-location label .tsf-sep-js{display:inline;min-width:0;white-space:pre}.tsf-metaboxes .tsf-nav-tab-wrapper,.tsf-metaboxes .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-metaboxes .tsf-nav-tab{float:right;border:1px solid #ccc;margin-right:.5em;margin-bottom:-1px;padding:5px 14px;font-size:12px;line-height:16px;background:#f1f1f1;color:#555;font-weight:600}.tsf-metaboxes .tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}.tsf-metaboxes .tsf-tabs-radio{display:none;width:0;height:0;position:absolute;left:-9001px}.tsf-metaboxes .tsf-active-tab,.tsf-metaboxes .tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-metaboxes .tsf-tabs-content{margin:1.33em auto 0}.tsf-metaboxes .tsf-content-no-js{margin:1.33em auto}body.js .tsf-metaboxes .tsf-tabs-content{display:none}body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content{display:block}.tsf-metaboxes .tsf-default-selected{border-color:#1c9d38}.tsf-metaboxes .tsf-default-selected:checked:before{color:#1c9d38}.tsf-metaboxes .tsf-warning-selected{border-color:#dd3811}.tsf-metaboxes .tsf-warning-selected:checked:before{color:#dd3811}.tsf-fields{font-size:13px;line-height:1.5;margin:1em 0}.tsf-fields .tsf-toblock{display:block;width:100%;margin-bottom:4px}.tsf-fields p.description{margin:7px 0 5px;color:#666}.tsf-option-spacer{margin:1em 0}.tsf-counter .tsf-ajax{margin-right:3px}.tsf-ajax:before{display:inline-block;line-height:1;font-family:dashicons;font-style:normal;font-weight:400;font-size:1.225em;vertical-align:middle;content:""}.tsf-ajax.tsf-loading:before{content:"\f463";color:#007bd2;-webkit-animation:tsf-spin 1.5s linear infinite;-moz-animation:tsf-spin 1.5s linear infinite;-o-animation:tsf-spin 1.5s linear infinite;animation:tsf-spin 1.5s linear infinite}.tsf-ajax.tsf-error:before{content:"\f158";color:#dd3811}.tsf-ajax.tsf-success:before{content:"\f147";color:#0cc34b}a.tsf-set-social-image.button{margin-left:7px}#tsf-inpost-box input[type=text]::-webkit-input-placeholder,#tsf-inpost-box textarea::-webkit-input-placeholder,.tsf-metaboxes input[type=text]::-webkit-input-placeholder,.tsf-metaboxes textarea::-webkit-input-placeholder{-webkit-transition:all .33s ease-in;-o-transition:all .33s ease-in;transition:all .33s ease-in}#tsf-inpost-box input[type=text]::-moz-placeholder,#tsf-inpost-box textarea::-moz-placeholder,.tsf-metaboxes input[type=text]::-moz-placeholder,.tsf-metaboxes textarea::-moz-placeholder{-moz-transition:all .33s ease-in;transition:all .33s ease-in}#tsf-inpost-box input[type=text]:-ms-input-placeholder,#tsf-inpost-box textarea:-ms-input-placeholder,.tsf-metaboxes input[type=text]:-ms-input-placeholder,.tsf-metaboxes textarea:-ms-input-placeholder{transition:all .33s ease-in}#tsf-inpost-box input[type=text]:focus::-webkit-input-placeholder,#tsf-inpost-box textarea:focus::-webkit-input-placeholder,.tsf-metaboxes input[type=text]:focus::-webkit-input-placeholder,.tsf-metaboxes textarea:focus::-webkit-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus::-moz-placeholder,#tsf-inpost-box textarea:focus::-moz-placeholder,.tsf-metaboxe textarea:focus::-moz-placeholder,.tsf-metaboxes input[type=text]:focus::-moz-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus:-ms-input-placeholder,#tsf-inpost-box textarea:focus:-ms-input-placeholder,.tsf-metaboxes input[type=text]:focus:-ms-input-placeholder,.tsf-metaboxes textarea:focus:-ms-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}@-webkit-keyframes tsf-spin{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes tsf-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media screen and (max-width:782px){.tsf-inpost-box p.tsf-fields,.tsf-metaboxes p.tsf-fields{line-height:2.8}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span{min-width:40px}.wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden){overflow:initial!important}}@media screen and (max-width:642px){.tsf-metaboxes span.tsf-nav-desktop{display:none}}@media screen and (max-width:510px){span.tsf-seo-bar.tsf-100{width:inherit}}@-moz-document url-prefix(){.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{margin:3px 1px}@media only screen and (min-width:768px){.widefat tr td.column-title:nth-child(2):nth-last-child(n+6),.widefat tr td.title:nth-child(2):nth-last-child(n+6),.widefat tr th.column-title:nth-child(2):nth-last-child(n+6),.widefat tr th.title:nth-child(2):nth-last-child(n+6){min-width:1em;width:25%;max-width:100%;white-space:unset}}.tsf-metaboxes .tsf-default-selected{box-shadow:0 0 2px 0 #1c9d38}.tsf-metaboxes .tsf-warning-selected{box-shadow:0 0 2px 0 #dd3811}.tsf-metaboxes legend h4{margin:2px 0}}
lib/css/{autodescription.css → tsf.css} RENAMED
@@ -72,8 +72,8 @@ a.tsf-dismiss:hover {
72
  }
73
 
74
  /**
75
- * WooCommerce fix @TODO make this load only when admin bar is showing.
76
- */
77
  table.wp-list-table .column-name {
78
  width: 15%;
79
  }
@@ -84,7 +84,8 @@ table.wp-list-table .column-name {
84
  table.wp-list-table .column-is_in_stock,
85
  table.wp-list-table .column-sku,
86
  table.wp-list-table .column-price,
87
- table.wp-list-table .column-icl_translations {
 
88
  width: 8%;
89
  }
90
 
@@ -99,6 +100,7 @@ table.wp-list-table .column-icl_translations {
99
  padding: 0;
100
  height: auto;
101
  width: auto;
 
102
  }
103
 
104
  #tsf-title-offset {
@@ -151,10 +153,9 @@ span.tsf-count-good {
151
 
152
  span.tsf-counter-one {
153
  color: #fff;
154
- padding: 3px;
155
- border-radius: 58px;
156
- padding: 0 1px;
157
- min-width: 29px;
158
  display: inline-block;
159
  text-align: center;
160
  vertical-align: baseline;
@@ -461,11 +462,11 @@ span.tsf-seo-bar .tsf-explanation-desc div {
461
  min-width: 150px;
462
  }
463
 
464
- .tsf-metaboxes #tsf-home-title-location label span.custom-title-js,
465
  .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,
466
  .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,
467
- .tsf-metaboxes #tsf-title-location label .autodescription-sep-js,
468
- .tsf-metaboxes #tsf-home-title-location label .autodescription-sep-js {
469
  display: inline;
470
  min-width: 0;
471
  white-space: pre;
@@ -524,7 +525,7 @@ span.tsf-seo-bar .tsf-explanation-desc div {
524
  margin: 1.33em auto 0;
525
  }
526
 
527
- .tsf-metaboxes .seoframework-content-no-js {
528
  margin: 1.33em auto;
529
  }
530
 
@@ -611,6 +612,58 @@ body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content {
611
  color: #0cc34b;
612
  }
613
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
614
  @-webkit-keyframes tsf-spin {
615
  0% {
616
  -webkit-transform: rotate( 0deg );
@@ -639,6 +692,10 @@ body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content {
639
  .tsf-metaboxes #tsf-home-title-location label span {
640
  min-width: 40px;
641
  }
 
 
 
 
642
  }
643
 
644
  @media screen and (max-width: 642px) {
72
  }
73
 
74
  /**
75
+ * WooCommerce fix @TODO make this load only when admin sidebar is showing.
76
+ */
77
  table.wp-list-table .column-name {
78
  width: 15%;
79
  }
84
  table.wp-list-table .column-is_in_stock,
85
  table.wp-list-table .column-sku,
86
  table.wp-list-table .column-price,
87
+ table.wp-list-table .column-icl_translations,
88
+ th.column-tsf-seo-bar-wrap ~ th {
89
  width: 8%;
90
  }
91
 
100
  padding: 0;
101
  height: auto;
102
  width: auto;
103
+ overflow: hidden;
104
  }
105
 
106
  #tsf-title-offset {
153
 
154
  span.tsf-counter-one {
155
  color: #fff;
156
+ border-radius: 4em;
157
+ padding: 0 0.5em;
158
+ min-width: 2em;
 
159
  display: inline-block;
160
  text-align: center;
161
  vertical-align: baseline;
462
  min-width: 150px;
463
  }
464
 
465
+ .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-title-js,
466
  .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,
467
  .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,
468
+ .tsf-metaboxes #tsf-title-location label .tsf-sep-js,
469
+ .tsf-metaboxes #tsf-home-title-location label .tsf-sep-js {
470
  display: inline;
471
  min-width: 0;
472
  white-space: pre;
525
  margin: 1.33em auto 0;
526
  }
527
 
528
+ .tsf-metaboxes .tsf-content-no-js {
529
  margin: 1.33em auto;
530
  }
531
 
612
  color: #0cc34b;
613
  }
614
 
615
+ a.tsf-set-social-image.button {
616
+ margin-right: 7px;
617
+ }
618
+
619
+ #tsf-inpost-box input[type="text"]::-webkit-input-placeholder,
620
+ #tsf-inpost-box textarea::-webkit-input-placeholder,
621
+ .tsf-metaboxes input[type="text"]::-webkit-input-placeholder,
622
+ .tsf-metaboxes textarea::-webkit-input-placeholder {
623
+ -webkit-transition: all 0.33s ease-in;
624
+ -o-transition: all 0.33s ease-in;
625
+ transition: all 0.33s ease-in;
626
+ }
627
+
628
+ #tsf-inpost-box input[type="text"]::-moz-placeholder,
629
+ #tsf-inpost-box textarea::-moz-placeholder,
630
+ .tsf-metaboxes input[type="text"]::-moz-placeholder,
631
+ .tsf-metaboxes textarea::-moz-placeholder {
632
+ -moz-transition: all 0.33s ease-in;
633
+ transition: all 0.33s ease-in;
634
+ }
635
+
636
+ #tsf-inpost-box input[type="text"]:-ms-input-placeholder,
637
+ #tsf-inpost-box textarea:-ms-input-placeholder,
638
+ .tsf-metaboxes input[type="text"]:-ms-input-placeholder,
639
+ .tsf-metaboxes textarea:-ms-input-placeholder {
640
+ transition: all 0.33s ease-in;
641
+ }
642
+
643
+ #tsf-inpost-box input[type="text"]:focus::-webkit-input-placeholder,
644
+ #tsf-inpost-box textarea:focus::-webkit-input-placeholder,
645
+ .tsf-metaboxes input[type="text"]:focus::-webkit-input-placeholder,
646
+ .tsf-metaboxes textarea:focus::-webkit-input-placeholder {
647
+ color: transparent;
648
+ text-shadow: 0 0 1px rgba(114, 119, 124, 0.75);
649
+ }
650
+
651
+ #tsf-inpost-box input[type="text"]:focus::-moz-placeholder,
652
+ #tsf-inpost-box textarea:focus::-moz-placeholder,
653
+ .tsf-metaboxes input[type="text"]:focus::-moz-placeholder,
654
+ .tsf-metaboxe textarea:focus::-moz-placeholder {
655
+ color: transparent;
656
+ text-shadow: 0 0 1px rgba(114, 119, 124, 0.75);
657
+ }
658
+
659
+ #tsf-inpost-box input[type="text"]:focus:-ms-input-placeholder,
660
+ #tsf-inpost-box textarea:focus:-ms-input-placeholder,
661
+ .tsf-metaboxes input[type="text"]:focus:-ms-input-placeholder,
662
+ .tsf-metaboxes textarea:focus:-ms-input-placeholder {
663
+ color: transparent;
664
+ text-shadow: 0 0 1px rgba(114, 119, 124, 0.75);
665
+ }
666
+
667
  @-webkit-keyframes tsf-spin {
668
  0% {
669
  -webkit-transform: rotate( 0deg );
692
  .tsf-metaboxes #tsf-home-title-location label span {
693
  min-width: 40px;
694
  }
695
+
696
+ .wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden) {
697
+ overflow: initial !important;
698
+ }
699
  }
700
 
701
  @media screen and (max-width: 642px) {
lib/css/tsf.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .tsf-notice{position:relative;clear:both}.tsf-notice.tsf-show-icon p:before{content:'';margin-right:12px;background:0 0;display:inline-block;font:400 14px/16px dashicons;speak:none;height:16px;text-align:center;vertical-align:middle;width:16px;line-height:14px;-webkit-font-smoothing:antialiased}.error.tsf-notice.tsf-show-icon p:before{color:#dd3811;content:"\f534"}.notice-warning.tsf-notice.tsf-show-icon p:before{color:#ffa01b;content:"\f227"}.updated.tsf-notice.tsf-show-icon p:before{color:#0cc34b;font-size:16px;content:"\f147"}a.tsf-dismiss{position:absolute;top:0;right:1px;border:none;margin:0;padding:9px;background:0 0;color:#b4b9be;cursor:pointer;text-decoration:none}a.tsf-dismiss:before{background:0 0;content:"\f153";display:block;font:400 16px/20px dashicons;speak:none;height:20px;text-align:center;width:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a.tsf-dismiss:hover{color:#c00}table.wp-list-table .column-name{width:15%}table.wp-list-table .column-icl_translations,table.wp-list-table .column-is_in_stock,table.wp-list-table .column-price,table.wp-list-table .column-sku,th.column-tsf-seo-bar-wrap~th{width:8%}.tsf-seo-bar a{text-decoration:none;font-size:13px}#tsf-title-wrap{position:relative;display:block;padding:0;height:auto;width:auto;overflow:hidden}#tsf-title-offset{visibility:hidden;height:0;display:inline-block;position:absolute;left:0;color:transparent;white-space:pre}#tsf-title-placeholder{position:absolute;color:#777;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;top:0;left:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.tsf-counter{font-weight:600;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}span.tsf-count-bad{color:#dd3811}span.tsf-count-okay{color:#ffa700}span.tsf-count-good{color:#0cc34b}span.tsf-counter-one{color:#fff;border-radius:4em;padding:0 .5em;min-width:2em;display:inline-block;text-align:center;vertical-align:baseline}span.tsf-counter-one.tsf-count-bad{background-color:#dd3811}span.tsf-counter-one.tsf-count-okay{background-color:#ffa700}span.tsf-counter-one.tsf-count-good{background-color:#0cc34b}#tsf-seo-bar-wrap{width:18%}th:last-of-type#tsf-seo-bar-wrap{width:160px}span.tsf-seo-bar{display:block;width:95%;max-width:220px;border-radius:0;padding:3px;text-shadow:0 0 3px rgba(0,0,0,.3)}span.tsf-seo-bar.tsf-100{width:100%}span.tsf-seo-bar-inner-wrap{display:table;width:100%;border-radius:0;margin:0 auto;border-collapse:separate;border-spacing:0;vertical-align:middle;position:relative}span.tsf-seo-bar-section-wrap{display:table-cell;border-collapse:collapse}.tsf-seo-bar-inner-wrap a{display:table;width:100%;color:#fff;text-align:center;cursor:help;height:100%;min-width:12px;vertical-align:top;line-height:1.625em;box-shadow:2px 0 0 -1px rgba(0,0,0,.1) inset,-2px 0 0 -1px rgba(0,0,0,.1) inset}span.tsf-seo-bar.pill,span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap{border-radius:30px}span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a{box-shadow:2px 6px 3px -2px rgba(255,255,255,.2) inset,-2px -6px 3px -2px rgba(41,41,41,.2) inset,0 0 1px rgba(41,41,41,.6)}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type a{border-top-left-radius:30px;border-bottom-left-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type a{border-top-right-radius:30px;border-bottom-right-radius:30px}.tsf-100{width:100%}.tsf-60{width:60%}.tsf-50{width:50%}.tsf-40{width:40%}.tsf-33{width:33.333%}.tsf-25{width:25%}.tsf-20{width:20%}.tsf-16{width:16.666%}.tsf-12-5{width:12.5%}.ad-11{width:11.333%}.tsf-10{width:10%}.tsf-seo-bar-bad{background-color:#dd3811}.tsf-seo-bar-okay{background-color:#ffa700}.tsf-seo-bar-good{background-color:#0cc34b}.tsf-seo-bar-unknown{background-color:#007bd2}span.tsf-seo-bar .tsf-explanation-desc{position:absolute;width:auto;min-width:90%;max-width:220px;font-weight:600;background:#007bd2;padding:8px 12px;color:#fdfdfd;border-radius:0;z-index:900142;box-shadow:0 0 2px rgba(0,0,0,.6);left:0;right:0;text-align:left}span.tsf-seo-bar .tsf-explanation-desc span{text-decoration:underline}span.tsf-seo-bar .tsf-explanation-desc div{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-top:12px solid #007bd2;position:absolute;bottom:-8px;z-index:9999999;left:0}.tsf-seo-bar-wrap.column-tsf-seo-bar-temp{overflow:initial!important;min-width:160px}#col-container,#col-right{overflow:initial}.tsf-metaboxes{box-sizing:border-box;max-width:690px;padding-bottom:20px}.tsf-metaboxes .tsf-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-metaboxes .tsf-top-wrap>h1,.tsf-metaboxes .tsf-top-wrap>h2{float:left}.tsf-metaboxes .metabox-holder{clear:both}.tsf-metaboxes .tsf-top-buttons{float:right}.tsf-metaboxes .tsf-bottom-buttons{text-align:right}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}.tsf-metaboxes #tsf-description-separator,.tsf-metaboxes #tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}.tsf-metaboxes #tsf-description-separator input,.tsf-metaboxes #tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #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-metaboxes #tsf-description-separator label.tsf-recommended,.tsf-metaboxes #tsf-title-separator label.tsf-recommended{border:1px solid #0cc34b;box-shadow:-1px -1px 1px #0cc34b inset}.tsf-metaboxes #tsf-description-separator input:hover+label,.tsf-metaboxes #tsf-description-separator label:hover,.tsf-metaboxes #tsf-title-separator input:hover+label,.tsf-metaboxes #tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}.tsf-metaboxes #tsf-description-separator input:checked+label,.tsf-metaboxes #tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}.tsf-metaboxes #tsf-home-title-location,.tsf-metaboxes #tsf-title-location{display:block}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span,.tsf-metaboxes #tsf-twitter-cards label span{display:inline-block;min-width:60px;vertical-align:baseline}.tsf-metaboxes #tsf-twitter-cards label span{min-width:150px}.tsf-metaboxes #tsf-home-title-location label .tsf-sep-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,.tsf-metaboxes #tsf-home-title-location label span.tsf-custom-title-js,.tsf-metaboxes #tsf-title-location label .tsf-sep-js{display:inline;min-width:0;white-space:pre}.tsf-metaboxes .tsf-nav-tab-wrapper,.tsf-metaboxes .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-metaboxes .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}.tsf-metaboxes .tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}.tsf-metaboxes .tsf-tabs-radio{display:none;width:0;height:0;position:absolute;left:-9001px}.tsf-metaboxes .tsf-active-tab,.tsf-metaboxes .tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-metaboxes .tsf-tabs-content{margin:1.33em auto 0}.tsf-metaboxes .tsf-content-no-js{margin:1.33em auto}body.js .tsf-metaboxes .tsf-tabs-content{display:none}body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content{display:block}.tsf-metaboxes .tsf-default-selected{border-color:#1c9d38}.tsf-metaboxes .tsf-default-selected:checked:before{color:#1c9d38}.tsf-metaboxes .tsf-warning-selected{border-color:#dd3811}.tsf-metaboxes .tsf-warning-selected:checked:before{color:#dd3811}.tsf-fields{font-size:13px;line-height:1.5;margin:1em 0}.tsf-fields .tsf-toblock{display:block;width:100%;margin-bottom:4px}.tsf-fields p.description{margin:7px 0 5px;color:#666}.tsf-option-spacer{margin:1em 0}.tsf-counter .tsf-ajax{margin-left:3px}.tsf-ajax:before{display:inline-block;line-height:1;font-family:dashicons;font-style:normal;font-weight:400;font-size:1.225em;vertical-align:middle;content:""}.tsf-ajax.tsf-loading:before{content:"\f463";color:#007bd2;-webkit-animation:tsf-spin 1.5s linear infinite;-moz-animation:tsf-spin 1.5s linear infinite;-o-animation:tsf-spin 1.5s linear infinite;animation:tsf-spin 1.5s linear infinite}.tsf-ajax.tsf-error:before{content:"\f158";color:#dd3811}.tsf-ajax.tsf-success:before{content:"\f147";color:#0cc34b}a.tsf-set-social-image.button{margin-right:7px}#tsf-inpost-box input[type=text]::-webkit-input-placeholder,#tsf-inpost-box textarea::-webkit-input-placeholder,.tsf-metaboxes input[type=text]::-webkit-input-placeholder,.tsf-metaboxes textarea::-webkit-input-placeholder{-webkit-transition:all .33s ease-in;-o-transition:all .33s ease-in;transition:all .33s ease-in}#tsf-inpost-box input[type=text]::-moz-placeholder,#tsf-inpost-box textarea::-moz-placeholder,.tsf-metaboxes input[type=text]::-moz-placeholder,.tsf-metaboxes textarea::-moz-placeholder{-moz-transition:all .33s ease-in;transition:all .33s ease-in}#tsf-inpost-box input[type=text]:-ms-input-placeholder,#tsf-inpost-box textarea:-ms-input-placeholder,.tsf-metaboxes input[type=text]:-ms-input-placeholder,.tsf-metaboxes textarea:-ms-input-placeholder{transition:all .33s ease-in}#tsf-inpost-box input[type=text]:focus::-webkit-input-placeholder,#tsf-inpost-box textarea:focus::-webkit-input-placeholder,.tsf-metaboxes input[type=text]:focus::-webkit-input-placeholder,.tsf-metaboxes textarea:focus::-webkit-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus::-moz-placeholder,#tsf-inpost-box textarea:focus::-moz-placeholder,.tsf-metaboxe textarea:focus::-moz-placeholder,.tsf-metaboxes input[type=text]:focus::-moz-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}#tsf-inpost-box input[type=text]:focus:-ms-input-placeholder,#tsf-inpost-box textarea:focus:-ms-input-placeholder,.tsf-metaboxes input[type=text]:focus:-ms-input-placeholder,.tsf-metaboxes textarea:focus:-ms-input-placeholder{color:transparent;text-shadow:0 0 1px rgba(114,119,124,.75)}@-webkit-keyframes tsf-spin{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes tsf-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media screen and (max-width:782px){.tsf-inpost-box p.tsf-fields,.tsf-metaboxes p.tsf-fields{line-height:2.8}.tsf-metaboxes #tsf-home-title-location label span,.tsf-metaboxes #tsf-title-location label span{min-width:40px}.wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden){overflow:initial!important}}@media screen and (max-width:642px){.tsf-metaboxes span.tsf-nav-desktop{display:none}}@media screen and (max-width:510px){span.tsf-seo-bar.tsf-100{width:inherit}}@-moz-document url-prefix(){.tsf-metaboxes #tsf-description-separator label,.tsf-metaboxes #tsf-title-separator label{margin:3px 1px}@media only screen and (min-width:768px){.widefat tr td.column-title:nth-child(2):nth-last-child(n+6),.widefat tr td.title:nth-child(2):nth-last-child(n+6),.widefat tr th.column-title:nth-child(2):nth-last-child(n+6),.widefat tr th.title:nth-child(2):nth-last-child(n+6){min-width:1em;width:25%;max-width:100%;white-space:unset}}.tsf-metaboxes .tsf-default-selected{box-shadow:0 0 2px 0 #1c9d38}.tsf-metaboxes .tsf-warning-selected{box-shadow:0 0 2px 0 #dd3811}.tsf-metaboxes legend h4{margin:2px 0}}
lib/js/autodescription.js DELETED
@@ -1,1408 +0,0 @@
1
- /**
2
- * This file holds The SEO Framework plugin's JS code.
3
- * Serve JavaScript as an addition, not as a means.
4
- *
5
- * @author Sybre Waaijer https://cyberwire.nl/
6
- * @pluginURI https://wordpress.org/plugins/autodescription/
7
- *
8
- * @credits StudioPress (http://www.studiopress.com/) for some code.
9
- */
10
-
11
- /**
12
- * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2016 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
17
- * by the Free Software Foundation.
18
- *
19
- * This program is distributed in the hope that it will be useful,
20
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
- * GNU General Public License for more details.
23
- *
24
- * You should have received a copy of the GNU General Public License
25
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
26
- */
27
-
28
- // ==ClosureCompiler==
29
- // @compilation_level ADVANCED_OPTIMIZATIONS
30
- // @output_file_name autodescription.min.js
31
- // @externs_url https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/jquery-1.9.js
32
- // @js_externs /** @constructor */ function autodescription() {}; /** @function */ autodescription.statusBarHover; /** @type {Array|string} */ var autodescriptionL10n;
33
- // ==/ClosureCompiler==
34
- // http://closure-compiler.appspot.com/home
35
-
36
- /* global autodescription, confirm, autodescriptionL10n */
37
-
38
- /**
39
- * Advanced Optimizations caused me to move away from dot annotations, as they
40
- * get wrongfully minified.
41
- */
42
-
43
- /**
44
- * Holds AutoDescription values in an object to avoid polluting global namespace.
45
- *
46
- * @since 2.2.4
47
- *
48
- * @constructor
49
- */
50
- window[ 'autodescription' ] = {
51
-
52
- /**
53
- * Determines if the settings have been changed since visit.
54
- * @param {Boolean} settingsChanged
55
- */
56
- settingsChanged: false,
57
-
58
- /**
59
- * The current title tagline.
60
- * @param {String} titleTagline
61
- */
62
- titleTagline : autodescriptionL10n['titleTagline'],
63
-
64
- /**
65
- * @since 2.7.0
66
- * @param {String} nonce The AJAX nonce
67
- */
68
- nonce : autodescriptionL10n['nonce'],
69
-
70
- /**
71
- * Mixed string and int (i10n is string, JS is int).
72
- * @param {String|int} countertype The autodescription.counterType
73
- */
74
- counterType : autodescriptionL10n['counterType'],
75
-
76
- /**
77
- * The current character counter additions class.
78
- * @param {String} additionsClass
79
- */
80
- additionsClass : '',
81
-
82
- /**
83
- * The current title/description separator.
84
- * @param {String} titleSeparator
85
- * @param {String} descriptionSeparator
86
- */
87
- titleSeparator : autodescriptionL10n['titleSeparator'],
88
- descriptionSeparator : autodescriptionL10n['descriptionSeparator'],
89
-
90
- /**
91
- * Cached doctitle function.
92
- *
93
- * @since 2.3.3
94
- *
95
- * @function
96
- *
97
- * @returns {Object} The jQuery doctitle ID's
98
- */
99
- docTitles: function() {
100
- 'use strict';
101
-
102
- var $doctitles = jQuery( '#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]' );
103
-
104
- return $doctitles;
105
- },
106
-
107
- /**
108
- * Cached description function.
109
- *
110
- * @since 2.5.0
111
- *
112
- * @function
113
- *
114
- * @returns {Object} The jQuery description ID's
115
- */
116
- docDescriptions: function() {
117
- 'use strict';
118
-
119
- var $descriptions = jQuery( "#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]" );
120
-
121
- return $descriptions;
122
- },
123
-
124
- /**
125
- * Helper function for confirming a user action.
126
- *
127
- * @since 2.2.4
128
- *
129
- * @function
130
- *
131
- * @param {String} text The text to display.
132
- * @return {Boolean|null}
133
- */
134
- confirm: function( text ) {
135
- 'use strict';
136
-
137
- return confirm( text );
138
- },
139
-
140
- /**
141
- * Description length counter.
142
- *
143
- * @since 2.2.4
144
- *
145
- * @function
146
- * @param {jQuery.event} event
147
- */
148
- updateCharacterCountDescription: function( event ) {
149
- 'use strict';
150
-
151
- var $this = jQuery( event.target ),
152
- $length = $this.val().length,
153
- $phLength = $this.attr( 'placeholder' ).length,
154
- $counter = jQuery( '#' + autodescription.escapeStr( event.target.id ) + '_chars' ),
155
- $additionsClass = autodescription.additionsClass,
156
- $counterType = autodescription.counterType,
157
- $counterClass = '',
158
- $name = '',
159
- $output = '';
160
-
161
- // Emptied input, get Description placeholder.
162
- if ( 0 === $length ) {
163
- //* Output length from placeholder.
164
- $length = $phLength;
165
- }
166
-
167
- if ( $length < 100 || $length >= 175 ) {
168
- $counterClass = 'tsf-count-bad';
169
- $name = autodescription.getCounterName( 'bad' );
170
- } else if ( $length < 137 || ( $length > 155 && $length < 175 ) ) {
171
- $counterClass = 'tsf-count-okay';
172
- $name = autodescription.getCounterName( 'okay' );
173
- } else {
174
- $counterClass = 'tsf-count-good';
175
- $name = autodescription.getCounterName( 'good' );
176
- }
177
-
178
- if ( $additionsClass )
179
- $counterClass += ' ' + $additionsClass;
180
-
181
- if ( ! $counterType || 1 == $counterType ) {
182
- $output = $length.toString();
183
- } else if ( 2 == $counterType ) {
184
- $output = $name;
185
- } else if ( 3 == $counterType ) {
186
- $output = $length.toString() + ' - ' + $name;
187
- }
188
-
189
- $counter.html( $output ).removeClass().addClass( $counterClass );
190
- },
191
-
192
- /**
193
- * Title length counter, with special characters
194
- *
195
- * @since 2.2.4
196
- *
197
- * @function
198
- * @param {jQuery.event} event
199
- */
200
- updateCharacterCountTitle: function( event ) {
201
- 'use strict';
202
-
203
- var $this = jQuery( event.target ),
204
- $additions = autodescriptionL10n['titleAdditions'].length,
205
- $description = autodescriptionL10n['blogDescription'].length,
206
- $siteTitle = autodescriptionL10n['siteTitle'].length,
207
- $titleLength = $this.val().length,
208
- $placeholder = $this.attr( 'placeholder' ).length,
209
- $tagline = jQuery( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).val(),
210
- $seplen = 3,
211
- $counter = jQuery( '#' + autodescription.escapeStr( event.target.id ) + '_chars' ),
212
- $length = 0,
213
- $additionsClass = autodescription.additionsClass,
214
- $counterType = autodescription.counterType,
215
- $counterClass = '',
216
- $name = '',
217
- $output = '';
218
-
219
- // Additions or tagline removed, remove additions and separator.
220
- if ( ! autodescription.titleTagline ) {
221
- $additions = 0;
222
- $seplen = 0;
223
- }
224
-
225
- // Emptied input, get Site title.
226
- if ( 0 === $titleLength ) {
227
- if ( 0 !== $siteTitle ) {
228
- $titleLength = $siteTitle;
229
- } else {
230
- //* Output length from placeholder.
231
- $length = $placeholder;
232
- }
233
- }
234
-
235
- // Length should be something now.
236
- if ( 0 !== $titleLength ) {
237
-
238
- if ( 0 !== $additions && typeof $tagline !== 'undefined' ) {
239
- var $tagLength = $tagline.length;
240
-
241
- // Replace $additions with $tagline is $tagline isn't empty.
242
- if ( 0 !== $tagLength ) {
243
- $additions = $tagLength;
244
- } else {
245
- $additions = $description;
246
- }
247
- }
248
-
249
- // Put it all together
250
- if ( 0 === $additions ) {
251
- $length = $titleLength;
252
- } else {
253
- $length = $titleLength + $seplen + $additions;
254
- }
255
- }
256
-
257
- if ( $length < 25 || $length >= 75 ) {
258
- $counterClass = 'tsf-count-bad';
259
- $name = autodescription.getCounterName( 'bad' );
260
- } else if ( $length < 42 || ( $length > 55 && $length < 75 ) ) {
261
- $counterClass = 'tsf-count-okay';
262
- $name = autodescription.getCounterName( 'okay' );
263
- } else {
264
- $counterClass = 'tsf-count-good';
265
- $name = autodescription.getCounterName( 'good' );
266
- }
267
-
268
- if ( $additionsClass )
269
- $counterClass += ' ' + $additionsClass;
270
-
271
- if ( ! $counterType || 1 == $counterType ) {
272
- $output = $length.toString();
273
- } else if ( 2 == $counterType ) {
274
- $output = $name;
275
- } else if ( 3 == $counterType ) {
276
- $output = $length.toString() + ' - ' + $name;
277
- }
278
-
279
- $counter.html( $output ).removeClass().addClass( $counterClass );
280
- },
281
-
282
- /**
283
- * Escapes HTML strings.
284
- *
285
- * @since 2.2.4
286
- *
287
- * @function
288
- *
289
- * @param {String} str
290
- * @return {String} HTML to jQuery converted string
291
- */
292
- escapeStr: function( str ) {
293
- 'use strict';
294
-
295
- if ( str )
296
- return str.replace(/([\[\]\/])/g,'\\$1');
297
-
298
- return str;
299
- },
300
-
301
- /**
302
- * Dynamic Title separator replacement in metabox
303
- *
304
- * @since 2.2.2
305
- *
306
- * @function
307
- * @param {jQuery.event} event
308
- */
309
- separatorSwitch: function( event ) {
310
- 'use strict';
311
-
312
- var $sep = jQuery( ".autodescription-sep-js" ),
313
- $val = jQuery( event.target ).val();
314
-
315
- //* Update cache.
316
- autodescription.titleSeparator = $val;
317
-
318
- if ( 'pipe' === $val ) {
319
- $sep.text( " | " );
320
- } else if ( 'dash' === $val ) {
321
- $sep.text( " - " );
322
- } else {
323
- $sep.html( " &" + $val + "; " );
324
- }
325
- },
326
-
327
- /**
328
- * Dynamic Description separator replacement in metabox
329
- *
330
- * @since 2.3.4
331
- *
332
- * @function
333
- * @param {jQuery.event} event
334
- */
335
- separatorSwitchDesc: function( event ) {
336
- 'use strict';
337
-
338
- var $sep = jQuery( "#autodescription-descsep-js" ),
339
- $val = jQuery( event.target ).val();
340
-
341
- if ( 'pipe' === $val ) {
342
- $sep.text( " | " );
343
- } else if ( 'dash' === $val ) {
344
- $sep.text( " - " );
345
- } else {
346
- $sep.html( " &" + $val + "; " );
347
- }
348
- },
349
-
350
- /**
351
- * Status bar description init on hover actions.
352
- *
353
- * @since 2.1.9
354
- *
355
- * @function
356
- */
357
- statusBarHover: function() {
358
- 'use strict';
359
-
360
- var $wrap = jQuery( '.tsf-seo-bar-inner-wrap' ).find( 'a' );
361
-
362
- $wrap.on( 'mouseenter', autodescription.statusBarHoverEnter );
363
- $wrap.on( 'mousemove', autodescription.statusBarHoverMove );
364
- $wrap.on( 'mouseleave', autodescription.statusBarHoverLeave );
365
-
366
- },
367
-
368
- /**
369
- * Status bar description output on hover enter.
370
- *
371
- * @since 2.6.0
372
- *
373
- * @function
374
- */
375
- statusBarHoverEnter: function() {
376
- 'use strict';
377
-
378
- var $this = jQuery( this ),
379
- $thisDesc = $this.attr( 'data-desc' );
380
-
381
- if ( $thisDesc !== undefined && 0 === $this.find( 'div' ).length ) {
382
- $this.append( '<div class="tsf-explanation-desc">' + $thisDesc + '<div></div></div>' );
383
-
384
- var $thisHeight = $this.find( 'div.tsf-explanation-desc' ).height() + 28;
385
-
386
- $this.find( 'div.tsf-explanation-desc' ).css( 'top', ( $this.position().top - $thisHeight ) + 'px' );
387
- }
388
- },
389
-
390
- /**
391
- * Status bar description output on hover move.
392
- *
393
- * @since 2.6.0
394
- *
395
- * @function
396
- * @param {jQuery.event} event
397
- */
398
- statusBarHoverMove: function( event ) {
399
- 'use strict';
400
-
401
- var $this = jQuery( event.target ),
402
- $pagex = event.pageX,
403
- $mousex = $pagex - jQuery( '.tsf-seo-bar-inner-wrap' ).offset().left - 11, // 22px width of arrow / 2 = 11 middle
404
- $balloon = $this.find( '.tsf-explanation-desc' ),
405
- $arrow = $balloon.find( 'div' );
406
-
407
- if ( $mousex < 1 ) {
408
- $arrow.css( 'left', 0 + "px" );
409
- } else if ( $balloon.offset() !== undefined ) {
410
- var $width = $balloon.width(),
411
- $maxOffset = $balloon.offset().left + $width + 11;
412
-
413
- if ( $pagex > $maxOffset ) {
414
- $arrow.css( 'left', $width + "px" );
415
- } else {
416
- $arrow.css( 'left', $mousex + "px" );
417
- }
418
- }
419
- },
420
-
421
-
422
- /**
423
- * Status bar description removal on hover leave.
424
- *
425
- * @since 2.6.0
426
- *
427
- * @function
428
- */
429
- statusBarHoverLeave: function() {
430
- 'use strict';
431
-
432
- jQuery( this ).find( 'div.tsf-explanation-desc' ).remove();
433
- },
434
-
435
- /**
436
- * Remove Status bar desc if clicked outside (touch support)
437
- *
438
- * @since 2.1.9
439
- *
440
- * @function
441
- * @param {jQuery.event} event
442
- */
443
- removeDesc: function( event ) {
444
- 'use strict';
445
-
446
- var $this = jQuery( event.target ),
447
- $desc = jQuery('.tsf-seo-bar-inner-wrap a');
448
-
449
- if ( ! $this.closest( $desc ).length )
450
- $desc.find( 'div.tsf-explanation-desc' ).remove();
451
- },
452
-
453
- /**
454
- * Refines Styling for the navigation tabs on the settings pages
455
- *
456
- * @since 2.2.2
457
- *
458
- * Rewritten
459
- * @since 2.6.0
460
- *
461
- * @function
462
- * @param {jQuery.event} event
463
- */
464
- tabToggle: function( event ) {
465
- 'use strict';
466
-
467
- var $target = jQuery( event.target ).attr( 'id' ),
468
- $name = jQuery( event.target ).attr( 'name' );
469
-
470
- if ( typeof $target !== 'undefined' ) {
471
- var $content = jQuery( '#' + $target + '-content' ),
472
- $other = jQuery( '.' + $name + '-content' );
473
-
474
- if ( typeof $content !== 'undefined' ) {
475
- $other.removeClass( 'tsf-active-tab-content' );
476
- $content.addClass( 'tsf-active-tab-content' );
477
- }
478
- }
479
- },
480
-
481
- /**
482
- * Toggle tagline within the Left/Right example for the HomePage Title
483
- *
484
- * @since 2.2.4
485
- *
486
- * @function
487
- * @param {jQuery.event} event
488
- */
489
- taglineToggle: function( event ) {
490
- 'use strict';
491
-
492
- var $this = jQuery( event.target ),
493
- $tag = jQuery( '.tsf-custom-blogname-js' );
494
-
495
- if ( $this.is( ':checked' ) ) {
496
- $tag.css( 'display', 'inline' );
497
- autodescription.titleTagline = true;
498
- } else {
499
- $tag.css( 'display', 'none' );
500
- autodescription.titleTagline = false;
501
- }
502
-
503
- autodescription.docTitles().trigger( 'keyup', autodescription.updateCharacterCountTitle );
504
- },
505
-
506
- /**
507
- * Toggle tagline within the Description Example.
508
- *
509
- * @since 2.3.4
510
- *
511
- * @function
512
- * @param {jQuery.event} event
513
- */
514
- taglineToggleDesc: function( event ) {
515
- 'use strict';
516
-
517
- var $this = jQuery( event.target ),
518
- $tagDesc = jQuery( '#tsf-on-blogname-js' );
519
-
520
- if ( $this.is(':checked') ) {
521
- $tagDesc.css( 'display', 'inline' );
522
- } else {
523
- $tagDesc.css( 'display', 'none' );
524
- }
525
- },
526
-
527
- /**
528
- * Toggle title additions location for the Title examples.
529
- *
530
- * @since 2.6.0
531
- *
532
- * @function
533
- * @param {jQuery.event} event
534
- */
535
- titleLocationToggle: function( event ) {
536
- 'use strict';
537
-
538
- var $this = jQuery( event.target ).val(),
539
- $titleExampleLeft = jQuery( '.tsf-title-additions-example-left' ),
540
- $titleExampleRight = jQuery( '.tsf-title-additions-example-right' );
541
-
542
- if ( 'right' === $this ) {
543
- $titleExampleLeft.css( 'display', 'none' );
544
- $titleExampleRight.css( 'display', 'inline' );
545
- } else {
546
- $titleExampleLeft.css( 'display', 'inline' );
547
- $titleExampleRight.css( 'display', 'none' );
548
- }
549
- },
550
-
551
- /**
552
- * Toggle title prefixes for the Prefix Title example.
553
- *
554
- * @since 2.6.0
555
- *
556
- * @function
557
- * @param {jQuery.event} event
558
- */
559
- titlePrefixToggle: function( event ) {
560
- 'use strict';
561
-
562
- var $this = jQuery( event.target ),
563
- $prefix = jQuery( '.tsf-title-prefix-example' );
564
-
565
- if ( $this.is(':checked') ) {
566
- $prefix.css( 'display', 'none' );
567
- } else {
568
- $prefix.css( 'display', 'inline' );
569
- }
570
- },
571
-
572
- /**
573
- * Toggle additions within Description example for the Example Description
574
- *
575
- * @since 2.6.0
576
- *
577
- * @function
578
- * @param {jQuery.event} event
579
- */
580
- additionsToggleDesc: function( event ) {
581
- 'use strict';
582
-
583
- var $this = jQuery( event.target ),
584
- $tagDesc = jQuery( '#tsf-description-additions-js' );
585
-
586
- if ( $this.is(':checked') ) {
587
- $tagDesc.css( 'display', 'inline' );
588
- } else {
589
- $tagDesc.css( 'display', 'none' );
590
- }
591
- },
592
-
593
- /**
594
- * Toggle tagline end examples within the Left/Right example for the
595
- * HomePage Title or Description.
596
- *
597
- * @since 2.2.7
598
- *
599
- * @function
600
- * @param {jQuery.event} event
601
- */
602
- taglineToggleOnload: function( event ) {
603
- 'use strict';
604
-
605
- var $tagTitle = jQuery( '#tsf-title-tagline-toggle :input' ),
606
- $title = jQuery( '.tsf-custom-blogname-js' ),
607
- $tagDescAdditions = jQuery( '#tsf-description-additions-toggle :input' ),
608
- $descAdditions = jQuery( '#tsf-description-additions-js' ),
609
- $tagDescBlogname = jQuery( '#tsf-description-onblogname-toggle :input' ),
610
- $descBlogname = jQuery( '#tsf-on-blogname-js' ),
611
- $tagTitleAdditions = jQuery( '#tsf-title-additions-toggle :input' ),
612
- $titleAdditions = jQuery( '.tsf-title-additions-js' );
613
-
614
- if ( $tagTitle.is( ':checked' ) ) {
615
- $title.css( 'display', 'inline' );
616
- } else {
617
- $title.css( 'display', 'none' );
618
- }
619
-
620
- if ( $tagDescAdditions.is( ':checked' ) ) {
621
- $descAdditions.css( 'display', 'inline' );
622
- } else {
623
- $descAdditions.css( 'display', 'none' );
624
- }
625
-
626
- if ( $tagDescBlogname.is( ':checked' ) ) {
627
- $descBlogname.css( 'display', 'inline' );
628
- } else {
629
- $descBlogname.css( 'display', 'none' );
630
- }
631
-
632
- // Reverse option.
633
- if ( $tagTitleAdditions.is( ':checked' ) ) {
634
- $titleAdditions.css( 'display', 'none' );
635
- } else {
636
- $titleAdditions.css( 'display', 'inline' );
637
- }
638
-
639
- },
640
-
641
- /**
642
- * Change Home Page Title based on input of the Custom Title
643
- *
644
- * @since 2.2.4
645
- *
646
- * @function
647
- * @param {jQuery.event} event
648
- */
649
- titleProp: function( event ) {
650
- 'use strict';
651
-
652
- var $val = jQuery( event.target ).val(),
653
- $title = jQuery( '.custom-title-js' );
654
-
655
- if ( $val.length === 0 ) {
656
- $title.text( autodescriptionL10n['siteTitle'] );
657
- } else {
658
- $title.text( $val );
659
- }
660
-
661
- },
662
-
663
- /**
664
- * Change Title based on input of the Custom Title
665
- *
666
- * @since 2.3.8
667
- *
668
- * @function
669
- * @param {jQuery.event} event
670
- */
671
- taglineProp: function( event ) {
672
- 'use strict';
673
-
674
- var $val = jQuery( event.target ).val(),
675
- $floatTag = jQuery( '.tsf-custom-tagline-js' ),
676
- $target = jQuery( '#autodescription-site-settings\\[homepage_title\\]' ),
677
- $leftRight = jQuery( '#tsf-home-title-location input:checked' ).val(),
678
- $toggle = jQuery( '#autodescription-site-settings\\[homepage_tagline\\]' ),
679
- $title = autodescriptionL10n['siteTitle'],
680
- $placeholder = $title,
681
- $description = autodescriptionL10n['blogDescription'],
682
- $sep = autodescription.getSep( 'title' );
683
-
684
- if ( $toggle.is( ':checked' ) ) {
685
-
686
- if ( $val.length !== 0 ) {
687
- $description = $val;
688
- }
689
-
690
- if ( $leftRight.length !== 0 && 'left' === $leftRight ) {
691
- $placeholder = $title + ' ' + $sep + ' ' + $description;
692
- } else {
693
- $placeholder = $description + ' ' + $sep + ' ' + $title;
694
- }
695
-
696
- }
697
-
698
- $floatTag.text( $description );
699
- $target.attr( "placeholder", $placeholder );
700
-
701
- // Notify tagline has changed.
702
- autodescription.docTitles().trigger( 'input', autodescription.updateCharacterCountTitle );
703
- },
704
-
705
- /**
706
- * Trigger Change on Left/Right selection of Home Page Title
707
- *
708
- * @since 2.5.0
709
- *
710
- * @function
711
- */
712
- taglinePropTrigger: function() {
713
- 'use strict';
714
-
715
- jQuery( "#autodescription-site-settings\\[homepage_title_tagline\\]" ).trigger( 'input', autodescription.taglineProp );
716
- },
717
-
718
- /**
719
- * Trigger Change on Left/Right selection of Global Title
720
- *
721
- * @since 2.5.2
722
- *
723
- * @function
724
- */
725
- titleToggle: function() {
726
- 'use strict';
727
-
728
- var $this = jQuery( event.target ),
729
- $tagDesc = jQuery( '.tsf-title-additions-js' );
730
-
731
- if ( $this.is( ':checked' ) ) {
732
- $tagDesc.css( 'display', 'none' );
733
- } else {
734
- $tagDesc.css( 'display', 'inline' );
735
- }
736
- },
737
-
738
- /**
739
- * Have all form fields in The SEO Framework metaboxes set a dirty flag when changed.
740
- *
741
- * @since 2.0.0
742
- *
743
- * @function
744
- */
745
- attachUnsavedChangesListener: function() {
746
- 'use strict';
747
-
748
- jQuery( '.tsf-metaboxes :input, #tsf-inpost-box .inside :input' ).not( '.tsf-tab :input' ).change( function() {
749
- autodescription.registerChange();
750
- });
751
-
752
- jQuery( '.tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea' ).not( '.tsf-nav-tab-wrapper :input' ).on( 'input', function() {
753
- autodescription.registerChange();
754
- });
755
-
756
- window.onbeforeunload = function() {
757
- if ( autodescription.settingsChanged ) {
758
- return autodescriptionL10n['saveAlert'];
759
- }
760
- };
761
-
762
- jQuery( '.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete' ).click( function() {
763
- window.onbeforeunload = null;
764
- });
765
- },
766
-
767
- /**
768
- * Set a flag, to indicate form fields have changed.
769
- *
770
- * @since 2.2.4
771
- *
772
- * @function
773
- */
774
- registerChange: function() {
775
- 'use strict';
776
-
777
- autodescription.settingsChanged = true;
778
- },
779
-
780
- /**
781
- * Ask user to confirm that settings should now be reset.
782
- *
783
- * @since 2.2.4
784
- *
785
- * @function
786
- *
787
- * @return {Boolean|null} True if reset should occur, false if not.
788
- */
789
- confirmedReset: function() {
790
- 'use strict';
791
-
792
- return confirm( autodescriptionL10n['confirmReset'] );
793
- },
794
-
795
- /**
796
- * Adds dynamic placeholder to Title input based on site settings.
797
- *
798
- * @since 2.5.0
799
- *
800
- * @function
801
- * @param {jQuery.event} event
802
- *
803
- * @return {String} the placeholder additions.
804
- */
805
- dynamicPlaceholder: function( event ) {
806
- 'use strict';
807
-
808
- var $hasAdditions = autodescriptionL10n['titleAdditions'].length,
809
- $placeholder = jQuery( '#tsf-title-placeholder' );
810
-
811
- // If check is defined, we're on SEO settings page.
812
- if ( 0 === $hasAdditions ) {
813
- var $this = jQuery( event.target );
814
-
815
- // Empty the placeholder as we can't execute.
816
- $this.css( 'text-indent', "initial" );
817
- return $placeholder.empty();
818
- }
819
-
820
- var $after = false,
821
- $check = jQuery( '#tsf-home-title-location input:checked' ).val(),
822
- $rtl = autodescriptionL10n['isRTL'],
823
- $additions = '';
824
-
825
- if ( typeof $check !== 'undefined' && $check.length !== 0 ) {
826
- //* We're in SEO Settings page.
827
-
828
- if ( '1' === $rtl ) {
829
- if ( 'right' === $check ) {
830
- $after = true;
831
- }
832
- } else {
833
- if ( 'left' === $check ) {
834
- $after = true;
835
- }
836
- }
837
- } else {
838
- //* We're in post/page edit screen.
839
-
840
- var $isHome = autodescriptionL10n['isHome'],
841
- $titleLocation = autodescriptionL10n['titleLocation'],
842
- $tagline = autodescription.titleTagline;
843
-
844
- // We're on post/page screen.
845
- if ( '1' === $isHome ) {
846
- // Static Front page, switch check.
847
- if ( '1' === $tagline ) {
848
- if ( '1' === $rtl ) {
849
- if ( 'right' === $titleLocation ) {
850
- $after = true;
851
- }
852
- } else if ( 'left' === $titleLocation ) {
853
- $after = true;
854
- }
855
- }
856
- } else {
857
- if ( '1' === $rtl ) {
858
- if ( 'left' === $titleLocation ) {
859
- $after = true;
860
- }
861
- } else if ( 'right' === $titleLocation ) {
862
- $after = true;
863
- }
864
- }
865
- }
866
-
867
- var $tagbox = jQuery( '#tsf-title-tagline-toggle :input' );
868
-
869
- if ( typeof $tagbox !== "undefined" && $tagbox.length > 0 && ! $tagbox.is( ':checked' ) ) {
870
- //* We're on SEO Settings Page now, and tagline has been disabled.
871
- var $this = jQuery( event.target );
872
-
873
- $this.css( 'text-indent', "initial" );
874
- $placeholder.css( 'display', 'none' );
875
- } else {
876
-
877
- var $this = jQuery( event.target ),
878
- $inputVal = $this.val(),
879
- $offsetTest = jQuery( "#tsf-title-offset" ),
880
- $offsetWidth = 0,
881
- $heightPad = ( $this.outerHeight( true ) - $this.height() ) / 2,
882
- $horPad = ( $this.outerWidth() - $this.width() ) / 2,
883
- $leftOffset = ( $this.outerWidth( true ) - $this.width() ) / 2,
884
- $taglineVal = jQuery( "#autodescription-site-settings\\[homepage_title_tagline\\]" ).val(),
885
- $pos = 'left',
886
- $separator = autodescription.getSep( 'title' );
887
-
888
- if ( '1' === $rtl ) {
889
- $pos = 'right';
890
- }
891
-
892
- if ( typeof $taglineVal !== "undefined" && $taglineVal.length === 0) {
893
- $taglineVal = autodescriptionL10n['blogDescription'];
894
- }
895
-
896
- if ( $after ) {
897
- $additions = $separator + " " + autodescriptionL10n['titleAdditions'];
898
-
899
- // Exchange the placeholder value of the custom Tagline in the HomePage Metabox
900
- if ( typeof $taglineVal !== "undefined" && $taglineVal.length > 0 ) {
901
- $additions = $separator + " " + $taglineVal;
902
- }
903
-
904
- $this.css( 'text-indent', "initial" );
905
- } else {
906
- $additions = autodescriptionL10n['titleAdditions'] + " " + $separator;
907
-
908
- // Exchange the placeholder value of the custom Tagline in the HomePage Metabox
909
- if ( typeof $taglineVal !== "undefined" && $taglineVal.length > 0 ) {
910
- $additions = $taglineVal + " " + $separator;
911
- }
912
- }
913
-
914
- // Width offset container, copy variables and remain hidden.
915
- $offsetTest.text( $inputVal );
916
- $offsetTest.css({
917
- fontFamily: $this.css( "fontFamily" ),
918
- fontWeight: $this.css( "fontWeight" ),
919
- letterSpacing: $this.css( "letterSpacing" ),
920
- fontSize: $this.css( "fontSize" ),
921
- });
922
- $offsetWidth = $offsetTest.width();
923
-
924
- var $maxWidth = $this.width() - $horPad - $offsetWidth;
925
-
926
- if ( $maxWidth < 0 )
927
- $maxWidth = 0;
928
-
929
- // Moving Placeholder output
930
- $placeholder.css({
931
- display: $this.css( "display" ),
932
- lineHeight: $this.css( "lineHeight" ),
933
- paddingTop: $heightPad + "px",
934
- paddingBottom: $heightPad + "px",
935
- fontFamily: $this.css( "fontFamily" ),
936
- fontWeight: $this.css( "fontWeight" ),
937
- fontSize: $this.css( "fontSize" ),
938
- letterSpacing: $this.css( "letterSpacing" ),
939
- maxWidth: $maxWidth + "px",
940
- });
941
-
942
- //* Empty or fill placeholder and offsets.
943
- if ( typeof $inputVal === "undefined" || $inputVal.length < 1 ) {
944
-
945
- if ( ! $after )
946
- $this.css( 'text-indent', "initial" );
947
-
948
- $placeholder.empty();
949
- } else {
950
- $placeholder.text( $additions );
951
-
952
- // Don't calculate when empty.
953
- if ( $this.outerWidth() > $leftOffset ) {
954
- if ( $after ) {
955
- $placeholder.css( $pos, $horPad + $leftOffset + $offsetTest.width() + "px" );
956
- } else {
957
- var $indent = $horPad + $placeholder.width();
958
-
959
- if ( $indent < 0 )
960
- $indent = 0;
961
-
962
- $placeholder.css( $pos, $leftOffset + "px" );
963
- $this.css( 'text-indent', $indent + "px" );
964
- }
965
- }
966
- }
967
- }
968
- },
969
-
970
- /**
971
- * Makes user click act natural by selecting the parent Title text input.
972
- *
973
- * @since 2.5.0
974
- *
975
- * @function
976
- */
977
- selectTitleInput: function() {
978
- 'use strict';
979
-
980
- var $input = autodescription.docTitles();
981
-
982
- $input.focus();
983
-
984
- if ( $input.setSelectionRange ) {
985
- // Go to end times 2 if setSelectionRange exists.
986
- var $length = $input.val().length * 2;
987
- $input.setSelectionRange( $length, $length );
988
- } else {
989
- // Replace value with itself.
990
- $input.val( $input.val() ).focus();
991
- }
992
- },
993
-
994
- /**
995
- * Adds dynamic placeholder to Title input based on site settings on Load.
996
- *
997
- * @since 2.5.0
998
- *
999
- * @function
1000
- */
1001
- dynamicPlaceholderOnLoad: function() {
1002
- 'use strict';
1003
-
1004
- var $input = autodescription.docTitles();
1005
-
1006
- if ( typeof $input.val() !== "undefined" ) {
1007
- if ( $input.val().length > 0 ) {
1008
- $input.trigger( 'input', autodescription.dynamicPlaceholder );
1009
- } else {
1010
- $input.trigger( 'input', autodescription.updateCharacterCountTitle );
1011
- }
1012
- }
1013
- },
1014
-
1015
- /**
1016
- * Triggers keyup on description input so the counter can colorize.
1017
- *
1018
- * @since 2.5.0
1019
- *
1020
- * @function
1021
- */
1022
- triggerDescriptionOnLoad: function() {
1023
- 'use strict';
1024
-
1025
- var $input = autodescription.docDescriptions();
1026
-
1027
- $input.trigger( 'input', autodescription.updateCharacterCountDescription );
1028
- },
1029
-
1030
-
1031
- /**
1032
- * Triggers keyup on title input so the counter can colorize.
1033
- *
1034
- * @since 2.6.0
1035
- *
1036
- * @function
1037
- */
1038
- triggerTitleOnLoad: function() {
1039
- 'use strict';
1040
-
1041
- var $input = autodescription.docTitles();
1042
-
1043
- $input.trigger( 'input', autodescription.updateCharacterCountTitle );
1044
- },
1045
-
1046
- /**
1047
- * OnLoad changes can affect settings changes. This function reverts those.
1048
- *
1049
- * @since 2.5.0
1050
- *
1051
- * @function
1052
- */
1053
- onLoadUnregisterChange: function() {
1054
- 'use strict';
1055
-
1056
- //* Prevent trigger of settings change
1057
- autodescription.settingsChanged = false;
1058
- },
1059
-
1060
- /**
1061
- * Dismissible notices. Uses class .tsf-notice.
1062
- *
1063
- * @since 2.6.0
1064
- *
1065
- * @function
1066
- * @param {jQuery.event} event
1067
- */
1068
- dismissNotice: function( event ) {
1069
- 'use strict';
1070
-
1071
- var $this = jQuery( event.target );
1072
-
1073
- $this.parents( '.tsf-notice' ).slideUp( 200, function() {
1074
- $this.remove();
1075
- });
1076
-
1077
- },
1078
-
1079
- /**
1080
- * Visualizes AJAX loading time through target class change.
1081
- *
1082
- * @since 2.7.0
1083
- *
1084
- * @function
1085
- * @param {String} target
1086
- */
1087
- setAjaxLoader: function( target ) {
1088
- 'use strict';
1089
-
1090
- jQuery( target ).toggleClass( 'tsf-loading' );
1091
- },
1092
-
1093
- /**
1094
- * Adjusts class loaders on Ajax response.
1095
- *
1096
- * @since 2.7.0
1097
- *
1098
- * @function
1099
- * @param {String} target
1100
- * @param {Boolean} success
1101
- */
1102
- unsetAjaxLoader: function( target, success ) {
1103
- 'use strict';
1104
-
1105
- var $newclass = 'tsf-success',
1106
- $fade = 2500;
1107
-
1108
- if ( ! success ) {
1109
- $newclass = 'tsf-error';
1110
- $fade = 5000;
1111
- }
1112
-
1113
- jQuery( target ).removeClass( 'tsf-loading' ).addClass( $newclass ).fadeOut( $fade );
1114
- },
1115
-
1116
- /**
1117
- * Cleans and resets Ajax wrapper class and contents to default.
1118
- * Also stops any animation and resets fadeout to beginning.
1119
- *
1120
- * @since 2.7.0
1121
- *
1122
- * @function
1123
- * @param {String} target
1124
- */
1125
- resetAjaxLoader: function( target ) {
1126
- 'use strict';
1127
-
1128
- jQuery( target ).stop().empty().attr( 'class', 'tsf-ajax' ).css( 'opacity', '1' ).removeAttr( 'style' );
1129
- },
1130
-
1131
- /**
1132
- * Updates the counter type.
1133
- *
1134
- * @since 2.6.0
1135
- *
1136
- * @function
1137
- * @param {jQuery.event} event
1138
- */
1139
- counterUpdate: function( event ) {
1140
- 'use strict';
1141
-
1142
- // Count up, reset to 0 if needed. We have 4 options: 0, 1, 2, 3
1143
- autodescription.counterType = autodescription.counterType + 1;
1144
- if ( autodescription.counterType > 3 )
1145
- autodescription.counterType = 0;
1146
-
1147
- //* Update counters locally.
1148
- autodescription.additionsClassInit();
1149
-
1150
- var $target = '.tsf-counter .tsf-ajax',
1151
- $status = 0;
1152
-
1153
- //* Reset ajax loader
1154
- autodescription.resetAjaxLoader( $target );
1155
-
1156
- //* Set ajax loader.
1157
- autodescription.setAjaxLoader( $target );
1158
-
1159
- //* Setup external update.
1160
- var settings = {
1161
- method: 'POST',
1162
- url: ajaxurl,
1163
- datatype: 'json',
1164
- data: {
1165
- 'action' : 'the_seo_framework_update_counter',
1166
- 'nonce' : autodescription.nonce,
1167
- 'val' : autodescription.counterType,
1168
- },
1169
- async: true,
1170
- success: function( response ) {
1171
-
1172
- response = jQuery.parseJSON( response );
1173
-
1174
- //* I could do value check, but that will simply lag behind. Unless an annoying execution delay is added.
1175
- if ( 'success' === response.type )
1176
- $status = 1;
1177
-
1178
- autodescription.counterUpdatedResponse( $target, $status );
1179
- },
1180
- }
1181
-
1182
- jQuery.ajax( settings );
1183
- },
1184
-
1185
- /**
1186
- * Visualizes the AJAX response to the user.
1187
- *
1188
- * @since 2.7.0
1189
- *
1190
- * @function
1191
- * @param {String} target
1192
- * @param {Integer} success
1193
- */
1194
- counterUpdatedResponse: function( target, success ) {
1195
- 'use strict';
1196
-
1197
- switch ( success ) {
1198
- case 0:
1199
- autodescription.unsetAjaxLoader( target, false );
1200
- break;
1201
- case 1:
1202
- autodescription.unsetAjaxLoader( target, true );
1203
- break;
1204
- default:
1205
- autodescription.resetAjaxLoader( target );
1206
- break;
1207
- }
1208
-
1209
- },
1210
-
1211
- /**
1212
- * Sets up additionsClass variable.
1213
- * Also sets up browser caches correctly.
1214
- *
1215
- * @since 2.6.0
1216
- *
1217
- * @function
1218
- */
1219
- additionsClassInit: function() {
1220
- 'use strict';
1221
-
1222
- /**
1223
- * Mixed string and int (i10n is string, JS is int).
1224
- * @param {String|int} $counterType
1225
- * @param {Boolean} $settingsChanged
1226
- */
1227
- var $counterType = autodescription.counterType,
1228
- $settingsChanged = autodescription.settingsChanged;
1229
-
1230
- if ( 1 == $counterType ) {
1231
- autodescription.additionsClass = 'tsf-counter-one';
1232
- autodescription.counterType = 1;
1233
- } else if ( 2 == $counterType ) {
1234
- autodescription.additionsClass = 'tsf-counter-two';
1235
- autodescription.counterType = 2;
1236
- } else if ( 3 == $counterType ) {
1237
- autodescription.additionsClass = 'tsf-counter-three';
1238
- autodescription.counterType = 3;
1239
- } else {
1240
- autodescription.additionsClass = 'tsf-counter-zero';
1241
- autodescription.counterType = 0;
1242
- }
1243
-
1244
- autodescription.updateCounters();
1245
-
1246
- // Reset settingschanges to previous value.
1247
- autodescription.settingsChanged = $settingsChanged;
1248
- },
1249
-
1250
- /**
1251
- * Update counters.
1252
- *
1253
- * @since 2.6.0
1254
- *
1255
- * @function
1256
- */
1257
- updateCounters: function() {
1258
- 'use strict';
1259
-
1260
- autodescription.triggerTitleOnLoad();
1261
- autodescription.triggerDescriptionOnLoad();
1262
- },
1263
-
1264
- /**
1265
- * Returns counter name.
1266
- *
1267
- * @since 2.6.0
1268
- * @function
1269
- *
1270
- * @param {String|null} type
1271
- * @return {String} name Human readable counter name.
1272
- */
1273
- getCounterName: function( type ) {
1274
- 'use strict';
1275
-
1276
- var name = autodescriptionL10n[ type ];
1277
-
1278
- return name;
1279
- },
1280
-
1281
- /**
1282
- * Returns converted HTML title/description separator.
1283
- *
1284
- * @since 2.7.0
1285
- * @function
1286
- *
1287
- * @param {String} type
1288
- * @return {String} sep The converted separator.
1289
- */
1290
- getSep: function( type ) {
1291
-
1292
- if ( 'title' === type ) {
1293
- var sep = autodescription.titleSeparator;
1294
- } else {
1295
- var sep = autodescription.descriptionSeparator;
1296
- }
1297
-
1298
- if ( 'pipe' === sep || '|' === sep ) {
1299
- sep = ( "|" );
1300
- } else if ( 'dash' === sep || '-' === sep ) {
1301
- sep = ( "-" );
1302
- } else if ( sep.charCodeAt(0) < 123 ) {
1303
- //* Checked for UTF-8 conversion.
1304
- // Create a memory div to store the html in, convert to text to append in $placeholder
1305
- sep = jQuery( '<div/>' ).html( "&" + sep + ";" ).text();
1306
- }
1307
-
1308
- return sep;
1309
- },
1310
-
1311
- /**
1312
- * Initialises all aspects of the scripts.
1313
- *
1314
- * Generally ordered with stuff that inserts new elements into the DOM first,
1315
- * then stuff that triggers an event on existing DOM elements when ready,
1316
- * followed by stuff that triggers an event only on user interaction. This
1317
- * keeps any screen jumping from occuring later on.
1318
- *
1319
- * @since 2.2.4
1320
- * @since 2.7.0 jQuery object is now passed.
1321
- *
1322
- * @param {Object} jQ jQuery
1323
- * @function
1324
- */
1325
- ready: function( jQ ) {
1326
- 'use strict';
1327
-
1328
- // Move the page updates notices below the tsf-top-wrap.
1329
- jQ( 'div.updated, div.error, div.notice-warning' ).insertAfter( 'div.tsf-top-wrap' );
1330
-
1331
- // Set up additions classes.
1332
- jQ( document.body ).ready( autodescription.additionsClassInit );
1333
-
1334
- // Toggle Dynamic Title Placeholder onLoad, also toggles doing it right colors.
1335
- jQ( document.body ).ready( autodescription.dynamicPlaceholderOnLoad );
1336
-
1337
- // Check if the Title Tagline or Description Additions should be removed when page is loaded.
1338
- jQ( document.body ).ready( autodescription.taglineToggleOnload );
1339
-
1340
- // Initialize the status bar hover balloon.
1341
- jQ( document.body ).ready( autodescription.statusBarHover );
1342
-
1343
- // Initialize status bar removal hover for touch screens.
1344
- jQ( document.body ).on( 'click touchstart MSPointerDown', autodescription.removeDesc );
1345
-
1346
- // #== Before Change listener
1347
-
1348
- // Initialise form field changing flag.
1349
- autodescription.attachUnsavedChangesListener();
1350
-
1351
- // Deregister changes.
1352
- jQ( document.body ).ready( autodescription.onLoadUnregisterChange );
1353
-
1354
- // #== After Change listener
1355
-
1356
- // Bind character counters.
1357
- autodescription.docDescriptions().on( 'input', autodescription.updateCharacterCountDescription );
1358
- autodescription.docTitles().on( 'input', autodescription.updateCharacterCountTitle );
1359
-
1360
- // Allow the title separator to be changed dynamically.
1361
- jQ( '#tsf-title-separator input' ).on( 'click', autodescription.separatorSwitch );
1362
- // Allow description separator to be changed dynamically.
1363
- jQ( '#tsf-description-separator input' ).on( 'click', autodescription.separatorSwitchDesc );
1364
-
1365
- // Bind reset confirmation.
1366
- jQ( '.autodescription-js-confirm-reset' ).on( 'click.autodescription.autodescription_confirm_reset', autodescription.confirmedReset );
1367
-
1368
- // Toggle Tabs in the SEO settings page.
1369
- jQ( '.tsf-tab' ).on( 'click', autodescription.tabToggle );
1370
-
1371
- // Toggle Title tagline aditions removal.
1372
- jQ( '#tsf-title-tagline-toggle :input' ).on( 'click', autodescription.taglineToggle );
1373
- // Toggle Title additions location.
1374
- jQ( '#tsf-title-location input' ).on( 'click', autodescription.titleLocationToggle );
1375
- // Toggle Title prefixes display.
1376
- jQ( '#title-prefixes-toggle :input' ).on( 'click', autodescription.titlePrefixToggle );
1377
-
1378
- // Toggle Description additions removal.
1379
- jQ( '#tsf-description-onblogname-toggle :input' ).on( 'click', autodescription.taglineToggleDesc );
1380
- jQ( '#tsf-description-additions-toggle :input' ).on( 'click', autodescription.additionsToggleDesc );
1381
-
1382
- // Change Home Page Title Example prop on input changes.
1383
- jQ( '#autodescription-site-settings\\[homepage_title\\]' ).on( 'input', autodescription.titleProp );
1384
- jQ( '#tsf-home-title-location :input, #tsf-title-tagline-toggle :input, #tsf-title-separator input' ).on( 'click', autodescription.taglinePropTrigger );
1385
- jQ( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).on( 'input', autodescription.taglineProp );
1386
-
1387
- // Make sure the titleProp is correctly rendered when revealed after being hidden.
1388
- jQ( '#homepage-tab-general' ).on( 'change', autodescription.taglinePropTrigger );
1389
-
1390
- // Change Global Title Example prop on input changes.
1391
- jQ( '#autodescription-site-settings\\[title_rem_additions\\]' ).on( 'click', autodescription.titleToggle );
1392
-
1393
- // Dynamic Placeholder, acts on keydown for a11y, although more cpu intensive. Acts on keyup for perfect output.
1394
- autodescription.docTitles().on( 'input', autodescription.dynamicPlaceholder );
1395
-
1396
- // Move click on dynamic additions to focus input behind.
1397
- jQ( '#tsf-title-placeholder' ).on( 'click', autodescription.selectTitleInput );
1398
-
1399
- // Dismiss notices.
1400
- jQ( '.tsf-dismiss' ).on( 'click', autodescription.dismissNotice );
1401
-
1402
- // AJAX counter
1403
- jQ( '.tsf-counter' ).on( 'click', autodescription.counterUpdate );
1404
-
1405
- }
1406
-
1407
- };
1408
- jQuery( autodescription.ready );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/js/autodescription.min.js DELETED
@@ -1,25 +0,0 @@
1
- window.autodescription={g:!1,i:autodescriptionL10n.titleTagline,N:autodescriptionL10n.nonce,a:autodescriptionL10n.counterType,c:"",B:autodescriptionL10n.titleSeparator,K:autodescriptionL10n.descriptionSeparator,b:function(){return jQuery("#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]")},l:function(){return jQuery("#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]")},
2
- confirm:function(a){return confirm(a)},D:function(a){var b=jQuery(a.target),d=b.val().length,c=b.attr("placeholder").length;a=jQuery("#"+autodescription.o(a.target.id)+"_chars");var b=autodescription.c,f=autodescription.a,e,h="";0===d&&(d=c);100>d||175<=d?(c="tsf-count-bad",e=autodescription.f("bad")):137>d||155<d&&175>d?(c="tsf-count-okay",e=autodescription.f("okay")):(c="tsf-count-good",e=autodescription.f("good"));b&&(c+=" "+b);f&&1!=f?2==f?h=e:3==f&&(h=d.toString()+" - "+e):h=d.toString();a.html(h).removeClass().addClass(c)},
3
- h:function(a){var b=jQuery(a.target),d=autodescriptionL10n.titleAdditions.length,c=autodescriptionL10n.blogDescription.length,f=autodescriptionL10n.siteTitle.length,e=b.val().length,h=b.attr("placeholder").length,k=jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").val(),g=3;a=jQuery("#"+autodescription.o(a.target.id)+"_chars");var l=0,b=autodescription.c,n=autodescription.a,m="";autodescription.i||(g=d=0);0===e&&(0!==f?e=f:l=h);0!==e&&(0!==d&&"undefined"!==typeof k&&(d=k.length,
4
- d=0!==d?d:c),l=0===d?e:e+g+d);25>l||75<=l?(c="tsf-count-bad",e=autodescription.f("bad")):42>l||55<l&&75>l?(c="tsf-count-okay",e=autodescription.f("okay")):(c="tsf-count-good",e=autodescription.f("good"));b&&(c+=" "+b);n&&1!=n?2==n?m=e:3==n&&(m=l.toString()+" - "+e):m=l.toString();a.html(m).removeClass().addClass(c)},o:function(a){return a?a.replace(/([\[\]\/])/g,"\\$1"):a},S:function(a){var b=jQuery(".autodescription-sep-js");a=jQuery(a.target).val();autodescription.B=a;"pipe"===a?b.text(" | "):"dash"===
5
- a?b.text(" - "):b.html(" &"+a+"; ")},T:function(a){var b=jQuery("#autodescription-descsep-js");a=jQuery(a.target).val();"pipe"===a?b.text(" | "):"dash"===a?b.text(" - "):b.html(" &"+a+"; ")},statusBarHover:function(){var a=jQuery(".tsf-seo-bar-inner-wrap").find("a");a.on("mouseenter",autodescription.V);a.on("mousemove",autodescription.X);a.on("mouseleave",autodescription.W)},V:function(){var a=jQuery(this),b=a.attr("data-desc");void 0!==b&&0===a.find("div").length&&(a.append('<div class="tsf-explanation-desc">'+
6
- b+"<div></div></div>"),b=a.find("div.tsf-explanation-desc").height()+28,a.find("div.tsf-explanation-desc").css("top",a.position().top-b+"px"))},X:function(a){var b=jQuery(a.target);a=a.pageX;var d=a-jQuery(".tsf-seo-bar-inner-wrap").offset().left-11,c=b.find(".tsf-explanation-desc"),b=c.find("div");if(1>d)b.css("left","0px");else if(void 0!==c.offset()){var f=c.width(),c=c.offset().left+f+11;a>c?b.css("left",f+"px"):b.css("left",d+"px")}},W:function(){jQuery(this).find("div.tsf-explanation-desc").remove()},
7
- P:function(a){a=jQuery(a.target);var b=jQuery(".tsf-seo-bar-inner-wrap a");a.closest(b).length||b.find("div.tsf-explanation-desc").remove()},Y:function(a){var b=jQuery(a.target).attr("id");a=jQuery(a.target).attr("name");"undefined"!==typeof b&&(b=jQuery("#"+b+"-content"),a=jQuery("."+a+"-content"),"undefined"!==typeof b&&(a.removeClass("tsf-active-tab-content"),b.addClass("tsf-active-tab-content")))},Z:function(a){a=jQuery(a.target);var b=jQuery(".tsf-custom-blogname-js");a.is(":checked")?(b.css("display",
8
- "inline"),autodescription.i=!0):(b.css("display","none"),autodescription.i=!1);autodescription.b().trigger("keyup",autodescription.h)},aa:function(a){a=jQuery(a.target);var b=jQuery("#tsf-on-blogname-js");a.is(":checked")?b.css("display","inline"):b.css("display","none")},ca:function(a){a=jQuery(a.target).val();var b=jQuery(".tsf-title-additions-example-left"),d=jQuery(".tsf-title-additions-example-right");"right"===a?(b.css("display","none"),d.css("display","inline")):(b.css("display","inline"),
9
- d.css("display","none"))},da:function(a){a=jQuery(a.target);var b=jQuery(".tsf-title-prefix-example");a.is(":checked")?b.css("display","none"):b.css("display","inline")},F:function(a){a=jQuery(a.target);var b=jQuery("#tsf-description-additions-js");a.is(":checked")?b.css("display","inline"):b.css("display","none")},ba:function(){var a=jQuery("#tsf-title-tagline-toggle :input"),b=jQuery(".tsf-custom-blogname-js"),d=jQuery("#tsf-description-additions-toggle :input"),c=jQuery("#tsf-description-additions-js"),
10
- f=jQuery("#tsf-description-onblogname-toggle :input"),e=jQuery("#tsf-on-blogname-js"),h=jQuery("#tsf-title-additions-toggle :input"),k=jQuery(".tsf-title-additions-js");a.is(":checked")?b.css("display","inline"):b.css("display","none");d.is(":checked")?c.css("display","inline"):c.css("display","none");f.is(":checked")?e.css("display","inline"):e.css("display","none");h.is(":checked")?k.css("display","none"):k.css("display","inline")},ea:function(a){a=jQuery(a.target).val();var b=jQuery(".custom-title-js");
11
- 0===a.length?b.text(autodescriptionL10n.siteTitle):b.text(a)},w:function(a){a=jQuery(a.target).val();var b=jQuery(".tsf-custom-tagline-js"),d=jQuery("#autodescription-site-settings\\[homepage_title\\]"),c=jQuery("#tsf-home-title-location input:checked").val(),f=jQuery("#autodescription-site-settings\\[homepage_tagline\\]"),e=autodescriptionL10n.siteTitle,h=e,k=autodescriptionL10n.blogDescription,g=autodescription.s("title");f.is(":checked")&&(0!==a.length&&(k=a),h=0!==c.length&&"left"===c?e+" "+g+
12
- " "+k:k+" "+g+" "+e);b.text(k);d.attr("placeholder",h);autodescription.b().trigger("input",autodescription.h)},A:function(){jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").trigger("input",autodescription.w)},fa:function(){var a=jQuery(event.target),b=jQuery(".tsf-title-additions-js");a.is(":checked")?b.css("display","none"):b.css("display","inline")},G:function(){jQuery(".tsf-metaboxes :input, #tsf-inpost-box .inside :input").not(".tsf-tab :input").change(function(){autodescription.u()});
13
- jQuery(".tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea").not(".tsf-nav-tab-wrapper :input").on("input",function(){autodescription.u()});window.onbeforeunload=function(){if(autodescription.g)return autodescriptionL10n.saveAlert};jQuery('.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete').click(function(){window.onbeforeunload=null})},u:function(){autodescription.g=
14
- !0},H:function(){return confirm(autodescriptionL10n.confirmReset)},m:function(a){var b=autodescriptionL10n.titleAdditions.length,d=jQuery("#tsf-title-placeholder");if(0===b)return a=jQuery(a.target),a.css("text-indent","initial"),d.empty();var b=!1,c=jQuery("#tsf-home-title-location input:checked").val(),f=autodescriptionL10n.isRTL;if("undefined"!==typeof c&&0!==c.length)"1"===f?"right"===c&&(b=!0):"left"===c&&(b=!0);else{var c=autodescriptionL10n.titleLocation,e=autodescription.i;"1"===autodescriptionL10n.isHome?
15
- "1"===e&&("1"===f?"right"===c&&(b=!0):"left"===c&&(b=!0)):"1"===f?"left"===c&&(b=!0):"right"===c&&(b=!0)}c=jQuery("#tsf-title-tagline-toggle :input");if("undefined"!==typeof c&&0<c.length&&!c.is(":checked"))a=jQuery(a.target),a.css("text-indent","initial"),d.css("display","none");else{a=jQuery(a.target);var h=a.val(),k=jQuery("#tsf-title-offset"),g,l=(a.outerHeight(!0)-a.height())/2,n=(a.outerWidth()-a.width())/2,c=(a.outerWidth(!0)-a.width())/2;g=jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").val();
16
- var e="left",m=autodescription.s("title");"1"===f&&(e="right");"undefined"!==typeof g&&0===g.length&&(g=autodescriptionL10n.blogDescription);b?(f=m+" "+autodescriptionL10n.titleAdditions,"undefined"!==typeof g&&0<g.length&&(f=m+" "+g),a.css("text-indent","initial")):(f=autodescriptionL10n.titleAdditions+" "+m,"undefined"!==typeof g&&0<g.length&&(f=g+" "+m));k.text(h);k.css({fontFamily:a.css("fontFamily"),fontWeight:a.css("fontWeight"),letterSpacing:a.css("letterSpacing"),fontSize:a.css("fontSize")});
17
- g=k.width();g=a.width()-n-g;0>g&&(g=0);d.css({display:a.css("display"),lineHeight:a.css("lineHeight"),paddingTop:l+"px",paddingBottom:l+"px",fontFamily:a.css("fontFamily"),fontWeight:a.css("fontWeight"),fontSize:a.css("fontSize"),letterSpacing:a.css("letterSpacing"),maxWidth:g+"px"});"undefined"===typeof h||1>h.length?(b||a.css("text-indent","initial"),d.empty()):(d.text(f),a.outerWidth()>c&&(b?d.css(e,n+c+k.width()+"px"):(b=n+d.width(),0>b&&(b=0),d.css(e,c+"px"),a.css("text-indent",b+"px"))))}},
18
- R:function(){var a=autodescription.b();a.focus();if(a.setSelectionRange){var b=2*a.val().length;a.setSelectionRange(b,b)}else a.val(a.val()).focus()},M:function(){var a=autodescription.b();"undefined"!==typeof a.val()&&(0<a.val().length?a.trigger("input",autodescription.m):a.trigger("input",autodescription.h))},ga:function(){autodescription.l().trigger("input",autodescription.D)},ha:function(){autodescription.b().trigger("input",autodescription.h)},O:function(){autodescription.g=!1},L:function(a){var b=
19
- jQuery(a.target);b.parents(".tsf-notice").slideUp(200,function(){b.remove()})},U:function(a){jQuery(a).toggleClass("tsf-loading")},C:function(a,b){var d="tsf-success",c=2500;b||(d="tsf-error",c=5E3);jQuery(a).removeClass("tsf-loading").addClass(d).fadeOut(c)},v:function(a){jQuery(a).stop().empty().attr("class","tsf-ajax").css("opacity","1").removeAttr("style")},I:function(){autodescription.a+=1;3<autodescription.a&&(autodescription.a=0);autodescription.j();var a=0;autodescription.v(".tsf-counter .tsf-ajax");
20
- autodescription.U(".tsf-counter .tsf-ajax");jQuery.ajax({method:"POST",url:ajaxurl,ja:"json",data:{action:"the_seo_framework_update_counter",nonce:autodescription.N,val:autodescription.a},async:!0,success:function(b){b=jQuery.parseJSON(b);"success"===b.type&&(a=1);autodescription.J(".tsf-counter .tsf-ajax",a)}})},J:function(a,b){switch(b){case 0:autodescription.C(a,!1);break;case 1:autodescription.C(a,!0);break;default:autodescription.v(a)}},j:function(){var a=autodescription.a,b=autodescription.g;
21
- 1==a?(autodescription.c="tsf-counter-one",autodescription.a=1):2==a?(autodescription.c="tsf-counter-two",autodescription.a=2):3==a?(autodescription.c="tsf-counter-three",autodescription.a=3):(autodescription.c="tsf-counter-zero",autodescription.a=0);autodescription.ia();autodescription.g=b},ia:function(){autodescription.ha();autodescription.ga()},f:function(a){return autodescriptionL10n[a]},s:function(a){a="title"===a?autodescription.B:autodescription.K;"pipe"===a||"|"===a?a="|":"dash"===a||"-"===
22
- a?a="-":123>a.charCodeAt(0)&&(a=jQuery("<div/>").html("&"+a+";").text());return a},ready:function(a){a("div.updated, div.error, div.notice-warning").insertAfter("div.tsf-top-wrap");a(document.body).ready(autodescription.j);a(document.body).ready(autodescription.M);a(document.body).ready(autodescription.ba);a(document.body).ready(autodescription.statusBarHover);a(document.body).on("click touchstart MSPointerDown",autodescription.P);autodescription.G();a(document.body).ready(autodescription.O);autodescription.l().on("input",
23
- autodescription.D);autodescription.b().on("input",autodescription.h);a("#tsf-title-separator input").on("click",autodescription.S);a("#tsf-description-separator input").on("click",autodescription.T);a(".autodescription-js-confirm-reset").on("click.autodescription.autodescription_confirm_reset",autodescription.H);a(".tsf-tab").on("click",autodescription.Y);a("#tsf-title-tagline-toggle :input").on("click",autodescription.Z);a("#tsf-title-location input").on("click",autodescription.ca);a("#title-prefixes-toggle :input").on("click",
24
- autodescription.da);a("#tsf-description-onblogname-toggle :input").on("click",autodescription.aa);a("#tsf-description-additions-toggle :input").on("click",autodescription.F);a("#autodescription-site-settings\\[homepage_title\\]").on("input",autodescription.ea);a("#tsf-home-title-location :input, #tsf-title-tagline-toggle :input, #tsf-title-separator input").on("click",autodescription.A);a("#autodescription-site-settings\\[homepage_title_tagline\\]").on("input",autodescription.w);a("#homepage-tab-general").on("change",
25
- autodescription.A);a("#autodescription-site-settings\\[title_rem_additions\\]").on("click",autodescription.fa);autodescription.b().on("input",autodescription.m);a("#tsf-title-placeholder").on("click",autodescription.R);a(".tsf-dismiss").on("click",autodescription.L);a(".tsf-counter").on("click",autodescription.I)}};jQuery(autodescription.ready);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lib/js/tsf.externs.js ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file holds The SEO Framework Extension Manager plugin's JS code externs
3
+ * for Google's Closure Compiler.
4
+ *
5
+ * @author Sybre Waaijer https://cyberwire.nl/
6
+ * @link https://wordpress.org/plugins/the-seo-framework-extension-manager/
7
+ */
8
+
9
+ /**
10
+ * The SEO Framework - Extension Manager plugin
11
+ * Copyright (C) 2016 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
15
+ * by the Free Software Foundation.
16
+ *
17
+ * This program is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
+ */
25
+
26
+ /**
27
+ * @fileoverview Externs for The SEO Framework tsf.js
28
+ *
29
+ * This file acts as a sort of interface of all public tsf JS object methods.
30
+ *
31
+ * @see https://github.com/sybrew/the-seo-framework
32
+ * @see https://developer.theseoframework.com/ (i.e. https://theseoframework.com/api/)
33
+ * @see https://raw.githubusercontent.com/sybrew/the-seo-framework/master/lib/js/tsf.externs.js
34
+ * @externs
35
+ */
36
+
37
+ /**
38
+ * @constructor
39
+ * @struct
40
+ */
41
+ function tsf() {};
42
+
43
+ /**
44
+ * @type {string}
45
+ */
46
+ tsf.nonce;
47
+
48
+ /**
49
+ * @const {Object<string, string>}
50
+ */
51
+ tsf.i18n = {};
52
+
53
+ /**
54
+ * @const {Object<string, boolean|number>}
55
+ */
56
+ tsf.states = {};
57
+
58
+ /**
59
+ * @const {Object<string, string>}
60
+ */
61
+ tsf.params = {};
62
+
63
+ /**
64
+ * @const {Object<string, ?>}
65
+ */
66
+ tsf.other = {};
67
+
68
+ /**
69
+ * @const {Object<string, ?>}
70
+ */
71
+ tsf.cropper = {};
72
+
73
+ /**
74
+ * @type {(Object<string, *>|Array<Object<string, *>>)}
75
+ * @const
76
+ */
77
+ var tsfL10n = {};
78
+
79
+ /**
80
+ * @type {string}
81
+ */
82
+ tsfL10n.prototype.nonce;
83
+
84
+ /**
85
+ * @const {Object<string, string>}
86
+ */
87
+ tsfL10n.prototype.i18n;
88
+
89
+ /**
90
+ * @const {Object<string, boolean|number>}
91
+ */
92
+ tsfL10n.prototype.states;
93
+
94
+ /**
95
+ * @const {Object<string, *>}
96
+ */
97
+ tsfL10n.prototype.params = {};
98
+
99
+ /**
100
+ * @const {Object<string, ?>}
101
+ */
102
+ tsfL10n.prototype.other = {};
103
+
104
+ /**
105
+ * @return {undefined}
106
+ */
107
+ tsf.prototype.statusBarHover = function() {};
108
+
109
+ /**
110
+ * @type {!Object<?, ?>}
111
+ */
112
+ tsf.calculateImageSelectOptions.prototype.attachment = {};
113
+
114
+ /**
115
+ * @param {string} arg1
116
+ * @return {!Object}
117
+ * @nosideeffects
118
+ */
119
+ tsf.calculateImageSelectOptions.attachment.prototype.get = function( arg1 ) {};
120
+
121
+ /**
122
+ * @param {string} arg1
123
+ * @param {*} arg2
124
+ * @return {!Object}
125
+ * @nosideeffects
126
+ */
127
+ tsf.calculateImageSelectOptions.attachment.prototype.set = function( arg1, arg2 ) {};
128
+
129
+ /**
130
+ * @type {!Object<?, ?>}
131
+ * @nosideeffects
132
+ */
133
+ tsf.cropper.prototype.control = {};
134
+
135
+ /**
136
+ * @type {!Object<string, ?>}
137
+ * @nosideeffects
138
+ */
139
+ tsf.cropper.control.prototype.params = {};
140
+
141
+ /**
142
+ * @type {number}
143
+ */
144
+ tsf.cropper.prototype.width;
145
+
146
+ /**
147
+ * @type {number}
148
+ */
149
+ tsf.cropper.prototype.height;
150
+
151
+ /**
152
+ * @type {number}
153
+ */
154
+ tsf.cropper.prototype.dst_width;
155
+
156
+ /**
157
+ * @type {number}
158
+ */
159
+ tsf.cropper.prototype.dst_height;
160
+
161
+ /**
162
+ * @type {number}
163
+ */
164
+ tsf.cropper.prototype.flex_width;
165
+
166
+ /**
167
+ * @type {number}
168
+ */
169
+ tsf.cropper.prototype.flex_height;
170
+
171
+ /**
172
+ * +========================+
173
+ * +====== WP externs ======+
174
+ * +========================+
175
+ *
176
+ * Specifically, cropper, color picker and AJAX.
177
+ */
178
+
179
+ /**
180
+ * @type {string}
181
+ */
182
+ var ajaxurl;
183
+
184
+ /**
185
+ * @constructor
186
+ * @struct
187
+ */
188
+ function wp() {};
189
+
190
+ /**
191
+ * @const
192
+ * @type {!Object<*, *>}
193
+ */
194
+ wp.prototype.media = {};
195
+
196
+ /**
197
+ * @type {!Object<*, *>}
198
+ */
199
+ wp.media.prototype.controller = {};
200
+
201
+ /**
202
+ * @param {*=} arg1
203
+ * @return {*}
204
+ */
205
+ wp.media.prototype.query = function( arg1 ) {};
206
+
207
+ /**
208
+ * @type {!Object<*, *>}
209
+ */
210
+ wp.media.controller.prototype.Cropper = {};
211
+
212
+ /**
213
+ * @type {!Object<*, *>}
214
+ */
215
+ wp.media.controller.prototype.Library = {};
216
+
217
+ /**
218
+ * @type {!Object<*, *>}
219
+ */
220
+ wp.prototype.ajax = {};
221
+
222
+ /**
223
+ * @param {string} action
224
+ * @param {*=} arg2
225
+ * @return {*}
226
+ */
227
+ wp.ajax.prototype.post = function( action, arg2 ) {};
228
+
229
+ /**
230
+ * @constructor {Object.wp}
231
+ * @struct
232
+ */
233
+ var frame = {};
234
+
235
+ /**
236
+ * @param {string} action
237
+ * @param {*=} arg2
238
+ * @return {undefined}
239
+ */
240
+ frame.prototype.on = function( action, arg2 ) {};
241
+
242
+ /**
243
+ * @return {undefined}
244
+ */
245
+ frame.prototype.open = function() {};
246
+
247
+ /**
248
+ * @param {string} state
249
+ * @return {undefined}
250
+ */
251
+ frame.prototype.setState = function( state ) {};
252
+
253
+ /**
254
+ * @constructor
255
+ * @param {!Object} attachment
256
+ * @return {!jQuery.jqXHR}
257
+ */
258
+ function doCrop( attachment ) {};
259
+
260
+ /**
261
+ * @param {string} arg1
262
+ * @return {!Object}
263
+ * @nosideeffects
264
+ */
265
+ doCrop.prototype.get = function( arg1 ) {};
266
+
267
+ /**
268
+ * @return {string}
269
+ * @nosideeffects
270
+ */
271
+ doCrop.get.prototype.edit = function() {};
272
+
273
+ /**
274
+ * @param {(string|Object<string,*>)} arg1
275
+ * @return {(string|!jQuery)}
276
+ */
277
+ jQuery.prototype.wpColorPicker = function( arg1 ) {};
lib/js/tsf.externs.protected.js ADDED
@@ -0,0 +1,412 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file holds The SEO Framework Extension Manager plugin's JS code externs
3
+ * for Google's Closure Compiler.
4
+ *
5
+ * @author Sybre Waaijer https://cyberwire.nl/
6
+ * @link https://wordpress.org/plugins/the-seo-framework-extension-manager/
7
+ */
8
+
9
+ /**
10
+ * The SEO Framework - Extension Manager plugin
11
+ * Copyright (C) 2016 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
15
+ * by the Free Software Foundation.
16
+ *
17
+ * This program is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
+ */
25
+
26
+ /**
27
+ * @fileoverview Externs for The SEO Framework tsf.js
28
+ *
29
+ * These are listed per reference, and should only be included if all protected methods
30
+ * and properties are wished for to be made public.
31
+ *
32
+ * @see https://github.com/sybrew/the-seo-framework
33
+ * @see https://developer.theseoframework.com/ (i.e. https://theseoframework.com/api/)
34
+ * @externs
35
+ */
36
+
37
+ /**
38
+ * @protected
39
+ * @type {(Boolean|null|undefined)}
40
+ */
41
+ tsf.prototype.settingsChanged;
42
+
43
+ /**
44
+ * @protected
45
+ * @type {Boolean}
46
+ */
47
+ tsf.prototype.titleTagline;
48
+
49
+ /**
50
+ * @protected
51
+ * @type {String}
52
+ */
53
+ tsf.prototype.titleSeparator;
54
+
55
+ /**
56
+ * @protected
57
+ * @type {String}
58
+ */
59
+ tsf.prototype.descriptionSeparator;
60
+
61
+ /**
62
+ * @protected
63
+ * @type {(String|number)}
64
+ */
65
+ tsf.prototype.counterType;
66
+
67
+ /**
68
+ * @protected
69
+ * @type {(Boolean|null|undefined)}
70
+ */
71
+ tsf.prototype.hasInput;
72
+
73
+ /**
74
+ * @protected
75
+ * @type {(String|null)}
76
+ */
77
+ tsf.prototype.additionsClass;
78
+
79
+ /**
80
+ * @protected
81
+ * @type {!Object}
82
+ */
83
+ tsf.prototype.cropper;
84
+
85
+ /**
86
+ * @protected
87
+ * @return {!jQuery}
88
+ */
89
+ tsf.prototype.docTitles = function() {};
90
+
91
+ /**
92
+ * @protected
93
+ * @return {!jQuery}
94
+ */
95
+ tsf.prototype.docDescriptions = function() {};
96
+
97
+ /**
98
+ * @protected
99
+ * @param {String} text
100
+ * @return {Boolean|null}
101
+ */
102
+ tsf.prototype.confirm = function( text ) {};
103
+
104
+ /**
105
+ * @protected
106
+ * @param {!jQuery.Event} event
107
+ * @return {undefined}
108
+ */
109
+ tsf.prototype.updateCharacterCountDescription = function( event ) {};
110
+
111
+ /**
112
+ * @protected
113
+ * @param {!jQuery.Event} event
114
+ * @return {undefined}
115
+ */
116
+ tsf.prototype.updateCharacterCountTitle = function( event ) {};
117
+
118
+ /**
119
+ * @protected
120
+ * @param {String} str
121
+ * @return {String}
122
+ */
123
+ tsf.prototype.escapeStr = function( str ) {};
124
+
125
+ /**
126
+ * @protected
127
+ * @param {!jQuery.Event} event
128
+ * @return {undefined}
129
+ */
130
+ tsf.prototype.separatorSwitchTitle = function( event ) {};
131
+
132
+ /**
133
+ * @protected
134
+ * @param {!jQuery.Event} event
135
+ * @return {undefined}
136
+ */
137
+ tsf.prototype.separatorSwitchDesc = function( event ) {};
138
+
139
+ /**
140
+ * @protected
141
+ * @return {undefined}
142
+ */
143
+ tsf.prototype.statusBarHover = function() {};
144
+
145
+ /**
146
+ * @protected
147
+ * @param {!jQuery.Event} event
148
+ * @return {undefined}
149
+ */
150
+ tsf.prototype.statusBarHoverEnter = function( event ) {};
151
+
152
+ /**
153
+ * @protected
154
+ * @param {!jQuery.Event} event
155
+ * @return {undefined}
156
+ */
157
+ tsf.prototype.statusBarHoverMove = function( event ) {};
158
+
159
+ /**
160
+ * @protected
161
+ * @param {!jQuery.Event} event
162
+ * @return {undefined}
163
+ */
164
+ tsf.prototype.statusBarHoverLeave = function( event ) {};
165
+
166
+ /**
167
+ * @protected
168
+ * @return {undefined}
169
+ */
170
+ tsf.prototype.removeDesc = function() {};
171
+
172
+ /**
173
+ * @protected
174
+ * @param {!jQuery.Event} event
175
+ * @return {undefined}
176
+ */
177
+ tsf.prototype.tabToggle = function( event ) {};
178
+
179
+ /**
180
+ * @protected
181
+ * @param {!jQuery.Event} event
182
+ * @return {undefined}
183
+ */
184
+ tsf.prototype.taglineToggleTitle = function( event ) {};
185
+
186
+ /**
187
+ * @protected
188
+ * @param {!jQuery.Event} event
189
+ * @return {undefined}
190
+ */
191
+ tsf.prototype.taglineToggleDesc = function( event ) {};
192
+
193
+ /**
194
+ * @protected
195
+ * @param {!jQuery.Event} event
196
+ * @return {undefined}
197
+ */
198
+ tsf.prototype.titleLocationToggle = function( event ) {};
199
+
200
+ /**
201
+ * @protected
202
+ * @param {!jQuery.Event} event
203
+ * @return {undefined}
204
+ */
205
+ tsf.prototype.titlePrefixToggle = function( event ) {};
206
+
207
+ /**
208
+ * @protected
209
+ * @param {!jQuery.Event} event
210
+ * @return {undefined}
211
+ */
212
+ tsf.prototype.additionsToggleDesc = function( event ) {};
213
+
214
+ /**
215
+ * @protected
216
+ * @return {undefined}
217
+ */
218
+ tsf.prototype.taglineToggleOnload = function() {};
219
+
220
+ /**
221
+ * @protected
222
+ * @param {!jQuery.Event} event
223
+ * @return {undefined}
224
+ */
225
+ tsf.prototype.titleProp = function( event ) {};
226
+
227
+ /**
228
+ * @protected
229
+ * @param {!jQuery.Event} event
230
+ * @return {undefined}
231
+ */
232
+ tsf.prototype.taglineProp = function( event ) {};
233
+
234
+ /**
235
+ * @protected
236
+ * @return {undefined}
237
+ */
238
+ tsf.prototype.taglinePropTrigger = function() {};
239
+
240
+ /**
241
+ * @protected
242
+ * @return {undefined}
243
+ */
244
+ tsf.prototype.titleToggle = function() {};
245
+
246
+ /**
247
+ * @protected
248
+ * @return {undefined}
249
+ */
250
+ tsf.prototype.attachUnsavedChangesListener = function() {};
251
+
252
+ /**
253
+ * @protected
254
+ * @return {undefined}
255
+ */
256
+ tsf.prototype.registerChange = function() {};
257
+
258
+ /**
259
+ * @protected
260
+ * @return {undefined}
261
+ */
262
+ tsf.prototype.confirmedReset = function() {};
263
+
264
+ /**
265
+ * @protected
266
+ * @return {Boolean|null}
267
+ */
268
+ tsf.prototype.confirmedReset = function() {};
269
+
270
+ /**
271
+ * @protected
272
+ * @param {!jQuery.Event} event
273
+ * @return {(!jQuery|undefined)}
274
+ */
275
+ tsf.prototype.dynamicPlaceholder = function( event ) {};
276
+
277
+ /**
278
+ * @protected
279
+ * @return {undefined}
280
+ */
281
+ tsf.prototype.selectTitleInput = function() {};
282
+
283
+ /**
284
+ * @protected
285
+ * @return {undefined}
286
+ */
287
+ tsf.prototype.dynamicPlaceholderOnLoad = function() {};
288
+
289
+ /**
290
+ * @protected
291
+ * @return {undefined}
292
+ */
293
+ tsf.prototype.triggerDescriptionOnLoad = function() {};
294
+
295
+ /**
296
+ * @protected
297
+ * @return {undefined}
298
+ */
299
+ tsf.prototype.triggerTitleOnLoad = function() {};
300
+
301
+ /**
302
+ * @protected
303
+ * @return {undefined}
304
+ */
305
+ tsf.prototype.onLoadUnregisterChange = function() {};
306
+
307
+ /**
308
+ * @protected
309
+ * @param {!jQuery.Event} event
310
+ * @return {undefined}
311
+ */
312
+ tsf.prototype.dismissNotice = function( event ) {};
313
+
314
+ /**
315
+ * @protected
316
+ * @param {String} target
317
+ * @return {undefined}
318
+ */
319
+ tsf.prototype.setAjaxLoader = function( target ) {};
320
+
321
+ /**
322
+ * @protected
323
+ * @param {String} target
324
+ * @param {Boolean} success
325
+ * @return {undefined}
326
+ */
327
+ tsf.prototype.unsetAjaxLoader = function( target, success ) {};
328
+
329
+ /**
330
+ * @protected
331
+ * @param {String} target
332
+ * @return {undefined}
333
+ */
334
+ tsf.prototype.resetAjaxLoader = function( target ) {};
335
+
336
+ /**
337
+ * @protected
338
+ * @param {!jQuery.Event} event
339
+ * @return {undefined}
340
+ */
341
+ tsf.prototype.counterUpdate = function( event ) {};
342
+
343
+ /**
344
+ * @protected
345
+ * @param {String} target
346
+ * @param {Boolean} success
347
+ * @return {undefined}
348
+ */
349
+ tsf.prototype.counterUpdatedResponse = function( target, success ) {};
350
+
351
+ /**
352
+ * @protected
353
+ * @return {undefined}
354
+ */
355
+ tsf.prototype.additionsClassInit = function() {};
356
+
357
+ /**
358
+ * @protected
359
+ * @return {undefined}
360
+ */
361
+ tsf.prototype.updateCounters = function() {};
362
+
363
+ /**
364
+ * @protected
365
+ * @param {String} type
366
+ * @return {String}
367
+ */
368
+ tsf.prototype.getCounterName = function( type ) {};
369
+
370
+ /**
371
+ * @protected
372
+ * @param {String} type
373
+ * @return {String}
374
+ */
375
+ tsf.prototype.getSep = function( type ) {};
376
+
377
+ /**
378
+ * @protected
379
+ * @param {!jQuery.Event} event
380
+ * @return {(undefined|null)}
381
+ */
382
+ tsf.prototype.openImageEditor = function( event ) {};
383
+
384
+ /**
385
+ * @protected
386
+ * @return {(Object<?, ?>|undefined|null)}
387
+ */
388
+ tsf.prototype.extendCropper = function() {};
389
+
390
+ /**
391
+ * @protected
392
+ * @param {wp.media.model.Attachment} attachment
393
+ * @param {wp.media.controller.Cropper} controller
394
+ * @return {Object}
395
+ */
396
+ tsf.prototype.calculateImageSelectOptions = function( attachment, controller ) {};
397
+
398
+ /**
399
+ * @protected
400
+ * @param {Number} dstW
401
+ * @param {Number} dstH
402
+ * @param {Number} imgW
403
+ * @param {Number} imgH
404
+ * @return {Boolean}
405
+ */
406
+ tsf.prototype.mustBeCropped = function( dstW, dstH, imgW, imgH ) {};
407
+
408
+ /**
409
+ * @protected
410
+ * @return {undefined}
411
+ */
412
+ tsf.prototype.ready = function() {};
lib/js/tsf.js ADDED
@@ -0,0 +1,2011 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * This file holds The SEO Framework plugin's JS code.
3
+ * Serve JavaScript as an addition, not as a means.
4
+ *
5
+ * @author Sybre Waaijer https://cyberwire.nl/
6
+ * @link https://wordpress.org/plugins/autodescription/
7
+ */
8
+
9
+ /**
10
+ * The SEO Framework plugin
11
+ * Copyright (C) 2015 - 2016 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
15
+ * by the Free Software Foundation.
16
+ *
17
+ * This program is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24
+ */
25
+
26
+ // ==ClosureCompiler==
27
+ // @compilation_level ADVANCED_OPTIMIZATIONS
28
+ // @output_file_name tsf.min.js
29
+ // @externs_url https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/jquery-1.9.js
30
+ // @externs_url https://raw.githubusercontent.com/sybrew/the-seo-framework/master/lib/js/tsf.externs.js
31
+ // ==/ClosureCompiler==
32
+ // http://closure-compiler.appspot.com/home
33
+
34
+ /**
35
+ * Holds The SEO Framework values in an object to avoid polluting global namespace.
36
+ *
37
+ * @since 2.2.4
38
+ * @todo spread methods accross files/classes through protoype?
39
+ *
40
+ * @constructor
41
+ */
42
+ window.tsf = {
43
+
44
+ /**
45
+ * AJAX Nonce string.
46
+ *
47
+ * @since 2.7.0
48
+ *
49
+ * @type {String} nonce The AJAX nonce
50
+ */
51
+ nonce : tsfL10n.nonce,
52
+
53
+ /**
54
+ * i18n object.
55
+ *
56
+ * @since 2.8.0
57
+ *
58
+ * @const
59
+ * @type {Object<string, string>} i18n Localized strings
60
+ */
61
+ i18n : tsfL10n.i18n,
62
+
63
+ /**
64
+ * Page states object.
65
+ *
66
+ * @since 2.8.0
67
+ *
68
+ * @const
69
+ * @type {Object<string, *>} states Localized states
70
+ */
71
+ states : tsfL10n.states,
72
+
73
+ /**
74
+ * Option parameters object.
75
+ *
76
+ * @since 2.8.0
77
+ *
78
+ * @const
79
+ * @type {Object<string, *>} params Localized parameters
80
+ */
81
+ params : tsfL10n.params,
82
+
83
+ /**
84
+ * Other parameters object.
85
+ *
86
+ * @since 2.8.0
87
+ *
88
+ * @const
89
+ * @type {Object<string, ?>} other Localized strings|parameters|states
90
+ */
91
+ other : tsfL10n.other,
92
+
93
+ /**
94
+ * Determines if the settings have been changed since visit.
95
+ *
96
+ * @since 2.2.0
97
+ *
98
+ * @typedef {(Boolean|null|undefined)} settingsChanged
99
+ */
100
+ settingsChanged: false,
101
+
102
+ /**
103
+ * The current title tagline.
104
+ *
105
+ * @since 2.5.0
106
+ *
107
+ * @type {(Boolean|null)} titleTagline
108
+ */
109
+ titleTagline : false,
110
+
111
+ /**
112
+ * The current title separator.
113
+ *
114
+ * @since 2.7.0
115
+ *
116
+ * @type {(String|null)} titleSeparator
117
+ */
118
+ titleSeparator : '',
119
+
120
+ /**
121
+ * The current description separator.
122
+ *
123
+ * @since 2.7.0
124
+ *
125
+ * @type {(String|null)} descriptionSeparator
126
+ */
127
+ descriptionSeparator : '',
128
+
129
+ /**
130
+ * Mixed string and int (i10n is string, JS is int).
131
+ *
132
+ * @since 2.6.0
133
+ *
134
+ * @type {(String|number)} countertype The counterType
135
+ */
136
+ counterType : 0,
137
+
138
+ /**
139
+ * Determines if the current page has input boxes for The SEO Framework.
140
+ *
141
+ * @since 2.7.0
142
+ *
143
+ * @typedef {(Boolean|null|undefined)} hasInput
144
+ */
145
+ hasInput : false,
146
+
147
+ /**
148
+ * The current character counter additions class.
149
+ *
150
+ * @since 2.6.0
151
+ *
152
+ * @type {(string|null)} additionsClass
153
+ */
154
+ additionsClass : '',
155
+
156
+ /**
157
+ * Image cropper instance.
158
+ *
159
+ * @since 2.8.0
160
+ *
161
+ * @type {!Object} cropper
162
+ */
163
+ cropper : {},
164
+
165
+ /**
166
+ * Cached doctitle function.
167
+ *
168
+ * @since 2.3.3
169
+ *
170
+ * @function
171
+ * @return {!jQuery} The jQuery doctitle ID's
172
+ */
173
+ docTitles: function() {
174
+ 'use strict';
175
+
176
+ var $doctitles = jQuery( "#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]" );
177
+
178
+ return $doctitles;
179
+ },
180
+
181
+ /**
182
+ * Cached description function.
183
+ *
184
+ * @since 2.5.0
185
+ *
186
+ * @function
187
+ * @return {!jQuery} The jQuery description ID's
188
+ */
189
+ docDescriptions: function() {
190
+ 'use strict';
191
+
192
+ var $descriptions = jQuery( "#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]" );
193
+
194
+ return $descriptions;
195
+ },
196
+
197
+ /**
198
+ * Helper function for confirming a user action.
199
+ *
200
+ * @since 2.2.4
201
+ *
202
+ * @function
203
+ * @param {String} text The text to display.
204
+ * @return {(Boolean|null)} True on OK, false on cancel.
205
+ */
206
+ confirm: function( text ) {
207
+ 'use strict';
208
+
209
+ return confirm( text );
210
+ },
211
+
212
+ /**
213
+ * Description length counter.
214
+ *
215
+ * @since 2.2.4
216
+ *
217
+ * @function
218
+ * @param {!jQuery.Event} event
219
+ * @return {undefined}
220
+ */
221
+ updateCharacterCountDescription: function( event ) {
222
+ 'use strict';
223
+
224
+ var $this = jQuery( event.target ),
225
+ calcLength = $this.val().length,
226
+ $counter = jQuery( '#' + tsf.escapeStr( event.target.id ) + '_chars' ),
227
+ counterClass = '',
228
+ name = '',
229
+ output = '';
230
+
231
+ // Emptied input, get Description placeholder.
232
+ if ( 0 === calcLength ) {
233
+ //* Output length from placeholder.
234
+ calcLength = $this.prop( 'placeholder' ).length;
235
+ }
236
+
237
+ if ( calcLength < 100 || calcLength >= 175 ) {
238
+ counterClass = 'tsf-count-bad';
239
+ name = tsf.getCounterName( 'bad' );
240
+ } else if ( calcLength < 137 || ( calcLength > 155 && calcLength < 175 ) ) {
241
+ counterClass = 'tsf-count-okay';
242
+ name = tsf.getCounterName( 'okay' );
243
+ } else {
244
+ counterClass = 'tsf-count-good';
245
+ name = tsf.getCounterName( 'good' );
246
+ }
247
+
248
+ if ( tsf.additionsClass )
249
+ counterClass += ' ' + tsf.additionsClass;
250
+
251
+ if ( ! tsf.counterType || 1 == tsf.counterType ) {
252
+ output = calcLength.toString();
253
+ } else if ( 2 == tsf.counterType ) {
254
+ output = name;
255
+ } else if ( 3 == tsf.counterType ) {
256
+ output = calcLength.toString() + ' - ' + name;
257
+ }
258
+
259
+ $counter.html( output ).removeClass().addClass( counterClass );
260
+ },
261
+
262
+ /**
263
+ * Title length counter, with special characters
264
+ *
265
+ * @since 2.2.4
266
+ *
267
+ * @function
268
+ * @param {!jQuery.Event} event
269
+ * @return {undefined}
270
+ */
271
+ updateCharacterCountTitle: function( event ) {
272
+ 'use strict';
273
+
274
+ var $this = jQuery( event.target ),
275
+ additions = tsf.params['titleAdditions'].length,
276
+ description = tsf.params['blogDescription'].length,
277
+ siteTitle = tsf.params['siteTitle'].length,
278
+ titleLength = $this.val().length,
279
+ placeholder = $this.prop( 'placeholder' ).length,
280
+ tagline = jQuery( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).val(),
281
+ seplen = 3,
282
+ $counter = jQuery( '#' + tsf.escapeStr( event.target.id ) + '_chars' ),
283
+ calcLength = 0,
284
+ additionsClass = tsf.additionsClass,
285
+ counterType = tsf.counterType,
286
+ counterClass = '',
287
+ name = '',
288
+ output = '';
289
+
290
+ // Additions or tagline removed, remove additions and separator.
291
+ if ( ! tsf.titleTagline ) {
292
+ additions = 0;
293
+ seplen = 0;
294
+ }
295
+
296
+ // Emptied input, get Site title.
297
+ if ( 0 === titleLength ) {
298
+ if ( 0 !== siteTitle ) {
299
+ titleLength = siteTitle;
300
+ } else {
301
+ //* Output length from placeholder.
302
+ calcLength = placeholder;
303
+ }
304
+ }
305
+
306
+ // Length should be something now.
307
+ if ( 0 !== titleLength ) {
308
+
309
+ if ( 0 !== additions && typeof tagline !== 'undefined' ) {
310
+ var $tagLength = tagline.length;
311
+
312
+ // Replace additions with tagline is tagline isn't empty.
313
+ if ( 0 !== $tagLength ) {
314
+ additions = $tagLength;
315
+ } else {
316
+ additions = description;
317
+ }
318
+ }
319
+
320
+ // Put it all together
321
+ if ( 0 === additions ) {
322
+ calcLength = titleLength;
323
+ } else {
324
+ calcLength = titleLength + seplen + additions;
325
+ }
326
+ }
327
+
328
+ if ( calcLength < 25 || calcLength >= 75 ) {
329
+ counterClass = 'tsf-count-bad';
330
+ name = tsf.getCounterName( 'bad' );
331
+ } else if ( calcLength < 42 || ( calcLength > 55 && calcLength < 75 ) ) {
332
+ counterClass = 'tsf-count-okay';
333
+ name = tsf.getCounterName( 'okay' );
334
+ } else {
335
+ counterClass = 'tsf-count-good';
336
+ name = tsf.getCounterName( 'good' );
337
+ }
338
+
339
+ if ( additionsClass )
340
+ counterClass += ' ' + additionsClass;
341
+
342
+ if ( ! counterType || 1 == counterType ) {
343
+ output = calcLength.toString();
344
+ } else if ( 2 == counterType ) {
345
+ output = name;
346
+ } else if ( 3 == counterType ) {
347
+ output = calcLength.toString() + ' - ' + name;
348
+ }
349
+
350
+ $counter.html( output ).removeClass().addClass( counterClass );
351
+ },
352
+
353
+ /**
354
+ * Escapes HTML strings.
355
+ *
356
+ * @since 2.2.4
357
+ *
358
+ * @function
359
+ *
360
+ * @param {String} str
361
+ * @return {(String|null)} HTML to jQuery converted string
362
+ */
363
+ escapeStr: function( str ) {
364
+ 'use strict';
365
+
366
+ if ( str )
367
+ return str.replace( /([\[\]\/])/g,'\\$1');
368
+
369
+ return str;
370
+ },
371
+
372
+ /**
373
+ * Dynamic Title separator replacement in metabox
374
+ *
375
+ * @since 2.2.2
376
+ *
377
+ * @function
378
+ * @param {!jQuery.Event} event
379
+ * @return {undefined}
380
+ */
381
+ separatorSwitchTitle: function( event ) {
382
+ 'use strict';
383
+
384
+ var $sep = jQuery( ".tsf-sep-js" ),
385
+ val = jQuery( event.target ).val();
386
+
387
+ //* Update cache.
388
+ tsf.titleSeparator = val;
389
+
390
+ if ( 'pipe' === val ) {
391
+ $sep.text( " | " );
392
+ } else if ( 'dash' === val ) {
393
+ $sep.text( " - " );
394
+ } else {
395
+ $sep.html( " &" + val + "; " );
396
+ }
397
+ },
398
+
399
+ /**
400
+ * Dynamic Description separator replacement in metabox
401
+ *
402
+ * @since 2.3.4
403
+ *
404
+ * @function
405
+ * @param {!jQuery.Event} event
406
+ * @return {undefined}
407
+ */
408
+ separatorSwitchDesc: function( event ) {
409
+ 'use strict';
410
+
411
+ var $sep = jQuery( "#autodescription-descsep-js" ),
412
+ val = jQuery( event.target ).val();
413
+
414
+ if ( 'pipe' === val ) {
415
+ $sep.text( " | " );
416
+ } else if ( 'dash' === val ) {
417
+ $sep.text( " - " );
418
+ } else {
419
+ $sep.html( " &" + val + "; " );
420
+ }
421
+ },
422
+
423
+ /**
424
+ * Status bar description init on hover actions.
425
+ *
426
+ * @since 2.1.9
427
+ *
428
+ * @function
429
+ * @return {undefined}
430
+ */
431
+ statusBarHover: function() {
432
+ 'use strict';
433
+
434
+ var $wrap = jQuery( '.tsf-seo-bar-inner-wrap' ).find( 'a' );
435
+
436
+ $wrap.on( 'mouseenter', tsf.statusBarHoverEnter );
437
+ $wrap.on( 'mousemove', tsf.statusBarHoverMove );
438
+ $wrap.on( 'mouseleave', tsf.statusBarHoverLeave );
439
+ },
440
+
441
+ /**
442
+ * Status bar description output on hover enter.
443
+ *
444
+ * @since 2.6.0
445
+ *
446
+ * @function
447
+ * @param {!jQuery.Event} event
448
+ * @return {undefined}
449
+ */
450
+ statusBarHoverEnter: function( event ) {
451
+ 'use strict';
452
+
453
+ var $this = jQuery( event.target ),
454
+ desc = $this.data( 'desc' );
455
+
456
+ if ( desc !== undefined && 0 === $this.find( 'div' ).length ) {
457
+ $this.append( '<div class="tsf-explanation-desc">' + desc + '<div></div></div>' );
458
+
459
+ var height = $this.find( 'div.tsf-explanation-desc' ).height() + 28;
460
+
461
+ $this.find( 'div.tsf-explanation-desc' ).css( 'top', ( $this.position().top - height ) + 'px' );
462
+ }
463
+ },
464
+
465
+ /**
466
+ * Status bar description output on hover move.
467
+ *
468
+ * @since 2.6.0
469
+ *
470
+ * @function
471
+ * @param {!jQuery.Event} event
472
+ * @return {undefined}
473
+ */
474
+ statusBarHoverMove: function( event ) {
475
+ 'use strict';
476
+
477
+ var $this = jQuery( event.target ),
478
+ pagex = event.pageX,
479
+ mousex = pagex - jQuery( '.tsf-seo-bar-inner-wrap' ).offset().left - 11, // 22px width of arrow / 2 = 11 middle
480
+ $balloon = $this.find( '.tsf-explanation-desc' ),
481
+ $arrow = $balloon.find( 'div' );
482
+
483
+ if ( mousex < 1 ) {
484
+ $arrow.css( 'left', 0 + "px" );
485
+ } else if ( $balloon.offset() !== undefined ) {
486
+ var width = $balloon.width(),
487
+ maxOffset = $balloon.offset().left + width + 11;
488
+
489
+ if ( pagex > maxOffset ) {
490
+ $arrow.css( 'left', width + "px" );
491
+ } else {
492
+ $arrow.css( 'left', mousex + "px" );
493
+ }
494
+ }
495
+ },
496
+
497
+ /**
498
+ * Status bar description removal on hover leave.
499
+ *
500
+ * @since 2.6.0
501
+ *
502
+ * @function
503
+ * @param {!jQuery.Event} event
504
+ * @return {undefined}
505
+ */
506
+ statusBarHoverLeave: function( event ) {
507
+ 'use strict';
508
+
509
+ jQuery( event.target ).find( 'div.tsf-explanation-desc' ).remove();
510
+ },
511
+
512
+ /**
513
+ * Remove Status bar desc if clicked outside (touch support)
514
+ *
515
+ * @since 2.1.9
516
+ *
517
+ * @function
518
+ * @return {undefined}
519
+ */
520
+ removeDesc: function() {
521
+ 'use strict';
522
+
523
+ var $target = jQuery( document.body.target ),
524
+ $desc = jQuery( '.tsf-seo-bar-inner-wrap a' );
525
+
526
+ if ( ! $target.closest( $desc ).length )
527
+ $desc.find( 'div.tsf-explanation-desc' ).remove();
528
+ },
529
+
530
+ /**
531
+ * Refines Styling for the navigation tabs on the settings pages
532
+ *
533
+ * @since 2.2.2
534
+ *
535
+ * Rewritten
536
+ * @since 2.6.0
537
+ *
538
+ * @function
539
+ * @param {!jQuery.Event} event
540
+ * @return {undefined}
541
+ */
542
+ tabToggle: function( event ) {
543
+ 'use strict';
544
+
545
+ var target = jQuery( event.target ).prop( 'id' ),
546
+ name = jQuery( event.target ).prop( 'name' );
547
+
548
+ if ( typeof target !== 'undefined' ) {
549
+ var $content = jQuery( '#' + target + '-content' ),
550
+ $other = jQuery( '.' + name + '-content' );
551
+
552
+ if ( typeof $content !== 'undefined' ) {
553
+ $other.removeClass( 'tsf-active-tab-content' );
554
+ $content.addClass( 'tsf-active-tab-content' );
555
+ }
556
+ }
557
+ },
558
+
559
+ /**
560
+ * Toggle tagline within the Left/Right example for the HomePage Title
561
+ *
562
+ * @since 2.2.4
563
+ *
564
+ * @function
565
+ * @param {!jQuery.Event} event
566
+ * @return {undefined}
567
+ */
568
+ taglineToggleTitle: function( event ) {
569
+ 'use strict';
570
+
571
+ var $this = jQuery( event.target ),
572
+ $tag = jQuery( '.tsf-custom-blogname-js' );
573
+
574
+ if ( $this.is( ':checked' ) ) {
575
+ $tag.css( 'display', 'inline' );
576
+ tsf.titleTagline = true;
577
+ } else {
578
+ $tag.css( 'display', 'none' );
579
+ tsf.titleTagline = false;
580
+ }
581
+
582
+ tsf.docTitles().trigger( 'keyup', tsf.updateCharacterCountTitle );
583
+ },
584
+
585
+ /**
586
+ * Toggle tagline within the Description Example.
587
+ *
588
+ * @since 2.3.4
589
+ *
590
+ * @function
591
+ * @param {!jQuery.Event} event
592
+ * @return {undefined}
593
+ */
594
+ taglineToggleDesc: function( event ) {
595
+ 'use strict';
596
+
597
+ var $this = jQuery( event.target ),
598
+ $tagDesc = jQuery( '#tsf-on-blogname-js' );
599
+
600
+ if ( $this.is(':checked') ) {
601
+ $tagDesc.css( 'display', 'inline' );
602
+ } else {
603
+ $tagDesc.css( 'display', 'none' );
604
+ }
605
+ },
606
+
607
+ /**
608
+ * Toggle title additions location for the Title examples.
609
+ *
610
+ * @since 2.6.0
611
+ *
612
+ * @function
613
+ * @param {!jQuery.Event} event
614
+ * @return {undefined}
615
+ */
616
+ titleLocationToggle: function( event ) {
617
+ 'use strict';
618
+
619
+ var val = jQuery( event.target ).val(),
620
+ $titleExampleLeft = jQuery( '.tsf-title-additions-example-left' ),
621
+ $titleExampleRight = jQuery( '.tsf-title-additions-example-right' );
622
+
623
+ if ( 'right' === val ) {
624
+ $titleExampleLeft.css( 'display', 'none' );
625
+ $titleExampleRight.css( 'display', 'inline' );
626
+ } else {
627
+ $titleExampleLeft.css( 'display', 'inline' );
628
+ $titleExampleRight.css( 'display', 'none' );
629
+ }
630
+ },
631
+
632
+ /**
633
+ * Toggle title prefixes for the Prefix Title example.
634
+ *
635
+ * @since 2.6.0
636
+ *
637
+ * @function
638
+ * @param {!jQuery.Event} event
639
+ * @return {undefined}
640
+ */
641
+ titlePrefixToggle: function( event ) {
642
+ 'use strict';
643
+
644
+ var $this = jQuery( event.target ),
645
+ $prefix = jQuery( '.tsf-title-prefix-example' );
646
+
647
+ if ( $this.is(':checked') ) {
648
+ $prefix.css( 'display', 'none' );
649
+ } else {
650
+ $prefix.css( 'display', 'inline' );
651
+ }
652
+ },
653
+
654
+ /**
655
+ * Toggle additions within Description example for the Example Description
656
+ *
657
+ * @since 2.6.0
658
+ *
659
+ * @function
660
+ * @param {!jQuery.Event} event
661
+ * @return {undefined}
662
+ */
663
+ additionsToggleDesc: function( event ) {
664
+ 'use strict';
665
+
666
+ var $this = jQuery( event.target ),
667
+ $tagDesc = jQuery( '#tsf-description-additions-js' );
668
+
669
+ if ( $this.is(':checked') ) {
670
+ $tagDesc.css( 'display', 'inline' );
671
+ } else {
672
+ $tagDesc.css( 'display', 'none' );
673
+ }
674
+ },
675
+
676
+ /**
677
+ * Toggle tagline end examples within the Left/Right example for the
678
+ * HomePage Title or Description.
679
+ *
680
+ * @since 2.2.7
681
+ *
682
+ * @function
683
+ * @return {undefined}
684
+ */
685
+ taglineToggleOnload: function() {
686
+ 'use strict';
687
+
688
+ if ( ! tsf.hasInput )
689
+ return;
690
+
691
+ var $tagTitle = jQuery( '#tsf-title-tagline-toggle :input' ),
692
+ $title = jQuery( '.tsf-custom-blogname-js' ),
693
+ $tagDescAdditions = jQuery( '#tsf-description-additions-toggle :input' ),
694
+ $descAdditions = jQuery( '#tsf-description-additions-js' ),
695
+ $tagDescBlogname = jQuery( '#tsf-description-onblogname-toggle :input' ),
696
+ $descBlogname = jQuery( '#tsf-on-blogname-js' ),
697
+ $tagTitleAdditions = jQuery( '#tsf-title-additions-toggle :input' ),
698
+ $titleAdditions = jQuery( '.tsf-title-additions-js' );
699
+
700
+ if ( $tagTitle.is( ':checked' ) ) {
701
+ $title.css( 'display', 'inline' );
702
+ } else {
703
+ $title.css( 'display', 'none' );
704
+ }
705
+
706
+ if ( $tagDescAdditions.is( ':checked' ) ) {
707
+ $descAdditions.css( 'display', 'inline' );
708
+ } else {
709
+ $descAdditions.css( 'display', 'none' );
710
+ }
711
+
712
+ if ( $tagDescBlogname.is( ':checked' ) ) {
713
+ $descBlogname.css( 'display', 'inline' );
714
+ } else {
715
+ $descBlogname.css( 'display', 'none' );
716
+ }
717
+
718
+ // Reverse option.
719
+ if ( $tagTitleAdditions.is( ':checked' ) ) {
720
+ $titleAdditions.css( 'display', 'none' );
721
+ } else {
722
+ $titleAdditions.css( 'display', 'inline' );
723
+ }
724
+ },
725
+
726
+ /**
727
+ * Change Home Page Title based on input of the Custom Title
728
+ *
729
+ * @since 2.2.4
730
+ *
731
+ * @function
732
+ * @param {!jQuery.Event} event
733
+ * @return {undefined}
734
+ */
735
+ titleProp: function( event ) {
736
+ 'use strict';
737
+
738
+ var val = jQuery( event.target ).val(),
739
+ $title = jQuery( '.tsf-custom-title-js' );
740
+
741
+ if ( val.length === 0 ) {
742
+ $title.text( tsf.i18n['siteTitle'] );
743
+ } else {
744
+ $title.text( val );
745
+ }
746
+ },
747
+
748
+ /**
749
+ * Change Title based on input of the Custom Title
750
+ *
751
+ * @since 2.3.8
752
+ *
753
+ * @function
754
+ * @param {!jQuery.Event} event
755
+ * @return {undefined}
756
+ */
757
+ taglineProp: function( event ) {
758
+ 'use strict';
759
+
760
+ var val = jQuery( event.target ).val(),
761
+ $floatTag = jQuery( '.tsf-custom-tagline-js' ),
762
+ $target = jQuery( '#autodescription-site-settings\\[homepage_title\\]' ),
763
+ leftRight = jQuery( '#tsf-home-title-location input:checked' ).val(),
764
+ $toggle = jQuery( '#autodescription-site-settings\\[homepage_tagline\\]' ),
765
+ title = tsf.params['siteTitle'],
766
+ placeholder = title,
767
+ description = tsf.params['blogDescription'],
768
+ sep = tsf.getSep( 'title' );
769
+
770
+ if ( $toggle.is( ':checked' ) ) {
771
+
772
+ if ( val.length !== 0 ) {
773
+ description = val;
774
+ }
775
+
776
+ if ( leftRight.length !== 0 && 'left' === leftRight ) {
777
+ placeholder = title + ' ' + sep + ' ' + description;
778
+ } else {
779
+ placeholder = description + ' ' + sep + ' ' + title;
780
+ }
781
+
782
+ }
783
+
784
+ $floatTag.text( description );
785
+ $target.prop( 'placeholder', placeholder );
786
+
787
+ // Notify tagline has changed.
788
+ tsf.docTitles().trigger( 'input', tsf.updateCharacterCountTitle );
789
+ },
790
+
791
+ /**
792
+ * Trigger Change on Left/Right selection of Home Page Title
793
+ *
794
+ * @since 2.5.0
795
+ *
796
+ * @function
797
+ * @return {undefined}
798
+ */
799
+ taglinePropTrigger: function() {
800
+ 'use strict';
801
+
802
+ jQuery( "#autodescription-site-settings\\[homepage_title_tagline\\]" ).trigger( 'input', tsf.taglineProp );
803
+ },
804
+
805
+ /**
806
+ * Trigger Change on Left/Right selection of Global Title
807
+ *
808
+ * @since 2.5.2
809
+ *
810
+ * @function
811
+ * @return {undefined}
812
+ */
813
+ titleToggle: function() {
814
+ 'use strict';
815
+
816
+ var $this = jQuery( event.target ),
817
+ $tagDesc = jQuery( '.tsf-title-additions-js' );
818
+
819
+ if ( $this.is( ':checked' ) ) {
820
+ $tagDesc.css( 'display', 'none' );
821
+ } else {
822
+ $tagDesc.css( 'display', 'inline' );
823
+ }
824
+ },
825
+
826
+ /**
827
+ * Have all form fields in The SEO Framework metaboxes set a dirty flag when changed.
828
+ *
829
+ * @since 2.0.0
830
+ *
831
+ * @function
832
+ * @return {undefined}
833
+ */
834
+ attachUnsavedChangesListener: function() {
835
+ 'use strict';
836
+
837
+ if ( ! tsf.hasInput )
838
+ return;
839
+
840
+ jQuery( '.tsf-metaboxes :input, #tsf-inpost-box .inside :input' ).not( '.tsf-tab :input' ).change( function() {
841
+ tsf.registerChange();
842
+ } );
843
+
844
+ jQuery( '.tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea' ).not(
845
+ '.tsf-nav-tab-wrapper :input' ).on( 'input', function() {
846
+ tsf.registerChange();
847
+ } );
848
+
849
+ window.onbeforeunload = function() {
850
+ if ( tsf.settingsChanged ) {
851
+ return tsf.i18n['saveAlert'];
852
+ }
853
+ };
854
+
855
+ jQuery( '.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete' ).click( function() {
856
+ window.onbeforeunload = null;
857
+ } );
858
+ },
859
+
860
+ /**
861
+ * Set a flag, to indicate form fields have changed.
862
+ *
863
+ * @since 2.2.4
864
+ *
865
+ * @function
866
+ * @return {undefined}
867
+ */
868
+ registerChange: function() {
869
+ 'use strict';
870
+
871
+ tsf.settingsChanged = true;
872
+ },
873
+
874
+ /**
875
+ * Ask user to confirm that settings should now be reset.
876
+ *
877
+ * @since 2.2.4
878
+ *
879
+ * @function
880
+ * @return {(Boolean|null)} True if reset should occur, false if not.
881
+ */
882
+ confirmedReset: function() {
883
+ 'use strict';
884
+
885
+ return confirm( tsf.i18n['confirmReset'] );
886
+ },
887
+
888
+ /**
889
+ * Adds dynamic placeholder to Title input based on site settings.
890
+ *
891
+ * @since 2.5.0
892
+ *
893
+ * @function
894
+ * @param {!jQuery.Event} event
895
+ * @return {(!jQuery|undefined)}
896
+ */
897
+ dynamicPlaceholder: function( event ) {
898
+ 'use strict';
899
+
900
+ var hasAdditions = tsf.params['titleAdditions'].length,
901
+ $placeholder = jQuery( '#tsf-title-placeholder' );
902
+
903
+ // If check is defined, we're on SEO settings page.
904
+ if ( 0 === hasAdditions ) {
905
+ var $this = jQuery( event.target );
906
+
907
+ // Empty the placeholder as we can't execute.
908
+ $this.css( 'text-indent', "initial" );
909
+ return $placeholder.empty();
910
+ }
911
+
912
+ var after = false,
913
+ check = jQuery( '#tsf-home-title-location input:checked' ).val(),
914
+ rtl = tsf.states['isRTL'],
915
+ additions = '';
916
+
917
+ if ( typeof check !== 'undefined' && check.length !== 0 ) {
918
+ //* We're in SEO Settings page.
919
+
920
+ if ( '1' === rtl ) {
921
+ if ( 'right' === check ) {
922
+ after = true;
923
+ }
924
+ } else {
925
+ if ( 'left' === check ) {
926
+ after = true;
927
+ }
928
+ }
929
+ } else {
930
+ //* We're in post/page edit screen.
931
+
932
+ var isHome = tsf.states['isHome'],
933
+ titleLocation = tsf.params['titleLocation'],
934
+ tagline = tsf.titleTagline;
935
+
936
+ // We're on post/page screen.
937
+ if ( isHome ) {
938
+ // Static Front page, switch check.
939
+ if ( tagline ) {
940
+ if ( rtl ) {
941
+ if ( 'right' === titleLocation ) {
942
+ after = true;
943
+ }
944
+ } else if ( 'left' === titleLocation ) {
945
+ after = true;
946
+ }
947
+ }
948
+ } else {
949
+ if ( rtl ) {
950
+ if ( 'left' === titleLocation ) {
951
+ after = true;
952
+ }
953
+ } else if ( 'right' === titleLocation ) {
954
+ after = true;
955
+ }
956
+ }
957
+ }
958
+
959
+ var $tagbox = jQuery( '#tsf-title-tagline-toggle :input' );
960
+
961
+ if ( typeof $tagbox !== "undefined" && $tagbox.length > 0 && ! $tagbox.is( ':checked' ) ) {
962
+ //* We're on SEO Settings Page now, and tagline has been disabled.
963
+ var $this = jQuery( event.target );
964
+
965
+ $this.css( 'text-indent', "initial" );
966
+ $placeholder.css( 'display', 'none' );
967
+ } else {
968
+ var $this = jQuery( event.target ),
969
+ inputVal = $this.val(),
970
+ $offsetTest = jQuery( "#tsf-title-offset" ),
971
+ offsetWidth = 0,
972
+ heightPad = ( $this.outerHeight( true ) - $this.height() ) / 2,
973
+ horPad = ( $this.outerWidth() - $this.width() ) / 2,
974
+ leftOffset = ( $this.outerWidth( true ) - $this.width() ) / 2,
975
+ taglineVal = jQuery( "#autodescription-site-settings\\[homepage_title_tagline\\]" ).val(),
976
+ pos = 'left',
977
+ separator = tsf.getSep( 'title' );
978
+
979
+ if ( rtl ) {
980
+ pos = 'right';
981
+ }
982
+
983
+ if ( typeof taglineVal !== "undefined" && taglineVal.length === 0) {
984
+ taglineVal = tsf.params['blogDescription'];
985
+ }
986
+
987
+ if ( after ) {
988
+ additions = separator + " " + tsf.params['titleAdditions'];
989
+
990
+ // Exchange the placeholder value of the custom Tagline in the HomePage Metabox
991
+ if ( typeof taglineVal !== "undefined" && taglineVal.length > 0 ) {
992
+ additions = separator + " " + taglineVal;
993
+ }
994
+
995
+ $this.css( 'text-indent', "initial" );
996
+ } else {
997
+ additions = tsf.params['titleAdditions'] + " " + separator;
998
+
999
+ // Exchange the placeholder value of the custom Tagline in the HomePage Metabox
1000
+ if ( typeof taglineVal !== "undefined" && taglineVal.length > 0 ) {
1001
+ additions = taglineVal + " " + separator;
1002
+ }
1003
+ }
1004
+
1005
+ // Width offset container, copy variables and remain hidden.
1006
+ $offsetTest.text( inputVal );
1007
+ $offsetTest.css({
1008
+ 'fontFamily' : $this.css( "fontFamily" ),
1009
+ 'fontWeight' : $this.css( "fontWeight" ),
1010
+ 'letterSpacing' : $this.css( "letterSpacing" ),
1011
+ 'fontSize' : $this.css( "fontSize" ),
1012
+ });
1013
+ offsetWidth = $offsetTest.width();
1014
+
1015
+ var maxWidth = $this.width() - horPad - offsetWidth;
1016
+
1017
+ if ( maxWidth < 0 )
1018
+ maxWidth = 0;
1019
+
1020
+ // Moving Placeholder output
1021
+ $placeholder.css({
1022
+ 'display': $this.css( "display" ),
1023
+ 'lineHeight': $this.css( "lineHeight" ),
1024
+ 'paddingTop': heightPad + "px",
1025
+ 'paddingBottom': heightPad + "px",
1026
+ 'fontFamily': $this.css( "fontFamily" ),
1027
+ 'fontWeight': $this.css( "fontWeight" ),
1028
+ 'fontSize': $this.css( "fontSize" ),
1029
+ 'letterSpacing': $this.css( "letterSpacing" ),
1030
+ 'maxWidth': maxWidth + "px",
1031
+ });
1032
+
1033
+ //* Empty or fill placeholder and offsets.
1034
+ if ( typeof inputVal === "undefined" || inputVal.length < 1 ) {
1035
+
1036
+ if ( ! after )
1037
+ $this.css( 'text-indent', "initial" );
1038
+
1039
+ $placeholder.empty();
1040
+ } else {
1041
+ $placeholder.text( additions );
1042
+
1043
+ // Don't calculate when empty.
1044
+ if ( $this.outerWidth() > leftOffset ) {
1045
+ if ( after ) {
1046
+ $placeholder.css( pos, horPad + leftOffset + $offsetTest.width() + "px" );
1047
+ } else {
1048
+ var indent = horPad + $placeholder.width();
1049
+
1050
+ if ( indent < 0 )
1051
+ indent = 0;
1052
+
1053
+ $placeholder.css( pos, leftOffset + "px" );
1054
+ $this.css( 'text-indent', indent + "px" );
1055
+ }
1056
+ }
1057
+ }
1058
+ }
1059
+ },
1060
+
1061
+ /**
1062
+ * Makes user click act natural by selecting the parent Title text input.
1063
+ *
1064
+ * @since 2.5.0
1065
+ *
1066
+ * @function
1067
+ * @return {undefined}
1068
+ */
1069
+ selectTitleInput: function() {
1070
+ 'use strict';
1071
+
1072
+ var $input = tsf.docTitles();
1073
+
1074
+ $input.focus();
1075
+
1076
+ if ( $input.setSelectionRange ) {
1077
+ // Go to end times 2 if setSelectionRange exists.
1078
+ var length = $input.val().length * 2;
1079
+ $input.setSelectionRange( length, length );
1080
+ } else {
1081
+ // Replace value with itself.
1082
+ $input.val( $input.val() ).focus();
1083
+ }
1084
+ },
1085
+
1086
+ /**
1087
+ * Adds dynamic placeholder to Title input based on site settings on Load.
1088
+ *
1089
+ * @since 2.5.0
1090
+ *
1091
+ * @function
1092
+ * @return {undefined}
1093
+ */
1094
+ dynamicPlaceholderOnLoad: function() {
1095
+ 'use strict';
1096
+
1097
+ if ( ! tsf.hasInput )
1098
+ return;
1099
+
1100
+ var $input = tsf.docTitles();
1101
+
1102
+ if ( typeof $input.val() !== "undefined" ) {
1103
+ if ( $input.val().length > 0 ) {
1104
+ $input.trigger( 'input', tsf.dynamicPlaceholder );
1105
+ } else {
1106
+ $input.trigger( 'input', tsf.updateCharacterCountTitle );
1107
+ }
1108
+ }
1109
+ },
1110
+
1111
+ /**
1112
+ * Triggers keyup on description input so the counter can colorize.
1113
+ *
1114
+ * @since 2.5.0
1115
+ *
1116
+ * @function
1117
+ * @return {undefined}
1118
+ */
1119
+ triggerDescriptionOnLoad: function() {
1120
+ 'use strict';
1121
+
1122
+ if ( ! tsf.hasInput )
1123
+ return;
1124
+
1125
+ var $input = tsf.docDescriptions();
1126
+
1127
+ $input.trigger( 'input', tsf.updateCharacterCountDescription );
1128
+ },
1129
+
1130
+
1131
+ /**
1132
+ * Triggers keyup on title input so the counter can colorize.
1133
+ *
1134
+ * @since 2.6.0
1135
+ *
1136
+ * @function
1137
+ * @return {undefined}
1138
+ */
1139
+ triggerTitleOnLoad: function() {
1140
+ 'use strict';
1141
+
1142
+ if ( ! tsf.hasInput )
1143
+ return;
1144
+
1145
+ var $input = tsf.docTitles();
1146
+
1147
+ $input.trigger( 'input', tsf.updateCharacterCountTitle );
1148
+ },
1149
+
1150
+ /**
1151
+ * OnLoad changes can affect settings changes. This function reverts those.
1152
+ *
1153
+ * @since 2.5.0
1154
+ *
1155
+ * @function
1156
+ * @return {undefined}
1157
+ */
1158
+ onLoadUnregisterChange: function() {
1159
+ 'use strict';
1160
+
1161
+ //* Prevent trigger of settings change
1162
+ tsf.settingsChanged = false;
1163
+ },
1164
+
1165
+ /**
1166
+ * Dismissible notices. Uses class .tsf-notice.
1167
+ *
1168
+ * @since 2.6.0
1169
+ *
1170
+ * @function
1171
+ * @param {!jQuery.Event} event
1172
+ * @return {undefined}
1173
+ */
1174
+ dismissNotice: function( event ) {
1175
+ 'use strict';
1176
+
1177
+ var $this = jQuery( event.target );
1178
+
1179
+ $this.parents( '.tsf-notice' ).slideUp( 200, function() {
1180
+ $this.remove();
1181
+ } );
1182
+ },
1183
+
1184
+ /**
1185
+ * Visualizes AJAX loading time through target class change.
1186
+ *
1187
+ * @since 2.7.0
1188
+ *
1189
+ * @function
1190
+ * @param {String} target
1191
+ * @return {undefined}
1192
+ */
1193
+ setAjaxLoader: function( target ) {
1194
+ 'use strict';
1195
+
1196
+ jQuery( target ).toggleClass( 'tsf-loading' );
1197
+ },
1198
+
1199
+ /**
1200
+ * Adjusts class loaders on Ajax response.
1201
+ *
1202
+ * @since 2.7.0
1203
+ *
1204
+ * @function
1205
+ * @param {String} target
1206
+ * @param {Boolean} success
1207
+ * @return {undefined}
1208
+ */
1209
+ unsetAjaxLoader: function( target, success ) {
1210
+ 'use strict';
1211
+
1212
+ var newclass = 'tsf-success',
1213
+ fade = 2500;
1214
+
1215
+ if ( ! success ) {
1216
+ newclass = 'tsf-error';
1217
+ fade = 5000;
1218
+ }
1219
+
1220
+ jQuery( target ).removeClass( 'tsf-loading' ).addClass( newclass ).fadeOut( fade );
1221
+ },
1222
+
1223
+ /**
1224
+ * Cleans and resets Ajax wrapper class and contents to default.
1225
+ * Also stops any animation and resets fadeout to beginning.
1226
+ *
1227
+ * @since 2.7.0
1228
+ *
1229
+ * @function
1230
+ * @param {String} target
1231
+ * @return {undefined}
1232
+ */
1233
+ resetAjaxLoader: function( target ) {
1234
+ 'use strict';
1235
+
1236
+ jQuery( target ).stop().empty().prop( 'class', 'tsf-ajax' ).css( 'opacity', '1' ).removeProp( 'style' );
1237
+ },
1238
+
1239
+ /**
1240
+ * Updates the counter type.
1241
+ *
1242
+ * @since 2.6.0
1243
+ *
1244
+ * @function
1245
+ * @param {!jQuery.Event} event
1246
+ * @return {undefined}
1247
+ */
1248
+ counterUpdate: function( event ) {
1249
+ 'use strict';
1250
+
1251
+ // Count up, reset to 0 if needed. We have 4 options: 0, 1, 2, 3
1252
+ tsf.counterType = tsf.counterType + 1;
1253
+ if ( tsf.counterType > 3 )
1254
+ tsf.counterType = 0;
1255
+
1256
+ //* Update counters locally.
1257
+ tsf.additionsClassInit();
1258
+
1259
+ var target = '.tsf-counter .tsf-ajax',
1260
+ status = 0;
1261
+
1262
+ //* Reset ajax loader
1263
+ tsf.resetAjaxLoader( target );
1264
+
1265
+ //* Set ajax loader.
1266
+ tsf.setAjaxLoader( target );
1267
+
1268
+ //* Setup external update.
1269
+ var settings = {
1270
+ method: 'POST',
1271
+ url: ajaxurl,
1272
+ datatype: 'json',
1273
+ data: {
1274
+ 'action' : 'the_seo_framework_update_counter',
1275
+ 'nonce' : tsf.nonce,
1276
+ 'val' : tsf.counterType,
1277
+ },
1278
+ async: true,
1279
+ success: function( response ) {
1280
+
1281
+ response = jQuery.parseJSON( response );
1282
+
1283
+ //* I could do value check, but that will simply lag behind. Unless an annoying execution delay is added.
1284
+ if ( 'success' === response.type )
1285
+ status = 1;
1286
+
1287
+ tsf.counterUpdatedResponse( target, status );
1288
+ },
1289
+ }
1290
+
1291
+ jQuery.ajax( settings );
1292
+ },
1293
+
1294
+ /**
1295
+ * Visualizes the AJAX response to the user.
1296
+ *
1297
+ * @since 2.7.0
1298
+ *
1299
+ * @function
1300
+ * @param {String} target
1301
+ * @param {Number} success
1302
+ * @return {undefined}
1303
+ */
1304
+ counterUpdatedResponse: function( target, success ) {
1305
+ 'use strict';
1306
+
1307
+ switch ( success ) {
1308
+ case 0:
1309
+ tsf.unsetAjaxLoader( target, false );
1310
+ break;
1311
+ case 1:
1312
+ tsf.unsetAjaxLoader( target, true );
1313
+ break;
1314
+ default:
1315
+ tsf.resetAjaxLoader( target );
1316
+ break;
1317
+ }
1318
+ },
1319
+
1320
+ /**
1321
+ * Sets up additionsClass variable.
1322
+ * Also sets up browser caches correctly.
1323
+ *
1324
+ * @since 2.6.0
1325
+ *
1326
+ * @function
1327
+ * @return {undefined}
1328
+ */
1329
+ additionsClassInit: function() {
1330
+ 'use strict';
1331
+
1332
+ if ( ! tsf.hasInput )
1333
+ return;
1334
+
1335
+ var counterType = tsf.counterType,
1336
+ cache = tsf.settingsChanged;
1337
+
1338
+ if ( 1 == counterType ) {
1339
+ tsf.additionsClass = 'tsf-counter-one';
1340
+ tsf.counterType = 1;
1341
+ } else if ( 2 == counterType ) {
1342
+ tsf.additionsClass = 'tsf-counter-two';
1343
+ tsf.counterType = 2;
1344
+ } else if ( 3 == counterType ) {
1345
+ tsf.additionsClass = 'tsf-counter-three';
1346
+ tsf.counterType = 3;
1347
+ } else {
1348
+ tsf.additionsClass = 'tsf-counter-zero';
1349
+ tsf.counterType = 0;
1350
+ }
1351
+
1352
+ tsf.updateCounters();
1353
+
1354
+ // Reset settingsChanged to previous value.
1355
+ tsf.settingsChanged = cache;
1356
+ },
1357
+
1358
+ /**
1359
+ * Update counters.
1360
+ *
1361
+ * @since 2.6.0
1362
+ *
1363
+ * @function
1364
+ * @return {undefined}
1365
+ */
1366
+ updateCounters: function() {
1367
+ 'use strict';
1368
+
1369
+ tsf.triggerTitleOnLoad();
1370
+ tsf.triggerDescriptionOnLoad();
1371
+ },
1372
+
1373
+ /**
1374
+ * Returns counter name.
1375
+ *
1376
+ * @since 2.6.0
1377
+ *
1378
+ * @function
1379
+ * @param {String} type
1380
+ * @return {String} name Human readable counter name.
1381
+ */
1382
+ getCounterName: function( type ) {
1383
+ 'use strict';
1384
+
1385
+ return tsf.i18n[ type ];
1386
+ },
1387
+
1388
+ /**
1389
+ * Returns converted HTML title/description separator.
1390
+ *
1391
+ * @since 2.7.0
1392
+ *
1393
+ * @function
1394
+ * @param {String} type
1395
+ * @return {String} sep The converted separator.
1396
+ */
1397
+ getSep: function( type ) {
1398
+ 'use strict';
1399
+
1400
+ if ( 'title' === type ) {
1401
+ var sep = tsf.titleSeparator;
1402
+ } else {
1403
+ var sep = tsf.descriptionSeparator;
1404
+ }
1405
+
1406
+ if ( 'pipe' === sep || '|' === sep ) {
1407
+ sep = ( "|" );
1408
+ } else if ( 'dash' === sep || '-' === sep ) {
1409
+ sep = ( "-" );
1410
+ } else if ( sep.charCodeAt(0) < 123 ) {
1411
+ //* Checked for UTF-8 conversion.
1412
+ // Create a memory div to store the html in, convert to text to append in $placeholder
1413
+ sep = jQuery.trim( sep );
1414
+ if ( '&' === sep.charAt(0) && ';' === sep.slice(-1) )
1415
+ sep = sep.substr(1).slice(0, -1);
1416
+
1417
+ sep = jQuery( '<div/>' ).html( "&" + sep + ";" ).text();
1418
+ }
1419
+
1420
+ return sep;
1421
+ },
1422
+
1423
+ /**
1424
+ * Opens the image editor on request.
1425
+ *
1426
+ * @since 2.8.0
1427
+ *
1428
+ * @function
1429
+ * @param {!jQuery.Event} event jQuery event
1430
+ * @return {(undefined|null)}
1431
+ */
1432
+ openImageEditor: function( event ) {
1433
+ 'use strict';
1434
+
1435
+ if ( jQuery( event.target ).prop( 'disabled' ) || 'undefined' === typeof wp.media ) {
1436
+ //* TODO error handling?
1437
+ event.preventDefault();
1438
+ event.stopPropagation();
1439
+ return;
1440
+ }
1441
+
1442
+ var $target = jQuery( event.target ),
1443
+ inputID = $target.data( 'inputid' ),
1444
+ frame;
1445
+
1446
+ if ( frame ) {
1447
+ frame.open();
1448
+ return;
1449
+ }
1450
+
1451
+ event.preventDefault();
1452
+ event.stopPropagation();
1453
+
1454
+ //* Init extend cropper.
1455
+ tsf.extendCropper();
1456
+
1457
+ frame = wp.media( {
1458
+ button : {
1459
+ 'text' : tsf.other[ inputID ]['frame_button'],
1460
+ 'close' : false,
1461
+ },
1462
+ states: [
1463
+ new wp.media.controller.Library( {
1464
+ 'title' : tsf.other[ inputID ]['frame_title'],
1465
+ 'library' : wp.media.query({ 'type' : 'image' }),
1466
+ 'multiple' : false,
1467
+ 'date' : false,
1468
+ 'priority' : 20,
1469
+ 'suggestedWidth' : 1200,
1470
+ 'suggestedHeight' : 630
1471
+ } ),
1472
+ new tsf.cropper( {
1473
+ 'imgSelectOptions' : tsf.calculateImageSelectOptions
1474
+ } ),
1475
+ ],
1476
+ } );
1477
+
1478
+ frame.on( 'select', function() {
1479
+ frame.setState( 'cropper' );
1480
+ } );
1481
+
1482
+ frame.on( 'cropped', function( croppedImage ) {
1483
+
1484
+ var url = croppedImage.url,
1485
+ attachmentId = croppedImage.id,
1486
+ w = croppedImage.width,
1487
+ h = croppedImage.height;
1488
+
1489
+ // Send the attachment id to our hidden input. URL to explicit output.
1490
+ jQuery( '#' + inputID + '-url' ).val( url );
1491
+ jQuery( '#' + inputID + '-id' ).val( attachmentId );
1492
+ } );
1493
+
1494
+ frame.on( 'skippedcrop', function( selection ) {
1495
+
1496
+ var url = selection.get( 'url' ),
1497
+ attachmentId = selection.get( 'id' ),
1498
+ w = selection.get( 'width' ),
1499
+ h = selection.get( 'height' );
1500
+
1501
+ // Send the attachment id to our hidden input. URL to explicit output.
1502
+ jQuery( '#' + inputID + '-url' ).val( url );
1503
+ jQuery( '#' + inputID + '-id' ).val( attachmentId );
1504
+ } );
1505
+
1506
+ frame.on( 'skippedcrop cropped', function( imageSelection ) {
1507
+ jQuery( '#' + inputID + '-select' ).text( tsf.other[ inputID ]['change'] );
1508
+ jQuery( '#' + inputID + '-url' ).prop( 'readonly', true ).css( 'opacity', 0 ).animate(
1509
+ { 'opacity' : 1 },
1510
+ { 'queue' : true, 'duration' : 1000 },
1511
+ 'swing'
1512
+ );
1513
+
1514
+ tsf.appendRemoveButton( $target, inputID, true );
1515
+ tsf.registerChange();
1516
+ } );
1517
+
1518
+ frame.open();
1519
+ },
1520
+
1521
+ /**
1522
+ * Removes the image editor image on request.
1523
+ *
1524
+ * @since 2.8.0
1525
+ *
1526
+ * @function
1527
+ * @param {!jQuery.event.target} target jQuery event.target
1528
+ * @param {string} inputID The input ID.
1529
+ * @return {(undefined|null)}
1530
+ */
1531
+ appendRemoveButton: function( target, inputID, animate ) {
1532
+
1533
+ if ( target && inputID ) {
1534
+ if ( ! jQuery( '#' + inputID + '-remove' ).length ) {
1535
+ target.after(
1536
+ '<a href="javascript:void(0)" id="'
1537
+ + inputID + '-remove" class="tsf-remove-social-image button button-small" data-inputid="'
1538
+ + inputID +
1539
+ '" title="' + tsf.other[ inputID ]['remove_title'] + '">' + tsf.other[ inputID ]['remove'] + '</a>'
1540
+ );
1541
+ if ( animate ) {
1542
+ jQuery( '#' + inputID + '-remove' ).css( 'opacity', 0 ).animate(
1543
+ { 'opacity' : 1 },
1544
+ { 'queue' : true, 'duration' : 1000 },
1545
+ 'swing'
1546
+ );
1547
+ }
1548
+ }
1549
+ }
1550
+
1551
+ //* Reset cache.
1552
+ tsf.resetImageEditorActions();
1553
+ },
1554
+
1555
+ /**
1556
+ * Removes the image editor image on request.
1557
+ *
1558
+ * @since 2.8.0
1559
+ *
1560
+ * @function
1561
+ * @param {!jQuery.Event} event jQuery event
1562
+ * @return {(undefined|null)}
1563
+ */
1564
+ removeEditorImage: function( event ) {
1565
+
1566
+ var $target = jQuery( event.target ),
1567
+ inputID = $target.data( 'inputid' );
1568
+
1569
+ if ( jQuery( '#' + inputID + '-select' ).prop( 'disabled' ) )
1570
+ return;
1571
+
1572
+ jQuery( '#' + inputID + '-select' ).addClass( 'disabled' ).prop( 'disabled', true );
1573
+
1574
+ //* target.event.id === '#' + inputID + '-remove'.
1575
+ jQuery( '#' + inputID + '-remove' ).addClass( 'disabled' ).prop( 'disabled', true ).fadeOut( 500, function() {
1576
+ jQuery( this ).remove();
1577
+ jQuery( '#' + inputID + '-select' ).text( tsf.other[ inputID ]['select'] ).removeClass( 'disabled' ).removeProp( 'disabled' );
1578
+ } );
1579
+
1580
+ jQuery( '#' + inputID + '-url' ).val( '' ).removeProp( 'readonly' ).css( 'opacity', 0 ).animate(
1581
+ { 'opacity' : 1 },
1582
+ { 'queue' : true, 'duration' : 500 },
1583
+ 'swing'
1584
+ );
1585
+
1586
+ jQuery( '#' + inputID + '-id' ).val( '' );
1587
+
1588
+ tsf.registerChange();
1589
+ },
1590
+
1591
+ /**
1592
+ * Builds constructor for media cropper.
1593
+ *
1594
+ * @since 2.8.0
1595
+ *
1596
+ * @function
1597
+ * @return {(undefined|null)}
1598
+ */
1599
+ extendCropper: function() {
1600
+ 'use strict';
1601
+
1602
+ if ( 'undefined' !== typeof tsf.cropper.control )
1603
+ return;
1604
+
1605
+ /**
1606
+ * tsf.extendCropper => wp.media.controller.TSFCropper
1607
+ *
1608
+ * A state for cropping an image.
1609
+ *
1610
+ * @class
1611
+ * @augments wp.media.controller.Cropper
1612
+ * @augments wp.media.controller.State
1613
+ * @augments Backbone.Model
1614
+ */
1615
+ var Controller = wp.media.controller,
1616
+ TSFCropper;
1617
+
1618
+ TSFCropper = Controller.Cropper.extend( {
1619
+ doCrop: function( attachment ) {
1620
+ var cropDetails = attachment.get( 'cropDetails' ),
1621
+ control = tsf.cropper.control;
1622
+
1623
+ // Use crop measurements when flexible in both directions.
1624
+ if ( control.params.flex_width && control.params.flex_height ) {
1625
+ // Square
1626
+ if ( cropDetails.width === cropDetails.height ) {
1627
+ if ( cropDetails.width > control.params.flex_width ) {
1628
+ cropDetails.dst_width = cropDetails.dst_height = control.params.flex_width;
1629
+ }
1630
+ // Landscape/Portrait
1631
+ } else {
1632
+ // Resize to flex width/height
1633
+ if ( cropDetails.width > control.params.flex_width || cropDetails.height > control.params.flex_height ) {
1634
+ // Landscape
1635
+ if ( cropDetails.width > cropDetails.height ) {
1636
+ var _ratio = cropDetails.width / control.params.flex_width;
1637
+
1638
+ cropDetails.dst_width = control.params.flex_width;
1639
+ cropDetails.dst_height = Math.round( cropDetails.height / _ratio );
1640
+ // Portrait
1641
+ } else {
1642
+ var _ratio = cropDetails.height / control.params.flex_height;
1643
+
1644
+ cropDetails.dst_height = control.params.flex_height;
1645
+ cropDetails.dst_width = Math.round( cropDetails.width / _ratio );
1646
+ }
1647
+ }
1648
+ }
1649
+ }
1650
+
1651
+ // Nothing happened. Set destination to 0 and let PHP figure it out.
1652
+ if ( 'undefined' === typeof cropDetails.dst_width ) {
1653
+ cropDetails.dst_width = 0;
1654
+ cropDetails.dst_height = 0;
1655
+ }
1656
+
1657
+ return wp.ajax.post( 'crop-image', {
1658
+ 'nonce' : attachment.get( 'nonces' ).edit,
1659
+ 'id' : attachment.get( 'id' ),
1660
+ 'context' : 'tsf-image',
1661
+ 'cropDetails' : cropDetails
1662
+ } );
1663
+ }
1664
+ } );
1665
+
1666
+ TSFCropper.prototype.control = {};
1667
+ TSFCropper.control = {
1668
+ 'params' : {
1669
+ 'flex_width' : 1500,
1670
+ 'flex_height' : 1500,
1671
+ 'width' : 1200,
1672
+ 'height' : 630,
1673
+ },
1674
+ };
1675
+
1676
+ tsf.cropper = TSFCropper;
1677
+
1678
+ return;
1679
+ },
1680
+
1681
+ /**
1682
+ * Returns a set of options, computed from the attached image data and
1683
+ * control-specific data, to be fed to the imgAreaSelect plugin in
1684
+ * wp.media.view.Cropper.
1685
+ *
1686
+ * @function
1687
+ * @param {wp.media.model.Attachment} attachment
1688
+ * @param {wp.media.controller.Cropper} controller
1689
+ * @return {Object} imgSelectOptions
1690
+ */
1691
+ calculateImageSelectOptions: function( attachment, controller ) {
1692
+ 'use strict';
1693
+
1694
+ var control = tsf.cropper.control,
1695
+ flexWidth = !! parseInt( control.params.flex_width, 10 ),
1696
+ flexHeight = !! parseInt( control.params.flex_height, 10 ),
1697
+ realWidth = attachment.get( 'width' ),
1698
+ realHeight = attachment.get( 'height' ),
1699
+ xInit = parseInt( control.params.width, 10 ),
1700
+ yInit = parseInt( control.params.height, 10 ),
1701
+ ratio = xInit / yInit,
1702
+ xImg = xInit,
1703
+ yImg = yInit,
1704
+ x1, y1, imgSelectOptions;
1705
+
1706
+ controller.set( 'control', control.params );
1707
+ controller.set( 'canSkipCrop', ! tsf.mustBeCropped( control.params.flex_width, control.params.flex_height, realWidth, realHeight ) );
1708
+
1709
+ if ( realWidth / realHeight > ratio ) {
1710
+ yInit = realHeight;
1711
+ xInit = yInit * ratio;
1712
+ } else {
1713
+ xInit = realWidth;
1714
+ yInit = xInit / ratio;
1715
+ }
1716
+
1717
+ x1 = ( realWidth - xInit ) / 2;
1718
+ y1 = ( realHeight - yInit ) / 2;
1719
+
1720
+ imgSelectOptions = {
1721
+ 'handles' : true,
1722
+ 'keys' : true,
1723
+ 'instance' : true,
1724
+ 'persistent' : true,
1725
+ 'imageWidth' : realWidth,
1726
+ 'imageHeight' : realHeight,
1727
+ 'minWidth' : xImg > xInit ? xInit : xImg,
1728
+ 'minHeight' : yImg > yInit ? yInit : yImg,
1729
+ 'x1' : x1,
1730
+ 'y1' : y1,
1731
+ 'x2' : xInit + x1,
1732
+ 'y2' : yInit + y1
1733
+ };
1734
+
1735
+ if ( false === flexHeight && false === flexWidth ) {
1736
+ imgSelectOptions.aspectRatio = xInit + ':' + yInit;
1737
+ }
1738
+
1739
+ // @TODO Convert set img min-width/height to output ratio.
1740
+ // i.e. 200x2000 will become x = 1500/2000*200 = 150px, which is too small.
1741
+
1742
+ if ( true === flexHeight ) {
1743
+ imgSelectOptions.minHeight = 200;
1744
+ imgSelectOptions.maxWidth = realWidth;
1745
+ }
1746
+
1747
+ if ( true === flexWidth ) {
1748
+ imgSelectOptions.minWidth = 200;
1749
+ imgSelectOptions.maxHeight = realHeight;
1750
+ }
1751
+
1752
+ return imgSelectOptions;
1753
+ },
1754
+
1755
+ /**
1756
+ * Return whether the image must be cropped, based on required dimensions.
1757
+ * Disregards flexWidth/Height.
1758
+ *
1759
+ * @function
1760
+ * @param {Number} dstW
1761
+ * @param {Number} dstH
1762
+ * @param {Number} imgW
1763
+ * @param {Number} imgH
1764
+ * @return {Boolean}
1765
+ */
1766
+ mustBeCropped: function( dstW, dstH, imgW, imgH ) {
1767
+ 'use strict';
1768
+
1769
+ if ( imgW <= dstW && imgH <= dstH ) {
1770
+ return false;
1771
+ }
1772
+
1773
+ return true;
1774
+ },
1775
+
1776
+ /**
1777
+ * Resets jQuery image editor cache.
1778
+ *
1779
+ * @since 2.8.0
1780
+ *
1781
+ * @function
1782
+ * @return {(undefined|null)}
1783
+ */
1784
+ resetImageEditorActions: function() {
1785
+ jQuery( '.tsf-remove-social-image' ).on( 'click', tsf.removeEditorImage );
1786
+ },
1787
+
1788
+ /**
1789
+ * Sets up jQuery image editor cache.
1790
+ *
1791
+ * @since 2.8.0
1792
+ *
1793
+ * @function
1794
+ * @return {(undefined|null)}
1795
+ */
1796
+ setupImageEditorActions: function() {
1797
+ jQuery( '.tsf-set-social-image' ).on( 'click', tsf.openImageEditor );
1798
+ jQuery( '.tsf-remove-social-image' ).on( 'click', tsf.removeEditorImage );
1799
+ },
1800
+
1801
+ /**
1802
+ * Checks if input is filled in by image editor.
1803
+ *
1804
+ * @since 2.8.0
1805
+ *
1806
+ * @function
1807
+ * @return {(undefined|null)}
1808
+ */
1809
+ checkImageEditorInput: function() {
1810
+
1811
+ var $buttons = jQuery( '.tsf-set-social-image' );
1812
+
1813
+ if ( $buttons.length ) {
1814
+ var inputID = '',
1815
+ $valID = '';
1816
+
1817
+ jQuery.each( $buttons, function( index, value ) {
1818
+ inputID = jQuery( value ).data( 'inputid' );
1819
+ $valID = jQuery( '#' + inputID + '-id' );
1820
+
1821
+ if ( $valID.length && $valID.val() > 0 ) {
1822
+ jQuery( '#' + inputID + '-url' ).prop( 'readonly', true );
1823
+ tsf.appendRemoveButton( jQuery( value ), inputID, false );
1824
+ }
1825
+
1826
+ if ( jQuery( '#' + inputID + '-url' ).val() ) {
1827
+ jQuery( '#' + inputID + '-select' ).text( tsf.other[ inputID ]['change'] );
1828
+ }
1829
+ } );
1830
+ }
1831
+ },
1832
+
1833
+ /**
1834
+ * Enables wpColorPicker on input.
1835
+ *
1836
+ * @since 2.8.0
1837
+ *
1838
+ * @function
1839
+ * @return {(undefined|null)}
1840
+ */
1841
+ setColorOnload: function() {
1842
+
1843
+ var $selectors = jQuery( '.tsf-color-picker' );
1844
+
1845
+ if ( $selectors.length ) {
1846
+ jQuery.each( $selectors, function( index, value ) {
1847
+ var $input = jQuery( value ),
1848
+ currentColor = '',
1849
+ defaultColor = $input.data( 'tsf-default-color' );
1850
+
1851
+ $input.wpColorPicker( {
1852
+ 'defaultColor' : defaultColor,
1853
+ 'width' : 238,
1854
+ 'change' : function( event, ui ) {
1855
+ currentColor = $input.wpColorPicker( 'color' );
1856
+
1857
+ if ( '' === currentColor )
1858
+ currentColor = defaultColor;
1859
+
1860
+ $input.val( currentColor );
1861
+
1862
+ tsf.registerChange();
1863
+ },
1864
+ 'clear' : function() {
1865
+ //* Privately marked WP class... open ticket?
1866
+ $input.parent().siblings( '.wp-color-result' ).css( 'backgroundColor', defaultColor );
1867
+
1868
+ tsf.registerChange();
1869
+ },
1870
+ 'palettes' : false,
1871
+ } );
1872
+ } );
1873
+ }
1874
+ },
1875
+
1876
+ /**
1877
+ * Sets up object parameters.
1878
+ *
1879
+ * @since 2.8.0
1880
+ *
1881
+ * @function
1882
+ * @return {(undefined|null)}
1883
+ */
1884
+ setupVars: function() {
1885
+
1886
+ //The current title separator.
1887
+ tsf.titleSeparator = tsf.params['titleSeparator'];
1888
+
1889
+ //The current description separator.
1890
+ tsf.descriptionSeparator = tsf.params['descriptionSeparator'];
1891
+
1892
+ // The current title tagline.
1893
+ tsf.titleTagline = tsf.states['titleTagline'];
1894
+
1895
+ // Mixed string and int (i10n is string, JS is int).
1896
+ tsf.counterType = tsf.states['counterType'];
1897
+
1898
+ // Determines if the current page has input boxes for The SEO Framework.
1899
+ tsf.hasInput = tsf.states['hasInput'];
1900
+ },
1901
+
1902
+ /**
1903
+ * Initialises all aspects of the scripts.
1904
+ *
1905
+ * Generally ordered with stuff that inserts new elements into the DOM first,
1906
+ * then stuff that triggers an event on existing DOM elements when ready,
1907
+ * followed by stuff that triggers an event only on user interaction. This
1908
+ * keeps any screen jumping from occuring later on.
1909
+ *
1910
+ * @since 2.2.4
1911
+ * @since 2.7.0 jQuery object is now passed.
1912
+ *
1913
+ * @function
1914
+ * @param {!jQuery} jQ jQuery
1915
+ * @return {undefined}
1916
+ */
1917
+ ready: function( jQ ) {
1918
+ 'use strict';
1919
+
1920
+ // Set up object parameters.
1921
+ tsf.setupVars();
1922
+
1923
+ // Move the page updates notices below the tsf-top-wrap.
1924
+ jQ( 'div.updated, div.error, div.notice-warning' ).insertAfter( 'div.tsf-top-wrap' );
1925
+
1926
+ // Set up additions classes.
1927
+ jQ( document.body ).ready( tsf.additionsClassInit );
1928
+
1929
+ // Toggle Dynamic Title Placeholder onLoad, also toggles doing it right colors.
1930
+ jQ( document.body ).ready( tsf.dynamicPlaceholderOnLoad );
1931
+
1932
+ // Check if the Title Tagline or Description Additions should be removed when page is loaded.
1933
+ jQ( document.body ).ready( tsf.taglineToggleOnload );
1934
+
1935
+ // Initialize the status bar hover balloon.
1936
+ jQ( document.body ).ready( tsf.statusBarHover );
1937
+
1938
+ // Initialize status bar removal hover for touch screens.
1939
+ jQ( document.body ).on( 'click touchstart MSPointerDown', tsf.removeDesc );
1940
+
1941
+ // Initialize image uploader button cache.
1942
+ jQ( document.body ).ready( tsf.setupImageEditorActions );
1943
+
1944
+ // Determine image editor button input states.
1945
+ jQ( document.body ).ready( tsf.checkImageEditorInput );
1946
+
1947
+ // Color picker
1948
+ jQ( document.body ).ready( tsf.setColorOnload );
1949
+
1950
+ // #== End Before Change listener
1951
+
1952
+ // Initialise form field changing flag.
1953
+ jQ( document.body ).ready( tsf.attachUnsavedChangesListener );
1954
+
1955
+ // Deregister changes.
1956
+ jQ( document.body ).ready( tsf.onLoadUnregisterChange );
1957
+
1958
+ // #== Start After Change listener
1959
+
1960
+ // Bind character counters.
1961
+ tsf.docDescriptions().on( 'input', tsf.updateCharacterCountDescription );
1962
+ tsf.docTitles().on( 'input', tsf.updateCharacterCountTitle );
1963
+
1964
+ // Allow the title separator to be changed dynamically.
1965
+ jQ( '#tsf-title-separator input' ).on( 'click', tsf.separatorSwitchTitle );
1966
+ // Allow description separator to be changed dynamically.
1967
+ jQ( '#tsf-description-separator input' ).on( 'click', tsf.separatorSwitchDesc );
1968
+
1969
+ // Bind reset confirmation.
1970
+ jQ( '.tsf-js-confirm-reset' ).on( 'click', tsf.confirmedReset );
1971
+
1972
+ // Toggle Tabs in the SEO settings page.
1973
+ jQ( '.tsf-tab' ).on( 'click', tsf.tabToggle );
1974
+
1975
+ // Toggle Title tagline aditions removal.
1976
+ jQ( '#tsf-title-tagline-toggle :input' ).on( 'click', tsf.taglineToggleTitle );
1977
+ // Toggle Title additions location.
1978
+ jQ( '#tsf-title-location input' ).on( 'click', tsf.titleLocationToggle );
1979
+ // Toggle Title prefixes display.
1980
+ jQ( '#title-prefixes-toggle :input' ).on( 'click', tsf.titlePrefixToggle );
1981
+
1982
+ // Toggle Description additions removal.
1983
+ jQ( '#tsf-description-onblogname-toggle :input' ).on( 'click', tsf.taglineToggleDesc );
1984
+ jQ( '#tsf-description-additions-toggle :input' ).on( 'click', tsf.additionsToggleDesc );
1985
+
1986
+ // Change Home Page Title Example prop on input changes.
1987
+ jQ( '#autodescription-site-settings\\[homepage_title\\]' ).on( 'input', tsf.titleProp );
1988
+ jQ( '#tsf-home-title-location :input, #tsf-title-tagline-toggle :input, #tsf-title-separator input' ).on( 'click', tsf.taglinePropTrigger );
1989
+ jQ( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).on( 'input', tsf.taglineProp );
1990
+
1991
+ // Make sure the titleProp is correctly rendered when revealed after being hidden.
1992
+ jQ( '#homepage-tab-general' ).on( 'change', tsf.taglinePropTrigger );
1993
+
1994
+ // Change Global Title Example prop on input changes.
1995
+ jQ( '#autodescription-site-settings\\[title_rem_additions\\]' ).on( 'click', tsf.titleToggle );
1996
+
1997
+ // Dynamic Placeholder, acts on keydown for a11y, although more cpu intensive. Acts on keyup for perfect output.
1998
+ tsf.docTitles().on( 'input', tsf.dynamicPlaceholder );
1999
+
2000
+ // Move click on dynamic additions to focus input behind.
2001
+ jQ( '#tsf-title-placeholder' ).on( 'click', tsf.selectTitleInput );
2002
+
2003
+ // Dismiss notices.
2004
+ jQ( '.tsf-dismiss' ).on( 'click', tsf.dismissNotice );
2005
+
2006
+ // AJAX counter
2007
+ jQ( '.tsf-counter' ).on( 'click', tsf.counterUpdate );
2008
+
2009
+ }
2010
+ };
2011
+ jQuery( tsf.ready );
lib/js/tsf.min.js ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ window.tsf={nonce:tsfL10n.nonce,i18n:tsfL10n.i18n,states:tsfL10n.states,params:tsfL10n.params,other:tsfL10n.other,i:!1,j:!1,m:"",u:"",a:0,f:!1,b:"",cropper:{},c:function(){return jQuery("#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]")},v:function(){return jQuery("#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]")},confirm:function(a){return confirm(a)},I:function(a){var b=
2
+ jQuery(a.target),d=b.val().length;a=jQuery("#"+tsf.A(a.target.id)+"_chars");var c,e="";0===d&&(d=b.prop("placeholder").length);100>d||175<=d?(b="tsf-count-bad",c=tsf.g("bad")):137>d||155<d&&175>d?(b="tsf-count-okay",c=tsf.g("okay")):(b="tsf-count-good",c=tsf.g("good"));tsf.b&&(b+=" "+tsf.b);tsf.a&&1!=tsf.a?2==tsf.a?e=c:3==tsf.a&&(e=d.toString()+" - "+c):e=d.toString();a.html(e).removeClass().addClass(b)},l:function(a){var b=jQuery(a.target),d=tsf.params.titleAdditions.length,c=tsf.params.blogDescription.length,
3
+ e=tsf.params.siteTitle.length,f=b.val().length,m=b.prop("placeholder").length,h=jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").val(),g=3;a=jQuery("#"+tsf.A(a.target.id)+"_chars");var k=0,b=tsf.b,l=tsf.a,n="";tsf.j||(g=d=0);0===f&&(0!==e?f=e:k=m);0!==f&&(0!==d&&"undefined"!==typeof h&&(d=h.length,d=0!==d?d:c),k=0===d?f:f+g+d);25>k||75<=k?(c="tsf-count-bad",f=tsf.g("bad")):42>k||55<k&&75>k?(c="tsf-count-okay",f=tsf.g("okay")):(c="tsf-count-good",f=tsf.g("good"));b&&(c+=" "+b);
4
+ l&&1!=l?2==l?n=f:3==l&&(n=k.toString()+" - "+f):n=k.toString();a.html(n).removeClass().addClass(c)},A:function(a){return a?a.replace(/([\[\]\/])/g,"\\$1"):a},aa:function(a){var b=jQuery(".tsf-sep-js");a=jQuery(a.target).val();tsf.m=a;"pipe"===a?b.text(" | "):"dash"===a?b.text(" - "):b.html(" &"+a+"; ")},Z:function(a){var b=jQuery("#autodescription-descsep-js");a=jQuery(a.target).val();"pipe"===a?b.text(" | "):"dash"===a?b.text(" - "):b.html(" &"+a+"; ")},statusBarHover:function(){var a=jQuery(".tsf-seo-bar-inner-wrap").find("a");
5
+ a.on("mouseenter",tsf.fa);a.on("mousemove",tsf.ha);a.on("mouseleave",tsf.ga)},fa:function(a){a=jQuery(a.target);var b=a.data("desc");void 0!==b&&0===a.find("div").length&&(a.append('<div class="tsf-explanation-desc">'+b+"<div></div></div>"),b=a.find("div.tsf-explanation-desc").height()+28,a.find("div.tsf-explanation-desc").css("top",a.position().top-b+"px"))},ha:function(a){var b=jQuery(a.target);a=a.pageX;var d=a-jQuery(".tsf-seo-bar-inner-wrap").offset().left-11,c=b.find(".tsf-explanation-desc"),
6
+ b=c.find("div");if(1>d)b.css("left","0px");else if(void 0!==c.offset()){var e=c.width(),c=c.offset().left+e+11;a>c?b.css("left",e+"px"):b.css("left",d+"px")}},ga:function(a){jQuery(a.target).find("div.tsf-explanation-desc").remove()},W:function(){var a=jQuery(document.body.target),b=jQuery(".tsf-seo-bar-inner-wrap a");a.closest(b).length||b.find("div.tsf-explanation-desc").remove()},ia:function(a){var b=jQuery(a.target).prop("id");a=jQuery(a.target).prop("name");"undefined"!==typeof b&&(b=jQuery("#"+
7
+ b+"-content"),a=jQuery("."+a+"-content"),"undefined"!==typeof b&&(a.removeClass("tsf-active-tab-content"),b.addClass("tsf-active-tab-content")))},la:function(a){a=jQuery(a.target);var b=jQuery(".tsf-custom-blogname-js");a.is(":checked")?(b.css("display","inline"),tsf.j=!0):(b.css("display","none"),tsf.j=!1);tsf.c().trigger("keyup",tsf.l)},ja:function(a){a=jQuery(a.target);var b=jQuery("#tsf-on-blogname-js");a.is(":checked")?b.css("display","inline"):b.css("display","none")},ma:function(a){a=jQuery(a.target).val();
8
+ var b=jQuery(".tsf-title-additions-example-left"),d=jQuery(".tsf-title-additions-example-right");"right"===a?(b.css("display","none"),d.css("display","inline")):(b.css("display","inline"),d.css("display","none"))},na:function(a){a=jQuery(a.target);var b=jQuery(".tsf-title-prefix-example");a.is(":checked")?b.css("display","none"):b.css("display","inline")},J:function(a){a=jQuery(a.target);var b=jQuery("#tsf-description-additions-js");a.is(":checked")?b.css("display","inline"):b.css("display","none")},
9
+ ka:function(){if(tsf.f){var a=jQuery("#tsf-title-tagline-toggle :input"),b=jQuery(".tsf-custom-blogname-js"),d=jQuery("#tsf-description-additions-toggle :input"),c=jQuery("#tsf-description-additions-js"),e=jQuery("#tsf-description-onblogname-toggle :input"),f=jQuery("#tsf-on-blogname-js"),m=jQuery("#tsf-title-additions-toggle :input"),h=jQuery(".tsf-title-additions-js");a.is(":checked")?b.css("display","inline"):b.css("display","none");d.is(":checked")?c.css("display","inline"):c.css("display","none");
10
+ e.is(":checked")?f.css("display","inline"):f.css("display","none");m.is(":checked")?h.css("display","none"):h.css("display","inline")}},oa:function(a){a=jQuery(a.target).val();var b=jQuery(".tsf-custom-title-js");0===a.length?b.text(tsf.i18n.siteTitle):b.text(a)},F:function(a){a=jQuery(a.target).val();var b=jQuery(".tsf-custom-tagline-js"),d=jQuery("#autodescription-site-settings\\[homepage_title\\]"),c=jQuery("#tsf-home-title-location input:checked").val(),e=jQuery("#autodescription-site-settings\\[homepage_tagline\\]"),
11
+ f=tsf.params.siteTitle,m=f,h=tsf.params.blogDescription,g=tsf.B("title");e.is(":checked")&&(0!==a.length&&(h=a),m=0!==c.length&&"left"===c?f+" "+g+" "+h:h+" "+g+" "+f);b.text(h);d.prop("placeholder",m);tsf.c().trigger("input",tsf.l)},G:function(){jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").trigger("input",tsf.F)},pa:function(){var a=jQuery(event.target),b=jQuery(".tsf-title-additions-js");a.is(":checked")?b.css("display","none"):b.css("display","inline")},K:function(){tsf.f&&
12
+ (jQuery(".tsf-metaboxes :input, #tsf-inpost-box .inside :input").not(".tsf-tab :input").change(function(){tsf.h()}),jQuery(".tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea").not(".tsf-nav-tab-wrapper :input").on("input",function(){tsf.h()}),window.onbeforeunload=function(){if(tsf.i)return tsf.i18n.saveAlert},jQuery('.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete').click(function(){window.onbeforeunload=
13
+ null}))},h:function(){tsf.i=!0},M:function(){return confirm(tsf.i18n.confirmReset)},w:function(a){var b=tsf.params.titleAdditions.length,d=jQuery("#tsf-title-placeholder");if(0===b)return a=jQuery(a.target),a.css("text-indent","initial"),d.empty();var b=!1,c=jQuery("#tsf-home-title-location input:checked").val(),e=tsf.states.isRTL;if("undefined"!==typeof c&&0!==c.length)"1"===e?"right"===c&&(b=!0):"left"===c&&(b=!0);else{var c=tsf.params.titleLocation,f=tsf.j;tsf.states.isHome?f&&(e?"right"===c&&
14
+ (b=!0):"left"===c&&(b=!0)):e?"left"===c&&(b=!0):"right"===c&&(b=!0)}c=jQuery("#tsf-title-tagline-toggle :input");if("undefined"!==typeof c&&0<c.length&&!c.is(":checked"))a=jQuery(a.target),a.css("text-indent","initial"),d.css("display","none");else{a=jQuery(a.target);var m=a.val(),h=jQuery("#tsf-title-offset"),g,k=(a.outerHeight(!0)-a.height())/2,l=(a.outerWidth()-a.width())/2,c=(a.outerWidth(!0)-a.width())/2;g=jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").val();var f="left",
15
+ n=tsf.B("title");e&&(f="right");"undefined"!==typeof g&&0===g.length&&(g=tsf.params.blogDescription);b?(e=n+" "+tsf.params.titleAdditions,"undefined"!==typeof g&&0<g.length&&(e=n+" "+g),a.css("text-indent","initial")):(e=tsf.params.titleAdditions+" "+n,"undefined"!==typeof g&&0<g.length&&(e=g+" "+n));h.text(m);h.css({fontFamily:a.css("fontFamily"),fontWeight:a.css("fontWeight"),letterSpacing:a.css("letterSpacing"),fontSize:a.css("fontSize")});g=h.width();g=a.width()-l-g;0>g&&(g=0);d.css({display:a.css("display"),
16
+ lineHeight:a.css("lineHeight"),paddingTop:k+"px",paddingBottom:k+"px",fontFamily:a.css("fontFamily"),fontWeight:a.css("fontWeight"),fontSize:a.css("fontSize"),letterSpacing:a.css("letterSpacing"),maxWidth:g+"px"});"undefined"===typeof m||1>m.length?(b||a.css("text-indent","initial"),d.empty()):(d.text(e),a.outerWidth()>c&&(b?d.css(f,l+c+h.width()+"px"):(b=l+d.width(),0>b&&(b=0),d.css(f,c+"px"),a.css("text-indent",b+"px"))))}},Y:function(){var a=tsf.c();a.focus();if(a.setSelectionRange){var b=2*a.val().length;
17
+ a.setSelectionRange(b,b)}else a.val(a.val()).focus()},R:function(){if(tsf.f){var a=tsf.c();"undefined"!==typeof a.val()&&(0<a.val().length?a.trigger("input",tsf.w):a.trigger("input",tsf.l))}},qa:function(){tsf.f&&tsf.v().trigger("input",tsf.I)},ra:function(){tsf.f&&tsf.c().trigger("input",tsf.l)},U:function(){tsf.i=