The SEO Framework - Version 2.9.2

Version Description

  • Diminutive Consolidation =

Release date:

  • May 8th, 2017

Summarized:

  • Now, Polylang is officially supported by The SEO Framework.
  • The sitemap now supports plain permalinks. That means it now literally works for every website.
  • The robots.txt file has been enhanced, so it now informs you when the output location is incorrect.
  • Moreover, various bugs have been fixed, mainly concerning third party plugins.

We're looking for translation editors:

  • First, thank you so much to all the translation contributors.
  • Now, if you want to see The SEO Framework in your language, head over to this page and feel free to contribute.
  • If you wish to easily maintain and keep a close eye on all the contributions for your language, ask us to ask WordPress Polyglots to add you as a contributor.
  • 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.

A few notes about translations:

  • 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!
  • If you notice that strings are very hard to translate, e.g. because of grammatical gender, let us know!
  • Please don't translate "The SEO Framework", it's a registered brand-name.
  • Be sure not to add spaces if you see backticks, asterisks, or brackets. They're used for Markdown language construction.
  • In TSF, you generally can't use UTF character codes like ♡, as they're automatically removed or rendered unreadable for added security. Add them as displayed instead: ****.

Detailed log:

If you are a friend, speak the password, and the doors will open, and you can enter.

Download this release

Release Info

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

Code changes from version 2.9.1 to 2.9.2

Files changed (52) hide show
  1. autodescription.php +29 -10
  2. inc/classes/admin-init.class.php +60 -7
  3. inc/classes/admin-pages.class.php +10 -2
  4. inc/classes/cache.class.php +9 -5
  5. inc/classes/compat.class.php +10 -2
  6. inc/classes/core.class.php +33 -21
  7. inc/classes/debug.class.php +1 -1
  8. inc/classes/deprecated.class.php +2 -2
  9. inc/classes/detect.class.php +8 -3
  10. inc/classes/doing-it-right.class.php +3 -3
  11. inc/classes/feed.class.php +1 -1
  12. inc/classes/generate-description.class.php +38 -10
  13. inc/classes/generate-image.class.php +3 -2
  14. inc/classes/generate-ldjson.class.php +3 -2
  15. inc/classes/generate-title.class.php +17 -7
  16. inc/classes/generate-url.class.php +148 -104
  17. inc/classes/generate.class.php +1 -1
  18. inc/classes/init.class.php +31 -66
  19. inc/classes/inpost.class.php +1 -1
  20. inc/classes/load.class.php +1 -1
  21. inc/classes/metaboxes.class.php +1 -1
  22. inc/classes/post-data.class.php +1 -1
  23. inc/classes/query.class.php +23 -1
  24. inc/classes/render.class.php +82 -4
  25. inc/classes/sanitize.class.php +1 -3
  26. inc/classes/site-options.class.php +13 -6
  27. inc/classes/sitemaps.class.php +87 -15
  28. inc/classes/term-data.class.php +1 -1
  29. inc/compat/php-mbstring.php +4 -4
  30. inc/compat/plugin-polylang.php +187 -0
  31. inc/compat/plugin-wpforo.php +82 -0
  32. inc/compat/plugin-wpml.php +63 -37
  33. inc/functions/deprecated.php +2 -68
  34. inc/functions/optionsapi.php +1 -1
  35. inc/functions/plugin-test-server.php +1 -1
  36. inc/functions/upgrade.php +1 -1
  37. inc/interfaces/debug.interface.php +1 -1
  38. inc/views/metaboxes/general-metabox.php +34 -34
  39. inc/views/metaboxes/schema-metabox.php +10 -9
  40. inc/views/metaboxes/sitemaps-metabox.php +73 -79
  41. inc/views/sitemap/xsl-stylesheet.php +8 -6
  42. language/autodescription.pot +262 -243
  43. lib/css/tsf-rtl.css +2 -0
  44. lib/css/tsf-rtl.min.css +1 -1
  45. lib/css/tsf.css +2 -0
  46. lib/css/tsf.min.css +1 -1
  47. lib/js/tsf.externs.js +1 -1
  48. lib/js/tsf.externs.protected.js +1 -1
  49. lib/js/tsf.js +56 -47
  50. lib/js/tsf.min.js +32 -32
  51. load.php +53 -1
  52. readme.txt +135 -108
autodescription.php CHANGED
@@ -3,9 +3,9 @@
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.1
7
  * Author: Sybre Waaijer
8
- * Author URI: https://cyberwire.nl/
9
  * License: GPLv3
10
  * Text Domain: autodescription
11
  * Domain Path: /language
@@ -15,7 +15,7 @@ defined( 'ABSPATH' ) or die;
15
 
16
  /**
17
  * The SEO Framework plugin
18
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
19
  *
20
  * This program is free software: you can redistribute it and/or modify
21
  * it under the terms of the GNU General Public License version 3 as published
@@ -42,26 +42,43 @@ defined( 'ABSPATH' ) or die;
42
  //}},0);
43
 
44
  /**
45
- * CDN Cache buster. 3 to 4 point.
46
- * Not many caching plugins use CDN in dashboard. What a shame. Firefox does cache.
 
 
 
 
 
47
  * @since 1.0.0
48
  */
49
- define( 'THE_SEO_FRAMEWORK_VERSION', '2.9.1' );
50
 
51
  /**
52
- * Plugin Database version for lightweight version upgrade comparing.
 
 
 
53
  * @since 2.7.0
54
  */
55
  define( 'THE_SEO_FRAMEWORK_DB_VERSION', '2903' );
56
 
57
  /**
58
- * Plugin options filter.
 
 
 
 
 
59
  * @since 2.2.2
60
  */
61
  define( 'THE_SEO_FRAMEWORK_SITE_OPTIONS', (string) apply_filters( 'the_seo_framework_site_options', 'autodescription-site-settings' ) );
62
 
63
  /**
64
- * Plugin options filter.
 
 
 
 
65
  * @since 2.2.2
66
  */
67
  define( 'THE_SEO_FRAMEWORK_NETWORK_OPTIONS', (string) apply_filters( 'the_seo_framework_network_settings', 'autodescription-network-settings' ) );
@@ -139,6 +156,7 @@ the_seo_framework_pre_load();
139
  * Determines whether we can "just" load the plugin, or require verification beforehand.
140
  *
141
  * @since 2.8.0
 
142
  */
