The SEO Framework - Version 3.0.2

Version Description

  • Esteem =

Release date:

  • November 23rd, 2017

Fixed:

  • A fatal error no longer occurs on the wpForo Forum plugin pages.
Download this release

Release Info

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

Code changes from version 2.9.4 to 3.0.2

Files changed (80) hide show
  1. autodescription.php +8 -8
  2. inc/classes/admin-init.class.php +174 -74
  3. inc/classes/admin-pages.class.php +166 -103
  4. inc/classes/cache.class.php +104 -18
  5. inc/classes/compat.class.php +15 -22
  6. inc/classes/core.class.php +54 -17
  7. inc/classes/debug.class.php +22 -29
  8. inc/classes/deprecated.class.php +2012 -1290
  9. inc/classes/detect.class.php +8 -3
  10. inc/classes/doing-it-right.class.php +73 -61
  11. inc/classes/feed.class.php +184 -187
  12. inc/classes/generate-description.class.php +23 -13
  13. inc/classes/generate-image.class.php +17 -1
  14. inc/classes/generate-ldjson.class.php +214 -226
  15. inc/classes/generate-title.class.php +18 -12
  16. inc/classes/generate-url.class.php +467 -548
  17. inc/classes/generate.class.php +38 -35
  18. inc/classes/index.php +48 -0
  19. inc/classes/init.class.php +70 -66
  20. inc/classes/inpost.class.php +51 -108
  21. inc/classes/load.class.php +10 -18
  22. inc/classes/metaboxes.class.php +12 -0
  23. inc/classes/post-data.class.php +217 -25
  24. inc/classes/profile.class.php +138 -0
  25. inc/classes/query.class.php +49 -16
  26. inc/classes/render.class.php +151 -128
  27. inc/classes/sanitize.class.php +76 -34
  28. inc/classes/site-options.class.php +16 -129
  29. inc/classes/sitemaps.class.php +54 -50
  30. inc/classes/term-data.class.php +92 -33
  31. inc/classes/user-data.class.php +235 -0
  32. inc/compat/php-mbstring.php +11 -11
  33. inc/compat/plugin-bbpress.php +3 -12
  34. inc/compat/plugin-buddypress.php +22 -0
  35. inc/compat/plugin-donncha-dm.php +0 -69
  36. inc/compat/plugin-polylang.php +0 -187
  37. inc/compat/plugin-qtranslatex.php +0 -100
  38. inc/compat/plugin-wpforo.php +3 -23
  39. inc/compat/plugin-wpml.php +1 -183
  40. inc/compat/plugin-wpmudev-dm.php +0 -134
  41. inc/compat/theme-genesis.php +10 -25
  42. inc/compat/wp-460.php +58 -0
  43. inc/functions/optionsapi.php +1 -2
  44. inc/functions/plugin-activation.php +73 -0
  45. inc/functions/plugin-deactivation.php +71 -0
  46. inc/functions/plugin-test-server.php +1 -1
  47. inc/functions/upgrade.php +72 -8
  48. inc/views/admin/index.php +6 -0
  49. inc/views/admin/seo-settings-columns.php +35 -0
  50. inc/views/admin/seo-settings-wrap.php +48 -0
  51. inc/views/inpost/seo-settings-singular.php +34 -47
  52. inc/views/inpost/seo-settings-tt.php +69 -23
  53. inc/views/inpost/wrap.php +100 -0
  54. inc/views/metaboxes/description-metabox.php +15 -7
  55. inc/views/metaboxes/feed-metabox.php +2 -2
  56. inc/views/metaboxes/general-metabox.php +119 -14
  57. inc/views/metaboxes/homepage-metabox.php +40 -31
  58. inc/views/metaboxes/robots-metabox.php +56 -54
  59. inc/views/metaboxes/schema-metabox.php +90 -94
  60. inc/views/metaboxes/sitemaps-metabox.php +27 -67
  61. inc/views/metaboxes/social-metabox.php +66 -67
  62. inc/views/metaboxes/title-metabox.php +10 -8
  63. inc/views/metaboxes/webmaster-metabox.php +29 -9
  64. inc/views/profile/author.php +26 -0
  65. inc/views/profile/index.php +6 -0
  66. inc/views/templates/index.php +6 -0
  67. inc/views/templates/inpost/index.php +6 -0
  68. inc/views/templates/inpost/primary-term-selector.php +29 -0
  69. language/autodescription.pot +675 -607
  70. lib/css/tsf-rtl.css +360 -106
  71. lib/css/tsf-rtl.min.css +1 -1
  72. lib/css/tsf.css +358 -109
  73. lib/css/tsf.min.css +1 -1
  74. lib/js/{tsf.externs.js → externs/tsf.externs.js} +0 -0
  75. lib/js/{tsf.externs.protected.js → externs/tsf.externs.protected.js} +1 -1
  76. lib/js/tsf.js +2145 -1272
  77. lib/js/tsf.min.js +1 -38
  78. load.php +4 -96
  79. patch/index.php +0 -10
  80. readme.txt +101 -146
autodescription.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: The SEO Framework
4
  * Plugin URI: https://theseoframework.com/
5
  * Description: An automated, advanced, accessible, unbranded and extremely fast SEO solution for any WordPress website.
6
- * Version: 2.9.4
7
  * Author: Sybre Waaijer
8
  * Author URI: https://theseoframework.com/
9
  * License: GPLv3
@@ -33,7 +33,7 @@ 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' );
@@ -51,7 +51,7 @@ defined( 'ABSPATH' ) or die;
51
  *
52
  * @since 1.0.0
53
  */
54
- define( 'THE_SEO_FRAMEWORK_VERSION', '2.9.4' );
55
 
56
  /**
57
  * The plugin Database version.
@@ -60,7 +60,7 @@ define( 'THE_SEO_FRAMEWORK_VERSION', '2.9.4' );
60
  *
61
  * @since 2.7.0
62
  */
63
- define( 'THE_SEO_FRAMEWORK_DB_VERSION', '2941' );
64
 
65
  /**
66
  * The plugin options database option_name.
@@ -182,7 +182,7 @@ function the_seo_framework_pre_load() {
182
  function the_seo_framework_test_server() {
183
 
184
  //* Load on init action (manual FTP upload) or after plugin has been upgraded.
185
- require_once( THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'plugin-test-server.php' );
186
 
187
  if ( get_option( 'the_seo_framework_tested_upgrade_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION )
188
  the_seo_framework_load_base_files();
@@ -200,7 +200,7 @@ function the_seo_framework_load_base_files() {
200
  * @since 1.0.0
201
  * @uses THE_SEO_FRAMEWORK_DIR_PATH
202
  */
203
- require_once( THE_SEO_FRAMEWORK_DIR_PATH . 'load.php' );
204
 
205
  /**
206
  * Load deprecated functions.
@@ -209,12 +209,12 @@ function the_seo_framework_load_base_files() {
209
  * @since 2.9.2 No longer called to improve performance.
210
  * @uses THE_SEO_FRAMEWORK_DIR_PATH_FUNCT
211
  */
212
- // require_once( THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'deprecated.php' );
213
 
214
  /**
215
  * Load API files.
216
  * @since 2.1.6
217
  * @uses THE_SEO_FRAMEWORK_DIR_PATH_FUNCT
218
  */
219
- require_once( THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'optionsapi.php' );
220
  }
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: 3.0.2
7
  * Author: Sybre Waaijer
8
  * Author URI: https://theseoframework.com/
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' );
51
  *
52
  * @since 1.0.0
53
  */
54
+ define( 'THE_SEO_FRAMEWORK_VERSION', '3.0.2' );
55
 
56
  /**
57
  * The plugin Database version.
60
  *
61
  * @since 2.7.0
62
  */
63
+ define( 'THE_SEO_FRAMEWORK_DB_VERSION', '3001' );
64
 
65
  /**
66
  * The plugin options database option_name.
182
  function the_seo_framework_test_server() {
183
 
184
  //* Load on init action (manual FTP upload) or after plugin has been upgraded.
185
+ require THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'plugin-test-server.php';
186
 
187
  if ( get_option( 'the_seo_framework_tested_upgrade_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION )
188
  the_seo_framework_load_base_files();
200
  * @since 1.0.0
201
  * @uses THE_SEO_FRAMEWORK_DIR_PATH
202
  */
203
+ require THE_SEO_FRAMEWORK_DIR_PATH . 'load.php';
204
 
205
  /**
206
  * Load deprecated functions.
209
  * @since 2.9.2 No longer called to improve performance.
210
  * @uses THE_SEO_FRAMEWORK_DIR_PATH_FUNCT
211
  */
212
+ // require THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'deprecated.php';
213
 
214
  /**
215
  * Load API files.
216
  * @since 2.1.6
217
  * @uses THE_SEO_FRAMEWORK_DIR_PATH_FUNCT
218
  */
219
+ require THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'optionsapi.php';
220
  }
inc/classes/admin-init.class.php CHANGED
@@ -153,7 +153,6 @@ class Admin_Init extends Init {
153
  * @since 2.5.2.2
154
  */
155
  \add_action( 'admin_footer', array( $this, '_localize_admin_javascript' ) );
156
-
157
  }
158
 
159
  /**
@@ -177,7 +176,6 @@ class Admin_Init extends Init {
177
  \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 );
178
 
179
  $registered = true;
180
-
181
  }
182
 
183
  /**
@@ -199,12 +197,13 @@ class Admin_Init extends Init {
199
  \wp_localize_script( $this->js_name, "{$this->js_name}L10n", $strings );
200
 
201
  $localized = true;
202
-
203
  }
204
 
205
  /**
206
  * Generate Javascript Localization.
207
  *
 
 
208
  * @since 2.6.0
209
  * @staticvar array $strings : The l10n strings.
210
  * @since 2.7.0 Added AJAX nonce: 'autodescription-ajax-nonce'
@@ -218,137 +217,178 @@ class Admin_Init extends Init {
218
  */
219
  protected function get_javascript_l10n() {
220
 
 
221
  $blog_name = $this->get_blogname();
222
  $description = $this->get_blogdescription();
223
- $title = '';
224
  $additions = '';
225
 
226
- $tagline = (bool) $this->get_option( 'homepage_tagline' );
227
  $home_tagline = $this->get_option( 'homepage_title_tagline' );
228
  $title_location = $this->get_option( 'title_location' );
229
  $title_add_additions = $this->add_title_additions();
230
  $counter_type = (int) $this->get_user_option( 0, 'counter_type', 3 );
231
 
232
- //* Enunciate the lenghts of Titles and Descriptions.
233
- $good = \__( 'Good', 'autodescription' );
234
- $okay = \__( 'Okay', 'autodescription' );
235
- $bad = \__( 'Bad', 'autodescription' );
236
- $unknown = \__( 'Unknown', 'autodescription' );
237
-
238
  $title_separator = $this->get_separator( 'title' );
239
  $description_separator = $this->get_separator( 'description' );
240
 
241
  $ishome = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
243
  if ( isset( $this->page_base_file ) && $this->page_base_file ) {
244
  // We're somewhere within default WordPress pages.
245
- $post_id = $this->get_the_real_ID();
246
-
247
- if ( $this->is_static_frontpage( $post_id ) ) {
248
- $title = $blog_name;
249
  $title_location = $this->get_option( 'home_title_location' );
250
  $ishome = true;
251
 
252
- if ( $tagline ) {
253
  $additions = $home_tagline ? $home_tagline : $description;
254
  } else {
255
  $additions = '';
256
  }
257
- } elseif ( $post_id ) {
258
  //* We're on post.php
259
  $generated_doctitle_args = array(
260
- 'term_id' => $post_id,
261
  'notagline' => true,
262
  'get_custom_field' => false,
263
  );
264
 
265
- $title = $this->title( '', '', '', $generated_doctitle_args );
266
 
267
  if ( $title_add_additions ) {
268
  $additions = $blog_name;
269
- $tagline = true;
270
  } else {
271
  $additions = '';
272
- $tagline = false;
273
  }
274
- } elseif ( $this->is_archive() ) {
275
  //* Category or Tag.
276
- if ( isset( $GLOBALS['current_screen']->taxonomy ) ) {
277
-
278
- $term_id = $this->get_admin_term_id();
279
-
280
- if ( $term_id ) {
281
- $generated_doctitle_args = array(
282
- 'term_id' => $term_id,
283
- 'taxonomy' => $GLOBALS['current_screen']->taxonomy,
284
- 'notagline' => true,
285
- 'get_custom_field' => false,
286
- );
287
-
288
- $title = $this->title( '', '', '', $generated_doctitle_args );
289
- $additions = $title_add_additions ? $blog_name : '';
290
- }
291
  }
292
  } else {
293
  //* We're in a special place.
294
  // Can't fetch title.
295
- $title = '';
296
  $additions = $title_add_additions ? $blog_name : '';
297
  }
298
- } else {
299
  // We're on our SEO settings pages.
300
  if ( $this->has_page_on_front() ) {
301
  // Home is a page.
302
- $inpost_title = $this->get_custom_field( '_genesis_title', \get_option( 'page_on_front' ) );
 
303
  } else {
304
  // Home is a blog.
305
  $inpost_title = '';
306
  }
307
- $title = $inpost_title ?: $blog_name;
308
  $additions = $home_tagline ?: $description;
309
  }
310
 
311
- //* @TODO deprecate
312
- $nonce = \wp_create_nonce( 'autodescription-ajax-nonce' );
313
-
314
  $this->set_js_nonces( array(
315
  /**
316
- * Use $this->settings_capability() ?... might conflict with other nonces.
317
  */
318
  // 'manage_options' => \current_user_can( 'manage_options' ) ? \wp_create_nonce( 'tsf-ajax-manage_options' ) : false,
319
  'upload_files' => \current_user_can( 'upload_files' ) ? \wp_create_nonce( 'tsf-ajax-upload_files' ) : false,
320
  'edit_posts' => \current_user_can( 'edit_posts' ) ? \wp_create_nonce( 'tsf-ajax-edit_posts' ) : false,
321
  ) );
322
 
323
- return array(
324
- 'nonce' => $nonce,
 
 
 
 
 
 
 
325
  'nonces' => $this->get_js_nonces(),
326
- 'i18n' => array(
327
- 'saveAlert' => \esc_html__( 'The changes you made will be lost if you navigate away from this page.', 'autodescription' ),
328
- 'confirmReset' => \esc_html__( 'Are you sure you want to reset all SEO settings to their defaults?', 'autodescription' ),
329
- 'good' => \esc_html( $good ),
330
- 'okay' => \esc_html( $okay ),
331
- 'bad' => \esc_html( $bad ),
332
- 'unknown' => \esc_html( $unknown ),
333
- ),
334
  'states' => array(
335
  'isRTL' => (bool) \is_rtl(),
336
  'isHome' => $ishome,
337
- 'hasInput' => $this->is_term_edit() || $this->is_post_edit() || $this->is_seo_settings_page(),
338
  'counterType' => \absint( $counter_type ),
339
- 'titleTagline' => $tagline,
340
- 'isSettingsPage' => $this->is_seo_settings_page(),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  ),
342
  'params' => array(
343
- 'siteTitle' => \esc_html( \wp_kses_decode_entities( $title ) ),
344
- 'titleAdditions' => \esc_html( \wp_kses_decode_entities( $additions ) ),
345
- 'blogDescription' => \esc_html( \wp_kses_decode_entities( $description ) ),
346
- 'titleSeparator' => \esc_html( $title_separator ),
347
- 'descriptionSeparator' => \esc_html( $description_separator ),
348
- 'titleLocation' => \esc_html( $title_location ),
 
 
 
 
349
  ),
350
  'other' => $this->additional_js_l10n( null, array(), true ),
351
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  }
353
 
354
  /**
@@ -448,13 +488,14 @@ class Admin_Init extends Init {
448
  * valid and generated between 12-24 hours ago.
449
  */
450
  public function check_tsf_ajax_referer( $capability ) {
451
- return \check_ajax_referer( 'tsf-ajax-' . $capability, 'nonce' );
452
  }
453
 
454
  /**
455
  * CSS for the AutoDescription Bar
456
  *
457
  * @since 2.1.9
 
458
  *
459
  * @param $hook the current page
460
  */
@@ -475,6 +516,8 @@ class Admin_Init extends Init {
475
 
476
  \wp_enqueue_style( $this->css_name );
477
 
 
 
478
  }
479
 
480
  /**
@@ -496,7 +539,65 @@ class Admin_Init extends Init {
496
  $registered = true;
497
 
498
  \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' );
 
499
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
500
  }
501
 
502
  /**
@@ -505,7 +606,7 @@ class Admin_Init extends Init {
505
  * @since 2.8.0
506
  *
507
  * @param array $removable_query_args
508
- * @return array $removable_query_args The adjusted removable query args.
509
  */
510
  public function add_removable_query_args( $removable_query_args = array() ) {
511
 
@@ -569,7 +670,7 @@ class Admin_Init extends Init {
569
  * Provides an accessible error for when redirecting fails.
570
  *
571
  * @since 2.9.2
572
- * @link https://developer.wordpress.org/reference/functions/wp_redirect/
573
  *
574
  * @param string $target The redirect target location. Should be escaped.
575
  * @return void
@@ -607,6 +708,7 @@ class Admin_Init extends Init {
607
  * @since 2.6.0
608
  * @since 2.9.0 : 1. Changed capability from 'publish_posts' to 'edit_posts'.
609
  * 2. Added json header.
 
610
  * @access private
611
  */
612
  public function wp_ajax_update_counter_type() {
@@ -614,11 +716,12 @@ class Admin_Init extends Init {
614
  if ( $this->is_admin() && $this->doing_ajax() ) :
615
 
616
  $this->check_tsf_ajax_referer( 'edit_posts' );
 
 
 
 
617
  //* If current user isn't allowed to edit posts, don't do anything and kill PHP.
618
  if ( ! \current_user_can( 'edit_posts' ) ) {
619
- //* Remove output buffer.
620
- $this->clean_response_header();
621
-
622
  //* Encode and echo results. Requires JSON decode within JS.
623
  echo json_encode( array( 'type' => 'failure', 'value' => '' ) );
624
  exit;
@@ -642,9 +745,6 @@ class Admin_Init extends Init {
642
  'value' => $value,
643
  );
644
 
645
- //* Remove output buffer.
646
- $this->clean_response_header();
647
-
648
  //* Encode and echo results. Requires JSON decode within JS.
649
  echo json_encode( $results );
650
 
@@ -663,6 +763,7 @@ class Admin_Init extends Init {
663
  * 4. It no longer accepts a default context.
664
  *
665
  * @since 2.9.0
 
666
  * @access private
667
  */
668
  public function wp_ajax_crop_image() {
@@ -720,7 +821,6 @@ class Admin_Init extends Init {
720
  * Filters the cropped image attachment metadata.
721
  *
722
  * @since 4.3.0 WordPress Core
723
- *
724
  * @see wp_generate_attachment_metadata()
725
  *
726
  * @param array $metadata Attachment metadata.
153
  * @since 2.5.2.2
154
  */
155
  \add_action( 'admin_footer', array( $this, '_localize_admin_javascript' ) );
 
156
  }
157
 
158
  /**
176
  \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 );
177
 
178
  $registered = true;
 
179
  }
180
 
181
  /**
197
  \wp_localize_script( $this->js_name, "{$this->js_name}L10n", $strings );
198
 
199
  $localized = true;
 
200
  }
201
 
202
  /**
203
  * Generate Javascript Localization.
204
  *
205
+ * @TODO rewrite, it's slow and a mess.
206
+ *
207
  * @since 2.6.0
208
  * @staticvar array $strings : The l10n strings.
209
  * @since 2.7.0 Added AJAX nonce: 'autodescription-ajax-nonce'
217
  */
218
  protected function get_javascript_l10n() {
219
 
220
+ $id = $this->get_the_real_ID();
221
  $blog_name = $this->get_blogname();
222
  $description = $this->get_blogdescription();
223
+ $object_title = '';
224
  $additions = '';
225
 
226
+ $use_additions = (bool) $this->get_option( 'homepage_tagline' );
227
  $home_tagline = $this->get_option( 'homepage_title_tagline' );
228
  $title_location = $this->get_option( 'title_location' );
229
  $title_add_additions = $this->add_title_additions();
230
  $counter_type = (int) $this->get_user_option( 0, 'counter_type', 3 );
231
 
 
 
 
 
 
 
232
  $title_separator = $this->get_separator( 'title' );
233
  $description_separator = $this->get_separator( 'description' );
234
 
235
  $ishome = false;
236
+ $is_settings_page = $this->is_seo_settings_page();
237
+ $is_post_edit = $this->is_post_edit();
238
+ $is_term_edit = $this->is_term_edit();
239
+ $has_input = $is_settings_page || $is_post_edit || $is_term_edit;
240
+
241
+ $post_type = $is_post_edit ? \get_post_type( $id ) : false;
242
+ $_taxonomies = $post_type ? $this->get_hierarchical_taxonomies_as( 'objects', $post_type ) : array();
243
+
244
+ $taxonomies = array();
245
+
246
+ foreach ( $_taxonomies as $_t ) {
247
+ $_i18n_name = strtolower( $_t->labels->singular_name );
248
+ $taxonomies[ $_t->name ] = array(
249
+ 'name' => $_t->name,
250
+ 'i18n' => array(
251
+ /* translators: %s = term name */
252
+ 'makePrimary' => sprintf( \esc_html__( 'Make primary %s', 'autodescription' ), $_i18n_name ),
253
+ /* translators: %s = term name */
254
+ 'primary' => sprintf( \esc_html__( 'Primary %s', 'autodescription' ), $_i18n_name ),
255
+ ),
256
+ 'primary' => $this->get_primary_term_id( $id, $_t->name ) ?: 0,
257
+ );
258
+ }
259
 
260
  if ( isset( $this->page_base_file ) && $this->page_base_file ) {
261
  // We're somewhere within default WordPress pages.
262
+ if ( $this->is_static_frontpage( $id ) ) {
263
+ $object_title = $this->get_option( 'homepage_title' ) ?: $blog_name;
 
 
264
  $title_location = $this->get_option( 'home_title_location' );
265
  $ishome = true;
266
 
267
+ if ( $use_additions ) {
268
  $additions = $home_tagline ? $home_tagline : $description;
269
  } else {
270
  $additions = '';
271
  }
272
+ } elseif ( $is_post_edit ) {
273
  //* We're on post.php
274
  $generated_doctitle_args = array(
275
+ 'term_id' => $id,
276
  'notagline' => true,
277
  'get_custom_field' => false,
278
  );
279
 
280
+ $object_title = $this->title( '', '', '', $generated_doctitle_args );
281
 
282
  if ( $title_add_additions ) {
283
  $additions = $blog_name;
284
+ $use_additions = true;
285
  } else {
286
  $additions = '';
287
+ $use_additions = false;
288
  }
289
+ } elseif ( $is_term_edit ) {
290
  //* Category or Tag.
291
+ if ( isset( $GLOBALS['current_screen']->taxonomy ) && $id ) {
292
+ $object_title = $this->single_term_title( '', false, $this->fetch_the_term( $id ) );
293
+ $additions = $title_add_additions ? $blog_name : '';
 
 
 
 
 
 
 
 
 
 
 
 
294
  }
295
  } else {
296
  //* We're in a special place.
297
  // Can't fetch title.
298
+ $object_title = '';
299
  $additions = $title_add_additions ? $blog_name : '';
300
  }
301
+ } elseif ( $is_settings_page ) {
302
  // We're on our SEO settings pages.
303
  if ( $this->has_page_on_front() ) {
304
  // Home is a page.
305
+ $id = \get_option( 'page_on_front' );
306
+ $inpost_title = $this->get_custom_field( '_genesis_title', $id );
307
  } else {
308
  // Home is a blog.
309
  $inpost_title = '';
310
  }
311
+ $object_title = $inpost_title ?: $blog_name;
312
  $additions = $home_tagline ?: $description;
313
  }
314
 
 
 
 
315
  $this->set_js_nonces( array(
316
  /**
317
+ * Use $this->get_settings_capability() ?... might conflict with other nonces.
318
  */
319
  // 'manage_options' => \current_user_can( 'manage_options' ) ? \wp_create_nonce( 'tsf-ajax-manage_options' ) : false,
320
  'upload_files' => \current_user_can( 'upload_files' ) ? \wp_create_nonce( 'tsf-ajax-upload_files' ) : false,
321
  'edit_posts' => \current_user_can( 'edit_posts' ) ? \wp_create_nonce( 'tsf-ajax-edit_posts' ) : false,
322
  ) );
323
 
324
+ $term_name = '';
325
+ $use_term_prefix = false;
326
+ if ( $is_term_edit ) {
327
+ $_term = $this->fetch_the_term( $id );
328
+ $term_name = $this->get_the_term_name( $_term, true, false );
329
+ $use_term_prefix = $this->use_archive_prefix( $_term );
330
+ }
331
+
332
+ $l10n = array(
333
  'nonces' => $this->get_js_nonces(),
 
 
 
 
 
 
 
 
334
  'states' => array(
335
  'isRTL' => (bool) \is_rtl(),
336
  'isHome' => $ishome,
337
+ 'hasInput' => $has_input,
338
  'counterType' => \absint( $counter_type ),
339
+ 'useTagline' => $use_additions,
340
+ 'useTermPrefix' => $use_term_prefix,
341
+ 'isSettingsPage' => $is_settings_page,
342
+ 'isPostEdit' => $is_post_edit,
343
+ 'isTermEdit' => $is_term_edit,
344
+ 'postType' => $post_type,
345
+ 'taxonomies' => $taxonomies,
346
+ 'isPrivate' => $has_input && $id && $this->is_private( $id ),
347
+ 'isPasswordProtected' => $has_input && $id && $this->is_password_protected( $id ),
348
+ 'debug' => $this->script_debug,
349
+ ),
350
+ 'i18n' => array(
351
+ 'saveAlert' => \__( 'The changes you made will be lost if you navigate away from this page.', 'autodescription' ),
352
+ 'confirmReset' => \__( 'Are you sure you want to reset all SEO settings to their defaults?', 'autodescription' ),
353
+ 'good' => \__( 'Good', 'autodescription' ),
354
+ 'okay' => \__( 'Okay', 'autodescription' ),
355
+ 'bad' => \__( 'Bad', 'autodescription' ),
356
+ 'unknown' => \__( 'Unknown', 'autodescription' ),
357
+ 'privateTitle' => $has_input && $id ? \__( 'Private:', 'autodescription' ) : '',
358
+ 'protectedTitle' => $has_input && $id ? \__( 'Protected:', 'autodescription' ) : '',
359
+ /* translators: Pixel counter. 1: width, 2: guideline */
360
+ 'pixelsUsed' => $has_input ? \__( '%1$d out of %2$d pixels are used.', 'autodescription' ) : '',
361
  ),
362
  'params' => array(
363
+ 'objectTitle' => $object_title,
364
+ 'titleAdditions' => $additions,
365
+ 'blogDescription' => $description,
366
+ 'termName' => $term_name,
367
+ 'untitledTitle' => $this->untitled(),
368
+ 'titleSeparator' => $title_separator,
369
+ 'descriptionSeparator' => $description_separator,
370
+ 'titleLocation' => $title_location,
371
+ 'titlePixelGuideline' => 600,
372
+ 'descPixelGuideline' => $is_post_edit ? ( $this->is_page() ? 920 : 820 ) : 920,
373
  ),
374
  'other' => $this->additional_js_l10n( null, array(), true ),
375
  );
376
+
377
+ $decode = array( 'i18n', 'params' );
378
+ $flags = ENT_COMPAT;
379
+ foreach ( $decode as $key ) {
380
+ foreach ( $l10n[ $key ] as $k => $v ) {
381
+ $l10n[ $key ][ $k ] = \esc_js( \html_entity_decode( $v, $flags, 'UTF-8' ) );
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Applies filters 'the_seo_framework_js_l10n'
387
+ *
388
+ * @since 3.0.0
389
+ * @param array $l10n
390
+ */
391
+ return (array) \apply_filters( 'the_seo_framework_js_l10n', $l10n );
392
  }
393
 
394
  /**
488
  * valid and generated between 12-24 hours ago.
489
  */
490
  public function check_tsf_ajax_referer( $capability ) {
491
+ return \check_ajax_referer( 'tsf-ajax-' . $capability, 'nonce', true );
492
  }
493
 
494
  /**
495
  * CSS for the AutoDescription Bar
496
  *
497
  * @since 2.1.9
498
+ * @since 3.0.0 Now also outputs colors.
499
  *
500
  * @param $hook the current page
501
  */
516
 
517
  \wp_enqueue_style( $this->css_name );
518
 
519
+ $color_css = $this->get_admin_color_css()
520
+ and \wp_add_inline_style( $this->css_name, $color_css );
521
  }
522
 
523
  /**
539
  $registered = true;
540
 
541
  \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' );
542
+ }
543
 
544
+ /**
545
+ * Outputs additional CSS based on admin theme colors.
546
+ *
547
+ * @since 3.0.0
548
+ *
549
+ * @return string Additional admin CSS.
550
+ */
551
+ protected function get_admin_color_css() {
552
+
553
+ //* @see wp_style_loader_src()
554
+ $scheme = \get_user_option( 'admin_color' ) ?: 'fresh';
555
+
556
+ $_colors = $GLOBALS['_wp_admin_css_colors'];
557
+
558
+ if ( ! isset( $_colors[ $scheme ]->colors ) || ! is_array( $_colors[ $scheme ]->colors ) )
559
+ return '';
560
+
561
+ $_scheme = $_colors[ $scheme ]->colors;
562
+
563
+ $bg = $_scheme[0];
564
+ $bg_accent = $_scheme[1];
565
+ $color = $_scheme[2];
566
+ $color_accent = $_scheme[3];
567
+
568
+ $bg_alt_font = '#' . $this->get_relative_fontcolor( $bg );
569
+ // $bg_accent_alt_font = '#' . $this->get_relative_fontcolor( $bg_accent );
570
+
571
+ $css = array(
572
+ '.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked + .tsf-flex-nav-tab-label' => array(
573
+ "box-shadow:0 -2px 0 0 $color_accent inset",
574
+ ),
575
+ '.tsf-tooltip-text-wrap' => array(
576
+ "background-color:$bg_accent",
577
+ "color:$bg_alt_font",
578
+ ),
579
+ '.tsf-tooltip-arrow:after' => array(
580
+ "border-top-color:$bg_accent",
581
+ ),
582
+ '.tsf-tooltip-down .tsf-tooltip-arrow:after' => array(
583
+ "border-bottom-color:$bg_accent",
584
+ ),
585
+ );
586
+
587
+ /**
588
+ * Applies filters 'the_seo_framework_admin_color_css'
589
+ *
590
+ * @since 3.0.0
591
+ * @param array $css The current styles.
592
+ * @param string $scheme The current admin scheme.
593
+ */
594
+ $css = (array) \apply_filters( 'the_seo_framework_admin_color_css', $css, $scheme );
595
+
596
+ $out = '';
597
+ foreach ( $css as $attr => $style )
598
+ $out .= $attr . '{' . implode( ';', $style ) . '}';
599
+
600
+ return $out;
601
  }
602
 
603
  /**
606
  * @since 2.8.0
607
  *
608
  * @param array $removable_query_args
609
+ * @return array The adjusted removable query args.
610
  */
611
  public function add_removable_query_args( $removable_query_args = array() ) {
612
 
670
  * Provides an accessible error for when redirecting fails.
671
  *
672
  * @since 2.9.2
673
+ * @see https://developer.wordpress.org/reference/functions/wp_redirect/
674
  *
675
  * @param string $target The redirect target location. Should be escaped.
676
  * @return void
708
  * @since 2.6.0
709
  * @since 2.9.0 : 1. Changed capability from 'publish_posts' to 'edit_posts'.
710
  * 2. Added json header.
711
+ * @securitycheck 3.0.0 OK.
712
  * @access private
713
  */
714
  public function wp_ajax_update_counter_type() {
716
  if ( $this->is_admin() && $this->doing_ajax() ) :
717
 
718
  $this->check_tsf_ajax_referer( 'edit_posts' );
719
+
720
+ //* Remove output buffer.
721
+ $this->clean_response_header();
722
+
723
  //* If current user isn't allowed to edit posts, don't do anything and kill PHP.
724
  if ( ! \current_user_can( 'edit_posts' ) ) {
 
 
 
725
  //* Encode and echo results. Requires JSON decode within JS.
726
  echo json_encode( array( 'type' => 'failure', 'value' => '' ) );
727
  exit;
745
  'value' => $value,
746
  );
747
 
 
 
 
748
  //* Encode and echo results. Requires JSON decode within JS.
749
  echo json_encode( $results );
750
 
763
  * 4. It no longer accepts a default context.
764
  *
765
  * @since 2.9.0
766
+ * @securitycheck 3.0.0 OK.
767
  * @access private
768
  */
769
  public function wp_ajax_crop_image() {
821
  * Filters the cropped image attachment metadata.
822
  *
823
  * @since 4.3.0 WordPress Core
 
824
  * @see wp_generate_attachment_metadata()
825
  *
826
  * @param array $metadata Attachment metadata.
inc/classes/admin-pages.class.php CHANGED
@@ -108,9 +108,9 @@ class Admin_Pages extends Inpost {
108
  $menu = array(
109
  'page_title' => \esc_html__( 'SEO Settings', 'autodescription' ),
110
  'menu_title' => \esc_html__( 'SEO', 'autodescription' ),
111
- 'capability' => $this->settings_capability(),
112
  'menu_slug' => $this->seo_settings_page_slug,
113
- 'callback' => array( $this, 'admin' ),
114
  'icon' => 'dashicons-search',
115
  'position' => '90.9001',
116
  );
@@ -160,50 +160,36 @@ class Admin_Pages extends Inpost {
160
  $this->handle_update_post();
161
 
162
  //* Output metaboxes.
163
- \add_action( $this->seo_settings_page_hook . '_settings_page_boxes', array( $this, 'do_metaboxes' ) );
164
- \add_action( 'load-' . $this->seo_settings_page_hook, array( $this, 'metaboxes' ) );
165
  }
166
 
167
  /**
168
- * Echo out the do_metaboxes() and wrapping markup.
169
  *
170
- * @since 2.2.2
 
171
  */
172
- public function do_metaboxes() {
173
- ?>
174
- <div class="metabox-holder columns-2">
175
- <div class="postbox-container-1">
176
- <?php
177
- \do_action( 'the_seo_framework_before_siteadmin_metaboxes', $this->seo_settings_page_hook );
178
-
179
- \do_meta_boxes( $this->seo_settings_page_hook, 'main', null );
180
-
181
- if ( isset( $GLOBALS['wp_meta_boxes'][ $this->seo_settings_page_hook ]['main_extra'] ) )
182
- \do_meta_boxes( $this->seo_settings_page_hook, 'main_extra', null );
183
-
184
- \do_action( 'the_seo_framework_after_siteadmin_metaboxes', $this->seo_settings_page_hook );
185
- ?>
186
- </div>
187
- <div class="postbox-container-2">
188
- <?php
189
- \do_action( 'the_seo_framework_before_siteadmin_metaboxes_side', $this->seo_settings_page_hook );
190
-
191
- /**
192
- * @TODO fill this in
193
- * @priority low 2.9.0
194
- */
195
-
196
- \do_action( 'the_seo_framework_after_siteadmin_metaboxes_side', $this->seo_settings_page_hook );
197
- ?>
198
- </div>
199
- </div>
200
- <?php
201
  }
202
 
203
  /**
204
- * Register meta boxes on the Site SEO Settings page.
205
  *
206
- * @since 2.2.2
 
 
 
 
 
 
 
 
 
 
207
  *
208
  * @see $this->general_metabox() Callback for General Settings box.
209
  * @see $this->title_metabox() Callback for Title Settings box.
@@ -216,7 +202,7 @@ class Admin_Pages extends Inpost {
216
  * @see $this->sitemaps_metabox() Callback for Sitemap Settings box.
217
  * @see $this->feed_metabox() Callback for Feed Settings box.
218
  */
219
- public function metaboxes() {
220
 
221
  /**
222
  * Various metabox filters.
@@ -347,63 +333,13 @@ class Admin_Pages extends Inpost {
347
  );
348
  }
349
 
350
- /**
351
- * Use this as the settings admin callback to create an admin page with sortable metaboxes.
352
- * Create a 'settings_boxes' method to add metaboxes.
353
- *
354
- * @since 2.2.2
355
- * @todo deprecate (method name is arbitrary) and convert to view.
356
- */
357
- public function admin() {
358
-
359
- ?>
360
- <div class="wrap tsf-metaboxes">
361
- <form method="post" action="options.php">
362
-
363
- <?php \wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
364
- <?php \wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
365
- <?php \settings_fields( $this->settings_field ); ?>
366
-
367
- <div class="tsf-top-wrap">
368
- <h1><?php echo \esc_html( \get_admin_page_title() ); ?></h1>
369
- <p class="tsf-top-buttons">
370
- <?php
371
- \submit_button( $this->page_defaults['save_button_text'], 'primary', 'submit', false, array( 'id' => '' ) );
372
- \submit_button( $this->page_defaults['reset_button_text'], 'secondary tsf-js-confirm-reset', $this->get_field_name( 'tsf-settings-reset' ), false, array( 'id' => '' ) );
373
- ?>
374
- </p>
375
- </div>
376
-
377
- <?php \do_action( "{$this->seo_settings_page_hook}_settings_page_boxes", $this->seo_settings_page_hook ); ?>
378
-
379
- <div class="tsf-bottom-buttons">
380
- <?php
381
- \submit_button( $this->page_defaults['save_button_text'], 'primary', 'submit', false, array( 'id' => '' ) );
382
- \submit_button( $this->page_defaults['reset_button_text'], 'secondary tsf-js-confirm-reset', $this->get_field_name( 'tsf-settings-reset' ), false, array( 'id' => '' ) );
383
- ?>
384
- </div>
385
- </form>
386
- </div>
387
- <?php // Add postbox listeners ?>
388
- <script type="text/javascript">
389
- //<![CDATA[
390
- jQuery(document).ready( function($) {
391
- // close postboxes that should be closed
392
- $('.if-js-closed').removeClass('if-js-closed').addClass('closed');
393
- // postboxes setup
394
- postboxes.add_postbox_toggles('<?php echo \esc_js( $this->seo_settings_page_hook ); ?>');
395
- });
396
- //]]>
397
- </script>
398
- <?php
399
-
400
- }
401
-
402
  /**
403
  * Display notices on the save or reset of settings.
404
  *
405
  * @since 2.2.2
 
406
  * @todo convert the "get" into secure "error_notice" option. See TSF Extension Manager.
 
407
  *
408
  * @return void
409
  */
@@ -519,7 +455,7 @@ class Admin_Pages extends Inpost {
519
  *
520
  * @param string $input The input to wrap. Should already be escaped.
521
  * @param boolean $echo Whether to escape echo or just return.
522
- * @return Wrapped $input.
523
  */
524
  public function wrap_fields( $input = '', $echo = false ) {
525
 
@@ -544,7 +480,7 @@ class Admin_Pages extends Inpost {
544
  * @param string $label The checkbox description label.
545
  * @param string $description Addition description to place beneath the checkbox.
546
  * @param bool $escape Whether to escape the label and description.
547
- * @return HTML checkbox output.
548
  */
549
  public function make_checkbox( $field_id = '', $label = '', $description = '', $escape = true ) {
550
 
@@ -586,7 +522,7 @@ class Admin_Pages extends Inpost {
586
  * @param string $description Addition description to place beneath the checkbox.
587
  * @param string $placeholder The text field placeholder.
588
  * @param bool $escape Whether to escape the label and description.
589
- * @return HTML text field output.
590
  */
591
  public function make_textfield( $field_id = '', $label = '', $description = '', $placeholder = '', $escape = true ) {
592
 
@@ -620,20 +556,30 @@ class Admin_Pages extends Inpost {
620
  * Return a wrapped question mark.
621
  *
622
  * @since 2.6.0
 
623
  *
624
  * @param string $description The descriptive on-hover title.
625
  * @param string $link The non-escaped link.
626
  * @param bool $echo Whether to echo or return.
627
- * @return HTML checkbox output if $echo is false.
628
  */
629
  public function make_info( $description = '', $link = '', $echo = true ) {
630
 
631
  if ( $link ) {
632
- $output = '<a href="' . \esc_url( $link, array( 'http', 'https' ) ) . '" target="_blank" title="' . \esc_attr( $description ) . '">[?]</a>';
 
 
 
 
633
  } else {
634
- $output = '<span title="' . \esc_attr( $description ) . '">[?]</span>';
 
 
 
635
  }
636
 
 
 
637
  if ( $echo ) {
638
  //* Already escaped.
639
  echo $output;
@@ -831,7 +777,6 @@ class Admin_Pages extends Inpost {
831
  * Also registers additional i18n strings for JS.
832
  *
833
  * @since 2.8.0
834
- * @todo optimize? Sanitation and translations are duplicated -> microseconds...
835
  *
836
  * @param string $input_id Required. The HTML input id to pass URL into.
837
  * @return string The image uploader button.
@@ -841,11 +786,20 @@ class Admin_Pages extends Inpost {
841
  if ( ! $input_id )
842
  return '';
843
 
844
- $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>',
845
- \esc_url( \get_upload_iframe_src( 'image', $this->get_the_real_ID() ) ),
846
- \esc_attr_x( 'Select social image', 'Button hover', 'autodescription' ),
847
- \esc_attr( $input_id ),
848
- \esc_html__( 'Select Image', 'autodescription' )
 
 
 
 
 
 
 
 
 
849
  );
850
 
851
  $button_labels = array(
@@ -859,8 +813,117 @@ class Admin_Pages extends Inpost {
859
  );
860
 
861
  //* Already escaped. Turn off escaping.
862
- $this->additional_js_l10n( \esc_attr( $input_id ), $button_labels, false, false );
863
 
864
  return $content;
865
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
866
  }
108
  $menu = array(
109
  'page_title' => \esc_html__( 'SEO Settings', 'autodescription' ),
110
  'menu_title' => \esc_html__( 'SEO', 'autodescription' ),
111
+ 'capability' => $this->get_settings_capability(),
112
  'menu_slug' => $this->seo_settings_page_slug,
113
+ 'callback' => array( $this, '_output_seo_settings_wrap' ),
114
  'icon' => 'dashicons-search',
115
  'position' => '90.9001',
116
  );
160
  $this->handle_update_post();
161
 
162
  //* Output metaboxes.
163
+ \add_action( $this->seo_settings_page_hook . '_settings_page_boxes', array( $this, '_output_seo_settings_columns' ) );
164
+ \add_action( 'load-' . $this->seo_settings_page_hook, array( $this, '_register_seo_settings_metaboxes' ) );
165
  }
166
 
167
  /**
168
+ * Outputs SEO Settings page wrap.
169
  *
170
+ * @since 3.0.0
171
+ * @access private
172
  */
173
+ public function _output_seo_settings_wrap() {
174
+ \do_action( 'the_seo_framework_pre_seo_settings' );
175
+ $this->get_view( 'admin/seo-settings-wrap', get_defined_vars() );
176
+ \do_action( 'the_seo_framework_pro_seo_settings' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  }
178
 
179
  /**
180
+ * Outputs SEO Settings columns.
181
  *
182
+ * @since 3.0.0
183
+ * @access private
184
+ */
185
+ public function _output_seo_settings_columns() {
186
+ $this->get_view( 'admin/seo-settings-columns', get_defined_vars() );
187
+ }
188
+
189
+ /**
190
+ * Registers meta boxes on the Site SEO Settings page.
191
+ *
192
+ * @since 3.0.0
193
  *
194
  * @see $this->general_metabox() Callback for General Settings box.
195
  * @see $this->title_metabox() Callback for Title Settings box.
202
  * @see $this->sitemaps_metabox() Callback for Sitemap Settings box.
203
  * @see $this->feed_metabox() Callback for Feed Settings box.
204
  */
205
+ public function _register_seo_settings_metaboxes() {
206
 
207
  /**
208
  * Various metabox filters.
333
  );
334
  }
335
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  /**
337
  * Display notices on the save or reset of settings.
338
  *
339
  * @since 2.2.2
340
+ * @securitycheck 3.0.0 OK. NOTE: Users can however MANUALLY trigger these on the SEO settings page.
341
  * @todo convert the "get" into secure "error_notice" option. See TSF Extension Manager.
342
+ * @todo convert $this->page_defaults to inline texts. It's now uselessly rendering.
343
  *
344
  * @return void
345
  */
455
  *
456
  * @param string $input The input to wrap. Should already be escaped.
457
  * @param boolean $echo Whether to escape echo or just return.
458
+ * @return string|void Wrapped $input.
459
  */
460
  public function wrap_fields( $input = '', $echo = false ) {
461
 
480
  * @param string $label The checkbox description label.
481
  * @param string $description Addition description to place beneath the checkbox.
482
  * @param bool $escape Whether to escape the label and description.
483
+ * @return string HTML checkbox output.
484
  */
485
  public function make_checkbox( $field_id = '', $label = '', $description = '', $escape = true ) {
486
 
522
  * @param string $description Addition description to place beneath the checkbox.
523
  * @param string $placeholder The text field placeholder.
524
  * @param bool $escape Whether to escape the label and description.
525
+ * @return string HTML text field output.
526
  */
527
  public function make_textfield( $field_id = '', $label = '', $description = '', $placeholder = '', $escape = true ) {
528
 
556
  * Return a wrapped question mark.
557
  *
558
  * @since 2.6.0
559
+ * @since 3.0.0 Links are now no longer followed, referred or bound to opener.
560
  *
561
  * @param string $description The descriptive on-hover title.
562
  * @param string $link The non-escaped link.
563
  * @param bool $echo Whether to echo or return.
564
+ * @return string HTML checkbox output if $echo is false.
565
  */
566
  public function make_info( $description = '', $link = '', $echo = true ) {
567
 
568
  if ( $link ) {
569
+ $output = sprintf(
570
+ '<a href="%1$s" class="tsf-tooltip-item" target="_blank" rel="nofollow noreferrer noopener" title="%2$s" data-desc="%2$s">[?]</a>',
571
+ \esc_url( $link, array( 'http', 'https' ) ),
572
+ \esc_attr( $description )
573
+ );
574
  } else {
575
+ $output = sprintf(
576
+ '<span class="tsf-tooltip-item" title="%1$s" data-desc="%1$s">[?]</span>',
577
+ \esc_attr( $description )
578
+ );
579
  }
580
 
581
+ $output = sprintf( '<span class="tsf-tooltip-wrap">%s</span>', $output );
582
+
583
  if ( $echo ) {
584
  //* Already escaped.
585
  echo $output;
777
  * Also registers additional i18n strings for JS.
778
  *
779
  * @since 2.8.0
 
780
  *
781
  * @param string $input_id Required. The HTML input id to pass URL into.
782
  * @return string The image uploader button.
786
  if ( ! $input_id )
787
  return '';
788
 
789
+ $s_input_id = \esc_attr( $input_id );
790
+
791
+ $content = vsprintf(
792
+ '<a href="%1$s" class="tsf-set-social-image button button-primary button-small" title="%2$s" id="%3$s-select"
793
+ data-inputid="%3$s" data-width="%4$s" data-height="%5$s" data-flex="%6$d">%7$s</a>',
794
+ array(
795
+ \esc_url( \get_upload_iframe_src( 'image', $this->get_the_real_ID() ) ),
796
+ \esc_attr_x( 'Select social image', 'Button hover', 'autodescription' ),
797
+ $s_input_id,
798
+ '1200',
799
+ '630',
800
+ true,
801
+ \esc_html__( 'Select Image', 'autodescription' ),
802
+ )
803
  );
804
 
805
  $button_labels = array(
813
  );
814
 
815
  //* Already escaped. Turn off escaping.
816
+ $this->additional_js_l10n( $s_input_id, $button_labels, false, false );
817
 
818
  return $content;
819
  }
820
+
821
+ /**
822
+ * Returns logo uploader form buttons.
823
+ * Also registers additional i18n strings for JS.
824
+ *
825
+ * @since 3.0.0
826
+ *
827
+ * @param string $input_id Required. The HTML input id to pass URL into.
828
+ * @return string The image uploader button.
829
+ */
830
+ public function get_logo_uploader_form( $input_id ) {
831
+
832
+ if ( ! $input_id )
833
+ return '';
834
+
835
+ $s_input_id = \esc_attr( $input_id );
836
+
837
+ $content = vsprintf(
838
+ '<a href="%1$s" class="tsf-set-social-image button button-primary button-small" title="%2$s" id="%3$s-select"
839
+ data-inputid="%3$s" data-width="%4$s" data-height="%5$s" data-flex="%6$d">%7$s</a>',
840
+ array(
841
+ \esc_url( \get_upload_iframe_src( 'image', $this->get_the_real_ID() ) ),
842
+ '',
843
+ $s_input_id,
844
+ '512',
845
+ '512',
846
+ false,
847
+ \esc_html__( 'Select Logo', 'autodescription' ),
848
+ )
849
+ );
850
+
851
+ $button_labels = array(
852
+ 'select' => \esc_attr__( 'Select Logo', 'autodescription' ),
853
+ 'select_title' => '',
854
+ 'change' => \esc_attr__( 'Change Logo', 'autodescription' ),
855
+ 'remove' => \esc_attr__( 'Remove Logo', 'autodescription' ),
856
+ 'remove_title' => \esc_attr__( 'Unset selected logo', 'autodescription' ),
857
+ 'frame_title' => \esc_attr_x( 'Select Logo', 'Frame title', 'autodescription' ),
858
+ 'frame_button' => \esc_attr__( 'Use this image', 'autodescription' ),
859
+ );
860
+
861
+ //* Already escaped. Turn off escaping.
862
+ $this->additional_js_l10n( $s_input_id, $button_labels, false, false );
863
+
864
+ return $content;
865
+ }
866
+
867
+ /**
868
+ * Outputs floating title HTML for JavaScript.
869
+ *
870
+ * @since 3.0.0
871
+ */
872
+ public function output_floating_title_elements() {
873
+ ?>
874
+ <span id="tsf-title-offset" class="hide-if-no-js"></span>
875
+ <span id="tsf-title-placeholder" class="hide-if-no-js"></span>
876
+ <span id="tsf-title-placeholder-prefix" class="hide-if-no-js"></span>
877
+ <?php
878
+ }
879
+
880
+ /**
881
+ * Outputs character counter wrap for both JavaScript and no-Javascript.
882
+ *
883
+ * @since 3.0.0
884
+ *
885
+ * @param string $for The input ID it's for.
886
+ * @param string $initial The initial value for no-JS.
887
+ * @param bool $display Whether to display the counter.
888
+ */
889
+ public function output_character_counter_wrap( $for, $initial = 0, $display = true ) {
890
+ printf(
891
+ '<div class="tsf-counter-wrap" %s><span class="description tsf-counter">%s</span><span class="hide-if-no-js tsf-ajax"></span></div>',
892
+ $display ? '' : 'style="display:none;"',
893
+ sprintf(
894
+ /* translators: %s = number */
895
+ \esc_html__( 'Characters Used: %s', 'autodescription' ),
896
+ sprintf(
897
+ '<span id="%s_chars">%s</span>',
898
+ \esc_attr( $for ),
899
+ (int) mb_strlen( $initial )
900
+ )
901
+ )
902
+ );
903
+ }
904
+
905
+ /**
906
+ * Outputs pixel counter wrap for javascript.
907
+ *
908
+ * @since 3.0.0
909
+ *
910
+ * @param string $for The input ID it's for.
911
+ * @param string $type Whether it's a 'title' or 'description' counter.
912
+ * @param bool $display Whether to display the counter.
913
+ */
914
+ public function output_pixel_counter_wrap( $for, $type, $display = true ) {
915
+ printf(
916
+ '<div class="tsf-pixel-counter-wrap hide-if-no-js" %s>%s%s</div>',
917
+ $display ? '' : 'style="display:none;"',
918
+ sprintf(
919
+ '<div id="%s_pixels" class="tsf-tooltip-wrap">%s</div>',
920
+ \esc_attr( $for ),
921
+ '<span class="tsf-pixel-counter-bar tsf-tooltip-item" aria-label="" data-desc=""><span class="tsf-pixel-counter-fluid"></span></span>'
922
+ ),
923
+ sprintf(
924
+ '<div class="tsf-pixel-shadow-wrap"><span class="tsf-pixel-counter-shadow tsf-%s-pixel-counter-shadow"></span></div>',
925
+ \esc_attr( $type )
926
+ )
927
+ );
928
+ }
929
  }
inc/classes/cache.class.php CHANGED
@@ -64,10 +64,19 @@ class Cache extends Sitemaps {
64
  *
65
  * @since 2.5.2
66
  *
67
- * @var string The Theme Doing It Right Transient Name.
68
  */
69
  protected $theme_doing_it_right_transient;
70
 
 
 
 
 
 
 
 
 
 
71
  /**
72
  * Constructor, load parent constructor and set up caches.
73
  */
@@ -148,6 +157,9 @@ class Cache extends Sitemaps {
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
 
@@ -166,15 +178,19 @@ class Cache extends Sitemaps {
166
  }
167
 
168
  /**
169
- * Delete transient on post save.
170
  *
171
  * @since 2.8.0
 
172
  *
173
  * @param int $post_id The Post ID that has been updated.
174
  * @return bool True on success, false on failure.
175
  */
176
  public function delete_post_cache( $post_id ) {
177
 
 
 
 
178
  $success = array();
179
 
180
  $success[] = $this->delete_cache( 'post', $post_id );
@@ -188,6 +204,30 @@ class Cache extends Sitemaps {
188
  return ! in_array( false, $success, true );
189
  }
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  /**
192
  * Deletes cache on profile save.
193
  *
@@ -284,6 +324,10 @@ class Cache extends Sitemaps {
284
  return $this->object_cache_delete( $this->get_robots_txt_cache_key() );
285
  break;
286
 
 
 
 
 
287
  case 'detection' :
288
  return $this->delete_theme_dir_transient();
289
  break;
@@ -380,7 +424,7 @@ class Cache extends Sitemaps {
380
  * @param string $value Transient value. Expected to not be SQL-escaped.
381
  * @param int $expiration Optional Transient expiration date, optional. Expected to not be SQL-escaped.
382
  */
383
- public function set_transient( $transient, $value, $expiration = '' ) {
384
 
385
  if ( $this->the_seo_framework_use_transients )
386
  \set_transient( $transient, $value, $expiration );
@@ -469,6 +513,7 @@ class Cache extends Sitemaps {
469
  * @since 2.8.0:
470
  * 1. Added locale suffix.
471
  * 2. Added check for option 'cache_sitemap'.
 
472
  * @global int $blog_id
473
  */
474
  public function setup_transient_names() {
@@ -478,11 +523,13 @@ class Cache extends Sitemaps {
478
  * When the caching mechanism changes. Change this value.
479
  * Use hex. e.g. 0, 1, 2, 9, a, b
480
  */
481
- $sitemap_revision = '3';
482
- $theme_dir_revision = '0';
 
483
 
484
  $this->sitemap_transient = $this->is_option_checked( 'cache_sitemap' ) ? $this->add_cache_key_suffix( 'tsf_sitemap_' . $sitemap_revision ) : '';
485
  $this->theme_doing_it_right_transient = 'tsf_tdir_' . $theme_dir_revision . '_' . $blog_id;
 
486
  }
487
 
488
  /**
@@ -519,7 +566,7 @@ class Cache extends Sitemaps {
519
 
520
  $cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
521
 
522
- $revision = '2';
523
  $additions = $this->add_description_additions( $page_id, $taxonomy );
524
 
525
  if ( $additions ) {
@@ -563,13 +610,12 @@ class Cache extends Sitemaps {
563
 
564
  $cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
565
 
566
- $revision = '5';
567
 
568
  /**
569
  * Change key based on options.
570
  */
571
  $options = $this->enable_ld_json_breadcrumbs() ? '1' : '0';
572
- $options .= $this->enable_ld_json_sitename() ? '1' : '0';
573
  $options .= $this->enable_ld_json_searchbox() ? '1' : '0';
574
 
575
  return 'tsf_' . $revision . '_' . $options . '_ldjs_' . $cache_key;
@@ -822,18 +868,18 @@ class Cache extends Sitemaps {
822
  * @since 2.8.0 1: $locale is now static.
823
  * 2: $key may now be empty.
824
  * @staticvar string $locale
 
825
  *
826
  * @return string the cache key.
827
  */
828
  protected function add_cache_key_suffix( $key = '' ) {
829
- global $blog_id;
830
 
831
  static $locale = null;
832
 
833
  if ( is_null( $locale ) )
834
  $locale = strtolower( \get_locale() );
835
 
836
- return $key . '_' . $blog_id . '_' . $locale;
837
  }
838
 
839
  /**
@@ -970,6 +1016,8 @@ class Cache extends Sitemaps {
970
  *
971
  * @since 2.9.1
972
  * @uses THE_SEO_FRAMEWORK_DB_VERSION as cache key buster.
 
 
973
  *
974
  * @param int $id The ID. Defaults to $this->get_the_real_ID();
975
  * @param string $taxonomy The term taxonomy
@@ -983,10 +1031,10 @@ class Cache extends Sitemaps {
983
  */
984
  $key = $this->generate_cache_key_by_type( $id, $taxonomy, $type ) . '_' . THE_SEO_FRAMEWORK_DB_VERSION;
985
 
986
- $page = '1';
987
- $paged = '1';
988
 
989
- return $cache_key = 'seo_framework_output_' . $key . '_' . $paged . '_' . $page;
990
  }
991
 
992
  /**
@@ -1011,13 +1059,13 @@ class Cache extends Sitemaps {
1011
  *
1012
  * @since 2.3.0
1013
  * @since 2.7.0 : Added admin referer check.
 
1014
  *
1015
  * @return bool Whether if sitemap transient is deleted.
1016
  */
1017
  public function delete_sitemap_transient_permalink_updated() {
1018
 
1019
  if ( isset( $_POST['permalink_structure'] ) || isset( $_POST['category_base'] ) ) {
1020
-
1021
  if ( \check_admin_referer( 'update-permalink' ) )
1022
  return $this->delete_cache( 'sitemap' );
1023
  }
@@ -1126,10 +1174,8 @@ class Cache extends Sitemaps {
1126
  */
1127
  public function delete_theme_dir_transient( $value = null, $options = null ) {
1128
 
1129
- if ( isset( $options['type'] ) ) {
1130
- if ( 'theme' !== $options['type'] )
1131
- return false;
1132
- }
1133
 
1134
  \delete_transient( $this->theme_doing_it_right_transient );
1135
 
@@ -1158,4 +1204,44 @@ class Cache extends Sitemaps {
1158
  \set_transient( $this->theme_doing_it_right_transient, $dir, 0 );
1159
  }
1160
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1161
  }
64
  *
65
  * @since 2.5.2
66
  *
67
+ * @var string
68
  */
69
  protected $theme_doing_it_right_transient;
70
 
71
+ /**
72
+ * The excluded Post IDs transient name.
73
+ *
74
+ * @since 3.0.0
75
+ *
76
+ * @var string
77
+ */
78
+ protected $excluded_post_ids_transient;
79
+
80
  /**
81
  * Constructor, load parent constructor and set up caches.
82
  */
157
  \add_action( 'post_updated', array( $this, 'delete_post_cache' ) );
158
  \add_action( 'page_updated', array( $this, 'delete_post_cache' ) );
159
 
160
+ //* Excluded IDs cache.
161
+ \add_action( 'save_post', array( $this, 'delete_excluded_ids_cache' ) );
162
+
163
  $run = true;
164
  }
165
 
178
  }
179
 
180
  /**
181
+ * Deletes transient on post save.
182
  *
183
  * @since 2.8.0
184
+ * @since 3.0.0 Process is halted when no valid $post_id is supplied.
185
  *
186
  * @param int $post_id The Post ID that has been updated.
187
  * @return bool True on success, false on failure.
188
  */
189
  public function delete_post_cache( $post_id ) {
190
 
191
+ if ( ! $post_id )
192
+ return false;
193
+
194
  $success = array();
195
 
196
  $success[] = $this->delete_cache( 'post', $post_id );
204
  return ! in_array( false, $success, true );
205
  }
206
 
207
+ /**
208
+ * Deletes excluded post IDs cache.
209
+ *
210
+ * @since 3.0.0
211
+ *
212
+ * @return bool True on success, false on failure.
213
+ */
214
+ public function delete_excluded_ids_cache() {
215
+ return $this->delete_cache( 'excluded_post_ids' );
216
+ }
217
+
218
+ /**
219
+ * Deletes excluded post IDs transient cache.
220
+ *
221
+ * @since 3.0.0
222
+ * @see $this->delete_excluded_ids_cache()
223
+ *
224
+ * @return bool True
225
+ */
226
+ public function delete_excluded_post_ids_transient() {
227
+ \delete_transient( $this->excluded_post_ids_transient );
228
+ return true;
229
+ }
230
+
231
  /**
232
  * Deletes cache on profile save.
233
  *
324
  return $this->object_cache_delete( $this->get_robots_txt_cache_key() );
325
  break;
326
 
327
+ case 'excluded_post_ids' :
328
+ return $this->delete_excluded_post_ids_transient();
329
+ break;
330
+
331
  case 'detection' :
332
  return $this->delete_theme_dir_transient();
333
  break;
424
  * @param string $value Transient value. Expected to not be SQL-escaped.
425
  * @param int $expiration Optional Transient expiration date, optional. Expected to not be SQL-escaped.
426
  */
427
+ public function set_transient( $transient, $value, $expiration = 0 ) {
428
 
429
  if ( $this->the_seo_framework_use_transients )
430
  \set_transient( $transient, $value, $expiration );
513
  * @since 2.8.0:
514
  * 1. Added locale suffix.
515
  * 2. Added check for option 'cache_sitemap'.
516
+ * @since 3.0.0 Now also sets up $excluded_post_ids_transient
517
  * @global int $blog_id
518
  */
519
  public function setup_transient_names() {
523
  * When the caching mechanism changes. Change this value.
524
  * Use hex. e.g. 0, 1, 2, 9, a, b
525
  */
526
+ $sitemap_revision = '4';
527
+ $theme_dir_revision = '1';
528
+ $exclude_revision = '0';
529
 
530
  $this->sitemap_transient = $this->is_option_checked( 'cache_sitemap' ) ? $this->add_cache_key_suffix( 'tsf_sitemap_' . $sitemap_revision ) : '';
531
  $this->theme_doing_it_right_transient = 'tsf_tdir_' . $theme_dir_revision . '_' . $blog_id;
532
+ $this->excluded_post_ids_transient = 'tsf_exclude_' . $exclude_revision . '_' . $blog_id;
533
  }
534
 
535
  /**
566
 
567
  $cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
568
 
569
+ $revision = '3';
570
  $additions = $this->add_description_additions( $page_id, $taxonomy );
571
 
572
  if ( $additions ) {
610
 
611
  $cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
612
 
613
+ $revision = '6';
614
 
615
  /**
616
  * Change key based on options.
617
  */
618
  $options = $this->enable_ld_json_breadcrumbs() ? '1' : '0';
 
619
  $options .= $this->enable_ld_json_searchbox() ? '1' : '0';
620
 
621
  return 'tsf_' . $revision . '_' . $options . '_ldjs_' . $cache_key;
868
  * @since 2.8.0 1: $locale is now static.
869
  * 2: $key may now be empty.
870
  * @staticvar string $locale
871
+ * @global string $blog_id
872
  *
873
  * @return string the cache key.
874
  */
875
  protected function add_cache_key_suffix( $key = '' ) {
 
876
 
877
  static $locale = null;
878
 
879
  if ( is_null( $locale ) )
880
  $locale = strtolower( \get_locale() );
881
 
882
+ return $key . '_' . $GLOBALS['blog_id'] . '_' . $locale;
883
  }
884
 
885
  /**
1016
  *
1017
  * @since 2.9.1
1018
  * @uses THE_SEO_FRAMEWORK_DB_VERSION as cache key buster.
1019
+ * @uses $this->generate_cache_key_by_type()
1020
+ * @see $this->get_meta_output_cache_key_by_query()
1021
  *
1022
  * @param int $id The ID. Defaults to $this->get_the_real_ID();
1023
  * @param string $taxonomy The term taxonomy
1031
  */
1032
  $key = $this->generate_cache_key_by_type( $id, $taxonomy, $type ) . '_' . THE_SEO_FRAMEWORK_DB_VERSION;
1033
 
1034
+ //= Refers to the first page, always.
1035
+ $_page = $_paged = '1';
1036
 
1037
+ return $cache_key = 'seo_framework_output_' . $key . '_' . $_paged . '_' . $_page;
1038
  }
1039
 
1040
  /**
1059
  *
1060
  * @since 2.3.0
1061
  * @since 2.7.0 : Added admin referer check.
1062
+ * @securitycheck 3.0.0 OK.
1063
  *
1064
  * @return bool Whether if sitemap transient is deleted.
1065
  */
1066
  public function delete_sitemap_transient_permalink_updated() {
1067
 
1068
  if ( isset( $_POST['permalink_structure'] ) || isset( $_POST['category_base'] ) ) {
 
1069
  if ( \check_admin_referer( 'update-permalink' ) )
1070
  return $this->delete_cache( 'sitemap' );
1071
  }
1174
  */
1175
  public function delete_theme_dir_transient( $value = null, $options = null ) {
1176
 
1177
+ if ( isset( $options['type'] ) && 'theme' !== $options['type'] )
1178
+ return false;
 
 
1179
 
1180
  \delete_transient( $this->theme_doing_it_right_transient );
1181
 
1204
  \set_transient( $this->theme_doing_it_right_transient, $dir, 0 );
1205
  }
1206
  }
1207
+
1208
+ /**
1209
+ * Builds and returns the excluded post IDs transient.
1210
+ *
1211
+ * @since 3.0.0
1212
+ * @staticvar array $cache
1213
+ *
1214
+ * @return array : { 'archive', 'search' }
1215
+ */
1216
+ public function get_excluded_ids_from_cache() {
1217
+
1218
+ static $cache = null;
1219
+
1220
+ if ( null === $cache )
1221
+ $cache = $this->get_transient( $this->excluded_post_ids_transient );
1222
+
1223
+ if ( false === $cache ) {
1224
+ global $wpdb;
1225
+ $cache = array();
1226
+
1227
+ //= Two separated equals queries are faster than a single IN with 'meta_key'.
1228
+ $cache['archive'] = $wpdb->get_results(
1229
+ $wpdb->prepare( "SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = '%s'", 'exclude_from_archive' )
1230
+ );
1231
+ $cache['search'] = $wpdb->get_results(
1232
+ $wpdb->prepare( "SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = '%s'", 'exclude_local_search' )
1233
+ );
1234
+
1235
+ foreach ( array( 'archive', 'search' ) as $key ) {
1236
+ array_walk( $cache[ $key ], function( &$v ) {
1237
+ $v = $v->meta_value ? (int) $v->post_id : false;
1238
+ } );
1239
+ $cache[ $key ] = array_filter( $cache[ $key ] );
1240
+ }
1241
+
1242
+ $this->set_transient( $this->excluded_post_ids_transient, $cache );
1243
+ }
1244
+
1245
+ return $cache;
1246
+ }
1247
  }
inc/classes/compat.class.php CHANGED
@@ -43,9 +43,6 @@ class Compat extends Core {
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
  /**
@@ -63,36 +60,32 @@ class Compat extends Core {
63
  $this->_include_compat( 'mbstring', 'php' );
64
  }
65
 
 
 
 
 
 
 
 
66
  if ( $this->is_theme( 'genesis' ) ) {
67
  //* Genesis Framework
68
  $this->_include_compat( 'genesis', 'theme' );
69
  }
70
 
71
- if ( defined( 'DOMAIN_MAPPING' ) ) {
72
- if ( $this->detect_plugin( array( 'functions' => array( 'redirect_to_mapped_domain' ) ) ) ) {
73
- //* Donncha domain mapping.
74
- $this->_include_compat( 'donncha-dm', 'plugin' );
75
- } elseif ( $this->detect_plugin( array( 'functions' => array( 'domainmap_launch' ) ) ) ) {
76
- //* WPMUdev domain mapping.
77
- $this->_include_compat( 'wpmudev-dm', 'plugin' );
78
- }
79
- }
80
-
81
- if ( $this->detect_plugin( array( 'globals' => array( 'polylang' ) ) ) ) {
82
- //* PolyLang... it includes compat for WPML, but let's see how this works for now.
83
- $this->_include_compat( 'polylang', 'plugin' );
84
- } elseif ( $this->detect_plugin( array( 'constants' => array( 'ICL_LANGUAGE_CODE' ) ) ) ) {
85
  //* WPML
86
  $this->_include_compat( 'wpml', 'plugin' );
87
- } elseif ( $this->detect_plugin( array( 'constants' => array( 'QTX_VERSION' ) ) ) ) {
88
- //* qTranslate X
89
- $this->_include_compat( 'qtranslatex', 'plugin' );
90
  }
91
 
92
  if ( $this->detect_plugin( array( 'globals' => array( 'ultimatemember' ) ) ) ) {
93
  //* Ultimate Member
94
  $this->_include_compat( 'ultimatemember', 'plugin' );
95
  }
 
 
 
 
 
96
 
97
  if ( $this->detect_plugin( array( 'functions' => array( 'bbpress' ) ) ) ) {
98
  //* bbPress
@@ -118,8 +111,8 @@ class Compat extends Core {
118
 
119
  static $included = array();
120
 
121
- isset( $included[ $what ][ $type ] )
122
- or $included[ $what ][ $type ] = (bool) require_once( THE_SEO_FRAMEWORK_DIR_PATH_COMPAT . $type . '-' . $what . '.php' );
123
 
124
  return $included[ $what ][ $type ];
125
  }
43
 
44
  //* Jetpack compat.
45
  \add_action( 'init', array( $this, 'jetpack_compat' ) );
 
 
 
46
  }
47
 
48
  /**
60
  $this->_include_compat( 'mbstring', 'php' );
61
  }
62
 
63
+ $wp_version = $GLOBALS['wp_version'];
64
+
65
+ if ( version_compare( $wp_version, '4.6', '<' ) ) {
66
+ //* WP 4.6.0
67
+ $this->_include_compat( '460', 'wp' );
68
+ }
69
+
70
  if ( $this->is_theme( 'genesis' ) ) {
71
  //* Genesis Framework
72
  $this->_include_compat( 'genesis', 'theme' );
73
  }
74
 
75
+ if ( $this->detect_plugin( array( 'constants' => array( 'ICL_LANGUAGE_CODE' ) ) ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  //* WPML
77
  $this->_include_compat( 'wpml', 'plugin' );
 
 
 
78
  }
79
 
80
  if ( $this->detect_plugin( array( 'globals' => array( 'ultimatemember' ) ) ) ) {
81
  //* Ultimate Member
82
  $this->_include_compat( 'ultimatemember', 'plugin' );
83
  }
84
+ if ( $this->detect_plugin( array( 'globals' => array( 'bp' ) ) ) ) {
85
+ //* BuddyPress
86
+ $this->_include_compat( 'buddypress', 'plugin' );
87
+
88
+ }
89
 
90
  if ( $this->detect_plugin( array( 'functions' => array( 'bbpress' ) ) ) ) {
91
  //* bbPress
111
 
112
  static $included = array();
113
 
114
+ if ( ! isset( $included[ $what ][ $type ] ) )
115
+ $included[ $what ][ $type ] = (bool) require THE_SEO_FRAMEWORK_DIR_PATH_COMPAT . $type . '-' . $what . '.php';
116
 
117
  return $included[ $what ][ $type ];
118
  }
inc/classes/core.class.php CHANGED
@@ -54,7 +54,7 @@ class Core {
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
 
@@ -76,7 +76,7 @@ class Core {
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
 
@@ -120,7 +120,7 @@ class Core {
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' ) );
@@ -140,9 +140,8 @@ class Core {
140
  protected function clean_response_header() {
141
 
142
  if ( $level = ob_get_level() ) {
143
- while ( $level ) {
144
  ob_end_clean();
145
- $level--;
146
  }
147
  return true;
148
  }
@@ -160,7 +159,7 @@ class Core {
160
  *
161
  * @param string $view The file name.
162
  * @param array $args The arguments to be supplied within the file name.
163
- * Each array key is converted to a variable with its value attached.
164
  * @param string $instance The instance suffix to call back upon.
165
  */
166
  public function get_view( $view, array $args = array(), $instance = 'main' ) {
@@ -170,7 +169,7 @@ class Core {
170
 
171
  $file = THE_SEO_FRAMEWORK_DIR_PATH_VIEWS . $view . '.php';
172
 
173
- include( $file );
174
  }
175
 
176
  /**
@@ -241,6 +240,8 @@ class Core {
241
  *
242
  * @since 2.2.8
243
  * @since 2.9.2 : Added TSFEM link.
 
 
244
  *
245
  * @param array $links The current links.
246
  * @return array The plugin links.
@@ -250,9 +251,9 @@ class Core {
250
  $tsf_links = array();
251
 
252
  if ( $this->load_options )
253
- $tsf_links['settings'] = '<a href="' . \esc_url( \admin_url( 'admin.php?page=' . $this->seo_settings_page_slug ) ) . '">' . \esc_html__( 'SEO Settings', 'autodescription' ) . '</a>';
254
 
255
- $tsf_links['home'] = '<a href="' . \esc_url( 'https://theseoframework.com/' ) . '" rel="noopener" target="_blank">' . \esc_html_x( 'Plugin Home', 'As in: The Plugin Home Page', 'autodescription' ) . '</a>';
256
 
257
  /**
258
  * These are weak checks.
@@ -261,7 +262,7 @@ class Core {
261
  if ( ! defined( 'TSF_EXTENSION_MANAGER_VERSION' ) ) {
262
  $tsfem = \get_plugins( '/the-seo-framework-extension-manager' );
263
  if ( empty( $tsfem ) )
264
- $tsf_links['tsfem'] = '<a href="' . \esc_url( \__( 'https://wordpress.org/plugins/the-seo-framework-extension-manager/', 'autodescription' ) ) . '" rel="noopener" target="_blank">' . \esc_html_x( 'Extensions', 'Plugin extensions', 'autodescription' ) . '</a>';
265
  }
266
 
267
  return array_merge( $tsf_links, $links );
@@ -572,18 +573,32 @@ class Core {
572
  /**
573
  * Returns the minimum role required to adjust settings.
574
  *
575
- * Applies filter 'the_seo_framework_settings_capability' : string
576
- * This filter changes the minimum role for viewing and editing the plugin's settings.
577
- *
578
- * @since 2.6.0
579
- * @access private
580
  *
581
  * @return string The minimum required capability for SEO Settings.
582
  */
583
- public function settings_capability() {
 
 
 
 
 
 
584
  return (string) \apply_filters( 'the_seo_framework_settings_capability', 'manage_options' );
585
  }
586
 
 
 
 
 
 
 
 
 
 
 
 
 
587
  /**
588
  * Returns the SEO Settings page URL.
589
  *
@@ -612,7 +627,7 @@ class Core {
612
  *
613
  * @param bool $guess : If true, the timezone will be guessed from the
614
  * WordPress core gmt_offset option.
615
- * @return string|empty PHP Timezone String.
616
  */
617
  public function get_timezone_string( $guess = false ) {
618
 
@@ -710,6 +725,28 @@ class Core {
710
  return '';
711
  }
712
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
713
  /**
714
  * Counts words encounters from input string.
715
  * Case insensitive. Returns first encounter of each word if found multiple times.
54
  */
55
  final public function __set( $name, $value ) {
56
  /**
57
+ * For now, no deprecation is being handled; as no properties have been deprecated.
58
  */
59
  $this->_deprecated_function( 'the_seo_framework()->' . \esc_html( $name ), 'unknown' );
60
 
76
 
77
  switch ( $name ) :
78
  case 'pagehook' :
79
+ $this->_deprecated_function( 'the_seo_framework()->pagehook', '2.7.0', 'the_seo_framework()->seo_settings_page_hook' );
80
  return $this->seo_settings_page_hook;
81
  break;
82
 
120
 
121
  if ( $this->the_seo_framework_debug ) {
122
 
123
+ $debug_instance = 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' ) );
140
  protected function clean_response_header() {
141
 
142
  if ( $level = ob_get_level() ) {
143
+ while ( $level-- ) {
144
  ob_end_clean();
 
145
  }
146
  return true;
147
  }
159
  *
160
  * @param string $view The file name.
161
  * @param array $args The arguments to be supplied within the file name.
162
+ * Each array key is converted to a variable with its value attached.
163
  * @param string $instance The instance suffix to call back upon.
164
  */
165
  public function get_view( $view, array $args = array(), $instance = 'main' ) {
169
 
170
  $file = THE_SEO_FRAMEWORK_DIR_PATH_VIEWS . $view . '.php';
171
 
172
+ include $file;
173
  }
174
 
175
  /**
240
  *
241
  * @since 2.2.8
242
  * @since 2.9.2 : Added TSFEM link.
243
+ * @since 3.0.0 : 1. Shortened names.
244
+ * 2. Added noreferrer to the external links.
245
  *
246
  * @param array $links The current links.
247
  * @return array The plugin links.
251
  $tsf_links = array();
252
 
253
  if ( $this->load_options )
254
+ $tsf_links['settings'] = '<a href="' . \esc_url( \admin_url( 'admin.php?page=' . $this->seo_settings_page_slug ) ) . '">' . \esc_html__( 'Settings', 'autodescription' ) . '</a>';
255
 
256
+ $tsf_links['home'] = '<a href="' . \esc_url( 'https://theseoframework.com/' ) . '" rel="noreferrer noopener" target="_blank">' . \esc_html_x( 'Home', 'As in: The Plugin Home Page', 'autodescription' ) . '</a>';
257
 
258
  /**
259
  * These are weak checks.
262
  if ( ! defined( 'TSF_EXTENSION_MANAGER_VERSION' ) ) {
263
  $tsfem = \get_plugins( '/the-seo-framework-extension-manager' );
264
  if ( empty( $tsfem ) )
265
+ $tsf_links['tsfem'] = '<a href="' . \esc_url( \__( 'https://wordpress.org/plugins/the-seo-framework-extension-manager/', 'autodescription' ) ) . '" rel="noreferrer noopener" target="_blank">' . \esc_html_x( 'Extensions', 'Plugin extensions', 'autodescription' ) . '</a>';
266
  }
267
 
268
  return array_merge( $tsf_links, $links );
573
  /**
574
  * Returns the minimum role required to adjust settings.
575
  *
576
+ * @since 3.0.0
 
 
 
 
577
  *
578
  * @return string The minimum required capability for SEO Settings.
579
  */
580
+ public function get_settings_capability() {
581
+ /**
582
+ * Applies filters 'the_seo_framework_settings_capability'
583
+ *
584
+ * @since 2.6.0
585
+ * @string $capability The user capability required to adjust settings.
586
+ */
587
  return (string) \apply_filters( 'the_seo_framework_settings_capability', 'manage_options' );
588
  }
589
 
590
+ /**
591
+ * Determines if the current user can do settings.
592
+ * Not cached as it's imposing security functionality.
593
+ *
594
+ * @since 3.0.0
595
+ *
596
+ * @return bool
597
+ */
598
+ public function can_access_settings() {
599
+ return \current_user_can( $this->get_settings_capability() );
600
+ }
601
+
602
  /**
603
  * Returns the SEO Settings page URL.
604
  *
627
  *
628
  * @param bool $guess : If true, the timezone will be guessed from the
629
  * WordPress core gmt_offset option.
630
+ * @return string PHP Timezone String.
631
  */
632
  public function get_timezone_string( $guess = false ) {
633
 
725
  return '';
726
  }
727
 
728
+ /**
729
+ * Returns timestamp format based on timestamp settings.
730
+ *
731
+ * @since 3.0.0
732
+ *
733
+ * @return string The timestamp format used in PHP date.
734
+ */
735
+ public function get_timestamp_format() {
736
+ return '1' === $this->get_option( 'timestamps_format' ) ? 'Y-m-d\TH:iP' : 'Y-m-d';
737
+ }
738
+
739
+ /**
740
+ * Determines if time is used in the timestamp format.
741
+ *
742
+ * @since 3.0.0
743
+ *
744
+ * @return bool True if time is used. False otherwise.
745
+ */
746
+ public function uses_time_in_timestamp_format() {
747
+ return '1' === $this->get_option( 'timestamps_format' );
748
+ }
749
+
750
  /**
751
  * Counts words encounters from input string.
752
  * Case insensitive. Returns first encounter of each word if found multiple times.
inc/classes/debug.class.php CHANGED
@@ -209,29 +209,29 @@ final class Debug implements Debug_Interface {
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
- *
220
- * @since WP Core 3.1.0
221
- *
222
- * @param string $function The function that was called.
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.
230
- *
231
- * @since 3.1.0
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' ) );
@@ -272,8 +272,8 @@ final class Debug implements Debug_Interface {
272
  *
273
  * @since 2.7.0
274
  *
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
 
@@ -451,8 +451,7 @@ final class Debug implements Debug_Interface {
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
  /**
@@ -462,11 +461,8 @@ final class Debug implements Debug_Interface {
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
  /**
@@ -864,11 +860,8 @@ final class Debug implements Debug_Interface {
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
  /**
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
+ *
220
+ * @since WP Core 3.1.0
221
+ *
222
+ * @param string $function The function that was called.
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.
230
+ *
231
+ * @since 3.1.0
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' ) );
272
  *
273
  * @since 2.7.0
274
  *
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
 
451
  * @return bool True if there's output.
452
  */
453
  public static function has_debug_output() {
454
+ return (bool) static::get_instance()->debug_output;
 
455
  }
456
 
457
  /**
461
  * @access private
462
  */
463
  public static function _output_debug() {
 
 
464
  //* Already escaped.
465
+ echo static::get_instance()->debug_output;
 
466
  }
467
 
468
  /**
860
  * @access private
861
  */
862
  public static function _output_debug_header() {
 
 
863
  //* Already escaped.
864
+ echo static::get_instance()->get_debug_header_output();
 
865
  }
866
 
867
  /**
inc/classes/deprecated.class.php CHANGED
@@ -1,1290 +1,2012 @@
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 - 2017 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 deprecated.
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
-
506
- /**
507
- * Fetches og:image URL.
508
- *
509
- * @since 2.2.2
510
- * @since 2.2.8 : Added theme icon detection.
511
- * @since 2.5.2 : Added args filters.
512
- * @since 2.8.0 : 1. Added theme logo detection.
513
- * 2. Added inpost image selection detection.
514
- * @since 2.8.2 : 1. Now returns something on post ID 0.
515
- * 2. Added SEO settings fallback image selection detection.
516
- * @since 2.9.0 : 1. Added 'skip_fallback' option to arguments.
517
- * 2. Added 'escape' option to arguments.
518
- * 3. First parameter is now arguments. Fallback for integer is added.
519
- * 4. Second parameter is now deprecated.
520
- * 5. Deprecated.
521
- * @deprecated Use get_social_image instead.
522
- *
523
- * @param int|array $args The image arguments.
524
- * Was: $post_id.
525
- * Warning: Integer usage is only used for backwards compat.
526
- * @param array $depr_args, Deprecated;
527
- * Was $args The image arguments.
528
- * @param bool $escape Whether to escape the image URL.
529
- * Deprecated: You should use $args['escape'].
530
- * @return string the image URL.
531
- */
532
- public function get_image( $args = array(), $depr_args = '', $depr_escape = true ) {
533
-
534
- $tsf = \the_seo_framework();
535
-
536
- $tsf->_deprecated_function( 'the_seo_framework()->get_image()', '2.9.0', 'the_seo_framework()->get_social_image()' );
537
-
538
- if ( is_int( $args ) || is_array( $depr_args ) ) {
539
- $tsf->_doing_it_wrong( __METHOD__, 'First parameter is now used for arguments. Second parameter is deprecated.', '2.9.0' );
540
-
541
- $post_id = $args;
542
- $args = array();
543
-
544
- /**
545
- * Backwards compat with parse args.
546
- * @since 2.5.0
547
- */
548
- if ( ! isset( $depr_args['post_id'] ) ) {
549
- $args['post_id'] = $post_id ?: ( $tsf->is_singular( $post_id ) ? $tsf->get_the_real_ID() : 0 );
550
- }
551
-
552
- if ( is_array( $depr_args ) ) {
553
- $args = \wp_parse_args( $depr_args, $args );
554
- }
555
- }
556
-
557
- if ( false === $depr_escape ) {
558
- $tsf->_doing_it_wrong( __METHOD__, 'Third parameter has been deprecated. Use `$args["escape"] => false` instead.', '2.9.0' );
559
- $args['escape'] = false;
560
- }
561
-
562
- $args = $tsf->reparse_image_args( $args );
563
-
564
- //* 0. Image from argument.
565
- pre_0 : {
566
- if ( $image = $args['image'] )
567
- goto end;
568
- }
569
-
570
- //* Check if there are no disallowed arguments.
571
- $all_allowed = empty( $args['disallowed'] );
572
-
573
- //* 1. Fetch image from homepage SEO meta upload.
574
- if ( $all_allowed || false === in_array( 'homemeta', $args['disallowed'], true ) ) {
575
- if ( $image = $tsf->get_social_image_url_from_home_meta( $args['post_id'], true ) )
576
- goto end;
577
- }
578
-
579
- if ( $args['post_id'] ) {
580
- //* 2. Fetch image from SEO meta upload.
581
- if ( $all_allowed || false === in_array( 'postmeta', $args['disallowed'], true ) ) {
582
- if ( $image = $tsf->get_social_image_url_from_post_meta( $args['post_id'], true ) )
583
- goto end;
584
- }
585
-
586
- //* 3. Fetch image from featured.
587
- if ( $all_allowed || false === in_array( 'featured', $args['disallowed'], true ) ) {
588
- if ( $image = $tsf->get_image_from_post_thumbnail( $args, true ) )
589
- goto end;
590
- }
591
- }
592
-
593
- if ( $args['skip_fallback'] )
594
- goto end;
595
-
596
- //* 4. Fetch image from SEO settings
597
- if ( $all_allowed || false === in_array( 'option', $args['disallowed'], true ) ) {
598
- if ( $image = $tsf->get_social_image_url_from_seo_settings( true ) )
599
- goto end;
600
- }
601
-
602
- //* 5. Fetch image from fallback filter 1
603
- /**
604
- * Applies filters 'the_seo_framework_og_image_after_featured' : string
605
- * @since 2.5.2
606
- */
607
- fallback_1 : {
608
- if ( $image = (string) \apply_filters( 'the_seo_framework_og_image_after_featured', '', $args['post_id'] ) )
609
- goto end;
610
- }
611
-
612
- //* 6. Fallback: Get header image if exists
613
- if ( ( $all_allowed || false === in_array( 'header', $args['disallowed'], true ) ) && \current_theme_supports( 'custom-header', 'default-image' ) ) {
614
- if ( $image = $tsf->get_header_image( true ) )
615
- goto end;
616
- }
617
-
618
- //* 7. Fetch image from fallback filter 2
619
- /**
620
- * Applies filters 'the_seo_framework_og_image_after_header' : string
621
- * @since 2.5.2
622
- */
623
- fallback_2 : {
624
- if ( $image = (string) \apply_filters( 'the_seo_framework_og_image_after_header', '', $args['post_id'] ) )
625
- goto end;
626
- }
627
-
628
- //* 8. Get the WP 4.5 Site Logo
629
- if ( ( $all_allowed || false === in_array( 'logo', $args['disallowed'], true ) ) && $tsf->can_use_logo() ) {
630
- if ( $image = $tsf->get_site_logo( true ) )
631
- goto end;
632
- }
633
-
634
- //* 9. Get the WP 4.3 Site Icon
635
- if ( $all_allowed || false === in_array( 'icon', $args['disallowed'], true ) ) {
636
- if ( $image = $tsf->get_site_icon( 'full', true ) )
637
- goto end;
638
- }
639
-
640
- end :;
641
-
642
- if ( $args['escape'] && $image )
643
- $image = \esc_url( $image );
644
-
645
- return (string) $image;
646
- }
647
-
648
- /**
649
- * Fetches image from post thumbnail.
650
- * Resizes the image between 4096px if bigger. Then it saves the image and
651
- * Keeps dimensions relative.
652
- *
653
- * @since 2.3.0
654
- * @since 2.9.0 Changed parameters.
655
- * @since 2.9.0 Deprecated.
656
- * @since 2.9.3 Now supports 4K, rather than 1500px.
657
- * @deprecated
658
- *
659
- * @param array $args The image args.
660
- * Was: int $id The post/page ID.
661
- * @param bool $set_og_dimensions Whether to set Open Graph image dimensions.
662
- * Was: array $depr_args Deprecated. Image arguments.
663
- * @return string|null the image url.
664
- */
665
- public function get_image_from_post_thumbnail( $args = array(), $set_og_dimensions = false ) {
666
-
667
- $tsf = \the_seo_framework();
668
-
669
- $tsf->_deprecated_function( 'the_seo_framework()->get_image_from_post_thumbnail()', '2.9.0', 'the_seo_framework()->get_social_image_url_from_post_thumbnail()' );
670
-
671
- if ( is_array( $set_og_dimensions ) ) {
672
- $tsf->_doing_it_wrong( __METHOD__, 'First parameter are now arguments, second parameter is for setting og dimensions.', '2.9.0' );
673
- $args = $set_og_dimensions;
674
- $set_og_dimensions = false;
675
- }
676
-
677
- $args = $tsf->reparse_image_args( $args );
678
-
679
- $id = \get_post_thumbnail_id( $args['post_id'] );
680
-
681
- $args['get_the_real_ID'] = true;
682
-
683
- $image = $id ? $tsf->parse_og_image( $id, $args, $set_og_dimensions ) : '';
684
-
685
- return $image;
686
- }
687
-
688
- /**
689
- * Detects front page.
690
- *
691
- * Returns true on SEO settings page if ID is 0.
692
- *
693
- * @since 2.6.0
694
- * @since 2.9.0: Deprecated.
695
- * @deprecated
696
- *
697
- * @param int $id The Page or Post ID.
698
- * @return bool
699
- */
700
- public function is_front_page( $id = 0 ) {
701
-
702
- $tsf = \the_seo_framework();
703
-
704
- $tsf->_deprecated_function( 'the_seo_framework()->is_front_page()', '2.9.0', 'the_seo_framework()->is_real_front_page() or the_seo_framework()->is_front_page_by_id()' );
705
-
706
- static $cache = array();
707
-
708
- if ( null !== $cache = $tsf->get_query_cache( __METHOD__, null, $id ) )
709
- return $cache;
710
-
711
- $is_front_page = false;
712
-
713
- if ( \is_front_page() && empty( $id ) )
714
- $is_front_page = true;
715
-
716
- //* Elegant Themes Support. Yay.
717
- if ( false === $is_front_page && empty( $id ) && $tsf->is_home() ) {
718
- $sof = \get_option( 'show_on_front' );
719
-
720
- if ( 'page' !== $sof && 'posts' !== $sof )
721
- $is_front_page = true;
722
- }
723
-
724
- //* Compare against $id
725
- if ( false === $is_front_page && $id ) {
726
- $sof = \get_option( 'show_on_front' );
727
-
728
- if ( 'page' === $sof && (int) \get_option( 'page_on_front' ) === $id )
729
- $is_front_page = true;
730
-
731
- if ( 'posts' === $sof && (int) \get_option( 'page_for_posts' ) === $id )
732
- $is_front_page = true;
733
- } elseif ( empty( $id ) && $tsf->is_seo_settings_page() ) {
734
- $is_front_page = true;
735
- }
736
-
737
- $tsf->set_query_cache(
738
- __METHOD__,
739
- $is_front_page,
740
- $id
741
- );
742
-
743
- return $is_front_page;
744
- }
745
-
746
- /**
747
- * Returns http://schema.org json encoded context URL.
748
- *
749
- * @staticvar string $context
750
- * @since 2.6.0
751
- * @since 2.9.3 Deprecated.
752
- * @deprecated
753
- *
754
- * @return string The json encoded context url.
755
- */
756
- public function schema_context() {
757
-
758
- \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_context()', '2.9.3' );
759
-
760
- static $context;
761
-
762
- if ( isset( $context ) )
763
- return $context;
764
-
765
- return $context = json_encode( 'http://schema.org' );
766
- }
767
-
768
-
769
- /**
770
- * Returns 'WebSite' json encoded type name.
771
- *
772
- * @staticvar string $context
773
- * @since 2.6.0
774
- * @since 2.9.3 Deprecated.
775
- * @deprecated
776
- *
777
- * @return string The json encoded type name.
778
- */
779
- public function schema_type() {
780
-
781
- \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_type()', '2.9.3' );
782
-
783
- static $type;
784
-
785
- if ( isset( $type ) )
786
- return $type;
787
-
788
- return $type = json_encode( 'WebSite' );
789
- }
790
-
791
- /**
792
- * Returns json encoded home url.
793
- *
794
- * @staticvar string $url
795
- * @since 2.6.0
796
- * @since 2.9.3 Deprecated.
797
- * @deprecated
798
- *
799
- * @return string The json encoded home url.
800
- */
801
- public function schema_home_url() {
802
-
803
- \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_home_url()', '2.9.3' );
804
-
805
- static $type;
806
-
807
- if ( isset( $type ) )
808
- return $type;
809
-
810
- return $type = json_encode( \the_seo_framework()->the_home_url_from_cache() );
811
- }
812
-
813
- /**
814
- * Returns json encoded blogname.
815
- *
816
- * @staticvar string $name
817
- * @since 2.6.0
818
- * @since 2.9.3 Deprecated.
819
- * @deprecated
820
- *
821
- * @return string The json encoded blogname.
822
- */
823
- public function schema_blog_name() {
824
-
825
- \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_blog_name()', '2.9.3' );
826
-
827
- static $name;
828
-
829
- if ( isset( $name ) )
830
- return $name;
831
-
832
- return $name = json_encode( \the_seo_framework()->get_blogname() );
833
- }
834
-
835
- /**
836
- * Returns 'BreadcrumbList' json encoded type name.
837
- *
838
- * @staticvar string $crumblist
839
- * @since 2.6.0
840
- * @since 2.9.3 Deprecated.
841
- * @deprecated
842
- *
843
- * @return string The json encoded 'BreadcrumbList'.
844
- */
845
- public function schema_breadcrumblist() {
846
-
847
- \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_breadcrumblist()', '2.9.3' );
848
-
849
- static $crumblist;
850
-
851
- if ( isset( $crumblist ) )
852
- return $crumblist;
853
-
854
- return $crumblist = json_encode( 'BreadcrumbList' );
855
- }
856
-
857
- /**
858
- * Returns 'ListItem' json encoded type name.
859
- *
860
- * @staticvar string $listitem
861
- * @since 2.6.0
862
- * @since 2.9.3 Deprecated.
863
- * @deprecated
864
- *
865
- * @return string The json encoded 'ListItem'.
866
- */
867
- public function schema_listitem() {
868
-
869
- \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_listitem()', '2.9.3' );
870
-
871
- static $listitem;
872
-
873
- if ( isset( $listitem ) )
874
- return $listitem;
875
-
876
- return $listitem = json_encode( 'ListItem' );
877
- }
878
-
879
- /**
880
- * Returns 'image' json encoded value.
881
- *
882
- * @staticvar array $images
883
- * @since 2.7.0
884
- * @since 2.9.0 : 1. No longer uses image from cache, instead: it skips fallback images.
885
- * 2. Can now fetch home-page as blog set image.
886
- * @since 2.9.3 Deprecated.
887
- * @deprecated
888
- *
889
- * @param int|string $id The page, post, product or term ID.
890
- * @param bool $singular Whether the ID is singular.
891
- */
892
- public function schema_image( $id = 0, $singular = false ) {
893
-
894
- $tsf = \the_seo_framework();
895
-
896
- $tsf->_deprecated_function( 'the_seo_framework()->schema_image()', '2.9.3' );
897
-
898
- static $images = array();
899
-
900
- $id = (int) $id;
901
-
902
- if ( isset( $images[ $id ][ $singular ] ) )
903
- return $images[ $id ][ $singular ];
904
-
905
- $image = '';
906
-
907
- if ( $singular ) {
908
- if ( $id === $tsf->get_the_front_page_ID() ) {
909
- if ( $tsf->has_page_on_front() ) {
910
- $image_args = array(
911
- 'post_id' => $id,
912
- 'skip_fallback' => true,
913
- );
914
- } else {
915
- $image_args = array(
916
- 'post_id' => $id,
917
- 'skip_fallback' => true,
918
- 'disallowed' => array(
919
- 'postmeta',
920
- 'featured',
921
- ),
922
- );
923
- }
924
- } else {
925
- $image_args = array(
926
- 'post_id' => $id,
927
- 'skip_fallback' => true,
928
- 'disallowed' => array(
929
- 'homemeta'
930
- ),
931
- );
932
- }
933
- $image = $tsf->get_social_image( $image_args );
934
- } else {
935
- //* Placeholder.
936
- $image = '';
937
- }
938
-
939
- /**
940
- * Applies filters 'the_seo_framework_ld_json_breadcrumb_image' : string
941
- * @since 2.7.0
942
- * @param string $image The current image.
943
- * @param int $id The page, post, product or term ID.
944
- * @param bool $singular Whether the ID is singular.
945
- */
946
- $image = \apply_filters( 'the_seo_framework_ld_json_breadcrumb_image', $image, $id, $singular );
947
-
948
- return $images[ $id ][ $singular ] = json_encode( \esc_url_raw( $image ) );
949
- }
950
-
951
- /**
952
- * Generate LD+Json search helper.
953
- *
954
- * @since 2.2.8
955
- * @since 2.9.3 Deprecated.
956
- * @deprecated
957
- *
958
- * @return escaped LD+json search helper string.
959
- */
960
- public function ld_json_search() {
961
-
962
- $tsf = \the_seo_framework();
963
-
964
- $tsf->_deprecated_function( 'the_seo_framework()->ld_json_search()', '2.9.3' );
965
-
966
- if ( false === $tsf->enable_ld_json_searchbox() )
967
- return '';
968
-
969
- $context = $this->schema_context();
970
- $webtype = $this->schema_type();
971
- $url = $this->schema_home_url();
972
- $name = $this->schema_blog_name();
973
- $actiontype = json_encode( 'SearchAction' );
974
-
975
- /**
976
- * Applies filters 'the_seo_framework_ld_json_search_url' : string
977
- * @since 2.7.0
978
- * @param string $search_url The default WordPress search URL without query parameters.
979
- */
980
- $search_url = (string) \apply_filters( 'the_seo_framework_ld_json_search_url', $tsf->the_home_url_from_cache( true ) . '?s=' );
981
-
982
- // Remove trailing quote and add it back.
983
- $target = mb_substr( json_encode( $search_url ), 0, -1 ) . '{search_term_string}"';
984
-
985
- $queryaction = json_encode( 'required name=search_term_string' );
986
-
987
- $json = sprintf( '{"@context":%s,"@type":%s,"url":%s,"name":%s,"potentialAction":{"@type":%s,"target":%s,"query-input":%s}}', $context, $webtype, $url, $name, $actiontype, $target, $queryaction );
988
-
989
- $output = '';
990
-
991
- if ( $json )
992
- $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
993
-
994
- return $output;
995
- }
996
-
997
- /**
998
- * Generate Site Name LD+Json script.
999
- *
1000
- * @since 2.6.0
1001
- * @since 2.9.3 Deprecated.
1002
- * @deprecated
1003
- *
1004
- * @return string The LD+JSon Site Name script.
1005
- */
1006
- public function ld_json_name() {
1007
-
1008
- $tsf = \the_seo_framework();
1009
-
1010
- $tsf->_deprecated_function( 'the_seo_framework()->ld_json_name()', '2.9.3' );
1011
-
1012
- if ( false === $tsf->enable_ld_json_sitename() )
1013
- return '';
1014
-
1015
- $context = $this->schema_context();
1016
- $webtype = $this->schema_type();
1017
- $url = $this->schema_home_url();
1018
- $name = $this->schema_blog_name();
1019
- $alternate = '';
1020
-
1021
- $blogname = $tsf->get_blogname();
1022
- $knowledge_name = $tsf->get_option( 'knowledge_name' );
1023
-
1024
- if ( $knowledge_name && $knowledge_name !== $blogname ) {
1025
- $alternate = json_encode( \esc_html( $knowledge_name ) );
1026
- }
1027
-
1028
- if ( $alternate ) {
1029
- $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"alternateName":%s,"url":%s}', $context, $webtype, $name, $alternate, $url );
1030
- } else {
1031
- $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s}', $context, $webtype, $name, $url );
1032
- }
1033
-
1034
- $output = '';
1035
- if ( $json )
1036
- $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
1037
-
1038
- return $output;
1039
- }
1040
-
1041
- /**
1042
- * Return LD+Json Knowledge Graph helper.
1043
- *
1044
- * @since 2.2.8
1045
- * @since 2.9.2 : Now grabs home URL from cache.
1046
- * @since 2.9.3 Deprecated.
1047
- * @deprecated
1048
- *
1049
- * @return string LD+json Knowledge Graph helper.
1050
- */
1051
- public function ld_json_knowledge() {
1052
-
1053
- $tsf = \the_seo_framework();
1054
-
1055
- $tsf->_deprecated_function( 'the_seo_framework()->ld_json_name()', '2.9.3', 'the_seo_framework()->get_ld_json_links()' );
1056
-
1057
- return $tsf->get_ld_json_links();
1058
- }
1059
-
1060
- /**
1061
- * Generate LD+Json breadcrumb helper.
1062
- *
1063
- * @since 2.4.2
1064
- * @since 2.9.3 Deprecated.
1065
- * @deprecated
1066
- *
1067
- * @return escaped LD+json search helper string.
1068
- */
1069
- public function ld_json_breadcrumbs() {
1070
-
1071
- $tsf = \the_seo_framework();
1072
-
1073
- $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumbs()', '2.9.3', 'the_seo_framework()->get_ld_json_breadcrumbs()' );
1074
-
1075
- return $tsf->get_ld_json_breadcrumbs();
1076
- }
1077
-
1078
- /**
1079
- * Generate post breadcrumb.
1080
- *
1081
- * @since 2.6.0
1082
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1083
- * @since 2.9.3 Deprecated.
1084
- * @deprecated
1085
- *
1086
- * @return string $output The breadcrumb script.
1087
- */
1088
- public function ld_json_breadcrumbs_post() {
1089
-
1090
- $tsf = \the_seo_framework();
1091
-
1092
- $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumbs_post()', '2.9.3', 'the_seo_framework()->get_ld_json_breadcrumbs_post()' );
1093
-
1094
- return $tsf->get_ld_json_breadcrumbs_post();
1095
- }
1096
-
1097
- /**
1098
- * Generate page breadcrumb.
1099
- *
1100
- * @since 2.6.0
1101
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1102
- * @since 2.9.3 Deprecated.
1103
- * @deprecated
1104
- *
1105
- * @return string $output The breadcrumb script.
1106
- */
1107
- public function ld_json_breadcrumbs_page() {
1108
-
1109
- $tsf = \the_seo_framework();
1110
-
1111
- $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumbs_page()', '2.9.3', 'the_seo_framework()->get_ld_json_breadcrumbs_page()' );
1112
-
1113
- return $tsf->get_ld_json_breadcrumbs_page();
1114
- }
1115
-
1116
- /**
1117
- * Return home page item for LD Json Breadcrumbs.
1118
- *
1119
- * @since 2.4.2
1120
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1121
- * @since 2.9.3 Deprecated.
1122
- * @deprecated
1123
- * @staticvar string $first_item.
1124
- *
1125
- * @param string|null $item_type the breadcrumb item type.
1126
- * @return string Home Breadcrumb item
1127
- */
1128
- public function ld_json_breadcrumb_first( $item_type = null ) {
1129
-
1130
- $tsf = \the_seo_framework();
1131
-
1132
- $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumb_first()', '2.9.3' );
1133
-
1134
- static $first_item = null;
1135
-
1136
- if ( isset( $first_item ) )
1137
- return $first_item;
1138
-
1139
- if ( is_null( $item_type ) )
1140
- $item_type = json_encode( 'ListItem' );
1141
-
1142
- $id = json_encode( $tsf->the_home_url_from_cache() );
1143
-
1144
- if ( $tsf->ld_json_breadcrumbs_use_seo_title() ) {
1145
-
1146
- $home_title = $tsf->get_option( 'homepage_title' );
1147
-
1148
- if ( $home_title ) {
1149
- $custom_name = $home_title;
1150
- } elseif ( $tsf->has_page_on_front() ) {
1151
- $home_id = (int) \get_option( 'page_on_front' );
1152
-
1153
- $custom_name = $tsf->get_custom_field( '_genesis_title', $home_id ) ?: $tsf->get_blogname();
1154
- } else {
1155
- $custom_name = $tsf->get_blogname();
1156
- }
1157
- } else {
1158
- $custom_name = $tsf->get_blogname();
1159
- }
1160
-
1161
- $custom_name = json_encode( $custom_name );
1162
- $image = $this->schema_image( $tsf->get_the_front_page_ID(), true );
1163
-
1164
- $breadcrumb = array(
1165
- 'type' => $item_type,
1166
- 'pos' => '1',
1167
- 'id' => $id,
1168
- 'name' => $custom_name,
1169
- 'image' => $image,
1170
- );
1171
-
1172
- return $first_item = $tsf->make_breadcrumb( $breadcrumb, true );
1173
- }
1174
-
1175
- /**
1176
- * Return current page item for LD Json Breadcrumbs.
1177
- *
1178
- * @since 2.4.2
1179
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1180
- * @since 2.9.3 Deprecated.
1181
- * @deprecated
1182
- * @staticvar string $last_item.
1183
- * @staticvar string $type The breadcrumb item type.
1184
- * @staticvar string $id The current post/page/archive url.
1185
- * @staticvar string $name The current post/page/archive title.
1186
- *
1187
- * @param string $item_type the breadcrumb item type.
1188
- * @param int $pos Last known position.
1189
- * @param int $post_id The current Post ID
1190
- * @return string Last Breadcrumb item
1191
- */
1192
- public function ld_json_breadcrumb_last( $item_type = null, $pos = null, $post_id = null ) {
1193
-
1194
- $tsf = \the_seo_framework();
1195
-
1196
- $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumb_last()', '2.9.3' );
1197
-
1198
- /**
1199
- * 2 (becomes 3) holds mostly true for single term items.
1200
- * This shouldn't run anyway. Pos should always be provided.
1201
- */
1202
- if ( is_null( $pos ) )
1203
- $pos = 2;
1204
-
1205
- //* Add current page.
1206
- $pos = $pos + 1;
1207
-
1208
- if ( is_null( $item_type ) ) {
1209
- static $type = null;
1210
-
1211
- if ( ! isset( $type ) )
1212
- $type = json_encode( 'ListItem' );
1213
-
1214
- $item_type = $type;
1215
- }
1216
-
1217
- if ( empty( $post_id ) )
1218
- $post_id = $tsf->get_the_real_ID();
1219
-
1220
- static $id = null;
1221
- static $name = null;
1222
-
1223
- if ( ! isset( $id ) )
1224
- $id = json_encode( $tsf->the_url_from_cache() );
1225
-
1226
- $title_args = array(
1227
- 'term_id' => $post_id,
1228
- 'placeholder' => true,
1229
- 'meta' => true,
1230
- 'notagline' => true,
1231
- 'description_title' => true,
1232
- 'get_custom_field' => false,
1233
- );
1234
-
1235
- if ( ! isset( $name ) ) {
1236
- if ( $tsf->ld_json_breadcrumbs_use_seo_title() ) {
1237
- $name = $tsf->get_custom_field( '_genesis_title', $post_id ) ?: $tsf->title( '', '', '', $title_args );
1238
- } else {
1239
- $name = $tsf->title( '', '', '', $title_args );
1240
- }
1241
- $name = json_encode( $name );
1242
- }
1243
-
1244
- $image = $this->schema_image( $post_id, true );
1245
-
1246
- $breadcrumb = array(
1247
- 'type' => $item_type,
1248
- 'pos' => (string) $pos,
1249
- 'id' => $id,
1250
- 'name' => $name,
1251
- 'image' => $image,
1252
- );
1253
-
1254
- return $this->make_breadcrumb( $breadcrumb, false );
1255
- }
1256
-
1257
- /**
1258
- * Builds a breadcrumb.
1259
- *
1260
- * @since 2.6.0
1261
- * @since 2.9.0 : No longer outputs image if it's not present.
1262
- * @since 2.9.3 Deprecated.
1263
- * @deprecated
1264
- *
1265
- * @param array $item : {
1266
- * 'type',
1267
- * 'pos',
1268
- * 'id',
1269
- * 'name'
1270
- * }
1271
- * @param bool $comma Whether to add a trailing comma.
1272
- * @return string The LD+Json breadcrumb.
1273
- */
1274
- public function make_breadcrumb( $item, $comma = true ) {
1275
-
1276
- $tsf = \the_seo_framework();
1277
-
1278
- $tsf->_deprecated_function( 'the_seo_framework()->make_breadcrumb()', '2.9.3' );
1279
-
1280
- $comma = $comma ? ',' : '';
1281
-
1282
- if ( $item['image'] && '""' !== $item['image'] ) {
1283
- $retval = sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s,"image":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $item['image'], $comma );
1284
- } else {
1285
- $retval = sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $comma );
1286
- }
1287
-
1288
- return $retval;
1289
- }
1290
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 - 2017 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 deprecated.
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
+
506
+ /**
507
+ * Fetches og:image URL.
508
+ *
509
+ * @since 2.2.2
510
+ * @since 2.2.8 : Added theme icon detection.
511
+ * @since 2.5.2 : Added args filters.
512
+ * @since 2.8.0 : 1. Added theme logo detection.
513
+ * 2. Added inpost image selection detection.
514
+ * @since 2.8.2 : 1. Now returns something on post ID 0.
515
+ * 2. Added SEO settings fallback image selection detection.
516
+ * @since 2.9.0 : 1. Added 'skip_fallback' option to arguments.
517
+ * 2. Added 'escape' option to arguments.
518
+ * 3. First parameter is now arguments. Fallback for integer is added.
519
+ * 4. Second parameter is now deprecated.
520
+ * 5. Deprecated.
521
+ * @deprecated Use get_social_image instead.
522
+ *
523
+ * @param int|array $args The image arguments.
524
+ * Was: $post_id.
525
+ * Warning: Integer usage is only used for backwards compat.
526
+ * @param array $depr_args, Deprecated;
527
+ * Was $args The image arguments.
528
+ * @param bool $escape Whether to escape the image URL.
529
+ * Deprecated: You should use $args['escape'].
530
+ * @return string the image URL.
531
+ */
532
+ public function get_image( $args = array(), $depr_args = '', $depr_escape = true ) {
533
+
534
+ $tsf = \the_seo_framework();
535
+
536
+ $tsf->_deprecated_function( 'the_seo_framework()->get_image()', '2.9.0', 'the_seo_framework()->get_social_image()' );
537
+
538
+ if ( is_int( $args ) || is_array( $depr_args ) ) {
539
+ $tsf->_doing_it_wrong( __METHOD__, 'First parameter is now used for arguments. Second parameter is deprecated.', '2.9.0' );
540
+
541
+ $post_id = $args;
542
+ $args = array();
543
+
544
+ /**
545
+ * Backwards compat with parse args.
546
+ * @since 2.5.0
547
+ */
548
+ if ( ! isset( $depr_args['post_id'] ) ) {
549
+ $args['post_id'] = $post_id ?: ( $tsf->is_singular( $post_id ) ? $tsf->get_the_real_ID() : 0 );
550
+ }
551
+
552
+ if ( is_array( $depr_args ) ) {
553
+ $args = \wp_parse_args( $depr_args, $args );
554
+ }
555
+ }
556
+
557
+ if ( false === $depr_escape ) {
558
+ $tsf->_doing_it_wrong( __METHOD__, 'Third parameter has been deprecated. Use `$args["escape"] => false` instead.', '2.9.0' );
559
+ $args['escape'] = false;
560
+ }
561
+
562
+ $args = $tsf->reparse_image_args( $args );
563
+
564
+ //* 0. Image from argument.
565
+ pre_0 : {
566
+ if ( $image = $args['image'] )
567
+ goto end;
568
+ }
569
+
570
+ //* Check if there are no disallowed arguments.
571
+ $all_allowed = empty( $args['disallowed'] );
572
+
573
+ //* 1. Fetch image from homepage SEO meta upload.
574
+ if ( $all_allowed || false === in_array( 'homemeta', $args['disallowed'], true ) ) {
575
+ if ( $image = $tsf->get_social_image_url_from_home_meta( $args['post_id'], true ) )
576
+ goto end;
577
+ }
578
+
579
+ if ( $args['post_id'] ) {
580
+ //* 2. Fetch image from SEO meta upload.
581
+ if ( $all_allowed || false === in_array( 'postmeta', $args['disallowed'], true ) ) {
582
+ if ( $image = $tsf->get_social_image_url_from_post_meta( $args['post_id'], true ) )
583
+ goto end;
584
+ }
585
+
586
+ //* 3. Fetch image from featured.
587
+ if ( $all_allowed || false === in_array( 'featured', $args['disallowed'], true ) ) {
588
+ if ( $image = $tsf->get_image_from_post_thumbnail( $args, true ) )
589
+ goto end;
590
+ }
591
+ }
592
+
593
+ if ( $args['skip_fallback'] )
594
+ goto end;
595
+
596
+ //* 4. Fetch image from SEO settings
597
+ if ( $all_allowed || false === in_array( 'option', $args['disallowed'], true ) ) {
598
+ if ( $image = $tsf->get_social_image_url_from_seo_settings( true ) )
599
+ goto end;
600
+ }
601
+
602
+ //* 5. Fetch image from fallback filter 1
603
+ /**
604
+ * Applies filters 'the_seo_framework_og_image_after_featured' : string
605
+ * @since 2.5.2
606
+ */
607
+ fallback_1 : {
608
+ if ( $image = (string) \apply_filters( 'the_seo_framework_og_image_after_featured', '', $args['post_id'] ) )
609
+ goto end;
610
+ }
611
+
612
+ //* 6. Fallback: Get header image if exists
613
+ if ( ( $all_allowed || false === in_array( 'header', $args['disallowed'], true ) ) && \current_theme_supports( 'custom-header', 'default-image' ) ) {
614
+ if ( $image = $tsf->get_header_image( true ) )
615
+ goto end;
616
+ }
617
+
618
+ //* 7. Fetch image from fallback filter 2
619
+ /**
620
+ * Applies filters 'the_seo_framework_og_image_after_header' : string
621
+ * @since 2.5.2
622
+ */
623
+ fallback_2 : {
624
+ if ( $image = (string) \apply_filters( 'the_seo_framework_og_image_after_header', '', $args['post_id'] ) )
625
+ goto end;
626
+ }
627
+
628
+ //* 8. Get the WP 4.5 Site Logo
629
+ if ( ( $all_allowed || false === in_array( 'logo', $args['disallowed'], true ) ) && $tsf->can_use_logo() ) {
630
+ if ( $image = $tsf->get_site_logo( true ) )
631
+ goto end;
632
+ }
633
+
634
+ //* 9. Get the WP 4.3 Site Icon
635
+ if ( $all_allowed || false === in_array( 'icon', $args['disallowed'], true ) ) {
636
+ if ( $image = $tsf->get_site_icon( 'full', true ) )
637
+ goto end;
638
+ }
639
+
640
+ end :;
641
+
642
+ if ( $args['escape'] && $image )
643
+ $image = \esc_url( $image );
644
+
645
+ return (string) $image;
646
+ }
647
+
648
+ /**
649
+ * Fetches image from post thumbnail.
650
+ * Resizes the image between 4096px if bigger. Then it saves the image and
651
+ * Keeps dimensions relative.
652
+ *
653
+ * @since 2.3.0
654
+ * @since 2.9.0 Changed parameters.
655
+ * @since 2.9.0 Deprecated.
656
+ * @since 2.9.3 Now supports 4K, rather than 1500px.
657
+ * @deprecated
658
+ *
659
+ * @param array $args The image args.
660
+ * Was: int $id The post/page ID.
661
+ * @param bool $set_og_dimensions Whether to set Open Graph image dimensions.
662
+ * Was: array $depr_args Deprecated. Image arguments.
663
+ * @return string|null the image url.
664
+ */
665
+ public function get_image_from_post_thumbnail( $args = array(), $set_og_dimensions = false ) {
666
+
667
+ $tsf = \the_seo_framework();
668
+
669
+ $tsf->_deprecated_function( 'the_seo_framework()->get_image_from_post_thumbnail()', '2.9.0', 'the_seo_framework()->get_social_image_url_from_post_thumbnail()' );
670
+
671
+ if ( is_array( $set_og_dimensions ) ) {
672
+ $tsf->_doing_it_wrong( __METHOD__, 'First parameter are now arguments, second parameter is for setting og dimensions.', '2.9.0' );
673
+ $args = $set_og_dimensions;
674
+ $set_og_dimensions = false;
675
+ }
676
+
677
+ $args = $tsf->reparse_image_args( $args );
678
+
679
+ $id = \get_post_thumbnail_id( $args['post_id'] );
680
+
681
+ $args['get_the_real_ID'] = true;
682
+
683
+ $image = $id ? $tsf->parse_og_image( $id, $args, $set_og_dimensions ) : '';
684
+
685
+ return $image;
686
+ }
687
+
688
+ /**
689
+ * Detects front page.
690
+ *
691
+ * Returns true on SEO settings page if ID is 0.
692
+ *
693
+ * @since 2.6.0
694
+ * @since 2.9.0: Deprecated.
695
+ * @deprecated
696
+ *
697
+ * @param int $id The Page or Post ID.
698
+ * @return bool
699
+ */
700
+ public function is_front_page( $id = 0 ) {
701
+
702
+ $tsf = \the_seo_framework();
703
+
704
+ $tsf->_deprecated_function( 'the_seo_framework()->is_front_page()', '2.9.0', 'the_seo_framework()->is_real_front_page() or the_seo_framework()->is_front_page_by_id()' );
705
+
706
+ static $cache = array();
707
+
708
+ if ( null !== $cache = $tsf->get_query_cache( __METHOD__, null, $id ) )
709
+ return $cache;
710
+
711
+ $is_front_page = false;
712
+
713
+ if ( \is_front_page() && empty( $id ) )
714
+ $is_front_page = true;
715
+
716
+ //* Elegant Themes Support. Yay.
717
+ if ( false === $is_front_page && empty( $id ) && $tsf->is_home() ) {
718
+ $sof = \get_option( 'show_on_front' );
719
+
720
+ if ( 'page' !== $sof && 'posts' !== $sof )
721
+ $is_front_page = true;
722
+ }
723
+
724
+ //* Compare against $id
725
+ if ( false === $is_front_page && $id ) {
726
+ $sof = \get_option( 'show_on_front' );
727
+
728
+ if ( 'page' === $sof && (int) \get_option( 'page_on_front' ) === $id )
729
+ $is_front_page = true;
730
+
731
+ if ( 'posts' === $sof && (int) \get_option( 'page_for_posts' ) === $id )
732
+ $is_front_page = true;
733
+ } elseif ( empty( $id ) && $tsf->is_seo_settings_page() ) {
734
+ $is_front_page = true;
735
+ }
736
+
737
+ $tsf->set_query_cache(
738
+ __METHOD__,
739
+ $is_front_page,
740
+ $id
741
+ );
742
+
743
+ return $is_front_page;
744
+ }
745
+
746
+ /**
747
+ * Returns http://schema.org json encoded context URL.
748
+ *
749
+ * @staticvar string $context
750
+ * @since 2.6.0
751
+ * @since 2.9.3 Deprecated.
752
+ * @deprecated
753
+ *
754
+ * @return string The json encoded context url.
755
+ */
756
+ public function schema_context() {
757
+
758
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_context()', '2.9.3' );
759
+
760
+ static $context;
761
+
762
+ if ( isset( $context ) )
763
+ return $context;
764
+
765
+ return $context = json_encode( 'http://schema.org' );
766
+ }
767
+
768
+
769
+ /**
770
+ * Returns 'WebSite' json encoded type name.
771
+ *
772
+ * @staticvar string $context
773
+ * @since 2.6.0
774
+ * @since 2.9.3 Deprecated.
775
+ * @deprecated
776
+ *
777
+ * @return string The json encoded type name.
778
+ */
779
+ public function schema_type() {
780
+
781
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_type()', '2.9.3' );
782
+
783
+ static $type;
784
+
785
+ if ( isset( $type ) )
786
+ return $type;
787
+
788
+ return $type = json_encode( 'WebSite' );
789
+ }
790
+
791
+ /**
792
+ * Returns json encoded home url.
793
+ *
794
+ * @staticvar string $url
795
+ * @since 2.6.0
796
+ * @since 2.9.3 Deprecated.
797
+ * @deprecated
798
+ *
799
+ * @return string The json encoded home url.
800
+ */
801
+ public function schema_home_url() {
802
+
803
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_home_url()', '2.9.3' );
804
+
805
+ static $type;
806
+
807
+ if ( isset( $type ) )
808
+ return $type;
809
+
810
+ return $type = json_encode( \the_seo_framework()->the_home_url_from_cache() );
811
+ }
812
+
813
+ /**
814
+ * Returns json encoded blogname.
815
+ *
816
+ * @staticvar string $name
817
+ * @since 2.6.0
818
+ * @since 2.9.3 Deprecated.
819
+ * @deprecated
820
+ *
821
+ * @return string The json encoded blogname.
822
+ */
823
+ public function schema_blog_name() {
824
+
825
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_blog_name()', '2.9.3' );
826
+
827
+ static $name;
828
+
829
+ if ( isset( $name ) )
830
+ return $name;
831
+
832
+ return $name = json_encode( \the_seo_framework()->get_blogname() );
833
+ }
834
+
835
+ /**
836
+ * Returns 'BreadcrumbList' json encoded type name.
837
+ *
838
+ * @staticvar string $crumblist
839
+ * @since 2.6.0
840
+ * @since 2.9.3 Deprecated.
841
+ * @deprecated
842
+ *
843
+ * @return string The json encoded 'BreadcrumbList'.
844
+ */
845
+ public function schema_breadcrumblist() {
846
+
847
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_breadcrumblist()', '2.9.3' );
848
+
849
+ static $crumblist;
850
+
851
+ if ( isset( $crumblist ) )
852
+ return $crumblist;
853
+
854
+ return $crumblist = json_encode( 'BreadcrumbList' );
855
+ }
856
+
857
+ /**
858
+ * Returns 'ListItem' json encoded type name.
859
+ *
860
+ * @staticvar string $listitem
861
+ * @since 2.6.0
862
+ * @since 2.9.3 Deprecated.
863
+ * @deprecated
864
+ *
865
+ * @return string The json encoded 'ListItem'.
866
+ */
867
+ public function schema_listitem() {
868
+
869
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->schema_listitem()', '2.9.3' );
870
+
871
+ static $listitem;
872
+
873
+ if ( isset( $listitem ) )
874
+ return $listitem;
875
+
876
+ return $listitem = json_encode( 'ListItem' );
877
+ }
878
+
879
+ /**
880
+ * Returns 'image' json encoded value.
881
+ *
882
+ * @staticvar array $images
883
+ * @since 2.7.0
884
+ * @since 2.9.0 : 1. No longer uses image from cache, instead: it skips fallback images.
885
+ * 2. Can now fetch home-page as blog set image.
886
+ * @since 2.9.3 Deprecated.
887
+ * @deprecated
888
+ *
889
+ * @param int|string $id The page, post, product or term ID.
890
+ * @param bool $singular Whether the ID is singular.
891
+ */
892
+ public function schema_image( $id = 0, $singular = false ) {
893
+
894
+ $tsf = \the_seo_framework();
895
+
896
+ $tsf->_deprecated_function( 'the_seo_framework()->schema_image()', '2.9.3' );
897
+
898
+ static $images = array();
899
+
900
+ $id = (int) $id;
901
+
902
+ if ( isset( $images[ $id ][ $singular ] ) )
903
+ return $images[ $id ][ $singular ];
904
+
905
+ $image = '';
906
+
907
+ if ( $singular ) {
908
+ if ( $id === $tsf->get_the_front_page_ID() ) {
909
+ if ( $tsf->has_page_on_front() ) {
910
+ $image_args = array(
911
+ 'post_id' => $id,
912
+ 'skip_fallback' => true,
913
+ );
914
+ } else {
915
+ $image_args = array(
916
+ 'post_id' => $id,
917
+ 'skip_fallback' => true,
918
+ 'disallowed' => array(
919
+ 'postmeta',
920
+ 'featured',
921
+ ),
922
+ );
923
+ }
924
+ } else {
925
+ $image_args = array(
926
+ 'post_id' => $id,
927
+ 'skip_fallback' => true,
928
+ 'disallowed' => array(
929
+ 'homemeta'
930
+ ),
931
+ );
932
+ }
933
+ $image = $tsf->get_social_image( $image_args );
934
+ } else {
935
+ //* Placeholder.
936
+ $image = '';
937
+ }
938
+
939
+ /**
940
+ * Applies filters 'the_seo_framework_ld_json_breadcrumb_image' : string
941
+ * @since 2.7.0
942
+ * @param string $image The current image.
943
+ * @param int $id The page, post, product or term ID.
944
+ * @param bool $singular Whether the ID is singular.
945
+ */
946
+ $image = \apply_filters( 'the_seo_framework_ld_json_breadcrumb_image', $image, $id, $singular );
947
+
948
+ return $images[ $id ][ $singular ] = json_encode( \esc_url_raw( $image ) );
949
+ }
950
+
951
+ /**
952
+ * Generate LD+Json search helper.
953
+ *
954
+ * @since 2.2.8
955
+ * @since 2.9.3 Deprecated.
956
+ * @deprecated
957
+ *
958
+ * @return escaped LD+json search helper string.
959
+ */
960
+ public function ld_json_search() {
961
+
962
+ $tsf = \the_seo_framework();
963
+
964
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_search()', '2.9.3' );
965
+
966
+ if ( false === $tsf->enable_ld_json_searchbox() )
967
+ return '';
968
+
969
+ $context = $this->schema_context();
970
+ $webtype = $this->schema_type();
971
+ $url = $this->schema_home_url();
972
+ $name = $this->schema_blog_name();
973
+ $actiontype = json_encode( 'SearchAction' );
974
+
975
+ /**
976
+ * Applies filters 'the_seo_framework_ld_json_search_url' : string
977
+ * @since 2.7.0
978
+ * @param string $search_url The default WordPress search URL without query parameters.
979
+ */
980
+ $search_url = (string) \apply_filters( 'the_seo_framework_ld_json_search_url', $tsf->the_home_url_from_cache( true ) . '?s=' );
981
+
982
+ // Remove trailing quote and add it back.
983
+ $target = mb_substr( json_encode( $search_url ), 0, -1 ) . '{search_term_string}"';
984
+
985
+ $queryaction = json_encode( 'required name=search_term_string' );
986
+
987
+ $json = sprintf( '{"@context":%s,"@type":%s,"url":%s,"name":%s,"potentialAction":{"@type":%s,"target":%s,"query-input":%s}}', $context, $webtype, $url, $name, $actiontype, $target, $queryaction );
988
+
989
+ $output = '';
990
+
991
+ if ( $json )
992
+ $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
993
+
994
+ return $output;
995
+ }
996
+
997
+ /**
998
+ * Generate Site Name LD+Json script.
999
+ *
1000
+ * @since 2.6.0
1001
+ * @since 2.9.3 Deprecated.
1002
+ * @deprecated
1003
+ *
1004
+ * @return string The LD+JSon Site Name script.
1005
+ */
1006
+ public function ld_json_name() {
1007
+
1008
+ $tsf = \the_seo_framework();
1009
+
1010
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_name()', '2.9.3' );
1011
+
1012
+ $context = $this->schema_context();
1013
+ $webtype = $this->schema_type();
1014
+ $url = $this->schema_home_url();
1015
+ $name = $this->schema_blog_name();
1016
+ $alternate = '';
1017
+
1018
+ $blogname = $tsf->get_blogname();
1019
+ $knowledge_name = $tsf->get_option( 'knowledge_name' );
1020
+
1021
+ if ( $knowledge_name && $knowledge_name !== $blogname ) {
1022
+ $alternate = json_encode( \esc_html( $knowledge_name ) );
1023
+ }
1024
+
1025
+ if ( $alternate ) {
1026
+ $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"alternateName":%s,"url":%s}', $context, $webtype, $name, $alternate, $url );
1027
+ } else {
1028
+ $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s}', $context, $webtype, $name, $url );
1029
+ }
1030
+
1031
+ $output = '';
1032
+ if ( $json )
1033
+ $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
1034
+
1035
+ return $output;
1036
+ }
1037
+
1038
+ /**
1039
+ * Return LD+Json Knowledge Graph helper.
1040
+ *
1041
+ * @since 2.2.8
1042
+ * @since 2.9.2 : Now grabs home URL from cache.
1043
+ * @since 2.9.3 Deprecated.
1044
+ * @deprecated
1045
+ *
1046
+ * @return string LD+json Knowledge Graph helper.
1047
+ */
1048
+ public function ld_json_knowledge() {
1049
+
1050
+ $tsf = \the_seo_framework();
1051
+
1052
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_name()', '2.9.3', 'the_seo_framework()->get_ld_json_links()' );
1053
+
1054
+ return $tsf->get_ld_json_links();
1055
+ }
1056
+
1057
+ /**
1058
+ * Generate LD+Json breadcrumb helper.
1059
+ *
1060
+ * @since 2.4.2
1061
+ * @since 2.9.3 Deprecated.
1062
+ * @deprecated
1063
+ *
1064
+ * @return escaped LD+json search helper string.
1065
+ */
1066
+ public function ld_json_breadcrumbs() {
1067
+
1068
+ $tsf = \the_seo_framework();
1069
+
1070
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumbs()', '2.9.3', 'the_seo_framework()->get_ld_json_breadcrumbs()' );
1071
+
1072
+ return $tsf->get_ld_json_breadcrumbs();
1073
+ }
1074
+
1075
+ /**
1076
+ * Generate post breadcrumb.
1077
+ *
1078
+ * @since 2.6.0
1079
+ * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1080
+ * @since 2.9.3 Deprecated.
1081
+ * @deprecated
1082
+ *
1083
+ * @return string $output The breadcrumb script.
1084
+ */
1085
+ public function ld_json_breadcrumbs_post() {
1086
+
1087
+ $tsf = \the_seo_framework();
1088
+
1089
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumbs_post()', '2.9.3', 'the_seo_framework()->get_ld_json_breadcrumbs_post()' );
1090
+
1091
+ return $tsf->get_ld_json_breadcrumbs_post();
1092
+ }
1093
+
1094
+ /**
1095
+ * Generate page breadcrumb.
1096
+ *
1097
+ * @since 2.6.0
1098
+ * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1099
+ * @since 2.9.3 Deprecated.
1100
+ * @deprecated
1101
+ *
1102
+ * @return string $output The breadcrumb script.
1103
+ */
1104
+ public function ld_json_breadcrumbs_page() {
1105
+
1106
+ $tsf = \the_seo_framework();
1107
+
1108
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumbs_page()', '2.9.3', 'the_seo_framework()->get_ld_json_breadcrumbs_page()' );
1109
+
1110
+ return $tsf->get_ld_json_breadcrumbs_page();
1111
+ }
1112
+
1113
+ /**
1114
+ * Return home page item for LD Json Breadcrumbs.
1115
+ *
1116
+ * @since 2.4.2
1117
+ * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1118
+ * @since 2.9.3 Deprecated.
1119
+ * @deprecated
1120
+ * @staticvar string $first_item.
1121
+ *
1122
+ * @param string|null $item_type the breadcrumb item type.
1123
+ * @return string Home Breadcrumb item
1124
+ */
1125
+ public function ld_json_breadcrumb_first( $item_type = null ) {
1126
+
1127
+ $tsf = \the_seo_framework();
1128
+
1129
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumb_first()', '2.9.3' );
1130
+
1131
+ static $first_item = null;
1132
+
1133
+ if ( isset( $first_item ) )
1134
+ return $first_item;
1135
+
1136
+ if ( is_null( $item_type ) )
1137
+ $item_type = json_encode( 'ListItem' );
1138
+
1139
+ $id = json_encode( $tsf->the_home_url_from_cache() );
1140
+
1141
+ if ( $tsf->ld_json_breadcrumbs_use_seo_title() ) {
1142
+
1143
+ $home_title = $tsf->get_option( 'homepage_title' );
1144
+
1145
+ if ( $home_title ) {
1146
+ $custom_name = $home_title;
1147
+ } elseif ( $tsf->has_page_on_front() ) {
1148
+ $home_id = (int) \get_option( 'page_on_front' );
1149
+
1150
+ $custom_name = $tsf->get_custom_field( '_genesis_title', $home_id ) ?: $tsf->get_blogname();
1151
+ } else {
1152
+ $custom_name = $tsf->get_blogname();
1153
+ }
1154
+ } else {
1155
+ $custom_name = $tsf->get_blogname();
1156
+ }
1157
+
1158
+ $custom_name = json_encode( $custom_name );
1159
+ $image = $this->schema_image( $tsf->get_the_front_page_ID(), true );
1160
+
1161
+ $breadcrumb = array(
1162
+ 'type' => $item_type,
1163
+ 'pos' => '1',
1164
+ 'id' => $id,
1165
+ 'name' => $custom_name,
1166
+ 'image' => $image,
1167
+ );
1168
+
1169
+ return $first_item = $tsf->make_breadcrumb( $breadcrumb, true );
1170
+ }
1171
+
1172
+ /**
1173
+ * Return current page item for LD Json Breadcrumbs.
1174
+ *
1175
+ * @since 2.4.2
1176
+ * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
1177
+ * @since 2.9.3 Deprecated.
1178
+ * @deprecated
1179
+ * @staticvar string $last_item.
1180
+ * @staticvar string $type The breadcrumb item type.
1181
+ * @staticvar string $id The current post/page/archive url.
1182
+ * @staticvar string $name The current post/page/archive title.
1183
+ *
1184
+ * @param string $item_type the breadcrumb item type.
1185
+ * @param int $pos Last known position.
1186
+ * @param int $post_id The current Post ID
1187
+ * @return string Last Breadcrumb item
1188
+ */
1189
+ public function ld_json_breadcrumb_last( $item_type = null, $pos = null, $post_id = null ) {
1190
+
1191
+ $tsf = \the_seo_framework();
1192
+
1193
+ $tsf->_deprecated_function( 'the_seo_framework()->ld_json_breadcrumb_last()', '2.9.3' );
1194
+
1195
+ /**
1196
+ * 2 (becomes 3) holds mostly true for single term items.
1197
+ * This shouldn't run anyway. Pos should always be provided.
1198
+ */
1199
+ if ( is_null( $pos ) )
1200
+ $pos = 2;
1201
+
1202
+ //* Add current page.
1203
+ $pos = $pos + 1;
1204
+
1205
+ if ( is_null( $item_type ) ) {
1206
+ static $type = null;
1207
+
1208
+ if ( ! isset( $type ) )
1209
+ $type = json_encode( 'ListItem' );
1210
+
1211
+ $item_type = $type;
1212
+ }
1213
+
1214
+ if ( empty( $post_id ) )
1215
+ $post_id = $tsf->get_the_real_ID();
1216
+
1217
+ static $id = null;
1218
+ static $name = null;
1219
+
1220
+ if ( ! isset( $id ) )
1221
+ $id = json_encode( $tsf->the_url_from_cache() );
1222
+
1223
+ $title_args = array(
1224
+ 'term_id' => $post_id,
1225
+ 'placeholder' => true,
1226
+ 'meta' => true,
1227
+ 'notagline' => true,
1228
+ 'description_title' => true,
1229
+ 'get_custom_field' => false,
1230
+ );
1231
+
1232
+ if ( ! isset( $name ) ) {
1233
+ if ( $tsf->ld_json_breadcrumbs_use_seo_title() ) {
1234
+ $name = $tsf->get_custom_field( '_genesis_title', $post_id ) ?: $tsf->title( '', '', '', $title_args );
1235
+ } else {
1236
+ $name = $tsf->title( '', '', '', $title_args );
1237
+ }
1238
+ $name = json_encode( $name );
1239
+ }
1240
+
1241
+ $image = $this->schema_image( $post_id, true );
1242
+
1243
+ $breadcrumb = array(
1244
+ 'type' => $item_type,
1245
+ 'pos' => (string) $pos,
1246
+ 'id' => $id,
1247
+ 'name' => $name,
1248
+ 'image' => $image,
1249
+ );
1250
+
1251
+ return $this->make_breadcrumb( $breadcrumb, false );
1252
+ }
1253
+
1254
+ /**
1255
+ * Builds a breadcrumb.
1256
+ *
1257
+ * @since 2.6.0
1258
+ * @since 2.9.0 : No longer outputs image if it's not present.
1259
+ * @since 2.9.3 Deprecated.
1260
+ * @deprecated
1261
+ *
1262
+ * @param array $item : {
1263
+ * 'type',
1264
+ * 'pos',
1265
+ * 'id',
1266
+ * 'name'
1267
+ * }
1268
+ * @param bool $comma Whether to add a trailing comma.
1269
+ * @return string The LD+Json breadcrumb.
1270
+ */
1271
+ public function make_breadcrumb( $item, $comma = true ) {
1272
+
1273
+ $tsf = \the_seo_framework();
1274
+
1275
+ $tsf->_deprecated_function( 'the_seo_framework()->make_breadcrumb()', '2.9.3' );
1276
+
1277
+ $comma = $comma ? ',' : '';
1278
+
1279
+ if ( $item['image'] && '""' !== $item['image'] ) {
1280
+ $retval = sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s,"image":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $item['image'], $comma );
1281
+ } else {
1282
+ $retval = sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $comma );
1283
+ }
1284
+
1285
+ return $retval;
1286
+ }
1287
+
1288
+ /**
1289
+ * Fetch set Term data.
1290
+ *
1291
+ * @since 2.6.0
1292
+ * @since 2.7.0 Handles term object differently for upgraded database.
1293
+ * @since 3.0.0 Deprecated.
1294
+ *
1295
+ * @deprecated.
1296
+ *
1297
+ * @param object|null $term The TT object, if it isn't set, one is fetched.
1298
+ * @param int $term_id The term object.
1299
+ * @return array The SEO Framework TT data.
1300
+ */
1301
+ public function get_term_data( $term = null, $term_id = 0 ) {
1302
+
1303
+ $tsf = \the_seo_framework();
1304
+
1305
+ $tsf->_deprecated_function( 'the_seo_framework()->get_term_data( $term, $term_id )', '3.0.0', 'the_seo_framework()->get_term_meta( $term_id )' );
1306
+
1307
+ if ( is_null( $term ) )
1308
+ $term = $tsf->fetch_the_term( $term_id );
1309
+
1310
+ if ( isset( $term->term_id ) )
1311
+ return $tsf->get_term_meta( $term->term_id );
1312
+
1313
+ //* Return null if no term can be set.
1314
+ return null;
1315
+ }
1316
+
1317
+ /**
1318
+ * Creates canonical URL.
1319
+ *
1320
+ * @since 2.0.0
1321
+ * @since 2.4.2 : Refactored arguments
1322
+ * @since 2.8.0 : No longer tolerates $id as Post object.
1323
+ * @since 2.9.0 : When using 'home => true' args parameter, the home path is added when set.
1324
+ * @since 2.9.2 Added filter usage cache.
1325
+ * @since 3.0.0 Deprecated.
1326
+ * @deprecated
1327
+ * @staticvar array $_has_filters
1328
+ *
1329
+ * @param string $url the url
1330
+ * @param array $args : accepted args : {
1331
+ * @param bool $paged Return current page URL without pagination if false
1332
+ * @param bool $paged_plural Whether to add pagination for the second or later page.
1333
+ * @param bool $from_option Get the canonical uri option
1334
+ * @param object $post The Post Object.
1335
+ * @param bool $external Whether to fetch the current WP Request or get the permalink by Post Object.
1336
+ * @param bool $is_term Fetch url for term.
1337
+ * @param object $term The term object.
1338
+ * @param bool $home Fetch home URL.
1339
+ * @param bool $forceslash Fetch home URL and slash it, always.
1340
+ * @param int $id The Page or Term ID.
1341
+ * }
1342
+ * @return string Escape url.
1343
+ */
1344
+ public function the_url( $url = '', $args = array() ) {
1345
+
1346
+ $tsf = \the_seo_framework();
1347
+
1348
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->the_url()', '3.0.0', 'the_seo_framework()->get_canonical_url()' );
1349
+
1350
+ $args = $tsf->reparse_url_args( $args );
1351
+
1352
+ /**
1353
+ * Fetch permalink if Feed.
1354
+ * @since 2.5.2
1355
+ */
1356
+ if ( $tsf->is_feed() )
1357
+ $url = \get_permalink();
1358
+
1359
+ //* Reset cache.
1360
+ $tsf->url_slashit = true;
1361
+ $tsf->unset_current_subdomain();
1362
+ $tsf->current_host = '';
1363
+
1364
+ $path = '';
1365
+ $scheme = '';
1366
+ $slashit = true;
1367
+
1368
+ if ( false === $args['home'] && empty( $url ) ) {
1369
+ /**
1370
+ * Get URL from options.
1371
+ * @since 2.2.9
1372
+ */
1373
+ if ( $args['get_custom_field'] && $tsf->is_singular() ) {
1374
+ $custom_url = $tsf->get_custom_field( '_genesis_canonical_uri' );
1375
+
1376
+ if ( $custom_url ) {
1377
+ $url = $custom_url;
1378
+ $tsf->url_slashit = false;
1379
+ $parsed_url = \wp_parse_url( $custom_url );
1380
+ $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : 'http';
1381
+ }
1382
+ }
1383
+
1384
+ if ( empty( $url ) )
1385
+ $path = $tsf->generate_url_path( $args );
1386
+ } elseif ( $args['home'] ) {
1387
+ $path = $tsf->get_home_path();
1388
+ }
1389
+
1390
+ static $_has_filters = null;
1391
+ if ( null === $_has_filters ) {
1392
+ $_has_filters = array();
1393
+ $_has_filters['the_seo_framework_url_path'] = \has_filter( 'the_seo_framework_url_path' );
1394
+ $_has_filters['the_seo_framework_url_output_args'] = \has_filter( 'the_seo_framework_url_output_args' );
1395
+ }
1396
+
1397
+ if ( $_has_filters['the_seo_framework_url_path'] ) {
1398
+ /**
1399
+ * Applies filters 'the_seo_framework_url_path' : array
1400
+ *
1401
+ * @since 2.8.0
1402
+ *
1403
+ * @param string $path the URL path.
1404
+ * @param int $id The current post, page or term ID.
1405
+ * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
1406
+ */
1407
+ $path = (string) \apply_filters( 'the_seo_framework_url_path', $path, $args['id'], $args['external'] );
1408
+ }
1409
+
1410
+ if ( $_has_filters['the_seo_framework_url_output_args'] ) {
1411
+ /**
1412
+ * Applies filters 'the_seo_framework_sanitize_redirect_url' : array
1413
+ *
1414
+ * @since 2.8.0
1415
+ *
1416
+ * @param array : { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
1417
+ * @param string $path the URL path.
1418
+ * @param int $id The current post, page or term ID.
1419
+ * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
1420
+ */
1421
+ $url_filter = (array) \apply_filters( 'the_seo_framework_url_output_args', array(), $path, $args['id'], $args['external'] );
1422
+
1423
+ if ( $url_filter ) {
1424
+ $url = $url_filter['url'];
1425
+ $scheme = $url_filter['scheme'];
1426
+ }
1427
+ }
1428
+
1429
+ //* Non-custom URL
1430
+ if ( empty( $url ) ) {
1431
+ //* Reset cache if request is for the home URL.
1432
+ if ( $args['home'] )
1433
+ $tsf->unset_current_subdomain();
1434
+
1435
+ $url = $tsf->add_url_host( $path );
1436
+ $scheme = '';
1437
+
1438
+ $url = $tsf->add_url_subdomain( $url );
1439
+ }
1440
+
1441
+ $scheme = $scheme ?: $tsf->get_preferred_scheme();
1442
+
1443
+ $url = $tsf->set_url_scheme( $url, $scheme );
1444
+
1445
+ if ( $tsf->url_slashit ) {
1446
+ if ( $args['forceslash'] ) {
1447
+ $url = \trailingslashit( $url );
1448
+ } elseif ( $slashit ) {
1449
+ $url = \user_trailingslashit( $url );
1450
+ }
1451
+ }
1452
+
1453
+ if ( $tsf->pretty_permalinks ) {
1454
+ $url = \esc_url( $url, array( 'http', 'https' ) );
1455
+ } else {
1456
+ //* Keep the &'s more readable.
1457
+ $url = \esc_url_raw( $url, array( 'http', 'https' ) );
1458
+ }
1459
+
1460
+ return $url;
1461
+ }
1462
+
1463
+ /**
1464
+ * Parse and sanitize url args.
1465
+ *
1466
+ * @since 2.4.2
1467
+ * @since 2.9.2 Added filter usage cache.
1468
+ * @since 3.0.0 Deprecated.
1469
+ * @deprecated
1470
+ * @staticvar bool $_has_filter
1471
+ *
1472
+ * @param array $args required The passed arguments.
1473
+ * @param array $defaults The default arguments.
1474
+ * @param bool $get_defaults Return the default arguments. Ignoring $args.
1475
+ * @return array $args parsed args.
1476
+ */
1477
+ public function parse_url_args( $args = array(), $defaults = array(), $get_defaults = false ) {
1478
+
1479
+ $tsf = \the_seo_framework();
1480
+
1481
+ $tsf->_deprecated_function( 'the_seo_framework()->parse_url_args()', '3.0.0' );
1482
+
1483
+ //* Passing back the defaults reduces the memory usage.
1484
+ if ( empty( $defaults ) ) :
1485
+ $defaults = array(
1486
+ 'paged' => false,
1487
+ 'paged_plural' => true,
1488
+ 'get_custom_field' => true,
1489
+ 'external' => false,
1490
+ 'is_term' => false,
1491
+ 'post' => null,
1492
+ 'term' => null,
1493
+ 'home' => false,
1494
+ 'forceslash' => false,
1495
+ 'id' => $tsf->get_the_real_ID(),
1496
+ );
1497
+
1498
+ static $_has_filter = null;
1499
+ if ( null === $_has_filter )
1500
+ $_has_filter = \has_filter( 'the_seo_framework_url_args' );
1501
+
1502
+ if ( $_has_filter ) {
1503
+ /**
1504
+ * @applies filters the_seo_framework_url_args : {
1505
+ * @param bool $paged Return current page URL without pagination if false
1506
+ * @param bool $paged_plural Whether to add pagination for the second or later page.
1507
+ * @param bool $from_option Get the canonical uri option
1508
+ * @param object $post The Post Object.
1509
+ * @param bool $external Whether to fetch the current WP Request or get the permalink by Post Object.
1510
+ * @param bool $is_term Fetch url for term.
1511
+ * @param object $term The term object.
1512
+ * @param bool $home Fetch home URL.
1513
+ * @param bool $forceslash Fetch home URL and slash it, always.
1514
+ * @param int $id The Page or Term ID.
1515
+ * }
1516
+ *
1517
+ * @since 2.5.0
1518
+ * @since 3.0.0 Deprecated
1519
+ * @deprecated
1520
+ *
1521
+ * @param array $defaults The url defaults.
1522
+ * @param array $args The input args.
1523
+ */
1524
+ $defaults = (array) \apply_filters( 'the_seo_framework_url_args', $defaults, $args );
1525
+ }
1526
+ endif;
1527
+
1528
+ //* Return early if it's only a default args request.
1529
+ if ( $get_defaults )
1530
+ return $defaults;
1531
+
1532
+ //* Array merge doesn't support sanitation. We're simply type casting here.
1533
+ $args['paged'] = isset( $args['paged'] ) ? (bool) $args['paged'] : $defaults['paged'];
1534
+ $args['paged_plural'] = isset( $args['paged_plural'] ) ? (bool) $args['paged_plural'] : $defaults['paged_plural'];
1535
+ $args['get_custom_field'] = isset( $args['get_custom_field'] ) ? (bool) $args['get_custom_field'] : $defaults['get_custom_field'];
1536
+ $args['external'] = isset( $args['external'] ) ? (bool) $args['external'] : $defaults['external'];
1537
+ $args['is_term'] = isset( $args['is_term'] ) ? (bool) $args['is_term'] : $defaults['is_term'];
1538
+ $args['post'] = isset( $args['post'] ) ? (object) $args['post'] : $defaults['post'];
1539
+ $args['term'] = isset( $args['term'] ) ? (object) $args['term'] : $defaults['term'];
1540
+ $args['home'] = isset( $args['home'] ) ? (bool) $args['home'] : $defaults['home'];
1541
+ $args['forceslash'] = isset( $args['forceslash'] ) ? (bool) $args['forceslash'] : $defaults['forceslash'];
1542
+ $args['id'] = isset( $args['id'] ) ? (int) $args['id'] : $defaults['id'];
1543
+
1544
+ return $args;
1545
+ }
1546
+
1547
+ /**
1548
+ * Reparse URL args.
1549
+ *
1550
+ * @since 2.6.2
1551
+ * @since 2.9.2 Now passes args to filter.
1552
+ * @since 3.0.0 Deprecated.
1553
+ * @deprecated
1554
+ *
1555
+ * @param array $args required The passed arguments.
1556
+ * @return array $args parsed args.
1557
+ */
1558
+ public function reparse_url_args( $args = array() ) {
1559
+
1560
+ $tsf = \the_seo_framework();
1561
+
1562
+ $tsf->_deprecated_function( 'the_seo_framework()->reparse_url_args()', '3.0.0' );
1563
+
1564
+ $default_args = $tsf->parse_url_args( $args, '', true );
1565
+
1566
+ if ( is_array( $args ) ) {
1567
+ if ( empty( $args ) ) {
1568
+ $args = $default_args;
1569
+ } else {
1570
+ $args = $tsf->parse_url_args( $args, $default_args );
1571
+ }
1572
+ } else {
1573
+ //* Old style parameters are used. Doing it wrong.
1574
+ $tsf->_doing_it_wrong( __METHOD__, 'Use $args = array() for parameters.', '2.4.2' );
1575
+ $args = $default_args;
1576
+ }
1577
+
1578
+ return $args;
1579
+ }
1580
+
1581
+ /**
1582
+ * Generate URL from arguments.
1583
+ *
1584
+ * @since 2.6.0
1585
+ * @since 3.0.0 Deprecated.
1586
+ * @deprecated
1587
+ * @NOTE: Handles full path, including home directory.
1588
+ *
1589
+ * @param array $args the URL args.
1590
+ * @return string $path
1591
+ */
1592
+ public function generate_url_path( $args = array() ) {
1593
+
1594
+ $tsf = \the_seo_framework();
1595
+
1596
+ $tsf->_deprecated_function( 'the_seo_framework()->generate_url_path()', '3.0.0' );
1597
+
1598
+ $args = $tsf->reparse_url_args( $args );
1599
+
1600
+ if ( $tsf->is_archive() || $args['is_term'] ) :
1601
+
1602
+ $term = $args['term'];
1603
+
1604
+ //* Term or Taxonomy.
1605
+ if ( ! isset( $term ) )
1606
+ $term = \get_queried_object();
1607
+
1608
+ if ( isset( $term->taxonomy ) ) {
1609
+ //* Registered Terms and Taxonomies.
1610
+ $path = $tsf->get_relative_term_url( $term, $args );
1611
+ } elseif ( ! $args['external'] && isset( $GLOBALS['wp']->request ) ) {
1612
+ //* Everything else.
1613
+ $_url = \trailingslashit( \get_option( 'home' ) ) . $GLOBALS['wp']->request;
1614
+ $path = $tsf->set_url_scheme( $_url, 'relative' );
1615
+ } else {
1616
+ //* Nothing to see here...
1617
+ $path = '';
1618
+ }
1619
+ elseif ( $tsf->is_search() ) :
1620
+ $_url = \get_search_link();
1621
+ $path = $tsf->set_url_scheme( $_url, 'relative' );
1622
+ else :
1623
+ /**
1624
+ * Reworked to use the $args['id'] check based on get_the_real_ID.
1625
+ * @since 2.6.0 & 2.6.2
1626
+ */
1627
+ $post_id = isset( $args['post']->ID ) ? $args['post']->ID : $args['id'];
1628
+
1629
+ if ( $tsf->pretty_permalinks && $post_id && $tsf->is_singular( $post_id ) ) {
1630
+ $post = \get_post( $post_id );
1631
+
1632
+ //* Don't slash draft links.
1633
+ if ( isset( $post->post_status ) && ( 'auto-draft' === $post->post_status || 'draft' === $post->post_status ) )
1634
+ $tsf->url_slashit = false;
1635
+ }
1636
+
1637
+ $path = $tsf->build_singular_relative_url( $post_id, $args );
1638
+ endif;
1639
+
1640
+ return $path;
1641
+ }
1642
+
1643
+ /**
1644
+ * Generates relative URL for the Homepage and Singular Posts.
1645
+ *
1646
+ * @since 2.6.5
1647
+ * @NOTE: Handles full path, including home directory.
1648
+ * @since 2.8.0: Continues on empty post ID. Handles it as HomePage.
1649
+ * @since 3.0.0 Deprecated.
1650
+ * @deprecated
1651
+ *
1652
+ * @param int $post_id The ID.
1653
+ * @param array $args The URL arguments.
1654
+ * @return string relative Post or Page url.
1655
+ */
1656
+ public function build_singular_relative_url( $post_id = null, $args = array() ) {
1657
+
1658
+ $tsf = \the_seo_framework();
1659
+
1660
+ $tsf->_deprecated_function( 'the_seo_framework()->build_singular_relative_url()', '3.0.0' );
1661
+
1662
+ if ( empty( $post_id ) ) {
1663
+ //* We can't fetch the post ID when there's an external request.
1664
+ if ( $args['external'] ) {
1665
+ $post_id = 0;
1666
+ } else {
1667
+ $post_id = $tsf->get_the_real_ID();
1668
+ }
1669
+ }
1670
+
1671
+ $args = $tsf->reparse_url_args( $args );
1672
+
1673
+ if ( $args['external'] || ! $tsf->is_real_front_page() || ! $tsf->is_front_page_by_id( $post_id ) ) {
1674
+ $url = \get_permalink( $post_id );
1675
+ } elseif ( $tsf->is_real_front_page() || $tsf->is_front_page_by_id( $post_id ) ) {
1676
+ $url = \get_home_url();
1677
+ } elseif ( ! $args['external'] ) {
1678
+ if ( isset( $GLOBALS['wp']->request ) )
1679
+ $url = \trailingslashit( \get_home_url() ) . $GLOBALS['wp']->request;
1680
+ }
1681
+
1682
+ //* No permalink found.
1683
+ if ( ! isset( $url ) )
1684
+ return '';
1685
+
1686
+ $paged = false;
1687
+
1688
+ if ( false === $args['external'] ) {
1689
+ $paged = $tsf->is_singular() ? $tsf->page() : $tsf->paged();
1690
+ $paged = $tsf->maybe_get_paged( $paged, $args['paged'], $args['paged_plural'] );
1691
+ }
1692
+
1693
+ if ( $paged ) {
1694
+ if ( $tsf->pretty_permalinks ) {
1695
+ if ( $tsf->is_singular() ) {
1696
+ $url = \trailingslashit( $url ) . $paged;
1697
+ } else {
1698
+ $url = \trailingslashit( $url ) . 'page/' . $paged;
1699
+ }
1700
+ } else {
1701
+ if ( $tsf->is_singular() ) {
1702
+ $url = \add_query_arg( 'page', $paged, $url );
1703
+ } else {
1704
+ $url = \add_query_arg( 'paged', $paged, $url );
1705
+ }
1706
+ }
1707
+ }
1708
+
1709
+ return $tsf->set_url_scheme( $url, 'relative' );
1710
+ }
1711
+
1712
+ /**
1713
+ * Generates relative URL for current term.
1714
+ *
1715
+ * @since 2.4.2
1716
+ * @since 2.7.0 Added home directory to output.
1717
+ * @since 3.0.0 Deprecated.
1718
+ * @deprecated
1719
+ * @global object $wp_rewrite
1720
+ * @NOTE: Handles full path, including home directory.
1721
+ *
1722
+ * @param object $term The term object.
1723
+ * @param array|bool $args {
1724
+ * 'external' : Whether to fetch the WP Request or get the permalink by Post Object.
1725
+ * 'paged' : Whether to add pagination for all types.
1726
+ * 'paged_plural' : Whether to add pagination for the second or later page.
1727
+ * }
1728
+ * @return string Relative term or taxonomy URL.
1729
+ */
1730
+ public function get_relative_term_url( $term = null, $args = array() ) {
1731
+
1732
+ $tsf = \the_seo_framework();
1733
+
1734
+ $tsf->_deprecated_function( 'the_seo_framework()->get_relative_term_url()', '3.0.0' );
1735
+
1736
+ global $wp_rewrite;
1737
+
1738
+ if ( ! is_array( $args ) ) {
1739
+ /**
1740
+ * @since 2.6.0
1741
+ * '$args = array()' replaced '$no_request = false'.
1742
+ */
1743
+ $tsf->_doing_it_wrong( __METHOD__, 'Use $args = array() for parameters.', '2.6.0' );
1744
+
1745
+ $no_request = (bool) $args;
1746
+ $args = $tsf->parse_url_args( '', '', true );
1747
+ $args['external'] = $no_request;
1748
+ }
1749
+
1750
+ // We can't fetch the Term object within sitemaps.
1751
+ if ( $args['external'] && is_null( $term ) )
1752
+ return '';
1753
+
1754
+ if ( is_null( $term ) )
1755
+ $term = \get_queried_object();
1756
+
1757
+ $taxonomy = $term->taxonomy;
1758
+ $path = $wp_rewrite->get_extra_permastruct( $taxonomy );
1759
+
1760
+ $slug = $term->slug;
1761
+ $t = \get_taxonomy( $taxonomy );
1762
+
1763
+ $paged = $tsf->maybe_get_paged( $tsf->paged(), $args['paged'], $args['paged_plural'] );
1764
+
1765
+ if ( empty( $path ) ) :
1766
+ //* Default permalink structure.
1767
+
1768
+ if ( 'category' === $taxonomy ) {
1769
+ $path = '?cat=' . $term->term_id;
1770
+ } elseif ( isset( $t->query_var ) && '' !== $t->query_var ) {
1771
+ $path = '?' . $t->query_var . '=' . $slug;
1772
+ } else {
1773
+ $path = '?taxonomy=' . $taxonomy . '&term=' . $slug;
1774
+ }
1775
+
1776
+ if ( $paged )
1777
+ $path .= '&paged=' . $paged;
1778
+
1779
+ //* Don't slash it.
1780
+ $tsf->url_slashit = false;
1781
+
1782
+ else :
1783
+ if ( $t->rewrite['hierarchical'] ) {
1784
+ $hierarchical_slugs = array();
1785
+ $ancestors = \get_ancestors( $term->term_id, $taxonomy, 'taxonomy' );
1786
+
1787
+ foreach ( (array) $ancestors as $ancestor ) {
1788
+ $ancestor_term = \get_term( $ancestor, $taxonomy );
1789
+ $hierarchical_slugs[] = $ancestor_term->slug;
1790
+ }
1791
+
1792
+ $hierarchical_slugs = array_reverse( $hierarchical_slugs );
1793
+ $hierarchical_slugs[] = $slug;
1794
+
1795
+ $path = str_replace( "%$taxonomy%", implode( '/', $hierarchical_slugs ), $path );
1796
+ } else {
1797
+ $path = str_replace( "%$taxonomy%", $slug, $path );
1798
+ }
1799
+
1800
+ if ( $paged )
1801
+ $path = \trailingslashit( $path ) . 'page/' . $paged;
1802
+
1803
+ $path = \user_trailingslashit( $path, 'category' );
1804
+ endif;
1805
+
1806
+ //* Add plausible domain subdirectories.
1807
+ $url = \trailingslashit( \get_option( 'home' ) ) . ltrim( $path, ' \\/' );
1808
+ $path = $tsf->set_url_scheme( $url, 'relative' );
1809
+
1810
+ return $path;
1811
+ }
1812
+
1813
+ /**
1814
+ * Adds subdomain to input URL.
1815
+ *
1816
+ * @since 2.6.5
1817
+ * @since 3.0.0 Deprecated.
1818
+ * @deprecated
1819
+ *
1820
+ * @param string $url The current URL without subdomain.
1821
+ * @return string $url Fully qualified URL with possible subdomain.
1822
+ */
1823
+ public function add_url_subdomain( $url = '' ) {
1824
+
1825
+ $tsf = \the_seo_framework();
1826
+ $tsf->_deprecated_function( 'the_seo_framework()->add_url_subdomain()', '3.0.0' );
1827
+
1828
+ $url = $tsf->make_fully_qualified_url( $url );
1829
+
1830
+ //* Add subdomain, if set.
1831
+ if ( $subdomain = $tsf->get_current_subdomain() ) {
1832
+ $parsed_url = \wp_parse_url( $url );
1833
+ $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : 'http';
1834
+ $url = str_replace( $scheme . '://', '', $url );
1835
+
1836
+ //* Put it together.
1837
+ $url = $scheme . '://' . $subdomain . '.' . $url;
1838
+ }
1839
+
1840
+ return $url;
1841
+ }
1842
+
1843
+ /**
1844
+ * Fetches current subdomain set by $this->set_current_subdomain();
1845
+ *
1846
+ * @since 2.7.0
1847
+ * @since 3.0.0 Deprecated.
1848
+ * @deprecated
1849
+ * @staticvar string $subdomain
1850
+ *
1851
+ * @param null|string $set Whether to set a new subdomain.
1852
+ * @param bool $unset Whether to remove subdomain from cache.
1853
+ * @return string|bool The set subdomain, false if none is set.
1854
+ */
1855
+ public function get_current_subdomain( $set = null, $unset = false ) {
1856
+
1857
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->get_current_subdomain()', '3.0.0' );
1858
+
1859
+ static $subdomain = null;
1860
+
1861
+ if ( isset( $set ) )
1862
+ $subdomain = \esc_html( $set );
1863
+
1864
+ if ( $unset )
1865
+ unset( $subdomain );
1866
+
1867
+ if ( isset( $subdomain ) )
1868
+ return $subdomain;
1869
+
1870
+ return false;
1871
+ }
1872
+
1873
+ /**
1874
+ * Sets current working subdomain.
1875
+ *
1876
+ * @since 2.7.0
1877
+ * @since 3.0.0 Deprecated.
1878
+ * @deprecated
1879
+ *
1880
+ * @param string $subdomain The current subdomain.
1881
+ * @return string The set subdomain.
1882
+ */
1883
+ public function set_current_subdomain( $subdomain = '' ) {
1884
+
1885
+ $tsf = \the_seo_framework();
1886
+
1887
+ $tsf->_deprecated_function( 'the_seo_framework()->unset_current_subdomain()', '3.0.0' );
1888
+
1889
+ return $tsf->get_current_subdomain( $subdomain );
1890
+ }
1891
+
1892
+ /**
1893
+ * Unsets current working subdomain.
1894
+ *
1895
+ * @since 2.7.0
1896
+ * @since 3.0.0 Deprecated.
1897
+ * @deprecated
1898
+ */
1899
+ public function unset_current_subdomain() {
1900
+
1901
+ $tsf = \the_seo_framework();
1902
+
1903
+ $tsf->_deprecated_function( 'the_seo_framework()->unset_current_subdomain()', '3.0.0' );
1904
+
1905
+ $tsf->get_current_subdomain( null, true );
1906
+ }
1907
+
1908
+ /**
1909
+ * Create full valid URL with parsed host.
1910
+ * Don't forget to use set_url_scheme() afterwards.
1911
+ *
1912
+ * Note: will return $path if no host can be found.
1913
+ *
1914
+ * @since 2.6.5
1915
+ * @since 3.0.0 Deprecated.
1916
+ * @deprecated
1917
+ *
1918
+ * @param string $path Current path.
1919
+ * @return string Full valid URL with http host.
1920
+ */
1921
+ public function add_url_host( $path = '' ) {
1922
+
1923
+ $tsf = \the_seo_framework();
1924
+
1925
+ $tsf->_deprecated_function( 'the_seo_framework()->add_url_host()', '3.0.0' );
1926
+
1927
+ $host = $tsf->current_host ?: $tsf->get_home_host();
1928
+
1929
+ $scheme = $host ? 'http://' : '';
1930
+
1931
+ return $url = $scheme . \trailingslashit( $host ) . ltrim( $path, ' \\/' );
1932
+ }
1933
+
1934
+ /**
1935
+ * Fetches home URL subdirectory path. Like "wordpress.org/plugins/".
1936
+ *
1937
+ * @since 2.7.0
1938
+ * @since 3.0.0 Deprecated.
1939
+ * @deprecated
1940
+ * @staticvar string $cache
1941
+ *
1942
+ * @return string The home URL path.
1943
+ */
1944
+ public function get_home_path() {
1945
+
1946
+ \the_seo_framework()->_deprecated_function( 'the_seo_framework()->get_home_path()', '3.0.0' );
1947
+
1948
+ static $cache = null;
1949
+
1950
+ if ( isset( $cache ) )
1951
+ return $cache;
1952
+
1953
+ $path = '';
1954
+
1955
+ $parsed_url = \wp_parse_url( \get_option( 'home' ) );
1956
+
1957
+ if ( ! empty( $parsed_url['path'] ) && $path = ltrim( $parsed_url['path'], ' \\/' ) )
1958
+ $path = '/' . $path;
1959
+
1960
+ return $cache = $path;
1961
+ }
1962
+
1963
+ /**
1964
+ * Cache current URL in static variable
1965
+ * Must be called inside the loop
1966
+ *
1967
+ * @since 2.2.2
1968
+ * @since 3.0.0 Deprecated.
1969
+ * @deprecated
1970
+ * @staticvar array $url_cache
1971
+ *
1972
+ * @param string $url the url
1973
+ * @param int $post_id the page id, if empty it will fetch the requested ID, else the page uri
1974
+ * @param bool $paged Return current page URL with pagination
1975
+ * @param bool $from_option Get the canonical uri option
1976
+ * @param bool $paged_plural Whether to allow pagination on second or later pages.
1977
+ * @return string The url
1978
+ */
1979
+ public function the_url_from_cache( $url = '', $post_id = null, $paged = false, $from_option = true, $paged_plural = true ) {
1980
+
1981
+ $tsf = \the_seo_framework();
1982
+ $tsf->_deprecated_function( 'the_seo_framework()->the_url_from_cache()', '3.0.0', `the_seo_framework()->get_current_canonical_url()` );
1983
+
1984
+ return $tsf->get_current_canonical_url();
1985
+ }
1986
+
1987
+ /**
1988
+ * Cache home URL in static variable
1989
+ *
1990
+ * @since 2.5.0
1991
+ * @since 2.9.0 Now returns subdirectory installations paths too.
1992
+ * @since 3.0.0 1: Now no longer regenerates home URL when parameters differ.
1993
+ * 2: Deprecated.
1994
+ * @deprecated
1995
+ * @staticvar string $url
1996
+ *
1997
+ * @param bool $force_slash Force slash
1998
+ * @return string The url
1999
+ */
2000
+ public function the_home_url_from_cache( $force_slash = false ) {
2001
+
2002
+ $tsf = \the_seo_framework();
2003
+ $tsf->_deprecated_function( 'the_seo_framework()->the_home_url_from_cache()', '3.0.0', 'the_seo_framework()->get_homepage_permalink()' );
2004
+
2005
+ static $url;
2006
+
2007
+ if ( ! $url )
2008
+ $url = $tsf->get_homepage_permalink();
2009
+
2010
+ return $force_slash ? \trailingslashit( $url ) : $url;
2011
+ }
2012
+ }
inc/classes/detect.class.php CHANGED
@@ -147,7 +147,6 @@ class Detect extends Render {
147
  'XML Sitemap & Google News feeds' => 'xml-sitemap-feed/xml-sitemap.php',
148
  'Google Sitemap by BestWebSoft' => 'google-sitemap-plugin/google-sitemap-plugin.php',
149
  'Simple Wp Sitemap' => 'simple-wp-sitemap/simple-wp-sitemap.php',
150
- 'Simple Sitemap' => 'simple-sitemap/simple-sitemap.php',
151
  'XML Sitemaps' => 'xml-sitemaps/xml-sitemaps.php',
152
  ),
153
  'open_graph' => array(
@@ -160,7 +159,6 @@ class Detect extends Render {
160
  'Fedmichs Facebook Open Graph Meta' => 'facebook-and-digg-thumbnail-generator/facebook-and-digg-thumbnail-generator.php',
161
  'Header and Footer' => 'header-footer/plugin.php',
162
  'NextGEN Facebook OG' => 'nextgen-facebook/nextgen-facebook.php',
163
- 'NextScripts SNAP' => 'social-networks-auto-poster-facebook-twitter-g/NextScripts_SNAP.php',
164
  'Open Graph' => 'opengraph/opengraph.php',
165
  'Open Graph Protocol Framework' => 'open-graph-protocol-framework/open-graph-protocol-framework.php',
166
  'Shareaholic2' => 'shareaholic/sexy-bookmarks.php',
@@ -1140,6 +1138,13 @@ class Detect extends Render {
1140
 
1141
  static $cache = null;
1142
 
1143
- return isset( $cache ) ? $cache : '' !== $this->get_home_path();
 
 
 
 
 
 
 
1144
  }
1145
  }
147
  'XML Sitemap & Google News feeds' => 'xml-sitemap-feed/xml-sitemap.php',
148
  'Google Sitemap by BestWebSoft' => 'google-sitemap-plugin/google-sitemap-plugin.php',
149
  'Simple Wp Sitemap' => 'simple-wp-sitemap/simple-wp-sitemap.php',
 
150
  'XML Sitemaps' => 'xml-sitemaps/xml-sitemaps.php',
151
  ),
152
  'open_graph' => array(
159
  'Fedmichs Facebook Open Graph Meta' => 'facebook-and-digg-thumbnail-generator/facebook-and-digg-thumbnail-generator.php',
160
  'Header and Footer' => 'header-footer/plugin.php',
161
  'NextGEN Facebook OG' => 'nextgen-facebook/nextgen-facebook.php',
 
162
  'Open Graph' => 'opengraph/opengraph.php',
163
  'Open Graph Protocol Framework' => 'open-graph-protocol-framework/open-graph-protocol-framework.php',
164
  'Shareaholic2' => 'shareaholic/sexy-bookmarks.php',
1138
 
1139
  static $cache = null;
1140
 
1141
+ if ( isset( $cache ) )
1142
+ return $cache;
1143
+
1144
+ $parsed_url = \wp_parse_url( \get_option( 'home' ) );
1145
+ if ( ! empty( $parsed_url['path'] ) && ltrim( $parsed_url['path'], ' \\/' ) )
1146
+ $cache = true;
1147
+
1148
+ return $cache ?: $cache = false;
1149
  }
1150
  }
inc/classes/doing-it-right.class.php CHANGED
@@ -94,6 +94,7 @@ class Doing_It_Right extends Generate_Ldjson {
94
  * Initializes SEO columns for adding a tag or category.
95
  *
96
  * @since 2.9.1
 
97
  * @access private
98
  */
99
  public function _init_columns_wp_ajax_add_tag() {
@@ -115,6 +116,7 @@ class Doing_It_Right extends Generate_Ldjson {
115
  * Initializes SEO columns for adding a tag or category.
116
  *
117
  * @since 2.9.1
 
118
  * @access private
119
  */
120
  public function _init_columns_wp_ajax_inline_save() {
@@ -143,6 +145,7 @@ class Doing_It_Right extends Generate_Ldjson {
143
  * Initializes SEO columns for adding a tag or category.
144
  *
145
  * @since 2.9.1
 
146
  * @access private
147
  */
148
  public function _init_columns_wp_ajax_inline_save_tax() {
@@ -168,8 +171,10 @@ class Doing_It_Right extends Generate_Ldjson {
168
  *
169
  * @since 2.1.9
170
  * @since 2.9.1 Now supports inline edit AJAX.
 
 
171
  *
172
- * @param object|empty $screen WP_Screen
173
  * @param bool $doing_ajax Whether we're doing an AJAX response.
174
  * @return void If filter is set to false.
175
  */
@@ -500,8 +505,8 @@ class Doing_It_Right extends Generate_Ldjson {
500
  $bar = $this->post_status_special( $context, '!', 'bad' );
501
  }
502
 
503
- //* Already escaped.
504
  if ( $echo ) {
 
505
  echo $bar;
506
  } else {
507
  return $bar;
@@ -509,28 +514,34 @@ class Doing_It_Right extends Generate_Ldjson {
509
  }
510
 
511
  /**
512
- * Outputs a part of the SEO Bar based on parameters.
513
  *
514
  * @since 2.6.0
 
515
  *
516
  * @param array $args : {
517
- * string $indicator
518
- * string $notice
519
- * string $width
520
- * string $class
521
  * }
522
  * @return string The SEO Bar block part.
523
  */
524
  protected function wrap_the_seo_bar_block( $args ) {
525
-
526
- $wrap = '<span class="tsf-seo-bar-section-wrap ' . $args['width'] . '">'
527
- . '<a onclick="return false;" class="' . $args['class'] . '" aria-label="' . $args['notice'] . '" data-desc="' . $args['notice'] . '">'
528
- . $args['indicator']
529
- . '</a>'
530
- . '</span>'
531
- ;
532
-
533
- return $wrap;
 
 
 
 
 
534
  }
535
 
536
  /**
@@ -561,13 +572,15 @@ class Doing_It_Right extends Generate_Ldjson {
561
  }
562
 
563
  if ( isset( $ajax_id ) ) {
564
- //* Ajax handler.
565
- $script = '<script>jQuery("#' . \esc_js( $ajax_id ) . '").on( "hover click", tsf.statusBarHover );</script>';
 
 
566
 
567
- return sprintf( '<span class="%s" id="%s"><span class="tsf-seo-bar-inner-wrap">%s</span></span>', $class, \esc_attr( $ajax_id ), $content ) . $script;
568
  }
569
 
570
- return sprintf( '<span class="%s"><span class="tsf-seo-bar-inner-wrap">%s</span></span>', $class, $content );
571
  }
572
 
573
  /**
@@ -576,28 +589,27 @@ class Doing_It_Right extends Generate_Ldjson {
576
  * @since 2.6.0
577
  *
578
  * @param array $args {
579
- * 'is_term' => bool $is_term,
580
- * 'term' => object $term,
581
- * 'post_i18n' => string $post_i18n,
582
- * 'post_low' => string $post_low,
583
- * 'type' => string $type,
584
  * }
585
  * @return string $content The SEO bar.
586
  */
587
  protected function the_seo_bar_term( $args ) {
588
 
589
- $term = $args['term'];
590
- $post = $args['post_i18n'];
591
  $is_term = true;
592
 
593
- $data = $this->get_term_data( $term, $term->term_id );
594
 
595
  $noindex = isset( $data['noindex'] ) && $data['noindex'];
596
  $redirect = false; // We don't apply redirect on taxonomies (yet)
597
 
598
  //* Blocked SEO, return simple bar.
599
  if ( $redirect || $noindex )
600
- return $this->the_seo_bar_blocked( array( 'is_term' => $is_term, 'redirect' => $redirect, 'noindex' => $noindex, 'post_i18n' => $post ) );
601
 
602
  $title_notice = $this->the_seo_bar_title_notice( $args );
603
  $description_notice = $this->the_seo_bar_description_notice( $args );
@@ -616,12 +628,12 @@ class Doing_It_Right extends Generate_Ldjson {
616
  * @since 2.6.0
617
  *
618
  * @param array $args {
619
- * 'is_term' => $is_term,
620
- * 'term' => $term,
621
- * 'post_id' => $post_id,
622
- * 'post_i18n' => $post_i18n,
623
- * 'post_low' => $post_low,
624
- * 'type' => $type,
625
  * }
626
  * @return string $content The SEO bar.
627
  */
@@ -661,12 +673,12 @@ class Doing_It_Right extends Generate_Ldjson {
661
  *
662
  * @param array $args The term/post args.
663
  * @return array $data {
664
- * 'title' => $title,
665
- * 'title_is_from_custom_field' => $title_is_from_custom_field,
666
- * 'description' => $description,
667
- * 'description_is_from_custom_field' => $description_is_from_custom_field,
668
- * 'nofollow' => $nofollow,
669
- * 'noarchive' => $noarchive
670
  * }
671
  */
672
  protected function the_seo_bar_data( $args ) {
@@ -709,7 +721,7 @@ class Doing_It_Right extends Generate_Ldjson {
709
  $term_id = $args['post_id'];
710
  $taxonomy = $args['type'];
711
 
712
- $data = $this->get_term_data( $term, $term_id );
713
 
714
  $title_custom_field = isset( $data['doctitle'] ) ? $data['doctitle'] : '';
715
  $description_custom_field = isset( $data['description'] ) ? $data['description'] : '';
@@ -973,16 +985,16 @@ class Doing_It_Right extends Generate_Ldjson {
973
  * @param int $desc_len The Title length
974
  * @param string $class The current color class.
975
  * @return array {
976
- * notice => The notice,
977
- * class => The class,
978
  * }
979
  */
980
  protected function get_the_seo_bar_description_length_warning( $desc_len, $class ) {
981
 
982
  $classes = $this->get_the_seo_bar_classes();
983
- $bad = $classes['bad'];
984
- $okay = $classes['okay'];
985
- $good = $classes['good'];
986
 
987
  $i18n = $this->get_the_seo_bar_i18n();
988
 
@@ -1175,9 +1187,9 @@ class Doing_It_Right extends Generate_Ldjson {
1175
 
1176
  $ind_wrap_args = array(
1177
  'indicator' => $index_short,
1178
- 'notice' => $ind_notice,
1179
- 'width' => $ad_125,
1180
- 'class' => $ind_class,
1181
  );
1182
 
1183
  $index_notice = $this->wrap_the_seo_bar_block( $ind_wrap_args );
@@ -1317,9 +1329,9 @@ class Doing_It_Right extends Generate_Ldjson {
1317
 
1318
  $fol_wrap_args = array(
1319
  'indicator' => $follow_short,
1320
- 'notice' => $fol_notice,
1321
- 'width' => $ad_125,
1322
- 'class' => $fol_class,
1323
  );
1324
 
1325
  $follow_notice = $this->wrap_the_seo_bar_block( $fol_wrap_args );
@@ -1344,7 +1356,7 @@ class Doing_It_Right extends Generate_Ldjson {
1344
  $post_low = $args['post_low'];
1345
 
1346
  $data = $this->the_seo_bar_data( $args );
1347
- $noarchive = $data['noarchive'];
1348
 
1349
  $classes = $this->get_the_seo_bar_classes();
1350
  $unknown = $classes['unknown'];
@@ -1484,10 +1496,10 @@ class Doing_It_Right extends Generate_Ldjson {
1484
  * @since 2.6.0
1485
  *
1486
  * @param array $args {
1487
- * $is_term => bool,
1488
- * $redirect => bool,
1489
- * $noindex => bool,
1490
- * $post_i18n => string
1491
  * }
1492
  * @return string The SEO Bar
1493
  */
@@ -1575,9 +1587,9 @@ class Doing_It_Right extends Generate_Ldjson {
1575
  * @param int $tit_len The Title length
1576
  * @param string $class The Current Title notification class.
1577
  * @return array {
1578
- * string $notice => The notice,
1579
- * string $class => The class,
1580
- * bool $but => Whether we should use but or and,
1581
  * }
1582
  */
1583
  protected function get_the_seo_bar_title_length_warning( $tit_len, $class ) {
94
  * Initializes SEO columns for adding a tag or category.
95
  *
96
  * @since 2.9.1
97
+ * @securitycheck 3.0.0 OK.
98
  * @access private
99
  */
100
  public function _init_columns_wp_ajax_add_tag() {
116
  * Initializes SEO columns for adding a tag or category.
117
  *
118
  * @since 2.9.1
119
+ * @securitycheck 3.0.0 OK.
120
  * @access private
121
  */
122
  public function _init_columns_wp_ajax_inline_save() {
145
  * Initializes SEO columns for adding a tag or category.
146
  *
147
  * @since 2.9.1
148
+ * @securitycheck 3.0.0 OK.
149
  * @access private
150
  */
151
  public function _init_columns_wp_ajax_inline_save_tax() {
171
  *
172
  * @since 2.1.9
173
  * @since 2.9.1 Now supports inline edit AJAX.
174
+ * @securitycheck 3.0.0 OK. NOTE: Sanity check is done in _init_columns_wp_ajax_inline_save_tax()
175
+ * & _init_columns_wp_ajax_inline_save()
176
  *
177
+ * @param \WP_Screen|string $screen \WP_Screen
178
  * @param bool $doing_ajax Whether we're doing an AJAX response.
179
  * @return void If filter is set to false.
180
  */
505
  $bar = $this->post_status_special( $context, '!', 'bad' );
506
  }
507
 
 
508
  if ( $echo ) {
509
+ //* Already escaped.
510
  echo $bar;
511
  } else {
512
  return $bar;
514
  }
515
 
516
  /**
517
+ * Returns a part of the SEO Bar based on parameters.
518
  *
519
  * @since 2.6.0
520
+ * @since 3.0.0 Now uses spans instead of a's
521
  *
522
  * @param array $args : {
523
+ * string $indicator Required. The block text.
524
+ * string $notice Required. The tooltip message.
525
+ * string $width Required. The width class.
526
+ * string $class Required. The item class.
527
  * }
528
  * @return string The SEO Bar block part.
529
  */
530
  protected function wrap_the_seo_bar_block( $args ) {
531
+ return vsprintf(
532
+ '<span class="tsf-seo-bar-section-wrap %s">%s</span>',
533
+ array(
534
+ $args['width'],
535
+ vsprintf(
536
+ '<span class="tsf-seo-bar-item tsf-tooltip-item %1$s" aria-label="%2$s" data-desc="%2$s">%3$s</span>',
537
+ array(
538
+ $args['class'],
539
+ $args['notice'],
540
+ $args['indicator'],
541
+ )
542
+ ),
543
+ )
544
+ );
545
  }
546
 
547
  /**
572
  }
573
 
574
  if ( isset( $ajax_id ) ) {
575
+ //= Ajax handler.
576
+
577
+ //* Resets tooltips.
578
+ $script = '<script>tsf._triggerTooltipReset();</script>';
579
 
580
+ return sprintf( '<span class="%s" id="%s"><span class="tsf-seo-bar-inner-wrap tsf-tooltip-wrap">%s</span></span>', $class, \esc_attr( $ajax_id ), $content ) . $script;
581
  }
582
 
583
+ return sprintf( '<span class="%s"><span class="tsf-seo-bar-inner-wrap tsf-tooltip-wrap">%s</span></span>', $class, $content );
584
  }
585
 
586
  /**
589
  * @since 2.6.0
590
  *
591
  * @param array $args {
592
+ * 'is_term' => bool $is_term,
593
+ * 'term' => object $term,
594
+ * 'post_i18n' => string $post_i18n,
595
+ * 'post_low' => string $post_low,
596
+ * 'type' => string $type,
597
  * }
598
  * @return string $content The SEO bar.
599
  */
600
  protected function the_seo_bar_term( $args ) {
601
 
602
+ $i18n = $args['post_i18n'];
 
603
  $is_term = true;
604
 
605
+ $data = $this->get_term_meta( $args['term']->term_id );
606
 
607
  $noindex = isset( $data['noindex'] ) && $data['noindex'];
608
  $redirect = false; // We don't apply redirect on taxonomies (yet)
609
 
610
  //* Blocked SEO, return simple bar.
611
  if ( $redirect || $noindex )
612
+ return $this->the_seo_bar_blocked( array( 'is_term' => $is_term, 'redirect' => $redirect, 'noindex' => $noindex, 'post_i18n' => $i18n ) );
613
 
614
  $title_notice = $this->the_seo_bar_title_notice( $args );
615
  $description_notice = $this->the_seo_bar_description_notice( $args );
628
  * @since 2.6.0
629
  *
630
  * @param array $args {
631
+ * 'is_term' => $is_term,
632
+ * 'term' => $term,
633
+ * 'post_id' => $post_id,
634
+ * 'post_i18n' => $post_i18n,
635
+ * 'post_low' => $post_low,
636
+ * 'type' => $type,
637
  * }
638
  * @return string $content The SEO bar.
639
  */
673
  *
674
  * @param array $args The term/post args.
675
  * @return array $data {
676
+ * 'title' => $title,
677
+ * 'title_is_from_custom_field' => $title_is_from_custom_field,
678
+ * 'description' => $description,
679
+ * 'description_is_from_custom_field' => $description_is_from_custom_field,
680
+ * 'nofollow' => $nofollow,
681
+ * 'noarchive' => $noarchive
682
  * }
683
  */
684
  protected function the_seo_bar_data( $args ) {
721
  $term_id = $args['post_id'];
722
  $taxonomy = $args['type'];
723
 
724
+ $data = $this->get_term_meta( $term_id );
725
 
726
  $title_custom_field = isset( $data['doctitle'] ) ? $data['doctitle'] : '';
727
  $description_custom_field = isset( $data['description'] ) ? $data['description'] : '';
985
  * @param int $desc_len The Title length
986
  * @param string $class The current color class.
987
  * @return array {
988
+ * notice => The notice,
989
+ * class => The class,
990
  * }
991
  */
992
  protected function get_the_seo_bar_description_length_warning( $desc_len, $class ) {
993
 
994
  $classes = $this->get_the_seo_bar_classes();
995
+ $bad = $classes['bad'];
996
+ $okay = $classes['okay'];
997
+ $good = $classes['good'];
998
 
999
  $i18n = $this->get_the_seo_bar_i18n();
1000
 
1187
 
1188
  $ind_wrap_args = array(
1189
  'indicator' => $index_short,
1190
+ 'notice' => $ind_notice,
1191
+ 'width' => $ad_125,
1192
+ 'class' => $ind_class,
1193
  );
1194
 
1195
  $index_notice = $this->wrap_the_seo_bar_block( $ind_wrap_args );
1329
 
1330
  $fol_wrap_args = array(
1331
  'indicator' => $follow_short,
1332
+ 'notice' => $fol_notice,
1333
+ 'width' => $ad_125,
1334
+ 'class' => $fol_class,
1335
  );
1336
 
1337
  $follow_notice = $this->wrap_the_seo_bar_block( $fol_wrap_args );
1356
  $post_low = $args['post_low'];
1357
 
1358
  $data = $this->the_seo_bar_data( $args );
1359
+ $noarchive = $data['noarchive'];
1360
 
1361
  $classes = $this->get_the_seo_bar_classes();
1362
  $unknown = $classes['unknown'];
1496
  * @since 2.6.0
1497
  *
1498
  * @param array $args {
1499
+ * $is_term => bool,
1500
+ * $redirect => bool,
1501
+ * $noindex => bool,
1502
+ * $post_i18n => string
1503
  * }
1504
  * @return string The SEO Bar
1505
  */
1587
  * @param int $tit_len The Title length
1588
  * @param string $class The Current Title notification class.
1589
  * @return array {
1590
+ * string $notice => The notice,
1591
+ * string $class => The class,
1592
+ * bool $but => Whether we should use but or and,
1593
  * }
1594
  */
1595
  protected function get_the_seo_bar_title_length_warning( $tit_len, $class ) {
inc/classes/feed.class.php CHANGED
@@ -1,187 +1,184 @@
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 - 2017 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
- * 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
- /**
44
- * Initializes feed actions and hooks.
45
- *
46
- * @since 2.9.0
47
- * @access private
48
- *
49
- * @return void Early if this request isn't for a feed.
50
- */
51
- public function _init_feed_output() {
52
-
53
- if ( ! $this->is_feed() )
54
- return;
55
-
56
- \add_filter( 'the_content_feed', array( $this, 'the_content_feed' ), 10, 2 );
57
-
58
- //* Only add the feed link to the excerpt if we're only building excerpts.
59
- if ( $this->rss_uses_excerpt() )
60
- \add_filter( 'the_excerpt_rss', array( $this, 'the_content_feed' ), 10, 1 );
61
-
62
- }
63
-
64
- /**
65
- * Determines whether the WordPress excerpt RSS feed option is used.
66
- *
67
- * @since 2.6.0
68
- *
69
- * @return bool
70
- */
71
- public function rss_uses_excerpt() {
72
- return (bool) \get_option( 'rss_use_excerpt' );
73
- }
74
-
75
- /**
76
- * Changes feed's content based on options.
77
- *
78
- * This method converts the input $content to an excerpt and is able to add
79
- * a nofollow backlink at the end of the feed.
80
- *
81
- * @since 2.5.2
82
- *
83
- * @param $content The feed's content.
84
- * @param $feed_type The feed type (not used in excerpted content)
85
- * @return string The modified feed entry.
86
- */
87
- public function the_content_feed( $content = '', $feed_type = null ) {
88
-
89
- if ( ! $content )
90
- return '';
91
-
92
- /**
93
- * Don't alter already-excerpts or descriptions.
94
- * $feed_type is only set on 'the_content_feed' filter.
95
- */
96
- if ( isset( $feed_type ) && $this->get_option( 'excerpt_the_feed' ) ) {
97
- $content = $this->convert_feed_entry_to_excerpt( $content );
98
- }
99
-
100
- if ( $this->get_option( 'source_the_feed' ) ) {
101
- $content .= PHP_EOL . $this->get_feed_entry_source_link();
102
- }
103
-
104
- return $content;
105
- }
106
-
107
- /**
108
- * Converts feed content to excerpt.
109
- *
110
- * @since 2.9.0
111
- *
112
- * @param string $content The full feed entry content.
113
- * @return string The excerpted feed.
114
- */
115
- protected function convert_feed_entry_to_excerpt( $content = '' ) {
116
-
117
- if ( ! $content )
118
- return '';
119
-
120
- //* Strip all code and lines.
121
- $excerpt = $this->s_excerpt_raw( $content, false );
122
-
123
- $excerpt_len = (int) mb_strlen( $excerpt );
124
- /**
125
- * Applies filters the_seo_framework_max_content_feed_length : The max excerpt length.
126
- * @since 2.5.2
127
- */
128
- $max_len = (int) \apply_filters( 'the_seo_framework_max_content_feed_length', 400 );
129
-
130
- //* Generate excerpt.
131
- $excerpt = $this->trim_excerpt( $excerpt, $excerpt_len, $max_len );
132
-
133
- $h2_output = '';
134
-
135
- if ( 0 === strpos( $content, '<h2>' ) ) {
136
- //* Add the h2 title back
137
- $h2_end = mb_strpos( $content, '</h2>' );
138
-
139
- if ( false !== $h2_end ) {
140
- //* Start of content, plus <h2>
141
- $h2_start = 4;
142
- //* Remove the length of <h2>, again.
143
- $h2_end = $h2_end - $h2_start;
144
-
145
- //* Fetch h2 content.
146
- $h2_content = mb_substr( $content, $h2_start, $h2_end );
147
-
148
- //* Remove the H2 content from the excerpt.
149
- $count = 1;
150
- $excerpt = str_replace( $h2_content, '', $excerpt, $count );
151
-
152
- //* Wrap h2 content in h2 tags.
153
- $h2_output = '<h2>' . $h2_content . '</h2>' . PHP_EOL;
154
- }
155
- }
156
-
157
- $content = $h2_output . '<p>' . trim( $excerpt ) . '</p>';
158
-
159
- return $content;
160
- }
161
-
162
- /**
163
- * Generates and returns feed source link.
164
- *
165
- * @since 2.9.0
166
- *
167
- * @return string The translatable feed entry source link.
168
- */
169
- protected function get_feed_entry_source_link() {
170
-
171
- //* Fetch permalink and add it to the content. Already escaped.
172
- $permalink = $this->the_url();
173
-
174
- /**
175
- * Applies filters 'the_seo_framework_feed_source_link' : string
176
- *
177
- * @since 2.6.0
178
- * @since 2.7.2 or 2.7.3: Escaped output.
179
- *
180
- * @param string $source The source indication string.
181
- */
182
- $source_i18n = (string) \apply_filters( 'the_seo_framework_feed_source_link_text', \_x( 'Source', 'The content source', 'autodescription' ) );
183
- $content = '<p><a href="' . $permalink . '" rel="nofollow">' . \esc_html( $source_i18n ) . '</a></p>';
184
-
185
- return $content;
186
- }
187
- }
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 - 2017 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
+ * 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
+ /**
44
+ * Initializes feed actions and hooks.
45
+ *
46
+ * @since 2.9.0
47
+ * @access private
48
+ *
49
+ * @return void Early if this request isn't for a feed.
50
+ */
51
+ public function _init_feed_output() {
52
+
53
+ if ( ! $this->is_feed() )
54
+ return;
55
+
56
+ \add_filter( 'the_content_feed', array( $this, 'the_content_feed' ), 10, 2 );
57
+
58
+ //* Only add the feed link to the excerpt if we're only building excerpts.
59
+ if ( $this->rss_uses_excerpt() )
60
+ \add_filter( 'the_excerpt_rss', array( $this, 'the_content_feed' ), 10, 1 );
61
+
62
+ }
63
+
64
+ /**
65
+ * Determines whether the WordPress excerpt RSS feed option is used.
66
+ *
67
+ * @since 2.6.0
68
+ *
69
+ * @return bool
70
+ */
71
+ public function rss_uses_excerpt() {
72
+ return (bool) \get_option( 'rss_use_excerpt' );
73
+ }
74
+
75
+ /**
76
+ * Changes feed's content based on options.
77
+ *
78
+ * This method converts the input $content to an excerpt and is able to add
79
+ * a nofollow backlink at the end of the feed.
80
+ *
81
+ * @since 2.5.2
82
+ *
83
+ * @param $content The feed's content.
84
+ * @param $feed_type The feed type (not used in excerpted content)
85
+ * @return string The modified feed entry.
86
+ */
87
+ public function the_content_feed( $content = '', $feed_type = null ) {
88
+
89
+ if ( ! $content )
90
+ return '';
91
+
92
+ /**
93
+ * Don't alter already-excerpts or descriptions.
94
+ * $feed_type is only set on 'the_content_feed' filter.
95
+ */
96
+ if ( isset( $feed_type ) && $this->get_option( 'excerpt_the_feed' ) ) {
97
+ $content = $this->convert_feed_entry_to_excerpt( $content );
98
+ }
99
+
100
+ if ( $this->get_option( 'source_the_feed' ) ) {
101
+ $content .= PHP_EOL . $this->get_feed_entry_source_link();
102
+ }
103
+
104
+ return $content;
105
+ }
106
+
107
+ /**
108
+ * Converts feed content to excerpt.
109
+ *
110
+ * @since 2.9.0
111
+ *
112
+ * @param string $content The full feed entry content.
113
+ * @return string The excerpted feed.
114
+ */
115
+ protected function convert_feed_entry_to_excerpt( $content = '' ) {
116
+
117
+ if ( ! $content )
118
+ return '';
119
+
120
+ //* Strip all code and lines.
121
+ $excerpt = $this->s_excerpt_raw( $content, false );
122
+
123
+ $excerpt_len = (int) mb_strlen( $excerpt );
124
+ /**
125
+ * Applies filters the_seo_framework_max_content_feed_length : The max excerpt length.
126
+ * @since 2.5.2
127
+ */
128
+ $max_len = (int) \apply_filters( 'the_seo_framework_max_content_feed_length', 400 );
129
+
130
+ //* Generate excerpt.
131
+ $excerpt = $this->trim_excerpt( $excerpt, $excerpt_len, $max_len );
132
+
133
+ $h2_output = '';
134
+
135
+ if ( 0 === strpos( $content, '<h2>' ) ) {
136
+ //* Add the h2 title back
137
+ $h2_end = mb_strpos( $content, '</h2>' );
138
+
139
+ if ( false !== $h2_end ) {
140
+ //* Start of content, plus <h2>
141
+ $h2_start = 4;
142
+ //* Remove the length of <h2>, again.
143
+ $h2_end = $h2_end - $h2_start;
144
+
145
+ //* Fetch h2 content.
146
+ $h2_content = mb_substr( $content, $h2_start, $h2_end );
147
+
148
+ //* Remove the H2 content from the excerpt.
149
+ $count = 1;
150
+ $excerpt = str_replace( $h2_content, '', $excerpt, $count );
151
+
152
+ //* Wrap h2 content in h2 tags.
153
+ $h2_output = '<h2>' . $h2_content . '</h2>' . PHP_EOL;
154
+ }
155
+ }
156
+
157
+ $content = $h2_output . '<p>' . trim( $excerpt ) . '</p>';
158
+
159
+ return $content;
160
+ }
161
+
162
+ /**
163
+ * Generates and returns feed source link.
164
+ *
165
+ * @since 2.9.0
166
+ * @since 3.0.0 Now uses plain permalink, rather than enhanced canonical URL.
167
+ *
168
+ * @return string The translatable feed entry source link.
169
+ */
170
+ protected function get_feed_entry_source_link() {
171
+ /**
172
+ * Applies filters 'the_seo_framework_feed_source_link' : string
173
+ *
174
+ * @since 2.6.0
175
+ * @since 2.7.2 or 2.7.3: Escaped output.
176
+ *
177
+ * @param string $source The source indication string.
178
+ */
179
+ $source_i18n = (string) \apply_filters( 'the_seo_framework_feed_source_link_text', \_x( 'Source', 'The content source', 'autodescription' ) );
180
+ $content = '<p><a href="' . \esc_url( \get_permalink() ) . '" rel="nofollow">' . \esc_html( $source_i18n ) . '</a></p>';
181
+
182
+ return $content;
183
+ }
184
+ }
 
 
 
inc/classes/generate-description.class.php CHANGED
@@ -282,15 +282,15 @@ class Generate_Description extends Generate {
282
  protected function get_custom_archive_description( $args ) {
283
 
284
  $description = '';
 
285
 
286
- if ( $this->is_archive() ) {
287
- if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
288
-
289
- $term = $this->fetch_the_term( $args['id'] );
290
- $data = $this->get_term_data( $term, $args['id'] );
291
 
292
- $description = empty( $data['description'] ) ? $description : $data['description'];
293
- }
 
294
  }
295
 
296
  return $description;
@@ -300,6 +300,8 @@ class Generate_Description extends Generate {
300
  * Generates description from content while parsing filters.
301
  *
302
  * @since 2.3.3
 
 
303
  *
304
  * @param array $args description args : {
305
  * @param int $id the term or page id.
@@ -316,12 +318,15 @@ class Generate_Description extends Generate {
316
  $this->the_seo_framework_debug and $this->debug_init( __METHOD__, true, $debug_key = microtime( true ), get_defined_vars() );
317
 
318
  /**
319
- * Applies filters bool 'the_seo_framework_enable_auto_description' : Enable or disable the description.
320
  *
321
  * @since 2.5.0
 
 
 
322
  */
323
- $autodescription = (bool) \apply_filters( 'the_seo_framework_enable_auto_description', true );
324
- if ( false === $autodescription || $this->is_protected( $args['id'] ) )
325
  return '';
326
 
327
  $description = $this->generate_the_description( $args, false );
@@ -340,6 +345,7 @@ class Generate_Description extends Generate {
340
  * @since 2.6.0
341
  * @since 2.8.0 : The output is always trimmed if $escape is false.
342
  * : The cache will no longer be maintained on previews or search.
 
343
  *
344
  * @param array $args description args : {
345
  * @param int $id the term or page id.
@@ -364,6 +370,10 @@ class Generate_Description extends Generate {
364
  if ( $args['is_home'] || $this->is_real_front_page() || $this->is_front_page_by_id( $args['id'] ) )
365
  return $this->generate_home_page_description( $args['get_custom_field'], $escape );
366
 
 
 
 
 
367
  /**
368
  * Determines whether to prevent caching of transients.
369
  * @since 2.8.0
@@ -658,7 +668,7 @@ class Generate_Description extends Generate {
658
  * @access private
659
  *
660
  * @param int $id The post or term ID
661
- * @param object|empty $term The term object
662
  * @param bool $ignore Whether to ignore options and filters.
663
  * @return array : {
664
  * $title => The title
@@ -741,7 +751,7 @@ class Generate_Description extends Generate {
741
  * @since 2.5.2
742
  *
743
  * @param int $id The page ID.
744
- * @param void|object $term The term object.
745
  * @param bool $page_on_front If front page.
746
  * @return string The description title.
747
  */
@@ -774,7 +784,7 @@ class Generate_Description extends Generate {
774
  } elseif ( $term && isset( $term->term_id ) ) {
775
  //* We're on a taxonomy now.
776
 
777
- $data = $this->get_term_data( $term, $term->term_id );
778
 
779
  if ( ! empty( $data['doctitle'] ) ) {
780
  $title = $data['doctitle'];
282
  protected function get_custom_archive_description( $args ) {
283
 
284
  $description = '';
285
+ $is_term = false;
286
 
287
+ if ( $args['taxonomy'] && $args['id'] ) {
288
+ $is_term = (bool) \get_term( $args['id'], $args['taxonomy'] );
289
+ }
 
 
290
 
291
+ if ( $is_term || $this->is_archive() ) {
292
+ $data = $this->get_term_meta( $args['id'] );
293
+ $description = empty( $data['description'] ) ? '' : $data['description'];
294
  }
295
 
296
  return $description;
300
  * Generates description from content while parsing filters.
301
  *
302
  * @since 2.3.3
303
+ * @since 3.0.0 No longer checks for protected posts.
304
+ * Check is moved to $this->generate_the_description().
305
  *
306
  * @param array $args description args : {
307
  * @param int $id the term or page id.
318
  $this->the_seo_framework_debug and $this->debug_init( __METHOD__, true, $debug_key = microtime( true ), get_defined_vars() );
319
 
320
  /**
321
+ * Applies filters bool 'the_seo_framework_enable_auto_description'
322
  *
323
  * @since 2.5.0
324
+ * @since 3.0.0 Now passes $args as the second parameter.
325
+ * @param bool $autodescription Enable or disable the automated descriptions.
326
+ * @param array $args The description arguments.
327
  */
328
+ $autodescription = (bool) \apply_filters( 'the_seo_framework_enable_auto_description', true, $args );
329
+ if ( false === $autodescription )
330
  return '';
331
 
332
  $description = $this->generate_the_description( $args, false );
345
  * @since 2.6.0
346
  * @since 2.8.0 : The output is always trimmed if $escape is false.
347
  * : The cache will no longer be maintained on previews or search.
348
+ * @since 3.0.0 : Now checks for protected posts.
349
  *
350
  * @param array $args description args : {
351
  * @param int $id the term or page id.
370
  if ( $args['is_home'] || $this->is_real_front_page() || $this->is_front_page_by_id( $args['id'] ) )
371
  return $this->generate_home_page_description( $args['get_custom_field'], $escape );
372
 
373
+ //* If the post is protected, don't generate a description.
374
+ if ( $this->is_protected( $args['id'] ) )
375
+ return '';
376
+
377
  /**
378
  * Determines whether to prevent caching of transients.
379
  * @since 2.8.0
668
  * @access private
669
  *
670
  * @param int $id The post or term ID
671
+ * @param object|string $term The term object
672
  * @param bool $ignore Whether to ignore options and filters.
673
  * @return array : {
674
  * $title => The title
751
  * @since 2.5.2
752
  *
753
  * @param int $id The page ID.
754
+ * @param object|string $term The term object.
755
  * @param bool $page_on_front If front page.
756
  * @return string The description title.
757
  */
784
  } elseif ( $term && isset( $term->term_id ) ) {
785
  //* We're on a taxonomy now.
786
 
787
+ $data = $this->get_term_meta( $term->term_id );
788
 
789
  if ( ! empty( $data['doctitle'] ) ) {
790
  $title = $data['doctitle'];
inc/classes/generate-image.class.php CHANGED
@@ -517,6 +517,7 @@ class Generate_Image extends Generate_Url {
517
  * 2. Now adds ID call to OG image called listener.
518
  * @since 2.9.0 : Added $set_og_dimension parameter
519
  * @since 2.9.3 : 4k baby.
 
520
  *
521
  * @todo create formula to fetch transient.
522
  * @priority high 2.7.0
@@ -525,7 +526,7 @@ class Generate_Image extends Generate_Url {
525
  * @param int $id The attachment ID.
526
  * @param array $args The image args
527
  * @param bool $set_og_dimensions Whether to set OG dimensions.
528
- * @return string|empty Parsed image url or empty if already called
529
  */
530
  public function parse_og_image( $id, $args = array(), $set_og_dimensions = false ) {
531
 
@@ -608,6 +609,9 @@ class Generate_Image extends Generate_Url {
608
  $this->image_dimensions = $this->image_dimensions + array( $usage_id => array( 'width' => $w, 'height' => $h ) );
609
  }
610
 
 
 
 
611
  return $i;
612
  }
613
 
@@ -615,6 +619,7 @@ class Generate_Image extends Generate_Url {
615
  * Fetches site icon brought in WordPress 4.3
616
  *
617
  * @since 2.8.0
 
618
  *
619
  * @param string|int $size The icon size, accepts 'full' and pixel values.
620
  * @param bool $set_og_dimensions Whether to set size for OG image. Always falls back to the current post ID.
@@ -649,6 +654,9 @@ class Generate_Image extends Generate_Url {
649
  $icon = \get_site_icon_url( $size );
650
  }
651
 
 
 
 
652
  return $icon;
653
  }
654
 
@@ -656,6 +664,7 @@ class Generate_Image extends Generate_Url {
656
  * Fetches site logo brought in WordPress 4.5
657
  *
658
  * @since 2.8.0
 
659
  *
660
  * @param bool $set_og_dimensions Whether to set size for OG image. Always falls back to the current post ID.
661
  * @return string URL site logo, not escaped.
@@ -683,6 +692,9 @@ class Generate_Image extends Generate_Url {
683
  }
684
  }
685
 
 
 
 
686
  return $logo;
687
  }
688
 
@@ -691,6 +703,7 @@ class Generate_Image extends Generate_Url {
691
  * Also sets image dimensions. Falls back to current post ID for index.
692
  *
693
  * @since 2.7.0
 
694
  *
695
  * @param bool $set_og_dimensions Whether to set size for OG image. Always falls back to the current post ID.
696
  * @return string The header image URL, not escaped.
@@ -708,6 +721,9 @@ class Generate_Image extends Generate_Url {
708
  $this->image_dimensions = $this->image_dimensions + array( $this->get_the_real_ID() => array( 'width' => $w, 'height' => $h ) );
709
  }
710
 
 
 
 
711
  return $image;
712
  }
713
  }
517
  * 2. Now adds ID call to OG image called listener.
518
  * @since 2.9.0 : Added $set_og_dimension parameter
519
  * @since 2.9.3 : 4k baby.
520
+ * @since 3.0.0 : Now sets preferred canonical URL scheme.
521
  *
522
  * @todo create formula to fetch transient.
523
  * @priority high 2.7.0
526
  * @param int $id The attachment ID.
527
  * @param array $args The image args
528
  * @param bool $set_og_dimensions Whether to set OG dimensions.
529
+ * @return string Parsed image url or empty if already called
530
  */
531
  public function parse_og_image( $id, $args = array(), $set_og_dimensions = false ) {
532
 
609
  $this->image_dimensions = $this->image_dimensions + array( $usage_id => array( 'width' => $w, 'height' => $h ) );
610
  }
611
 
612
+ if ( $i && $this->matches_this_domain( $i ) )
613
+ $i = $this->set_preferred_url_scheme( $i );
614
+
615
  return $i;
616
  }
617
 
619
  * Fetches site icon brought in WordPress 4.3
620
  *
621
  * @since 2.8.0
622
+ * @since 3.0.0 : Now sets preferred canonical URL scheme.
623
  *
624
  * @param string|int $size The icon size, accepts 'full' and pixel values.
625
  * @param bool $set_og_dimensions Whether to set size for OG image. Always falls back to the current post ID.
654
  $icon = \get_site_icon_url( $size );
655
  }
656
 
657
+ if ( $icon && $this->matches_this_domain( $icon ) )
658
+ $icon = $this->set_preferred_url_scheme( $icon );
659
+
660
  return $icon;
661
  }
662
 
664
  * Fetches site logo brought in WordPress 4.5
665
  *
666
  * @since 2.8.0
667
+ * @since 3.0.0 : Now sets preferred canonical URL scheme.
668
  *
669
  * @param bool $set_og_dimensions Whether to set size for OG image. Always falls back to the current post ID.
670
  * @return string URL site logo, not escaped.
692
  }
693
  }
694
 
695
+ if ( $logo && $this->matches_this_domain( $logo ) )
696
+ $logo = $this->set_preferred_url_scheme( $logo );
697
+
698
  return $logo;
699
  }
700
 
703
  * Also sets image dimensions. Falls back to current post ID for index.
704
  *
705
  * @since 2.7.0
706
+ * @since 3.0.0 : Now sets preferred canonical URL scheme.
707
  *
708
  * @param bool $set_og_dimensions Whether to set size for OG image. Always falls back to the current post ID.
709
  * @return string The header image URL, not escaped.
721
  $this->image_dimensions = $this->image_dimensions + array( $this->get_the_real_ID() => array( 'width' => $w, 'height' => $h ) );
722
  }
723
 
724
+ if ( $image && $this->matches_this_domain( $image ) )
725
+ $image = $this->set_preferred_url_scheme( $image );
726
+
727
  return $image;
728
  }
729
  }
inc/classes/generate-ldjson.class.php CHANGED
@@ -33,7 +33,7 @@ defined( 'ABSPATH' ) or die;
33
  class Generate_Ldjson extends Generate_Image {
34
 
35
  /**
36
- * Constructor, load parent constructor
37
  */
38
  protected function __construct() {
39
  parent::__construct();
@@ -196,36 +196,35 @@ class Generate_Ldjson extends Generate_Image {
196
  * Generates LD+JSON Search and Sitename script.
197
  *
198
  * @since 2.9.3
 
199
  *
200
- * @return escaped LD+JSON Search and Sitename script.
201
  */
202
  public function get_ld_json_website() {
203
 
204
- $use_sitename = $this->enable_ld_json_sitename();
205
- $use_searchbox = $this->enable_ld_json_searchbox();
206
-
207
- if ( false === $use_sitename && false === $use_searchbox )
208
  return '';
209
 
210
  $data = array(
211
  '@context' => 'http://schema.org',
212
  '@type' => 'WebSite',
213
- 'url' => $this->the_home_url_from_cache(),
214
  );
215
 
216
- if ( $use_sitename ) {
217
- $name = $this->get_blogname();
218
  $kn = $this->get_option( 'knowledge_name' );
219
 
220
- $alternate_name = $kn && $kn !== $name ? $kn : '';
221
 
222
  $data += array(
223
- 'name' => $this->escape_title( $name ),
224
  'alternateName' => $this->escape_title( $alternate_name ),
225
  );
226
  }
227
 
228
- if ( $use_searchbox ) {
 
229
  $action_name = 'search_term_string';
230
  $search_link = $this->pretty_permalinks ? \trailingslashit( \get_search_link() ) : \get_search_link();
231
  /**
@@ -272,14 +271,13 @@ class Generate_Ldjson extends Generate_Image {
272
  $data = array(
273
  '@context' => 'http://schema.org',
274
  '@type' => ucfirst( \esc_attr( $knowledge_type ) ),
275
- 'url' => $this->the_home_url_from_cache(),
276
  'name' => $this->escape_title( $knowledge_name ),
277
  );
278
 
279
  if ( $this->get_option( 'knowledge_logo' ) && 'organization' === $knowledge_type ) {
280
- $logo = $this->get_site_logo() ?: $this->get_site_icon();
281
  $data += array(
282
- 'logo' => \esc_url_raw( $logo ),
283
  );
284
  }
285
 
@@ -323,12 +321,37 @@ class Generate_Ldjson extends Generate_Image {
323
  return '';
324
  }
325
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  /**
327
  * Generates LD+JSON Breadcrumbs script.
328
  *
329
  * @since 2.9.3
330
  *
331
- * @return escaped LD+JSON Breadcrumbs script.
332
  */
333
  public function get_ld_json_breadcrumbs() {
334
 
@@ -352,7 +375,7 @@ class Generate_Ldjson extends Generate_Image {
352
  *
353
  * @since 2.9.3
354
  *
355
- * @return escaped LD+JSON breadcrumbs script for Pages.
356
  */
357
  public function get_ld_json_breadcrumbs_page() {
358
 
@@ -381,12 +404,17 @@ class Generate_Ldjson extends Generate_Image {
381
  '@type' => 'ListItem',
382
  'position' => $position,
383
  'item' => array(
384
- '@id' => $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'id' => $parent_id ) ),
 
 
 
 
385
  'name' => $this->escape_title( $parent_name ),
386
  ),
387
  );
388
 
389
- if ( $image = $this->get_schema_image( $parent_id ) )
 
390
  $crumb['item']['image'] = $image;
391
 
392
  $items[] = $crumb;
@@ -405,20 +433,37 @@ class Generate_Ldjson extends Generate_Image {
405
  * Generates LD+JSON Breadcrumbs script for Posts.
406
  *
407
  * @since 2.9.3
 
 
408
  *
409
- * @return escaped LD+JSON breadcrumbs script for Posts.
410
  */
411
  public function get_ld_json_breadcrumbs_post() {
412
 
413
  $output = '';
414
 
415
  $post_id = $this->get_the_real_ID();
 
 
 
 
 
 
 
 
 
 
 
 
416
 
417
- //* WooCommerce support.
418
- $cat_type = $this->is_wc_product() ? 'product_cat' : 'category';
 
 
 
419
 
420
  //* Test categories.
421
- $r = \is_object_in_term( $post_id, $cat_type, '' );
422
  if ( ! $r || \is_wp_error( $r ) )
423
  return '';
424
 
@@ -426,218 +471,121 @@ class Generate_Ldjson extends Generate_Image {
426
  * Applies filter 'the_seo_framework_ld_json_breadcrumb_terms' : array
427
  * @since 2.8.0
428
  *
429
- * @param array $cats The LD+JSON terms that are being used
430
  * @param int $post_id The current Post ID.
431
- * @param string $cat_type The current taxonomy (either category or product_cat).
432
  */
433
- $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 ) );
434
 
435
- if ( empty( $cats ) )
436
  return '';
437
 
438
- $cats = \wp_list_pluck( $cats, 'parent', 'term_id' );
439
- asort( $cats, SORT_NUMERIC );
440
 
441
- $assigned_ids = array();
442
- $kittens = array();
443
  $parents = array();
444
- $parents_merge = array();
445
 
446
  //* Fetch cats children id's, if any.
447
- foreach ( $cats as $term_id => $parent_id ) :
448
-
449
- //* Store all used IDs to compare and filter stray Cat ID's later.
450
- //= i.e. $kittens => $term_id_1 => $term_id_maybe_unassigned_to_post.
451
- $assigned_ids[] = $term_id;
452
-
453
- // Check if they have kittens (gets them all).
454
- $children = \get_term_children( $term_id, $cat_type );
455
- if ( ! \is_wp_error( $children ) ) {
456
- /**
457
- * Save children id's as kittens.
458
- * Although stray terms don't have children, we assign them as
459
- * $kittens are also the latest version (even if $children === 0).
460
- *
461
- * This gets filtered later.
462
- */
463
- $kittens[ $term_id ] = $children;
464
- }
465
-
466
  // Check if they have parents (gets them all).
467
- $ancestors = \get_ancestors( $term_id, $cat_type );
468
  if ( $ancestors ) {
469
  //= Save parents to find duplicates.
470
  $parents[ $term_id ] = $ancestors;
 
 
 
471
  }
472
  endforeach;
473
  //= Circle of life...
474
- unset( $cats );
475
 
476
- if ( ! $kittens )
477
- return '';
478
 
479
- foreach ( $kittens as $kit_id => $child_id ) :
 
480
  foreach ( $child_id as $ckey => $cid ) :
481
-
482
- /**
483
- * Seed out children that aren't assigned.
484
- * (from levels too deep as get_term_children gets them all).
485
- */
486
- if ( $cid && ! in_array( $cid, $assigned_ids, true ) )
487
- unset( $kittens[ $kit_id ][ $ckey ] );
488
-
489
- /**
490
- * Make the tree count down multiple children are assigned.
491
- * This fetches the array from the ancestors.
492
- *
493
- * What we want is that the latest child ID gets its own single tree.
494
- * All ancestors should be a representation of the previous assigned trees.
495
- *
496
- * E.g. We have this structure, all assigned:
497
- * - Cat 1
498
- * - Cat 2
499
- * - Cat 3
500
- *
501
- * We want a tree for "Cat 1+2+3", "Cat 1+2", and "Cat 3".
502
- *
503
- * We could add Cat 1 as well, but that's will give two single category lines, which could be misinterperted.
504
- * So we only use what we know: The kittens (child tree).
505
- */
506
- if ( isset( $parents[ $cid ] ) && ! empty( $parents[ $kit_id ] ) ) {
507
- $parents_merge[ $kit_id ] = $parents[ $kit_id ];
508
- unset( $kittens[ $kit_id ] );
509
  }
510
  endforeach;
511
  endforeach;
512
 
513
- /**
514
- * Build category ID trees for kittens.
515
- */
516
- $trees = $this->build_ld_json_breadcrumb_trees( $kittens );
517
-
518
- //* Empty parents.
519
- $parents = array();
520
-
521
- if ( ! empty( $parents_merge ) ) :
522
- foreach ( $parents_merge as $child_id => $parents_ids ) {
523
-
524
- //* Reset kitten.
525
- $kitten = array();
526
-
527
- //* Last element should be parent.
528
- $pid = array_pop( $parents_ids );
529
-
530
- if ( isset( $pid ) ) {
531
- //* Parents are reversed children. Let's fix that.
532
- $parents_ids = array_reverse( $parents_ids );
533
-
534
- //* Add previous parent at the end of the rest.
535
- array_push( $parents_ids, $child_id );
536
-
537
- //* Temporarily array.
538
- $kitten[ $pid ] = $parents_ids;
539
-
540
- $trees = $this->build_ld_json_breadcrumb_trees( $kitten, $trees );
541
- } else {
542
- //* Parents are reversed children. Let's fix that.
543
- $parents_ids = array_reverse( $parents_ids );
544
-
545
- $trees = $this->build_ld_json_breadcrumb_trees( $parents_ids, $trees );
546
- }
547
- }
548
- endif;
549
 
550
- if ( ! $trees )
551
  return '';
552
 
 
 
 
 
553
  /**
554
- * Sort by number of id's. Provides a cleaner layout, better Search Engine understanding and more consistent cache.
 
 
555
  */
556
- if ( count( $trees ) > 1 ) :
557
- $cb_filter = null;
558
- if ( \has_filter( 'the_seo_framework_breadcrumb_post_sorting_callback' ) ) {
559
- /**
560
- * Applies filter 'the_seo_framework_breadcrumb_post_sorting_callback' : string|array
561
- * @since 2.8.0
562
- *
563
- * @param mixed $function The method or function callback. Default false.
564
- * @param array $trees The current tree list.
565
- */
566
- $cb_filter = \apply_filters_ref_array( 'the_seo_framework_breadcrumb_post_sorting_callback', array( false, $trees ) );
567
- }
568
-
569
- if ( $cb_filter ) {
570
- $trees = $this->call_function( $callback_filter, '2.8.0', $trees );
571
- } else {
572
- array_multisort( array_map( 'count', $trees ), SORT_DESC, SORT_REGULAR, $trees );
573
  }
574
- endif;
575
-
576
- if ( ! $trees )
577
- return '';
578
-
579
- //* For each of the tree items, create a separated script.
580
- foreach ( $trees as $tree_ids ) :
581
-
582
- if ( is_scalar( $tree_ids ) )
583
- $tree_ids = array( $tree_ids );
584
-
585
- /**
586
- * @staticvar int $item_cache
587
- * Used to prevent duplicated item re-generation.
588
- */
589
- static $item_cache = array();
590
-
591
- $items = array();
592
 
593
- //* Put the children in the right order.
594
- $tree_ids = array_reverse( $tree_ids, false );
595
 
596
- foreach ( $tree_ids as $pos => $child_id ) :
597
- if ( ! in_array( $child_id, $assigned_ids, true ) )
598
- continue;
599
 
600
- $position = $pos + 2;
 
601
 
602
- //* Fetch item from cache if available.
603
- if ( isset( $item_cache[ $child_id ] ) ) {
604
- //* Adjust postition.
605
- $item_cache[ $child_id ]['position'] = $position;
606
- $items[] = $item_cache[ $child_id ];
 
607
  } else {
608
- $cat = \get_term( $child_id, $cat_type );
609
-
610
- if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
611
- //* Note: WordPress Core translation.
612
- $data = $this->get_term_data( $cat, $child_id );
613
- $cat_name = empty( $data['doctitle'] ) ? ( empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name ) : $data['doctitle'];
614
- } else {
615
- //* Note: WordPress Core translation.
616
- $cat_name = empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name;
617
- }
618
-
619
- //* Store in cache.
620
- $item_cache[ $child_id ] = array(
621
- '@type' => 'ListItem',
622
- 'position' => $position,
623
- 'item' => array(
624
- '@id' => $this->the_url( '', array( 'get_custom_field' => false, 'is_term' => true, 'external' => true, 'term' => $cat ) ),
625
- 'name' => $this->escape_title( $cat_name ),
626
- // 'image' => $this->get_schema_image( $child_id ),
627
- ),
628
- );
629
-
630
- $items[] = $item_cache[ $child_id ];
631
  }
632
- endforeach;
633
-
634
- if ( $items ) {
635
- array_unshift( $items, $this->get_ld_json_breadcrumb_home_crumb() );
636
- array_push( $items, $this->get_ld_json_breadcrumb_current( $position ) );
637
- $output .= $this->make_breadcrumb_script( $items );
638
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
639
  endforeach;
640
 
 
 
 
 
 
 
641
  return $output;
642
  }
643
 
@@ -683,6 +631,37 @@ class Generate_Ldjson extends Generate_Image {
683
  return $trees;
684
  }
685
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
686
  /**
687
  * Generates homepage LD+JSON breadcrumb.
688
  *
@@ -718,8 +697,8 @@ class Generate_Ldjson extends Generate_Image {
718
  '@type' => 'ListItem',
719
  'position' => 1,
720
  'item' => array(
721
- '@id' => $this->the_home_url_from_cache(),
722
- 'name' => $custom_name,
723
  ),
724
  );
725
 
@@ -733,6 +712,7 @@ class Generate_Ldjson extends Generate_Image {
733
  * Generates current Page/Post LD+JSON breadcrumb.
734
  *
735
  * @since 2.9.3
 
736
  * @staticvar array $crumb
737
  *
738
  * @param int $position The previous crumb position.
@@ -761,8 +741,8 @@ class Generate_Ldjson extends Generate_Image {
761
  '@type' => 'ListItem',
762
  'position' => $position,
763
  'item' => array(
764
- '@id' => $this->the_url_from_cache(),
765
- 'name' => $name,
766
  ),
767
  );
768
 
@@ -808,6 +788,39 @@ class Generate_Ldjson extends Generate_Image {
808
  return '';
809
  }
810
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
811
  /**
812
  * Determines whether to use the SEO title or only the fallback page title.
813
  *
@@ -859,31 +872,6 @@ class Generate_Ldjson extends Generate_Image {
859
  return $cache = $filter && $option;
860
  }
861
 
862
- /**
863
- * Determines if sitename script is enabled.
864
- *
865
- * @since 2.6.0
866
- * @staticvar bool $cache
867
- *
868
- * @return bool
869
- */
870
- public function enable_ld_json_sitename() {
871
-
872
- static $cache = null;
873
-
874
- if ( isset( $cache ) )
875
- return $cache;
876
-
877
- /**
878
- * Applies filters the_seo_framework_json_sitename_output
879
- * @since 2.6.0
880
- */
881
- $filter = (bool) \apply_filters( 'the_seo_framework_json_sitename_output', true );
882
- $option = $this->is_option_checked( 'ld_json_sitename' );
883
-
884
- return $cache = $filter && $option;
885
- }
886
-
887
  /**
888
  * Determines if searchbox script is enabled.
889
  *
33
  class Generate_Ldjson extends Generate_Image {
34
 
35
  /**
36
+ * Constructor, load parent constructor and inits class.
37
  */
38
  protected function __construct() {
39
  parent::__construct();
196
  * Generates LD+JSON Search and Sitename script.
197
  *
198
  * @since 2.9.3
199
+ * @since 3.0.0 This whole functions now only listens to the searchbox option.
200
  *
201
+ * @return string escaped LD+JSON Search and Sitename script.
202
  */
203
  public function get_ld_json_website() {
204
 
205
+ if ( ! $this->enable_ld_json_searchbox() )
 
 
 
206
  return '';
207
 
208
  $data = array(
209
  '@context' => 'http://schema.org',
210
  '@type' => 'WebSite',
211
+ 'url' => $this->get_homepage_permalink(),
212
  );
213
 
214
+ name : {
215
+ $blogname = $this->get_blogname();
216
  $kn = $this->get_option( 'knowledge_name' );
217
 
218
+ $alternate_name = $kn && $kn !== $blogname ? $kn : '';
219
 
220
  $data += array(
221
+ 'name' => $this->escape_title( $blogname ),
222
  'alternateName' => $this->escape_title( $alternate_name ),
223
  );
224
  }
225
 
226
+ //= The actual searchbox part.
227
+ searchbox : {
228
  $action_name = 'search_term_string';
229
  $search_link = $this->pretty_permalinks ? \trailingslashit( \get_search_link() ) : \get_search_link();
230
  /**
271
  $data = array(
272
  '@context' => 'http://schema.org',
273
  '@type' => ucfirst( \esc_attr( $knowledge_type ) ),
274
+ 'url' => $this->get_homepage_permalink(),
275
  'name' => $this->escape_title( $knowledge_name ),
276
  );
277
 
278
  if ( $this->get_option( 'knowledge_logo' ) && 'organization' === $knowledge_type ) {
 
279
  $data += array(
280
+ 'logo' => \esc_url_raw( $this->get_knowledge_logo() ),
281
  );
282
  }
283
 
321
  return '';
322
  }
323
 
324
+ /**
325
+ * Returns knowledge logo URL.
326
+ * It first tries to get the option and then the Customizer icon.
327
+ *
328
+ * @since 3.0.0
329
+ *
330
+ * @param bool $get_option Whether to fetch the option.
331
+ * @return string The logo URL.
332
+ */
333
+ public function get_knowledge_logo( $get_option = true ) {
334
+ /**
335
+ * Applies filters 'the_seo_framework_knowledge_logo'
336
+ *
337
+ * @since 3.0.0
338
+ * @param string $logo The current logo URL.
339
+ * @param bool $get_option Whether to test the option or just the fallbacks.
340
+ */
341
+ return \apply_filters_ref_array( 'the_seo_framework_knowledge_logo', array(
342
+ ( $get_option ? $this->get_option( 'knowledge_logo_url' ) : false )
343
+ ?: $this->get_site_icon()
344
+ ?: '',
345
+ $get_option,
346
+ ) );
347
+ }
348
+
349
  /**
350
  * Generates LD+JSON Breadcrumbs script.
351
  *
352
  * @since 2.9.3
353
  *
354
+ * @return string LD+JSON Breadcrumbs script.
355
  */
356
  public function get_ld_json_breadcrumbs() {
357
 
375
  *
376
  * @since 2.9.3
377
  *
378
+ * @return string LD+JSON breadcrumbs script for Pages.
379
  */
380
  public function get_ld_json_breadcrumbs_page() {
381
 
404
  '@type' => 'ListItem',
405
  'position' => $position,
406
  'item' => array(
407
+ '@id' => $this->get_schema_url_id(
408
+ 'breadcrumb',
409
+ 'create',
410
+ array( 'id' => $parent_id )
411
+ ),
412
  'name' => $this->escape_title( $parent_name ),
413
  ),
414
  );
415
 
416
+ $image = $this->get_schema_image( $parent_id );
417
+ if ( $image )
418
  $crumb['item']['image'] = $image;
419
 
420
  $items[] = $crumb;
433
  * Generates LD+JSON Breadcrumbs script for Posts.
434
  *
435
  * @since 2.9.3
436
+ * @since 3.0.0 1: Now only returns one crumb.
437
+ * 2: Now listens to primary term ID.
438
  *
439
+ * @return string LD+JSON breadcrumbs script for Posts.
440
  */
441
  public function get_ld_json_breadcrumbs_post() {
442
 
443
  $output = '';
444
 
445
  $post_id = $this->get_the_real_ID();
446
+ $post_type = \get_post_type( $post_id );
447
+ $taxonomies = $this->get_hierarchical_taxonomies_as( 'names', \get_post_type( $post_id ) );
448
+
449
+ /**
450
+ * Applies filters 'the_seo_framework_ld_json_breadcrumb_terms'
451
+ *
452
+ * @since 3.0.0
453
+ * @param array|string $taxonomies The assigned hierarchical taxonomies.
454
+ * @param string $post_type The current post type.
455
+ * @param int $post_id The current Post ID.
456
+ */
457
+ $taxonomies = \apply_filters( 'the_seo_framework_ld_json_breadcrumb_taxonomies', $taxonomies, $post_type, $post_id );
458
 
459
+ if ( is_array( $taxonomies ) ) {
460
+ $taxonomy = reset( $taxonomies );
461
+ } else {
462
+ $taxonomy = $taxonomies;
463
+ }
464
 
465
  //* Test categories.
466
+ $r = \is_object_in_term( $post_id, $taxonomy, '' );
467
  if ( ! $r || \is_wp_error( $r ) )
468
  return '';
469
 
471
  * Applies filter 'the_seo_framework_ld_json_breadcrumb_terms' : array
472
  * @since 2.8.0
473
  *
474
+ * @param array $terms The LD+JSON terms that are being used
475
  * @param int $post_id The current Post ID.
476
+ * @param string $taxonomy The current taxonomy (either category or product_cat).
477
  */
478
+ $terms = (array) \apply_filters_ref_array( 'the_seo_framework_ld_json_breadcrumb_terms', array( \get_the_terms( $post_id, $taxonomy ), $post_id, $taxonomy ) );
479
 
480
+ if ( empty( $terms ) )
481
  return '';
482
 
483
+ $terms = \wp_list_pluck( $terms, 'parent', 'term_id' );
 
484
 
 
 
485
  $parents = array();
486
+ $assigned_ids = array();
487
 
488
  //* Fetch cats children id's, if any.
489
+ foreach ( $terms as $term_id => $parent_id ) :
490
+ $assigned_ids[ $term_id ] = $parent_id;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
  // Check if they have parents (gets them all).
492
+ $ancestors = \get_ancestors( $term_id, $taxonomy );
493
  if ( $ancestors ) {
494
  //= Save parents to find duplicates.
495
  $parents[ $term_id ] = $ancestors;
496
+ } else {
497
+ //= Save current only with empty parent id..
498
+ $parents[ $term_id ] = array();
499
  }
500
  endforeach;
501
  //= Circle of life...
502
+ unset( $terms );
503
 
504
+ if ( ! $parents )
505
+ return;
506
 
507
+ //* Seed out parents that have multiple assigned children.
508
+ foreach ( $parents as $pa_id => $child_id ) :
509
  foreach ( $child_id as $ckey => $cid ) :
510
+ if ( isset( $parents[ $cid ] ) ) {
511
+ unset( $parents[ $cid ] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
  }
513
  endforeach;
514
  endforeach;
515
 
516
+ //* Merge tree list.
517
+ $tree_ids = $this->build_ld_json_breadcrumb_trees( $parents );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518
 
519
+ if ( ! $tree_ids )
520
  return '';
521
 
522
+ $primary_term = $this->get_primary_term( $post_id, $taxonomy );
523
+ $primary_term_id = $primary_term ? (int) $primary_term->term_id : 0;
524
+
525
+ $filtered = false;
526
  /**
527
+ * Only get one crumb.
528
+ * If a category has multiple trees, it will filter until found.
529
+ * @since 3.0.0
530
  */
531
+ if ( $primary_term_id ) {
532
+ $_trees = $this->filter_ld_json_breadcrumb_trees( $tree_ids, $primary_term_id );
533
+ if ( $_trees ) {
534
+ $tree_ids = $_trees;
535
+ $filtered = true;
 
 
 
 
 
 
 
 
 
 
 
 
536
  }
537
+ }
538
+ if ( ! $filtered ) {
539
+ //= Only get the first tree through numeric ordering.
540
+ ksort( $assigned_ids, SORT_NUMERIC );
541
+ $tree_ids = $this->filter_ld_json_breadcrumb_trees( $tree_ids, key( $assigned_ids ) );
542
+ }
 
 
 
 
 
 
 
 
 
 
 
 
543
 
544
+ if ( is_scalar( $tree_ids ) )
545
+ $tree_ids = array( $tree_ids );
546
 
547
+ $items = array();
 
 
548
 
549
+ foreach ( $tree_ids as $pos => $child_id ) :
550
+ $position = $pos + 2;
551
 
552
+ if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
553
+ $data = $this->get_term_meta( $child_id );
554
+ if ( empty( $data['doctitle'] ) ) {
555
+ $cat = \get_term( $child_id, $taxonomy );
556
+ //* Note: WordPress Core translation.
557
+ $cat_name = empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name;
558
  } else {
559
+ $cat_name = $data['doctitle'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
  }
561
+ } else {
562
+ $cat = \get_term( $child_id, $taxonomy );
563
+ //* Note: WordPress Core translation.
564
+ $cat_name = empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name;
 
 
565
  }
566
+
567
+ //* Store in cache.
568
+ $items[] = array(
569
+ '@type' => 'ListItem',
570
+ 'position' => $position,
571
+ 'item' => array(
572
+ '@id' => $this->get_schema_url_id(
573
+ 'breadcrumb',
574
+ 'create',
575
+ array( 'id' => $child_id, 'taxonomy' => $taxonomy )
576
+ ),
577
+ 'name' => $this->escape_title( $cat_name ),
578
+ // 'image' => $this->get_schema_image( $child_id ),
579
+ ),
580
+ );
581
  endforeach;
582
 
583
+ if ( $items ) {
584
+ array_unshift( $items, $this->get_ld_json_breadcrumb_home_crumb() );
585
+ array_push( $items, $this->get_ld_json_breadcrumb_current( $position ) );
586
+ $output .= $this->make_breadcrumb_script( $items );
587
+ }
588
+
589
  return $output;
590
  }
591
 
631
  return $trees;
632
  }
633
 
634
+ /**
635
+ * Filters breadcrumb tree until $until is found.
636
+ *
637
+ * @since 3.0.0
638
+ *
639
+ * @param array|int $trees
640
+ * @param int $until
641
+ * @return array $trees. Empty if $until is nowhere to be found.
642
+ */
643
+ protected function filter_ld_json_breadcrumb_trees( $trees, $until ) {
644
+
645
+ $found = array();
646
+
647
+ if ( in_array( $until, (array) $trees, true ) ) {
648
+ $found = array( $until );
649
+ } elseif ( is_array( $trees ) ) {
650
+ foreach ( $trees as $tree ) {
651
+ if ( $this->filter_ld_json_breadcrumb_trees( $tree, $until ) ) {
652
+ $found = array_splice(
653
+ $tree,
654
+ 0,
655
+ array_search( $until, $tree, true ) + 1
656
+ );
657
+ break;
658
+ }
659
+ }
660
+ }
661
+
662
+ return $found;
663
+ }
664
+
665
  /**
666
  * Generates homepage LD+JSON breadcrumb.
667
  *
697
  '@type' => 'ListItem',
698
  'position' => 1,
699
  'item' => array(
700
+ '@id' => $this->get_schema_url_id( 'breadcrumb', 'homepage' ),
701
+ 'name' => $this->escape_title( $custom_name ),
702
  ),
703
  );
704
 
712
  * Generates current Page/Post LD+JSON breadcrumb.
713
  *
714
  * @since 2.9.3
715
+ * @since 3.0.0 Removed @id output to allow for more same-page schema items.
716
  * @staticvar array $crumb
717
  *
718
  * @param int $position The previous crumb position.
741
  '@type' => 'ListItem',
742
  'position' => $position,
743
  'item' => array(
744
+ // '@id' => $this->get_schema_url_id( 'breadcrumb', 'currentpage' ),
745
+ 'name' => $this->escape_title( $name ),
746
  ),
747
  );
748
 
788
  return '';
789
  }
790
 
791
+ /**
792
+ * Returns Schema.org '@id' part from URL.
793
+ *
794
+ * @since 3.0.0
795
+ *
796
+ * @param string $id The type of script. Must be escaped.
797
+ * @param string $from Where to generate from.
798
+ * @param array $args The URL generation args.
799
+ * @return string The JSON URL '@id'
800
+ */
801
+ public function get_schema_url_id( $id, $from, $args = array() ) {
802
+
803
+ switch ( $from ) {
804
+ case 'currentpage' :
805
+ $url = $this->get_current_permalink();
806
+ break;
807
+
808
+ case 'homepage' :
809
+ $url = $this->get_homepage_permalink();
810
+ break;
811
+
812
+ case 'create' :
813
+ $url = $this->create_canonical_url( $args );
814
+ break;
815
+
816
+ default :
817
+ $url = '';
818
+ break;
819
+ }
820
+
821
+ return $url;
822
+ }
823
+
824
  /**
825
  * Determines whether to use the SEO title or only the fallback page title.
826
  *
872
  return $cache = $filter && $option;
873
  }
874
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
875
  /**
876
  * Determines if searchbox script is enabled.
877
  *
inc/classes/generate-title.class.php CHANGED
@@ -544,6 +544,7 @@ class Generate_Title extends Generate_Description {
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 {
@@ -723,18 +724,22 @@ class Generate_Title extends Generate_Description {
723
  $title = '';
724
  $term = null;
725
 
 
726
  if ( $args['term_id'] && $args['taxonomy'] )
727
  $term = \get_term( $args['term_id'], $args['taxonomy'], OBJECT, 'raw' );
728
 
729
- if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
 
730
  if ( ! isset( $term ) && $this->is_tax() )
731
  $term = \get_term_by( 'slug', \get_query_var( 'term' ), \get_query_var( 'taxonomy' ) );
732
 
 
733
  if ( ! isset( $term ) )
734
  $term = $this->fetch_the_term( $args['term_id'] );
735
 
736
- if ( $args['get_custom_field'] ) {
737
- $data = $this->get_term_data( $term, $args['term_id'] );
 
738
  $title = empty( $data['doctitle'] ) ? $title : $data['doctitle'];
739
  }
740
  }
@@ -773,10 +778,14 @@ class Generate_Title extends Generate_Description {
773
  } elseif ( $this->is_blog_page( $id ) ) {
774
  //* Posts page title.
775
  $title = $this->get_custom_field( '_genesis_title', $id ) ?: \get_the_title( $id );
776
- } elseif ( $this->is_archive() || ( $id && $taxonomy ) ) {
 
 
777
  //* Get the custom title for terms.
778
  $term = \get_term( $id, $taxonomy, OBJECT, 'raw' );
779
- $data = $this->get_term_data( $term, $id );
 
 
780
 
781
  $title = empty( $data['doctitle'] ) ? $title : $data['doctitle'];
782
  }
@@ -820,7 +829,7 @@ class Generate_Title extends Generate_Description {
820
  /**
821
  * @since 2.6.0
822
  */
823
- $use_prefix = $this->use_archive_prefix( $term, $args );
824
 
825
  if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
826
  $title = $this->single_term_title( '', false, $term );
@@ -879,7 +888,7 @@ class Generate_Title extends Generate_Description {
879
  } elseif ( \is_post_type_archive() ) {
880
  $title = \post_type_archive_title( '', false ) ?: $this->get_the_term_name( $term, true, false );
881
  /* translators: Front-end output. */
882
- $title = $use_prefix ? sprintf( __( 'Archives: %s' ), $title ) : $title;
883
  } elseif ( isset( $term ) ) {
884
  $title = $this->single_term_title( '', false, $term );
885
 
@@ -1283,17 +1292,14 @@ class Generate_Title extends Generate_Description {
1283
  * Determines whether to use a title prefix or not.
1284
  *
1285
  * @since 2.6.0
 
1286
  * @staticvar bool $cache
1287
  *
1288
  * @param object $term The Term object.
1289
  * @param array $args The title arguments.
1290
  * @return bool
1291
  */
1292
- public function use_archive_prefix( $term = null, $args = array() ) {
1293
-
1294
- //* Don't add prefix in meta.
1295
- if ( $args['meta'] )
1296
- return false;
1297
 
1298
  static $cache = null;
1299
 
544
  if ( $args['page_on_front'] ) {
545
  $title = $this->title_for_home( '', $args['get_custom_field'], false, true );
546
  } elseif ( $this->is_archive() ) {
547
+ //= @CODEDEBT
548
  if ( ( $id && $taxonomy ) || $this->is_category() || $this->is_tag() || $this->is_tax() ) {
549
  $title = $this->title_for_terms( $args, false );
550
  } else {
724
  $title = '';
725
  $term = null;
726
 
727
+ //= @CODEDEBT
728
  if ( $args['term_id'] && $args['taxonomy'] )
729
  $term = \get_term( $args['term_id'], $args['taxonomy'], OBJECT, 'raw' );
730
 
731
+ if ( $this->is_term_meta_capable() ) {
732
+ //= @CODEDEBT
733
  if ( ! isset( $term ) && $this->is_tax() )
734
  $term = \get_term_by( 'slug', \get_query_var( 'term' ), \get_query_var( 'taxonomy' ) );
735
 
736
+ //= @CODEDEBT
737
  if ( ! isset( $term ) )
738
  $term = $this->fetch_the_term( $args['term_id'] );
739
 
740
+ //= @CODEDEBT
741
+ if ( $args['get_custom_field'] && $term ) {
742
+ $data = $this->get_term_meta( $term->term_id );
743
  $title = empty( $data['doctitle'] ) ? $title : $data['doctitle'];
744
  }
745
  }
778
  } elseif ( $this->is_blog_page( $id ) ) {
779
  //* Posts page title.
780
  $title = $this->get_custom_field( '_genesis_title', $id ) ?: \get_the_title( $id );
781
+ } elseif ( $this->is_term_meta_capable() || ( $id && $taxonomy ) ) {
782
+ //= @CODEDEBT
783
+
784
  //* Get the custom title for terms.
785
  $term = \get_term( $id, $taxonomy, OBJECT, 'raw' );
786
+
787
+ if ( $term && isset( $term->term_id ) )
788
+ $data = $this->get_term_meta( $term->term_id );
789
 
790
  $title = empty( $data['doctitle'] ) ? $title : $data['doctitle'];
791
  }
829
  /**
830
  * @since 2.6.0
831
  */
832
+ $use_prefix = ! empty( $args['meta'] ) ? false : $this->use_archive_prefix( $term );
833
 
834
  if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
835
  $title = $this->single_term_title( '', false, $term );
888
  } elseif ( \is_post_type_archive() ) {
889
  $title = \post_type_archive_title( '', false ) ?: $this->get_the_term_name( $term, true, false );
890
  /* translators: Front-end output. */
891
+ $title = $use_prefix ? sprintf( \__( 'Archives: %s' ), $title ) : $title;
892
  } elseif ( isset( $term ) ) {
893
  $title = $this->single_term_title( '', false, $term );
894
 
1292
  * Determines whether to use a title prefix or not.
1293
  *
1294
  * @since 2.6.0
1295
+ * @since 3.0.0 Removed second parameter.
1296
  * @staticvar bool $cache
1297
  *
1298
  * @param object $term The Term object.
1299
  * @param array $args The title arguments.
1300
  * @return bool
1301
  */
1302
+ public function use_archive_prefix( $term = null ) {
 
 
 
 
1303
 
1304
  static $cache = null;
1305
 
inc/classes/generate-url.class.php CHANGED
@@ -32,26 +32,6 @@ defined( 'ABSPATH' ) or die;
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
  */
@@ -60,498 +40,413 @@ class Generate_Url extends Generate_Title {
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
- * @since 2.9.0 : When using 'home => true' args parameter, the home path is added when set.
69
- * @since 2.9.2 Added filter usage cache.
70
- * @staticvar array $_has_filters
71
  *
72
- * @param string $url the url
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.
76
- * @param bool $from_option Get the canonical uri option
77
- * @param object $post The Post Object.
78
- * @param bool $external Whether to fetch the current WP Request or get the permalink by Post Object.
79
- * @param bool $is_term Fetch url for term.
80
- * @param object $term The term object.
81
- * @param bool $home Fetch home URL.
82
- * @param bool $forceslash Fetch home URL and slash it, always.
83
- * @param int $id The Page or Term ID.
84
  * }
85
- * @return string Escape url.
86
  */
87
- public function the_url( $url = '', $args = array() ) {
88
-
89
- $this->the_seo_framework_debug && false === $this->doing_sitemap and $this->debug_init( __METHOD__, true, $debug_key = microtime( true ), get_defined_vars() );
90
 
91
- $args = $this->reparse_url_args( $args );
 
 
 
 
 
92
 
93
- /**
94
- * Fetch permalink if Feed.
95
- * @since 2.5.2
96
- */
97
- if ( $this->is_feed() )
98
- $url = \get_permalink();
99
-
100
- //* Reset cache.
101
- $this->url_slashit = true;
102
- $this->unset_current_subdomain();
103
- $this->current_host = '';
104
 
105
- $path = '';
106
- $scheme = '';
107
- $slashit = true;
 
 
 
 
 
 
108
 
109
- if ( false === $args['home'] && empty( $url ) ) {
110
- /**
111
- * Get URL from options.
112
- * @since 2.2.9
113
- */
114
- if ( $args['get_custom_field'] && $this->is_singular() ) {
115
- $custom_url = $this->get_custom_field( '_genesis_canonical_uri' );
116
-
117
- if ( $custom_url ) {
118
- $url = $custom_url;
119
- $this->url_slashit = false;
120
- $parsed_url = \wp_parse_url( $custom_url );
121
- $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : 'http';
122
- }
123
- }
124
 
125
- if ( empty( $url ) )
126
- $path = $this->generate_url_path( $args );
127
- } elseif ( $args['home'] ) {
128
- $path = $this->get_home_path();
 
 
 
129
  }
130
 
131
- static $_has_filters = null;
132
- if ( null === $_has_filters ) {
133
- $_has_filters = array();
134
- $_has_filters['the_seo_framework_url_path'] = \has_filter( 'the_seo_framework_url_path' );
135
- $_has_filters['the_seo_framework_url_output_args'] = \has_filter( 'the_seo_framework_url_output_args' );
136
- }
137
 
138
- if ( $_has_filters['the_seo_framework_url_path'] ) {
139
- /**
140
- * Applies filters 'the_seo_framework_url_path' : array
141
- *
142
- * @since 2.8.0
143
- *
144
- * @param string $path the URL path.
145
- * @param int $id The current post, page or term ID.
146
- * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
147
- */
148
- $path = (string) \apply_filters( 'the_seo_framework_url_path', $path, $args['id'], $args['external'] );
149
  }
150
-
151
- if ( $_has_filters['the_seo_framework_url_output_args'] ) {
152
- /**
153
- * Applies filters 'the_seo_framework_sanitize_redirect_url' : array
154
- *
155
- * @since 2.8.0
156
- *
157
- * @param array : { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
158
- * @param string $path the URL path.
159
- * @param int $id The current post, page or term ID.
160
- * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
161
- */
162
- $url_filter = (array) \apply_filters( 'the_seo_framework_url_output_args', array(), $path, $args['id'], $args['external'] );
163
-
164
- if ( $url_filter ) {
165
- $url = $url_filter['url'];
166
- $scheme = $url_filter['scheme'];
167
- }
168
  }
 
169
 
170
- //* Non-custom URL
171
- if ( empty( $url ) ) {
172
- //* Reset cache if request is for the home URL.
173
- if ( $args['home'] )
174
- $this->unset_current_subdomain();
175
 
176
- $url = $this->add_url_host( $path );
177
- $scheme = '';
178
 
179
- $url = $this->add_url_subdomain( $url );
180
- }
 
 
 
 
 
 
 
 
181
 
182
- $scheme = $scheme ?: $this->get_prefered_scheme();
 
183
 
184
- $url = $this->set_url_scheme( $url, $scheme );
185
 
186
- if ( $this->url_slashit ) {
187
- if ( $args['forceslash'] ) {
188
- $url = \trailingslashit( $url );
189
- } elseif ( $slashit ) {
190
- $url = \user_trailingslashit( $url );
191
  }
192
- }
193
 
194
- if ( $this->pretty_permalinks ) {
195
- $url = \esc_url( $url, array( 'http', 'https' ) );
196
- } else {
197
- //* Keep the &'s more readable.
198
- $url = \esc_url_raw( $url, array( 'http', 'https' ) );
 
 
199
  }
200
 
201
- $this->the_seo_framework_debug && false === $this->doing_sitemap and $this->debug_init( __METHOD__, false, $debug_key, array( 'url_output' => $url ) );
202
-
203
- return $url;
204
  }
205
 
206
  /**
207
- * Parse and sanitize url args.
208
  *
209
- * @since 2.4.2
210
- * @since 2.9.2 Added filter usage cache.
211
- * @staticvar bool $_has_filter
212
  *
213
- * @param array $args required The passed arguments.
214
- * @param array $defaults The default arguments.
215
- * @param bool $get_defaults Return the default arguments. Ignoring $args.
216
- * @return array $args parsed args.
217
  */
218
- public function parse_url_args( $args = array(), $defaults = array(), $get_defaults = false ) {
219
-
220
- //* Passing back the defaults reduces the memory usage.
221
- if ( empty( $defaults ) ) :
222
- $defaults = array(
223
- 'paged' => false,
224
- 'paged_plural' => true,
225
- 'get_custom_field' => true,
226
- 'external' => false,
227
- 'is_term' => false,
228
- 'post' => null,
229
- 'term' => null,
230
- 'home' => false,
231
- 'forceslash' => false,
232
- 'id' => $this->get_the_real_ID(),
233
- );
234
-
235
- static $_has_filter = null;
236
- if ( null === $_has_filter )
237
- $_has_filter = \has_filter( 'the_seo_framework_url_args' );
238
-
239
- if ( $_has_filter ) {
240
- /**
241
- * @applies filters the_seo_framework_url_args : {
242
- * @param bool $paged Return current page URL without pagination if false
243
- * @param bool $paged_plural Whether to add pagination for the second or later page.
244
- * @param bool $from_option Get the canonical uri option
245
- * @param object $post The Post Object.
246
- * @param bool $external Whether to fetch the current WP Request or get the permalink by Post Object.
247
- * @param bool $is_term Fetch url for term.
248
- * @param object $term The term object.
249
- * @param bool $home Fetch home URL.
250
- * @param bool $forceslash Fetch home URL and slash it, always.
251
- * @param int $id The Page or Term ID.
252
- * }
253
- *
254
- * @since 2.5.0
255
- *
256
- * @param array $defaults The url defaults.
257
- * @param array $args The input args.
258
- */
259
- $defaults = (array) \apply_filters( 'the_seo_framework_url_args', $defaults, $args );
260
  }
261
- endif;
 
 
262
 
263
- //* Return early if it's only a default args request.
264
- if ( $get_defaults )
265
- return $defaults;
266
-
267
- //* Array merge doesn't support sanitation. We're simply type casting here.
268
- $args['paged'] = isset( $args['paged'] ) ? (bool) $args['paged'] : $defaults['paged'];
269
- $args['paged_plural'] = isset( $args['paged_plural'] ) ? (bool) $args['paged_plural'] : $defaults['paged_plural'];
270
- $args['get_custom_field'] = isset( $args['get_custom_field'] ) ? (bool) $args['get_custom_field'] : $defaults['get_custom_field'];
271
- $args['external'] = isset( $args['external'] ) ? (bool) $args['external'] : $defaults['external'];
272
- $args['is_term'] = isset( $args['is_term'] ) ? (bool) $args['is_term'] : $defaults['is_term'];
273
- $args['post'] = isset( $args['post'] ) ? (object) $args['post'] : $defaults['post'];
274
- $args['term'] = isset( $args['term'] ) ? (object) $args['term'] : $defaults['term'];
275
- $args['home'] = isset( $args['home'] ) ? (bool) $args['home'] : $defaults['home'];
276
- $args['forceslash'] = isset( $args['forceslash'] ) ? (bool) $args['forceslash'] : $defaults['forceslash'];
277
- $args['id'] = isset( $args['id'] ) ? (int) $args['id'] : $defaults['id'];
278
-
279
- return $args;
280
  }
281
 
282
  /**
283
- * Reparse URL args.
 
284
  *
285
- * @since 2.6.2
286
- * @since 2.9.2 Now passes args to filter.
287
  *
288
- * @param array $args required The passed arguments.
289
- * @return array $args parsed args.
290
  */
291
- public function reparse_url_args( $args = array() ) {
292
 
293
- $default_args = $this->parse_url_args( $args, '', true );
294
-
295
- if ( is_array( $args ) ) {
296
- if ( empty( $args ) ) {
297
- $args = $default_args;
298
- } else {
299
- $args = $this->parse_url_args( $args, $default_args );
300
- }
301
  } else {
302
- //* Old style parameters are used. Doing it wrong.
303
- $this->_doing_it_wrong( __METHOD__, 'Use $args = array() for parameters.', '2.4.2' );
304
- $args = $default_args;
305
  }
306
 
307
- return $args;
308
  }
309
 
310
  /**
311
- * Generate URL from arguments.
 
312
  *
313
- * @since 2.6.0
314
- * @NOTE: Handles full path, including home directory.
315
  *
316
- * @param array $args the URL args.
317
- * @return string $path
318
  */
319
- public function generate_url_path( $args = array() ) {
320
-
321
- $args = $this->reparse_url_args( $args );
322
-
323
- if ( $this->is_archive() || $args['is_term'] ) :
324
-
325
- $term = $args['term'];
326
 
327
- //* Term or Taxonomy.
328
- if ( ! isset( $term ) )
329
- $term = \get_queried_object();
330
 
331
- if ( isset( $term->taxonomy ) ) {
332
- //* Registered Terms and Taxonomies.
333
- $path = $this->get_relative_term_url( $term, $args );
334
- } elseif ( ! $args['external'] && isset( $GLOBALS['wp']->request ) ) {
335
- //* Everything else.
336
- $_url = \trailingslashit( \get_option( 'home' ) ) . $GLOBALS['wp']->request;
337
- $path = $this->set_url_scheme( $_url, 'relative' );
338
- } else {
339
- //* Nothing to see here...
340
- $path = '';
341
- }
342
- elseif ( $this->is_search() ) :
343
- $_url = \get_search_link();
344
- $path = $this->set_url_scheme( $_url, 'relative' );
345
- else :
346
- /**
347
- * Reworked to use the $args['id'] check based on get_the_real_ID.
348
- * @since 2.6.0 & 2.6.2
349
- */
350
- $post_id = isset( $args['post']->ID ) ? $args['post']->ID : $args['id'];
351
-
352
- if ( $this->pretty_permalinks && $post_id && $this->is_singular( $post_id ) ) {
353
- $post = \get_post( $post_id );
354
-
355
- //* Don't slash draft links.
356
- if ( isset( $post->post_status ) && ( 'auto-draft' === $post->post_status || 'draft' === $post->post_status ) )
357
- $this->url_slashit = false;
358
  }
359
 
360
- $path = $this->build_singular_relative_url( $post_id, $args );
361
- endif;
362
 
363
- return $path;
364
  }
365
 
366
  /**
367
- * Generates relative URL for the Homepage and Singular Posts.
368
  *
369
- * @since 2.6.5
370
- * @NOTE: Handles full path, including home directory.
371
- * @since 2.8.0: Continues on empty post ID. Handles it as HomePage.
372
  *
373
- * @param int $post_id The ID.
374
- * @param array $args The URL arguments.
375
- * @return relative Post or Page url.
376
  */
377
- public function build_singular_relative_url( $post_id = null, $args = array() ) {
378
-
379
- if ( empty( $post_id ) ) {
380
- //* We can't fetch the post ID when there's an external request.
381
- if ( $args['external'] ) {
382
- $post_id = 0;
383
- } else {
384
- $post_id = $this->get_the_real_ID();
385
- }
386
- }
387
 
388
- $args = $this->reparse_url_args( $args );
 
 
 
 
 
 
 
 
 
 
 
389
 
390
- if ( $args['external'] || ! $this->is_real_front_page() || ! $this->is_front_page_by_id( $post_id ) ) {
391
- $url = \get_permalink( $post_id );
392
- } elseif ( $this->is_real_front_page() || $this->is_front_page_by_id( $post_id ) ) {
393
- $url = \get_home_url();
394
- } elseif ( ! $args['external'] ) {
395
- if ( isset( $GLOBALS['wp']->request ) )
396
- $url = \trailingslashit( \get_home_url() ) . $GLOBALS['wp']->request;
397
- }
398
 
399
- //* No permalink found.
400
- if ( ! isset( $url ) )
401
  return '';
402
 
403
- $paged = false;
404
-
405
- if ( false === $args['external'] ) {
406
- $paged = $this->is_singular() ? $this->page() : $this->paged();
407
- $paged = $this->maybe_get_paged( $paged, $args['paged'], $args['paged_plural'] );
408
  }
409
 
410
- if ( $paged ) {
411
- if ( $this->pretty_permalinks ) {
412
- if ( $this->is_singular() ) {
413
- $url = \trailingslashit( $url ) . $paged;
414
- } else {
415
- $url = \trailingslashit( $url ) . 'page/' . $paged;
416
- }
417
- } else {
418
- if ( $this->is_singular() ) {
419
- $url = \add_query_arg( 'page', $paged, $url );
420
- } else {
421
- $url = \add_query_arg( 'paged', $paged, $url );
422
- }
423
- }
424
- }
425
-
426
- return $this->set_url_scheme( $url, 'relative' );
427
  }
428
 
429
  /**
430
- * Create full valid URL with parsed host.
431
- * Don't forget to use set_url_scheme() afterwards.
432
  *
433
- * Note: will return $path if no host can be found.
434
  *
435
- * @since 2.6.5
436
- *
437
- * @param string $path Current path.
438
- * @return string Full valid URL with http host.
439
  */
440
- public function add_url_host( $path = '' ) {
 
 
441
 
442
- $host = $this->current_host ?: $this->get_home_host();
 
443
 
444
- $scheme = $host ? 'http://' : '';
 
 
 
445
 
446
- return $url = $scheme . \trailingslashit( $host ) . ltrim( $path, ' \\/' );
447
  }
448
 
449
  /**
450
- * Generates relative URL for current term.
451
  *
452
- * @since 2.4.2
453
- * @since 2.7.0 Added home directory to output.
454
- * @global object $wp_rewrite
455
- * @NOTE: Handles full path, including home directory.
456
  *
457
- * @param object $term The term object.
458
- * @param array|bool $args {
459
- * 'external' : Whether to fetch the WP Request or get the permalink by Post Object.
460
- * 'paged' : Whether to add pagination for all types.
461
- * 'paged_plural' : Whether to add pagination for the second or later page.
462
- * }
463
- * @return Relative term or taxonomy URL.
464
  */
465
- public function get_relative_term_url( $term = null, $args = array() ) {
466
- global $wp_rewrite;
467
-
468
- if ( ! is_array( $args ) ) {
469
- /**
470
- * @since 2.6.0
471
- * '$args = array()' replaced '$no_request = false'.
472
- */
473
- $this->_doing_it_wrong( __METHOD__, 'Use $args = array() for parameters.', '2.6.0' );
474
 
475
- $no_request = (bool) $args;
476
- $args = $this->parse_url_args( '', '', true );
477
- $args['external'] = $no_request;
478
- }
479
-
480
- // We can't fetch the Term object within sitemaps.
481
- if ( $args['external'] && is_null( $term ) )
482
- return '';
483
 
484
- if ( is_null( $term ) )
485
- $term = \get_queried_object();
486
 
487
- $taxonomy = $term->taxonomy;
488
- $path = $wp_rewrite->get_extra_permastruct( $taxonomy );
 
 
 
 
 
 
489
 
490
- $slug = $term->slug;
491
- $t = \get_taxonomy( $taxonomy );
492
 
493
- $paged = $this->maybe_get_paged( $this->paged(), $args['paged'], $args['paged_plural'] );
 
 
 
 
 
 
 
 
 
494
 
495
- if ( empty( $path ) ) :
496
- //* Default permalink structure.
497
 
498
- if ( 'category' === $taxonomy ) {
499
- $path = '?cat=' . $term->term_id;
500
- } elseif ( isset( $t->query_var ) && '' !== $t->query_var ) {
501
- $path = '?' . $t->query_var . '=' . $slug;
502
- } else {
503
- $path = '?taxonomy=' . $taxonomy . '&term=' . $slug;
504
- }
505
 
506
- if ( $paged )
507
- $path .= '&paged=' . $paged;
 
 
508
 
509
- //* Don't slash it.
510
- $this->url_slashit = false;
511
 
512
- else :
513
- if ( $t->rewrite['hierarchical'] ) {
514
- $hierarchical_slugs = array();
515
- $ancestors = \get_ancestors( $term->term_id, $taxonomy, 'taxonomy' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
516
 
517
- foreach ( (array) $ancestors as $ancestor ) {
518
- $ancestor_term = \get_term( $ancestor, $taxonomy );
519
- $hierarchical_slugs[] = $ancestor_term->slug;
520
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
 
522
- $hierarchical_slugs = array_reverse( $hierarchical_slugs );
523
- $hierarchical_slugs[] = $slug;
 
 
524
 
525
- $path = str_replace( "%$taxonomy%", implode( '/', $hierarchical_slugs ), $path );
526
- } else {
527
- $path = str_replace( "%$taxonomy%", $slug, $path );
528
- }
529
 
530
- if ( $paged )
531
- $path = \trailingslashit( $path ) . 'page/' . $paged;
 
 
 
 
 
 
 
 
 
532
 
533
- $path = \user_trailingslashit( $path, 'category' );
534
- endif;
 
535
 
536
- //* Add plausible domain subdirectories.
537
- $url = \trailingslashit( \get_option( 'home' ) ) . ltrim( $path, ' \\/' );
538
- $path = $this->set_url_scheme( $url, 'relative' );
 
539
 
540
- return $path;
541
  }
542
 
543
  /**
544
- * Returns preferred $url scheme.
545
- * Can be automatically be detected.
546
  *
547
  * @since 2.8.0
548
  * @since 2.9.2 Added filter usage cache.
 
 
 
549
  * @staticvar string $scheme
550
- * @staticvar bool $_has_filter
551
  *
552
  * @return string The preferred URl scheme.
553
  */
554
  public function get_prefered_scheme() {
 
 
 
 
 
 
 
 
 
 
 
 
 
555
 
556
  static $scheme;
557
 
@@ -567,27 +462,19 @@ class Generate_Url extends Generate_Title {
567
  $scheme = 'http';
568
  break;
569
 
570
- case 'automatic' :
571
  default :
 
572
  $scheme = $this->is_ssl() ? 'https' : 'http';
573
  break;
574
  endswitch;
575
 
576
- static $_has_filter = null;
577
-
578
- if ( null === $_has_filter )
579
- $_has_filter = \has_filter( 'the_seo_framework_preferred_url_scheme' );
580
-
581
- if ( $_has_filter ) {
582
- /**
583
- * Applies filters 'the_seo_framework_preferred_url_scheme' : string
584
- *
585
- * @since 2.8.0
586
- *
587
- * @param string $scheme The current URL scheme.
588
- */
589
- $scheme = (string) \apply_filters( 'the_seo_framework_preferred_url_scheme', $scheme );
590
- }
591
 
592
  return $scheme;
593
  }
@@ -602,7 +489,7 @@ class Generate_Url extends Generate_Title {
602
  * @return string The URL with the preferred scheme.
603
  */
604
  public function set_preferred_url_scheme( $url ) {
605
- return $this->set_url_scheme( $url, $this->get_prefered_scheme(), false );
606
  }
607
 
608
  /**
@@ -610,13 +497,14 @@ class Generate_Url extends Generate_Title {
610
  * WordPress core function, without filter.
611
  *
612
  * @since 2.4.2
 
613
  *
614
  * @param string $url Absolute url that includes a scheme.
615
  * @param string $scheme optional. Scheme to give $url. Currently 'http', 'https', 'login', 'login_post', 'admin', or 'relative'.
616
  * @param bool $use_filter Whether to parse filters.
617
  * @return string url with chosen scheme.
618
  */
619
- public function set_url_scheme( $url, $scheme = null, $use_filter = true ) {
620
 
621
  if ( empty( $scheme ) ) {
622
  $scheme = $this->is_ssl() ? 'https' : 'http';
@@ -663,19 +551,17 @@ class Generate_Url extends Generate_Title {
663
  $_has_filter = \has_filter( 'the_seo_framework_canonical_force_scheme' );
664
 
665
  if ( $_has_filter ) {
666
-
667
  $this->_deprecated_filter( 'the_seo_framework_canonical_force_scheme', '2.8.0', 'the_seo_framework_preferred_url_scheme' );
668
-
669
  /**
670
  * Applies filters the_seo_framework_canonical_force_scheme : Changes scheme.
671
  *
672
  * Accepted variables:
673
- * (string) 'https' : Force https
674
- * (bool) true : Force https
675
- * (bool) false : Force http
676
- * (string) 'http' : Force http
677
- * (string) 'relative' : Scheme relative
678
- * (void) null : Do nothing
679
  *
680
  * @since 2.4.2
681
  * @since 2.8.0 Deprecated.
@@ -699,6 +585,103 @@ class Generate_Url extends Generate_Title {
699
  return $url;
700
  }
701
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
702
  /**
703
  * Generates shortlink URL.
704
  *
@@ -773,7 +756,7 @@ class Generate_Url extends Generate_Title {
773
  $post_id = $this->get_the_real_ID();
774
 
775
  //* Get additional public queries from the page URL.
776
- $url = $this->the_url_from_cache( '', $post_id, false, false, false );
777
  $query = parse_url( $url, PHP_URL_QUERY );
778
 
779
  $additions = '';
@@ -810,8 +793,8 @@ class Generate_Url extends Generate_Title {
810
  $path .= '&page=' . $page;
811
  }
812
 
813
- $home_url = $this->the_home_url_from_cache( true );
814
- $url = $home_url . $path . $additions;
815
 
816
  return \esc_url_raw( $url, array( 'http', 'https' ) );
817
  }
@@ -820,6 +803,7 @@ class Generate_Url extends Generate_Title {
820
  * Generates Previous and Next links.
821
  *
822
  * @since 2.2.4
 
823
  *
824
  * @param string $prev_next Previous or next page link.
825
  * @param int $post_id The post ID.
@@ -899,15 +883,15 @@ class Generate_Url extends Generate_Title {
899
  * Returns the special URL of a paged post.
900
  *
901
  * Taken from _wp_link_page() in WordPress core, but instead of anchor markup, just return the URL.
902
- * Also adds WPMUdev Domain Mapping support and is optimized for speed.
903
  *
904
  * @since 2.2.4
905
- * @uses $this->the_url_from_cache();
 
906
  *
907
  * @param int $i The page number to generate the URL from.
908
- * @param int $post_id The post ID
909
- * @param string $pos Which url to get, accepts next|prev
910
- * @return string Unescaped URL
911
  */
912
  public function get_paged_post_url( $i, $post_id = 0, $pos = 'prev' ) {
913
 
@@ -917,19 +901,18 @@ class Generate_Url extends Generate_Title {
917
  $post_id = $this->get_the_real_ID();
918
 
919
  if ( 1 === $i ) :
920
- $url = $this->the_url_from_cache( '', $post_id, false, $from_option, false );
921
  else :
922
  $post = \get_post( $post_id );
923
-
924
- $urlfromcache = $this->the_url_from_cache( '', $post_id, false, $from_option, false );
925
 
926
  if ( $i >= 2 ) {
927
  //* Fix adding pagination url.
928
 
929
  //* Parse query arg, put in var and remove from current URL.
930
- $query_arg = parse_url( $urlfromcache, PHP_URL_QUERY );
931
  if ( isset( $query_arg ) )
932
- $urlfromcache = str_replace( '?' . $query_arg, '', $urlfromcache );
933
 
934
  //* Continue if still bigger than or equal to 2.
935
  if ( $i >= 2 ) {
@@ -937,10 +920,10 @@ class Generate_Url extends Generate_Title {
937
  $_current = 'next' === $pos ? (string) ( $i - 1 ) : (string) ( $i + 1 );
938
 
939
  //* We're adding a page.
940
- $_last_occurrence = strrpos( $urlfromcache, '/' . $_current . '/' );
941
 
942
  if ( false !== $_last_occurrence )
943
- $urlfromcache = substr_replace( $urlfromcache, '/', $_last_occurrence, strlen( '/' . $_current . '/' ) );
944
  }
945
  }
946
 
@@ -948,19 +931,19 @@ class Generate_Url extends Generate_Title {
948
 
949
  //* Put removed query arg back prior to adding pagination.
950
  if ( isset( $query_arg ) )
951
- $urlfromcache = $urlfromcache . '?' . $query_arg;
952
 
953
- $url = \add_query_arg( 'page', $i, $urlfromcache );
954
  } elseif ( $this->is_static_frontpage( $post_id ) ) {
955
  global $wp_rewrite;
956
 
957
- $url = \trailingslashit( $urlfromcache ) . \user_trailingslashit( $wp_rewrite->pagination_base . '/' . $i, 'single_paged' );
958
 
959
  //* Add back query arg if removed.
960
  if ( isset( $query_arg ) )
961
  $url = $url . '?' . $query_arg;
962
  } else {
963
- $url = \trailingslashit( $urlfromcache ) . \user_trailingslashit( $i, 'single_paged' );
964
 
965
  //* Add back query arg if removed.
966
  if ( isset( $query_arg ) )
@@ -972,75 +955,31 @@ class Generate_Url extends Generate_Title {
972
  }
973
 
974
  /**
975
- * Adds subdomain to input URL.
976
- *
977
- * @since 2.6.5
978
- *
979
- * @param string $url The current URL without subdomain.
980
- * @return string $url Fully qualified URL with possible subdomain.
981
- */
982
- public function add_url_subdomain( $url = '' ) {
983
-
984
- $url = $this->make_fully_qualified_url( $url );
985
-
986
- //* Add subdomain, if set.
987
- if ( $subdomain = $this->get_current_subdomain() ) {
988
- $parsed_url = \wp_parse_url( $url );
989
- $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : 'http';
990
- $url = str_replace( $scheme . '://', '', $url );
991
-
992
- //* Put it together.
993
- $url = $scheme . '://' . $subdomain . '.' . $url;
994
- }
995
-
996
- return $url;
997
- }
998
-
999
- /**
1000
- * Fetches current subdomain set by $this->set_current_subdomain();
1001
  *
1002
  * @since 2.7.0
1003
- * @staticvar string $subdomain
 
 
1004
  *
1005
- * @param null|string $set Whether to set a new subdomain.
1006
- * @param bool $unset Whether to remove subdomain from cache.
1007
- * @return string|bool The set subdomain, false if none is set.
1008
  */
1009
- public function get_current_subdomain( $set = null, $unset = false ) {
1010
-
1011
- static $subdomain = null;
1012
 
1013
- if ( isset( $set ) )
1014
- $subdomain = \esc_html( $set );
1015
 
1016
- if ( $unset )
1017
- unset( $subdomain );
1018
 
1019
- if ( isset( $subdomain ) )
1020
- return $subdomain;
1021
 
1022
- return false;
1023
- }
1024
 
1025
- /**
1026
- * Sets current working subdomain.
1027
- *
1028
- * @since 2.7.0
1029
- *
1030
- * @param string $subdomain The current subdomain.
1031
- * @return string The set subdomain.
1032
- */
1033
- public function set_current_subdomain( $subdomain = '' ) {
1034
- return $this->get_current_subdomain( $subdomain );
1035
- }
1036
 
1037
- /**
1038
- * Unsets current working subdomain.
1039
- *
1040
- * @since 2.7.0
1041
- */
1042
- public function unset_current_subdomain() {
1043
- $this->get_current_subdomain( null, true );
1044
  }
1045
 
1046
  /**
@@ -1106,55 +1045,35 @@ class Generate_Url extends Generate_Title {
1106
  }
1107
 
1108
  /**
1109
- * Fetches home URL host. Like "wordpress.org".
1110
- * If this fails, you're going to have a bad time.
1111
  *
1112
- * @since 2.7.0
1113
- * @since 2.9.2 : Now considers port too.
1114
- * : Now uses get_home_url(), rather than get_option('home').
1115
- * @staticvar string $cache
1116
  *
1117
- * @return string The home URL host.
 
 
1118
  */
1119
- public function get_home_host() {
1120
 
1121
- static $cache = null;
1122
-
1123
- if ( isset( $cache ) )
1124
- return $cache;
1125
-
1126
- $parsed_url = \wp_parse_url( \get_home_url() );
1127
 
1128
- $host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : '';
 
 
1129
 
1130
- if ( $host && isset( $parsed_url['port'] ) )
1131
- $host .= ':' . $parsed_url['port'];
1132
 
1133
- return $cache = $host;
1134
- }
1135
-
1136
- /**
1137
- * Fetches home URL subdirectory path. Like "wordpress.org/plugins/".
1138
- *
1139
- * @since 2.7.0
1140
- * @staticvar string $cache
1141
- *
1142
- * @return string The home URL path.
1143
- */
1144
- public function get_home_path() {
1145
-
1146
- static $cache = null;
1147
-
1148
- if ( isset( $cache ) )
1149
- return $cache;
1150
-
1151
- $path = '';
1152
-
1153
- $parsed_url = \wp_parse_url( \get_option( 'home' ) );
1154
 
1155
- if ( ! empty( $parsed_url['path'] ) && $path = ltrim( $parsed_url['path'], ' \\/' ) )
1156
- $path = '/' . $path;
1157
 
1158
- return $cache = $path;
1159
  }
1160
  }
32
  */
33
  class Generate_Url extends Generate_Title {
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  /**
36
  * Constructor, load parent constructor and set up variables.
37
  */
40
  }
41
 
42
  /**
43
+ * Returns a canonical URL based on parameters.
44
+ * The URL will never be paginated.
45
  *
46
+ * @since 3.0.0
 
 
 
 
 
47
  *
48
+ * @param array $args The canonical URL arguments : {
49
+ * int $id The Post, Page or Term ID to generate the URL for.
50
+ * string $taxonomy The taxonomy.
51
+ * bool $get_custom_field Whether to get custom canonical URLs from user settings.
 
 
 
 
 
 
 
 
52
  * }
53
+ * @return string The canonical URL, if any.
54
  */
55
+ public function create_canonical_url( $args = array() ) {
 
 
56
 
57
+ $defaults = array(
58
+ 'id' => 0,
59
+ 'taxonomy' => '',
60
+ 'get_custom_field' => false,
61
+ );
62
+ $args = array_merge( $defaults, $args );
63
 
64
+ return $this->get_canonical_url( $args );
65
+ }
 
 
 
 
 
 
 
 
 
66
 
67
+ /**
68
+ * Returns the current canonical URL.
69
+ *
70
+ * @since 3.0.0
71
+ *
72
+ * @param array $args : Private variable. Use $this->create_canonical_url() instead.
73
+ * @return string The canonical URL, if any.
74
+ */
75
+ public function get_canonical_url( $args = null ) {
76
 
77
+ $this->the_seo_framework_debug && false === $this->doing_sitemap and $this->debug_init( __METHOD__, true, $debug_key = microtime( true ), get_defined_vars() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
+ if ( $args ) {
80
+ //= See $this->create_canonical_url().
81
+ $canonical_url = $this->build_canonical_url( $args );
82
+ $query = false;
83
+ } else {
84
+ $canonical_url = $this->generate_canonical_url();
85
+ $query = true;
86
  }
87
 
88
+ if ( ! $canonical_url )
89
+ return '';
 
 
 
 
90
 
91
+ if ( ! $query && $args['id'] === $this->get_the_real_ID() ) {
92
+ $canonical_url = $this->remove_pagination_from_url( $canonical_url );
 
 
 
 
 
 
 
 
 
93
  }
94
+ if ( $this->matches_this_domain( $canonical_url ) ) {
95
+ $canonical_url = $this->set_preferred_url_scheme( $canonical_url );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  }
97
+ $canonical_url = $this->clean_canonical_url( $canonical_url );
98
 
99
+ $this->the_seo_framework_debug && false === $this->doing_sitemap and $this->debug_init( __METHOD__, false, $debug_key, compact( 'canonical_url' ) );
 
 
 
 
100
 
101
+ return $canonical_url;
102
+ }
103
 
104
+ /**
105
+ * Builds canonical URL from input arguments.
106
+ *
107
+ * @since 3.0.0
108
+ * @see $this->create_canonical_url()
109
+ *
110
+ * @param array $args. Use $this->create_canonical_url().
111
+ * @return string The canonical URL.
112
+ */
113
+ protected function build_canonical_url( $args ) {
114
 
115
+ //* See $this->create_canonical_url().
116
+ extract( $args );
117
 
118
+ $canonical_url = '';
119
 
120
+ if ( $taxonomy ) {
121
+ $canonical_url = $this->get_taxonomial_canonical_url( $id, $taxonomy );
122
+ } else {
123
+ if ( $get_custom_field ) {
124
+ $canonical_url = $this->get_singular_custom_canonical_url( $id );
125
  }
 
126
 
127
+ if ( ! $canonical_url ) {
128
+ if ( ! $id || ( $this->has_page_on_front() && $this->is_front_page_by_id( $id ) ) ) {
129
+ $canonical_url = $this->get_home_canonical_url();
130
+ } elseif ( $id ) {
131
+ $canonical_url = $this->get_singular_canonical_url( $id );
132
+ }
133
+ }
134
  }
135
 
136
+ return $canonical_url;
 
 
137
  }
138
 
139
  /**
140
+ * Generates canonical URL from current query.
141
  *
142
+ * @since 3.0.0
143
+ * @see $this->get_canonical_url()
 
144
  *
145
+ * @return string The canonical URL.
 
 
 
146
  */
147
+ protected function generate_canonical_url() {
148
+
149
+ $id = $this->get_the_real_ID();
150
+ $canonical_url = '';
151
+
152
+ if ( $this->is_real_front_page() ) {
153
+ if ( $this->has_page_on_front() )
154
+ $canonical_url = $this->get_singular_custom_canonical_url( $id );
155
+ if ( ! $canonical_url )
156
+ $canonical_url = $this->get_home_canonical_url();
157
+ } elseif ( $this->is_singular() ) {
158
+ $canonical_url = $this->get_singular_custom_canonical_url( $id );
159
+ if ( ! $canonical_url )
160
+ $canonical_url = $this->get_singular_canonical_url( $id );
161
+ } elseif ( $this->is_archive() ) {
162
+ if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
163
+ $canonical_url = $this->get_taxonomial_canonical_url( $id, $this->get_current_taxonomy() );
164
+ } elseif ( \is_post_type_archive() ) {
165
+ $canonical_url = $this->get_post_type_archive_canonical_url( $id );
166
+ } elseif ( $this->is_author() ) {
167
+ $canonical_url = $this->get_author_canonical_url( $id );
168
+ } elseif ( $this->is_date() ) {
169
+ if ( $this->is_day() ) {
170
+ $canonical_url = $this->get_date_canonical_url( \get_query_var( 'year' ), \get_query_var( 'monthnum' ), \get_query_var( 'day' ) );
171
+ } elseif ( $this->is_month() ) {
172
+ $canonical_url = $this->get_date_canonical_url( \get_query_var( 'year' ), \get_query_var( 'monthnum' ) );
173
+ } elseif ( $this->is_year() ) {
174
+ $canonical_url = $this->get_date_canonical_url( \get_query_var( 'year' ) );
175
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  }
177
+ } elseif ( $this->is_search() ) {
178
+ $canonical_url = $this->get_search_canonical_url();
179
+ }
180
 
181
+ return $canonical_url;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  }
183
 
184
  /**
185
+ * Cleans canonical URL.
186
+ * Looks at permalink settings to determine roughness of escaping.
187
  *
188
+ * @since 3.0.0
 
189
  *
190
+ * @param string $url A fully qualified URL.
191
+ * @return string A fully qualified clean URL.
192
  */
193
+ public function clean_canonical_url( $url ) {
194
 
195
+ if ( $this->pretty_permalinks ) {
196
+ $url = \esc_url( $url, array( 'http', 'https' ) );
 
 
 
 
 
 
197
  } else {
198
+ //= Keep the &'s more readable.
199
+ $url = \esc_url_raw( $url, array( 'http', 'https' ) );
 
200
  }
201
 
202
+ return $url;
203
  }
204
 
205
  /**
206
+ * Returns home canonical URL.
207
+ * Automatically adds pagination if the ID matches the query.
208
  *
209
+ * @since 3.0.0
 
210
  *
211
+ * @return string The home canonical URL.
 
212
  */
213
+ public function get_home_canonical_url() {
 
 
 
 
 
 
214
 
215
+ //= Prevent admin bias by passing preferred scheme.
216
+ $url = \get_home_url( null, '', $this->get_preferred_scheme() );
 
217
 
218
+ if ( $url ) {
219
+ if ( $this->get_the_real_ID() === (int) \get_option( 'page_for_posts' ) ) {
220
+ $url = $this->add_url_pagination( $url, $this->paged(), true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  }
222
 
223
+ return \user_trailingslashit( $url );
224
+ }
225
 
226
+ return '';
227
  }
228
 
229
  /**
230
+ * Returns singular custom field's canonical URL.
231
  *
232
+ * @since 3.0.0
 
 
233
  *
234
+ * @param int $id The page ID.
235
+ * @return string The custom canonical URL, if any.
 
236
  */
237
+ public function get_singular_custom_canonical_url( $id ) {
238
+ return $this->get_custom_field( '_genesis_canonical_uri', $id ) ?: '';
239
+ }
 
 
 
 
 
 
 
240
 
241
+ /**
242
+ * Returns singular canonical URL.
243
+ * Automatically adds pagination if the ID matches the query.
244
+ *
245
+ * Prevents SEO attacks regarding pagination.
246
+ *
247
+ * @since 3.0.0
248
+ *
249
+ * @param int|null $id The page ID.
250
+ * @return string The custom canonical URL, if any.
251
+ */
252
+ public function get_singular_canonical_url( $id = null ) {
253
 
254
+ $canonical_url = \wp_get_canonical_url( $id );
 
 
 
 
 
 
 
255
 
256
+ if ( ! $canonical_url )
 
257
  return '';
258
 
259
+ //* @link https://core.trac.wordpress.org/ticket/37505
260
+ $_page = \get_query_var( 'page', 0 );
261
+ if ( $_page !== $this->page() ) {
262
+ $canonical_url = $this->remove_pagination_from_url( $canonical_url, $_page );
 
263
  }
264
 
265
+ return $canonical_url;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  }
267
 
268
  /**
269
+ * Returns taxonomial canonical URL.
270
+ * Automatically adds pagination if the ID matches the query.
271
  *
272
+ * @since 3.0.0
273
  *
274
+ * @param int $term_id The term ID.
275
+ * @param string $taxonomy The taxonomy.
276
+ * @return string The taxonomial canonical URL, if any.
 
277
  */
278
+ public function get_taxonomial_canonical_url( $term_id, $taxonomy ) {
279
+
280
+ $link = \get_term_link( $term_id, $taxonomy );
281
 
282
+ if ( \is_wp_error( $link ) )
283
+ return '';
284
 
285
+ if ( $term_id === $this->get_the_real_ID() ) {
286
+ //= Adds pagination if ID matches query.
287
+ $link = $this->add_url_pagination( $link, $this->paged(), true );
288
+ }
289
 
290
+ return $link;
291
  }
292
 
293
  /**
294
+ * Returns post type archive canonical URL.
295
  *
296
+ * @since 3.0.0
 
 
 
297
  *
298
+ * @param int|string $post_type The post type archive ID or post type.
299
+ * @return string The post type archive canonical URL, if any.
 
 
 
 
 
300
  */
301
+ public function get_post_type_archive_canonical_url( $post_type ) {
 
 
 
 
 
 
 
 
302
 
303
+ if ( is_int( $post_type ) ) {
304
+ $term_id = (int) $post_type;
305
+ $term = $this->fetch_the_term( $term_id );
 
 
 
 
 
306
 
307
+ if ( $term instanceof \WP_Post_Type ) {
308
+ $link = \get_post_type_archive_link( $term->name );
309
 
310
+ if ( $term_id === $this->get_the_real_ID() ) {
311
+ //= Adds pagination if ID matches query.
312
+ $link = $this->add_url_pagination( $link, $this->paged(), true );
313
+ }
314
+ }
315
+ } else {
316
+ $link = \get_post_type_archive_link( $post_type );
317
+ }
318
 
319
+ return $link ?: '';
320
+ }
321
 
322
+ /**
323
+ * Returns author canonical URL.
324
+ * Automatically adds pagination if the ID matches the query.
325
+ *
326
+ * @since 3.0.0
327
+ *
328
+ * @param int $author_id The author ID.
329
+ * @return string The author canonical URL, if any.
330
+ */
331
+ public function get_author_canonical_url( $author_id ) {
332
 
333
+ $link = \get_author_posts_url( $author_id );
 
334
 
335
+ if ( ! $link )
336
+ return '';
 
 
 
 
 
337
 
338
+ if ( $author_id === $this->get_the_real_ID() ) {
339
+ //= Adds pagination if ID matches query.
340
+ $link = $this->add_url_pagination( $link, $this->paged(), true );
341
+ }
342
 
343
+ return $link;
344
+ }
345
 
346
+ /**
347
+ * Returns date canonical URL.
348
+ * Automatically adds pagination if the date input matches the query.
349
+ *
350
+ * @since 3.0.0
351
+ *
352
+ * @param int $year The year.
353
+ * @param int $month The month.
354
+ * @param int $day The day.
355
+ * @return string The author canonical URL, if any.
356
+ */
357
+ public function get_date_canonical_url( $year, $month = null, $day = null ) {
358
+
359
+ if ( $day ) {
360
+ $link = \get_day_link( $year, $month, $day );
361
+ $_get = 'day';
362
+ } elseif ( $month ) {
363
+ $link = \get_month_link( $year, $month );
364
+ $_get = 'month';
365
+ $_get = 1;
366
+ } else {
367
+ $link = \get_year_link( $year );
368
+ $_get = 'year';
369
+ }
370
 
371
+ //* Determine whether the input matches query.
372
+ $_paginate = true;
373
+ switch ( $_get ) {
374
+ case 'day' :
375
+ $_day = \get_query_var( 'day' );
376
+ $_paginate = $_paginate && $_day == $day;
377
+ $_get = 'month';
378
+ // Continue switch.
379
+
380
+ case 'month' :
381
+ $_month = \get_query_var( 'monthnum' );
382
+ $_paginate = $_paginate && $_month == $month;
383
+ $_get = 'year';
384
+ // Continue switch.
385
+
386
+ case 'year' :
387
+ $_year = \get_query_var( 'year' );
388
+ $_paginate = $_paginate && $_year == $year;
389
+ }
390
 
391
+ if ( $_paginate ) {
392
+ //= Adds pagination if input matches query.
393
+ $link = $this->add_url_pagination( $link, $this->paged(), true );
394
+ }
395
 
396
+ return $link;
397
+ }
 
 
398
 
399
+ /**
400
+ * Returns search canonical URL.
401
+ * Automatically adds pagination if the input matches the query.
402
+ *
403
+ * @since 3.0.0
404
+ *
405
+ * @param string $query The search query. Mustn't be escaped.
406
+ * When left empty, the current query will be used.
407
+ * @return string The search link.
408
+ */
409
+ public function get_search_canonical_url( $query = '' ) {
410
 
411
+ $_query = \get_search_query( false );
412
+ $query = $query ?: $_query;
413
+ $link = \get_search_link( $query );
414
 
415
+ if ( $_query === $query ) {
416
+ //= Adds pagination if input matches query.
417
+ $link = $this->add_url_pagination( $link, $this->paged(), true );
418
+ }
419
 
420
+ return $link;
421
  }
422
 
423
  /**
424
+ * Alias of $this->get_preferred_scheme().
425
+ * Typo.
426
  *
427
  * @since 2.8.0
428
  * @since 2.9.2 Added filter usage cache.
429
+ * @since 3.0.0 Silently deprecated.
430
+ * @TODO deprecate visually
431
+ * @deprecated
432
  * @staticvar string $scheme
 
433
  *
434
  * @return string The preferred URl scheme.
435
  */
436
  public function get_prefered_scheme() {
437
+ return $this->get_preferred_scheme();
438
+ }
439
+
440
+ /**
441
+ * Returns preferred $url scheme.
442
+ * Can automatically be detected.
443
+ *
444
+ * @since 3.0.0
445
+ * @staticvar string $scheme
446
+ *
447
+ * @return string The preferred URl scheme.
448
+ */
449
+ public function get_preferred_scheme() {
450
 
451
  static $scheme;
452
 
462
  $scheme = 'http';
463
  break;
464
 
 
465
  default :
466
+ case 'automatic' :
467
  $scheme = $this->is_ssl() ? 'https' : 'http';
468
  break;
469
  endswitch;
470
 
471
+ /**
472
+ * Applies filters 'the_seo_framework_preferred_url_scheme'
473
+ *
474
+ * @since 2.8.0
475
+ * @param string $scheme The current URL scheme.
476
+ */
477
+ $scheme = (string) \apply_filters( 'the_seo_framework_preferred_url_scheme', $scheme );
 
 
 
 
 
 
 
 
478
 
479
  return $scheme;
480
  }
489
  * @return string The URL with the preferred scheme.
490
  */
491
  public function set_preferred_url_scheme( $url ) {
492
+ return $this->set_url_scheme( $url, $this->get_preferred_scheme(), false );
493
  }
494
 
495
  /**
497
  * WordPress core function, without filter.
498
  *
499
  * @since 2.4.2
500
+ * @since 3.0.0 $use_filter now defaults to false.
501
  *
502
  * @param string $url Absolute url that includes a scheme.
503
  * @param string $scheme optional. Scheme to give $url. Currently 'http', 'https', 'login', 'login_post', 'admin', or 'relative'.
504
  * @param bool $use_filter Whether to parse filters.
505
  * @return string url with chosen scheme.
506
  */
507
+ public function set_url_scheme( $url, $scheme = null, $use_filter = false ) {
508
 
509
  if ( empty( $scheme ) ) {
510
  $scheme = $this->is_ssl() ? 'https' : 'http';
551
  $_has_filter = \has_filter( 'the_seo_framework_canonical_force_scheme' );
552
 
553
  if ( $_has_filter ) {
 
554
  $this->_deprecated_filter( 'the_seo_framework_canonical_force_scheme', '2.8.0', 'the_seo_framework_preferred_url_scheme' );
 
555
  /**
556
  * Applies filters the_seo_framework_canonical_force_scheme : Changes scheme.
557
  *
558
  * Accepted variables:
559
+ * (string) 'https' : Force https
560
+ * (bool) true : Force https
561
+ * (bool) false : Force http
562
+ * (string) 'http' : Force http
563
+ * (string) 'relative' : Scheme relative
564
+ * (void) null : Do nothing
565
  *
566
  * @since 2.4.2
567
  * @since 2.8.0 Deprecated.
585
  return $url;
586
  }
587
 
588
+ /**
589
+ * Adds pagination to input URL.
590
+ *
591
+ * @since 3.0.0
592
+ *
593
+ * @param string $url The fully qualified URL.
594
+ * @param int $page The page number. Must be bigger than 1.
595
+ * @param bool $use_base Whether to use pagination base. True on archives, false on pages.
596
+ * @return string The fully qualified URL with pagination.
597
+ */
598
+ public function add_url_pagination( $url, $page, $use_base ) {
599
+
600
+ if ( $page < 2 )
601
+ return $url;
602
+
603
+ if ( $this->pretty_permalinks ) {
604
+ if ( $use_base ) {
605
+ static $base;
606
+ $base = $base ?: $GLOBALS['wp_rewrite']->pagination_base;
607
+
608
+ $url = \user_trailingslashit( \trailingslashit( $url ) . $base . '/' . $page, 'single_paged' );
609
+ } else {
610
+ $url = \user_trailingslashit( \trailingslashit( $url ) . $page, 'single_paged' );
611
+ }
612
+ } else {
613
+ if ( $use_base ) {
614
+ $url = \add_query_arg( 'paged', $page, $url );
615
+ } else {
616
+ $url = \add_query_arg( 'page', $page, $url );
617
+ }
618
+ }
619
+
620
+ return $url;
621
+ }
622
+
623
+ /**
624
+ * Removes pagination from input URL.
625
+ * The URL must match this query.
626
+ *
627
+ * @since 3.0.0
628
+ *
629
+ * @param string $url The fully qualified URL to remove pagination from.
630
+ * @param int $page The page number to remove. If empty, it will get query.
631
+ * @param int $paged The page number to remove. If empty, it will get query.
632
+ * @return string $url The fully qualified URL without pagination.
633
+ */
634
+ protected function remove_pagination_from_url( $url, $page = 0, $paged = 0 ) {
635
+
636
+ if ( $this->pretty_permalinks ) {
637
+ //* Defensive programming...
638
+ static $user_slash;
639
+ $user_slash = isset( $user_slash ) ? $user_slash :
640
+ ( $GLOBALS['wp_rewrite']->use_trailing_slashes ? '/' : '' );
641
+
642
+ $paged = $paged ?: $this->paged();
643
+ $page = $page ?: $this->page();
644
+ $find = '';
645
+
646
+ if ( $paged > 1 ) {
647
+ static $base;
648
+ $base = $base ?: $GLOBALS['wp_rewrite']->pagination_base;
649
+
650
+ $find = '/' . $base . '/' . $paged . $user_slash;
651
+ } elseif ( $page > 1 ) {
652
+ $find = '/' . $page . $user_slash;
653
+ }
654
+
655
+ if ( $find ) {
656
+ $pos = strrpos( $url, $find );
657
+ //* Defensive programming...
658
+ $continue = $pos && $pos + strlen( $find ) === strlen( $url );
659
+ if ( $continue ) {
660
+ $url = substr( $url, 0, $pos );
661
+ $url = \user_trailingslashit( $url );
662
+ }
663
+ }
664
+ } else {
665
+ $url = \remove_query_arg( array( 'page', 'paged', 'cpage' ), $url );
666
+ }
667
+
668
+ return $url;
669
+ }
670
+
671
+ /**
672
+ * Adjusts category post link.
673
+ *
674
+ * @since 3.0.0
675
+ *
676
+ * @param \WP_Term $term The category to use in the permalink.
677
+ * @param array $terms Array of all categories (WP_Term objects) associated with the post.
678
+ * @param \WP_Post $post The post in question.
679
+ * @return \WP_Term The primary term.
680
+ */
681
+ public function _adjust_post_link_category( $term, $terms = null, $post = null ) {
682
+ return $this->get_primary_term( $post->ID, $term->taxonomy ) ?: $term;
683
+ }
684
+
685
  /**
686
  * Generates shortlink URL.
687
  *
756
  $post_id = $this->get_the_real_ID();
757
 
758
  //* Get additional public queries from the page URL.
759
+ $url = \get_permalink( $post_id );
760
  $query = parse_url( $url, PHP_URL_QUERY );
761
 
762
  $additions = '';
793
  $path .= '&page=' . $page;
794
  }
795
 
796
+ $home_url = $this->get_homepage_permalink();
797
+ $url = \trailingslashit( $home_url ) . $path . $additions;
798
 
799
  return \esc_url_raw( $url, array( 'http', 'https' ) );
800
  }
803
  * Generates Previous and Next links.
804
  *
805
  * @since 2.2.4
806
+ * @TODO rewrite to use the new 3.0.0+ URL generation.
807
  *
808
  * @param string $prev_next Previous or next page link.
809
  * @param int $post_id The post ID.
883
  * Returns the special URL of a paged post.
884
  *
885
  * Taken from _wp_link_page() in WordPress core, but instead of anchor markup, just return the URL.
 
886
  *
887
  * @since 2.2.4
888
+ * @since 3.0.0 Now uses WordPress permalinks.
889
+ * @TODO deprecate.
890
  *
891
  * @param int $i The page number to generate the URL from.
892
+ * @param int $post_id The post ID.
893
+ * @param string $pos Which url to get, accepts next|prev.
894
+ * @return string The unescaped paged URL.
895
  */
896
  public function get_paged_post_url( $i, $post_id = 0, $pos = 'prev' ) {
897
 
901
  $post_id = $this->get_the_real_ID();
902
 
903
  if ( 1 === $i ) :
904
+ $url = \get_permalink( $post_id );
905
  else :
906
  $post = \get_post( $post_id );
907
+ $url = \get_permalink( $post_id );
 
908
 
909
  if ( $i >= 2 ) {
910
  //* Fix adding pagination url.
911
 
912
  //* Parse query arg, put in var and remove from current URL.
913
+ $query_arg = parse_url( $url, PHP_URL_QUERY );
914
  if ( isset( $query_arg ) )
915
+ $url = str_replace( '?' . $query_arg, '', $url );
916
 
917
  //* Continue if still bigger than or equal to 2.
918
  if ( $i >= 2 ) {
920
  $_current = 'next' === $pos ? (string) ( $i - 1 ) : (string) ( $i + 1 );
921
 
922
  //* We're adding a page.
923
+ $_last_occurrence = strrpos( $url, '/' . $_current . '/' );
924
 
925
  if ( false !== $_last_occurrence )
926
+ $url = substr_replace( $url, '/', $_last_occurrence, strlen( '/' . $_current . '/' ) );
927
  }
928
  }
929
 
931
 
932
  //* Put removed query arg back prior to adding pagination.
933
  if ( isset( $query_arg ) )
934
+ $url = $url . '?' . $query_arg;
935
 
936
+ $url = \add_query_arg( 'page', $i, $url );
937
  } elseif ( $this->is_static_frontpage( $post_id ) ) {
938
  global $wp_rewrite;
939
 
940
+ $url = \trailingslashit( $url ) . \user_trailingslashit( $wp_rewrite->pagination_base . '/' . $i, 'single_paged' );
941
 
942
  //* Add back query arg if removed.
943
  if ( isset( $query_arg ) )
944
  $url = $url . '?' . $query_arg;
945
  } else {
946
+ $url = \trailingslashit( $url ) . \user_trailingslashit( $i, 'single_paged' );
947
 
948
  //* Add back query arg if removed.
949
  if ( isset( $query_arg ) )
955
  }
956
 
957
  /**
958
+ * Fetches home URL host. Like "wordpress.org".
959
+ * If this fails, you're going to have a bad time.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
960
  *
961
  * @since 2.7.0
962
+ * @since 2.9.2 : Now considers port too.
963
+ * : Now uses get_home_url(), rather than get_option('home').
964
+ * @staticvar string $cache
965
  *
966
+ * @return string The home URL host.
 
 
967
  */
968
+ public function get_home_host() {
 
 
969
 
970
+ static $cache = null;
 
971
 
972
+ if ( isset( $cache ) )
973
+ return $cache;
974
 
975
+ $parsed_url = \wp_parse_url( \get_home_url() );
 
976
 
977
+ $host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : '';
 
978
 
979
+ if ( $host && isset( $parsed_url['port'] ) )
980
+ $host .= ':' . $parsed_url['port'];
 
 
 
 
 
 
 
 
 
981
 
982
+ return $cache = $host;
 
 
 
 
 
 
983
  }
984
 
985
  /**
1045
  }
1046
 
1047
  /**
1048
+ * Appends given query to given URL.
 
1049
  *
1050
+ * @since 3.0.0
 
 
 
1051
  *
1052
+ * @param string $url A fully qualified URL.
1053
+ * @param string $query A fully qualified query taken from parse_url( $url, PHP_URL_QUERY );
1054
+ * @return string A fully qualified URL with appended $query.
1055
  */
1056
+ public function append_php_query( $url, $query = '' ) {
1057
 
1058
+ if ( ! $query )
1059
+ return $url;
 
 
 
 
1060
 
1061
+ $p = parse_url( $url );
1062
+ $_fragment = ! empty( $p['fragment'] ) ? $p['fragment'] : '';
1063
+ $_query = ! empty( $p['query'] ) ? $p['query'] : '';
1064
 
1065
+ if ( $_fragment )
1066
+ $url = str_replace( '#' . $_fragment, '', $url );
1067
 
1068
+ if ( $_query ) {
1069
+ $url .= '&' . $query;
1070
+ } else {
1071
+ $url .= '?' . $query;
1072
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1073
 
1074
+ if ( $_fragment )
1075
+ $url .= '#' . $_fragment;
1076
 
1077
+ return $url;
1078
  }
1079
  }
inc/classes/generate.class.php CHANGED
@@ -30,7 +30,7 @@ defined( 'ABSPATH' ) or die;
30
  *
31
  * @since 2.8.0
32
  */
33
- class Generate extends Term_Data {
34
 
35
  /**
36
  * Constructor, load parent constructor
@@ -40,12 +40,14 @@ class Generate extends Term_Data {
40
  }
41
 
42
  /**
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
  *
@@ -58,22 +60,24 @@ class Generate extends Term_Data {
58
  'noindex' => $this->get_option( 'site_noindex' ) ? 'noindex' : '',
59
  'nofollow' => $this->get_option( 'site_nofollow' ) ? 'nofollow' : '',
60
  'noarchive' => $this->get_option( 'site_noarchive' ) ? 'noarchive' : '',
61
- 'noodp' => $this->get_option( 'noodp' ) ? 'noodp' : '',
62
  'noydir' => $this->get_option( 'noydir' ) ? 'noydir' : '',
63
  );
64
 
 
 
 
65
  /**
66
  * Check the Robots SEO settings, set noindex for paged archives.
67
  * @since 2.2.4
68
  */
69
- if ( $this->is_archive() && $this->paged() > 1 )
70
  $meta['noindex'] = $this->get_option( 'paged_noindex' ) ? 'noindex' : $meta['noindex'];
71
 
72
- if ( $this->is_real_front_page() && ( $this->page() > 1 || $this->paged() > 1 ) )
73
  $meta['noindex'] = $this->get_option( 'home_paged_noindex' ) ? 'noindex' : $meta['noindex'];
74
 
75
  //* Check home page SEO settings, set noindex, nofollow and noarchive
76
- if ( $this->is_real_front_page() ) {
77
  $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'homepage_noindex' ) ? 'noindex' : $meta['noindex'];
78
  $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->is_option_checked( 'homepage_nofollow' ) ? 'nofollow' : $meta['nofollow'];
79
  $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'homepage_noarchive' ) ? 'noarchive' : $meta['noarchive'];
@@ -91,13 +95,14 @@ class Generate extends Term_Data {
91
  $meta['noindex'] = 'noindex';
92
  }
93
 
94
- if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
95
-
96
- $data = $this->get_term_data();
97
 
98
- $meta['noindex'] = empty( $meta['noindex'] ) && ! empty( $data['noindex'] ) ? 'noindex' : $meta['noindex'];
99
- $meta['nofollow'] = empty( $meta['nofollow'] ) && ! empty( $data['nofollow'] ) ? 'nofollow' : $meta['nofollow'];
100
- $meta['noarchive'] = empty( $meta['noarchive'] ) && ! empty( $data['noarchive'] ) ? 'noarchive' : $meta['noarchive'];
 
 
101
 
102
  //* If on custom Taxonomy page, but not a category or tag, then should've received specific term SEO settings.
103
  if ( $this->is_category() ) {
@@ -108,20 +113,16 @@ class Generate extends Term_Data {
108
  $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'tag_noindex' ) ? 'noindex' : $meta['noindex'];
109
  $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->is_option_checked( 'tag_nofollow' ) ? 'nofollow' : $meta['nofollow'];
110
  $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'tag_noindex' ) ? 'noarchive' : $meta['noarchive'];
 
 
 
 
 
 
 
 
111
  }
112
- }
113
-
114
- if ( $this->is_author() ) {
115
- $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'author_noindex' ) ? 'noindex' : $meta['noindex'];
116
- $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->is_option_checked( 'author_nofollow' ) ? 'nofollow' : $meta['nofollow'];
117
- $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'author_noarchive' ) ? 'noarchive' : $meta['noarchive'];
118
- }
119
-
120
- if ( $this->is_date() ) {
121
- $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'date_noindex' ) ? 'noindex' : $meta['noindex'];
122
- $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->is_option_checked( 'date_nofollow' ) ? 'nofollow' : $meta['nofollow'];
123
- $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'date_noarchive' ) ? 'noarchive' : $meta['noarchive'];
124
- }
125
 
126
  if ( $this->is_search() ) {
127
  $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'search_noindex' ) ? 'noindex' : $meta['noindex'];
@@ -129,12 +130,6 @@ class Generate extends Term_Data {
129
  $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'search_noarchive' ) ? 'noarchive' : $meta['noarchive'];
130
  }
131
 
132
- if ( $this->is_attachment() ) {
133
- $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'attachment_noindex' ) ? 'noindex' : $meta['noindex'];
134
- $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->is_option_checked( 'attachment_nofollow' ) ? 'nofollow' : $meta['nofollow'];
135
- $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'attachment_noarchive' ) ? 'noarchive' : $meta['noarchive'];
136
- }
137
-
138
  if ( $this->is_singular() ) {
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'];
@@ -143,11 +138,20 @@ class Generate extends Term_Data {
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
 
@@ -228,6 +232,7 @@ class Generate extends Term_Data {
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.
@@ -241,7 +246,7 @@ class Generate extends Term_Data {
241
 
242
  $description = trim( \get_bloginfo( 'description', 'display' ) );
243
 
244
- return $description = $description ?: $this->untitled();
245
  }
246
 
247
  /**
@@ -310,8 +315,6 @@ class Generate extends Term_Data {
310
  $type = 'article';
311
  } elseif ( $this->is_author() ) {
312
  $type = 'profile';
313
- } elseif ( $this->is_blog_page() || ( $this->is_real_front_page() && ! $this->has_page_on_front() ) ) {
314
- $type = 'blog';
315
  } else {
316
  $type = 'website';
317
  }
30
  *
31
  * @since 2.8.0
32
  */
33
+ class Generate extends User_Data {
34
 
35
  /**
36
  * Constructor, load parent constructor
40
  }
41
 
42
  /**
43
+ * Returns the `index`, `follow`, `noydir`, `noarchive` robots meta code 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
+ * @since 3.0.0 1: Removed noodp.
50
+ * 2: Improved efficiency by grouping if statements.
51
  *
52
  * @global object $wp_query
53
  *
60
  'noindex' => $this->get_option( 'site_noindex' ) ? 'noindex' : '',
61
  'nofollow' => $this->get_option( 'site_nofollow' ) ? 'nofollow' : '',
62
  'noarchive' => $this->get_option( 'site_noarchive' ) ? 'noarchive' : '',
 
63
  'noydir' => $this->get_option( 'noydir' ) ? 'noydir' : '',
64
  );
65
 
66
+ $is_archive = $this->is_archive();
67
+ $is_front_page = $this->is_real_front_page();
68
+
69
  /**
70
  * Check the Robots SEO settings, set noindex for paged archives.
71
  * @since 2.2.4
72
  */
73
+ if ( $is_archive && $this->paged() > 1 )
74
  $meta['noindex'] = $this->get_option( 'paged_noindex' ) ? 'noindex' : $meta['noindex'];
75
 
76
+ if ( $is_front_page && ( $this->page() > 1 || $this->paged() > 1 ) )
77
  $meta['noindex'] = $this->get_option( 'home_paged_noindex' ) ? 'noindex' : $meta['noindex'];
78
 
79
  //* Check home page SEO settings, set noindex, nofollow and noarchive
80
+ if ( $is_front_page ) {
81
  $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'homepage_noindex' ) ? 'noindex' : $meta['noindex'];
82
  $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->is_option_checked( 'homepage_nofollow' ) ? 'nofollow' : $meta['nofollow'];
83
  $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'homepage_noarchive' ) ? 'noarchive' : $meta['noarchive'];
95
  $meta['noindex'] = 'noindex';
96
  }
97
 
98
+ if ( $is_archive ) :
99
+ $term_data = $this->get_current_term_meta();
 
100
 
101
+ if ( $term_data ) {
102
+ $meta['noindex'] = empty( $meta['noindex'] ) && ! empty( $term_data['noindex'] ) ? 'noindex' : $meta['noindex'];
103
+ $meta['nofollow'] = empty( $meta['nofollow'] ) && ! empty( $term_data['nofollow'] ) ? 'nofollow' : $meta['nofollow'];
104
+ $meta['noarchive'] = empty( $meta['noarchive'] ) && ! empty( $term_data['noarchive'] ) ? 'noarchive' : $meta['noarchive'];
105
+ }
106
 
107
  //* If on custom Taxonomy page, but not a category or tag, then should've received specific term SEO settings.
108
  if ( $this->is_category() ) {
113
  $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'tag_noindex' ) ? 'noindex' : $meta['noindex'];
114
  $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->is_option_checked( 'tag_nofollow' ) ? 'nofollow' : $meta['nofollow'];
115
  $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'tag_noindex' ) ? 'noarchive' : $meta['noarchive'];
116
+ } elseif ( $this->is_author() ) {
117
+ $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'author_noindex' ) ? 'noindex' : $meta['noindex'];
118
+ $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->is_option_checked( 'author_nofollow' ) ? 'nofollow' : $meta['nofollow'];
119
+ $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'author_noarchive' ) ? 'noarchive' : $meta['noarchive'];
120
+ } elseif ( $this->is_date() ) {
121
+ $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'date_noindex' ) ? 'noindex' : $meta['noindex'];
122
+ $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->is_option_checked( 'date_nofollow' ) ? 'nofollow' : $meta['nofollow'];
123
+ $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'date_noarchive' ) ? 'noarchive' : $meta['noarchive'];
124
  }
125
+ endif;
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
  if ( $this->is_search() ) {
128
  $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'search_noindex' ) ? 'noindex' : $meta['noindex'];
130
  $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'search_noarchive' ) ? 'noarchive' : $meta['noarchive'];
131
  }
132
 
 
 
 
 
 
 
133
  if ( $this->is_singular() ) {
134
  $meta['noindex'] = empty( $meta['noindex'] ) && $this->get_custom_field( '_genesis_noindex' ) ? 'noindex' : $meta['noindex'];
135
  $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->get_custom_field( '_genesis_nofollow' ) ? 'nofollow' : $meta['nofollow'];
138
  if ( $this->is_protected( $this->get_the_real_ID() ) ) {
139
  $meta['noindex'] = 'noindex';
140
  }
141
+
142
+ if ( $this->is_attachment() ) {
143
+ $meta['noindex'] = empty( $meta['noindex'] ) && $this->is_option_checked( 'attachment_noindex' ) ? 'noindex' : $meta['noindex'];
144
+ $meta['nofollow'] = empty( $meta['nofollow'] ) && $this->is_option_checked( 'attachment_nofollow' ) ? 'nofollow' : $meta['nofollow'];
145
+ $meta['noarchive'] = empty( $meta['noarchive'] ) && $this->is_option_checked( 'attachment_noarchive' ) ? 'noarchive' : $meta['noarchive'];
146
+ }
147
  }
148
 
149
  /**
150
+ * Applies filters the_seo_framework_robots_meta_array
151
+ *
152
  * @since 2.6.0
153
+ *
154
+ * @param array $meta The current term meta.
155
  */
156
  $meta = (array) \apply_filters( 'the_seo_framework_robots_meta_array', $meta );
157
 
232
  * Fetch blog description.
233
  *
234
  * @since 2.5.2
235
+ * @since 3.0.0 No longer returns untitled when empty, instead, it just returns an empty string.
236
  * @staticvar string $description
237
  *
238
  * @return string $blogname The trimmed and sanitized blog description.
246
 
247
  $description = trim( \get_bloginfo( 'description', 'display' ) );
248
 
249
+ return $description = $description ?: '';
250
  }
251
 
252
  /**
315
  $type = 'article';
316
  } elseif ( $this->is_author() ) {
317
  $type = 'profile';
 
 
318
  } else {
319
  $type = 'website';
320
  }
inc/classes/index.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class call tree
4
+ *
5
+ * # Namespace: The_SEO_Framework
6
+ *
7
+ * ## Separated:
8
+ * - Deprecated
9
+ * |-> Final
10
+ * - Debug
11
+ * |-> Interface:
12
+ * - Debug_Interface
13
+ * |-> Final
14
+ *
15
+ * ## Façade (bottom is called first):
16
+ * - | Core
17
+ * | Compat
18
+ * | Query
19
+ * | Init
20
+ * | Admin_Init
21
+ * | Render
22
+ * | Detect
23
+ * | Post_Data
24
+ * | Term_Data
25
+ * | User_Data
26
+ * | Generate
27
+ * | Generate_Description
28
+ * | Generate_Title
29
+ * | Generate_Url
30
+ * | Generate_Image
31
+ * | Generate_Ldjson
32
+ * | Doing_It_Right
33
+ * | Profile
34
+ * | Inpost
35
+ * | Admin_Pages
36
+ * | Sanitize
37
+ * | Site_Options
38
+ * | Metaboxes
39
+ * | Sitemaps
40
+ * | Cache
41
+ * | Feed
42
+ * | Load
43
+ * |-> Interface:
44
+ * - Debug_Interface
45
+ * |-> Final
46
+ * |-> Instance
47
+ *
48
+ */
inc/classes/init.class.php CHANGED
@@ -48,15 +48,23 @@ class Init extends Query {
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
 
@@ -130,6 +138,9 @@ class Init extends Query {
130
 
131
  //* Add query strings for sitemap rewrite.
132
  \add_filter( 'query_vars', array( $this, 'enqueue_sitemap_query_vars' ), 1, 1 );
 
 
 
133
  }
134
 
135
  /**
@@ -159,8 +170,15 @@ class Init extends Query {
159
  //* Initialize caching actions.
160
  $this->init_admin_caching_actions();
161
 
 
 
 
 
 
 
162
  //* Save post data.
163
  \add_action( 'save_post', array( $this, 'inpost_seo_save' ), 1, 2 );
 
164
 
165
  //* Enqueues admin scripts.
166
  \add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ), 0, 1 );
@@ -197,6 +215,9 @@ class Init extends Query {
197
  //* Enqueue Inpost meta boxes.
198
  \add_action( 'add_meta_boxes', array( $this, 'add_inpost_seo_box_init' ), 5 );
199
 
 
 
 
200
  //* Enqueue Taxonomy meta output.
201
  \add_action( 'current_screen', array( $this, 'add_taxonomy_seo_box_init' ), 10 );
202
 
@@ -331,7 +352,7 @@ class Init extends Query {
331
  *
332
  * @param string|array $args the arguments that will be passed onto the callback.
333
  * @param bool $before if the header actions should be before or after the SEO Frameworks output
334
- * @return string|empty The filter output.
335
  */
336
  public function header_actions( $args = '', $before = true ) {
337
 
@@ -372,6 +393,7 @@ class Init extends Query {
372
  *
373
  * @since 1.0.0
374
  * @since 2.8.0 Cache is busted on each new release.
 
375
  */
376
  public function html_output() {
377
 
@@ -424,6 +446,9 @@ class Init extends Query {
424
  . $this->yandex_site_output()
425
  . $this->pint_site_output();
426
  else :
 
 
 
427
  $output = $this->the_description()
428
  . $this->og_image()
429
  . $this->og_locale()
@@ -451,6 +476,8 @@ class Init extends Query {
451
  . $this->bing_site_output()
452
  . $this->yandex_site_output()
453
  . $this->pint_site_output();
 
 
454
  endif;
455
 
456
  $after_actions = $this->header_actions( '', false );
@@ -534,7 +561,7 @@ class Init extends Query {
534
  *
535
  * @since 2.8.0
536
  *
537
- * @param unsigned int $redirect_type
538
  */
539
  $redirect_type = \absint( \apply_filters( 'the_seo_framework_redirect_status_code', 301 ) );
540
 
@@ -542,9 +569,9 @@ class Init extends Query {
542
  $this->_doing_it_wrong( __METHOD__, 'You should use 3xx HTTP Status Codes. Recommended 301 and 302.', '2.8.0' );
543
 
544
  if ( false === $allow_external ) {
545
- //= Only HTTP/HTTPS and internal URLs are allowed.
546
- $url = $this->set_url_scheme( $url, 'relative' );
547
- $url = $this->add_url_host( $url );
548
  $scheme = $this->is_ssl() ? 'https' : 'http';
549
 
550
  \wp_safe_redirect( $this->set_url_scheme( $url, $scheme ), $redirect_type );
@@ -590,7 +617,7 @@ class Init extends Query {
590
  if ( false === $output ) :
591
  $output = '';
592
 
593
- $parsed_home_url = \wp_parse_url( rtrim( $this->the_home_url_from_cache(), ' /\\' ) );
594
  $home_path = ! empty( $parsed_home_url['path'] ) ? \esc_attr( $parsed_home_url['path'] ) : '';
595
 
596
  if ( $this->is_subdirectory_installation() || $home_path ) {
@@ -599,20 +626,19 @@ class Init extends Query {
599
  $output .= "\r\n";
600
  }
601
 
 
 
 
602
  /**
603
- * Apply filters the_seo_framework_robots_txt_pre & the_seo_framework_robots_txt_pro : string
604
- * Adds custom cacheable lines.
605
  * Don't forget to add line breaks ( "\r\n" || PHP_EOL )
606
  *
607
  * @since 2.5.0
 
 
608
  */
609
- $pre = (string) \apply_filters( 'the_seo_framework_robots_txt_pre', '' );
610
- $pro = (string) \apply_filters( 'the_seo_framework_robots_txt_pro', '' );
611
-
612
- $site_url = \wp_parse_url( \site_url() );
613
- $site_path = ( ! empty( $site_url['path'] ) ) ? \esc_attr( $site_url['path'] ) : '';
614
 
615
- $output .= $pre;
616
  //* Output defaults
617
  $output .= "User-agent: *\r\n";
618
  $output .= "Disallow: $site_path/wp-admin/\r\n";
@@ -627,7 +653,13 @@ class Init extends Query {
627
  $output .= "Disallow: $home_path/*?*\r\n";
628
  }
629
 
630
- $output .= $pro;
 
 
 
 
 
 
631
 
632
  //* Add extra whitespace and sitemap full URL
633
  if ( $this->can_do_sitemap_robots( true ) )
@@ -691,8 +723,11 @@ class Init extends Query {
691
  * Alters search query.
692
  *
693
  * @since 2.9.4
 
 
 
694
  *
695
- * @param WP_Query $wp_query The WP_Query instance.
696
  * @return void Early if no search query is found.
697
  */
698
  public function _alter_search_query_in( $wp_query ) {
@@ -706,26 +741,19 @@ class Init extends Query {
706
  if ( $this->is_archive_query_adjustment_blocked( $wp_query ) )
707
  return;
708
 
709
- $meta_query = $wp_query->get( 'meta_query' );
710
 
711
- //* Convert to array. Unset it if it's empty.
712
- if ( ! is_array( $meta_query ) )
713
- $meta_query = $meta_query ? (array) $meta_query : array();
714
 
715
- /**
716
- * Exclude posts with exclude_local_search option on.
717
- *
718
- * Query is faster when the global relation is not set. Defaults to AND.
719
- * Query is faster when no value is set. Defaults to 'IS NULL' because
720
- * of 'compare'. Having no effect whatsoever as it's an exclusion.
721
- */
722
- $meta_query[] = array(
723
- 'key' => 'exclude_local_search',
724
- 'type' => 'NUMERIC',
725
- 'compare' => 'NOT EXISTS',
726
- );
727
 
728
- $wp_query->set( 'meta_query', $meta_query );
729
  }
730
  }
731
 
@@ -733,9 +761,11 @@ class Init extends Query {
733
  * Alters archive query.
734
  *
735
  * @since 2.9.4
 
 
736
  * @access private
737
  *
738
- * @param WP_Query $wp_query The WP_Query instance.
739
  * @return void Early if query alteration is useless or blocked.
740
  */
741
  public function _alter_archive_query_in( $wp_query ) {
@@ -744,32 +774,7 @@ class Init extends Query {
744
  if ( $this->is_archive_query_adjustment_blocked( $wp_query ) )
745
  return;
746
 
747
- $meta_query = $wp_query->get( 'meta_query' );
748
-
749
- //* Convert to array. Unset it if it's empty.
750
- if ( ! is_array( $meta_query ) )
751
- $meta_query = $meta_query ? (array) $meta_query : array();
752
-
753
- /**
754
- * Exclude posts with exclude_from_archive option on.
755
- *
756
- * Query is faster when the global relation is not set. Defaults to AND.
757
- * Query is faster when no value is set. Defaults to 'IS NULL' because
758
- * of 'compare'. Having no effect whatsoever as it's an exclusion.
759
- */
760
- $meta_query[] = array(
761
- 'key' => 'exclude_from_archive',
762
- 'type' => 'NUMERIC',
763
- 'compare' => 'NOT EXISTS',
764
- );
765
-
766
- $wp_query->set( 'meta_query', $meta_query );
767
- }
768
-
769
- /* @TODO exchange above with this 3.0+
770
- if ( ! empty( $wp_query->is_archive ) || ! empty( $wp_query->is_home ) ) {
771
-
772
- $excluded = $this->get_exclude_from_archive_ids_cache();
773
 
774
  if ( ! $excluded )
775
  return;
@@ -783,7 +788,6 @@ class Init extends Query {
783
 
784
  $wp_query->set( 'post__not_in', $excluded );
785
  }
786
- */
787
  }
788
 
789
  /**
@@ -793,7 +797,7 @@ class Init extends Query {
793
  * @access private
794
  *
795
  * @param array $posts The array of retrieved posts.
796
- * @param WP_Query $wp_query The WP_Query instance.
797
  * @return array $posts
798
  */
799
  public function _alter_search_query_post( $posts, $wp_query ) {
@@ -821,7 +825,7 @@ class Init extends Query {
821
  * @access private
822
  *
823
  * @param array $posts The array of retrieved posts.
824
- * @param WP_Query $wp_query The WP_Query instance.
825
  * @return array $posts
826
  */
827
  public function _alter_archive_query_post( $posts, $wp_query ) {
@@ -847,7 +851,7 @@ class Init extends Query {
847
  *
848
  * @since 2.9.4
849
  *
850
- * @param WP_Query $wp_query WP_Query object. Passed by reference.
851
  * @return bool
852
  */
853
  protected function is_archive_query_adjustment_blocked( &$wp_query ) {
48
  parent::__construct();
49
 
50
  /**
51
+ * Applies filters 'the_seo_framework_load_options'
52
+ * Allows the options page to be removed
53
+ *
54
  * @since 2.2.2
55
+ *
56
+ * @param bool $load_options
57
  */
58
  $this->load_options = (bool) \apply_filters( 'the_seo_framework_load_options', true );
59
 
60
  /**
61
+ * Applies filters 'the_seo_framework_use_object_cache'
62
+ * Enables object caching usage.
63
+ *
64
  * @since 2.4.3
65
  * @since 2.8.0 : Uses method $this->use_object_cache() as default.
66
+ *
67
+ * @param bool $use_object_cache
68
  */
69
  $this->use_object_cache = (bool) \apply_filters( 'the_seo_framework_use_object_cache', $this->use_object_cache() );
70
 
138
 
139
  //* Add query strings for sitemap rewrite.
140
  \add_filter( 'query_vars', array( $this, 'enqueue_sitemap_query_vars' ), 1, 1 );
141
+
142
+ //* Adjust category link to accommodate primary term.
143
+ \add_filter( 'post_link_category', array( $this, '_adjust_post_link_category' ), 10, 3 );
144
  }
145
 
146
  /**
170
  //* Initialize caching actions.
171
  $this->init_admin_caching_actions();
172
 
173
+ //= Initialize profile fields.
174
+ $this->init_profile_fields();
175
+
176
+ //= Initialize term meta filters and actions.
177
+ $this->initialize_term_meta();
178
+
179
  //* Save post data.
180
  \add_action( 'save_post', array( $this, 'inpost_seo_save' ), 1, 2 );
181
+ \add_action( 'save_post', array( $this, '_save_inpost_primary_term' ), 1, 2 );
182
 
183
  //* Enqueues admin scripts.
184
  \add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ), 0, 1 );
215
  //* Enqueue Inpost meta boxes.
216
  \add_action( 'add_meta_boxes', array( $this, 'add_inpost_seo_box_init' ), 5 );
217
 
218
+ //* Enqueue Inpost primary term template.
219
+ \add_action( 'admin_footer', array( $this, '_include_primary_term_selector_template' ) );
220
+
221
  //* Enqueue Taxonomy meta output.
222
  \add_action( 'current_screen', array( $this, 'add_taxonomy_seo_box_init' ), 10 );
223
 
352
  *
353
  * @param string|array $args the arguments that will be passed onto the callback.
354
  * @param bool $before if the header actions should be before or after the SEO Frameworks output
355
+ * @return string The filter output.
356
  */
357
  public function header_actions( $args = '', $before = true ) {
358
 
393
  *
394
  * @since 1.0.0
395
  * @since 2.8.0 Cache is busted on each new release.
396
+ * @since 3.0.0 Now converts timezone if needed.
397
  */
398
  public function html_output() {
399
 
446
  . $this->yandex_site_output()
447
  . $this->pint_site_output();
448
  else :
449
+ $set_timezone = $this->uses_time_in_timestamp_format() && ( $this->output_published_time() || $this->output_modified_time() );
450
+ $set_timezone and $this->set_timezone();
451
+
452
  $output = $this->the_description()
453
  . $this->og_image()
454
  . $this->og_locale()
476
  . $this->bing_site_output()
477
  . $this->yandex_site_output()
478
  . $this->pint_site_output();
479
+
480
+ $set_timezone and $this->reset_timezone();
481
  endif;
482
 
483
  $after_actions = $this->header_actions( '', false );
561
  *
562
  * @since 2.8.0
563
  *
564
+ * @param int <unsigned> $redirect_type
565
  */
566
  $redirect_type = \absint( \apply_filters( 'the_seo_framework_redirect_status_code', 301 ) );
567
 
569
  $this->_doing_it_wrong( __METHOD__, 'You should use 3xx HTTP Status Codes. Recommended 301 and 302.', '2.8.0' );
570
 
571
  if ( false === $allow_external ) {
572
+ //= Only HTTP/HTTPS and home URLs are allowed.
573
+ $path = $this->set_url_scheme( $url, 'relative' );
574
+ $url = \trailingslashit( $this->get_home_host() ) . ltrim( $path, ' /' );
575
  $scheme = $this->is_ssl() ? 'https' : 'http';
576
 
577
  \wp_safe_redirect( $this->set_url_scheme( $url, $scheme ), $redirect_type );
617
  if ( false === $output ) :
618
  $output = '';
619
 
620
+ $parsed_home_url = \wp_parse_url( rtrim( \get_home_url(), ' /\\' ) );
621
  $home_path = ! empty( $parsed_home_url['path'] ) ? \esc_attr( $parsed_home_url['path'] ) : '';
622
 
623
  if ( $this->is_subdirectory_installation() || $home_path ) {
626
  $output .= "\r\n";
627
  }
628
 
629
+ $site_url = \wp_parse_url( \site_url() );
630
+ $site_path = ( ! empty( $site_url['path'] ) ) ? \esc_attr( $site_url['path'] ) : '';
631
+
632
  /**
633
+ * Applies filters 'the_seo_framework_robots_txt_pre'
 
634
  * Don't forget to add line breaks ( "\r\n" || PHP_EOL )
635
  *
636
  * @since 2.5.0
637
+ *
638
+ * @param string $pre
639
  */
640
+ $output .= (string) \apply_filters( 'the_seo_framework_robots_txt_pre', '' );
 
 
 
 
641
 
 
642
  //* Output defaults
643
  $output .= "User-agent: *\r\n";
644
  $output .= "Disallow: $site_path/wp-admin/\r\n";
653
  $output .= "Disallow: $home_path/*?*\r\n";
654
  }
655
 
656
+ /**
657
+ * Applies filters 'the_seo_framework_robots_txt_pro'
658
+ * Don't forget to add line breaks ( "\r\n" || PHP_EOL )
659
+ *
660
+ * @param string $pro
661
+ */
662
+ $output .= (string) \apply_filters( 'the_seo_framework_robots_txt_pro', '' );
663
 
664
  //* Add extra whitespace and sitemap full URL
665
  if ( $this->can_do_sitemap_robots( true ) )
723
  * Alters search query.
724
  *
725
  * @since 2.9.4
726
+ * @since 3.0.0 Exchanged meta query for post__not_in query.
727
+ * @see Twenty Fourteen theme @source \Featured_Content::pre_get_posts()
728
+ * @access private
729
  *
730
+ * @param \WP_Query $wp_query The WP_Query instance.
731
  * @return void Early if no search query is found.
732
  */
733
  public function _alter_search_query_in( $wp_query ) {
741
  if ( $this->is_archive_query_adjustment_blocked( $wp_query ) )
742
  return;
743
 
744
+ $excluded = $this->get_ids_excluded_from_search();
745
 
746
+ if ( ! $excluded )
747
+ return;
 
748
 
749
+ $post__not_in = $wp_query->get( 'post__not_in' );
750
+
751
+ if ( ! empty( $post__not_in ) ) {
752
+ $excluded = array_merge( (array) $post__not_in, $excluded );
753
+ $excluded = array_unique( $excluded );
754
+ }
 
 
 
 
 
 
755
 
756
+ $wp_query->set( 'post__not_in', $excluded );
757
  }
758
  }
759
 
761
  * Alters archive query.
762
  *
763
  * @since 2.9.4
764
+ * @since 3.0.0 Exchanged meta query for post__not_in query.
765
+ * @see Twenty Fourteen theme @source \Featured_Content::pre_get_posts()
766
  * @access private
767
  *
768
+ * @param \WP_Query $wp_query The WP_Query instance.
769
  * @return void Early if query alteration is useless or blocked.
770
  */
771
  public function _alter_archive_query_in( $wp_query ) {
774
  if ( $this->is_archive_query_adjustment_blocked( $wp_query ) )
775
  return;
776
 
777
+ $excluded = $this->get_ids_excluded_from_archive();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778
 
779
  if ( ! $excluded )
780
  return;
788
 
789
  $wp_query->set( 'post__not_in', $excluded );
790
  }
 
791
  }
792
 
793
  /**
797
  * @access private
798
  *
799
  * @param array $posts The array of retrieved posts.
800
+ * @param \WP_Query $wp_query The WP_Query instance.
801
  * @return array $posts
802
  */
803
  public function _alter_search_query_post( $posts, $wp_query ) {
825
  * @access private
826
  *
827
  * @param array $posts The array of retrieved posts.
828
+ * @param \WP_Query $wp_query The WP_Query instance.
829
  * @return array $posts
830
  */
831
  public function _alter_archive_query_post( $posts, $wp_query ) {
851
  *
852
  * @since 2.9.4
853
  *
854
+ * @param \WP_Query $wp_query WP_Query object. Passed by reference.
855
  * @return bool
856
  */
857
  protected function is_archive_query_adjustment_blocked( &$wp_query ) {
inc/classes/inpost.class.php CHANGED
@@ -30,7 +30,7 @@ defined( 'ABSPATH' ) or die;
30
  *
31
  * @since 2.8.0
32
  */
33
- class Inpost extends Doing_It_Right {
34
 
35
  /**
36
  * Add inpost SEO Bar through a filter.
@@ -60,13 +60,13 @@ class Inpost extends Doing_It_Right {
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 :
@@ -81,14 +81,13 @@ class Inpost extends Doing_It_Right {
81
  * }
82
  */
83
  $this->inpost_seo_bar = \apply_filters( 'the_seo_framework_inpost_seo_bar', false );
84
-
85
  }
86
 
87
  /**
88
- * Inpost setting nav tab wrappers.
89
- * Outputs Tabs and settings content.
90
  *
91
  * @since 2.9.0
 
92
  *
93
  * @param string $id The Nav Tab ID
94
  * @param array $tabs the tab content {
@@ -100,103 +99,10 @@ class Inpost extends Doing_It_Right {
100
  * )
101
  * }
102
  * @param string $version the The SEO Framework version for debugging. May be emptied.
103
- * @param bool $use_tabs Whether to output tabs, only works when $tabs is greater than 1.
104
  */
105
  public function inpost_flex_nav_tab_wrapper( $id, $tabs = array(), $version = '2.3.6', $use_tabs = true ) {
106
-
107
- //* Whether tabs are active.
108
- $use_tabs = $use_tabs && count( $tabs ) > 1;
109
-
110
- /**
111
- * Start navigational tabs.
112
- *
113
- * Don't output navigation if $use_tabs is false and the amount of tabs is 1 or lower.
114
- */
115
- if ( $use_tabs ) :
116
- ?>
117
- <div class="tsf-flex tsf-flex-nav-tab-wrapper tsf-flex-hide-if-no-js" id="<?php echo \esc_attr( 'tsf-flex-' . $id . '-tabs-wrapper' ); ?>">
118
- <div class="tsf-flex tsf-flex-nav-tab-inner">
119
- <?php
120
- $count = 1;
121
- foreach ( $tabs as $tab => $value ) :
122
- $dashicon = isset( $value['dashicon'] ) ? $value['dashicon'] : '';
123
- $label_name = isset( $value['name'] ) ? $value['name'] : '';
124
-
125
- $wrapper_id = \esc_attr( 'tsf-flex-nav-tab-' . $tab );
126
- $wrapper_active = 1 === $count ? ' tsf-flex-nav-tab-active' : '';
127
-
128
- $input_checked = 1 === $count ? 'checked' : '';
129
- $input_id = \esc_attr( 'tsf-flex-' . $id . '-tab-' . $tab );
130
- $input_name = \esc_attr( 'tsf-flex-' . $id . '-tabs' );
131
-
132
- //= All output below is escaped.
133
- ?>
134
- <div class="tsf-flex tsf-flex-nav-tab tsf-flex<?php echo $wrapper_active; ?>" id="<?php echo $wrapper_id; ?>">
135
- <input type="radio" class="tsf-flex-nav-tab-radio" id="<?php echo $input_id; ?>" name="<?php echo $input_name; ?>" <?php echo $input_checked; ?>>
136
- <label for="<?php echo $input_id; ?>" class="tsf-flex tsf-flex-nav-tab-label">
137
- <?php
138
- echo $dashicon ? '<span class="tsf-flex dashicons dashicons-' . \esc_attr( $dashicon ) . ' tsf-flex-nav-dashicon"></span>' : '';
139
- echo $label_name ? '<span class="tsf-flex tsf-flex-nav-name">' . \esc_attr( $label_name ) . '</span>' : '';
140
- ?>
141
- </label>
142
- </div>
143
- <?php
144
-
145
- $count++;
146
- endforeach;
147
- ?>
148
- </div>
149
- </div>
150
- <?php
151
- endif;
152
-
153
- /**
154
- * Start Content.
155
- *
156
- * The content is relative to the navigation, and uses CSS to become visible.
157
- */
158
- $count = 1;
159
- foreach ( $tabs as $tab => $value ) :
160
-
161
- $radio_id = \esc_attr( 'tsf-flex-' . $id . '-tab-' . $tab . '-content' );
162
- $radio_class = \esc_attr( 'tsf-flex-' . $id . '-tabs-content' );
163
-
164
- //* Current tab for JS.
165
- $current_class = 1 === $count ? ' tsf-flex-tab-content-active' : '';
166
-
167
- ?>
168
- <div class="tsf-flex tsf-flex-tab-content <?php echo \esc_attr( $radio_class . $current_class ); ?>" id="<?php echo \esc_attr( $radio_id ); ?>" >
169
- <?php
170
- //* No-JS tabs.
171
- if ( $use_tabs ) :
172
- $dashicon = isset( $value['dashicon'] ) ? $value['dashicon'] : '';
173
- $label_name = isset( $value['name'] ) ? $value['name'] : '';
174
-
175
- ?>
176
- <div class="tsf-flex tsf-flex-hide-if-js tsf-flex-tabs-content-no-js">
177
- <div class="tsf-flex tsf-flex-nav-tab tsf-flex-tab-no-js">
178
- <span class="tsf-flex tsf-flex-nav-tab">
179
- <?php echo $dashicon ? '<span class="tsf-flex dashicons dashicons-' . \esc_attr( $dashicon ) . ' tsf-flex-nav-dashicon"></span>' : ''; ?>
180
- <?php echo $label_name ? '<span class="tsf-flex tsf-flex-nav-name">' . \esc_attr( $label_name ) . '</span>' : ''; ?>
181
- </span>
182
- </div>
183
- </div>
184
- <?php
185
- endif;
186
-
187
- $callback = isset( $value['callback'] ) ? $value['callback'] : '';
188
-
189
- if ( $callback ) {
190
- $params = isset( $value['args'] ) ? $value['args'] : '';
191
- //* Should already be escaped.
192
- echo $this->call_function( $callback, $version, $params );
193
- }
194
- ?>
195
- </div>
196
- <?php
197
-
198
- $count++;
199
- endforeach;
200
  }
201
 
202
  /**
@@ -267,8 +173,8 @@ class Inpost extends Doing_It_Right {
267
 
268
  if ( $labels ) :
269
  //* Title and type are used interchangeably.
270
- $title = isset( $labels->singular_name ) ? $labels->singular_name : $labels->name;
271
- $args = array( $title, 'is_post_page' );
272
 
273
  /**
274
  * Applies filters 'the_seo_framework_metabox_id' : string
@@ -297,14 +203,35 @@ class Inpost extends Doing_It_Right {
297
 
298
  /**
299
  * High priority, this box is seen right below the post/page edit screen.
 
300
  * Applies filters 'the_seo_framework_metabox_priority' : string
301
  * @since 2.6.0
302
  * @param string $default Accepts 'high', 'default', 'low'
303
  */
304
  $priority = (string) \apply_filters( 'the_seo_framework_metabox_priority', 'high' );
305
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
  /* translators: %s = Post type name */
307
- \add_meta_box( $id, sprintf( \__( '%s SEO Settings', 'autodescription' ), $title ), array( $this, 'pre_seo_box' ), $post_type, $context, $priority, $args );
308
  endif;
309
  endif;
310
  }
@@ -473,6 +400,17 @@ class Inpost extends Doing_It_Right {
473
  \do_action( 'the_seo_framework_pro_page_inpost_social_tab' );
474
  }
475
 
 
 
 
 
 
 
 
 
 
 
 
476
  /**
477
  * Fills in input variables by call for general tabs.
478
  *
@@ -484,9 +422,9 @@ class Inpost extends Doing_It_Right {
484
  * @ignore
485
  * @todo Remove and refactor caller.
486
  *
487
- * @param int $tit_len_parsed. Passed by reference.
488
  * @param string $doctitle_placeholder. Passed by reference.
489
- * @param int $desc_len_parsed. Passed by reference.
490
  * @param string $description_placeholder. Passed by reference.
491
  */
492
  public function _get_inpost_general_tab_vars( &$tit_len_parsed, &$doctitle_placeholder, &$desc_len_parsed, &$description_placeholder ) {
@@ -549,7 +487,12 @@ class Inpost extends Doing_It_Right {
549
  */
550
  if ( $is_static_frontpage ) {
551
  if ( $this->get_option( 'homepage_tagline' ) ) {
552
- $tit_len_pre = $title ? $title . ' | ' . $this->get_blogdescription() : $generated_doctitle;
 
 
 
 
 
553
  } else {
554
  $tit_len_pre = $title ?: $generated_doctitle;
555
  }
30
  *
31
  * @since 2.8.0
32
  */
33
+ class Inpost extends Profile {
34
 
35
  /**
36
  * Add inpost SEO Bar through a filter.
60
  public $inpost_nonce_field;
61
 
62
  /**
63
+ * Constructor, load parent constructor and sets up variables.
64
  */
65
  protected function __construct() {
66
  parent::__construct();
67
 
68
+ $this->inpost_nonce_name = 'tsf_inpost_seo_settings';
69
+ $this->inpost_nonce_field = 'tsf_inpost_nonce';
70
 
71
  /**
72
  * Applies filters bool|string the_seo_framework_inpost_seo_bar :
81
  * }
82
  */
83
  $this->inpost_seo_bar = \apply_filters( 'the_seo_framework_inpost_seo_bar', false );
 
84
  }
85
 
86
  /**
87
+ * Outputs in-post flex navigational wrapper and its content.
 
88
  *
89
  * @since 2.9.0
90
+ * @since 3.0.0: Converted to view.
91
  *
92
  * @param string $id The Nav Tab ID
93
  * @param array $tabs the tab content {
99
  * )
100
  * }
101
  * @param string $version the The SEO Framework version for debugging. May be emptied.
102
+ * @param bool $use_tabs Whether to output tabs, only works when $tabs count is greater than 1.
103
  */
104
  public function inpost_flex_nav_tab_wrapper( $id, $tabs = array(), $version = '2.3.6', $use_tabs = true ) {
105
+ $this->get_view( 'inpost/wrap', get_defined_vars() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  }
107
 
108
  /**
173
 
174
  if ( $labels ) :
175
  //* Title and type are used interchangeably.
176
+ $label = isset( $labels->singular_name ) ? $labels->singular_name : $labels->name;
177
+ $args = array( $label, 'is_post_page' );
178
 
179
  /**
180
  * Applies filters 'the_seo_framework_metabox_id' : string
203
 
204
  /**
205
  * High priority, this box is seen right below the post/page edit screen.
206
+ *
207
  * Applies filters 'the_seo_framework_metabox_priority' : string
208
  * @since 2.6.0
209
  * @param string $default Accepts 'high', 'default', 'low'
210
  */
211
  $priority = (string) \apply_filters( 'the_seo_framework_metabox_priority', 'high' );
212
 
213
+ if ( $this->is_front_page_by_id( $this->get_the_real_ID() ) ) {
214
+ if ( $this->can_access_settings() ) {
215
+ $schema = \is_rtl() ? '%2$s - %1$s' : '%1$s - %2$s';
216
+ $title = sprintf(
217
+ $schema,
218
+ \__( 'Homepage SEO Settings', 'autodescription' ),
219
+ $this->make_info(
220
+ \__( 'The SEO Settings take precedence over these settings.', 'autodescription' ),
221
+ $this->seo_settings_page_url(),
222
+ false
223
+ )
224
+ );
225
+ } else {
226
+ $title = \__( 'Homepage SEO Settings', 'autodescription' );
227
+ }
228
+ } else {
229
+ /* translators: %s = Post Type */
230
+ $title = sprintf( \__( '%s SEO Settings', 'autodescription' ), $label );
231
+ }
232
+
233
  /* translators: %s = Post type name */
234
+ \add_meta_box( $id, $title, array( $this, 'pre_seo_box' ), $post_type, $context, $priority, $args );
235
  endif;
236
  endif;
237
  }
400
  \do_action( 'the_seo_framework_pro_page_inpost_social_tab' );
401
  }
402
 
403
+ /**
404
+ * Outputs Primary Term nonce tempalte.
405
+ *
406
+ * @since 3.0.0
407
+ * @access private
408
+ */
409
+ public function _include_primary_term_selector_template() {
410
+ if ( $this->is_post_edit() )
411
+ $this->get_view( 'templates/inpost/primary-term-selector', array() );
412
+ }
413
+
414
  /**
415
  * Fills in input variables by call for general tabs.
416
  *
422
  * @ignore
423
  * @todo Remove and refactor caller.
424
  *
425
+ * @param string $tit_len_parsed. Passed by reference.
426
  * @param string $doctitle_placeholder. Passed by reference.
427
+ * @param string $desc_len_parsed. Passed by reference.
428
  * @param string $description_placeholder. Passed by reference.
429
  */
430
  public function _get_inpost_general_tab_vars( &$tit_len_parsed, &$doctitle_placeholder, &$desc_len_parsed, &$description_placeholder ) {
487
  */
488
  if ( $is_static_frontpage ) {
489
  if ( $this->get_option( 'homepage_tagline' ) ) {
490
+ $_blogdescription = $this->get_blogdescription();
491
+ if ( $_blogdescription ) {
492
+ $tit_len_pre = $title ? $title . ' | ' . $_blogdescription : $generated_doctitle;
493
+ } else {
494
+ $tit_len_pre = $title ? $title : $generated_doctitle;
495
+ }
496
  } else {
497
  $tit_len_pre = $title ?: $generated_doctitle;
498
  }
inc/classes/load.class.php CHANGED
@@ -43,10 +43,10 @@ final class Load extends Feed implements Debug_Interface {
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.
@@ -89,7 +89,6 @@ final class Load extends Feed implements Debug_Interface {
89
 
90
  //* WP Core definition.
91
  $this->script_debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ?: $this->script_debug;
92
-
93
  }
94
 
95
  /**
@@ -185,8 +184,7 @@ final class Load extends Feed implements Debug_Interface {
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
  /**
@@ -202,8 +200,7 @@ final class Load extends Feed implements Debug_Interface {
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
  /**
@@ -219,8 +216,7 @@ final class Load extends Feed implements Debug_Interface {
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
  /**
@@ -235,8 +231,7 @@ final class Load extends Feed implements Debug_Interface {
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.
@@ -251,13 +246,10 @@ final class Load extends Feed implements Debug_Interface {
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
  }
43
  * @var bool Whether transients are enabled.
44
  * @var bool Whether script debugging is enabled.
45
  */
46
+ public $the_seo_framework_debug = false,
47
+ $the_seo_framework_debug_hidden = false,
48
+ $the_seo_framework_use_transients = true,
49
+ $script_debug = false;
50
 
51
  /**
52
  * Constructor, setup debug vars and then load parent constructor.
89
 
90
  //* WP Core definition.
91
  $this->script_debug = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ?: $this->script_debug;
 
92
  }
93
 
94
  /**
184
  * @param string $replacement Optional. The function that should have been called. Default null.
185
  */
186
  public function _deprecated_filter( $filter, $version, $replacement = null ) {
187
+ Debug::get_instance()->_deprecated_filter( $filter, $version, $replacement );
 
188
  }
189
 
190
  /**
200
  * @param string $replacement Optional. The function that should have been called. Default null.
201
  */
202
  public function _deprecated_function( $function, $version, $replacement = null ) {
203
+ Debug::get_instance()->_deprecated_function( $function, $version, $replacement );
 
204
  }
205
 
206
  /**
216
  * @param string $version The version of WordPress where the message was added.
217
  */
218
  public function _doing_it_wrong( $function, $message, $version = null ) {
219
+ Debug::get_instance()->_doing_it_wrong( $function, $message, $version );
 
220
  }
221
 
222
  /**
231
  * @param string $message A message explaining what has been done incorrectly.
232
  */
233
  public function _inaccessible_p_or_m( $p_or_m, $message = '' ) {
234
+ Debug::get_instance()->_inaccessible_p_or_m( $p_or_m, $message );
 
235
  }
236
  /**
237
  * Debug init. Simplified way of debugging a function, only works in admin.
246
  * @return void early if debugging is disabled or when storing cache values.
247
  */
248
  public function debug_init( $method, $store, $debug_key = null ) {
 
 
 
249
  if ( func_num_args() >= 4 ) {
250
+ Debug::get_instance()->debug_init( $method, $store, $debug_key, array_slice( func_get_args(), 3 ) );
251
  } else {
252
+ Debug::get_instance()->debug_init( $method, $store, $debug_key );
253
  }
254
  }
255
  }
inc/classes/metaboxes.class.php CHANGED
@@ -201,6 +201,17 @@ class Metaboxes extends Site_Options {
201
  public function general_metabox_canonical_tab() {
202
  $this->get_view( 'metaboxes/general-metabox', array(), 'canonical' );
203
  }
 
 
 
 
 
 
 
 
 
 
 
204
  /**
205
  * Title meta box on the Site SEO Settings page.
206
  *
@@ -551,6 +562,7 @@ class Metaboxes extends Site_Options {
551
  * Schema Metabox General Tab output.
552
  *
553
  * @since 2.8.0
 
554
  * @see $this->schema_metabox() Callback for Schema.org Settings box.
555
  */
556
  public function schema_metabox_general_tab() {
201
  public function general_metabox_canonical_tab() {
202
  $this->get_view( 'metaboxes/general-metabox', array(), 'canonical' );
203
  }
204
+
205
+ /**
206
+ * Outputs General Settings meta box timestamps tab.
207
+ *
208
+ * @since 3.0.0
209
+ * @see $this->general_metabox() : Callback for General Settings box.
210
+ */
211
+ public function general_metabox_timestamps_tab() {
212
+ $this->get_view( 'metaboxes/general-metabox', array(), 'timestamps' );
213
+ }
214
+
215
  /**
216
  * Title meta box on the Site SEO Settings page.
217
  *
562
  * Schema Metabox General Tab output.
563
  *
564
  * @since 2.8.0
565
+ * @since 3.0.0 No longer used.
566
  * @see $this->schema_metabox() Callback for Schema.org Settings box.
567
  */
568
  public function schema_metabox_general_tab() {
inc/classes/post-data.class.php CHANGED
@@ -84,12 +84,12 @@ class Post_Data extends Detect {
84
  *
85
  * @since 2.0.0
86
  * @since 2.9.3 : Added 'exclude_from_archive'.
 
87
  * @uses $this->save_custom_fields() : Perform security checks and saves post meta / custom field data to a post or page.
88
  *
89
- * @param integer $post_id Post ID.
90
- * @param object $post Post object.
91
- * @return mixed Returns post id if permissions incorrect, null if doing autosave, ajax or future post, false if update
92
- * or delete failed, and true on success.
93
  */
94
  public function inpost_seo_save( $post_id, $post ) {
95
 
@@ -97,23 +97,25 @@ class Post_Data extends Detect {
97
  if ( empty( $_POST['autodescription'] ) )
98
  return;
99
 
100
- /**
101
- * Merge user submitted options with fallback defaults
102
- * Passes through nonce at the end of the function.
103
- */
104
- $data = \wp_parse_args( $_POST['autodescription'], array(
105
  '_genesis_title' => '',
106
  '_genesis_description' => '',
107
  '_genesis_canonical_uri' => '',
108
- 'redirect' => '',
109
  '_social_image_url' => '',
110
  '_social_image_id' => 0,
111
  '_genesis_noindex' => 0,
112
  '_genesis_nofollow' => 0,
113
  '_genesis_noarchive' => 0,
114
- 'exclude_local_search' => 0,
115
- 'exclude_from_archive' => 0,
116
- ) );
 
 
 
 
 
 
117
 
118
  foreach ( (array) $data as $key => $value ) :
119
  switch ( $key ) :
@@ -174,13 +176,14 @@ class Post_Data extends Detect {
174
  * repeated checks against the nonce, request and permissions are avoided.
175
  *
176
  * @since 2.0.0
 
177
  *
178
  * @thanks StudioPress (http://www.studiopress.com/) for some code.
179
  *
180
  * @param array $data Key/Value pairs of data to save in '_field_name' => 'value' format.
181
  * @param string $nonce_action Nonce action for use with wp_verify_nonce().
182
  * @param string $nonce_name Name of the nonce to check for permissions.
183
- * @param WP_Post|integer $post Post object or ID.
184
  * @return mixed Return null if permissions incorrect, doing autosave, ajax or future post, false if update or delete
185
  * failed, and true on success.
186
  */
@@ -228,6 +231,57 @@ class Post_Data extends Detect {
228
  }
229
  }
230
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  /**
232
  * Fetches or parses the excerpt of the post.
233
  *
@@ -265,7 +319,7 @@ class Post_Data extends Detect {
265
  *
266
  * @param int $the_id The Post ID.
267
  * @param int $tt_id The Taxonomy Term ID.
268
- * @return string|empty excerpt.
269
  */
270
  public function fetch_excerpt( $the_id = '', $tt_id = '' ) {
271
 
@@ -299,7 +353,7 @@ class Post_Data extends Detect {
299
  * @param int $the_id The Post ID.
300
  * @param int $tt_id The Taxonomy Term ID
301
  * @param mixed $output The value type to return. Accepts OBJECT, ARRAY_A, or ARRAY_N
302
- * @return empty|array The Post Array.
303
  */
304
  protected function fetch_post_by_id( $the_id = '', $tt_id = '', $output = ARRAY_A ) {
305
 
@@ -489,23 +543,161 @@ class Post_Data extends Detect {
489
  * Only works on singular pages.
490
  *
491
  * @since 2.8.0
 
 
 
492
  *
493
- * @param int|object The post ID or WP Post object.
494
- * @return bool True if private, false otherwise.
495
  */
496
- public function is_protected( $id = 0 ) {
497
-
498
- if ( false === $this->is_singular() )
499
- return false;
500
 
501
  $post = \get_post( $id, OBJECT );
 
502
 
503
  if ( isset( $post->post_password ) && '' !== $post->post_password ) {
504
- return true;
505
  } elseif ( isset( $post->post_status ) && 'private' === $post->post_status ) {
506
- return true;
507
  }
508
 
509
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  }
511
  }
84
  *
85
  * @since 2.0.0
86
  * @since 2.9.3 : Added 'exclude_from_archive'.
87
+ * @securitycheck 3.0.0 OK. NOTE: Check is done at save_custom_fields().
88
  * @uses $this->save_custom_fields() : Perform security checks and saves post meta / custom field data to a post or page.
89
  *
90
+ * @param integer $post_id Post ID.
91
+ * @param \WP_Post $post Post object.
92
+ * @return void
 
93
  */
94
  public function inpost_seo_save( $post_id, $post ) {
95
 
97
  if ( empty( $_POST['autodescription'] ) )
98
  return;
99
 
100
+ $defaults = array(
 
 
 
 
101
  '_genesis_title' => '',
102
  '_genesis_description' => '',
103
  '_genesis_canonical_uri' => '',
104
+ 'redirect' => '', // Will be displayed in custom fields when set...
105
  '_social_image_url' => '',
106
  '_social_image_id' => 0,
107
  '_genesis_noindex' => 0,
108
  '_genesis_nofollow' => 0,
109
  '_genesis_noarchive' => 0,
110
+ 'exclude_local_search' => 0, // Will be displayed in custom fields when set...
111
+ 'exclude_from_archive' => 0, // Will be displayed in custom fields when set...
112
+ );
113
+
114
+ /**
115
+ * Merge user submitted options with fallback defaults
116
+ * Passes through nonce at the end of the function.
117
+ */
118
+ $data = \wp_parse_args( $_POST['autodescription'], $defaults );
119
 
120
  foreach ( (array) $data as $key => $value ) :
121
  switch ( $key ) :
176
  * repeated checks against the nonce, request and permissions are avoided.
177
  *
178
  * @since 2.0.0
179
+ * @securitycheck 3.0.0 OK.
180
  *
181
  * @thanks StudioPress (http://www.studiopress.com/) for some code.
182
  *
183
  * @param array $data Key/Value pairs of data to save in '_field_name' => 'value' format.
184
  * @param string $nonce_action Nonce action for use with wp_verify_nonce().
185
  * @param string $nonce_name Name of the nonce to check for permissions.
186
+ * @param \WP_Post|integer $post Post object or ID.
187
  * @return mixed Return null if permissions incorrect, doing autosave, ajax or future post, false if update or delete
188
  * failed, and true on success.
189
  */
231
  }
232
  }
233
 
234
+ /**
235
+ * Saves primary term data for posts.
236
+ *
237
+ * @since 3.0.0
238
+ * @securitycheck 3.0.0 OK.
239
+ *
240
+ * @param integer $post_id Post ID.
241
+ * @param \WP_Post $post Post object.
242
+ * @return void
243
+ */
244
+ public function _save_inpost_primary_term( $post_id, $post ) {
245
+
246
+ //* Nonce is done at the end of this function.
247
+ if ( empty( $_POST['autodescription'] ) )
248
+ return;
249
+
250
+ $post_type = \get_post_type( $post_id ) ?: false;
251
+
252
+ if ( ! $post_type )
253
+ return;
254
+
255
+ /**
256
+ * Don't save if WP is creating a revision (same as DOING_AUTOSAVE?)
257
+ * @todo @see wp_is_post_revision(), which also returns the post revision ID...
258
+ */
259
+ if ( 'revision' === $post_type )
260
+ return;
261
+
262
+ //* Check that the user is allowed to edit the post
263
+ if ( ! \current_user_can( 'edit_post', $post_id ) )
264
+ return;
265
+
266
+ $_taxonomies = $this->get_hierarchical_taxonomies_as( 'names', $post_type );
267
+ $values = array();
268
+
269
+ foreach ( $_taxonomies as $_taxonomy ) {
270
+ $_post_key = '_primary_term_' . $_taxonomy;
271
+ $values[ $_taxonomy ] = array(
272
+ 'action' => $this->inpost_nonce_field . '_pt',
273
+ 'name' => $this->inpost_nonce_name . '_pt_' . $_taxonomy,
274
+ 'value' => isset( $_POST['autodescription'][ $_post_key ] ) ? \absint( $_POST['autodescription'][ $_post_key ] ) : false,
275
+ );
276
+ }
277
+
278
+ foreach ( $values as $t => $v ) {
279
+ if ( \wp_verify_nonce( $v['name'], $v['action'] ) ) {
280
+ $this->update_primary_term_id( $post_id, $t, $v['value'] );
281
+ }
282
+ }
283
+ }
284
+
285
  /**
286
  * Fetches or parses the excerpt of the post.
287
  *
319
  *
320
  * @param int $the_id The Post ID.
321
  * @param int $tt_id The Taxonomy Term ID.
322
+ * @return string The excerpt.
323
  */
324
  public function fetch_excerpt( $the_id = '', $tt_id = '' ) {
325
 
353
  * @param int $the_id The Post ID.
354
  * @param int $tt_id The Taxonomy Term ID
355
  * @param mixed $output The value type to return. Accepts OBJECT, ARRAY_A, or ARRAY_N
356
+ * @return string|array The Post Array.
357
  */
358
  protected function fetch_post_by_id( $the_id = '', $tt_id = '', $output = ARRAY_A ) {
359
 
543
  * Only works on singular pages.
544
  *
545
  * @since 2.8.0
546
+ * @since 3.0.0 1. No longer checks for current query.
547
+ * 2. Input parameter now default to null.
548
+ * This currently doesn't affect how it works.
549
  *
550
+ * @param int|null|\WP_Post The post ID or WP Post object.
551
+ * @return bool True if protected, false otherwise.
552
  */
553
+ public function is_protected( $id = null ) {
 
 
 
554
 
555
  $post = \get_post( $id, OBJECT );
556
+ $ret = false;
557
 
558
  if ( isset( $post->post_password ) && '' !== $post->post_password ) {
559
+ $ret = true;
560
  } elseif ( isset( $post->post_status ) && 'private' === $post->post_status ) {
561
+ $ret = true;
562
  }
563
 
564
+ return $ret;
565
+ }
566
+
567
+ /**
568
+ * Determines if the current post has a password.
569
+ *
570
+ * @since 3.0.0
571
+ *
572
+ * @param int|null|\WP_Post The post ID or WP Post object.
573
+ * @return bool True if private, false otherwise.
574
+ */
575
+ public function is_password_protected( $id = null ) {
576
+
577
+ $post = \get_post( $id, OBJECT );
578
+ $ret = false;
579
+
580
+ if ( isset( $post->post_password ) && '' !== $post->post_password )
581
+ $ret = true;
582
+
583
+ return $ret;
584
+ }
585
+
586
+ /**
587
+ * Determines if the current post is private.
588
+ *
589
+ * @since 3.0.0
590
+ *
591
+ * @param int|null|\WP_Post The post ID or WP Post object.
592
+ * @return bool True if private, false otherwise.
593
+ */
594
+ public function is_private( $id = null ) {
595
+
596
+ $post = \get_post( $id, OBJECT );
597
+ $ret = false;
598
+
599
+ if ( isset( $post->post_status ) && 'private' === $post->post_status )
600
+ $ret = true;
601
+
602
+ return $ret;
603
+ }
604
+
605
+ /**
606
+ * Returns list of post IDs that are excluded from search.
607
+ *
608
+ * @since 3.0.0
609
+ *
610
+ * @return array The excluded post IDs.
611
+ */
612
+ public function get_ids_excluded_from_search() {
613
+
614
+ $cache = $this->get_excluded_ids_from_cache();
615
+ $ids = array();
616
+
617
+ if ( ! empty( $cache['search'] ) ) {
618
+ $ids = $cache['search'];
619
+ }
620
+
621
+ return $ids;
622
+ }
623
+
624
+ /**
625
+ * Returns list of post IDs that are excluded from archive.
626
+ *
627
+ * @since 3.0.0
628
+ *
629
+ * @return array The excluded post IDs.
630
+ */
631
+ public function get_ids_excluded_from_archive() {
632
+
633
+ $cache = $this->get_excluded_ids_from_cache();
634
+ $ids = array();
635
+
636
+ if ( ! empty( $cache['archive'] ) ) {
637
+ $ids = $cache['archive'];
638
+ }
639
+
640
+ return $ids;
641
+ }
642
+
643
+ /**
644
+ * Returns the primary term for post.
645
+ *
646
+ * @since 3.0.0
647
+ *
648
+ * @param int|null $post_id The post ID.
649
+ * @param string $taxonomy The taxonomy name.
650
+ * @return \WP_Term|false The primary term. False if not set.
651
+ */
652
+ public function get_primary_term( $post_id = null, $taxonomy = '' ) {
653
+
654
+ $primary_id = $this->get_primary_term_id( $post_id, $taxonomy );
655
+
656
+ if ( ! $primary_id )
657
+ return false;
658
+
659
+ $terms = \get_the_terms( $post_id, $taxonomy );
660
+ $primary_term = false;
661
+
662
+ foreach ( $terms as $term ) {
663
+ if ( $primary_id === (int) $term->term_id ) {
664
+ $primary_term = $term;
665
+ break;
666
+ }
667
+ }
668
+
669
+ return $primary_term;
670
+ }
671
+
672
+ /**
673
+ * Returns the primary term ID for post.
674
+ *
675
+ * @since 3.0.0
676
+ *
677
+ * @param int|null $post_id The post ID.
678
+ * @param string $taxonomy The taxonomy name.
679
+ * @return int The primary term ID. 0 if not set.
680
+ */
681
+ public function get_primary_term_id( $post_id = null, $taxonomy = '' ) {
682
+ return (int) $this->get_custom_field( '_primary_term_' . $taxonomy, $post_id ) ?: 0;
683
+ }
684
+
685
+ /**
686
+ * Updates the primary term ID for post.
687
+ *
688
+ * @since 3.0.0
689
+ *
690
+ * @param int|null $post_id The post ID.
691
+ * @param string $taxonomy The taxonomy name.
692
+ * @param int $value The new value. If empty, it will delete the entry.
693
+ * @return bool True on success, false on failure.
694
+ */
695
+ public function update_primary_term_id( $post_id = null, $taxonomy = '', $value = 0 ) {
696
+ if ( empty( $value ) ) {
697
+ $success = \delete_post_meta( $post_id, '_primary_term_' . $taxonomy );
698
+ } else {
699
+ $success = \update_post_meta( $post_id, '_primary_term_' . $taxonomy, $value );
700
+ }
701
+ return $success;
702
  }
703
  }
inc/classes/profile.class.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 - 2017 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
+ * Class The_SEO_Framework\Profile
28
+ *
29
+ * Outputs Profile fields and saves metadata.
30
+ *
31
+ * @since 3.0.0
32
+ */
33
+ class Profile extends Doing_It_Right {
34
+
35
+ public $profile_settings = array();
36
+
37
+ /**
38
+ * Constructor, loads parent constructor.
39
+ */
40
+ protected function __construct() {
41
+ parent::__construct();
42
+ }
43
+
44
+ /**
45
+ * Outputs profile fields and prepares saving thereof.
46
+ *
47
+ * @since 3.0.0
48
+ */
49
+ protected function init_profile_fields() {
50
+
51
+ //= No need to load anything if the user can't even publish posts.
52
+ if ( ! \current_user_can( 'publish_posts' ) )
53
+ return;
54
+
55
+ $this->profile_settings = (object) array(
56
+ 'keys' => array(
57
+ 'facebook_page' => 'tsf_facebook_page',
58
+ 'twitter_page' => 'tsf_twitter_page',
59
+ ),
60
+ 'sanitation' => array(
61
+ 'facebook_page' => 's_facebook_profile',
62
+ 'twitter_page' => 's_twitter_name',
63
+ ),
64
+ );
65
+
66
+ \add_action( 'show_user_profile', array( $this, '_add_user_author_fields' ), 0, 1 );
67
+ \add_action( 'edit_user_profile', array( $this, '_add_user_author_fields' ), 0, 1 );
68
+
69
+ \add_action( 'personal_options_update', array( $this, '_update_user_settings' ), 10, 1 );
70
+ \add_action( 'edit_user_profile_update', array( $this, '_update_user_settings' ), 10, 1 );
71
+ }
72
+
73
+ /**
74
+ * Outputs user profile fields.
75
+ *
76
+ * @since 3.0.0
77
+ * @access private
78
+ *
79
+ * @param WP_User $user WP_User object.
80
+ */
81
+ public function _add_user_author_fields( \WP_User $user ) {
82
+
83
+ if ( ! $user->has_cap( 'publish_posts' ) )
84
+ return;
85
+
86
+ $fields = array(
87
+ $this->profile_settings->keys['facebook_page'] => (object) array(
88
+ 'name' => \__( 'Facebook profile page', 'autodescription' ),
89
+ 'placeholder' => \_x( 'https://www.facebook.com/YourPersonalProfile', 'Example Facebook Personal URL', 'autodescription' ),
90
+ 'value' => $this->get_user_option( $user->ID, 'facebook_page' ),
91
+ ),
92
+ $this->profile_settings->keys['twitter_page'] => (object) array(
93
+ 'name' => \__( 'Twitter profile', 'autodescription' ),
94
+ 'placeholder' => \_x( '@your-personal-username', 'Twitter @username', 'autodescription' ),
95
+ 'value' => $this->get_user_option( $user->ID, 'twitter_page' ),
96
+ ),
97
+ );
98
+
99
+ $this->get_view( 'profile/author', get_defined_vars() );
100
+ }
101
+
102
+ /**
103
+ * Saves user profile fields.
104
+ *
105
+ * @since 3.0.0
106
+ * @securitycheck 3.0.0 OK. NOTE: Nonces and refer(r)ers have been checked prior
107
+ * to the actions bound to this method.
108
+ * @access private
109
+ *
110
+ * @param int $user_id The user ID.
111
+ */
112
+ public function _update_user_settings( $user_id ) {
113
+
114
+ $le_post = $_POST;
115
+
116
+ if ( empty( $le_post ) )
117
+ return;
118
+
119
+ $user = new \WP_User( $user_id );
120
+
121
+ if ( ! $user->has_cap( 'publish_posts' ) )
122
+ return;
123
+
124
+ $success = array();
125
+ $defaults = $this->get_default_user_data();
126
+
127
+ foreach ( $this->profile_settings->keys as $option => $post_key ) {
128
+ if ( isset( $le_post[ $post_key ] ) ) {
129
+ //= Sanitizes value from $_POST.
130
+ $value = $this->{$this->profile_settings->sanitation[ $option ]}( $le_post[ $post_key ] ) ?: $defaults[ $option ];
131
+
132
+ $success[] = (bool) $this->update_user_option( $user_id, $option, $value );
133
+ }
134
+ }
135
+
136
+ //? Do something with $success?
137
+ }
138
+ }
inc/classes/query.class.php CHANGED
@@ -53,7 +53,7 @@ class Query extends Compat {
53
  */
54
  public function can_cache_query() {
55
 
56
- static $cache = null;
57
 
58
  if ( isset( $cache ) )
59
  return $cache;
@@ -61,7 +61,29 @@ class Query extends Compat {
61
  if ( isset( $GLOBALS['wp_query']->query ) || isset( $GLOBALS['current_screen'] ) )
62
  return $cache = true;
63
 
64
- $this->_doing_it_wrong( __METHOD__, "You've initiated a method that uses queries too early.", '2.9.0' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
  //* Backtrace debugging.
67
  if ( $this->the_seo_framework_debug ) {
@@ -73,8 +95,6 @@ class Query extends Compat {
73
  $_more = false;
74
  }
75
  }
76
-
77
- return false;
78
  }
79
 
80
  /**
@@ -185,6 +205,7 @@ class Query extends Compat {
185
  *
186
  * @since 2.6.0
187
  * @since 2.6.6 Moved from class The_SEO_Framework_Term_Data.
 
188
  *
189
  * @return int Term ID.
190
  */
@@ -203,7 +224,7 @@ class Query extends Compat {
203
  * through global $current_screen. Will output 'Invalid taxonomy' on try.
204
  */
205
  if ( ! empty( $_GET['tag_ID'] ) ) {
206
- //* WordPress 4.5+
207
  $term_id = $_GET['tag_ID'];
208
  } elseif ( ! empty( $_GET['term_id'] ) ) {
209
  //* Older WordPress versions.
@@ -218,6 +239,18 @@ class Query extends Compat {
218
  return $term_id;
219
  }
220
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  /**
222
  * Detects 404.
223
  *
@@ -424,7 +457,7 @@ class Query extends Compat {
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;
@@ -1153,11 +1186,11 @@ class Query extends Compat {
1153
 
1154
  /**
1155
  * Fetches the number of the current page.
1156
- * Fetches global $paged through Query Var to prevent conflicts.
1157
  *
1158
  * @since 2.6.0
1159
  *
1160
- * @return int $paged
1161
  */
1162
  public function paged() {
1163
 
@@ -1210,12 +1243,12 @@ class Query extends Compat {
1210
  * Must always be inside a single array when $value_to_set is set. @see $this->set_query_cache()
1211
  * Must always be separated parameters otherwise.
1212
  * @return mixed : {
1213
- * mixed The cached value if set and $value_to_set is null.
1214
- * null If the query can't be cached yet, or when no value has been set.
1215
- * If $value_to_set is set : {
1216
- * true If the value is being set for the first time.
1217
- * false If the value has been set and $value_to_set is being overwritten.
1218
- * }
1219
  * }
1220
  */
1221
  public function get_query_cache( $key, $value_to_set = null ) {
@@ -1263,8 +1296,8 @@ class Query extends Compat {
1263
  * @param mixed $value_to_set If null, no cache will be set.
1264
  * @param mixed $hash Extra arguments, that will be used to generate an alternative cache key.
1265
  * @return bool : {
1266
- * true If the value is being set for the first time.
1267
- * false If the value has been set and $value_to_set is being overwritten.
1268
  * }
1269
  */
1270
  public function set_query_cache( $key, $value_to_set ) {
53
  */
54
  public function can_cache_query() {
55
 
56
+ static $cache;
57
 
58
  if ( isset( $cache ) )
59
  return $cache;
61
  if ( isset( $GLOBALS['wp_query']->query ) || isset( $GLOBALS['current_screen'] ) )
62
  return $cache = true;
63
 
64
+ $this->do_query_error_notice( __METHOD__ );
65
+
66
+ return false;
67
+ }
68
+
69
+ /**
70
+ * Outputs a doing it wrong notice if an error occurs in the current query.
71
+ *
72
+ * @since 3.0.0
73
+ *
74
+ * @param string $method The original error method, from 2.9.0.
75
+ */
76
+ protected function do_query_error_notice( $method ) {
77
+
78
+ $message = "You've initiated a method that uses queries too early.";
79
+
80
+ $trace = @debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 4 );
81
+ if ( ! empty( $trace[3] ) ) {
82
+ $message .= ' - In file: ' . $trace[3]['file'];
83
+ $message .= ' - On line: ' . $trace[3]['line'];
84
+ }
85
+
86
+ $this->_doing_it_wrong( $method, \esc_html( $message ), '2.9.0' );
87
 
88
  //* Backtrace debugging.
89
  if ( $this->the_seo_framework_debug ) {
95
  $_more = false;
96
  }
97
  }
 
 
98
  }
99
 
100
  /**
205
  *
206
  * @since 2.6.0
207
  * @since 2.6.6 Moved from class The_SEO_Framework_Term_Data.
208
+ * @securitycheck 3.0.0 OK.
209
  *
210
  * @return int Term ID.
211
  */
224
  * through global $current_screen. Will output 'Invalid taxonomy' on try.
225
  */
226
  if ( ! empty( $_GET['tag_ID'] ) ) {
227
+ //* WordPress 4.5+.
228
  $term_id = $_GET['tag_ID'];
229
  } elseif ( ! empty( $_GET['term_id'] ) ) {
230
  //* Older WordPress versions.
239
  return $term_id;
240
  }
241
 
242
+ /**
243
+ * Returns the current taxonomy, if any.
244
+ *
245
+ * @since 3.0.0
246
+ *
247
+ * @return string The queried taxonomy type.
248
+ */
249
+ public function get_current_taxonomy() {
250
+ $_object = \get_queried_object();
251
+ return ! empty( $_object->taxonomy ) ? $_object->taxonomy : '';
252
+ }
253
+
254
  /**
255
  * Detects 404.
256
  *
457
  $pfp = (int) \get_option( 'page_for_posts' );
458
 
459
  if ( $this->has_page_on_front() ) {
460
+ if ( $id && $id === $pfp && false === \is_archive() ) {
461
  $is_blog_page = true;
462
  } elseif ( \is_home() ) {
463
  $is_blog_page = true;
1186
 
1187
  /**
1188
  * Fetches the number of the current page.
1189
+ * Fetches global $paged through Query var to prevent conflicts.
1190
  *
1191
  * @since 2.6.0
1192
  *
1193
+ * @return int $paged Always a positive number.
1194
  */
1195
  public function paged() {
1196
 
1243
  * Must always be inside a single array when $value_to_set is set. @see $this->set_query_cache()
1244
  * Must always be separated parameters otherwise.
1245
  * @return mixed : {
1246
+ * mixed The cached value if set and $value_to_set is null.
1247
+ * null If the query can't be cached yet, or when no value has been set.
1248
+ * If $value_to_set is set : {
1249
+ * true If the value is being set for the first time.
1250
+ * false If the value has been set and $value_to_set is being overwritten.
1251
+ * }
1252
  * }
1253
  */
1254
  public function get_query_cache( $key, $value_to_set = null ) {
1296
  * @param mixed $value_to_set If null, no cache will be set.
1297
  * @param mixed $hash Extra arguments, that will be used to generate an alternative cache key.
1298
  * @return bool : {
1299
+ * true If the value is being set for the first time.
1300
+ * false If the value has been set and $value_to_set is being overwritten.
1301
  * }
1302
  */
1303
  public function set_query_cache( $key, $value_to_set ) {
inc/classes/render.class.php CHANGED
@@ -49,69 +49,70 @@ class Render extends Admin_Init {
49
  }
50
 
51
  /**
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 ) {
61
-
62
- static $description_cache = array();
63
 
64
- if ( isset( $description_cache[ $social ] ) )
65
- return $description_cache[ $social ];
66
 
67
- return $description_cache[ $social ] = $this->generate_description( '', array( 'social' => $social ) );
68
  }
69
 
70
  /**
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 ) {
 
 
85
 
86
- static $url_cache = array();
 
 
 
87
 
88
- if ( empty( $post_id ) )
89
- $post_id = $this->get_the_real_ID();
 
 
 
 
 
 
 
90
 
91
- if ( isset( $url_cache[ $url ][ $post_id ][ $paged ][ $from_option ][ $paged_plural ] ) )
92
- return $url_cache[ $url ][ $post_id ][ $paged ][ $from_option ][ $paged_plural ];
93
 
94
- return $url_cache[ $url ][ $post_id ][ $paged ][ $from_option ][ $paged_plural ] = $this->the_url( $url, array( 'paged' => $paged, 'get_custom_field' => $from_option, 'id' => $post_id, 'paged_plural' => $paged_plural ) );
95
  }
96
 
97
  /**
98
- * Cache home URL in static variable
 
99
  *
100
- * @since 2.5.0
101
- * @since 2.9.0 Now returns subdirectory installations paths too.
102
- * @staticvar array $url_cache
103
  *
104
- * @param bool $force_slash Force slash
105
- * @return string The url
106
  */
107
- public function the_home_url_from_cache( $force_slash = false ) {
108
 
109
- static $url_cache = array();
110
 
111
- if ( isset( $url_cache[ $force_slash ] ) )
112
- return $url_cache[ $force_slash ];
113
 
114
- return $url_cache[ $force_slash ] = $this->the_url( '', array( 'home' => true, 'forceslash' => $force_slash ) );
115
  }
116
 
117
  /**
@@ -124,7 +125,7 @@ class Render extends Admin_Init {
124
  *
125
  * @param string $title The Title to return
126
  * @param string $sep The Title sepeartor
127
- * @param string $seplocation The Title sepeartor location ( accepts 'left' or 'right' )
128
  * @param bool $meta Ignore theme doing it wrong.
129
  * @return string The title
130
  */
@@ -136,12 +137,12 @@ class Render extends Admin_Init {
136
  *
137
  * @since 2.4.0
138
  */
139
- static $setup_cache = null;
140
- static $title_param_cache = null;
141
- static $sep_param_cache = null;
142
- static $seplocation_param_cache = null;
143
 
144
- if ( ! isset( $setup_cache ) ) {
145
  if ( \doing_filter( 'pre_get_document_title' ) || \doing_filter( 'wp_title' ) ) {
146
  $title_param_cache = $title;
147
  $sep_param_cache = $sep;
@@ -314,7 +315,9 @@ class Render extends Admin_Init {
314
  if ( ! $this->use_og_tags() )
315
  return '';
316
 
317
- if ( $type = $this->get_og_type() )
 
 
318
  return '<meta property="og:type" content="' . \esc_attr( $type ) . '" />' . "\r\n";
319
 
320
  return '';
@@ -451,7 +454,7 @@ class Render extends Admin_Init {
451
  *
452
  * @since 1.3.0
453
  * @since 2.9.3 Added filter
454
- * @uses $this->the_url_from_cache()
455
  *
456
  * @return string The Open Graph URL meta tag.
457
  */
@@ -468,11 +471,8 @@ class Render extends Admin_Init {
468
  * @param string $url The canonical/Open Graph URL. Must be escaped.
469
  * @param int $id The current page or term ID.
470
  */
471
- $url = (string) \apply_filters( 'the_seo_framework_ogurl_output', $this->the_url_from_cache(), $this->get_the_real_ID() );
472
 
473
- /**
474
- * @since 2.7.0 Listens to the second filter.
475
- */
476
  if ( $url )
477
  return '<meta property="og:url" content="' . $url . '" />' . "\r\n";
478
  }
@@ -535,7 +535,8 @@ class Render extends Admin_Init {
535
  *
536
  * @since 2.2.2
537
  * @since 2.9.3 No longer has a fallback to twitter:site:id
538
- * @link https://dev.twitter.com/cards/getting-started
 
539
  *
540
  * @return string The Twitter Creator or Twitter Site ID meta tag.
541
  */
@@ -544,15 +545,21 @@ class Render extends Admin_Init {
544
  if ( ! $this->use_twitter_tags() )
545
  return '';
546
 
 
 
547
  /**
548
  * Applies filters 'the_seo_framework_twittercreator_output' : string
 
549
  * @since 2.3.0
550
  * @since 2.7.0 Added output within filter.
 
 
 
551
  */
552
- $creator = (string) \apply_filters( 'the_seo_framework_twittercreator_output', $this->get_option( 'twitter_creator' ), $this->get_the_real_ID() );
553
 
554
- if ( $creator )
555
- return '<meta name="twitter:creator" content="' . \esc_attr( $creator ) . '" />' . "\r\n";
556
 
557
  return '';
558
  }
@@ -646,7 +653,8 @@ class Render extends Admin_Init {
646
  * Renders Facebook Author meta tag.
647
  *
648
  * @since 2.2.2
649
- * @since 2.8.0 : Return empty on og:type 'website' or 'product'
 
650
  *
651
  * @return string The Facebook Author meta tag.
652
  */
@@ -655,18 +663,20 @@ class Render extends Admin_Init {
655
  if ( ! $this->use_facebook_tags() )
656
  return '';
657
 
658
- if ( in_array( $this->get_og_type(), array( 'website', 'product' ), true ) )
659
  return '';
660
 
 
 
661
  /**
662
  * Applies filters 'the_seo_framework_facebookauthor_output' : string
663
  * @since 2.3.0
664
  * @since 2.7.0 Added output within filter.
665
  */
666
- $author = (string) \apply_filters( 'the_seo_framework_facebookauthor_output', $this->get_option( 'facebook_author' ), $this->get_the_real_ID() );
667
 
668
- if ( $author )
669
- return '<meta property="article:author" content="' . \esc_attr( \esc_url_raw( $author, array( 'http', 'https' ) ) ) . '" />' . "\r\n";
670
 
671
  return '';
672
  }
@@ -675,6 +685,7 @@ class Render extends Admin_Init {
675
  * Renders Facebook Publisher meta tag.
676
  *
677
  * @since 2.2.2
 
678
  *
679
  * @return string The Facebook Publisher meta tag.
680
  */
@@ -683,6 +694,9 @@ class Render extends Admin_Init {
683
  if ( ! $this->use_facebook_tags() )
684
  return '';
685
 
 
 
 
686
  /**
687
  * Applies filters 'the_seo_framework_facebookpublisher_output' : string
688
  * @since 2.3.0
@@ -726,40 +740,31 @@ class Render extends Admin_Init {
726
  *
727
  * @since 2.2.2
728
  * @since 2.8.0 Returns empty on product pages.
 
 
 
729
  *
730
  * @return string The Article Publishing Time meta tag.
731
  */
732
  public function article_published_time() {
733
 
734
- //* Don't do anything if it's not a page or post.
735
- if ( false === $this->is_singular() )
736
  return '';
737
 
738
- if ( 'product' === $this->get_og_type() )
739
- return '';
740
 
741
- if ( $this->is_real_front_page() ) {
742
- //* If it's the frontpage, but the option is disabled, don't do anything.
743
- if ( ! $this->get_option( 'home_publish_time' ) )
744
- return '';
745
- } else {
746
- //* If it's a post, but the option is disabled, don't do anything.
747
- if ( $this->is_single() && ! $this->get_option( 'post_publish_time' ) )
748
- return '';
749
 
750
- //* If it's a page, but the option is disabled, don't do anything.
751
- if ( $this->is_page() && ! $this->get_option( 'page_publish_time' ) )
752
- return '';
753
- }
754
-
755
- $id = $this->get_the_real_ID();
756
 
757
  /**
758
  * Applies filters 'the_seo_framework_publishedtime_output' : string
759
  * @since 2.3.0
760
  * @since 2.7.0 Added output within filter.
761
  */
762
- $time = (string) \apply_filters( 'the_seo_framework_publishedtime_output', \get_the_date( 'Y-m-d', $id ), $id );
763
 
764
  if ( $time )
765
  return '<meta property="article:published_time" content="' . \esc_attr( $time ) . '" />' . "\r\n";
@@ -774,40 +779,30 @@ class Render extends Admin_Init {
774
  * @since 2.2.2
775
  * @since 2.7.0 Listens to $this->get_the_real_ID() instead of WordPress Core ID determination.
776
  * @since 2.8.0 Returns empty on product pages.
 
 
777
  *
778
  * @return string The Article Modified Time meta tag, and optionally the Open Graph Updated Time.
779
  */
780
  public function article_modified_time() {
781
 
782
- // Don't do anything if it's not a page or post.
783
- if ( false === $this->is_singular() )
784
  return '';
785
 
786
- if ( 'product' === $this->get_og_type() )
787
- return '';
788
-
789
- if ( $this->is_real_front_page() ) {
790
- //* If it's the frontpage, but the option is disabled, don't do anything.
791
- if ( ! $this->get_option( 'home_modify_time' ) )
792
- return '';
793
- } else {
794
- //* If it's a post, but the option is disabled, don't do anyhting.
795
- if ( $this->is_single() && ! $this->get_option( 'post_modify_time' ) )
796
- return '';
797
 
798
- //* If it's a page, but the option is disabled, don't do anything.
799
- if ( $this->is_page() && ! $this->get_option( 'page_modify_time' ) )
800
- return '';
801
- }
802
 
803
- $id = $this->get_the_real_ID();
 
804
 
805
  /**
806
  * Applies filters 'the_seo_framework_modifiedtime_output' : string
807
  * @since 2.3.0
808
  * @since 2.7.0 Added output within filter.
809
  */
810
- $time = (string) \apply_filters( 'the_seo_framework_modifiedtime_output', \get_post_modified_time( 'Y-m-d', false, $id, false ), $id );
811
 
812
  if ( $time ) {
813
  $output = '<meta property="article:modified_time" content="' . \esc_attr( $time ) . '" />' . "\r\n";
@@ -825,25 +820,13 @@ class Render extends Admin_Init {
825
  * Renders Canonical URL meta tag.
826
  *
827
  * @since 2.0.6
828
- * @uses $this->the_url_from_cache()
 
829
  *
830
  * @return string The Canonical URL meta tag.
831
  */
832
  public function canonical() {
833
 
834
- /**
835
- * Applies filters the_seo_framework_output_canonical : Don't output canonical if false.
836
- * @since 2.4.2
837
- *
838
- * @deprecated
839
- * @since 2.7.0
840
- */
841
- if ( \has_filter( 'the_seo_framework_output_canonical' ) ) {
842
- $this->_deprecated_filter( 'the_seo_framework_output_canonical', '2.7.0', "add_filter( 'the_seo_framework_rel_canonical_output', '__return_empty_string' );" );
843
- if ( true !== \apply_filters( 'the_seo_framework_output_canonical', true, $this->get_the_real_ID() ) )
844
- return '';
845
- }
846
-
847
  /**
848
  * Applies filters 'the_seo_framework_rel_canonical_output' : string
849
  * Changes canonical URL output.
@@ -853,13 +836,13 @@ class Render extends Admin_Init {
853
  * @param string $url The canonical URL. Must be escaped.
854
  * @param int $id The current page or term ID.
855
  */
856
- $url = (string) \apply_filters( 'the_seo_framework_rel_canonical_output', $this->the_url_from_cache(), $this->get_the_real_ID() );
857
 
858
  /**
859
  * @since 2.7.0 Listens to the second filter.
860
  */
861
  if ( $url )
862
- return '<link rel="canonical" href="' . $url . '" />' . "\r\n";
863
 
864
  return '';
865
  }
@@ -907,7 +890,7 @@ class Render extends Admin_Init {
907
  $code = (string) \apply_filters( 'the_seo_framework_googlesite_output', $this->get_option( 'google_verification' ), $this->get_the_real_ID() );
908
 
909
  if ( $code )
910
- return '<meta name="google-site-verification" content="' . \esc_attr( $code ) . '" />' . "\r\n";
911
 
912
  return '';
913
  }
@@ -928,7 +911,7 @@ class Render extends Admin_Init {
928
  $code = (string) \apply_filters( 'the_seo_framework_bingsite_output', $this->get_option( 'bing_verification' ), $this->get_the_real_ID() );
929
 
930
  if ( $code )
931
- return '<meta name="msvalidate.01" content="' . \esc_attr( $code ) . '" />' . "\r\n";
932
 
933
  return '';
934
  }
@@ -949,7 +932,7 @@ class Render extends Admin_Init {
949
  $code = (string) \apply_filters( 'the_seo_framework_yandexsite_output', $this->get_option( 'yandex_verification' ), $this->get_the_real_ID() );
950
 
951
  if ( $code )
952
- return '<meta name="yandex-verification" content="' . \esc_attr( $code ) . '" />' . "\r\n";
953
 
954
  return '';
955
  }
@@ -970,7 +953,7 @@ class Render extends Admin_Init {
970
  $code = (string) \apply_filters( 'the_seo_framework_pintsite_output', $this->get_option( 'pint_verification' ), $this->get_the_real_ID() );
971
 
972
  if ( $code )
973
- return '<meta name="p:domain_verify" content="' . \esc_attr( $code ) . '" />' . "\r\n";
974
 
975
  return '';
976
  }
@@ -998,7 +981,7 @@ class Render extends Admin_Init {
998
  if ( empty( $meta ) )
999
  return '';
1000
 
1001
- return sprintf( '<meta name="robots" content="%s" />' . "\r\n", implode( ',', $meta ) );
1002
  }
1003
 
1004
  /**
@@ -1018,10 +1001,10 @@ class Render extends Admin_Init {
1018
  * Applies filters 'the_seo_framework_shortlink_output' : string
1019
  * @since 2.6.0
1020
  */
1021
- $url = (string) \apply_filters( 'the_seo_framework_shortlink_output', $this->get_shortlink( $id ), $this->get_the_real_ID( $id ) );
1022
 
1023
  if ( $url )
1024
- return sprintf( '<link rel="shortlink" href="%s" />' . "\r\n", $url );
1025
 
1026
  return '';
1027
  }
@@ -1053,10 +1036,10 @@ class Render extends Admin_Init {
1053
  $output = '';
1054
 
1055
  if ( $prev )
1056
- $output .= sprintf( '<link rel="prev" href="%s" />' . "\r\n", $prev );
1057
 
1058
  if ( $next )
1059
- $output .= sprintf( '<link rel="next" href="%s" />' . "\r\n", $next );
1060
 
1061
  return $output;
1062
  }
@@ -1073,7 +1056,7 @@ class Render extends Admin_Init {
1073
  */
1074
  public function get_plugin_indicator( $where = 'before', $timing = 0 ) {
1075
 
1076
- static $run, $_cache = null;
1077
 
1078
  if ( ! isset( $run ) ) {
1079
  /**
@@ -1089,10 +1072,8 @@ class Render extends Admin_Init {
1089
  if ( false === $run )
1090
  return '';
1091
 
1092
- if ( null === $_cache ) {
1093
-
1094
  $_cache = array();
1095
-
1096
  /**
1097
  * Applies filters 'sybre_waaijer_<3'
1098
  *
@@ -1135,6 +1116,48 @@ class Render extends Admin_Init {
1135
  return sprintf( '<!-- %s -->', $output ) . PHP_EOL;
1136
  }
1137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1138
  /**
1139
  * Determines whether we can use Open Graph tags.
1140
  *
49
  }
50
 
51
  /**
52
+ * Caches and returns the current URL.
 
53
  *
54
+ * @since 3.0.0
55
+ * @staticvar string $cache
56
  *
57
+ * @return string The current URL.
58
  */
59
+ public function get_current_canonical_url() {
 
 
60
 
61
+ static $cache;
 
62
 
63
+ return isset( $cache ) ? $cache : $cache = $this->get_canonical_url();
64
  }
65
 
66
  /**
67
+ * Caches and returns the current permalink.
68
+ * This link excludes any pagination. Great for structured data.
69
  *
70
+ * @since 3.0.0
71
+ * @staticvar string $cache
72
+ *
73
+ * @return string The current permalink.
 
 
 
 
 
74
  */
75
+ public function get_current_permalink() {
76
+
77
+ static $cache;
78
 
79
+ return isset( $cache ) ? $cache : $cache = $this->create_canonical_url(
80
+ array( 'id' => $this->get_the_real_ID(), 'is_term' => $this->is_archive() )
81
+ );
82
+ }
83
 
84
+ /**
85
+ * Caches and returns the homepage URL.
86
+ *
87
+ * @since 3.0.0
88
+ * @staticvar string $cache
89
+ *
90
+ * @return string The home URL.
91
+ */
92
+ public function get_homepage_permalink() {
93
 
94
+ static $cache;
 
95
 
96
+ return isset( $cache ) ? $cache : $cache = $this->create_canonical_url( array( 'id' => $this->get_the_front_page_ID() ) );
97
  }
98
 
99
  /**
100
+ * Cache description in static variable
101
+ * Must be called inside the loop
102
  *
103
+ * @since 2.2.2
104
+ * @staticvar array $description_cache
 
105
  *
106
+ * @return string The description
 
107
  */
108
+ public function description_from_cache( $social = false ) {
109
 
110
+ static $description_cache = array();
111
 
112
+ if ( isset( $description_cache[ $social ] ) )
113
+ return $description_cache[ $social ];
114
 
115
+ return $description_cache[ $social ] = $this->generate_description( '', array( 'social' => $social ) );
116
  }
117
 
118
  /**
125
  *
126
  * @param string $title The Title to return
127
  * @param string $sep The Title sepeartor
128
+ * @param string $seplocation The Title sepeartor location, accepts 'left' or 'right'.
129
  * @param bool $meta Ignore theme doing it wrong.
130
  * @return string The title
131
  */
137
  *
138
  * @since 2.4.0
139
  */
140
+ static $setup_cache,
141
+ $title_param_cache,
142
+ $sep_param_cache,
143
+ $seplocation_param_cache;
144
 
145
+ if ( ! $setup_cache ) {
146
  if ( \doing_filter( 'pre_get_document_title' ) || \doing_filter( 'wp_title' ) ) {
147
  $title_param_cache = $title;
148
  $sep_param_cache = $sep;
315
  if ( ! $this->use_og_tags() )
316
  return '';
317
 
318
+ $type = $this->get_og_type();
319
+
320
+ if ( $type )
321
  return '<meta property="og:type" content="' . \esc_attr( $type ) . '" />' . "\r\n";
322
 
323
  return '';
454
  *
455
  * @since 1.3.0
456
  * @since 2.9.3 Added filter
457
+ * @uses $this->get_current_canonical_url()
458
  *
459
  * @return string The Open Graph URL meta tag.
460
  */
471
  * @param string $url The canonical/Open Graph URL. Must be escaped.
472
  * @param int $id The current page or term ID.
473
  */
474
+ $url = (string) \apply_filters( 'the_seo_framework_ogurl_output', $this->get_current_canonical_url(), $this->get_the_real_ID() );
475
 
 
 
 
476
  if ( $url )
477
  return '<meta property="og:url" content="' . $url . '" />' . "\r\n";
478
  }
535
  *
536
  * @since 2.2.2
537
  * @since 2.9.3 No longer has a fallback to twitter:site:id
538
+ * @link https://dev.twitter.com/cards/getting-started
539
+ * @since 3.0.0 Now uses author meta data.
540
  *
541
  * @return string The Twitter Creator or Twitter Site ID meta tag.
542
  */
545
  if ( ! $this->use_twitter_tags() )
546
  return '';
547
 
548
+ $twitter_page = $this->get_current_author_option( 'twitter_page' ) ?: $this->get_option( 'twitter_creator' );
549
+
550
  /**
551
  * Applies filters 'the_seo_framework_twittercreator_output' : string
552
+ *
553
  * @since 2.3.0
554
  * @since 2.7.0 Added output within filter.
555
+ *
556
+ * @param string $twitter_page
557
+ * @param int $id
558
  */
559
+ $twitter_page = (string) \apply_filters( 'the_seo_framework_twittercreator_output', $twitter_page, $this->get_the_real_ID() );
560
 
561
+ if ( $twitter_page )
562
+ return '<meta name="twitter:creator" content="' . \esc_attr( $twitter_page ) . '" />' . "\r\n";
563
 
564
  return '';
565
  }
653
  * Renders Facebook Author meta tag.
654
  *
655
  * @since 2.2.2
656
+ * @since 2.8.0 Returns empty on og:type 'website' or 'product'
657
+ * @since 3.0.0 Fetches Author meta data.
658
  *
659
  * @return string The Facebook Author meta tag.
660
  */
663
  if ( ! $this->use_facebook_tags() )
664
  return '';
665
 
666
+ if ( 'article' !== $this->get_og_type() )
667
  return '';
668
 
669
+ $facebook_page = $this->get_current_author_option( 'facebook_page' ) ?: $this->get_option( 'facebook_author' );
670
+
671
  /**
672
  * Applies filters 'the_seo_framework_facebookauthor_output' : string
673
  * @since 2.3.0
674
  * @since 2.7.0 Added output within filter.
675
  */
676
+ $facebook_page = (string) \apply_filters( 'the_seo_framework_facebookauthor_output', $facebook_page, $this->get_the_real_ID() );
677
 
678
+ if ( $facebook_page )
679
+ return '<meta property="article:author" content="' . \esc_attr( \esc_url_raw( $facebook_page, array( 'http', 'https' ) ) ) . '" />' . "\r\n";
680
 
681
  return '';
682
  }
685
  * Renders Facebook Publisher meta tag.
686
  *
687
  * @since 2.2.2
688
+ * @since 3.0.0 No longer outputs tag when "og:type" isn't 'article'.
689
  *
690
  * @return string The Facebook Publisher meta tag.
691
  */
694
  if ( ! $this->use_facebook_tags() )
695
  return '';
696
 
697
+ if ( 'article' !== $this->get_og_type() )
698
+ return '';
699
+
700
  /**
701
  * Applies filters 'the_seo_framework_facebookpublisher_output' : string
702
  * @since 2.3.0
740
  *
741
  * @since 2.2.2
742
  * @since 2.8.0 Returns empty on product pages.
743
+ * @since 3.0.0: 1. Now checks for 0000 timestamps.
744
+ * 2. Now uses timestamp formats.
745
+ * 3. Now uses GMT time.
746
  *
747
  * @return string The Article Publishing Time meta tag.
748
  */
749
  public function article_published_time() {
750
 
751
+ if ( ! $this->output_published_time() )
 
752
  return '';
753
 
754
+ $id = $this->get_the_real_ID();
 
755
 
756
+ $post = \get_post( $id );
757
+ $post_date_gmt = $post->post_date_gmt;
 
 
 
 
 
 
758
 
759
+ if ( '0000-00-00 00:00:00' === $post_date_gmt )
760
+ return '';
 
 
 
 
761
 
762
  /**
763
  * Applies filters 'the_seo_framework_publishedtime_output' : string
764
  * @since 2.3.0
765
  * @since 2.7.0 Added output within filter.
766
  */
767
+ $time = (string) \apply_filters( 'the_seo_framework_publishedtime_output', $this->gmt2date( $this->get_timestamp_format(), $post_date_gmt ), $id );
768
 
769
  if ( $time )
770
  return '<meta property="article:published_time" content="' . \esc_attr( $time ) . '" />' . "\r\n";
779
  * @since 2.2.2
780
  * @since 2.7.0 Listens to $this->get_the_real_ID() instead of WordPress Core ID determination.
781
  * @since 2.8.0 Returns empty on product pages.
782
+ * @since 3.0.0: 1. Now checks for 0000 timestamps.
783
+ * 2. Now uses timestamp formats.
784
  *
785
  * @return string The Article Modified Time meta tag, and optionally the Open Graph Updated Time.
786
  */
787
  public function article_modified_time() {
788
 
789
+ if ( ! $this->output_modified_time() )
 
790
  return '';
791
 
792
+ $id = $this->get_the_real_ID();
 
 
 
 
 
 
 
 
 
 
793
 
794
+ $post = \get_post( $id );
795
+ $post_modified_gmt = $post->post_modified_gmt;
 
 
796
 
797
+ if ( '0000-00-00 00:00:00' === $post_modified_gmt )
798
+ return '';
799
 
800
  /**
801
  * Applies filters 'the_seo_framework_modifiedtime_output' : string
802
  * @since 2.3.0
803
  * @since 2.7.0 Added output within filter.
804
  */
805
+ $time = (string) \apply_filters( 'the_seo_framework_modifiedtime_output', $this->gmt2date( $this->get_timestamp_format(), $post_modified_gmt ), $id );
806
 
807
  if ( $time ) {
808
  $output = '<meta property="article:modified_time" content="' . \esc_attr( $time ) . '" />' . "\r\n";
820
  * Renders Canonical URL meta tag.
821
  *
822
  * @since 2.0.6
823
+ * @since 3.0.0 Deleted filter `the_seo_framework_output_canonical`.
824
+ * @uses $this->get_current_canonical_url()
825
  *
826
  * @return string The Canonical URL meta tag.
827
  */
828
  public function canonical() {
829
 
 
 
 
 
 
 
 
 
 
 
 
 
 
830
  /**
831
  * Applies filters 'the_seo_framework_rel_canonical_output' : string
832
  * Changes canonical URL output.
836
  * @param string $url The canonical URL. Must be escaped.
837
  * @param int $id The current page or term ID.
838
  */
839
+ $url = (string) \apply_filters( 'the_seo_framework_rel_canonical_output', $this->get_current_canonical_url(), $this->get_the_real_ID() );
840
 
841
  /**
842
  * @since 2.7.0 Listens to the second filter.
843
  */
844
  if ( $url )
845
+ return '<link rel="canonical" href="' . $url . '" />' . PHP_EOL;
846
 
847
  return '';
848
  }
890
  $code = (string) \apply_filters( 'the_seo_framework_googlesite_output', $this->get_option( 'google_verification' ), $this->get_the_real_ID() );
891
 
892
  if ( $code )
893
+ return '<meta name="google-site-verification" content="' . \esc_attr( $code ) . '" />' . PHP_EOL;
894
 
895
  return '';
896
  }
911
  $code = (string) \apply_filters( 'the_seo_framework_bingsite_output', $this->get_option( 'bing_verification' ), $this->get_the_real_ID() );
912
 
913
  if ( $code )
914
+ return '<meta name="msvalidate.01" content="' . \esc_attr( $code ) . '" />' . PHP_EOL;
915
 
916
  return '';
917
  }
932
  $code = (string) \apply_filters( 'the_seo_framework_yandexsite_output', $this->get_option( 'yandex_verification' ), $this->get_the_real_ID() );
933
 
934
  if ( $code )
935
+ return '<meta name="yandex-verification" content="' . \esc_attr( $code ) . '" />' . PHP_EOL;
936
 
937
  return '';
938
  }
953
  $code = (string) \apply_filters( 'the_seo_framework_pintsite_output', $this->get_option( 'pint_verification' ), $this->get_the_real_ID() );
954
 
955
  if ( $code )
956
+ return '<meta name="p:domain_verify" content="' . \esc_attr( $code ) . '" />' . PHP_EOL;
957
 
958
  return '';
959
  }
981
  if ( empty( $meta ) )
982
  return '';
983
 
984
+ return sprintf( '<meta name="robots" content="%s" />' . PHP_EOL, implode( ',', $meta ) );
985
  }
986
 
987
  /**
1001
  * Applies filters 'the_seo_framework_shortlink_output' : string
1002
  * @since 2.6.0
1003
  */
1004
+ $url = (string) \apply_filters( 'the_seo_framework_shortlink_output', $this->get_shortlink( $id ), $id );
1005
 
1006
  if ( $url )
1007
+ return '<link rel="shortlink" href="' . $url . '" />' . PHP_EOL;
1008
 
1009
  return '';
1010
  }
1036
  $output = '';
1037
 
1038
  if ( $prev )
1039
+ $output .= '<link rel="prev" href="' . $prev . '" />' . PHP_EOL;
1040
 
1041
  if ( $next )
1042
+ $output .= '<link rel="next" href="' . $next . '" />' . PHP_EOL;
1043
 
1044
  return $output;
1045
  }
1056
  */
1057
  public function get_plugin_indicator( $where = 'before', $timing = 0 ) {
1058
 
1059
+ static $run, $_cache;
1060
 
1061
  if ( ! isset( $run ) ) {
1062
  /**
1072
  if ( false === $run )
1073
  return '';
1074
 
1075
+ if ( ! isset( $_cache ) ) {
 
1076
  $_cache = array();
 
1077
  /**
1078
  * Applies filters 'sybre_waaijer_<3'
1079
  *
1116
  return sprintf( '<!-- %s -->', $output ) . PHP_EOL;
1117
  }
1118
 
1119
+ /**
1120
+ * Determines if modified time should be used in the current query.
1121
+ *
1122
+ * @since 3.0.0
1123
+ * @staticvar bool $cache
1124
+ *
1125
+ * @return bool
1126
+ */
1127
+ public function output_modified_time() {
1128
+
1129
+ static $cache;
1130
+
1131
+ if ( isset( $cache ) )
1132
+ return $cache;
1133
+
1134
+ if ( 'article' !== $this->get_og_type() )
1135
+ return $cache = false;
1136
+
1137
+ return $cache = (bool) $this->get_option( 'post_modify_time' );
1138
+ }
1139
+
1140
+ /**
1141
+ * Determines if published time should be used in the current query.
1142
+ *
1143
+ * @since 3.0.0
1144
+ * @staticvar bool $cache
1145
+ *
1146
+ * @return bool
1147
+ */
1148
+ public function output_published_time() {
1149
+
1150
+ static $cache;
1151
+
1152
+ if ( isset( $cache ) )
1153
+ return $cache;
1154
+
1155
+ if ( 'article' !== $this->get_og_type() )
1156
+ return $cache = false;
1157
+
1158
+ return $cache = (bool) $this->get_option( 'post_publish_time' );
1159
+ }
1160
+
1161
  /**
1162
  * Determines whether we can use Open Graph tags.
1163
  *
inc/classes/sanitize.class.php CHANGED
@@ -46,6 +46,7 @@ class Sanitize extends Admin_Pages {
46
  * Never run a sensitive function when it's returning false. This means no nonce can be verified.
47
  *
48
  * @since 2.7.0
 
49
  * @staticvar bool $verified.
50
  *
51
  * @return bool True if verified and matches. False if can't verify.
@@ -197,6 +198,9 @@ class Sanitize extends Admin_Pages {
197
  'alter_search_query',
198
  'alter_archive_query',
199
 
 
 
 
200
  'cache_meta_description',
201
  'cache_meta_schema',
202
  'cache_sitemap',
@@ -211,7 +215,6 @@ class Sanitize extends Admin_Pages {
211
  'description_additions',
212
  'description_blogname',
213
 
214
- 'noodp',
215
  'noydir',
216
 
217
  'category_noindex',
@@ -263,13 +266,6 @@ class Sanitize extends Admin_Pages {
263
  'post_publish_time',
264
  'post_modify_time',
265
 
266
- 'page_publish_time',
267
- 'page_modify_time',
268
-
269
- 'home_modify_time',
270
- 'home_publish_time',
271
-
272
- 'noodp',
273
  'noydir',
274
 
275
  'knowledge_logo',
@@ -282,13 +278,11 @@ class Sanitize extends Admin_Pages {
282
  'source_the_feed',
283
 
284
  'ld_json_searchbox',
285
- 'ld_json_sitename',
286
  'ld_json_breadcrumbs',
287
 
288
  'sitemaps_output',
289
  'sitemaps_robots',
290
  'sitemaps_modified',
291
- 'sitemap_timestamps',
292
  'sitemap_styles',
293
  'sitemap_logo',
294
  )
@@ -304,6 +298,14 @@ class Sanitize extends Admin_Pages {
304
  )
305
  );
306
 
 
 
 
 
 
 
 
 
307
  /*
308
  $this->add_option_filter(
309
  's_no_html',
@@ -333,15 +335,12 @@ class Sanitize extends Admin_Pages {
333
  's_url',
334
  $this->settings_field,
335
  array(
336
- 'facebook_publisher',
337
- 'facebook_author',
338
-
339
  'knowledge_facebook',
340
  'knowledge_twitter',
341
  'knowledge_gplus',
342
  'knowledge_instagram',
343
  'knowledge_youtube',
344
- // 'knowledge_myspace',
345
  'knowledge_pinterest',
346
  'knowledge_soundcloud',
347
  'knowledge_tumblr',
@@ -359,6 +358,15 @@ class Sanitize extends Admin_Pages {
359
  )
360
  );
361
 
 
 
 
 
 
 
 
 
 
362
  $this->add_option_filter(
363
  's_twitter_name',
364
  $this->settings_field,
@@ -549,25 +557,25 @@ class Sanitize extends Admin_Pages {
549
  's_knowledge_type' => array( $this, 's_knowledge_type' ),
550
  's_alter_query_type' => array( $this, 's_alter_query_type' ),
551
  's_one_zero' => array( $this, 's_one_zero' ),
 
552
  's_no_html' => array( $this, 's_no_html' ),
553
  's_no_html_space' => array( $this, 's_no_html_space' ),
554
  's_absint' => array( $this, 's_absint' ),
555
  's_safe_html' => array( $this, 's_safe_html' ),
556
  's_url' => array( $this, 's_url' ),
557
  's_url_query' => array( $this, 's_url_query' ),
 
558
  's_twitter_name' => array( $this, 's_twitter_name' ),
559
  's_twitter_card' => array( $this, 's_twitter_card' ),
560
  's_canonical_scheme' => array( $this, 's_canonical_scheme' ),
561
  );
562
 
563
  /**
564
- * Filter the available sanitization filter types.
565
  *
566
  * @since 2.2.2
567
- *
568
- * Applies filters the_seo_framework_available_sanitizer_filters : array
569
- * @param array $default_filters Array with keys of sanitization types,
570
- * and values of the filter function name as a callback
571
  */
572
  return (array) \apply_filters( 'the_seo_framework_available_sanitizer_filters', $default_filters );
573
  }
@@ -950,6 +958,21 @@ class Sanitize extends Admin_Pages {
950
  return (int) (bool) $new_value;
951
  }
952
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
953
  /**
954
  * Returns a positive integer value.
955
  *
@@ -996,7 +1019,6 @@ class Sanitize extends Admin_Pages {
996
  * @since 2.8.0 Method is now public.
997
  *
998
  * @param string $new_value String, a URL, possibly unsafe.
999
- * @param boolean/sphaghetti $flush Whether to flush to transient.
1000
  * @return string String a safe URL without Query Arguments.
1001
  */
1002
  public function s_url( $new_value ) {
@@ -1056,6 +1078,8 @@ class Sanitize extends Admin_Pages {
1056
  *
1057
  * @since 2.2.2
1058
  * @since 2.8.0 Method is now public.
 
 
1059
  *
1060
  * @param string $new_value String with potentially wrong Twitter username.
1061
  * @return string String with 'correct' Twitter username
@@ -1063,23 +1087,39 @@ class Sanitize extends Admin_Pages {
1063
  public function s_twitter_name( $new_value ) {
1064
 
1065
  if ( empty( $new_value ) )
1066
- return (string) $new_value;
1067
 
1068
  $profile = trim( strip_tags( $new_value ) );
 
 
1069
 
1070
- if ( 'http' === substr( $profile, 0, 4 ) ) {
1071
- $parsed_url = \wp_parse_url( $profile );
1072
- $path = isset( $parsed_url['path'] ) ? str_replace( '/', '', $parsed_url['path'] ) : '';
1073
- $profile = $path ? '@' . $path : '';
1074
 
1075
- return (string) $profile;
1076
- }
1077
 
1078
- if ( '@' !== substr( $profile, 0, 1 ) ) {
1079
- $profile = '@' . $profile;
1080
- }
 
 
 
 
 
 
 
 
1081
 
1082
- return (string) $profile;
 
 
 
 
 
 
 
 
1083
  }
1084
 
1085
  /**
@@ -1180,7 +1220,7 @@ class Sanitize extends Admin_Pages {
1180
  $url = $filter['url'];
1181
  $scheme = $filter['scheme'];
1182
  } else {
1183
- $url = $this->the_home_url_from_cache( true ) . ltrim( $path, ' /' );
1184
  $scheme = $this->is_ssl() ? 'https' : 'http';
1185
  }
1186
 
@@ -1192,8 +1232,10 @@ class Sanitize extends Admin_Pages {
1192
  endif;
1193
 
1194
  /**
1195
- * Applies filters the_seo_framework_301_noqueries : bool remove query args from 301
 
1196
  * @since 2.5.0
 
1197
  */
1198
  $noqueries = (bool) \apply_filters( 'the_seo_framework_301_noqueries', true );
1199
 
@@ -1207,7 +1249,7 @@ class Sanitize extends Admin_Pages {
1207
  /**
1208
  * Remove query args
1209
  *
1210
- * @see The_SEO_Framework_Sanitize::s_url
1211
  * @since 2.2.4
1212
  */
1213
  $new_value = $this->s_url( $url );
46
  * Never run a sensitive function when it's returning false. This means no nonce can be verified.
47
  *
48
  * @since 2.7.0
49
+ * @securitycheck 3.0.0 OK.
50
  * @staticvar bool $verified.
51
  *
52
  * @return bool True if verified and matches. False if can't verify.
198
  'alter_search_query',
199
  'alter_archive_query',
200
 
201
+ 'display_pixel_counter',
202
+ 'display_character_counter',
203
+
204
  'cache_meta_description',
205
  'cache_meta_schema',
206
  'cache_sitemap',
215
  'description_additions',
216
  'description_blogname',
217
 
 
218
  'noydir',
219
 
220
  'category_noindex',
266
  'post_publish_time',
267
  'post_modify_time',
268
 
 
 
 
 
 
 
 
269
  'noydir',
270
 
271
  'knowledge_logo',
278
  'source_the_feed',
279
 
280
  'ld_json_searchbox',
 
281
  'ld_json_breadcrumbs',
282
 
283
  'sitemaps_output',
284
  'sitemaps_robots',
285
  'sitemaps_modified',
 
286
  'sitemap_styles',
287
  'sitemap_logo',
288
  )
298
  )
299
  );
300
 
301
+ $this->add_option_filter(
302
+ 's_numeric_string',
303
+ $this->settings_field,
304
+ array(
305
+ 'timestamps_format',
306
+ )
307
+ );
308
+
309
  /*
310
  $this->add_option_filter(
311
  's_no_html',
335
  's_url',
336
  $this->settings_field,
337
  array(
 
 
 
338
  'knowledge_facebook',
339
  'knowledge_twitter',
340
  'knowledge_gplus',
341
  'knowledge_instagram',
342
  'knowledge_youtube',
343
+ // 'knowledge_myspace',
344
  'knowledge_pinterest',
345
  'knowledge_soundcloud',
346
  'knowledge_tumblr',
358
  )
359
  );
360
 
361
+ $this->add_option_filter(
362
+ 's_facebook_profile',
363
+ $this->settings_field,
364
+ array(
365
+ 'facebook_publisher',
366
+ 'facebook_author',
367
+ )
368
+ );
369
+
370
  $this->add_option_filter(
371
  's_twitter_name',
372
  $this->settings_field,
557
  's_knowledge_type' => array( $this, 's_knowledge_type' ),
558
  's_alter_query_type' => array( $this, 's_alter_query_type' ),
559
  's_one_zero' => array( $this, 's_one_zero' ),
560
+ 's_numeric_string' => array( $this, 's_numeric_string' ),
561
  's_no_html' => array( $this, 's_no_html' ),
562
  's_no_html_space' => array( $this, 's_no_html_space' ),
563
  's_absint' => array( $this, 's_absint' ),
564
  's_safe_html' => array( $this, 's_safe_html' ),
565
  's_url' => array( $this, 's_url' ),
566
  's_url_query' => array( $this, 's_url_query' ),
567
+ 's_facebook_profile' => array( $this, 's_facebook_profile' ),
568
  's_twitter_name' => array( $this, 's_twitter_name' ),
569
  's_twitter_card' => array( $this, 's_twitter_card' ),
570
  's_canonical_scheme' => array( $this, 's_canonical_scheme' ),
571
  );
572
 
573
  /**
574
+ * Applies filters the_seo_framework_available_sanitizer_filters
575
  *
576
  * @since 2.2.2
577
+ * @param array $default_filters Array with keys of sanitization types,
578
+ * and values of the filter function name as a callback
 
 
579
  */
580
  return (array) \apply_filters( 'the_seo_framework_available_sanitizer_filters', $default_filters );
581
  }
958
  return (int) (bool) $new_value;
959
  }
960
 
961
+ /**
962
+ * Returns a numeric string, like '0', '1', '2'.
963
+ *
964
+ * Uses double casting. First, we cast to integer, then to string.
965
+ * Rounds floats down. Converts non-numeric inputs to '0'.
966
+ *
967
+ * @since 3.0.0
968
+ *
969
+ * @param mixed $new_value Should ideally be an integer.
970
+ * @return string An integer as string.
971
+ */
972
+ public function s_numeric_string( $new_value ) {
973
+ return (string) (int) $new_value;
974
+ }
975
+
976
  /**
977
  * Returns a positive integer value.
978
  *
1019
  * @since 2.8.0 Method is now public.
1020
  *
1021
  * @param string $new_value String, a URL, possibly unsafe.
 
1022
  * @return string String a safe URL without Query Arguments.
1023
  */
1024
  public function s_url( $new_value ) {
1078
  *
1079
  * @since 2.2.2
1080
  * @since 2.8.0 Method is now public.
1081
+ * @since 3.0.0: 1. Now removes '@' from the URL path.
1082
+ * 2. Now removes spaces and tabs.
1083
  *
1084
  * @param string $new_value String with potentially wrong Twitter username.
1085
  * @return string String with 'correct' Twitter username
1087
  public function s_twitter_name( $new_value ) {
1088
 
1089
  if ( empty( $new_value ) )
1090
+ return '';
1091
 
1092
  $profile = trim( strip_tags( $new_value ) );
1093
+ $profile = $this->s_relative_url( $profile );
1094
+ $profile = rtrim( $profile, ' /' );
1095
 
1096
+ if ( '@' !== substr( $profile, 0, 1 ) )
1097
+ $profile = '@' . $profile;
 
 
1098
 
1099
+ return str_replace( array( ' ', "\t" ), '', $profile );
1100
+ }
1101
 
1102
+ /**
1103
+ * Parses Facebook profile URLs. Exchanges URLs for Facebook's.
1104
+ *
1105
+ * @since 2.2.2
1106
+ * @since 2.8.0 Method is now public.
1107
+ * @since 3.0.0 Now removed '@' from the URL path.
1108
+ *
1109
+ * @param string $new_value String with potentially wrong Twitter username.
1110
+ * @return string String with 'correct' Twitter username
1111
+ */
1112
+ public function s_facebook_profile( $new_value ) {
1113
 
1114
+ if ( empty( $new_value ) )
1115
+ return '';
1116
+
1117
+ $link = trim( strip_tags( $new_value ) );
1118
+
1119
+ $link = 'https://www.facebook.com/' . $this->s_relative_url( $link );
1120
+ $link = rtrim( $link, ' /' );
1121
+
1122
+ return $this->s_url( $link );
1123
  }
1124
 
1125
  /**
1220
  $url = $filter['url'];
1221
  $scheme = $filter['scheme'];
1222
  } else {
1223
+ $url = \trailingslashit( $this->get_homepage_permalink() ) . ltrim( $path, ' /' );
1224
  $scheme = $this->is_ssl() ? 'https' : 'http';
1225
  }
1226
 
1232
  endif;
1233
 
1234
  /**
1235
+ * Applies filters 'the_seo_framework_301_noqueries'
1236
+ *
1237
  * @since 2.5.0
1238
+ * @param bool $noqueries
1239
  */
1240
  $noqueries = (bool) \apply_filters( 'the_seo_framework_301_noqueries', true );
1241
 
1249
  /**
1250
  * Remove query args
1251
  *
1252
+ * @see The_SEO_Framework\Sanitize::s_url
1253
  * @since 2.2.4
1254
  */
1255
  $new_value = $this->s_url( $url );
inc/classes/site-options.class.php CHANGED
@@ -70,6 +70,7 @@ class Site_Options extends Sanitize {
70
  $this->o_plugin_updated = 'updated_' . THE_SEO_FRAMEWORK_DB_VERSION;
71
  $this->seo_settings_page_slug = 'theseoframework-settings';
72
 
 
73
  }
74
 
75
  /**
@@ -120,9 +121,15 @@ class Site_Options extends Sanitize {
120
  'display_seo_bar_tables' => 1, // SEO Bar post-list tables.
121
  'display_seo_bar_metabox' => 0, // SEO Bar post SEO Settings.
122
 
 
 
 
123
  // General. Canonical.
124
  'canonical_scheme' => 'automatic', // Canonical URL scheme.
125
 
 
 
 
126
  // Title.
127
  'title_seperator' => 'pipe', // Title separator (note: TYPO), dropdown
128
  'title_location' => $titleloc, // Title separation location
@@ -136,7 +143,6 @@ class Site_Options extends Sanitize {
136
  // 'description_custom' => '', // Custom prefix TODO
137
 
138
  // Robots directory.
139
- 'noodp' => 1, // Site noopd robots settings
140
  'noydir' => 1, // Site noydir robots settings
141
 
142
  // Robots index.
@@ -201,12 +207,6 @@ class Site_Options extends Sanitize {
201
  'post_publish_time' => 1, // Article Published Time
202
  'post_modify_time' => 1, // Article Modified Time
203
 
204
- 'page_publish_time' => 0, // Article Published Time
205
- 'page_modify_time' => 0, // Article Modified Time
206
-
207
- 'home_publish_time' => 0, // Article Modified Time
208
- 'home_modify_time' => 0, // Article Modified Time
209
-
210
  // Twitter.
211
  'twitter_card' => 'summary_large_image', // Twitter Card layout. If no twitter:image image is found, it'll change to 'summary', radio
212
  'twitter_site' => '', // Twitter business @username
@@ -233,12 +233,12 @@ class Site_Options extends Sanitize {
233
  'knowledge_type' => 'organization', // Organization or Person, dropdown
234
 
235
  // Knowledge business. https://developers.google.com/structured-data/customize/logos
236
- 'knowledge_logo' => 1, // Fetch logo from WP Favicon
237
  'knowledge_name' => '', // Person or Organization name
238
 
239
  // Knowledge Logo image
240
- // 'knowledge_logo_url' => '', // TODO
241
- // 'knowledge_logo_id' => 0, // TODO
242
 
243
  // Knowledge sameas locations
244
  'knowledge_facebook' => '', // Facebook Account
@@ -255,7 +255,6 @@ class Site_Options extends Sanitize {
255
  // Sitemaps.
256
  'sitemaps_output' => 1, // Output of sitemaps
257
  'sitemaps_modified' => 1, // Add sitemaps modified time
258
- 'sitemap_timestamps' => '1', // Sitemaps modified time format, dropdown
259
  'sitemaps_robots' => 1, // Add sitemaps location to robots.txt
260
  'ping_google' => 1, // Ping Google
261
  'ping_bing' => 1, // Ping Bing
@@ -271,7 +270,6 @@ class Site_Options extends Sanitize {
271
 
272
  // Schema
273
  'ld_json_searchbox' => 1, // LD+Json Sitelinks Searchbox
274
- 'ld_json_sitename' => 1, // LD+Json Sitename
275
  'ld_json_breadcrumbs' => 1, // LD+Json Breadcrumbs
276
 
277
  // Cache.
@@ -310,6 +308,7 @@ class Site_Options extends Sanitize {
310
  * Updates special hidden values to default on settings save.
311
  *
312
  * @since 2.6.0
 
313
  * @TODO REMOVE THIS and use a better upgrade handler. Source for code debt.
314
  */
315
  protected function update_hidden_options_to_default() {
@@ -354,7 +353,7 @@ class Site_Options extends Sanitize {
354
  return;
355
 
356
  //* If current user isn't allowed to update options, don't do anything.
357
- if ( ! \current_user_can( $this->settings_capability() ) )
358
  return;
359
 
360
  $updated = false;
@@ -410,7 +409,7 @@ class Site_Options extends Sanitize {
410
  * Only checks for extra parameters. Then redirects further to only output
411
  * notice. User capability is checked beforehand.
412
  */
413
- if ( \current_user_can( $this->settings_capability() ) && $this->is_seo_settings_page( false ) ) {
414
  //* Redirect to current page if on options page to correct option values. Once.
415
  if ( ! isset( $_REQUEST['tsf-settings-updated'] ) || 'true' !== $_REQUEST['tsf-settings-updated'] )
416
  $this->admin_redirect( $this->seo_settings_page_slug, array( 'tsf-settings-updated' => 'true' ) );
@@ -423,7 +422,7 @@ class Site_Options extends Sanitize {
423
  $this->init_admin_scripts();
424
 
425
  //* Output notice.
426
- \add_action( 'admin_notices', array( $this, 'site_updated_plugin_notice' ) );
427
 
428
  }
429
 
@@ -434,7 +433,7 @@ class Site_Options extends Sanitize {
434
  *
435
  * @access private
436
  */
437
- public function site_updated_plugin_notice() {
438
 
439
  $settings_url = $this->seo_settings_page_url();
440
  $link = sprintf( '<a href="%s" title="%s" target="_self">%s</a>', $settings_url, \esc_attr__( 'SEO Settings', 'autodescription' ), \esc_html__( 'here', 'autodescription' ) );
@@ -661,7 +660,7 @@ class Site_Options extends Sanitize {
661
  * These can only be set when one has access to the Settings Page or database.
662
  * Also checks for capabilities.
663
  */
664
- if ( ! \current_user_can( $this->settings_capability() ) || ! $this->is_seo_settings_page( false ) )
665
  return;
666
 
667
  if ( $this->get_option( 'tsf-settings-reset', false ) ) {
@@ -826,118 +825,6 @@ class Site_Options extends Sanitize {
826
  return $warned_cache[ $key ];
827
  }
828
 
829
- /**
830
- * Fetches user SEO user meta data by name.
831
- * Caches all meta data per $user_id.
832
- *
833
- * @since 2.7.0
834
- * @staticvar array $options_cache
835
- *
836
- * @param int $user_id The user ID. When empty, it will try to fetch the current user.
837
- * @param string $option The option name.
838
- * @param mixed $default The default value to return when the data doesn't exist.
839
- * @return mixed The metadata value.
840
- */
841
- public function get_user_option( $user_id = 0, $option, $default = null ) {
842
-
843
- if ( ! $option )
844
- return null;
845
-
846
- if ( empty( $user_id ) )
847
- $user_id = $this->get_user_id();
848
-
849
- if ( ! $user_id )
850
- return null;
851
-
852
- static $options_cache = array();
853
-
854
- if ( isset( $options_cache[ $user_id ][ $option ] ) )
855
- return $options_cache[ $user_id ][ $option ];
856
-
857
- $usermeta = $this->get_user_meta( $user_id );
858
-
859
- return $options_cache[ $user_id ][ $option ] = isset( $usermeta[ $option ] ) ? $usermeta[ $option ] : $default;
860
- }
861
-
862
- /**
863
- * Sets up user ID and returns it if user is found.
864
- * To be used in AJAX, back-end and front-end.
865
- *
866
- * @since 2.7.0
867
- *
868
- * @return int $user_id : 0 if user is not found.
869
- */
870
- public function get_user_id() {
871
-
872
- static $user_id = null;
873
-
874
- if ( isset( $user_id ) )
875
- return $user_id;
876
-
877
- $user = \wp_get_current_user();
878
-
879
- return $user_id = $user->exists() ? (int) $user->ID : 0;
880
- }
881
-
882
- /**
883
- * Fetches The SEO Framework usermeta.
884
- *
885
- * @since 2.7.0
886
- * @since 2.8.0 Always returns array, even if no value is assigned.
887
- * @staticvar array $usermeta_cache
888
- *
889
- * @param int $user_id The user ID.
890
- * @param string $key The user metadata key. Leave empty to fetch all data.
891
- * @param bool $use_cache Whether to store and use options from cache.
892
- * @return array The user SEO meta data.
893
- */
894
- public function get_user_meta( $user_id, $key = THE_SEO_FRAMEWORK_USER_OPTIONS, $use_cache = true ) {
895
-
896
- if ( false === $use_cache )
897
- return ( $meta = \get_user_meta( $user_id, $key, true ) ) && is_array( $meta ) ? $meta : array();
898
-
899
- static $usermeta_cache = array();
900
-
901
- if ( isset( $usermeta_cache[ $user_id ][ $key ] ) )
902
- return $usermeta_cache[ $user_id ][ $key ];
903
-
904
- return $usermeta_cache[ $user_id ][ $key ] = ( $meta = \get_user_meta( $user_id, $key, true ) ) && is_array( $meta ) ? $meta : array();
905
- }
906
-
907
- /**
908
- * Updates user SEO option.
909
- *
910
- * @since 2.7.0
911
- * @since 2.8.0 New users now get a new array assigned.
912
- *
913
- * @param int $user_id The user ID.
914
- * @param string $option The user's SEO metadata option.
915
- * @param mixed $value The escaped option value.
916
- * @return bool True on success. False on failure.
917
- */
918
- public function update_user_option( $user_id = 0, $option, $value ) {
919
-
920
- if ( ! $option )
921
- return false;
922
-
923
- if ( empty( $user_id ) )
924
- $user_id = $this->get_user_id();
925
-
926
- if ( empty( $user_id ) )
927
- return false;
928
-
929
- $meta = $this->get_user_meta( $user_id, THE_SEO_FRAMEWORK_USER_OPTIONS, false );
930
-
931
- /**
932
- * @since 2.8.0 initializes new array on empty values.
933
- */
934
- is_array( $meta ) or $meta = array();
935
-
936
- $meta[ $option ] = $value;
937
-
938
- return \update_user_meta( $user_id, THE_SEO_FRAMEWORK_USER_OPTIONS, $meta );
939
- }
940
-
941
  /**
942
  * Returns Facebook locales array values.
943
  *
70
  $this->o_plugin_updated = 'updated_' . THE_SEO_FRAMEWORK_DB_VERSION;
71
  $this->seo_settings_page_slug = 'theseoframework-settings';
72
 
73
+ \add_filter( "option_page_capability_{$this->settings_field}", array( $this, 'get_settings_capability' ) );
74
  }
75
 
76
  /**
121
  'display_seo_bar_tables' => 1, // SEO Bar post-list tables.
122
  'display_seo_bar_metabox' => 0, // SEO Bar post SEO Settings.
123
 
124
+ 'display_pixel_counter' => 1, // Pixel counter.
125
+ 'display_character_counter' => 0, // Character counter.
126
+
127
  // General. Canonical.
128
  'canonical_scheme' => 'automatic', // Canonical URL scheme.
129
 
130
+ // General. Timestamps.
131
+ 'timestamps_format' => '1', // Timestamp format, numeric string
132
+
133
  // Title.
134
  'title_seperator' => 'pipe', // Title separator (note: TYPO), dropdown
135
  'title_location' => $titleloc, // Title separation location
143
  // 'description_custom' => '', // Custom prefix TODO
144
 
145
  // Robots directory.
 
146
  'noydir' => 1, // Site noydir robots settings
147
 
148
  // Robots index.
207
  'post_publish_time' => 1, // Article Published Time
208
  'post_modify_time' => 1, // Article Modified Time
209
 
 
 
 
 
 
 
210
  // Twitter.
211
  'twitter_card' => 'summary_large_image', // Twitter Card layout. If no twitter:image image is found, it'll change to 'summary', radio
212
  'twitter_site' => '', // Twitter business @username
233
  'knowledge_type' => 'organization', // Organization or Person, dropdown
234
 
235
  // Knowledge business. https://developers.google.com/structured-data/customize/logos
236
+ 'knowledge_logo' => 1, // Use Knowledge Logo from anywhere.
237
  'knowledge_name' => '', // Person or Organization name
238
 
239
  // Knowledge Logo image
240
+ 'knowledge_logo_url' => '',
241
+ 'knowledge_logo_id' => 0,
242
 
243
  // Knowledge sameas locations
244
  'knowledge_facebook' => '', // Facebook Account
255
  // Sitemaps.
256
  'sitemaps_output' => 1, // Output of sitemaps
257
  'sitemaps_modified' => 1, // Add sitemaps modified time
 
258
  'sitemaps_robots' => 1, // Add sitemaps location to robots.txt
259
  'ping_google' => 1, // Ping Google
260
  'ping_bing' => 1, // Ping Bing
270
 
271
  // Schema
272
  'ld_json_searchbox' => 1, // LD+Json Sitelinks Searchbox
 
273
  'ld_json_breadcrumbs' => 1, // LD+Json Breadcrumbs
274
 
275
  // Cache.
308
  * Updates special hidden values to default on settings save.
309
  *
310
  * @since 2.6.0
311
+ * @securitycheck 3.0.0 OK.
312
  * @TODO REMOVE THIS and use a better upgrade handler. Source for code debt.
313
  */
314
  protected function update_hidden_options_to_default() {
353
  return;
354
 
355
  //* If current user isn't allowed to update options, don't do anything.
356
+ if ( ! $this->can_access_settings() )
357
  return;
358
 
359
  $updated = false;
409
  * Only checks for extra parameters. Then redirects further to only output
410
  * notice. User capability is checked beforehand.
411
  */
412
+ if ( $this->can_access_settings() && $this->is_seo_settings_page( false ) ) {
413
  //* Redirect to current page if on options page to correct option values. Once.
414
  if ( ! isset( $_REQUEST['tsf-settings-updated'] ) || 'true' !== $_REQUEST['tsf-settings-updated'] )
415
  $this->admin_redirect( $this->seo_settings_page_slug, array( 'tsf-settings-updated' => 'true' ) );
422
  $this->init_admin_scripts();
423
 
424
  //* Output notice.
425
+ \add_action( 'admin_notices', array( $this, 'do_settings_updated_notice' ) );
426
 
427
  }
428
 
433
  *
434
  * @access private
435
  */
436
+ public function do_settings_updated_notice() {
437
 
438
  $settings_url = $this->seo_settings_page_url();
439
  $link = sprintf( '<a href="%s" title="%s" target="_self">%s</a>', $settings_url, \esc_attr__( 'SEO Settings', 'autodescription' ), \esc_html__( 'here', 'autodescription' ) );
660
  * These can only be set when one has access to the Settings Page or database.
661
  * Also checks for capabilities.
662
  */
663
+ if ( ! $this->can_access_settings() || ! $this->is_seo_settings_page( false ) )
664
  return;
665
 
666
  if ( $this->get_option( 'tsf-settings-reset', false ) ) {
825
  return $warned_cache[ $key ];
826
  }
827
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
828
  /**
829
  * Returns Facebook locales array values.
830
  *
inc/classes/sitemaps.class.php CHANGED
@@ -307,7 +307,7 @@ class Sitemaps extends Metaboxes {
307
  echo "\n" . '<!-- Site estimated peak usage: ' . number_format( memory_get_peak_usage() / 1024 / 1024, 3 ) . ' MB -->';
308
  echo "\n" . '<!-- System estimated peak usage: ' . number_format( memory_get_peak_usage( true ) / 1024 / 1024, 3 ) . ' MB -->';
309
  echo "\n" . '<!-- Freed memory prior to generation: ' . number_format( $this->clean_up_globals_for_sitemap( true ) / 1024, 3 ) . ' kB -->';
310
- echo "\n" . '<!-- Sitemap generation time: ' . ( number_format( microtime( true ) - $timer_start, 6 ) ) . ' seconds -->';
311
  }
312
  }
313
 
@@ -396,6 +396,8 @@ class Sitemaps extends Metaboxes {
396
  * Returns the stylesheet XSL location URL.
397
  *
398
  * @since 2.8.0
 
 
399
  * @global object $wp_rewrite
400
  *
401
  * @return string URL location of the XSL stylesheet. Unescaped.
@@ -403,18 +405,15 @@ class Sitemaps extends Metaboxes {
403
  public function get_sitemap_xsl_url() {
404
  global $wp_rewrite;
405
 
406
- $home = \trailingslashit( $this->set_url_scheme( $this->the_home_url_from_cache() ) );
407
- /** Figure out if this is helpful...
408
- if ( ! $this->is_subdirectory_installation() ) {
409
- //= 1. $home = \trailingslashit( $this->set_url_scheme( $this->get_home_host() ) );
410
 
411
- //= 2.:
412
- $_path = $this->set_url_scheme( $home, 'relative' );
413
- if ( false !== ( $_pos = strrpos( $home, $_path ) ) ) {
414
- $home = \trailingslashit( substr_replace( $home, '', $_pos, strlen( $_path ) ) );
415
- }
416
- }
417
- */
418
 
419
  if ( $wp_rewrite->using_index_permalinks() ) {
420
  $loc = $home . 'index.php/sitemap.xsl';
@@ -424,6 +423,9 @@ class Sitemaps extends Metaboxes {
424
  $loc = $home . '?the_seo_framework_sitemap=xsl';
425
  }
426
 
 
 
 
427
  return $loc;
428
  }
429
 
@@ -431,6 +433,8 @@ class Sitemaps extends Metaboxes {
431
  * Returns the sitemap XML location URL.
432
  *
433
  * @since 2.9.2
 
 
434
  * @global object $wp_rewrite
435
  *
436
  * @return string URL location of the XML sitemap. Unescaped.
@@ -438,18 +442,18 @@ class Sitemaps extends Metaboxes {
438
  public function get_sitemap_xml_url() {
439
  global $wp_rewrite;
440
 
441
- $home = \trailingslashit( $this->set_url_scheme( $this->the_home_url_from_cache() ) );
442
- /** Figure out if this is helpful...
443
- if ( ! $this->is_subdirectory_installation() ) {
444
- //= 1. $home = \trailingslashit( $this->set_url_scheme( $this->get_home_host() ) );
445
 
446
- //= 2.:
447
- $_path = $this->set_url_scheme( $home, 'relative' );
448
- if ( false !== ( $_pos = strrpos( $home, $_path ) ) ) {
449
- $home = \trailingslashit( substr_replace( $home, '', $_pos, strlen( $_path ) ) );
450
- }
451
- }
452
- */
 
 
 
453
 
454
  if ( $wp_rewrite->using_index_permalinks() ) {
455
  $loc = $home . 'index.php/sitemap.xml';
@@ -459,6 +463,9 @@ class Sitemaps extends Metaboxes {
459
  $loc = $home . '?the_seo_framework_sitemap=xml';
460
  }
461
 
 
 
 
462
  return $loc;
463
  }
464
 
@@ -539,7 +546,9 @@ class Sitemaps extends Metaboxes {
539
  */
540
  protected function generate_sitemap() {
541
 
542
- function_exists( '\wp_is_ini_value_changeable' ) and \wp_is_ini_value_changeable( 'memory_limit' ) and @ini_set( 'memory_limit', WP_MAX_MEMORY_LIMIT );
 
 
543
 
544
  $content = '';
545
 
@@ -578,8 +587,7 @@ class Sitemaps extends Metaboxes {
578
 
579
  //* Sets timezone according to WordPress settings.
580
  $this->set_timezone();
581
- $timestamp_format = $this->get_option( 'sitemap_timestamps' );
582
- $timestamp_format = '1' === $timestamp_format ? 'Y-m-d\TH:iP' : 'Y-m-d';
583
 
584
  /**
585
  * Fetch the page/post modified options.
@@ -587,13 +595,7 @@ class Sitemaps extends Metaboxes {
587
  */
588
  $sitemaps_modified = $this->is_option_checked( 'sitemaps_modified' );
589
  if ( $sitemaps_modified ) {
590
- $page_lastmod = true;
591
- $post_lastmod = true;
592
- $home_lastmod = true;
593
- } else {
594
- $page_lastmod = $this->is_option_checked( 'page_modify_time' );
595
- $post_lastmod = $this->is_option_checked( 'post_modify_time' );
596
- $home_lastmod = $page_lastmod ?: $this->is_option_checked( 'home_modify_time' );
597
  }
598
 
599
  /**
@@ -618,6 +620,7 @@ class Sitemaps extends Metaboxes {
618
  'orderby' => 'date',
619
  'order' => 'ASC',
620
  'post_status' => 'publish',
 
621
  'fields' => 'ids',
622
  'cache_results' => false,
623
  'suppress_filters' => true,
@@ -660,7 +663,7 @@ class Sitemaps extends Metaboxes {
660
  //* Continue if indexed.
661
  if ( $indexed ) {
662
  $content .= "\t<url>\n";
663
- $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'home' => true ) ) . "</loc>\n";
664
 
665
  // Keep it consistent. Only parse if page_lastmod is true.
666
  if ( $home_lastmod ) {
@@ -672,6 +675,7 @@ class Sitemaps extends Metaboxes {
672
  'numberposts' => 1,
673
  'post_type' => 'post',
674
  'post_status' => 'publish',
 
675
  'orderby' => 'post_date',
676
  'order' => 'DESC',
677
  'offset' => 0,
@@ -707,7 +711,7 @@ class Sitemaps extends Metaboxes {
707
  //* Continue if indexed.
708
  if ( $indexed && isset( $page->ID ) ) {
709
  $content .= "\t<url>\n";
710
- $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $page, 'id' => $page_for_posts_id ) ) . "</loc>\n";
711
 
712
  // Keep it consistent. Only parse if page_lastmod is true.
713
  if ( $page_lastmod ) {
@@ -715,6 +719,7 @@ class Sitemaps extends Metaboxes {
715
  'numberposts' => 1,
716
  'post_type' => 'post',
717
  'post_status' => 'publish',
 
718
  'orderby' => 'post_date',
719
  'order' => 'DESC',
720
  'offset' => 0,
@@ -745,21 +750,18 @@ class Sitemaps extends Metaboxes {
745
  * This can be heavy.
746
  */
747
  foreach ( $latest_pages as $page_id ) :
748
-
749
  $page = \get_post( $page_id );
750
 
751
  if ( isset( $page->ID ) ) :
752
  $page_id = $page->ID;
753
-
754
  if ( '' === $excluded || empty( $excluded[ $page_id ] ) ) {
755
-
756
  //* Fetch the noindex option, per page.
757
  $indexed = ! $this->get_custom_field( '_genesis_noindex', $page_id );
758
 
759
  //* Continue if indexed.
760
  if ( $indexed ) {
761
  $content .= "\t<url>\n";
762
- $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $page, 'id' => $page_id ) ) . "</loc>\n";
763
 
764
  // Keep it consistent. Only parse if page_lastmod is true.
765
  if ( $page_lastmod ) {
@@ -788,6 +790,7 @@ class Sitemaps extends Metaboxes {
788
  'orderby' => 'date',
789
  'order' => 'DESC',
790
  'post_status' => 'publish',
 
791
  'fields' => 'ids',
792
  'cache_results' => false,
793
  'suppress_filters' => true,
@@ -838,14 +841,11 @@ class Sitemaps extends Metaboxes {
838
  * This can be heavy.
839
  */
840
  foreach ( $latest_posts as $post_id ) :
841
-
842
  $post = \get_post( $post_id );
843
 
844
  if ( isset( $post->ID ) ) :
845
  $post_id = $post->ID;
846
-
847
  if ( '' === $excluded || empty( $excluded[ $post_id ] ) ) {
848
-
849
  //* Fetch the noindex option, per page.
850
  $indexed = ! $this->get_custom_field( '_genesis_noindex', $post_id );
851
 
@@ -854,7 +854,7 @@ class Sitemaps extends Metaboxes {
854
 
855
  $content .= "\t<url>\n";
856
  // No need to use static vars
857
- $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $post, 'id' => $post_id ) ) . "</loc>\n";
858
 
859
  // Keep it consistent. Only parse if page_lastmod is true.
860
  if ( $post_lastmod ) {
@@ -910,6 +910,7 @@ class Sitemaps extends Metaboxes {
910
  'orderby' => 'date',
911
  'order' => 'DESC',
912
  'post_status' => 'publish',
 
913
  'fields' => 'ids',
914
  'cache_results' => false,
915
  'suppress_filters' => true,
@@ -971,7 +972,7 @@ class Sitemaps extends Metaboxes {
971
 
972
  $content .= "\t<url>\n";
973
  //* No need to use static vars
974
- $content .= "\t\t<loc>" . $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'post' => $ctp_post, 'id' => $cpt_id ) ) . "</loc>\n";
975
 
976
  //* Keep it consistent. Only parse if page_lastmod is true.
977
  if ( $post_lastmod ) {
@@ -1000,14 +1001,17 @@ class Sitemaps extends Metaboxes {
1000
  endif;
1001
 
1002
  /**
1003
- * Applies filters the_seo_framework_sitemap_additional_urls : {
1004
- * @param string url The absolute url to the page. : {
1005
- * @param string lastmod UNIXTIME Last modified date, e.g. "2016-01-26 13:04:55"
1006
- * @param float|int|string priority URL Priority
1007
- * }
1008
- * }
1009
  *
1010
  * @since 2.5.2
 
 
 
 
 
 
 
 
1011
  */
1012
  $custom_urls = (array) \apply_filters( 'the_seo_framework_sitemap_additional_urls', array() );
1013
 
307
  echo "\n" . '<!-- Site estimated peak usage: ' . number_format( memory_get_peak_usage() / 1024 / 1024, 3 ) . ' MB -->';
308
  echo "\n" . '<!-- System estimated peak usage: ' . number_format( memory_get_peak_usage( true ) / 1024 / 1024, 3 ) . ' MB -->';
309
  echo "\n" . '<!-- Freed memory prior to generation: ' . number_format( $this->clean_up_globals_for_sitemap( true ) / 1024, 3 ) . ' kB -->';
310
+ echo "\n" . '<!-- Sitemap generation time: ' . number_format( microtime( true ) - $timer_start, 6 ) . ' seconds -->';
311
  }
312
  }
313
 
396
  * Returns the stylesheet XSL location URL.
397
  *
398
  * @since 2.8.0
399
+ * @since 3.0.0 1: No longer uses home URL from cache. But now uses `get_home_url()`.
400
+ * 2: Now takes query parameters (if any) and restores them correctly.
401
  * @global object $wp_rewrite
402
  *
403
  * @return string URL location of the XSL stylesheet. Unescaped.
405
  public function get_sitemap_xsl_url() {
406
  global $wp_rewrite;
407
 
408
+ $home = $this->set_url_scheme( \get_home_url() );
 
 
 
409
 
410
+ $parsed = parse_url( $home );
411
+ $query = isset( $parsed['query'] ) ? $parsed['query'] : '';
412
+
413
+ if ( $query )
414
+ $home = str_replace( '?' . $query, '', $home );
415
+
416
+ $home = \trailingslashit( $home );
417
 
418
  if ( $wp_rewrite->using_index_permalinks() ) {
419
  $loc = $home . 'index.php/sitemap.xsl';
423
  $loc = $home . '?the_seo_framework_sitemap=xsl';
424
  }
425
 
426
+ if ( $query )
427
+ $loc = $this->append_php_query( $loc, $query );
428
+
429
  return $loc;
430
  }
431
 
433
  * Returns the sitemap XML location URL.
434
  *
435
  * @since 2.9.2
436
+ * @since 3.0.0 1: No longer uses home URL from cache. But now uses `get_home_url()`.
437
+ * 2: Now takes query parameters (if any) and restores them correctly.
438
  * @global object $wp_rewrite
439
  *
440
  * @return string URL location of the XML sitemap. Unescaped.
442
  public function get_sitemap_xml_url() {
443
  global $wp_rewrite;
444
 
445
+ $home = $this->set_url_scheme( \get_home_url() );
 
 
 
446
 
447
+ $parsed = parse_url( $home );
448
+ $query = isset( $parsed['query'] ) ? $parsed['query'] : '';
449
+
450
+ if ( $query )
451
+ $home = str_replace( '?' . $query, '', $home );
452
+
453
+ $home = \trailingslashit( $home );
454
+
455
+ if ( $query )
456
+ $home = str_replace( '?' . $query, '', $home );
457
 
458
  if ( $wp_rewrite->using_index_permalinks() ) {
459
  $loc = $home . 'index.php/sitemap.xml';
463
  $loc = $home . '?the_seo_framework_sitemap=xml';
464
  }
465
 
466
+ if ( $query )
467
+ $loc = $this->append_php_query( $loc, $query );
468
+
469
  return $loc;
470
  }
471
 
546
  */
547
  protected function generate_sitemap() {
548
 
549
+ function_exists( '\wp_is_ini_value_changeable' )
550
+ and \wp_is_ini_value_changeable( 'memory_limit' )
551
+ and @ini_set( 'memory_limit', WP_MAX_MEMORY_LIMIT );
552
 
553
  $content = '';
554
 
587
 
588
  //* Sets timezone according to WordPress settings.
589
  $this->set_timezone();
590
+ $timestamp_format = $this->get_timestamp_format();
 
591
 
592
  /**
593
  * Fetch the page/post modified options.
595
  */
596
  $sitemaps_modified = $this->is_option_checked( 'sitemaps_modified' );
597
  if ( $sitemaps_modified ) {
598
+ $page_lastmod = $post_lastmod = $home_lastmod = true;
 
 
 
 
 
 
599
  }
600
 
601
  /**
620
  'orderby' => 'date',
621
  'order' => 'ASC',
622
  'post_status' => 'publish',
623
+ 'has_password' => false,
624
  'fields' => 'ids',
625
  'cache_results' => false,
626
  'suppress_filters' => true,
663
  //* Continue if indexed.
664
  if ( $indexed ) {
665
  $content .= "\t<url>\n";
666
+ $content .= "\t\t<loc>" . $this->get_homepage_permalink() . "</loc>\n";
667
 
668
  // Keep it consistent. Only parse if page_lastmod is true.
669
  if ( $home_lastmod ) {
675
  'numberposts' => 1,
676
  'post_type' => 'post',
677
  'post_status' => 'publish',
678
+ 'has_password' => false,
679
  'orderby' => 'post_date',
680
  'order' => 'DESC',
681
  'offset' => 0,
711
  //* Continue if indexed.
712
  if ( $indexed && isset( $page->ID ) ) {
713
  $content .= "\t<url>\n";
714
+ $content .= "\t\t<loc>" . $this->create_canonical_url( array( 'id' => $page->ID ) ) . "</loc>\n";
715
 
716
  // Keep it consistent. Only parse if page_lastmod is true.
717
  if ( $page_lastmod ) {
719
  'numberposts' => 1,
720
  'post_type' => 'post',
721
  'post_status' => 'publish',
722
+ 'has_password' => false,
723
  'orderby' => 'post_date',
724
  'order' => 'DESC',
725
  'offset' => 0,
750
  * This can be heavy.
751
  */
752
  foreach ( $latest_pages as $page_id ) :
 
753
  $page = \get_post( $page_id );
754
 
755
  if ( isset( $page->ID ) ) :
756
  $page_id = $page->ID;
 
757
  if ( '' === $excluded || empty( $excluded[ $page_id ] ) ) {
 
758
  //* Fetch the noindex option, per page.
759
  $indexed = ! $this->get_custom_field( '_genesis_noindex', $page_id );
760
 
761
  //* Continue if indexed.
762
  if ( $indexed ) {
763
  $content .= "\t<url>\n";
764
+ $content .= "\t\t<loc>" . $this->create_canonical_url( array( 'id' => $page_id ) ) . "</loc>\n";
765
 
766
  // Keep it consistent. Only parse if page_lastmod is true.
767
  if ( $page_lastmod ) {
790
  'orderby' => 'date',
791
  'order' => 'DESC',
792
  'post_status' => 'publish',
793
+ 'has_password' => false,
794
  'fields' => 'ids',
795
  'cache_results' => false,
796
  'suppress_filters' => true,
841
  * This can be heavy.
842
  */
843
  foreach ( $latest_posts as $post_id ) :
 
844
  $post = \get_post( $post_id );
845
 
846
  if ( isset( $post->ID ) ) :
847
  $post_id = $post->ID;
 
848
  if ( '' === $excluded || empty( $excluded[ $post_id ] ) ) {
 
849
  //* Fetch the noindex option, per page.
850
  $indexed = ! $this->get_custom_field( '_genesis_noindex', $post_id );
851
 
854
 
855
  $content .= "\t<url>\n";
856
  // No need to use static vars
857
+ $content .= "\t\t<loc>" . $this->create_canonical_url( array( 'id' => $post_id ) ) . "</loc>\n";
858
 
859
  // Keep it consistent. Only parse if page_lastmod is true.
860
  if ( $post_lastmod ) {
910
  'orderby' => 'date',
911
  'order' => 'DESC',
912
  'post_status' => 'publish',
913
+ 'has_password' => false,
914
  'fields' => 'ids',
915
  'cache_results' => false,
916
  'suppress_filters' => true,
972
 
973
  $content .= "\t<url>\n";
974
  //* No need to use static vars
975
+ $content .= "\t\t<loc>" . $this->create_canonical_url( array( 'id' => $cpt_id ) ) . "</loc>\n";
976
 
977
  //* Keep it consistent. Only parse if page_lastmod is true.
978
  if ( $post_lastmod ) {
1001
  endif;
1002
 
1003
  /**
1004
+ * Applies filters the_seo_framework_sitemap_additional_urls :
 
 
 
 
 
1005
  *
1006
  * @since 2.5.2
1007
+ * @param array $custom_urls : {
1008
+ * @param string (key) $url The absolute url to the page. : array {
1009
+ * @param string $lastmod UNIXTIME Last modified date, e.g. "2016-01-26 13:04:55"
1010
+ * @param float|int|string $priority URL Priority
1011
+ * }
1012
+ * }
1013
+ *
1014
+ * @example return value: [ 'http://example.com' => [ 'lastmod' => '14-01-2018', 'priority' => 0.9 ] ]
1015
  */
1016
  $custom_urls = (array) \apply_filters( 'the_seo_framework_sitemap_additional_urls', array() );
1017
 
inc/classes/term-data.class.php CHANGED
@@ -37,21 +37,52 @@ class Term_Data extends Post_Data {
37
  */
38
  protected function __construct() {
39
  parent::__construct();
40
-
41
- //* Initialize term meta filters and actions.
42
- $this->initialize_term_meta();
43
  }
44
 
45
  /**
46
  * Initializes term meta data filters and functions.
47
  *
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
  /**
@@ -80,11 +111,21 @@ class Term_Data extends Post_Data {
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
  *
@@ -122,6 +163,7 @@ class Term_Data extends Post_Data {
122
  * Sanitizes and saves term meta data when a term is altered.
123
  *
124
  * @since 2.7.0
 
125
  *
126
  * @param int $term_id Term ID.
127
  * @param int $tt_id Term Taxonomy ID.
@@ -157,6 +199,8 @@ class Term_Data extends Post_Data {
157
  continue 2;
158
 
159
  default :
 
 
160
  break;
161
  endswitch;
162
  endforeach;
@@ -192,35 +236,13 @@ class Term_Data extends Post_Data {
192
  }
193
  }
194
 
195
- /**
196
- * Fetch set Term data.
197
- *
198
- * @since 2.6.0
199
- * @since 2.7.0 Handles term object differently for upgraded database.
200
- *
201
- * @todo @since 2.8.0 Will no longer use $term.
202
- *
203
- * @param object|null $term The TT object, if it isn't set, one is fetched.
204
- * @param object|null $term_id The term object.
205
- * @return array The SEO Framework TT data.
206
- */
207
- public function get_term_data( $term = null, $term_id = 0 ) {
208
-
209
- if ( is_null( $term ) )
210
- $term = $this->fetch_the_term( $term_id );
211
-
212
- if ( isset( $term->term_id ) )
213
- return $this->get_term_meta( $term->term_id );
214
-
215
- //* Return null if no term can be set.
216
- return null;
217
- }
218
-
219
  /**
220
  * Try to fetch a term if none can be found.
221
  *
222
  * @since 2.6.0
 
223
  * @access private
 
224
  *
225
  * @param int $id The possible taxonomy Term ID.
226
  * @return false|object The Term object.
@@ -248,6 +270,8 @@ class Term_Data extends Post_Data {
248
  $term[ $id ] = \get_queried_object();
249
  } elseif ( $this->is_tax() ) {
250
  $term[ $id ] = \get_term_by( 'slug', \get_query_var( 'term' ), \get_query_var( 'taxonomy' ) );
 
 
251
  }
252
  }
253
 
@@ -341,4 +365,39 @@ class Term_Data extends Post_Data {
341
 
342
  return $term_name[ $singular ] = '';
343
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  }
37
  */
38
  protected function __construct() {
39
  parent::__construct();
 
 
 
40
  }
41
 
42
  /**
43
  * Initializes term meta data filters and functions.
44
  *
45
  * @since 2.7.0
46
+ * @since 3.0.0 No longer checks for admin query.
47
  */
48
  public function initialize_term_meta() {
49
+ \add_action( 'edit_term', array( $this, 'update_term_meta' ), 10, 2 );
50
+ \add_action( 'delete_term', array( $this, 'delete_term_meta' ), 10, 2 );
51
+ }
52
+
53
+ /**
54
+ * Determines if current query handles term meta.
55
+ *
56
+ * @since 3.0.0
57
+ *
58
+ * @return bool
59
+ */
60
+ public function is_term_meta_capable() {
61
+ return $this->is_category() || $this->is_tag() || $this->is_tax() || \is_post_type_archive();
62
+ }
63
+
64
+ /**
65
+ * Returns and caches term meta for the current query.
66
+ *
67
+ * @since 3.0.0
68
+ * @staticvar array $cache
69
+ *
70
+ * @return array The current term meta.
71
+ */
72
+ public function get_current_term_meta() {
73
+
74
+ static $cache;
75
+
76
+ if ( isset( $cache ) )
77
+ return $cache ?: array();
78
+
79
+ if ( $this->is_term_meta_capable() ) {
80
+ $cache = $this->get_term_meta( \get_queried_object_id() ) ?: false;
81
+ } else {
82
+ $cache = false;
83
  }
84
+
85
+ return $cache ?: array();
86
  }
87
 
88
  /**
111
  $data = \get_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, true );
112
 
113
  //* Evaluate merely by presence.
114
+ if ( isset( $data['saved_flag'] ) ) {
115
+ /**
116
+ * Applies filters 'the_seo_framework_current_term_meta'.
117
+ *
118
+ * @since 3.0.0
119
+ *
120
+ * @param array $data The current term data.
121
+ * @param int $term_id The term ID.
122
+ */
123
+ return $cache[ $term_id ] = \apply_filters( 'the_seo_framework_current_term_meta', $data, $term_id );
124
+ }
125
 
126
  /**
127
+ * Applies filters 'the_seo_framework_get_term_meta'.
128
+ * NOTE: Only works before TSF sets its saved - flag. To be used prior to migration.
129
  *
130
  * @since 2.8.0
131
  *
163
  * Sanitizes and saves term meta data when a term is altered.
164
  *
165
  * @since 2.7.0
166
+ * @securitycheck 3.0.0 OK.
167
  *
168
  * @param int $term_id Term ID.
169
  * @param int $tt_id Term Taxonomy ID.
199
  continue 2;
200
 
201
  default :
202
+ // Not implemented for compatibility reasons.
203
+ // unset( $data[ $key ] );
204
  break;
205
  endswitch;
206
  endforeach;
236
  }
237
  }
238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  /**
240
  * Try to fetch a term if none can be found.
241
  *
242
  * @since 2.6.0
243
+ * @since 3.0.0 Can now get custom post type objects.
244
  * @access private
245
+ * @todo deprecate
246
  *
247
  * @param int $id The possible taxonomy Term ID.
248
  * @return false|object The Term object.
270
  $term[ $id ] = \get_queried_object();
271
  } elseif ( $this->is_tax() ) {
272
  $term[ $id ] = \get_term_by( 'slug', \get_query_var( 'term' ), \get_query_var( 'taxonomy' ) );
273
+ } elseif ( \is_post_type_archive() ) {
274
+ $term[ $id ] = \get_post_type_object( \get_query_var( 'post_type' ) );
275
  }
276
  }
277
 
365
 
366
  return $term_name[ $singular ] = '';
367
  }
368
+
369
+ /**
370
+ * Returns hierarchical taxonomies for post type.
371
+ *
372
+ * @since 3.0.0
373
+ *
374
+ * @param string $get Whether to get the names or objects.
375
+ * @param string $post_type The post type. Will default to current post type.
376
+ * @return array The post type objects or names.
377
+ */
378
+ public function get_hierarchical_taxonomies_as( $get = 'objects', $post_type = '' ) {
379
+
380
+ if ( ! $post_type )
381
+ $post_type = \get_post_type( $this->get_the_real_ID() );
382
+
383
+ if ( ! $post_type )
384
+ return array();
385
+
386
+ $taxonomies = \get_object_taxonomies( $post_type, 'objects' );
387
+ $taxonomies = array_filter( $taxonomies, function( $t ) {
388
+ return $t->hierarchical;
389
+ } );
390
+
391
+ switch ( $get ) {
392
+ case 'names' :
393
+ $taxonomies = array_keys( $taxonomies );
394
+ break;
395
+
396
+ default :
397
+ case 'objects' :
398
+ break;
399
+ }
400
+
401
+ return $taxonomies;
402
+ }
403
  }
inc/classes/user-data.class.php ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 - 2017 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
+ * Class The_SEO_Framework\User_Data
28
+ *
29
+ * Holds and maintains User data.
30
+ *
31
+ * @since 3.0.0
32
+ */
33
+ class User_Data extends Term_Data {
34
+
35
+ /**
36
+ * Constructor, load parent constructor
37
+ */
38
+ protected function __construct() {
39
+ parent::__construct();
40
+ }
41
+
42
+ /**
43
+ * Returns default user meta.
44
+ *
45
+ * @since 3.0.0
46
+ *
47
+ * @return array The default user meta index and values.
48
+ */
49
+ public function get_default_user_data() {
50
+ return array(
51
+ 'counter_type' => 3,
52
+ 'facebook_page' => '',
53
+ 'twitter_page' => '',
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Returns the current post author ID.
59
+ *
60
+ * @since 3.0.0
61
+ * @staticvar $cache
62
+ *
63
+ * @return int|bool Post author on success, false on failure.
64
+ */
65
+ public function get_current_post_author_id() {
66
+
67
+ static $cache;
68
+
69
+ if ( isset( $cache ) )
70
+ return $cache;
71
+
72
+ $post = \get_post( $this->get_the_real_ID() );
73
+
74
+ return $cache = isset( $post->post_author ) ? (int) $post->post_author : false;
75
+ }
76
+
77
+ /**
78
+ * Sets up user ID and returns it if user is found.
79
+ * To be used in AJAX, back-end and front-end.
80
+ *
81
+ * @since 2.7.0
82
+ *
83
+ * @return int $user_id : 0 if user is not found.
84
+ */
85
+ public function get_user_id() {
86
+
87
+ static $user_id = null;
88
+
89
+ if ( isset( $user_id ) )
90
+ return $user_id;
91
+
92
+ $user = \wp_get_current_user();
93
+
94
+ return $user_id = $user->exists() ? (int) $user->ID : 0;
95
+ }
96
+
97
+ /**
98
+ * Fetches The SEO Framework usermeta.
99
+ *
100
+ * @since 2.7.0
101
+ * @since 2.8.0 Always returns array, even if no value is assigned.
102
+ * @staticvar array $usermeta_cache
103
+ *
104
+ * @param int $user_id The user ID.
105
+ * @param string $key The user metadata key. Leave empty to fetch all data.
106
+ * @param bool $use_cache Whether to store and use options from cache.
107
+ * @return array The user SEO meta data.
108
+ */
109
+ public function get_user_meta( $user_id, $key = THE_SEO_FRAMEWORK_USER_OPTIONS, $use_cache = true ) {
110
+
111
+ if ( false === $use_cache )
112
+ return ( $meta = \get_user_meta( $user_id, $key, true ) ) && is_array( $meta ) ? $meta : array();
113
+
114
+ static $usermeta_cache = array();
115
+
116
+ if ( isset( $usermeta_cache[ $user_id ][ $key ] ) )
117
+ return $usermeta_cache[ $user_id ][ $key ];
118
+
119
+ return $usermeta_cache[ $user_id ][ $key ] = ( $meta = \get_user_meta( $user_id, $key, true ) ) && is_array( $meta ) ? $meta : array();
120
+ }
121
+
122
+ /**
123
+ * Returns current post author option.
124
+ *
125
+ * @since 3.0.0
126
+ *
127
+ * @param int $author_id The author ID. When empty, it will return $default.
128
+ * @param string $option The option name. When empty, it will return $default.
129
+ * @param mixed $default The default value to return when the data doesn't exist.
130
+ * @return mixed The metadata value
131
+ */
132
+ public function get_author_option( $author_id, $option, $default = null ) {
133
+
134
+ if ( ! $author_id || ! $option )
135
+ return $default;
136
+
137
+ return $this->get_user_option( $author_id, $option, $default );
138
+ }
139
+
140
+ /**
141
+ * Returns current post author option.
142
+ *
143
+ * @since 3.0.0
144
+ *
145
+ * @param string $option The option name.
146
+ * @param mixed $default The default value to return when the data doesn't exist.
147
+ * @return mixed The metadata value
148
+ */
149
+ public function get_current_author_option( $option, $default = null ) {
150
+ return $this->get_author_option( $this->get_current_post_author_id(), $option, $default );
151
+ }
152
+
153
+ /**
154
+ * Fetches user SEO user meta data by name.
155
+ * Caches all meta data per $user_id.
156
+ *
157
+ * If no $user_id is supplied, it will fetch the current logged in user ID.
158
+ *
159
+ * @since 2.7.0
160
+ * @since 3.0.0 1. Default is no longer cached.
161
+ * 2. Now always fallbacks to $default.
162
+ * 3. Added not-found cache.
163
+ * @staticvar array $options_cache
164
+ * @staticvar array $notfound_cache
165
+ *
166
+ * @param int $user_id The user ID. When empty, it will try to fetch the current user.
167
+ * @param string $option The option name.
168
+ * @param mixed $default The default value to return when the data doesn't exist.
169
+ * @return mixed The metadata value.
170
+ */
171
+ public function get_user_option( $user_id = 0, $option, $default = null ) {
172
+
173
+ if ( ! $option )
174
+ return $default;
175
+
176
+ if ( empty( $user_id ) )
177
+ $user_id = $this->get_user_id();
178
+
179
+ if ( ! $user_id )
180
+ return $default;
181
+
182
+ static $options_cache = array(),
183
+ $notfound_cache = array();
184
+
185
+ if ( isset( $options_cache[ $user_id ][ $option ] ) )
186
+ return $options_cache[ $user_id ][ $option ];
187
+
188
+ if ( isset( $notfound_cache[ $user_id ][ $option ] ) )
189
+ return $default;
190
+
191
+ $usermeta = $this->get_user_meta( $user_id );
192
+
193
+ if ( isset( $usermeta[ $option ] ) ) {
194
+ return $options_cache[ $user_id ][ $option ] = $usermeta[ $option ];
195
+ } else {
196
+ $notfound_cache[ $user_id ][ $option ] = true;
197
+ }
198
+
199
+ return $default;
200
+ }
201
+
202
+ /**
203
+ * Updates user SEO option.
204
+ *
205
+ * @since 2.7.0
206
+ * @since 2.8.0 New users now get a new array assigned.
207
+ *
208
+ * @param int $user_id The user ID.
209
+ * @param string $option The user's SEO metadata option.
210
+ * @param mixed $value The escaped option value.
211
+ * @return bool True on success. False on failure.
212
+ */
213
+ public function update_user_option( $user_id = 0, $option, $value ) {
214
+
215
+ if ( ! $option )
216
+ return false;
217
+
218
+ if ( empty( $user_id ) )
219
+ $user_id = $this->get_user_id();
220
+
221
+ if ( empty( $user_id ) )
222
+ return false;
223
+
224
+ $meta = $this->get_user_meta( $user_id, THE_SEO_FRAMEWORK_USER_OPTIONS, false );
225
+
226
+ /**
227
+ * @since 2.8.0 initializes new array on empty values.
228
+ */
229
+ is_array( $meta ) or $meta = array();
230
+
231
+ $meta[ $option ] = $value;
232
+
233
+ return \update_user_meta( $user_id, THE_SEO_FRAMEWORK_USER_OPTIONS, $meta );
234
+ }
235
+ }
inc/compat/php-mbstring.php CHANGED
@@ -10,10 +10,10 @@ defined( 'ABSPATH' ) or die;
10
  *
11
  * @see _mb_strpos()
12
  *
13
- * @param string $haystack The string to search in.
14
- * @param mixed $needle If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.
15
- * @param int $offset Optional, search will start this number of characters counted from the beginning of the string. The offset cannot be negative.
16
- * @param string|null $encoding Optional. Character encoding to use. Default null.
17
  *
18
  * @license GLPv2 or later
19
  * @return int Position of first occurrence found of $haystack of `$needle`.
@@ -34,10 +34,10 @@ endif;
34
  * @since 2.2.0 The SEO Framework
35
  * @license GLPv2 or later
36
  *
37
- * @param string $haystack The string to search in.
38
- * @param mixed $needle If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.
39
- * @param int $offset Optional, search will start this number of characters counted from the beginning of the string. The offset cannot be negative.
40
- * @param string|null $encoding Optional. Character encoding to use. Default null.
41
  *
42
  * @license GLPv2 or later
43
  * @return int Position of first occurrence found of $haystack of `$needle`.
@@ -51,7 +51,7 @@ if ( ! function_exists( '_mb_strpos' ) ) :
51
 
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
 
@@ -81,7 +81,7 @@ if ( ! function_exists( '_mb_strpos' ) ) :
81
 
82
  if ( _wp_can_use_pcre_u() ) {
83
  // Use the regex unicode support to separate the UTF-8 characters into an array
84
- preg_match_all( "/./us", $haystack, $match_h );
85
  preg_match_all( "/$needle/us", $haystack_sub, $match_n );
86
 
87
  $inter = array_intersect( $match_h[0], $match_n[0] );
@@ -165,7 +165,7 @@ if ( ! function_exists( '_mb_strpos' ) ) :
165
  * Compute match of haystack offset with needle
166
  * If passed, return the array key number within the full haystack.
167
  */
168
- if ( false !== in_array( $match_n[0], $match_hs ) ) {
169
  $inter = array_intersect( $match_h, $match_n );
170
 
171
  if ( ! isset( $inter ) )
10
  *
11
  * @see _mb_strpos()
12
  *
13
+ * @param string $haystack The string to search in.
14
+ * @param mixed $needle If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.
15
+ * @param int $offset Optional, search will start this number of characters counted from the beginning of the string. The offset cannot be negative.
16
+ * @param string|null $encoding Optional. Character encoding to use. Default null.
17
  *
18
  * @license GLPv2 or later
19
  * @return int Position of first occurrence found of $haystack of `$needle`.
34
  * @since 2.2.0 The SEO Framework
35
  * @license GLPv2 or later
36
  *
37
+ * @param string $haystack The string to search in.
38
+ * @param mixed $needle If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.
39
+ * @param int $offset Optional, search will start this number of characters counted from the beginning of the string. The offset cannot be negative.
40
+ * @param string|null $encoding Optional. Character encoding to use. Default null.
41
  *
42
  * @license GLPv2 or later
43
  * @return int Position of first occurrence found of $haystack of `$needle`.
51
 
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' ), true ) ) {
55
  return 0 === $offset ? strpos( $haystack, $needle ) : strpos( $haystack, $needle, $offset );
56
  }
57
 
81
 
82
  if ( _wp_can_use_pcre_u() ) {
83
  // Use the regex unicode support to separate the UTF-8 characters into an array
84
+ preg_match_all( '/./us', $haystack, $match_h );
85
  preg_match_all( "/$needle/us", $haystack_sub, $match_n );
86
 
87
  $inter = array_intersect( $match_h[0], $match_n[0] );
165
  * Compute match of haystack offset with needle
166
  * If passed, return the array key number within the full haystack.
167
  */
168
+ if ( false !== in_array( $match_n[0], $match_hs, true ) ) {
169
  $inter = array_intersect( $match_h, $match_n );
170
 
171
  if ( ! isset( $inter ) )
inc/compat/plugin-bbpress.php CHANGED
@@ -53,15 +53,13 @@ function _bbpress_filter_order_keys( $current_keys = array() ) {
53
  function _bbpress_filter_pre_title( $title = '', $args = array(), $escape = true ) {
54
 
55
  if ( \is_bbpress() ) {
56
-
57
  if ( \bbp_is_topic_tag() ) {
58
-
59
- $term = \get_queried_object();
60
- $data = \the_seo_framework()->get_term_data( $term, $term->term_id );
61
 
62
  if ( ! empty( $data['doctitle'] ) ) {
63
  $title = $data['doctitle'];
64
  } else {
 
65
  $title = $term->name ?: \the_seo_framework()->untitled();
66
  }
67
  }
@@ -157,11 +155,8 @@ function _bbpress_filter_url_path( $path, $id = 0, $external = false ) {
157
  function _bbpress_filter_excerpt_generation( $excerpt = '', $page_id = 0, $term = '', $max_char_length = 155 ) {
158
 
159
  if ( \is_bbpress() ) {
160
-
161
  if ( \bbp_is_topic_tag() ) {
162
-
163
  $term = \get_queried_object();
164
-
165
  $description = $term->description ?: '';
166
 
167
  //* Always overwrite.
@@ -190,12 +185,8 @@ function _bbpress_filter_excerpt_generation( $excerpt = '', $page_id = 0, $term
190
  function _bbpress_filter_custom_field_description( $description = '', $args = array() ) {
191
 
192
  if ( \is_bbpress() ) {
193
-
194
  if ( \bbp_is_topic_tag() ) {
195
-
196
- $term = \get_queried_object();
197
- $data = \the_seo_framework()->get_term_data( $term, $term->term_id );
198
-
199
  if ( ! empty( $data['description'] ) ) {
200
  $description = $data['description'];
201
  } else {
53
  function _bbpress_filter_pre_title( $title = '', $args = array(), $escape = true ) {
54
 
55
  if ( \is_bbpress() ) {
 
56
  if ( \bbp_is_topic_tag() ) {
57
+ $data = \the_seo_framework()->get_term_meta( \get_queried_object_id() );
 
 
58
 
59
  if ( ! empty( $data['doctitle'] ) ) {
60
  $title = $data['doctitle'];
61
  } else {
62
+ $term = \get_queried_object();
63
  $title = $term->name ?: \the_seo_framework()->untitled();
64
  }
65
  }
155
  function _bbpress_filter_excerpt_generation( $excerpt = '', $page_id = 0, $term = '', $max_char_length = 155 ) {
156
 
157
  if ( \is_bbpress() ) {
 
158
  if ( \bbp_is_topic_tag() ) {
 
159
  $term = \get_queried_object();
 
160
  $description = $term->description ?: '';
161
 
162
  //* Always overwrite.
185
  function _bbpress_filter_custom_field_description( $description = '', $args = array() ) {
186
 
187
  if ( \is_bbpress() ) {
 
188
  if ( \bbp_is_topic_tag() ) {
189
+ $data = \the_seo_framework()->get_term_meta( \get_queried_object_id() );
 
 
 
190
  if ( ! empty( $data['description'] ) ) {
191
  $description = $data['description'];
192
  } else {
inc/compat/plugin-buddypress.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Compat\Plugin\BuddyPress
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( 'wp_head', __NAMESPACE__ . '\\_buddypress_init_compat', 0 );
10
+ /**
11
+ * Initializes BuddyPress compatibility loader.
12
+ * At wp_head, as BuddyPress loads very late.
13
+ *
14
+ * @since 3.0.0
15
+ * @access private
16
+ */
17
+ function _buddypress_init_compat() {
18
+ if ( \is_buddypress() ) {
19
+ //= Remove TSF canonical URL, and let BuddyPress handle it.
20
+ \add_filter( 'the_seo_framework_rel_canonical_output', '\\__return_empty_string' );
21
+ }
22
+ }
inc/compat/plugin-donncha-dm.php DELETED
@@ -1,69 +0,0 @@
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 The unescaped URL, or the URL and 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
- if ( $get_scheme ) {
65
- return array( '', '' );
66
- } else {
67
- return '';
68
- }
69
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/compat/plugin-polylang.php DELETED
@@ -1,187 +0,0 @@
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
- \add_filter( 'the_seo_framework_url_output_args', __NAMESPACE__ . '\\_polylang_filter_url_args', 10, 4 );
10
- /**
11
- * Filters the canonical generation URL and Scheme arguments.
12
- *
13
- * @since 2.9.2
14
- * @access private
15
- * @global object $polylang
16
- *
17
- * @param array $args the URL arguments to supply. : {
18
- * 'url' => The full URL built from $path,
19
- * 'scheme' => The preferred scheme
20
- * }
21
- * @param string $path the URL path.
22
- * @param int $id The current post, page or term ID.
23
- * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
24
- * @return array { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
25
- */
26
- function _polylang_filter_url_args( $args = array(), $path = '', $id = 0, $external = false ) {
27
- global $polylang;
28
-
29
- if ( ! is_object( $polylang ) || ! ( isset( $polylang->filters_links ) && is_object( $polylang->filters_links ) ) )
30
- return $args;
31
-
32
- static $state = null;
33
-
34
- if ( null === $state ) {
35
- ( \the_seo_framework()->is_sitemap() || \the_seo_framework()->is_robots() ) and $state = 1
36
- or \the_seo_framework()->is_admin() and $state = 2
37
- or $state = 3;
38
- }
39
-
40
- if ( 1 === $state || $external )
41
- return \The_SEO_Framework\_polylang_external_filter_url_args( $args, $path, $id, $external );
42
-
43
- if ( 2 === $state )
44
- return \The_SEO_Framework\_polylang_admin_filter_url_args( $args, $path, $id, $external );
45
-
46
- return \The_SEO_Framework\_polylang_frontend_filter_url_args( $args, $path, $id, $external );
47
- }
48
-
49
- /**
50
- * Filters the canonical generation URL and Scheme arguments for external parsing.
51
- *
52
- * @since 2.9.2
53
- * @access private
54
- * @staticvar string $home_url
55
- * @global object $polylang
56
- *
57
- * @param array $args the URL arguments to supply. : {
58
- * 'url' => The full URL built from $path,
59
- * 'scheme' => The preferred scheme
60
- * }
61
- * @param string $path the URL path.
62
- * @param int $id The current post, page or term ID.
63
- * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
64
- * @return array { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
65
- */
66
- function _polylang_external_filter_url_args( $args = array(), $path = '', $id = 0, $external = false ) {
67
- global $polylang;
68
-
69
- static $home_url = null;
70
- //* We don't want to fire internal filters that lead to this function.
71
- if ( null === $home_url )
72
- $home_url = \untrailingslashit( \esc_url_raw( \the_seo_framework()->set_preferred_url_scheme( \the_seo_framework()->get_home_host() ), array( 'http', 'https' ) ) );
73
-
74
- $_post = \get_post( $id );
75
- $_link = $home_url . $path;
76
-
77
- if ( null === $_post ) {
78
- if ( method_exists( $polylang->filters_links, 'post_type_link' ) )
79
- $args['url'] = $polylang->links->get_home_url( '' );
80
- } elseif ( method_exists( $polylang->filters_links, 'post_type_link' ) ) {
81
- $args['url'] = $polylang->filters_links->post_type_link( $_link, $_post );
82
- }
83
-
84
- if ( isset( $args['url'] ) ) {
85
- $parsed_url = \wp_parse_url( $args['url'] );
86
- $args['scheme'] = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : '';
87
- }
88
-
89
- return $args;
90
- }
91
-
92
- /**
93
- * Filters the canonical generation URL and Scheme arguments for the admin side.
94
- *
95
- * @since 2.9.2
96
- * @access private
97
- * @global object $polylang
98
- *
99
- * @param array $args the URL arguments to supply. : {
100
- * 'url' => The full URL built from $path,
101
- * 'scheme' => The preferred scheme
102
- * }
103
- * @param string $path the URL path.
104
- * @param int $id The current post, page or term ID.
105
- * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
106
- * @return array { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
107
- */
108
- function _polylang_admin_filter_url_args( $args = array(), $path = '', $id = 0, $external = false ) {
109
- global $polylang;
110
-
111
- //* We don't want to fire internal filters that lead to this function.
112
- $home_url = \untrailingslashit( \esc_url_raw( \the_seo_framework()->set_preferred_url_scheme( \the_seo_framework()->get_home_host() ), array( 'http', 'https' ) ) );
113
-
114
- if ( \the_seo_framework()->is_real_front_page() || \the_seo_framework()->is_front_page_by_id( $id ) || \the_seo_framework()->is_404() ) {
115
- if ( isset( $polylang->links ) && method_exists( $polylang->links, 'get_home_url' ) ) {
116
- if ( isset( $polylang->curlang ) && is_object( $polylang->curlang ) )
117
- $args['url'] = $polylang->links->get_home_url( $polylang->curlang, false );
118
- } else {
119
- $args['url'] = $home_url;
120
- }
121
- } elseif ( $path ) {
122
- $_post = \get_post( $id );
123
- $_link = $home_url . $path;
124
-
125
- if ( method_exists( $polylang->filters_links, 'post_type_link' ) ) {
126
- $args['url'] = $polylang->filters_links->post_type_link( $_link, $_post );
127
- }
128
- }
129
-
130
- if ( isset( $args['url'] ) ) {
131
- $parsed_url = \wp_parse_url( $args['url'] );
132
- $args['scheme'] = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : '';
133
- }
134
-
135
- return $args;
136
- }
137
-
138
- /**
139
- * Filters the canonical generation URL and Scheme arguments for the frontend.
140
- *
141
- * @since 2.9.2
142
- * @access private
143
- * @global object $polylang
144
- *
145
- * @param array $args the URL arguments to supply. : {
146
- * 'url' => The full URL built from $path,
147
- * 'scheme' => The preferred scheme
148
- * }
149
- * @param string $path the URL path.
150
- * @param int $id The current post, page or term ID.
151
- * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
152
- * @return array { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
153
- */
154
- function _polylang_frontend_filter_url_args( $args = array(), $path = '', $id = 0, $external = false ) {
155
- global $polylang;
156
-
157
- //* We don't want to fire internal filters that lead to this function.
158
- $home_url = \untrailingslashit( \esc_url_raw( \the_seo_framework()->set_preferred_url_scheme( \the_seo_framework()->get_home_host() ), array( 'http', 'https' ) ) );
159
-
160
- if ( \the_seo_framework()->is_real_front_page() || \the_seo_framework()->is_404() || \the_seo_framework()->is_search() ) {
161
- if ( isset( $polylang->links ) && method_exists( $polylang->links, 'get_home_url' ) ) {
162
- $_curlang = isset( $polylang->curlang ) ? $polylang->curlang : '';
163
- $args['url'] = $polylang->links->get_home_url( $_curlang );
164
- } else {
165
- $args['url'] = $home_url;
166
- }
167
- } elseif ( $path ) {
168
- $_requested_url = $home_url . $path;
169
-
170
- // Only pass if it's not empty, otherwise we'll have XSS issues.
171
- if ( $_requested_url ) {
172
- if ( \is_post_type_archive() && isset( $polylang->links_model ) && method_exists( $polylang->links_model, 'switch_language_in_link' ) ) {
173
- $_curlang = isset( $polylang->curlang ) ? $polylang->curlang : '';
174
- $args['url'] = $polylang->links_model->switch_language_in_link( $_requested_url, $_curlang );
175
- } elseif ( method_exists( $polylang->filters_links, 'check_canonical_url' ) ) {
176
- $args['url'] = $polylang->filters_links->check_canonical_url( $_requested_url, false );
177
- }
178
- }
179
- }
180
-
181
- if ( isset( $args['url'] ) ) {
182
- $parsed_url = \wp_parse_url( $args['url'] );
183
- $args['scheme'] = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] : '';
184
- }
185
-
186
- return $args;
187
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/compat/plugin-qtranslatex.php DELETED
@@ -1,100 +0,0 @@
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 ( false !== strpos( $path, '?lang=' . $current_lang ) )
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-wpforo.php CHANGED
@@ -16,7 +16,9 @@ function _wpforo_fix_page() {
16
 
17
  if ( function_exists( '\\is_wpforo_page' ) && \is_wpforo_page() ) {
18
  \add_filter( 'the_seo_framework_pre_add_title', __NAMESPACE__ . '\\_wpforo_filter_pre_title', 10, 3 );
19
- \add_filter( 'the_seo_framework_url_path', __NAMESPACE__ . '\\_wpforo_filter_url_path', 10, 3 );
 
 
20
  \add_filter( 'the_seo_framework_description_args', __NAMESPACE__ . '\\_wpforo_filter_description_arguments', 10, 3 );
21
 
22
  //* Remove wpforo SEO meta output.
@@ -40,28 +42,6 @@ function _wpforo_filter_pre_title( $title, $args, $escape ) {
40
  return $wpforo_title[0] ?: $title;
41
  }
42
 
43
- /**
44
- * Fixes wpForo page URL paths.
45
- *
46
- * @since 2.9.2
47
- * @access private
48
- *
49
- * @param string $path The current path.
50
- * @param int $id The page/post ID.
51
- * @param bool $external Whether the request is external (i.e. sitemap)
52
- * @return string The URL path.
53
- */
54
- function _wpforo_filter_url_path( $path, $id, $external ) {
55
-
56
- if ( $external )
57
- return $path;
58
-
59
- if ( '' === \the_seo_framework()->permalink_structure() )
60
- return $path;
61
-
62
- return \the_seo_framework()->set_url_scheme( \wpforo_get_request_uri(), 'relative' );
63
- }
64
-
65
  /**
66
  * Fixes wpForo page descriptions.
67
  *
16
 
17
  if ( function_exists( '\\is_wpforo_page' ) && \is_wpforo_page() ) {
18
  \add_filter( 'the_seo_framework_pre_add_title', __NAMESPACE__ . '\\_wpforo_filter_pre_title', 10, 3 );
19
+ \add_filter( 'get_canonical_url', function( $canonical_url, $post ) {
20
+ return \wpforo_get_request_uri();
21
+ }, 10, 2 );
22
  \add_filter( 'the_seo_framework_description_args', __NAMESPACE__ . '\\_wpforo_filter_description_arguments', 10, 3 );
23
 
24
  //* Remove wpforo SEO meta output.
42
  return $wpforo_title[0] ?: $title;
43
  }
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  /**
46
  * Fixes wpForo page descriptions.
47
  *
inc/compat/plugin-wpml.php CHANGED
@@ -9,193 +9,11 @@ defined( 'ABSPATH' ) and $_this = \the_seo_framework_class() and $this instanceo
9
  /**
10
  * Warns homepage global title and description about receiving 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
- * @since 2.9.2 : Now passes $external paramerer
23
- * @access private
24
- *
25
- * @param string $path the URL path.
26
- * @param int $id The current post, page or term ID.
27
- * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
28
- * @return string The URL path.
29
- */
30
- function _wpml_filter_url_path( $path = '', $id = 0, $external = false ) {
31
- return \The_SEO_Framework\_wmpl_get_relative_url( $path, $id, $external );
32
- }
33
-
34
- /**
35
- * Generate relative WPML url.
36
- *
37
- * @since 2.4.3
38
- * @since 2.9.2 : 1. Added $is_external staticvar.
39
- * : 2. Added $current_language staticvar.
40
- * : 3. Cached $current_language through WPML determination, improving performance.
41
- * : 4. Can now receive $external parameter.
42
- *
43
- * @staticvar bool $is_external
44
- * @staticvar bool $gli_exists
45
- * @staticvar string $default_lang
46
- * @staticvar string $current_language
47
- * @staticvar string $lang_code
48
- * @global object $sitepress
49
- * @NOTE: Handles full path, including home directory.
50
- * @access private
51
- *
52
- * @param string $path The current path.
53
- * @param int $post_id The Post ID.
54
- * @param bool $external Whether the call is made from outside the current ID scope.
55
- * @return relative path for WPML urls.
56
- */
57
- function _wmpl_get_relative_url( $path = '', $post_id = '', $external = false ) {
58
- global $sitepress;
59
-
60
- if ( ! is_object( $sitepress ) )
61
- return $path;
62
-
63
- static $is_external = null;
64
- if ( null === $is_external )
65
- $is_external = \the_seo_framework()->is_sitemap() || \the_seo_framework()->is_robots();
66
-
67
- //* Reset cache.
68
- \the_seo_framework()->url_slashit = true;
69
- \the_seo_framework()->unset_current_subdomain();
70
-
71
- static $gli_exists = null;
72
- if ( null === $gli_exists )
73
- $gli_exists = function_exists( 'wpml_get_language_information' );
74
-
75
- if ( false === $gli_exists )
76
- return $path;
77
-
78
- if ( empty( $post_id ) )
79
- $post_id = \the_seo_framework()->get_the_real_ID();
80
-
81
- //* Cache default language.
82
- static $default_lang = null;
83
- if ( null === $default_lang )
84
- $default_lang = is_callable( array( $sitepress, 'get_default_language' ) ) ? $sitepress->get_default_language() : '';
85
-
86
- //* Cache current language.
87
- static $current_language = null;
88
- if ( null === $current_language )
89
- $current_language = ! ( $is_external || $external ) && is_callable( array( $sitepress, 'get_current_language' ) ) ? $sitepress->get_current_language() : '';
90
-
91
- if ( empty( $current_language ) ) {
92
- /**
93
- * Applies filters 'wpml_post_language_details' : array|wp_error
94
- *
95
- * Only works for singular items.
96
- *
97
- * ... Somehow WPML thought this would be great and understandable.
98
- * This should be put inside a callable function.
99
- *
100
- * @since 2.6.0
101
- */
102
- $lang_info = \apply_filters( 'wpml_post_language_details', null, $post_id );
103
-
104
- if ( \is_wp_error( $lang_info ) ) {
105
- //* Terms and Taxonomies.
106
- $lang_info = array();
107
-
108
- //* Cache the code.
109
- static $lang_code = null;
110
- if ( null === $lang_code )
111
- $lang_code = defined( 'ICL_LANGUAGE_CODE' ) ? ICL_LANGUAGE_CODE : false;
112
-
113
- $lang_info['language_code'] = $lang_code;
114
- }
115
-
116
- //* If filter isn't used, bail.
117
- if ( empty( $lang_info['language_code'] ) )
118
- return $path;
119
-
120
- $current_lang = $lang_info['language_code'];
121
- } else {
122
- $current_lang = $current_language;
123
- }
124
-
125
- //* No need to alter URL if we're on default lang.
126
- if ( $current_lang === $default_lang )
127
- return $path;
128
-
129
- //* Cache negotiation type.
130
- static $negotiation_type = null;
131
- if ( null === $negotiation_type )
132
- $negotiation_type = is_callable( array( $sitepress, 'get_current_language' ) ) ? $sitepress->get_setting( 'language_negotiation_type' ) : '';
133
-
134
- switch ( $negotiation_type ) :
135
- case '1' :
136
- //* Subdirectory
137
-
138
- $t_path = \trailingslashit( $path );
139
-
140
- if ( 0 === strpos( $t_path, '/' . $current_lang . '/' ) ) {
141
- //* Link is already good.
142
- return $path;
143
- } elseif ( 0 === strpos( $t_path, '/' . $default_lang . '/' ) ) {
144
- //* Link contains default lang. Strip.
145
- $t_path = substr( $t_path, strlen( '/' . $default_lang ) );
146
-
147
- if ( 0 === strpos( $t_path, '/' . $current_lang . '/' ) ) {
148
- //* New link contains current lang correctly.
149
- return \user_trailingslashit( $t_path );
150
- } else {
151
- return $path = \trailingslashit( $current_lang ) . ltrim( \user_trailingslashit( $t_path ), ' \\/' );
152
- }
153
- }
154
-
155
- return $path = \trailingslashit( $current_lang ) . ltrim( \user_trailingslashit( $path ), ' \\/' );
156
- break;
157
-
158
- case '2' :
159
- //* Custom domain.
160
-
161
- $langsettings = $sitepress->get_setting( 'language_domains' );
162
- $current_lang_setting = isset( $langsettings[ $current_lang ] ) ? $langsettings[ $current_lang ] : '';
163
-
164
- if ( empty( $current_lang_setting ) )
165
- return $path;
166
-
167
- $current_lang_setting = \the_seo_framework()->make_fully_qualified_url( $current_lang_setting );
168
- $parsed = \wp_parse_url( $current_lang_setting );
169
-
170
- \the_seo_framework()->current_host = isset( $parsed['host'] ) ? $parsed['host'] : '';
171
- $current_path = isset( $parsed['path'] ) ? \trailingslashit( $parsed['path'] ) : '';
172
-
173
- return $current_path . $path;
174
- break;
175
-
176
- case '3' :
177
- //* Negotiation type query var.
178
-
179
- //* Don't slash it further.
180
- \the_seo_framework()->url_slashit = false;
181
-
182
- /**
183
- * Path must have trailing slash for pagination permalinks to work.
184
- * So we remove the query string and add it back with slash.
185
- */
186
- if ( false !== strpos( $path, '?lang=' . $current_lang ) )
187
- $path = str_replace( '?lang=' . $current_lang, '', $path );
188
-
189
- return \user_trailingslashit( $path ) . '?lang=' . $current_lang;
190
- break;
191
-
192
- default :
193
- break;
194
- endswitch;
195
-
196
- return $path;
197
- }
198
-
199
  \add_action( 'current_screen', __NAMESPACE__ . '\\_wpml_do_current_screen_action' );
200
  /**
201
  * Adds WPML filters only on SEO plugin page.
9
  /**
10
  * Warns homepage global title and description about receiving input.
11
  *
12
+ * @since 2.8.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_action( 'current_screen', __NAMESPACE__ . '\\_wpml_do_current_screen_action' );
18
  /**
19
  * Adds WPML filters only on SEO plugin page.
inc/compat/plugin-wpmudev-dm.php DELETED
@@ -1,134 +0,0 @@
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
- * @since 2.9.2 Now also returns an array if $get_scheme is true when no output is found.
39
- * @global object $wpdb
40
- * @global int $blog_id
41
- * @access private
42
- *
43
- * @param string $path The post relative path.
44
- * @param bool $get_scheme Output array with scheme.
45
- * @return string|array The unescaped URL, or the URL and the Scheme.
46
- */
47
- function _wpmudev_domainmap_get_url( $path, $get_scheme = false ) {
48
- global $wpdb, $blog_id;
49
-
50
- /**
51
- * Cache revisions. Hexadecimal.
52
- * @since 2.6.0
53
- */
54
- $revision = '1';
55
-
56
- $cache_key = 'wpmudev_mapped_domain_' . $revision . '_' . $blog_id;
57
-
58
- //* Check if the domain is mapped. Store in object cache.
59
- $mapped_domain = \the_seo_framework()->object_cache_get( $cache_key );
60
- if ( false === $mapped_domain ) :
61
- $mapped_domains = $wpdb->get_results(
62
- $wpdb->prepare(
63
- "SELECT id, domain, is_primary, scheme FROM {$wpdb->base_prefix}domain_mapping WHERE blog_id = %d", $blog_id
64
- ), OBJECT
65
- );
66
-
67
- $primary_key = 0;
68
- $domain_ids = array();
69
-
70
- foreach ( $mapped_domains as $key => $domain ) :
71
- if ( isset( $domain->is_primary ) && '1' === $domain->is_primary ) {
72
- $primary_key = $key;
73
-
74
- //* We've found the primary key, break loop.
75
- break;
76
- } else {
77
- //* Save IDs.
78
- if ( isset( $domain->id ) && $domain->id )
79
- $domain_ids[ $key ] = $domain->id;
80
- }
81
- endforeach;
82
-
83
- if ( 0 === $primary_key && ! empty( $domain_ids ) ) {
84
- //* No primary ID has been found. Get the one with the lowest ID, which has been added first.
85
- $primary_key = array_keys( $domain_ids, min( $domain_ids ), true );
86
- $primary_key = reset( $primary_key );
87
- }
88
-
89
- //* Set 0, as we check for false to begin with.
90
- $mapped_domain = isset( $mapped_domains[ $primary_key ] ) ? $mapped_domains[ $primary_key ] : 0;
91
-
92
- \the_seo_framework()->object_cache_set( $cache_key, $mapped_domain, 3600 );
93
- endif;
94
-
95
- if ( $mapped_domain ) :
96
-
97
- $domain = isset( $mapped_domain->domain ) ? $mapped_domain->domain : '0';
98
- $scheme = isset( $mapped_domain->scheme ) ? $mapped_domain->scheme : '';
99
-
100
- //* Fallback to is_ssl if no scheme has been found.
101
- if ( '' === $scheme )
102
- $scheme = \the_seo_framework()->is_ssl() ? '1' : '0';
103
-
104
- if ( '1' === $scheme ) {
105
- //* HTTPS
106
- $scheme_full = 'https://';
107
- $scheme = 'https';
108
- } elseif ( '2' === $scheme ) {
109
- //* HTTP/HTTPS, use preferred scheme and build URL expected (https).
110
- // This will be converted back anyway later if preferred is http.
111
- $scheme_full = 'https://';
112
- $scheme = '';
113
- } else {
114
- //* HTTP
115
- $scheme_full = 'http://';
116
- $scheme = 'http';
117
- }
118
-
119
- //* Put it all together.
120
- $url = \trailingslashit( $scheme_full . $domain ) . ltrim( $path, ' \\/' );
121
-
122
- if ( $get_scheme ) {
123
- return array( $url, $scheme );
124
- } else {
125
- return $url;
126
- }
127
- endif;
128
-
129
- if ( $get_scheme ) {
130
- return array( '', '' );
131
- } else {
132
- return '';
133
- }
134
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/compat/theme-genesis.php CHANGED
@@ -21,35 +21,20 @@ defined( 'ABSPATH' ) and $_this = \the_seo_framework_class() and $this instanceo
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', 'The_SEO_Framework\\_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
- * @since 2.9.3 No longer used. It is conflicting with the homepage Schema output.
45
- * @access private
46
- */
47
- function _genesis_add_head_attributes() {
48
- //* Reverse the removal of head attributes, this shouldn't affect SEO.
49
- \remove_filter( 'genesis_attr_head', 'genesis_attributes_empty_class' );
50
- \add_filter( 'genesis_attr_head', 'genesis_attributes_head' );
51
- }
52
-
53
  \add_filter( 'the_seo_framework_get_term_meta', __NAMESPACE__ . '\\_genesis_get_term_meta', 10, 2 );
54
  /**
55
  * Returns Genesis term meta.
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_filter( 'the_seo_framework_get_term_meta', __NAMESPACE__ . '\\_genesis_get_term_meta', 10, 2 );
39
  /**
40
  * Returns Genesis term meta.
inc/compat/wp-460.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) or die;
4
+
5
+ if ( ! function_exists( 'wp_get_canonical_url' ) ) :
6
+ /**
7
+ * Returns the canonical URL for a post.
8
+ *
9
+ * When the post is the same as the current requested page the function will handle the
10
+ * pagination arguments too.
11
+ *
12
+ * @since 4.6.0
13
+ *
14
+ * @param int|WP_Post $post Optional. Post ID or object. Default is global `$post`.
15
+ * @return string|false The canonical URL, or false if the post does not exist or has not
16
+ * been published yet.
17
+ */
18
+ function wp_get_canonical_url( $post = null ) {
19
+ $post = get_post( $post );
20
+
21
+ if ( ! $post ) {
22
+ return false;
23
+ }
24
+
25
+ if ( 'publish' !== $post->post_status ) {
26
+ return false;
27
+ }
28
+
29
+ $canonical_url = get_permalink( $post );
30
+
31
+ // If a canonical is being generated for the current page, make sure it has pagination if needed.
32
+ if ( $post->ID === get_queried_object_id() ) {
33
+ $page = get_query_var( 'page', 0 );
34
+ if ( $page >= 2 ) {
35
+ if ( '' == get_option( 'permalink_structure' ) ) {
36
+ $canonical_url = add_query_arg( 'page', $page, $canonical_url );
37
+ } else {
38
+ $canonical_url = trailingslashit( $canonical_url ) . user_trailingslashit( $page, 'single_paged' );
39
+ }
40
+ }
41
+
42
+ $cpage = get_query_var( 'cpage', 0 );
43
+ if ( $cpage ) {
44
+ $canonical_url = get_comments_pagenum_link( $cpage );
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Filters the canonical URL for a post.
50
+ *
51
+ * @since 4.6.0
52
+ *
53
+ * @param string $canonical_url The post's canonical URL.
54
+ * @param WP_Post $post Post object.
55
+ */
56
+ return apply_filters( 'get_canonical_url', $canonical_url, $post );
57
+ }
58
+ endif;
inc/functions/optionsapi.php CHANGED
@@ -136,7 +136,6 @@ function the_seo_framework_options_pagehook() {
136
  return null;
137
  }
138
 
139
-
140
  /**
141
  * Fetch an option from The SEO Framework.
142
  *
@@ -205,7 +204,7 @@ function the_seo_framework_the_url_from_cache() {
205
  $theseoframework = the_seo_framework();
206
 
207
  if ( isset( $theseoframework ) )
208
- return $theseoframework->the_url_from_cache();
209
 
210
  return null;
211
  }
136
  return null;
137
  }
138
 
 
139
  /**
140
  * Fetch an option from The SEO Framework.
141
  *
204
  $theseoframework = the_seo_framework();
205
 
206
  if ( isset( $theseoframework ) )
207
+ return $theseoframework->get_current_canonical_url();
208
 
209
  return null;
210
  }
inc/functions/plugin-activation.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'THE_SEO_FRAMEWORK_DIR_PATH' ) or die;
8
+
9
+ /**
10
+ * The SEO Framework plugin
11
+ * Copyright (C) 2015 - 2017 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
+ //! @php7+ convert to IIFE
27
+ \The_SEO_Framework\_activation_setup_sitemap();
28
+ \The_SEO_Framework\_activation_set_options_autoload();
29
+
30
+ /**
31
+ * Add and Flush rewrite rules on plugin activation.
32
+ *
33
+ * @since 2.6.6
34
+ * @since 2.7.1: 1. Now no longer reinitializes global $wp_rewrite.
35
+ * 2. Now always listens to the preconditions of the sitemap addition.
36
+ * 3. Now flushes the rules on shutdown.
37
+ * @since 2.8.0: Added namespace and renamed function.
38
+ * @access private
39
+ */
40
+ function _activation_setup_sitemap() {
41
+
42
+ $the_seo_framework = \the_seo_framework();
43
+
44
+ if ( isset( $the_seo_framework ) ) {
45
+ $the_seo_framework->rewrite_rule_sitemap();
46
+ \add_action( 'shutdown', 'flush_rewrite_rules' );
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Turns on autoloading for The SEO Framework main options.
52
+ *
53
+ * @since 2.9.2
54
+ * @access private
55
+ */
56
+ function _activation_set_options_autoload() {
57
+
58
+ $the_seo_framework = \the_seo_framework();
59
+
60
+ if ( isset( $the_seo_framework ) ) {
61
+ $options = $the_seo_framework->get_all_options();
62
+ $setting = THE_SEO_FRAMEWORK_SITE_OPTIONS;
63
+
64
+ \remove_all_filters( "pre_update_option_{$setting}" );
65
+ \remove_all_actions( "update_option_{$setting}" );
66
+ \remove_all_filters( "sanitize_option_{$setting}" );
67
+
68
+ // Set to false, so we can reset the options.
69
+ $_success = \update_option( $setting, false );
70
+ if ( $_success )
71
+ \update_option( $setting, $options, 'yes' );
72
+ }
73
+ }
inc/functions/plugin-deactivation.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework
4
+ */
5
+ namespace The_SEO_Framework;
6
+
7
+ defined( 'THE_SEO_FRAMEWORK_DIR_PATH' ) or die;
8
+
9
+ /**
10
+ * The SEO Framework plugin
11
+ * Copyright (C) 2015 - 2017 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
+ //! @php7+ convert to IIFE
27
+ \The_SEO_Framework\_deactivation_unset_options_autoload();
28
+ \The_SEO_Framework\_deactivation_unset_sitemap();
29
+
30
+ /**
31
+ * Flush rewrite rules on plugin deactivation.
32
+ *
33
+ * @since 2.6.6
34
+ * @since 2.7.1: 1. Now no longer reinitializes global $wp_rewrite.
35
+ * 2. Now flushes the rules on shutdown.
36
+ * @since 2.8.0: Added namespace and renamed function.
37
+ * @access private
38
+ * @global object $wp_rewrite
39
+ */
40
+ function _deactivation_unset_sitemap() {
41
+
42
+ unset( $GLOBALS['wp_rewrite']->extra_rules_top['sitemap\.xml$'] );
43
+ unset( $GLOBALS['wp_rewrite']->extra_rules_top['sitemap\.xsl$'] );
44
+
45
+ \add_action( 'shutdown', 'flush_rewrite_rules' );
46
+ }
47
+
48
+ /**
49
+ * Turns off autoloading for The SEO Framework main options.
50
+ *
51
+ * @since 2.9.2
52
+ * @access private
53
+ */
54
+ function _deactivation_unset_options_autoload() {
55
+
56
+ $the_seo_framework = \the_seo_framework();
57
+
58
+ if ( isset( $the_seo_framework ) ) {
59
+ $options = $the_seo_framework->get_all_options();
60
+ $setting = THE_SEO_FRAMEWORK_SITE_OPTIONS;
61
+
62
+ \remove_all_filters( "pre_update_option_{$setting}" );
63
+ \remove_all_actions( "update_option_{$setting}" );
64
+ \remove_all_filters( "sanitize_option_{$setting}" );
65
+
66
+ // Set to false, so we can reset the options.
67
+ $_success = \update_option( $setting, false );
68
+ if ( $_success )
69
+ \update_option( $setting, $options, 'no' );
70
+ }
71
+ }
inc/functions/plugin-test-server.php CHANGED
@@ -91,7 +91,7 @@ function the_seo_framework_test_server_phase() {
91
  }
92
 
93
  if ( ! function_exists( 'deactivate_plugins' ) )
94
- require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
95
 
96
  $admin = is_admin();
97
  $silent = ! $admin;
91
  }
92
 
93
  if ( ! function_exists( 'deactivate_plugins' ) )
94
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
95
 
96
  $admin = is_admin();
97
  $silent = ! $admin;
inc/functions/upgrade.php CHANGED
@@ -27,6 +27,20 @@ defined( 'ABSPATH' ) or die;
27
  * @access private
28
  */
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  add_action( 'admin_init', 'the_seo_framework_do_upgrade', 20 );
31
  /**
32
  * Upgrade The SEO Framework to the latest version.
@@ -38,12 +52,15 @@ add_action( 'admin_init', 'the_seo_framework_do_upgrade', 20 );
38
  *
39
  * @since 2.7.0
40
  * @since 2.9.4 No longer tests WP version. This file won't be loaded anyway if rendered incompatible.
 
41
  *
42
  * @thanks StudioPress for some code.
43
  */
44
  function the_seo_framework_do_upgrade() {
45
 
46
- if ( get_option( 'the_seo_framework_upgraded_db_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION )
 
 
47
  return;
48
 
49
  //* If the WordPress Database hasn't been upgraded yet, make the user upgrade first.
@@ -52,14 +69,22 @@ function the_seo_framework_do_upgrade() {
52
  exit;
53
  }
54
 
55
- if ( get_option( 'the_seo_framework_upgraded_db_version' ) < '2701' )
56
  the_seo_framework_do_upgrade_2701();
57
-
58
- if ( get_option( 'the_seo_framework_upgraded_db_version' ) < '2802' )
 
59
  the_seo_framework_do_upgrade_2802();
60
-
61
- if ( get_option( 'the_seo_framework_upgraded_db_version' ) < '2900' )
 
62
  the_seo_framework_do_upgrade_2900();
 
 
 
 
 
 
63
 
64
  do_action( 'the_seo_framework_upgraded' );
65
  }
@@ -103,6 +128,7 @@ add_action( 'admin_notices', 'the_seo_framework_output_upgrade_notices' );
103
  * Outputs available upgrade notices.
104
  *
105
  * @since 2.9.0
 
106
  * @uses the_seo_framework_add_upgrade_notice()
107
  */
108
  function the_seo_framework_output_upgrade_notices() {
@@ -110,7 +136,8 @@ function the_seo_framework_output_upgrade_notices() {
110
  $notices = the_seo_framework_add_upgrade_notice( '', true );
111
 
112
  foreach ( $notices as $notice ) {
113
- the_seo_framework()->do_dismissible_notice( $notice, 'updated' );
 
114
  }
115
  }
116
 
@@ -150,7 +177,7 @@ function the_seo_framework_do_upgrade_2802() {
150
  * Updates Twitter 'photo' card option to 'summary_large_image'.
151
  * Invalidates object cache if changed.
152
  *
153
- * @since 2.8.0
154
  */
155
  function the_seo_framework_do_upgrade_2900() {
156
 
@@ -168,3 +195,40 @@ function the_seo_framework_do_upgrade_2900() {
168
 
169
  update_option( 'the_seo_framework_upgraded_db_version', '2900' );
170
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  * @access private
28
  */
29
 
30
+ the_seo_framework_previous_db_version(); // sets cache.
31
+ /**
32
+ * Returns the version set before upgrading began.
33
+ *
34
+ * @since 3.0.0
35
+ * @staticvar string $cache
36
+ *
37
+ * @return string The prior-to-upgrade TSF db version.
38
+ */
39
+ function the_seo_framework_previous_db_version() {
40
+ static $cache;
41
+ return isset( $cache ) ? $cache : $cache = get_option( 'the_seo_framework_upgraded_db_version', '0' );
42
+ }
43
+
44
  add_action( 'admin_init', 'the_seo_framework_do_upgrade', 20 );
45
  /**
46
  * Upgrade The SEO Framework to the latest version.
52
  *
53
  * @since 2.7.0
54
  * @since 2.9.4 No longer tests WP version. This file won't be loaded anyway if rendered incompatible.
55
+ * @since 3.0.0 Fewer option calls are now made when version is higher than former checks.
56
  *
57
  * @thanks StudioPress for some code.
58
  */
59
  function the_seo_framework_do_upgrade() {
60
 
61
+ $version = the_seo_framework_previous_db_version();
62
+
63
+ if ( $version >= THE_SEO_FRAMEWORK_DB_VERSION )
64
  return;
65
 
66
  //* If the WordPress Database hasn't been upgraded yet, make the user upgrade first.
69
  exit;
70
  }
71
 
72
+ if ( $version < '2701' ) {
73
  the_seo_framework_do_upgrade_2701();
74
+ $version = '2701';
75
+ }
76
+ if ( $version < '2802' ) {
77
  the_seo_framework_do_upgrade_2802();
78
+ $version = '2802';
79
+ }
80
+ if ( $version < '2900' ) {
81
  the_seo_framework_do_upgrade_2900();
82
+ $version = '2900';
83
+ }
84
+ if ( $version < '3001' ) {
85
+ the_seo_framework_do_upgrade_3001();
86
+ $version = '3001';
87
+ }
88
 
89
  do_action( 'the_seo_framework_upgraded' );
90
  }
128
  * Outputs available upgrade notices.
129
  *
130
  * @since 2.9.0
131
+ * @since 3.0.0 Added prefix.
132
  * @uses the_seo_framework_add_upgrade_notice()
133
  */
134
  function the_seo_framework_output_upgrade_notices() {
136
  $notices = the_seo_framework_add_upgrade_notice( '', true );
137
 
138
  foreach ( $notices as $notice ) {
139
+ //* @TODO rtl?
140
+ the_seo_framework()->do_dismissible_notice( 'SEO: ' . $notice, 'updated' );
141
  }
142
  }
143
 
177
  * Updates Twitter 'photo' card option to 'summary_large_image'.
178
  * Invalidates object cache if changed.
179
  *
180
+ * @since 2.9.0
181
  */
182
  function the_seo_framework_do_upgrade_2900() {
183
 
195
 
196
  update_option( 'the_seo_framework_upgraded_db_version', '2900' );
197
  }
198
+
199
+ /**
200
+ * Converts sitemap timestamp settings to global timestamp settings.
201
+ * Adds new character counter settings.
202
+ * Invalidates object cache.
203
+ *
204
+ * @since 3.0.0
205
+ */
206
+ function the_seo_framework_do_upgrade_3001() {
207
+
208
+ $tsf = the_seo_framework();
209
+ $previous_version = the_seo_framework_previous_db_version();
210
+
211
+ $timestamp_format = $tsf->get_option( 'sitemap_timestamps', false );
212
+ //= Only change if option exists. Falls back to default upgrader instead.
213
+ if ( '' !== $timestamp_format ) {
214
+ $tsf->update_option( 'timestamps_format', (string) (int) $timestamp_format );
215
+ //= Only set notice if an actual upgrade took place. (redundancy check)
216
+ if ( $previous_version > '0' ) {
217
+ the_seo_framework_add_upgrade_notice(
218
+ esc_html__( 'The previous sitemap timestamp settings have been converted into new global timestamp settings.', 'autodescription' )
219
+ );
220
+ }
221
+ }
222
+
223
+ if ( $previous_version > '0' ) {
224
+ $tsf->update_option( 'display_character_counter', 1 );
225
+ $tsf->update_option( 'display_pixel_counter', 1 );
226
+ } else {
227
+ $tsf->update_option( 'display_character_counter', 0 );
228
+ $tsf->update_option( 'display_pixel_counter', 1 );
229
+ }
230
+
231
+ $tsf->delete_object_cache();
232
+
233
+ update_option( 'the_seo_framework_upgraded_db_version', '3001' );
234
+ }
inc/views/admin/index.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Private property began the instant somebody had a mind of his own.
4
+ *
5
+ * - Edward Estlin "E. E." Cummings
6
+ */
inc/views/admin/seo-settings-columns.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ ?>
9
+ <div class="metabox-holder columns-2">
10
+ <div class="postbox-container-1">
11
+ <?php
12
+ \do_action( 'the_seo_framework_before_siteadmin_metaboxes', $this->seo_settings_page_hook );
13
+
14
+ \do_meta_boxes( $this->seo_settings_page_hook, 'main', null );
15
+
16
+ if ( isset( $GLOBALS['wp_meta_boxes'][ $this->seo_settings_page_hook ]['main_extra'] ) )
17
+ \do_meta_boxes( $this->seo_settings_page_hook, 'main_extra', null );
18
+
19
+ \do_action( 'the_seo_framework_after_siteadmin_metaboxes', $this->seo_settings_page_hook );
20
+ ?>
21
+ </div>
22
+ <div class="postbox-container-2">
23
+ <?php
24
+ \do_action( 'the_seo_framework_before_siteadmin_metaboxes_side', $this->seo_settings_page_hook );
25
+
26
+ /**
27
+ * @TODO fill this in
28
+ * @priority low 2.9.0
29
+ */
30
+
31
+ \do_action( 'the_seo_framework_after_siteadmin_metaboxes_side', $this->seo_settings_page_hook );
32
+ ?>
33
+ </div>
34
+ </div>
35
+ <?php
inc/views/admin/seo-settings-wrap.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ ?>
9
+ <div class="wrap tsf-metaboxes">
10
+ <form method="post" action="options.php">
11
+ <?php \wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
12
+ <?php \wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
13
+ <?php \settings_fields( $this->settings_field ); ?>
14
+
15
+ <div class="tsf-top-wrap">
16
+ <h1><?php echo \esc_html( \get_admin_page_title() ); ?></h1>
17
+ <p class="tsf-top-buttons">
18
+ <?php
19
+ \submit_button( $this->page_defaults['save_button_text'], 'primary', 'submit', false, array( 'id' => '' ) );
20
+ \submit_button( $this->page_defaults['reset_button_text'], 'secondary tsf-js-confirm-reset', $this->get_field_name( 'tsf-settings-reset' ), false, array( 'id' => '' ) );
21
+ ?>
22
+ </p>
23
+ </div>
24
+
25
+ <?php \do_action( "{$this->seo_settings_page_hook}_settings_page_boxes", $this->seo_settings_page_hook ); ?>
26
+
27
+ <div class="tsf-bottom-buttons">
28
+ <?php
29
+ \submit_button( $this->page_defaults['save_button_text'], 'primary', 'submit', false, array( 'id' => '' ) );
30
+ \submit_button( $this->page_defaults['reset_button_text'], 'secondary tsf-js-confirm-reset', $this->get_field_name( 'tsf-settings-reset' ), false, array( 'id' => '' ) );
31
+ ?>
32
+ </div>
33
+ </form>
34
+ </div>
35
+ <?php
36
+ //= Add postbox listeners
37
+ ?>
38
+ <script type="text/javascript">
39
+ //<![CDATA[
40
+ jQuery(document).ready( function($) {
41
+ // close postboxes that should be closed
42
+ $('.if-js-closed').removeClass('if-js-closed').addClass('closed');
43
+ // postboxes setup
44
+ postboxes.add_postbox_toggles('<?php echo \esc_js( $this->seo_settings_page_hook ); ?>');
45
+ });
46
+ //]]>
47
+ </script>
48
+ <?php
inc/views/inpost/seo-settings-singular.php CHANGED
@@ -73,7 +73,7 @@ switch ( $instance ) :
73
 
74
  case 'inpost_general' :
75
  //* Temporarily. TODO refactor.
76
- $tit_len_parsed = $desc_len_parsed = 0;
77
  $doctitle_placeholder = $description_placeholder = '';
78
  $this->_get_inpost_general_tab_vars( $tit_len_parsed, $doctitle_placeholder, $desc_len_parsed, $description_placeholder );
79
  //= End temporarily.
@@ -108,36 +108,23 @@ switch ( $instance ) :
108
  printf( esc_html__( 'Custom %s Title', 'autodescription' ), esc_html( $type ) );
109
  ?>
110
  </strong></div>
111
- <div>
112
- <?php
113
- $this->make_info(
114
- __( 'Recommended Length: 50 to 55 characters', 'autodescription' ),
115
- 'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#3'
116
- );
117
- ?>
118
- </div>
119
  </label>
120
- <span class="description tsf-counter">
121
- <?php
122
- printf(
123
- /* translators: %s = number */
124
- esc_html__( 'Characters Used: %s', 'autodescription' ),
125
- '<span id="autodescription_title_chars">' . (int) mb_strlen( $tit_len_parsed ) . '</span>'
126
- );
127
- ?>
128
- <span class="hide-if-no-js tsf-ajax"></span>
129
- </span>
130
  </div>
131
  </div>
132
  <div class="tsf-flex-setting-input tsf-flex">
133
  <div id="tsf-title-wrap">
134
  <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' ) ); ?>" autocomplete=off />
135
- <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
136
  </div>
137
  </div>
138
  </div>
139
 
140
-
141
  <div class="tsf-flex-setting tsf-flex">
142
  <div class="tsf-flex-setting-label tsf-flex">
143
  <div class="tsf-flex-setting-label-inner-wrap tsf-flex">
@@ -148,18 +135,13 @@ switch ( $instance ) :
148
  printf( esc_html__( 'Custom %s Description', 'autodescription' ), esc_html( $type ) );
149
  ?>
150
  </strong></div>
151
- <div><?php $this->make_info( __( 'Recommended Length: 145 to 155 characters', 'autodescription' ), 'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#1' ); ?></div>
152
  </label>
153
- <span class="description tsf-counter">
154
- <?php
155
- printf(
156
- /* translators: %s = number */
157
- esc_html__( 'Characters Used: %s', 'autodescription' ),
158
- '<span id="autodescription_description_chars">' . (int) mb_strlen( $desc_len_parsed ) . '</span>'
159
- );
160
- ?>
161
- <span class="hide-if-no-js tsf-ajax"></span>
162
- </span>
163
  </div>
164
  </div>
165
  <div class="tsf-flex-setting-input tsf-flex">
@@ -173,7 +155,7 @@ switch ( $instance ) :
173
  //* Fetch Canonical URL.
174
  $canonical = $this->get_custom_field( '_genesis_canonical_uri' );
175
  //* Fetch Canonical URL Placeholder.
176
- $canonical_placeholder = $this->the_url_from_cache( '', $post_id, false, false );
177
 
178
  ?>
179
  <div class="tsf-flex-setting tsf-flex">
@@ -184,11 +166,7 @@ switch ( $instance ) :
184
  <div>
185
  <?php
186
  $this->make_info(
187
- sprintf(
188
- /* translators: %s = Post type name */
189
- __( 'Preferred %s URL location', 'autodescription' ),
190
- $type
191
- ),
192
  'https://support.google.com/webmasters/answer/139066?hl=' . $language
193
  );
194
  ?>
@@ -219,7 +197,7 @@ switch ( $instance ) :
219
  echo ' ';
220
  $this->make_info(
221
  sprintf(
222
- __( 'Tell Search Engines not to show this %s in their search results', 'autodescription' ),
223
  $type
224
  ),
225
  'https://support.google.com/webmasters/answer/93710?hl=' . $language
@@ -233,7 +211,10 @@ switch ( $instance ) :
233
  /* translators: 1: Option, 2: Post or Page */
234
  printf( esc_html__( 'Apply %1$s to this %2$s', 'autodescription' ), $this->code_wrap( 'nofollow' ), esc_html( $type ) );
235
  echo ' ';
236
- $this->make_info( sprintf( __( 'Tell Search Engines not to follow links on this %s', 'autodescription' ), $type ), 'https://support.google.com/webmasters/answer/96569?hl=' . $language );
 
 
 
237
  ?>
238
  </label>
239
  </div>
@@ -248,7 +229,13 @@ switch ( $instance ) :
248
  );
249
  echo ' ';
250
  /* translators: %s = Post type name */
251
- $this->make_info( sprintf( __( 'Tell Search Engines not to save a cached copy of this %s', 'autodescription' ), $type ), 'https://support.google.com/webmasters/answer/79812?hl=' . $language );
 
 
 
 
 
 
252
  ?>
253
  </label>
254
  </div>
@@ -256,7 +243,7 @@ switch ( $instance ) :
256
  </div>
257
 
258
  <?php
259
- $can_do_archive_query = $this->is_option_checked( 'alter_archive_query' ) && $this->post_type_supports_taxonomies();
260
  $can_do_search_query = $this->is_option_checked( 'alter_search_query' );
261
  ?>
262
 
@@ -278,7 +265,7 @@ switch ( $instance ) :
278
  printf( esc_html__( 'Exclude this %s from local search', 'autodescription' ), esc_html( $type ) );
279
  echo ' ';
280
  /* translators: %s = Post type name */
281
- $this->make_info( sprintf( __( 'This excludes this %s from local on-site search results', 'autodescription' ), $type ) );
282
  ?>
283
  </label>
284
  </div>
@@ -288,10 +275,10 @@ switch ( $instance ) :
288
  <label for="autodescription_exclude_from_archive"><input type="checkbox" name="autodescription[exclude_from_archive]" id="autodescription_exclude_from_archive" value="1" <?php checked( $this->get_custom_field( 'exclude_from_archive' ) ); ?> />
289
  <?php
290
  /* translators: %s = Post type name */
291
- printf( esc_html__( 'Exclude this %s from all archive listings', 'autodescription' ), esc_html( $type ) );
292
  echo ' ';
293
  /* translators: %s = Post type name */
294
- $this->make_info( sprintf( __( 'This excludes this %s from on-site archive pages', 'autodescription' ), $type ) );
295
  ?>
296
  </label>
297
  </div>
@@ -310,7 +297,7 @@ switch ( $instance ) :
310
  <div>
311
  <?php
312
  $this->make_info(
313
- __( 'This will force visitors to go to another URL', 'autodescription' ),
314
  'https://support.google.com/webmasters/answer/93633?hl=' . $language
315
  );
316
  ?>
@@ -340,7 +327,7 @@ switch ( $instance ) :
340
  $this->make_info(
341
  sprintf(
342
  /* translators: %s = Post type name */
343
- __( 'Preferred %s Social Image URL location', 'autodescription' ),
344
  $type
345
  ),
346
  'https://developers.facebook.com/docs/sharing/best-practices#images'
73
 
74
  case 'inpost_general' :
75
  //* Temporarily. TODO refactor.
76
+ $tit_len_parsed = $desc_len_parsed = '';
77
  $doctitle_placeholder = $description_placeholder = '';
78
  $this->_get_inpost_general_tab_vars( $tit_len_parsed, $doctitle_placeholder, $desc_len_parsed, $description_placeholder );
79
  //= End temporarily.
108
  printf( esc_html__( 'Custom %s Title', 'autodescription' ), esc_html( $type ) );
109
  ?>
110
  </strong></div>
 
 
 
 
 
 
 
 
111
  </label>
112
+ <?php
113
+ $this->get_option( 'display_character_counter' )
114
+ and $this->output_character_counter_wrap( 'autodescription_title', $tit_len_parsed );
115
+ $this->get_option( 'display_pixel_counter' )
116
+ and $this->output_pixel_counter_wrap( 'autodescription_title', 'title' );
117
+ ?>
 
 
 
 
118
  </div>
119
  </div>
120
  <div class="tsf-flex-setting-input tsf-flex">
121
  <div id="tsf-title-wrap">
122
  <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' ) ); ?>" autocomplete=off />
123
+ <?php echo $this->output_floating_title_elements(); ?>
124
  </div>
125
  </div>
126
  </div>
127
 
 
128
  <div class="tsf-flex-setting tsf-flex">
129
  <div class="tsf-flex-setting-label tsf-flex">
130
  <div class="tsf-flex-setting-label-inner-wrap tsf-flex">
135
  printf( esc_html__( 'Custom %s Description', 'autodescription' ), esc_html( $type ) );
136
  ?>
137
  </strong></div>
 
138
  </label>
139
+ <?php
140
+ $this->get_option( 'display_character_counter' )
141
+ and $this->output_character_counter_wrap( 'autodescription_description', $desc_len_parsed );
142
+ $this->get_option( 'display_pixel_counter' )
143
+ and $this->output_pixel_counter_wrap( 'autodescription_description', 'description' );
144
+ ?>
 
 
 
 
145
  </div>
146
  </div>
147
  <div class="tsf-flex-setting-input tsf-flex">
155
  //* Fetch Canonical URL.
156
  $canonical = $this->get_custom_field( '_genesis_canonical_uri' );
157
  //* Fetch Canonical URL Placeholder.
158
+ $canonical_placeholder = $this->create_canonical_url( array( 'id' => $post_id ) );
159
 
160
  ?>
161
  <div class="tsf-flex-setting tsf-flex">
166
  <div>
167
  <?php
168
  $this->make_info(
169
+ __( 'This urges search engines to go to the outputted URL.', 'autodescription' ),
 
 
 
 
170
  'https://support.google.com/webmasters/answer/139066?hl=' . $language
171
  );
172
  ?>
197
  echo ' ';
198
  $this->make_info(
199
  sprintf(
200
+ __( 'This tells search engines not to show this %s in their search results.', 'autodescription' ),
201
  $type
202
  ),
203
  'https://support.google.com/webmasters/answer/93710?hl=' . $language
211
  /* translators: 1: Option, 2: Post or Page */
212
  printf( esc_html__( 'Apply %1$s to this %2$s', 'autodescription' ), $this->code_wrap( 'nofollow' ), esc_html( $type ) );
213
  echo ' ';
214
+ $this->make_info(
215
+ sprintf( __( 'This tells search engines not to follow links on this %s.', 'autodescription' ), $type ),
216
+ 'https://support.google.com/webmasters/answer/96569?hl=' . $language
217
+ );
218
  ?>
219
  </label>
220
  </div>
229
  );
230
  echo ' ';
231
  /* translators: %s = Post type name */
232
+ $this->make_info(
233
+ sprintf(
234
+ __( 'This tells search engines not to save a cached copy of this %s.', 'autodescription' ),
235
+ $type
236
+ ),
237
+ 'https://support.google.com/webmasters/answer/79812?hl=' . $language
238
+ );
239
  ?>
240
  </label>
241
  </div>
243
  </div>
244
 
245
  <?php
246
+ $can_do_archive_query = $this->post_type_supports_taxonomies() && $this->is_option_checked( 'alter_archive_query' );
247
  $can_do_search_query = $this->is_option_checked( 'alter_search_query' );
248
  ?>
249
 
265
  printf( esc_html__( 'Exclude this %s from local search', 'autodescription' ), esc_html( $type ) );
266
  echo ' ';
267
  /* translators: %s = Post type name */
268
+ $this->make_info( sprintf( __( 'This excludes this %s from local on-site search results.', 'autodescription' ), $type ) );
269
  ?>
270
  </label>
271
  </div>
275
  <label for="autodescription_exclude_from_archive"><input type="checkbox" name="autodescription[exclude_from_archive]" id="autodescription_exclude_from_archive" value="1" <?php checked( $this->get_custom_field( 'exclude_from_archive' ) ); ?> />
276
  <?php
277
  /* translators: %s = Post type name */
278
+ printf( esc_html__( 'Exclude this %s from all archive listings.', 'autodescription' ), esc_html( $type ) );
279
  echo ' ';
280
  /* translators: %s = Post type name */
281
+ $this->make_info( sprintf( __( 'This excludes this %s from on-site archive pages.', 'autodescription' ), $type ) );
282
  ?>
283
  </label>
284
  </div>
297
  <div>
298
  <?php
299
  $this->make_info(
300
+ __( 'This will force visitors to go to another URL.', 'autodescription' ),
301
  'https://support.google.com/webmasters/answer/93633?hl=' . $language
302
  );
303
  ?>
327
  $this->make_info(
328
  sprintf(
329
  /* translators: %s = Post type name */
330
+ __( 'Set preferred %s Social Image URL location.', 'autodescription' ),
331
  $type
332
  ),
333
  'https://developers.facebook.com/docs/sharing/best-practices#images'
inc/views/inpost/seo-settings-tt.php CHANGED
@@ -11,7 +11,7 @@ $language = $this->google_language();
11
  //* Fetch Term ID and taxonomy.
12
  $term_id = $object->term_id;
13
  $taxonomy = $object->taxonomy;
14
- $data = $this->get_term_data( $object, $term_id );
15
 
16
  $title = isset( $data['doctitle'] ) ? $data['doctitle'] : '';
17
  $description = isset( $data['description'] ) ? $data['description'] : '';
@@ -67,7 +67,12 @@ $title_placeholder = $generated_doctitle;
67
  $description_placeholder = $generated_description;
68
 
69
  ?>
70
- <h3><?php printf( esc_html__( '%s SEO Settings', 'autodescription' ), esc_html( $type ) ); ?></h3>
 
 
 
 
 
71
 
72
  <table class="form-table">
73
  <tbody>
@@ -83,35 +88,47 @@ $description_placeholder = $generated_description;
83
  <tr class="form-field">
84
  <th scope="row" valign="top">
85
  <label for="autodescription-meta[doctitle]">
86
- <strong><?php printf( esc_html__( '%s Title', 'autodescription' ), esc_html( $type ) ); ?></strong>
87
- <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>
 
 
 
 
88
  </label>
 
 
 
 
 
 
89
  </th>
90
  <td>
91
  <div id="tsf-title-wrap">
92
- <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" autocomplete=off />
93
- <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
94
  </div>
95
- <p class="description tsf-counter">
96
- <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="autodescription-meta[doctitle]_chars">' . esc_html( mb_strlen( $tit_len_parsed ) ) . '</span>' ); ?>
97
- <span class="hide-if-no-js tsf-ajax"></span>
98
- </p>
99
  </td>
100
  </tr>
101
 
102
  <tr class="form-field">
103
  <th scope="row" valign="top">
104
  <label for="autodescription-meta[description]">
105
- <strong><?php printf( esc_html__( '%s Meta Description', 'autodescription' ), esc_html( $type ) ); ?></strong>
106
- <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>
 
 
 
 
107
  </label>
 
 
 
 
 
 
108
  </th>
109
  <td>
110
  <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>
111
- <p class="description tsf-counter">
112
- <?php printf( esc_html__( 'Characters Used: %s', 'autodescription' ), '<span id="autodescription-meta[description]_chars">' . esc_html( mb_strlen( $desc_len_parsed ) ) . '</span>' ); ?>
113
- <span class="hide-if-no-js tsf-ajax"></span>
114
- </p>
115
  </td>
116
  </tr>
117
 
@@ -119,25 +136,54 @@ $description_placeholder = $generated_description;
119
  <th scope="row" valign="top"><?php esc_html_e( 'Robots Meta Settings', 'autodescription' ); ?></th>
120
  <td>
121
  <label for="autodescription-meta[noindex]"><input name="autodescription-meta[noindex]" id="autodescription-meta[noindex]" type="checkbox" value="1" <?php checked( $noindex ); ?> />
122
- <?php printf( esc_html__( 'Apply %s to this term?', 'autodescription' ), $this->code_wrap( 'noindex' ) ); ?>
123
- <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>
 
 
 
 
 
 
 
 
 
124
  </label>
125
 
126
  <br>
127
 
128
  <label for="autodescription-meta[nofollow]"><input name="autodescription-meta[nofollow]" id="autodescription-meta[nofollow]" type="checkbox" value="1" <?php checked( $nofollow ); ?> />
129
- <?php printf( esc_html__( 'Apply %s to this term?', 'autodescription' ), $this->code_wrap( 'nofollow' ) ); ?>
130
- <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>
 
 
 
 
 
 
 
 
 
131
  </label>
132
 
133
  <br>
134
 
135
  <label for="autodescription-meta[noarchive]"><input name="autodescription-meta[noarchive]" id="autodescription-meta[noarchive]" type="checkbox" value="1" <?php checked( $noarchive ); ?> />
136
- <?php printf( esc_html__( 'Apply %s to this term?', 'autodescription' ), $this->code_wrap( 'noarchive' ) ); ?>
137
- <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>
 
 
 
 
 
 
 
 
 
138
  </label>
139
 
140
- <?php // Saved flag, if set then it won't fetch for Genesis meta anymore ?>
 
 
141
  <label class="hidden" for="autodescription-meta[saved_flag]">
142
  <input name="autodescription-meta[saved_flag]" id="autodescription-meta[saved_flag]" type="checkbox" value="1" checked='checked' />
143
  </label>
11
  //* Fetch Term ID and taxonomy.
12
  $term_id = $object->term_id;
13
  $taxonomy = $object->taxonomy;
14
+ $data = $this->get_term_meta( $object->term_id );
15
 
16
  $title = isset( $data['doctitle'] ) ? $data['doctitle'] : '';
17
  $description = isset( $data['description'] ) ? $data['description'] : '';
67
  $description_placeholder = $generated_description;
68
 
69
  ?>
70
+ <h3>
71
+ <?php
72
+ /* translators: %s = Term type */
73
+ printf( esc_html__( '%s SEO Settings', 'autodescription' ), esc_html( $type ) );
74
+ ?>
75
+ </h3>
76
 
77
  <table class="form-table">
78
  <tbody>
88
  <tr class="form-field">
89
  <th scope="row" valign="top">
90
  <label for="autodescription-meta[doctitle]">
91
+ <strong>
92
+ <?php
93
+ /* translators: %s = Term type */
94
+ printf( esc_html__( '%s Title', 'autodescription' ), esc_html( $type ) );
95
+ ?>
96
+ </strong>
97
  </label>
98
+ <?php
99
+ $this->get_option( 'display_character_counter' )
100
+ and $this->output_character_counter_wrap( 'autodescription-meta[doctitle]', $tit_len_parsed );
101
+ $this->get_option( 'display_pixel_counter' )
102
+ and $this->output_pixel_counter_wrap( 'autodescription-meta[doctitle]', 'title' );
103
+ ?>
104
  </th>
105
  <td>
106
  <div id="tsf-title-wrap">
107
+ <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" autocomplete=off />
108
+ <?php $this->output_floating_title_elements(); ?>
109
  </div>
 
 
 
 
110
  </td>
111
  </tr>
112
 
113
  <tr class="form-field">
114
  <th scope="row" valign="top">
115
  <label for="autodescription-meta[description]">
116
+ <strong>
117
+ <?php
118
+ /* translators: %s = Term type */
119
+ printf( esc_html__( '%s Meta Description', 'autodescription' ), esc_html( $type ) );
120
+ ?>
121
+ </strong>
122
  </label>
123
+ <?php
124
+ $this->get_option( 'display_character_counter' )
125
+ and $this->output_character_counter_wrap( 'autodescription-meta[description]', $desc_len_parsed );
126
+ $this->get_option( 'display_pixel_counter' )
127
+ and $this->output_pixel_counter_wrap( 'autodescription-meta[description]', 'description' );
128
+ ?>
129
  </th>
130
  <td>
131
  <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>
 
 
 
 
132
  </td>
133
  </tr>
134
 
136
  <th scope="row" valign="top"><?php esc_html_e( 'Robots Meta Settings', 'autodescription' ); ?></th>
137
  <td>
138
  <label for="autodescription-meta[noindex]"><input name="autodescription-meta[noindex]" id="autodescription-meta[noindex]" type="checkbox" value="1" <?php checked( $noindex ); ?> />
139
+ <?php
140
+ printf(
141
+ /* translators: %s = noindex/nofollow/noarchive */
142
+ esc_html__( 'Apply %s to this term?', 'autodescription' ),
143
+ $this->code_wrap( 'noindex' )
144
+ );
145
+ $this->make_info(
146
+ __( 'This tells search engines not to show this page in their search results.', 'autodescription' ),
147
+ 'https://support.google.com/webmasters/answer/93710?hl=' . $language
148
+ );
149
+ ?>
150
  </label>
151
 
152
  <br>
153
 
154
  <label for="autodescription-meta[nofollow]"><input name="autodescription-meta[nofollow]" id="autodescription-meta[nofollow]" type="checkbox" value="1" <?php checked( $nofollow ); ?> />
155
+ <?php
156
+ printf(
157
+ /* translators: %s = noindex/nofollow/noarchive */
158
+ esc_html__( 'Apply %s to this term?', 'autodescription' ),
159
+ $this->code_wrap( 'nofollow' )
160
+ );
161
+ $this->make_info(
162
+ __( 'This tells search engines not to follow links on this page.', 'autodescription' ),
163
+ 'https://support.google.com/webmasters/answer/96569?hl=' . $language
164
+ );
165
+ ?>
166
  </label>
167
 
168
  <br>
169
 
170
  <label for="autodescription-meta[noarchive]"><input name="autodescription-meta[noarchive]" id="autodescription-meta[noarchive]" type="checkbox" value="1" <?php checked( $noarchive ); ?> />
171
+ <?php
172
+ printf(
173
+ /* translators: %s = noindex/nofollow/noarchive */
174
+ esc_html__( 'Apply %s to this term?', 'autodescription' ),
175
+ $this->code_wrap( 'noarchive' )
176
+ );
177
+ $this->make_info(
178
+ __( 'This tells search engines not to follow links on this page.', 'autodescription' ),
179
+ 'https://support.google.com/webmasters/answer/79812?hl=' . $language
180
+ );
181
+ ?>
182
  </label>
183
 
184
+ <?php
185
+ // Saved flag, if set then it won't fetch for Genesis meta anymore
186
+ ?>
187
  <label class="hidden" for="autodescription-meta[saved_flag]">
188
  <input name="autodescription-meta[saved_flag]" id="autodescription-meta[saved_flag]" type="checkbox" value="1" checked='checked' />
189
  </label>
inc/views/inpost/wrap.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ //* Whether tabs are active.
9
+ $use_tabs = $use_tabs && count( $tabs ) > 1;
10
+
11
+ /**
12
+ * Start navigational tabs.
13
+ *
14
+ * Don't output navigation if $use_tabs is false and the amount of tabs is 1 or lower.
15
+ */
16
+ if ( $use_tabs ) :
17
+ ?>
18
+ <div class="tsf-flex tsf-flex-nav-tab-wrapper tsf-flex-hide-if-no-js" id="<?php echo \esc_attr( 'tsf-flex-' . $id . '-tabs-wrapper' ); ?>">
19
+ <div class="tsf-flex tsf-flex-nav-tab-inner">
20
+ <?php
21
+ $count = 1;
22
+ foreach ( $tabs as $tab => $value ) :
23
+ $dashicon = isset( $value['dashicon'] ) ? $value['dashicon'] : '';
24
+ $label_name = isset( $value['name'] ) ? $value['name'] : '';
25
+
26
+ $wrapper_id = \esc_attr( 'tsf-flex-nav-tab-' . $tab );
27
+ $wrapper_active = 1 === $count ? ' tsf-flex-nav-tab-active' : '';
28
+
29
+ $input_checked = 1 === $count ? 'checked' : '';
30
+ $input_id = \esc_attr( 'tsf-flex-' . $id . '-tab-' . $tab );
31
+ $input_name = \esc_attr( 'tsf-flex-' . $id . '-tabs' );
32
+
33
+ //= All output below is escaped.
34
+ ?>
35
+ <div class="tsf-flex tsf-flex-nav-tab tsf-flex<?php echo $wrapper_active; ?>" id="<?php echo $wrapper_id; ?>">
36
+ <input type="radio" class="tsf-flex-nav-tab-radio" id="<?php echo $input_id; ?>" name="<?php echo $input_name; ?>" <?php echo $input_checked; ?>>
37
+ <label for="<?php echo $input_id; ?>" class="tsf-flex tsf-flex-nav-tab-label">
38
+ <?php
39
+ echo $dashicon ? '<span class="tsf-flex dashicons dashicons-' . \esc_attr( $dashicon ) . ' tsf-flex-nav-dashicon"></span>' : '';
40
+ echo $label_name ? '<span class="tsf-flex tsf-flex-nav-name">' . \esc_attr( $label_name ) . '</span>' : '';
41
+ ?>
42
+ </label>
43
+ </div>
44
+ <?php
45
+
46
+ $count++;
47
+ endforeach;
48
+ ?>
49
+ </div>
50
+ </div>
51
+ <?php
52
+ endif;
53
+
54
+ /**
55
+ * Start Content.
56
+ *
57
+ * The content is relative to the navigation, and uses CSS to become visible.
58
+ */
59
+ $count = 1;
60
+ foreach ( $tabs as $tab => $value ) :
61
+
62
+ $radio_id = \esc_attr( 'tsf-flex-' . $id . '-tab-' . $tab . '-content' );
63
+ $radio_class = \esc_attr( 'tsf-flex-' . $id . '-tabs-content' );
64
+
65
+ //* Current tab for JS.
66
+ $current_class = 1 === $count ? ' tsf-flex-tab-content-active' : '';
67
+
68
+ ?>
69
+ <div class="tsf-flex tsf-flex-tab-content <?php echo \esc_attr( $radio_class . $current_class ); ?>" id="<?php echo \esc_attr( $radio_id ); ?>" >
70
+ <?php
71
+ //* No-JS tabs.
72
+ if ( $use_tabs ) :
73
+ $dashicon = isset( $value['dashicon'] ) ? $value['dashicon'] : '';
74
+ $label_name = isset( $value['name'] ) ? $value['name'] : '';
75
+
76
+ ?>
77
+ <div class="tsf-flex tsf-flex-hide-if-js tsf-flex-tabs-content-no-js">
78
+ <div class="tsf-flex tsf-flex-nav-tab tsf-flex-tab-no-js">
79
+ <span class="tsf-flex tsf-flex-nav-tab">
80
+ <?php echo $dashicon ? '<span class="tsf-flex dashicons dashicons-' . \esc_attr( $dashicon ) . ' tsf-flex-nav-dashicon"></span>' : ''; ?>
81
+ <?php echo $label_name ? '<span class="tsf-flex tsf-flex-nav-name">' . \esc_attr( $label_name ) . '</span>' : ''; ?>
82
+ </span>
83
+ </div>
84
+ </div>
85
+ <?php
86
+ endif;
87
+
88
+ $callback = isset( $value['callback'] ) ? $value['callback'] : '';
89
+
90
+ if ( $callback ) {
91
+ $params = isset( $value['args'] ) ? $value['args'] : '';
92
+ //* Should already be escaped.
93
+ echo $this->call_function( $callback, $version, $params );
94
+ }
95
+ ?>
96
+ </div>
97
+ <?php
98
+
99
+ $count++;
100
+ endforeach;
inc/views/metaboxes/description-metabox.php CHANGED
@@ -97,7 +97,10 @@ switch ( $instance ) :
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 ); ?> />
@@ -106,7 +109,6 @@ switch ( $instance ) :
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>
110
  </fieldset>
111
  <?php
112
  break;
@@ -127,18 +129,24 @@ switch ( $instance ) :
127
 
128
  <h4><?php esc_html_e( 'Add descriptive Additions to Description', 'autodescription' ); ?></h4>
129
  <p id="tsf-description-additions-toggle">
130
- <label for="<?php $this->field_id( 'description_additions' ); ?>" class="tsf-toblock">
131
  <input type="checkbox" name="<?php $this->field_name( 'description_additions' ); ?>" id="<?php $this->field_id( 'description_additions' ); ?>" <?php $this->is_conditional_checked( 'description_additions' ); ?> value="1" <?php checked( $this->get_field_value( 'description_additions' ) ); ?> />
132
- <?php esc_html_e( 'Add Additions to automated description?', 'autodescription' ); ?>
133
- <a href="<?php echo esc_url( $google_explanation ); ?>" target="_blank" class="description" title="<?php esc_attr_e( 'This creates good meta descriptions', 'autodescription' ); ?>">[?]</a>
 
 
 
 
 
 
134
  </label>
135
  </p>
136
 
137
  <h4><?php esc_html_e( 'Add Blogname to Additions', 'autodescription' ); ?></h4>
138
  <p id="tsf-description-onblogname-toggle">
139
- <label for="<?php $this->field_id( 'description_blogname' ); ?>" class="tsf-toblock">
140
  <input type="checkbox" name="<?php $this->field_name( 'description_blogname' ); ?>" id="<?php $this->field_id( 'description_blogname' ); ?>" <?php $this->is_conditional_checked( 'description_blogname' ); ?> value="1" <?php checked( $this->get_field_value( 'description_blogname' ) ); ?> />
141
- <?php esc_html_e( 'Add Blogname to automated description additions?', 'autodescription' ); ?>
142
  </label>
143
  </p>
144
  <?php
97
 
98
  ?>
99
  <fieldset>
100
+ <legend>
101
+ <h4><?php esc_html_e( 'Description Excerpt Separator', 'autodescription' ); ?></h4>
102
+ <?php $this->description( __( 'If the Automated Description consists of two parts (title and excerpt), then the separator will go in-between them.', 'autodescription' ) ); ?>
103
+ </legend>
104
  <p id="tsf-description-separator" class="tsf-fields">
105
  <?php foreach ( $description_separator as $name => $html ) { ?>
106
  <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 ); ?> />
109
  </label>
110
  <?php } ?>
111
  </p>
 
112
  </fieldset>
113
  <?php
114
  break;
129
 
130
  <h4><?php esc_html_e( 'Add descriptive Additions to Description', 'autodescription' ); ?></h4>
131
  <p id="tsf-description-additions-toggle">
132
+ <label for="<?php $this->field_id( 'description_additions' ); ?>">
133
  <input type="checkbox" name="<?php $this->field_name( 'description_additions' ); ?>" id="<?php $this->field_id( 'description_additions' ); ?>" <?php $this->is_conditional_checked( 'description_additions' ); ?> value="1" <?php checked( $this->get_field_value( 'description_additions' ) ); ?> />
134
+ <?php
135
+ esc_html_e( 'Add Additions to automated description?', 'autodescription' );
136
+ echo ' ';
137
+ $this->make_info(
138
+ __( 'This creates better automated meta descriptions.', 'autodescription' ),
139
+ $google_explanation
140
+ );
141
+ ?>
142
  </label>
143
  </p>
144
 
145
  <h4><?php esc_html_e( 'Add Blogname to Additions', 'autodescription' ); ?></h4>
146
  <p id="tsf-description-onblogname-toggle">
147
+ <label for="<?php $this->field_id( 'description_blogname' ); ?>">
148
  <input type="checkbox" name="<?php $this->field_name( 'description_blogname' ); ?>" id="<?php $this->field_id( 'description_blogname' ); ?>" <?php $this->is_conditional_checked( 'description_blogname' ); ?> value="1" <?php checked( $this->get_field_value( 'description_blogname' ) ); ?> />
149
+ <?php esc_html_e( 'Add the blog name to the automated description?', 'autodescription' ); ?>
150
  </label>
151
  </p>
152
  <?php
inc/views/metaboxes/feed-metabox.php CHANGED
@@ -17,10 +17,10 @@ switch ( $instance ) :
17
  <h4><?php esc_html_e( 'Change Feed Settings', 'autodescription' ); ?></h4>
18
  <?php
19
  $excerpt_the_feed_label = esc_html__( 'Convert feed entries into excerpts?', 'autodescription' );
20
- $excerpt_the_feed_label .= ' ' . $this->make_info( __( 'By default the excerpt will be at most 400 characters long', 'autodescription' ), '', false );
21
 
22
  $source_the_feed_label = esc_html__( 'Add link to source below the feed entry content?', 'autodescription' );
23
- $source_the_feed_label .= ' ' . $this->make_info( __( 'This link will not be followed by Search Engines', 'autodescription' ), '', false );
24
 
25
  //* Echo checkboxes.
26
  $this->wrap_fields(
17
  <h4><?php esc_html_e( 'Change Feed Settings', 'autodescription' ); ?></h4>
18
  <?php
19
  $excerpt_the_feed_label = esc_html__( 'Convert feed entries into excerpts?', 'autodescription' );
20
+ $excerpt_the_feed_label .= ' ' . $this->make_info( __( 'By default the excerpt will be at most 400 characters long.', 'autodescription' ), '', false );
21
 
22
  $source_the_feed_label = esc_html__( 'Add link to source below the feed entry content?', 'autodescription' );
23
+ $source_the_feed_label .= ' ' . $this->make_info( __( 'This link will not be followed by search engines.', 'autodescription' ), '', false );
24
 
25
  //* Echo checkboxes.
26
  $this->wrap_fields(
inc/views/metaboxes/general-metabox.php CHANGED
@@ -29,6 +29,11 @@ switch ( $instance ) :
29
  'callback' => array( $this, 'general_metabox_canonical_tab' ),
30
  'dashicon' => 'external',
31
  ),
 
 
 
 
 
32
  );
33
 
34
  /**
@@ -48,7 +53,9 @@ switch ( $instance ) :
48
  break;
49
 
50
  case 'the_seo_framework_general_metabox_layout' :
51
- ?><h4><?php esc_html_e( 'Administrative Layout Settings', 'autodescription' ); ?></h4><?php
 
 
52
  $this->description( __( 'SEO hints can be visually displayed throughout the dashboard.', 'autodescription' ) );
53
 
54
  ?>
@@ -73,17 +80,54 @@ switch ( $instance ) :
73
  ),
74
  true
75
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  break;
77
 
78
  case 'the_seo_framework_general_metabox_performance' :
79
 
80
- ?><h4><?php esc_html_e( 'Performance Settings', 'autodescription' ); ?></h4><?php
 
 
81
  $this->description( __( "Depending on your server's configuration, adjusting these settings can affect performance.", 'autodescription' ) );
82
 
83
  ?>
84
  <hr>
85
 
86
- <h4><?php esc_html_e( 'Query alteration Settings', 'autodescription' ); ?></h4>
87
  <?php
88
  $this->description_noesc(
89
  esc_html__( "Altering the query allows for more control of the site's hierarchy.", 'autodescription' )
@@ -157,7 +201,7 @@ switch ( $instance ) :
157
  $this->make_checkbox(
158
  'alter_search_query',
159
  esc_html__( 'Enable search query alteration?', 'autodescription' )
160
- . ' ' . $this->make_info( __( 'This allows you to exclude pages from on-site search results', 'autodescription' ), '', false ),
161
  '',
162
  false
163
  ),
@@ -171,7 +215,7 @@ switch ( $instance ) :
171
  $this->make_checkbox(
172
  'alter_archive_query',
173
  esc_html__( 'Enable archive query alteration?', 'autodescription' )
174
- . ' ' . $this->make_info( __( 'This allows you to exclude pages from on-site archive listings', 'autodescription' ), '', false ),
175
  '',
176
  false
177
  ),
@@ -192,21 +236,21 @@ switch ( $instance ) :
192
  $this->make_checkbox(
193
  'cache_meta_description',
194
  esc_html__( 'Enable automated description output cache?', 'autodescription' )
195
- . ' ' . $this->make_info( __( 'Description generation can use a lot of server resources when it reads the page content', 'autodescription' ), '', false ),
196
  '',
197
  false
198
  ),
199
  $this->make_checkbox(
200
  'cache_meta_schema',
201
  esc_html__( 'Enable automated Schema output cache?', 'autodescription' )
202
- . ' ' . $this->make_info( __( 'Schema.org output generally makes multiple calls to the database', 'autodescription' ), '', false ),
203
  '',
204
  false
205
  ),
206
  $this->make_checkbox(
207
  'cache_sitemap',
208
  esc_html__( 'Enable sitemap generation cache?', 'autodescription' )
209
- . ' ' . $this->make_info( __( 'Generating the sitemap can use a lot of server resources', 'autodescription' ), '', false ),
210
  '',
211
  false
212
  ),
@@ -225,7 +269,7 @@ switch ( $instance ) :
225
  $this->make_checkbox(
226
  'cache_object',
227
  esc_html__( 'Enable object cache?', 'autodescription' )
228
- . ' ' . $this->make_info( __( 'Object cache generally works faster than transient cache', 'autodescription' ), '', false ),
229
  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' ),
230
  false
231
  ),
@@ -235,9 +279,10 @@ switch ( $instance ) :
235
  break;
236
 
237
  case 'the_seo_framework_general_metabox_canonical' :
238
-
239
- ?><h4><?php esc_html_e( 'Canonical URL Settings', 'autodescription' ); ?></h4><?php
240
- $this->description( __( 'The canonical URL meta tag urges Search Engines to go to the outputted URL.', 'autodescription' ) );
 
241
  $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' ) );
242
  $this->description( __( 'Only adjust these options if you are aware of their SEO effects.', 'autodescription' ) );
243
  ?>
@@ -268,8 +313,9 @@ switch ( $instance ) :
268
 
269
  <hr>
270
 
271
- <h4><?php esc_html_e( 'Link Relationship Settings', 'autodescription' ); ?></h4><?php
272
- $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' ) );
 
273
  $this->description( __( "It's recommended to turn this option on for better SEO consistency and to prevent duplicate content errors.", 'autodescription' ) );
274
 
275
  /* translators: %s = <code>rel</code> */
@@ -288,6 +334,65 @@ switch ( $instance ) :
288
  $this->wrap_fields( $prev_next_posts_checkbox . $prev_next_archives_checkbox . $prev_next_frontpage_checkbox, true );
289
  break;
290
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  default :
292
  break;
293
  endswitch;
29
  'callback' => array( $this, 'general_metabox_canonical_tab' ),
30
  'dashicon' => 'external',
31
  ),
32
+ 'timestamps' => array(
33
+ 'name' => __( 'Timestamps', 'autodescription' ),
34
+ 'callback' => array( $this, 'general_metabox_timestamps_tab' ),
35
+ 'dashicon' => 'clock',
36
+ ),
37
  );
38
 
39
  /**
53
  break;
54
 
55
  case 'the_seo_framework_general_metabox_layout' :
56
+ ?>
57
+ <h4><?php esc_html_e( 'Administrative Layout Settings', 'autodescription' ); ?></h4>
58
+ <?php
59
  $this->description( __( 'SEO hints can be visually displayed throughout the dashboard.', 'autodescription' ) );
60
 
61
  ?>
80
  ),
81
  true
82
  );
83
+
84
+ ?>
85
+ <hr>
86
+
87
+ <h4><?php esc_html_e( 'Counter Settings', 'autodescription' ); ?></h4>
88
+ <?php
89
+
90
+ $pixel_info = $this->make_info(
91
+ __( 'The pixel counter computes whether the input will fit on Search Engine Result Pages.', 'autodescription' ),
92
+ '',
93
+ false
94
+ );
95
+ $character_info = $this->make_info(
96
+ __( 'The character counter is based on guidelines.', 'autodescription' ),
97
+ '',
98
+ false
99
+ );
100
+
101
+ $this->wrap_fields(
102
+ array(
103
+ $this->make_checkbox(
104
+ 'display_pixel_counter',
105
+ esc_html__( 'Display pixel counters?', 'autodescription' ) . ' ' . $pixel_info,
106
+ '',
107
+ false
108
+ ),
109
+ $this->make_checkbox(
110
+ 'display_character_counter',
111
+ esc_html__( 'Display character counters?', 'autodescription' ) . ' ' . $character_info,
112
+ '',
113
+ false
114
+ ),
115
+ ),
116
+ true
117
+ );
118
  break;
119
 
120
  case 'the_seo_framework_general_metabox_performance' :
121
 
122
+ ?>
123
+ <h4><?php esc_html_e( 'Performance Settings', 'autodescription' ); ?></h4>
124
+ <?php
125
  $this->description( __( "Depending on your server's configuration, adjusting these settings can affect performance.", 'autodescription' ) );
126
 
127
  ?>
128
  <hr>
129
 
130
+ <h4><?php esc_html_e( 'Query Alteration Settings', 'autodescription' ); ?></h4>
131
  <?php
132
  $this->description_noesc(
133
  esc_html__( "Altering the query allows for more control of the site's hierarchy.", 'autodescription' )
201
  $this->make_checkbox(
202
  'alter_search_query',
203
  esc_html__( 'Enable search query alteration?', 'autodescription' )
204
+ . ' ' . $this->make_info( __( 'This allows you to exclude pages from on-site search results.', 'autodescription' ), '', false ),
205
  '',
206
  false
207
  ),
215
  $this->make_checkbox(
216
  'alter_archive_query',
217
  esc_html__( 'Enable archive query alteration?', 'autodescription' )
218
+ . ' ' . $this->make_info( __( 'This allows you to exclude pages from on-site archive listings.', 'autodescription' ), '', false ),
219
  '',
220
  false
221
  ),
236
  $this->make_checkbox(
237
  'cache_meta_description',
238
  esc_html__( 'Enable automated description output cache?', 'autodescription' )
239
+ . ' ' . $this->make_info( __( 'Description generation can use a lot of server resources when it reads the page content.', 'autodescription' ), '', false ),
240
  '',
241
  false
242
  ),
243
  $this->make_checkbox(
244
  'cache_meta_schema',
245
  esc_html__( 'Enable automated Schema output cache?', 'autodescription' )
246
+ . ' ' . $this->make_info( __( 'Schema.org output generally makes multiple calls to the database.', 'autodescription' ), '', false ),
247
  '',
248
  false
249
  ),
250
  $this->make_checkbox(
251
  'cache_sitemap',
252
  esc_html__( 'Enable sitemap generation cache?', 'autodescription' )
253
+ . ' ' . $this->make_info( __( 'Generating the sitemap can use a lot of server resources.', 'autodescription' ), '', false ),
254
  '',
255
  false
256
  ),
269
  $this->make_checkbox(
270
  'cache_object',
271
  esc_html__( 'Enable object cache?', 'autodescription' )
272
+ . ' ' . $this->make_info( __( 'Object cache generally works faster than transient cache.', 'autodescription' ), '', false ),
273
  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' ),
274
  false
275
  ),
279
  break;
280
 
281
  case 'the_seo_framework_general_metabox_canonical' :
282
+ ?>
283
+ <h4><?php esc_html_e( 'Canonical URL Settings', 'autodescription' ); ?></h4>
284
+ <?php
285
+ $this->description( __( 'The canonical URL meta tag urges search engines to go to the outputted URL.', 'autodescription' ) );
286
  $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' ) );
287
  $this->description( __( 'Only adjust these options if you are aware of their SEO effects.', 'autodescription' ) );
288
  ?>
313
 
314
  <hr>
315
 
316
+ <h4><?php esc_html_e( 'Link Relationship Settings', 'autodescription' ); ?></h4>
317
+ <?php
318
+ $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' ) );
319
  $this->description( __( "It's recommended to turn this option on for better SEO consistency and to prevent duplicate content errors.", 'autodescription' ) );
320
 
321
  /* translators: %s = <code>rel</code> */
334
  $this->wrap_fields( $prev_next_posts_checkbox . $prev_next_archives_checkbox . $prev_next_frontpage_checkbox, true );
335
  break;
336
 
337
+
338
+ case 'the_seo_framework_general_metabox_timestamps' :
339
+ //* Sets timezone according to WordPress settings.
340
+ $this->set_timezone();
341
+
342
+ $timestamp_0 = date( 'Y-m-d' );
343
+
344
+ /**
345
+ * @link https://www.w3.org/TR/NOTE-datetime
346
+ * We use the second expression of the time zone offset handling.
347
+ */
348
+ $timestamp_1 = date( 'Y-m-d\TH:iP' );
349
+
350
+ //* Reset timezone to previous value.
351
+ $this->reset_timezone();
352
+
353
+ ?>
354
+ <h4><?php esc_html_e( 'Timestamp Settings', 'autodescription' ); ?></h4>
355
+ <?php
356
+ $this->description( __( 'Timestamps indicate when a page has been published and modified.', 'autodescription' ) );
357
+ ?>
358
+ <hr>
359
+
360
+ <fieldset>
361
+ <legend>
362
+ <h4><?php esc_html_e( 'Timestamp Format Settings', 'autodescription' ); ?></h4>
363
+ <?php $this->description( __( 'This setting determines how specific the timestamp is.', 'autodescription' ) ); ?>
364
+ </legend>
365
+
366
+ <p id="sitemaps-timestamp-format" class="tsf-fields">
367
+ <span class="tsf-toblock">
368
+ <input type="radio" name="<?php $this->field_name( 'timestamps_format' ); ?>" id="<?php $this->field_id( 'timestamps_format_0' ); ?>" value="0" <?php checked( $this->get_field_value( 'timestamps_format' ), '0' ); ?> />
369
+ <label for="<?php $this->field_id( 'timestamps_format_0' ); ?>">
370
+ <?php
371
+ echo $this->code_wrap( $timestamp_0 );
372
+ echo ' ';
373
+ $this->make_info(
374
+ __( 'This outputs the complete date.', 'autodescription' )
375
+ );
376
+ ?>
377
+ </label>
378
+ </span>
379
+ <span class="tsf-toblock">
380
+ <input type="radio" name="<?php $this->field_name( 'timestamps_format' ); ?>" id="<?php $this->field_id( 'timestamps_format_1' ); ?>" value="1" <?php checked( $this->get_field_value( 'timestamps_format' ), '1' ); ?> />
381
+ <label for="<?php $this->field_id( 'timestamps_format_1' ); ?>">
382
+ <?php
383
+ echo $this->code_wrap( $timestamp_1 );
384
+ echo ' ';
385
+ $this->make_info(
386
+ __( 'This outputs the complete date including hours, minutes, and timezone.', 'autodescription' )
387
+ );
388
+ ?>
389
+ </label>
390
+ </span>
391
+ </p>
392
+ </fieldset>
393
+ <?php
394
+ break;
395
+
396
  default :
397
  break;
398
  endswitch;
inc/views/metaboxes/homepage-metabox.php CHANGED
@@ -7,9 +7,7 @@ $instance = $this->get_view_instance( 'the_seo_framework_homepage_metabox', $ins
7
 
8
  switch ( $instance ) :
9
  case 'the_seo_framework_homepage_metabox_main' :
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
@@ -20,11 +18,11 @@ switch ( $instance ) :
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(
@@ -168,19 +166,24 @@ switch ( $instance ) :
168
 
169
  <hr>
170
 
171
- <p>
172
  <label for="<?php $this->field_id( 'homepage_title' ); ?>" class="tsf-toblock">
173
- <strong><?php printf( esc_html__( 'Custom %s Title', 'autodescription' ), $home_page_i18n ); ?></strong>
174
- <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>
175
- <span class="description tsf-counter">
176
- <?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>' ); ?>
177
- <span class="hide-if-no-js tsf-ajax"></span>
178
- </span>
179
  </label>
180
- </p>
 
 
 
 
 
181
  <p id="tsf-title-wrap">
182
  <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' ) ); ?>" autocomplete=off />
183
- <span id="tsf-title-offset" class="hide-if-no-js"></span><span id="tsf-title-placeholder" class="hide-if-no-js"></span>
184
  </p>
185
  <?php
186
  /**
@@ -220,16 +223,20 @@ switch ( $instance ) :
220
  ?>
221
  <hr>
222
 
223
- <p>
224
  <label for="<?php $this->field_id( 'homepage_description' ); ?>" class="tsf-toblock">
225
- <strong><?php printf( esc_html__( 'Custom %s Description', 'autodescription' ), $home_page_i18n ); ?></strong>
226
- <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>
227
- <span class="description tsf-counter">
228
- <?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>' ); ?>
229
- <span class="hide-if-no-js tsf-ajax"></span>
230
- </span>
231
  </label>
232
- </p>
 
 
 
 
 
233
  <p>
234
  <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>
235
  </p>
@@ -275,8 +282,10 @@ switch ( $instance ) :
275
 
276
  ?>
277
  <fieldset>
278
- <legend><h4><?php esc_html_e( 'Document Title Additions Location', 'autodescription' ); ?></h4></legend>
279
- <?php $this->description( __( 'Determines which side the added title text will go on.', 'autodescription' ) ); ?>
 
 
280
 
281
  <p id="tsf-home-title-location" class="tsf-fields">
282
  <span class="tsf-toblock">
@@ -349,7 +358,7 @@ switch ( $instance ) :
349
  $i_label = sprintf( esc_html__( 'Apply %1$s to the %2$s?', 'autodescription' ), $this->code_wrap( 'noindex' ), $home_page_i18n );
350
  $i_label .= ' ';
351
  $i_label .= $this->make_info(
352
- __( 'Tell Search Engines not to show this page in their search results', 'autodescription' ),
353
  'https://support.google.com/webmasters/answer/93710?hl=' . $language,
354
  false
355
  ) . $noindex_note;
@@ -359,7 +368,7 @@ switch ( $instance ) :
359
  $f_label = sprintf( esc_html__( 'Apply %1$s to the %2$s?', 'autodescription' ), $this->code_wrap( 'nofollow' ), $home_page_i18n );
360
  $f_label .= ' ';
361
  $f_label .= $this->make_info(
362
- __( 'Tell Search Engines not to follow links on this page', 'autodescription' ),
363
  'https://support.google.com/webmasters/answer/96569?hl=' . $language,
364
  false
365
  ) . $nofollow_note;
@@ -369,7 +378,7 @@ switch ( $instance ) :
369
  $a_label = sprintf( esc_html__( 'Apply %1$s to the %2$s?', 'autodescription' ), $this->code_wrap( 'noarchive' ), $home_page_i18n );
370
  $a_label .= ' ';
371
  $a_label .= $this->make_info(
372
- __( 'Tell Search Engines not to save a cached copy of this page', 'autodescription' ),
373
  'https://support.google.com/webmasters/answer/79812?hl=' . $language,
374
  false
375
  ) . $noarchive_note;
@@ -457,8 +466,8 @@ switch ( $instance ) :
457
  ?>
458
  <p>
459
  <label for="tsf_homepage_socialimage-url">
460
- <strong><?php esc_html_e( 'Custom Home Page Image URL', 'autodescription' ); ?></strong>
461
- <?php $this->make_info( __( 'Preferred Home Page Social Image URL location', 'autodescription' ), 'https://developers.facebook.com/docs/sharing/best-practices#images' ); ?>
462
  </label>
463
  </p>
464
  <p>
7
 
8
  switch ( $instance ) :
9
  case 'the_seo_framework_homepage_metabox_main' :
 
10
  $this->description( __( 'These settings will take precedence over the settings set within the Home Page edit screen, if any.', 'autodescription' ) );
 
11
  ?>
12
  <hr>
13
  <?php
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
24
+ * 'dashicon' => Desired dashicon
25
+ * )
26
  * }
27
  */
28
  $default_tabs = array(
166
 
167
  <hr>
168
 
169
+ <div>
170
  <label for="<?php $this->field_id( 'homepage_title' ); ?>" class="tsf-toblock">
171
+ <strong>
172
+ <?php
173
+ /* translators: %s = Post type */
174
+ printf( esc_html__( 'Custom %s Title', 'autodescription' ), $home_page_i18n );
175
+ ?>
176
+ </strong>
177
  </label>
178
+ <?php
179
+ //* Output these unconditionally, with inline CSS attached to allow reacting on settings.
180
+ $this->output_character_counter_wrap( $this->get_field_id( 'homepage_title' ), $tit_len, (bool) $this->get_option( 'display_character_counter' ) );
181
+ $this->output_pixel_counter_wrap( $this->get_field_id( 'homepage_title' ), 'title', (bool) $this->get_option( 'display_pixel_counter' ) );
182
+ ?>
183
+ </div>
184
  <p id="tsf-title-wrap">
185
  <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' ) ); ?>" autocomplete=off />
186
+ <?php $this->output_floating_title_elements(); ?>
187
  </p>
188
  <?php
189
  /**
223
  ?>
224
  <hr>
225
 
226
+ <div>
227
  <label for="<?php $this->field_id( 'homepage_description' ); ?>" class="tsf-toblock">
228
+ <strong>
229
+ <?php
230
+ printf( esc_html__( 'Custom %s Description', 'autodescription' ), $home_page_i18n );
231
+ ?>
232
+ </strong>
 
233
  </label>
234
+ <?php
235
+ //* Output these unconditionally, with inline CSS attached to allow reacting on settings.
236
+ $this->output_character_counter_wrap( $this->get_field_id( 'homepage_description' ), $desc_len, (bool) $this->get_option( 'display_character_counter' ) );
237
+ $this->output_pixel_counter_wrap( $this->get_field_id( 'homepage_description' ), 'description', (bool) $this->get_option( 'display_pixel_counter' ) );
238
+ ?>
239
+ </div>
240
  <p>
241
  <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>
242
  </p>
282
 
283
  ?>
284
  <fieldset>
285
+ <legend>
286
+ <h4><?php esc_html_e( 'Title Additions Location', 'autodescription' ); ?></h4>
287
+ <?php $this->description( __( 'This setting determines which side the added title text will go on.', 'autodescription' ) ); ?>
288
+ </legend>
289
 
290
  <p id="tsf-home-title-location" class="tsf-fields">
291
  <span class="tsf-toblock">
358
  $i_label = sprintf( esc_html__( 'Apply %1$s to the %2$s?', 'autodescription' ), $this->code_wrap( 'noindex' ), $home_page_i18n );
359
  $i_label .= ' ';
360
  $i_label .= $this->make_info(
361
+ __( 'This tells search engines not to show this page in their search results.', 'autodescription' ),
362
  'https://support.google.com/webmasters/answer/93710?hl=' . $language,
363
  false
364
  ) . $noindex_note;
368
  $f_label = sprintf( esc_html__( 'Apply %1$s to the %2$s?', 'autodescription' ), $this->code_wrap( 'nofollow' ), $home_page_i18n );
369
  $f_label .= ' ';
370
  $f_label .= $this->make_info(
371
+ __( 'This tells search engines not to follow links on this page.', 'autodescription' ),
372
  'https://support.google.com/webmasters/answer/96569?hl=' . $language,
373
  false
374
  ) . $nofollow_note;
378
  $a_label = sprintf( esc_html__( 'Apply %1$s to the %2$s?', 'autodescription' ), $this->code_wrap( 'noarchive' ), $home_page_i18n );
379
  $a_label .= ' ';
380
  $a_label .= $this->make_info(
381
+ __( 'This tells search engines not to save a cached copy of this page.', 'autodescription' ),
382
  'https://support.google.com/webmasters/answer/79812?hl=' . $language,
383
  false
384
  ) . $noarchive_note;
466
  ?>
467
  <p>
468
  <label for="tsf_homepage_socialimage-url">
469
+ <strong><?php esc_html_e( 'Custom Homepage Image URL', 'autodescription' ); ?></strong>
470
+ <?php $this->make_info( __( 'Set preferred homepage Social Image URL location.', 'autodescription' ), 'https://developers.facebook.com/docs/sharing/best-practices#images' ); ?>
471
  </label>
472
  </p>
473
  <p>
inc/views/metaboxes/robots-metabox.php CHANGED
@@ -23,18 +23,18 @@ switch ( $instance ) :
23
  $robots = array(
24
  'noindex' => array(
25
  'value' => 'noindex',
26
- 'name' => __( 'NoIndex', 'autodescription' ),
27
- 'desc' => __( 'These options prevent indexing of the selected archives and pages. If you enable this, the selected archives or pages will be removed from Search Engine results pages.', 'autodescription' ),
28
  ),
29
  'nofollow' => array(
30
  'value' => 'nofollow',
31
- 'name' => __( 'NoFollow', 'autodescription' ),
32
- 'desc' => __( 'These options prevent links from being followed on the selected archives and pages. If you enable this, the selected archives or pages in-page links will gain no SEO value, including your own links.', 'autodescription' ),
33
  ),
34
  'noarchive' => array(
35
  'value' => 'noarchive',
36
- 'name' => __( 'NoArchive', 'autodescription' ),
37
- 'desc' => __( 'These options prevent caching of the selected archives and pages. If you enable this, Search Engines will not create a cached copy of the selected archives or pages.', 'autodescription' ),
38
  ),
39
  );
40
 
@@ -44,40 +44,40 @@ switch ( $instance ) :
44
  * @since 2.2.2
45
  *
46
  * @param array $default_tabs { 'id' = The identifier =>
47
- * array(
48
- * 'name' => The name
49
- * 'callback' => function callback
50
- * 'dashicon' => WordPress Dashicon
51
- * 'args' => function args
52
- * )
53
  * }
54
  */
55
  $default_tabs = array(
56
- 'general' => array(
57
- 'name' => __( 'General', 'autodescription' ),
58
- 'callback' => array( $this, 'robots_metabox_general_tab' ),
59
- 'dashicon' => 'admin-generic',
60
- 'args' => '',
61
- ),
62
- 'index' => array(
63
- 'name' => __( 'Indexing', 'autodescription' ),
64
- 'callback' => array( $this, 'robots_metabox_no_tab' ),
65
- 'dashicon' => 'filter',
66
- 'args' => array( $types, $robots['noindex'] ),
67
- ),
68
- 'follow' => array(
69
- 'name' => __( 'Following', 'autodescription' ),
70
- 'callback' => array( $this, 'robots_metabox_no_tab' ),
71
- 'dashicon' => 'editor-unlink',
72
- 'args' => array( $types, $robots['nofollow'] ),
73
- ),
74
- 'archive' => array(
75
- 'name' => __( 'Archiving', 'autodescription' ),
76
- 'callback' => array( $this, 'robots_metabox_no_tab' ),
77
- 'dashicon' => 'download',
78
- 'args' => array( $types, $robots['noarchive'] ),
79
- ),
80
- );
81
 
82
  /**
83
  * Applies filters 'the_seo_framework_robots_settings_tabs' : array see $default_tabs
@@ -94,31 +94,33 @@ switch ( $instance ) :
94
 
95
  case 'the_seo_framework_robots_metabox_general' :
96
 
97
- ?><h4><?php esc_html_e( 'Open Directory Settings', 'autodescription' ); ?></h4><?php
98
- $this->description( __( "Sometimes, Search Engines use resources from certain Directories to find titles and descriptions for your content. You generally don't want them to. Turn these options on to prevent them from doing so.", 'autodescription' ) );
99
- $this->description( __( "The Open Directory Project and the Yahoo! Directory may contain outdated SEO values. Therefore, it's best to leave these options checked.", 'autodescription' ) );
 
 
100
 
101
  $fields = $this->wrap_fields(
102
- array(
103
- $this->make_checkbox(
104
- 'noodp',
105
- sprintf( esc_html__( 'Apply %s to the entire site?', 'autodescription' ), $this->code_wrap( 'noodp' ) ),
106
- '',
107
- false
108
- ),
109
- $this->make_checkbox(
110
- 'noydir',
111
- sprintf( esc_html__( 'Apply %s to the entire site?', 'autodescription' ), $this->code_wrap( 'noydir' ) ),
112
- '',
113
- false
114
- ),
115
  ), true
116
  );
117
  ?>
118
  <hr>
119
 
120
  <h4><?php esc_html_e( 'Paginated Archive Settings', 'autodescription' ); ?></h4>
121
- <p class="description"><?php printf( esc_html__( "Indexing the second or later page of any archive might cause duplication errors. Search Engines look down upon them; therefore, it's recommended to disable indexing of those pages.", 'autodescription' ), $this->code_wrap( 'noodp' ), $this->code_wrap( 'noydir' ) ); ?></p>
 
 
 
 
 
 
 
 
122
  <?php
123
 
124
  $this->wrap_fields(
23
  $robots = array(
24
  'noindex' => array(
25
  'value' => 'noindex',
26
+ 'name' => __( 'NoIndex', 'autodescription' ),
27
+ 'desc' => __( 'These options prevent indexing of the selected archives and pages. If you enable this, the selected archives or pages will be removed from Search Engine results pages.', 'autodescription' ),
28
  ),
29
  'nofollow' => array(
30
  'value' => 'nofollow',
31
+ 'name' => __( 'NoFollow', 'autodescription' ),
32
+ 'desc' => __( 'These options prevent links from being followed on the selected archives and pages. If you enable this, the selected archives or pages in-page links will gain no SEO value, including your own links.', 'autodescription' ),
33
  ),
34
  'noarchive' => array(
35
  'value' => 'noarchive',
36
+ 'name' => __( 'NoArchive', 'autodescription' ),
37
+ 'desc' => __( 'These options prevent caching of the selected archives and pages. If you enable this, search engines will not create a cached copy of the selected archives or pages.', 'autodescription' ),
38
  ),
39
  );
40
 
44
  * @since 2.2.2
45
  *
46
  * @param array $default_tabs { 'id' = The identifier =>
47
+ * array(
48
+ * 'name' => The name
49
+ * 'callback' => function callback
50
+ * 'dashicon' => WordPress Dashicon
51
+ * 'args' => function args
52
+ * )
53
  * }
54
  */
55
  $default_tabs = array(
56
+ 'general' => array(
57
+ 'name' => __( 'General', 'autodescription' ),
58
+ 'callback' => array( $this, 'robots_metabox_general_tab' ),
59
+ 'dashicon' => 'admin-generic',
60
+ 'args' => '',
61
+ ),
62
+ 'index' => array(
63
+ 'name' => __( 'Indexing', 'autodescription' ),
64
+ 'callback' => array( $this, 'robots_metabox_no_tab' ),
65
+ 'dashicon' => 'filter',
66
+ 'args' => array( $types, $robots['noindex'] ),
67
+ ),
68
+ 'follow' => array(
69
+ 'name' => __( 'Following', 'autodescription' ),
70
+ 'callback' => array( $this, 'robots_metabox_no_tab' ),
71
+ 'dashicon' => 'editor-unlink',
72
+ 'args' => array( $types, $robots['nofollow'] ),
73
+ ),
74
+ 'archive' => array(
75
+ 'name' => __( 'Archiving', 'autodescription' ),
76
+ 'callback' => array( $this, 'robots_metabox_no_tab' ),
77
+ 'dashicon' => 'download',
78
+ 'args' => array( $types, $robots['noarchive'] ),
79
+ ),
80
+ );
81
 
82
  /**
83
  * Applies filters 'the_seo_framework_robots_settings_tabs' : array see $default_tabs
94
 
95
  case 'the_seo_framework_robots_metabox_general' :
96
 
97
+ ?>
98
+ <h4><?php esc_html_e( 'Open Directory Settings', 'autodescription' ); ?></h4>
99
+ <?php
100
+ $this->description( __( "Sometimes, search engines use resources from certain Directories to find titles and descriptions for your content. You generally don't want them to. Turn these options on to prevent them from doing so.", 'autodescription' ) );
101
+ $this->description( __( "The Yahoo! Directory may contain outdated SEO values. Therefore, it's best to leave the option checked.", 'autodescription' ) );
102
 
103
  $fields = $this->wrap_fields(
104
+ $this->make_checkbox(
105
+ 'noydir',
106
+ sprintf( esc_html__( 'Apply %s to the entire site?', 'autodescription' ), $this->code_wrap( 'noydir' ) ),
107
+ '',
108
+ false
 
 
 
 
 
 
 
 
109
  ), true
110
  );
111
  ?>
112
  <hr>
113
 
114
  <h4><?php esc_html_e( 'Paginated Archive Settings', 'autodescription' ); ?></h4>
115
+ <p class="description">
116
+ <?php
117
+ printf(
118
+ esc_html__( "Indexing the second or later page of any archive might cause duplication errors. Search engines look down upon them; therefore, it's recommended to disable indexing of those pages.", 'autodescription' ),
119
+ $this->code_wrap( 'noodp' ),
120
+ $this->code_wrap( 'noydir' )
121
+ );
122
+ ?>
123
+ </p>
124
  <?php
125
 
126
  $this->wrap_fields(
inc/views/metaboxes/schema-metabox.php CHANGED
@@ -7,7 +7,6 @@ $instance = $this->get_view_instance( 'the_seo_framework_schema_metabox', $insta
7
 
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
@@ -16,7 +15,7 @@ switch ( $instance ) :
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
  /**
@@ -25,19 +24,19 @@ switch ( $instance ) :
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' ),
@@ -64,101 +63,51 @@ switch ( $instance ) :
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',
@@ -166,27 +115,71 @@ switch ( $instance ) :
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>
190
  <?php
191
  $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' ) );
192
  $this->description( __( 'Add the link that leads directly to the social page of this website.', 'autodescription' ) );
@@ -263,20 +256,23 @@ switch ( $instance ) :
263
  ),
264
  );
265
 
266
- foreach ( $socialsites as $key => $value ) {
267
  ?>
268
  <p>
269
- <label for="<?php $this->field_id( $value['option'] ); ?>">
270
- <strong><?php echo esc_html( $value['desc'] ); ?></strong>
271
  <?php
272
- if ( $value['examplelink'] ) {
273
- ?><a href="<?php echo esc_url( $value['examplelink'] ); ?>" target="_blank">[?]</a><?php
 
 
 
274
  }
275
  ?>
276
  </label>
277
  </p>
278
  <p>
279
- <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'] ) ); ?>" />
280
  </p>
281
  <?php
282
  }
7
 
8
  switch ( $instance ) :
9
  case 'the_seo_framework_schema_metabox_main' :
 
10
  ?>
11
  <h4><?php esc_html_e( 'Schema.org Output Settings', 'autodescription' ); ?></h4>
12
  <?php
15
  $this->description( __( 'Another Schema.org plugin has been detected.', 'autodescription' ) );
16
  else :
17
  $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' ) );
18
+ $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' ) );
19
  $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' ) );
20
 
21
  /**
24
  * @since 2.8.0
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
  $default_tabs = array(
35
+ // 'general' => array(
36
+ // 'name' => __( 'General', 'autodescription' ),
37
+ // 'callback' => array( $this, 'schema_metabox_general_tab' ),
38
+ // 'dashicon' => 'admin-generic',
39
+ // ),
40
  'structure' => array(
41
  'name' => __( 'Structure', 'autodescription' ),
42
  'callback' => array( $this, 'schema_metabox_structure_tab' ),
63
  break;
64
 
65
  case 'the_seo_framework_schema_metabox_general' :
66
+ //* Emptied @ 3.0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  break;
68
 
69
  case 'the_seo_framework_schema_metabox_structure' :
 
 
 
 
 
70
  ?>
71
+ <h4><?php esc_html_e( 'Site Structure Options', 'autodescription' ); ?></h4>
72
+ <?php
73
+ $this->description( __( 'The site structure Schema.org output allows search engines to gain knowledge on how your website is built.', 'autodescription' ) );
74
+ $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' ) );
 
 
 
 
 
 
 
 
 
75
  ?>
76
  <hr>
77
+ <h4><?php esc_html_e( 'Breadcrumbs', 'autodescription' ); ?></h4>
 
78
  <?php
79
+ $this->description( __( "Breadcrumb trails indicate page positions in the site's hierarchy. Using the following option will show the hierarchy within the Search Results when available.", 'autodescription' ) );
80
 
81
+ $info = $this->make_info( __( 'Learn how this data is used.', 'autodescription' ), 'https://developers.google.com/search/docs/data-types/breadcrumbs', false );
 
 
 
 
82
  $this->wrap_fields( $this->make_checkbox(
83
+ 'ld_json_breadcrumbs',
84
+ esc_html__( 'Enable Breadcrumbs?', 'autodescription' ) . ' ' . $info,
85
+ '',
86
  false
87
  ), true );
88
 
89
  ?>
90
  <hr>
91
+ <h4><?php echo esc_html( _x( 'Sitelinks Searchbox', 'Product name', 'autodescription' ) ); ?></h4>
92
  <?php
 
 
 
93
  $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' ) );
94
 
95
+ $info = $this->make_info( __( 'Learn how this data is used.', 'autodescription' ), 'https://developers.google.com/search/docs/data-types/sitelinks-searchbox', false );
96
  $this->wrap_fields( $this->make_checkbox(
97
  'ld_json_searchbox',
98
+ esc_html_x( 'Enable Sitelinks Searchbox?', 'Sitelinks Searchbox is a Product name', 'autodescription' ) . ' ' . $info,
99
  '',
100
  false
101
  ), true );
102
  break;
103
 
104
  case 'the_seo_framework_schema_metabox_presence' :
105
+ ?>
106
+ <h4><?php esc_html_e( 'Authorized Presence Options', 'autodescription' ); ?></h4>
107
+ <?php
108
  $this->description( __( 'The authorized presence Schema.org output helps Search Engine users find ways to interact with this website.', 'autodescription' ) );
109
 
110
+ $info = $this->make_info( __( 'Learn how this data is used.', 'autodescription' ), 'https://developers.google.com/search/docs/guides/enhance-site#add-your-sites-name-logo-and-social-links', false );
111
  //* Echo checkbox.
112
  $this->wrap_fields( $this->make_checkbox(
113
  'knowledge_output',
115
  '',
116
  false
117
  ), true );
 
118
  ?>
119
  <hr>
120
 
121
+ <h4><?php esc_html_e( 'About this website', 'autodescription' ); ?></h4>
122
+ <p>
123
+ <label for="<?php $this->field_id( 'knowledge_type' ); ?>"><?php echo esc_html_x( 'This website represents:', '...Organization or Person.', 'autodescription' ); ?></label>
124
+ <select name="<?php $this->field_name( 'knowledge_type' ); ?>" id="<?php $this->field_id( 'knowledge_type' ); ?>">
125
+ <?php
126
+ $knowledge_type = (array) apply_filters(
127
+ 'the_seo_framework_knowledge_types',
128
+ array(
129
+ 'organization' => __( 'An Organization', 'autodescription' ),
130
+ 'person' => __( 'A Person', 'autodescription' ),
131
+ )
132
+ );
133
+ foreach ( $knowledge_type as $value => $name ) {
134
+ echo '<option value="' . esc_attr( $value ) . '"' . selected( $this->get_field_value( 'knowledge_type' ), esc_attr( $value ), false ) . '>' . esc_html( $name ) . '</option>' . "\n";
135
+ }
136
+ ?>
137
+ </select>
138
+ </p>
139
+
140
+ <p>
141
+ <label for="<?php $this->field_id( 'knowledge_name' ); ?>">
142
+ <strong><?php esc_html_e( 'The organization or personal name', 'autodescription' ); ?></strong>
143
+ </label>
144
+ </p>
145
+ <p>
146
+ <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' ) ); ?>" />
147
+ </p>
148
+ <hr>
149
+
150
  <h4><?php esc_html_e( 'Website logo', 'autodescription' ); ?></h4>
151
  <?php
152
+ $this->description( esc_html__( 'These options are used when this site represents an organization. When no logo is outputted, search engine will look elsewhere.', 'autodescription' ) );
153
+ $info = $this->make_info( __( 'Learn how this data is used.', 'autodescription' ), 'https://developers.google.com/search/docs/data-types/logo', false );
 
 
154
  $this->wrap_fields( $this->make_checkbox(
155
  'knowledge_logo',
156
+ esc_html__( 'Enable logo?', 'autodescription' ) . ' ' . $info,
157
+ '',
158
  false
159
  ), true );
160
 
161
+ $logo_placeholder = $this->get_knowledge_logo( false );
162
  ?>
163
+ <p>
164
+ <label for="knowledge_logo-url">
165
+ <strong><?php esc_html_e( 'Logo URL', 'autodescription' ); ?></strong>
166
+ <?php $this->make_info( __( 'The logo image must be square.', 'autodescription' ) ); ?>
167
+ </label>
168
+ </p>
169
+ <p>
170
+ <span class="hide-if-js attention"><?php esc_html_e( 'Setting a logo requires JavaScript.', 'autodescription' ); ?></span>
171
+ <input class="large-text" type="text" readonly="readonly" data-readonly="1" name="<?php $this->field_name( 'knowledge_logo_url' ); ?>" id="knowledge_logo-url" placeholder="<?php echo esc_url( $logo_placeholder ); ?>" value="<?php echo esc_url( $this->get_field_value( 'knowledge_logo_url' ) ); ?>" />
172
+ <input type="hidden" name="<?php $this->field_name( 'knowledge_logo_id' ); ?>" id="knowledge_logo-id" value="<?php echo absint( $this->get_field_value( 'knowledge_logo_id' ) ); ?>" />
173
+ </p>
174
+ <p class="hide-if-no-js">
175
+ <?php
176
+ //* Already escaped.
177
+ echo $this->get_logo_uploader_form( 'knowledge_logo' );
178
+ ?>
179
+ </p>
180
  <hr>
181
 
182
+ <h4><?php esc_html_e( 'Connected Social Pages', 'autodescription' ); ?></h4>
183
  <?php
184
  $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' ) );
185
  $this->description( __( 'Add the link that leads directly to the social page of this website.', 'autodescription' ) );
256
  ),
257
  );
258
 
259
+ foreach ( $socialsites as $key => $v ) {
260
  ?>
261
  <p>
262
+ <label for="<?php $this->field_id( $v['option'] ); ?>">
263
+ <strong><?php echo esc_html( $v['desc'] ); ?></strong>
264
  <?php
265
+ if ( $v['examplelink'] ) {
266
+ $this->make_info(
267
+ __( 'View your profile.', 'autodescription' ),
268
+ $v['examplelink']
269
+ );
270
  }
271
  ?>
272
  </label>
273
  </p>
274
  <p>
275
+ <input type="text" name="<?php $this->field_name( $v['option'] ); ?>" class="large-text" id="<?php $this->field_id( $v['option'] ); ?>" placeholder="<?php echo esc_attr( $v['placeholder'] ); ?>" value="<?php echo esc_attr( $this->get_field_value( $v['option'] ) ); ?>" />
276
  </p>
277
  <?php
278
  }
inc/views/metaboxes/sitemaps-metabox.php CHANGED
@@ -7,16 +7,15 @@ $instance = $this->get_view_instance( 'the_seo_framework_sitemaps_metabox', $ins
7
 
8
  switch ( $instance ) :
9
  case 'the_seo_framework_sitemaps_metabox_main' :
10
-
11
  /**
12
  * Parse tabs content
13
  *
14
- * @param array $default_tabs { 'id' = The identifier =>
15
- * array(
16
- * 'name' => The name
17
- * 'callback' => The callback function, use array for method calling
18
- * 'dashicon' => Desired dashicon
19
- * )
20
  * }
21
  *
22
  * @since 2.2.9
@@ -35,7 +34,7 @@ switch ( $instance ) :
35
  'timestamps' => array(
36
  'name' => __( 'Timestamps', 'autodescription' ),
37
  'callback' => array( $this, 'sitemaps_metabox_timestamps_tab' ),
38
- 'dashicon' => 'backup',
39
  ),
40
  'notify' => array(
41
  'name' => _x( 'Ping', 'Ping or notify Search Engine', 'autodescription' ),
@@ -76,7 +75,6 @@ switch ( $instance ) :
76
  break;
77
 
78
  case 'the_seo_framework_sitemaps_metabox_general' :
79
-
80
  $sitemap_url = $this->get_sitemap_xml_url();
81
  $has_sitemap_plugin = $this->detect_sitemap_plugin();
82
  $sitemap_detected = $this->has_sitemap_xml();
@@ -90,7 +88,7 @@ switch ( $instance ) :
90
  elseif ( $sitemap_detected ) :
91
  $this->description( __( 'A sitemap has been detected in the root folder of your website. This means that the sitemap functionality has no effect.', 'autodescription' ) );
92
  else :
93
- $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' ) );
94
  $this->description( __( 'The optional metadata include the post and page modified time and a page priority indication, which is automated.', 'autodescription' ) );
95
 
96
  ?>
@@ -117,7 +115,6 @@ switch ( $instance ) :
117
  break;
118
 
119
  case 'the_seo_framework_sitemaps_metabox_robots' :
120
-
121
  $locate_url = true;
122
 
123
  ?>
@@ -131,15 +128,19 @@ switch ( $instance ) :
131
  $permalink_settings_url = admin_url( 'options-permalink.php' );
132
  $here = '<a href="' . esc_url( $permalink_settings_url, array( 'http', 'https' ) ) . '" target="_blank" title="' . esc_attr__( 'Permalink Settings', 'autodescription' ) . '">' . esc_html_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
133
 
134
- ?><h4><?php esc_html_e( "You're using the plain permalink structure.", 'autodescription' ); ?></h4><?php
 
 
135
  $this->description( __( "This means the robots.txt file can't be outputted through the WordPress rewrite rules.", 'autodescription' ) );
136
- ?><hr><?php
 
 
137
  $this->description_noesc( sprintf( esc_html_x( 'Change your Permalink Settings %s (Recommended: "Post name").', '%s = here', 'autodescription' ), $here ) );
138
 
139
  $locate_url = false;
140
  elseif ( $this->can_do_sitemap_robots( false ) ) :
141
- $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' ) );
142
- $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' ) );
143
 
144
  ?>
145
  <hr>
@@ -151,7 +152,7 @@ switch ( $instance ) :
151
  $this->wrap_fields(
152
  $this->make_checkbox(
153
  'sitemaps_robots',
154
- esc_html__( 'Add sitemap location in robots?', 'autodescription' ) . ' ' . $this->make_info( __( 'This only has effect if the sitemap is active', 'autodescription' ), '', false ),
155
  '',
156
  false
157
  ), true
@@ -174,31 +175,15 @@ switch ( $instance ) :
174
  break;
175
 
176
  case 'the_seo_framework_sitemaps_metabox_timestamps' :
177
-
178
- //* Sets timezone according to WordPress settings.
179
- $this->set_timezone();
180
-
181
- $timestamp_0 = date( 'Y-m-d' );
182
-
183
- /**
184
- * @link https://www.w3.org/TR/NOTE-datetime
185
- * We use the second expression of the time zone offset handling.
186
- */
187
- $timestamp_1 = date( 'Y-m-d\TH:iP' );
188
-
189
- //* Reset timezone to previous value.
190
- $this->reset_timezone();
191
-
192
- ?><h4><?php esc_html_e( 'Timestamps Settings', 'autodescription' ); ?></h4><?php
193
- $this->description( __( 'The modified time suggests to Search Engines where to look for content changes. It has no impact on the SEO value unless you drastically change pages or posts. It then depends on how well your content is constructed.', 'autodescription' ) );
194
- $this->description( __( "By default, the sitemap only outputs the modified date if you've enabled them within the Social Metabox. This setting overrides those settings for the Sitemap.", 'autodescription' ) );
195
-
196
  ?>
197
  <hr>
198
 
199
  <h4><?php esc_html_e( 'Output Modified Date', 'autodescription' ); ?></h4>
200
  <?php
201
-
202
  //* Echo checkbox.
203
  $this->wrap_fields(
204
  $this->make_checkbox(
@@ -208,36 +193,13 @@ switch ( $instance ) :
208
  false
209
  ), true
210
  );
211
-
212
- ?>
213
- <hr>
214
-
215
- <fieldset>
216
- <legend><h4><?php esc_html_e( 'Timestamp Format Settings', 'autodescription' ); ?></h4></legend>
217
- <?php $this->description( __( 'Determines how specific the modification timestamp is.', 'autodescription' ) ); ?>
218
-
219
- <p id="sitemaps-timestamp-format" class="tsf-fields">
220
- <span class="tsf-toblock">
221
- <input type="radio" name="<?php $this->field_name( 'sitemap_timestamps' ); ?>" id="<?php $this->field_id( 'sitemap_timestamps_0' ); ?>" value="0" <?php checked( $this->get_field_value( 'sitemap_timestamps' ), '0' ); ?> />
222
- <label for="<?php $this->field_id( 'sitemap_timestamps_0' ); ?>">
223
- <span title="<?php esc_attr_e( 'Complete date', 'autodescription' ); ?>"><?php echo $this->code_wrap( $timestamp_0 ); ?> [?]</span>
224
- </label>
225
- </span>
226
- <span class="tsf-toblock">
227
- <input type="radio" name="<?php $this->field_name( 'sitemap_timestamps' ); ?>" id="<?php $this->field_id( 'sitemap_timestamps_1' ); ?>" value="1" <?php checked( $this->get_field_value( 'sitemap_timestamps' ), '1' ); ?> />
228
- <label for="<?php $this->field_id( 'sitemap_timestamps_1' ); ?>">
229
- <span title="<?php esc_attr_e( 'Complete date plus hours, minutes and timezone', 'autodescription' ); ?>"><?php echo $this->code_wrap( $timestamp_1 ); ?> [?]</span>
230
- </label>
231
- </span>
232
- </p>
233
- </fieldset>
234
- <?php
235
  break;
236
 
237
  case 'the_seo_framework_sitemaps_metabox_notify' :
238
-
239
- ?><h4><?php esc_html_e( 'Ping Settings', 'autodescription' ); ?></h4><?php
240
- $this->description( __( 'Notifying Search Engines of a sitemap change is helpful to get your content indexed as soon as possible.', 'autodescription' ) );
 
241
  $this->description( __( 'By default this will happen at most once an hour.', 'autodescription' ) );
242
 
243
  ?>
@@ -264,7 +226,6 @@ switch ( $instance ) :
264
  break;
265
 
266
  case 'the_seo_framework_sitemaps_metabox_style' :
267
-
268
  ?>
269
  <h4><?php esc_html_e( 'Sitemap Styling Settings', 'autodescription' ); ?></h4>
270
  <?php
@@ -281,7 +242,7 @@ switch ( $instance ) :
281
  $this->wrap_fields(
282
  $this->make_checkbox(
283
  'sitemap_styles',
284
- esc_html__( 'Style Sitemap?', 'autodescription' ) . ' ' . $this->make_info( __( 'This makes the sitemap more readable for humans', 'autodescription' ), '', false ),
285
  '',
286
  false
287
  ), true
@@ -298,7 +259,7 @@ switch ( $instance ) :
298
  $this->wrap_fields(
299
  $this->make_checkbox(
300
  'sitemap_logo',
301
- esc_html__( 'Add site logo?', 'autodescription' ) . ' ' . $this->make_info( __( 'The logo is set in Customizer', 'autodescription' ), '', false ),
302
  '',
303
  false
304
  ), true
@@ -327,7 +288,6 @@ switch ( $instance ) :
327
  <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'] ); ?>" />
328
  </p>
329
  <?php
330
-
331
  break;
332
 
333
  default :
7
 
8
  switch ( $instance ) :
9
  case 'the_seo_framework_sitemaps_metabox_main' :
 
10
  /**
11
  * Parse tabs content
12
  *
13
+ * @param array $default_tabs {
14
+ * 'id' = The identifier => array(
15
+ * 'name' => The name
16
+ * 'callback' => The callback function, use array for method calling
17
+ * 'dashicon' => Desired dashicon
18
+ * )
19
  * }
20
  *
21
  * @since 2.2.9
34
  'timestamps' => array(
35
  'name' => __( 'Timestamps', 'autodescription' ),
36
  'callback' => array( $this, 'sitemaps_metabox_timestamps_tab' ),
37
+ 'dashicon' => 'clock',
38
  ),
39
  'notify' => array(
40
  'name' => _x( 'Ping', 'Ping or notify Search Engine', 'autodescription' ),
75
  break;
76
 
77
  case 'the_seo_framework_sitemaps_metabox_general' :
 
78
  $sitemap_url = $this->get_sitemap_xml_url();
79
  $has_sitemap_plugin = $this->detect_sitemap_plugin();
80
  $sitemap_detected = $this->has_sitemap_xml();
88
  elseif ( $sitemap_detected ) :
89
  $this->description( __( 'A sitemap has been detected in the root folder of your website. This means that the sitemap functionality has no effect.', 'autodescription' ) );
90
  else :
91
+ $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' ) );
92
  $this->description( __( 'The optional metadata include the post and page modified time and a page priority indication, which is automated.', 'autodescription' ) );
93
 
94
  ?>
115
  break;
116
 
117
  case 'the_seo_framework_sitemaps_metabox_robots' :
 
118
  $locate_url = true;
119
 
120
  ?>
128
  $permalink_settings_url = admin_url( 'options-permalink.php' );
129
  $here = '<a href="' . esc_url( $permalink_settings_url, array( 'http', 'https' ) ) . '" target="_blank" title="' . esc_attr__( 'Permalink Settings', 'autodescription' ) . '">' . esc_html_x( 'here', 'The sitemap can be found %s.', 'autodescription' ) . '</a>';
130
 
131
+ ?>
132
+ <h4><?php esc_html_e( "You're using the plain permalink structure.", 'autodescription' ); ?></h4>
133
+ <?php
134
  $this->description( __( "This means the robots.txt file can't be outputted through the WordPress rewrite rules.", 'autodescription' ) );
135
+ ?>
136
+ <hr>
137
+ <?php
138
  $this->description_noesc( sprintf( esc_html_x( 'Change your Permalink Settings %s (Recommended: "Post name").', '%s = here', 'autodescription' ), $here ) );
139
 
140
  $locate_url = false;
141
  elseif ( $this->can_do_sitemap_robots( false ) ) :
142
+ $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' ) );
143
+ $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' ) );
144
 
145
  ?>
146
  <hr>
152
  $this->wrap_fields(
153
  $this->make_checkbox(
154
  'sitemaps_robots',
155
+ esc_html__( 'Add sitemap location in robots?', 'autodescription' ) . ' ' . $this->make_info( __( 'This only has effect if the sitemap is active.', 'autodescription' ), '', false ),
156
  '',
157
  false
158
  ), true
175
  break;
176
 
177
  case 'the_seo_framework_sitemaps_metabox_timestamps' :
178
+ ?>
179
+ <h4><?php esc_html_e( 'Timestamps Settings', 'autodescription' ); ?></h4>
180
+ <?php
181
+ $this->description( __( 'The modified time suggests to search engines where to look for content changes. It has no impact on the SEO value unless you drastically change pages or posts. It then depends on how well your content is constructed.', 'autodescription' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  ?>
183
  <hr>
184
 
185
  <h4><?php esc_html_e( 'Output Modified Date', 'autodescription' ); ?></h4>
186
  <?php
 
187
  //* Echo checkbox.
188
  $this->wrap_fields(
189
  $this->make_checkbox(
193
  false
194
  ), true
195
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  break;
197
 
198
  case 'the_seo_framework_sitemaps_metabox_notify' :
199
+ ?>
200
+ <h4><?php esc_html_e( 'Ping Settings', 'autodescription' ); ?></h4>
201
+ <?php
202
+ $this->description( __( 'Notifying search engines of a sitemap change is helpful to get your content indexed as soon as possible.', 'autodescription' ) );
203
  $this->description( __( 'By default this will happen at most once an hour.', 'autodescription' ) );
204
 
205
  ?>
226
  break;
227
 
228
  case 'the_seo_framework_sitemaps_metabox_style' :
 
229
  ?>
230
  <h4><?php esc_html_e( 'Sitemap Styling Settings', 'autodescription' ); ?></h4>
231
  <?php
242
  $this->wrap_fields(
243
  $this->make_checkbox(
244
  'sitemap_styles',
245
+ esc_html__( 'Style Sitemap?', 'autodescription' ) . ' ' . $this->make_info( __( 'This makes the sitemap more readable for humans.', 'autodescription' ), '', false ),
246
  '',
247
  false
248
  ), true
259
  $this->wrap_fields(
260
  $this->make_checkbox(
261
  'sitemap_logo',
262
+ esc_html__( 'Add site logo?', 'autodescription' ) . ' ' . $this->make_info( __( 'The logo is set in Customizer.', 'autodescription' ), '', false ),
263
  '',
264
  false
265
  ), true
288
  <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'] ); ?>" />
289
  </p>
290
  <?php
 
291
  break;
292
 
293
  default :
inc/views/metaboxes/social-metabox.php CHANGED
@@ -13,11 +13,11 @@ 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
19
- * 'dashicon' => Desired dashicon
20
- * )
21
  * }
22
  */
23
  $default_tabs = array(
@@ -61,7 +61,6 @@ switch ( $instance ) :
61
  break;
62
 
63
  case 'the_seo_framework_social_metabox_general' :
64
-
65
  ?>
66
  <h4><?php esc_html_e( 'Social Meta Tags Settings', 'autodescription' ); ?></h4>
67
  <?php
@@ -123,7 +122,7 @@ switch ( $instance ) :
123
  <p>
124
  <label for="tsf_fb_socialimage-url">
125
  <strong><?php esc_html_e( 'Social Image Fallback URL', 'autodescription' ); ?></strong>
126
- <?php $this->make_info( __( 'Preferred Social Image fallback URL location', 'autodescription' ), 'https://developers.facebook.com/docs/sharing/best-practices#images' ); ?>
127
  </label>
128
  </p>
129
  <p>
@@ -164,66 +163,83 @@ switch ( $instance ) :
164
  break;
165
 
166
  case 'the_seo_framework_social_metabox_facebook' :
167
-
168
  $fb_author = $this->get_field_value( 'facebook_author' );
169
- $fb_author_placeholder = empty( $fb_publisher ) ? _x( 'https://www.facebook.com/YourPersonalProfile', 'Example Facebook Personal URL', 'autodescription' ) : '';
170
 
171
  $fb_publisher = $this->get_field_value( 'facebook_publisher' );
172
- $fb_publisher_placeholder = empty( $fb_publisher ) ? _x( 'https://www.facebook.com/YourVerifiedBusinessProfile', 'Example Verified Facebook Business URL', 'autodescription' ) : '';
173
 
174
  $fb_appid = $this->get_field_value( 'facebook_appid' );
175
- $fb_appid_placeholder = empty( $fb_appid ) ? '123456789012345' : '';
176
 
177
- ?><h4><?php esc_html_e( 'Default Facebook Integration Settings', 'autodescription' ); ?></h4><?php
 
 
178
  $this->description( __( 'Facebook post sharing works mostly through Open Graph. However, you can also link your Business and Personal Facebook pages, among various other options.', 'autodescription' ) );
179
- $this->description( __( 'When these options are filled in, Facebook might link your Facebook profile to be followed and liked when your post or page is shared.', 'autodescription' ) );
180
-
181
  ?>
182
  <hr>
183
 
184
  <p>
185
- <label for="<?php $this->field_id( 'facebook_author' ); ?>">
186
- <strong><?php esc_html_e( 'Article Author Facebook URL', 'autodescription' ); ?></strong>
187
- <a href="<?php echo esc_url( 'https://facebook.com/me' ); ?>" class="description" target="_blank" title="<?php esc_attr_e( 'Your Facebook Profile', 'autodescription' ); ?>">[?]</a>
188
  </label>
 
 
 
 
 
 
189
  </p>
190
  <p>
191
- <input type="text" name="<?php $this->field_name( 'facebook_author' ); ?>" class="large-text" id="<?php $this->field_id( 'facebook_author' ); ?>" placeholder="<?php echo esc_attr( $fb_author_placeholder ); ?>" value="<?php echo esc_attr( $fb_author ); ?>" />
192
  </p>
193
 
194
  <p>
195
  <label for="<?php $this->field_id( 'facebook_publisher' ); ?>">
196
  <strong><?php esc_html_e( 'Article Publisher Facebook URL', 'autodescription' ); ?></strong>
197
- <a href="<?php echo esc_url( 'https://instantarticles.fb.com/' ); ?>" class="description" target="_blank" title="<?php esc_html_e( 'To use this, you need to be a verified business', 'autodescription' ); ?>">[?]</a>
198
  </label>
 
 
 
 
 
 
199
  </p>
200
  <p>
201
  <input type="text" name="<?php $this->field_name( 'facebook_publisher' ); ?>" class="large-text" id="<?php $this->field_id( 'facebook_publisher' ); ?>" placeholder="<?php echo esc_attr( $fb_publisher_placeholder ); ?>" value="<?php echo esc_attr( $fb_publisher ); ?>" />
202
  </p>
203
 
204
  <p>
205
- <label for="<?php $this->field_id( 'facebook_appid' ); ?>">
206
- <strong><?php esc_html_e( 'Facebook App ID', 'autodescription' ); ?></strong>
207
- <a href="<?php echo esc_url( 'https://developers.facebook.com/apps' ); ?>" target="_blank" class="description" title="<?php esc_html_e( 'Get Facebook App ID', 'autodescription' ); ?>">[?]</a>
208
  </label>
 
 
 
 
 
 
209
  </p>
 
210
  <p>
211
- <input type="text" name="<?php $this->field_name( 'facebook_appid' ); ?>" class="large-text" id="<?php $this->field_id( 'facebook_appid' ); ?>" placeholder="<?php echo esc_attr( $fb_appid_placeholder ); ?>" value="<?php echo esc_attr( $fb_appid ); ?>" />
212
  </p>
213
  <?php
214
  break;
215
 
216
  case 'the_seo_framework_social_metabox_twitter' :
217
-
218
  $tw_site = $this->get_field_value( 'twitter_site' );
219
- $tw_site_placeholder = empty( $tw_site ) ? _x( '@your-site-username', 'Twitter @username', 'autodescription' ) : '';
220
 
221
  $tw_creator = $this->get_field_value( 'twitter_creator' );
222
- $tw_creator_placeholder = empty( $tw_creator ) ? _x( '@your-personal-username', 'Twitter @username', 'autodescription' ) : '';
223
 
224
  $twitter_card = $this->get_twitter_card_types();
225
 
226
- ?><h4><?php esc_html_e( 'Default Twitter Integration Settings', 'autodescription' ); ?></h4><?php
 
 
227
  $this->description( __( 'Twitter post sharing works mostly through Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options.', 'autodescription' ) );
228
 
229
  ?>
@@ -260,13 +276,20 @@ switch ( $instance ) :
260
 
261
  <hr>
262
 
263
- <?php $this->description( __( 'When the following options are filled in, Twitter might link your Twitter Site or Personal Profile when your post or page is shared.', 'autodescription' ) ); ?>
 
 
264
 
265
  <p>
266
  <label for="<?php $this->field_id( 'twitter_site' ); ?>" class="tsf-toblock">
267
- <strong><?php esc_html_e( "Your Website's Twitter Profile", 'autodescription' ); ?></strong>
268
- <a href="<?php echo esc_url( 'https://twitter.com/home' ); ?>" target="_blank" class="description" title="<?php esc_html_e( 'Find your @username', 'autodescription' ); ?>">[?]</a>
269
  </label>
 
 
 
 
 
 
270
  </p>
271
  <p>
272
  <input type="text" name="<?php $this->field_name( 'twitter_site' ); ?>" class="large-text" id="<?php $this->field_id( 'twitter_site' ); ?>" placeholder="<?php echo esc_attr( $tw_site_placeholder ); ?>" value="<?php echo esc_attr( $tw_site ); ?>" />
@@ -274,10 +297,16 @@ switch ( $instance ) :
274
 
275
  <p>
276
  <label for="<?php $this->field_id( 'twitter_creator' ); ?>" class="tsf-toblock">
277
- <strong><?php esc_html_e( 'Your Personal Twitter Profile', 'autodescription' ); ?></strong>
278
- <a href="<?php echo esc_url( 'https://twitter.com/home' ); ?>" target="_blank" class="description" title="<?php esc_attr_e( 'Find your @username', 'autodescription' ); ?>">[?]</a>
279
  </label>
 
 
 
 
 
 
280
  </p>
 
281
  <p>
282
  <input type="text" name="<?php $this->field_name( 'twitter_creator' ); ?>" class="large-text" id="<?php $this->field_id( 'twitter_creator' ); ?>" placeholder="<?php echo esc_attr( $tw_creator_placeholder ); ?>" value="<?php echo esc_attr( $tw_creator ); ?>" />
283
  </p>
@@ -285,54 +314,24 @@ switch ( $instance ) :
285
  break;
286
 
287
  case 'the_seo_framework_social_metabox_postdates' :
288
-
289
- $pages_i18n = esc_html__( 'Pages', 'autodescription' );
290
  $posts_i18n = esc_html__( 'Posts', 'autodescription' );
291
  $home_i18n = esc_html__( 'Home Page', 'autodescription' );
292
 
293
- ?><h4><?php esc_html_e( 'Post Date Settings', 'autodescription' ); ?></h4><?php
294
- $this->description( __( '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.', 'autodescription' ) );
295
- $this->description( __( "It's recommended on posts, but it's not recommended on pages unless you modify or create new pages frequently.", 'autodescription' ) );
 
296
 
297
  /* translators: 1: Option, 2: Post Type */
298
  $post_publish_time_label = sprintf( esc_html__( 'Add %1$s to %2$s?', 'autodescription' ), $this->code_wrap( 'article:published_time' ), $posts_i18n );
299
  $post_publish_time_checkbox = $this->make_checkbox( 'post_publish_time', $post_publish_time_label, '', false );
300
 
301
- /* translators: 1: Option, 2: Post Type */
302
- $page_publish_time_label = sprintf( esc_html__( 'Add %1$s to %2$s?', 'autodescription' ), $this->code_wrap( 'article:published_time' ), $pages_i18n );
303
- $page_publish_time_checkbox = $this->make_checkbox( 'page_publish_time', $page_publish_time_label, '', false );
304
-
305
- //* Echo checkboxes.
306
- $this->wrap_fields( $post_publish_time_checkbox . $page_publish_time_checkbox, true );
307
-
308
  /* translators: 1: Option, 2: Post Type */
309
  $post_modify_time_label = sprintf( esc_html__( 'Add %1$s to %2$s?', 'autodescription' ), $this->code_wrap( 'article:modified_time' ), $posts_i18n );
310
  $post_modify_time_checkbox = $this->make_checkbox( 'post_modify_time', $post_modify_time_label, '', false );
311
 
312
- /* translators: 1: Option, 2: Post Type */
313
- $page_modify_time_label = sprintf( esc_html__( 'Add %1$s to %2$s?', 'autodescription' ), $this->code_wrap( 'article:modified_time' ), $pages_i18n );
314
- $page_modify_time_checkbox = $this->make_checkbox( 'page_modify_time', $page_modify_time_label, '', false );
315
-
316
- //* Echo checkboxes.
317
- $this->wrap_fields( $post_modify_time_checkbox . $page_modify_time_checkbox, true );
318
-
319
- ?>
320
- <hr>
321
-
322
- <h4><?php esc_html_e( 'Home Page', 'autodescription' ); ?></h4>
323
- <?php
324
- $this->description( __( '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.', 'autodescription' ) );
325
-
326
- /* translators: 1: Option, 2: Post Type */
327
- $home_publish_time_label = sprintf( esc_html__( 'Add %1$s to %2$s?', 'autodescription' ), $this->code_wrap( 'article:published_time' ), $home_i18n );
328
- $home_publish_time_checkbox = $this->make_checkbox( 'home_publish_time', $home_publish_time_label, '', false );
329
-
330
- /* translators: 1: Option, 2: Post Type */
331
- $home_modify_time_label = sprintf( esc_html__( 'Add %1$s to %2$s?', 'autodescription' ), $this->code_wrap( 'article:modified_time' ), $home_i18n );
332
- $home_modify_time_checkbox = $this->make_checkbox( 'home_modify_time', $home_modify_time_label, '', false );
333
-
334
  //* Echo checkboxes.
335
- $this->wrap_fields( $home_publish_time_checkbox . $home_modify_time_checkbox, true );
336
  break;
337
 
338
  default :
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(
61
  break;
62
 
63
  case 'the_seo_framework_social_metabox_general' :
 
64
  ?>
65
  <h4><?php esc_html_e( 'Social Meta Tags Settings', 'autodescription' ); ?></h4>
66
  <?php
122
  <p>
123
  <label for="tsf_fb_socialimage-url">
124
  <strong><?php esc_html_e( 'Social Image Fallback URL', 'autodescription' ); ?></strong>
125
+ <?php $this->make_info( __( 'Set preferred Social Image fallback URL location.', 'autodescription' ), 'https://developers.facebook.com/docs/sharing/best-practices#images' ); ?>
126
  </label>
127
  </p>
128
  <p>
163
  break;
164
 
165
  case 'the_seo_framework_social_metabox_facebook' :
 
166
  $fb_author = $this->get_field_value( 'facebook_author' );
167
+ $fb_author_placeholder = _x( 'https://www.facebook.com/YourPersonalProfile', 'Example Facebook Personal URL', 'autodescription' );
168
 
169
  $fb_publisher = $this->get_field_value( 'facebook_publisher' );
170
+ $fb_publisher_placeholder = _x( 'https://www.facebook.com/YourVerifiedBusinessProfile', 'Example Verified Facebook Business URL', 'autodescription' );
171
 
172
  $fb_appid = $this->get_field_value( 'facebook_appid' );
173
+ $fb_appid_placeholder = '123456789012345';
174
 
175
+ ?>
176
+ <h4><?php esc_html_e( 'Default Facebook Integration Settings', 'autodescription' ); ?></h4>
177
+ <?php
178
  $this->description( __( 'Facebook post sharing works mostly through Open Graph. However, you can also link your Business and Personal Facebook pages, among various other options.', 'autodescription' ) );
179
+ $this->description( __( 'When these options are filled in, Facebook might link the Facebook profile to be followed and liked when your post or page is shared.', 'autodescription' ) );
 
180
  ?>
181
  <hr>
182
 
183
  <p>
184
+ <label for="<?php $this->field_id( 'facebook_appid' ); ?>">
185
+ <strong><?php esc_html_e( 'Facebook App ID', 'autodescription' ); ?></strong>
 
186
  </label>
187
+ <?php
188
+ $this->make_info(
189
+ __( 'Get Facebook App ID.', 'autodescription' ),
190
+ 'https://developers.facebook.com/apps'
191
+ );
192
+ ?>
193
  </p>
194
  <p>
195
+ <input type="text" name="<?php $this->field_name( 'facebook_appid' ); ?>" class="large-text" id="<?php $this->field_id( 'facebook_appid' ); ?>" placeholder="<?php echo esc_attr( $fb_appid_placeholder ); ?>" value="<?php echo esc_attr( $fb_appid ); ?>" />
196
  </p>
197
 
198
  <p>
199
  <label for="<?php $this->field_id( 'facebook_publisher' ); ?>">
200
  <strong><?php esc_html_e( 'Article Publisher Facebook URL', 'autodescription' ); ?></strong>
 
201
  </label>
202
+ <?php
203
+ $this->make_info(
204
+ __( 'To use this, you need to be a verified business.', 'autodescription' ),
205
+ 'https://instantarticles.fb.com/'
206
+ );
207
+ ?>
208
  </p>
209
  <p>
210
  <input type="text" name="<?php $this->field_name( 'facebook_publisher' ); ?>" class="large-text" id="<?php $this->field_id( 'facebook_publisher' ); ?>" placeholder="<?php echo esc_attr( $fb_publisher_placeholder ); ?>" value="<?php echo esc_attr( $fb_publisher ); ?>" />
211
  </p>
212
 
213
  <p>
214
+ <label for="<?php $this->field_id( 'facebook_author' ); ?>">
215
+ <strong><?php esc_html_e( 'Article Author Facebook Fallback URL', 'autodescription' ); ?></strong>
 
216
  </label>
217
+ <?php
218
+ $this->make_info(
219
+ __( 'Your Facebook Profile.', 'autodescription' ),
220
+ 'https://facebook.com/me'
221
+ );
222
+ ?>
223
  </p>
224
+ <?php $this->description( __( 'Authors can override this option on their profile page.', 'autodescription' ) ); ?>
225
  <p>
226
+ <input type="text" name="<?php $this->field_name( 'facebook_author' ); ?>" class="large-text" id="<?php $this->field_id( 'facebook_author' ); ?>" placeholder="<?php echo esc_attr( $fb_author_placeholder ); ?>" value="<?php echo esc_attr( $fb_author ); ?>" />
227
  </p>
228
  <?php
229
  break;
230
 
231
  case 'the_seo_framework_social_metabox_twitter' :
 
232
  $tw_site = $this->get_field_value( 'twitter_site' );
233
+ $tw_site_placeholder = _x( '@your-site-username', 'Twitter @username', 'autodescription' );
234
 
235
  $tw_creator = $this->get_field_value( 'twitter_creator' );
236
+ $tw_creator_placeholder = _x( '@your-personal-username', 'Twitter @username', 'autodescription' );
237
 
238
  $twitter_card = $this->get_twitter_card_types();
239
 
240
+ ?>
241
+ <h4><?php esc_html_e( 'Default Twitter Integration Settings', 'autodescription' ); ?></h4>
242
+ <?php
243
  $this->description( __( 'Twitter post sharing works mostly through Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options.', 'autodescription' ) );
244
 
245
  ?>
276
 
277
  <hr>
278
 
279
+ <?php
280
+ $this->description( __( 'When the following options are filled in, Twitter might link your Twitter Site or Author Profile when your post or page is shared.', 'autodescription' ) );
281
+ ?>
282
 
283
  <p>
284
  <label for="<?php $this->field_id( 'twitter_site' ); ?>" class="tsf-toblock">
285
+ <strong><?php esc_html_e( 'Website Twitter Profile', 'autodescription' ); ?></strong>
 
286
  </label>
287
+ <?php
288
+ $this->make_info(
289
+ __( 'Find your @username.', 'autodescription' ),
290
+ 'https://twitter.com/home'
291
+ );
292
+ ?>
293
  </p>
294
  <p>
295
  <input type="text" name="<?php $this->field_name( 'twitter_site' ); ?>" class="large-text" id="<?php $this->field_id( 'twitter_site' ); ?>" placeholder="<?php echo esc_attr( $tw_site_placeholder ); ?>" value="<?php echo esc_attr( $tw_site ); ?>" />
297
 
298
  <p>
299
  <label for="<?php $this->field_id( 'twitter_creator' ); ?>" class="tsf-toblock">
300
+ <strong><?php esc_html_e( 'Twitter Author Fallback Profile', 'autodescription' ); ?></strong>
 
301
  </label>
302
+ <?php
303
+ $this->make_info(
304
+ __( 'Find your @username.', 'autodescription' ),
305
+ 'https://twitter.com/home'
306
+ );
307
+ ?>
308
  </p>
309
+ <?php $this->description( __( 'Authors can override this option on their profile page.', 'autodescription' ) ); ?>
310
  <p>
311
  <input type="text" name="<?php $this->field_name( 'twitter_creator' ); ?>" class="large-text" id="<?php $this->field_id( 'twitter_creator' ); ?>" placeholder="<?php echo esc_attr( $tw_creator_placeholder ); ?>" value="<?php echo esc_attr( $tw_creator ); ?>" />
312
  </p>
314
  break;
315
 
316
  case 'the_seo_framework_social_metabox_postdates' :
 
 
317
  $posts_i18n = esc_html__( 'Posts', 'autodescription' );
318
  $home_i18n = esc_html__( 'Home Page', 'autodescription' );
319
 
320
+ ?>
321
+ <h4><?php esc_html_e( 'Post Date Settings', 'autodescription' ); ?></h4>
322
+ <?php
323
+ $this->description( __( 'Some social sites output the published date and modified date in the sharing snippet.', 'autodescription' ) );
324
 
325
  /* translators: 1: Option, 2: Post Type */
326
  $post_publish_time_label = sprintf( esc_html__( 'Add %1$s to %2$s?', 'autodescription' ), $this->code_wrap( 'article:published_time' ), $posts_i18n );
327
  $post_publish_time_checkbox = $this->make_checkbox( 'post_publish_time', $post_publish_time_label, '', false );
328
 
 
 
 
 
 
 
 
329
  /* translators: 1: Option, 2: Post Type */
330
  $post_modify_time_label = sprintf( esc_html__( 'Add %1$s to %2$s?', 'autodescription' ), $this->code_wrap( 'article:modified_time' ), $posts_i18n );
331
  $post_modify_time_checkbox = $this->make_checkbox( 'post_modify_time', $post_modify_time_label, '', false );
332
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  //* Echo checkboxes.
334
+ $this->wrap_fields( $post_publish_time_checkbox . $post_modify_time_checkbox, true );
335
  break;
336
 
337
  default :
inc/views/metaboxes/title-metabox.php CHANGED
@@ -106,14 +106,16 @@ switch ( $instance ) :
106
 
107
  ?>
108
  <fieldset>
109
- <legend><h4><?php esc_html_e( 'Document Title Separator', 'autodescription' ); ?></h4></legend>
 
 
 
110
  <p id="tsf-title-separator" class="tsf-fields">
111
  <?php foreach ( $title_separator as $name => $html ) { ?>
112
  <input type="radio" name="<?php $this->field_name( 'title_seperator' ); ?>" id="<?php $this->field_id( 'title_seperator_' . $name ); ?>" value="<?php echo esc_attr( $name ); ?>" <?php checked( $this->get_field_value( 'title_seperator' ), $name ); ?> />
113
  <label for="<?php $this->field_id( 'title_seperator_' . $name ); ?>" <?php echo in_array( $name, array( 'dash', 'pipe' ), true ) ? $recommended : ''; ?>><?php echo esc_html( $html ); ?></label>
114
  <?php } ?>
115
  </p>
116
- <?php $this->description( __( 'If the title consists of two parts (original title and optional addition), then the separator will go in-between them.', 'autodescription' ) ); ?>
117
  </fieldset>
118
  <?php
119
  break;
@@ -129,10 +131,10 @@ switch ( $instance ) :
129
 
130
  ?>
131
  <fieldset>
132
- <legend><h4><?php esc_html_e( 'Document Title Additions Location', 'autodescription' ); ?></h4></legend>
133
-
134
- <?php $this->description( __( 'Determines which side the added title text will go on.', 'autodescription' ) ); ?>
135
-
136
  <p id="tsf-title-location" class="tsf-fields">
137
  <span class="tsf-toblock">
138
  <input type="radio" name="<?php $this->field_name( 'title_location' ); ?>" id="<?php $this->field_id( 'title_location_left' ); ?>" value="left" <?php checked( $this->get_field_value( 'title_location' ), 'left' ); ?> />
@@ -162,7 +164,7 @@ switch ( $instance ) :
162
  <div id="tsf-title-additions-toggle">
163
  <?php
164
  $info = $this->make_info(
165
- __( 'This might decouple your posts and pages from the rest of the website', 'autodescription' ),
166
  'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#3',
167
  false
168
  );
@@ -243,7 +245,7 @@ switch ( $instance ) :
243
  </label>
244
  <?php
245
  $this->make_info(
246
- __( "The prefix helps visitors and Search Engines determine what kind of page they're visiting", 'autodescription' ),
247
  'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#3',
248
  true
249
  );
106
 
107
  ?>
108
  <fieldset>
109
+ <legend>
110
+ <h4><?php esc_html_e( 'Title Separator', 'autodescription' ); ?></h4>
111
+ <?php $this->description( __( 'If the title consists of two parts (original title and optional addition), then the separator will go in-between them.', 'autodescription' ) ); ?>
112
+ </legend>
113
  <p id="tsf-title-separator" class="tsf-fields">
114
  <?php foreach ( $title_separator as $name => $html ) { ?>
115
  <input type="radio" name="<?php $this->field_name( 'title_seperator' ); ?>" id="<?php $this->field_id( 'title_seperator_' . $name ); ?>" value="<?php echo esc_attr( $name ); ?>" <?php checked( $this->get_field_value( 'title_seperator' ), $name ); ?> />
116
  <label for="<?php $this->field_id( 'title_seperator_' . $name ); ?>" <?php echo in_array( $name, array( 'dash', 'pipe' ), true ) ? $recommended : ''; ?>><?php echo esc_html( $html ); ?></label>
117
  <?php } ?>
118
  </p>
 
119
  </fieldset>
120
  <?php
121
  break;
131
 
132
  ?>
133
  <fieldset>
134
+ <legend>
135
+ <h4><?php esc_html_e( 'Title Additions Location', 'autodescription' ); ?></h4>
136
+ <?php $this->description( __( 'This setting determines which side the added title text will go on.', 'autodescription' ) ); ?>
137
+ </legend>
138
  <p id="tsf-title-location" class="tsf-fields">
139
  <span class="tsf-toblock">
140
  <input type="radio" name="<?php $this->field_name( 'title_location' ); ?>" id="<?php $this->field_id( 'title_location_left' ); ?>" value="left" <?php checked( $this->get_field_value( 'title_location' ), 'left' ); ?> />
164
  <div id="tsf-title-additions-toggle">
165
  <?php
166
  $info = $this->make_info(
167
+ __( 'This might decouple your posts and pages from the rest of the website.', 'autodescription' ),
168
  'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#3',
169
  false
170
  );
245
  </label>
246
  <?php
247
  $this->make_info(
248
+ __( "The prefix helps visitors and search engines determine what kind of page they're visiting.", 'autodescription' ),
249
  'https://support.google.com/webmasters/answer/35624?hl=' . $language . '#3',
250
  true
251
  );
inc/views/metaboxes/webmaster-metabox.php CHANGED
@@ -7,7 +7,7 @@ $instance = $this->get_view_instance( 'the_seo_framework_webmaster_metabox', $in
7
 
8
  switch ( $instance ) :
9
  case 'the_seo_framework_webmaster_metabox_main' :
10
- $site_url = $this->the_home_url_from_cache();
11
  $language = $this->google_language();
12
 
13
  $bing_site_url = 'https://www.bing.com/webmaster/configure/verify/ownership?url=' . urlencode( $site_url );
@@ -23,40 +23,60 @@ switch ( $instance ) :
23
  <hr>
24
 
25
  <p>
26
- <label for="<?php $this->field_id( 'google_verification' ); ?>" class="tsf-toblock">
27
  <strong><?php esc_html_e( 'Google Webmaster Verification Code', 'autodescription' ); ?></strong>
28
- <a href="<?php echo esc_url( $google_site_url ); ?>" target="_blank" class="description" title="<?php esc_attr_e( 'Get the Google Verification code', 'autodescription' ); ?>">[?]</a>
29
  </label>
 
 
 
 
 
 
30
  </p>
31
  <p>
32
  <input type="text" name="<?php $this->field_name( 'google_verification' ); ?>" class="large-text" id="<?php $this->field_id( 'google_verification' ); ?>" placeholder="ABC1d2eFg34H5iJ6klmNOp7qRstUvWXyZaBc8dEfG9" value="<?php echo esc_attr( $this->get_field_value( 'google_verification' ) ); ?>" />
33
  </p>
34
 
35
  <p>
36
- <label for="<?php $this->field_id( 'bing_verification' ); ?>" class="tsf-toblock">
37
  <strong><?php esc_html_e( 'Bing Webmaster Verification Code', 'autodescription' ); ?></strong>
38
- <a href="<?php echo esc_url( $bing_site_url ); ?>" target="_blank" class="description" title="<?php esc_attr_e( 'Get the Bing Verification Code', 'autodescription' ); ?>">[?]</a>
39
  </label>
 
 
 
 
 
 
40
  </p>
41
  <p>
42
  <input type="text" name="<?php $this->field_name( 'bing_verification' ); ?>" class="large-text" id="<?php $this->field_id( 'bing_verification' ); ?>" placeholder="123A456B78901C2D3456E7890F1A234D" value="<?php echo esc_attr( $this->get_field_value( 'bing_verification' ) ); ?>" />
43
  </p>
44
 
45
  <p>
46
- <label for="<?php $this->field_id( 'yandex_verification' ); ?>" class="tsf-toblock">
47
  <strong><?php esc_html_e( 'Yandex Webmaster Verification Code', 'autodescription' ); ?></strong>
48
- <a href="<?php echo esc_url( $yandex_site_url ); ?>" target="_blank" class="description" title="<?php esc_attr_e( 'Get the Yandex Verification Code', 'autodescription' ); ?>">[?]</a>
49
  </label>
 
 
 
 
 
 
50
  </p>
51
  <p>
52
  <input type="text" name="<?php $this->field_name( 'yandex_verification' ); ?>" class="large-text" id="<?php $this->field_id( 'yandex_verification' ); ?>" placeholder="12345abc678901d2" value="<?php echo esc_attr( $this->get_field_value( 'yandex_verification' ) ); ?>" />
53
  </p>
54
 
55
  <p>
56
- <label for="<?php $this->field_id( 'pint_verification' ); ?>" class="tsf-toblock">
57
  <strong><?php esc_html_e( 'Pinterest Analytics Verification Code', 'autodescription' ); ?></strong>
58
- <a href="<?php echo esc_url( $pint_site_url ); ?>" target="_blank" class="description" title="<?php esc_attr_e( 'Get the Pinterest Verification Code', 'autodescription' ); ?>">[?]</a>
59
  </label>
 
 
 
 
 
 
60
  </p>
61
  <p>
62
  <input type="text" name="<?php $this->field_name( 'pint_verification' ); ?>" class="large-text" id="<?php $this->field_id( 'pint_verification' ); ?>" placeholder="123456a7b8901de2fa34bcdef5a67b98" value="<?php echo esc_attr( $this->get_field_value( 'pint_verification' ) ); ?>" />
7
 
8
  switch ( $instance ) :
9
  case 'the_seo_framework_webmaster_metabox_main' :
10
+ $site_url = $this->get_homepage_permalink();
11
  $language = $this->google_language();
12
 
13
  $bing_site_url = 'https://www.bing.com/webmaster/configure/verify/ownership?url=' . urlencode( $site_url );
23
  <hr>
24
 
25
  <p>
26
+ <label for="<?php $this->field_id( 'google_verification' ); ?>">
27
  <strong><?php esc_html_e( 'Google Webmaster Verification Code', 'autodescription' ); ?></strong>
 
28
  </label>
29
+ <?php
30
+ $this->make_info(
31
+ __( 'Get the Google verification code.', 'autodescription' ),
32
+ $google_site_url
33
+ );
34
+ ?>
35
  </p>
36
  <p>
37
  <input type="text" name="<?php $this->field_name( 'google_verification' ); ?>" class="large-text" id="<?php $this->field_id( 'google_verification' ); ?>" placeholder="ABC1d2eFg34H5iJ6klmNOp7qRstUvWXyZaBc8dEfG9" value="<?php echo esc_attr( $this->get_field_value( 'google_verification' ) ); ?>" />
38
  </p>
39
 
40
  <p>
41
+ <label for="<?php $this->field_id( 'bing_verification' ); ?>">
42
  <strong><?php esc_html_e( 'Bing Webmaster Verification Code', 'autodescription' ); ?></strong>
 
43
  </label>
44
+ <?php
45
+ $this->make_info(
46
+ __( 'Get the Bing verification code.', 'autodescription' ),
47
+ $bing_site_url
48
+ );
49
+ ?>
50
  </p>
51
  <p>
52
  <input type="text" name="<?php $this->field_name( 'bing_verification' ); ?>" class="large-text" id="<?php $this->field_id( 'bing_verification' ); ?>" placeholder="123A456B78901C2D3456E7890F1A234D" value="<?php echo esc_attr( $this->get_field_value( 'bing_verification' ) ); ?>" />
53
  </p>
54
 
55
  <p>
56
+ <label for="<?php $this->field_id( 'yandex_verification' ); ?>">
57
  <strong><?php esc_html_e( 'Yandex Webmaster Verification Code', 'autodescription' ); ?></strong>
 
58
  </label>
59
+ <?php
60
+ $this->make_info(
61
+ __( 'Get the Yandex verification code.', 'autodescription' ),
62
+ $yandex_site_url
63
+ );
64
+ ?>
65
  </p>
66
  <p>
67
  <input type="text" name="<?php $this->field_name( 'yandex_verification' ); ?>" class="large-text" id="<?php $this->field_id( 'yandex_verification' ); ?>" placeholder="12345abc678901d2" value="<?php echo esc_attr( $this->get_field_value( 'yandex_verification' ) ); ?>" />
68
  </p>
69
 
70
  <p>
71
+ <label for="<?php $this->field_id( 'pint_verification' ); ?>">
72
  <strong><?php esc_html_e( 'Pinterest Analytics Verification Code', 'autodescription' ); ?></strong>
 
73
  </label>
74
+ <?php
75
+ $this->make_info(
76
+ __( 'Get the Pinterest verification code.', 'autodescription' ),
77
+ $pint_site_url
78
+ );
79
+ ?>
80
  </p>
81
  <p>
82
  <input type="text" name="<?php $this->field_name( 'pint_verification' ); ?>" class="large-text" id="<?php $this->field_id( 'pint_verification' ); ?>" placeholder="123456a7b8901de2fa34bcdef5a67b98" value="<?php echo esc_attr( $this->get_field_value( 'pint_verification' ) ); ?>" />
inc/views/profile/author.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Views\Profile
4
+ */
5
+
6
+ defined( 'ABSPATH' ) and $_this = the_seo_framework_class() and $this instanceof $_this or die;
7
+
8
+ ?>
9
+ <h2><?php esc_html_e( 'Authorial Info', 'autodescription' ); ?></h2>
10
+ <table class="form-table">
11
+ <?php
12
+ foreach ( $fields as $field => $labels ) :
13
+ ?>
14
+ <tr class="user-<?php echo $field; ?>-wrap">
15
+ <th><label for="<?php echo $field; ?>">
16
+ <?php echo esc_html( $labels->name ); ?>
17
+ </label></th>
18
+ <td>
19
+ <input type="text" name="<?php echo $field; ?>" id="<?php echo $field; ?>" value="<?php echo esc_attr( $labels->value ) ?>" placeholder="<?php echo esc_attr( $labels->placeholder ) ?>" class="regular-text" />
20
+ </td>
21
+ </tr>
22
+ <?php
23
+ endforeach;
24
+ ?>
25
+ </table>
26
+ <?php
inc/views/profile/index.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Communication - the human connection - is the key to personal and career success.
4
+ *
5
+ * - Paul J. Meyer
6
+ */
inc/views/templates/index.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Life is a great big canvas, and you should throw all the paint on it you can.
4
+ *
5
+ * - Danny Kaye
6
+ */
inc/views/templates/inpost/index.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Painting is easy when you don't know how, but very difficult when you do.
4
+ *
5
+ * - Edgar Degas
6
+ */
inc/views/templates/inpost/primary-term-selector.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) and $_this = the_seo_framework_class() and $this instanceof $_this or die;
4
+
5
+ ?>
6
+ <script type="text/html" id="tmpl-tsf-primary-term-selector">
7
+ <input type="hidden" id="autodescription[_primary_term_{{data.taxonomy.name}}]" name="autodescription[_primary_term_{{data.taxonomy.name}}]" value="{{data.taxonomy.primary}}">
8
+ <?php
9
+ wp_nonce_field(
10
+ $this->inpost_nonce_field . '_pt',
11
+ $this->inpost_nonce_name . '_pt_{{data.taxonomy.name}}'
12
+ );
13
+ ?>
14
+ </script>
15
+
16
+ <script type="text/html" id="tmpl-tsf-primary-term-selector-help">
17
+ <span class="tsf-primary-term-selector-help-wrap">
18
+ <?php
19
+ $this->make_info(
20
+ sprintf(
21
+ /* translators: %s = term name */
22
+ \esc_html__( 'You can set the primary %s through the buttons below.', 'autodescription' ),
23
+ '{{data.taxonomy.name}}'
24
+ )
25
+ );
26
+ ?>
27
+ </span>
28
+ </script>
29
+ <?php
language/autodescription.pot CHANGED
@@ -2,9 +2,9 @@
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.9.4\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/autodescription\n"
7
- "POT-Creation-Date: 2017-08-30 07:01:11+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -12,37 +12,63 @@ msgstr ""
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
- #: inc/classes/admin-init.class.php:233
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  msgid "Good"
17
  msgstr ""
18
 
19
- #: inc/classes/admin-init.class.php:234
20
  msgid "Okay"
21
  msgstr ""
22
 
23
- #: inc/classes/admin-init.class.php:235
24
  msgid "Bad"
25
  msgstr ""
26
 
27
- #: inc/classes/admin-init.class.php:236
28
  msgid "Unknown"
29
  msgstr ""
30
 
31
- #: inc/classes/admin-init.class.php:327
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:328
36
- msgid "Are you sure you want to reset all SEO settings to their defaults?"
 
 
 
 
 
 
37
  msgstr ""
38
 
39
  #. translators: %s = Redirect URL markdown
40
 
41
- #: inc/classes/admin-init.class.php:595
42
  msgid "There has been an error redirecting. Refresh the page or follow [this link](%s)."
43
  msgstr ""
44
 
45
- #: inc/classes/admin-init.class.php:681 inc/classes/admin-init.class.php:743
46
  msgid "Image could not be processed."
47
  msgstr ""
48
 
@@ -70,8 +96,7 @@ msgstr ""
70
  msgid "New SEO Settings have been updated."
71
  msgstr ""
72
 
73
- #: inc/classes/admin-pages.class.php:109 inc/classes/core.class.php:253
74
- #: inc/classes/site-options.class.php:440
75
  msgid "SEO Settings"
76
  msgstr ""
77
 
@@ -79,97 +104,128 @@ msgstr ""
79
  msgid "SEO"
80
  msgstr ""
81
 
82
- #: inc/classes/admin-pages.class.php:243
83
  msgid "General Settings"
84
  msgstr ""
85
 
86
- #: inc/classes/admin-pages.class.php:254
87
  msgid "Title Settings"
88
  msgstr ""
89
 
90
- #: inc/classes/admin-pages.class.php:265
91
  msgid "Description Meta Settings"
92
  msgstr ""
93
 
94
- #: inc/classes/admin-pages.class.php:276
95
  msgid "Home Page Settings"
96
  msgstr ""
97
 
98
- #: inc/classes/admin-pages.class.php:287
99
  msgid "Social Meta Settings"
100
  msgstr ""
101
 
102
- #: inc/classes/admin-pages.class.php:298
103
  msgid "Schema Settings"
104
  msgstr ""
105
 
106
- #: inc/classes/admin-pages.class.php:309
107
- #: inc/views/inpost/seo-settings-singular.php:208
108
- #: inc/views/inpost/seo-settings-tt.php:119
109
  msgid "Robots Meta Settings"
110
  msgstr ""
111
 
112
- #: inc/classes/admin-pages.class.php:320
113
  msgid "Webmaster Meta Settings"
114
  msgstr ""
115
 
116
- #: inc/classes/admin-pages.class.php:331
117
  msgid "Sitemap Settings"
118
  msgstr ""
119
 
120
- #: inc/classes/admin-pages.class.php:342
121
  msgid "Feed Settings"
122
  msgstr ""
123
 
124
- #: inc/classes/admin-pages.class.php:846 inc/classes/admin-pages.class.php:853
125
  msgctxt "Button hover"
126
  msgid "Select social image"
127
  msgstr ""
128
 
129
- #: inc/classes/admin-pages.class.php:848 inc/classes/admin-pages.class.php:852
130
  msgid "Select Image"
131
  msgstr ""
132
 
133
- #: inc/classes/admin-pages.class.php:854
134
  msgid "Change Image"
135
  msgstr ""
136
 
137
- #: inc/classes/admin-pages.class.php:855
138
  msgid "Remove Image"
139
  msgstr ""
140
 
141
- #: inc/classes/admin-pages.class.php:856
142
  msgid "Remove selected social image"
143
  msgstr ""
144
 
145
- #: inc/classes/admin-pages.class.php:857
146
  msgctxt "Frame title"
147
  msgid "Select Social Image"
148
  msgstr ""
149
 
150
- #: inc/classes/admin-pages.class.php:858
151
  msgid "Use this image"
152
  msgstr ""
153
 
154
- #: inc/classes/core.class.php:255
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  msgctxt "As in: The Plugin Home Page"
156
- msgid "Plugin Home"
157
  msgstr ""
158
 
159
- #: inc/classes/core.class.php:264
160
  msgid "https://wordpress.org/plugins/the-seo-framework-extension-manager/"
161
  msgstr ""
162
 
163
- #: inc/classes/core.class.php:264
164
  msgctxt "Plugin extensions"
165
  msgid "Extensions"
166
  msgstr ""
167
 
168
- #: inc/classes/core.class.php:316
169
  msgid "Dismiss"
170
  msgstr ""
171
 
172
- #: inc/classes/core.class.php:459
173
  msgctxt "e.g. en for English, nl for Dutch, fi for Finish, de for German"
174
  msgid "en"
175
  msgstr ""
@@ -221,249 +277,251 @@ msgstr ""
221
  msgid "No Archive"
222
  msgstr ""
223
 
224
- #: inc/classes/doing-it-right.class.php:366
225
  msgid "Refresh to see the SEO Bar status."
226
  msgstr ""
227
 
228
- #: inc/classes/doing-it-right.class.php:450
229
  msgid "Post"
230
  msgstr ""
231
 
232
- #: inc/classes/doing-it-right.class.php:454 inc/classes/inpost.class.php:383
233
- #: inc/classes/term-data.class.php:337
234
- #: inc/views/metaboxes/schema-metabox.php:204
 
 
235
  msgid "Page"
236
  msgstr ""
237
 
238
- #: inc/classes/doing-it-right.class.php:498
239
  msgid "Failed to fetch post ID."
240
  msgstr ""
241
 
242
  #. translators: %s = But or And
243
 
244
- #: inc/classes/doing-it-right.class.php:886
245
  msgid "%s the Title contains the Blogname multiple times."
246
  msgstr ""
247
 
248
  #. translators: 1: Word, 2: Occurrences
249
 
250
- #: inc/classes/doing-it-right.class.php:1057
251
  msgid "%1$s is used %2$d times."
252
  msgstr ""
253
 
254
  #. Translators: %s = Post / Page / Category, etc.
255
 
256
- #: inc/classes/doing-it-right.class.php:1102
257
  msgid "%s is being indexed."
258
  msgstr ""
259
 
260
- #: inc/classes/doing-it-right.class.php:1111
261
  msgid "But you've discouraged indexing for the whole site."
262
  msgstr ""
263
 
264
  #. translators: 1: But or And, 2: Current taxonomy term plural label
265
 
266
- #: inc/classes/doing-it-right.class.php:1135
267
  msgid "%1$s indexing for %2$s have been discouraged."
268
  msgstr ""
269
 
270
  #. translators: 1 = But or And, 1 = Post/Page
271
 
272
- #: inc/classes/doing-it-right.class.php:1148
273
  msgid "%1$s the %2$s is protected from public visibility. This means indexing is discouraged."
274
  msgstr ""
275
 
276
  #. translators: %s = But or And
277
 
278
- #: inc/classes/doing-it-right.class.php:1157
279
  msgid "%s the blog isn't set to public. This means WordPress discourages indexing."
280
  msgstr ""
281
 
282
  #. translators: %s = But or And
283
 
284
- #: inc/classes/doing-it-right.class.php:1171
285
  msgid "%s there are no posts in this term; therefore, indexing has been discouraged."
286
  msgstr ""
287
 
288
- #: inc/classes/doing-it-right.class.php:1255
289
  msgid "%s links aren't being followed."
290
  msgstr ""
291
 
292
- #: inc/classes/doing-it-right.class.php:1261
293
  msgid "%s links are being followed."
294
  msgstr ""
295
 
296
  #. translators: %s = But or And
297
 
298
- #: inc/classes/doing-it-right.class.php:1273
299
  msgid "%s you've discouraged the following of links for the whole site."
300
  msgstr ""
301
 
302
  #. translators: 1: But or And, 2: Current taxonomy term plural label
303
 
304
- #: inc/classes/doing-it-right.class.php:1299
305
  msgid "%1$s following for %2$s have been discouraged."
306
  msgstr ""
307
 
308
  #. translators: %s = But or And
309
 
310
- #: inc/classes/doing-it-right.class.php:1311
311
  msgid "%s the blog isn't set to public. This means WordPress allows the links to be followed regardless."
312
  msgstr ""
313
 
314
- #: inc/classes/doing-it-right.class.php:1363
315
  msgid "Search Engines aren't allowed to archive this %s."
316
  msgstr ""
317
 
318
- #: inc/classes/doing-it-right.class.php:1368
319
  msgid "Search Engines are allowed to archive this %s."
320
  msgstr ""
321
 
322
- #: inc/classes/doing-it-right.class.php:1380
323
  msgid "But you've discouraged archiving for the whole site."
324
  msgstr ""
325
 
326
  #. translators: 1: But or And, 2: Current taxonomy term plural label
327
 
328
- #: inc/classes/doing-it-right.class.php:1406
329
  msgid "%1$s archiving for %2$s have been discouraged."
330
  msgstr ""
331
 
332
  #. translators: %s = But or And
333
 
334
- #: inc/classes/doing-it-right.class.php:1419
335
  msgid "%s the blog isn't set to public. This means WordPress allows the blog to be archived regardless."
336
  msgstr ""
337
 
338
- #: inc/classes/doing-it-right.class.php:1465
339
  msgid "%s isn't being redirected."
340
  msgstr ""
341
 
342
- #: inc/classes/doing-it-right.class.php:1507
343
- #: inc/classes/doing-it-right.class.php:1536
344
  msgid "%s is being redirected. This means no SEO values have to be set."
345
  msgstr ""
346
 
347
- #: inc/classes/doing-it-right.class.php:1510
348
- #: inc/classes/doing-it-right.class.php:1552
349
  msgid "%s is not being indexed. This means no SEO values have to be set."
350
  msgstr ""
351
 
352
- #: inc/classes/doing-it-right.class.php:1666
353
  msgid "Title:"
354
  msgstr ""
355
 
356
- #: inc/classes/doing-it-right.class.php:1667
357
  msgid "Description:"
358
  msgstr ""
359
 
360
- #: inc/classes/doing-it-right.class.php:1668
361
  msgid "Index:"
362
  msgstr ""
363
 
364
- #: inc/classes/doing-it-right.class.php:1669
365
  msgid "Follow:"
366
  msgstr ""
367
 
368
- #: inc/classes/doing-it-right.class.php:1670
369
  msgid "Archive:"
370
  msgstr ""
371
 
372
- #: inc/classes/doing-it-right.class.php:1671
373
  msgid "Redirect:"
374
  msgstr ""
375
 
376
- #: inc/classes/doing-it-right.class.php:1673
377
  msgid "Generated: Automatically generated."
378
  msgstr ""
379
 
380
- #: inc/classes/doing-it-right.class.php:1675
381
  msgctxt "Generated"
382
  msgid "G"
383
  msgstr ""
384
 
385
- #: inc/classes/doing-it-right.class.php:1676
386
  msgctxt "Title"
387
  msgid "T"
388
  msgstr ""
389
 
390
- #: inc/classes/doing-it-right.class.php:1677
391
  msgctxt "Description"
392
  msgid "D"
393
  msgstr ""
394
 
395
- #: inc/classes/doing-it-right.class.php:1678
396
  msgctxt "no-Index"
397
  msgid "I"
398
  msgstr ""
399
 
400
- #: inc/classes/doing-it-right.class.php:1679
401
  msgctxt "no-Follow"
402
  msgid "F"
403
  msgstr ""
404
 
405
- #: inc/classes/doing-it-right.class.php:1680
406
  msgctxt "no-Archive"
407
  msgid "A"
408
  msgstr ""
409
 
410
- #: inc/classes/doing-it-right.class.php:1681
411
  msgctxt "Redirect"
412
  msgid "R"
413
  msgstr ""
414
 
415
- #: inc/classes/doing-it-right.class.php:1683
416
  msgctxt "But there are..."
417
  msgid "But"
418
  msgstr ""
419
 
420
- #: inc/classes/doing-it-right.class.php:1684
421
  msgctxt "And there are..."
422
  msgid "And"
423
  msgstr ""
424
 
425
- #: inc/classes/doing-it-right.class.php:1686
426
  msgid "Length is far too short."
427
  msgstr ""
428
 
429
- #: inc/classes/doing-it-right.class.php:1687
430
  msgid "Length is too short."
431
  msgstr ""
432
 
433
- #: inc/classes/doing-it-right.class.php:1688
434
  msgid "Length is too long."
435
  msgstr ""
436
 
437
- #: inc/classes/doing-it-right.class.php:1689
438
  msgid "Length is far too long."
439
  msgstr ""
440
 
441
- #: inc/classes/doing-it-right.class.php:1690
442
  msgid "Length is good."
443
  msgstr ""
444
 
445
- #: inc/classes/feed.class.php:182
446
  msgctxt "The content source"
447
  msgid "Source"
448
  msgstr ""
449
 
450
  #. translators: 1: Title, 2: Separator, 3: Excerpt
451
 
452
- #: inc/classes/generate-description.class.php:441
453
  msgctxt "1: Title, 2: Separator, 3: Excerpt"
454
  msgid "%1$s %2$s %3$s"
455
  msgstr ""
456
 
457
  #. translators: 1: Title, 2: on, 3: Blogname
458
 
459
- #: inc/classes/generate-description.class.php:648
460
  msgctxt "1: Title, 2: on, 3: Blogname"
461
  msgid "%1$s %2$s %3$s"
462
  msgstr ""
463
 
464
  #. translators: Front-end output.
465
 
466
- #: inc/classes/generate-description.class.php:685
467
  #: inc/views/metaboxes/description-metabox.php:18
468
  msgctxt "Placement. e.g. Post Title \"on\" Blog Name"
469
  msgid "on"
@@ -471,200 +529,227 @@ msgstr ""
471
 
472
  #. translators: Front-end output.
473
 
474
- #: inc/classes/generate-description.class.php:773
475
  msgid "Latest posts:"
476
  msgstr ""
477
 
478
- #: inc/classes/generate-ldjson.class.php:613
479
- #: inc/classes/generate-ldjson.class.php:616
480
  msgid "Uncategorized"
481
  msgstr ""
482
 
483
  #. translators: Front-end output. 1: Taxonomy singular name, 2: Current
484
  #. taxonomy term
485
 
486
- #: inc/classes/generate-title.class.php:828
487
- #: inc/classes/generate-title.class.php:888
488
  msgid "%1$s: %2$s"
489
  msgstr ""
490
 
491
  #. translators: Front-end output.
492
 
493
- #: inc/classes/generate-title.class.php:832
494
  msgid "Author: %s"
495
  msgstr ""
496
 
497
  #. translators: Front-end output.
498
 
499
- #: inc/classes/generate-title.class.php:836
500
  msgctxt "yearly archives date format"
501
  msgid "Y"
502
  msgstr ""
503
 
504
  #. translators: Front-end output.
505
 
506
- #: inc/classes/generate-title.class.php:838
507
  msgid "Year: %s"
508
  msgstr ""
509
 
510
  #. translators: Front-end output.
511
 
512
- #: inc/classes/generate-title.class.php:841
513
  msgctxt "monthly archives date format"
514
  msgid "F Y"
515
  msgstr ""
516
 
517
  #. translators: Front-end output.
518
 
519
- #: inc/classes/generate-title.class.php:843
520
  msgid "Month: %s"
521
  msgstr ""
522
 
523
  #. translators: Front-end output.
524
 
525
- #: inc/classes/generate-title.class.php:846
526
  msgctxt "daily archives date format"
527
  msgid "F j, Y"
528
  msgstr ""
529
 
530
  #. translators: Front-end output.
531
 
532
- #: inc/classes/generate-title.class.php:848
533
  msgid "Day: %s"
534
  msgstr ""
535
 
536
  #. translators: Front-end output.
537
 
538
- #: inc/classes/generate-title.class.php:853
539
  msgctxt "post format archive title"
540
  msgid "Asides"
541
  msgstr ""
542
 
543
  #. translators: Front-end output.
544
 
545
- #: inc/classes/generate-title.class.php:856
546
  msgctxt "post format archive title"
547
  msgid "Galleries"
548
  msgstr ""
549
 
550
  #. translators: Front-end output.
551
 
552
- #: inc/classes/generate-title.class.php:859
553
  msgctxt "post format archive title"
554
  msgid "Images"
555
  msgstr ""
556
 
557
  #. translators: Front-end output.
558
 
559
- #: inc/classes/generate-title.class.php:862
560
  msgctxt "post format archive title"
561
  msgid "Videos"
562
  msgstr ""
563
 
564
  #. translators: Front-end output.
565
 
566
- #: inc/classes/generate-title.class.php:865
567
  msgctxt "post format archive title"
568
  msgid "Quotes"
569
  msgstr ""
570
 
571
  #. translators: Front-end output.
572
 
573
- #: inc/classes/generate-title.class.php:868
574
  msgctxt "post format archive title"
575
  msgid "Links"
576
  msgstr ""
577
 
578
  #. translators: Front-end output.
579
 
580
- #: inc/classes/generate-title.class.php:871
581
  msgctxt "post format archive title"
582
  msgid "Statuses"
583
  msgstr ""
584
 
585
  #. translators: Front-end output.
586
 
587
- #: inc/classes/generate-title.class.php:874
588
  msgctxt "post format archive title"
589
  msgid "Audio"
590
  msgstr ""
591
 
592
  #. translators: Front-end output.
593
 
594
- #: inc/classes/generate-title.class.php:877
595
  msgctxt "post format archive title"
596
  msgid "Chats"
597
  msgstr ""
598
 
599
  #. translators: Front-end output.
600
 
601
- #: inc/classes/generate-title.class.php:882
602
  msgid "Archives: %s"
603
  msgstr ""
604
 
605
  #. translators: Front-end output.
606
 
607
- #: inc/classes/generate-title.class.php:892
608
  msgid "Archives"
609
  msgstr ""
610
 
611
  #. translators: Front-end output.
612
 
613
- #: inc/classes/generate-title.class.php:1006
614
  msgid "Untitled"
615
  msgstr ""
616
 
617
  #. translators: Front-end output.
618
 
619
- #: inc/classes/generate-title.class.php:1041
620
  msgid "Search results for:"
621
  msgstr ""
622
 
623
  #. translators: Front-end output.
624
 
625
- #: inc/classes/generate-title.class.php:1217
626
  msgid "Protected: %s"
627
  msgstr ""
628
 
629
  #. translators: Front-end output.
630
 
631
- #: inc/classes/generate-title.class.php:1221
632
  msgid "Private: %s"
633
  msgstr ""
634
 
635
  #. translators: %d = page number. Front-end output.
636
 
637
- #: inc/classes/generate-title.class.php:1269
638
  msgid "Page %d"
639
  msgstr ""
640
 
641
- #. translators: %s = Post type name
 
 
 
 
 
 
 
 
 
642
 
643
- #: inc/classes/inpost.class.php:307 inc/views/inpost/seo-settings-tt.php:70
644
  msgid "%s SEO Settings"
645
  msgstr ""
646
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
647
  #. translators: %s = 'The SEO Framework'
648
 
649
- #: inc/classes/render.class.php:1118
650
  msgid "Start %s"
651
  msgstr ""
652
 
653
  #. translators: %s = 'The SEO Framework'
654
 
655
- #: inc/classes/render.class.php:1120
656
  msgid "End %s"
657
  msgstr ""
658
 
659
- #: inc/classes/render.class.php:1121
660
  msgid "by Sybre Waaijer"
661
  msgstr ""
662
 
663
- #: inc/classes/site-options.class.php:440
664
  msgid "here"
665
  msgstr ""
666
 
667
- #: inc/classes/site-options.class.php:441
668
  msgctxt "%s = here"
669
  msgid "View the new options %s."
670
  msgstr ""
@@ -677,25 +762,27 @@ msgstr ""
677
  msgid "Sitemap is served from cache"
678
  msgstr ""
679
 
680
- #: inc/classes/sitemaps.class.php:607
681
  msgid "Sitemap is generated on"
682
  msgstr ""
683
 
684
- #: inc/classes/term-data.class.php:339
685
- #: inc/views/metaboxes/social-metabox.php:289
686
  msgid "Pages"
687
  msgstr ""
688
 
689
- #: inc/functions/upgrade.php:165
690
  msgid "Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable."
691
  msgstr ""
692
 
 
 
 
 
693
  #: inc/views/inpost/seo-settings-singular.php:38
694
  #: inc/views/metaboxes/description-metabox.php:67
695
- #: inc/views/metaboxes/homepage-metabox.php:32
696
  #: inc/views/metaboxes/robots-metabox.php:57
697
- #: inc/views/metaboxes/schema-metabox.php:37
698
- #: inc/views/metaboxes/sitemaps-metabox.php:26
699
  #: inc/views/metaboxes/social-metabox.php:25
700
  #: inc/views/metaboxes/title-metabox.php:61
701
  msgid "General"
@@ -706,158 +793,136 @@ msgid "Visibility"
706
  msgstr ""
707
 
708
  #: inc/views/inpost/seo-settings-singular.php:50
709
- #: inc/views/metaboxes/homepage-metabox.php:47
710
  msgid "Social"
711
  msgstr ""
712
 
713
  #: inc/views/inpost/seo-settings-singular.php:87
714
- #: inc/views/inpost/seo-settings-tt.php:76
715
- #: inc/views/inpost/seo-settings-tt.php:149
716
  msgid "Doing it Right"
717
  msgstr ""
718
 
719
  #. translators: %s = Post type name
 
720
 
721
  #: inc/views/inpost/seo-settings-singular.php:108
722
- #: inc/views/metaboxes/homepage-metabox.php:173
723
- msgid "Custom %s Title"
724
- msgstr ""
725
-
726
- #: inc/views/inpost/seo-settings-singular.php:114
727
- #: inc/views/inpost/seo-settings-tt.php:87
728
  #: inc/views/metaboxes/homepage-metabox.php:174
729
- msgid "Recommended Length: 50 to 55 characters"
730
- msgstr ""
731
-
732
- #. translators: %s = number
733
-
734
- #: inc/views/inpost/seo-settings-singular.php:124
735
- #: inc/views/inpost/seo-settings-singular.php:157
736
- #: inc/views/inpost/seo-settings-tt.php:96
737
- #: inc/views/inpost/seo-settings-tt.php:112
738
- #: inc/views/metaboxes/homepage-metabox.php:176
739
- #: inc/views/metaboxes/homepage-metabox.php:228
740
- msgid "Characters Used: %s"
741
  msgstr ""
742
 
743
  #. translators: %s = Post type name
744
 
745
- #: inc/views/inpost/seo-settings-singular.php:148
746
- #: inc/views/metaboxes/homepage-metabox.php:225
747
  msgid "Custom %s Description"
748
  msgstr ""
749
 
750
- #: inc/views/inpost/seo-settings-singular.php:151
751
- #: inc/views/inpost/seo-settings-tt.php:106
752
- #: inc/views/metaboxes/homepage-metabox.php:226
753
- msgid "Recommended Length: 145 to 155 characters"
754
- msgstr ""
755
-
756
- #: inc/views/inpost/seo-settings-singular.php:183
757
  msgid "Custom Canonical URL"
758
  msgstr ""
759
 
760
- #. translators: %s = Post type name
761
-
762
- #: inc/views/inpost/seo-settings-singular.php:189
763
- msgid "Preferred %s URL location"
764
  msgstr ""
765
 
766
  #. translators: 1: Option, 2: Post or Page
767
 
768
- #: inc/views/inpost/seo-settings-singular.php:218
769
- #: inc/views/inpost/seo-settings-singular.php:234
770
- #: inc/views/inpost/seo-settings-singular.php:245
771
  msgid "Apply %1$s to this %2$s"
772
  msgstr ""
773
 
774
- #: inc/views/inpost/seo-settings-singular.php:222
775
- msgid "Tell Search Engines not to show this %s in their search results"
776
  msgstr ""
777
 
778
- #: inc/views/inpost/seo-settings-singular.php:236
779
- msgid "Tell Search Engines not to follow links on this %s"
780
  msgstr ""
781
 
782
  #. translators: %s = Post type name
783
 
784
- #: inc/views/inpost/seo-settings-singular.php:251
785
- msgid "Tell Search Engines not to save a cached copy of this %s"
786
  msgstr ""
787
 
788
- #: inc/views/inpost/seo-settings-singular.php:268
789
  msgid "Archive Settings"
790
  msgstr ""
791
 
792
  #. translators: %s = Post type name
793
 
794
- #: inc/views/inpost/seo-settings-singular.php:278
795
  msgid "Exclude this %s from local search"
796
  msgstr ""
797
 
798
  #. translators: %s = Post type name
799
 
800
- #: inc/views/inpost/seo-settings-singular.php:281
801
- msgid "This excludes this %s from local on-site search results"
802
  msgstr ""
803
 
804
  #. translators: %s = Post type name
805
 
806
- #: inc/views/inpost/seo-settings-singular.php:291
807
- msgid "Exclude this %s from all archive listings"
808
  msgstr ""
809
 
810
  #. translators: %s = Post type name
811
 
812
- #: inc/views/inpost/seo-settings-singular.php:294
813
- msgid "This excludes this %s from on-site archive pages"
814
  msgstr ""
815
 
816
- #: inc/views/inpost/seo-settings-singular.php:308
817
  msgid "Custom 301 Redirect URL"
818
  msgstr ""
819
 
820
- #: inc/views/inpost/seo-settings-singular.php:313
821
- msgid "This will force visitors to go to another URL"
822
  msgstr ""
823
 
824
- #: inc/views/inpost/seo-settings-singular.php:337
825
  msgid "Custom Social Image URL"
826
  msgstr ""
827
 
828
  #. translators: %s = Post type name
829
 
830
- #: inc/views/inpost/seo-settings-singular.php:343
831
- msgid "Preferred %s Social Image URL location"
832
  msgstr ""
833
 
834
- #: inc/views/inpost/seo-settings-tt.php:86
 
 
835
  msgid "%s Title"
836
  msgstr ""
837
 
838
- #: inc/views/inpost/seo-settings-tt.php:105
 
 
839
  msgid "%s Meta Description"
840
  msgstr ""
841
 
842
- #: inc/views/inpost/seo-settings-tt.php:122
843
- #: inc/views/inpost/seo-settings-tt.php:129
844
- #: inc/views/inpost/seo-settings-tt.php:136
845
- msgid "Apply %s to this term?"
846
- msgstr ""
847
 
848
- #: inc/views/inpost/seo-settings-tt.php:123
849
- #: inc/views/metaboxes/homepage-metabox.php:352
850
- msgid "Tell Search Engines not to show this page in their search results"
 
851
  msgstr ""
852
 
853
- #: inc/views/inpost/seo-settings-tt.php:130
854
- #: inc/views/metaboxes/homepage-metabox.php:362
855
- msgid "Tell Search Engines not to follow links on this page"
856
  msgstr ""
857
 
858
- #: inc/views/inpost/seo-settings-tt.php:137
859
- #: inc/views/metaboxes/homepage-metabox.php:372
860
- msgid "Tell Search Engines not to save a cached copy of this page"
 
861
  msgstr ""
862
 
863
  #: inc/views/metaboxes/description-metabox.php:17
@@ -873,7 +938,7 @@ msgid "Automated Description Settings"
873
  msgstr ""
874
 
875
  #: inc/views/metaboxes/description-metabox.php:42
876
- #: inc/views/metaboxes/homepage-metabox.php:237
877
  msgid "The meta description can be used to determine the text used under the title on Search Engine results pages."
878
  msgstr ""
879
 
@@ -882,49 +947,49 @@ msgid "Example Automated Description Output"
882
  msgstr ""
883
 
884
  #: inc/views/metaboxes/description-metabox.php:72
885
- #: inc/views/metaboxes/homepage-metabox.php:37
886
  #: inc/views/metaboxes/title-metabox.php:66
887
  msgid "Additions"
888
  msgstr ""
889
 
890
- #: inc/views/metaboxes/description-metabox.php:100
891
  msgid "Description Excerpt Separator"
892
  msgstr ""
893
 
894
- #: inc/views/metaboxes/description-metabox.php:109
895
  msgid "If the Automated Description consists of two parts (title and excerpt), then the separator will go in-between them."
896
  msgstr ""
897
 
898
- #: inc/views/metaboxes/description-metabox.php:120
899
  msgid "Description Additions Settings"
900
  msgstr ""
901
 
902
- #: inc/views/metaboxes/description-metabox.php:122
903
  msgid "To create a more organic description, a small introduction can be added before the description."
904
  msgstr ""
905
 
906
- #: inc/views/metaboxes/description-metabox.php:123
907
  msgid "The introduction consists of the title and optionally the blogname."
908
  msgstr ""
909
 
910
- #: inc/views/metaboxes/description-metabox.php:128
911
  msgid "Add descriptive Additions to Description"
912
  msgstr ""
913
 
914
- #: inc/views/metaboxes/description-metabox.php:132
915
  msgid "Add Additions to automated description?"
916
  msgstr ""
917
 
918
- #: inc/views/metaboxes/description-metabox.php:133
919
- msgid "This creates good meta descriptions"
920
  msgstr ""
921
 
922
- #: inc/views/metaboxes/description-metabox.php:137
923
  msgid "Add Blogname to Additions"
924
  msgstr ""
925
 
926
- #: inc/views/metaboxes/description-metabox.php:141
927
- msgid "Add Blogname to automated description additions?"
928
  msgstr ""
929
 
930
  #: inc/views/metaboxes/feed-metabox.php:10
@@ -948,7 +1013,7 @@ msgid "Convert feed entries into excerpts?"
948
  msgstr ""
949
 
950
  #: inc/views/metaboxes/feed-metabox.php:20
951
- msgid "By default the excerpt will be at most 400 characters long"
952
  msgstr ""
953
 
954
  #: inc/views/metaboxes/feed-metabox.php:22
@@ -956,7 +1021,7 @@ msgid "Add link to source below the feed entry content?"
956
  msgstr ""
957
 
958
  #: inc/views/metaboxes/feed-metabox.php:23
959
- msgid "This link will not be followed by Search Engines"
960
  msgstr ""
961
 
962
  #: inc/views/metaboxes/feed-metabox.php:35
@@ -994,335 +1059,387 @@ msgstr ""
994
  msgid "Canonical"
995
  msgstr ""
996
 
997
- #: inc/views/metaboxes/general-metabox.php:51
 
 
 
 
 
998
  msgid "Administrative Layout Settings"
999
  msgstr ""
1000
 
1001
- #: inc/views/metaboxes/general-metabox.php:52
1002
  msgid "SEO hints can be visually displayed throughout the dashboard."
1003
  msgstr ""
1004
 
1005
- #: inc/views/metaboxes/general-metabox.php:57
1006
  msgid "SEO Bar Settings"
1007
  msgstr ""
1008
 
1009
- #: inc/views/metaboxes/general-metabox.php:63
1010
  msgid "Display the SEO Bar in overview tables?"
1011
  msgstr ""
1012
 
1013
- #: inc/views/metaboxes/general-metabox.php:69
1014
  msgid "Display the SEO Bar in the SEO Settings metabox?"
1015
  msgstr ""
1016
 
1017
- #: inc/views/metaboxes/general-metabox.php:80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1018
  msgid "Performance Settings"
1019
  msgstr ""
1020
 
1021
- #: inc/views/metaboxes/general-metabox.php:81
1022
  msgid "Depending on your server's configuration, adjusting these settings can affect performance."
1023
  msgstr ""
1024
 
1025
- #: inc/views/metaboxes/general-metabox.php:86
1026
- msgid "Query alteration Settings"
1027
  msgstr ""
1028
 
1029
- #: inc/views/metaboxes/general-metabox.php:89
1030
  msgid "Altering the query allows for more control of the site's hierarchy."
1031
  msgstr ""
1032
 
1033
- #: inc/views/metaboxes/general-metabox.php:91
1034
  msgid "If your website has thousands of pages, these options can greatly affect database performance."
1035
  msgstr ""
1036
 
1037
- #: inc/views/metaboxes/general-metabox.php:95
1038
  msgid "Altering the query in the database is more accurate, but can increase database query time."
1039
  msgstr ""
1040
 
1041
- #: inc/views/metaboxes/general-metabox.php:97
1042
  msgid "Altering the query on the site is much faster, but can lead to inconsistent pagination. It can also lead to 404 error messages if all queried pages have been excluded."
1043
  msgstr ""
1044
 
1045
- #: inc/views/metaboxes/general-metabox.php:103
1046
  msgctxt "Perform query alteration..."
1047
  msgid "In the database"
1048
  msgstr ""
1049
 
1050
- #: inc/views/metaboxes/general-metabox.php:104
1051
  msgctxt "Perform query alteration..."
1052
  msgid "On the site"
1053
  msgstr ""
1054
 
1055
- #: inc/views/metaboxes/general-metabox.php:132
1056
  msgid "Perform alteration:"
1057
  msgstr ""
1058
 
1059
- #: inc/views/metaboxes/general-metabox.php:159
1060
  msgid "Enable search query alteration?"
1061
  msgstr ""
1062
 
1063
- #: inc/views/metaboxes/general-metabox.php:160
1064
- msgid "This allows you to exclude pages from on-site search results"
1065
  msgstr ""
1066
 
1067
- #: inc/views/metaboxes/general-metabox.php:173
1068
  msgid "Enable archive query alteration?"
1069
  msgstr ""
1070
 
1071
- #: inc/views/metaboxes/general-metabox.php:174
1072
- msgid "This allows you to exclude pages from on-site archive listings"
1073
  msgstr ""
1074
 
1075
- #: inc/views/metaboxes/general-metabox.php:185
1076
  msgid "Transient Cache Settings"
1077
  msgstr ""
1078
 
1079
- #: inc/views/metaboxes/general-metabox.php:187
1080
  msgid "To improve performance, generated SEO output can be stored in the database as transient cache."
1081
  msgstr ""
1082
 
1083
- #: inc/views/metaboxes/general-metabox.php:188
1084
  msgid "If your website has thousands of pages, or if other forms of caching are used, you might wish to adjust these options."
1085
  msgstr ""
1086
 
1087
- #: inc/views/metaboxes/general-metabox.php:194
1088
  msgid "Enable automated description output cache?"
1089
  msgstr ""
1090
 
1091
- #: inc/views/metaboxes/general-metabox.php:195
1092
- msgid "Description generation can use a lot of server resources when it reads the page content"
1093
  msgstr ""
1094
 
1095
- #: inc/views/metaboxes/general-metabox.php:201
1096
  msgid "Enable automated Schema output cache?"
1097
  msgstr ""
1098
 
1099
- #: inc/views/metaboxes/general-metabox.php:202
1100
- msgid "Schema.org output generally makes multiple calls to the database"
1101
  msgstr ""
1102
 
1103
- #: inc/views/metaboxes/general-metabox.php:208
1104
  msgid "Enable sitemap generation cache?"
1105
  msgstr ""
1106
 
1107
- #: inc/views/metaboxes/general-metabox.php:209
1108
- msgid "Generating the sitemap can use a lot of server resources"
1109
  msgstr ""
1110
 
1111
- #: inc/views/metaboxes/general-metabox.php:221
1112
  msgid "Object Cache Settings"
1113
  msgstr ""
1114
 
1115
- #: inc/views/metaboxes/general-metabox.php:227
1116
  msgid "Enable object cache?"
1117
  msgstr ""
1118
 
1119
- #: inc/views/metaboxes/general-metabox.php:228
1120
- msgid "Object cache generally works faster than transient cache"
1121
  msgstr ""
1122
 
1123
- #: inc/views/metaboxes/general-metabox.php:229
1124
  msgid "An object cache handler has been detected. If you enable this option, you might wish to disable description and Schema transient caching."
1125
  msgstr ""
1126
 
1127
- #: inc/views/metaboxes/general-metabox.php:239
1128
  msgid "Canonical URL Settings"
1129
  msgstr ""
1130
 
1131
- #: inc/views/metaboxes/general-metabox.php:240
1132
- msgid "The canonical URL meta tag urges Search Engines to go to the outputted URL."
1133
  msgstr ""
1134
 
1135
- #: inc/views/metaboxes/general-metabox.php:241
1136
  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."
1137
  msgstr ""
1138
 
1139
- #: inc/views/metaboxes/general-metabox.php:242
1140
  msgid "Only adjust these options if you are aware of their SEO effects."
1141
  msgstr ""
1142
 
1143
- #: inc/views/metaboxes/general-metabox.php:247
1144
  msgid "Scheme Settings"
1145
  msgstr ""
1146
 
1147
- #: inc/views/metaboxes/general-metabox.php:249
1148
  msgid "If your website is accessible on both HTTP as HTTPS, set this to HTTPS in order to prevent duplicate content."
1149
  msgstr ""
1150
 
1151
- #: inc/views/metaboxes/general-metabox.php:250
1152
  msgid "Otherwise, automatic detection is recommended."
1153
  msgstr ""
1154
 
1155
- #: inc/views/metaboxes/general-metabox.php:252
1156
  msgctxt "= Detect Automatically, HTTPS, HTTP"
1157
  msgid "Preferred canonical URL scheme:"
1158
  msgstr ""
1159
 
1160
- #: inc/views/metaboxes/general-metabox.php:258
1161
  msgid "Detect automatically"
1162
  msgstr ""
1163
 
1164
- #: inc/views/metaboxes/general-metabox.php:271
1165
  msgid "Link Relationship Settings"
1166
  msgstr ""
1167
 
1168
- #: inc/views/metaboxes/general-metabox.php:272
1169
- 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."
1170
  msgstr ""
1171
 
1172
- #: inc/views/metaboxes/general-metabox.php:273
1173
  msgid "It's recommended to turn this option on for better SEO consistency and to prevent duplicate content errors."
1174
  msgstr ""
1175
 
1176
  #. translators: %s = <code>rel</code>
1177
 
1178
- #: inc/views/metaboxes/general-metabox.php:276
1179
  msgid "Add %s link tags to Posts and Pages?"
1180
  msgstr ""
1181
 
1182
  #. translators: %s = <code>rel</code>
1183
 
1184
- #: inc/views/metaboxes/general-metabox.php:280
1185
  msgid "Add %s link tags to Archives?"
1186
  msgstr ""
1187
 
1188
  #. translators: %s = <code>rel</code>
1189
 
1190
- #: inc/views/metaboxes/general-metabox.php:284
1191
  msgid "Add %s link tags to the Home Page?"
1192
  msgstr ""
1193
 
1194
- #: inc/views/metaboxes/homepage-metabox.php:11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1195
  msgid "These settings will take precedence over the settings set within the Home Page edit screen, if any."
1196
  msgstr ""
1197
 
1198
- #: inc/views/metaboxes/homepage-metabox.php:42
1199
  msgid "Robots"
1200
  msgstr ""
1201
 
1202
- #: inc/views/metaboxes/homepage-metabox.php:71
1203
  msgid "Title"
1204
  msgstr ""
1205
 
1206
- #: inc/views/metaboxes/homepage-metabox.php:72
1207
  msgid "Description"
1208
  msgstr ""
1209
 
1210
- #: inc/views/metaboxes/homepage-metabox.php:73
1211
- #: inc/views/metaboxes/homepage-metabox.php:274
1212
- #: inc/views/metaboxes/homepage-metabox.php:319
1213
- #: inc/views/metaboxes/social-metabox.php:291
1214
- #: inc/views/metaboxes/social-metabox.php:322
1215
  msgid "Home Page"
1216
  msgstr ""
1217
 
1218
- #: inc/views/metaboxes/homepage-metabox.php:143
1219
- #: inc/views/metaboxes/homepage-metabox.php:196
1220
  msgid "Page SEO Settings"
1221
  msgstr ""
1222
 
1223
  #. translators: 1: Option, 2: Page SEO Settings, 3: Home Page
1224
 
1225
- #: inc/views/metaboxes/homepage-metabox.php:145
1226
- #: inc/views/metaboxes/homepage-metabox.php:194
1227
  msgid "Note: The %1$s is fetched from the %2$s on the %3$s."
1228
  msgstr ""
1229
 
1230
- #: inc/views/metaboxes/homepage-metabox.php:162
1231
  msgid "Custom %s Title Tagline"
1232
  msgstr ""
1233
 
1234
  #. translators: %s = Home page URL markdown
1235
 
1236
- #: inc/views/metaboxes/homepage-metabox.php:212
1237
- #: inc/views/metaboxes/homepage-metabox.php:253
1238
  msgid "A plugin has been detected that suggests to maintain this option on the [Home Page](%s)."
1239
  msgstr ""
1240
 
1241
- #: inc/views/metaboxes/homepage-metabox.php:278
1242
- #: inc/views/metaboxes/title-metabox.php:132
1243
- msgid "Document Title Additions Location"
1244
  msgstr ""
1245
 
1246
- #: inc/views/metaboxes/homepage-metabox.php:279
1247
- #: inc/views/metaboxes/title-metabox.php:134
1248
- msgid "Determines which side the added title text will go on."
1249
  msgstr ""
1250
 
1251
- #: inc/views/metaboxes/homepage-metabox.php:285
1252
- #: inc/views/metaboxes/title-metabox.php:140
1253
  msgid "Left:"
1254
  msgstr ""
1255
 
1256
- #: inc/views/metaboxes/homepage-metabox.php:295
1257
- #: inc/views/metaboxes/title-metabox.php:147
1258
  msgid "Right:"
1259
  msgstr ""
1260
 
1261
- #: inc/views/metaboxes/homepage-metabox.php:306
1262
  msgid "%s Tagline"
1263
  msgstr ""
1264
 
1265
- #: inc/views/metaboxes/homepage-metabox.php:310
1266
  msgid "Add site description (tagline) to the Title on the %s?"
1267
  msgstr ""
1268
 
1269
- #: inc/views/metaboxes/homepage-metabox.php:336
1270
  msgid "View Home Page Settings"
1271
  msgstr ""
1272
 
1273
- #: inc/views/metaboxes/homepage-metabox.php:336
1274
  msgid "Checked in Page"
1275
  msgstr ""
1276
 
1277
- #: inc/views/metaboxes/homepage-metabox.php:340
1278
  msgid "Home Page Robots Meta Settings"
1279
  msgstr ""
1280
 
1281
  #. translators: 1: Option, 2: Location
1282
 
1283
- #: inc/views/metaboxes/homepage-metabox.php:349
1284
- #: inc/views/metaboxes/homepage-metabox.php:359
1285
- #: inc/views/metaboxes/homepage-metabox.php:369
1286
  msgid "Apply %1$s to the %2$s?"
1287
  msgstr ""
1288
 
1289
- #: inc/views/metaboxes/homepage-metabox.php:404
 
 
 
 
1290
  msgid "Note: If any of these options are unchecked, but are checked on the Home Page, they will be outputted regardless."
1291
  msgstr ""
1292
 
1293
- #: inc/views/metaboxes/homepage-metabox.php:410
1294
  msgid "Home Page Pagination Robots Settings"
1295
  msgstr ""
1296
 
1297
- #: inc/views/metaboxes/homepage-metabox.php:411
1298
  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."
1299
  msgstr ""
1300
 
1301
  #. translators: 1: Option, 2: Location
1302
 
1303
- #: inc/views/metaboxes/homepage-metabox.php:419
1304
  msgid "Apply %1$s to every second or later page on the %2$s?"
1305
  msgstr ""
1306
 
1307
- #: inc/views/metaboxes/homepage-metabox.php:429
1308
- #: inc/views/metaboxes/social-metabox.php:116
1309
  msgid "Social Image Settings"
1310
  msgstr ""
1311
 
1312
- #: inc/views/metaboxes/homepage-metabox.php:431
1313
  msgid "A social image can be displayed when your homepage is shared. It is a great way to grab attention."
1314
  msgstr ""
1315
 
1316
- #: inc/views/metaboxes/homepage-metabox.php:460
1317
- msgid "Custom Home Page Image URL"
1318
  msgstr ""
1319
 
1320
- #: inc/views/metaboxes/homepage-metabox.php:461
1321
- msgid "Preferred Home Page Social Image URL location"
1322
  msgstr ""
1323
 
1324
  #: inc/views/metaboxes/robots-metabox.php:13
1325
- #: inc/views/metaboxes/title-metabox.php:192
1326
  msgid "Category"
1327
  msgstr ""
1328
 
@@ -1372,7 +1489,7 @@ msgid "NoArchive"
1372
  msgstr ""
1373
 
1374
  #: inc/views/metaboxes/robots-metabox.php:37
1375
- msgid "These options prevent caching of the selected archives and pages. If you enable this, Search Engines will not create a cached copy of the selected archives or pages."
1376
  msgstr ""
1377
 
1378
  #: inc/views/metaboxes/robots-metabox.php:63
@@ -1387,440 +1504,398 @@ msgstr ""
1387
  msgid "Archiving"
1388
  msgstr ""
1389
 
1390
- #: inc/views/metaboxes/robots-metabox.php:97
1391
  msgid "Open Directory Settings"
1392
  msgstr ""
1393
 
1394
- #: inc/views/metaboxes/robots-metabox.php:98
1395
- msgid "Sometimes, Search Engines use resources from certain Directories to find titles and descriptions for your content. You generally don't want them to. Turn these options on to prevent them from doing so."
1396
  msgstr ""
1397
 
1398
- #: inc/views/metaboxes/robots-metabox.php:99
1399
- msgid "The Open Directory Project and the Yahoo! Directory may contain outdated SEO values. Therefore, it's best to leave these options checked."
1400
  msgstr ""
1401
 
1402
- #: inc/views/metaboxes/robots-metabox.php:105
1403
- #: inc/views/metaboxes/robots-metabox.php:111
1404
  msgid "Apply %s to the entire site?"
1405
  msgstr ""
1406
 
1407
- #: inc/views/metaboxes/robots-metabox.php:120
1408
  msgid "Paginated Archive Settings"
1409
  msgstr ""
1410
 
1411
- #: inc/views/metaboxes/robots-metabox.php:121
1412
- msgid "Indexing the second or later page of any archive might cause duplication errors. Search Engines look down upon them; therefore, it's recommended to disable indexing of those pages."
1413
  msgstr ""
1414
 
1415
- #: inc/views/metaboxes/robots-metabox.php:127
1416
  msgid "Apply %s to every second or later archive page?"
1417
  msgstr ""
1418
 
1419
- #: inc/views/metaboxes/robots-metabox.php:140
1420
  msgid "%s Robots Settings"
1421
  msgstr ""
1422
 
1423
  #. translators: 1: Option, 2: Post Type
1424
 
1425
- #: inc/views/metaboxes/robots-metabox.php:149
1426
  msgid "Apply %1$s to %2$s?"
1427
  msgstr ""
1428
 
1429
  #. translators: 1: Option, 2: Post Type
1430
 
1431
- #: inc/views/metaboxes/robots-metabox.php:153
1432
  msgid "Apply %1$s to %2$s Archives?"
1433
  msgstr ""
1434
 
1435
- #: inc/views/metaboxes/schema-metabox.php:12
1436
  msgid "Schema.org Output Settings"
1437
  msgstr ""
1438
 
1439
- #: inc/views/metaboxes/schema-metabox.php:16
1440
  msgid "Another Schema.org plugin has been detected."
1441
  msgstr ""
1442
 
1443
- #: inc/views/metaboxes/schema-metabox.php:18
1444
  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."
1445
  msgstr ""
1446
 
1447
- #: inc/views/metaboxes/schema-metabox.php:19
1448
- 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."
1449
  msgstr ""
1450
 
1451
- #: inc/views/metaboxes/schema-metabox.php:20
1452
  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."
1453
  msgstr ""
1454
 
1455
- #: inc/views/metaboxes/schema-metabox.php:42
1456
  msgid "Structure"
1457
  msgstr ""
1458
 
1459
- #: inc/views/metaboxes/schema-metabox.php:47
1460
  msgid "Presence"
1461
  msgstr ""
1462
 
1463
- #: inc/views/metaboxes/schema-metabox.php:69
1464
- msgid "About this website"
1465
- msgstr ""
1466
-
1467
- #: inc/views/metaboxes/schema-metabox.php:72
1468
- msgctxt "...Organization or Person."
1469
- msgid "This website represents:"
1470
- msgstr ""
1471
-
1472
- #: inc/views/metaboxes/schema-metabox.php:78
1473
- msgid "An Organization"
1474
- msgstr ""
1475
-
1476
- #: inc/views/metaboxes/schema-metabox.php:79
1477
- msgid "A Person"
1478
- msgstr ""
1479
-
1480
- #: inc/views/metaboxes/schema-metabox.php:91
1481
- msgid "The organization or personal name"
1482
- msgstr ""
1483
-
1484
- #: inc/views/metaboxes/schema-metabox.php:102
1485
  msgid "Site Structure Options"
1486
  msgstr ""
1487
 
1488
- #: inc/views/metaboxes/schema-metabox.php:103
1489
- msgid "The site structure Schema.org output allows Search Engines to gain knowledge on how your website is built."
1490
  msgstr ""
1491
 
1492
- #: inc/views/metaboxes/schema-metabox.php:104
1493
- msgid "For example, Search Engines display your pages' URLs when listed in the Search Results. These options allow you to enhance those URLs output."
1494
  msgstr ""
1495
 
1496
- #: inc/views/metaboxes/schema-metabox.php:109
1497
  msgid "Breadcrumbs"
1498
  msgstr ""
1499
 
1500
- #: inc/views/metaboxes/schema-metabox.php:110
1501
- 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."
1502
  msgstr ""
1503
 
1504
- #: inc/views/metaboxes/schema-metabox.php:112
1505
- msgid "About Breadcrumbs"
 
 
 
1506
  msgstr ""
1507
 
1508
- #: inc/views/metaboxes/schema-metabox.php:115
1509
  msgid "Enable Breadcrumbs?"
1510
  msgstr ""
1511
 
1512
- #: inc/views/metaboxes/schema-metabox.php:116
1513
- msgid "Multiple trails can be outputted. The longest trail is prioritized."
 
1514
  msgstr ""
1515
 
1516
- #: inc/views/metaboxes/schema-metabox.php:123
1517
- msgid "Site Name"
1518
  msgstr ""
1519
 
1520
- #: inc/views/metaboxes/schema-metabox.php:125
1521
- 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."
 
1522
  msgstr ""
1523
 
1524
- #: inc/views/metaboxes/schema-metabox.php:128
1525
- msgid "Include your Site Name in Search Results"
1526
  msgstr ""
1527
 
1528
- #: inc/views/metaboxes/schema-metabox.php:134
1529
- msgid "Convert URL to Site Name?"
1530
  msgstr ""
1531
 
1532
- #: inc/views/metaboxes/schema-metabox.php:135
1533
- msgid "The Site Name is: %s"
1534
  msgstr ""
1535
 
1536
- #. translators:
1537
- #. https:developers.google.com/search/docs/data-types/sitelinks-searchbox
1538
-
1539
- #: inc/views/metaboxes/schema-metabox.php:144
1540
- #: inc/views/metaboxes/schema-metabox.php:147
1541
- msgctxt "Product name"
1542
- msgid "Sitelinks Searchbox"
1543
  msgstr ""
1544
 
1545
- #: inc/views/metaboxes/schema-metabox.php:145
1546
- msgid "When Search users search for your brand name, the following option allows them to search through this website directly from the Search Results."
 
1547
  msgstr ""
1548
 
1549
- #: inc/views/metaboxes/schema-metabox.php:150
1550
- msgctxt "Product name"
1551
- msgid "Enable Sitelinks Searchbox?"
1552
  msgstr ""
1553
 
1554
- #: inc/views/metaboxes/schema-metabox.php:158
1555
- msgid "Authorized Presence Options"
1556
  msgstr ""
1557
 
1558
- #: inc/views/metaboxes/schema-metabox.php:159
1559
- msgid "The authorized presence Schema.org output helps Search Engine users find ways to interact with this website."
1560
  msgstr ""
1561
 
1562
- #: inc/views/metaboxes/schema-metabox.php:161
1563
- msgid "About Authorized Presence"
1564
  msgstr ""
1565
 
1566
- #: inc/views/metaboxes/schema-metabox.php:165
1567
- msgid "Output Authorized Presence?"
1568
  msgstr ""
1569
 
1570
- #: inc/views/metaboxes/schema-metabox.php:173
1571
- msgid "Website logo"
1572
  msgstr ""
1573
 
1574
- #: inc/views/metaboxes/schema-metabox.php:178
1575
- msgid "About Organization Logo"
1576
  msgstr ""
1577
 
1578
- #: inc/views/metaboxes/schema-metabox.php:181
1579
- msgid "Use the Favicon from Customizer as the Organization Logo?"
1580
  msgstr ""
1581
 
1582
- #: inc/views/metaboxes/schema-metabox.php:182
1583
- 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."
1584
  msgstr ""
1585
 
1586
- #: inc/views/metaboxes/schema-metabox.php:189
1587
- msgid "Social Pages connected to this website"
1588
  msgstr ""
1589
 
1590
- #: inc/views/metaboxes/schema-metabox.php:191
1591
  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."
1592
  msgstr ""
1593
 
1594
- #: inc/views/metaboxes/schema-metabox.php:192
1595
  msgid "Add the link that leads directly to the social page of this website."
1596
  msgstr ""
1597
 
1598
- #: inc/views/metaboxes/schema-metabox.php:194
1599
  msgctxt "No spaces. E.g. https://facebook.com/RelatedProfile"
1600
  msgid "RelatedProfile"
1601
  msgstr ""
1602
 
1603
- #: inc/views/metaboxes/schema-metabox.php:195
1604
  msgctxt "Social Profile"
1605
  msgid "Profile"
1606
  msgstr ""
1607
 
1608
- #: inc/views/metaboxes/schema-metabox.php:260
1609
  msgid "Blog"
1610
  msgstr ""
1611
 
1612
- #: inc/views/metaboxes/sitemaps-metabox.php:36
1613
- msgid "Timestamps"
1614
  msgstr ""
1615
 
1616
- #: inc/views/metaboxes/sitemaps-metabox.php:41
1617
  msgctxt "Ping or notify Search Engine"
1618
  msgid "Ping"
1619
  msgstr ""
1620
 
1621
- #: inc/views/metaboxes/sitemaps-metabox.php:46
1622
  msgid "Style"
1623
  msgstr ""
1624
 
1625
- #: inc/views/metaboxes/sitemaps-metabox.php:85
1626
  msgid "Sitemap Integration Settings"
1627
  msgstr ""
1628
 
1629
- #: inc/views/metaboxes/sitemaps-metabox.php:89
1630
  msgid "Another active sitemap plugin has been detected. This means that the sitemap functionality has been replaced."
1631
  msgstr ""
1632
 
1633
- #: inc/views/metaboxes/sitemaps-metabox.php:91
1634
  msgid "A sitemap has been detected in the root folder of your website. This means that the sitemap functionality has no effect."
1635
  msgstr ""
1636
 
1637
- #: inc/views/metaboxes/sitemaps-metabox.php:93
1638
- 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."
1639
  msgstr ""
1640
 
1641
- #: inc/views/metaboxes/sitemaps-metabox.php:94
1642
  msgid "The optional metadata include the post and page modified time and a page priority indication, which is automated."
1643
  msgstr ""
1644
 
1645
- #: inc/views/metaboxes/sitemaps-metabox.php:99
1646
  msgid "Sitemap Output"
1647
  msgstr ""
1648
 
1649
- #: inc/views/metaboxes/sitemaps-metabox.php:106
1650
  msgid "Output Sitemap?"
1651
  msgstr ""
1652
 
1653
- #: inc/views/metaboxes/sitemaps-metabox.php:114
1654
  msgid "View sitemap"
1655
  msgstr ""
1656
 
1657
- #: inc/views/metaboxes/sitemaps-metabox.php:114
1658
- #: inc/views/metaboxes/sitemaps-metabox.php:132
1659
- #: inc/views/metaboxes/sitemaps-metabox.php:170
1660
  msgctxt "The sitemap can be found %s."
1661
  msgid "here"
1662
  msgstr ""
1663
 
1664
- #: inc/views/metaboxes/sitemaps-metabox.php:115
1665
  msgctxt "%s = here"
1666
  msgid "The sitemap can be found %s."
1667
  msgstr ""
1668
 
1669
- #: inc/views/metaboxes/sitemaps-metabox.php:124
1670
  msgid "Robots.txt Settings"
1671
  msgstr ""
1672
 
1673
- #: inc/views/metaboxes/sitemaps-metabox.php:128
1674
  msgid "A robots.txt file has been detected in the root folder of your website; therefore no settings are able to alter its output."
1675
  msgstr ""
1676
 
1677
- #: inc/views/metaboxes/sitemaps-metabox.php:132
1678
  msgid "Permalink Settings"
1679
  msgstr ""
1680
 
1681
- #: inc/views/metaboxes/sitemaps-metabox.php:134
1682
  msgid "You're using the plain permalink structure."
1683
  msgstr ""
1684
 
1685
- #: inc/views/metaboxes/sitemaps-metabox.php:135
1686
  msgid "This means the robots.txt file can't be outputted through the WordPress rewrite rules."
1687
  msgstr ""
1688
 
1689
- #: inc/views/metaboxes/sitemaps-metabox.php:137
1690
  msgctxt "%s = here"
1691
  msgid "Change your Permalink Settings %s (Recommended: \"Post name\")."
1692
  msgstr ""
1693
 
1694
- #: inc/views/metaboxes/sitemaps-metabox.php:141
1695
- 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."
1696
  msgstr ""
1697
 
1698
- #: inc/views/metaboxes/sitemaps-metabox.php:142
1699
- msgid "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."
1700
  msgstr ""
1701
 
1702
- #: inc/views/metaboxes/sitemaps-metabox.php:147
1703
  msgid "Add sitemap location in robots.txt"
1704
  msgstr ""
1705
 
1706
- #: inc/views/metaboxes/sitemaps-metabox.php:154
1707
  msgid "Add sitemap location in robots?"
1708
  msgstr ""
1709
 
1710
- #: inc/views/metaboxes/sitemaps-metabox.php:154
1711
- msgid "This only has effect if the sitemap is active"
1712
  msgstr ""
1713
 
1714
- #: inc/views/metaboxes/sitemaps-metabox.php:161
1715
  msgid "No robots.txt file can be generated on subdirectory installations."
1716
  msgstr ""
1717
 
1718
- #: inc/views/metaboxes/sitemaps-metabox.php:164
1719
  msgid "Another robots.txt sitemap location addition has been detected."
1720
  msgstr ""
1721
 
1722
- #: inc/views/metaboxes/sitemaps-metabox.php:170
1723
  msgid "View robots.txt"
1724
  msgstr ""
1725
 
1726
- #: inc/views/metaboxes/sitemaps-metabox.php:172
1727
  msgctxt "%s = here"
1728
  msgid "The robots.txt file can be found %s."
1729
  msgstr ""
1730
 
1731
- #: inc/views/metaboxes/sitemaps-metabox.php:192
1732
  msgid "Timestamps Settings"
1733
  msgstr ""
1734
 
1735
- #: inc/views/metaboxes/sitemaps-metabox.php:193
1736
- msgid "The modified time suggests to Search Engines where to look for content changes. It has no impact on the SEO value unless you drastically change pages or posts. It then depends on how well your content is constructed."
1737
  msgstr ""
1738
 
1739
- #: inc/views/metaboxes/sitemaps-metabox.php:194
1740
- msgid "By default, the sitemap only outputs the modified date if you've enabled them within the Social Metabox. This setting overrides those settings for the Sitemap."
1741
- msgstr ""
1742
-
1743
- #: inc/views/metaboxes/sitemaps-metabox.php:199
1744
  msgid "Output Modified Date"
1745
  msgstr ""
1746
 
1747
- #: inc/views/metaboxes/sitemaps-metabox.php:206
1748
  msgid "Add %s to the sitemap?"
1749
  msgstr ""
1750
 
1751
- #: inc/views/metaboxes/sitemaps-metabox.php:216
1752
- msgid "Timestamp Format Settings"
1753
- msgstr ""
1754
-
1755
- #: inc/views/metaboxes/sitemaps-metabox.php:217
1756
- msgid "Determines how specific the modification timestamp is."
1757
- msgstr ""
1758
-
1759
- #: inc/views/metaboxes/sitemaps-metabox.php:223
1760
- msgid "Complete date"
1761
- msgstr ""
1762
-
1763
- #: inc/views/metaboxes/sitemaps-metabox.php:229
1764
- msgid "Complete date plus hours, minutes and timezone"
1765
- msgstr ""
1766
-
1767
- #: inc/views/metaboxes/sitemaps-metabox.php:239
1768
  msgid "Ping Settings"
1769
  msgstr ""
1770
 
1771
- #: inc/views/metaboxes/sitemaps-metabox.php:240
1772
- msgid "Notifying Search Engines of a sitemap change is helpful to get your content indexed as soon as possible."
1773
  msgstr ""
1774
 
1775
- #: inc/views/metaboxes/sitemaps-metabox.php:241
1776
  msgid "By default this will happen at most once an hour."
1777
  msgstr ""
1778
 
1779
- #: inc/views/metaboxes/sitemaps-metabox.php:246
1780
  msgid "Notify Search Engines"
1781
  msgstr ""
1782
 
1783
- #: inc/views/metaboxes/sitemaps-metabox.php:258
1784
  msgid "Notify %s about sitemap changes?"
1785
  msgstr ""
1786
 
1787
- #: inc/views/metaboxes/sitemaps-metabox.php:269
1788
  msgid "Sitemap Styling Settings"
1789
  msgstr ""
1790
 
1791
- #: inc/views/metaboxes/sitemaps-metabox.php:272
1792
  msgid "You can style the sitemap to give it a more personal look. Styling the sitemap has no SEO value whatsoever."
1793
  msgstr ""
1794
 
1795
- #: inc/views/metaboxes/sitemaps-metabox.php:277
1796
  msgid "Enable styling"
1797
  msgstr ""
1798
 
1799
- #: inc/views/metaboxes/sitemaps-metabox.php:284
1800
  msgid "Style Sitemap?"
1801
  msgstr ""
1802
 
1803
- #: inc/views/metaboxes/sitemaps-metabox.php:284
1804
- msgid "This makes the sitemap more readable for humans"
1805
  msgstr ""
1806
 
1807
- #: inc/views/metaboxes/sitemaps-metabox.php:293
1808
  msgid "Style configuration"
1809
  msgstr ""
1810
 
1811
- #: inc/views/metaboxes/sitemaps-metabox.php:301
1812
  msgid "Add site logo?"
1813
  msgstr ""
1814
 
1815
- #: inc/views/metaboxes/sitemaps-metabox.php:301
1816
- msgid "The logo is set in Customizer"
1817
  msgstr ""
1818
 
1819
- #: inc/views/metaboxes/sitemaps-metabox.php:314
1820
  msgid "Sitemap header background color"
1821
  msgstr ""
1822
 
1823
- #: inc/views/metaboxes/sitemaps-metabox.php:323
1824
  msgid "Sitemap title and lines color"
1825
  msgstr ""
1826
 
@@ -1828,78 +1903,73 @@ msgstr ""
1828
  msgid "Post Dates"
1829
  msgstr ""
1830
 
1831
- #: inc/views/metaboxes/social-metabox.php:66
1832
  msgid "Social Meta Tags Settings"
1833
  msgstr ""
1834
 
1835
- #: inc/views/metaboxes/social-metabox.php:68
1836
  msgid "Output various meta tags for social site integration, among other 3rd party services."
1837
  msgstr ""
1838
 
1839
- #: inc/views/metaboxes/social-metabox.php:78
1840
  msgid "Output Open Graph meta tags?"
1841
  msgstr ""
1842
 
1843
- #: inc/views/metaboxes/social-metabox.php:79
1844
  msgid "Facebook, Twitter, Pinterest and many other social sites make use of these tags."
1845
  msgstr ""
1846
 
1847
- #: inc/views/metaboxes/social-metabox.php:86
1848
  msgid "Note: Another Open Graph plugin has been detected."
1849
  msgstr ""
1850
 
1851
- #: inc/views/metaboxes/social-metabox.php:92
1852
  msgid "Output Facebook meta tags?"
1853
  msgstr ""
1854
 
1855
- #: inc/views/metaboxes/social-metabox.php:93
1856
- #: inc/views/metaboxes/social-metabox.php:104
1857
  msgid "Output various tags targetted at %s."
1858
  msgstr ""
1859
 
1860
- #: inc/views/metaboxes/social-metabox.php:103
1861
  msgid "Output Twitter meta tags?"
1862
  msgstr ""
1863
 
1864
- #: inc/views/metaboxes/social-metabox.php:111
1865
  msgid "Note: Another Twitter Card plugin has been detected."
1866
  msgstr ""
1867
 
1868
- #: inc/views/metaboxes/social-metabox.php:118
1869
  msgid "A social image can be displayed when your website is shared. It is a great way to grab attention."
1870
  msgstr ""
1871
 
1872
- #: inc/views/metaboxes/social-metabox.php:125
1873
  msgid "Social Image Fallback URL"
1874
  msgstr ""
1875
 
1876
- #: inc/views/metaboxes/social-metabox.php:126
1877
- msgid "Preferred Social Image fallback URL location"
1878
  msgstr ""
1879
 
1880
- #: inc/views/metaboxes/social-metabox.php:150
1881
  msgid "Site Shortlink Settings"
1882
  msgstr ""
1883
 
1884
- #: inc/views/metaboxes/social-metabox.php:152
1885
  msgid "The shortlink tag can be manually used for microblogging services like Twitter, but it has no SEO value whatsoever."
1886
  msgstr ""
1887
 
1888
- #: inc/views/metaboxes/social-metabox.php:158
1889
  msgid "Output shortlink tag?"
1890
  msgstr ""
1891
 
1892
- #: inc/views/metaboxes/social-metabox.php:169
1893
- msgctxt "Example Facebook Personal URL"
1894
- msgid "https://www.facebook.com/YourPersonalProfile"
1895
- msgstr ""
1896
-
1897
- #: inc/views/metaboxes/social-metabox.php:172
1898
  msgctxt "Example Verified Facebook Business URL"
1899
  msgid "https://www.facebook.com/YourVerifiedBusinessProfile"
1900
  msgstr ""
1901
 
1902
- #: inc/views/metaboxes/social-metabox.php:177
1903
  msgid "Default Facebook Integration Settings"
1904
  msgstr ""
1905
 
@@ -1908,113 +1978,101 @@ msgid "Facebook post sharing works mostly through Open Graph. However, you can a
1908
  msgstr ""
1909
 
1910
  #: inc/views/metaboxes/social-metabox.php:179
1911
- 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."
1912
  msgstr ""
1913
 
1914
- #: inc/views/metaboxes/social-metabox.php:186
1915
- msgid "Article Author Facebook URL"
1916
  msgstr ""
1917
 
1918
- #: inc/views/metaboxes/social-metabox.php:187
1919
- msgid "Your Facebook Profile"
1920
  msgstr ""
1921
 
1922
- #: inc/views/metaboxes/social-metabox.php:196
1923
  msgid "Article Publisher Facebook URL"
1924
  msgstr ""
1925
 
1926
- #: inc/views/metaboxes/social-metabox.php:197
1927
- msgid "To use this, you need to be a verified business"
1928
  msgstr ""
1929
 
1930
- #: inc/views/metaboxes/social-metabox.php:206
1931
- msgid "Facebook App ID"
1932
  msgstr ""
1933
 
1934
- #: inc/views/metaboxes/social-metabox.php:207
1935
- msgid "Get Facebook App ID"
1936
  msgstr ""
1937
 
1938
- #: inc/views/metaboxes/social-metabox.php:219
1939
- msgctxt "Twitter @username"
1940
- msgid "@your-site-username"
1941
  msgstr ""
1942
 
1943
- #: inc/views/metaboxes/social-metabox.php:222
1944
  msgctxt "Twitter @username"
1945
- msgid "@your-personal-username"
1946
  msgstr ""
1947
 
1948
- #: inc/views/metaboxes/social-metabox.php:226
1949
  msgid "Default Twitter Integration Settings"
1950
  msgstr ""
1951
 
1952
- #: inc/views/metaboxes/social-metabox.php:227
1953
  msgid "Twitter post sharing works mostly through Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options."
1954
  msgstr ""
1955
 
1956
- #: inc/views/metaboxes/social-metabox.php:233
1957
  msgid "Twitter Card Type"
1958
  msgstr ""
1959
 
1960
  #. translators: %s = "summary" Twitter card type
1961
 
1962
- #: inc/views/metaboxes/social-metabox.php:238
1963
  msgid "What kind of Twitter card would you like to use? It will default to %s if no image is found."
1964
  msgstr ""
1965
 
1966
- #: inc/views/metaboxes/social-metabox.php:252
1967
  msgid "Example"
1968
  msgstr ""
1969
 
1970
- #: inc/views/metaboxes/social-metabox.php:263
1971
- msgid "When the following options are filled in, Twitter might link your Twitter Site or Personal Profile when your post or page is shared."
1972
  msgstr ""
1973
 
1974
- #: inc/views/metaboxes/social-metabox.php:267
1975
- msgid "Your Website's Twitter Profile"
1976
  msgstr ""
1977
 
1978
- #: inc/views/metaboxes/social-metabox.php:268
1979
- #: inc/views/metaboxes/social-metabox.php:278
1980
- msgid "Find your @username"
1981
  msgstr ""
1982
 
1983
- #: inc/views/metaboxes/social-metabox.php:277
1984
- msgid "Your Personal Twitter Profile"
1985
  msgstr ""
1986
 
1987
- #: inc/views/metaboxes/social-metabox.php:290
1988
  msgid "Posts"
1989
  msgstr ""
1990
 
1991
- #: inc/views/metaboxes/social-metabox.php:293
1992
  msgid "Post Date Settings"
1993
  msgstr ""
1994
 
1995
- #: inc/views/metaboxes/social-metabox.php:294
1996
- 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."
1997
- msgstr ""
1998
-
1999
- #: inc/views/metaboxes/social-metabox.php:295
2000
- msgid "It's recommended on posts, but it's not recommended on pages unless you modify or create new pages frequently."
2001
  msgstr ""
2002
 
2003
  #. translators: 1: Option, 2: Post Type
2004
 
2005
- #: inc/views/metaboxes/social-metabox.php:298
2006
- #: inc/views/metaboxes/social-metabox.php:302
2007
- #: inc/views/metaboxes/social-metabox.php:309
2008
- #: inc/views/metaboxes/social-metabox.php:313
2009
- #: inc/views/metaboxes/social-metabox.php:327
2010
- #: inc/views/metaboxes/social-metabox.php:331
2011
  msgid "Add %1$s to %2$s?"
2012
  msgstr ""
2013
 
2014
- #: inc/views/metaboxes/social-metabox.php:324
2015
- 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."
2016
- msgstr ""
2017
-
2018
  #: inc/views/metaboxes/title-metabox.php:17
2019
  msgid "Example Post Title"
2020
  msgstr ""
@@ -2039,60 +2097,60 @@ msgstr ""
2039
  msgid "Recommended"
2040
  msgstr ""
2041
 
2042
- #: inc/views/metaboxes/title-metabox.php:109
2043
- msgid "Document Title Separator"
2044
  msgstr ""
2045
 
2046
- #: inc/views/metaboxes/title-metabox.php:116
2047
  msgid "If the title consists of two parts (original title and optional addition), then the separator will go in-between them."
2048
  msgstr ""
2049
 
2050
- #: inc/views/metaboxes/title-metabox.php:128
2051
  msgid "The Home Page has a specific option."
2052
  msgstr ""
2053
 
2054
- #: inc/views/metaboxes/title-metabox.php:161
2055
  msgid "Remove Blogname from Title"
2056
  msgstr ""
2057
 
2058
- #: inc/views/metaboxes/title-metabox.php:165
2059
- msgid "This might decouple your posts and pages from the rest of the website"
2060
  msgstr ""
2061
 
2062
- #: inc/views/metaboxes/title-metabox.php:173
2063
  msgid "Remove Blogname from title?"
2064
  msgstr ""
2065
 
2066
- #: inc/views/metaboxes/title-metabox.php:182
2067
  msgid "Only use this option if you are aware of its SEO effects."
2068
  msgstr ""
2069
 
2070
- #: inc/views/metaboxes/title-metabox.php:208
2071
  msgid "Example Category"
2072
  msgstr ""
2073
 
2074
- #: inc/views/metaboxes/title-metabox.php:226
2075
  msgid "Title prefix options"
2076
  msgstr ""
2077
 
2078
- #: inc/views/metaboxes/title-metabox.php:227
2079
  msgid "On archives a descriptive prefix may be added to the title."
2080
  msgstr ""
2081
 
2082
- #: inc/views/metaboxes/title-metabox.php:230
2083
  msgid "Example Automated Archive Title Output"
2084
  msgstr ""
2085
 
2086
- #: inc/views/metaboxes/title-metabox.php:238
2087
  msgid "Remove Archive Title Prefixes"
2088
  msgstr ""
2089
 
2090
- #: inc/views/metaboxes/title-metabox.php:242
2091
  msgid "Remove prefixes from title?"
2092
  msgstr ""
2093
 
2094
- #: inc/views/metaboxes/title-metabox.php:246
2095
- msgid "The prefix helps visitors and Search Engines determine what kind of page they're visiting"
2096
  msgstr ""
2097
 
2098
  #: inc/views/metaboxes/webmaster-metabox.php:18
@@ -2111,32 +2169,36 @@ msgstr ""
2111
  msgid "Google Webmaster Verification Code"
2112
  msgstr ""
2113
 
2114
- #: inc/views/metaboxes/webmaster-metabox.php:28
2115
- msgid "Get the Google Verification code"
2116
  msgstr ""
2117
 
2118
- #: inc/views/metaboxes/webmaster-metabox.php:37
2119
  msgid "Bing Webmaster Verification Code"
2120
  msgstr ""
2121
 
2122
- #: inc/views/metaboxes/webmaster-metabox.php:38
2123
- msgid "Get the Bing Verification Code"
2124
  msgstr ""
2125
 
2126
- #: inc/views/metaboxes/webmaster-metabox.php:47
2127
  msgid "Yandex Webmaster Verification Code"
2128
  msgstr ""
2129
 
2130
- #: inc/views/metaboxes/webmaster-metabox.php:48
2131
- msgid "Get the Yandex Verification Code"
2132
  msgstr ""
2133
 
2134
- #: inc/views/metaboxes/webmaster-metabox.php:57
2135
  msgid "Pinterest Analytics Verification Code"
2136
  msgstr ""
2137
 
2138
- #: inc/views/metaboxes/webmaster-metabox.php:58
2139
- msgid "Get the Pinterest Verification Code"
 
 
 
 
2140
  msgstr ""
2141
 
2142
  #: inc/views/sitemap/xsl-stylesheet.php:8
@@ -2173,6 +2235,12 @@ msgstr ""
2173
  #: inc/views/sitemap/xsl-stylesheet.php:236
2174
  msgid "Generated by [The SEO Framework](https://wordpress.org/plugins/autodescription/)"
2175
  msgstr ""
 
 
 
 
 
 
2176
  #. Plugin Name of the plugin/theme
2177
  msgid "The SEO Framework"
2178
  msgstr ""
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 3.0.0\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/autodescription\n"
7
+ "POT-Creation-Date: 2017-11-19 18:46:04+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
+ #. translators: %s = term name
16
+
17
+ #: inc/classes/admin-init.class.php:252
18
+ msgid "Make primary %s"
19
+ msgstr ""
20
+
21
+ #. translators: %s = term name
22
+
23
+ #: inc/classes/admin-init.class.php:254
24
+ msgid "Primary %s"
25
+ msgstr ""
26
+
27
+ #: inc/classes/admin-init.class.php:351
28
+ msgid "The changes you made will be lost if you navigate away from this page."
29
+ msgstr ""
30
+
31
+ #: inc/classes/admin-init.class.php:352
32
+ msgid "Are you sure you want to reset all SEO settings to their defaults?"
33
+ msgstr ""
34
+
35
+ #: inc/classes/admin-init.class.php:353
36
  msgid "Good"
37
  msgstr ""
38
 
39
+ #: inc/classes/admin-init.class.php:354
40
  msgid "Okay"
41
  msgstr ""
42
 
43
+ #: inc/classes/admin-init.class.php:355
44
  msgid "Bad"
45
  msgstr ""
46
 
47
+ #: inc/classes/admin-init.class.php:356
48
  msgid "Unknown"
49
  msgstr ""
50
 
51
+ #: inc/classes/admin-init.class.php:357
52
+ msgid "Private:"
53
  msgstr ""
54
 
55
+ #: inc/classes/admin-init.class.php:358
56
+ msgid "Protected:"
57
+ msgstr ""
58
+
59
+ #. translators: Pixel counter. 1: width, 2: guideline
60
+
61
+ #: inc/classes/admin-init.class.php:360
62
+ msgid "%1$d out of %2$d pixels are used."
63
  msgstr ""
64
 
65
  #. translators: %s = Redirect URL markdown
66
 
67
+ #: inc/classes/admin-init.class.php:696
68
  msgid "There has been an error redirecting. Refresh the page or follow [this link](%s)."
69
  msgstr ""
70
 
71
+ #: inc/classes/admin-init.class.php:782 inc/classes/admin-init.class.php:843
72
  msgid "Image could not be processed."
73
  msgstr ""
74
 
96
  msgid "New SEO Settings have been updated."
97
  msgstr ""
98
 
99
+ #: inc/classes/admin-pages.class.php:109 inc/classes/site-options.class.php:439
 
100
  msgid "SEO Settings"
101
  msgstr ""
102
 
104
  msgid "SEO"
105
  msgstr ""
106
 
107
+ #: inc/classes/admin-pages.class.php:229
108
  msgid "General Settings"
109
  msgstr ""
110
 
111
+ #: inc/classes/admin-pages.class.php:240
112
  msgid "Title Settings"
113
  msgstr ""
114
 
115
+ #: inc/classes/admin-pages.class.php:251
116
  msgid "Description Meta Settings"
117
  msgstr ""
118
 
119
+ #: inc/classes/admin-pages.class.php:262
120
  msgid "Home Page Settings"
121
  msgstr ""
122
 
123
+ #: inc/classes/admin-pages.class.php:273
124
  msgid "Social Meta Settings"
125
  msgstr ""
126
 
127
+ #: inc/classes/admin-pages.class.php:284
128
  msgid "Schema Settings"
129
  msgstr ""
130
 
131
+ #: inc/classes/admin-pages.class.php:295
132
+ #: inc/views/inpost/seo-settings-singular.php:186
133
+ #: inc/views/inpost/seo-settings-tt.php:136
134
  msgid "Robots Meta Settings"
135
  msgstr ""
136
 
137
+ #: inc/classes/admin-pages.class.php:306
138
  msgid "Webmaster Meta Settings"
139
  msgstr ""
140
 
141
+ #: inc/classes/admin-pages.class.php:317
142
  msgid "Sitemap Settings"
143
  msgstr ""
144
 
145
+ #: inc/classes/admin-pages.class.php:328
146
  msgid "Feed Settings"
147
  msgstr ""
148
 
149
+ #: inc/classes/admin-pages.class.php:796 inc/classes/admin-pages.class.php:807
150
  msgctxt "Button hover"
151
  msgid "Select social image"
152
  msgstr ""
153
 
154
+ #: inc/classes/admin-pages.class.php:801 inc/classes/admin-pages.class.php:806
155
  msgid "Select Image"
156
  msgstr ""
157
 
158
+ #: inc/classes/admin-pages.class.php:808
159
  msgid "Change Image"
160
  msgstr ""
161
 
162
+ #: inc/classes/admin-pages.class.php:809
163
  msgid "Remove Image"
164
  msgstr ""
165
 
166
+ #: inc/classes/admin-pages.class.php:810
167
  msgid "Remove selected social image"
168
  msgstr ""
169
 
170
+ #: inc/classes/admin-pages.class.php:811
171
  msgctxt "Frame title"
172
  msgid "Select Social Image"
173
  msgstr ""
174
 
175
+ #: inc/classes/admin-pages.class.php:812 inc/classes/admin-pages.class.php:858
176
  msgid "Use this image"
177
  msgstr ""
178
 
179
+ #: inc/classes/admin-pages.class.php:847 inc/classes/admin-pages.class.php:852
180
+ msgid "Select Logo"
181
+ msgstr ""
182
+
183
+ #: inc/classes/admin-pages.class.php:854
184
+ msgid "Change Logo"
185
+ msgstr ""
186
+
187
+ #: inc/classes/admin-pages.class.php:855
188
+ msgid "Remove Logo"
189
+ msgstr ""
190
+
191
+ #: inc/classes/admin-pages.class.php:856
192
+ msgid "Unset selected logo"
193
+ msgstr ""
194
+
195
+ #: inc/classes/admin-pages.class.php:857
196
+ msgctxt "Frame title"
197
+ msgid "Select Logo"
198
+ msgstr ""
199
+
200
+ #. translators: %s = number
201
+
202
+ #: inc/classes/admin-pages.class.php:895
203
+ msgid "Characters Used: %s"
204
+ msgstr ""
205
+
206
+ #: inc/classes/core.class.php:254
207
+ msgid "Settings"
208
+ msgstr ""
209
+
210
+ #: inc/classes/core.class.php:256
211
  msgctxt "As in: The Plugin Home Page"
212
+ msgid "Home"
213
  msgstr ""
214
 
215
+ #: inc/classes/core.class.php:265
216
  msgid "https://wordpress.org/plugins/the-seo-framework-extension-manager/"
217
  msgstr ""
218
 
219
+ #: inc/classes/core.class.php:265
220
  msgctxt "Plugin extensions"
221
  msgid "Extensions"
222
  msgstr ""
223
 
224
+ #: inc/classes/core.class.php:317
225
  msgid "Dismiss"
226
  msgstr ""
227
 
228
+ #: inc/classes/core.class.php:460
229
  msgctxt "e.g. en for English, nl for Dutch, fi for Finish, de for German"
230
  msgid "en"
231
  msgstr ""
277
  msgid "No Archive"
278
  msgstr ""
279
 
280
+ #: inc/classes/doing-it-right.class.php:371
281
  msgid "Refresh to see the SEO Bar status."
282
  msgstr ""
283
 
284
+ #: inc/classes/doing-it-right.class.php:455
285
  msgid "Post"
286
  msgstr ""
287
 
288
+ #. translators: %s = Post type name
289
+
290
+ #: inc/classes/doing-it-right.class.php:459 inc/classes/inpost.class.php:310
291
+ #: inc/classes/term-data.class.php:361
292
+ #: inc/views/metaboxes/schema-metabox.php:197
293
  msgid "Page"
294
  msgstr ""
295
 
296
+ #: inc/classes/doing-it-right.class.php:503
297
  msgid "Failed to fetch post ID."
298
  msgstr ""
299
 
300
  #. translators: %s = But or And
301
 
302
+ #: inc/classes/doing-it-right.class.php:898
303
  msgid "%s the Title contains the Blogname multiple times."
304
  msgstr ""
305
 
306
  #. translators: 1: Word, 2: Occurrences
307
 
308
+ #: inc/classes/doing-it-right.class.php:1069
309
  msgid "%1$s is used %2$d times."
310
  msgstr ""
311
 
312
  #. Translators: %s = Post / Page / Category, etc.
313
 
314
+ #: inc/classes/doing-it-right.class.php:1114
315
  msgid "%s is being indexed."
316
  msgstr ""
317
 
318
+ #: inc/classes/doing-it-right.class.php:1123
319
  msgid "But you've discouraged indexing for the whole site."
320
  msgstr ""
321
 
322
  #. translators: 1: But or And, 2: Current taxonomy term plural label
323
 
324
+ #: inc/classes/doing-it-right.class.php:1147
325
  msgid "%1$s indexing for %2$s have been discouraged."
326
  msgstr ""
327
 
328
  #. translators: 1 = But or And, 1 = Post/Page
329
 
330
+ #: inc/classes/doing-it-right.class.php:1160
331
  msgid "%1$s the %2$s is protected from public visibility. This means indexing is discouraged."
332
  msgstr ""
333
 
334
  #. translators: %s = But or And
335
 
336
+ #: inc/classes/doing-it-right.class.php:1169
337
  msgid "%s the blog isn't set to public. This means WordPress discourages indexing."
338
  msgstr ""
339
 
340
  #. translators: %s = But or And
341
 
342
+ #: inc/classes/doing-it-right.class.php:1183
343
  msgid "%s there are no posts in this term; therefore, indexing has been discouraged."
344
  msgstr ""
345
 
346
+ #: inc/classes/doing-it-right.class.php:1267
347
  msgid "%s links aren't being followed."
348
  msgstr ""
349
 
350
+ #: inc/classes/doing-it-right.class.php:1273
351
  msgid "%s links are being followed."
352
  msgstr ""
353
 
354
  #. translators: %s = But or And
355
 
356
+ #: inc/classes/doing-it-right.class.php:1285
357
  msgid "%s you've discouraged the following of links for the whole site."
358
  msgstr ""
359
 
360
  #. translators: 1: But or And, 2: Current taxonomy term plural label
361
 
362
+ #: inc/classes/doing-it-right.class.php:1311
363
  msgid "%1$s following for %2$s have been discouraged."
364
  msgstr ""
365
 
366
  #. translators: %s = But or And
367
 
368
+ #: inc/classes/doing-it-right.class.php:1323
369
  msgid "%s the blog isn't set to public. This means WordPress allows the links to be followed regardless."
370
  msgstr ""
371
 
372
+ #: inc/classes/doing-it-right.class.php:1375
373
  msgid "Search Engines aren't allowed to archive this %s."
374
  msgstr ""
375
 
376
+ #: inc/classes/doing-it-right.class.php:1380
377
  msgid "Search Engines are allowed to archive this %s."
378
  msgstr ""
379
 
380
+ #: inc/classes/doing-it-right.class.php:1392
381
  msgid "But you've discouraged archiving for the whole site."
382
  msgstr ""
383
 
384
  #. translators: 1: But or And, 2: Current taxonomy term plural label
385
 
386
+ #: inc/classes/doing-it-right.class.php:1418
387
  msgid "%1$s archiving for %2$s have been discouraged."
388
  msgstr ""
389
 
390
  #. translators: %s = But or And
391
 
392
+ #: inc/classes/doing-it-right.class.php:1431
393
  msgid "%s the blog isn't set to public. This means WordPress allows the blog to be archived regardless."
394
  msgstr ""
395
 
396
+ #: inc/classes/doing-it-right.class.php:1477
397
  msgid "%s isn't being redirected."
398
  msgstr ""
399
 
400
+ #: inc/classes/doing-it-right.class.php:1519
401
+ #: inc/classes/doing-it-right.class.php:1548
402
  msgid "%s is being redirected. This means no SEO values have to be set."
403
  msgstr ""
404
 
405
+ #: inc/classes/doing-it-right.class.php:1522
406
+ #: inc/classes/doing-it-right.class.php:1564
407
  msgid "%s is not being indexed. This means no SEO values have to be set."
408
  msgstr ""
409
 
410
+ #: inc/classes/doing-it-right.class.php:1678
411
  msgid "Title:"
412
  msgstr ""
413
 
414
+ #: inc/classes/doing-it-right.class.php:1679
415
  msgid "Description:"
416
  msgstr ""
417
 
418
+ #: inc/classes/doing-it-right.class.php:1680
419
  msgid "Index:"
420
  msgstr ""
421
 
422
+ #: inc/classes/doing-it-right.class.php:1681
423
  msgid "Follow:"
424
  msgstr ""
425
 
426
+ #: inc/classes/doing-it-right.class.php:1682
427
  msgid "Archive:"
428
  msgstr ""
429
 
430
+ #: inc/classes/doing-it-right.class.php:1683
431
  msgid "Redirect:"
432
  msgstr ""
433
 
434
+ #: inc/classes/doing-it-right.class.php:1685
435
  msgid "Generated: Automatically generated."
436
  msgstr ""
437
 
438
+ #: inc/classes/doing-it-right.class.php:1687
439
  msgctxt "Generated"
440
  msgid "G"
441
  msgstr ""
442
 
443
+ #: inc/classes/doing-it-right.class.php:1688
444
  msgctxt "Title"
445
  msgid "T"
446
  msgstr ""
447
 
448
+ #: inc/classes/doing-it-right.class.php:1689
449
  msgctxt "Description"
450
  msgid "D"
451
  msgstr ""
452
 
453
+ #: inc/classes/doing-it-right.class.php:1690
454
  msgctxt "no-Index"
455
  msgid "I"
456
  msgstr ""
457
 
458
+ #: inc/classes/doing-it-right.class.php:1691
459
  msgctxt "no-Follow"
460
  msgid "F"
461
  msgstr ""
462
 
463
+ #: inc/classes/doing-it-right.class.php:1692
464
  msgctxt "no-Archive"
465
  msgid "A"
466
  msgstr ""
467
 
468
+ #: inc/classes/doing-it-right.class.php:1693
469
  msgctxt "Redirect"
470
  msgid "R"
471
  msgstr ""
472
 
473
+ #: inc/classes/doing-it-right.class.php:1695
474
  msgctxt "But there are..."
475
  msgid "But"
476
  msgstr ""
477
 
478
+ #: inc/classes/doing-it-right.class.php:1696
479
  msgctxt "And there are..."
480
  msgid "And"
481
  msgstr ""
482
 
483
+ #: inc/classes/doing-it-right.class.php:1698
484
  msgid "Length is far too short."
485
  msgstr ""
486
 
487
+ #: inc/classes/doing-it-right.class.php:1699
488
  msgid "Length is too short."
489
  msgstr ""
490
 
491
+ #: inc/classes/doing-it-right.class.php:1700
492
  msgid "Length is too long."
493
  msgstr ""
494
 
495
+ #: inc/classes/doing-it-right.class.php:1701
496
  msgid "Length is far too long."
497
  msgstr ""
498
 
499
+ #: inc/classes/doing-it-right.class.php:1702
500
  msgid "Length is good."
501
  msgstr ""
502
 
503
+ #: inc/classes/feed.class.php:179
504
  msgctxt "The content source"
505
  msgid "Source"
506
  msgstr ""
507
 
508
  #. translators: 1: Title, 2: Separator, 3: Excerpt
509
 
510
+ #: inc/classes/generate-description.class.php:451
511
  msgctxt "1: Title, 2: Separator, 3: Excerpt"
512
  msgid "%1$s %2$s %3$s"
513
  msgstr ""
514
 
515
  #. translators: 1: Title, 2: on, 3: Blogname
516
 
517
+ #: inc/classes/generate-description.class.php:658
518
  msgctxt "1: Title, 2: on, 3: Blogname"
519
  msgid "%1$s %2$s %3$s"
520
  msgstr ""
521
 
522
  #. translators: Front-end output.
523
 
524
+ #: inc/classes/generate-description.class.php:695
525
  #: inc/views/metaboxes/description-metabox.php:18
526
  msgctxt "Placement. e.g. Post Title \"on\" Blog Name"
527
  msgid "on"
529
 
530
  #. translators: Front-end output.
531
 
532
+ #: inc/classes/generate-description.class.php:783
533
  msgid "Latest posts:"
534
  msgstr ""
535
 
536
+ #: inc/classes/generate-ldjson.class.php:557
537
+ #: inc/classes/generate-ldjson.class.php:564
538
  msgid "Uncategorized"
539
  msgstr ""
540
 
541
  #. translators: Front-end output. 1: Taxonomy singular name, 2: Current
542
  #. taxonomy term
543
 
544
+ #: inc/classes/generate-title.class.php:837
545
+ #: inc/classes/generate-title.class.php:897
546
  msgid "%1$s: %2$s"
547
  msgstr ""
548
 
549
  #. translators: Front-end output.
550
 
551
+ #: inc/classes/generate-title.class.php:841
552
  msgid "Author: %s"
553
  msgstr ""
554
 
555
  #. translators: Front-end output.
556
 
557
+ #: inc/classes/generate-title.class.php:845
558
  msgctxt "yearly archives date format"
559
  msgid "Y"
560
  msgstr ""
561
 
562
  #. translators: Front-end output.
563
 
564
+ #: inc/classes/generate-title.class.php:847
565
  msgid "Year: %s"
566
  msgstr ""
567
 
568
  #. translators: Front-end output.
569
 
570
+ #: inc/classes/generate-title.class.php:850
571
  msgctxt "monthly archives date format"
572
  msgid "F Y"
573
  msgstr ""
574
 
575
  #. translators: Front-end output.
576
 
577
+ #: inc/classes/generate-title.class.php:852
578
  msgid "Month: %s"
579
  msgstr ""
580
 
581
  #. translators: Front-end output.
582
 
583
+ #: inc/classes/generate-title.class.php:855
584
  msgctxt "daily archives date format"
585
  msgid "F j, Y"
586
  msgstr ""
587
 
588
  #. translators: Front-end output.
589
 
590
+ #: inc/classes/generate-title.class.php:857
591
  msgid "Day: %s"
592
  msgstr ""
593
 
594
  #. translators: Front-end output.
595
 
596
+ #: inc/classes/generate-title.class.php:862
597
  msgctxt "post format archive title"
598
  msgid "Asides"
599
  msgstr ""
600
 
601
  #. translators: Front-end output.
602
 
603
+ #: inc/classes/generate-title.class.php:865
604
  msgctxt "post format archive title"
605
  msgid "Galleries"
606
  msgstr ""
607
 
608
  #. translators: Front-end output.
609
 
610
+ #: inc/classes/generate-title.class.php:868
611
  msgctxt "post format archive title"
612
  msgid "Images"
613
  msgstr ""
614
 
615
  #. translators: Front-end output.
616
 
617
+ #: inc/classes/generate-title.class.php:871
618
  msgctxt "post format archive title"
619
  msgid "Videos"
620
  msgstr ""
621
 
622
  #. translators: Front-end output.
623
 
624
+ #: inc/classes/generate-title.class.php:874
625
  msgctxt "post format archive title"
626
  msgid "Quotes"
627
  msgstr ""
628
 
629
  #. translators: Front-end output.
630
 
631
+ #: inc/classes/generate-title.class.php:877
632
  msgctxt "post format archive title"
633
  msgid "Links"
634
  msgstr ""
635
 
636
  #. translators: Front-end output.
637
 
638
+ #: inc/classes/generate-title.class.php:880
639
  msgctxt "post format archive title"
640
  msgid "Statuses"
641
  msgstr ""
642
 
643
  #. translators: Front-end output.
644
 
645
+ #: inc/classes/generate-title.class.php:883
646
  msgctxt "post format archive title"
647
  msgid "Audio"
648
  msgstr ""
649
 
650
  #. translators: Front-end output.
651
 
652
+ #: inc/classes/generate-title.class.php:886
653
  msgctxt "post format archive title"
654
  msgid "Chats"
655
  msgstr ""
656
 
657
  #. translators: Front-end output.
658
 
659
+ #: inc/classes/generate-title.class.php:891
660
  msgid "Archives: %s"
661
  msgstr ""
662
 
663
  #. translators: Front-end output.
664
 
665
+ #: inc/classes/generate-title.class.php:901
666
  msgid "Archives"
667
  msgstr ""
668
 
669
  #. translators: Front-end output.
670
 
671
+ #: inc/classes/generate-title.class.php:1015
672
  msgid "Untitled"
673
  msgstr ""
674
 
675
  #. translators: Front-end output.
676
 
677
+ #: inc/classes/generate-title.class.php:1050
678
  msgid "Search results for:"
679
  msgstr ""
680
 
681
  #. translators: Front-end output.
682
 
683
+ #: inc/classes/generate-title.class.php:1226
684
  msgid "Protected: %s"
685
  msgstr ""
686
 
687
  #. translators: Front-end output.
688
 
689
+ #: inc/classes/generate-title.class.php:1230
690
  msgid "Private: %s"
691
  msgstr ""
692
 
693
  #. translators: %d = page number. Front-end output.
694
 
695
+ #: inc/classes/generate-title.class.php:1278
696
  msgid "Page %d"
697
  msgstr ""
698
 
699
+ #: inc/classes/inpost.class.php:218 inc/classes/inpost.class.php:226
700
+ msgid "Homepage SEO Settings"
701
+ msgstr ""
702
+
703
+ #: inc/classes/inpost.class.php:220
704
+ msgid "The SEO Settings take precedence over these settings."
705
+ msgstr ""
706
+
707
+ #. translators: %s = Post Type
708
+ #. translators: %s = Term type
709
 
710
+ #: inc/classes/inpost.class.php:230 inc/views/inpost/seo-settings-tt.php:73
711
  msgid "%s SEO Settings"
712
  msgstr ""
713
 
714
+ #: inc/classes/profile.class.php:88
715
+ msgid "Facebook profile page"
716
+ msgstr ""
717
+
718
+ #: inc/classes/profile.class.php:89 inc/views/metaboxes/social-metabox.php:167
719
+ msgctxt "Example Facebook Personal URL"
720
+ msgid "https://www.facebook.com/YourPersonalProfile"
721
+ msgstr ""
722
+
723
+ #: inc/classes/profile.class.php:93
724
+ msgid "Twitter profile"
725
+ msgstr ""
726
+
727
+ #: inc/classes/profile.class.php:94 inc/views/metaboxes/social-metabox.php:236
728
+ msgctxt "Twitter @username"
729
+ msgid "@your-personal-username"
730
+ msgstr ""
731
+
732
  #. translators: %s = 'The SEO Framework'
733
 
734
+ #: inc/classes/render.class.php:1099
735
  msgid "Start %s"
736
  msgstr ""
737
 
738
  #. translators: %s = 'The SEO Framework'
739
 
740
+ #: inc/classes/render.class.php:1101
741
  msgid "End %s"
742
  msgstr ""
743
 
744
+ #: inc/classes/render.class.php:1102
745
  msgid "by Sybre Waaijer"
746
  msgstr ""
747
 
748
+ #: inc/classes/site-options.class.php:439
749
  msgid "here"
750
  msgstr ""
751
 
752
+ #: inc/classes/site-options.class.php:440
753
  msgctxt "%s = here"
754
  msgid "View the new options %s."
755
  msgstr ""
762
  msgid "Sitemap is served from cache"
763
  msgstr ""
764
 
765
+ #: inc/classes/sitemaps.class.php:609
766
  msgid "Sitemap is generated on"
767
  msgstr ""
768
 
769
+ #: inc/classes/term-data.class.php:363
 
770
  msgid "Pages"
771
  msgstr ""
772
 
773
+ #: inc/functions/upgrade.php:192
774
  msgid "Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable."
775
  msgstr ""
776
 
777
+ #: inc/functions/upgrade.php:218
778
+ msgid "The previous sitemap timestamp settings have been converted into new global timestamp settings."
779
+ msgstr ""
780
+
781
  #: inc/views/inpost/seo-settings-singular.php:38
782
  #: inc/views/metaboxes/description-metabox.php:67
783
+ #: inc/views/metaboxes/homepage-metabox.php:30
784
  #: inc/views/metaboxes/robots-metabox.php:57
785
+ #: inc/views/metaboxes/sitemaps-metabox.php:25
 
786
  #: inc/views/metaboxes/social-metabox.php:25
787
  #: inc/views/metaboxes/title-metabox.php:61
788
  msgid "General"
793
  msgstr ""
794
 
795
  #: inc/views/inpost/seo-settings-singular.php:50
796
+ #: inc/views/metaboxes/homepage-metabox.php:45
797
  msgid "Social"
798
  msgstr ""
799
 
800
  #: inc/views/inpost/seo-settings-singular.php:87
801
+ #: inc/views/inpost/seo-settings-tt.php:81
802
+ #: inc/views/inpost/seo-settings-tt.php:195
803
  msgid "Doing it Right"
804
  msgstr ""
805
 
806
  #. translators: %s = Post type name
807
+ #. translators: %s = Post type
808
 
809
  #: inc/views/inpost/seo-settings-singular.php:108
 
 
 
 
 
 
810
  #: inc/views/metaboxes/homepage-metabox.php:174
811
+ msgid "Custom %s Title"
 
 
 
 
 
 
 
 
 
 
 
812
  msgstr ""
813
 
814
  #. translators: %s = Post type name
815
 
816
+ #: inc/views/inpost/seo-settings-singular.php:135
817
+ #: inc/views/metaboxes/homepage-metabox.php:230
818
  msgid "Custom %s Description"
819
  msgstr ""
820
 
821
+ #: inc/views/inpost/seo-settings-singular.php:165
 
 
 
 
 
 
822
  msgid "Custom Canonical URL"
823
  msgstr ""
824
 
825
+ #: inc/views/inpost/seo-settings-singular.php:169
826
+ msgid "This urges search engines to go to the outputted URL."
 
 
827
  msgstr ""
828
 
829
  #. translators: 1: Option, 2: Post or Page
830
 
831
+ #: inc/views/inpost/seo-settings-singular.php:196
832
+ #: inc/views/inpost/seo-settings-singular.php:212
833
+ #: inc/views/inpost/seo-settings-singular.php:226
834
  msgid "Apply %1$s to this %2$s"
835
  msgstr ""
836
 
837
+ #: inc/views/inpost/seo-settings-singular.php:200
838
+ msgid "This tells search engines not to show this %s in their search results."
839
  msgstr ""
840
 
841
+ #: inc/views/inpost/seo-settings-singular.php:215
842
+ msgid "This tells search engines not to follow links on this %s."
843
  msgstr ""
844
 
845
  #. translators: %s = Post type name
846
 
847
+ #: inc/views/inpost/seo-settings-singular.php:234
848
+ msgid "This tells search engines not to save a cached copy of this %s."
849
  msgstr ""
850
 
851
+ #: inc/views/inpost/seo-settings-singular.php:255
852
  msgid "Archive Settings"
853
  msgstr ""
854
 
855
  #. translators: %s = Post type name
856
 
857
+ #: inc/views/inpost/seo-settings-singular.php:265
858
  msgid "Exclude this %s from local search"
859
  msgstr ""
860
 
861
  #. translators: %s = Post type name
862
 
863
+ #: inc/views/inpost/seo-settings-singular.php:268
864
+ msgid "This excludes this %s from local on-site search results."
865
  msgstr ""
866
 
867
  #. translators: %s = Post type name
868
 
869
+ #: inc/views/inpost/seo-settings-singular.php:278
870
+ msgid "Exclude this %s from all archive listings."
871
  msgstr ""
872
 
873
  #. translators: %s = Post type name
874
 
875
+ #: inc/views/inpost/seo-settings-singular.php:281
876
+ msgid "This excludes this %s from on-site archive pages."
877
  msgstr ""
878
 
879
+ #: inc/views/inpost/seo-settings-singular.php:295
880
  msgid "Custom 301 Redirect URL"
881
  msgstr ""
882
 
883
+ #: inc/views/inpost/seo-settings-singular.php:300
884
+ msgid "This will force visitors to go to another URL."
885
  msgstr ""
886
 
887
+ #: inc/views/inpost/seo-settings-singular.php:324
888
  msgid "Custom Social Image URL"
889
  msgstr ""
890
 
891
  #. translators: %s = Post type name
892
 
893
+ #: inc/views/inpost/seo-settings-singular.php:330
894
+ msgid "Set preferred %s Social Image URL location."
895
  msgstr ""
896
 
897
+ #. translators: %s = Term type
898
+
899
+ #: inc/views/inpost/seo-settings-tt.php:94
900
  msgid "%s Title"
901
  msgstr ""
902
 
903
+ #. translators: %s = Term type
904
+
905
+ #: inc/views/inpost/seo-settings-tt.php:119
906
  msgid "%s Meta Description"
907
  msgstr ""
908
 
909
+ #. translators: %s = noindex/nofollow/noarchive
 
 
 
 
910
 
911
+ #: inc/views/inpost/seo-settings-tt.php:142
912
+ #: inc/views/inpost/seo-settings-tt.php:158
913
+ #: inc/views/inpost/seo-settings-tt.php:174
914
+ msgid "Apply %s to this term?"
915
  msgstr ""
916
 
917
+ #: inc/views/inpost/seo-settings-tt.php:146
918
+ #: inc/views/metaboxes/homepage-metabox.php:361
919
+ msgid "This tells search engines not to show this page in their search results."
920
  msgstr ""
921
 
922
+ #: inc/views/inpost/seo-settings-tt.php:162
923
+ #: inc/views/inpost/seo-settings-tt.php:178
924
+ #: inc/views/metaboxes/homepage-metabox.php:371
925
+ msgid "This tells search engines not to follow links on this page."
926
  msgstr ""
927
 
928
  #: inc/views/metaboxes/description-metabox.php:17
938
  msgstr ""
939
 
940
  #: inc/views/metaboxes/description-metabox.php:42
941
+ #: inc/views/metaboxes/homepage-metabox.php:244
942
  msgid "The meta description can be used to determine the text used under the title on Search Engine results pages."
943
  msgstr ""
944
 
947
  msgstr ""
948
 
949
  #: inc/views/metaboxes/description-metabox.php:72
950
+ #: inc/views/metaboxes/homepage-metabox.php:35
951
  #: inc/views/metaboxes/title-metabox.php:66
952
  msgid "Additions"
953
  msgstr ""
954
 
955
+ #: inc/views/metaboxes/description-metabox.php:101
956
  msgid "Description Excerpt Separator"
957
  msgstr ""
958
 
959
+ #: inc/views/metaboxes/description-metabox.php:102
960
  msgid "If the Automated Description consists of two parts (title and excerpt), then the separator will go in-between them."
961
  msgstr ""
962
 
963
+ #: inc/views/metaboxes/description-metabox.php:122
964
  msgid "Description Additions Settings"
965
  msgstr ""
966
 
967
+ #: inc/views/metaboxes/description-metabox.php:124
968
  msgid "To create a more organic description, a small introduction can be added before the description."
969
  msgstr ""
970
 
971
+ #: inc/views/metaboxes/description-metabox.php:125
972
  msgid "The introduction consists of the title and optionally the blogname."
973
  msgstr ""
974
 
975
+ #: inc/views/metaboxes/description-metabox.php:130
976
  msgid "Add descriptive Additions to Description"
977
  msgstr ""
978
 
979
+ #: inc/views/metaboxes/description-metabox.php:135
980
  msgid "Add Additions to automated description?"
981
  msgstr ""
982
 
983
+ #: inc/views/metaboxes/description-metabox.php:138
984
+ msgid "This creates better automated meta descriptions."
985
  msgstr ""
986
 
987
+ #: inc/views/metaboxes/description-metabox.php:145
988
  msgid "Add Blogname to Additions"
989
  msgstr ""
990
 
991
+ #: inc/views/metaboxes/description-metabox.php:149
992
+ msgid "Add the blog name to the automated description?"
993
  msgstr ""
994
 
995
  #: inc/views/metaboxes/feed-metabox.php:10
1013
  msgstr ""
1014
 
1015
  #: inc/views/metaboxes/feed-metabox.php:20
1016
+ msgid "By default the excerpt will be at most 400 characters long."
1017
  msgstr ""
1018
 
1019
  #: inc/views/metaboxes/feed-metabox.php:22
1021
  msgstr ""
1022
 
1023
  #: inc/views/metaboxes/feed-metabox.php:23
1024
+ msgid "This link will not be followed by search engines."
1025
  msgstr ""
1026
 
1027
  #: inc/views/metaboxes/feed-metabox.php:35
1059
  msgid "Canonical"
1060
  msgstr ""
1061
 
1062
+ #: inc/views/metaboxes/general-metabox.php:33
1063
+ #: inc/views/metaboxes/sitemaps-metabox.php:35
1064
+ msgid "Timestamps"
1065
+ msgstr ""
1066
+
1067
+ #: inc/views/metaboxes/general-metabox.php:57
1068
  msgid "Administrative Layout Settings"
1069
  msgstr ""
1070
 
1071
+ #: inc/views/metaboxes/general-metabox.php:59
1072
  msgid "SEO hints can be visually displayed throughout the dashboard."
1073
  msgstr ""
1074
 
1075
+ #: inc/views/metaboxes/general-metabox.php:64
1076
  msgid "SEO Bar Settings"
1077
  msgstr ""
1078
 
1079
+ #: inc/views/metaboxes/general-metabox.php:70
1080
  msgid "Display the SEO Bar in overview tables?"
1081
  msgstr ""
1082
 
1083
+ #: inc/views/metaboxes/general-metabox.php:76
1084
  msgid "Display the SEO Bar in the SEO Settings metabox?"
1085
  msgstr ""
1086
 
1087
+ #: inc/views/metaboxes/general-metabox.php:87
1088
+ msgid "Counter Settings"
1089
+ msgstr ""
1090
+
1091
+ #: inc/views/metaboxes/general-metabox.php:91
1092
+ msgid "The pixel counter computes whether the input will fit on Search Engine Result Pages."
1093
+ msgstr ""
1094
+
1095
+ #: inc/views/metaboxes/general-metabox.php:96
1096
+ msgid "The character counter is based on guidelines."
1097
+ msgstr ""
1098
+
1099
+ #: inc/views/metaboxes/general-metabox.php:105
1100
+ msgid "Display pixel counters?"
1101
+ msgstr ""
1102
+
1103
+ #: inc/views/metaboxes/general-metabox.php:111
1104
+ msgid "Display character counters?"
1105
+ msgstr ""
1106
+
1107
+ #: inc/views/metaboxes/general-metabox.php:123
1108
  msgid "Performance Settings"
1109
  msgstr ""
1110
 
1111
+ #: inc/views/metaboxes/general-metabox.php:125
1112
  msgid "Depending on your server's configuration, adjusting these settings can affect performance."
1113
  msgstr ""
1114
 
1115
+ #: inc/views/metaboxes/general-metabox.php:130
1116
+ msgid "Query Alteration Settings"
1117
  msgstr ""
1118
 
1119
+ #: inc/views/metaboxes/general-metabox.php:133
1120
  msgid "Altering the query allows for more control of the site's hierarchy."
1121
  msgstr ""
1122
 
1123
+ #: inc/views/metaboxes/general-metabox.php:135
1124
  msgid "If your website has thousands of pages, these options can greatly affect database performance."
1125
  msgstr ""
1126
 
1127
+ #: inc/views/metaboxes/general-metabox.php:139
1128
  msgid "Altering the query in the database is more accurate, but can increase database query time."
1129
  msgstr ""
1130
 
1131
+ #: inc/views/metaboxes/general-metabox.php:141
1132
  msgid "Altering the query on the site is much faster, but can lead to inconsistent pagination. It can also lead to 404 error messages if all queried pages have been excluded."
1133
  msgstr ""
1134
 
1135
+ #: inc/views/metaboxes/general-metabox.php:147
1136
  msgctxt "Perform query alteration..."
1137
  msgid "In the database"
1138
  msgstr ""
1139
 
1140
+ #: inc/views/metaboxes/general-metabox.php:148
1141
  msgctxt "Perform query alteration..."
1142
  msgid "On the site"
1143
  msgstr ""
1144
 
1145
+ #: inc/views/metaboxes/general-metabox.php:176
1146
  msgid "Perform alteration:"
1147
  msgstr ""
1148
 
1149
+ #: inc/views/metaboxes/general-metabox.php:203
1150
  msgid "Enable search query alteration?"
1151
  msgstr ""
1152
 
1153
+ #: inc/views/metaboxes/general-metabox.php:204
1154
+ msgid "This allows you to exclude pages from on-site search results."
1155
  msgstr ""
1156
 
1157
+ #: inc/views/metaboxes/general-metabox.php:217
1158
  msgid "Enable archive query alteration?"
1159
  msgstr ""
1160
 
1161
+ #: inc/views/metaboxes/general-metabox.php:218
1162
+ msgid "This allows you to exclude pages from on-site archive listings."
1163
  msgstr ""
1164
 
1165
+ #: inc/views/metaboxes/general-metabox.php:229
1166
  msgid "Transient Cache Settings"
1167
  msgstr ""
1168
 
1169
+ #: inc/views/metaboxes/general-metabox.php:231
1170
  msgid "To improve performance, generated SEO output can be stored in the database as transient cache."
1171
  msgstr ""
1172
 
1173
+ #: inc/views/metaboxes/general-metabox.php:232
1174
  msgid "If your website has thousands of pages, or if other forms of caching are used, you might wish to adjust these options."
1175
  msgstr ""
1176
 
1177
+ #: inc/views/metaboxes/general-metabox.php:238
1178
  msgid "Enable automated description output cache?"
1179
  msgstr ""
1180
 
1181
+ #: inc/views/metaboxes/general-metabox.php:239
1182
+ msgid "Description generation can use a lot of server resources when it reads the page content."
1183
  msgstr ""
1184
 
1185
+ #: inc/views/metaboxes/general-metabox.php:245
1186
  msgid "Enable automated Schema output cache?"
1187
  msgstr ""
1188
 
1189
+ #: inc/views/metaboxes/general-metabox.php:246
1190
+ msgid "Schema.org output generally makes multiple calls to the database."
1191
  msgstr ""
1192
 
1193
+ #: inc/views/metaboxes/general-metabox.php:252
1194
  msgid "Enable sitemap generation cache?"
1195
  msgstr ""
1196
 
1197
+ #: inc/views/metaboxes/general-metabox.php:253
1198
+ msgid "Generating the sitemap can use a lot of server resources."
1199
  msgstr ""
1200
 
1201
+ #: inc/views/metaboxes/general-metabox.php:265
1202
  msgid "Object Cache Settings"
1203
  msgstr ""
1204
 
1205
+ #: inc/views/metaboxes/general-metabox.php:271
1206
  msgid "Enable object cache?"
1207
  msgstr ""
1208
 
1209
+ #: inc/views/metaboxes/general-metabox.php:272
1210
+ msgid "Object cache generally works faster than transient cache."
1211
  msgstr ""
1212
 
1213
+ #: inc/views/metaboxes/general-metabox.php:273
1214
  msgid "An object cache handler has been detected. If you enable this option, you might wish to disable description and Schema transient caching."
1215
  msgstr ""
1216
 
1217
+ #: inc/views/metaboxes/general-metabox.php:283
1218
  msgid "Canonical URL Settings"
1219
  msgstr ""
1220
 
1221
+ #: inc/views/metaboxes/general-metabox.php:285
1222
+ msgid "The canonical URL meta tag urges search engines to go to the outputted URL."
1223
  msgstr ""
1224
 
1225
+ #: inc/views/metaboxes/general-metabox.php:286
1226
  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."
1227
  msgstr ""
1228
 
1229
+ #: inc/views/metaboxes/general-metabox.php:287
1230
  msgid "Only adjust these options if you are aware of their SEO effects."
1231
  msgstr ""
1232
 
1233
+ #: inc/views/metaboxes/general-metabox.php:292
1234
  msgid "Scheme Settings"
1235
  msgstr ""
1236
 
1237
+ #: inc/views/metaboxes/general-metabox.php:294
1238
  msgid "If your website is accessible on both HTTP as HTTPS, set this to HTTPS in order to prevent duplicate content."
1239
  msgstr ""
1240
 
1241
+ #: inc/views/metaboxes/general-metabox.php:295
1242
  msgid "Otherwise, automatic detection is recommended."
1243
  msgstr ""
1244
 
1245
+ #: inc/views/metaboxes/general-metabox.php:297
1246
  msgctxt "= Detect Automatically, HTTPS, HTTP"
1247
  msgid "Preferred canonical URL scheme:"
1248
  msgstr ""
1249
 
1250
+ #: inc/views/metaboxes/general-metabox.php:303
1251
  msgid "Detect automatically"
1252
  msgstr ""
1253
 
1254
+ #: inc/views/metaboxes/general-metabox.php:316
1255
  msgid "Link Relationship Settings"
1256
  msgstr ""
1257
 
1258
+ #: inc/views/metaboxes/general-metabox.php:318
1259
+ 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."
1260
  msgstr ""
1261
 
1262
+ #: inc/views/metaboxes/general-metabox.php:319
1263
  msgid "It's recommended to turn this option on for better SEO consistency and to prevent duplicate content errors."
1264
  msgstr ""
1265
 
1266
  #. translators: %s = <code>rel</code>
1267
 
1268
+ #: inc/views/metaboxes/general-metabox.php:322
1269
  msgid "Add %s link tags to Posts and Pages?"
1270
  msgstr ""
1271
 
1272
  #. translators: %s = <code>rel</code>
1273
 
1274
+ #: inc/views/metaboxes/general-metabox.php:326
1275
  msgid "Add %s link tags to Archives?"
1276
  msgstr ""
1277
 
1278
  #. translators: %s = <code>rel</code>
1279
 
1280
+ #: inc/views/metaboxes/general-metabox.php:330
1281
  msgid "Add %s link tags to the Home Page?"
1282
  msgstr ""
1283
 
1284
+ #: inc/views/metaboxes/general-metabox.php:354
1285
+ msgid "Timestamp Settings"
1286
+ msgstr ""
1287
+
1288
+ #: inc/views/metaboxes/general-metabox.php:356
1289
+ msgid "Timestamps indicate when a page has been published and modified."
1290
+ msgstr ""
1291
+
1292
+ #: inc/views/metaboxes/general-metabox.php:362
1293
+ msgid "Timestamp Format Settings"
1294
+ msgstr ""
1295
+
1296
+ #: inc/views/metaboxes/general-metabox.php:363
1297
+ msgid "This setting determines how specific the timestamp is."
1298
+ msgstr ""
1299
+
1300
+ #: inc/views/metaboxes/general-metabox.php:374
1301
+ msgid "This outputs the complete date."
1302
+ msgstr ""
1303
+
1304
+ #: inc/views/metaboxes/general-metabox.php:386
1305
+ msgid "This outputs the complete date including hours, minutes, and timezone."
1306
+ msgstr ""
1307
+
1308
+ #: inc/views/metaboxes/homepage-metabox.php:10
1309
  msgid "These settings will take precedence over the settings set within the Home Page edit screen, if any."
1310
  msgstr ""
1311
 
1312
+ #: inc/views/metaboxes/homepage-metabox.php:40
1313
  msgid "Robots"
1314
  msgstr ""
1315
 
1316
+ #: inc/views/metaboxes/homepage-metabox.php:69
1317
  msgid "Title"
1318
  msgstr ""
1319
 
1320
+ #: inc/views/metaboxes/homepage-metabox.php:70
1321
  msgid "Description"
1322
  msgstr ""
1323
 
1324
+ #: inc/views/metaboxes/homepage-metabox.php:71
1325
+ #: inc/views/metaboxes/homepage-metabox.php:281
1326
+ #: inc/views/metaboxes/homepage-metabox.php:328
1327
+ #: inc/views/metaboxes/social-metabox.php:318
 
1328
  msgid "Home Page"
1329
  msgstr ""
1330
 
1331
+ #: inc/views/metaboxes/homepage-metabox.php:141
1332
+ #: inc/views/metaboxes/homepage-metabox.php:199
1333
  msgid "Page SEO Settings"
1334
  msgstr ""
1335
 
1336
  #. translators: 1: Option, 2: Page SEO Settings, 3: Home Page
1337
 
1338
+ #: inc/views/metaboxes/homepage-metabox.php:143
1339
+ #: inc/views/metaboxes/homepage-metabox.php:197
1340
  msgid "Note: The %1$s is fetched from the %2$s on the %3$s."
1341
  msgstr ""
1342
 
1343
+ #: inc/views/metaboxes/homepage-metabox.php:160
1344
  msgid "Custom %s Title Tagline"
1345
  msgstr ""
1346
 
1347
  #. translators: %s = Home page URL markdown
1348
 
1349
+ #: inc/views/metaboxes/homepage-metabox.php:215
1350
+ #: inc/views/metaboxes/homepage-metabox.php:260
1351
  msgid "A plugin has been detected that suggests to maintain this option on the [Home Page](%s)."
1352
  msgstr ""
1353
 
1354
+ #: inc/views/metaboxes/homepage-metabox.php:286
1355
+ #: inc/views/metaboxes/title-metabox.php:135
1356
+ msgid "Title Additions Location"
1357
  msgstr ""
1358
 
1359
+ #: inc/views/metaboxes/homepage-metabox.php:287
1360
+ #: inc/views/metaboxes/title-metabox.php:136
1361
+ msgid "This setting determines which side the added title text will go on."
1362
  msgstr ""
1363
 
1364
+ #: inc/views/metaboxes/homepage-metabox.php:294
1365
+ #: inc/views/metaboxes/title-metabox.php:142
1366
  msgid "Left:"
1367
  msgstr ""
1368
 
1369
+ #: inc/views/metaboxes/homepage-metabox.php:304
1370
+ #: inc/views/metaboxes/title-metabox.php:149
1371
  msgid "Right:"
1372
  msgstr ""
1373
 
1374
+ #: inc/views/metaboxes/homepage-metabox.php:315
1375
  msgid "%s Tagline"
1376
  msgstr ""
1377
 
1378
+ #: inc/views/metaboxes/homepage-metabox.php:319
1379
  msgid "Add site description (tagline) to the Title on the %s?"
1380
  msgstr ""
1381
 
1382
+ #: inc/views/metaboxes/homepage-metabox.php:345
1383
  msgid "View Home Page Settings"
1384
  msgstr ""
1385
 
1386
+ #: inc/views/metaboxes/homepage-metabox.php:345
1387
  msgid "Checked in Page"
1388
  msgstr ""
1389
 
1390
+ #: inc/views/metaboxes/homepage-metabox.php:349
1391
  msgid "Home Page Robots Meta Settings"
1392
  msgstr ""
1393
 
1394
  #. translators: 1: Option, 2: Location
1395
 
1396
+ #: inc/views/metaboxes/homepage-metabox.php:358
1397
+ #: inc/views/metaboxes/homepage-metabox.php:368
1398
+ #: inc/views/metaboxes/homepage-metabox.php:378
1399
  msgid "Apply %1$s to the %2$s?"
1400
  msgstr ""
1401
 
1402
+ #: inc/views/metaboxes/homepage-metabox.php:381
1403
+ msgid "This tells search engines not to save a cached copy of this page."
1404
+ msgstr ""
1405
+
1406
+ #: inc/views/metaboxes/homepage-metabox.php:413
1407
  msgid "Note: If any of these options are unchecked, but are checked on the Home Page, they will be outputted regardless."
1408
  msgstr ""
1409
 
1410
+ #: inc/views/metaboxes/homepage-metabox.php:419
1411
  msgid "Home Page Pagination Robots Settings"
1412
  msgstr ""
1413
 
1414
+ #: inc/views/metaboxes/homepage-metabox.php:420
1415
  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."
1416
  msgstr ""
1417
 
1418
  #. translators: 1: Option, 2: Location
1419
 
1420
+ #: inc/views/metaboxes/homepage-metabox.php:428
1421
  msgid "Apply %1$s to every second or later page on the %2$s?"
1422
  msgstr ""
1423
 
1424
+ #: inc/views/metaboxes/homepage-metabox.php:438
1425
+ #: inc/views/metaboxes/social-metabox.php:115
1426
  msgid "Social Image Settings"
1427
  msgstr ""
1428
 
1429
+ #: inc/views/metaboxes/homepage-metabox.php:440
1430
  msgid "A social image can be displayed when your homepage is shared. It is a great way to grab attention."
1431
  msgstr ""
1432
 
1433
+ #: inc/views/metaboxes/homepage-metabox.php:469
1434
+ msgid "Custom Homepage Image URL"
1435
  msgstr ""
1436
 
1437
+ #: inc/views/metaboxes/homepage-metabox.php:470
1438
+ msgid "Set preferred homepage Social Image URL location."
1439
  msgstr ""
1440
 
1441
  #: inc/views/metaboxes/robots-metabox.php:13
1442
+ #: inc/views/metaboxes/title-metabox.php:194
1443
  msgid "Category"
1444
  msgstr ""
1445
 
1489
  msgstr ""
1490
 
1491
  #: inc/views/metaboxes/robots-metabox.php:37
1492
+ msgid "These options prevent caching of the selected archives and pages. If you enable this, search engines will not create a cached copy of the selected archives or pages."
1493
  msgstr ""
1494
 
1495
  #: inc/views/metaboxes/robots-metabox.php:63
1504
  msgid "Archiving"
1505
  msgstr ""
1506
 
1507
+ #: inc/views/metaboxes/robots-metabox.php:98
1508
  msgid "Open Directory Settings"
1509
  msgstr ""
1510
 
1511
+ #: inc/views/metaboxes/robots-metabox.php:100
1512
+ msgid "Sometimes, search engines use resources from certain Directories to find titles and descriptions for your content. You generally don't want them to. Turn these options on to prevent them from doing so."
1513
  msgstr ""
1514
 
1515
+ #: inc/views/metaboxes/robots-metabox.php:101
1516
+ msgid "The Yahoo! Directory may contain outdated SEO values. Therefore, it's best to leave the option checked."
1517
  msgstr ""
1518
 
1519
+ #: inc/views/metaboxes/robots-metabox.php:106
 
1520
  msgid "Apply %s to the entire site?"
1521
  msgstr ""
1522
 
1523
+ #: inc/views/metaboxes/robots-metabox.php:114
1524
  msgid "Paginated Archive Settings"
1525
  msgstr ""
1526
 
1527
+ #: inc/views/metaboxes/robots-metabox.php:118
1528
+ msgid "Indexing the second or later page of any archive might cause duplication errors. Search engines look down upon them; therefore, it's recommended to disable indexing of those pages."
1529
  msgstr ""
1530
 
1531
+ #: inc/views/metaboxes/robots-metabox.php:129
1532
  msgid "Apply %s to every second or later archive page?"
1533
  msgstr ""
1534
 
1535
+ #: inc/views/metaboxes/robots-metabox.php:142
1536
  msgid "%s Robots Settings"
1537
  msgstr ""
1538
 
1539
  #. translators: 1: Option, 2: Post Type
1540
 
1541
+ #: inc/views/metaboxes/robots-metabox.php:151
1542
  msgid "Apply %1$s to %2$s?"
1543
  msgstr ""
1544
 
1545
  #. translators: 1: Option, 2: Post Type
1546
 
1547
+ #: inc/views/metaboxes/robots-metabox.php:155
1548
  msgid "Apply %1$s to %2$s Archives?"
1549
  msgstr ""
1550
 
1551
+ #: inc/views/metaboxes/schema-metabox.php:11
1552
  msgid "Schema.org Output Settings"
1553
  msgstr ""
1554
 
1555
+ #: inc/views/metaboxes/schema-metabox.php:15
1556
  msgid "Another Schema.org plugin has been detected."
1557
  msgstr ""
1558
 
1559
+ #: inc/views/metaboxes/schema-metabox.php:17
1560
  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."
1561
  msgstr ""
1562
 
1563
+ #: inc/views/metaboxes/schema-metabox.php:18
1564
+ 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."
1565
  msgstr ""
1566
 
1567
+ #: inc/views/metaboxes/schema-metabox.php:19
1568
  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."
1569
  msgstr ""
1570
 
1571
+ #: inc/views/metaboxes/schema-metabox.php:41
1572
  msgid "Structure"
1573
  msgstr ""
1574
 
1575
+ #: inc/views/metaboxes/schema-metabox.php:46
1576
  msgid "Presence"
1577
  msgstr ""
1578
 
1579
+ #: inc/views/metaboxes/schema-metabox.php:71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1580
  msgid "Site Structure Options"
1581
  msgstr ""
1582
 
1583
+ #: inc/views/metaboxes/schema-metabox.php:73
1584
+ msgid "The site structure Schema.org output allows search engines to gain knowledge on how your website is built."
1585
  msgstr ""
1586
 
1587
+ #: inc/views/metaboxes/schema-metabox.php:74
1588
+ msgid "For example, search engines display your pages' URLs when listed in the Search Results. These options allow you to enhance those URLs output."
1589
  msgstr ""
1590
 
1591
+ #: inc/views/metaboxes/schema-metabox.php:77
1592
  msgid "Breadcrumbs"
1593
  msgstr ""
1594
 
1595
+ #: inc/views/metaboxes/schema-metabox.php:79
1596
+ msgid "Breadcrumb trails indicate page positions in the site's hierarchy. Using the following option will show the hierarchy within the Search Results when available."
1597
  msgstr ""
1598
 
1599
+ #: inc/views/metaboxes/schema-metabox.php:81
1600
+ #: inc/views/metaboxes/schema-metabox.php:95
1601
+ #: inc/views/metaboxes/schema-metabox.php:110
1602
+ #: inc/views/metaboxes/schema-metabox.php:153
1603
+ msgid "Learn how this data is used."
1604
  msgstr ""
1605
 
1606
+ #: inc/views/metaboxes/schema-metabox.php:84
1607
  msgid "Enable Breadcrumbs?"
1608
  msgstr ""
1609
 
1610
+ #: inc/views/metaboxes/schema-metabox.php:91
1611
+ msgctxt "Product name"
1612
+ msgid "Sitelinks Searchbox"
1613
  msgstr ""
1614
 
1615
+ #: inc/views/metaboxes/schema-metabox.php:93
1616
+ msgid "When Search users search for your brand name, the following option allows them to search through this website directly from the Search Results."
1617
  msgstr ""
1618
 
1619
+ #: inc/views/metaboxes/schema-metabox.php:98
1620
+ msgctxt "Sitelinks Searchbox is a Product name"
1621
+ msgid "Enable Sitelinks Searchbox?"
1622
  msgstr ""
1623
 
1624
+ #: inc/views/metaboxes/schema-metabox.php:106
1625
+ msgid "Authorized Presence Options"
1626
  msgstr ""
1627
 
1628
+ #: inc/views/metaboxes/schema-metabox.php:108
1629
+ msgid "The authorized presence Schema.org output helps Search Engine users find ways to interact with this website."
1630
  msgstr ""
1631
 
1632
+ #: inc/views/metaboxes/schema-metabox.php:114
1633
+ msgid "Output Authorized Presence?"
1634
  msgstr ""
1635
 
1636
+ #: inc/views/metaboxes/schema-metabox.php:121
1637
+ msgid "About this website"
 
 
 
 
 
1638
  msgstr ""
1639
 
1640
+ #: inc/views/metaboxes/schema-metabox.php:123
1641
+ msgctxt "...Organization or Person."
1642
+ msgid "This website represents:"
1643
  msgstr ""
1644
 
1645
+ #: inc/views/metaboxes/schema-metabox.php:129
1646
+ msgid "An Organization"
 
1647
  msgstr ""
1648
 
1649
+ #: inc/views/metaboxes/schema-metabox.php:130
1650
+ msgid "A Person"
1651
  msgstr ""
1652
 
1653
+ #: inc/views/metaboxes/schema-metabox.php:142
1654
+ msgid "The organization or personal name"
1655
  msgstr ""
1656
 
1657
+ #: inc/views/metaboxes/schema-metabox.php:150
1658
+ msgid "Website logo"
1659
  msgstr ""
1660
 
1661
+ #: inc/views/metaboxes/schema-metabox.php:152
1662
+ msgid "These options are used when this site represents an organization. When no logo is outputted, search engine will look elsewhere."
1663
  msgstr ""
1664
 
1665
+ #: inc/views/metaboxes/schema-metabox.php:156
1666
+ msgid "Enable logo?"
1667
  msgstr ""
1668
 
1669
+ #: inc/views/metaboxes/schema-metabox.php:165
1670
+ msgid "Logo URL"
1671
  msgstr ""
1672
 
1673
+ #: inc/views/metaboxes/schema-metabox.php:166
1674
+ msgid "The logo image must be square."
1675
  msgstr ""
1676
 
1677
+ #: inc/views/metaboxes/schema-metabox.php:170
1678
+ msgid "Setting a logo requires JavaScript."
1679
  msgstr ""
1680
 
1681
+ #: inc/views/metaboxes/schema-metabox.php:182
1682
+ msgid "Connected Social Pages"
1683
  msgstr ""
1684
 
1685
+ #: inc/views/metaboxes/schema-metabox.php:184
1686
  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."
1687
  msgstr ""
1688
 
1689
+ #: inc/views/metaboxes/schema-metabox.php:185
1690
  msgid "Add the link that leads directly to the social page of this website."
1691
  msgstr ""
1692
 
1693
+ #: inc/views/metaboxes/schema-metabox.php:187
1694
  msgctxt "No spaces. E.g. https://facebook.com/RelatedProfile"
1695
  msgid "RelatedProfile"
1696
  msgstr ""
1697
 
1698
+ #: inc/views/metaboxes/schema-metabox.php:188
1699
  msgctxt "Social Profile"
1700
  msgid "Profile"
1701
  msgstr ""
1702
 
1703
+ #: inc/views/metaboxes/schema-metabox.php:253
1704
  msgid "Blog"
1705
  msgstr ""
1706
 
1707
+ #: inc/views/metaboxes/schema-metabox.php:267
1708
+ msgid "View your profile."
1709
  msgstr ""
1710
 
1711
+ #: inc/views/metaboxes/sitemaps-metabox.php:40
1712
  msgctxt "Ping or notify Search Engine"
1713
  msgid "Ping"
1714
  msgstr ""
1715
 
1716
+ #: inc/views/metaboxes/sitemaps-metabox.php:45
1717
  msgid "Style"
1718
  msgstr ""
1719
 
1720
+ #: inc/views/metaboxes/sitemaps-metabox.php:83
1721
  msgid "Sitemap Integration Settings"
1722
  msgstr ""
1723
 
1724
+ #: inc/views/metaboxes/sitemaps-metabox.php:87
1725
  msgid "Another active sitemap plugin has been detected. This means that the sitemap functionality has been replaced."
1726
  msgstr ""
1727
 
1728
+ #: inc/views/metaboxes/sitemaps-metabox.php:89
1729
  msgid "A sitemap has been detected in the root folder of your website. This means that the sitemap functionality has no effect."
1730
  msgstr ""
1731
 
1732
+ #: inc/views/metaboxes/sitemaps-metabox.php:91
1733
+ 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."
1734
  msgstr ""
1735
 
1736
+ #: inc/views/metaboxes/sitemaps-metabox.php:92
1737
  msgid "The optional metadata include the post and page modified time and a page priority indication, which is automated."
1738
  msgstr ""
1739
 
1740
+ #: inc/views/metaboxes/sitemaps-metabox.php:97
1741
  msgid "Sitemap Output"
1742
  msgstr ""
1743
 
1744
+ #: inc/views/metaboxes/sitemaps-metabox.php:104
1745
  msgid "Output Sitemap?"
1746
  msgstr ""
1747
 
1748
+ #: inc/views/metaboxes/sitemaps-metabox.php:112
1749
  msgid "View sitemap"
1750
  msgstr ""
1751
 
1752
+ #: inc/views/metaboxes/sitemaps-metabox.php:112
1753
+ #: inc/views/metaboxes/sitemaps-metabox.php:129
1754
+ #: inc/views/metaboxes/sitemaps-metabox.php:171
1755
  msgctxt "The sitemap can be found %s."
1756
  msgid "here"
1757
  msgstr ""
1758
 
1759
+ #: inc/views/metaboxes/sitemaps-metabox.php:113
1760
  msgctxt "%s = here"
1761
  msgid "The sitemap can be found %s."
1762
  msgstr ""
1763
 
1764
+ #: inc/views/metaboxes/sitemaps-metabox.php:121
1765
  msgid "Robots.txt Settings"
1766
  msgstr ""
1767
 
1768
+ #: inc/views/metaboxes/sitemaps-metabox.php:125
1769
  msgid "A robots.txt file has been detected in the root folder of your website; therefore no settings are able to alter its output."
1770
  msgstr ""
1771
 
1772
+ #: inc/views/metaboxes/sitemaps-metabox.php:129
1773
  msgid "Permalink Settings"
1774
  msgstr ""
1775
 
1776
+ #: inc/views/metaboxes/sitemaps-metabox.php:132
1777
  msgid "You're using the plain permalink structure."
1778
  msgstr ""
1779
 
1780
+ #: inc/views/metaboxes/sitemaps-metabox.php:134
1781
  msgid "This means the robots.txt file can't be outputted through the WordPress rewrite rules."
1782
  msgstr ""
1783
 
1784
+ #: inc/views/metaboxes/sitemaps-metabox.php:138
1785
  msgctxt "%s = here"
1786
  msgid "Change your Permalink Settings %s (Recommended: \"Post name\")."
1787
  msgstr ""
1788
 
1789
+ #: inc/views/metaboxes/sitemaps-metabox.php:142
1790
+ 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."
1791
  msgstr ""
1792
 
1793
+ #: inc/views/metaboxes/sitemaps-metabox.php:143
1794
+ msgid "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."
1795
  msgstr ""
1796
 
1797
+ #: inc/views/metaboxes/sitemaps-metabox.php:148
1798
  msgid "Add sitemap location in robots.txt"
1799
  msgstr ""
1800
 
1801
+ #: inc/views/metaboxes/sitemaps-metabox.php:155
1802
  msgid "Add sitemap location in robots?"
1803
  msgstr ""
1804
 
1805
+ #: inc/views/metaboxes/sitemaps-metabox.php:155
1806
+ msgid "This only has effect if the sitemap is active."
1807
  msgstr ""
1808
 
1809
+ #: inc/views/metaboxes/sitemaps-metabox.php:162
1810
  msgid "No robots.txt file can be generated on subdirectory installations."
1811
  msgstr ""
1812
 
1813
+ #: inc/views/metaboxes/sitemaps-metabox.php:165
1814
  msgid "Another robots.txt sitemap location addition has been detected."
1815
  msgstr ""
1816
 
1817
+ #: inc/views/metaboxes/sitemaps-metabox.php:171
1818
  msgid "View robots.txt"
1819
  msgstr ""
1820
 
1821
+ #: inc/views/metaboxes/sitemaps-metabox.php:173
1822
  msgctxt "%s = here"
1823
  msgid "The robots.txt file can be found %s."
1824
  msgstr ""
1825
 
1826
+ #: inc/views/metaboxes/sitemaps-metabox.php:179
1827
  msgid "Timestamps Settings"
1828
  msgstr ""
1829
 
1830
+ #: inc/views/metaboxes/sitemaps-metabox.php:181
1831
+ msgid "The modified time suggests to search engines where to look for content changes. It has no impact on the SEO value unless you drastically change pages or posts. It then depends on how well your content is constructed."
1832
  msgstr ""
1833
 
1834
+ #: inc/views/metaboxes/sitemaps-metabox.php:185
 
 
 
 
1835
  msgid "Output Modified Date"
1836
  msgstr ""
1837
 
1838
+ #: inc/views/metaboxes/sitemaps-metabox.php:191
1839
  msgid "Add %s to the sitemap?"
1840
  msgstr ""
1841
 
1842
+ #: inc/views/metaboxes/sitemaps-metabox.php:200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1843
  msgid "Ping Settings"
1844
  msgstr ""
1845
 
1846
+ #: inc/views/metaboxes/sitemaps-metabox.php:202
1847
+ msgid "Notifying search engines of a sitemap change is helpful to get your content indexed as soon as possible."
1848
  msgstr ""
1849
 
1850
+ #: inc/views/metaboxes/sitemaps-metabox.php:203
1851
  msgid "By default this will happen at most once an hour."
1852
  msgstr ""
1853
 
1854
+ #: inc/views/metaboxes/sitemaps-metabox.php:208
1855
  msgid "Notify Search Engines"
1856
  msgstr ""
1857
 
1858
+ #: inc/views/metaboxes/sitemaps-metabox.php:220
1859
  msgid "Notify %s about sitemap changes?"
1860
  msgstr ""
1861
 
1862
+ #: inc/views/metaboxes/sitemaps-metabox.php:230
1863
  msgid "Sitemap Styling Settings"
1864
  msgstr ""
1865
 
1866
+ #: inc/views/metaboxes/sitemaps-metabox.php:233
1867
  msgid "You can style the sitemap to give it a more personal look. Styling the sitemap has no SEO value whatsoever."
1868
  msgstr ""
1869
 
1870
+ #: inc/views/metaboxes/sitemaps-metabox.php:238
1871
  msgid "Enable styling"
1872
  msgstr ""
1873
 
1874
+ #: inc/views/metaboxes/sitemaps-metabox.php:245
1875
  msgid "Style Sitemap?"
1876
  msgstr ""
1877
 
1878
+ #: inc/views/metaboxes/sitemaps-metabox.php:245
1879
+ msgid "This makes the sitemap more readable for humans."
1880
  msgstr ""
1881
 
1882
+ #: inc/views/metaboxes/sitemaps-metabox.php:254
1883
  msgid "Style configuration"
1884
  msgstr ""
1885
 
1886
+ #: inc/views/metaboxes/sitemaps-metabox.php:262
1887
  msgid "Add site logo?"
1888
  msgstr ""
1889
 
1890
+ #: inc/views/metaboxes/sitemaps-metabox.php:262
1891
+ msgid "The logo is set in Customizer."
1892
  msgstr ""
1893
 
1894
+ #: inc/views/metaboxes/sitemaps-metabox.php:275
1895
  msgid "Sitemap header background color"
1896
  msgstr ""
1897
 
1898
+ #: inc/views/metaboxes/sitemaps-metabox.php:284
1899
  msgid "Sitemap title and lines color"
1900
  msgstr ""
1901
 
1903
  msgid "Post Dates"
1904
  msgstr ""
1905
 
1906
+ #: inc/views/metaboxes/social-metabox.php:65
1907
  msgid "Social Meta Tags Settings"
1908
  msgstr ""
1909
 
1910
+ #: inc/views/metaboxes/social-metabox.php:67
1911
  msgid "Output various meta tags for social site integration, among other 3rd party services."
1912
  msgstr ""
1913
 
1914
+ #: inc/views/metaboxes/social-metabox.php:77
1915
  msgid "Output Open Graph meta tags?"
1916
  msgstr ""
1917
 
1918
+ #: inc/views/metaboxes/social-metabox.php:78
1919
  msgid "Facebook, Twitter, Pinterest and many other social sites make use of these tags."
1920
  msgstr ""
1921
 
1922
+ #: inc/views/metaboxes/social-metabox.php:85
1923
  msgid "Note: Another Open Graph plugin has been detected."
1924
  msgstr ""
1925
 
1926
+ #: inc/views/metaboxes/social-metabox.php:91
1927
  msgid "Output Facebook meta tags?"
1928
  msgstr ""
1929
 
1930
+ #: inc/views/metaboxes/social-metabox.php:92
1931
+ #: inc/views/metaboxes/social-metabox.php:103
1932
  msgid "Output various tags targetted at %s."
1933
  msgstr ""
1934
 
1935
+ #: inc/views/metaboxes/social-metabox.php:102
1936
  msgid "Output Twitter meta tags?"
1937
  msgstr ""
1938
 
1939
+ #: inc/views/metaboxes/social-metabox.php:110
1940
  msgid "Note: Another Twitter Card plugin has been detected."
1941
  msgstr ""
1942
 
1943
+ #: inc/views/metaboxes/social-metabox.php:117
1944
  msgid "A social image can be displayed when your website is shared. It is a great way to grab attention."
1945
  msgstr ""
1946
 
1947
+ #: inc/views/metaboxes/social-metabox.php:124
1948
  msgid "Social Image Fallback URL"
1949
  msgstr ""
1950
 
1951
+ #: inc/views/metaboxes/social-metabox.php:125
1952
+ msgid "Set preferred Social Image fallback URL location."
1953
  msgstr ""
1954
 
1955
+ #: inc/views/metaboxes/social-metabox.php:149
1956
  msgid "Site Shortlink Settings"
1957
  msgstr ""
1958
 
1959
+ #: inc/views/metaboxes/social-metabox.php:151
1960
  msgid "The shortlink tag can be manually used for microblogging services like Twitter, but it has no SEO value whatsoever."
1961
  msgstr ""
1962
 
1963
+ #: inc/views/metaboxes/social-metabox.php:157
1964
  msgid "Output shortlink tag?"
1965
  msgstr ""
1966
 
1967
+ #: inc/views/metaboxes/social-metabox.php:170
 
 
 
 
 
1968
  msgctxt "Example Verified Facebook Business URL"
1969
  msgid "https://www.facebook.com/YourVerifiedBusinessProfile"
1970
  msgstr ""
1971
 
1972
+ #: inc/views/metaboxes/social-metabox.php:176
1973
  msgid "Default Facebook Integration Settings"
1974
  msgstr ""
1975
 
1978
  msgstr ""
1979
 
1980
  #: inc/views/metaboxes/social-metabox.php:179
1981
+ msgid "When these options are filled in, Facebook might link the Facebook profile to be followed and liked when your post or page is shared."
1982
  msgstr ""
1983
 
1984
+ #: inc/views/metaboxes/social-metabox.php:185
1985
+ msgid "Facebook App ID"
1986
  msgstr ""
1987
 
1988
+ #: inc/views/metaboxes/social-metabox.php:189
1989
+ msgid "Get Facebook App ID."
1990
  msgstr ""
1991
 
1992
+ #: inc/views/metaboxes/social-metabox.php:200
1993
  msgid "Article Publisher Facebook URL"
1994
  msgstr ""
1995
 
1996
+ #: inc/views/metaboxes/social-metabox.php:204
1997
+ msgid "To use this, you need to be a verified business."
1998
  msgstr ""
1999
 
2000
+ #: inc/views/metaboxes/social-metabox.php:215
2001
+ msgid "Article Author Facebook Fallback URL"
2002
  msgstr ""
2003
 
2004
+ #: inc/views/metaboxes/social-metabox.php:219
2005
+ msgid "Your Facebook Profile."
2006
  msgstr ""
2007
 
2008
+ #: inc/views/metaboxes/social-metabox.php:224
2009
+ #: inc/views/metaboxes/social-metabox.php:309
2010
+ msgid "Authors can override this option on their profile page."
2011
  msgstr ""
2012
 
2013
+ #: inc/views/metaboxes/social-metabox.php:233
2014
  msgctxt "Twitter @username"
2015
+ msgid "@your-site-username"
2016
  msgstr ""
2017
 
2018
+ #: inc/views/metaboxes/social-metabox.php:241
2019
  msgid "Default Twitter Integration Settings"
2020
  msgstr ""
2021
 
2022
+ #: inc/views/metaboxes/social-metabox.php:243
2023
  msgid "Twitter post sharing works mostly through Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options."
2024
  msgstr ""
2025
 
2026
+ #: inc/views/metaboxes/social-metabox.php:249
2027
  msgid "Twitter Card Type"
2028
  msgstr ""
2029
 
2030
  #. translators: %s = "summary" Twitter card type
2031
 
2032
+ #: inc/views/metaboxes/social-metabox.php:254
2033
  msgid "What kind of Twitter card would you like to use? It will default to %s if no image is found."
2034
  msgstr ""
2035
 
2036
+ #: inc/views/metaboxes/social-metabox.php:268
2037
  msgid "Example"
2038
  msgstr ""
2039
 
2040
+ #: inc/views/metaboxes/social-metabox.php:280
2041
+ msgid "When the following options are filled in, Twitter might link your Twitter Site or Author Profile when your post or page is shared."
2042
  msgstr ""
2043
 
2044
+ #: inc/views/metaboxes/social-metabox.php:285
2045
+ msgid "Website Twitter Profile"
2046
  msgstr ""
2047
 
2048
+ #: inc/views/metaboxes/social-metabox.php:289
2049
+ #: inc/views/metaboxes/social-metabox.php:304
2050
+ msgid "Find your @username."
2051
  msgstr ""
2052
 
2053
+ #: inc/views/metaboxes/social-metabox.php:300
2054
+ msgid "Twitter Author Fallback Profile"
2055
  msgstr ""
2056
 
2057
+ #: inc/views/metaboxes/social-metabox.php:317
2058
  msgid "Posts"
2059
  msgstr ""
2060
 
2061
+ #: inc/views/metaboxes/social-metabox.php:321
2062
  msgid "Post Date Settings"
2063
  msgstr ""
2064
 
2065
+ #: inc/views/metaboxes/social-metabox.php:323
2066
+ msgid "Some social sites output the published date and modified date in the sharing snippet."
 
 
 
 
2067
  msgstr ""
2068
 
2069
  #. translators: 1: Option, 2: Post Type
2070
 
2071
+ #: inc/views/metaboxes/social-metabox.php:326
2072
+ #: inc/views/metaboxes/social-metabox.php:330
 
 
 
 
2073
  msgid "Add %1$s to %2$s?"
2074
  msgstr ""
2075
 
 
 
 
 
2076
  #: inc/views/metaboxes/title-metabox.php:17
2077
  msgid "Example Post Title"
2078
  msgstr ""
2097
  msgid "Recommended"
2098
  msgstr ""
2099
 
2100
+ #: inc/views/metaboxes/title-metabox.php:110
2101
+ msgid "Title Separator"
2102
  msgstr ""
2103
 
2104
+ #: inc/views/metaboxes/title-metabox.php:111
2105
  msgid "If the title consists of two parts (original title and optional addition), then the separator will go in-between them."
2106
  msgstr ""
2107
 
2108
+ #: inc/views/metaboxes/title-metabox.php:130
2109
  msgid "The Home Page has a specific option."
2110
  msgstr ""
2111
 
2112
+ #: inc/views/metaboxes/title-metabox.php:163
2113
  msgid "Remove Blogname from Title"
2114
  msgstr ""
2115
 
2116
+ #: inc/views/metaboxes/title-metabox.php:167
2117
+ msgid "This might decouple your posts and pages from the rest of the website."
2118
  msgstr ""
2119
 
2120
+ #: inc/views/metaboxes/title-metabox.php:175
2121
  msgid "Remove Blogname from title?"
2122
  msgstr ""
2123
 
2124
+ #: inc/views/metaboxes/title-metabox.php:184
2125
  msgid "Only use this option if you are aware of its SEO effects."
2126
  msgstr ""
2127
 
2128
+ #: inc/views/metaboxes/title-metabox.php:210
2129
  msgid "Example Category"
2130
  msgstr ""
2131
 
2132
+ #: inc/views/metaboxes/title-metabox.php:228
2133
  msgid "Title prefix options"
2134
  msgstr ""
2135
 
2136
+ #: inc/views/metaboxes/title-metabox.php:229
2137
  msgid "On archives a descriptive prefix may be added to the title."
2138
  msgstr ""
2139
 
2140
+ #: inc/views/metaboxes/title-metabox.php:232
2141
  msgid "Example Automated Archive Title Output"
2142
  msgstr ""
2143
 
2144
+ #: inc/views/metaboxes/title-metabox.php:240
2145
  msgid "Remove Archive Title Prefixes"
2146
  msgstr ""
2147
 
2148
+ #: inc/views/metaboxes/title-metabox.php:244
2149
  msgid "Remove prefixes from title?"
2150
  msgstr ""
2151
 
2152
+ #: inc/views/metaboxes/title-metabox.php:248
2153
+ msgid "The prefix helps visitors and search engines determine what kind of page they're visiting."
2154
  msgstr ""
2155
 
2156
  #: inc/views/metaboxes/webmaster-metabox.php:18
2169
  msgid "Google Webmaster Verification Code"
2170
  msgstr ""
2171
 
2172
+ #: inc/views/metaboxes/webmaster-metabox.php:31
2173
+ msgid "Get the Google verification code."
2174
  msgstr ""
2175
 
2176
+ #: inc/views/metaboxes/webmaster-metabox.php:42
2177
  msgid "Bing Webmaster Verification Code"
2178
  msgstr ""
2179
 
2180
+ #: inc/views/metaboxes/webmaster-metabox.php:46
2181
+ msgid "Get the Bing verification code."
2182
  msgstr ""
2183
 
2184
+ #: inc/views/metaboxes/webmaster-metabox.php:57
2185
  msgid "Yandex Webmaster Verification Code"
2186
  msgstr ""
2187
 
2188
+ #: inc/views/metaboxes/webmaster-metabox.php:61
2189
+ msgid "Get the Yandex verification code."
2190
  msgstr ""
2191
 
2192
+ #: inc/views/metaboxes/webmaster-metabox.php:72
2193
  msgid "Pinterest Analytics Verification Code"
2194
  msgstr ""
2195
 
2196
+ #: inc/views/metaboxes/webmaster-metabox.php:76
2197
+ msgid "Get the Pinterest verification code."
2198
+ msgstr ""
2199
+
2200
+ #: inc/views/profile/author.php:9
2201
+ msgid "Authorial Info"
2202
  msgstr ""
2203
 
2204
  #: inc/views/sitemap/xsl-stylesheet.php:8
2235
  #: inc/views/sitemap/xsl-stylesheet.php:236
2236
  msgid "Generated by [The SEO Framework](https://wordpress.org/plugins/autodescription/)"
2237
  msgstr ""
2238
+
2239
+ #. translators: %s = term name
2240
+
2241
+ #: inc/views/templates/inpost/primary-term-selector.php:22
2242
+ msgid "You can set the primary %s through the buttons below."
2243
+ msgstr ""
2244
  #. Plugin Name of the plugin/theme
2245
  msgid "The SEO Framework"
2246
  msgstr ""
lib/css/tsf-rtl.css CHANGED
@@ -1,3 +1,8 @@
 
 
 
 
 
1
  /**
2
  * Dismissible Notices.
3
  */
@@ -67,7 +72,7 @@ a.tsf-dismiss:hover {
67
  }
68
 
69
  /**
70
- * WooCommerce fix
71
  */
72
  table.wp-list-table .column-name {
73
  width: 15%;
@@ -84,9 +89,13 @@ th.column-tsf-seo-bar-wrap ~ th {
84
  width: 8%;
85
  }
86
 
87
- .tsf-seo-bar a {
88
  text-decoration: none;
89
  font-size: 13px;
 
 
 
 
90
  }
91
 
92
  #tsf-title-wrap {
@@ -108,7 +117,8 @@ th.column-tsf-seo-bar-wrap ~ th {
108
  white-space: pre;
109
  }
110
 
111
- #tsf-title-placeholder {
 
112
  position: absolute;
113
  color: #777;
114
  -webkit-user-select: none;
@@ -126,8 +136,13 @@ th.column-tsf-seo-bar-wrap ~ th {
126
 
127
  /* START Character Counters */
128
 
 
 
 
 
129
  .tsf-counter {
130
- font-weight: 600;
 
131
  cursor: pointer;
132
  -webkit-user-select: none;
133
  -moz-user-select: none;
@@ -136,19 +151,19 @@ th.column-tsf-seo-bar-wrap ~ th {
136
  will-change: contents;
137
  }
138
 
139
- span.tsf-count-bad {
140
  color: #dd3811;
141
  }
142
 
143
- span.tsf-count-okay {
144
  color: #ffa700;
145
  }
146
 
147
- span.tsf-count-good {
148
  color: #0cc34b;
149
  }
150
 
151
- span.tsf-counter-one {
152
  color: #fff;
153
  border-radius: 4em;
154
  padding: 0 0.5em;
@@ -157,18 +172,101 @@ span.tsf-counter-one {
157
  text-align: center;
158
  vertical-align: baseline;
159
  }
160
- span.tsf-counter-one.tsf-count-bad {
161
  background-color: #dd3811;
162
  }
163
- span.tsf-counter-one.tsf-count-okay {
164
  background-color: #ffa700;
165
  }
166
- span.tsf-counter-one.tsf-count-good {
167
  background-color: #0cc34b;
168
  }
169
 
170
  /* END Character Counters */
171
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  #tsf-seo-bar-wrap {
173
  width: 18%;
174
  }
@@ -178,7 +276,7 @@ th:last-of-type#tsf-seo-bar-wrap {
178
  width: 160px;
179
  }
180
 
181
- span.tsf-seo-bar {
182
  display: block;
183
  width: 95%;
184
  max-width: 220px;
@@ -187,11 +285,11 @@ span.tsf-seo-bar {
187
  text-shadow: 0 0 3px rgba(0,0,0,0.3);
188
  }
189
 
190
- span.tsf-seo-bar.tsf-100 {
191
  width: 100%;
192
  }
193
 
194
- span.tsf-seo-bar-inner-wrap {
195
  display: table;
196
  width: 100%;
197
  border-radius: 0;
@@ -199,20 +297,18 @@ span.tsf-seo-bar-inner-wrap {
199
  border-collapse: separate;
200
  border-spacing: 0;
201
  vertical-align: middle;
202
- position: relative;
203
  }
204
 
205
- span.tsf-seo-bar-section-wrap {
206
  display: table-cell;
207
  border-collapse: collapse;
208
  }
209
 
210
- .tsf-seo-bar-inner-wrap a {
211
  display: table;
212
  width: 100%;
213
  color: #fff;
214
  text-align: center;
215
- cursor: help;
216
  height: 100%;
217
  min-width: 12px;
218
  vertical-align: top;
@@ -220,17 +316,21 @@ span.tsf-seo-bar-section-wrap {
220
  box-shadow: 2px 0px 0px -1px rgba(0,0,0,0.1) inset, -2px 0px 0px -1px rgba(0,0,0,0.1) inset;
221
  }
222
 
223
- span.tsf-seo-bar.pill,
224
- span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap {
 
 
 
 
225
  border-radius: 30px;
226
  }
227
 
228
- span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a {
229
  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);
230
  }
231
 
232
- .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type,
233
- .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type a {
234
  border-top-left-radius: 30px;
235
  border-bottom-left-radius: 30px;
236
  }
@@ -301,40 +401,140 @@ span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a {
301
  background-color: #007bd2;
302
  }
303
 
304
- span.tsf-seo-bar .tsf-explanation-desc {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  position: absolute;
306
- width: auto;
307
- min-width: 90%;
308
- max-width: 220px;
309
- font-weight: 600;
310
- background: #007bd2;
311
- padding: 8px 12px;
312
- color: #fdfdfd;
313
- border-radius: 0px;
314
- z-index: 900142;
315
- box-shadow: 0px 0px 2px rgba(0,0,0,0.6);
316
  left: 0;
317
- right: 0;
318
- text-align: left;
319
  pointer-events: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  }
321
 
322
- span.tsf-seo-bar .tsf-explanation-desc span {
323
  text-decoration: underline;
324
  }
325
 
326
- span.tsf-seo-bar .tsf-explanation-desc div {
327
- width: 0;
328
- height: 0;
329
- border-left: 12px solid transparent;
330
- border-right: 12px solid transparent;
331
- border-top: 12px solid #007bd2;
 
 
332
  position: absolute;
333
  bottom: -8px;
334
  z-index: 9999999;
335
  left: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  }
337
 
 
 
338
  /* Mobile support */
339
  /* Needs more refining.... e.g. iPhone 6 = good, iPhone 6+ = offscreen */
340
  .tsf-seo-bar-wrap.column-tsf-seo-bar-temp {
@@ -356,14 +556,14 @@ span.tsf-seo-bar .tsf-explanation-desc div {
356
  padding-bottom: 20px;
357
  }
358
 
359
- .tsf-metaboxes .tsf-top-wrap {
360
  width: 100%;
361
  display: inline-block;
362
  vertical-align: top;
363
  }
364
 
365
- .tsf-metaboxes .tsf-top-wrap > h1,
366
- .tsf-metaboxes .tsf-top-wrap > h2 {
367
  float: left;
368
  }
369
 
@@ -371,11 +571,11 @@ span.tsf-seo-bar .tsf-explanation-desc div {
371
  clear: both;
372
  }
373
 
374
- .tsf-metaboxes .tsf-top-buttons {
375
  float: left;
376
  }
377
 
378
- .tsf-metaboxes .tsf-bottom-buttons {
379
  text-align: left;
380
  }
381
 
@@ -388,16 +588,16 @@ span.tsf-seo-bar .tsf-explanation-desc div {
388
  clear: both;
389
  }
390
 
391
- .tsf-metaboxes #tsf-title-separator,
392
- .tsf-metaboxes #tsf-description-separator {
393
  display: table;
394
  width: 100%;
395
  border-collapse: collapse;
396
  border-spacing: 0;
397
  }
398
 
399
- .tsf-metaboxes #tsf-title-separator input,
400
- .tsf-metaboxes #tsf-description-separator input {
401
  display: none;
402
  float: left;
403
  width: 0;
@@ -405,8 +605,8 @@ span.tsf-seo-bar .tsf-explanation-desc div {
405
  opacity: 0;
406
  }
407
 
408
- .tsf-metaboxes #tsf-title-separator label,
409
- .tsf-metaboxes #tsf-description-separator label {
410
  display: inline-block;
411
  width: auto;
412
  min-width: 28px;
@@ -423,48 +623,48 @@ span.tsf-seo-bar .tsf-explanation-desc div {
423
  font-size: 16px;
424
  }
425
 
426
- .tsf-metaboxes #tsf-title-separator label.tsf-recommended,
427
- .tsf-metaboxes #tsf-description-separator label.tsf-recommended {
428
  border: 1px solid #0cc34b;
429
  box-shadow: -1px -1px 1px #0cc34b inset;
430
  }
431
 
432
- .tsf-metaboxes #tsf-title-separator input:hover + label,
433
- .tsf-metaboxes #tsf-title-separator label:hover,
434
- .tsf-metaboxes #tsf-description-separator input:hover + label,
435
- .tsf-metaboxes #tsf-description-separator label:hover {
436
  box-shadow: 1px 1px 1px #aaa inset;
437
  background-color: #fff;
438
  }
439
 
440
- .tsf-metaboxes #tsf-title-separator input:checked + label,
441
- .tsf-metaboxes #tsf-description-separator input:checked + label {
442
  box-shadow: 1px 1px 1px #333 inset;
443
  background-color: #fff;
444
  }
445
 
446
- .tsf-metaboxes #tsf-title-location,
447
- .tsf-metaboxes #tsf-home-title-location {
448
  display: block;
449
  }
450
 
451
- .tsf-metaboxes #tsf-title-location label span,
452
- .tsf-metaboxes #tsf-home-title-location label span,
453
- .tsf-metaboxes #tsf-twitter-cards label span {
454
  display: inline-block;
455
  min-width: 60px;
456
  vertical-align: baseline;
457
  }
458
 
459
- .tsf-metaboxes #tsf-twitter-cards label span {
460
  min-width: 150px;
461
  }
462
 
463
- .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-title-js,
464
- .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,
465
- .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,
466
- .tsf-metaboxes #tsf-title-location label .tsf-sep-js,
467
- .tsf-metaboxes #tsf-home-title-location label .tsf-sep-js {
468
  display: inline;
469
  min-width: 0;
470
  white-space: pre;
@@ -473,8 +673,8 @@ span.tsf-seo-bar .tsf-explanation-desc div {
473
  /**
474
  * Start Tabs.
475
  */
476
- .tsf-metaboxes .tsf-tab-no-js,
477
- .tsf-metaboxes .tsf-nav-tab-wrapper {
478
  position: relative;
479
  clear: both;
480
  width: 100%;
@@ -485,7 +685,7 @@ span.tsf-seo-bar .tsf-explanation-desc div {
485
  margin: -4px -12px;
486
  }
487
 
488
- .tsf-metaboxes .tsf-nav-tab {
489
  float: right;
490
  border: 1px solid #ccc;
491
  margin-right: .5em;
@@ -498,13 +698,13 @@ span.tsf-seo-bar .tsf-explanation-desc div {
498
  font-weight: 600;
499
  }
500
 
501
- .tsf-metaboxes .tsf-dashicons-tabs {
502
  font-size: initial;
503
  display: inline;
504
  vertical-align: text-bottom;
505
  }
506
 
507
- .tsf-metaboxes .tsf-tabs-radio {
508
  display: none;
509
  width: 0;
510
  height: 0;
@@ -512,26 +712,26 @@ span.tsf-seo-bar .tsf-explanation-desc div {
512
  left: -9001px;
513
  }
514
 
515
- .tsf-metaboxes .tsf-tabs-radio:checked + label,
516
- .tsf-metaboxes .tsf-active-tab {
517
  background-color: inherit;
518
  border-bottom-color: #fff;
519
  color: #000;
520
  }
521
 
522
- .tsf-metaboxes .tsf-tabs-content {
523
  margin: 1.33em auto 0;
524
  }
525
 
526
- .tsf-metaboxes .tsf-content-no-js {
527
  margin: 1.33em auto;
528
  }
529
 
530
- body.js .tsf-metaboxes .tsf-tabs-content {
531
  display: none;
532
  }
533
 
534
- body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content {
535
  display: block;
536
  }
537
 
@@ -634,12 +834,6 @@ body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content {
634
  margin-right: 0;
635
  }
636
 
637
- .tsf-flex-setting-label .tsf-counter {
638
- font-weight: 400;
639
- color: #666;
640
- margin-top: 15px;
641
- }
642
-
643
  .tsf-social-image-buttons {
644
  margin-top: 15px;
645
  margin-left: 1px;
@@ -778,6 +972,50 @@ body.js .tsf-flex-tab-content.tsf-flex-tab-content-active {
778
  flex: 0 1 auto;
779
  }
780
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
781
  /**
782
  * End inpost.
783
  */
@@ -785,19 +1023,19 @@ body.js .tsf-flex-tab-content.tsf-flex-tab-content-active {
785
  /**
786
  * General fields.
787
  */
788
- .tsf-metaboxes .tsf-default-selected {
789
  border-color: #1c9d38;
790
  }
791
 
792
- .tsf-metaboxes .tsf-default-selected:checked:before {
793
  color: #1c9d38;
794
  }
795
 
796
- .tsf-metaboxes .tsf-warning-selected {
797
  border-color: #dd3811;
798
  }
799
 
800
- .tsf-metaboxes .tsf-warning-selected:checked:before {
801
  color: #dd3811;
802
  }
803
 
@@ -830,6 +1068,14 @@ body.js .tsf-flex-tab-content.tsf-flex-tab-content-active {
830
  margin-top: 0;
831
  }
832
 
 
 
 
 
 
 
 
 
833
  /**
834
  * Start AJAX
835
  */
@@ -943,32 +1189,44 @@ a.tsf-set-social-image.button {
943
  line-height: 2.8;
944
  }
945
 
946
- .tsf-metaboxes #tsf-title-location label span,
947
- .tsf-metaboxes #tsf-home-title-location label span {
948
  min-width: 40px;
949
  }
950
 
951
  .wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden) {
952
  overflow: initial !important;
953
  }
 
 
 
 
 
 
 
 
 
 
 
 
954
  }
955
 
956
  @media screen and (max-width: 642px) {
957
- .tsf-metaboxes span.tsf-nav-desktop {
958
  display: none;
959
  }
960
  }
961
 
962
  @media screen and (max-width: 510px) {
963
- span.tsf-seo-bar.tsf-100 {
964
  width: inherit;
965
  }
966
  }
967
 
968
  /* Firefix */
969
  @-moz-document url-prefix() {
970
- .tsf-metaboxes #tsf-title-separator label,
971
- .tsf-metaboxes #tsf-description-separator label {
972
  margin: 3px 1px;
973
  }
974
 
@@ -988,17 +1246,13 @@ a.tsf-set-social-image.button {
988
  }
989
  }
990
 
991
- .tsf-metaboxes .tsf-default-selected {
992
  box-shadow: 0 0 2px 0 #1c9d38;
993
  }
994
 
995
- .tsf-metaboxes .tsf-warning-selected {
996
  box-shadow: 0 0 2px 0 #dd3811;
997
  }
998
-
999
- .tsf-metaboxes legend h4 {
1000
- margin: 2px 0;
1001
- }
1002
  }
1003
 
1004
  /**
1
+ /**
2
+ * See, for colors:
3
+ * https://color.adobe.com/create/color-wheel/?base=2&rule=Custom&selected=1&name=Mijn%20Color-thema&mode=rgb&rgbvalues=0,0,0,1,0.6289566724811484,0.10577297701442445,0.04724043389094745,0.7647058823529411,0.2945255209368204,0,0.4806705005377058,0.8235294117647058,0.8666666666666667,0.2196078431372549,0.06666666666666667&swatchOrder=0,1,2,3,4
4
+ */
5
+
6
  /**
7
  * Dismissible Notices.
8
  */
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%;
89
  width: 8%;
90
  }
91
 
92
+ .tsf-seo-bar-item {
93
  text-decoration: none;
94
  font-size: 13px;
95
+ -webkit-user-select: none;
96
+ -moz-user-select: none;
97
+ -ms-user-select: none;
98
+ user-select: none;
99
  }
100
 
101
  #tsf-title-wrap {
117
  white-space: pre;
118
  }
119
 
120
+ #tsf-title-placeholder,
121
+ #tsf-title-placeholder-prefix {
122
  position: absolute;
123
  color: #777;
124
  -webkit-user-select: none;
136
 
137
  /* START Character Counters */
138
 
139
+ .tsf-counter-wrap {
140
+ margin-top: 15px;
141
+ }
142
+
143
  .tsf-counter {
144
+ font-weight: 400;
145
+ color: #666;
146
  cursor: pointer;
147
  -webkit-user-select: none;
148
  -moz-user-select: none;
151
  will-change: contents;
152
  }
153
 
154
+ .tsf-count-bad {
155
  color: #dd3811;
156
  }
157
 
158
+ .tsf-count-okay {
159
  color: #ffa700;
160
  }
161
 
162
+ .tsf-count-good {
163
  color: #0cc34b;
164
  }
165
 
166
+ .tsf-counter-one {
167
  color: #fff;
168
  border-radius: 4em;
169
  padding: 0 0.5em;
172
  text-align: center;
173
  vertical-align: baseline;
174
  }
175
+ .tsf-counter-one.tsf-count-bad {
176
  background-color: #dd3811;
177
  }
178
+ .tsf-counter-one.tsf-count-okay {
179
  background-color: #ffa700;
180
  }
181
+ .tsf-counter-one.tsf-count-good {
182
  background-color: #0cc34b;
183
  }
184
 
185
  /* END Character Counters */
186
 
187
+ /* START Pixel Counters */
188
+
189
+ /*Temporarily fix.*/
190
+ .tsf-tabs-content .tsf-pixel-counter-wrap {
191
+ margin-right: 1px;
192
+ max-width: 99%;
193
+ }
194
+
195
+ .tsf-pixel-shadow-wrap {
196
+ position: relative;
197
+ overflow: hidden;
198
+ width: 0;
199
+ height: 0;
200
+ }
201
+
202
+ /* 8 + 4 = 12. The 4px and 3px margins account for line height. */
203
+ .tsf-pixel-counter-wrap {
204
+ border-bottom: 1px solid #ccc;
205
+ margin-top: 12px;
206
+ margin-bottom: 3px;
207
+ }
208
+
209
+ .tsf-pixel-counter-bar {
210
+ padding-top: 7px;
211
+ display: block;
212
+ height: 3px;
213
+ width: 100%;
214
+ }
215
+
216
+ .tsf-pixel-counter-fluid {
217
+ display: block;
218
+ pointer-events: none;
219
+ height: 3px;
220
+ width: 0%;
221
+ max-width: 100%;
222
+ background: #007bd2;
223
+ box-shadow: 0px 1px 3px 0px #ccc;
224
+ -webkit-transition: width .15s cubic-bezier(0.4, 0, 0.75, 1);
225
+ -o-transition: width .15s cubic-bezier(0.4, 0, 0.75, 1);
226
+ transition: width .15s cubic-bezier(0.4, 0, 0.75, 1);
227
+ }
228
+
229
+ .tsf-pixel-counter-overflown .tsf-pixel-counter-fluid {
230
+ background-color: #dd3811;
231
+ }
232
+
233
+ .tsf-pixel-counter-fit .tsf-pixel-counter-fluid {
234
+ background-color: #0cc34b;
235
+ }
236
+
237
+ .tsf-description-pixel-counter-shadow,
238
+ .tsf-title-pixel-counter-shadow {
239
+ position: absolute;
240
+ right: 0;
241
+ top: 0;
242
+ z-index: -100;
243
+ overflow: visible;
244
+ visibility: hidden;
245
+ padding: 0;
246
+ margin: 0;
247
+ border: 0;
248
+ display: inline;
249
+ text-decoration: none;
250
+ white-space: nowrap;
251
+ word-wrap: normal;
252
+ zoom: 1;
253
+ text-overflow: clip;
254
+ -webkit-transition: none;
255
+ -moz-transition: none;
256
+ -o-transition: none;
257
+ -ms-transition: none;
258
+ transition: none;
259
+ font-size: 18px;
260
+ font-weight: 600;
261
+ }
262
+
263
+ .tsf-description-pixel-counter-shadow {
264
+ font-size: 13px;
265
+ font-weight: 400;
266
+ }
267
+
268
+ /* END Pixel Counters */
269
+
270
  #tsf-seo-bar-wrap {
271
  width: 18%;
272
  }
276
  width: 160px;
277
  }
278
 
279
+ .tsf-seo-bar {
280
  display: block;
281
  width: 95%;
282
  max-width: 220px;
285
  text-shadow: 0 0 3px rgba(0,0,0,0.3);
286
  }
287
 
288
+ .tsf-seo-bar.tsf-100 {
289
  width: 100%;
290
  }
291
 
292
+ .tsf-seo-bar-inner-wrap {
293
  display: table;
294
  width: 100%;
295
  border-radius: 0;
297
  border-collapse: separate;
298
  border-spacing: 0;
299
  vertical-align: middle;
 
300
  }
301
 
302
+ .tsf-seo-bar-section-wrap {
303
  display: table-cell;
304
  border-collapse: collapse;
305
  }
306
 
307
+ .tsf-seo-bar-item {
308
  display: table;
309
  width: 100%;
310
  color: #fff;
311
  text-align: center;
 
312
  height: 100%;
313
  min-width: 12px;
314
  vertical-align: top;
316
  box-shadow: 2px 0px 0px -1px rgba(0,0,0,0.1) inset, -2px 0px 0px -1px rgba(0,0,0,0.1) inset;
317
  }
318
 
319
+ body.no-js .tsf-seo-bar-item {
320
+ cursor: default;
321
+ }
322
+
323
+ .tsf-seo-bar.pill,
324
+ .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap {
325
  border-radius: 30px;
326
  }
327
 
328
+ .tsf-seo-bar.pill .tsf-seo-bar-item {
329
  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);
330
  }
331
 
332
+ .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap .tsf-seo-bar-section-wrap:last-of-type,
333
+ .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap .tsf-seo-bar-section-wrap:last-of-type a {
334
  border-top-left-radius: 30px;
335
  border-bottom-left-radius: 30px;
336
  }
401
  background-color: #007bd2;
402
  }
403
 
404
+ /* # Start tooltips */
405
+
406
+ .tsf-tooltip-wrap {
407
+ position: relative;
408
+ }
409
+
410
+ .tsf-tooltip-item {
411
+ cursor: help;
412
+ }
413
+
414
+ a.tsf-tooltip-item {
415
+ cursor: auto;
416
+ }
417
+
418
+ .tsf-tooltip {
419
  position: absolute;
420
+ padding: 0;
421
+ margin: 0;
422
+ bottom: 0;
 
 
 
 
 
 
 
423
  left: 0;
424
+ z-index: 900142;
425
+ text-align: right;
426
  pointer-events: none;
427
+ box-sizing: border-box;
428
+ display: -webkit-box;
429
+ display: -webkit-flex;
430
+ display: -ms-flexbox;
431
+ display: flex;
432
+ -webkit-flex: 1 1 auto;
433
+ flex: 1 1 auto;
434
+ -webkit-flex-wrap: wrap;
435
+ -ms-flex-wrap: wrap;
436
+ flex-wrap: wrap;
437
+ -webkit-flex-direction: row;
438
+ flex-direction: row;
439
+ -webkit-justify-content: flex-start;
440
+ justify-content: flex-start;
441
+ }
442
+
443
+ .tsf-tooltip-down {
444
+ bottom: auto;
445
+ top: 0;
446
+ }
447
+
448
+ .tsf-tooltip-text-wrap {
449
+ padding: 10px 12px;
450
+ font-size: 1em;
451
+ font-weight: 500;
452
+ line-height: 1.625em;
453
+ border-radius: 3px;
454
+ background: #007bd2;
455
+ color: #fdfdfd;
456
+ box-shadow: 0px 0px 2px rgba(0,0,0,.6);
457
+ text-shadow: none;
458
+ word-wrap: break-word;
459
+ overflow-wrap: break-word;
460
+ word-break: break-word;
461
+ white-space: pre-line;
462
+ display: -webkit-box;
463
+ display: -webkit-flex;
464
+ display: -ms-flexbox;
465
+ display: flex;
466
+ -webkit-flex: 1 0 150px;
467
+ flex: 1 0 150px;
468
+ -webkit-flex-wrap: wrap;
469
+ -ms-flex-wrap: wrap;
470
+ flex-wrap: wrap;
471
+ -webkit-flex-direction: row;
472
+ flex-direction: row;
473
+ -webkit-justify-content: flex-start;
474
+ justify-content: flex-start;
475
  }
476
 
477
+ .tsf-tooltip-text span {
478
  text-decoration: underline;
479
  }
480
 
481
+ /* fix breaks */
482
+ .tsf-tooltip-text br {
483
+ display: block;
484
+ width: 100%;
485
+ content: "\A";
486
+ }
487
+
488
+ .tsf-tooltip-arrow {
489
  position: absolute;
490
  bottom: -8px;
491
  z-index: 9999999;
492
  left: 0;
493
+ width: 0;
494
+ height: 0;
495
+ }
496
+
497
+ .tsf-tooltip-down .tsf-tooltip-arrow {
498
+ bottom: auto;
499
+ top: -8px;
500
+ }
501
+
502
+ .tsf-tooltip-arrow:before {
503
+ content: "";
504
+ border-left: 9px solid transparent;
505
+ border-right: 9px solid transparent;
506
+ border-top: 9px solid rgba(0,0,0,.25);
507
+ position: absolute;
508
+ bottom: -1px;
509
+ left: -1px;
510
+ }
511
+
512
+ .tsf-tooltip-arrow:after {
513
+ content: "";
514
+ border-left: 8px solid transparent;
515
+ border-right: 8px solid transparent;
516
+ border-top: 8px solid #007bd2;
517
+ position: absolute;
518
+ bottom: 0;
519
+ left: 0;
520
+ }
521
+
522
+ .tsf-tooltip-down .tsf-tooltip-arrow:before {
523
+ bottom: auto;
524
+ top: 0;
525
+ border-top: 0;
526
+ border-bottom: 9px solid rgba(0,0,0,.25);
527
+ }
528
+
529
+ .tsf-tooltip-down .tsf-tooltip-arrow:after {
530
+ bottom: auto;
531
+ top: 1px;
532
+ border-top: 0;
533
+ border-bottom: 8px solid #007bd2;
534
  }
535
 
536
+ /* # End tooltips */
537
+
538
  /* Mobile support */
539
  /* Needs more refining.... e.g. iPhone 6 = good, iPhone 6+ = offscreen */
540
  .tsf-seo-bar-wrap.column-tsf-seo-bar-temp {
556
  padding-bottom: 20px;
557
  }
558
 
559
+ .tsf-top-wrap {
560
  width: 100%;
561
  display: inline-block;
562
  vertical-align: top;
563
  }
564
 
565
+ .tsf-top-wrap > h1,
566
+ .tsf-top-wrap > h2 {
567
  float: left;
568
  }
569
 
571
  clear: both;
572
  }
573
 
574
+ .tsf-top-buttons {
575
  float: left;
576
  }
577
 
578
+ .tsf-bottom-buttons {
579
  text-align: left;
580
  }
581
 
588
  clear: both;
589
  }
590
 
591
+ #tsf-title-separator,
592
+ #tsf-description-separator {
593
  display: table;
594
  width: 100%;
595
  border-collapse: collapse;
596
  border-spacing: 0;
597
  }
598
 
599
+ #tsf-title-separator input,
600
+ #tsf-description-separator input {
601
  display: none;
602
  float: left;
603
  width: 0;
605
  opacity: 0;
606
  }
607
 
608
+ #tsf-title-separator label,
609
+ #tsf-description-separator label {
610
  display: inline-block;
611
  width: auto;
612
  min-width: 28px;
623
  font-size: 16px;
624
  }
625
 
626
+ #tsf-title-separator label.tsf-recommended,
627
+ #tsf-description-separator label.tsf-recommended {
628
  border: 1px solid #0cc34b;
629
  box-shadow: -1px -1px 1px #0cc34b inset;
630
  }
631
 
632
+ #tsf-title-separator input:hover + label,
633
+ #tsf-title-separator label:hover,
634
+ #tsf-description-separator input:hover + label,
635
+ #tsf-description-separator label:hover {
636
  box-shadow: 1px 1px 1px #aaa inset;
637
  background-color: #fff;
638
  }
639
 
640
+ #tsf-title-separator input:checked + label,
641
+ #tsf-description-separator input:checked + label {
642
  box-shadow: 1px 1px 1px #333 inset;
643
  background-color: #fff;
644
  }
645
 
646
+ #tsf-title-location,
647
+ #tsf-home-title-location {
648
  display: block;
649
  }
650
 
651
+ #tsf-title-location label span,
652
+ #tsf-home-title-location label span,
653
+ #tsf-twitter-cards label span {
654
  display: inline-block;
655
  min-width: 60px;
656
  vertical-align: baseline;
657
  }
658
 
659
+ #tsf-twitter-cards label span {
660
  min-width: 150px;
661
  }
662
 
663
+ #tsf-home-title-location label span.tsf-custom-title-js,
664
+ #tsf-home-title-location label span.tsf-custom-blogname-js,
665
+ #tsf-home-title-location label span.tsf-custom-tagline-js,
666
+ #tsf-title-location label .tsf-sep-js,
667
+ #tsf-home-title-location label .tsf-sep-js {
668
  display: inline;
669
  min-width: 0;
670
  white-space: pre;
673
  /**
674
  * Start Tabs.
675
  */
676
+ .tsf-tab-no-js,
677
+ .tsf-nav-tab-wrapper {
678
  position: relative;
679
  clear: both;
680
  width: 100%;
685
  margin: -4px -12px;
686
  }
687
 
688
+ .tsf-nav-tab {
689
  float: right;
690
  border: 1px solid #ccc;
691
  margin-right: .5em;
698
  font-weight: 600;
699
  }
700
 
701
+ .tsf-dashicons-tabs {
702
  font-size: initial;
703
  display: inline;
704
  vertical-align: text-bottom;
705
  }
706
 
707
+ input.tsf-tabs-radio {
708
  display: none;
709
  width: 0;
710
  height: 0;
712
  left: -9001px;
713
  }
714
 
715
+ .tsf-tabs-radio:checked + label,
716
+ .tsf-active-tab {
717
  background-color: inherit;
718
  border-bottom-color: #fff;
719
  color: #000;
720
  }
721
 
722
+ .tsf-tabs-content {
723
  margin: 1.33em auto 0;
724
  }
725
 
726
+ .tsf-content-no-js {
727
  margin: 1.33em auto;
728
  }
729
 
730
+ body.js .tsf-tabs-content {
731
  display: none;
732
  }
733
 
734
+ body.js .tsf-tabs-content.tsf-active-tab-content {
735
  display: block;
736
  }
737
 
834
  margin-right: 0;
835
  }
836
 
 
 
 
 
 
 
837
  .tsf-social-image-buttons {
838
  margin-top: 15px;
839
  margin-left: 1px;
972
  flex: 0 1 auto;
973
  }
974
 
975
+ #tsf-inpost-box .hndle .tsf-tooltip-wrap a {
976
+ font-size: 14px;
977
+ line-height: 1em;
978
+ }
979
+
980
+ /**
981
+ * Primary category selectors.
982
+ */
983
+ .tsf-is-primary-term {
984
+ font-weight: 600;
985
+ }
986
+
987
+ .tsf-primary-term-selector {
988
+ margin: 0;
989
+ padding: 0;
990
+ float: left;
991
+ line-height: inherit;
992
+ display: inline-block;
993
+ }
994
+
995
+ .tsf-primary-term-selector input {
996
+ vertical-align: middle;
997
+ height: 14px;
998
+ width: 14px;
999
+ min-width: 14px;
1000
+ line-height: inherit;
1001
+ margin: 0;
1002
+ padding: 0;
1003
+ pointer-events: none;
1004
+ }
1005
+
1006
+ .tsf-primary-term-selector input:checked:before {
1007
+ width: 6px;
1008
+ height: 6px;
1009
+ margin: 3px;
1010
+ line-height: inherit;
1011
+ }
1012
+
1013
+ .tsf-primary-term-selector-help-wrap {
1014
+ position: absolute;
1015
+ top: 0;
1016
+ left: 25px;
1017
+ }
1018
+
1019
  /**
1020
  * End inpost.
1021
  */
1023
  /**
1024
  * General fields.
1025
  */
1026
+ .tsf-default-selected {
1027
  border-color: #1c9d38;
1028
  }
1029
 
1030
+ .tsf-default-selected:checked:before {
1031
  color: #1c9d38;
1032
  }
1033
 
1034
+ .tsf-warning-selected {
1035
  border-color: #dd3811;
1036
  }
1037
 
1038
+ .tsf-warning-selected:checked:before {
1039
  color: #dd3811;
1040
  }
1041
 
1068
  margin-top: 0;
1069
  }
1070
 
1071
+ .tsf-metaboxes legend h4 {
1072
+ margin: 2px 0;
1073
+ }
1074
+
1075
+ .tsf-metaboxes legend p:last-of-type {
1076
+ margin-bottom: 0;
1077
+ }
1078
+
1079
  /**
1080
  * Start AJAX
1081
  */
1189
  line-height: 2.8;
1190
  }
1191
 
1192
+ #tsf-title-location label span,
1193
+ #tsf-home-title-location label span {
1194
  min-width: 40px;
1195
  }
1196
 
1197
  .wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden) {
1198
  overflow: initial !important;
1199
  }
1200
+
1201
+ .tsf-primary-term-selector input {
1202
+ height: 18px;
1203
+ width: 18px;
1204
+ min-width: 18px;
1205
+ }
1206
+
1207
+ .tsf-primary-term-selector input:checked:before {
1208
+ width: 8px;
1209
+ height: 8px;
1210
+ margin: 4px;
1211
+ }
1212
  }
1213
 
1214
  @media screen and (max-width: 642px) {
1215
+ .tsf-nav-desktop {
1216
  display: none;
1217
  }
1218
  }
1219
 
1220
  @media screen and (max-width: 510px) {
1221
+ .tsf-seo-bar.tsf-100 {
1222
  width: inherit;
1223
  }
1224
  }
1225
 
1226
  /* Firefix */
1227
  @-moz-document url-prefix() {
1228
+ #tsf-title-separator label,
1229
+ #tsf-description-separator label {
1230
  margin: 3px 1px;
1231
  }
1232
 
1246
  }
1247
  }
1248
 
1249
+ .tsf-default-selected {
1250
  box-shadow: 0 0 2px 0 #1c9d38;
1251
  }
1252
 
1253
+ .tsf-warning-selected {
1254
  box-shadow: 0 0 2px 0 #dd3811;
1255
  }
 
 
 
 
1256
  }
1257
 
1258
  /**
lib/css/tsf-rtl.min.css CHANGED
@@ -1 +1 @@
1
- #tsf-title-offset,#tsf-title-placeholder{right:0;white-space:pre;position:absolute}.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;color:transparent}#tsf-title-placeholder{color:#777;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:content-box;top:0;overflow:hidden;text-overflow:ellipsis;will-change:left,right}.tsf-counter{font-weight:600;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;will-change:contents}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%}.tsf-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;pointer-events:none}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-inpost-box .inside,.tsf-flex{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 auto;flex:1 1 auto;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:flex-start;justify-content:flex-start}#tsf-inpost-box.closed .inside,body.js .tsf-flex-tab-content{display:none}#tsf-inpost-box .inside{margin:0;padding:0;-webkit-flex:1 0 100%;flex:1 0 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.tsf-flex-inside-wrap{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto}.tsf-flex-setting{width:100%;-webkit-flex-direction:row;flex-direction:row}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;-webkit-flex:10 1 350px;flex:10 1 350px;box-shadow:0 0 0 1px #e9e9e9}.tsf-flex-setting-label{background-color:#f9f9f9;-webkit-flex:1 1 200px;flex:1 1 200px}.tsf-flex-setting-input{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-grow:0;flex-grow:0}.tsf-flex-setting-label-inner-wrap{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-flex-setting-label .tsf-counter{font-weight:400;color:#666;margin-top:15px}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}.tsf-flex-setting-input textarea{max-height:250px}input[type=radio].tsf-flex-nav-tab-radio{display:none;width:0;height:0;margin:0;padding:0;position:absolute;left:-9001px}.tsf-flex-nav-tab-wrapper{background-color:#fcfcfc;border-bottom:2px solid #dadada;-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 100%;flex:1 1 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%}.tsf-flex-nav-tab-inner{-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex:1 0 auto;flex:1 0 auto}.tsf-flex-nav-tab{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;-webkit-flex-direction:row;flex-direction:row;box-shadow:0 0 0 0 transparent inset;-webkit-transition:box-shadow .15s ease-out;-o-transition:box-shadow .15s ease-out;transition:box-shadow .15s ease-out;-webkit-align-items:center;align-items:center;-webkit-align-content:space-between;align-content:space-between}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-transition:box-shadow .25s ease-in;-o-transition:box-shadow .25s ease-in;transition:box-shadow .25s ease-in}.tsf-flex-tab-content{-webkit-flex:1 0 100%;flex:1 0 100%;max-width:100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:0 1 auto;flex:0 1 auto}.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-checkbox-wrapper{margin-top:15px}.tsf-checkbox-wrapper:first-child{margin-top: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:color .33s ease-in,text-shadow .33s ease-in;-o-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .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:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .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:color .33s ease-in,text-shadow .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}}.tsf-flex-hide-if-no-js,body.js .tsf-flex-hide-if-js{display:none}body.js .tsf-flex-hide-if-no-js{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}
1
+ .tsf-top-buttons,.tsf-top-wrap>h1,.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-item{text-decoration:none;font-size:13px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#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,#tsf-title-placeholder-prefix{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;right:0;overflow:hidden;white-space:pre;text-overflow:ellipsis;will-change:left,right}.tsf-counter-wrap{margin-top:15px}.tsf-counter{font-weight:400;color:#666;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;will-change:contents}.tsf-count-bad{color:#dd3811}.tsf-count-okay{color:#ffa700}.tsf-count-good{color:#0cc34b}.tsf-counter-one{color:#fff;border-radius:4em;padding:0 .5em;min-width:2em;display:inline-block;text-align:center;vertical-align:baseline}.tsf-counter-one.tsf-count-bad{background-color:#dd3811}.tsf-counter-one.tsf-count-okay{background-color:#ffa700}.tsf-counter-one.tsf-count-good{background-color:#0cc34b}.tsf-tabs-content .tsf-pixel-counter-wrap{margin-right:1px;max-width:99%}.tsf-pixel-shadow-wrap{position:relative;overflow:hidden;width:0;height:0}.tsf-pixel-counter-wrap{border-bottom:1px solid #ccc;margin-top:12px;margin-bottom:3px}.tsf-pixel-counter-bar{padding-top:7px;display:block;height:3px;width:100%}.tsf-pixel-counter-fluid{display:block;pointer-events:none;height:3px;width:0;max-width:100%;background:#007bd2;box-shadow:0 1px 3px 0 #ccc;-webkit-transition:width .15s cubic-bezier(.4,0,.75,1);-o-transition:width .15s cubic-bezier(.4,0,.75,1);transition:width .15s cubic-bezier(.4,0,.75,1)}.tsf-pixel-counter-overflown .tsf-pixel-counter-fluid{background-color:#dd3811}.tsf-pixel-counter-fit .tsf-pixel-counter-fluid{background-color:#0cc34b}.tsf-description-pixel-counter-shadow,.tsf-title-pixel-counter-shadow{position:absolute;right:0;top:0;z-index:-100;overflow:visible;visibility:hidden;padding:0;margin:0;border:0;display:inline;text-decoration:none;white-space:nowrap;word-wrap:normal;zoom:1;text-overflow:clip;-webkit-transition:none;-moz-transition:none;-o-transition:none;-ms-transition:none;transition:none;font-size:18px;font-weight:600}.tsf-description-pixel-counter-shadow{font-size:13px;font-weight:400}#tsf-seo-bar-wrap{width:18%}th:last-of-type#tsf-seo-bar-wrap{width:160px}.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)}.tsf-seo-bar.tsf-100{width:100%}.tsf-seo-bar-inner-wrap{display:table;width:100%;border-radius:0;margin:0 auto;border-collapse:separate;border-spacing:0;vertical-align:middle}.tsf-seo-bar-section-wrap{display:table-cell;border-collapse:collapse}.tsf-seo-bar-item{display:table;width:100%;color:#fff;text-align:center;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}body.no-js .tsf-seo-bar-item{cursor:default}.tsf-seo-bar.pill,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap{border-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-item{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 .tsf-seo-bar-section-wrap:last-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap .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%}.tsf-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}.tsf-tooltip-wrap{position:relative}.tsf-tooltip-item{cursor:help}a.tsf-tooltip-item{cursor:auto}.tsf-tooltip{position:absolute;padding:0;margin:0;bottom:0;left:0;z-index:900142;text-align:right;pointer-events:none;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 auto;flex:1 1 auto;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:flex-start;justify-content:flex-start}.tsf-tooltip-down{bottom:auto;top:0}.tsf-tooltip-text-wrap{padding:10px 12px;font-size:1em;font-weight:500;line-height:1.625em;border-radius:3px;background:#007bd2;color:#fdfdfd;box-shadow:0 0 2px rgba(0,0,0,.6);text-shadow:none;word-wrap:break-word;overflow-wrap:break-word;word-break:break-word;white-space:pre-line;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 0 150px;flex:1 0 150px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:flex-start;justify-content:flex-start}.tsf-is-primary-term,.tsf-nav-tab{font-weight:600}.tsf-tooltip-text span{text-decoration:underline}.tsf-tooltip-text br{display:block;width:100%;content:"\A"}.tsf-ajax:before,.tsf-tooltip-arrow:after,.tsf-tooltip-arrow:before{content:""}.tsf-tooltip-arrow{position:absolute;bottom:-8px;z-index:9999999;left:0;width:0;height:0}.tsf-tooltip-down .tsf-tooltip-arrow{bottom:auto;top:-8px}.tsf-tooltip-arrow:before{border-left:9px solid transparent;border-right:9px solid transparent;border-top:9px solid rgba(0,0,0,.25);position:absolute;bottom:-1px;left:-1px}.tsf-tooltip-arrow:after{border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #007bd2;position:absolute;bottom:0;left:0}.tsf-tooltip-down .tsf-tooltip-arrow:before{bottom:auto;top:0;border-top:0;border-bottom:9px solid rgba(0,0,0,.25)}.tsf-tooltip-down .tsf-tooltip-arrow:after{bottom:auto;top:1px;border-top:0;border-bottom:8px solid #007bd2}.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-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-metaboxes .metabox-holder{clear:both}.tsf-bottom-buttons{text-align:left}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}#tsf-description-separator,#tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}#tsf-description-separator input,#tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}#tsf-description-separator label,#tsf-title-separator label{display:inline-block;width:auto;min-width:28px;min-height:28px;margin:3px;-moz-margin-end:1.5px;-moz-margin-start:1.5px;padding:0 4px;border:1px solid #ccc;line-height:28px;text-align:center;cursor:pointer;box-shadow:-1px -1px 1px #aaa inset;font-size:16px}#tsf-description-separator label.tsf-recommended,#tsf-title-separator label.tsf-recommended{border:1px solid #0cc34b;box-shadow:-1px -1px 1px #0cc34b inset}#tsf-description-separator input:hover+label,#tsf-description-separator label:hover,#tsf-title-separator input:hover+label,#tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}#tsf-description-separator input:checked+label,#tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}#tsf-home-title-location,#tsf-title-location{display:block}#tsf-home-title-location label span,#tsf-title-location label span,#tsf-twitter-cards label span{display:inline-block;min-width:60px;vertical-align:baseline}#tsf-twitter-cards label span{min-width:150px}#tsf-home-title-location label .tsf-sep-js,#tsf-home-title-location label span.tsf-custom-blogname-js,#tsf-home-title-location label span.tsf-custom-tagline-js,#tsf-home-title-location label span.tsf-custom-title-js,#tsf-title-location label .tsf-sep-js{display:inline;min-width:0;white-space:pre}.tsf-nav-tab-wrapper,.tsf-tab-no-js{position:relative;clear:both;width:100%;display:inline-block;border-bottom:1px solid #ccc;line-height:inherit;padding:8px 12px 0;margin:-4px -12px}.tsf-nav-tab{float:right;border:1px solid #ccc;margin-right:.5em;margin-bottom:-1px;padding:5px 14px;font-size:12px;line-height:16px;background:#f1f1f1;color:#555}.tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}input.tsf-tabs-radio{display:none;width:0;height:0;position:absolute;left:-9001px}.tsf-active-tab,.tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-tabs-content{margin:1.33em auto 0}.tsf-content-no-js{margin:1.33em auto}body.js .tsf-tabs-content{display:none}body.js .tsf-tabs-content.tsf-active-tab-content{display:block}#tsf-inpost-box .inside,.tsf-flex{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 auto;flex:1 1 auto;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:flex-start;justify-content:flex-start}#tsf-inpost-box.closed .inside,body.js .tsf-flex-tab-content{display:none}#tsf-inpost-box .inside{margin:0;padding:0;-webkit-flex:1 0 100%;flex:1 0 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.tsf-flex-inside-wrap{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto}.tsf-flex-setting{width:100%;-webkit-flex-direction:row;flex-direction:row}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;-webkit-flex:10 1 350px;flex:10 1 350px;box-shadow:0 0 0 1px #e9e9e9}.tsf-flex-setting-label{background-color:#f9f9f9;-webkit-flex:1 1 200px;flex:1 1 200px}.tsf-flex-setting-input{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-grow:0;flex-grow:0}.tsf-flex-setting-label-inner-wrap{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}.tsf-flex-setting-input textarea{max-height:250px}input[type=radio].tsf-flex-nav-tab-radio{display:none;width:0;height:0;margin:0;padding:0;position:absolute;left:-9001px}.tsf-flex-nav-tab-wrapper{background-color:#fcfcfc;border-bottom:2px solid #dadada;-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 100%;flex:1 1 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%}.tsf-flex-nav-tab-inner{-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex:1 0 auto;flex:1 0 auto}.tsf-flex-nav-tab{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;-webkit-flex-direction:row;flex-direction:row;box-shadow:0 0 0 0 transparent inset;-webkit-transition:box-shadow .15s ease-out;-o-transition:box-shadow .15s ease-out;transition:box-shadow .15s ease-out;-webkit-align-items:center;align-items:center;-webkit-align-content:space-between;align-content:space-between}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-transition:box-shadow .25s ease-in;-o-transition:box-shadow .25s ease-in;transition:box-shadow .25s ease-in}.tsf-flex-tab-content{-webkit-flex:1 0 100%;flex:1 0 100%;max-width:100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:0 1 auto;flex:0 1 auto}#tsf-inpost-box .hndle .tsf-tooltip-wrap a{font-size:14px;line-height:1em}.tsf-primary-term-selector{margin:0;padding:0;float:left;line-height:inherit;display:inline-block}.tsf-primary-term-selector input{vertical-align:middle;height:14px;width:14px;min-width:14px;line-height:inherit;margin:0;padding:0;pointer-events:none}.tsf-primary-term-selector input:checked:before{width:6px;height:6px;margin:3px;line-height:inherit}.tsf-primary-term-selector-help-wrap{position:absolute;top:0;left:25px}.tsf-default-selected{border-color:#1c9d38}.tsf-default-selected:checked:before{color:#1c9d38}.tsf-warning-selected{border-color:#dd3811}.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-checkbox-wrapper{margin-top:15px}.tsf-checkbox-wrapper:first-child{margin-top:0}.tsf-metaboxes legend h4{margin:2px 0}.tsf-metaboxes legend p:last-of-type{margin-bottom: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}.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:color .33s ease-in,text-shadow .33s ease-in;-o-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .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:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .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:color .33s ease-in,text-shadow .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-home-title-location label span,#tsf-title-location label span{min-width:40px}.wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden){overflow:initial!important}.tsf-primary-term-selector input{height:18px;width:18px;min-width:18px}.tsf-primary-term-selector input:checked:before{width:8px;height:8px;margin:4px}}@media screen and (max-width:642px){.tsf-nav-desktop{display:none}}@media screen and (max-width:510px){.tsf-seo-bar.tsf-100{width:inherit}}@-moz-document url-prefix(){#tsf-description-separator label,#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-default-selected{box-shadow:0 0 2px 0 #1c9d38}.tsf-warning-selected{box-shadow:0 0 2px 0 #dd3811}}.tsf-flex-hide-if-no-js,body.js .tsf-flex-hide-if-js{display:none}body.js .tsf-flex-hide-if-no-js{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}
lib/css/tsf.css CHANGED
@@ -1,7 +1,7 @@
1
  /**
2
- * See, for colors:
3
- * https://color.adobe.com/create/color-wheel/?base=2&rule=Custom&selected=1&name=Mijn%20Color-thema&mode=rgb&rgbvalues=0,0,0,1,0.6289566724811484,0.10577297701442445,0.04724043389094745,0.7647058823529411,0.2945255209368204,0,0.4806705005377058,0.8235294117647058,0.8666666666666667,0.2196078431372549,0.06666666666666667&swatchOrder=0,1,2,3,4
4
- */
5
 
6
  /**
7
  * Dismissible Notices.
@@ -89,9 +89,13 @@ th.column-tsf-seo-bar-wrap ~ th {
89
  width: 8%;
90
  }
91
 
92
- .tsf-seo-bar a {
93
  text-decoration: none;
94
  font-size: 13px;
 
 
 
 
95
  }
96
 
97
  #tsf-title-wrap {
@@ -113,7 +117,8 @@ th.column-tsf-seo-bar-wrap ~ th {
113
  white-space: pre;
114
  }
115
 
116
- #tsf-title-placeholder {
 
117
  position: absolute;
118
  color: #777;
119
  -webkit-user-select: none;
@@ -131,8 +136,13 @@ th.column-tsf-seo-bar-wrap ~ th {
131
 
132
  /* START Character Counters */
133
 
 
 
 
 
134
  .tsf-counter {
135
- font-weight: 600;
 
136
  cursor: pointer;
137
  -webkit-user-select: none;
138
  -moz-user-select: none;
@@ -141,19 +151,19 @@ th.column-tsf-seo-bar-wrap ~ th {
141
  will-change: contents;
142
  }
143
 
144
- span.tsf-count-bad {
145
  color: #dd3811;
146
  }
147
 
148
- span.tsf-count-okay {
149
  color: #ffa700;
150
  }
151
 
152
- span.tsf-count-good {
153
  color: #0cc34b;
154
  }
155
 
156
- span.tsf-counter-one {
157
  color: #fff;
158
  border-radius: 4em;
159
  padding: 0 0.5em;
@@ -162,18 +172,101 @@ span.tsf-counter-one {
162
  text-align: center;
163
  vertical-align: baseline;
164
  }
165
- span.tsf-counter-one.tsf-count-bad {
166
  background-color: #dd3811;
167
  }
168
- span.tsf-counter-one.tsf-count-okay {
169
  background-color: #ffa700;
170
  }
171
- span.tsf-counter-one.tsf-count-good {
172
  background-color: #0cc34b;
173
  }
174
 
175
  /* END Character Counters */
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  #tsf-seo-bar-wrap {
178
  width: 18%;
179
  }
@@ -183,7 +276,7 @@ th:last-of-type#tsf-seo-bar-wrap {
183
  width: 160px;
184
  }
185
 
186
- span.tsf-seo-bar {
187
  display: block;
188
  width: 95%;
189
  max-width: 220px;
@@ -192,11 +285,11 @@ span.tsf-seo-bar {
192
  text-shadow: 0 0 3px rgba(0,0,0,0.3);
193
  }
194
 
195
- span.tsf-seo-bar.tsf-100 {
196
  width: 100%;
197
  }
198
 
199
- span.tsf-seo-bar-inner-wrap {
200
  display: table;
201
  width: 100%;
202
  border-radius: 0;
@@ -204,20 +297,18 @@ span.tsf-seo-bar-inner-wrap {
204
  border-collapse: separate;
205
  border-spacing: 0;
206
  vertical-align: middle;
207
- position: relative;
208
  }
209
 
210
- span.tsf-seo-bar-section-wrap {
211
  display: table-cell;
212
  border-collapse: collapse;
213
  }
214
 
215
- .tsf-seo-bar-inner-wrap a {
216
  display: table;
217
  width: 100%;
218
  color: #fff;
219
  text-align: center;
220
- cursor: help;
221
  height: 100%;
222
  min-width: 12px;
223
  vertical-align: top;
@@ -225,23 +316,27 @@ span.tsf-seo-bar-section-wrap {
225
  box-shadow: 2px 0px 0px -1px rgba(0,0,0,0.1) inset, -2px 0px 0px -1px rgba(0,0,0,0.1) inset;
226
  }
227
 
228
- span.tsf-seo-bar.pill,
229
- span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap {
 
 
 
 
230
  border-radius: 30px;
231
  }
232
 
233
- span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a {
234
  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);
235
  }
236
 
237
- .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type,
238
- .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:first-of-type a {
239
  border-top-left-radius: 30px;
240
  border-bottom-left-radius: 30px;
241
  }
242
 
243
- .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type,
244
- .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap span.tsf-seo-bar-section-wrap:last-of-type a {
245
  border-top-right-radius: 30px;
246
  border-bottom-right-radius: 30px;
247
  }
@@ -306,40 +401,140 @@ span.tsf-seo-bar.pill span.tsf-seo-bar-inner-wrap a {
306
  background-color: #007bd2;
307
  }
308
 
309
- span.tsf-seo-bar .tsf-explanation-desc {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  position: absolute;
311
- width: auto;
312
- min-width: 90%;
313
- max-width: 220px;
314
- font-weight: 600;
315
- background: #007bd2;
316
- padding: 8px 12px;
317
- color: #fdfdfd;
318
- border-radius: 0px;
319
- z-index: 900142;
320
- box-shadow: 0px 0px 2px rgba(0,0,0,0.6);
321
  left: 0;
322
- right: 0;
323
  text-align: left;
324
  pointer-events: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  }
326
 
327
- span.tsf-seo-bar .tsf-explanation-desc span {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
  text-decoration: underline;
329
  }
330
 
331
- span.tsf-seo-bar .tsf-explanation-desc div {
332
- width: 0;
333
- height: 0;
334
- border-left: 12px solid transparent;
335
- border-right: 12px solid transparent;
336
- border-top: 12px solid #007bd2;
 
 
337
  position: absolute;
338
  bottom: -8px;
339
  z-index: 9999999;
340
  left: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  }
342
 
 
 
343
  /* Mobile support */
344
  /* Needs more refining.... e.g. iPhone 6 = good, iPhone 6+ = offscreen */
345
  .tsf-seo-bar-wrap.column-tsf-seo-bar-temp {
@@ -361,14 +556,14 @@ span.tsf-seo-bar .tsf-explanation-desc div {
361
  padding-bottom: 20px;
362
  }
363
 
364
- .tsf-metaboxes .tsf-top-wrap {
365
  width: 100%;
366
  display: inline-block;
367
  vertical-align: top;
368
  }
369
 
370
- .tsf-metaboxes .tsf-top-wrap > h1,
371
- .tsf-metaboxes .tsf-top-wrap > h2 {
372
  float: left;
373
  }
374
 
@@ -376,11 +571,11 @@ span.tsf-seo-bar .tsf-explanation-desc div {
376
  clear: both;
377
  }
378
 
379
- .tsf-metaboxes .tsf-top-buttons {
380
  float: right;
381
  }
382
 
383
- .tsf-metaboxes .tsf-bottom-buttons {
384
  text-align: right;
385
  }
386
 
@@ -393,16 +588,16 @@ span.tsf-seo-bar .tsf-explanation-desc div {
393
  clear: both;
394
  }
395
 
396
- .tsf-metaboxes #tsf-title-separator,
397
- .tsf-metaboxes #tsf-description-separator {
398
  display: table;
399
  width: 100%;
400
  border-collapse: collapse;
401
  border-spacing: 0;
402
  }
403
 
404
- .tsf-metaboxes #tsf-title-separator input,
405
- .tsf-metaboxes #tsf-description-separator input {
406
  display: none;
407
  float: left;
408
  width: 0;
@@ -410,8 +605,8 @@ span.tsf-seo-bar .tsf-explanation-desc div {
410
  opacity: 0;
411
  }
412
 
413
- .tsf-metaboxes #tsf-title-separator label,
414
- .tsf-metaboxes #tsf-description-separator label {
415
  display: inline-block;
416
  width: auto;
417
  min-width: 28px;
@@ -428,48 +623,48 @@ span.tsf-seo-bar .tsf-explanation-desc div {
428
  font-size: 16px;
429
  }
430
 
431
- .tsf-metaboxes #tsf-title-separator label.tsf-recommended,
432
- .tsf-metaboxes #tsf-description-separator label.tsf-recommended {
433
  border: 1px solid #0cc34b;
434
  box-shadow: -1px -1px 1px #0cc34b inset;
435
  }
436
 
437
- .tsf-metaboxes #tsf-title-separator input:hover + label,
438
- .tsf-metaboxes #tsf-title-separator label:hover,
439
- .tsf-metaboxes #tsf-description-separator input:hover + label,
440
- .tsf-metaboxes #tsf-description-separator label:hover {
441
  box-shadow: 1px 1px 1px #aaa inset;
442
  background-color: #fff;
443
  }
444
 
445
- .tsf-metaboxes #tsf-title-separator input:checked + label,
446
- .tsf-metaboxes #tsf-description-separator input:checked + label {
447
  box-shadow: 1px 1px 1px #333 inset;
448
  background-color: #fff;
449
  }
450
 
451
- .tsf-metaboxes #tsf-title-location,
452
- .tsf-metaboxes #tsf-home-title-location {
453
  display: block;
454
  }
455
 
456
- .tsf-metaboxes #tsf-title-location label span,
457
- .tsf-metaboxes #tsf-home-title-location label span,
458
- .tsf-metaboxes #tsf-twitter-cards label span {
459
  display: inline-block;
460
  min-width: 60px;
461
  vertical-align: baseline;
462
  }
463
 
464
- .tsf-metaboxes #tsf-twitter-cards label span {
465
  min-width: 150px;
466
  }
467
 
468
- .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-title-js,
469
- .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-blogname-js,
470
- .tsf-metaboxes #tsf-home-title-location label span.tsf-custom-tagline-js,
471
- .tsf-metaboxes #tsf-title-location label .tsf-sep-js,
472
- .tsf-metaboxes #tsf-home-title-location label .tsf-sep-js {
473
  display: inline;
474
  min-width: 0;
475
  white-space: pre;
@@ -478,8 +673,8 @@ span.tsf-seo-bar .tsf-explanation-desc div {
478
  /**
479
  * Start Tabs.
480
  */
481
- .tsf-metaboxes .tsf-tab-no-js,
482
- .tsf-metaboxes .tsf-nav-tab-wrapper {
483
  position: relative;
484
  clear: both;
485
  width: 100%;
@@ -490,7 +685,7 @@ span.tsf-seo-bar .tsf-explanation-desc div {
490
  margin: -4px -12px;
491
  }
492
 
493
- .tsf-metaboxes .tsf-nav-tab {
494
  float: left;
495
  border: 1px solid #ccc;
496
  margin-left: .5em;
@@ -503,13 +698,13 @@ span.tsf-seo-bar .tsf-explanation-desc div {
503
  font-weight: 600;
504
  }
505
 
506
- .tsf-metaboxes .tsf-dashicons-tabs {
507
  font-size: initial;
508
  display: inline;
509
  vertical-align: text-bottom;
510
  }
511
 
512
- .tsf-metaboxes .tsf-tabs-radio {
513
  display: none;
514
  width: 0;
515
  height: 0;
@@ -517,26 +712,26 @@ span.tsf-seo-bar .tsf-explanation-desc div {
517
  left: -9001px;
518
  }
519
 
520
- .tsf-metaboxes .tsf-tabs-radio:checked + label,
521
- .tsf-metaboxes .tsf-active-tab {
522
  background-color: inherit;
523
  border-bottom-color: #fff;
524
  color: #000;
525
  }
526
 
527
- .tsf-metaboxes .tsf-tabs-content {
528
  margin: 1.33em auto 0;
529
  }
530
 
531
- .tsf-metaboxes .tsf-content-no-js {
532
  margin: 1.33em auto;
533
  }
534
 
535
- body.js .tsf-metaboxes .tsf-tabs-content {
536
  display: none;
537
  }
538
 
539
- body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content {
540
  display: block;
541
  }
542
 
@@ -639,12 +834,6 @@ body.js .tsf-metaboxes .tsf-tabs-content.tsf-active-tab-content {
639
  margin-right: 0;
640
  }
641
 
642
- .tsf-flex-setting-label .tsf-counter {
643
- font-weight: 400;
644
- color: #666;
645
- margin-top: 15px;
646
- }
647
-
648
  .tsf-social-image-buttons {
649
  margin-top: 15px;
650
  margin-left: 1px;
@@ -783,6 +972,50 @@ body.js .tsf-flex-tab-content.tsf-flex-tab-content-active {
783
  flex: 0 1 auto;
784
  }
785
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
786
  /**
787
  * End inpost.
788
  */
@@ -790,19 +1023,19 @@ body.js .tsf-flex-tab-content.tsf-flex-tab-content-active {
790
  /**
791
  * General fields.
792
  */
793
- .tsf-metaboxes .tsf-default-selected {
794
  border-color: #1c9d38;
795
  }
796
 
797
- .tsf-metaboxes .tsf-default-selected:checked:before {
798
  color: #1c9d38;
799
  }
800
 
801
- .tsf-metaboxes .tsf-warning-selected {
802
  border-color: #dd3811;
803
  }
804
 
805
- .tsf-metaboxes .tsf-warning-selected:checked:before {
806
  color: #dd3811;
807
  }
808
 
@@ -835,6 +1068,14 @@ body.js .tsf-flex-tab-content.tsf-flex-tab-content-active {
835
  margin-top: 0;
836
  }
837
 
 
 
 
 
 
 
 
 
838
  /**
839
  * Start AJAX
840
  */
@@ -948,32 +1189,44 @@ a.tsf-set-social-image.button {
948
  line-height: 2.8;
949
  }
950
 
951
- .tsf-metaboxes #tsf-title-location label span,
952
- .tsf-metaboxes #tsf-home-title-location label span {
953
  min-width: 40px;
954
  }
955
 
956
  .wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden) {
957
  overflow: initial !important;
958
  }
 
 
 
 
 
 
 
 
 
 
 
 
959
  }
960
 
961
  @media screen and (max-width: 642px) {
962
- .tsf-metaboxes span.tsf-nav-desktop {
963
  display: none;
964
  }
965
  }
966
 
967
  @media screen and (max-width: 510px) {
968
- span.tsf-seo-bar.tsf-100 {
969
  width: inherit;
970
  }
971
  }
972
 
973
  /* Firefix */
974
  @-moz-document url-prefix() {
975
- .tsf-metaboxes #tsf-title-separator label,
976
- .tsf-metaboxes #tsf-description-separator label {
977
  margin: 3px 1px;
978
  }
979
 
@@ -993,17 +1246,13 @@ a.tsf-set-social-image.button {
993
  }
994
  }
995
 
996
- .tsf-metaboxes .tsf-default-selected {
997
  box-shadow: 0 0 2px 0 #1c9d38;
998
  }
999
 
1000
- .tsf-metaboxes .tsf-warning-selected {
1001
  box-shadow: 0 0 2px 0 #dd3811;
1002
  }
1003
-
1004
- .tsf-metaboxes legend h4 {
1005
- margin: 2px 0;
1006
- }
1007
  }
1008
 
1009
  /**
1
  /**
2
+ * See, for colors:
3
+ * https://color.adobe.com/create/color-wheel/?base=2&rule=Custom&selected=1&name=Mijn%20Color-thema&mode=rgb&rgbvalues=0,0,0,1,0.6289566724811484,0.10577297701442445,0.04724043389094745,0.7647058823529411,0.2945255209368204,0,0.4806705005377058,0.8235294117647058,0.8666666666666667,0.2196078431372549,0.06666666666666667&swatchOrder=0,1,2,3,4
4
+ */
5
 
6
  /**
7
  * Dismissible Notices.
89
  width: 8%;
90
  }
91
 
92
+ .tsf-seo-bar-item {
93
  text-decoration: none;
94
  font-size: 13px;
95
+ -webkit-user-select: none;
96
+ -moz-user-select: none;
97
+ -ms-user-select: none;
98
+ user-select: none;
99
  }
100
 
101
  #tsf-title-wrap {
117
  white-space: pre;
118
  }
119
 
120
+ #tsf-title-placeholder,
121
+ #tsf-title-placeholder-prefix {
122
  position: absolute;
123
  color: #777;
124
  -webkit-user-select: none;
136
 
137
  /* START Character Counters */
138
 
139
+ .tsf-counter-wrap {
140
+ margin-top: 15px;
141
+ }
142
+
143
  .tsf-counter {
144
+ font-weight: 400;
145
+ color: #666;
146
  cursor: pointer;
147
  -webkit-user-select: none;
148
  -moz-user-select: none;
151
  will-change: contents;
152
  }
153
 
154
+ .tsf-count-bad {
155
  color: #dd3811;
156
  }
157
 
158
+ .tsf-count-okay {
159
  color: #ffa700;
160
  }
161
 
162
+ .tsf-count-good {
163
  color: #0cc34b;
164
  }
165
 
166
+ .tsf-counter-one {
167
  color: #fff;
168
  border-radius: 4em;
169
  padding: 0 0.5em;
172
  text-align: center;
173
  vertical-align: baseline;
174
  }
175
+ .tsf-counter-one.tsf-count-bad {
176
  background-color: #dd3811;
177
  }
178
+ .tsf-counter-one.tsf-count-okay {
179
  background-color: #ffa700;
180
  }
181
+ .tsf-counter-one.tsf-count-good {
182
  background-color: #0cc34b;
183
  }
184
 
185
  /* END Character Counters */
186
 
187
+ /* START Pixel Counters */
188
+
189
+ /*Temporarily fix.*/
190
+ .tsf-tabs-content .tsf-pixel-counter-wrap {
191
+ margin-left: 1px;
192
+ max-width: 99%;
193
+ }
194
+
195
+ .tsf-pixel-shadow-wrap {
196
+ position: relative;
197
+ overflow: hidden;
198
+ width: 0;
199
+ height: 0;
200
+ }
201
+
202
+ /* 8 + 4 = 12. The 4px and 3px margins account for line height. */
203
+ .tsf-pixel-counter-wrap {
204
+ border-bottom: 1px solid #ccc;
205
+ margin-top: 12px;
206
+ margin-bottom: 3px;
207
+ }
208
+
209
+ .tsf-pixel-counter-bar {
210
+ padding-top: 7px;
211
+ display: block;
212
+ height: 3px;
213
+ width: 100%;
214
+ }
215
+
216
+ .tsf-pixel-counter-fluid {
217
+ display: block;
218
+ pointer-events: none;
219
+ height: 3px;
220
+ width: 0%;
221
+ max-width: 100%;
222
+ background: #007bd2;
223
+ box-shadow: 0px 1px 3px 0px #ccc;
224
+ -webkit-transition: width .15s cubic-bezier(0.4, 0, 0.75, 1);
225
+ -o-transition: width .15s cubic-bezier(0.4, 0, 0.75, 1);
226
+ transition: width .15s cubic-bezier(0.4, 0, 0.75, 1);
227
+ }
228
+
229
+ .tsf-pixel-counter-overflown .tsf-pixel-counter-fluid {
230
+ background-color: #dd3811;
231
+ }
232
+
233
+ .tsf-pixel-counter-fit .tsf-pixel-counter-fluid {
234
+ background-color: #0cc34b;
235
+ }
236
+
237
+ .tsf-description-pixel-counter-shadow,
238
+ .tsf-title-pixel-counter-shadow {
239
+ position: absolute;
240
+ left: 0;
241
+ top: 0;
242
+ z-index: -100;
243
+ overflow: visible;
244
+ visibility: hidden;
245
+ padding: 0;
246
+ margin: 0;
247
+ border: 0;
248
+ display: inline;
249
+ text-decoration: none;
250
+ white-space: nowrap;
251
+ word-wrap: normal;
252
+ zoom: 1;
253
+ text-overflow: clip;
254
+ -webkit-transition: none;
255
+ -moz-transition: none;
256
+ -o-transition: none;
257
+ -ms-transition: none;
258
+ transition: none;
259
+ font-size: 18px;
260
+ font-weight: 600;
261
+ }
262
+
263
+ .tsf-description-pixel-counter-shadow {
264
+ font-size: 13px;
265
+ font-weight: 400;
266
+ }
267
+
268
+ /* END Pixel Counters */
269
+
270
  #tsf-seo-bar-wrap {
271
  width: 18%;
272
  }
276
  width: 160px;
277
  }
278
 
279
+ .tsf-seo-bar {
280
  display: block;
281
  width: 95%;
282
  max-width: 220px;
285
  text-shadow: 0 0 3px rgba(0,0,0,0.3);
286
  }
287
 
288
+ .tsf-seo-bar.tsf-100 {
289
  width: 100%;
290
  }
291
 
292
+ .tsf-seo-bar-inner-wrap {
293
  display: table;
294
  width: 100%;
295
  border-radius: 0;
297
  border-collapse: separate;
298
  border-spacing: 0;
299
  vertical-align: middle;
 
300
  }
301
 
302
+ .tsf-seo-bar-section-wrap {
303
  display: table-cell;
304
  border-collapse: collapse;
305
  }
306
 
307
+ .tsf-seo-bar-item {
308
  display: table;
309
  width: 100%;
310
  color: #fff;
311
  text-align: center;
 
312
  height: 100%;
313
  min-width: 12px;
314
  vertical-align: top;
316
  box-shadow: 2px 0px 0px -1px rgba(0,0,0,0.1) inset, -2px 0px 0px -1px rgba(0,0,0,0.1) inset;
317
  }
318
 
319
+ body.no-js .tsf-seo-bar-item {
320
+ cursor: default;
321
+ }
322
+
323
+ .tsf-seo-bar.pill,
324
+ .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap {
325
  border-radius: 30px;
326
  }
327
 
328
+ .tsf-seo-bar.pill .tsf-seo-bar-item {
329
  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);
330
  }
331
 
332
+ .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap .tsf-seo-bar-section-wrap:first-of-type,
333
+ .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap .tsf-seo-bar-section-wrap:first-of-type .tsf-seo-bar-item {
334
  border-top-left-radius: 30px;
335
  border-bottom-left-radius: 30px;
336
  }
337
 
338
+ .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap .tsf-seo-bar-section-wrap:last-of-type,
339
+ .tsf-seo-bar.pill .tsf-seo-bar-inner-wrap .tsf-seo-bar-section-wrap:last-of-type .tsf-seo-bar-item {
340
  border-top-right-radius: 30px;
341
  border-bottom-right-radius: 30px;
342
  }
401
  background-color: #007bd2;
402
  }
403
 
404
+ /* # Start tooltips */
405
+
406
+ .tsf-tooltip-wrap {
407
+ position: relative;
408
+ }
409
+
410
+ .tsf-tooltip-item {
411
+ cursor: help;
412
+ }
413
+
414
+ a.tsf-tooltip-item {
415
+ cursor: auto;
416
+ }
417
+
418
+ .tsf-tooltip {
419
  position: absolute;
420
+ padding: 0;
421
+ margin: 0;
422
+ bottom: 0;
 
 
 
 
 
 
 
423
  left: 0;
424
+ z-index: 900142;
425
  text-align: left;
426
  pointer-events: none;
427
+ box-sizing: border-box;
428
+ display: -webkit-box;
429
+ display: -webkit-flex;
430
+ display: -ms-flexbox;
431
+ display: flex;
432
+ -webkit-flex: 1 1 auto;
433
+ flex: 1 1 auto;
434
+ -webkit-flex-wrap: wrap;
435
+ -ms-flex-wrap: wrap;
436
+ flex-wrap: wrap;
437
+ -webkit-flex-direction: row;
438
+ flex-direction: row;
439
+ -webkit-justify-content: flex-start;
440
+ justify-content: flex-start;
441
+ }
442
+
443
+ .tsf-tooltip-down {
444
+ bottom: auto;
445
+ top: 0;
446
  }
447
 
448
+ .tsf-tooltip-text-wrap {
449
+ padding: 10px 12px;
450
+ font-size: 1em;
451
+ font-weight: 500;
452
+ line-height: 1.625em;
453
+ border-radius: 3px;
454
+ background: #007bd2;
455
+ color: #fdfdfd;
456
+ box-shadow: 0px 0px 2px rgba(0,0,0,.6);
457
+ text-shadow: none;
458
+ word-wrap: break-word;
459
+ overflow-wrap: break-word;
460
+ word-break: break-word;
461
+ white-space: pre-line;
462
+ display: -webkit-box;
463
+ display: -webkit-flex;
464
+ display: -ms-flexbox;
465
+ display: flex;
466
+ -webkit-flex: 1 0 150px;
467
+ flex: 1 0 150px;
468
+ -webkit-flex-wrap: wrap;
469
+ -ms-flex-wrap: wrap;
470
+ flex-wrap: wrap;
471
+ -webkit-flex-direction: row;
472
+ flex-direction: row;
473
+ -webkit-justify-content: flex-start;
474
+ justify-content: flex-start;
475
+ }
476
+
477
+ .tsf-tooltip-text span {
478
  text-decoration: underline;
479
  }
480
 
481
+ /* fix breaks */
482
+ .tsf-tooltip-text br {
483
+ display: block;
484
+ width: 100%;
485
+ content: "\A";
486
+ }
487
+
488
+ .tsf-tooltip-arrow {
489
  position: absolute;
490
  bottom: -8px;
491
  z-index: 9999999;
492
  left: 0;
493
+ width: 0;
494
+ height: 0;
495
+ }
496
+
497
+ .tsf-tooltip-down .tsf-tooltip-arrow {
498
+ bottom: auto;
499
+ top: -8px;
500
+ }
501
+
502
+ .tsf-tooltip-arrow:before {
503
+ content: "";
504
+ border-left: 9px solid transparent;
505
+ border-right: 9px solid transparent;
506
+ border-top: 9px solid rgba(0,0,0,.25);
507
+ position: absolute;
508
+ bottom: -1px;
509
+ left: -1px;
510
+ }
511
+
512
+ .tsf-tooltip-arrow:after {
513
+ content: "";
514
+ border-left: 8px solid transparent;
515
+ border-right: 8px solid transparent;
516
+ border-top: 8px solid #007bd2;
517
+ position: absolute;
518
+ bottom: 0;
519
+ left: 0;
520
+ }
521
+
522
+ .tsf-tooltip-down .tsf-tooltip-arrow:before {
523
+ bottom: auto;
524
+ top: 0;
525
+ border-top: 0;
526
+ border-bottom: 9px solid rgba(0,0,0,.25);
527
+ }
528
+
529
+ .tsf-tooltip-down .tsf-tooltip-arrow:after {
530
+ bottom: auto;
531
+ top: 1px;
532
+ border-top: 0;
533
+ border-bottom: 8px solid #007bd2;
534
  }
535
 
536
+ /* # End tooltips */
537
+
538
  /* Mobile support */
539
  /* Needs more refining.... e.g. iPhone 6 = good, iPhone 6+ = offscreen */
540
  .tsf-seo-bar-wrap.column-tsf-seo-bar-temp {
556
  padding-bottom: 20px;
557
  }
558
 
559
+ .tsf-top-wrap {
560
  width: 100%;
561
  display: inline-block;
562
  vertical-align: top;
563
  }
564
 
565
+ .tsf-top-wrap > h1,
566
+ .tsf-top-wrap > h2 {
567
  float: left;
568
  }
569
 
571
  clear: both;
572
  }
573
 
574
+ .tsf-top-buttons {
575
  float: right;
576
  }
577
 
578
+ .tsf-bottom-buttons {
579
  text-align: right;
580
  }
581
 
588
  clear: both;
589
  }
590
 
591
+ #tsf-title-separator,
592
+ #tsf-description-separator {
593
  display: table;
594
  width: 100%;
595
  border-collapse: collapse;
596
  border-spacing: 0;
597
  }
598
 
599
+ #tsf-title-separator input,
600
+ #tsf-description-separator input {
601
  display: none;
602
  float: left;
603
  width: 0;
605
  opacity: 0;
606
  }
607
 
608
+ #tsf-title-separator label,
609
+ #tsf-description-separator label {
610
  display: inline-block;
611
  width: auto;
612
  min-width: 28px;
623
  font-size: 16px;
624
  }
625
 
626
+ #tsf-title-separator label.tsf-recommended,
627
+ #tsf-description-separator label.tsf-recommended {
628
  border: 1px solid #0cc34b;
629
  box-shadow: -1px -1px 1px #0cc34b inset;
630
  }
631
 
632
+ #tsf-title-separator input:hover + label,
633
+ #tsf-title-separator label:hover,
634
+ #tsf-description-separator input:hover + label,
635
+ #tsf-description-separator label:hover {
636
  box-shadow: 1px 1px 1px #aaa inset;
637
  background-color: #fff;
638
  }
639
 
640
+ #tsf-title-separator input:checked + label,
641
+ #tsf-description-separator input:checked + label {
642
  box-shadow: 1px 1px 1px #333 inset;
643
  background-color: #fff;
644
  }
645
 
646
+ #tsf-title-location,
647
+ #tsf-home-title-location {
648
  display: block;
649
  }
650
 
651
+ #tsf-title-location label span,
652
+ #tsf-home-title-location label span,
653
+ #tsf-twitter-cards label span {
654
  display: inline-block;
655
  min-width: 60px;
656
  vertical-align: baseline;
657
  }
658
 
659
+ #tsf-twitter-cards label span {
660
  min-width: 150px;
661
  }
662
 
663
+ #tsf-home-title-location label span.tsf-custom-title-js,
664
+ #tsf-home-title-location label span.tsf-custom-blogname-js,
665
+ #tsf-home-title-location label span.tsf-custom-tagline-js,
666
+ #tsf-title-location label .tsf-sep-js,
667
+ #tsf-home-title-location label .tsf-sep-js {
668
  display: inline;
669
  min-width: 0;
670
  white-space: pre;
673
  /**
674
  * Start Tabs.
675
  */
676
+ .tsf-tab-no-js,
677
+ .tsf-nav-tab-wrapper {
678
  position: relative;
679
  clear: both;
680
  width: 100%;
685
  margin: -4px -12px;
686
  }
687
 
688
+ .tsf-nav-tab {
689
  float: left;
690
  border: 1px solid #ccc;
691
  margin-left: .5em;
698
  font-weight: 600;
699
  }
700
 
701
+ .tsf-dashicons-tabs {
702
  font-size: initial;
703
  display: inline;
704
  vertical-align: text-bottom;
705
  }
706
 
707
+ input.tsf-tabs-radio {
708
  display: none;
709
  width: 0;
710
  height: 0;
712
  left: -9001px;
713
  }
714
 
715
+ .tsf-tabs-radio:checked + label,
716
+ .tsf-active-tab {
717
  background-color: inherit;
718
  border-bottom-color: #fff;
719
  color: #000;
720
  }
721
 
722
+ .tsf-tabs-content {
723
  margin: 1.33em auto 0;
724
  }
725
 
726
+ .tsf-content-no-js {
727
  margin: 1.33em auto;
728
  }
729
 
730
+ body.js .tsf-tabs-content {
731
  display: none;
732
  }
733
 
734
+ body.js .tsf-tabs-content.tsf-active-tab-content {
735
  display: block;
736
  }
737
 
834
  margin-right: 0;
835
  }
836
 
 
 
 
 
 
 
837
  .tsf-social-image-buttons {
838
  margin-top: 15px;
839
  margin-left: 1px;
972
  flex: 0 1 auto;
973
  }
974
 
975
+ #tsf-inpost-box .hndle .tsf-tooltip-wrap a {
976
+ font-size: 14px;
977
+ line-height: 1em;
978
+ }
979
+
980
+ /**
981
+ * Primary category selectors.
982
+ */
983
+ .tsf-is-primary-term {
984
+ font-weight: 600;
985
+ }
986
+
987
+ .tsf-primary-term-selector {
988
+ margin: 0;
989
+ padding: 0;
990
+ float: right;
991
+ line-height: inherit;
992
+ display: inline-block;
993
+ }
994
+
995
+ .tsf-primary-term-selector input {
996
+ vertical-align: middle;
997
+ height: 14px;
998
+ width: 14px;
999
+ min-width: 14px;
1000
+ line-height: inherit;
1001
+ margin: 0;
1002
+ padding: 0;
1003
+ pointer-events: none;
1004
+ }
1005
+
1006
+ .tsf-primary-term-selector input:checked:before {
1007
+ width: 6px;
1008
+ height: 6px;
1009
+ margin: 3px;
1010
+ line-height: inherit;
1011
+ }
1012
+
1013
+ .tsf-primary-term-selector-help-wrap {
1014
+ position: absolute;
1015
+ top: 0;
1016
+ right: 25px;
1017
+ }
1018
+
1019
  /**
1020
  * End inpost.
1021
  */
1023
  /**
1024
  * General fields.
1025
  */
1026
+ .tsf-default-selected {
1027
  border-color: #1c9d38;
1028
  }
1029
 
1030
+ .tsf-default-selected:checked:before {
1031
  color: #1c9d38;
1032
  }
1033
 
1034
+ .tsf-warning-selected {
1035
  border-color: #dd3811;
1036
  }
1037
 
1038
+ .tsf-warning-selected:checked:before {
1039
  color: #dd3811;
1040
  }
1041
 
1068
  margin-top: 0;
1069
  }
1070
 
1071
+ .tsf-metaboxes legend h4 {
1072
+ margin: 2px 0;
1073
+ }
1074
+
1075
+ .tsf-metaboxes legend p:last-of-type {
1076
+ margin-bottom: 0;
1077
+ }
1078
+
1079
  /**
1080
  * Start AJAX
1081
  */
1189
  line-height: 2.8;
1190
  }
1191
 
1192
+ #tsf-title-location label span,
1193
+ #tsf-home-title-location label span {
1194
  min-width: 40px;
1195
  }
1196
 
1197
  .wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden) {
1198
  overflow: initial !important;
1199
  }
1200
+
1201
+ .tsf-primary-term-selector input {
1202
+ height: 18px;
1203
+ width: 18px;
1204
+ min-width: 18px;
1205
+ }
1206
+
1207
+ .tsf-primary-term-selector input:checked:before {
1208
+ width: 8px;
1209
+ height: 8px;
1210
+ margin: 4px;
1211
+ }
1212
  }
1213
 
1214
  @media screen and (max-width: 642px) {
1215
+ .tsf-nav-desktop {
1216
  display: none;
1217
  }
1218
  }
1219
 
1220
  @media screen and (max-width: 510px) {
1221
+ .tsf-seo-bar.tsf-100 {
1222
  width: inherit;
1223
  }
1224
  }
1225
 
1226
  /* Firefix */
1227
  @-moz-document url-prefix() {
1228
+ #tsf-title-separator label,
1229
+ #tsf-description-separator label {
1230
  margin: 3px 1px;
1231
  }
1232
 
1246
  }
1247
  }
1248
 
1249
+ .tsf-default-selected {
1250
  box-shadow: 0 0 2px 0 #1c9d38;
1251
  }
1252
 
1253
+ .tsf-warning-selected {
1254
  box-shadow: 0 0 2px 0 #dd3811;
1255
  }
 
 
 
 
1256
  }
1257
 
1258
  /**
lib/css/tsf.min.css CHANGED
@@ -1 +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:pre;text-overflow:ellipsis;will-change:left,right}.tsf-counter{font-weight:600;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;will-change:contents}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%}.tsf-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;pointer-events:none}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-inpost-box .inside,.tsf-flex{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 auto;flex:1 1 auto;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:flex-start;justify-content:flex-start}#tsf-inpost-box.closed .inside,body.js .tsf-flex-tab-content{display:none}#tsf-inpost-box .inside{margin:0;padding:0;-webkit-flex:1 0 100%;flex:1 0 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.tsf-flex-inside-wrap{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto}.tsf-flex-setting{width:100%;-webkit-flex-direction:row;flex-direction:row}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;-webkit-flex:10 1 350px;flex:10 1 350px;box-shadow:0 0 0 1px #e9e9e9}.tsf-flex-setting-label{background-color:#f9f9f9;-webkit-flex:1 1 200px;flex:1 1 200px}.tsf-flex-setting-input{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-grow:0;flex-grow:0}.tsf-flex-setting-label-inner-wrap{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-flex-setting-label .tsf-counter{font-weight:400;color:#666;margin-top:15px}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}.tsf-flex-setting-input textarea{max-height:250px}input[type=radio].tsf-flex-nav-tab-radio{display:none;width:0;height:0;margin:0;padding:0;position:absolute;left:-9001px}.tsf-flex-nav-tab-wrapper{background-color:#fcfcfc;border-bottom:2px solid #dadada;-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 100%;flex:1 1 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%}.tsf-flex-nav-tab-inner{-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex:1 0 auto;flex:1 0 auto}.tsf-flex-nav-tab{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;-webkit-flex-direction:row;flex-direction:row;box-shadow:0 0 0 0 transparent inset;-webkit-transition:box-shadow .15s ease-out;-o-transition:box-shadow .15s ease-out;transition:box-shadow .15s ease-out;-webkit-align-items:center;align-items:center;-webkit-align-content:space-between;align-content:space-between}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-transition:box-shadow .25s ease-in;-o-transition:box-shadow .25s ease-in;transition:box-shadow .25s ease-in}.tsf-flex-tab-content{-webkit-flex:1 0 100%;flex:1 0 100%;max-width:100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:0 1 auto;flex:0 1 auto}.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-checkbox-wrapper{margin-top:15px}.tsf-checkbox-wrapper:first-child{margin-top: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:color .33s ease-in,text-shadow .33s ease-in;-o-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .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:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .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:color .33s ease-in,text-shadow .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}}.tsf-flex-hide-if-no-js,body.js .tsf-flex-hide-if-js{display:none}body.js .tsf-flex-hide-if-no-js{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}
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-item{text-decoration:none;font-size:13px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#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,#tsf-title-placeholder-prefix{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:pre;text-overflow:ellipsis;will-change:left,right}.tsf-counter-wrap{margin-top:15px}.tsf-counter{font-weight:400;color:#666;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;will-change:contents}.tsf-count-bad{color:#dd3811}.tsf-count-okay{color:#ffa700}.tsf-count-good{color:#0cc34b}.tsf-counter-one{color:#fff;border-radius:4em;padding:0 .5em;min-width:2em;display:inline-block;text-align:center;vertical-align:baseline}.tsf-counter-one.tsf-count-bad{background-color:#dd3811}.tsf-counter-one.tsf-count-okay{background-color:#ffa700}.tsf-counter-one.tsf-count-good{background-color:#0cc34b}.tsf-tabs-content .tsf-pixel-counter-wrap{margin-left:1px;max-width:99%}.tsf-pixel-shadow-wrap{position:relative;overflow:hidden;width:0;height:0}.tsf-pixel-counter-wrap{border-bottom:1px solid #ccc;margin-top:12px;margin-bottom:3px}.tsf-pixel-counter-bar{padding-top:7px;display:block;height:3px;width:100%}.tsf-pixel-counter-fluid{display:block;pointer-events:none;height:3px;width:0;max-width:100%;background:#007bd2;box-shadow:0 1px 3px 0 #ccc;-webkit-transition:width .15s cubic-bezier(.4,0,.75,1);-o-transition:width .15s cubic-bezier(.4,0,.75,1);transition:width .15s cubic-bezier(.4,0,.75,1)}.tsf-pixel-counter-overflown .tsf-pixel-counter-fluid{background-color:#dd3811}.tsf-pixel-counter-fit .tsf-pixel-counter-fluid{background-color:#0cc34b}.tsf-description-pixel-counter-shadow,.tsf-title-pixel-counter-shadow{position:absolute;left:0;top:0;z-index:-100;overflow:visible;visibility:hidden;padding:0;margin:0;border:0;display:inline;text-decoration:none;white-space:nowrap;word-wrap:normal;zoom:1;text-overflow:clip;-webkit-transition:none;-moz-transition:none;-o-transition:none;-ms-transition:none;transition:none;font-size:18px;font-weight:600}.tsf-description-pixel-counter-shadow{font-size:13px;font-weight:400}#tsf-seo-bar-wrap{width:18%}th:last-of-type#tsf-seo-bar-wrap{width:160px}.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)}.tsf-seo-bar.tsf-100{width:100%}.tsf-seo-bar-inner-wrap{display:table;width:100%;border-radius:0;margin:0 auto;border-collapse:separate;border-spacing:0;vertical-align:middle}.tsf-seo-bar-section-wrap{display:table-cell;border-collapse:collapse}.tsf-seo-bar-item{display:table;width:100%;color:#fff;text-align:center;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}body.no-js .tsf-seo-bar-item{cursor:default}.tsf-seo-bar.pill,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap{border-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-item{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 .tsf-seo-bar-section-wrap:first-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap .tsf-seo-bar-section-wrap:first-of-type .tsf-seo-bar-item{border-top-left-radius:30px;border-bottom-left-radius:30px}.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap .tsf-seo-bar-section-wrap:last-of-type,.tsf-seo-bar.pill .tsf-seo-bar-inner-wrap .tsf-seo-bar-section-wrap:last-of-type .tsf-seo-bar-item{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%}.tsf-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}.tsf-tooltip-wrap{position:relative}.tsf-tooltip-item{cursor:help}a.tsf-tooltip-item{cursor:auto}.tsf-tooltip{position:absolute;padding:0;margin:0;bottom:0;left:0;z-index:900142;text-align:left;pointer-events:none;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 auto;flex:1 1 auto;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:flex-start;justify-content:flex-start}.tsf-tooltip-down{bottom:auto;top:0}.tsf-tooltip-text-wrap{padding:10px 12px;font-size:1em;font-weight:500;line-height:1.625em;border-radius:3px;background:#007bd2;color:#fdfdfd;box-shadow:0 0 2px rgba(0,0,0,.6);text-shadow:none;word-wrap:break-word;overflow-wrap:break-word;word-break:break-word;white-space:pre-line;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 0 150px;flex:1 0 150px;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:flex-start;justify-content:flex-start}.tsf-is-primary-term,.tsf-nav-tab{font-weight:600}.tsf-tooltip-text span{text-decoration:underline}.tsf-tooltip-text br{display:block;width:100%;content:"\A"}.tsf-ajax:before,.tsf-tooltip-arrow:after,.tsf-tooltip-arrow:before{content:""}.tsf-tooltip-arrow{position:absolute;bottom:-8px;z-index:9999999;left:0;width:0;height:0}.tsf-tooltip-down .tsf-tooltip-arrow{bottom:auto;top:-8px}.tsf-tooltip-arrow:before{border-left:9px solid transparent;border-right:9px solid transparent;border-top:9px solid rgba(0,0,0,.25);position:absolute;bottom:-1px;left:-1px}.tsf-tooltip-arrow:after{border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #007bd2;position:absolute;bottom:0;left:0}.tsf-tooltip-down .tsf-tooltip-arrow:before{bottom:auto;top:0;border-top:0;border-bottom:9px solid rgba(0,0,0,.25)}.tsf-tooltip-down .tsf-tooltip-arrow:after{bottom:auto;top:1px;border-top:0;border-bottom:8px solid #007bd2}.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-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-top-wrap>h1,.tsf-top-wrap>h2{float:left}.tsf-metaboxes .metabox-holder{clear:both}.tsf-top-buttons{float:right}.tsf-bottom-buttons{text-align:right}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}#tsf-description-separator,#tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}#tsf-description-separator input,#tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}#tsf-description-separator label,#tsf-title-separator label{display:inline-block;width:auto;min-width:28px;min-height:28px;margin:3px;-moz-margin-end:1.5px;-moz-margin-start:1.5px;padding:0 4px;border:1px solid #ccc;line-height:28px;text-align:center;cursor:pointer;box-shadow:-1px -1px 1px #aaa inset;font-size:16px}#tsf-description-separator label.tsf-recommended,#tsf-title-separator label.tsf-recommended{border:1px solid #0cc34b;box-shadow:-1px -1px 1px #0cc34b inset}#tsf-description-separator input:hover+label,#tsf-description-separator label:hover,#tsf-title-separator input:hover+label,#tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}#tsf-description-separator input:checked+label,#tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}#tsf-home-title-location,#tsf-title-location{display:block}#tsf-home-title-location label span,#tsf-title-location label span,#tsf-twitter-cards label span{display:inline-block;min-width:60px;vertical-align:baseline}#tsf-twitter-cards label span{min-width:150px}#tsf-home-title-location label .tsf-sep-js,#tsf-home-title-location label span.tsf-custom-blogname-js,#tsf-home-title-location label span.tsf-custom-tagline-js,#tsf-home-title-location label span.tsf-custom-title-js,#tsf-title-location label .tsf-sep-js{display:inline;min-width:0;white-space:pre}.tsf-nav-tab-wrapper,.tsf-tab-no-js{position:relative;clear:both;width:100%;display:inline-block;border-bottom:1px solid #ccc;line-height:inherit;padding:8px 12px 0;margin:-4px -12px}.tsf-nav-tab{float:left;border:1px solid #ccc;margin-left:.5em;margin-bottom:-1px;padding:5px 14px;font-size:12px;line-height:16px;background:#f1f1f1;color:#555}.tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}input.tsf-tabs-radio{display:none;width:0;height:0;position:absolute;left:-9001px}.tsf-active-tab,.tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-tabs-content{margin:1.33em auto 0}.tsf-content-no-js{margin:1.33em auto}body.js .tsf-tabs-content{display:none}body.js .tsf-tabs-content.tsf-active-tab-content{display:block}#tsf-inpost-box .inside,.tsf-flex{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1 1 auto;flex:1 1 auto;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-flex-direction:column;flex-direction:column;-webkit-justify-content:flex-start;justify-content:flex-start}#tsf-inpost-box.closed .inside,body.js .tsf-flex-tab-content{display:none}#tsf-inpost-box .inside{margin:0;padding:0;-webkit-flex:1 0 100%;flex:1 0 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.tsf-flex-inside-wrap{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto}.tsf-flex-setting{width:100%;-webkit-flex-direction:row;flex-direction:row}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;-webkit-flex:10 1 350px;flex:10 1 350px;box-shadow:0 0 0 1px #e9e9e9}.tsf-flex-setting-label{background-color:#f9f9f9;-webkit-flex:1 1 200px;flex:1 1 200px}.tsf-flex-setting-input{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex-direction:row;flex-direction:row;-webkit-justify-content:space-between;justify-content:space-between;-webkit-flex-grow:0;flex-grow:0}.tsf-flex-setting-label-inner-wrap{-webkit-justify-content:center;justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}.tsf-flex-setting-input textarea{max-height:250px}input[type=radio].tsf-flex-nav-tab-radio{display:none;width:0;height:0;margin:0;padding:0;position:absolute;left:-9001px}.tsf-flex-nav-tab-wrapper{background-color:#fcfcfc;border-bottom:2px solid #dadada;-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 100%;flex:1 1 100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-width:100%}.tsf-flex-nav-tab-inner{-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-flex:1 0 auto;flex:1 0 auto}.tsf-flex-nav-tab{-webkit-flex-direction:row;flex-direction:row;-webkit-flex:1 1 auto;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;-webkit-flex-direction:row;flex-direction:row;box-shadow:0 0 0 0 transparent inset;-webkit-transition:box-shadow .15s ease-out;-o-transition:box-shadow .15s ease-out;transition:box-shadow .15s ease-out;-webkit-align-items:center;align-items:center;-webkit-align-content:space-between;align-content:space-between}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-transition:box-shadow .25s ease-in;-o-transition:box-shadow .25s ease-in;transition:box-shadow .25s ease-in}.tsf-flex-tab-content{-webkit-flex:1 0 100%;flex:1 0 100%;max-width:100%;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{-webkit-align-items:baseline;align-items:baseline;-webkit-flex-direction:row;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;-webkit-flex-direction:row;flex-direction:row;-webkit-flex:0 1 auto;flex:0 1 auto}#tsf-inpost-box .hndle .tsf-tooltip-wrap a{font-size:14px;line-height:1em}.tsf-primary-term-selector{margin:0;padding:0;float:right;line-height:inherit;display:inline-block}.tsf-primary-term-selector input{vertical-align:middle;height:14px;width:14px;min-width:14px;line-height:inherit;margin:0;padding:0;pointer-events:none}.tsf-primary-term-selector input:checked:before{width:6px;height:6px;margin:3px;line-height:inherit}.tsf-primary-term-selector-help-wrap{position:absolute;top:0;right:25px}.tsf-default-selected{border-color:#1c9d38}.tsf-default-selected:checked:before{color:#1c9d38}.tsf-warning-selected{border-color:#dd3811}.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-checkbox-wrapper{margin-top:15px}.tsf-checkbox-wrapper:first-child{margin-top:0}.tsf-metaboxes legend h4{margin:2px 0}.tsf-metaboxes legend p:last-of-type{margin-bottom: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}.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:color .33s ease-in,text-shadow .33s ease-in;-o-transition:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .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:color .33s ease-in,text-shadow .33s ease-in;transition:color .33s ease-in,text-shadow .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:color .33s ease-in,text-shadow .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-home-title-location label span,#tsf-title-location label span{min-width:40px}.wp-list-table .is-expanded td.tsf-seo-bar-wrap:not(.hidden){overflow:initial!important}.tsf-primary-term-selector input{height:18px;width:18px;min-width:18px}.tsf-primary-term-selector input:checked:before{width:8px;height:8px;margin:4px}}@media screen and (max-width:642px){.tsf-nav-desktop{display:none}}@media screen and (max-width:510px){.tsf-seo-bar.tsf-100{width:inherit}}@-moz-document url-prefix(){#tsf-description-separator label,#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-default-selected{box-shadow:0 0 2px 0 #1c9d38}.tsf-warning-selected{box-shadow:0 0 2px 0 #dd3811}}.tsf-flex-hide-if-no-js,body.js .tsf-flex-hide-if-js{display:none}body.js .tsf-flex-hide-if-no-js{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}
lib/js/{tsf.externs.js → externs/tsf.externs.js} RENAMED
File without changes
lib/js/{tsf.externs.protected.js → externs/tsf.externs.protected.js} RENAMED
@@ -44,7 +44,7 @@ tsf.prototype.settingsChanged;
44
  * @protected
45
  * @type {Boolean}
46
  */
47
- tsf.prototype.titleTagline;
48
 
49
  /**
50
  * @protected
44
  * @protected
45
  * @type {Boolean}
46
  */
47
+ tsf.prototype.useTagline;
48
 
49
  /**
50
  * @protected
lib/js/tsf.js CHANGED
@@ -2,7 +2,7 @@
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
 
@@ -27,7 +27,7 @@
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
 
@@ -43,16 +43,6 @@
43
  */
44
  window.tsf = {
45
 
46
- /**
47
- * AJAX Nonce string.
48
- *
49
- * @since 2.7.0
50
- * @todo deprecate
51
- *
52
- * @type {String} nonce The AJAX nonce
53
- */
54
- nonce : tsfL10n.nonce,
55
-
56
  /**
57
  * AJAX Nonces object.
58
  *
@@ -111,33 +101,6 @@ window.tsf = {
111
  */
112
  settingsChanged: false,
113
 
114
- /**
115
- * The current title tagline.
116
- *
117
- * @since 2.5.0
118
- *
119
- * @type {(Boolean|null)} titleTagline
120
- */
121
- titleTagline : false,
122
-
123
- /**
124
- * The current title separator.
125
- *
126
- * @since 2.7.0
127
- *
128
- * @type {(String|null)} titleSeparator
129
- */
130
- titleSeparator : '',
131
-
132
- /**
133
- * The current description separator.
134
- *
135
- * @since 2.7.0
136
- *
137
- * @type {(String|null)} descriptionSeparator
138
- */
139
- descriptionSeparator : '',
140
-
141
  /**
142
  * Mixed string and int (i10n is string, JS is int).
143
  *
@@ -175,1399 +138,2246 @@ window.tsf = {
175
  cropper : {},
176
 
177
  /**
178
- * Cached doctitle function.
179
  *
180
- * @since 2.3.3
181
- * @todo Convert to class var instead of function call. It's much faster.
182
- * i.e. setDocTitles() == docTitles : {}
183
  *
184
  * @function
185
- * @return {!jQuery} The jQuery doctitle ID's
 
186
  */
187
- docTitles: function() {
188
- /** Concept:
189
- if ( this.docTitles.cache )
190
- return this.docTitles.cache;
191
-
192
- let $doctitles = this.docTitles.cache = jQuery( "#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]" );
193
- */
194
-
195
- let $doctitles = jQuery( "#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]" );
196
-
197
- return $doctitles;
198
  },
199
 
200
  /**
201
- * Cached description function.
202
  *
203
- * @since 2.5.0
204
- * @todo Convert to class var instead of function call. It's much faster.
205
  *
 
206
  * @function
207
- * @return {!jQuery} The jQuery description ID's
 
208
  */
209
- docDescriptions: function() {
210
- /** Concept:
211
- if ( this.docDescriptions.cache )
212
- return this.docDescriptions.cache;
213
 
214
- let $descriptions = this.docDescriptions.cache = jQuery( "#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]" );
215
- */
216
 
217
- let $descriptions = jQuery( "#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]" );
 
 
 
 
 
 
218
 
219
- return $descriptions;
 
 
220
  },
221
 
222
  /**
223
- * Helper function for confirming a user action.
224
- *
225
- * @since 2.2.4
226
  *
227
  * @function
228
- * @param {String} text The text to display.
229
- * @return {(Boolean|null)} True on OK, false on cancel.
230
  */
231
- confirm: function( text ) {
232
- return confirm( text );
 
 
 
 
 
 
 
 
233
  },
234
 
235
  /**
236
- * Description length counter.
237
- *
238
- * @since 2.2.4
239
- * @since 2.9.3 Refactored to plain JS for discovering performance bugs.
240
  *
241
  * @function
242
- * @param {!jQuery.Event} event
243
  * @return {undefined}
244
  */
245
- updateCharacterCountDescription: function( event ) {
246
-
247
- let calcLength = event.target.value && event.target.value.length || 0,
248
- item = document.getElementById( event.target.id + '_chars' ),
249
- counterType = tsf.counterType,
250
- additionsClass = tsf.additionsClass,
251
- counterClass = '',
252
- name = '',
253
- output = '';
254
-
255
- // Emptied input, get Description placeholder.
256
- if ( 0 === calcLength ) {
257
- //* Output length from placeholder.
258
- calcLength = event.target.placeholder && event.target.placeholder.length;
259
- }
260
-
261
- if ( calcLength < 100 || calcLength >= 175 ) {
262
- counterClass = 'tsf-count-bad';
263
- name = tsf.getCounterName( 'bad' );
264
- } else if ( calcLength < 137 || ( calcLength > 155 && calcLength < 175 ) ) {
265
- counterClass = 'tsf-count-okay';
266
- name = tsf.getCounterName( 'okay' );
 
 
 
 
 
 
 
 
267
  } else {
268
- counterClass = 'tsf-count-good';
269
- name = tsf.getCounterName( 'good' );
 
270
  }
271
 
272
- //* Not strict by design.
273
- if ( counterType < 2 ) {
274
- output = calcLength;
275
- } else if ( 2 == counterType ) {
276
- output = name;
277
- } else if ( 3 == counterType ) {
278
- output = calcLength + ' - ' + name;
279
- }
280
 
281
- item.innerHTML = output;
 
282
 
283
- if ( additionsClass )
284
- counterClass += ' ' + additionsClass;
 
 
285
 
286
- if ( item.className !== counterClass )
287
- item.className = counterClass;
 
288
  },
289
 
290
  /**
291
- * Title length counter, with special characters
 
292
  *
293
- * @since 2.2.4
294
  *
295
  * @function
296
- * @param {!jQuery.Event} event
297
  * @return {undefined}
298
  */
299
- updateCharacterCountTitle: function( event ) {
300
-
301
- var $this = jQuery( event.target ),
302
- additions = tsf.params['titleAdditions'].length,
303
- description = tsf.params['blogDescription'].length,
304
- siteTitle = tsf.params['siteTitle'].length,
305
- titleLength = event.target.value && event.target.value.length || 0,
306
- placeholder = jQuery( event.target ).prop( 'placeholder' ).length,
307
- tagline = jQuery( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).val(),
308
- seplen = 3,
309
- $counter = jQuery( '#' + tsf.escapeStr( event.target.id ) + '_chars' ),
310
- calcLength = 0,
311
- additionsClass = tsf.additionsClass,
312
- counterType = tsf.counterType,
313
- counterClass = '',
314
- name = '',
315
- output = '';
316
-
317
- // Additions or tagline removed, remove additions and separator.
318
- if ( ! tsf.titleTagline ) {
319
- additions = 0;
320
- seplen = 0;
321
- }
322
-
323
- // Emptied input, get Site title.
324
- if ( 0 === titleLength ) {
325
- if ( 0 !== siteTitle ) {
326
- titleLength = siteTitle;
327
- } else {
328
- //* Output length from placeholder.
329
- calcLength = placeholder;
330
- }
331
- }
332
 
333
- // Length should be something now.
334
- if ( 0 !== titleLength ) {
 
 
335
 
336
- if ( 0 !== additions && typeof tagline !== 'undefined' ) {
337
- var $tagLength = tagline.length;
338
 
339
- // Replace additions with tagline is tagline isn't empty.
340
- if ( 0 !== $tagLength ) {
341
- additions = $tagLength;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  } else {
343
- additions = description;
 
 
 
 
 
344
  }
345
  }
346
 
347
- // Put it all together
348
- if ( 0 === additions ) {
349
- calcLength = titleLength;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  } else {
351
- calcLength = titleLength + seplen + additions;
 
 
352
  }
353
- }
354
 
355
- if ( calcLength < 25 || calcLength >= 75 ) {
356
- counterClass = 'tsf-count-bad';
357
- name = tsf.getCounterName( 'bad' );
358
- } else if ( calcLength < 42 || ( calcLength > 55 && calcLength < 75 ) ) {
359
- counterClass = 'tsf-count-okay';
360
- name = tsf.getCounterName( 'okay' );
361
- } else {
362
- counterClass = 'tsf-count-good';
363
- name = tsf.getCounterName( 'good' );
364
- }
365
 
366
- if ( additionsClass )
367
- counterClass += ' ' + additionsClass;
 
 
 
 
368
 
369
- if ( ! counterType || 1 == counterType ) {
370
- output = calcLength.toString();
371
- } else if ( 2 == counterType ) {
372
- output = name;
373
- } else if ( 3 == counterType ) {
374
- output = calcLength.toString() + ' - ' + name;
375
  }
 
 
 
 
 
 
 
 
 
 
376
 
377
- $counter.text( output ).removeClass().addClass( counterClass );
378
- },
379
-
380
- /**
381
- * Escapes HTML strings.
382
- *
383
- * @since 2.2.4
384
- *
385
- * @function
386
- *
387
- * @param {String} str
388
- * @return {(String|null)} HTML to jQuery converted string
389
- */
390
- escapeStr: function( str ) {
391
 
392
- if ( str )
393
- return str.replace( /([\[\]\/])/g, '\\$1' );
 
 
 
 
394
 
395
- return str;
396
- },
 
397
 
398
- /**
399
- * Dynamic Title separator replacement in metabox
400
- *
401
- * @since 2.2.2
402
- *
403
- * @function
404
- * @param {!jQuery.Event} event
405
- * @return {undefined}
406
- */
407
- separatorSwitchTitle: function( event ) {
408
 
409
- let $sep = jQuery( ".tsf-sep-js" ),
410
- val = jQuery( event.target ).val();
411
 
412
- //* Update cache.
413
- tsf.titleSeparator = val;
414
 
415
- if ( 'pipe' === val ) {
416
- $sep.text( " | " );
417
- } else if ( 'dash' === val ) {
418
- $sep.text( " - " );
419
- } else {
420
- $sep.html( " &" + val + "; " ).text();
421
- }
422
- },
423
 
424
- /**
425
- * Dynamic Description separator replacement in metabox
426
- *
427
- * @since 2.3.4
428
- * @since 2.9.3 Removed sanitation on hardcoded input.
429
- *
430
- * @function
431
- * @param {!jQuery.Event} event
432
- * @return {undefined}
433
- */
434
- separatorSwitchDesc: function( event ) {
435
 
436
- let $sep = jQuery( "#autodescription-descsep-js" ),
437
- val = jQuery( event.target ).val();
 
 
 
438
 
439
- if ( 'pipe' === val ) {
440
- $sep.text( " | " );
441
- } else if ( 'dash' === val ) {
442
- $sep.text( " - " );
443
- } else {
444
- $sep.html( " &" + val + "; " ).text();
445
- }
446
- },
447
 
448
- /**
449
- * Status bar description init on hover actions.
450
- *
451
- * @since 2.1.9
452
- *
453
- * @function
454
- * @return {undefined}
455
- */
456
- statusBarHover: function() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
 
458
- let $wrap = jQuery( '.tsf-seo-bar-inner-wrap' ).find( 'a' );
459
 
460
- $wrap.off( 'mouseenter mousemove mouseleave mouseout' );
 
 
461
 
462
- $wrap.on( {
463
- 'mouseenter' : tsf.statusBarHoverEnter,
464
- 'mousemove' : tsf.statusBarHoverMove,
465
- 'mouseleave' : tsf.statusBarHoverLeave,
466
- 'mouseout' : tsf.statusBarHoverLeave,
467
- } );
468
- },
469
 
470
- /**
471
- * Status bar description output on hover enter.
472
- *
473
- * @since 2.6.0
474
- *
475
- * @function
476
- * @param {!jQuery.Event} event
477
- * @return {undefined}
478
- */
479
- statusBarHoverEnter: function( event ) {
480
 
481
- let $this = jQuery( event.target ),
482
- desc = $this.data( 'desc' );
 
 
 
 
 
483
 
484
- if ( desc !== undefined && 0 === $this.find( 'div' ).length ) {
485
- $this.append( '<div class="tsf-explanation-desc">' + desc + '<div></div></div>' );
486
 
487
- let height = $this.find( 'div.tsf-explanation-desc' ).height() + 28;
 
 
 
 
 
 
 
 
 
 
 
488
 
489
- $this.find( 'div.tsf-explanation-desc' ).css( 'top', ( $this.position().top - height ) + 'px' );
 
 
490
  }
491
- },
492
 
493
- /**
494
- * Status bar description output on hover move.
495
- *
496
- * @since 2.6.0
497
- *
498
- * @function
499
- * @param {!jQuery.Event} event
500
- * @return {undefined}
501
- */
502
- statusBarHoverMove: function( event ) {
503
-
504
- var $this = jQuery( event.target ),
505
- pagex = event.pageX,
506
- mousex = pagex - $this.closest( '.tsf-seo-bar-inner-wrap' ).offset().left - 11, // 22px width of arrow / 2 = 11 middle
507
- $balloon = $this.find( '.tsf-explanation-desc' ),
508
- $arrow = $balloon.find( 'div' );
509
-
510
- if ( mousex < 1 ) {
511
- $arrow.css( 'left', 0 + "px" );
512
- } else if ( $balloon.offset() !== undefined ) {
513
- let width = $balloon.width(),
514
- maxOffset = $balloon.offset().left + width + 11;
515
-
516
- if ( pagex > maxOffset ) {
517
- $arrow.css( 'left', width + "px" );
518
- } else {
519
- $arrow.css( 'left', mousex + "px" );
520
  }
521
- }
522
- },
523
 
524
- /**
525
- * Status bar description removal on hover leave.
526
- *
527
- * @since 2.6.0
528
- *
529
- * @function
530
- * @param {!jQuery.Event} event
531
- * @return {undefined}
532
- */
533
- statusBarHoverLeave: function( event ) {
534
- jQuery( event.target ).find( 'div.tsf-explanation-desc' ).remove();
535
- },
536
 
537
- /**
538
- * Remove Status bar desc if clicked outside (touch support).
539
- *
540
- * @since 2.9.3
541
- *
542
- * @function
543
- * @param {jQuery.event} event jQuery event
544
- */
545
- touchRemoveDesc: function( event ) {
546
 
547
- let $target = jQuery( event.target ),
548
- hasBalloon = $target.closest( '.tsf-seo-bar-inner-wrap a' ).length;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
549
 
550
- if ( ! hasBalloon ) {
551
- $target.closest( '.tsf-seo-bar-inner-wrap a' ).find( 'div.tsf-explanation-desc' ).remove();
552
- }
553
- },
554
 
555
- /**
556
- * Sets correct tab content and classes on toggle.
557
- *
558
- * @since 2.2.2
559
- * @since 2.6.0 Improved.
560
- * @since 2.9.0 Now always expects radio button input.
561
- * @see tsf.setTabsOnload
562
- *
563
- * @function
564
- * @param {!jQuery.Event} event
565
- * @return {(undefined|null)}
566
- */
567
- tabToggle: function( event ) {
568
 
569
- let $this = jQuery( event.target );
570
 
571
- if ( ! $this.is( ':checked' ) )
572
- return;
 
 
 
 
 
573
 
574
- let target = $this.prop( 'id' ),
575
- name = $this.prop( 'name' );
576
 
577
- if ( typeof name !== 'undefined' ) {
578
- let activeClass = 'tsf-active-tab-content',
579
- $newContent = jQuery( '#' + target + '-content' ),
580
- $previousContent = jQuery( '.' + activeClass );
 
 
581
 
582
- //* Only parse if old content isn't the new.
583
- if ( ! $newContent.is( $previousContent ) && typeof $newContent !== 'undefined' ) {
584
- let $allContent = jQuery( '.' + name + '-content' );
 
 
 
 
585
 
586
- $allContent.fadeOut( 150, function() {
587
- jQuery( this ).removeClass( activeClass );
588
- } );
589
- setTimeout( function() {
590
- $newContent.addClass( activeClass ).fadeIn( 250 );
591
- }, 150 );
592
- setTimeout( function() {
593
- jQuery( '#' + target ).trigger( 'tsf-tab-toggled' );
594
- }, 175 );
595
  }
596
- }
597
- },
598
 
599
- /**
600
- * Refines Styling for the navigation tabs on the settings pages
601
- *
602
- * @since 2.9.0
603
- * @todo merge with tabTobble or a collective method?
604
- *
605
- * @function
606
- * @param {!jQuery.Event} event
607
- * @return {(undefined|null)}
608
- */
609
- flexTabToggle : function( event ) {
610
 
611
- let $this = jQuery( event.target );
612
 
613
- if ( ! $this.is( ':checked' ) )
614
- return;
615
 
616
- let target = $this.prop( 'id' ),
617
- name = $this.prop( 'name' );
 
 
 
618
 
619
- if ( typeof name !== 'undefined' ) {
620
- let activeClass = 'tsf-flex-tab-content-active',
621
- $newContent = jQuery( '#' + target + '-content' ),
622
- $previousContent = jQuery( '.' + activeClass );
623
 
624
- //* Only parse if old content isn't the new.
625
- if ( ! $newContent.is( $previousContent ) && typeof $newContent !== 'undefined' ) {
626
- let $allContent = jQuery( '.' + name + '-content' );
627
 
628
- $allContent.fadeOut( 150, function() {
629
- jQuery( this ).removeClass( activeClass );
630
- } );
631
- setTimeout( function() {
632
- $newContent.addClass( activeClass ).fadeIn( 250 );
633
- }, 150 );
634
- setTimeout( function() {
635
- jQuery( '#' + target ).trigger( 'tsf-flex-tab-toggled' );
636
- }, 175 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
637
  }
 
 
 
 
 
 
 
 
638
  }
639
- },
640
 
641
- /**
642
- * Sets the navigation tabs content equal to the buttons.
643
- *
644
- * @since 2.9.0
645
- * @see tsf.tabToggle
646
- *
647
- * @function
648
- * @return {(undefined|null)}
649
- */
650
- setTabsOnload: function() {
 
 
 
 
 
651
 
652
- if ( tsf.hasInput ) {
653
- if ( tsf.states['isSettingsPage'] ) {
654
- let $buttons = jQuery( '.tsf-nav-tab-wrapper .tsf-tab:nth-of-type(n+2) input:checked' );
655
-
656
- // Select all second or later tabs that have attribute checked.
657
- if ( $buttons.length ) {
658
- $buttons.each( function( i ) {
659
- let $this = jQuery( this ),
660
- target = $this.prop( 'id' ),
661
- name = $this.prop( 'name' );
662
-
663
- if ( typeof name !== 'undefined' ) {
664
- let activeClass = 'tsf-active-tab-content',
665
- $newContent = jQuery( '#' + target + '-content' );
666
-
667
- //* Only parse if old content isn't the new.
668
- if ( typeof $newContent !== 'undefined' ) {
669
- let $allContent = jQuery( '.' + name + '-content' );
670
-
671
- $allContent.removeClass( activeClass );
672
- $newContent.addClass( activeClass );
673
- setTimeout( function() {
674
- jQuery( '#' + target ).trigger( 'tsf-tab-toggled' );
675
- }, 20 );
676
- }
677
- }
678
- } );
679
- }
680
- } else {
681
- // WordPress resets radio buttons on inpost settings. Leave this open for "when".
682
- }
683
  }
684
- },
685
 
686
- /**
687
- * Toggle tagline within the Left/Right example for the HomePage Title
688
- *
689
- * @since 2.2.4
690
- *
691
- * @function
692
- * @param {!jQuery.Event} event
693
- * @return {undefined}
694
- */
695
- taglineToggleTitle: function( event ) {
696
 
697
- let $this = jQuery( event.target ),
698
- $tag = jQuery( '.tsf-custom-blogname-js' );
 
 
 
 
 
 
 
 
699
 
700
- if ( $this.is( ':checked' ) ) {
701
- $tag.css( 'display', 'inline' );
702
- tsf.titleTagline = true;
703
- } else {
704
- $tag.css( 'display', 'none' );
705
- tsf.titleTagline = false;
 
 
 
706
  }
 
 
707
 
708
- tsf.docTitles().trigger( 'keyup', tsf.updateCharacterCountTitle );
709
- },
 
 
 
 
 
 
 
 
 
 
 
710
 
711
- /**
712
- * Toggle tagline within the Description Example.
713
- *
714
- * @since 2.3.4
715
- *
716
- * @function
717
- * @param {!jQuery.Event} event
718
- * @return {undefined}
719
- */
720
- taglineToggleDesc: function( event ) {
721
 
722
- let $this = jQuery( event.target ),
723
- $tagDesc = jQuery( '#tsf-on-blogname-js' );
 
 
 
 
 
724
 
725
- if ( $this.is(':checked') ) {
726
- $tagDesc.css( 'display', 'inline' );
727
- } else {
728
- $tagDesc.css( 'display', 'none' );
729
  }
730
- },
731
 
732
- /**
733
- * Toggle title additions location for the Title examples.
734
- *
735
- * @since 2.6.0
736
- *
737
- * @function
738
- * @param {!jQuery.Event} event
739
- * @return {undefined}
740
- */
741
- titleLocationToggle: function( event ) {
742
 
743
- let val = jQuery( event.target ).val(),
744
- $titleExampleLeft = jQuery( '.tsf-title-additions-example-left' ),
745
- $titleExampleRight = jQuery( '.tsf-title-additions-example-right' );
746
 
747
- if ( 'right' === val ) {
748
- $titleExampleLeft.css( 'display', 'none' );
749
- $titleExampleRight.css( 'display', 'inline' );
750
- } else {
751
- $titleExampleLeft.css( 'display', 'inline' );
752
- $titleExampleRight.css( 'display', 'none' );
 
 
 
 
 
 
 
 
 
 
 
 
753
  }
754
- },
755
 
756
- /**
757
- * Toggle title prefixes for the Prefix Title example.
758
- *
759
- * @since 2.6.0
760
- *
761
- * @function
762
- * @param {!jQuery.Event} event
763
- * @return {undefined}
764
- */
765
- titlePrefixToggle: function( event ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
766
 
767
- let $this = jQuery( event.target ),
768
- $prefix = jQuery( '.tsf-title-prefix-example' );
 
 
769
 
770
- if ( $this.is(':checked') ) {
771
- $prefix.css( 'display', 'none' );
772
- } else {
773
- $prefix.css( 'display', 'inline' );
 
 
 
 
 
 
 
774
  }
775
- },
 
 
776
 
777
- /**
778
- * Toggle additions within Description example for the Example Description
779
- *
780
- * @since 2.6.0
781
- *
782
- * @function
783
- * @param {!jQuery.Event} event
784
- * @return {undefined}
785
- */
786
- additionsToggleDesc: function( event ) {
 
 
 
787
 
788
- let $this = jQuery( event.target ),
789
- $tagDesc = jQuery( '#tsf-description-additions-js' );
 
 
 
 
 
 
 
 
 
 
790
 
791
- if ( $this.is(':checked') ) {
792
- $tagDesc.css( 'display', 'inline' );
793
- } else {
794
- $tagDesc.css( 'display', 'none' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
795
  }
 
796
  },
797
 
798
  /**
799
- * Toggle tagline end examples within the Left/Right example for the
800
- * HomePage Title or Description.
801
  *
802
- * @since 2.2.7
803
  *
804
  * @function
805
  * @return {undefined}
806
  */
807
- taglineToggleOnload: function() {
808
 
809
  if ( ! tsf.hasInput )
810
  return;
811
 
812
- let $tagTitle = jQuery( '#tsf-title-tagline-toggle :input' ),
813
- $title = jQuery( '.tsf-custom-blogname-js' ),
814
- $tagDescAdditions = jQuery( '#tsf-description-additions-toggle :input' ),
815
- $descAdditions = jQuery( '#tsf-description-additions-js' ),
816
- $tagDescBlogname = jQuery( '#tsf-description-onblogname-toggle :input' ),
817
- $descBlogname = jQuery( '#tsf-on-blogname-js' ),
818
- $tagTitleAdditions = jQuery( '#tsf-title-additions-toggle :input' ),
819
- $titleAdditions = jQuery( '.tsf-title-additions-js' );
820
 
821
- if ( $tagTitle.is( ':checked' ) ) {
822
- $title.css( 'display', 'inline' );
823
- } else {
824
- $title.css( 'display', 'none' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
825
  }
 
826
 
827
- if ( $tagDescAdditions.is( ':checked' ) ) {
828
- $descAdditions.css( 'display', 'inline' );
829
- } else {
830
- $descAdditions.css( 'display', 'none' );
 
 
 
 
 
 
 
 
 
831
  }
 
832
 
833
- if ( $tagDescBlogname.is( ':checked' ) ) {
834
- $descBlogname.css( 'display', 'inline' );
835
- } else {
836
- $descBlogname.css( 'display', 'none' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
837
  }
 
838
 
839
- // Reverse option.
840
- if ( $tagTitleAdditions.is( ':checked' ) ) {
841
- $titleAdditions.css( 'display', 'none' );
842
- } else {
843
- $titleAdditions.css( 'display', 'inline' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
844
  }
 
845
  },
846
 
847
  /**
848
- * Change Home Page Title based on input of the Custom Title
 
849
  *
850
- * @since 2.2.4
851
  *
852
  * @function
853
- * @param {!jQuery.Event} event
854
  * @return {undefined}
855
  */
856
- titleProp: function( event ) {
 
 
 
857
 
858
- let val = event.target.value || '',
859
- $title = jQuery( '.tsf-custom-title-js' );
860
 
861
- if ( 0 === val.length ) {
862
- $title.text( tsf.params['siteTitle'] );
863
- } else {
864
- $title.text( val );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
865
  }
866
- },
867
 
868
- /**
869
- * Change Title based on input of the Custom Title
870
- *
871
- * @since 2.3.8
872
- *
873
- * @function
874
- * @param {!jQuery.Event} event
875
- * @return {undefined}
876
- */
877
- taglineProp: function( event ) {
878
 
879
- var val = event.target.value || '',
880
- $floatTag = jQuery( '.tsf-custom-tagline-js' ),
881
- $target = jQuery( '#autodescription-site-settings\\[homepage_title\\]' ),
882
- leftRight = jQuery( '#tsf-home-title-location input:checked' ).val(),
883
- $toggle = jQuery( '#autodescription-site-settings\\[homepage_tagline\\]' ),
884
- title = tsf.params['siteTitle'],
885
- placeholder = title,
886
- description = tsf.params['blogDescription'],
887
- sep = tsf.getSep( 'title' );
 
 
 
 
 
 
888
 
889
- if ( $toggle.is( ':checked' ) ) {
 
 
 
 
 
 
 
 
 
890
 
891
- if ( val.length !== 0 ) {
892
- description = val;
 
 
 
 
893
  }
894
 
895
- if ( leftRight.length !== 0 && 'left' === leftRight ) {
896
- placeholder = title + ' ' + sep + ' ' + description;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
897
  } else {
898
- placeholder = description + ' ' + sep + ' ' + title;
 
 
 
 
 
 
899
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
900
  }
 
901
 
902
- $floatTag.text( description );
903
- $target.prop( 'placeholder', placeholder );
 
 
 
 
 
 
 
 
904
 
905
- // Notify tagline has changed.
906
- tsf.docTitles().trigger( 'input', tsf.updateCharacterCountTitle );
 
 
 
 
 
 
 
 
 
 
 
907
  },
908
 
909
  /**
910
- * Trigger input event for page titles.
911
  *
912
- * @since 2.5.0
913
  *
914
  * @function
915
  * @return {undefined}
916
  */
917
- taglinePropTrigger: function() {
918
 
919
- let settingsChangedCache = tsf.settingsChanged;
 
920
 
921
- if ( tsf.states['isSettingsPage'] ) {
922
- jQuery( "#autodescription-site-settings\\[homepage_title_tagline\\]" ).trigger( 'input', tsf.taglineProp );
923
- } else {
924
- jQuery( "#autodescription_title" ).trigger( 'input', tsf.taglineProp );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
925
  }
 
926
 
927
- // Reset settingsChanged to previous value.
928
- tsf.settingsChanged = settingsChangedCache;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
929
  },
930
 
931
  /**
932
- * Triggers input event for titles in set intervals on window resize.
933
  *
934
- * This only happens if boundaries are surpassed to reduce CPU usage.
935
- * This boundary is 782 pixels, because that forces input fields to change.
936
- * in WordPress.
937
- *
938
- * @since 2.9.0
939
  *
940
  * @function
941
  * @return {undefined}
942
  */
943
- taglinePropTriggerResize: function() {
944
 
945
- let resizeTimeout = 0,
946
- prevWidth = 0;
947
 
948
- jQuery( window ).resize( function() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
949
 
950
- clearTimeout( resizeTimeout );
 
 
951
 
952
- resizeTimeout = setTimeout( function() {
 
 
953
 
954
- let width = jQuery( window ).width();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
955
 
956
- if ( prevWidth < width ) {
957
- if ( prevWidth <= 782 && width >= 782 ) {
958
- tsf.taglinePropTrigger();
959
- }
960
- } else {
961
- if ( prevWidth >= 782 && width <= 782 ) {
962
- tsf.taglinePropTrigger();
963
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
964
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
965
 
966
- prevWidth = width;
967
- }, 250 );
968
- } );
969
- },
970
 
971
- /**
972
- * Trigger Change on Left/Right selection of Global Title
973
- *
974
- * @since 2.5.2
975
- *
976
- * @function
977
- * @return {undefined}
978
- */
979
- titleToggle: function() {
980
 
981
- let $this = jQuery( event.target ),
982
- $tagDesc = jQuery( '.tsf-title-additions-js' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
983
 
984
- if ( $this.is( ':checked' ) ) {
985
- $tagDesc.css( 'display', 'none' );
986
- } else {
987
- $tagDesc.css( 'display', 'inline' );
 
988
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
989
  },
990
 
991
  /**
992
- * Have all form fields in The SEO Framework metaboxes set a dirty flag when changed.
993
  *
994
- * @since 2.0.0
995
- * @since 2.9.3 No longer heavily invokes change listeners after change has been set.
996
  *
997
  * @function
998
  * @return {undefined}
999
  */
1000
- attachUnsavedChangesListener: function() {
1001
 
1002
- if ( ! tsf.hasInput )
1003
- return;
1004
 
1005
- //= Self calling and cancelling function.
1006
- let setUnsetChange = (function( event ) {
1007
- tsf.settingsChanged || tsf.registerChange();
1008
- jQuery( input ).not( except ).off( event.type, setUnsetChange );
1009
- });
 
 
1010
 
1011
- //= Mouse input
1012
- let input = '.tsf-metaboxes :input, #tsf-inpost-box .inside :input',
1013
- except = '.tsf-tab :input, .tsf-flex-nav-tab :input';
1014
- jQuery( input ).not( except ).on( 'change', setUnsetChange );
1015
 
1016
- //= Text input
1017
- input = '.tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea';
1018
- except = '.tsf-nav-tab-wrapper input, .tsf-flex-nav-tab-wrapper input';
1019
- jQuery( input ).not( except ).on( 'input', setUnsetChange );
1020
 
1021
- //= Alert caller (doesn't work well when leave alerts have been disabled)
1022
- window.onbeforeunload = function() {
1023
- if ( tsf.settingsChanged ) {
1024
- return tsf.i18n['saveAlert'];
 
 
 
 
 
 
 
 
 
1025
  }
1026
- };
1027
 
1028
- //= Remove alert on saving object or delete calls.
1029
- jQuery( '.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete' ).click( function() {
1030
- window.onbeforeunload = null;
1031
- } );
1032
- },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1033
 
1034
- /**
1035
- * Set a flag, to indicate form fields have changed.
1036
- *
1037
- * @since 2.2.4
1038
- *
1039
- * @function
1040
- * @return {undefined}
1041
- */
1042
- registerChange: function() {
1043
- tsf.settingsChanged = true;
1044
- },
1045
 
1046
- /**
1047
- * Ask user to confirm that settings should now be reset.
1048
- *
1049
- * @since 2.2.4
1050
- *
1051
- * @function
1052
- * @return {(Boolean|null)} True if reset should occur, false if not.
1053
- */
1054
- confirmedReset: function() {
1055
- return confirm( tsf.i18n['confirmReset'] );
1056
- },
1057
 
1058
- /**
1059
- * Adds dynamic placeholder to Title input based on site settings.
1060
- *
1061
- * @since 2.5.0
1062
- *
1063
- * @function
1064
- * @param {!jQuery.Event} event
1065
- * @return {(!jQuery|undefined)}
1066
- */
1067
- dynamicPlaceholder: function( event ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1068
 
1069
- let hasAdditions = tsf.params['titleAdditions'].length,
1070
- $placeholder = jQuery( '#tsf-title-placeholder' );
 
1071
 
1072
- // If hasAdditions is empty, there's nothing to do.
1073
- if ( ! hasAdditions ) {
1074
- // Empty the placeholder as we can't execute.
1075
- jQuery( event.target ).css( 'text-indent', "initial" );
1076
- return $placeholder.empty();
1077
  }
 
 
 
 
 
 
 
1078
 
1079
- let after = false,
1080
- check = jQuery( '#tsf-home-title-location input:checked' ).val(),
1081
- rtl = tsf.states['isRTL'],
1082
- additions = '';
1083
 
1084
- if ( typeof check !== 'undefined' && check.length !== 0 ) {
1085
- //* We're in SEO Settings page.
1086
 
1087
- if ( rtl ) {
1088
- if ( 'right' === check ) {
1089
- after = true;
1090
- }
1091
- } else {
1092
- if ( 'left' === check ) {
1093
- after = true;
 
 
 
1094
  }
1095
  }
1096
- } else {
1097
- //* We're in post/page edit screen.
1098
 
1099
- let titleLocation = tsf.params['titleLocation'];
1100
-
1101
- // We're on post/page screen.
1102
- if ( tsf.states['isHome'] ) {
1103
- // Static Front page, switch check.
1104
- if ( tsf.titleTagline ) {
1105
- if ( rtl ) {
1106
- if ( 'right' === titleLocation ) {
1107
- after = true;
1108
- }
1109
- } else if ( 'left' === titleLocation ) {
1110
- after = true;
1111
- }
1112
- }
1113
  } else {
1114
- if ( rtl ) {
1115
- if ( 'left' === titleLocation ) {
1116
- after = true;
1117
- }
1118
- } else if ( 'right' === titleLocation ) {
1119
- after = true;
1120
- }
1121
  }
1122
  }
1123
 
1124
- let $tagbox = jQuery( '#tsf-title-tagline-toggle :input' );
 
 
 
 
1125
 
1126
- if ( typeof $tagbox !== "undefined" && $tagbox.length > 0 && ! $tagbox.is( ':checked' ) ) {
1127
- //* We're on SEO Settings Page now, and tagline has been disabled.
1128
- let $this = jQuery( event.target );
1129
 
1130
- $this.css( 'text-indent', "initial" );
1131
- $placeholder.css( 'display', "none" );
1132
- } else {
1133
- var $this = jQuery( event.target ),
1134
- inputVal = $this.val(),
1135
- $offsetTest = jQuery( "#tsf-title-offset" );
1136
 
1137
- let offsetWidth = 0,
1138
- outerWidth = $this.outerWidth(),
1139
- heightPad = ( $this.outerHeight( true ) - $this.height() ) / 2,
1140
- horPad = ( outerWidth - $this.innerWidth() ) / 2,
1141
- leftOffset = ( $this.outerWidth( true ) - $this.width() ) / 2,
1142
- taglineVal = jQuery( "#autodescription-site-settings\\[homepage_title_tagline\\]" ).val(),
1143
- pos = 'left',
1144
- separator = tsf.getSep( 'title' );
1145
 
1146
- if ( rtl ) {
1147
- pos = 'right';
1148
- }
 
1149
 
1150
- if ( typeof taglineVal !== "undefined" && taglineVal.length === 0) {
1151
- taglineVal = tsf.params['blogDescription'];
1152
  }
1153
 
1154
- if ( after ) {
1155
- additions = " " + separator + " " + tsf.params['titleAdditions'];
 
1156
 
1157
- // Exchange the placeholder value of the custom Tagline in the HomePage Metabox
1158
- if ( typeof taglineVal !== "undefined" && taglineVal.length > 0 ) {
1159
- additions = " " + separator + " " + taglineVal;
1160
- }
1161
 
1162
- $this.css( 'text-indent', "initial" );
1163
  } else {
1164
- additions = tsf.params['titleAdditions'] + " " + separator + " ";
 
 
 
 
1165
 
1166
- // Exchange the placeholder value of the custom Tagline in the HomePage Metabox
1167
- if ( typeof taglineVal !== "undefined" && taglineVal.length > 0 ) {
1168
- additions = taglineVal + " " + separator + " ";
 
 
 
1169
  }
1170
  }
1171
 
1172
- // Width offset container, copy variables and remain hidden.
1173
- $offsetTest.text( inputVal );
1174
- $offsetTest.css({
1175
- 'fontFamily' : $this.css( "fontFamily" ),
1176
- 'fontWeight' : $this.css( "fontWeight" ),
1177
- 'letterSpacing' : $this.css( "letterSpacing" ),
1178
- 'fontSize' : $this.css( "fontSize" ),
1179
- });
1180
- offsetWidth = $offsetTest.width();
1181
-
1182
- let maxWidth = $this.width() - horPad - offsetWidth;
1183
-
1184
- if ( maxWidth < 0 )
1185
- maxWidth = 0;
1186
-
1187
- // Moving Placeholder output
1188
- $placeholder.css({
1189
- 'display': $this.css( "display" ),
1190
- 'lineHeight': $this.css( "lineHeight" ),
1191
- 'paddingTop': heightPad + "px",
1192
- 'paddingBottom': heightPad + "px",
1193
- 'fontFamily': $this.css( "fontFamily" ),
1194
- 'fontWeight': $this.css( "fontWeight" ),
1195
- 'fontSize': $this.css( "fontSize" ),
1196
- 'letterSpacing': $this.css( "letterSpacing" ),
1197
- 'maxWidth': maxWidth + "px",
1198
- });
1199
-
1200
- //* Empty or fill placeholder and offsets.
1201
- if ( typeof inputVal === "undefined" || inputVal.length < 1 ) {
1202
-
1203
- if ( ! after )
1204
- $this.css( 'text-indent', "initial" );
1205
-
1206
- $placeholder.empty();
1207
- } else {
1208
- $placeholder.text( additions );
1209
-
1210
- // Only calculate when context is present.
1211
- if ( outerWidth > leftOffset ) {
1212
- if ( after ) {
1213
- $placeholder.css( pos, horPad + leftOffset + $offsetTest.width() + "px" );
1214
- } else {
1215
- let indent = horPad + $placeholder.width();
1216
 
1217
- if ( indent < 0 )
1218
- indent = 0;
 
 
 
 
1219
 
1220
- $placeholder.css( pos, leftOffset + "px" );
1221
- $this.css( 'text-indent', indent + "px" );
1222
- }
1223
- }
1224
- }
1225
  }
 
 
 
 
 
 
 
1226
  },
1227
 
1228
  /**
1229
- * Makes user click act natural by selecting the parent Title text input.
1230
  *
1231
- * @since 2.5.0
1232
  *
1233
  * @function
 
1234
  * @return {undefined}
1235
  */
1236
- selectTitleInput: function() {
1237
-
1238
- let $input = tsf.docTitles();
1239
-
1240
- $input.focus();
1241
-
1242
- if ( $input.setSelectionRange ) {
1243
- // Go to end times 2 if setSelectionRange exists.
1244
- let length = $input.val().length * 2;
1245
- $input.setSelectionRange( length, length );
1246
- } else {
1247
- // Replace value with itself.
1248
- $input.val( $input.val() ).focus();
1249
- }
1250
  },
1251
 
1252
  /**
1253
- * Triggers keyup on description input so the counter can colorize.
1254
  *
1255
- * @since 2.5.0
 
 
 
1256
  *
1257
  * @function
1258
- * @return {undefined}
 
1259
  */
1260
- triggerDescriptionOnLoad: function() {
1261
 
1262
- if ( ! tsf.hasInput )
 
 
1263
  return;
1264
 
1265
- let $input = tsf.docDescriptions();
 
 
 
 
 
 
 
 
 
 
1266
 
1267
- $input.trigger( 'input', tsf.updateCharacterCountDescription );
 
 
 
 
 
 
 
 
 
 
1268
  },
1269
 
1270
  /**
1271
- * Triggers keyup on title input so the counter can colorize.
1272
  *
1273
- * @since 2.6.0
 
1274
  *
1275
  * @function
1276
- * @return {undefined}
 
1277
  */
1278
- triggerTitleOnLoad: function() {
1279
 
1280
- if ( ! tsf.hasInput )
 
 
1281
  return;
1282
 
1283
- let $input = tsf.docTitles();
 
 
 
 
 
 
 
 
 
 
1284
 
1285
- $input.trigger( 'input', tsf.updateCharacterCountTitle );
 
 
 
 
 
 
 
 
 
 
1286
  },
1287
 
1288
  /**
1289
- * OnLoad changes can affect settings changes. This function reverts those.
1290
  *
1291
- * @since 2.5.0
 
1292
  *
1293
  * @function
1294
- * @return {undefined}
1295
  */
1296
- onLoadUnregisterChange: function() {
1297
- //* Prevent trigger of settings change
1298
- tsf.settingsChanged = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1299
  },
1300
 
1301
  /**
1302
- * Dismissible notices. Uses class .tsf-notice.
1303
  *
1304
- * @since 2.6.0
1305
- * @since 2.9.3 Now correctly removes the node from DOM.
1306
  *
1307
  * @function
1308
  * @param {!jQuery.Event} event
1309
  * @return {undefined}
1310
  */
1311
- dismissNotice: function( event ) {
1312
- jQuery( event.target ).parents( '.tsf-notice' ).slideUp( 200, function() {
1313
- this.remove();
1314
- } );
 
 
 
 
 
 
1315
  },
1316
 
1317
  /**
1318
- * Visualizes AJAX loading time through target class change.
1319
  *
1320
- * @since 2.7.0
1321
  *
1322
  * @function
1323
- * @param {String} target
1324
  * @return {undefined}
1325
  */
1326
- setAjaxLoader: function( target ) {
1327
- jQuery( target ).toggleClass( 'tsf-loading' );
 
 
 
 
 
 
 
 
1328
  },
1329
 
1330
  /**
1331
- * Adjusts class loaders on Ajax response.
 
1332
  *
1333
- * @since 2.7.0
1334
  *
1335
  * @function
1336
- * @param {String} target
1337
- * @param {Boolean} success
1338
  * @return {undefined}
1339
  */
1340
- unsetAjaxLoader: function( target, success ) {
1341
 
1342
- let newclass = 'tsf-success',
1343
- fade = 2500;
1344
 
1345
- if ( ! success ) {
1346
- newclass = 'tsf-error';
1347
- fade = 5000;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1348
  }
1349
 
1350
- jQuery( target ).removeClass( 'tsf-loading' ).addClass( newclass ).fadeOut( fade );
 
 
 
 
 
1351
  },
1352
 
1353
  /**
1354
- * Cleans and resets Ajax wrapper class and contents to default.
1355
- * Also stops any animation and resets fadeout to beginning.
1356
  *
1357
- * @since 2.7.0
 
1358
  *
1359
  * @function
1360
- * @param {String} target
1361
  * @return {undefined}
1362
  */
1363
- resetAjaxLoader: function( target ) {
1364
- jQuery( target ).stop().empty().prop( 'class', 'tsf-ajax' ).css( 'opacity', '1' ).removeProp( 'style' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1365
  },
1366
 
1367
  /**
1368
- * Updates the counter type.
1369
  *
1370
- * @since 2.6.0
1371
  *
1372
  * @function
1373
- * @param {!jQuery.Event} event
1374
  * @return {undefined}
1375
  */
1376
- counterUpdate: function( event ) {
1377
-
1378
- // Count up, reset to 0 if needed. We have 4 options: 0, 1, 2, 3
1379
- tsf.counterType = tsf.counterType + 1;
1380
- if ( tsf.counterType > 3 )
1381
- tsf.counterType = 0;
1382
-
1383
- //* Update counters locally.
1384
- tsf.additionsClassInit();
1385
-
1386
- let target = '.tsf-counter .tsf-ajax',
1387
- status = 0;
1388
-
1389
- //* Reset ajax loader
1390
- tsf.resetAjaxLoader( target );
1391
-
1392
- //* Set ajax loader.
1393
- tsf.setAjaxLoader( target );
1394
-
1395
- //* Setup external update.
1396
- let settings = {
1397
- method: 'POST',
1398
- url: ajaxurl,
1399
- datatype: 'json',
1400
- data: {
1401
- 'action' : 'the_seo_framework_update_counter',
1402
- 'nonce' : tsf.nonces['edit_posts'],
1403
- 'val' : tsf.counterType,
1404
- },
1405
- async: true,
1406
- success: function( response ) {
1407
-
1408
- /**
1409
- * @TODO convert to json header and/or test for availability of response.type before parsing?
1410
- * @see convertJSONResponse() @ https://github.com/sybrew/The-SEO-Framework-Extension-Manager/blob/master/lib/js/tsfem.js
1411
- * @see send_json() @ https://github.com/sybrew/The-SEO-Framework-Extension-Manager/blob/master/inc/classes/core.class.php
1412
- */
1413
- response = jQuery.parseJSON( response );
1414
-
1415
- //* I could do value check, but that will simply lag behind. Unless an annoying execution delay is added.
1416
- if ( 'success' === response.type )
1417
- status = 1;
1418
-
1419
- tsf.counterUpdatedResponse( target, status );
1420
- },
1421
- }
1422
-
1423
- jQuery.ajax( settings );
1424
  },
1425
 
1426
  /**
1427
- * Visualizes the AJAX response to the user.
1428
  *
1429
- * @since 2.7.0
1430
  *
1431
  * @function
1432
- * @param {String} target
1433
- * @param {Number} success
1434
- * @return {undefined}
1435
  */
1436
- counterUpdatedResponse: function( target, success ) {
1437
- switch ( success ) {
1438
- case 0:
1439
- tsf.unsetAjaxLoader( target, false );
1440
- break;
1441
- case 1:
1442
- tsf.unsetAjaxLoader( target, true );
1443
- break;
1444
- default:
1445
- tsf.resetAjaxLoader( target );
1446
- break;
1447
- }
1448
  },
1449
 
1450
  /**
1451
- * Sets up additionsClass variable.
1452
- * Also sets up browser caches correctly.
1453
  *
1454
- * @since 2.6.0
1455
  *
1456
  * @function
1457
  * @return {undefined}
1458
  */
1459
- additionsClassInit: function() {
1460
-
1461
- if ( ! tsf.hasInput )
1462
- return;
1463
-
1464
- let counterType = tsf.counterType,
1465
- settingsChangedCache = tsf.settingsChanged;
1466
-
1467
- if ( 1 == counterType ) {
1468
- tsf.additionsClass = 'tsf-counter-one';
1469
- tsf.counterType = 1;
1470
- } else if ( 2 == counterType ) {
1471
- tsf.additionsClass = 'tsf-counter-two';
1472
- tsf.counterType = 2;
1473
- } else if ( 3 == counterType ) {
1474
- tsf.additionsClass = 'tsf-counter-three';
1475
- tsf.counterType = 3;
1476
- } else {
1477
- tsf.additionsClass = 'tsf-counter-zero';
1478
- tsf.counterType = 0;
1479
- }
1480
-
1481
- tsf.updateCounters();
1482
-
1483
- // Reset settingsChanged to previous value.
1484
- tsf.settingsChanged = settingsChangedCache;
1485
  },
1486
 
1487
  /**
1488
- * Update counters.
1489
  *
1490
  * @since 2.6.0
 
1491
  *
1492
  * @function
 
1493
  * @return {undefined}
1494
  */
1495
- updateCounters: function() {
1496
- tsf.triggerTitleOnLoad();
1497
- tsf.triggerDescriptionOnLoad();
 
1498
  },
1499
 
1500
  /**
1501
- * Returns counter name.
1502
  *
1503
- * @since 2.6.0
1504
  *
1505
  * @function
1506
- * @param {String} type
1507
- * @return {String} name Human readable counter name.
1508
  */
1509
- getCounterName: function( type ) {
1510
- return tsf.i18n[ type ];
1511
  },
1512
 
1513
  /**
1514
- * Returns converted HTML title/description separator.
1515
  *
1516
  * @since 2.7.0
1517
- * @since 2.9.0 Added caching.
1518
  *
1519
  * @function
1520
- * @param {String} type
1521
- * @return {String} sep The converted separator.
 
1522
  */
1523
- getSep: function( type ) {
1524
-
1525
- let sep = '',
1526
- retVal = '';
1527
-
1528
- if ( 'title' === type ) {
1529
- sep = tsf.titleSeparator;
1530
- } else {
1531
- sep = tsf.descriptionSeparator;
1532
- }
1533
-
1534
- /** Concept:
1535
- if ( this.getSep.cachedSep && this.getSep.cachedSep.hasOwnProperty( type ) && sep === this.getSep.cachedSep[ type ]['sep'] ) {
1536
- return this.getSep.cachedSep[ type ]['retVal'];
1537
- } else {
1538
- //* Setup main cache container.
1539
- if ( ! this.getSep.cachedSep )
1540
- this.getSep.cachedSep = {};
1541
-
1542
- //* Set up secondary cache container.
1543
- if ( ! this.getSep.cachedSep[ type ] )
1544
- this.getSep.cachedSep[ type ] = {};
1545
-
1546
- //* Setup cache listener.
1547
- this.getSep.cachedSep[ type ]['sep'] = sep;
1548
- }
1549
- */
1550
 
1551
- if ( 'pipe' === sep || '|' === sep ) {
1552
- retVal = ( "|" );
1553
- } else if ( 'dash' === sep || '-' === sep ) {
1554
- retVal = ( "-" );
1555
- } else if ( sep.charCodeAt(0) < 123 ) {
1556
- //* Checked for UTF-8 conversion.
1557
- // Create a memory div to store the html in, convert to text to append in $placeholder
1558
- retVal = jQuery.trim( sep );
1559
- if ( '&' === sep.charAt(0) && ';' === sep.slice(-1) )
1560
- sep = sep.substr(1).slice(0, -1);
1561
 
1562
- retVal = jQuery( '<div/>' ).html( "&" + sep + ";" ).text();
 
 
1563
  }
1564
 
1565
- /** Concept:
1566
- return this.getSep.cachedSep[ type ]['retVal'] = retVal;
1567
- */
1568
 
1569
- //* Setup cache listener and return val.
1570
- return retVal;
 
 
 
 
 
 
 
 
 
 
1571
  },
1572
 
1573
  /**
@@ -1588,7 +2398,7 @@ window.tsf = {
1588
  return;
1589
  }
1590
 
1591
- var $target = jQuery( event.target ),
1592
  inputID = $target.data( 'inputid' ),
1593
  frame;
1594
 
@@ -1603,6 +2413,22 @@ window.tsf = {
1603
  //* Init extend cropper.
1604
  tsf.extendCropper();
1605
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1606
  frame = wp.media( {
1607
  button : {
1608
  'text' : tsf.other[ inputID ]['frame_button'],
@@ -1615,60 +2441,60 @@ window.tsf = {
1615
  'multiple' : false,
1616
  'date' : false,
1617
  'priority' : 20,
1618
- 'suggestedWidth' : 1200,
1619
- 'suggestedHeight' : 630
1620
  } ),
1621
  new tsf.cropper( {
1622
- 'imgSelectOptions' : tsf.calculateImageSelectOptions
1623
  } ),
1624
  ],
1625
  } );
1626
 
1627
- let selectFunc = (function() {
1628
- frame.setState( 'cropper' );
1629
- } );
1630
- frame.off( 'select', selectFunc );
1631
- frame.on( 'select', selectFunc );
1632
-
1633
- let croppedFunc = (function( croppedImage ) {
1634
- let url = croppedImage.url,
1635
- attachmentId = croppedImage.id,
1636
- w = croppedImage.width,
1637
- h = croppedImage.height;
1638
-
1639
- // Send the attachment id to our hidden input. URL to explicit output.
1640
- jQuery( '#' + inputID + '-url' ).val( url );
1641
- jQuery( '#' + inputID + '-id' ).val( attachmentId );
1642
- } );
1643
- frame.off( 'cropped', croppedFunc );
1644
- frame.on( 'cropped', croppedFunc );
1645
-
1646
- let skippedcropFunc = (function( selection ) {
1647
- let url = selection.get( 'url' ),
1648
- attachmentId = selection.get( 'id' ),
1649
- w = selection.get( 'width' ),
1650
- h = selection.get( 'height' );
1651
-
1652
- // Send the attachment id to our hidden input. URL to explicit output.
1653
- jQuery( '#' + inputID + '-url' ).val( url );
1654
- jQuery( '#' + inputID + '-id' ).val( attachmentId );
1655
- } );
1656
- frame.off( 'skippedcrop', skippedcropFunc );
1657
- frame.on( 'skippedcrop', skippedcropFunc );
1658
-
1659
- let doneFunc = (function( imageSelection ) {
1660
- jQuery( '#' + inputID + '-select' ).text( tsf.other[ inputID ]['change'] );
1661
- jQuery( '#' + inputID + '-url' ).prop( 'readonly', true ).css( 'opacity', 0 ).animate(
1662
- { 'opacity' : 1 },
1663
- { 'queue' : true, 'duration' : 1000 },
1664
- 'swing'
1665
- );
1666
-
1667
- tsf.appendRemoveButton( $target, inputID, true );
1668
- tsf.registerChange();
1669
- } );
1670
- frame.off( 'skippedcrop cropped', doneFunc );
1671
- frame.on( 'skippedcrop cropped', doneFunc );
1672
 
1673
  frame.open();
1674
  },
@@ -1718,21 +2544,26 @@ window.tsf = {
1718
  */
1719
  removeEditorImage: function( event ) {
1720
 
1721
- var $target = jQuery( event.target ),
1722
- inputID = $target.data( 'inputid' );
1723
 
1724
  if ( jQuery( '#' + inputID + '-select' ).prop( 'disabled' ) )
1725
  return;
1726
 
1727
  jQuery( '#' + inputID + '-select' ).addClass( 'disabled' ).prop( 'disabled', true );
1728
 
1729
- //* target.event.id === '#' + inputID + '-remove'.
1730
  jQuery( '#' + inputID + '-remove' ).addClass( 'disabled' ).prop( 'disabled', true ).fadeOut( 500, function() {
1731
  jQuery( this ).remove();
1732
  jQuery( '#' + inputID + '-select' ).text( tsf.other[ inputID ]['select'] ).removeClass( 'disabled' ).removeProp( 'disabled' );
1733
  } );
1734
 
1735
- jQuery( '#' + inputID + '-url' ).val( '' ).removeProp( 'readonly' ).css( 'opacity', 0 ).animate(
 
 
 
 
 
 
1736
  { 'opacity' : 1 },
1737
  { 'queue' : true, 'duration' : 500 },
1738
  'swing'
@@ -1757,7 +2588,7 @@ window.tsf = {
1757
  return;
1758
 
1759
  /**
1760
- * tsf.extendCropper => wp.media.controller.TSFCropper
1761
  *
1762
  * A state for cropping an image.
1763
  *
@@ -1766,12 +2597,68 @@ window.tsf = {
1766
  * @augments wp.media.controller.State
1767
  * @augments Backbone.Model
1768
  */
1769
- var TSFCropper;
1770
- let Controller = wp.media.controller;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1771
 
1772
  TSFCropper = Controller.Cropper.extend( {
 
 
 
 
 
 
 
 
1773
  doCrop: function( attachment ) {
1774
- var cropDetails = attachment.get( 'cropDetails' ),
1775
  control = tsf.cropper.control;
1776
 
1777
  // Use crop measurements when flexible in both directions.
@@ -1787,13 +2674,13 @@ window.tsf = {
1787
  if ( cropDetails.width > control.params.flex_width || cropDetails.height > control.params.flex_height ) {
1788
  // Landscape
1789
  if ( cropDetails.width > cropDetails.height ) {
1790
- var _ratio = cropDetails.width / control.params.flex_width;
1791
 
1792
  cropDetails.dst_width = control.params.flex_width;
1793
  cropDetails.dst_height = Math.round( cropDetails.height / _ratio );
1794
  // Portrait
1795
  } else {
1796
- var _ratio = cropDetails.height / control.params.flex_height;
1797
 
1798
  cropDetails.dst_height = control.params.flex_height;
1799
  cropDetails.dst_width = Math.round( cropDetails.width / _ratio );
@@ -1818,14 +2705,6 @@ window.tsf = {
1818
  } );
1819
 
1820
  TSFCropper.prototype.control = {};
1821
- TSFCropper.control = {
1822
- 'params' : {
1823
- 'flex_width' : 4096,
1824
- 'flex_height' : 4096,
1825
- 'width' : 1200,
1826
- 'height' : 630,
1827
- },
1828
- };
1829
 
1830
  tsf.cropper = TSFCropper;
1831
 
@@ -1845,10 +2724,9 @@ window.tsf = {
1845
  * @return {Object} imgSelectOptions
1846
  */
1847
  calculateImageSelectOptions: function( attachment, controller ) {
1848
-
1849
  let control = tsf.cropper.control;
1850
 
1851
- var flexWidth = !! parseInt( control.params.flex_width, 10 ),
1852
  flexHeight = !! parseInt( control.params.flex_height, 10 ),
1853
  xInit = parseInt( control.params.width, 10 ),
1854
  yInit = parseInt( control.params.height, 10 );
@@ -1862,8 +2740,16 @@ window.tsf = {
1862
  y1,
1863
  imgSelectOptions;
1864
 
 
 
 
 
 
 
 
 
1865
  controller.set( 'control', control.params );
1866
- controller.set( 'canSkipCrop', ! tsf.mustBeCropped( control.params.flex_width, control.params.flex_height, realWidth, realHeight ) );
1867
 
1868
  if ( realWidth / realHeight > ratio ) {
1869
  yInit = realHeight;
@@ -1891,22 +2777,24 @@ window.tsf = {
1891
  'y2' : yInit + y1
1892
  };
1893
 
1894
- if ( false === flexHeight && false === flexWidth ) {
1895
- imgSelectOptions.aspectRatio = xInit + ':' + yInit;
1896
- }
1897
-
1898
  // @TODO Convert set img min-width/height to output ratio.
1899
  // i.e. 200x2000 will become x = 1500/2000*200 = 150px, which is too small.
1900
  //= Unlikely...
1901
 
1902
- if ( true === flexHeight ) {
1903
- imgSelectOptions.minHeight = 200;
1904
- imgSelectOptions.maxWidth = realWidth;
1905
- }
1906
-
1907
- if ( true === flexWidth ) {
1908
- imgSelectOptions.minWidth = 200;
1909
- imgSelectOptions.maxHeight = realHeight;
 
 
 
 
 
 
1910
  }
1911
 
1912
  return imgSelectOptions;
@@ -2036,78 +2924,6 @@ window.tsf = {
2036
  }
2037
  },
2038
 
2039
- /**
2040
- * Sets up object parameters.
2041
- *
2042
- * @since 2.8.0
2043
- *
2044
- * @function
2045
- * @return {(undefined|null)}
2046
- */
2047
- setupVars: function() {
2048
-
2049
- //The current title separator.
2050
- tsf.titleSeparator = tsf.params['titleSeparator'];
2051
-
2052
- //The current description separator.
2053
- tsf.descriptionSeparator = tsf.params['descriptionSeparator'];
2054
-
2055
- // The current title tagline.
2056
- tsf.titleTagline = tsf.states['titleTagline'];
2057
-
2058
- // The counter type. Mixed string and int (i10n is string, JS is int).
2059
- tsf.counterType = parseInt( tsf.states['counterType'] );
2060
-
2061
- // Determines if the current page has input boxes for The SEO Framework.
2062
- tsf.hasInput = tsf.states['hasInput'];
2063
- },
2064
-
2065
- /**
2066
- * Registers title prop listeners.
2067
- *
2068
- * @since 2.9.0
2069
- *
2070
- * @function
2071
- * @return {(undefined|null)}
2072
- */
2073
- _initTitlepropListener: function() {
2074
-
2075
- if ( tsf.hasInput ) {
2076
- let jQ = jQuery;
2077
-
2078
- //* Trigger directly on call load.
2079
- //tsf.taglinePropTrigger();
2080
-
2081
- // Toggle Title tagline aditions removal.
2082
- jQ( '#tsf-title-tagline-toggle :input' ).on( 'click', tsf.taglineToggleTitle );
2083
- // Toggle Title additions location.
2084
- jQ( '#tsf-title-location input' ).on( 'click', tsf.titleLocationToggle );
2085
- // Toggle Title prefixes display.
2086
- jQ( '#title-prefixes-toggle :input' ).on( 'click', tsf.titlePrefixToggle );
2087
-
2088
- // Change Home Page Title Example prop on input changes.
2089
- jQ( '#autodescription-site-settings\\[homepage_title\\]' ).on( 'input', tsf.titleProp );
2090
- jQ( '#tsf-home-title-location :input, #tsf-title-tagline-toggle :input, #tsf-title-separator input' ).on( 'click', tsf.taglinePropTrigger );
2091
- jQ( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).on( 'input', tsf.taglineProp );
2092
-
2093
- // Make sure the titleProp is correctly rendered when revealed after being hidden.
2094
- jQ( '#homepage-tab-general' ).on( 'tsf-tab-toggled', tsf.taglinePropTrigger );
2095
- jQ( '#autodescription-homepage-settings > button' ).on( 'click', tsf.taglinePropTrigger );
2096
- jQ( '#tsf-inpost-box > button' ).on( 'click', tsf.taglinePropTrigger );
2097
-
2098
- // Change Global Title Example prop on input changes.
2099
- jQ( '#autodescription-site-settings\\[title_rem_additions\\]' ).on( 'click', tsf.titleToggle );
2100
-
2101
- // Dynamic Placeholder, acts on keydown for a11y, although more cpu intensive. Acts on keyup for perfect output.
2102
- tsf.docTitles().on( 'input', tsf.dynamicPlaceholder );
2103
-
2104
- // Move click on dynamic additions to focus input behind.
2105
- jQ( '#tsf-title-placeholder' ).on( 'click', tsf.selectTitleInput );
2106
-
2107
- jQ( window ).resize( tsf.taglinePropTriggerResize );
2108
- }
2109
- },
2110
-
2111
  /**
2112
  * Registers on resize/orientationchange listeners and debounces to only run
2113
  * at intervals.
@@ -2127,14 +2943,15 @@ window.tsf = {
2127
  //* Set event listeners.
2128
  tsf._setResizeListeners();
2129
 
2130
- var resizeTimeout = 0,
2131
  $lastWidth = {},
2132
  timeOut = 0;
2133
 
2134
  // Warning: Only checks for the first item existence.
2135
- var $tabWrapper = jQuery( '.tsf-flex-nav-tab-wrapper' );
 
2136
 
2137
- jQuery( window ).on( 'tsf-flex-resize', function() {
2138
 
2139
  clearTimeout( resizeTimeout );
2140
 
@@ -2200,7 +3017,7 @@ window.tsf = {
2200
  } );
2201
 
2202
  //* Trigger after setup.
2203
- jQuery( window ).trigger( 'tsf-flex-resize' );
2204
  },
2205
 
2206
  /**
@@ -2218,6 +3035,31 @@ window.tsf = {
2218
  jQuery( '.meta-box-sortables' ).on( 'sortupdate', tsf._triggerResize );
2219
  },
2220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2221
  /**
2222
  * Triggers resize on event.
2223
  *
@@ -2230,6 +3072,18 @@ window.tsf = {
2230
  jQuery( window ).trigger( 'tsf-flex-resize' );
2231
  },
2232
 
 
 
 
 
 
 
 
 
 
 
 
 
2233
  /**
2234
  * Sets tsf.ready action.
2235
  *
@@ -2245,101 +3099,120 @@ window.tsf = {
2245
  },
2246
 
2247
  /**
2248
- * Initialises all aspects of the scripts.
2249
- *
2250
- * Generally ordered with stuff that inserts new elements into the DOM first,
2251
- * then stuff that triggers an event on existing DOM elements when ready,
2252
- * followed by stuff that triggers an event only on user interaction. This
2253
- * keeps any screen jumping from occuring later on.
2254
- *
2255
- * @since 2.2.4
2256
- * @since 2.7.0 jQuery object is now passed.
2257
  *
2258
- * @todo setup ready action list and action callers. Now it's ravioli that's
2259
- * dependent on eachother.
2260
  *
2261
  * @function
2262
- * @param {!jQuery} jQ jQuery
2263
- * @return {undefined}
2264
  */
2265
- ready: function( jQ ) {
2266
 
2267
- // Set up object parameters.
2268
- tsf.setupVars();
2269
-
2270
- // Move the page updates notices below the tsf-top-wrap.
2271
- jQ( 'div.updated, div.error, div.notice-warning' ).insertAfter( 'div.tsf-top-wrap' );
2272
 
2273
  // Add title prop listeners. Must load before setTabsOnload to work.
2274
- jQ( document.body ).ready( tsf._initTitlepropListener );
 
2275
 
2276
- // Sets tabs to correct radio button on load.
2277
- jQ( document.body ).ready( tsf.setTabsOnload );
 
 
 
2278
 
2279
- // Set up additions classes.
2280
- jQ( document.body ).ready( tsf.additionsClassInit );
2281
 
2282
  // Check if the Title Tagline or Description Additions should be removed when page is loaded.
2283
- jQ( document.body ).ready( tsf.taglineToggleOnload );
2284
 
2285
  // Initialize the status bar hover balloon.
2286
- jQ( document.body ).ready( tsf.statusBarHover );
2287
 
2288
  // Initialize image uploader button cache.
2289
- jQ( document.body ).ready( tsf.setupImageEditorActions );
2290
 
2291
  // Determine image editor button input states.
2292
- jQ( document.body ).ready( tsf.checkImageEditorInput );
2293
 
2294
  // Correct Color Picker input
2295
- jQ( document.body ).ready( tsf.setColorOnload );
2296
 
2297
  // #== End Before Change listener
2298
 
2299
  // Initialise form field changing flag.
2300
- jQ( document.body ).ready( tsf.attachUnsavedChangesListener );
2301
 
2302
  // Deregister changes.
2303
- jQ( document.body ).ready( tsf.onLoadUnregisterChange );
2304
 
2305
  // Trigger tsf-ready event.
2306
- jQ( document.body ).ready( tsf._triggerReady );
2307
 
2308
  // #== Start After Change listener
2309
 
2310
  // Do flex resize functionality.
2311
- jQ( document.body ).ready( tsf._doFlexResizeListener );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2312
 
2313
- // Initialize status bar removal hover for touch screens.
2314
- jQ( document.body ).on( 'click touchstart MSPointerDown', tsf.touchRemoveDesc );
2315
 
2316
- // Bind character counters.
2317
- tsf.docDescriptions().on( 'input', tsf.updateCharacterCountDescription );
2318
- tsf.docTitles().on( 'input', tsf.updateCharacterCountTitle );
2319
 
2320
- // Allow the title separator to be changed dynamically.
2321
- jQ( '#tsf-title-separator input' ).on( 'click', tsf.separatorSwitchTitle );
2322
- // Allow description separator to be changed dynamically.
2323
- jQ( '#tsf-description-separator input' ).on( 'click', tsf.separatorSwitchDesc );
2324
 
2325
  // Bind reset confirmation.
2326
- jQ( '.tsf-js-confirm-reset' ).on( 'click', tsf.confirmedReset );
2327
 
2328
  // Toggle Tabs in the SEO settings page.
2329
- jQ( '.tsf-tabs-radio' ).on( 'change', tsf.tabToggle );
2330
 
2331
  // Toggle Tabs for the inpost Flex settings.
2332
- jQ( '.tsf-flex-nav-tab-radio' ).on( 'change', tsf.flexTabToggle );
2333
 
2334
  // Toggle Description additions removal.
2335
- jQ( '#tsf-description-onblogname-toggle :input' ).on( 'click', tsf.taglineToggleDesc );
2336
- jQ( '#tsf-description-additions-toggle :input' ).on( 'click', tsf.additionsToggleDesc );
2337
 
2338
  // Dismiss notices.
2339
- jQ( '.tsf-dismiss' ).on( 'click', tsf.dismissNotice );
2340
-
2341
- // AJAX counter
2342
- jQ( '.tsf-counter' ).on( 'click', tsf.counterUpdate );
2343
  }
2344
  };
2345
  jQuery( tsf.ready );
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
 
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/externs/tsf.externs.js
31
  // ==/ClosureCompiler==
32
  // http://closure-compiler.appspot.com/home
33
 
43
  */
44
  window.tsf = {
45
 
 
 
 
 
 
 
 
 
 
 
46
  /**
47
  * AJAX Nonces object.
48
  *
101
  */
102
  settingsChanged: false,
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  /**
105
  * Mixed string and int (i10n is string, JS is int).
106
  *
138
  cropper : {},
139
 
140
  /**
141
+ * Helper function for confirming a user action.
142
  *
143
+ * @since 2.2.4
 
 
144
  *
145
  * @function
146
+ * @param {String} text The text to display.
147
+ * @return {(Boolean|null)} True on OK, false on cancel.
148
  */
149
+ confirm: function( text ) {
150
+ return confirm( text );
 
 
 
 
 
 
 
 
 
151
  },
152
 
153
  /**
154
+ * Escapes input string.
155
  *
156
+ * @since 3.0.1
 
157
  *
158
+ * @source <https://stackoverflow.com/a/4835406>
159
  * @function
160
+ * @param {string} str
161
+ * @return {string}
162
  */
163
+ escapeString: function( str ) {
 
 
 
164
 
165
+ if ( ! str.length )
166
+ return '';
167
 
168
+ var map = {
169
+ '&': '&amp;',
170
+ '<': '&lt;',
171
+ '>': '&gt;',
172
+ '"': '&quot;',
173
+ "'": '&#039;'
174
+ };
175
 
176
+ return str.replace( /[&<>"']/g, function( m ) {
177
+ return map[m];
178
+ } );
179
  },
180
 
181
  /**
182
+ * Gets string length.
183
+ * We do not trim in JavaScript; that should be self-taught by the user.
 
184
  *
185
  * @function
186
+ * @param {string} str
187
+ * @return {number}
188
  */
189
+ getStringLength: function( str ) {
190
+ let e,
191
+ length = 0;
192
+
193
+ if ( str.length ) {
194
+ e = document.createElement( 'span' );
195
+ e.innerHTML = tsf.escapeString( str );
196
+ length = e.childNodes[0].nodeValue.length;
197
+ }
198
+ return +length;
199
  },
200
 
201
  /**
202
+ * Updates pixel counter.
 
 
 
203
  *
204
  * @function
205
+ * @param {Object} test
206
  * @return {undefined}
207
  */
208
+ updatePixelCounter: function( test ) {
209
+
210
+ let e = test.e,
211
+ text = test.text,
212
+ guideline = test.guideline;
213
+
214
+ let wrap = e.parentElement;
215
+
216
+ if ( ! wrap )
217
+ return;
218
+
219
+ let bar = wrap.querySelector( '.tsf-pixel-counter-bar' ),
220
+ shadow = wrap.querySelector( '.tsf-pixel-counter-shadow' );
221
+
222
+ if ( ! bar || ! shadow )
223
+ return;
224
+
225
+ shadow.innerHTML = tsf.escapeString( text );
226
+
227
+ let testWidth = shadow.offsetWidth,
228
+ newClass = '',
229
+ newWidth = '';
230
+
231
+ let fitClass = 'tsf-pixel-counter-fit',
232
+ overflownClass = 'tsf-pixel-counter-overflown';
233
+
234
+ if ( testWidth > guideline ) {
235
+ //= Can never be 0. Good. Add 2/3rds of difference to it; implying emphasis.
236
+ newWidth = ( guideline / ( testWidth + ( ( testWidth - guideline ) * 2 / 3 ) ) * 100 ) + '%';
237
+ newClass = overflownClass;
238
  } else {
239
+ //= Can never be over 100. Good.
240
+ newWidth = ( testWidth / guideline * 100 ) + '%';
241
+ newClass = fitClass;
242
  }
243
 
244
+ let sub = bar.querySelector( '.tsf-pixel-counter-fluid' ),
245
+ label;
 
 
 
 
 
 
246
 
247
+ label = tsf.i18n.pixelsUsed.replace( /%1\$d/g, testWidth );
248
+ label = label.replace( /%2\$d/g, guideline );
249
 
250
+ bar.classList.remove( fitClass, overflownClass )
251
+ bar.classList.add( newClass );
252
+ bar.dataset.desc = label;
253
+ bar.setAttribute( 'aria-label', label );
254
 
255
+ sub.style.width = newWidth;
256
+
257
+ tsf._triggerTooltipUpdate( bar );
258
  },
259
 
260
  /**
261
+ * Initializes all aspects for title editing.
262
+ * Assumes only one title editor is present in the DOM.
263
  *
264
+ * @since 3.0.0
265
  *
266
  * @function
 
267
  * @return {undefined}
268
  */
269
+ _initTitleInputs: function() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
 
271
+ if ( ! tsf.hasInput )
272
+ return;
273
+
274
+ let $doctitles = jQuery( "#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]" );
275
 
276
+ if ( ! $doctitles.length )
277
+ return;
278
 
279
+ //= y u no fix dis, Microsoft. Crappy vars don't deserve CamelCase.
280
+ let ie11killswitch = false,
281
+ ie11 = !! navigator.userAgent.match(/Trident\/7\./);
282
+
283
+ let hoverPrefixPlacement,
284
+ hoverAdditionsPlacement,
285
+ hoverPrefixElement,
286
+ hoverPrefixValue = '',
287
+ hoverAdditionsElement,
288
+ hoverAdditionsValue = '',
289
+ separator = tsf.params.titleSeparator,
290
+ defaultTitle = tsf.params.objectTitle;
291
+
292
+ let useTagline = tsf.states.useTagline,
293
+ isRTL = tsf.states.isRTL,
294
+ isPrivate = tsf.states.isPrivate,
295
+ isPasswordProtected = tsf.states.isPasswordProtected;
296
+
297
+ //= Sets hoverPrefixPlacement.
298
+ hoverPrefixPlacement = isRTL ? 'after' : 'before';
299
+ //= Sets hoverAdditionsPlacement.
300
+ const setHoverAdditionsPlacement = function() {
301
+ let placement = 'before';
302
+
303
+ if ( tsf.states.isSettingsPage ) {
304
+ if ( isRTL ) {
305
+ if ( 'right' === jQuery( '#tsf-home-title-location input:checked' ).val() ) {
306
+ placement = 'after';
307
+ }
308
+ } else {
309
+ if ( 'left' === jQuery( '#tsf-home-title-location input:checked' ).val() ) {
310
+ placement = 'after';
311
+ }
312
+ }
313
+ } else {
314
+ if ( tsf.states.isHome ) {
315
+ //= Static front page.
316
+ if ( isRTL ) {
317
+ if ( 'right' === tsf.params.titleLocation )
318
+ placement = 'after';
319
+ } else if ( 'left' === tsf.params.titleLocation ) {
320
+ placement = 'after';
321
+ }
322
  } else {
323
+ if ( isRTL ) {
324
+ if ( 'left' === tsf.params.titleLocation )
325
+ placement = 'after';
326
+ } else if ( 'right' === tsf.params.titleLocation ) {
327
+ placement = 'after';
328
+ }
329
  }
330
  }
331
 
332
+ hoverAdditionsPlacement = placement;
333
+ }
334
+ setHoverAdditionsPlacement();
335
+ //= Sets hoverAdditionsValue.
336
+ const setHoverAdditionsValue = function() {
337
+ let newValue = '';
338
+
339
+ if ( tsf.states.isSettingsPage ) {
340
+ if ( useTagline ) {
341
+ //= Tagline is enabled.
342
+ let e = document.getElementById( 'autodescription-site-settings[homepage_title_tagline]' ),
343
+ customTagline = e ? e.value : '';
344
+
345
+ if ( customTagline.length ) {
346
+ newValue = customTagline;
347
+ } else {
348
+ newValue = tsf.params.blogDescription;
349
+ }
350
+ }
351
+ } else if ( tsf.states.isHome ) {
352
+ //= Static front page.
353
+ if ( useTagline )
354
+ newValue = tsf.params.titleAdditions;
355
  } else {
356
+ //= Global additions are enabled.
357
+ if ( useTagline )
358
+ newValue = tsf.params.titleAdditions;
359
  }
 
360
 
361
+ if ( newValue.length ) {
362
+ newValue = tsf.escapeString( newValue );
363
+ switch ( hoverAdditionsPlacement ) {
364
+ case 'before' :
365
+ newValue = newValue + ' ' + separator + ' ';
366
+ break;
 
 
 
 
367
 
368
+ case 'after' :
369
+ newValue = ' ' + separator + ' ' + newValue;
370
+ break;
371
+ }
372
+ }
373
+ hoverAdditionsValue = newValue.length ? newValue : '';
374
 
375
+ hoverAdditionsElement = document.getElementById( 'tsf-title-placeholder' );
376
+ if ( hoverAdditionsValue.length && hoverAdditionsElement ) {
377
+ hoverAdditionsElement.innerHTML = hoverAdditionsValue;
378
+ }
 
 
379
  }
380
+ setHoverAdditionsValue();
381
+ //= Sets hoverPrefixValue.
382
+ const setHoverPrefixValue = function() {
383
+ let newValue = '';
384
+
385
+ if ( isPrivate ) {
386
+ newValue = tsf.i18n.privateTitle;
387
+ } else if ( isPasswordProtected ) {
388
+ newValue = tsf.i18n.protectedTitle;
389
+ }
390
 
391
+ if ( newValue.length ) {
392
+ newValue = tsf.escapeString( newValue );
393
+ switch ( hoverPrefixPlacement ) {
394
+ case 'before' :
395
+ newValue = newValue + ' ';
396
+ break;
 
 
 
 
 
 
 
 
397
 
398
+ case 'after' :
399
+ newValue = ' ' + newValue;
400
+ break;
401
+ }
402
+ }
403
+ hoverPrefixValue = newValue.length ? newValue : '';
404
 
405
+ if ( hoverPrefixValue.length && hoverPrefixElement ) {
406
+ hoverPrefixElement.innerHTML = hoverPrefixValue;
407
+ }
408
 
409
+ hoverPrefixElement = document.getElementById( 'tsf-title-placeholder-prefix' );
410
+ if ( hoverPrefixValue.length && hoverPrefixElement ) {
411
+ hoverPrefixElement.innerHTML = hoverPrefixValue;
412
+ }
413
+ }
414
+ setHoverPrefixValue();
415
+ const updateHoverPlacement = function( event ) {
 
 
 
416
 
417
+ if ( ! hoverAdditionsElement && ! hoverPrefixElement )
418
+ return;
419
 
420
+ let $input = jQuery( event.target ),
421
+ inputValue = $input.val();
422
 
423
+ let hasAdditionsValue = !! hoverAdditionsValue.length,
424
+ hasPrefixValue = !! hoverPrefixValue.length;
 
 
 
 
 
 
425
 
426
+ if ( ! hasAdditionsValue && hoverAdditionsElement )
427
+ hoverAdditionsElement.style.display = 'none';
428
+ if ( ! hasPrefixValue && hoverPrefixElement )
429
+ hoverPrefixElement.style.display = 'none';
 
 
 
 
 
 
 
430
 
431
+ if ( ! hasAdditionsValue && ! hasPrefixValue ) {
432
+ //= Both items are emptied through settings.
433
+ $input.css( 'text-indent', 'initial' );
434
+ return;
435
+ }
436
 
437
+ if ( ! inputValue.length ) {
438
+ //= Input is emptied.
439
+ $input.css( 'text-indent', "initial" );
440
+ if ( hoverAdditionsElement ) hoverAdditionsElement.style.display = 'none';
441
+ if ( hoverPrefixElement ) hoverPrefixElement.style.display = 'none';
442
+ return;
443
+ }
 
444
 
445
+ let outerWidth = $input.outerWidth(),
446
+ verticalPadding = ( $input.outerHeight( true ) - $input.height() ) / 2,
447
+ horizontalPadding = ( outerWidth - $input.innerWidth() ) / 2;
448
+
449
+ let offsetPosition = isRTL ? 'right' : 'left',
450
+ leftOffset = ( $input.outerWidth( true ) - $input.width() ) / 2;
451
+
452
+ let fontStyleCSS = {
453
+ 'display': $input.css( "display" ),
454
+ 'lineHeight': $input.css( "lineHeight" ),
455
+ 'fontFamily': $input.css( "fontFamily" ),
456
+ 'fontWeight': $input.css( "fontWeight" ),
457
+ 'fontSize': $input.css( "fontSize" ),
458
+ 'letterSpacing': $input.css( "letterSpacing" ),
459
+ 'paddingTop': verticalPadding + "px",
460
+ 'paddingBottom': verticalPadding + "px",
461
+ };
462
+
463
+ let $prefixElement = jQuery( hoverPrefixElement ),
464
+ $additionsElement = jQuery( hoverAdditionsElement );
465
+
466
+ let additionsMaxWidth = 0,
467
+ additionsOffset = 0,
468
+ prefixOffset = 0,
469
+ totalIndent = 0,
470
+ prefixMaxWidth = 0;
471
+
472
+ if ( hasPrefixValue ) {
473
+ $prefixElement.css( fontStyleCSS );
474
+ $prefixElement.css( { 'maxWidth' : 'initial' } );
475
+ prefixMaxWidth = $prefixElement.width();
476
+ if ( prefixMaxWidth < 0 )
477
+ prefixMaxWidth = 0;
478
+ prefixOffset += leftOffset;
479
+ }
480
+ if ( hasAdditionsValue ) {
481
+ let textWidth = 0;
482
+
483
+ (function() {
484
+ let $offsetTest = jQuery( "#tsf-title-offset" );
485
+ $offsetTest.text( inputValue );
486
+ $offsetTest.css({
487
+ 'fontFamily' : fontStyleCSS.fontFamily,
488
+ 'fontWeight' : fontStyleCSS.fontWeight,
489
+ 'letterSpacing' : fontStyleCSS.letterSpacing,
490
+ 'fontSize' : fontStyleCSS.fontSize,
491
+ });
492
+ textWidth = $offsetTest.width();
493
+ })();
494
+
495
+ //= Input element width - Padding - input text width - prefix value width.
496
+ additionsMaxWidth = $input.width() - horizontalPadding - textWidth - prefixMaxWidth;
497
+ if ( additionsMaxWidth < 0 ) {
498
+ prefixMaxWidth -=- additionsMaxWidth;
499
+ additionsMaxWidth = 0;
500
+ }
501
 
502
+ $additionsElement.css( fontStyleCSS );
503
 
504
+ switch ( hoverAdditionsPlacement ) {
505
+ case 'before' :
506
+ let additionsWidth = $additionsElement.width();
507
 
508
+ if ( additionsWidth < 0 )
509
+ additionsWidth = 0;
 
 
 
 
 
510
 
511
+ totalIndent += additionsWidth;
512
+ prefixOffset += additionsWidth;
513
+ additionsOffset += leftOffset;
514
+ break;
 
 
 
 
 
 
515
 
516
+ case 'after' :
517
+ additionsOffset += leftOffset + textWidth + prefixMaxWidth;
518
+ break;
519
+ }
520
+ }
521
+ prefixMaxWidth = prefixMaxWidth < 0 ? 0 : prefixMaxWidth;
522
+ totalIndent += prefixMaxWidth;
523
 
524
+ let _css;
 
525
 
526
+ if ( hasPrefixValue ) {
527
+ _css = {};
528
+ _css[ offsetPosition ] = prefixOffset + "px";
529
+ _css['maxWidth'] = prefixMaxWidth + "px";
530
+ $prefixElement.css( _css );
531
+ }
532
+ if ( hasAdditionsValue ) {
533
+ _css = {};
534
+ _css[ offsetPosition ] = additionsOffset + "px";
535
+ _css['maxWidth'] = additionsMaxWidth + "px";
536
+ $additionsElement.css( _css );
537
+ }
538
 
539
+ _css = {};
540
+ _css['text-indent'] = totalIndent + "px";
541
+ $input.css( _css );
542
  }
543
+ const updatePlaceholder = function() {
544
 
545
+ let $input = $doctitles,
546
+ _placeholder = '';
547
+
548
+ let _hasAdditionsValue = !! hoverAdditionsValue.length,
549
+ _hasPrefixValue = !! hoverPrefixValue.length;
550
+
551
+ let _hoverAdditionsValue = hoverAdditionsValue,
552
+ _hoverPrefixValue = hoverPrefixValue;
553
+
554
+ if ( tsf.states.isTermEdit ) {
555
+ if ( tsf.params.termName ) {
556
+ _hoverPrefixValue = isRTL ? ' :' + tsf.params.termName : tsf.params.termName + ': ';
557
+ _hasPrefixValue = tsf.states.useTermPrefix;
558
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
559
  }
 
 
560
 
561
+ _placeholder = defaultTitle;
 
 
 
 
 
 
 
 
 
 
 
562
 
563
+ if ( _hasPrefixValue ) {
564
+ switch ( hoverPrefixPlacement ) {
565
+ case 'before' :
566
+ _placeholder = _hoverPrefixValue + _placeholder;
567
+ break;
 
 
 
 
568
 
569
+ case 'after' :
570
+ _placeholder = _placeholder + _hoverPrefixValue;
571
+ break;
572
+ }
573
+ }
574
+ if ( _hasAdditionsValue ) {
575
+ switch ( hoverAdditionsPlacement ) {
576
+ case 'before' :
577
+ _placeholder = _hoverAdditionsValue + _placeholder;
578
+ break;
579
+
580
+ case 'after' :
581
+ _placeholder = _placeholder + _hoverAdditionsValue;
582
+ break;
583
+ }
584
+ }
585
 
586
+ //= Microsoft be like: "Let's spare 0.000000000073% of our money."
587
+ if ( ie11 ) ie11killswitch = true;
 
 
588
 
589
+ //= Converts special characters without running scripts.
590
+ let phText = document.createElement( 'span' );
591
+ phText.innerHTML = _placeholder;
 
 
 
 
 
 
 
 
 
 
592
 
593
+ $input.prop( 'placeholder', phText.textContent );
594
 
595
+ //= Promise.
596
+ ie11 && setTimeout( function() {
597
+ ie11killswitch = false;
598
+ }, 0 );
599
+ }
600
+ const updateCounter = function( event ) {
601
+ let counter = document.getElementById( event.target.id + '_chars' );
602
 
603
+ if ( ! counter )
604
+ return;
605
 
606
+ let titLen = 0,
607
+ target = event.target,
608
+ counterClass = '',
609
+ counterType = tsf.counterType,
610
+ counterName = '',
611
+ output = '';
612
 
613
+ if ( target.value.length < 1 ) {
614
+ titLen = tsf.getStringLength( target.placeholder );
615
+ } else {
616
+ titLen = ( hoverPrefixValue ? tsf.getStringLength( hoverPrefixValue ) : 0 )
617
+ + tsf.getStringLength( target.value )
618
+ + ( hoverAdditionsValue ? tsf.getStringLength( hoverAdditionsValue ) : 0 );
619
+ }
620
 
621
+ if ( titLen < 25 || titLen >= 75 ) {
622
+ counterClass += 'tsf-count-bad';
623
+ counterName = tsf.i18n.bad;
624
+ } else if ( titLen < 42 || titLen > 55 ) {
625
+ counterClass += 'tsf-count-okay';
626
+ counterName = tsf.i18n.okay;
627
+ } else {
628
+ counterClass += 'tsf-count-good';
629
+ counterName = tsf.i18n.good;
630
  }
 
 
631
 
632
+ if ( ! counterType || 1 == counterType ) {
633
+ output = titLen.toString();
634
+ } else if ( 2 == counterType ) {
635
+ output = counterName;
636
+ } else if ( 3 == counterType ) {
637
+ output = titLen.toString() + ' - ' + counterName;
638
+ }
 
 
 
 
639
 
640
+ counter.innerHTML = output;
641
 
642
+ if ( tsf.additionsClass )
643
+ counterClass += ' ' + tsf.additionsClass;
644
 
645
+ if ( counter.className !== counterClass )
646
+ counter.className = counterClass;
647
+ }
648
+ const updatePixels = function( event ) {
649
+ let pixels = document.getElementById( event.target.id + '_pixels' );
650
 
651
+ if ( ! pixels )
652
+ return;
 
 
653
 
654
+ let text = '';
 
 
655
 
656
+ if ( event.target.value.length < 1 ) {
657
+ text = event.target.placeholder;
658
+ } else {
659
+ //= We must determine the position as trailing whitespace is rendered 0.
660
+ text = event.target.value;
661
+
662
+ if ( hoverPrefixValue.length ) {
663
+ switch ( hoverPrefixPlacement ) {
664
+ case 'before' :
665
+ text = hoverPrefixValue + text;
666
+ break;
667
+
668
+ case 'after' :
669
+ text = text + hoverPrefixValue;
670
+ break;
671
+ }
672
+ }
673
+ if ( hoverAdditionsValue.length ) {
674
+ switch ( hoverAdditionsPlacement ) {
675
+ case 'before' :
676
+ text = hoverAdditionsValue + text;
677
+ break;
678
+
679
+ case 'after' :
680
+ text = text + hoverAdditionsValue;
681
+ break;
682
+ }
683
+ }
684
  }
685
+
686
+ let test = {
687
+ 'e': pixels,
688
+ 'text' : text,
689
+ 'guideline' : tsf.params.titlePixelGuideline,
690
+ };
691
+
692
+ tsf.updatePixelCounter( test );
693
  }
 
694
 
695
+ /**
696
+ * Updates placements, placeholders and counters.
697
+ *
698
+ * @function
699
+ * @param {!jQuery.Event} event
700
+ * @return {undefined}
701
+ */
702
+ const updateTitlesTrigger = function( event ) {
703
+ if ( ie11killswitch ) return false;
704
+ updateHoverPlacement( event );
705
+ updatePlaceholder();
706
+ updateCounter( event );
707
+ updatePixels( event );
708
+ }
709
+ $doctitles.on( 'input.tsfUpdateTitles', updateTitlesTrigger );
710
 
711
+ /**
712
+ * Updates character counters.
713
+ *
714
+ * @function
715
+ * @param {!jQuery.Event} event
716
+ * @return {undefined}
717
+ */
718
+ const updateCounterTrigger = function( event ) {
719
+ updateCounter( event );
720
+ updatePixels( event );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
721
  }
722
+ $doctitles.on( 'tsf-update-title-counter', updateCounterTrigger );
723
 
724
+ /**
725
+ * Triggers counter updates.
726
+ *
727
+ * @function
728
+ * @return {undefined}
729
+ */
730
+ const triggerCounter = function() {
731
+ $doctitles.trigger( 'tsf-update-title-counter' );
732
+ }
 
733
 
734
+ /**
735
+ * Triggers doctitles input.
736
+ *
737
+ * @function
738
+ * @return {undefined}
739
+ */
740
+ const triggerInput = function() {
741
+ $doctitles.trigger( 'input.tsfUpdateTitles' );
742
+ }
743
+ triggerInput();
744
 
745
+ /**
746
+ * Triggers additions hover update on tagline change.
747
+ *
748
+ * @function
749
+ * @return {undefined}
750
+ */
751
+ const updateTagline = function() {
752
+ setHoverAdditionsValue();
753
+ triggerInput();
754
  }
755
+ jQuery( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).on( 'input', updateTagline );
756
+ jQuery( '#autodescription-site-settings\\[homepage_tagline\\]' ).on( 'change', updateTagline );
757
 
758
+ let triggerBuffer = 0;
759
+ /**
760
+ * Triggers doctitles input.
761
+ * @function
762
+ * @return {undefined}
763
+ */
764
+ const enqueueTriggerInput = function() {
765
+ clearTimeout( triggerBuffer );
766
+ triggerBuffer = setTimeout( function() {
767
+ triggerInput();
768
+ }, 50 );
769
+ }
770
+ jQuery( window ).on( 'tsf-counter-updated', enqueueTriggerInput );
771
 
772
+ /**
773
+ * Toggles tagline left/right example additions visibility for the homepage title.
774
+ *
775
+ * @function
776
+ * @param {!jQuery.Event} event
777
+ * @return {undefined}
778
+ */
779
+ const changeHomePageAdditionsVisibility = function( event ) {
780
+ let prevUseTagline = useTagline;
 
781
 
782
+ if ( jQuery( event.target ).is( ':checked' ) ) {
783
+ jQuery( '.tsf-custom-blogname-js' ).css( 'display', 'inline' );
784
+ useTagline = true;
785
+ } else {
786
+ jQuery( '.tsf-custom-blogname-js' ).css( 'display', 'none' );
787
+ useTagline = false;
788
+ }
789
 
790
+ if ( prevUseTagline ^ useTagline ) {
791
+ setHoverAdditionsValue();
792
+ enqueueTriggerInput();
793
+ }
794
  }
795
+ jQuery( '#tsf-title-tagline-toggle :input' ).on( 'click', changeHomePageAdditionsVisibility );
796
 
797
+ /**
798
+ * Updates private/protected title prefix upon Post visibility switch.
799
+ *
800
+ * @function
801
+ * @param {!jQuery.Event} event
802
+ * @return {undefined}
803
+ */
804
+ const updateVisibility = function( event ) {
805
+ let value = jQuery( '#visibility' ).find( 'input:radio:checked' ).val();
 
806
 
807
+ isPrivate = false;
808
+ isPasswordProtected = false;
 
809
 
810
+ switch ( value ) {
811
+ case 'password' :
812
+ let p = jQuery( '#visibility' ).find( '#post_password' ).val();
813
+ isPasswordProtected = p ? !! p.length : false;
814
+ break;
815
+
816
+ case 'private' :
817
+ isPrivate = true;
818
+ break;
819
+
820
+ default :
821
+ case 'public' :
822
+ break;
823
+ }
824
+
825
+ //* @TODO move all of the above to a global state handler?
826
+ setHoverPrefixValue();
827
+ enqueueTriggerInput();
828
  }
829
+ jQuery( '#visibility .save-post-visibility' ).on( 'click', updateVisibility );
830
 
831
+ /**
832
+ * Updates used separator and all examples thereof.
833
+ *
834
+ * @function
835
+ * @param {!jQuery.Event} event
836
+ * @return {undefined}
837
+ */
838
+ const updateSeparator = function( event ) {
839
+ let val = jQuery( event.target ).val(),
840
+ newSep = '';
841
+
842
+ switch ( val ) {
843
+ case 'pipe' :
844
+ newSep = '|';
845
+ break;
846
+
847
+ case 'dash' :
848
+ newSep = '-';
849
+ break;
850
+
851
+ default :
852
+ newSep = jQuery( '<div/>' ).html( "&" + val + ";" ).text();
853
+ break;
854
+ }
855
+ separator = newSep;
856
+ jQuery( ".tsf-sep-js" ).text( ' ' + separator + ' ' );
857
 
858
+ setHoverAdditionsValue();
859
+ enqueueTriggerInput();
860
+ }
861
+ jQuery( '#tsf-title-separator :input' ).on( 'click', updateSeparator );
862
 
863
+ /**
864
+ * Triggers title update, without affecting change listeners.
865
+ *
866
+ * @function
867
+ * @param {!jQuery.Event}
868
+ * @return {undefined}
869
+ */
870
+ const triggerUnregisteredTitleChange = function() {
871
+ let settingsChangedCache = tsf.settingsChanged;
872
+ triggerInput();
873
+ tsf.settingsChanged = settingsChangedCache;
874
  }
875
+ jQuery( '#autodescription-homepage-settings > button, #tsf-inpost-box > button' ).on( 'click', triggerUnregisteredTitleChange );
876
+ jQuery( '#homepage-tab-general' ).on( 'tsf-tab-toggled', triggerUnregisteredTitleChange );
877
+ jQuery( '#tsf-flex-inpost-tab-general' ).on( 'tsf-flex-tab-toggled', triggerUnregisteredTitleChange );
878
 
879
+ let unregisteredTriggerBuffer = 0;
880
+ /**
881
+ * Triggers doctitles input.
882
+ * @function
883
+ * @return {undefined}
884
+ */
885
+ const enqueueUnregisteredTriggerInput = function() {
886
+ clearTimeout( unregisteredTriggerBuffer );
887
+ unregisteredTriggerBuffer = setTimeout( function() {
888
+ triggerUnregisteredTitleChange();
889
+ }, 50 );
890
+ }
891
+ jQuery( window ).on( 'tsf-flex-resize', enqueueUnregisteredTriggerInput );
892
 
893
+ /**
894
+ * Triggers additions hover update on tagline placement change.
895
+ *
896
+ * @function
897
+ * @return {undefined}
898
+ */
899
+ const setTaglinePlacement = function() {
900
+ setHoverAdditionsPlacement();
901
+ setHoverAdditionsValue();
902
+ enqueueTriggerInput();
903
+ }
904
+ jQuery( '#tsf-home-title-location :input' ).on( 'click', setTaglinePlacement );
905
 
906
+ /**
907
+ * Updates default title placeholder.
908
+ *
909
+ * @function
910
+ * @param {!jQuery.Event} event
911
+ * @return {undefined}
912
+ */
913
+ const updateDefaultTitle = function( event ) {
914
+ let val = event.target.value;
915
+ val = val.trim();
916
+
917
+ if ( val.length ) {
918
+ defaultTitle = val;
919
+ } else {
920
+ defaultTitle = tsf.params.untitledTitle;
921
+ }
922
+ updatePlaceholder();
923
+ triggerCounter();
924
+ }
925
+ //= The home page listens to a static preset value.
926
+ if ( ! tsf.states.isHome ) {
927
+ jQuery( '#edittag #name, #titlewrap #title' ).on( 'input', updateDefaultTitle );
928
+ }
929
+
930
+ /**
931
+ * Triggers input event for titles in set intervals on window resize.
932
+ *
933
+ * This only happens if boundaries are surpassed to reduce CPU usage.
934
+ * This boundary is 782 pixels, because that forces input fields to change.
935
+ * in WordPress.
936
+ *
937
+ * @function
938
+ * @return {undefined}
939
+ */
940
+ const prepareUnregisteredInputOnResize = function() {
941
+ let resizeTimeout = 0,
942
+ prevWidth = window.innerWidth;
943
+
944
+ window.addEventListener( 'resize', function() {
945
+ clearTimeout( resizeTimeout );
946
+ resizeTimeout = setTimeout( function() {
947
+ let width = window.innerWidth;
948
+ if ( prevWidth < width ) {
949
+ if ( prevWidth <= 782 && width >= 782 ) {
950
+ triggerUnregisteredTitleChange();
951
+ }
952
+ } else {
953
+ if ( prevWidth >= 782 && width <= 782 ) {
954
+ triggerUnregisteredTitleChange();
955
+ }
956
+ }
957
+ prevWidth = width;
958
+ }, 50 );
959
+ } );
960
  }
961
+ prepareUnregisteredInputOnResize();
962
  },
963
 
964
  /**
965
+ * Initializes unbound title settings, which don't affect prefix/additions
966
+ * on-page.
967
  *
968
+ * @since 3.0.0
969
  *
970
  * @function
971
  * @return {undefined}
972
  */
973
+ _initUnboundTitleSettings: function() {
974
 
975
  if ( ! tsf.hasInput )
976
  return;
977
 
978
+ let $doctitles = jQuery( "#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]" );
 
 
 
 
 
 
 
979
 
980
+ /**
981
+ * Makes user click act naturally by selecting the adjacent Title text
982
+ * input and move cursor all the way to the end.
983
+ *
984
+ * @function
985
+ * @param {!jQuery.Event} event
986
+ * @return {undefined}
987
+ */
988
+ const focusTitleInput = function( event ) {
989
+ let input = jQuery( event.target ).siblings( $doctitles )[0];
990
+
991
+ if ( 'function' === typeof input.setSelectionRange ) {
992
+ input.focus();
993
+ let length = input.value.length * 2;
994
+ input.setSelectionRange( length, length );
995
+ } else {
996
+ //= Older browser compat.
997
+ let val = input.value;
998
+ input.value = '';
999
+ input.focus();
1000
+ input.value = val;
1001
+ }
1002
  }
1003
+ jQuery( '#tsf-title-placeholder, #tsf-title-placeholder-prefix' ).on( 'click', focusTitleInput );
1004
 
1005
+ /**
1006
+ * Triggers Change on Left/Right selection of global title options.
1007
+ *
1008
+ * @function
1009
+ * @param {!jQuery.Event} event
1010
+ * @return {undefined}
1011
+ */
1012
+ const toggleExampleDisplay = function( event ) {
1013
+ if ( jQuery( event.target ).is( ':checked' ) ) {
1014
+ jQuery( '.tsf-title-additions-js' ).css( 'display', 'none' );
1015
+ } else {
1016
+ jQuery( '.tsf-title-additions-js' ).css( 'display', 'inline' );
1017
+ }
1018
  }
1019
+ jQuery( '#autodescription-site-settings\\[title_rem_additions\\]' ).on( 'click', toggleExampleDisplay );
1020
 
1021
+ /**
1022
+ * Toggles title additions location for the Title examples.
1023
+ * There are two elements, rather than one. One is hidden by default.
1024
+ *
1025
+ * @function
1026
+ * @param {!jQuery.Event} event
1027
+ * @return {undefined}
1028
+ */
1029
+ const toggleExampleLocation = function( event ) {
1030
+ let $titleExampleLeft = jQuery( '.tsf-title-additions-example-left' ),
1031
+ $titleExampleRight = jQuery( '.tsf-title-additions-example-right' );
1032
+
1033
+ if ( 'right' === jQuery( event.target ).val() ) {
1034
+ $titleExampleLeft.css( 'display', 'none' );
1035
+ $titleExampleRight.css( 'display', 'inline' );
1036
+ } else {
1037
+ $titleExampleLeft.css( 'display', 'inline' );
1038
+ $titleExampleRight.css( 'display', 'none' );
1039
+ }
1040
  }
1041
+ jQuery( '#tsf-title-location input' ).on( 'click', toggleExampleLocation );
1042
 
1043
+ /**
1044
+ * Adjusts homepage left/right title example part.
1045
+ *
1046
+ * @function
1047
+ * @param {!jQuery.Event} event
1048
+ * @return {undefined}
1049
+ */
1050
+ const adjustHomepageExampleOutput = function( event ) {
1051
+ let val = event.target.value || '',
1052
+ $title = jQuery( '.tsf-custom-title-js' );
1053
+
1054
+ if ( 0 === val.length ) {
1055
+ $title.text( tsf.params.objectTitle );
1056
+ } else {
1057
+ $title.text( val );
1058
+ }
1059
+ };
1060
+ jQuery( '#autodescription-site-settings\\[homepage_title\\]' ).on( 'input', adjustHomepageExampleOutput );
1061
+
1062
+ /**
1063
+ * Adjusts homepage left/right title example part.
1064
+ *
1065
+ * @function
1066
+ * @param {!jQuery.Event} event
1067
+ * @return {undefined}
1068
+ */
1069
+ const adjustHomepageTaglineExampleOutput = function( event ) {
1070
+ let val = event.target.value || '',
1071
+ $tagline = jQuery( '.tsf-custom-tagline-js' );
1072
+
1073
+ if ( 0 === val.length ) {
1074
+ $tagline.text( tsf.params.blogDescription );
1075
+
1076
+ if ( 0 === tsf.params.blogDescription.length ) {
1077
+ jQuery( '#tsf-home-title-location .tsf-sep-js' ).hide();
1078
+ } else {
1079
+ jQuery( '#tsf-home-title-location .tsf-sep-js' ).show();
1080
+ }
1081
+ } else {
1082
+ $tagline.text( val );
1083
+ jQuery( '#tsf-home-title-location .tsf-sep-js' ).show();
1084
+ }
1085
+ };
1086
+ jQuery( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).on( 'input', adjustHomepageTaglineExampleOutput );
1087
+ jQuery( '#autodescription-site-settings\\[homepage_title_tagline\\]' ).trigger( 'input' );
1088
+
1089
+ /**
1090
+ * Toggles title prefixes for the Prefix Title example.
1091
+ *
1092
+ * @function
1093
+ * @param {!jQuery.Event} event
1094
+ * @return {undefined}
1095
+ */
1096
+ const adjustPrefixExample = function( event ) {
1097
+ let $this = jQuery( event.target ),
1098
+ $prefix = jQuery( '.tsf-title-prefix-example' );
1099
+
1100
+ if ( $this.is(':checked') ) {
1101
+ $prefix.css( 'display', 'none' );
1102
+ } else {
1103
+ $prefix.css( 'display', 'inline' );
1104
+ }
1105
  }
1106
+ jQuery( '#title-prefixes-toggle :input' ).on( 'click', adjustPrefixExample );
1107
  },
1108
 
1109
  /**
1110
+ * Initializes all aspects for description editing.
1111
+ * Assumes only one description editor is present in the DOM.
1112
  *
1113
+ * @since 3.0.0
1114
  *
1115
  * @function
 
1116
  * @return {undefined}
1117
  */
1118
+ _initDescInputs: function() {
1119
+
1120
+ if ( ! tsf.hasInput )
1121
+ return;
1122
 
1123
+ let $descriptions = jQuery( "#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]" );
 
1124
 
1125
+ if ( ! $descriptions.length )
1126
+ return;
1127
+
1128
+ let separator = tsf.params.descriptionSeparator;
1129
+
1130
+ /**
1131
+ * Updates used separator and all examples thereof.
1132
+ *
1133
+ * @function
1134
+ * @param {!jQuery.Event} event
1135
+ * @return {undefined}
1136
+ */
1137
+ const updateSeparator = function( event ) {
1138
+ let val = jQuery( event.target ).val(),
1139
+ newSep = '';
1140
+
1141
+ switch ( val ) {
1142
+ case 'pipe' :
1143
+ newSep = '|';
1144
+ break;
1145
+
1146
+ case 'dash' :
1147
+ newSep = '-';
1148
+ break;
1149
+
1150
+ default :
1151
+ newSep = jQuery( '<div/>' ).html( "&" + val + ";" ).text();
1152
+ break;
1153
+ }
1154
+ separator = newSep;
1155
+ jQuery( "#autodescription-descsep-js" ).text( ' ' + separator + ' ' );
1156
+
1157
+ enqueueTriggerInput();
1158
  }
1159
+ jQuery( '#tsf-description-separator input' ).on( 'click', updateSeparator );
1160
 
1161
+ /**
1162
+ * Updates used separator and all examples thereof.
1163
+ *
1164
+ * @function
1165
+ * @param {!jQuery.Event} event
1166
+ * @return {undefined}
1167
+ */
1168
+ const updateCounter = function( event ) {
1169
+
1170
+ let counter = document.getElementById( event.target.id + '_chars' );
1171
 
1172
+ if ( ! counter )
1173
+ return;
1174
+
1175
+ let descLen = 0,
1176
+ target = event.target,
1177
+ counterClass = '',
1178
+ counterType = tsf.counterType,
1179
+ counterName = '',
1180
+ output = '';
1181
+
1182
+ if ( target.value.length < 1 ) {
1183
+ descLen = tsf.getStringLength( target.placeholder );
1184
+ } else {
1185
+ descLen = tsf.getStringLength( target.value );
1186
+ }
1187
 
1188
+ if ( descLen < 100 || descLen >= 175 ) {
1189
+ counterClass += 'tsf-count-bad';
1190
+ counterName = tsf.i18n.bad;
1191
+ } else if ( descLen < 137 || descLen > 155 ) {
1192
+ counterClass += 'tsf-count-okay';
1193
+ counterName = tsf.i18n.okay;
1194
+ } else {
1195
+ counterClass += 'tsf-count-good';
1196
+ counterName = tsf.i18n.good;
1197
+ }
1198
 
1199
+ if ( ! counterType || 1 == counterType ) {
1200
+ output = descLen.toString();
1201
+ } else if ( 2 == counterType ) {
1202
+ output = counterName;
1203
+ } else if ( 3 == counterType ) {
1204
+ output = descLen.toString() + ' - ' + counterName;
1205
  }
1206
 
1207
+ counter.innerHTML = output;
1208
+
1209
+ if ( tsf.additionsClass )
1210
+ counterClass += ' ' + tsf.additionsClass;
1211
+
1212
+ if ( counter.className !== counterClass )
1213
+ counter.className = counterClass;
1214
+ }
1215
+ const updatePixels = function( event ) {
1216
+ let element = document.getElementById( event.target.id + '_pixels' );
1217
+
1218
+ if ( ! element )
1219
+ return;
1220
+
1221
+ let text = '';
1222
+
1223
+ if ( event.target.value.length < 1 ) {
1224
+ text = event.target.placeholder;
1225
  } else {
1226
+ text = event.target.value;
1227
+ }
1228
+
1229
+ let test = {
1230
+ 'e': element,
1231
+ 'text' : text,
1232
+ 'guideline' : tsf.params.descPixelGuideline
1233
  }
1234
+
1235
+ tsf.updatePixelCounter( test );
1236
+ }
1237
+
1238
+ /**
1239
+ * Updates placements, placeholders and counters.
1240
+ *
1241
+ * @function
1242
+ * @param {!jQuery.Event} event
1243
+ * @return {undefined}
1244
+ */
1245
+ const updateDescriptionsTrigger = function( event ) {
1246
+ updateCounter( event );
1247
+ updatePixels( event );
1248
  }
1249
+ $descriptions.on( 'input.tsfUpdateDescriptions', updateDescriptionsTrigger );
1250
 
1251
+ /**
1252
+ * Triggers descriptions input.
1253
+ *
1254
+ * @function
1255
+ * @return {undefined}
1256
+ */
1257
+ const triggerInput = function() {
1258
+ $descriptions.trigger( 'input.tsfUpdateDescriptions' );
1259
+ }
1260
+ triggerInput();
1261
 
1262
+ let triggerBuffer = 0;
1263
+ /**
1264
+ * Triggers descriptions input.
1265
+ * @function
1266
+ * @return {undefined}
1267
+ */
1268
+ const enqueueTriggerInput = function() {
1269
+ clearTimeout( triggerBuffer );
1270
+ triggerBuffer = setTimeout( function() {
1271
+ triggerInput();
1272
+ }, 50 );
1273
+ }
1274
+ jQuery( window ).on( 'tsf-counter-updated', enqueueTriggerInput );
1275
  },
1276
 
1277
  /**
1278
+ * Initializes counters.
1279
  *
1280
+ * @since 3.0.0
1281
  *
1282
  * @function
1283
  * @return {undefined}
1284
  */
1285
+ _initCounters: function() {
1286
 
1287
+ if ( ! tsf.hasInput )
1288
+ return;
1289
 
1290
+ /**
1291
+ * Updates the counter type.
1292
+ *
1293
+ * @function
1294
+ * @param {!jQuery.Event} event
1295
+ * @return {undefined}
1296
+ */
1297
+ const counterUpdate = function( event ) {
1298
+
1299
+ // Count up, reset to 0 if needed. We have 4 options: 0, 1, 2, 3
1300
+ tsf.counterType = tsf.counterType + 1;
1301
+ if ( tsf.counterType > 3 )
1302
+ tsf.counterType = 0;
1303
+
1304
+ //* Update counters locally.
1305
+ updateCounterClasses();
1306
+
1307
+ let target = '.tsf-counter-wrap .tsf-ajax',
1308
+ status = 0;
1309
+
1310
+ //* Reset ajax loader
1311
+ tsf.resetAjaxLoader( target );
1312
+
1313
+ //* Set ajax loader.
1314
+ tsf.setAjaxLoader( target );
1315
+
1316
+ //* Setup external update.
1317
+ let settings = {
1318
+ method: 'POST',
1319
+ url: ajaxurl,
1320
+ datatype: 'json',
1321
+ data: {
1322
+ 'action' : 'the_seo_framework_update_counter',
1323
+ 'nonce' : tsf.nonces['edit_posts'],
1324
+ 'val' : tsf.counterType,
1325
+ },
1326
+ async: true,
1327
+ success: function( response ) {
1328
+
1329
+ /**
1330
+ * @TODO convert to json header and/or test for availability of response.type before parsing?
1331
+ * @see convertJSONResponse() @ https://github.com/sybrew/The-SEO-Framework-Extension-Manager/blob/master/lib/js/tsfem.js
1332
+ * @see send_json() @ https://github.com/sybrew/The-SEO-Framework-Extension-Manager/blob/master/inc/classes/core.class.php
1333
+ */
1334
+ response = jQuery.parseJSON( response );
1335
+
1336
+ //* I could do value check, but that will simply lag behind. Unless an annoying execution delay is added.
1337
+ if ( 'success' === response.type )
1338
+ status = 1;
1339
+
1340
+ switch ( status ) {
1341
+ case 0:
1342
+ tsf.unsetAjaxLoader( target, false );
1343
+ break;
1344
+ case 1:
1345
+ tsf.unsetAjaxLoader( target, true );
1346
+ break;
1347
+ default:
1348
+ tsf.resetAjaxLoader( target );
1349
+ break;
1350
+ }
1351
+ },
1352
+ }
1353
+
1354
+ jQuery.ajax( settings );
1355
+ }
1356
+ jQuery( '.tsf-counter' ).on( 'click', counterUpdate );
1357
+
1358
+ /**
1359
+ * Sets up additionsClass variable.
1360
+ * Also sets up browser caches correctly.
1361
+ *
1362
+ * @function
1363
+ * @return {undefined}
1364
+ */
1365
+ const updateCounterClasses = function() {
1366
+
1367
+ let counterType = tsf.counterType;
1368
+
1369
+ if ( 1 == counterType ) {
1370
+ tsf.additionsClass = 'tsf-counter-one';
1371
+ tsf.counterType = 1;
1372
+ } else if ( 2 == counterType ) {
1373
+ tsf.additionsClass = 'tsf-counter-two';
1374
+ tsf.counterType = 2;
1375
+ } else if ( 3 == counterType ) {
1376
+ tsf.additionsClass = 'tsf-counter-three';
1377
+ tsf.counterType = 3;
1378
+ } else {
1379
+ tsf.additionsClass = 'tsf-counter-zero';
1380
+ tsf.counterType = 0;
1381
+ }
1382
+
1383
+ tsf._triggerCounterUpdate();
1384
+ }
1385
+ updateCounterClasses();
1386
+
1387
+ /**
1388
+ * Triggers displaying/hiding of character counters.
1389
+ *
1390
+ * @function
1391
+ * @param {!jQuery.Event} event
1392
+ * @return {undefined}
1393
+ */
1394
+ const toggleCharacterCounterDisplay = function( event ) {
1395
+ if ( jQuery( event.target ).is( ':checked' ) ) {
1396
+ jQuery( '.tsf-counter-wrap' ).show();
1397
+ } else {
1398
+ jQuery( '.tsf-counter-wrap' ).hide();
1399
+ }
1400
  }
1401
+ jQuery( '#autodescription-site-settings\\[display_character_counter\\]' ).on( 'click', toggleCharacterCounterDisplay );
1402
 
1403
+ /**
1404
+ * Triggers displaying/hiding of character counters.
1405
+ *
1406
+ * @function
1407
+ * @param {!jQuery.Event} event
1408
+ * @return {undefined}
1409
+ */
1410
+ const togglePixelCounterDisplay = function( event ) {
1411
+ if ( jQuery( event.target ).is( ':checked' ) ) {
1412
+ jQuery( '.tsf-pixel-counter-wrap' ).show();
1413
+ //= Pixels couldn't be counted when it was hidden.
1414
+ tsf._triggerCounterUpdate();
1415
+ } else {
1416
+ jQuery( '.tsf-pixel-counter-wrap' ).hide();
1417
+ }
1418
+ }
1419
+ jQuery( '#autodescription-site-settings\\[display_pixel_counter\\]' ).on( 'click', togglePixelCounterDisplay );
1420
  },
1421
 
1422
  /**
1423
+ * Initializes primary term selection.
1424
  *
1425
+ * @since 3.0.0
 
 
 
 
1426
  *
1427
  * @function
1428
  * @return {undefined}
1429
  */
1430
+ _initPrimaryTerm: function() {
1431
 
1432
+ if ( ! tsf.hasInput || ! Object.keys( tsf.states.taxonomies ).length )
1433
+ return;
1434
 
1435
+ let taxonomies = tsf.states.taxonomies,
1436
+ inputTemplate = wp.template( 'tsf-primary-term-selector' ),
1437
+ helpTemplate = wp.template( 'tsf-primary-term-selector-help' );
1438
+
1439
+ let termSelector = document.createElement( 'span' );
1440
+ termSelector.classList.add( 'tsf-primary-term-selector' );
1441
+ termSelector.classList.add( 'tsf-set-primary-term' ); // newline for IE11 compat.
1442
+
1443
+ (function(){
1444
+ let radio = document.createElement( 'input' );
1445
+ radio.setAttribute( 'type', 'radio' );
1446
+ termSelector.appendChild( radio );
1447
+ })();
1448
+
1449
+ let input$ = {},
1450
+ checked$ = {},
1451
+ uniqueChecked$ = {},
1452
+ box$ = {},
1453
+ primaries = {};
1454
+
1455
+ const addInput = function( taxonomy ) {
1456
+ let $wrap = jQuery( '#' + taxonomy + 'div' ),
1457
+ template = inputTemplate( { 'taxonomy' : taxonomies[ taxonomy ] } );
1458
+ $wrap.append( template );
1459
+ }
1460
+ const addHelp = function( taxonomy ) {
1461
+ let $wrap = jQuery( '#taxonomy-' + taxonomy ),
1462
+ template = helpTemplate( { 'taxonomy' : taxonomies[ taxonomy ] } );
1463
+ $wrap.append( template );
1464
+ fixHelpPos( taxonomy );
1465
+ }
1466
+ const fixHelpPos = function( taxonomy ) {
1467
+ let wrap = document.getElementById( 'taxonomy-' + taxonomy ),
1468
+ tabs = wrap.querySelectorAll( '.tabs-panel' );
1469
 
1470
+ let tab = Array.prototype.slice.call( tabs ).filter( function( Element ) {
1471
+ return Element.offsetWidth > 0 || Element.offsetHeight > 0 || Element.getClientRects().length > 0;
1472
+ } )[0];
1473
 
1474
+ let offset = tab.scrollHeight > tab.clientHeight
1475
+ ? tab.offsetWidth - tab.clientWidth + 25 - 2 // 2px is padding or something?
1476
+ : 25;
1477
 
1478
+ if ( tsf.states.isRTL ) {
1479
+ wrap.querySelector( '.tsf-primary-term-selector-help-wrap' ).style.left = offset + 'px';
1480
+ } else {
1481
+ wrap.querySelector( '.tsf-primary-term-selector-help-wrap' ).style.right = offset + 'px';
1482
+ }
1483
+ }
1484
+ const fixHelpPosOnTabToggle = function( event ) {
1485
+ fixHelpPos( event.data.taxonomy );
1486
+ }
1487
+ const createSelector = function( taxonomy ) {
1488
+ let selector = termSelector.cloneNode( true );
1489
+ selector.setAttribute( 'title', taxonomies[ taxonomy ].i18n.makePrimary );
1490
+ selector.setAttribute( 'aria-label', taxonomies[ taxonomy ].i18n.makePrimary );
1491
+ return selector;
1492
+ }
1493
+ const setPostValue = function( taxonomy, value ) {
1494
+ let element = document.getElementById( 'autodescription[_primary_term_' + taxonomy + ']' );
1495
+ if ( element && element instanceof Element )
1496
+ element.value = value;
1497
+ }
1498
 
1499
+ const getBox = function( taxonomy, reset ) {
1500
+ if ( ! reset && box$[ taxonomy ] )
1501
+ return box$[ taxonomy ];
1502
+
1503
+ box$[ taxonomy ] = jQuery( '#' + taxonomy + 'checklist, #' + taxonomy + 'checklist-pop' );
1504
+ return box$[ taxonomy ];
1505
+ }
1506
+ const getInputWithVal = function( taxonomy, value ) {
1507
+ return input$[ taxonomy ].filter( '[value="' + value + '"]' );
1508
+ }
1509
+
1510
+ const makePrimary = function( taxonomy, value ) {
1511
+ let $label = getInputWithVal( taxonomy, value ).closest( 'label' );
1512
+ if ( $label.length ) {
1513
+ $label.addClass( 'tsf-is-primary-term' );
1514
+ $label.find( '.tsf-set-primary-term' ).each( function( index, e ) {
1515
+ e.setAttribute( 'title', taxonomies[ taxonomy ].i18n.primary );
1516
+ e.setAttribute( 'aria-label', taxonomies[ taxonomy ].i18n.primary );
1517
+ e.querySelector( 'input' ).checked = true;
1518
+ } );
1519
+ setPostValue( taxonomy, value );
1520
+ primaries[ taxonomy ] = value;
1521
+ } else {
1522
+ makeFirstPrimary( taxonomy );
1523
+ }
1524
+ }
1525
+ const unsetPrimaries = function( taxonomy ) {
1526
+ let $label = getBox( taxonomy ).find( 'label' );
1527
+ $label.removeClass( 'tsf-is-primary-term' );
1528
+ $label.find( '.tsf-set-primary-term' ).each( function( index, e ) {
1529
+ e.setAttribute( 'title', taxonomies[ taxonomy ].i18n.makePrimary );
1530
+ e.setAttribute( 'aria-label', taxonomies[ taxonomy ].i18n.makePrimary );
1531
+ e.querySelector( 'input' ).checked = false;
1532
+ } );
1533
+ setPostValue( taxonomy, '' );
1534
+ }
1535
+ const makeFirstPrimary = function( taxonomy ) {
1536
+ let $checked = uniqueChecked$[ taxonomy ].first(),
1537
+ value;
1538
+ if ( $checked.length ) {
1539
+ value = $checked.val() || '';
1540
+ makePrimary( taxonomy, value );
1541
+ primaries[ taxonomy ] = value;
1542
+ }
1543
+ }
1544
+
1545
+ const setPrimary = function( event ) {
1546
+ let taxonomy = event.data.taxonomy,
1547
+ value = jQuery( event.target ).closest( 'label' ).find( 'input[type=checkbox]' ).val();
1548
+
1549
+ unsetPrimaries( taxonomy );
1550
+ makePrimary( taxonomy, value );
1551
+
1552
+ //= Stop propagation
1553
+ return false;
1554
+ }
1555
+ const toggleShowSwitch = function( event ) {
1556
+ let taxonomy = event.data.taxonomy;
1557
+
1558
+ if ( event.target.checked ) {
1559
+ addCheckedNode( taxonomy, event.target );
1560
+ appendButton( taxonomy, event.target );
1561
+ } else {
1562
+ removeCheckedNode( taxonomy, event.target );
1563
+ removeButton( taxonomy, event.target );
1564
+ }
1565
+
1566
+ switch ( uniqueChecked$[ taxonomy ].length ) {
1567
+ case 0 :
1568
+ setPostValue( taxonomy, '' );
1569
+ break;
1570
+
1571
+ case 1 :
1572
+ makeFirstPrimary( taxonomy );
1573
+ break;
1574
+ }
1575
+ }
1576
+ const appendButton = function( taxonomy, element ) {
1577
+ let $label;
1578
+ getInputWithVal( taxonomy, element.value ).each( function( index, e ) {
1579
+ $label = jQuery( e ).closest( 'label' );
1580
+ if ( ! $label.find( '.tsf-primary-term-selector' ).length ) {
1581
+ $label.append( createSelector( taxonomy ) );
1582
  }
1583
+ } );
1584
+ }
1585
+ const removeButton = function( taxonomy, element ) {
1586
+ let $label, wasPrimary;
1587
+ getInputWithVal( taxonomy, element.value ).each( function( index, e ) {
1588
+ $label = jQuery( e ).closest( 'label' );
1589
+ wasPrimary = $label.hasClass( 'tsf-is-primary-term' );
1590
+ $label.removeClass( 'tsf-is-primary-term' );
1591
+ $label.find( '.tsf-primary-term-selector' ).remove();
1592
+ if ( wasPrimary ) makeFirstPrimary( taxonomy );
1593
+ } );
1594
+ }
1595
+ const addCheckedNode = function( taxonomy, element ) {
1596
+ checked$[ taxonomy ] = checked$[ taxonomy ].add( '[value="' + element.value + '"]' );
1597
+ uniqueChecked$[ taxonomy ] = uniqueChecked$[ taxonomy ].add( element );
1598
+ }
1599
+ const removeCheckedNode = function( taxonomy, element ) {
1600
+ checked$[ taxonomy ] = checked$[ taxonomy ].not( '[value="' + element.value + '"]' );
1601
+ uniqueChecked$[ taxonomy ] = uniqueChecked$[ taxonomy ].not( '[value="' + element.value + '"]' );
1602
+ }
1603
 
1604
+ const initVars = function( taxonomy ) {
1605
+ let $box = getBox( taxonomy, 1 );
 
 
1606
 
1607
+ input$[ taxonomy ] = $box.find( 'input[type=checkbox]' );
1608
+ checked$[ taxonomy ] = $box.find( 'input[type=checkbox]:checked' );
 
 
 
 
 
 
 
1609
 
1610
+ let found = {}, val;
1611
+ uniqueChecked$[ taxonomy ] = checked$[ taxonomy ];
1612
+ uniqueChecked$[ taxonomy ].each( function( index, element ) {
1613
+ val = jQuery( element ).val();
1614
+ if ( found[ val ] ) {
1615
+ uniqueChecked$[ taxonomy ].splice( index, 1 );
1616
+ } else {
1617
+ found[ val ] = true;
1618
+ }
1619
+ } );
1620
+ }
1621
+ const updateList = function( event, settings, wpList ) {
1622
+ if ( wpList.hasOwnProperty( 'settings' ) && wpList.settings.hasOwnProperty( 'what' ) ) {
1623
+ initVars( wpList.settings.what );
1624
+ initActions( wpList.settings.what );
1625
+ load( wpList.settings.what );
1626
+ fixHelpPos( wpList.settings.what );
1627
+ }
1628
+ }
1629
+ const initActions = function( taxonomy ) {
1630
+ let ns = 'tsfShowPrimary' + taxonomy,
1631
+ data = { 'taxonomy': taxonomy },
1632
+ $box = getBox( taxonomy ),
1633
+ $div = jQuery( '#' + taxonomy + 'div' ),
1634
+ $tabs = jQuery( '#' + taxonomy + '-tabs' );
1635
+
1636
+ $box.off( 'click.' + ns );
1637
+ $box.on( 'click.' + ns, 'input[type="checkbox"]', data, toggleShowSwitch );
1638
+ $box.on( 'click.' + ns, '.tsf-primary-term-selector', data, setPrimary );
1639
+
1640
+ $div.off( 'wpListAddEnd.' + ns );
1641
+ $div.on( 'wpListAddEnd.' + ns, '#' + taxonomy + 'checklist', updateList );
1642
+
1643
+ $tabs.off( 'click.' + ns );
1644
+ $tabs.on( 'click.' + ns, 'a', data, fixHelpPosOnTabToggle );
1645
+ }
1646
+ const load = function( taxonomy ) {
1647
+ getBox( taxonomy ).find( 'input[type="checkbox"]:checked' )
1648
+ .each( function( index, element ) {
1649
+ appendButton( taxonomy, element );
1650
+ } );
1651
 
1652
+ if ( taxonomies[ taxonomy ].primary ) {
1653
+ makePrimary( taxonomy, taxonomies[ taxonomy ].primary );
1654
+ } else {
1655
+ makeFirstPrimary( taxonomy );
1656
+ }
1657
  }
1658
+
1659
+ const init = function() {
1660
+ for ( let taxonomy in taxonomies ) {
1661
+ if ( getBox( taxonomy ).length ) {
1662
+ addInput( taxonomy );
1663
+ addHelp( taxonomy );
1664
+ initVars( taxonomy );
1665
+ initActions( taxonomy );
1666
+ load( taxonomy );
1667
+ }
1668
+ }
1669
+ }
1670
+ init();
1671
  },
1672
 
1673
  /**
1674
+ * Initializes status bar hover entries.
1675
  *
1676
+ * @since 3.0.0
 
1677
  *
1678
  * @function
1679
  * @return {undefined}
1680
  */
1681
+ _initToolTips: function() {
1682
 
1683
+ let touchBuffer = 0,
1684
+ inTouchBuffer = false;
1685
 
1686
+ const setTouchBuffer = function() {
1687
+ inTouchBuffer = true;
1688
+ clearTimeout( touchBuffer );
1689
+ touchBuffer = setTimeout( function() {
1690
+ inTouchBuffer = false;
1691
+ }, 250 );
1692
+ }
1693
 
1694
+ const setEvents = function( target, unset ) {
 
 
 
1695
 
1696
+ unset = unset || false;
 
 
 
1697
 
1698
+ let touchEvents = 'pointerdown.tsfTT touchstart.tsfTT click.tsfTT',
1699
+ $target = jQuery( target );
1700
+
1701
+ if ( unset ) {
1702
+ $target.off( 'mousemove mouseleave mouseout tsf-tooltip-update' );
1703
+ jQuery( document.body ).off( touchEvents );
1704
+ } else {
1705
+ $target.on( {
1706
+ 'mousemove' : mouseMove,
1707
+ 'mouseleave' : mouseLeave,
1708
+ 'mouseout' : mouseLeave,
1709
+ } );
1710
+ jQuery( document.body ).off( touchEvents ).on( touchEvents, touchRemove );
1711
  }
 
1712
 
1713
+ $target.on( 'tsf-tooltip-update', updateDesc );
1714
+ }
1715
+ const unsetEvents = function( target ) {
1716
+ setEvents( target, true );
1717
+ }
1718
+ const updateDesc = function( event ) {
1719
+ if ( event.target.classList.contains( 'tsf-tooltip-item' ) ) {
1720
+ let tooltipText = event.target.querySelector( '.tsf-tooltip-text' );
1721
+ if ( tooltipText instanceof Element )
1722
+ tooltipText.innerHTML = event.target.dataset.desc;
1723
+ }
1724
+ }
1725
+ const mouseEnter = function( event ) {
1726
+ let $hoverItem = jQuery( event.target ),
1727
+ desc = event.target.dataset.desc;
1728
+
1729
+ if ( desc && 0 === $hoverItem.find( 'div' ).length ) {
1730
+ //= Remove any titles attached.
1731
+ event.target.title = "";
1732
+
1733
+ let $tooltip = jQuery(
1734
+ '<div class="tsf-tooltip"><span class="tsf-tooltip-text-wrap"><span class="tsf-tooltip-text">'
1735
+ + desc +
1736
+ '</span></span><div class="tsf-tooltip-arrow"></div></div>'
1737
+ );
1738
+ $hoverItem.append( $tooltip );
1739
 
1740
+ let $boundary = $hoverItem.closest( '.tsf-tooltip-boundary' );
1741
+ $boundary = $boundary.length && $boundary || jQuery( document.body );
 
 
 
 
 
 
 
 
 
1742
 
1743
+ //= 9 = arrow (8) + shadow (1)
1744
+ let tooltipHeight = $hoverItem.outerHeight() + 9,
1745
+ tooltipTop = $tooltip.offset().top - tooltipHeight,
1746
+ boundaryTop = $boundary.offset().top - ( $boundary.prop( 'scrolltop' ) || 0 );
 
 
 
 
 
 
 
1747
 
1748
+ if ( boundaryTop > tooltipTop ) {
1749
+ $tooltip.addClass( 'tsf-tooltip-down' );
1750
+ $tooltip.css( 'top', tooltipHeight + 'px' );
1751
+ } else {
1752
+ $tooltip.css( 'bottom', tooltipHeight + 'px' );
1753
+ }
1754
+
1755
+ let $hoverItemWrap = $hoverItem.closest( '.tsf-tooltip-wrap' ),
1756
+ $textWrap = $tooltip.find( '.tsf-tooltip-text-wrap' ),
1757
+ $innerText = $textWrap.find( '.tsf-tooltip-text' ),
1758
+ hoverItemWrapWidth = $hoverItemWrap.width(),
1759
+ textWrapWidth = $textWrap.outerWidth( true ),
1760
+ textWidth = $innerText.outerWidth( true ),
1761
+ textLeft = $textWrap.offset().left,
1762
+ textRight = textLeft + textWidth,
1763
+ boundaryLeft = $boundary.offset().left - ( $boundary.prop( 'scrollLeft' ) || 0 ),
1764
+ boundaryRight = boundaryLeft + $boundary.outerWidth();
1765
+
1766
+ //= RTL and LTR are normalized to abide to left.
1767
+ let direction = 'left';
1768
+
1769
+ if ( textLeft < boundaryLeft ) {
1770
+ //= Overflown over left boundary (likely window)
1771
+ //= Add indent relative to boundary. 24px width of arrow / 2 = 12 middle
1772
+ let horIndent = boundaryLeft - textLeft + 12,
1773
+ basis = parseInt( $textWrap.css( 'flex-basis' ), 10 );
1774
+
1775
+ /**
1776
+ * If the overflow is greater than the tooltip flex basis,
1777
+ * the tooltip was grown. Shrink it back to basis and use that.
1778
+ */
1779
+ if ( horIndent < -basis )
1780
+ horIndent = -basis;
1781
+
1782
+ $tooltip.css( direction, horIndent + 'px' );
1783
+ $tooltip.data( 'overflow', horIndent );
1784
+ $tooltip.data( 'overflowDir', direction );
1785
+ } else if ( textRight > boundaryRight ) {
1786
+ //= Overflown over right boundary (likely window)
1787
+ //= Add indent relative to boundary. Add 12px for visual appeal.
1788
+ let horIndent = boundaryRight - textRight - hoverItemWrapWidth - 12,
1789
+ basis = parseInt( $textWrap.css( 'flex-basis' ), 10 );
1790
+
1791
+ /**
1792
+ * If the overflow is greater than the tooltip flex basis,
1793
+ * the tooltip was grown. Shrink it back to basis and use that.
1794
+ */
1795
+ if ( horIndent < -basis )
1796
+ horIndent = -basis;
1797
+
1798
+ $tooltip.css( direction, horIndent + 'px' );
1799
+ $tooltip.data( 'overflow', horIndent );
1800
+ $tooltip.data( 'overflowDir', direction );
1801
+ } else if ( hoverItemWrapWidth < 42 ) {
1802
+ //= Small tooltip container. Add indent to make it visually appealing.
1803
+ let indent = -15;
1804
+ $tooltip.css( direction, indent + 'px' );
1805
+ $tooltip.data( 'overflow', indent );
1806
+ $tooltip.data( 'overflowDir', direction );
1807
+ } else if ( hoverItemWrapWidth > textWrapWidth ) {
1808
+ //= Wrap is bigger than tooltip. Adjust accordingly.
1809
+ let pagex = event.originalEvent && event.originalEvent.pageX || event.pageX, // iOS touch support,
1810
+ hoverItemLeft = $hoverItemWrap.offset().left,
1811
+ center = pagex - hoverItemLeft,
1812
+ left = center - textWrapWidth / 2,
1813
+ right = left + textWrapWidth;
1814
+
1815
+ if ( left < 0 ) {
1816
+ //= Don't overflow left.
1817
+ left = 0;
1818
+ } else if ( right > hoverItemWrapWidth ) {
1819
+ //= Don't overflow right.
1820
+ //* Use textWidth instead of textWrapWidth as it gets squashed in flex.
1821
+ left = hoverItemWrapWidth - textWidth;
1822
+ }
1823
+
1824
+ $tooltip.css( direction, left + 'px' );
1825
+ $tooltip.data( 'adjust', left );
1826
+ $tooltip.data( 'adjustDir', direction );
1827
+ }
1828
+ }
1829
+ }
1830
+ const mouseMove = function( event ) {
1831
+ let $target = jQuery( event.target ),
1832
+ $tooltip = $target.find( '.tsf-tooltip' ),
1833
+ $arrow = $tooltip.find( '.tsf-tooltip-arrow' ),
1834
+ overflow = $tooltip.data( 'overflow' ),
1835
+ overflowDir = $tooltip.data( 'overflowDir' );
1836
+
1837
+ overflow = parseInt( overflow, 10 );
1838
+ overflow = isNaN( overflow ) ? 0 : - Math.round( overflow );
1839
+
1840
+ if ( overflow ) {
1841
+ //= Static arrow based on static overflow.
1842
+ $arrow.css( overflowDir, overflow + "px" );
1843
+ } else {
1844
+ let pagex = event.originalEvent && event.originalEvent.pageX || event.pageX, // iOS touch support
1845
+ arrowBoundary = 7,
1846
+ arrowWidth = 16,
1847
+ $hoverItemWrap = $target.closest( '.tsf-tooltip-wrap' ),
1848
+ mousex = pagex - $hoverItemWrap.offset().left - arrowWidth / 2,
1849
+ originalMousex = mousex,
1850
+ $textWrap = $tooltip.find( '.tsf-tooltip-text-wrap' ),
1851
+ textWrapWidth = $textWrap.outerWidth( true ),
1852
+ adjust = $tooltip.data( 'adjust' ),
1853
+ adjustDir = $tooltip.data( 'adjustDir' ),
1854
+ boundaryRight = textWrapWidth - arrowWidth - arrowBoundary;
1855
+
1856
+ //= mousex is skewed, adjust.
1857
+ adjust = parseInt( adjust, 10 );
1858
+ adjust = isNaN( adjust ) ? 0 : Math.round( adjust );
1859
+ if ( adjust ) {
1860
+ adjust = 'left' === adjustDir ? -adjust : adjust;
1861
+ mousex = mousex + adjust;
1862
+
1863
+ //= Use textWidth for right boundary if adjustment exceeds.
1864
+ if ( boundaryRight - adjust > $hoverItemWrap.outerWidth( true ) ) {
1865
+ let $innerText = $textWrap.find( '.tsf-tooltip-text' ),
1866
+ textWidth = $innerText.outerWidth( true );
1867
+ boundaryRight = textWidth - arrowWidth - arrowBoundary;
1868
+ }
1869
+ }
1870
+
1871
+ if ( mousex <= arrowBoundary ) {
1872
+ //* Overflown left.
1873
+ $arrow.css( 'left', arrowBoundary + "px" );
1874
+ } else if ( mousex >= boundaryRight ) {
1875
+ //* Overflown right.
1876
+ $arrow.css( 'left', boundaryRight + "px" );
1877
+ } else {
1878
+ //= Somewhere in the middle.
1879
+ $arrow.css( 'left', mousex + "px" );
1880
+ }
1881
+ }
1882
+ }
1883
+ const mouseLeave = function( event ) {
1884
 
1885
+ //* @see touchMove
1886
+ if ( inTouchBuffer )
1887
+ return;
1888
 
1889
+ jQuery( event.target ).find( '.tsf-tooltip' ).remove();
1890
+ unsetEvents( event.target );
 
 
 
1891
  }
1892
+ /**
1893
+ * ^^^
1894
+ * These two methods conflict eachother in EdgeHTML.
1895
+ * Thusly, touch buffer.
1896
+ * vvv
1897
+ */
1898
+ const touchRemove = function( event ) {
1899
 
1900
+ //* @see mouseLeave
1901
+ setTouchBuffer();
 
 
1902
 
1903
+ let itemSelector = '.tsf-tooltip-item',
1904
+ balloonSelector = '.tsf-tooltip';
1905
 
1906
+ let $target = jQuery( event.target ),
1907
+ $keepBalloon;
1908
+
1909
+ if ( $target.hasClass( 'tsf-tooltip-item' ) ) {
1910
+ $keepBalloon = $target.find( balloonSelector );
1911
+ }
1912
+ if ( ! $keepBalloon ) {
1913
+ let $children = $target.children( itemSelector );
1914
+ if ( $children.length ) {
1915
+ $keepBalloon = $children.find( balloonSelector );
1916
  }
1917
  }
 
 
1918
 
1919
+ if ( $keepBalloon && $keepBalloon.length ) {
1920
+ //= Remove all but this.
1921
+ jQuery( balloonSelector ).not( $keepBalloon ).remove();
 
 
 
 
 
 
 
 
 
 
 
1922
  } else {
1923
+ //= Remove all.
1924
+ jQuery( balloonSelector ).remove();
 
 
 
 
 
1925
  }
1926
  }
1927
 
1928
+ /**
1929
+ * Loads tooltips within wrapper.
1930
+ * @function
1931
+ */
1932
+ const loadToolTip = function( event ) {
1933
 
1934
+ if ( inTouchBuffer )
1935
+ return;
 
1936
 
1937
+ let isTouch = false;
 
 
 
 
 
1938
 
1939
+ switch ( event.type ) {
1940
+ case 'mouseenter' :
1941
+ //= Most likely, thus placed first.
1942
+ break;
 
 
 
 
1943
 
1944
+ case 'pointerdown' :
1945
+ case 'touchstart' :
1946
+ isTouch = true;
1947
+ break;
1948
 
1949
+ default :
1950
+ break;
1951
  }
1952
 
1953
+ if ( event.target.classList.contains( 'tsf-tooltip-item' ) ) {
1954
+ //= Removes previous items and sets buffer.
1955
+ isTouch && touchRemove( event );
1956
 
1957
+ mouseEnter( event );
1958
+ //= Initiate placement directly for Windows Touch or when overflown.
1959
+ mouseMove( event );
 
1960
 
1961
+ setEvents( event.target );
1962
  } else {
1963
+ //= Delegate or bubble, and go back to this method with the correct item.
1964
+ let item = event.target.querySelector( '.tsf-tooltip-item:hover' ),
1965
+ _event = new jQuery.Event( event.type );
1966
+
1967
+ _event.pageX = event.originalEvent && event.originalEvent.pageX || event.pageX;
1968
 
1969
+ if ( item ) {
1970
+ if ( tsfL10n.states.debug ) console.log( 'Tooltip event warning: delegation' );
1971
+ jQuery( item ).trigger( _event );
1972
+ } else {
1973
+ if ( tsfL10n.states.debug ) console.log( 'Tooltip event warning: bubbling' );
1974
+ jQuery( event.target ).closest( '.tsf-tooltip-wrap' ).find( '.tsf-tooltip-item:hover' ).trigger( _event );
1975
  }
1976
  }
1977
 
1978
+ //* Stop further propagation.
1979
+ event.stopPropagation();
1980
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1981
 
1982
+ /**
1983
+ * Initializes SEO Bar tooltips.
1984
+ * @function
1985
+ */
1986
+ const initTooltips = function() {
1987
+ let $wrap = jQuery( '.tsf-tooltip-wrap' );
1988
 
1989
+ $wrap.off( 'mouseenter pointerdown touchstart' );
1990
+ $wrap.on( 'mouseenter pointerdown touchstart', '.tsf-tooltip-item', loadToolTip );
 
 
 
1991
  }
1992
+ initTooltips();
1993
+ jQuery( window ).on( 'tsf-reset-tooltips', initTooltips );
1994
+
1995
+ (function() {
1996
+ let e = jQuery( '#wpcontent' );
1997
+ tsf.addTooltipBoundary( e );
1998
+ })();
1999
  },
2000
 
2001
  /**
2002
+ * Adds tooltip boundaries.
2003
  *
2004
+ * @since 3.0.0
2005
  *
2006
  * @function
2007
+ * @param {!jQuery|Element} e
2008
  * @return {undefined}
2009
  */
2010
+ addTooltipBoundary: function( e ) {
2011
+ jQuery( e ).addClass( 'tsf-tooltip-boundary' );
 
 
 
 
 
 
 
 
 
 
 
 
2012
  },
2013
 
2014
  /**
2015
+ * Sets correct tab content and classes on toggle.
2016
  *
2017
+ * @since 2.2.2
2018
+ * @since 2.6.0 Improved.
2019
+ * @since 2.9.0 Now always expects radio button input.
2020
+ * @see tsf.setTabsOnload
2021
  *
2022
  * @function
2023
+ * @param {!jQuery.Event} event
2024
+ * @return {(undefined|null)}
2025
  */
2026
+ tabToggle: function( event ) {
2027
 
2028
+ let $this = jQuery( event.target );
2029
+
2030
+ if ( ! $this.is( ':checked' ) )
2031
  return;
2032
 
2033
+ let target = $this.prop( 'id' ),
2034
+ name = $this.prop( 'name' );
2035
+
2036
+ if ( typeof name !== 'undefined' ) {
2037
+ let activeClass = 'tsf-active-tab-content',
2038
+ $newContent = jQuery( '#' + target + '-content' ),
2039
+ $previousContent = jQuery( '.' + activeClass );
2040
+
2041
+ //* Only parse if old content isn't the new.
2042
+ if ( ! $newContent.is( $previousContent ) && typeof $newContent !== 'undefined' ) {
2043
+ let $allContent = jQuery( '.' + name + '-content' );
2044
 
2045
+ $allContent.fadeOut( 150, function() {
2046
+ jQuery( this ).removeClass( activeClass );
2047
+ } );
2048
+ setTimeout( function() {
2049
+ $newContent.addClass( activeClass ).fadeIn( 250 );
2050
+ }, 150 );
2051
+ setTimeout( function() {
2052
+ jQuery( '#' + target ).trigger( 'tsf-tab-toggled' );
2053
+ }, 175 );
2054
+ }
2055
+ }
2056
  },
2057
 
2058
  /**
2059
+ * Refines Styling for the navigation tabs on the settings pages
2060
  *
2061
+ * @since 2.9.0
2062
+ * @todo merge with tabTobble or a collective method?
2063
  *
2064
  * @function
2065
+ * @param {!jQuery.Event} event
2066
+ * @return {(undefined|null)}
2067
  */
2068
+ flexTabToggle : function( event ) {
2069
 
2070
+ let $this = jQuery( event.target );
2071
+
2072
+ if ( ! $this.is( ':checked' ) )
2073
  return;
2074
 
2075
+ let target = $this.prop( 'id' ),
2076
+ name = $this.prop( 'name' );
2077
+
2078
+ if ( typeof name !== 'undefined' ) {
2079
+ let activeClass = 'tsf-flex-tab-content-active',
2080
+ $newContent = jQuery( '#' + target + '-content' ),
2081
+ $previousContent = jQuery( '.' + activeClass );
2082
+
2083
+ //* Only parse if old content isn't the new.
2084
+ if ( ! $newContent.is( $previousContent ) && typeof $newContent !== 'undefined' ) {
2085
+ let $allContent = jQuery( '.' + name + '-content' );
2086
 
2087
+ $allContent.fadeOut( 150, function() {
2088
+ jQuery( this ).removeClass( activeClass );
2089
+ } );
2090
+ setTimeout( function() {
2091
+ $newContent.addClass( activeClass ).fadeIn( 250 );
2092
+ }, 150 );
2093
+ setTimeout( function() {
2094
+ jQuery( '#' + target ).trigger( 'tsf-flex-tab-toggled' );
2095
+ }, 175 );
2096
+ }
2097
+ }
2098
  },
2099
 
2100
  /**
2101
+ * Sets the navigation tabs content equal to the buttons.
2102
  *
2103
+ * @since 2.9.0
2104
+ * @see tsf.tabToggle
2105
  *
2106
  * @function
2107
+ * @return {(undefined|null)}
2108
  */
2109
+ setTabsOnload: function() {
2110
+
2111
+ if ( ! tsf.hasInput )
2112
+ return;
2113
+
2114
+ if ( tsf.states['isSettingsPage'] ) {
2115
+ let $buttons = jQuery( '.tsf-nav-tab-wrapper .tsf-tab:nth-of-type(n+2) input:checked' );
2116
+
2117
+ // Select all second or later tabs that have attribute checked.
2118
+ if ( $buttons.length ) {
2119
+ $buttons.each( function( i ) {
2120
+ let $this = jQuery( this ),
2121
+ target = $this.prop( 'id' ),
2122
+ name = $this.prop( 'name' );
2123
+
2124
+ if ( typeof name !== 'undefined' ) {
2125
+ let activeClass = 'tsf-active-tab-content',
2126
+ $newContent = jQuery( '#' + target + '-content' );
2127
+
2128
+ //* Only parse if old content isn't the new.
2129
+ if ( typeof $newContent !== 'undefined' ) {
2130
+ let $allContent = jQuery( '.' + name + '-content' );
2131
+
2132
+ $allContent.removeClass( activeClass );
2133
+ $newContent.addClass( activeClass );
2134
+ setTimeout( function() {
2135
+ jQuery( '#' + target ).trigger( 'tsf-tab-toggled' );
2136
+ }, 20 );
2137
+ }
2138
+ }
2139
+ } );
2140
+ }
2141
+ } else {
2142
+ // WordPress resets radio buttons on inpost settings. Leave this open for "when".
2143
+ }
2144
  },
2145
 
2146
  /**
2147
+ * Toggle tagline within the Description Example.
2148
  *
2149
+ * @since 2.3.4
 
2150
  *
2151
  * @function
2152
  * @param {!jQuery.Event} event
2153
  * @return {undefined}
2154
  */
2155
+ taglineToggleDesc: function( event ) {
2156
+
2157
+ let $this = jQuery( event.target ),
2158
+ $tagDesc = jQuery( '#tsf-on-blogname-js' );
2159
+
2160
+ if ( $this.is(':checked') ) {
2161
+ $tagDesc.css( 'display', 'inline' );
2162
+ } else {
2163
+ $tagDesc.css( 'display', 'none' );
2164
+ }
2165
  },
2166
 
2167
  /**
2168
+ * Toggle additions within Description example for the Example Description
2169
  *
2170
+ * @since 2.6.0
2171
  *
2172
  * @function
2173
+ * @param {!jQuery.Event} event
2174
  * @return {undefined}
2175
  */
2176
+ additionsToggleDesc: function( event ) {
2177
+
2178
+ let $this = jQuery( event.target ),
2179
+ $tagDesc = jQuery( '#tsf-description-additions-js' );
2180
+
2181
+ if ( $this.is(':checked') ) {
2182
+ $tagDesc.css( 'display', 'inline' );
2183
+ } else {
2184
+ $tagDesc.css( 'display', 'none' );
2185
+ }
2186
  },
2187
 
2188
  /**
2189
+ * Toggle tagline end examples within the Left/Right example for the
2190
+ * HomePage Title or Description.
2191
  *
2192
+ * @since 2.2.7
2193
  *
2194
  * @function
 
 
2195
  * @return {undefined}
2196
  */
2197
+ taglineToggleOnload: function() {
2198
 
2199
+ if ( ! tsf.hasInput )
2200
+ return;
2201
 
2202
+ let $tagTitle = jQuery( '#tsf-title-tagline-toggle :input' ),
2203
+ $title = jQuery( '.tsf-custom-blogname-js' ),
2204
+ $tagDescAdditions = jQuery( '#tsf-description-additions-toggle :input' ),
2205
+ $descAdditions = jQuery( '#tsf-description-additions-js' ),
2206
+ $tagDescBlogname = jQuery( '#tsf-description-onblogname-toggle :input' ),
2207
+ $descBlogname = jQuery( '#tsf-on-blogname-js' ),
2208
+ $tagTitleAdditions = jQuery( '#tsf-title-additions-toggle :input' ),
2209
+ $titleAdditions = jQuery( '.tsf-title-additions-js' );
2210
+
2211
+ if ( $tagTitle.is( ':checked' ) ) {
2212
+ $title.css( 'display', 'inline' );
2213
+ } else {
2214
+ $title.css( 'display', 'none' );
2215
+ }
2216
+
2217
+ if ( $tagDescAdditions.is( ':checked' ) ) {
2218
+ $descAdditions.css( 'display', 'inline' );
2219
+ } else {
2220
+ $descAdditions.css( 'display', 'none' );
2221
+ }
2222
+
2223
+ if ( $tagDescBlogname.is( ':checked' ) ) {
2224
+ $descBlogname.css( 'display', 'inline' );
2225
+ } else {
2226
+ $descBlogname.css( 'display', 'none' );
2227
  }
2228
 
2229
+ // Reverse option.
2230
+ if ( $tagTitleAdditions.is( ':checked' ) ) {
2231
+ $titleAdditions.css( 'display', 'none' );
2232
+ } else {
2233
+ $titleAdditions.css( 'display', 'inline' );
2234
+ }
2235
  },
2236
 
2237
  /**
2238
+ * Have all form fields in The SEO Framework metaboxes set a dirty flag when changed.
 
2239
  *
2240
+ * @since 2.0.0
2241
+ * @since 2.9.3 No longer heavily invokes change listeners after change has been set.
2242
  *
2243
  * @function
 
2244
  * @return {undefined}
2245
  */
2246
+ attachUnsavedChangesListener: function() {
2247
+
2248
+ if ( ! tsf.hasInput )
2249
+ return;
2250
+
2251
+ //= Self calling and cancelling function.
2252
+ let setUnsetChange = (function( event ) {
2253
+ tsf.settingsChanged || tsf.registerChange();
2254
+ jQuery( input ).not( except ).off( event.type, setUnsetChange );
2255
+ });
2256
+
2257
+ //= Mouse input
2258
+ let input = '.tsf-metaboxes :input, #tsf-inpost-box .inside :input',
2259
+ except = '.tsf-tab :input, .tsf-flex-nav-tab :input';
2260
+ jQuery( input ).not( except ).on( 'change', setUnsetChange );
2261
+
2262
+ //= Text input
2263
+ input = '.tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea';
2264
+ except = '.tsf-nav-tab-wrapper input, .tsf-flex-nav-tab-wrapper input';
2265
+ jQuery( input ).not( except ).on( 'input', setUnsetChange );
2266
+
2267
+ //= Alert caller (doesn't work well when leave alerts have been disabled)
2268
+ window.onbeforeunload = function() {
2269
+ if ( tsf.settingsChanged ) {
2270
+ return tsf.i18n['saveAlert'];
2271
+ }
2272
+ };
2273
+
2274
+ //= Remove alert on saving object or delete calls.
2275
+ jQuery( '.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete' ).click( function() {
2276
+ window.onbeforeunload = null;
2277
+ } );
2278
  },
2279
 
2280
  /**
2281
+ * Set a flag, to indicate form fields have changed.
2282
  *
2283
+ * @since 2.2.4
2284
  *
2285
  * @function
 
2286
  * @return {undefined}
2287
  */
2288
+ registerChange: function() {
2289
+ tsf.settingsChanged = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2290
  },
2291
 
2292
  /**
2293
+ * Ask user to confirm that settings should now be reset.
2294
  *
2295
+ * @since 2.2.4
2296
  *
2297
  * @function
2298
+ * @return {(Boolean|null)} True if reset should occur, false if not.
 
 
2299
  */
2300
+ confirmedReset: function() {
2301
+ return confirm( tsf.i18n['confirmReset'] );
 
 
 
 
 
 
 
 
 
 
2302
  },
2303
 
2304
  /**
2305
+ * OnLoad changes can affect settings changes. This function reverts those.
 
2306
  *
2307
+ * @since 2.5.0
2308
  *
2309
  * @function
2310
  * @return {undefined}
2311
  */
2312
+ onLoadUnregisterChange: function() {
2313
+ //* Prevent trigger of settings change
2314
+ tsf.settingsChanged = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2315
  },
2316
 
2317
  /**
2318
+ * Dismissible notices. Uses class .tsf-notice.
2319
  *
2320
  * @since 2.6.0
2321
+ * @since 2.9.3 Now correctly removes the node from DOM.
2322
  *
2323
  * @function
2324
+ * @param {!jQuery.Event} event
2325
  * @return {undefined}
2326
  */
2327
+ dismissNotice: function( event ) {
2328
+ jQuery( event.target ).parents( '.tsf-notice' ).slideUp( 200, function() {
2329
+ this.remove();
2330
+ } );
2331
  },
2332
 
2333
  /**
2334
+ * Visualizes AJAX loading time through target class change.
2335
  *
2336
+ * @since 2.7.0
2337
  *
2338
  * @function
2339
+ * @param {String} target
2340
+ * @return {undefined}
2341
  */
2342
+ setAjaxLoader: function( target ) {
2343
+ jQuery( target ).toggleClass( 'tsf-loading' );
2344
  },
2345
 
2346
  /**
2347
+ * Adjusts class loaders on Ajax response.
2348
  *
2349
  * @since 2.7.0
 
2350
  *
2351
  * @function
2352
+ * @param {String} target
2353
+ * @param {Boolean} success
2354
+ * @return {undefined}
2355
  */
2356
+ unsetAjaxLoader: function( target, success ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2357
 
2358
+ let newclass = 'tsf-success',
2359
+ fadeTime = 2500;
 
 
 
 
 
 
 
 
2360
 
2361
+ if ( ! success ) {
2362
+ newclass = 'tsf-error';
2363
+ fadeTime = 5000;
2364
  }
2365
 
2366
+ jQuery( target ).removeClass( 'tsf-loading' ).addClass( newclass ).fadeOut( fadeTime );
2367
+ },
 
2368
 
2369
+ /**
2370
+ * Cleans and resets Ajax wrapper class and contents to default.
2371
+ * Also stops any animation and resets fadeout to beginning.
2372
+ *
2373
+ * @since 2.7.0
2374
+ *
2375
+ * @function
2376
+ * @param {String} target
2377
+ * @return {undefined}
2378
+ */
2379
+ resetAjaxLoader: function( target ) {
2380
+ jQuery( target ).stop().empty().prop( 'class', 'tsf-ajax' ).css( 'opacity', '1' ).removeProp( 'style' );
2381
  },
2382
 
2383
  /**
2398
  return;
2399
  }
2400
 
2401
+ let $target = jQuery( event.target ),
2402
  inputID = $target.data( 'inputid' ),
2403
  frame;
2404
 
2413
  //* Init extend cropper.
2414
  tsf.extendCropper();
2415
 
2416
+ let _states = {
2417
+ suggestedWidth: $target.data( 'width' ) || 1200,
2418
+ suggestedHeight: $target.data( 'height' ) || 630,
2419
+ isFlex: typeof $target.data( 'flex' ) !== 'undefined' ? $target.data( 'flex' ) : 1,
2420
+ };
2421
+
2422
+ tsf.cropper.control = {
2423
+ 'params' : {
2424
+ 'flex_width' : _states.isFlex ? 4096 : 0,
2425
+ 'flex_height' : _states.isFlex ? 4096 : 0,
2426
+ 'width' : _states.suggestedWidth,
2427
+ 'height' : _states.suggestedHeight,
2428
+ 'isFlex' : _states.isFlex,
2429
+ },
2430
+ };
2431
+
2432
  frame = wp.media( {
2433
  button : {
2434
  'text' : tsf.other[ inputID ]['frame_button'],
2441
  'multiple' : false,
2442
  'date' : false,
2443
  'priority' : 20,
2444
+ 'suggestedWidth' : _states.suggestedWidth,
2445
+ 'suggestedHeight' : _states.suggestedHeight
2446
  } ),
2447
  new tsf.cropper( {
2448
+ 'imgSelectOptions' : tsf.calculateImageSelectOptions,
2449
  } ),
2450
  ],
2451
  } );
2452
 
2453
+ const onSelect = (function() {
2454
+ frame.setState( 'cropper' );
2455
+ } );
2456
+ frame.off( 'select', onSelect );
2457
+ frame.on( 'select', onSelect );
2458
+
2459
+ const onCropped = function( croppedImage ) {
2460
+ let url = croppedImage.url,
2461
+ attachmentId = croppedImage.id,
2462
+ w = croppedImage.width,
2463
+ h = croppedImage.height;
2464
+
2465
+ // Send the attachment id to our hidden input. URL to explicit output.
2466
+ jQuery( '#' + inputID + '-url' ).val( url );
2467
+ jQuery( '#' + inputID + '-id' ).val( attachmentId );
2468
+ };
2469
+ frame.off( 'cropped', onCropped );
2470
+ frame.on( 'cropped', onCropped );
2471
+
2472
+ const onSkippedCrop = function( selection ) {
2473
+ let url = selection.get( 'url' ),
2474
+ attachmentId = selection.get( 'id' ),
2475
+ w = selection.get( 'width' ),
2476
+ h = selection.get( 'height' );
2477
+
2478
+ // Send the attachment id to our hidden input. URL to explicit output.
2479
+ jQuery( '#' + inputID + '-url' ).val( url );
2480
+ jQuery( '#' + inputID + '-id' ).val( attachmentId );
2481
+ };
2482
+ frame.off( 'skippedcrop', onSkippedCrop );
2483
+ frame.on( 'skippedcrop', onSkippedCrop );
2484
+
2485
+ const onDone = function( imageSelection ) {
2486
+ jQuery( '#' + inputID + '-select' ).text( tsf.other[ inputID ]['change'] );
2487
+ jQuery( '#' + inputID + '-url' ).prop( 'readonly', true ).css( 'opacity', 0 ).animate(
2488
+ { 'opacity' : 1 },
2489
+ { 'queue' : true, 'duration' : 1000 },
2490
+ 'swing'
2491
+ );
2492
+
2493
+ tsf.appendRemoveButton( $target, inputID, true );
2494
+ tsf.registerChange();
2495
+ };
2496
+ frame.off( 'skippedcrop cropped', onDone );
2497
+ frame.on( 'skippedcrop cropped', onDone );
2498
 
2499
  frame.open();
2500
  },
2544
  */
2545
  removeEditorImage: function( event ) {
2546
 
2547
+ let inputID = jQuery( event.target ).data( 'inputid' );
 
2548
 
2549
  if ( jQuery( '#' + inputID + '-select' ).prop( 'disabled' ) )
2550
  return;
2551
 
2552
  jQuery( '#' + inputID + '-select' ).addClass( 'disabled' ).prop( 'disabled', true );
2553
 
2554
+ //* event.target.id === '#' + inputID + '-remove'.
2555
  jQuery( '#' + inputID + '-remove' ).addClass( 'disabled' ).prop( 'disabled', true ).fadeOut( 500, function() {
2556
  jQuery( this ).remove();
2557
  jQuery( '#' + inputID + '-select' ).text( tsf.other[ inputID ]['select'] ).removeClass( 'disabled' ).removeProp( 'disabled' );
2558
  } );
2559
 
2560
+ let $inputUrl = jQuery( '#' + inputID + '-url' );
2561
+
2562
+ $inputUrl.val( '' );
2563
+ if ( ! $inputUrl.data( 'readonly' ) ) {
2564
+ $inputUrl.removeProp( 'readonly' );
2565
+ }
2566
+ $inputUrl.css( 'opacity', 0 ).animate(
2567
  { 'opacity' : 1 },
2568
  { 'queue' : true, 'duration' : 500 },
2569
  'swing'
2588
  return;
2589
 
2590
  /**
2591
+ * wp.media.controller.Cropper augmentation.
2592
  *
2593
  * A state for cropping an image.
2594
  *
2597
  * @augments wp.media.controller.State
2598
  * @augments Backbone.Model
2599
  */
2600
+ let TSFCropper,
2601
+ Controller = wp.media.controller;
2602
+
2603
+ /**
2604
+ * wp.media.view.Cropper augmentation.
2605
+ *
2606
+ * @class
2607
+ * @augments wp.media.View
2608
+ * @augments wp.Backbone.View
2609
+ * @augments Backbone.View
2610
+ */
2611
+ let TSFView,
2612
+ View = wp.media.view;
2613
+
2614
+ TSFView = View.Cropper.extend( {
2615
+ className: 'crop-content tsf-image',
2616
+ ready: function () {
2617
+ View.Cropper.prototype.ready.apply( this, arguments );
2618
+ },
2619
+ onImageLoad: function() {
2620
+ let imgOptions = this.controller.get( 'imgSelectOptions' ),
2621
+ imgSelect;
2622
+
2623
+ if ( typeof imgOptions === 'function' ) {
2624
+ imgOptions = imgOptions( this.options.attachment, this.controller );
2625
+ }
2626
+
2627
+ //= Seriously Core team, was this condition too hard to implement?
2628
+ if ( 'undefined' === typeof imgOptions.aspectRatio ) {
2629
+ imgOptions = _.extend( imgOptions, {
2630
+ parent: this.$el,
2631
+ onInit: function() {
2632
+ this.parent.children().on( 'mousedown touchstart', function( e ) {
2633
+ if ( e.shiftKey ) {
2634
+ imgSelect.setOptions( {
2635
+ aspectRatio: '1:1'
2636
+ } );
2637
+ } else {
2638
+ imgSelect.setOptions( {
2639
+ aspectRatio: false
2640
+ } );
2641
+ }
2642
+ } );
2643
+ }
2644
+ } );
2645
+ }
2646
+ this.trigger( 'image-loaded' );
2647
+ imgSelect = this.controller.imgSelect = this.$image.imgAreaSelect( imgOptions );
2648
+ },
2649
+ } );
2650
 
2651
  TSFCropper = Controller.Cropper.extend( {
2652
+ createCropContent: function() {
2653
+ this.cropperView = new TSFView( {
2654
+ controller: this,
2655
+ attachment: this.get( 'selection' ).first()
2656
+ } );
2657
+ this.cropperView.on( 'image-loaded', this.createCropToolbar, this );
2658
+ this.frame.content.set( this.cropperView );
2659
+ },
2660
  doCrop: function( attachment ) {
2661
+ let cropDetails = attachment.get( 'cropDetails' ),
2662
  control = tsf.cropper.control;
2663
 
2664
  // Use crop measurements when flexible in both directions.
2674
  if ( cropDetails.width > control.params.flex_width || cropDetails.height > control.params.flex_height ) {
2675
  // Landscape
2676
  if ( cropDetails.width > cropDetails.height ) {
2677
+ let _ratio = cropDetails.width / control.params.flex_width;
2678
 
2679
  cropDetails.dst_width = control.params.flex_width;
2680
  cropDetails.dst_height = Math.round( cropDetails.height / _ratio );
2681
  // Portrait
2682
  } else {
2683
+ let _ratio = cropDetails.height / control.params.flex_height;
2684
 
2685
  cropDetails.dst_height = control.params.flex_height;
2686
  cropDetails.dst_width = Math.round( cropDetails.width / _ratio );
2705
  } );
2706
 
2707
  TSFCropper.prototype.control = {};
 
 
 
 
 
 
 
 
2708
 
2709
  tsf.cropper = TSFCropper;
2710
 
2724
  * @return {Object} imgSelectOptions
2725
  */
2726
  calculateImageSelectOptions: function( attachment, controller ) {
 
2727
  let control = tsf.cropper.control;
2728
 
2729
+ let flexWidth = !! parseInt( control.params.flex_width, 10 ),
2730
  flexHeight = !! parseInt( control.params.flex_height, 10 ),
2731
  xInit = parseInt( control.params.width, 10 ),
2732
  yInit = parseInt( control.params.height, 10 );
2740
  y1,
2741
  imgSelectOptions;
2742
 
2743
+ let canSkipCrop;
2744
+ if ( control.params.isFlex ) {
2745
+ canSkipCrop = ! tsf.mustBeCropped( control.params.flex_width, control.params.flex_height, realWidth, realHeight );
2746
+ } else {
2747
+ //= Not flex. If ratios match, then we can skip.
2748
+ canSkipCrop = ratio === realWidth / realHeight;
2749
+ }
2750
+
2751
  controller.set( 'control', control.params );
2752
+ controller.set( 'canSkipCrop', canSkipCrop );
2753
 
2754
  if ( realWidth / realHeight > ratio ) {
2755
  yInit = realHeight;
2777
  'y2' : yInit + y1
2778
  };
2779
 
 
 
 
 
2780
  // @TODO Convert set img min-width/height to output ratio.
2781
  // i.e. 200x2000 will become x = 1500/2000*200 = 150px, which is too small.
2782
  //= Unlikely...
2783
 
2784
+ if ( ! control.params.isFlex ) {
2785
+ imgSelectOptions.handles = 'corners';
2786
+ imgSelectOptions.aspectRatio = xInit + ':' + yInit;
2787
+ } else if ( ! flexHeight && ! flexWidth ) {
2788
+ imgSelectOptions.aspectRatio = xInit + ':' + yInit;
2789
+ } else {
2790
+ if ( flexHeight ) {
2791
+ imgSelectOptions.minHeight = 200;
2792
+ imgSelectOptions.maxWidth = realWidth;
2793
+ }
2794
+ if ( flexWidth ) {
2795
+ imgSelectOptions.minWidth = 200;
2796
+ imgSelectOptions.maxHeight = realHeight;
2797
+ }
2798
  }
2799
 
2800
  return imgSelectOptions;
2924
  }
2925
  },
2926
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2927
  /**
2928
  * Registers on resize/orientationchange listeners and debounces to only run
2929
  * at intervals.
2943
  //* Set event listeners.
2944
  tsf._setResizeListeners();
2945
 
2946
+ let resizeTimeout = 0,
2947
  $lastWidth = {},
2948
  timeOut = 0;
2949
 
2950
  // Warning: Only checks for the first item existence.
2951
+ let $tabWrapper = jQuery( '.tsf-flex-nav-tab-wrapper' ),
2952
+ $window = jQuery( window );
2953
 
2954
+ $window.on( 'tsf-flex-resize', function() {
2955
 
2956
  clearTimeout( resizeTimeout );
2957
 
3017
  } );
3018
 
3019
  //* Trigger after setup.
3020
+ $window.trigger( 'tsf-flex-resize' );
3021
  },
3022
 
3023
  /**
3035
  jQuery( '.meta-box-sortables' ).on( 'sortupdate', tsf._triggerResize );
3036
  },
3037
 
3038
+ /**
3039
+ * Triggers tooltip reset.
3040
+ *
3041
+ * @since 3.0.0
3042
+ *
3043
+ * @function
3044
+ * @return {(undefined|null)}
3045
+ */
3046
+ _triggerTooltipReset: function() {
3047
+ jQuery( window ).trigger( 'tsf-reset-tooltips' );
3048
+ },
3049
+
3050
+ /**
3051
+ * Triggers active tooltip update.
3052
+ *
3053
+ * @since 3.0.0
3054
+ *
3055
+ * @function
3056
+ * @param {Element} item
3057
+ * @return {(undefined|null)}
3058
+ */
3059
+ _triggerTooltipUpdate: function( item ) {
3060
+ jQuery( item ).trigger( 'tsf-tooltip-update' );
3061
+ },
3062
+
3063
  /**
3064
  * Triggers resize on event.
3065
  *
3072
  jQuery( window ).trigger( 'tsf-flex-resize' );
3073
  },
3074
 
3075
+ /**
3076
+ * Triggers counter update event.
3077
+ *
3078
+ * @since 3.0.0
3079
+ *
3080
+ * @function
3081
+ * @return {(undefined|null)}
3082
+ */
3083
+ _triggerCounterUpdate: function() {
3084
+ jQuery( window ).trigger( 'tsf-counter-updated' );
3085
+ },
3086
+
3087
  /**
3088
  * Sets tsf.ready action.
3089
  *
3099
  },
3100
 
3101
  /**
3102
+ * Runs document-on-ready actions.
 
 
 
 
 
 
 
 
3103
  *
3104
+ * @since 3.0.0
3105
+ * @access private
3106
  *
3107
  * @function
 
 
3108
  */
3109
+ _doReady: function() {
3110
 
3111
+ // Add counter listeners.
3112
+ tsf._initCounters();
 
 
 
3113
 
3114
  // Add title prop listeners. Must load before setTabsOnload to work.
3115
+ tsf._initTitleInputs();
3116
+ tsf._initUnboundTitleSettings();
3117
 
3118
+ // Add description prop listeners. Must load before setTabsOnload to work.
3119
+ tsf._initDescInputs();
3120
+
3121
+ // Set primary term listeners.
3122
+ tsf._initPrimaryTerm();
3123
 
3124
+ // Sets tabs to correct radio button on load.
3125
+ tsf.setTabsOnload();
3126
 
3127
  // Check if the Title Tagline or Description Additions should be removed when page is loaded.
3128
+ tsf.taglineToggleOnload();
3129
 
3130
  // Initialize the status bar hover balloon.
3131
+ tsf._initToolTips();
3132
 
3133
  // Initialize image uploader button cache.
3134
+ tsf.setupImageEditorActions();
3135
 
3136
  // Determine image editor button input states.
3137
+ tsf.checkImageEditorInput();
3138
 
3139
  // Correct Color Picker input
3140
+ tsf.setColorOnload();
3141
 
3142
  // #== End Before Change listener
3143
 
3144
  // Initialise form field changing flag.
3145
+ tsf.attachUnsavedChangesListener();
3146
 
3147
  // Deregister changes.
3148
+ tsf.onLoadUnregisterChange();
3149
 
3150
  // Trigger tsf-ready event.
3151
+ tsf._triggerReady();
3152
 
3153
  // #== Start After Change listener
3154
 
3155
  // Do flex resize functionality.
3156
+ tsf._doFlexResizeListener();
3157
+ },
3158
+
3159
+ /**
3160
+ * Sets up object parameters.
3161
+ *
3162
+ * @since 2.8.0
3163
+ *
3164
+ * @function
3165
+ * @return {(undefined|null)}
3166
+ */
3167
+ setupVars: function() {
3168
+
3169
+ // The counter type. Mixed string and int (i10n is string, JS is int).
3170
+ tsf.counterType = parseInt( tsf.states['counterType'] );
3171
+
3172
+ // Determines if the current page has input boxes for The SEO Framework.
3173
+ tsf.hasInput = tsf.states['hasInput'];
3174
+ },
3175
+
3176
+ /**
3177
+ * Initialises all aspects of the scripts.
3178
+ *
3179
+ * Generally ordered with stuff that inserts new elements into the DOM first,
3180
+ * then stuff that triggers an event on existing DOM elements when ready,
3181
+ * followed by stuff that triggers an event only on user interaction. This
3182
+ * keeps any screen jumping from occuring later on.
3183
+ *
3184
+ * @since 2.2.4
3185
+ * @since 2.7.0 jQuery object is now passed.
3186
+ *
3187
+ * @function
3188
+ * @param {!jQuery} $ jQuery
3189
+ * @return {undefined}
3190
+ */
3191
+ ready: function( $ ) {
3192
 
3193
+ // Set up object parameters.
3194
+ tsf.setupVars();
3195
 
3196
+ // Move the page updates notices below the tsf-top-wrap.
3197
+ $( 'div.updated, div.error, div.notice-warning' ).insertAfter( 'div.tsf-top-wrap' );
 
3198
 
3199
+ $( document.body ).ready( tsf._doReady );
 
 
 
3200
 
3201
  // Bind reset confirmation.
3202
+ $( '.tsf-js-confirm-reset' ).on( 'click', tsf.confirmedReset );
3203
 
3204
  // Toggle Tabs in the SEO settings page.
3205
+ $( '.tsf-tabs-radio' ).on( 'change', tsf.tabToggle );
3206
 
3207
  // Toggle Tabs for the inpost Flex settings.
3208
+ $( '.tsf-flex-nav-tab-radio' ).on( 'change', tsf.flexTabToggle );
3209
 
3210
  // Toggle Description additions removal.
3211
+ $( '#tsf-description-onblogname-toggle :input' ).on( 'click', tsf.taglineToggleDesc );
3212
+ $( '#tsf-description-additions-toggle :input' ).on( 'click', tsf.additionsToggleDesc );
3213
 
3214
  // Dismiss notices.
3215
+ $( '.tsf-dismiss' ).on( 'click', tsf.dismissNotice );
 
 
 
3216
  }
3217
  };
3218
  jQuery( tsf.ready );
lib/js/tsf.min.js CHANGED
@@ -1,38 +1 @@
1
- window.tsf={nonce:tsfL10n.nonce,nonces:tsfL10n.nonces,i18n:tsfL10n.i18n,states:tsfL10n.states,params:tsfL10n.params,other:tsfL10n.other,f:!1,m:!1,B:"",F:"",a:0,c:!1,g:"",cropper:{},h:function(){return jQuery("#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]")},G:function(){return jQuery("#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]")},confirm:function(a){return confirm(a)},
2
- M:function(a){var b=a.target.value&&a.target.value.length||0,c=document.getElementById(a.target.id+"_chars"),d=tsf.a,e=tsf.g,f="";0===b&&(b=a.target.placeholder&&a.target.placeholder.length);if(100>b||175<=b){a="tsf-count-bad";var k=tsf.i("bad")}else 137>b||155<b&&175>b?(a="tsf-count-okay",k=tsf.i("okay")):(a="tsf-count-good",k=tsf.i("good"));2>d?f=b:2==d?f=k:3==d&&(f=b+" - "+k);c.innerHTML=f;e&&(a+=" "+e);c.className!==a&&(c.className=a)},u:function(a){jQuery(a.target);var b=tsf.params.titleAdditions.length,
3
- c=tsf.params.blogDescription.length,d=tsf.params.siteTitle.length,e=a.target.value&&a.target.value.length||0,f=jQuery(a.target).prop("placeholder").length,k=jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").val(),l=3;a=jQuery("#"+tsf.aa(a.target.id)+"_chars");var h=0,m=tsf.g,g=tsf.a,n="";tsf.m||(l=b=0);0===e&&(0!==d?e=d:h=f);0!==e&&(0!==b&&"undefined"!==typeof k&&(h=k.length,b=0!==h?h:c),h=0===b?e:e+l+b);25>h||75<=h?(c="tsf-count-bad",e=tsf.i("bad")):42>h||55<h&&75>h?(c="tsf-count-okay",
4
- e=tsf.i("okay")):(c="tsf-count-good",e=tsf.i("good"));m&&(c+=" "+m);g&&1!=g?2==g?n=e:3==g&&(n=h.toString()+" - "+e):n=h.toString();a.text(n).removeClass().addClass(c)},aa:function(a){return a?a.replace(/([\[\]\/])/g,"\\$1"):a},ja:function(a){var b=jQuery(".tsf-sep-js");a=jQuery(a.target).val();tsf.B=a;"pipe"===a?b.text(" | "):"dash"===a?b.text(" - "):b.html(" &"+a+"; ").text()},ia:function(a){var b=jQuery("#autodescription-descsep-js");a=jQuery(a.target).val();"pipe"===a?b.text(" | "):"dash"===a?
5
- b.text(" - "):b.html(" &"+a+"; ").text()},statusBarHover:function(){var a=jQuery(".tsf-seo-bar-inner-wrap").find("a");a.off("mouseenter mousemove mouseleave mouseout");a.on({mouseenter:tsf.pa,mousemove:tsf.qa,mouseleave:tsf.K,mouseout:tsf.K})},pa: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",
6
- a.position().top-b+"px"))},qa:function(a){var b=jQuery(a.target);a=a.pageX;var c=a-b.closest(".tsf-seo-bar-inner-wrap").offset().left-11,d=b.find(".tsf-explanation-desc");b=d.find("div");if(1>c)b.css("left","0px");else if(void 0!==d.offset()){var e=d.width();d=d.offset().left+e+11;a>d?b.css("left",e+"px"):b.css("left",c+"px")}},K:function(a){jQuery(a.target).find("div.tsf-explanation-desc").remove()},Aa:function(a){a=jQuery(a.target);a.closest(".tsf-seo-bar-inner-wrap a").length||a.closest(".tsf-seo-bar-inner-wrap a").find("div.tsf-explanation-desc").remove()},
7
- ra:function(a){a=jQuery(a.target);if(a.is(":checked")){var b=a.prop("id");a=a.prop("name");if("undefined"!==typeof a){var c=jQuery("#"+b+"-content"),d=jQuery(".tsf-active-tab-content");c.is(d)||"undefined"===typeof c||(jQuery("."+a+"-content").fadeOut(150,function(){jQuery(this).removeClass("tsf-active-tab-content")}),setTimeout(function(){c.addClass("tsf-active-tab-content").fadeIn(250)},150),setTimeout(function(){jQuery("#"+b).trigger("tsf-tab-toggled")},175))}}},ca:function(a){a=jQuery(a.target);
8
- if(a.is(":checked")){var b=a.prop("id");a=a.prop("name");if("undefined"!==typeof a){var c=jQuery("#"+b+"-content"),d=jQuery(".tsf-flex-tab-content-active");c.is(d)||"undefined"===typeof c||(jQuery("."+a+"-content").fadeOut(150,function(){jQuery(this).removeClass("tsf-flex-tab-content-active")}),setTimeout(function(){c.addClass("tsf-flex-tab-content-active").fadeIn(250)},150),setTimeout(function(){jQuery("#"+b).trigger("tsf-flex-tab-toggled")},175))}}},ma:function(){if(tsf.c&&tsf.states.isSettingsPage){var a=
9
- jQuery(".tsf-nav-tab-wrapper .tsf-tab:nth-of-type(n+2) input:checked");a.length&&a.each(function(){var a=jQuery(this),c=a.prop("id");a=a.prop("name");if("undefined"!==typeof a){var d=jQuery("#"+c+"-content");"undefined"!==typeof d&&(jQuery("."+a+"-content").removeClass("tsf-active-tab-content"),d.addClass("tsf-active-tab-content"),setTimeout(function(){jQuery("#"+c).trigger("tsf-tab-toggled")},20))}})}},va:function(a){a=jQuery(a.target);var b=jQuery(".tsf-custom-blogname-js");a.is(":checked")?(b.css("display",
10
- "inline"),tsf.m=!0):(b.css("display","none"),tsf.m=!1);tsf.h().trigger("keyup",tsf.u)},ta:function(a){a=jQuery(a.target);var b=jQuery("#tsf-on-blogname-js");a.is(":checked")?b.css("display","inline"):b.css("display","none")},wa:function(a){a=jQuery(a.target).val();var b=jQuery(".tsf-title-additions-example-left"),c=jQuery(".tsf-title-additions-example-right");"right"===a?(b.css("display","none"),c.css("display","inline")):(b.css("display","inline"),c.css("display","none"))},xa:function(a){a=jQuery(a.target);
11
- var b=jQuery(".tsf-title-prefix-example");a.is(":checked")?b.css("display","none"):b.css("display","inline")},S:function(a){a=jQuery(a.target);var b=jQuery("#tsf-description-additions-js");a.is(":checked")?b.css("display","inline"):b.css("display","none")},ua:function(){if(tsf.c){var a=jQuery("#tsf-title-tagline-toggle :input"),b=jQuery(".tsf-custom-blogname-js"),c=jQuery("#tsf-description-additions-toggle :input"),d=jQuery("#tsf-description-additions-js"),e=jQuery("#tsf-description-onblogname-toggle :input"),
12
- f=jQuery("#tsf-on-blogname-js"),k=jQuery("#tsf-title-additions-toggle :input"),l=jQuery(".tsf-title-additions-js");a.is(":checked")?b.css("display","inline"):b.css("display","none");c.is(":checked")?d.css("display","inline"):d.css("display","none");e.is(":checked")?f.css("display","inline"):f.css("display","none");k.is(":checked")?l.css("display","none"):l.css("display","inline")}},ya:function(a){a=a.target.value||"";var b=jQuery(".tsf-custom-title-js");0===a.length?b.text(tsf.params.siteTitle):b.text(a)},
13
- A:function(a){a=a.target.value||"";var b=jQuery(".tsf-custom-tagline-js"),c=jQuery("#autodescription-site-settings\\[homepage_title\\]"),d=jQuery("#tsf-home-title-location input:checked").val(),e=jQuery("#autodescription-site-settings\\[homepage_tagline\\]"),f=tsf.params.siteTitle,k=f,l=tsf.params.blogDescription,h=tsf.H("title");e.is(":checked")&&(0!==a.length&&(l=a),k=0!==d.length&&"left"===d?f+" "+h+" "+l:l+" "+h+" "+f);b.text(l);c.prop("placeholder",k);tsf.h().trigger("input",tsf.u)},j:function(){var a=
14
- tsf.f;tsf.states.isSettingsPage?jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").trigger("input",tsf.A):jQuery("#autodescription_title").trigger("input",tsf.A);tsf.f=a},sa:function(){var a=0,b=0;jQuery(window).resize(function(){clearTimeout(a);a=setTimeout(function(){var a=jQuery(window).width();b<a?782>=b&&782<=a&&tsf.j():782<=b&&782>=a&&tsf.j();b=a},250)})},za:function(){var a=jQuery(event.target),b=jQuery(".tsf-title-additions-js");a.is(":checked")?b.css("display","none"):b.css("display",
15
- "inline")},T:function(){if(tsf.c){var a=function(d){tsf.f||tsf.l();jQuery(b).not(c).off(d.type,a)},b=".tsf-metaboxes :input, #tsf-inpost-box .inside :input",c=".tsf-tab :input, .tsf-flex-nav-tab :input";jQuery(b).not(c).on("change",a);b=".tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea";c=".tsf-nav-tab-wrapper input, .tsf-flex-nav-tab-wrapper input";jQuery(b).not(c).on("input",a);window.onbeforeunload=function(){if(tsf.f)return tsf.i18n.saveAlert};
16
- jQuery('.tsf-metaboxes input[type="submit"], #publishing-action input[type="submit"], #save-action input[type="submit"], a.submitdelete').click(function(){window.onbeforeunload=null})}},l:function(){tsf.f=!0},V:function(){return confirm(tsf.i18n.confirmReset)},Z:function(a){var b=tsf.params.titleAdditions.length,c=jQuery("#tsf-title-placeholder");if(!b)return jQuery(a.target).css("text-indent","initial"),c.empty();b=!1;var d=jQuery("#tsf-home-title-location input:checked").val(),e=tsf.states.isRTL;
17
- "undefined"!==typeof d&&0!==d.length?e?"right"===d&&(b=!0):"left"===d&&(b=!0):(d=tsf.params.titleLocation,tsf.states.isHome?tsf.m&&(e?"right"===d&&(b=!0):"left"===d&&(b=!0)):e?"left"===d&&(b=!0):"right"===d&&(b=!0));d=jQuery("#tsf-title-tagline-toggle :input");if("undefined"!==typeof d&&0<d.length&&!d.is(":checked"))jQuery(a.target).css("text-indent","initial"),c.css("display","none");else{a=jQuery(a.target);var f=a.val(),k=jQuery("#tsf-title-offset"),l=a.outerWidth(),h=(a.outerHeight(!0)-a.height())/
18
- 2,m=(l-a.innerWidth())/2;d=(a.outerWidth(!0)-a.width())/2;var g=jQuery("#autodescription-site-settings\\[homepage_title_tagline\\]").val();var n="left",p=tsf.H("title");e&&(n="right");"undefined"!==typeof g&&0===g.length&&(g=tsf.params.blogDescription);b?(e=" "+p+" "+tsf.params.titleAdditions,"undefined"!==typeof g&&0<g.length&&(e=" "+p+" "+g),a.css("text-indent","initial")):(e=tsf.params.titleAdditions+" "+p+" ","undefined"!==typeof g&&0<g.length&&(e=g+" "+p+" "));k.text(f);k.css({fontFamily:a.css("fontFamily"),
19
- fontWeight:a.css("fontWeight"),letterSpacing:a.css("letterSpacing"),fontSize:a.css("fontSize")});g=k.width();g=a.width()-m-g;0>g&&(g=0);c.css({display:a.css("display"),lineHeight:a.css("lineHeight"),paddingTop:h+"px",paddingBottom:h+"px",fontFamily:a.css("fontFamily"),fontWeight:a.css("fontWeight"),fontSize:a.css("fontSize"),letterSpacing:a.css("letterSpacing"),maxWidth:g+"px"});"undefined"===typeof f||1>f.length?(b||a.css("text-indent","initial"),c.empty()):(c.text(e),l>d&&(b?c.css(n,m+d+k.width()+
20
- "px"):(b=m+c.width(),0>b&&(b=0),c.css(n,d+"px"),a.css("text-indent",b+"px"))))}},ha:function(){var a=tsf.h();a.focus();if(a.setSelectionRange){var b=2*a.val().length;a.setSelectionRange(b,b)}else a.val(a.val()).focus()},Ba:function(){tsf.c&&tsf.G().trigger("input",tsf.M)},Ca:function(){tsf.c&&tsf.h().trigger("input",tsf.u)},fa:function(){tsf.f=!1},Y:function(a){jQuery(a.target).parents(".tsf-notice").slideUp(200,function(){this.remove()})},ka:function(a){jQuery(a).toggleClass("tsf-loading")},L:function(a,
21
- b){var c="tsf-success",d=2500;b||(c="tsf-error",d=5E3);jQuery(a).removeClass("tsf-loading").addClass(c).fadeOut(d)},J:function(a){jQuery(a).stop().empty().prop("class","tsf-ajax").css("opacity","1").removeProp("style")},W:function(){tsf.a+=1;3<tsf.a&&(tsf.a=0);tsf.C();var a=0;tsf.J(".tsf-counter .tsf-ajax");tsf.ka(".tsf-counter .tsf-ajax");jQuery.ajax({method:"POST",url:ajaxurl,Ea:"json",data:{action:"the_seo_framework_update_counter",nonce:tsf.nonces.edit_posts,val:tsf.a},async:!0,success:function(b){b=
22
- jQuery.parseJSON(b);"success"===b.type&&(a=1);tsf.X(".tsf-counter .tsf-ajax",a)}})},X:function(a,b){switch(b){case 0:tsf.L(a,!1);break;case 1:tsf.L(a,!0);break;default:tsf.J(a)}},C:function(){if(tsf.c){var a=tsf.a,b=tsf.f;1==a?(tsf.g="tsf-counter-one",tsf.a=1):2==a?(tsf.g="tsf-counter-two",tsf.a=2):3==a?(tsf.g="tsf-counter-three",tsf.a=3):(tsf.g="tsf-counter-zero",tsf.a=0);tsf.Da();tsf.f=b}},Da:function(){tsf.Ca();tsf.Ba()},i:function(a){return tsf.i18n[a]},H:function(a){var b="";a="title"===a?tsf.B:
23
- tsf.F;"pipe"===a||"|"===a?b="|":"dash"===a||"-"===a?b="-":123>a.charCodeAt(0)&&("&"===a.charAt(0)&&";"===a.slice(-1)&&(a=a.substr(1).slice(0,-1)),b=jQuery("<div/>").html("&"+a+";").text());return b},I:function(a){if(jQuery(a.target).prop("disabled")||"undefined"===typeof wp.media)a.preventDefault(),a.stopPropagation();else{var b=jQuery(a.target),c=b.data("inputid");if(!d){a.preventDefault();a.stopPropagation();tsf.ba();var d=wp.media({button:{text:tsf.other[c].frame_button,close:!1},states:[new wp.media.controller.Library({title:tsf.other[c].frame_title,
24
- library:wp.media.query({type:"image"}),multiple:!1,date:!1,priority:20,suggestedWidth:1200,suggestedHeight:630}),new tsf.cropper({imgSelectOptions:tsf.calculateImageSelectOptions})]});a=function(){d.setState("cropper")};d.off("select",a);d.on("select",a);a=function(a){var b=a.url;a=a.id;jQuery("#"+c+"-url").val(b);jQuery("#"+c+"-id").val(a)};d.off("cropped",a);d.on("cropped",a);a=function(a){var b=a.get("url"),d=a.get("id");a.get("width");a.get("height");jQuery("#"+c+"-url").val(b);jQuery("#"+c+"-id").val(d)};
25
- d.off("skippedcrop",a);d.on("skippedcrop",a);a=function(){jQuery("#"+c+"-select").text(tsf.other[c].change);jQuery("#"+c+"-url").prop("readonly",!0).css("opacity",0).animate({opacity:1},{queue:!0,duration:1E3},"swing");tsf.D(b,c,!0);tsf.l()};d.off("skippedcrop cropped",a);d.on("skippedcrop cropped",a)}d.open()}},D:function(a,b,c){a&&b&&!jQuery("#"+b+"-remove").length&&(a.after('<a href="javascript:void(0)" id="'+b+'-remove" class="tsf-remove-social-image button button-small" data-inputid="'+b+'" title="'+
26
- tsf.other[b].remove_title+'">'+tsf.other[b].remove+"</a>"),c&&jQuery("#"+b+"-remove").css("opacity",0).animate({opacity:1},{queue:!0,duration:1E3},"swing"));tsf.ga()},s:function(a){var b=jQuery(a.target).data("inputid");jQuery("#"+b+"-select").prop("disabled")||(jQuery("#"+b+"-select").addClass("disabled").prop("disabled",!0),jQuery("#"+b+"-remove").addClass("disabled").prop("disabled",!0).fadeOut(500,function(){jQuery(this).remove();jQuery("#"+b+"-select").text(tsf.other[b].select).removeClass("disabled").removeProp("disabled")}),
27
- jQuery("#"+b+"-url").val("").removeProp("readonly").css("opacity",0).animate({opacity:1},{queue:!0,duration:500},"swing"),jQuery("#"+b+"-id").val(""),tsf.l())},ba:function(){if("undefined"===typeof tsf.cropper.control){var a=wp.media.controller.Cropper.extend({doCrop:function(a){var b=a.get("cropDetails"),d=tsf.cropper.control;if(d.params.flex_width&&d.params.flex_height)if(b.width===b.height)b.width>d.params.flex_width&&(b.dst_width=b.dst_height=d.params.flex_width);else if(b.width>d.params.flex_width||
28
- b.height>d.params.flex_height)if(b.width>b.height){var e=b.width/d.params.flex_width;b.dst_width=d.params.flex_width;b.dst_height=Math.round(b.height/e)}else e=b.height/d.params.flex_height,b.dst_height=d.params.flex_height,b.dst_width=Math.round(b.width/e);"undefined"===typeof b.dst_width&&(b.dst_width=0,b.dst_height=0);return wp.ajax.post("tsf-crop-image",{nonce:tsf.nonces.upload_files,id:a.get("id"),context:"tsf-image",cropDetails:b})}});a.prototype.control={};a.control={params:{flex_width:4096,
29
- flex_height:4096,width:1200,height:630}};tsf.cropper=a}},calculateImageSelectOptions:function(a,b){var c=tsf.cropper.control,d=!!parseInt(c.params.flex_width,10),e=!!parseInt(c.params.flex_height,10),f=parseInt(c.params.width,10),k=parseInt(c.params.height,10),l=a.get("width"),h=a.get("height"),m=f/k,g=f,n=k;b.set("control",c.params);b.set("canSkipCrop",!tsf.ea(c.params.flex_width,c.params.flex_height,l,h));l/h>m?(k=h,f=k*m):(f=l,k=f/m);c=(l-f)/2;m=(h-k)/2;g={handles:!0,keys:!0,instance:!0,persistent:!0,
30
- imageWidth:l,imageHeight:h,minWidth:g>f?f:g,minHeight:n>k?k:n,x1:c,y1:m,x2:f+c,y2:k+m};!1===e&&!1===d&&(g.aspectRatio=f+":"+k);!0===e&&(g.minHeight=200,g.maxWidth=l);!0===d&&(g.minWidth=200,g.maxHeight=h);return g},ea:function(a,b,c,d){return c<=a&&d<=b?!1:!0},ga:function(){jQuery(".tsf-remove-social-image").off("click",tsf.s);jQuery(".tsf-remove-social-image").on("click",tsf.s)},na:function(){jQuery(".tsf-set-social-image").off("click",tsf.I);jQuery(".tsf-remove-social-image").off("click",tsf.s);
31
- jQuery(".tsf-set-social-image").on("click",tsf.I);jQuery(".tsf-remove-social-image").on("click",tsf.s)},U:function(){var a=jQuery(".tsf-set-social-image");if(a.length){var b="",c="";jQuery.each(a,function(a,e){b=jQuery(e).data("inputid");c=jQuery("#"+b+"-id");c.length&&0<c.val()&&(jQuery("#"+b+"-url").prop("readonly",!0),tsf.D(jQuery(e),b,!1));jQuery("#"+b+"-url").val()&&jQuery("#"+b+"-select").text(tsf.other[b].change)})}},la:function(){var a=jQuery(".tsf-color-picker");a.length&&jQuery.each(a,function(a,
32
- c){var b=jQuery(c),e="",f=b.data("tsf-default-color");b.wpColorPicker({defaultColor:f,width:238,change:function(){e=b.wpColorPicker("color");""===e&&(e=f);b.val(e);tsf.l()},clear:function(){b.parent().siblings(".wp-color-result").css("backgroundColor",f);tsf.l()},palettes:!1})})},oa:function(){tsf.B=tsf.params.titleSeparator;tsf.F=tsf.params.descriptionSeparator;tsf.m=tsf.states.titleTagline;tsf.a=parseInt(tsf.states.counterType);tsf.c=tsf.states.hasInput},O:function(){if(tsf.c){var a=jQuery;a("#tsf-title-tagline-toggle :input").on("click",
33
- tsf.va);a("#tsf-title-location input").on("click",tsf.wa);a("#title-prefixes-toggle :input").on("click",tsf.xa);a("#autodescription-site-settings\\[homepage_title\\]").on("input",tsf.ya);a("#tsf-home-title-location :input, #tsf-title-tagline-toggle :input, #tsf-title-separator input").on("click",tsf.j);a("#autodescription-site-settings\\[homepage_title_tagline\\]").on("input",tsf.A);a("#homepage-tab-general").on("tsf-tab-toggled",tsf.j);a("#autodescription-homepage-settings > button").on("click",
34
- tsf.j);a("#tsf-inpost-box > button").on("click",tsf.j);a("#autodescription-site-settings\\[title_rem_additions\\]").on("click",tsf.za);tsf.h().on("input",tsf.Z);a("#tsf-title-placeholder").on("click",tsf.ha);a(window).resize(tsf.sa)}},N:function(){if(jQuery(".tsf-flex").length){tsf.P();var a=0,b={},c=0,d=jQuery(".tsf-flex-nav-tab-wrapper");jQuery(window).on("tsf-flex-resize",function(){clearTimeout(a);var e=0;a=setTimeout(function(){if(d.length){var a=jQuery(".tsf-flex-nav-tab-inner"),c=d.width(),
35
- l=a.width(),h=jQuery(".tsf-flex-nav-name");b.b||(b.b={},b.b.v=0,b.b.da=0,b.b.w=1);!b.b.w&&b.b.v<c&&(h.fadeIn(250),setTimeout(function(){l=a.width()},e));setTimeout(function(){l>c?(h.hide(),b.b.w=0):b.b.v<c&&(h.fadeIn(250),b.b.w=1)},2*e);setTimeout(function(){b.b.v=c;b.b.da=l},3*e)}},c);e=10;c=75});jQuery(window).trigger("tsf-flex-resize")}},P:function(){jQuery(window).on("resize orientationchange",tsf.o);jQuery("#collapse-menu").click(tsf.o);jQuery(".columns-prefs :input[type=radio]").change(tsf.o);
36
- jQuery(".meta-box-sortables").on("sortupdate",tsf.o)},o:function(){jQuery(window).trigger("tsf-flex-resize")},R:function(){jQuery(document.body).trigger("tsf-ready")},ready:function(a){tsf.oa();a("div.updated, div.error, div.notice-warning").insertAfter("div.tsf-top-wrap");a(document.body).ready(tsf.O);a(document.body).ready(tsf.ma);a(document.body).ready(tsf.C);a(document.body).ready(tsf.ua);a(document.body).ready(tsf.statusBarHover);a(document.body).ready(tsf.na);a(document.body).ready(tsf.U);a(document.body).ready(tsf.la);
37
- a(document.body).ready(tsf.T);a(document.body).ready(tsf.fa);a(document.body).ready(tsf.R);a(document.body).ready(tsf.N);a(document.body).on("click touchstart MSPointerDown",tsf.Aa);tsf.G().on("input",tsf.M);tsf.h().on("input",tsf.u);a("#tsf-title-separator input").on("click",tsf.ja);a("#tsf-description-separator input").on("click",tsf.ia);a(".tsf-js-confirm-reset").on("click",tsf.V);a(".tsf-tabs-radio").on("change",tsf.ra);a(".tsf-flex-nav-tab-radio").on("change",tsf.ca);a("#tsf-description-onblogname-toggle :input").on("click",
38
- tsf.ta);a("#tsf-description-additions-toggle :input").on("click",tsf.S);a(".tsf-dismiss").on("click",tsf.Y);a(".tsf-counter").on("click",tsf.W)}};jQuery(tsf.ready);
1
+ 'use strict';window.tsf={nonces:tsfL10n.nonces,i18n:tsfL10n.i18n,states:tsfL10n.states,params:tsfL10n.params,other:tsfL10n.other,settingsChanged:!1,counterType:0,hasInput:!1,additionsClass:'',cropper:{},confirm:function(t){return confirm(t)},escapeString:function(t){if(!t.length)return'';var s={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;','\'':'&#039;'};return t.replace(/[&<>"']/g,function(a){return s[a]})},getStringLength:function(t){let s,a=0;return t.length&&(s=document.createElement('span'),s.innerHTML=tsf.escapeString(t),a=s.childNodes[0].nodeValue.length),+a},updatePixelCounter:function(t){let s=t.e,a=t.text,o=t.guideline,n=s.parentElement;if(n){let r=n.querySelector('.tsf-pixel-counter-bar'),l=n.querySelector('.tsf-pixel-counter-shadow');if(r&&l){l.innerHTML=tsf.escapeString(a);let d=l.offsetWidth,c='',g='',f='tsf-pixel-counter-fit',u='tsf-pixel-counter-overflown';d>o?(g=100*(o/(d+2*(d-o)/3))+'%',c=u):(g=100*(d/o)+'%',c=f);let x,y=r.querySelector('.tsf-pixel-counter-fluid');x=tsf.i18n.pixelsUsed.replace(/%1\$d/g,d),x=x.replace(/%2\$d/g,o),r.classList.remove(f,u),r.classList.add(c),r.dataset.desc=x,r.setAttribute('aria-label',x),y.style.width=g,tsf._triggerTooltipUpdate(r)}}},_initTitleInputs:function(){if(tsf.hasInput){let t=jQuery('#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]');if(t.length){let o,n,r,d,s=!1,a=!!navigator.userAgent.match(/Trident\/7\./),l='',c='',g=tsf.params.titleSeparator,f=tsf.params.objectTitle,u=tsf.states.useTagline,y=tsf.states.isRTL,x=tsf.states.isPrivate,v=tsf.states.isPasswordProtected;o=y?'after':'before';const b=function(){let X='before';tsf.states.isSettingsPage?y?'right'===jQuery('#tsf-home-title-location input:checked').val()&&(X='after'):'left'===jQuery('#tsf-home-title-location input:checked').val()&&(X='after'):tsf.states.isHome?y?'right'===tsf.params.titleLocation&&(X='after'):'left'===tsf.params.titleLocation&&(X='after'):y?'left'===tsf.params.titleLocation&&(X='after'):'right'===tsf.params.titleLocation&&(X='after'),n=X};b();const k=function(){let X='';if(!tsf.states.isSettingsPage)tsf.states.isHome?u&&(X=tsf.params.titleAdditions):u&&(X=tsf.params.titleAdditions);else if(u){let V=document.getElementById('autodescription-site-settings[homepage_title_tagline]'),G=V?V.value:'';X=G.length?G:tsf.params.blogDescription}X.length&&(X=tsf.escapeString(X),'before'===n?X=X+' '+g+' ':'after'===n?X=' '+g+' '+X:void 0),c=X.length?X:'',d=document.getElementById('tsf-title-placeholder'),c.length&&d&&(d.innerHTML=c)};k();const T=function(){let X='';x?X=tsf.i18n.privateTitle:v&&(X=tsf.i18n.protectedTitle),X.length&&(X=tsf.escapeString(X),'before'===o?X+=' ':'after'===o?X=' '+X:void 0),l=X.length?X:'',l.length&&r&&(r.innerHTML=l),r=document.getElementById('tsf-title-placeholder-prefix'),l.length&&r&&(r.innerHTML=l)};T();const C=function(X){if(d||r){let V=jQuery(X.target),G=V.val(),J=!!c.length,K=!!l.length;if(!J&&d&&(d.style.display='none'),!K&&r&&(r.style.display='none'),!J&&!K)return void V.css('text-indent','initial');if(!G.length)return V.css('text-indent','initial'),d&&(d.style.display='none'),void(r&&(r.style.display='none'));let Y=V.outerWidth(),Z=(V.outerHeight(!0)-V.height())/2,Q=(Y-V.innerWidth())/2,tt=y?'right':'left',et=(V.outerWidth(!0)-V.width())/2,it={display:V.css('display'),lineHeight:V.css('lineHeight'),fontFamily:V.css('fontFamily'),fontWeight:V.css('fontWeight'),fontSize:V.css('fontSize'),letterSpacing:V.css('letterSpacing'),paddingTop:Z+'px',paddingBottom:Z+'px'},st=jQuery(r),at=jQuery(d),ot=0,nt=0,rt=0,lt=0,pt=0;if(K&&(st.css(it),st.css({maxWidth:'initial'}),pt=st.width(),0>pt&&(pt=0),rt+=et),J){let ct=0;switch(function(){let gt=jQuery('#tsf-title-offset');gt.text(G),gt.css({fontFamily:it.fontFamily,fontWeight:it.fontWeight,letterSpacing:it.letterSpacing,fontSize:it.fontSize}),ct=gt.width()}(),ot=V.width()-Q-ct-pt,0>ot&&(pt-=-ot,ot=0),at.css(it),n){case'before':let gt=at.width();0>gt&&(gt=0),lt+=gt,rt+=gt,nt+=et;break;case'after':nt+=et+ct+pt;}}pt=0>pt?0:pt,lt+=pt;let dt;K&&(dt={},dt[tt]=rt+'px',dt.maxWidth=pt+'px',st.css(dt)),J&&(dt={},dt[tt]=nt+'px',dt.maxWidth=ot+'px',at.css(dt)),dt={},dt['text-indent']=lt+'px',V.css(dt)}},I=function(){let V='',G=!!c.length,J=!!l.length,K=c,Y=l;tsf.states.isTermEdit&&tsf.params.termName&&(Y=y?' :'+tsf.params.termName:tsf.params.termName+': ',J=tsf.states.useTermPrefix),V=f,J&&('before'===o?V=Y+V:'after'===o?V+=Y:void 0),G&&('before'===n?V=K+V:'after'===n?V+=K:void 0),a&&(s=!0);let Z=document.createElement('span');Z.innerHTML=V,t.prop('placeholder',Z.textContent),a&&setTimeout(function(){s=!1},0)},S=function(X){let V=document.getElementById(X.target.id+'_chars');if(V){let G=0,J=X.target,K='',Y=tsf.counterType,Z='',Q='';G=1>J.value.length?tsf.getStringLength(J.placeholder):(l?tsf.getStringLength(l):0)+tsf.getStringLength(J.value)+(c?tsf.getStringLength(c):0),25>G||75<=G?(K+='tsf-count-bad',Z=tsf.i18n.bad):42>G||55<G?(K+='tsf-count-okay',Z=tsf.i18n.okay):(K+='tsf-count-good',Z=tsf.i18n.good),Y&&1!=Y?2==Y?Q=Z:3==Y&&(Q=G.toString()+' - '+Z):Q=G.toString(),V.innerHTML=Q,tsf.additionsClass&&(K+=' '+tsf.additionsClass),V.className!==K&&(V.className=K)}},L=function(X){let V=document.getElementById(X.target.id+'_pixels');if(V){let G='';1>X.target.value.length?G=X.target.placeholder:(G=X.target.value,l.length&&('before'===o?G=l+G:'after'===o?G+=l:void 0),c.length&&('before'===n?G=c+G:'after'===n?G+=c:void 0));let J={e:V,text:G,guideline:tsf.params.titlePixelGuideline};tsf.updatePixelCounter(J)}};t.on('input.tsfUpdateTitles',function(X){return!s&&void(C(X),I(),S(X),L(X))});t.on('tsf-update-title-counter',function(X){S(X),L(X)});const j=function(){t.trigger('tsf-update-title-counter')},P=function(){t.trigger('input.tsfUpdateTitles')};P();const R=function(){k(),P()};jQuery('#autodescription-site-settings\\[homepage_title_tagline\\]').on('input',R),jQuery('#autodescription-site-settings\\[homepage_tagline\\]').on('change',R);let A=0;const D=function(){clearTimeout(A),A=setTimeout(function(){P()},50)};jQuery(window).on('tsf-counter-updated',D);jQuery('#tsf-title-tagline-toggle :input').on('click',function(X){let V=u;jQuery(X.target).is(':checked')?(jQuery('.tsf-custom-blogname-js').css('display','inline'),u=!0):(jQuery('.tsf-custom-blogname-js').css('display','none'),u=!1),V^u&&(k(),D())});jQuery('#visibility .save-post-visibility').on('click',function(){let V=jQuery('#visibility').find('input:radio:checked').val();switch(x=!1,v=!1,V){case'password':let G=jQuery('#visibility').find('#post_password').val();v=!!G&&!!G.length;break;case'private':x=!0;break;default:case'public':}T(),D()});jQuery('#tsf-title-separator :input').on('click',function(X){let V=jQuery(X.target).val(),G='';G='pipe'===V?'|':'dash'===V?'-':jQuery('<div/>').html('&'+V+';').text(),g=G,jQuery('.tsf-sep-js').text(' '+g+' '),k(),D()});const U=function(){let X=tsf.settingsChanged;P(),tsf.settingsChanged=X};jQuery('#autodescription-homepage-settings > button, #tsf-inpost-box > button').on('click',U),jQuery('#homepage-tab-general').on('tsf-tab-toggled',U),jQuery('#tsf-flex-inpost-tab-general').on('tsf-flex-tab-toggled',U);let B=0;jQuery(window).on('tsf-flex-resize',function(){clearTimeout(B),B=setTimeout(function(){U()},50)});jQuery('#tsf-home-title-location :input').on('click',function(){b(),k(),D()});tsf.states.isHome||jQuery('#edittag #name, #titlewrap #title').on('input',function(X){let V=X.target.value;V=V.trim(),f=V.length?V:tsf.params.untitledTitle,I(),j()});(function(){let X=0,V=window.innerWidth;window.addEventListener('resize',function(){clearTimeout(X),X=setTimeout(function(){let G=window.innerWidth;V<G?782>=V&&782<=G&&U():782<=V&&782>=G&&U(),V=G},50)})})()}}},_initUnboundTitleSettings:function(){if(tsf.hasInput){let t=jQuery('#autodescription_title, #autodescription-meta\\[doctitle\\], #autodescription-site-settings\\[homepage_title\\]');jQuery('#tsf-title-placeholder, #tsf-title-placeholder-prefix').on('click',function(d){let c=jQuery(d.target).siblings(t)[0];if('function'==typeof c.setSelectionRange){c.focus();let g=2*c.value.length;c.setSelectionRange(g,g)}else{let g=c.value;c.value='',c.focus(),c.value=g}});jQuery('#autodescription-site-settings\\[title_rem_additions\\]').on('click',function(d){jQuery(d.target).is(':checked')?jQuery('.tsf-title-additions-js').css('display','none'):jQuery('.tsf-title-additions-js').css('display','inline')});jQuery('#tsf-title-location input').on('click',function(d){let c=jQuery('.tsf-title-additions-example-left'),g=jQuery('.tsf-title-additions-example-right');'right'===jQuery(d.target).val()?(c.css('display','none'),g.css('display','inline')):(c.css('display','inline'),g.css('display','none'))});jQuery('#autodescription-site-settings\\[homepage_title\\]').on('input',function(d){let c=d.target.value||'',g=jQuery('.tsf-custom-title-js');0===c.length?g.text(tsf.params.objectTitle):g.text(c)});jQuery('#autodescription-site-settings\\[homepage_title_tagline\\]').on('input',function(d){let c=d.target.value||'',g=jQuery('.tsf-custom-tagline-js');0===c.length?(g.text(tsf.params.blogDescription),0===tsf.params.blogDescription.length?jQuery('#tsf-home-title-location .tsf-sep-js').hide():jQuery('#tsf-home-title-location .tsf-sep-js').show()):(g.text(c),jQuery('#tsf-home-title-location .tsf-sep-js').show())}),jQuery('#autodescription-site-settings\\[homepage_title_tagline\\]').trigger('input');jQuery('#title-prefixes-toggle :input').on('click',function(d){let c=jQuery(d.target),g=jQuery('.tsf-title-prefix-example');c.is(':checked')?g.css('display','none'):g.css('display','inline')})}},_initDescInputs:function(){if(tsf.hasInput){let t=jQuery('#autodescription_description, #autodescription-meta\\[description\\], #autodescription-site-settings\\[homepage_description\\]');if(t.length){let s=tsf.params.descriptionSeparator;jQuery('#tsf-description-separator input').on('click',function(g){let f=jQuery(g.target).val(),u='';u='pipe'===f?'|':'dash'===f?'-':jQuery('<div/>').html('&'+f+';').text(),s=u,jQuery('#autodescription-descsep-js').text(' '+s+' '),c()});const o=function(g){let f=document.getElementById(g.target.id+'_chars');if(f){let u=0,y=g.target,x='',v=tsf.counterType,b='',k='';u=1>y.value.length?tsf.getStringLength(y.placeholder):tsf.getStringLength(y.value),100>u||175<=u?(x+='tsf-count-bad',b=tsf.i18n.bad):137>u||155<u?(x+='tsf-count-okay',b=tsf.i18n.okay):(x+='tsf-count-good',b=tsf.i18n.good),v&&1!=v?2==v?k=b:3==v&&(k=u.toString()+' - '+b):k=u.toString(),f.innerHTML=k,tsf.additionsClass&&(x+=' '+tsf.additionsClass),f.className!==x&&(f.className=x)}},n=function(g){let f=document.getElementById(g.target.id+'_pixels');if(f){let u='';u=1>g.target.value.length?g.target.placeholder:g.target.value;let y={e:f,text:u,guideline:tsf.params.descPixelGuideline};tsf.updatePixelCounter(y)}};t.on('input.tsfUpdateDescriptions',function(g){o(g),n(g)});const l=function(){t.trigger('input.tsfUpdateDescriptions')};l();let d=0;const c=function(){clearTimeout(d),d=setTimeout(function(){l()},50)};jQuery(window).on('tsf-counter-updated',c)}}},_initCounters:function(){if(tsf.hasInput){jQuery('.tsf-counter').on('click',function(){++tsf.counterType,3<tsf.counterType&&(tsf.counterType=0),s();let r='.tsf-counter-wrap .tsf-ajax',l=0;tsf.resetAjaxLoader(r),tsf.setAjaxLoader(r);let d={method:'POST',url:ajaxurl,datatype:'json',data:{action:'the_seo_framework_update_counter',nonce:tsf.nonces.edit_posts,val:tsf.counterType},async:!0,success:function(c){switch(c=jQuery.parseJSON(c),'success'===c.type&&(l=1),l){case 0:tsf.unsetAjaxLoader(r,!1);break;case 1:tsf.unsetAjaxLoader(r,!0);break;default:tsf.resetAjaxLoader(r);}}};jQuery.ajax(d)});const s=function(){let n=tsf.counterType;1==n?(tsf.additionsClass='tsf-counter-one',tsf.counterType=1):2==n?(tsf.additionsClass='tsf-counter-two',tsf.counterType=2):3==n?(tsf.additionsClass='tsf-counter-three',tsf.counterType=3):(tsf.additionsClass='tsf-counter-zero',tsf.counterType=0),tsf._triggerCounterUpdate()};s();jQuery('#autodescription-site-settings\\[display_character_counter\\]').on('click',function(n){jQuery(n.target).is(':checked')?jQuery('.tsf-counter-wrap').show():jQuery('.tsf-counter-wrap').hide()});jQuery('#autodescription-site-settings\\[display_pixel_counter\\]').on('click',function(n){jQuery(n.target).is(':checked')?(jQuery('.tsf-pixel-counter-wrap').show(),tsf._triggerCounterUpdate()):jQuery('.tsf-pixel-counter-wrap').hide()})}},_initPrimaryTerm:function(){if(tsf.hasInput&&Object.keys(tsf.states.taxonomies).length){let t=tsf.states.taxonomies,s=wp.template('tsf-primary-term-selector'),a=wp.template('tsf-primary-term-selector-help'),o=document.createElement('span');o.classList.add('tsf-primary-term-selector'),o.classList.add('tsf-set-primary-term'),function(){let O=document.createElement('input');O.setAttribute('type','radio'),o.appendChild(O)}();let n={},r={},l={},d={},c={};const g=function(O){let U=jQuery('#'+O+'div'),B=s({taxonomy:t[O]});U.append(B)},f=function(O){let U=jQuery('#taxonomy-'+O),B=a({taxonomy:t[O]});U.append(B),u(O)},u=function(O){let U=document.getElementById('taxonomy-'+O),B=U.querySelectorAll('.tabs-panel'),q=Array.prototype.slice.call(B).filter(function(N){return 0<N.offsetWidth||0<N.offsetHeight||0<N.getClientRects().length})[0],F=q.scrollHeight>q.clientHeight?q.offsetWidth-q.clientWidth+25-2:25;tsf.states.isRTL?U.querySelector('.tsf-primary-term-selector-help-wrap').style.left=F+'px':U.querySelector('.tsf-primary-term-selector-help-wrap').style.right=F+'px'},y=function(O){u(O.data.taxonomy)},x=function(O){let U=o.cloneNode(!0);return U.setAttribute('title',t[O].i18n.makePrimary),U.setAttribute('aria-label',t[O].i18n.makePrimary),U},v=function(O,U){let B=document.getElementById('autodescription[_primary_term_'+O+']');B&&B instanceof Element&&(B.value=U)},b=function(O,U){return!U&&d[O]?d[O]:(d[O]=jQuery('#'+O+'checklist, #'+O+'checklist-pop'),d[O])},k=function(O,U){return n[O].filter('[value="'+U+'"]')},T=function(O,U){let B=k(O,U).closest('label');B.length?(B.addClass('tsf-is-primary-term'),B.find('.tsf-set-primary-term').each(function(q,F){F.setAttribute('title',t[O].i18n.primary),F.setAttribute('aria-label',t[O].i18n.primary),F.querySelector('input').checked=!0}),v(O,U),c[O]=U):I(O)},C=function(O){let U=b(O).find('label');U.removeClass('tsf-is-primary-term'),U.find('.tsf-set-primary-term').each(function(B,q){q.setAttribute('title',t[O].i18n.makePrimary),q.setAttribute('aria-label',t[O].i18n.makePrimary),q.querySelector('input').checked=!1}),v(O,'')},I=function(O){let B,U=l[O].first();U.length&&(B=U.val()||'',T(O,B),c[O]=B)},S=function(O){let U=O.data.taxonomy,B=jQuery(O.target).closest('label').find('input[type=checkbox]').val();return C(U),T(U,B),!1},L=function(O){let U=O.data.taxonomy;switch(O.target.checked?(j(U,O.target),W(U,O.target)):(P(U,O.target),E(U,O.target)),l[U].length){case 0:v(U,'');break;case 1:I(U);}},W=function(O,U){let B;k(O,U.value).each(function(q,F){B=jQuery(F).closest('label'),B.find('.tsf-primary-term-selector').length||B.append(x(O))})},E=function(O,U){let B,q;k(O,U.value).each(function(F,N){B=jQuery(N).closest('label'),q=B.hasClass('tsf-is-primary-term'),B.removeClass('tsf-is-primary-term'),B.find('.tsf-primary-term-selector').remove(),q&&I(O)})},j=function(O,U){r[O]=r[O].add('[value="'+U.value+'"]'),l[O]=l[O].add(U)},P=function(O,U){r[O]=r[O].not('[value="'+U.value+'"]'),l[O]=l[O].not('[value="'+U.value+'"]')},R=function(O){let U=b(O,1);n[O]=U.find('input[type=checkbox]'),r[O]=U.find('input[type=checkbox]:checked');let q,B={};l[O]=r[O],l[O].each(function(F,N){q=jQuery(N).val(),B[q]?l[O].splice(F,1):B[q]=!0})},A=function(O,U,B){B.hasOwnProperty('settings')&&B.settings.hasOwnProperty('what')&&(R(B.settings.what),D(B.settings.what),H(B.settings.what),u(B.settings.what))},D=function(O){let U='tsfShowPrimary'+O,B={taxonomy:O},q=b(O),F=jQuery('#'+O+'div'),N=jQuery('#'+O+'-tabs');q.off('click.'+U),q.on('click.'+U,'input[type="checkbox"]',B,L),q.on('click.'+U,'.tsf-primary-term-selector',B,S),F.off('wpListAddEnd.'+U),F.on('wpListAddEnd.'+U,'#'+O+'checklist',A),N.off('click.'+U),N.on('click.'+U,'a',B,y)},H=function(O){b(O).find('input[type="checkbox"]:checked').each(function(U,B){W(O,B)}),t[O].primary?T(O,t[O].primary):I(O)};(function(){for(let O in t)b(O).length&&(g(O),f(O),R(O),D(O),H(O))})()}},_initToolTips:function(){let t=0,s=!1;const a=function(){s=!0,clearTimeout(t),t=setTimeout(function(){s=!1},250)},o=function(y,x){x=x||!1;let v='pointerdown.tsfTT touchstart.tsfTT click.tsfTT',b=jQuery(y);x?(b.off('mousemove mouseleave mouseout tsf-tooltip-update'),jQuery(document.body).off(v)):(b.on({mousemove:d,mouseleave:c,mouseout:c}),jQuery(document.body).off(v).on(v,g)),b.on('tsf-tooltip-update',r)},n=function(y){o(y,!0)},r=function(y){if(y.target.classList.contains('tsf-tooltip-item')){let x=y.target.querySelector('.tsf-tooltip-text');x instanceof Element&&(x.innerHTML=y.target.dataset.desc)}},l=function(y){let x=jQuery(y.target),v=y.target.dataset.desc;if(v&&0===x.find('div').length){y.target.title='';let b=jQuery('<div class="tsf-tooltip"><span class="tsf-tooltip-text-wrap"><span class="tsf-tooltip-text">'+v+'</span></span><div class="tsf-tooltip-arrow"></div></div>');x.append(b);let k=x.closest('.tsf-tooltip-boundary');k=k.length&&k||jQuery(document.body);let T=x.outerHeight()+9,C=b.offset().top-T,I=k.offset().top-(k.prop('scrolltop')||0);I>C?(b.addClass('tsf-tooltip-down'),b.css('top',T+'px')):b.css('bottom',T+'px');let S=x.closest('.tsf-tooltip-wrap'),L=b.find('.tsf-tooltip-text-wrap'),W=L.find('.tsf-tooltip-text'),E=S.width(),j=L.outerWidth(!0),P=W.outerWidth(!0),R=L.offset().left,A=R+P,D=k.offset().left-(k.prop('scrollLeft')||0),H=D+k.outerWidth(),z='left';if(R<D){let O=D-R+12,U=parseInt(L.css('flex-basis'),10);O<-U&&(O=-U),b.css(z,O+'px'),b.data('overflow',O),b.data('overflowDir',z)}else if(A>H){let O=H-A-E-12,U=parseInt(L.css('flex-basis'),10);O<-U&&(O=-U),b.css(z,O+'px'),b.data('overflow',O),b.data('overflowDir',z)}else if(42>E){let O=-15;b.css(z,O+'px'),b.data('overflow',O),b.data('overflowDir',z)}else if(E>j){let O=y.originalEvent&&y.originalEvent.pageX||y.pageX,U=S.offset().left,q=O-U-j/2,F=q+j;0>q?q=0:F>E&&(q=E-P),b.css(z,q+'px'),b.data('adjust',q),b.data('adjustDir',z)}}},d=function(y){let x=jQuery(y.target),v=x.find('.tsf-tooltip'),b=v.find('.tsf-tooltip-arrow'),k=v.data('overflow'),T=v.data('overflowDir');if(k=parseInt(k,10),k=isNaN(k)?0:-Math.round(k),k)b.css(T,k+'px');else{let C=y.originalEvent&&y.originalEvent.pageX||y.pageX,I=7,S=16,L=x.closest('.tsf-tooltip-wrap'),W=C-L.offset().left-S/2,j=v.find('.tsf-tooltip-text-wrap'),P=j.outerWidth(!0),R=v.data('adjust'),A=v.data('adjustDir'),D=P-S-I;if(R=parseInt(R,10),R=isNaN(R)?0:Math.round(R),R&&(R='left'===A?-R:R,W+=R,D-R>L.outerWidth(!0))){let H=j.find('.tsf-tooltip-text'),z=H.outerWidth(!0);D=z-S-I}W<=I?b.css('left',I+'px'):W>=D?b.css('left',D+'px'):b.css('left',W+'px')}},c=function(y){s||(jQuery(y.target).find('.tsf-tooltip').remove(),n(y.target))},g=function(y){a();let k,v='.tsf-tooltip',b=jQuery(y.target);if(b.hasClass('tsf-tooltip-item')&&(k=b.find(v)),!k){let T=b.children('.tsf-tooltip-item');T.length&&(k=T.find(v))}k&&k.length?jQuery(v).not(k).remove():jQuery(v).remove()},f=function(y){if(!s){let x=!1;switch(y.type){case'mouseenter':break;case'pointerdown':case'touchstart':x=!0;break;default:}if(y.target.classList.contains('tsf-tooltip-item'))x&&g(y),l(y),d(y),o(y.target);else{let v=y.target.querySelector('.tsf-tooltip-item:hover'),b=new jQuery.Event(y.type);b.pageX=y.originalEvent&&y.originalEvent.pageX||y.pageX,v?(tsfL10n.states.debug&&console.log('Tooltip event warning: delegation'),jQuery(v).trigger(b)):(tsfL10n.states.debug&&console.log('Tooltip event warning: bubbling'),jQuery(y.target).closest('.tsf-tooltip-wrap').find('.tsf-tooltip-item:hover').trigger(b))}y.stopPropagation()}},u=function(){let y=jQuery('.tsf-tooltip-wrap');y.off('mouseenter pointerdown touchstart'),y.on('mouseenter pointerdown touchstart','.tsf-tooltip-item',f)};u(),jQuery(window).on('tsf-reset-tooltips',u),function(){let y=jQuery('#wpcontent');tsf.addTooltipBoundary(y)}()},addTooltipBoundary:function(t){jQuery(t).addClass('tsf-tooltip-boundary')},tabToggle:function(t){let s=jQuery(t.target);if(s.is(':checked')){let a=s.prop('id'),o=s.prop('name');if('undefined'!=typeof o){let n='tsf-active-tab-content',r=jQuery('#'+a+'-content'),l=jQuery('.'+n);if(!r.is(l)&&'undefined'!=typeof r){let d=jQuery('.'+o+'-content');d.fadeOut(150,function(){jQuery(this).removeClass(n)}),setTimeout(function(){r.addClass(n).fadeIn(250)},150),setTimeout(function(){jQuery('#'+a).trigger('tsf-tab-toggled')},175)}}}},flexTabToggle:function(t){let s=jQuery(t.target);if(s.is(':checked')){let a=s.prop('id'),o=s.prop('name');if('undefined'!=typeof o){let n='tsf-flex-tab-content-active',r=jQuery('#'+a+'-content'),l=jQuery('.'+n);if(!r.is(l)&&'undefined'!=typeof r){let d=jQuery('.'+o+'-content');d.fadeOut(150,function(){jQuery(this).removeClass(n)}),setTimeout(function(){r.addClass(n).fadeIn(250)},150),setTimeout(function(){jQuery('#'+a).trigger('tsf-flex-tab-toggled')},175)}}}},setTabsOnload:function(){if(tsf.hasInput)if(tsf.states.isSettingsPage){let t=jQuery('.tsf-nav-tab-wrapper .tsf-tab:nth-of-type(n+2) input:checked');t.length&&t.each(function(){let a=jQuery(this),o=a.prop('id'),n=a.prop('name');if('undefined'!=typeof n){let r='tsf-active-tab-content',l=jQuery('#'+o+'-content');if('undefined'!=typeof l){let d=jQuery('.'+n+'-content');d.removeClass(r),l.addClass(r),setTimeout(function(){jQuery('#'+o).trigger('tsf-tab-toggled')},20)}}})}else;},taglineToggleDesc:function(t){let s=jQuery(t.target),a=jQuery('#tsf-on-blogname-js');s.is(':checked')?a.css('display','inline'):a.css('display','none')},additionsToggleDesc:function(t){let s=jQuery(t.target),a=jQuery('#tsf-description-additions-js');s.is(':checked')?a.css('display','inline'):a.css('display','none')},taglineToggleOnload:function(){if(tsf.hasInput){let t=jQuery('#tsf-title-tagline-toggle :input'),s=jQuery('.tsf-custom-blogname-js'),a=jQuery('#tsf-description-additions-toggle :input'),o=jQuery('#tsf-description-additions-js'),n=jQuery('#tsf-description-onblogname-toggle :input'),r=jQuery('#tsf-on-blogname-js'),l=jQuery('#tsf-title-additions-toggle :input'),d=jQuery('.tsf-title-additions-js');t.is(':checked')?s.css('display','inline'):s.css('display','none'),a.is(':checked')?o.css('display','inline'):o.css('display','none'),n.is(':checked')?r.css('display','inline'):r.css('display','none'),l.is(':checked')?d.css('display','none'):d.css('display','inline')}},attachUnsavedChangesListener:function(){if(tsf.hasInput){let t=function(o){tsf.settingsChanged||tsf.registerChange(),jQuery(s).not(a).off(o.type,t)},s='.tsf-metaboxes :input, #tsf-inpost-box .inside :input',a='.tsf-tab :input, .tsf-flex-nav-tab :input';jQuery(s).not(a).on('change',t),s='.tsf-metaboxes input[type=text], .tsf-metaboxes textarea, #tsf-inpost-box .inside input[type=text], #tsf-inpost-box .inside textarea',a='.tsf-nav-tab-wrapper input, .tsf-flex-nav-tab-wrapper input',jQuery(s).not(a).on('input',t),window.onbeforeunload=function(){if(tsf.settingsChanged)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=null})}},registerChange:function(){tsf.settingsChanged=!0},confirmedReset:function(){return confirm(tsf.i18n.confirmReset)},onLoadUnregisterChange:function(){tsf.settingsChanged=!1},dismissNotice:function(t){jQuery(t.target).parents('.tsf-notice').slideUp(200,function(){this.remove()})},setAjaxLoader:function(t){jQuery(t).toggleClass('tsf-loading')},unsetAjaxLoader:function(t,s){let a='tsf-success',o=2500;s||(a='tsf-error',o=5e3),jQuery(t).removeClass('tsf-loading').addClass(a).fadeOut(o)},resetAjaxLoader:function(t){jQuery(t).stop().empty().prop('class','tsf-ajax').css('opacity','1').removeProp('style')},openImageEditor:function(t){if(jQuery(t.target).prop('disabled')||'undefined'==typeof wp.media)return t.preventDefault(),void t.stopPropagation();let o,s=jQuery(t.target),a=s.data('inputid');if(o)return void o.open();t.preventDefault(),t.stopPropagation(),tsf.extendCropper();let n={suggestedWidth:s.data('width')||1200,suggestedHeight:s.data('height')||630,isFlex:'undefined'==typeof s.data('flex')?1:s.data('flex')};tsf.cropper.control={params:{flex_width:n.isFlex?4096:0,flex_height:n.isFlex?4096:0,width:n.suggestedWidth,height:n.suggestedHeight,isFlex:n.isFlex}},o=wp.media({button:{text:tsf.other[a].frame_button,close:!1},states:[new wp.media.controller.Library({title:tsf.other[a].frame_title,library:wp.media.query({type:'image'}),multiple:!1,date:!1,priority:20,suggestedWidth:n.suggestedWidth,suggestedHeight:n.suggestedHeight}),new tsf.cropper({imgSelectOptions:tsf.calculateImageSelectOptions})]});const r=function(){o.setState('cropper')};o.off('select',r),o.on('select',r);const l=function(g){let f=g.url,u=g.id,y=g.width,x=g.height;jQuery('#'+a+'-url').val(f),jQuery('#'+a+'-id').val(u)};o.off('cropped',l),o.on('cropped',l);const d=function(g){let f=g.get('url'),u=g.get('id'),y=g.get('width'),x=g.get('height');jQuery('#'+a+'-url').val(f),jQuery('#'+a+'-id').val(u)};o.off('skippedcrop',d),o.on('skippedcrop',d);const c=function(){jQuery('#'+a+'-select').text(tsf.other[a].change),jQuery('#'+a+'-url').prop('readonly',!0).css('opacity',0).animate({opacity:1},{queue:!0,duration:1000},'swing'),tsf.appendRemoveButton(s,a,!0),tsf.registerChange()};o.off('skippedcrop cropped',c),o.on('skippedcrop cropped',c),o.open()},appendRemoveButton:function(t,s,a){t&&s&&!jQuery('#'+s+'-remove').length&&(t.after('<a href="javascript:void(0)" id="'+s+'-remove" class="tsf-remove-social-image button button-small" data-inputid="'+s+'" title="'+tsf.other[s].remove_title+'">'+tsf.other[s].remove+'</a>'),a&&jQuery('#'+s+'-remove').css('opacity',0).animate({opacity:1},{queue:!0,duration:1000},'swing')),tsf.resetImageEditorActions()},removeEditorImage:function(t){let s=jQuery(t.target).data('inputid');if(!jQuery('#'+s+'-select').prop('disabled')){jQuery('#'+s+'-select').addClass('disabled').prop('disabled',!0),jQuery('#'+s+'-remove').addClass('disabled').prop('disabled',!0).fadeOut(500,function(){jQuery(this).remove(),jQuery('#'+s+'-select').text(tsf.other[s].select).removeClass('disabled').removeProp('disabled')});let a=jQuery('#'+s+'-url');a.val(''),a.data('readonly')||a.removeProp('readonly'),a.css('opacity',0).animate({opacity:1},{queue:!0,duration:500},'swing'),jQuery('#'+s+'-id').val(''),tsf.registerChange()}},extendCropper:function(){if('undefined'==typeof tsf.cropper.control){let t,a,s=wp.media.controller,o=wp.media.view;return a=o.Cropper.extend({className:'crop-content tsf-image',ready:function(){o.Cropper.prototype.ready.apply(this,arguments)},onImageLoad:function(){let r,n=this.controller.get('imgSelectOptions');'function'==typeof n&&(n=n(this.options.attachment,this.controller)),'undefined'==typeof n.aspectRatio&&(n=_.extend(n,{parent:this.$el,onInit:function(){this.parent.children().on('mousedown touchstart',function(l){l.shiftKey?r.setOptions({aspectRatio:'1:1'}):r.setOptions({aspectRatio:!1})})}})),this.trigger('image-loaded'),r=this.controller.imgSelect=this.$image.imgAreaSelect(n)}}),t=s.Cropper.extend({createCropContent:function(){this.cropperView=new a({controller:this,attachment:this.get('selection').first()}),this.cropperView.on('image-loaded',this.createCropToolbar,this),this.frame.content.set(this.cropperView)},doCrop:function(n){let r=n.get('cropDetails'),l=tsf.cropper.control;if(l.params.flex_width&&l.params.flex_height)if(r.width===r.height)r.width>l.params.flex_width&&(r.dst_width=r.dst_height=l.params.flex_width);else if(r.width>l.params.flex_width||r.height>l.params.flex_height)if(r.width>r.height){let d=r.width/l.params.flex_width;r.dst_width=l.params.flex_width,r.dst_height=Math.round(r.height/d)}else{let d=r.height/l.params.flex_height;r.dst_height=l.params.flex_height,r.dst_width=Math.round(r.width/d)}return'undefined'==typeof r.dst_width&&(r.dst_width=0,r.dst_height=0),wp.ajax.post('tsf-crop-image',{nonce:tsf.nonces.upload_files,id:n.get('id'),context:'tsf-image',cropDetails:r})}}),t.prototype.control={},void(tsf.cropper=t)}},calculateImageSelectOptions:function(t,s){let y,x,v,b,a=tsf.cropper.control,o=!!parseInt(a.params.flex_width,10),n=!!parseInt(a.params.flex_height,10),r=parseInt(a.params.width,10),l=parseInt(a.params.height,10),d=t.get('width'),c=t.get('height'),g=r/l,f=r,u=l;return b=a.params.isFlex?!tsf.mustBeCropped(a.params.flex_width,a.params.flex_height,d,c):g==d/c,s.set('control',a.params),s.set('canSkipCrop',b),d/c>g?(l=c,r=l*g):(r=d,l=r/g),y=(d-r)/2,x=(c-l)/2,v={handles:!0,keys:!0,instance:!0,persistent:!0,imageWidth:d,imageHeight:c,minWidth:f>r?r:f,minHeight:u>l?l:u,x1:y,y1:x,x2:r+y,y2:l+x},a.params.isFlex?n||o?(n&&(v.minHeight=200,v.maxWidth=d),o&&(v.minWidth=200,v.maxHeight=c)):v.aspectRatio=r+':'+l:(v.handles='corners',v.aspectRatio=r+':'+l),v},mustBeCropped:function(t,s,a,o){return a<=t&&o<=s?!1:!0},resetImageEditorActions:function(){jQuery('.tsf-remove-social-image').off('click',tsf.removeEditorImage),jQuery('.tsf-remove-social-image').on('click',tsf.removeEditorImage)},setupImageEditorActions:function(){jQuery('.tsf-set-social-image').off('click',tsf.openImageEditor),jQuery('.tsf-remove-social-image').off('click',tsf.removeEditorImage),jQuery('.tsf-set-social-image').on('click',tsf.openImageEditor),jQuery('.tsf-remove-social-image').on('click',tsf.removeEditorImage)},checkImageEditorInput:function(){let t=jQuery('.tsf-set-social-image');if(t.length){let s='',a='';jQuery.each(t,function(o,n){s=jQuery(n).data('inputid'),a=jQuery('#'+s+'-id'),a.length&&0<a.val()&&(jQuery('#'+s+'-url').prop('readonly',!0),tsf.appendRemoveButton(jQuery(n),s,!1)),jQuery('#'+s+'-url').val()&&jQuery('#'+s+'-select').text(tsf.other[s].change)})}},setColorOnload:function(){let t=jQuery('.tsf-color-picker');t.length&&jQuery.each(t,function(s,a){let o=jQuery(a),n='',r=o.data('tsf-default-color');o.wpColorPicker({defaultColor:r,width:238,change:function(){n=o.wpColorPicker('color'),''==n&&(n=r),o.val(n),tsf.registerChange()},clear:function(){o.parent().siblings('.wp-color-result').css('backgroundColor',r),tsf.registerChange()},palettes:!1})})},_doFlexResizeListener:function(){if(jQuery('.tsf-flex').length){tsf._setResizeListeners();let t=0,s={},a=0,o=jQuery('.tsf-flex-nav-tab-wrapper'),n=jQuery(window);n.on('tsf-flex-resize',function(){clearTimeout(t);let r=0;t=setTimeout(function(){if(o.length){let l=jQuery('.tsf-flex-nav-tab-inner'),d=o.width(),c=l.width(),g=jQuery('.tsf-flex-nav-name');s.tabWrapper||(s.tabWrapper={},s.tabWrapper.outer=0,s.tabWrapper.inner=0,s.tabWrapper.shown=1),!s.tabWrapper.shown&&s.tabWrapper.outer<d&&(g.fadeIn(250),setTimeout(function(){c=l.width()},r)),setTimeout(function(){c>d?(g.hide(),s.tabWrapper.shown=0):s.tabWrapper.outer<d&&(g.fadeIn(250),s.tabWrapper.shown=1)},2*r),setTimeout(function(){s.tabWrapper.outer=d,s.tabWrapper.inner=c},3*r)}},a),r=10,a=75}),n.trigger('tsf-flex-resize')}},_setResizeListeners:function(){jQuery(window).on('resize orientationchange',tsf._triggerResize),jQuery('#collapse-menu').click(tsf._triggerResize),jQuery('.columns-prefs :input[type=radio]').change(tsf._triggerResize),jQuery('.meta-box-sortables').on('sortupdate',tsf._triggerResize)},_triggerTooltipReset:function(){jQuery(window).trigger('tsf-reset-tooltips')},_triggerTooltipUpdate:function(t){jQuery(t).trigger('tsf-tooltip-update')},_triggerResize:function(){jQuery(window).trigger('tsf-flex-resize')},_triggerCounterUpdate:function(){jQuery(window).trigger('tsf-counter-updated')},_triggerReady:function(){jQuery(document.body).trigger('tsf-ready')},_doReady:function(){tsf._initCounters(),tsf._initTitleInputs(),tsf._initUnboundTitleSettings(),tsf._initDescInputs(),tsf._initPrimaryTerm(),tsf.setTabsOnload(),tsf.taglineToggleOnload(),tsf._initToolTips(),tsf.setupImageEditorActions(),tsf.checkImageEditorInput(),tsf.setColorOnload(),tsf.attachUnsavedChangesListener(),tsf.onLoadUnregisterChange(),tsf._triggerReady(),tsf._doFlexResizeListener()},setupVars:function(){tsf.counterType=parseInt(tsf.states.counterType),tsf.hasInput=tsf.states.hasInput},ready:function(t){tsf.setupVars(),t('div.updated, div.error, div.notice-warning').insertAfter('div.tsf-top-wrap'),t(document.body).ready(tsf._doReady),t('.tsf-js-confirm-reset').on('click',tsf.confirmedReset),t('.tsf-tabs-radio').on('change',tsf.tabToggle),t('.tsf-flex-nav-tab-radio').on('change',tsf.flexTabToggle),t('#tsf-description-onblogname-toggle :input').on('click',tsf.taglineToggleDesc),t('#tsf-description-additions-toggle :input').on('click',tsf.additionsToggleDesc),t('.tsf-dismiss').on('click',tsf.dismissNotice)}},jQuery(tsf.ready);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
load.php CHANGED
@@ -83,7 +83,7 @@ function _init_upgrade() {
83
  if ( \get_option( 'the_seo_framework_upgraded_db_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION )
84
  return;
85
 
86
- require_once( THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'upgrade.php' );
87
  }
88
 
89
  /**
@@ -147,7 +147,7 @@ function _autoload_classes( $class ) {
147
  $_class = str_replace( '_interface', '', $_class );
148
  $_class = str_replace( '_', '-', $_class );
149
 
150
- return $loaded[ $class ] = (bool) require_once( $path . $_class . $extension );
151
  }
152
 
153
  \add_action( 'activate_' . THE_SEO_FRAMEWORK_PLUGIN_BASENAME, __NAMESPACE__ . '\\_do_plugin_activation' );
@@ -159,9 +159,7 @@ function _autoload_classes( $class ) {
159
  * @access private
160
  */
161
  function _do_plugin_activation() {
162
-
163
- \The_SEO_Framework\_activation_setup_sitemap();
164
- \The_SEO_Framework\_activation_set_options_autoload();
165
  }
166
 
167
  \add_action( 'deactivate_' . THE_SEO_FRAMEWORK_PLUGIN_BASENAME, __NAMESPACE__ . '\\_do_plugin_deactivation' );
@@ -173,95 +171,5 @@ function _do_plugin_activation() {
173
  * @access private
174
  */
175
  function _do_plugin_deactivation() {
176
-
177
- \The_SEO_Framework\_deactivation_unset_options_autoload();
178
- \The_SEO_Framework\_deactivation_unset_sitemap();
179
- }
180
-
181
- /**
182
- * Add and Flush rewrite rules on plugin activation.
183
- *
184
- * @since 2.6.6
185
- * @since 2.7.1: 1. Now no longer reinitializes global $wp_rewrite.
186
- * 2. Now always listens to the preconditions of the sitemap addition.
187
- * 3. Now flushes the rules on shutdown.
188
- * @since 2.8.0: Added namespace and renamed function.
189
- * @access private
190
- */
191
- function _activation_setup_sitemap() {
192
-
193
- $the_seo_framework = \the_seo_framework();
194
-
195
- if ( isset( $the_seo_framework ) ) {
196
- $the_seo_framework->rewrite_rule_sitemap();
197
- \add_action( 'shutdown', 'flush_rewrite_rules' );
198
- }
199
- }
200
-
201
- /**
202
- * Flush rewrite rules on plugin deactivation.
203
- *
204
- * @since 2.6.6
205
- * @since 2.7.1: 1. Now no longer reinitializes global $wp_rewrite.
206
- * 2. Now flushes the rules on shutdown.
207
- * @since 2.8.0: Added namespace and renamed function.
208
- * @access private
209
- * @global object $wp_rewrite
210
- */
211
- function _deactivation_unset_sitemap() {
212
-
213
- unset( $GLOBALS['wp_rewrite']->extra_rules_top['sitemap\.xml$'] );
214
- unset( $GLOBALS['wp_rewrite']->extra_rules_top['sitemap\.xsl$'] );
215
-
216
- \add_action( 'shutdown', 'flush_rewrite_rules' );
217
- }
218
-
219
- /**
220
- * Turns on autoloading for The SEO Framework main options.
221
- *
222
- * @since 2.9.2
223
- * @access private
224
- */
225
- function _activation_set_options_autoload() {
226
-
227
- $the_seo_framework = \the_seo_framework();
228
-
229
- if ( isset( $the_seo_framework ) ) {
230
- $options = $the_seo_framework->get_all_options();
231
- $setting = THE_SEO_FRAMEWORK_SITE_OPTIONS;
232
-
233
- \remove_all_filters( "pre_update_option_{$setting}" );
234
- \remove_all_actions( "update_option_{$setting}" );
235
- \remove_all_filters( "sanitize_option_{$setting}" );
236
-
237
- // Set to false, so we can reset the options.
238
- $_success = \update_option( $setting, false );
239
- if ( $_success )
240
- \update_option( $setting, $options, 'yes' );
241
- }
242
- }
243
-
244
- /**
245
- * Turns off autoloading for The SEO Framework main options.
246
- *
247
- * @since 2.9.2
248
- * @access private
249
- */
250
- function _deactivation_unset_options_autoload() {
251
-
252
- $the_seo_framework = \the_seo_framework();
253
-
254
- if ( isset( $the_seo_framework ) ) {
255
- $options = $the_seo_framework->get_all_options();
256
- $setting = THE_SEO_FRAMEWORK_SITE_OPTIONS;
257
-
258
- \remove_all_filters( "pre_update_option_{$setting}" );
259
- \remove_all_actions( "update_option_{$setting}" );
260
- \remove_all_filters( "sanitize_option_{$setting}" );
261
-
262
- // Set to false, so we can reset the options.
263
- $_success = \update_option( $setting, false );
264
- if ( $_success )
265
- \update_option( $setting, $options, 'no' );
266
- }
267
  }
83
  if ( \get_option( 'the_seo_framework_upgraded_db_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION )
84
  return;
85
 
86
+ require THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'upgrade.php';
87
  }
88
 
89
  /**
147
  $_class = str_replace( '_interface', '', $_class );
148
  $_class = str_replace( '_', '-', $_class );
149
 
150
+ return $loaded[ $class ] = (bool) require $path . $_class . $extension;
151
  }
152
 
153
  \add_action( 'activate_' . THE_SEO_FRAMEWORK_PLUGIN_BASENAME, __NAMESPACE__ . '\\_do_plugin_activation' );
159
  * @access private
160
  */
161
  function _do_plugin_activation() {
162
+ require THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'plugin-activation.php';
 
 
163
  }
164
 
165
  \add_action( 'deactivate_' . THE_SEO_FRAMEWORK_PLUGIN_BASENAME, __NAMESPACE__ . '\\_do_plugin_deactivation' );
171
  * @access private
172
  */
173
  function _do_plugin_deactivation() {
174
+ require THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'plugin-deactivation.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  }
patch/index.php DELETED
@@ -1,10 +0,0 @@
1
- <?php
2
- /**
3
- * If you're reading this...
4
- * Congratulations, you're alive.
5
- * If that's not something to smile about,
6
- * then I don't know what is.
7
- * - Chad Sugg
8
- *
9
- * :)
10
- */
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -1,11 +1,11 @@
1
  === The SEO Framework ===
2
  Contributors: Cybr
3
  Donate link: https://theseoframework.com/donate/
4
- Tags: SEO, XML Sitemap, Google, Open Graph, Schema.org
5
  Requires at least: 4.4.0
6
- Tested up to: 4.8.1
7
  Requires PHP: 5.3.0
8
- Stable tag: 2.9.4
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
@@ -224,175 +224,127 @@ Transporting Terms and Taxonomies SEO data isn't supported.
224
 
225
  == Changelog ==
226
 
227
- = 2.9.4 - Terminal Queries =
228
 
229
  **Release date:**
230
 
231
- * August 30th, 2017
232
 
233
- **Summarized:**
234
-
235
- * New performance options have been added. They allow you to optimize Search and Archive query alterations.
236
- * Schema.org JSON-LD data is now cleaner when you run PHP 5.4 or later.
237
- * Custom input image URLs can now dynamically switch between HTTP and HTTPS and the dimensions are always set, regardless of input.
238
- * Multisite networks no longer initiate new database connections on every page for plugin compatibility checks.
239
-
240
- **Did you know?**
241
-
242
- * Local SEO has been added to the [Extension Manager](https://wordpress.org/plugins/the-seo-framework-extension-manager/).
243
- * It increases location-aware search presence in Google Search, Google Maps, and even Google Images.
244
-
245
- **Detailed log:**
246
 
247
- * ***I had not overlooked them, and [they shall be answered](https://theseoframework.com/?p=2135#detailed).***
248
 
249
- = 2.9.3 - Assiduous Substratum =
250
 
251
  **Release date:**
252
 
253
- * July 3rd, 2017
254
-
255
- **Announcement: Local SEO Beta**
256
-
257
- * Local SEO is a premium extension, and it's almost ready for testing.
258
- * As we do not want to spam your WordPress dashboard, I've created a new [Twitter account](https://twitter.com/TheSEOFramework) for future announcements.
259
- * Feel free to follow us to receive the latest updates. As we're planning a test-run prior to release, further details for beta-access will also follow in a tweet.
260
-
261
- [youtube https://www.youtube.com/?v=q_ZnBuU1BwY&w=611&h=642&showinfo=0&rel=0&showsearch=0]
262
-
263
- **Summarized:**
264
-
265
- * Social images can now scale up to 4K resolution. This means (manual and automated) forced cropping no longer initiates at 1500px but at 4096px.
266
- * A new option has been added for every taxonomical post type in the Visibility tab. It allows you to prevent the annotated pages from showing up in Archives.
267
- * Structured Data output has been revisited. This includes merging of output, removal of misplaced output, and performance improvements.
268
- * When your home page is a blog, pages without an ID (404, search, date archives, etc.) had output and caching issues. These issues have been resolved.
269
- * Several security concerns have also been addressed. Although, none of them could be verified as the coding environment is already well protected.
270
-
271
- **For everyone: Caching changes:**
272
 
273
- * Descriptions and Schema.org output transients are no longer enabled by default. Because for most sites, it's better left disabled.
274
- * This has been done to reduce database calls. Ultimately, the performance benefits of using the transients are use-case specific.
275
 
276
- **For developers: Schema.org output code changes:**
 
 
277
 
278
- * The Schema.org output code has been [rewritten](https://github.com/sybrew/the-seo-framework/issues/97). This improves reliability, performance and extensibility.
279
- * If you've extended or altered the Schema.org generation output, you might wish to revisit your coding implementations.
280
- * All affronted methods have been correctly deprecated and tested once more. So, 500 errors shouldn't occur.
281
- * To be certain, visit the detailed changelog and compare your code.
282
-
283
- **For high-traffic webmasters and Google Analytics integration plugin authors: About the Search URL change:**
284
-
285
- * From this update, new canonical URLs will be generated for search queries to comply to the pretty permalink structure.
286
- * WordPress natively supports the `/search/{search_term}` endpoint; however, Google Analytics does not.
287
- * To enable support, please visit [this page](https://support.google.com/analytics/answer/1012264?hl=en&ref_topic=1031951#Post) for more information.
288
- * I've created a plugin that will enhance support for you. You can download it [here](https://gist.github.com/sybrew/ab5553dd8a06e73794680c4a2cc24661).
289
- * An extension is planned that will implement Google Analytics for you, complying to those guidelines.
290
-
291
- **Detailed log:**
292
-
293
- * ***Already the Sun is climbing to noon, and I feel the need of [something to strengthen me](https://theseoframework.com/?p=2064#detailed).***
294
-
295
- = 2.9.2 - Diminutive Consolidation =
296
 
297
  **Release date:**
298
 
299
- * May 8th, 2017
300
-
301
- **Summarized:**
302
-
303
- * Now, Polylang is officially supported by The SEO Framework.
304
- * The sitemap now supports plain permalinks. That means it now literally works for every website.
305
- * The robots.txt file has been enhanced, so it now informs you when the output location is incorrect.
306
- * Moreover, various bugs have been fixed, mainly concerning third party plugins.
307
-
308
- **We're looking for translation editors:**
309
-
310
- * First, thank you so much to all the translation [contributors](https://translate.wordpress.org/projects/wp-plugins/autodescription/contributors).
311
- * Now, if you want to see The SEO Framework in your language, head over to [this page](https://translate.wordpress.org/projects/wp-plugins/autodescription) and feel free to contribute.
312
- * If you wish to easily maintain and keep a close eye on all the contributions for your language, [ask us](https://theseoframework.com/contact/) to ask WordPress Polyglots to add you as a contributor.
313
- * Ultimately, it's up to the WordPress Polyglots team to fulfill your request. It generally depends on how well you've submitted translations for you to be accepted.
314
-
315
- **A few notes about translations:**
316
-
317
- * If you use a machine to translate for you, note that they can generate out-of-context strings. So keep an eye out for those!
318
- * If you notice that strings are very hard to translate, e.g. because of grammatical gender, [let us know](https://github.com/sybrew/the-seo-framework/issues/new)!
319
- * Please don't translate "The SEO Framework", it's a registered brand-name.
320
- * Be sure not to add spaces if you see backticks, asterisks, or brackets. They're used for Markdown language construction.
321
- * In TSF, you generally can't use UTF character codes like `&#38;#x2661;`, as they're automatically removed or rendered unreadable for added security. Add them as displayed instead: **♡**.
322
 
323
- **Detailed log:**
324
-
325
- * ***If you are a friend, speak the password, and the doors will open, and [you can enter](https://theseoframework.com/?p=1982#detailed).***
326
-
327
- = 2.9.1 - Sovereign Comprehension =
328
-
329
- **Release date:**
330
-
331
- * March 27th, 2017
332
-
333
- **Summarized:**
334
-
335
- * This release patches a few bugs that were brought with the 2.9.0 release related to debugging and cache clearing.
336
- * And if you like to use quick edit a lot, the SEO Bar will now also re-render on save.
337
-
338
- **Detailed log:**
339
-
340
- * ***All we have to decide is what to do with [the time that is given us](https://theseoframework.com/?p=1912#detailed).***
341
-
342
- = 2.9.0 - Equitable Erudition =
343
-
344
- *Courage is found in unlikely places - J.R.R. Tolkien*
345
-
346
- **Release date:**
347
 
348
- * March 25th, 2017
349
 
350
  **Summarized:**
351
 
352
- * This update focuses on fixing bugs and expanding the API for developers.
353
- * To expand the API for per page (in-post) SEO settings, tabs had to be added in the SEO settings meta box.
354
- * The JavaScript code has also been overhauled to improve performance and allow third party implementation.
355
- * Moreover, the home page settings now allow you to upload a social image.
356
- * Structured data markup has also been improved, like the inclusion of an alternative Sitename and fixes for Breadcrumb images.
357
- * The sitemap can now include the blog page. The lastmod value of which listens to multiple pages to automatically determines what's best.
358
- * Unfortunately, Twitter has removed support for photo cards. This update makes sure that the regarding settings correctly convert to the current format.
359
-
360
- **Only one week left for the earliest of early-bird discounts:**
361
-
362
- * With [The SEO Framework - Extension Manager](https://wordpress.org/plugins/the-seo-framework-extension-manager/)'s release, a celebratory discount has been introduced.
363
- * If you wish to benefit from this lifetime discount, [visit the shop](https://premium.theseoframework.com/shop/) for more information.
364
- * More awesome extensions are coming soon!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
 
366
  **Survey:**
367
 
368
- * After updating, please fill in our [Update Survey](https://theseoframework.com/?p=1781): tell us what you like or can be done better.
369
-
370
- **For everyone: Tabbed In-post SEO layout**
371
-
372
- * This release brings tabbed layout to the in-post SEO settings.
373
- * With this change I've also altered the overall looks, with the help from [Daniel](https://github.com/danielpost).
374
- * This layout allows extensions from the [Extension Manager](https://wordpress.org/plugins/the-seo-framework-extension-manager/) to be implemented much easier.
375
- * This layout is self-responsive! This means it's not dependent on the browser size, but on how much content will fit.
376
- * Therefore, this layout allows the SEO settings to be placed in the right sidebar! Take a look at the [new screenshots](https://wordpress.org/plugins/autodescription/#screenshots).
377
-
378
- **For everyone: Browser support**
379
-
380
- * This release brings [CSS Flexbox](https://www.w3.org/TR/css-flexbox-1/) to the new in-post SEO settings meta box.
381
- * The flexbox module is still experimental, in a way that not all browsers correctly support this to the fullest extend.
382
- * However, support for as many browsers feasible has been implemented. Check out [the list](https://theseoframework.com/?p=1903#browser-support). Enjoy!
383
- * The gist is that Chrome, Firefox, IE10 and Safari 6 or later are supported.
384
-
385
- **SEO Tip of the Update - Trust in layout**
386
-
387
- * Is your website glitchy and has placeholder images, unmatched colors or weirdly contrasting borders all over the place?
388
- * Consider going for a more modern and clean layout. Strip out what isn't necessary. A clean layout implies professionalism and increases visitors' trust.
389
- * Even if you're just starting out with your website, remove all that could be but really isn't. Because if you leave in placeholders for the future, it implies amateurism.
390
- * People want their truth to be confirmed or their problems to be solved. If you can't confirm or solve the layout of your website, then they won't trust you to do so for their issues.
391
- * Simply put: It doesn't have to be perfect, it just must be done.
392
 
393
  **Detailed log:**
394
 
395
- * ***It is some miles, but [it will shorten your journey tomorrow](https://theseoframework.com/?p=1903#detailed).***
396
 
397
  = Full changelog =
398
 
@@ -400,6 +352,9 @@ Transporting Terms and Taxonomies SEO data isn't supported.
400
 
401
  == Upgrade Notice ==
402
 
 
 
 
403
  = 2.9.3 =
404
  A highly recommended update that fixes "Home Page as Blog" query issues.
405
 
1
  === The SEO Framework ===
2
  Contributors: Cybr
3
  Donate link: https://theseoframework.com/donate/
4
+ Tags: SEO, XML Sitemap, Google, Open Graph, Schema.org, Twitter
5
  Requires at least: 4.4.0
6
+ Tested up to: 4.9
7
  Requires PHP: 5.3.0
8
+ Stable tag: 3.0.2
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
224
 
225
  == Changelog ==
226
 
227
+ = 3.0.2 - Esteem =
228
 
229
  **Release date:**
230
 
231
+ * November 23rd, 2017
232
 
233
+ **Fixed:**
 
 
 
 
 
 
 
 
 
 
 
 
234
 
235
+ * A fatal error no longer occurs on the wpForo Forum plugin pages.
236
 
237
+ = 3.0.1 - Renown =
238
 
239
  **Release date:**
240
 
241
+ * November 20th, 2017
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
243
+ **Fixed:**
 
244
 
245
+ * A fatal error no longer occurs on pages when using plain permalinks.
246
+ * On-site search canonical URLs are now correct when no blog page is assigned.
247
+ * Title placeholders can now render HTML characters correctly.
248
 
249
+ = 3.0.0 - Eminence =
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
 
251
  **Release date:**
252
 
253
+ * November 19th, 2017
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
 
255
+ **Did you know?**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
 
257
+ * Since about a week ago, 3 new free extensions are available in the [Extension Manager](https://wordpress.org/plugins/the-seo-framework-extension-manager/).
258
 
259
  **Summarized:**
260
 
261
+ * Finally, after 8 months of preparation, experimenting, testing, and coding, TSF 3.0 is here.
262
+ * This update focuses on improved social site interaction, WordPress' API coherence, and optimizing UX.
263
+ * To improve social site interaction, social site links can be added to author profile pages.
264
+ * The Open Graph protocol has been updated, so will your meta output.
265
+ * The canonical URL generation has been revised, and it now works mostly through WordPress' API.
266
+ * For improved UX we've added pixel counters, better tooltips, and admin color scheme adherence.
267
+ * Oh, you can also select the primary term for each hierarchical post type.
268
+
269
+ **New primary terms:**
270
+
271
+ * *In WordPress, terms are generally known as categories.*
272
+ * The primary term influences how canonical URLs are generated for the post, and how breadcrumbs are constructed.
273
+ * Next to each term selection list, you'll now see radio buttons pop up aside each selected term.
274
+ * The selected term will be assigned as the primary term.
275
+ * If no primary term is selected, an assigned term that has been implemented earliest on the site will be used.
276
+ * Note that this feature requires JavaScript to be enabled. Authors without JavaScript can't change the primary term.
277
+
278
+ **Revised canonical URLs:**
279
+
280
+ * The canonical URL generation has been completely rewritten. Most users won't notice anything from this.
281
+ * It now uses WordPress' 4.6+ canonical URL generation (backward-compatibility is provided), instead of an in-house "guessing" version.
282
+ * **So, the Canonical URL should now always be compatible with any plugin, out of the box.** This is great news for translation plugin users!
283
+ * Note that canonical URLs are no longer outputted on private or unpublished posts.
284
+ * Note that if a query isn't registered correctly, the URL will also stay empty. Or, in unlikely cases, it will link to the home page.
285
+ * Contact the respective plugin author on such issues. I'd love to help them correct this.
286
+
287
+ **Finally, author SEO:**
288
+
289
+ * On profile pages of users with Author capabilities (or higher), two new settings have been added under heading **"Authorial Info"**.
290
+ * Here, authors can set their Facebook profile page and Twitter profile page.
291
+ * These links will be used in Open Graph and Twitter meta output.
292
+ * Note that the author's profile must be public for it to be used when sharing links.
293
+ * When no author links are set, the "new" fallback URLs from the Social Meta Settings will be used.
294
+ * Expand your authorial presence using the free [Articles Extension](https://theseoframework.com/extensions/articles/).
295
+
296
+ **A better admin experience:**
297
+
298
+ * This plugin now uses your chosen admin color scheme, subtly. You can see it being used as highlights and for tooltips.
299
+ * About tooltips, they've been completely rewritten:
300
+ * They now look for boundaries, so they won't fall off the page or bound box. They can also face down when needed.
301
+ * They try to center themselves based on your initial pointer position.
302
+ * They work perfectly on any touch screen, also using Windows Touch.
303
+ * They no longer gulp down RAM, they use cutlery. Basically, fewer DOM items initiate them and they self-destruct as they disappear.
304
+ * Tooltips are now used on every `[?]` mark, so you can instantly see what those marks convey.
305
+ * Title input and preview generation has also been completely rewritten, and this was a big challenge to implement:
306
+ * Titles now update on various actions, like updating the visibility or name of the page.
307
+ * Titles now show prefixes, like "Private:" or "Protected:". They'll try to fit neatly, wherever.
308
+ * Character counters are now always correct; they no longer "guess", they "know".
309
+ * Pixel counters have been added too. More on that below.
310
+ * The CSS and JS scripts implemented by TSF have been optimized even further. So your admin experience should be a little speedier.
311
+
312
+ **The pixel counter:**
313
+
314
+ * A character-count guideline is nice to have. But it remains a guideline, and you want facts... correct?
315
+ * So, we've added a pixel counter. This pixel counter knows exactly how much space your titles and descriptions take up in Google's SERP.
316
+ * To explain this difference visually: Five characters of "WWWWW" take up more space than five of "IIIII".
317
+ * Hover over the pixel counter to see how many pixels you've used.
318
+ * Through testing we found that time-sensitive items (i.e. articles) have less space available for descriptions.
319
+ * You can enable and disable the character and pixel counters at the Layout settings.
320
+ * Note that new installations won't get to see the character counter by default anymore.
321
+ * Note that the pixel counter isn't represented (yet) by the SEO Bar. So, you shouldn't have to worry about yellow or even red items.
322
+
323
+ **AI good structure:**
324
+
325
+ * You can now upload a square website logo. This is used in the [Articles Extension](https://theseoframework.com/extensions/articles/), too.
326
+ * The "Site Name" project has been dropped, and this data is now fetched through other means, like the "Sitelinks Searchbox".
327
+ * Breadcrumbs have been revised, too. The generation is now smarter in tree selection, and only one breadcrumb is outputted, which uses your primary term selection.
328
+ * WooCommerce 3.0+ products are recognized correctly by search engines, once more.
329
+
330
+ **Privacy everywhere:**
331
+
332
+ * When you click on any link outputted by TSF on your domain, you can be certain it no longer carries any traceable information.
333
+
334
+ **A note on browser compatibility:**
335
+
336
+ * As we want to move forward, we don't believe we should be supporting insecure browsers.
337
+ * So, your admin experience will be degraded when using an outdated browser.
338
+ * Be sure to use at least IE 11, Safari 10, iOS 10, or better.
339
+ * We expect only a few users to be negatively affected. For everyone else, we welcome you to the future of browsing.
340
 
341
  **Survey:**
342
 
343
+ * After updating and playing around with the update, feel free to fill in our [update survey](https://theseoframework.com/?p=1781). Tell us what you like or what could've been done better.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
 
345
  **Detailed log:**
346
 
347
+ * ***Before anything else, preparation is the [key to success](https://theseoframework.com/?p=2210#detailed).***
348
 
349
  = Full changelog =
350
 
352
 
353
  == Upgrade Notice ==
354
 
355
+ = 3.0.0 =
356
+ A major update. Make a backup of your database before upgrading.
357
+
358
  = 2.9.3 =
359
  A highly recommended update that fixes "Home Page as Blog" query issues.
360