143
  function the_seo_framework_pre_load() {
144
  if ( get_site_option( 'the_seo_framework_tested_upgrade_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION ) {
@@ -180,9 +198,10 @@ function the_seo_framework_load_base_files() {
180
  * Load deprecated functions.
181
  *
182
  * @since 2.7.0
 
183
  * @uses THE_SEO_FRAMEWORK_DIR_PATH_FUNCT
184
  */
185
- require_once( THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'deprecated.php' );
186
 
187
  /**
188
  * Load API files.
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.2
7
  * Author: Sybre Waaijer
8
+ * Author URI: https://theseoframework.com/
9
  * License: GPLv3
10
  * Text Domain: autodescription
11
  * Domain Path: /language
15
 
16
  /**
17
  * The SEO Framework plugin
18
+ * Copyright (C) 2015 - 2017 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
19
  *
20
  * This program is free software: you can redistribute it and/or modify
21
  * it under the terms of the GNU General Public License version 3 as published
42
  //}},0);
43
 
44
  /**
45
+ * The plugin version.
46
+ *
47
+ * Used as a CDN and Browser Cache buster.
48
+ * Chrome and Firefox cache admin scripts.
49
+ *
50
+ * 3 point: x.x.y; x.x is major; y is minor.
51
+ *
52
  * @since 1.0.0
53
  */
54
+ define( 'THE_SEO_FRAMEWORK_VERSION', '2.9.2' );
55
 
56
  /**
57
+ * The plugin Database version.
58
+ *
59
+ * Used for lightweight version upgrade comparing.
60
+ *
61
  * @since 2.7.0
62
  */
63
  define( 'THE_SEO_FRAMEWORK_DB_VERSION', '2903' );
64
 
65
  /**
66
+ * The plugin options database option_name.
67
+ *
68
+ * Used for storing the SEO options array.
69
+ *
70
+ * @todo document filter.
71
+ *
72
  * @since 2.2.2
73
  */
74
  define( 'THE_SEO_FRAMEWORK_SITE_OPTIONS', (string) apply_filters( 'the_seo_framework_site_options', 'autodescription-site-settings' ) );
75
 
76
  /**
77
+ * The plugin network options.
78
+ *
79
+ * @todo document filter.
80
+ * Unused. @todo remove
81
+ *
82
  * @since 2.2.2
83
  */
84
  define( 'THE_SEO_FRAMEWORK_NETWORK_OPTIONS', (string) apply_filters( 'the_seo_framework_network_settings', 'autodescription-network-settings' ) );
156
  * Determines whether we can "just" load the plugin, or require verification beforehand.
157
  *
158
  * @since 2.8.0
159
+ * @uses get_site_option(), so it will only test once per WordPress installation; multisite included.
160
  */
161
  function the_seo_framework_pre_load() {
162
  if ( get_site_option( 'the_seo_framework_tested_upgrade_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION ) {
198
  * Load deprecated functions.
199
  *
200
  * @since 2.7.0
201
+ * @since 2.9.2 No longer called to improve performance.
202
  * @uses THE_SEO_FRAMEWORK_DIR_PATH_FUNCT
203
  */
204
+ // require_once( THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'deprecated.php' );
205
 
206
  /**
207
  * Load API files.
inc/classes/admin-init.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -162,6 +162,8 @@ class Admin_Init extends Init {
162
  * @since 2.6.0
163
  * @staticvar bool $registered : Prevents Re-registering of the style.
164
  * @access private
 
 
165
  */
166
  public function _register_admin_javascript() {
167
 
@@ -433,7 +435,7 @@ class Admin_Init extends Init {
433
  /**
434
  * Checks ajax referred set by set_js_nonces based on capability.
435
  *
436
- * Performs die() on fail.
437
  *
438
  * @since 2.9.0
439
  * @access private
@@ -521,6 +523,7 @@ class Admin_Init extends Init {
521
  * for alerts, etc.
522
  *
523
  * @since 2.2.2
 
524
  *
525
  * @param string $page Menu slug.
526
  * @param array $query_args Optional. Associative array of query string arguments
@@ -539,12 +542,62 @@ class Admin_Init extends Init {
539
  unset( $query_args[ $key ] );
540
  }
541
 
542
- $url = \add_query_arg( $query_args, $url );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
543
 
544
- \wp_safe_redirect( \esc_url_raw( $url ), 302 );
545
  exit;
546
  }
547
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  /**
549
  * Handles counter option update on AJAX request.
550
  *
@@ -561,7 +614,7 @@ class Admin_Init extends Init {
561
  //* If current user isn't allowed to edit posts, don't do anything and kill PHP.
562
  if ( ! \current_user_can( 'edit_posts' ) ) {
563
  //* Remove output buffer.
564
- $this->clean_reponse_header();
565
 
566
  //* Encode and echo results. Requires JSON decode within JS.
567
  echo json_encode( array( 'type' => 'failure', 'value' => '' ) );
@@ -587,7 +640,7 @@ class Admin_Init extends Init {
587
  );
588
 
589
  //* Remove output buffer.
590
- $this->clean_reponse_header();
591
 
592
  //* Encode and echo results. Requires JSON decode within JS.
593
  echo json_encode( $results );
@@ -617,7 +670,7 @@ class Admin_Init extends Init {
617
 
618
  $attachment_id = \absint( $_POST['id'] );
619
 
620
- $context = str_replace( '_', '-', $_POST['context'] );
621
  $data = array_map( 'absint', $_POST['cropDetails'] );
622
  $cropped = \wp_crop_image( $attachment_id, $data['x1'], $data['y1'], $data['width'], $data['height'], $data['dst_width'], $data['dst_height'] );
623
 
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
162
  * @since 2.6.0
163
  * @staticvar bool $registered : Prevents Re-registering of the style.
164
  * @access private
165
+ *
166
+ * @return void Early if already registered.
167
  */
168
  public function _register_admin_javascript() {
169
 
435
  /**
436
  * Checks ajax referred set by set_js_nonces based on capability.
437
  *
438
+ * Performs die() on failure.
439
  *
440
  * @since 2.9.0
441
  * @access private
523
  * for alerts, etc.
524
  *
525
  * @since 2.2.2
526
+ * @since 2.9.2 : Added user-friendly exception handling.
527
  *
528
  * @param string $page Menu slug.
529
  * @param array $query_args Optional. Associative array of query string arguments
542
  unset( $query_args[ $key ] );
543
  }
544
 
545
+ $target = \add_query_arg( $query_args, $url );
546
+ $target = \esc_url_raw( $url );
547
+
548
+ //* Predict white screen:
549
+ $headers_sent = headers_sent();
550
+
551
+ /**
552
+ * Dev debug:
553
+ * 1. Change 302 to 500 if you wish to test headers.
554
+ * 2. Also force handle_admin_redirect_error() to run.
555
+ */
556
+ \wp_safe_redirect( $target, 302 );
557
+
558
+ //* White screen of death for non-debugging users. Let's make it friendlier.
559
+ if ( $headers_sent ) {
560
+ $this->handle_admin_redirect_error( $target );
561
+ }
562
 
 
563
  exit;
564
  }
565
 
566
+ /**
567
+ * Provides an accessible error for when redirecting fails.
568
+ *
569
+ * @since 2.9.2
570
+ * @link https://developer.wordpress.org/reference/functions/wp_redirect/
571
+ *
572
+ * @param string $target The redirect target location. Should be escaped.
573
+ * @return void
574
+ */
575
+ protected function handle_admin_redirect_error( $target = '' ) {
576
+
577
+ if ( empty( $target ) )
578
+ return;
579
+
580
+ $headers_list = headers_list();
581
+ $location = sprintf( 'Location: %s', \wp_sanitize_redirect( $target ) );
582
+
583
+ //* Test if WordPress' redirect header is sent. Bail if true.
584
+ if ( in_array( $location, $headers_list, true ) )
585
+ return;
586
+
587
+ //* Output message:
588
+ printf( '<p><strong>%s</strong></p>',
589
+ //* Markdown escapes.
590
+ $this->convert_markdown(
591
+ sprintf(
592
+ /* translators: %s = Redirect URL markdown */
593
+ \esc_html__( 'There has been an error redirecting. Refresh the page or follow [this link](%s).', 'autodescription' ),
594
+ $target
595
+ ),
596
+ array( 'a' )
597
+ )
598
+ );
599
+ }
600
+
601
  /**
602
  * Handles counter option update on AJAX request.
603
  *
614
  //* If current user isn't allowed to edit posts, don't do anything and kill PHP.
615
  if ( ! \current_user_can( 'edit_posts' ) ) {
616
  //* Remove output buffer.
617
+ $this->clean_response_header();
618
 
619
  //* Encode and echo results. Requires JSON decode within JS.
620
  echo json_encode( array( 'type' => 'failure', 'value' => '' ) );
640
  );
641
 
642
  //* Remove output buffer.
643
+ $this->clean_response_header();
644
 
645
  //* Encode and echo results. Requires JSON decode within JS.
646
  echo json_encode( $results );
670
 
671
  $attachment_id = \absint( $_POST['id'] );
672
 
673
+ $context = \sanitize_key( str_replace( '_', '-', $_POST['context'] ) );
674
  $data = array_map( 'absint', $_POST['cropDetails'] );
675
  $cropped = \wp_crop_image( $attachment_id, $data['x1'], $data['y1'], $data['width'], $data['height'], $data['dst_width'], $data['dst_height'] );
676
 
inc/classes/admin-pages.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -93,11 +93,18 @@ class Admin_Pages extends Inpost {
93
  * Adds menu links under "settings" in the wp-admin dashboard
94
  *
95
  * @since 2.2.2
 
 
96
  *
97
- * @return void
98
  */
99
  public function add_menu_link() {
100
 
 
 
 
 
 
101
  $menu = array(
102
  'page_title' => \esc_html__( 'SEO Settings', 'autodescription' ),
103
  'menu_title' => \esc_html__( 'SEO', 'autodescription' ),
@@ -137,6 +144,7 @@ class Admin_Pages extends Inpost {
137
  //* Enqueue scripts
138
  \add_action( 'admin_print_scripts-' . $this->seo_settings_page_hook, array( $this, 'enqueue_admin_javascript' ), 11 );
139
 
 
140
  }
141
 
142
  /**
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
93
  * Adds menu links under "settings" in the wp-admin dashboard
94
  *
95
  * @since 2.2.2
96
+ * @since 2.9.2 Added static cache so the method can only run once.
97
+ * @staticvar bool $run True if already run.
98
  *
99
+ * @return void Early if method is already called.
100
  */
101
  public function add_menu_link() {
102
 
103
+ static $run = false;
104
+
105
+ if ( $run )
106
+ return;
107
+
108
  $menu = array(
109
  'page_title' => \esc_html__( 'SEO Settings', 'autodescription' ),
110
  'menu_title' => \esc_html__( 'SEO', 'autodescription' ),
144
  //* Enqueue scripts
145
  \add_action( 'admin_print_scripts-' . $this->seo_settings_page_hook, array( $this, 'enqueue_admin_javascript' ), 11 );
146
 
147
+ $run = true;
148
  }
149
 
150
  /**
inc/classes/cache.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -476,7 +476,7 @@ class Cache extends Sitemaps {
476
  * When the caching mechanism changes. Change this value.
477
  * Use hex. e.g. 0, 1, 2, 9, a, b
478
  */
479
- $sitemap_revision = '2';
480
  $theme_dir_revision = '0';
481
 
482
  $this->sitemap_transient = $this->is_option_checked( 'cache_sitemap' ) ? $this->add_cache_key_suffix( 'tsf_sitemap_' . $sitemap_revision ) : '';
@@ -656,8 +656,9 @@ class Cache extends Sitemaps {
656
  } elseif ( $this->is_search() ) {
657
  $query = '';
658
 
 
659
  if ( function_exists( 'get_search_query' ) ) {
660
- $search_query = \get_search_query();
661
 
662
  if ( $search_query )
663
  $query = str_replace( ' ', '', $search_query );
@@ -714,7 +715,7 @@ class Cache extends Sitemaps {
714
  static $unix = null;
715
 
716
  if ( ! isset( $unix ) )
717
- $unix = date( 'U' );
718
 
719
  //* Temporarily disable caches to prevent database spam.
720
  $this->the_seo_framework_use_transients = false;
@@ -769,6 +770,7 @@ class Cache extends Sitemaps {
769
  * Use this method if you wish to evade the query usage.
770
  *
771
  * @since 2.9.1
 
772
  * @staticvar array $cached_id : contains cache strings.
773
  * @see $this->generate_cache_key().
774
  * @see $this->generate_cache_key_by_query() to get cache key from the query.
@@ -776,7 +778,7 @@ class Cache extends Sitemaps {
776
  * @param int|string|bool $page_id the Taxonomy or Post ID.
777
  * @param string $taxonomy The term taxonomy.
778
  * @param string $type The Post Type.
779
- * @return string The generated cache key by type.
780
  */
781
  public function generate_cache_key_by_type( $page_id, $taxonomy = '', $type = '' ) {
782
 
@@ -807,6 +809,8 @@ class Cache extends Sitemaps {
807
  return $this->add_cache_key_suffix( \esc_sql( $type . '_' . $page_id . '_' . $taxonomy ) );
808
  break;
809
  endswitch;
 
 
810
  }
811
 
812
  /**
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
476
  * When the caching mechanism changes. Change this value.
477
  * Use hex. e.g. 0, 1, 2, 9, a, b
478
  */
479
+ $sitemap_revision = '3';
480
  $theme_dir_revision = '0';
481
 
482
  $this->sitemap_transient = $this->is_option_checked( 'cache_sitemap' ) ? $this->add_cache_key_suffix( 'tsf_sitemap_' . $sitemap_revision ) : '';
656
  } elseif ( $this->is_search() ) {
657
  $query = '';
658
 
659
+ //* TODO figure out why this check is here... admin compat maybe?
660
  if ( function_exists( 'get_search_query' ) ) {
661
+ $search_query = \get_search_query( $_escaped = true );
662
 
663
  if ( $search_query )
664
  $query = str_replace( ' ', '', $search_query );
715
  static $unix = null;
716
 
717
  if ( ! isset( $unix ) )
718
+ $unix = time();
719
 
720
  //* Temporarily disable caches to prevent database spam.
721
  $this->the_seo_framework_use_transients = false;
770
  * Use this method if you wish to evade the query usage.
771
  *
772
  * @since 2.9.1
773
+ * @since 2.9.2 Now returns false when an incorrect $type is supplied.
774
  * @staticvar array $cached_id : contains cache strings.
775
  * @see $this->generate_cache_key().
776
  * @see $this->generate_cache_key_by_query() to get cache key from the query.
778
  * @param int|string|bool $page_id the Taxonomy or Post ID.
779
  * @param string $taxonomy The term taxonomy.
780
  * @param string $type The Post Type.
781
+ * @return string|bool String the generated cache key. Bool false on failure.
782
  */
783
  public function generate_cache_key_by_type( $page_id, $taxonomy = '', $type = '' ) {
784
 
809
  return $this->add_cache_key_suffix( \esc_sql( $type . '_' . $page_id . '_' . $taxonomy ) );
810
  break;
811
  endswitch;
812
+
813
+ return false;
814
  }
815
 
816
  /**
inc/classes/compat.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -54,6 +54,8 @@ class Compat extends Core {
54
  * rather than common paths. As they can require manual FTP upload.
55
  *
56
  * @since 2.8.0
 
 
57
  */
58
  protected function load_early_compat_files() {
59
 
@@ -76,7 +78,10 @@ class Compat extends Core {
76
  }
77
  }
78
 
79
- if ( $this->detect_plugin( array( 'constants' => array( 'ICL_LANGUAGE_CODE' ) ) ) ) {
 
 
 
80
  //* WPML
81
  $this->_include_compat( 'wpml', 'plugin' );
82
  } elseif ( $this->detect_plugin( array( 'constants' => array( 'QTX_VERSION' ) ) ) ) {
@@ -92,6 +97,9 @@ class Compat extends Core {
92
  if ( $this->detect_plugin( array( 'functions' => array( 'bbpress' ) ) ) ) {
93
  //* bbPress
94
  $this->_include_compat( 'bbpress', 'plugin' );
 
 
 
95
  }
96
  }
97
 
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
54
  * rather than common paths. As they can require manual FTP upload.
55
  *
56
  * @since 2.8.0
57
+ * @TODO Add transients that will bypass all these checks.
58
+ * Careful, recheck on each activation -- and even FTP deletion.
59
  */
60
  protected function load_early_compat_files() {
61
 
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' ) ) ) ) {
97
  if ( $this->detect_plugin( array( 'functions' => array( 'bbpress' ) ) ) ) {
98
  //* bbPress
99
  $this->_include_compat( 'bbpress', 'plugin' );
100
+ } elseif ( $this->detect_plugin( array( 'constants' => array( 'WPFORO_BASENAME' ) ) ) ) {
101
+ //* wpForo
102
+ $this->_include_compat( 'wpforo', 'plugin' );
103
  }
104
  }
105
 
inc/classes/core.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -137,7 +137,7 @@ class Core {
137
  *
138
  * @return bool True on clear. False otherwise.
139
  */
140
- protected function clean_reponse_header() {
141
 
142
  if ( $level = ob_get_level() ) {
143
  while ( $level ) {
@@ -223,7 +223,7 @@ class Core {
223
  'jetpack-portfolio',
224
  );
225
 
226
- /*
227
  * Applies filters the_seo_framework_supported_post_types : Array The supported post types.
228
  * @since 2.3.1
229
  */
@@ -231,17 +231,19 @@ class Core {
231
 
232
  $types = \wp_parse_args( $defaults, $post_types );
233
 
234
- foreach ( $types as $type )
235
  \add_post_type_support( $type, array( 'autodescription-meta' ) );
236
-
237
  }
238
 
239
  /**
240
  * Adds link from plugins page to SEO Settings page.
241
  *
242
- * @param array $links The current links.
243
- *
244
  * @since 2.2.8
 
 
 
 
245
  */
246
  public function plugin_action_links( $links = array() ) {
247
 
@@ -250,7 +252,17 @@ class Core {
250
  if ( $this->load_options )
251
  $tsf_links['settings'] = '<a href="' . \esc_url( \admin_url( 'admin.php?page=' . $this->seo_settings_page_slug ) ) . '">' . \esc_html__( 'SEO Settings', 'autodescription' ) . '</a>';
252
 
253
- $tsf_links['home'] = '<a href="' . \esc_url( 'https://theseoframework.com/' ) . '" target="_blank">' . \esc_html_x( 'Plugin Home', 'As in: The Plugin Home Page', 'autodescription' ) . '</a>';
 
 
 
 
 
 
 
 
 
 
254
 
255
  return array_merge( $tsf_links, $links );
256
  }
@@ -450,13 +462,7 @@ class Core {
450
  * @return bool Option is checked.
451
  */
452
  public function is_option_checked( $option ) {
453
-
454
- $option = $this->get_option( $option );
455
-
456
- if ( $this->is_checked( $option ) )
457
- return true;
458
-
459
- return false;
460
  }
461
 
462
  /**
@@ -592,7 +598,7 @@ class Core {
592
  //* Try Daylight savings.
593
  $tzstring = timezone_name_from_abbr( '', $seconds, 1 );
594
  /**
595
- * PHP bug workaround.
596
  * @link https://bugs.php.net/bug.php?id=44780
597
  */
598
  if ( false === $tzstring )
@@ -665,9 +671,14 @@ class Core {
665
  * @since 2.7.0
666
  *
667
  * @param string $string Required. The string to count words in.
668
- * @param int $amount Minimum amount of words to encounter in the string. Set to 0 to count all words longer than $bother_length.
669
- * @param int $amount_bother Minimum amount of words to encounter in the string that fall under the $bother_length. Set to 0 to count all words shorter than $bother_length.
670
- * @param int $bother_length The maximum string length of a word to pass for $amount_bother instead of $amount. Set to 0 to pass all words through $amount_bother
 
 
 
 
 
671
  * @return array Containing arrays of words with their count.
672
  */
673
  public function get_word_count( $string, $amount = 3, $amount_bother = 5, $bother_length = 3 ) {
@@ -725,11 +736,12 @@ class Core {
725
  *
726
  * @since 2.8.0
727
  * @since 2.9.0 Now adds a little more relative softness based on rel_lum.
 
728
  *
729
  * @param string $hex The 3 to 6 character RGB hex. '#' prefix is supported.
730
  * @return string The hexadecimal RGB relative font color, without '#' prefix.
731
  */
732
- public function get_relatitve_fontcolor( $hex = '' ) {
733
 
734
  $hex = ltrim( $hex, '#' );
735
 
@@ -893,7 +905,7 @@ class Core {
893
  for ( $i = 0; $i < $count; $i++ ) {
894
  $text = str_replace(
895
  $matches[0][ $i ],
896
- sprintf( '<a href="%s" rel="nofollow">%s</a>', \esc_url( $matches[2][ $i ] ), \esc_html( $matches[1][ $i ] ) ),
897
  $text
898
  );
899
  }
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
137
  *
138
  * @return bool True on clear. False otherwise.
139
  */
140
+ protected function clean_response_header() {
141
 
142
  if ( $level = ob_get_level() ) {
143
  while ( $level ) {
223
  'jetpack-portfolio',
224
  );
225
 
226
+ /**
227
  * Applies filters the_seo_framework_supported_post_types : Array The supported post types.
228
  * @since 2.3.1
229
  */
231
 
232
  $types = \wp_parse_args( $defaults, $post_types );
233
 
234
+ foreach ( $types as $type ) {
235
  \add_post_type_support( $type, array( 'autodescription-meta' ) );
236
+ }
237
  }
238
 
239
  /**
240
  * Adds link from plugins page to SEO Settings page.
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.
247
  */
248
  public function plugin_action_links( $links = array() ) {
249
 
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.
259
+ * But it has minimum to no UX/performance impact on failure.
260
+ */
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 );
268
  }
462
  * @return bool Option is checked.
463
  */
464
  public function is_option_checked( $option ) {
465
+ return $this->is_checked( $this->get_option( $option ) );
 
 
 
 
 
 
466
  }
467
 
468
  /**
598
  //* Try Daylight savings.
599
  $tzstring = timezone_name_from_abbr( '', $seconds, 1 );
600
  /**
601
+ * PHP bug workaround. Disable the DST check.
602
  * @link https://bugs.php.net/bug.php?id=44780
603
  */
604
  if ( false === $tzstring )
671
  * @since 2.7.0
672
  *
673
  * @param string $string Required. The string to count words in.
674
+ * @param int $amount Minimum amount of words to encounter in the string.
675
+ * Set to 0 to count all words longer than $bother_length.
676
+ * @param int $amount_bother Minimum amount of words to encounter in the string
677
+ * that fall under the $bother_length. Set to 0 to count all words
678
+ * shorter than $bother_length.
679
+ * @param int $bother_length The maximum string length of a word to pass for
680
+ * $amount_bother instead of $amount. Set to 0 to pass all words
681
+ * through $amount_bother
682
  * @return array Containing arrays of words with their count.
683
  */
684
  public function get_word_count( $string, $amount = 3, $amount_bother = 5, $bother_length = 3 ) {
736
  *
737
  * @since 2.8.0
738
  * @since 2.9.0 Now adds a little more relative softness based on rel_lum.
739
+ * @since 2.9.2 (Typo): Renamed from 'get_relatitve_fontcolor' to 'get_relative_fontcolor'.
740
  *
741
  * @param string $hex The 3 to 6 character RGB hex. '#' prefix is supported.
742
  * @return string The hexadecimal RGB relative font color, without '#' prefix.
743
  */
744
+ public function get_relative_fontcolor( $hex = '' ) {
745
 
746
  $hex = ltrim( $hex, '#' );
747
 
905
  for ( $i = 0; $i < $count; $i++ ) {
906
  $text = str_replace(
907
  $matches[0][ $i ],
908
+ sprintf( '<a href="%s" rel="nofollow noreferrer noopener">%s</a>', \esc_url( $matches[2][ $i ] ), \esc_html( $matches[1][ $i ] ) ),
909
  $text
910
  );
911
  }
inc/classes/debug.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
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
inc/classes/deprecated.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -247,7 +247,7 @@ final class Deprecated {
247
  * @since 2.7.0 No longer used for performance reasons.
248
  * @uses $this->exclude_search_ids()
249
  * @deprecated
250
- * @since 2.8.0
251
  *
252
  * @param array $query The possible search query.
253
  * @return void Early if no search query is found.
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
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.
inc/classes/detect.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -173,7 +173,7 @@ class Detect extends Render {
173
  *
174
  * @since 1.3.0
175
  * @since 2.8.0 : 1. Can now check for globals.
176
- * 2. Switched order from FAST to SLOW.
177
  *
178
  * @param array $plugins Array of array for constants, classes and / or functions to check for plugin existence.
179
  * @return boolean True if plugin exists or false if plugin constant, class or function not detected.
@@ -231,7 +231,8 @@ class Detect extends Render {
231
  * @staticvar array $cache
232
  * @uses $this->detect_plugin_multi()
233
  *
234
- * @param array $plugins Array of array for constants, classes and / or functions to check for plugin existence.
 
235
  * @param bool $use_cache Bypasses cache if false
236
  */
237
  public function can_i_use( array $plugins = array(), $use_cache = true ) {
@@ -518,6 +519,7 @@ class Detect extends Render {
518
  * @since 2.6.0
519
  * @since 2.8.0 Added check_option parameter.
520
  * @since 2.9.0 Now also checks for subdirectory installations.
 
521
  *
522
  * @param bool $check_option Whether to check for sitemap option.
523
  * @return bool True when no conflicting plugins are detected or when The SEO Framework's Sitemaps are output.
@@ -541,6 +543,9 @@ class Detect extends Render {
541
  if ( $this->is_subdirectory_installation() )
542
  return false;
543
 
 
 
 
544
  return true;
545
  }
546
 
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
173
  *
174
  * @since 1.3.0
175
  * @since 2.8.0 : 1. Can now check for globals.
176
+ * 2. Switched detection order from FAST to SLOW.
177
  *
178
  * @param array $plugins Array of array for constants, classes and / or functions to check for plugin existence.
179
  * @return boolean True if plugin exists or false if plugin constant, class or function not detected.
231
  * @staticvar array $cache
232
  * @uses $this->detect_plugin_multi()
233
  *
234
+ * @param array $plugins Array of array for globals, constants, classes
235
+ * and/or functions to check for plugin existence.
236
  * @param bool $use_cache Bypasses cache if false
237
  */
238
  public function can_i_use( array $plugins = array(), $use_cache = true ) {
519
  * @since 2.6.0
520
  * @since 2.8.0 Added check_option parameter.
521
  * @since 2.9.0 Now also checks for subdirectory installations.
522
+ * @since 2.9.2 Now also checks for permalinks.
523
  *
524
  * @param bool $check_option Whether to check for sitemap option.
525
  * @return bool True when no conflicting plugins are detected or when The SEO Framework's Sitemaps are output.
543
  if ( $this->is_subdirectory_installation() )
544
  return false;
545
 
546
+ if ( ! $this->pretty_permalinks )
547
+ return false;
548
+
549
  return true;
550
  }
551
 
inc/classes/doing-it-right.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -1048,10 +1048,10 @@ class Doing_It_Right extends Generate_Ldjson {
1048
  */
1049
  $desc_value = ctype_upper( $desc_value ) ? $desc_value : ucfirst( $desc_value );
1050
 
1051
- /* translators: 1: Word, 2: Occurences */
1052
  $notice .= sprintf( \esc_attr__( '%1$s is used %2$d times.', 'autodescription' ), '<span>' . $desc_value . '</span>', $desc_count );
1053
 
1054
- //* Don't add break at last occurence.
1055
  $notice .= $i === $count ? '' : '<br>';
1056
  $i++;
1057
  }
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
1048
  */
1049
  $desc_value = ctype_upper( $desc_value ) ? $desc_value : ucfirst( $desc_value );
1050
 
1051
+ /* translators: 1: Word, 2: Occurrences */
1052
  $notice .= sprintf( \esc_attr__( '%1$s is used %2$d times.', 'autodescription' ), '<span>' . $desc_value . '</span>', $desc_count );
1053
 
1054
+ //* Don't add break at last occurrence.
1055
  $notice .= $i === $count ? '' : '<br>';
1056
  $i++;
1057
  }
inc/classes/feed.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
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
inc/classes/generate-description.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -166,14 +166,15 @@ class Generate_Description extends Generate {
166
  /**
167
  * Reparses description args.
168
  *
169
- * @param array $args required The passed arguments.
170
- *
171
  * @since 2.6.0
 
 
 
172
  * @return array $args parsed args.
173
  */
174
  public function reparse_description_args( $args = array() ) {
175
 
176
- $default_args = $this->parse_description_args( '', '', true );
177
 
178
  if ( is_array( $args ) ) {
179
  if ( empty( $args ) ) {
@@ -651,6 +652,7 @@ class Generate_Description extends Generate {
651
  * Generates description additions.
652
  *
653
  * @since 2.6.0
 
654
  * @staticvar array $title string of titles.
655
  * @staticvar string $on
656
  * @access private
@@ -699,12 +701,38 @@ class Generate_Description extends Generate {
699
  $sep = '';
700
  }
701
 
702
- return array(
703
- 'title' => $title[ $id ],
704
- 'on' => $on,
705
- 'blogname' => $blogname,
706
- 'sep' => $sep,
707
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
  }
709
 
710
  /**
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
166
  /**
167
  * Reparses description args.
168
  *
 
 
169
  * @since 2.6.0
170
+ * @since 2.9.2 Now passes args to filter.
171
+ *
172
+ * @param array $args required The passed arguments.
173
  * @return array $args parsed args.
174
  */
175
  public function reparse_description_args( $args = array() ) {
176
 
177
+ $default_args = $this->parse_description_args( $args, '', true );
178
 
179
  if ( is_array( $args ) ) {
180
  if ( empty( $args ) ) {
652
  * Generates description additions.
653
  *
654
  * @since 2.6.0
655
+ * @since 2.9.2 Added filter.
656
  * @staticvar array $title string of titles.
657
  * @staticvar string $on
658
  * @access private
701
  $sep = '';
702
  }
703
 
704
+ if ( \has_filter( 'the_seo_framework_generated_description_additions' ) ) {
705
+ /**
706
+ * Applies filters 'the_seo_framework_generated_description_additions'
707
+ *
708
+ * @since 2.9.2
709
+ *
710
+ * @param array $data The description data.
711
+ * @param int $id The object ID.
712
+ * @param mixed $term The term object, or empty (falsy).
713
+ * @param bool $ignore Whether the settings have been ignored.
714
+ */
715
+ $data = \apply_filters_ref_array( 'the_seo_framework_generated_description_additions', array(
716
+ array(
717
+ 'title' => $title[ $id ],
718
+ 'on' => $on,
719
+ 'blogname' => $blogname,
720
+ 'sep' => $sep,
721
+ ),
722
+ $id,
723
+ $term,
724
+ $ignore,
725
+ ) );
726
+ } else {
727
+ $data = array(
728
+ 'title' => $title[ $id ],
729
+ 'on' => $on,
730
+ 'blogname' => $blogname,
731
+ 'sep' => $sep,
732
+ );
733
+ }
734
+
735
+ return $data;
736
  }
737
 
738
  /**
inc/classes/generate-image.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -221,13 +221,14 @@ class Generate_Image extends Generate_Url {
221
  * Reparses image args.
222
  *
223
  * @since 2.6.6
 
224
  *
225
  * @param array $args required The passed arguments.
226
  * @return array $args parsed args.
227
  */
228
  public function reparse_image_args( $args = array() ) {
229
 
230
- $default_args = $this->parse_image_args( '', '', true );
231
 
232
  if ( empty( $args ) ) {
233
  $args = $default_args;
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
221
  * Reparses image args.
222
  *
223
  * @since 2.6.6
224
+ * @since 2.9.2 Now passes args to filter.
225
  *
226
  * @param array $args required The passed arguments.
227
  * @return array $args parsed args.
228
  */
229
  public function reparse_image_args( $args = array() ) {
230
 
231
+ $default_args = $this->parse_image_args( $args, '', true );
232
 
233
  if ( empty( $args ) ) {
234
  $args = $default_args;
inc/classes/generate-ldjson.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -924,6 +924,7 @@ class Generate_Ldjson extends Generate_Image {
924
  * Return LD+Json Knowledge Graph helper.
925
  *
926
  * @since 2.2.8
 
927
  *
928
  * @return string LD+json Knowledge Graph helper.
929
  */
@@ -943,7 +944,7 @@ class Generate_Ldjson extends Generate_Image {
943
  $context = $this->schema_context();
944
  $type = json_encode( ucfirst( $knowledge_type ) );
945
  $name = json_encode( $knowledge_name );
946
- $url = json_encode( \esc_url( \home_url( '/' ) ) );
947
 
948
  $logo = '';
949
 
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
924
  * Return LD+Json Knowledge Graph helper.
925
  *
926
  * @since 2.2.8
927
+ * @since 2.9.2 : Now grabs home URL from cache.
928
  *
929
  * @return string LD+json Knowledge Graph helper.
930
  */
944
  $context = $this->schema_context();
945
  $type = json_encode( ucfirst( $knowledge_type ) );
946
  $name = json_encode( $knowledge_name );
947
+ $url = $this->schema_home_url();
948
 
949
  $logo = '';
950
 
inc/classes/generate-title.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -191,13 +191,14 @@ class Generate_Title extends Generate_Description {
191
  * Reparses title args.
192
  *
193
  * @since 2.6.0
 
194
  *
195
  * @param array $args required The passed arguments.
196
  * @return array $args parsed args.
197
  */
198
  public function reparse_title_args( $args = array() ) {
199
 
200
- $default_args = $this->parse_title_args( '', '', true );
201
 
202
  if ( is_array( $args ) ) {
203
  if ( empty( $args ) ) {
@@ -785,9 +786,11 @@ class Generate_Title extends Generate_Description {
785
 
786
  /**
787
  * Gets the archive Title, including filter. Also works in admin.
 
788
  * @NOTE Taken from WordPress core. Altered to work in the Admin area.
789
  *
790
  * @since 2.6.0
 
791
  *
792
  * @param object $term The Term object.
793
  * @param array $args The Title arguments.
@@ -822,7 +825,7 @@ class Generate_Title extends Generate_Description {
822
  $title = $use_prefix ? sprintf( \__( '%1$s: %2$s', 'autodescription' ), $this->get_the_term_name( $term ), $title ) : $title;
823
  } elseif ( $this->is_author() ) {
824
  $title = \get_the_author();
825
- /* translators: Front-end output. */
826
  $title = $use_prefix ? sprintf( \__( 'Author: %s', 'autodescription' ), $title ) : $title;
827
  } elseif ( $this->is_date() ) {
828
  if ( $this->is_year() ) {
@@ -886,7 +889,14 @@ class Generate_Title extends Generate_Description {
886
  $title = \__( 'Archives', 'autodescription' );
887
  }
888
 
889
- return $title;
 
 
 
 
 
 
 
890
  }
891
 
892
  /**
@@ -1268,9 +1278,9 @@ class Generate_Title extends Generate_Description {
1268
 
1269
  /**
1270
  * Applies filters the_seo_framework_use_archive_title_prefix : {
1271
- * @param bool true to add prefix.
1272
- * @param object $term The Term object.
1273
- * }
1274
  *
1275
  * @since 2.6.0
1276
  */
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
191
  * Reparses title args.
192
  *
193
  * @since 2.6.0
194
+ * @since 2.9.2 Now passes args to filter.
195
  *
196
  * @param array $args required The passed arguments.
197
  * @return array $args parsed args.
198
  */
199
  public function reparse_title_args( $args = array() ) {
200
 
201
+ $default_args = $this->parse_title_args( $args, '', true );
202
 
203
  if ( is_array( $args ) ) {
204
  if ( empty( $args ) ) {
786
 
787
  /**
788
  * Gets the archive Title, including filter. Also works in admin.
789
+ *
790
  * @NOTE Taken from WordPress core. Altered to work in the Admin area.
791
  *
792
  * @since 2.6.0
793
+ * @since 2.9.2 : Added WordPress core filter 'get_the_archive_title'
794
  *
795
  * @param object $term The Term object.
796
  * @param array $args The Title arguments.
825
  $title = $use_prefix ? sprintf( \__( '%1$s: %2$s', 'autodescription' ), $this->get_the_term_name( $term ), $title ) : $title;
826
  } elseif ( $this->is_author() ) {
827
  $title = \get_the_author();
828
+ /* translators: Front-end output. */
829
  $title = $use_prefix ? sprintf( \__( 'Author: %s', 'autodescription' ), $title ) : $title;
830
  } elseif ( $this->is_date() ) {
831
  if ( $this->is_year() ) {
889
  $title = \__( 'Archives', 'autodescription' );
890
  }
891
 
892
+ /**
893
+ * Filters the archive title.
894
+ *
895
+ * @since WordPress Core 4.1.0
896
+ *
897
+ * @param string $title Archive title to be displayed.
898
+ */
899
+ return \apply_filters( 'get_the_archive_title', $title );
900
  }
901
 
902
  /**
1278
 
1279
  /**
1280
  * Applies filters the_seo_framework_use_archive_title_prefix : {
1281
+ * @param bool true to add prefix.
1282
+ * @param object $term The Term object.
1283
+ * }
1284
  *
1285
  * @since 2.6.0
1286
  */
inc/classes/generate-url.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -66,6 +66,8 @@ class Generate_Url extends Generate_Title {
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
  *
70
  * @param string $url the url
71
  * @param array $args : accepted args : {
@@ -126,32 +128,43 @@ class Generate_Url extends Generate_Title {
126
  $path = $this->get_home_path();
127
  }
128
 
129
- /**
130
- * Applies filters 'the_seo_framework_url_path' : array
131
- *
132
- * @since 2.8.0
133
- *
134
- * @param string $path the URL path.
135
- * @param int $id The current post, page or term ID.
136
- * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
137
- */
138
- $path = (string) \apply_filters( 'the_seo_framework_url_path', $path, $args['id'], $args['external'] );
139
 
140
- /**
141
- * Applies filters 'the_seo_framework_sanitize_redirect_url' : array
142
- *
143
- * @since 2.8.0
144
- *
145
- * @param array : { 'url' => The full URL built from $path, 'scheme' => The preferred scheme }
146
- * @param string $path the URL path.
147
- * @param int $id The current post, page or term ID.
148
- * @param bool $external Whether the call is made from outside the current ID scope. Like from the Sitemap.
149
- */
150
- $url_filter = (array) \apply_filters( 'the_seo_framework_url_output_args', array(), $path, $args['id'], $args['external'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
 
152
- if ( $url_filter ) {
153
- $url = $url_filter['url'];
154
- $scheme = $url_filter['scheme'];
 
155
  }
156
 
157
  //* Non-custom URL
@@ -194,6 +207,8 @@ class Generate_Url extends Generate_Title {
194
  * Parse and sanitize url args.
195
  *
196
  * @since 2.4.2
 
 
197
  *
198
  * @param array $args required The passed arguments.
199
  * @param array $defaults The default arguments.
@@ -203,7 +218,7 @@ class Generate_Url extends Generate_Title {
203
  public function parse_url_args( $args = array(), $defaults = array(), $get_defaults = false ) {
204
 
205
  //* Passing back the defaults reduces the memory usage.
206
- if ( empty( $defaults ) ) {
207
  $defaults = array(
208
  'paged' => false,
209
  'paged_plural' => true,
@@ -217,27 +232,33 @@ class Generate_Url extends Generate_Title {
217
  'id' => $this->get_the_real_ID(),
218
  );
219
 
220
- /**
221
- * @applies filters the_seo_framework_url_args : {
222
- * @param bool $paged Return current page URL without pagination if false
223
- * @param bool $paged_plural Whether to add pagination for the second or later page.
224
- * @param bool $from_option Get the canonical uri option
225
- * @param object $post The Post Object.
226
- * @param bool $external Whether to fetch the current WP Request or get the permalink by Post Object.
227
- * @param bool $is_term Fetch url for term.
228
- * @param object $term The term object.
229
- * @param bool $home Fetch home URL.
230
- * @param bool $forceslash Fetch home URL and slash it, always.
231
- * @param int $id The Page or Term ID.
232
- * }
233
- *
234
- * @since 2.5.0
235
- *
236
- * @param array $defaults The url defaults.
237
- * @param array $args The input args.
238
- */
239
- $defaults = (array) \apply_filters( 'the_seo_framework_url_args', $defaults, $args );
240
- }
 
 
 
 
 
 
241
 
242
  //* Return early if it's only a default args request.
243
  if ( $get_defaults )
@@ -261,14 +282,15 @@ class Generate_Url extends Generate_Title {
261
  /**
262
  * Reparse URL args.
263
  *
264
- * @param array $args required The passed arguments.
265
- *
266
  * @since 2.6.2
 
 
 
267
  * @return array $args parsed args.
268
  */
269
  public function reparse_url_args( $args = array() ) {
270
 
271
- $default_args = $this->parse_url_args( '', '', true );
272
 
273
  if ( is_array( $args ) ) {
274
  if ( empty( $args ) ) {
@@ -311,8 +333,8 @@ class Generate_Url extends Generate_Title {
311
  $path = $this->get_relative_term_url( $term, $args );
312
  } elseif ( ! $args['external'] && isset( $GLOBALS['wp']->request ) ) {
313
  //* Everything else.
314
- $path = \trailingslashit( \get_option( 'home' ) ) . $GLOBALS['wp']->request;
315
- $path = $this->set_url_scheme( $path, 'relative' );
316
  } else {
317
  //* Nothing to see here...
318
  $path = '';
@@ -369,7 +391,7 @@ class Generate_Url extends Generate_Title {
369
  $url = \get_home_url();
370
  } elseif ( ! $args['external'] ) {
371
  if ( isset( $GLOBALS['wp']->request ) )
372
- $url = \trailingslashit( \get_option( 'home' ) ) . $GLOBALS['wp']->request;
373
  }
374
 
375
  //* No permalink found.
@@ -521,7 +543,9 @@ class Generate_Url extends Generate_Title {
521
  * Can be automatically be detected.
522
  *
523
  * @since 2.8.0
 
524
  * @staticvar string $scheme
 
525
  *
526
  * @return string The preferred URl scheme.
527
  */
@@ -547,14 +571,23 @@ class Generate_Url extends Generate_Title {
547
  break;
548
  endswitch;
549
 
550
- /**
551
- * Applies filters 'the_seo_framework_preferred_url_scheme' : string
552
- *
553
- * @since 2.8.0
554
- *
555
- * @param string $scheme The current URL scheme.
556
- */
557
- return $scheme = (string) \apply_filters( 'the_seo_framework_preferred_url_scheme', $scheme );
 
 
 
 
 
 
 
 
 
558
  }
559
 
560
  /**
@@ -613,6 +646,8 @@ class Generate_Url extends Generate_Title {
613
  *
614
  * @since 2.6.0
615
  * @since 2.8.0 Deprecated.
 
 
616
  * @deprecated
617
  *
618
  * @param string $url The url with scheme.
@@ -621,36 +656,41 @@ class Generate_Url extends Generate_Title {
621
  */
622
  public function set_url_scheme_filter( $url, $current_scheme ) {
623
 
624
- /**
625
- * Applies filters the_seo_framework_canonical_force_scheme : Changes scheme.
626
- *
627
- * Accepted variables:
628
- * (string) 'https' : Force https
629
- * (bool) true : Force https
630
- * (bool) false : Force http
631
- * (string) 'http' : Force http
632
- * (string) 'relative' : Scheme relative
633
- * (void) null : Do nothing
634
- *
635
- *
636
- * @since 2.4.2
637
- * @since 2.8.0 Deprecated.
638
- * @deprecated
639
- *
640
- * @param string $current_scheme the current used scheme.
641
- */
642
- $scheme_settings = \apply_filters( 'the_seo_framework_canonical_force_scheme', null, $current_scheme );
643
 
644
- if ( isset( $scheme_settings ) ) {
645
 
646
  $this->_deprecated_filter( 'the_seo_framework_canonical_force_scheme', '2.8.0', 'the_seo_framework_preferred_url_scheme' );
647
 
648
- if ( 'https' === $scheme_settings || 'http' === $scheme_settings || 'relative' === $scheme_settings ) {
649
- $url = $this->set_url_scheme( $url, $scheme_settings, false );
650
- } elseif ( ! $scheme_settings ) {
651
- $url = $this->set_url_scheme( $url, 'http', false );
652
- } elseif ( $scheme_setting ) {
653
- $url = $this->set_url_scheme( $url, 'https', false );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
654
  }
655
  }
656
 
@@ -783,17 +823,16 @@ class Generate_Url extends Generate_Title {
783
  $prev = '';
784
  $next = '';
785
 
786
- if ( $this->is_singular() ) {
787
  if ( $this->is_real_front_page() || $this->is_front_page_by_id( $post_id ) ) {
788
  $output_singular_paged = $this->is_option_checked( 'prev_next_frontpage' );
789
  } else {
790
  $output_singular_paged = $this->is_option_checked( 'prev_next_posts' );
791
  }
792
 
793
- if ( $output_singular_paged ) {
794
 
795
  $page = $this->page();
796
- $numpages = substr_count( $this->get_post_content( $post_id ), '<!--nextpage-->' ) + 1;
797
 
798
  if ( ! $page )
799
  $page = 1;
@@ -801,10 +840,11 @@ class Generate_Url extends Generate_Title {
801
  if ( 'prev' === $prev_next ) {
802
  $prev = $page > 1 ? $this->get_paged_post_url( $page - 1, $post_id, 'prev' ) : '';
803
  } elseif ( 'next' === $prev_next ) {
804
- $next = $page < $numpages ? $this->get_paged_post_url( $page + 1, $post_id, 'next' ) : '';
 
805
  }
806
- }
807
- } elseif ( $this->is_archive() || $this->is_home() ) {
808
 
809
  $output_archive_paged = false;
810
  if ( $this->is_real_front_page() || $this->is_front_page_by_id( $post_id ) ) {
@@ -834,7 +874,7 @@ class Generate_Url extends Generate_Title {
834
  $next = \get_pagenum_link( $paged, false );
835
  }
836
  }
837
- }
838
 
839
  if ( $prev )
840
  return $this->set_preferred_url_scheme( \esc_url_raw( $prev ) );
@@ -881,17 +921,16 @@ class Generate_Url extends Generate_Title {
881
  if ( isset( $query_arg ) )
882
  $urlfromcache = str_replace( '?' . $query_arg, '', $urlfromcache );
883
 
884
- // Calculate current page number.
885
- $current = 'next' === $pos ? ( $i - 1 ) : ( $i + 1 );
886
- $current = (string) $current;
887
-
888
  //* Continue if still bigger than or equal to 2.
889
  if ( $i >= 2 ) {
 
 
 
890
  //* We're adding a page.
891
- $last_occurence = strrpos( $urlfromcache, '/' . $current . '/' );
892
 
893
- if ( false !== $last_occurence )
894
- $urlfromcache = substr_replace( $urlfromcache, '/', $last_occurence, strlen( '/' . $current . '/' ) );
895
  }
896
  }
897
 
@@ -1017,11 +1056,11 @@ class Generate_Url extends Generate_Title {
1017
  *
1018
  * @since 2.6.0
1019
  *
1020
- * @param int $paged
1021
  * @param bool $singular Whether to allow plural and singular.
1022
  * @param bool $plural Whether to allow plural regardless.
1023
  *
1024
- * @return int|bool $paged. False if not allowed. Int if allowed.
1025
  */
1026
  protected function maybe_get_paged( $paged = 0, $singular = false, $plural = true ) {
1027
 
@@ -1061,6 +1100,8 @@ class Generate_Url extends Generate_Title {
1061
  * If this fails, you're going to have a bad time.
1062
  *
1063
  * @since 2.7.0
 
 
1064
  * @staticvar string $cache
1065
  *
1066
  * @return string The home URL host.
@@ -1072,10 +1113,13 @@ class Generate_Url extends Generate_Title {
1072
  if ( isset( $cache ) )
1073
  return $cache;
1074
 
1075
- $parsed_url = \wp_parse_url( \get_option( 'home' ) );
1076
 
1077
  $host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : '';
1078
 
 
 
 
1079
  return $cache = $host;
1080
  }
1081
 
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
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 : {
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
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.
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,
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 )
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 ) ) {
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 = '';
391
  $url = \get_home_url();
392
  } elseif ( ! $args['external'] ) {
393
  if ( isset( $GLOBALS['wp']->request ) )
394
+ $url = \trailingslashit( \get_home_url() ) . $GLOBALS['wp']->request;
395
  }
396
 
397
  //* No permalink found.
543
  * Can be automatically be detected.
544
  *
545
  * @since 2.8.0
546
+ * @since 2.9.2 Added filter usage cache.
547
  * @staticvar string $scheme
548
+ * @staticvar bool $_has_filter
549
  *
550
  * @return string The preferred URl scheme.
551
  */
571
  break;
572
  endswitch;
573
 
574
+ static $_has_filter = null;
575
+
576
+ if ( null === $_has_filter )
577
+ $_has_filter = \has_filter( 'the_seo_framework_preferred_url_scheme' );
578
+
579
+ if ( $_has_filter ) {
580
+ /**
581
+ * Applies filters 'the_seo_framework_preferred_url_scheme' : string
582
+ *
583
+ * @since 2.8.0
584
+ *
585
+ * @param string $scheme The current URL scheme.
586
+ */
587
+ $scheme = (string) \apply_filters( 'the_seo_framework_preferred_url_scheme', $scheme );
588
+ }
589
+
590
+ return $scheme;
591
  }
592
 
593
  /**
646
  *
647
  * @since 2.6.0
648
  * @since 2.8.0 Deprecated.
649
+ * @since 2.9.2 Added filter usage cache.
650
+ * @staticvar $_has_filter;
651
  * @deprecated
652
  *
653
  * @param string $url The url with scheme.
656
  */
657
  public function set_url_scheme_filter( $url, $current_scheme ) {
658
 
659
+ static $_has_filter = null;
660
+ if ( null === $_has_filter )
661
+ $_has_filter = \has_filter( 'the_seo_framework_canonical_force_scheme' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662
 
663
+ if ( $_has_filter ) {
664
 
665
  $this->_deprecated_filter( 'the_seo_framework_canonical_force_scheme', '2.8.0', 'the_seo_framework_preferred_url_scheme' );
666
 
667
+ /**
668
+ * Applies filters the_seo_framework_canonical_force_scheme : Changes scheme.
669
+ *
670
+ * Accepted variables:
671
+ * (string) 'https' : Force https
672
+ * (bool) true : Force https
673
+ * (bool) false : Force http
674
+ * (string) 'http' : Force http
675
+ * (string) 'relative' : Scheme relative
676
+ * (void) null : Do nothing
677
+ *
678
+ * @since 2.4.2
679
+ * @since 2.8.0 Deprecated.
680
+ * @deprecated
681
+ *
682
+ * @param string $current_scheme the current used scheme.
683
+ */
684
+ $scheme_settings = \apply_filters( 'the_seo_framework_canonical_force_scheme', null, $current_scheme );
685
+
686
+ if ( null !== $scheme_settings ) {
687
+ if ( 'https' === $scheme_settings || 'http' === $scheme_settings || 'relative' === $scheme_settings ) {
688
+ $url = $this->set_url_scheme( $url, $scheme_settings, false );
689
+ } elseif ( ! $scheme_settings ) {
690
+ $url = $this->set_url_scheme( $url, 'http', false );
691
+ } elseif ( $scheme_setting ) {
692
+ $url = $this->set_url_scheme( $url, 'https', false );
693
+ }
694
  }
695
  }
696
 
823
  $prev = '';
824
  $next = '';
825
 
826
+ if ( $this->is_singular() ) :
827
  if ( $this->is_real_front_page() || $this->is_front_page_by_id( $post_id ) ) {
828
  $output_singular_paged = $this->is_option_checked( 'prev_next_frontpage' );
829
  } else {
830
  $output_singular_paged = $this->is_option_checked( 'prev_next_posts' );
831
  }
832
 
833
+ if ( $output_singular_paged ) :
834
 
835
  $page = $this->page();
 
836
 
837
  if ( ! $page )
838
  $page = 1;
840
  if ( 'prev' === $prev_next ) {
841
  $prev = $page > 1 ? $this->get_paged_post_url( $page - 1, $post_id, 'prev' ) : '';
842
  } elseif ( 'next' === $prev_next ) {
843
+ $_numpages = substr_count( $this->get_post_content( $post_id ), '<!--nextpage-->' ) + 1;
844
+ $next = $page < $_numpages ? $this->get_paged_post_url( $page + 1, $post_id, 'next' ) : '';
845
  }
846
+ endif;
847
+ elseif ( $this->is_archive() || $this->is_home() ) :
848
 
849
  $output_archive_paged = false;
850
  if ( $this->is_real_front_page() || $this->is_front_page_by_id( $post_id ) ) {
874
  $next = \get_pagenum_link( $paged, false );
875
  }
876
  }
877
+ endif;
878
 
879
  if ( $prev )
880
  return $this->set_preferred_url_scheme( \esc_url_raw( $prev ) );
921
  if ( isset( $query_arg ) )
922
  $urlfromcache = str_replace( '?' . $query_arg, '', $urlfromcache );
923
 
 
 
 
 
924
  //* Continue if still bigger than or equal to 2.
925
  if ( $i >= 2 ) {
926
+ // Calculate current page number.
927
+ $_current = 'next' === $pos ? (string) ( $i - 1 ) : (string) ( $i + 1 );
928
+
929
  //* We're adding a page.
930
+ $_last_occurrence = strrpos( $urlfromcache, '/' . $_current . '/' );
931
 
932
+ if ( false !== $_last_occurrence )
933
+ $urlfromcache = substr_replace( $urlfromcache, '/', $_last_occurrence, strlen( '/' . $_current . '/' ) );
934
  }
935
  }
936
 
1056
  *
1057
  * @since 2.6.0
1058
  *
1059
+ * @param int $paged The current page number.
1060
  * @param bool $singular Whether to allow plural and singular.
1061
  * @param bool $plural Whether to allow plural regardless.
1062
  *
1063
+ * @return int|bool $paged. False if not allowed or on page 0. int if allowed.
1064
  */
1065
  protected function maybe_get_paged( $paged = 0, $singular = false, $plural = true ) {
1066
 
1100
  * If this fails, you're going to have a bad time.
1101
  *
1102
  * @since 2.7.0
1103
+ * @since 2.9.2 : Now considers port too.
1104
+ * : Now uses get_home_url(), rather than get_option('home').
1105
  * @staticvar string $cache
1106
  *
1107
  * @return string The home URL host.
1113
  if ( isset( $cache ) )
1114
  return $cache;
1115
 
1116
+ $parsed_url = \wp_parse_url( \get_home_url() );
1117
 
1118
  $host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : '';
1119
 
1120
+ if ( $host && isset( $parsed_url['port'] ) )
1121
+ $host .= ':' . $parsed_url['port'];
1122
+
1123
  return $cache = $host;
1124
  }
1125
 
inc/classes/generate.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
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
inc/classes/init.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -317,7 +317,7 @@ class Init extends Query {
317
  /**
318
  * @since 2.2.6
319
  *
320
- * Applies filters 'the_seo_framework_before_output' : array after functions output
321
  * Applies filters 'the_seo_framework_after_output' : array after functions output
322
  * @param array $functions {
323
  * 'callback' => string|array The function to call.
@@ -355,7 +355,7 @@ class Init extends Query {
355
  * Start the timer here. I know it doesn't calculate the initiation of
356
  * the plugin, but it will make the code smelly if I were to do so.
357
  * A static array cache counter function would make it possible, but meh.
358
- * This function takes the most time anyway.
359
  */
360
  $init_start = microtime( true );
361
 
@@ -439,60 +439,19 @@ class Init extends Query {
439
  $generator = (string) \apply_filters( 'the_seo_framework_generator_tag', '' );
440
 
441
  if ( $generator )
442
- $generator = '<meta name="generator" content="' . \esc_attr( $generator ) . '" />' . "\r\n";
443
 
444
  $output = $robots . $before . $before_actions . $output . $after_actions . $after . $generator;
445
 
446
  $this->use_object_cache and $this->object_cache_set( $cache_key, $output, DAY_IN_SECONDS );
447
  endif;
448
 
449
- /**
450
- * Applies filters 'the_seo_framework_indicator' : Boolean
451
- * Whether to show the indicator in HTML.
452
- * @since 2.0.0
453
- */
454
- $indicator = (bool) \apply_filters( 'the_seo_framework_indicator', true );
455
-
456
- $indicatorbefore = '';
457
- $indicatorafter = '';
458
-
459
- if ( $indicator ) :
460
-
461
- /**
462
- * Applies filters 'the_seo_framework_indicator_timing' : Boolean
463
- * Whether to show the hidden generation time in HTML.
464
- * @since 2.4.0
465
- */
466
- $timer = (bool) \apply_filters( 'the_seo_framework_indicator_timing', true );
467
-
468
- /**
469
- * Applies filters 'sybre_waaijer_<3' : Boolean
470
- * Whether to show the hidden author name in HTML.
471
- * @since 2.4.0
472
- */
473
- $sybre = (bool) \apply_filters( 'sybre_waaijer_<3', true );
474
-
475
- $start = \esc_html__( 'Start The SEO Framework', 'autodescription' );
476
- $end = \esc_html__( 'End The SEO Framework', 'autodescription' );
477
- $me = $sybre ? ' ' . \esc_html__( 'by Sybre Waaijer', 'autodescription' ) : '';
478
-
479
- $indicatorbefore = '<!-- ' . $start . $me . ' -->' . "\r\n";
480
-
481
- /**
482
- * Calculate the plugin load time.
483
- * @since 2.4.0
484
- */
485
- if ( $timer ) {
486
- $indicatorafter = '<!-- ' . $end . $me . ' | ' . number_format( microtime( true ) - $init_start, 5 ) . 's' . ' -->' . "\r\n";
487
- } else {
488
- $indicatorafter = '<!-- ' . $end . $me . ' -->' . "\r\n";
489
- }
490
- endif;
491
-
492
- $output = "\r\n" . $indicatorbefore . $output . $indicatorafter . "\r\n";
493
 
494
  //* Already escaped.
495
- echo $output;
496
 
497
  \do_action( 'the_seo_framework_do_after_output' );
498
 
@@ -563,6 +522,11 @@ class Init extends Query {
563
  * Edits the robots.txt output.
564
  * Requires not to have a robots.txt file in the root directory.
565
  *
 
 
 
 
 
566
  * @since 2.2.9
567
  * @uses robots_txt filter located at WP core
568
  *
@@ -573,7 +537,7 @@ class Init extends Query {
573
  public function robots_txt( $robots_txt = '', $public = '' ) {
574
 
575
  /**
576
- * Don't do anything if the blog isn't public
577
  */
578
  if ( '0' === $public )
579
  return $robots_txt;
@@ -588,6 +552,15 @@ class Init extends Query {
588
  if ( false === $output ) :
589
  $output = '';
590
 
 
 
 
 
 
 
 
 
 
591
  /**
592
  * Apply filters the_seo_framework_robots_txt_pre & the_seo_framework_robots_txt_pro : string
593
  * Adds custom cacheable lines.
@@ -599,36 +572,28 @@ class Init extends Query {
599
  $pro = (string) \apply_filters( 'the_seo_framework_robots_txt_pro', '' );
600
 
601
  $site_url = \wp_parse_url( \site_url() );
602
- $path = ( ! empty( $site_url['path'] ) ) ? $site_url['path'] : '';
603
 
604
  $output .= $pre;
605
  //* Output defaults
606
  $output .= "User-agent: *\r\n";
607
- $output .= "Disallow: $path/wp-admin/\r\n";
608
- $output .= "Allow: $path/wp-admin/admin-ajax.php\r\n";
609
 
610
  /**
611
- * Prevents query indexing
612
- * @since 2.2.9
613
- *
614
- * Applies filters the_seo_framework_robots_disallow_queries : Whether to allow queries for robots.
615
  * @since 2.5.0
616
  */
617
  if ( \apply_filters( 'the_seo_framework_robots_disallow_queries', false ) ) {
618
- $home_url = \wp_parse_url( rtrim( $this->the_home_url_from_cache(), ' /\\' ) );
619
- $home_path = ( ! empty( $home_url['path'] ) ) ? $home_url['path'] : '';
620
  $output .= "Disallow: $home_path/*?*\r\n";
621
  }
622
 
623
  $output .= $pro;
624
 
625
- if ( $this->get_option( 'sitemaps_robots' ) && $this->can_do_sitemap_robots() ) {
626
- //* Add whitespace before sitemap.
627
- $output .= "\r\n";
628
-
629
- //* Add sitemap full url
630
- $output .= 'Sitemap: ' . $this->the_home_url_from_cache( true ) . "sitemap.xml\r\n";
631
- }
632
 
633
  $this->use_object_cache and $this->object_cache_set( $cache_key, $output, 86400 );
634
  endif;
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
317
  /**
318
  * @since 2.2.6
319
  *
320
+ * Applies filters 'the_seo_framework_before_output' : array before functions output
321
  * Applies filters 'the_seo_framework_after_output' : array after functions output
322
  * @param array $functions {
323
  * 'callback' => string|array The function to call.
355
  * Start the timer here. I know it doesn't calculate the initiation of
356
  * the plugin, but it will make the code smelly if I were to do so.
357
  * A static array cache counter function would make it possible, but meh.
358
+ * This function presumably takes the most time anyway.
359
  */
360
  $init_start = microtime( true );
361
 
439
  $generator = (string) \apply_filters( 'the_seo_framework_generator_tag', '' );
440
 
441
  if ( $generator )
442
+ $generator = '<meta name="generator" content="' . \esc_attr( $generator ) . '" />' . PHP_EOL;
443
 
444
  $output = $robots . $before . $before_actions . $output . $after_actions . $after . $generator;
445
 
446
  $this->use_object_cache and $this->object_cache_set( $cache_key, $output, DAY_IN_SECONDS );
447
  endif;
448
 
449
+ $output = $this->get_plugin_indicator( 'before' )
450
+ . $output
451
+ . $this->get_plugin_indicator( 'after', $init_start );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
452
 
453
  //* Already escaped.
454
+ echo "\r\n" . $output . "\r\n";
455
 
456
  \do_action( 'the_seo_framework_do_after_output' );
457
 
522
  * Edits the robots.txt output.
523
  * Requires not to have a robots.txt file in the root directory.
524
  *
525
+ * This methods completely hijacks default output, intentionally.
526
+ * The robots.txt file should be left as default, so to improve SEO.
527
+ * The Robots Exclusion Protocol encourages you not to use this file for
528
+ * non-administrative endpoints.
529
+ *
530
  * @since 2.2.9
531
  * @uses robots_txt filter located at WP core
532
  *
537
  public function robots_txt( $robots_txt = '', $public = '' ) {
538
 
539
  /**
540
+ * Don't do anything if the blog isn't public.
541
  */
542
  if ( '0' === $public )
543
  return $robots_txt;
552
  if ( false === $output ) :
553
  $output = '';
554
 
555
+ $parsed_home_url = \wp_parse_url( rtrim( $this->the_home_url_from_cache(), ' /\\' ) );
556
+ $home_path = ! empty( $parsed_home_url['path'] ) ? \esc_attr( $parsed_home_url['path'] ) : '';
557
+
558
+ if ( $this->is_subdirectory_installation() || $home_path ) {
559
+ $output .= '# This is an invalid robots.txt location.' . "\r\n";
560
+ $output .= '# Please visit: ' . \esc_url( trailingslashit( $this->set_preferred_url_scheme( $this->get_home_host() ) ) . 'robots.txt' ) . "\r\n";
561
+ $output .= "\r\n";
562
+ }
563
+
564
  /**
565
  * Apply filters the_seo_framework_robots_txt_pre & the_seo_framework_robots_txt_pro : string
566
  * Adds custom cacheable lines.
572
  $pro = (string) \apply_filters( 'the_seo_framework_robots_txt_pro', '' );
573
 
574
  $site_url = \wp_parse_url( \site_url() );
575
+ $site_path = ( ! empty( $site_url['path'] ) ) ? \esc_attr( $site_url['path'] ) : '';
576
 
577
  $output .= $pre;
578
  //* Output defaults
579
  $output .= "User-agent: *\r\n";
580
+ $output .= "Disallow: $site_path/wp-admin/\r\n";
581
+ $output .= "Allow: $site_path/wp-admin/admin-ajax.php\r\n";
582
 
583
  /**
584
+ * Applies filters the_seo_framework_robots_disallow_queries : boolean
585
+ * Determines whether to allow queries for robots.
 
 
586
  * @since 2.5.0
587
  */
588
  if ( \apply_filters( 'the_seo_framework_robots_disallow_queries', false ) ) {
 
 
589
  $output .= "Disallow: $home_path/*?*\r\n";
590
  }
591
 
592
  $output .= $pro;
593
 
594
+ //* Add extra whitespace and sitemap full URL
595
+ if ( $this->can_do_sitemap_robots( true ) )
596
+ $output .= "\r\nSitemap: " . \esc_url( $this->get_sitemap_xml_url() ) . "\r\n";
 
 
 
 
597
 
598
  $this->use_object_cache and $this->object_cache_set( $cache_key, $output, 86400 );
599
  endif;
inc/classes/inpost.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
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
inc/classes/load.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
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
inc/classes/metaboxes.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
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
inc/classes/post-data.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
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
inc/classes/query.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -1153,6 +1153,28 @@ class Query extends Compat {
1153
  return $paged;
1154
  }
1155
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1156
  /**
1157
  * Handles object cache for the query class.
1158
  *
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
1153
  return $paged;
1154
  }
1155
 
1156
+ /**
1157
+ * Determines whether we're on The SEO Framework's sitemap or not.
1158
+ *
1159
+ * @since 2.9.2
1160
+ *
1161
+ * @return bool
1162
+ */
1163
+ public function is_sitemap() {
1164
+ return (bool) $this->doing_sitemap;
1165
+ }
1166
+
1167
+ /**
1168
+ * Determines whether we're on the robots.txt file output.
1169
+ *
1170
+ * @since 2.9.2
1171
+ *
1172
+ * @return bool
1173
+ */
1174
+ public function is_robots() {
1175
+ return \is_robots();
1176
+ }
1177
+
1178
  /**
1179
  * Handles object cache for the query class.
1180
  *
inc/classes/render.class.php CHANGED
@@ -8,7 +8,7 @@ defined( 'ABSPATH' ) or die;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2016 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -828,14 +828,20 @@ class Render extends Admin_Init {
828
  * @deprecated
829
  * @since 2.7.0
830
  */
831
- if ( true !== \apply_filters( 'the_seo_framework_output_canonical', true, $this->get_the_real_ID() ) ) {
832
  $this->_deprecated_filter( 'the_seo_framework_output_canonical', '2.7.0', "add_filter( 'the_seo_framework_rel_canonical_output', '__return_empty_string' );" );
833
- return '';
 
834
  }
835
 
836
  /**
837
- * Applies filters 'the_seo_framework_rel_canonical_output' : Change canonical URL output.
 
 
838
  * @since 2.6.5
 
 
 
839
  */
840
  $url = (string) \apply_filters( 'the_seo_framework_rel_canonical_output', $this->the_url_from_cache(), $this->get_the_real_ID() );
841
 
@@ -864,7 +870,11 @@ class Render extends Admin_Init {
864
 
865
  /**
866
  * Applies filters 'the_seo_framework_ldjson_scripts' : string
 
867
  * @since 2.6.0
 
 
 
868
  */
869
  $json = (string) \apply_filters( 'the_seo_framework_ldjson_scripts', $this->render_ld_json_scripts(), $this->get_the_real_ID() );
870
 
@@ -1038,6 +1048,74 @@ class Render extends Admin_Init {
1038
  return $output;
1039
  }
1040
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1041
  /**
1042
  * Determines whether we can use Open Graph tags.
1043
  *
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
828
  * @deprecated
829
  * @since 2.7.0
830
  */
831
+ if ( \has_filter( 'the_seo_framework_output_canonical' ) ) {
832
  $this->_deprecated_filter( 'the_seo_framework_output_canonical', '2.7.0', "add_filter( 'the_seo_framework_rel_canonical_output', '__return_empty_string' );" );
833
+ if ( true !== \apply_filters( 'the_seo_framework_output_canonical', true, $this->get_the_real_ID() ) )
834
+ return '';
835
  }
836
 
837
  /**
838
+ * Applies filters 'the_seo_framework_rel_canonical_output' : string
839
+ * Changes canonical URL output.
840
+ *
841
  * @since 2.6.5
842
+ *
843
+ * @param string $url The canonical URL. Must be escaped.
844
+ * @param int $id The current page or term ID.
845
  */
846
  $url = (string) \apply_filters( 'the_seo_framework_rel_canonical_output', $this->the_url_from_cache(), $this->get_the_real_ID() );
847
 
870
 
871
  /**
872
  * Applies filters 'the_seo_framework_ldjson_scripts' : string
873
+ *
874
  * @since 2.6.0
875
+ *
876
+ * @param string $json The JSON output. Must be escaped.
877
+ * @param int $id The current page or term ID.
878
  */
879
  $json = (string) \apply_filters( 'the_seo_framework_ldjson_scripts', $this->render_ld_json_scripts(), $this->get_the_real_ID() );
880
 
1048
  return $output;
1049
  }
1050
 
1051
+ /**
1052
+ * Returns the plugin hidden HTML indicators.
1053
+ *
1054
+ * @since 2.9.2
1055
+ *
1056
+ * @param string $where Determines the position of the indicator.
1057
+ * Accepts 'before' for before, anything else for after.
1058
+ * @param int $timing Determines when the output started.
1059
+ * @return string The SEO Framework's HTML plugin indicator.
1060
+ */
1061
+ public function get_plugin_indicator( $where = 'before', $timing = 0 ) {
1062
+
1063
+ static $run, $_cache = null;
1064
+
1065
+ if ( ! isset( $run ) ) {
1066
+ /**
1067
+ * Applies filters 'the_seo_framework_indicator' : Boolean
1068
+ * Whether to show the indicator in HTML.
1069
+ * @since 2.0.0
1070
+ */
1071
+ $run = (bool) \apply_filters( 'the_seo_framework_indicator', true );
1072
+ }
1073
+
1074
+ if ( false === $run )
1075
+ return '';
1076
+
1077
+ if ( null === $_cache ) {
1078
+
1079
+ $_cache = array();
1080
+
1081
+ /**
1082
+ * Applies filters 'sybre_waaijer_<3' : Boolean
1083
+ * Whether to show the hidden author name in HTML.
1084
+ * @since 2.4.0
1085
+ */
1086
+ $sybre = (bool) \apply_filters( 'sybre_waaijer_<3', true );
1087
+
1088
+ // Plugin name can't be translated. Yay.
1089
+ $tsf = 'The SEO Framework';
1090
+
1091
+ /**
1092
+ * Applies filters 'the_seo_framework_indicator_timing' : Boolean
1093
+ * Whether to show the hidden generation time in HTML.
1094
+ * @since 2.4.0
1095
+ */
1096
+ $_cache['show_timer'] = (bool) \apply_filters( 'the_seo_framework_indicator_timing', true );
1097
+
1098
+ /* translators: %s = 'The SEO Framework' */
1099
+ $_cache['start'] = sprintf( \esc_html__( 'Start %s', 'autodescription' ), $tsf );
1100
+ /* translators: %s = 'The SEO Framework' */
1101
+ $_cache['end'] = sprintf( \esc_html__( 'End %s', 'autodescription' ), $tsf );
1102
+ $_cache['author'] = $sybre ? ' ' . \esc_html__( 'by Sybre Waaijer', 'autodescription' ) : '';
1103
+ }
1104
+
1105
+ if ( 'before' === $where ) {
1106
+ $output = $_cache['start'] . $_cache['author'];
1107
+ } else {
1108
+ if ( $_cache['show_timer'] && $timing ) {
1109
+ $timer = ' | ' . number_format( microtime( true ) - $timing, 5 ) . 's';
1110
+ } else {
1111
+ $timer = '';
1112
+ }
1113
+ $output = $_cache['end'] . $_cache['author'] . $timer;
1114
+ }
1115
+
1116
+ return sprintf( '<!-- %s -->', $output ) . PHP_EOL;
1117
+ }
1118
+
1119