The SEO Framework - Version 2.9.3

Version Description

A highly recommended update that fixes "Home Page as Blog" query issues.

Download this release

Release Info

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

Code changes from version 2.9.2 to 2.9.3

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.2
7
* Author: Sybre Waaijer
8
* Author URI: https://theseoframework.com/
9
* License: GPLv3
@@ -31,15 +31,15 @@ defined( 'ABSPATH' ) or die;
31
*/
32
33
//* Debug. Not to be used on production websites as it dumps and/or disables all kinds of stuff everywhere.
34
- //add_action( 'plugins_loaded', function() { if ( is_super_admin() ) {
35
- //if ( is_admin() ) {
36
- //define( 'THE_SEO_FRAMEWORK_DEBUG', true );
37
- //define( 'THE_SEO_FRAMEWORK_DEBUG_HIDDEN', true );
38
- //define( 'THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS', true );
39
- //update_option( 'the_seo_framework_upgraded_db_version', '0' );
40
- //add_filter( 'the_seo_framework_use_object_cache', '__return_false' );
41
- //}
42
- //}},0);
43
44
/**
45
* The plugin version.
@@ -51,7 +51,7 @@ defined( 'ABSPATH' ) or die;
51
*
52
* @since 1.0.0
53
*/
54
- define( 'THE_SEO_FRAMEWORK_VERSION', '2.9.2' );
55
56
/**
57
* The plugin Database version.
@@ -90,11 +90,17 @@ define( 'THE_SEO_FRAMEWORK_NETWORK_OPTIONS', (string) apply_filters( 'the_seo_fr
90
define( 'THE_SEO_FRAMEWORK_TERM_OPTIONS', (string) apply_filters( 'the_seo_framework_term_options', 'autodescription-term-settings' ) );
91
92
/**
93
- * Plugin term options filter.
94
* @since 2.7.0
95
*/
96
define( 'THE_SEO_FRAMEWORK_USER_OPTIONS', (string) apply_filters( 'the_seo_framework_user_options', 'autodescription-user-settings' ) );
97
98
/**
99
* The plugin map url.
100
* Used for calling browser 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.3
7
* Author: Sybre Waaijer
8
* Author URI: https://theseoframework.com/
9
* License: GPLv3
31
*/
32
33
//* Debug. Not to be used on production websites as it dumps and/or disables all kinds of stuff everywhere.
34
+ // add_action( 'plugins_loaded', function() { if ( is_super_admin() ) {
35
+ // if ( is_admin() ) {
36
+ // define( 'THE_SEO_FRAMEWORK_DEBUG', true );
37
+ // define( 'THE_SEO_FRAMEWORK_DEBUG_HIDDEN', true );
38
+ // define( 'THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS', true );
39
+ // update_option( 'the_seo_framework_upgraded_db_version', '0' );
40
+ // add_filter( 'the_seo_framework_use_object_cache', '__return_false' );
41
+ // }
42
+ // }},0);
43
44
/**
45
* The plugin version.
51
*
52
* @since 1.0.0
53
*/
54
+ define( 'THE_SEO_FRAMEWORK_VERSION', '2.9.3' );
55
56
/**
57
* The plugin Database version.
90
define( 'THE_SEO_FRAMEWORK_TERM_OPTIONS', (string) apply_filters( 'the_seo_framework_term_options', 'autodescription-term-settings' ) );
91
92
/**
93
+ * Plugin user term options filter.
94
* @since 2.7.0
95
*/
96
define( 'THE_SEO_FRAMEWORK_USER_OPTIONS', (string) apply_filters( 'the_seo_framework_user_options', 'autodescription-user-settings' ) );
97
98
+ /**
99
+ * Plugin updates cache database name.
100
+ * @since 2.9.3
101
+ */
102
+ define( 'THE_SEO_FRAMEWORK_UPDATES_CACHE', (string) apply_filters( 'the_seo_framework_updates_cache', 'autodescription-updates-cache' ) );
103
+
104
/**
105
* The plugin map url.
106
* Used for calling browser files.
inc/classes/admin-init.class.php CHANGED
@@ -524,6 +524,8 @@ class Admin_Init extends Init {
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
@@ -543,7 +545,7 @@ class Admin_Init extends Init {
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();
@@ -593,7 +595,8 @@ class Admin_Init extends Init {
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
}
524
*
525
* @since 2.2.2
526
* @since 2.9.2 : Added user-friendly exception handling.
527
+ * @since 2.9.3 : 1. Query arguments work again (regression 2.9.2).
528
+ * 2. Now only accepts http and https protocols.
529
*
530
* @param string $page Menu slug.
531
* @param array $query_args Optional. Associative array of query string arguments
545
}
546
547
$target = \add_query_arg( $query_args, $url );
548
+ $target = \esc_url_raw( $target, array( 'http', 'https' ) );
549
550
//* Predict white screen:
551
$headers_sent = headers_sent();
595
\esc_html__( 'There has been an error redirecting. Refresh the page or follow [this link](%s).', 'autodescription' ),
596
$target
597
),
598
+ array( 'a' ),
599
+ array( 'a_internal' => true )
600
)
601
);
602
}
inc/classes/admin-pages.class.php CHANGED
@@ -403,7 +403,7 @@ class Admin_Pages extends Inpost {
403
* Display notices on the save or reset of settings.
404
*
405
* @since 2.2.2
406
- * @todo convert the "request" into secure "error_notice" option. See TSF Extension Manager.
407
*
408
* @return void
409
*/
@@ -412,18 +412,18 @@ class Admin_Pages extends Inpost {
412
if ( false === $this->is_seo_settings_page( true ) )
413
return;
414
415
- $request = isset( $_REQUEST ) ? $_REQUEST : null;
416
417
- if ( null === $request )
418
return;
419
420
- if ( isset( $request['settings-updated'] ) && 'true' === $request['settings-updated'] ) :
421
$this->do_dismissible_notice( $this->page_defaults['saved_notice_text'], 'updated' );
422
- elseif ( isset( $request['tsf-settings-reset'] ) && 'true' === $request['tsf-settings-reset'] ) :
423
$this->do_dismissible_notice( $this->page_defaults['reset_notice_text'], 'warning' );
424
- elseif ( isset( $request['error'] ) && 'true' === $request['error'] ) :
425
$this->do_dismissible_notice( $this->page_defaults['error_notice_text'], 'error' );
426
- elseif ( isset( $request['tsf-settings-updated'] ) && 'true' === $request['tsf-settings-updated'] ) :
427
$this->do_dismissible_notice( $this->page_defaults['plugin_update_text'], 'updated' );
428
endif;
429
}
@@ -629,7 +629,7 @@ class Admin_Pages extends Inpost {
629
public function make_info( $description = '', $link = '', $echo = true ) {
630
631
if ( $link ) {
632
- $output = '<a href="' . \esc_url( $link ) . '" target="_blank" title="' . \esc_attr( $description ) . '">[?]</a>';
633
} else {
634
$output = '<span title="' . \esc_attr( $description ) . '">[?]</span>';
635
}
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
*/
412
if ( false === $this->is_seo_settings_page( true ) )
413
return;
414
415
+ $get = empty( $_GET ) ? null : $_GET;
416
417
+ if ( null === $get )
418
return;
419
420
+ if ( isset( $get['settings-updated'] ) && 'true' === $get['settings-updated'] ) :
421
$this->do_dismissible_notice( $this->page_defaults['saved_notice_text'], 'updated' );
422
+ elseif ( isset( $get['tsf-settings-reset'] ) && 'true' === $get['tsf-settings-reset'] ) :
423
$this->do_dismissible_notice( $this->page_defaults['reset_notice_text'], 'warning' );
424
+ elseif ( isset( $get['error'] ) && 'true' === $get['error'] ) :
425
$this->do_dismissible_notice( $this->page_defaults['error_notice_text'], 'error' );
426
+ elseif ( isset( $get['tsf-settings-updated'] ) && 'true' === $get['tsf-settings-updated'] ) :
427
$this->do_dismissible_notice( $this->page_defaults['plugin_update_text'], 'updated' );
428
endif;
429
}
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
}
inc/classes/cache.class.php CHANGED
@@ -218,6 +218,7 @@ class Cache extends Sitemaps {
218
* Main cache deletion function handler.
219
*
220
* @since 2.8.0
221
*
222
* @param string $type The type
223
* @param int $id The post, page or TT ID. Defaults to $this->get_the_real_ID().
@@ -235,6 +236,7 @@ class Cache extends Sitemaps {
235
$this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $front_id, '', 'frontpage' ) );
236
$this->delete_auto_description_transient( $front_id, '', 'frontpage' );
237
$this->delete_ld_json_transient( $front_id, '', 'frontpage' );
238
break;
239
240
case 'post' :
@@ -561,7 +563,7 @@ class Cache extends Sitemaps {
561
562
$cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
563
564
- $revision = '3';
565
566
/**
567
* Change key based on options.
@@ -627,54 +629,6 @@ class Cache extends Sitemaps {
627
628
if ( $this->is_404() ) {
629
$the_id = '_404_';
630
- } elseif ( ( $this->is_real_front_page() || $this->is_front_page_by_id( $page_id ) ) || ( $this->is_admin() && $this->is_seo_settings_page( true ) ) ) {
631
- //* Front/HomePage.
632
- $the_id = $this->generate_front_page_cache_key();
633
- } elseif ( $this->is_blog_page( $page_id ) ) {
634
- $the_id = 'blog_' . $page_id;
635
- } elseif ( $this->is_singular() ) {
636
-
637
- $post_type = \get_post_type( $page_id );
638
-
639
- switch ( $post_type ) :
640
- case 'page' :
641
- $the_id = 'page_' . $page_id;
642
- break;
643
-
644
- case 'post' :
645
- $the_id = 'post_' . $page_id;
646
- break;
647
-
648
- case 'attachment' :
649
- $the_id = 'attach_' . $page_id;
650
- break;
651
-
652
- default :
653
- $the_id = 'singular_' . $page_id;
654
- break;
655
- endswitch;
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 );
665
-
666
- //* Limit to 10 chars.
667
- if ( mb_strlen( $query ) > 10 )
668
- $query = mb_substr( $query, 0, 10 );
669
-
670
- $query = \esc_sql( $query );
671
- }
672
-
673
- //* Temporarily disable caches to prevent database spam.
674
- $this->the_seo_framework_use_transients = false;
675
- $this->use_object_cache = false;
676
-
677
- $the_id = $page_id . '_s_' . $query;
678
} elseif ( $this->is_archive() ) {
679
if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
680
@@ -685,7 +639,7 @@ class Cache extends Sitemaps {
685
$t = $o->taxonomy;
686
}
687
688
- $the_id = $this->generate_taxonomial_cache_key( $page_id, $t );
689
690
if ( $this->is_tax() )
691
$the_id = 'archives_' . $the_id;
@@ -724,7 +678,7 @@ class Cache extends Sitemaps {
724
$the_id = 'unix_' . $unix;
725
}
726
} else {
727
- //* Other taxonomial archives.
728
729
if ( empty( $t ) ) {
730
$post_type = \get_query_var( 'post_type' );
@@ -743,10 +697,58 @@ class Cache extends Sitemaps {
743
if ( empty( $t ) )
744
$t = \get_query_var( 'taxonomy' );
745
746
- $the_id = $this->generate_taxonomial_cache_key( $page_id, $t );
747
748
$the_id = 'archives_' . $the_id;
749
}
750
}
751
752
/**
@@ -802,7 +804,7 @@ class Cache extends Sitemaps {
802
return $this->add_cache_key_suffix( 'singular_' . $page_id );
803
break;
804
case 'term' :
805
- return $this->add_cache_key_suffix( $this->generate_taxonomial_cache_key( $page_id, $taxonomy ) );
806
break;
807
default :
808
$this->_doing_it_wrong( __METHOD__, 'Third parameter must be a known type.', '2.6.5' );
@@ -858,16 +860,16 @@ class Cache extends Sitemaps {
858
}
859
860
/**
861
- * Generates Cache key for taxonomial archives.
862
*
863
* @since 2.6.0
864
*
865
* @param int $page_id The taxonomy or page ID.
866
* @param string $taxonomy The taxonomy name.
867
*
868
- * @return string The Taxonomial Archive cache key.
869
*/
870
- protected function generate_taxonomial_cache_key( $page_id = '', $taxonomy = '' ) {
871
872
$the_id = '';
873
218
* Main cache deletion function handler.
219
*
220
* @since 2.8.0
221
+ * @since 2.9.3 $type = 'front' now also returns true.
222
*
223
* @param string $type The type
224
* @param int $id The post, page or TT ID. Defaults to $this->get_the_real_ID().
236
$this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $front_id, '', 'frontpage' ) );
237
$this->delete_auto_description_transient( $front_id, '', 'frontpage' );
238
$this->delete_ld_json_transient( $front_id, '', 'frontpage' );
239
+ return true;
240
break;
241
242
case 'post' :
563
564
$cache_key = $this->generate_cache_key( $page_id, $taxonomy, $type );
565
566
+ $revision = '5';
567
568
/**
569
* Change key based on options.
629
630
if ( $this->is_404() ) {
631
$the_id = '_404_';
632
} elseif ( $this->is_archive() ) {
633
if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
634
639
$t = $o->taxonomy;
640
}
641
642
+ $the_id = $this->generate_taxonomical_cache_key( $page_id, $t );
643
644
if ( $this->is_tax() )
645
$the_id = 'archives_' . $the_id;
678
$the_id = 'unix_' . $unix;
679
}
680
} else {
681
+ //* Other taxonomical archives.
682
683
if ( empty( $t ) ) {
684
$post_type = \get_query_var( 'post_type' );
697
if ( empty( $t ) )
698
$t = \get_query_var( 'taxonomy' );
699
700
+ $the_id = $this->generate_taxonomical_cache_key( $page_id, $t );
701
702
$the_id = 'archives_' . $the_id;
703
}
704
+ } elseif ( ( $this->is_real_front_page() || $this->is_front_page_by_id( $page_id ) ) || ( $this->is_admin() && $this->is_seo_settings_page( true ) ) ) {
705
+ //* Front/HomePage.
706
+ $the_id = $this->generate_front_page_cache_key();
707
+ } elseif ( $this->is_blog_page( $page_id ) ) {
708
+ $the_id = 'blog_' . $page_id;
709
+ } elseif ( $this->is_singular() ) {
710
+
711
+ $post_type = \get_post_type( $page_id );
712
+
713
+ switch ( $post_type ) :
714
+ case 'page' :
715
+ $the_id = 'page_' . $page_id;
716
+ break;
717
+
718
+ case 'post' :
719
+ $the_id = 'post_' . $page_id;
720
+ break;
721
+
722
+ case 'attachment' :
723
+ $the_id = 'attach_' . $page_id;
724
+ break;
725
+
726
+ default :
727
+ $the_id = 'singular_' . $page_id;
728
+ break;
729
+ endswitch;
730
+ } elseif ( $this->is_search() ) {
731
+ $query = '';
732
+
733
+ //* TODO figure out why this check is here... admin compat maybe?
734
+ if ( function_exists( 'get_search_query' ) ) {
735
+ $search_query = \get_search_query( $_escaped = true );
736
+
737
+ if ( $search_query )
738
+ $query = str_replace( ' ', '', $search_query );
739
+
740
+ //* Limit to 10 chars.
741
+ if ( mb_strlen( $query ) > 10 )
742
+ $query = mb_substr( $query, 0, 10 );
743
+
744
+ $query = \esc_sql( $query );
745
+ }
746
+
747
+ //* Temporarily disable caches to prevent database spam.
748
+ $this->the_seo_framework_use_transients = false;
749
+ $this->use_object_cache = false;
750
+
751
+ $the_id = $page_id . '_s_' . $query;
752
}
753
754
/**
804
return $this->add_cache_key_suffix( 'singular_' . $page_id );
805
break;
806
case 'term' :
807
+ return $this->add_cache_key_suffix( $this->generate_taxonomical_cache_key( $page_id, $taxonomy ) );
808
break;
809
default :
810
$this->_doing_it_wrong( __METHOD__, 'Third parameter must be a known type.', '2.6.5' );
860
}
861
862
/**
863
+ * Generates Cache key for taxonomical archives.
864
*
865
* @since 2.6.0
866
*
867
* @param int $page_id The taxonomy or page ID.
868
* @param string $taxonomy The taxonomy name.
869
*
870
+ * @return string The Taxonomical Archive cache key.
871
*/
872
+ protected function generate_taxonomical_cache_key( $page_id = '', $taxonomy = '' ) {
873
874
$the_id = '';
875
inc/classes/core.class.php CHANGED
@@ -313,7 +313,7 @@ class Core {
313
$a11y = $a11y ? 'tsf-show-icon' : '';
314
315
$notice = '<div class="notice ' . \esc_attr( $type ) . ' tsf-notice ' . $a11y . '"><p>';
316
- $notice .= '<a class="hide-if-no-js tsf-dismiss" title="' . \esc_attr__( 'Dismiss', 'AutoDescription' ) . '"></a>';
317
$notice .= '<strong>' . $message . '</strong>';
318
$notice .= '</p></div>';
319
@@ -334,6 +334,52 @@ class Core {
334
echo $this->generate_dismissible_notice( $message, $type, (bool) $a11y, (bool) $escape );
335
}
336
337
/**
338
* Mark up content with code tags.
339
* Escapes all HTML, so `<` gets changed to `&lt;` and displays correctly.
@@ -552,7 +598,7 @@ class Core {
552
553
$url = html_entity_decode( \menu_page_url( $this->seo_settings_page_slug, false ) );
554
555
- return \esc_url( $url );
556
}
557
558
return '';
@@ -805,14 +851,17 @@ class Core {
805
* @since 2.9.0 : 1. Removed word boundary requirement for strong.
806
* 2. Now accepts regex count their numeric values in string.
807
* 3. Fixed header 1~6 calculation.
808
* @link https://wordpress.org/plugins/about/readme.txt
809
*
810
* @param string $text The text that might contain markdown. Expected to be escaped.
811
* @param array $convert The markdown style types wished to be converted.
812
- * If left empty, it will convert all.
813
* @return string The markdown converted text.
814
*/
815
- public function convert_markdown( $text, $convert = array() ) {
816
817
preprocess : {
818
$text = str_replace( "\r\n", "\n", $text );
@@ -823,6 +872,11 @@ class Core {
823
if ( '' === $text )
824
return '';
825
826
/**
827
* The conversion list's keys are per reference only.
828
*/
@@ -902,10 +956,12 @@ class Core {
902
case 'a' :
903
$count = preg_match_all( '/(?:(?:\[{1})([^\]{1}]+)(?:\]{1})(?:\({1})([^\)\(]+)(?:\){1}))/', $text, $matches, PREG_PATTERN_ORDER );
904
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
}
313
$a11y = $a11y ? 'tsf-show-icon' : '';
314
315
$notice = '<div class="notice ' . \esc_attr( $type ) . ' tsf-notice ' . $a11y . '"><p>';
316
+ $notice .= '<a class="hide-if-no-js tsf-dismiss" title="' . \esc_attr__( 'Dismiss', 'autodescription' ) . '"></a>';
317
$notice .= '<strong>' . $message . '</strong>';
318
$notice .= '</p></div>';
319
334
echo $this->generate_dismissible_notice( $message, $type, (bool) $a11y, (bool) $escape );
335
}
336
337
+ /**
338
+ * Generates dismissible notice that stick until the user dismisses it.
339
+ * Also loads scripts and styles if out of The SEO Framework's context.
340
+ *
341
+ * @since 2.9.3
342
+ * @see $this->do_dismissible_sticky_notice()
343
+ * @uses THE_SEO_FRAMEWORK_UPDATES_CACHE
344
+ * @todo make this do something.
345
+ * NOTE: This method is a placeholder.
346
+ *
347
+ * @param string $message The notice message. Expected to be escaped if $escape is false.
348
+ * @param string $key The notice key. Must be unique and tied to the stored updates cache option.
349
+ * @param array $args : {
350
+ * 'type' => string Optional. The notification type. Default 'updated'.
351
+ * 'a11y' => bool Optional. Whether to enable accessibility. Default true.
352
+ * 'escape' => bool Optional. Whether to escape the $message. Default true.
353
+ * 'color' => string Optional. If filled in, it will output the selected color. Default ''.
354
+ * 'icon' => string Optional. If filled in, it will output the selected icon. Default ''.
355
+ * }
356
+ * @return string The dismissible error notice.
357
+ */
358
+ public function generate_dismissible_sticky_notice( $message, $key, $args = array() ) {
359
+ return '';
360
+ }
361
+
362
+ /**
363
+ * Echos generated dismissible sticky notice.
364
+ *
365
+ * @since 2.9.3
366
+ * @uses $this->generate_dismissible_sticky_notice()
367
+ *
368
+ * @param string $message The notice message. Expected to be escaped if $escape is false.
369
+ * @param string $key The notice key. Must be unique and tied to the stored updates cache option.
370
+ * @param array $args : {
371
+ * 'type' => string Optional. The notification type. Default 'updated'.
372
+ * 'a11y' => bool Optional. Whether to enable accessibility. Default true.
373
+ * 'escape' => bool Optional. Whether to escape the $message. Default true.
374
+ * 'color' => string Optional. If filled in, it will output the selected color. Default ''.
375
+ * 'icon' => string Optional. If filled in, it will output the selected icon. Default ''.
376
+ * }
377
+ * @return string The dismissible error notice.
378
+ */
379
+ public function do_dismissible_sticky_notice( $message, $key, $args = array() ) {
380
+ echo $this->generate_dismissible_sticky_notice( $message, $key, $args );
381
+ }
382
+
383
/**
384
* Mark up content with code tags.
385
* Escapes all HTML, so `<` gets changed to `&lt;` and displays correctly.
598
599
$url = html_entity_decode( \menu_page_url( $this->seo_settings_page_slug, false ) );
600
601
+ return \esc_url( $url, array( 'http', 'https' ) );
602
}
603
604
return '';
851
* @since 2.9.0 : 1. Removed word boundary requirement for strong.
852
* 2. Now accepts regex count their numeric values in string.
853
* 3. Fixed header 1~6 calculation.
854
+ * @since 2.9.3 : 1. Added $args parameter.
855
+ * 2. TODO It now uses substr_replace instead of str_replace to prevent duplicated replacements.
856
* @link https://wordpress.org/plugins/about/readme.txt
857
*
858
* @param string $text The text that might contain markdown. Expected to be escaped.
859
* @param array $convert The markdown style types wished to be converted.
860
+ * If left empty, it will convert all.
861
+ * @param array $args The function arguments.
862
* @return string The markdown converted text.
863
*/
864
+ public function convert_markdown( $text, $convert = array(), $args = array() ) {
865
866
preprocess : {
867
$text = str_replace( "\r\n", "\n", $text );
872
if ( '' === $text )
873
return '';
874
875
+ $defaults = array(
876
+ 'a_internal' => false,
877
+ );
878
+ $args = array_merge( $defaults, $args );
879
+
880
/**
881
* The conversion list's keys are per reference only.
882
*/
956
case 'a' :
957
$count = preg_match_all( '/(?:(?:\[{1})([^\]{1}]+)(?:\]{1})(?:\({1})([^\)\(]+)(?:\){1}))/', $text, $matches, PREG_PATTERN_ORDER );
958
959
+ $_string = $args['a_internal'] ? '<a href="%s">%s</a>' : '<a href="%s" target="_blank" rel="nofollow noreferrer noopener">%s</a>';
960
+
961
for ( $i = 0; $i < $count; $i++ ) {
962
$text = str_replace(
963
$matches[0][ $i ],
964
+ sprintf( $_string, \esc_url( $matches[2][ $i ], array( 'http', 'https' ) ), \esc_html( $matches[1][ $i ] ) ),
965
$text
966
);
967
}
inc/classes/deprecated.class.php CHANGED
@@ -647,12 +647,13 @@ final class Deprecated {
647
648
/**
649
* Fetches image from post thumbnail.
650
- * Resizes the image between 1500px 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
* @deprecated
657
*
658
* @param array $args The image args.
@@ -741,4 +742,549 @@ final class Deprecated {
741
742
return $is_front_page;
743
}
744
}
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.
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
}
inc/classes/detect.class.php CHANGED
@@ -520,6 +520,7 @@ class Detect extends Render {
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.
@@ -536,7 +537,7 @@ class Detect extends Render {
536
return false;
537
538
if ( $check_option ) {
539
- if ( ! $this->is_option_checked( 'sitemaps_output' ) )
540
return false;
541
}
542
@@ -914,10 +915,12 @@ class Detect extends Render {
914
}
915
916
/**
917
- * Checks (current) Post Type for if this plugin may use it.
918
*
919
* @since 2.6.0
920
- * @staticvar string $cache
921
*
922
* @param bool $public Whether to only get Public Post types.
923
* @param string $post_type Optional. The post type to check.
@@ -925,6 +928,11 @@ class Detect extends Render {
925
*/
926
public function get_supported_post_type( $public = true, $post_type = '' ) {
927
928
if ( empty( $post_type ) ) {
929
global $current_screen;
930
@@ -937,11 +945,6 @@ class Detect extends Render {
937
938
$post_type_evaluated = $post_type;
939
940
- static $cache = array();
941
-
942
- if ( isset( $cache[ $public ][ $post_type ] ) )
943
- return $cache[ $public ][ $post_type ];
944
-
945
$object = \get_post_type_object( $post_type );
946
947
//* Check if rewrite is enabled. Bypass builtin post types.
@@ -970,6 +973,39 @@ class Detect extends Render {
970
return $cache[ $public ][ $post_type ] = $post_type;
971
}
972
973
/**
974
* Determines whether the theme is outputting the title correctly based on transient.
975
*
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
+ * @since 2.9.3 Now also checks for sitemap_robots option.
524
*
525
* @param bool $check_option Whether to check for sitemap option.
526
* @return bool True when no conflicting plugins are detected or when The SEO Framework's Sitemaps are output.
537
return false;
538
539
if ( $check_option ) {
540
+ if ( ! $this->is_option_checked( 'sitemaps_output' ) || ! $this->is_option_checked( 'sitemaps_robots' ) )
541
return false;
542
}
543
915
}
916
917
/**
918
+ * Checks (current) Post Type for if this plugin may use it for customizable SEO.
919
*
920
* @since 2.6.0
921
+ * @since 2.9.3 : Improved caching structure. i.e. it's faster now when no $post_type is supplied.
922
+ * @staticvar array $cache
923
+ * @global object $current_screen
924
*
925
* @param bool $public Whether to only get Public Post types.
926
* @param string $post_type Optional. The post type to check.
928
*/
929
public function get_supported_post_type( $public = true, $post_type = '' ) {
930
931
+ static $cache = array();
932
+
933
+ if ( isset( $cache[ $public ][ $post_type ] ) )
934
+ return $cache[ $public ][ $post_type ];
935
+
936
if ( empty( $post_type ) ) {
937
global $current_screen;
938
945
946
$post_type_evaluated = $post_type;
947
948
$object = \get_post_type_object( $post_type );
949
950
//* Check if rewrite is enabled. Bypass builtin post types.
973
return $cache[ $public ][ $post_type ] = $post_type;
974
}
975
976
+ /**
977
+ * Checks (current) Post Type for taxonomical archives.
978
+ *
979
+ * @since 2.9.3
980
+ * @staticvar array $cache
981
+ * @global object $current_screen
982
+ *
983
+ * @param string $post_type Optional. The post type to check.
984
+ * @return bool True when the post type has taxonomies.
985
+ */
986
+ public function post_type_supports_taxonomies( $post_type = '' ) {
987
+
988
+ static $cache = array();
989
+
990
+ if ( isset( $cache[ $post_type ] ) )
991
+ return $cache[ $post_type ];
992
+
993
+ if ( empty( $post_type ) ) {
994
+ global $current_screen;
995
+
996
+ if ( isset( $current_screen->post_type ) ) {
997
+ $post_type = $current_screen->post_type;
998
+ } else {
999
+ return false;
1000
+ }
1001
+ }
1002
+
1003
+ if ( \get_object_taxonomies( $post_type, 'names' ) )
1004
+ return $cache[ $post_type ] = true;
1005
+
1006
+ return $cache[ $post_type ] = false;
1007
+ }
1008
+
1009
/**
1010
* Determines whether the theme is outputting the title correctly based on transient.
1011
*
inc/classes/doing-it-right.class.php CHANGED
@@ -76,10 +76,14 @@ class Doing_It_Right extends Generate_Ldjson {
76
$post_id = isset( $post->ID ) ? $post->ID : false;
77
78
if ( $post_id ) {
79
- $searchexclude = (bool) $this->get_custom_field( 'exclude_local_search', $post_id );
80
81
- if ( $searchexclude )
82
$states[] = \esc_html__( 'No Search', 'autodescription' );
83
}
84
85
return $states;
76
$post_id = isset( $post->ID ) ? $post->ID : false;
77
78
if ( $post_id ) {
79
+ $search_exclude = (bool) $this->get_custom_field( 'exclude_local_search', $post_id );
80
+ $archive_exclude = (bool) $this->get_custom_field( 'exclude_from_archive', $post_id );
81
82
+ if ( $search_exclude )
83
$states[] = \esc_html__( 'No Search', 'autodescription' );
84
+
85
+ if ( $archive_exclude )
86
+ $states[] = \esc_html__( 'No Archive', 'autodescription' );
87
}
88
89
return $states;
inc/classes/generate-image.class.php CHANGED
@@ -48,6 +48,85 @@ class Generate_Image extends Generate_Url {
48
parent::__construct();
49
}
50
51
/**
52
* Returns social image URL and sets $this->image_dimensions.
53
*
@@ -343,10 +422,11 @@ class Generate_Image extends Generate_Url {
343
/**
344
* Fetches image from post thumbnail.
345
*
346
- * Resizes the image between 1500px if bigger. Then it saves the image and
347
* Keeps dimensions relative.
348
*
349
* @since 2.9.0
350
*
351
* @param int $id The post ID. Required.
352
* @param array $args The image args.
@@ -404,9 +484,11 @@ class Generate_Image extends Generate_Url {
404
* @since 2.8.0 : 1. Removed staticvar.
405
* 2. Now adds ID call to OG image called listener.
406
* @since 2.9.0 : Added $set_og_dimension parameter
407
*
408
* @todo create formula to fetch transient.
409
* @priority high 2.7.0
410
*
411
* @param int $id The attachment ID.
412
* @param array $args The image args
@@ -428,19 +510,22 @@ class Generate_Image extends Generate_Url {
428
$w = $src[1]; // Width
429
$h = $src[2]; // Height
430
431
- //* Preferred 1500px, resize it
432
- if ( $w > 1500 || $h > 1500 ) :
433
434
if ( $w === $h ) {
435
//* Square
436
- $w = 1500;
437
- $h = 1500;
438
} elseif ( $w > $h ) {
439
- //* Landscape, set $w to 1500.
440
- $h = $this->proportionate_dimensions( $h, $w, $w = 1500 );
441
} elseif ( $h > $w ) {
442
- //* Portrait, set $h to 1500.
443
- $w = $this->proportionate_dimensions( $w, $h, $h = 1500 );
444
}
445
446
//* Get path of image and load it into the wp_get_image_editor
48
parent::__construct();
49
}
50
51
+ /**
52
+ * Returns image URL suitable for Schema items.
53
+ *
54
+ * These are images that are strictly assigned to the Post or Page.
55
+ * Themes should compliment these. If not, then Open Graph should at least
56
+ * compliment these.
57
+ * If that's not even true, then I don't know what happens. But then you're
58
+ * in a grey area... @TODO make images optional for Schema?
59
+ *
60
+ * @since 2.9.3
61
+ * @uses $this->get_social_image()
62
+ * @staticvar array $images
63
+ *
64
+ * @TODO support Terms.
65
+ *
66
+ * @param int|string $id The page, post, product or term ID.
67
+ * @param bool $singular Whether the ID is singular or archival.
68
+ * @return string $url The Schema.org safe image.
69
+ */
70
+ public function get_schema_image( $id = 0, $singular = false ) {
71
+
72
+ //= TODO remove this when term images are introduced.
73
+ if ( ! $singular )
74
+ return '';
75
+
76
+ static $images = array();
77
+
78
+ $id = (int) $id;
79
+
80
+ if ( isset( $images[ $id ][ $singular ] ) )
81
+ return $images[ $id ][ $singular ];
82
+
83
+ if ( $singular ) {
84
+ if ( $id === $this->get_the_front_page_ID() ) {
85
+ if ( $this->has_page_on_front() ) {
86
+ $image_args = array(
87
+ 'post_id' => $id,
88
+ 'skip_fallback' => true,
89
+ 'escape' => false,
90
+ );
91
+ } else {
92
+ $image_args = array(
93
+ 'post_id' => $id,
94
+ 'skip_fallback' => true,
95
+ 'disallowed' => array(
96
+ 'postmeta',
97
+ 'featured',
98
+ ),
99
+ 'escape' => false,
100
+ );
101
+ }
102
+ } else {
103
+ $image_args = array(
104
+ 'post_id' => $id,
105
+ 'skip_fallback' => true,
106
+ 'disallowed' => array(
107
+ 'homemeta',
108
+ ),
109
+ 'escape' => false,
110
+ );
111
+ }
112
+ $url = $this->get_social_image( $image_args, false );
113
+ } else {
114
+ //* Placeholder for when Terms get image uploads.
115
+ $url = '';
116
+ }
117
+
118
+ /**
119
+ * Applies filters 'the_seo_framework_ld_json_breadcrumb_image' : string
120
+ * @since 2.7.0
121
+ * @param string $image The current image.
122
+ * @param int $id The page, post, product or term ID.
123
+ * @param bool $singular Whether the ID is singular.
124
+ */
125
+ $url = \apply_filters( 'the_seo_framework_ld_json_breadcrumb_image', $url, $id, $singular );
126
+
127
+ return $images[ $id ][ $singular ] = \esc_url_raw( $url );
128
+ }
129
+
130
/**
131
* Returns social image URL and sets $this->image_dimensions.
132
*
422
/**
423
* Fetches image from post thumbnail.
424
*
425
+ * Resizes the image between 4096px if bigger. Then it saves the image and
426
* Keeps dimensions relative.
427
*
428
* @since 2.9.0
429
+ * @since 2.9.3 Now supports 4K.
430
*
431
* @param int $id The post ID. Required.
432
* @param array $args The image args.
484
* @since 2.8.0 : 1. Removed staticvar.
485
* 2. Now adds ID call to OG image called listener.
486
* @since 2.9.0 : Added $set_og_dimension parameter
487
+ * @since 2.9.3 : 4k baby.
488
*
489
* @todo create formula to fetch transient.
490
* @priority high 2.7.0
491
+ * @prioerity lowered with 4K @ 2.9.3
492
*
493
* @param int $id The attachment ID.
494
* @param array $args The image args
510
$w = $src[1]; // Width
511
$h = $src[2]; // Height
512
513
+ //* @TODO add filter that can lower it?
514
+ $_size = 4096;
515
+
516
+ //* Preferred 4096px, resize it
517
+ if ( $w > $_size || $h > $_size ) :
518
519
if ( $w === $h ) {
520
//* Square
521
+ $w = $_size;
522
+ $h = $_size;
523
} elseif ( $w > $h ) {
524
+ //* Landscape, set $w to 4096.
525
+ $h = $this->proportionate_dimensions( $h, $w, $w = $_size );
526
} elseif ( $h > $w ) {
527
+ //* Portrait, set $h to 4096.
528
+ $w = $this->proportionate_dimensions( $w, $h, $h = $_size );
529
}
530
531
//* Get path of image and load it into the wp_get_image_editor
inc/classes/generate-ldjson.class.php CHANGED
@@ -40,11 +40,110 @@ class Generate_Ldjson extends Generate_Image {
40
}
41
42
/**
43
- * Render the LD+Json scripts.
44
*
45
* @since 2.6.0
46
*
47
- * @return string The LD+Json scripts.
48
*/
49
public function render_ld_json_scripts() {
50
@@ -53,39 +152,21 @@ class Generate_Ldjson extends Generate_Image {
53
54
$this->setup_ld_json_transient( $this->get_the_real_ID() );
55
56
- $this->the_seo_framework_debug and $this->debug_init( __METHOD__, false, $debug_key = microtime( true ), array( 'LD Json transient' => $this->ld_json_transient, 'Output from transient' => false !== $this->get_transient( $this->ld_json_transient ) ) );
57
58
$use_cache = $this->is_option_checked( 'cache_meta_schema' );
59
60
$output = $use_cache ? $this->get_transient( $this->ld_json_transient ) : false;
61
if ( false === $output ) :
62
-
63
- $output = '';
64
-
65
- //* Only display search helper and knowledge graph on front page.
66
if ( $this->is_real_front_page() ) {
67
68
- $sitename = $this->ld_json_name();
69
- $sitelinks = $this->ld_json_search();
70
- $knowledgegraph = $this->ld_json_knowledge();
71
-
72
- if ( $sitename )
73
- $output .= $sitename;
74
-
75
- if ( $sitelinks )
76
- $output .= $sitelinks;
77
-
78
- if ( $knowledgegraph )
79
- $output .= $knowledgegraph;
80
-
81
} else {
82
- $breadcrumbhelper = $this->ld_json_breadcrumbs();
83
-
84
- //* No wrapper, is done within script generator.
85
- if ( $breadcrumbhelper ) {
86
- $output .= $breadcrumbhelper;
87
- $output .= $this->ld_json_name();
88
- }
89
}
90
91
if ( $use_cache ) {
@@ -105,265 +186,231 @@ class Generate_Ldjson extends Generate_Image {
105
}
106
107
/**
108
- * Returns http://schema.org json encoded context URL.
109
*
110
- * @staticvar string $context
111
- * @since 2.6.0
112
*
113
- * @return string The json encoded context url.
114
*/
115
- public function schema_context() {
116
-
117
- static $context;
118
119
- if ( isset( $context ) )
120
- return $context;
121
122
- return $context = json_encode( 'http://schema.org' );
123
- }
124
125
- /**
126
- * Returns 'WebSite' json encoded type name.
127
- *
128
- * @staticvar string $context
129
- * @since 2.6.0
130
- *
131
- * @return string The json encoded type name.
132
- */
133
- public function schema_type() {
134
135
- static $type;
136
137
- if ( isset( $type ) )
138
- return $type;
139
140
- return $type = json_encode( 'WebSite' );
141
- }
142
143
- /**
144
- * Returns json encoded home url.
145
- *
146
- * @staticvar string $url
147
- * @since 2.6.0
148
- *
149
- * @return string The json encoded home url.
150
- */
151
- public function schema_home_url() {
152
153
- static $type;
154
155
- if ( isset( $type ) )
156
- return $type;
157
158
- return $type = json_encode( $this->the_home_url_from_cache() );
159
}
160
161
/**
162
- * Returns json encoded blogname.
163
*
164
- * @staticvar string $name
165
- * @since 2.6.0
166
*
167
- * @return string The json encoded blogname.
168
*/
169
- public function schema_blog_name() {
170
-
171
- static $name;
172
173
- if ( isset( $name ) )
174
- return $name;
175
176
- return $name = json_encode( $this->get_blogname() );
177
- }
178
179
- /**
180
- * Returns 'BreadcrumbList' json encoded type name.
181
- *
182
- * @staticvar string $crumblist
183
- * @since 2.6.0
184
- *
185
- * @return string The json encoded 'BreadcrumbList'.
186
- */
187
- public function schema_breadcrumblist() {
188
189
- static $crumblist;
190
191
- if ( isset( $crumblist ) )
192
- return $crumblist;
193
194
- return $crumblist = json_encode( 'BreadcrumbList' );
195
- }
196
197
- /**
198
- * Returns 'ListItem' json encoded type name.
199
- *
200
- * @staticvar string $listitem
201
- * @since 2.6.0
202
- *
203
- * @return string The json encoded 'ListItem'.
204
- */
205
- public function schema_listitem() {
206
207
- static $listitem;
208
209
- if ( isset( $listitem ) )
210
- return $listitem;
211
212
- return $listitem = json_encode( 'ListItem' );
213
}
214
215
/**
216
- * Returns 'image' json encoded value.
217
*
218
- * @staticvar array $images
219
- * @since 2.7.0
220
- * @since 2.9.0 : 1. No longer uses image from cache, instead: it skips fallback images.
221
- * 2. Can now fetch home-page as blog set image.
222
*
223
- * @param int|string $id The page, post, product or term ID.
224
- * @param bool $singular Whether the ID is singular.
225
*/
226
- public function schema_image( $id = 0, $singular = false ) {
227
-
228
- static $images = array();
229
230
- $id = (int) $id;
231
-
232
- if ( isset( $images[ $id ][ $singular ] ) )
233
- return $images[ $id ][ $singular ];
234
235
- $image = '';
236
237
- if ( $singular ) {
238
- if ( $id === $this->get_the_front_page_ID() ) {
239
- if ( $this->has_page_on_front() ) {
240
- $image_args = array(
241
- 'post_id' => $id,
242
- 'skip_fallback' => true,
243
- );
244
- } else {
245
- $image_args = array(
246
- 'post_id' => $id,
247
- 'skip_fallback' => true,
248
- 'disallowed' => array(
249
- 'postmeta',
250
- 'featured',
251
- ),
252
- );
253
- }
254
- } else {
255
- $image_args = array(
256
- 'post_id' => $id,
257
- 'skip_fallback' => true,
258
- 'disallowed' => array(
259
- 'homemeta'
260
- ),
261
- );
262
- }
263
- $image = $this->get_social_image( $image_args );
264
- } else {
265
- //* Placeholder.
266
- $image = '';
267
}
268
269
- /**
270
- * Applies filters 'the_seo_framework_ld_json_breadcrumb_image' : string
271
- * @since 2.7.0
272
- * @param string $image The current image.
273
- * @param int $id The page, post, product or term ID.
274
- * @param bool $singular Whether the ID is singular.
275
- */
276
- $image = \apply_filters( 'the_seo_framework_ld_json_breadcrumb_image', $image, $id, $singular );
277
-
278
- return $images[ $id ][ $singular ] = json_encode( \esc_url_raw( $image ) );
279
}
280
281
/**
282
- * Generate LD+Json search helper.
283
*
284
- * @since 2.2.8
285
*
286
- * @return escaped LD+json search helper string.
287
*/
288
- public function ld_json_search() {
289
-
290
- if ( false === $this->enable_ld_json_searchbox() )
291
- return '';
292
293
- $context = $this->schema_context();
294
- $webtype = $this->schema_type();
295
- $url = $this->schema_home_url();
296
- $name = $this->schema_blog_name();
297
- $actiontype = json_encode( 'SearchAction' );
298
-
299
- /**
300
- * Applies filters 'the_seo_framework_ld_json_search_url' : string
301
- * @since 2.7.0
302
- * @param string $search_url The default WordPress search URL without query parameters.
303
- */
304
- $search_url = (string) \apply_filters( 'the_seo_framework_ld_json_search_url', $this->the_home_url_from_cache( true ) . '?s=' );
305
306
- // Remove trailing quote and add it back.
307
- $target = mb_substr( json_encode( $search_url ), 0, -1 ) . '{search_term_string}"';
308
309
- $queryaction = json_encode( 'required name=search_term_string' );
310
311
- $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 );
312
313
- $output = '';
314
- if ( $json )
315
- $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
316
317
- return $output;
318
- }
319
320
- /**
321
- * Generate LD+Json breadcrumb helper.
322
- *
323
- * @since 2.4.2
324
- *
325
- * @return escaped LD+json search helper string.
326
- */
327
- public function ld_json_breadcrumbs() {
328
329
- if ( false === $this->enable_ld_json_breadcrumbs() )
330
- return '';
331
332
- //* Used to count ancestors and categories.
333
- $output = '';
334
335
- if ( $this->is_single() || $this->is_wc_product() ) {
336
- $output = $this->ld_json_breadcrumbs_post();
337
- } elseif ( false === $this->is_real_front_page() && $this->is_page() ) {
338
- $output = $this->ld_json_breadcrumbs_page();
339
}
340
341
return $output;
342
}
343
344
/**
345
- * Generate post breadcrumb.
346
*
347
- * @since 2.6.0
348
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
349
*
350
- * @return string $output The breadcrumb script.
351
*/
352
- public function ld_json_breadcrumbs_post() {
353
354
$output = '';
355
356
$post_id = $this->get_the_real_ID();
357
358
- $cat_type = 'category';
359
-
360
//* WooCommerce support.
361
- if ( $this->is_wc_product() )
362
- $cat_type = 'product_cat';
363
364
//* Test categories.
365
$r = \is_object_in_term( $post_id, $cat_type, '' );
366
-
367
if ( ! $r || \is_wp_error( $r ) )
368
return '';
369
@@ -371,8 +418,8 @@ class Generate_Ldjson extends Generate_Image {
371
* Applies filter 'the_seo_framework_ld_json_breadcrumb_terms' : array
372
* @since 2.8.0
373
*
374
- * @param array $cats The LD+Json terms that are being used
375
- * @param int $post_id The current Post ID.
376
* @param string $cat_type The current taxonomy (either category or product_cat).
377
*/
378
$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 ) );
@@ -390,23 +437,37 @@ class Generate_Ldjson extends Generate_Image {
390
391
//* Fetch cats children id's, if any.
392
foreach ( $cats as $term_id => $parent_id ) :
393
- //* Warning: This makes database calls...
394
- if ( ! \term_exists( $term_id, $cat_type, $parent_id ) )
395
- continue;
396
397
- //* Store to filter unused Cat ID's from the post.
398
$assigned_ids[] = $term_id;
399
400
- // Check if they have kittens.
401
$children = \get_term_children( $term_id, $cat_type );
402
- $ancestors = \get_ancestors( $term_id, $cat_type );
403
404
- //* Save children id's as kittens.
405
- $kittens[ $term_id ] = $children;
406
- $parents[ $term_id ] = $ancestors;
407
endforeach;
408
unset( $cats );
409
410
foreach ( $kittens as $kit_id => $child_id ) :
411
foreach ( $child_id as $ckey => $cid ) :
412
@@ -414,7 +475,7 @@ class Generate_Ldjson extends Generate_Image {
414
* Seed out children that aren't assigned.
415
* (from levels too deep as get_term_children gets them all).
416
*/
417
- if ( $cid && false === in_array( $cid, $assigned_ids, true ) )
418
unset( $kittens[ $kit_id ][ $ckey ] );
419
420
/**
@@ -444,7 +505,7 @@ class Generate_Ldjson extends Generate_Image {
444
/**
445
* Build category ID trees for kittens.
446
*/
447
- $trees = $this->build_breadcrumb_trees( $kittens );
448
449
//* Empty parents.
450
$parents = array();
@@ -468,235 +529,170 @@ class Generate_Ldjson extends Generate_Image {
468
//* Temporarily array.
469
$kitten[ $pid ] = $parents_ids;
470
471
- $trees = $this->build_breadcrumb_trees( $kitten, $trees );
472
} else {
473
//* Parents are reversed children. Let's fix that.
474
$parents_ids = array_reverse( $parents_ids );
475
476
- $trees = $this->build_breadcrumb_trees( $parents_ids, $trees );
477
}
478
}
479
endif;
480
481
/**
482
* Sort by number of id's. Provides a cleaner layout, better Search Engine understanding and more consistent cache.
483
*/
484
if ( count( $trees ) > 1 ) :
485
- /**
486
- * Applies filter 'the_seo_framework_breadcrumb_post_sorting_callback' : string|array
487
- * @since 2.8.0
488
- *
489
- * @param mixed $function The method or function callback. Default false.
490
- * @param array $trees The current tree list.
491
- */
492
- $callback_filter = \apply_filters_ref_array( 'the_seo_framework_breadcrumb_post_sorting_callback', array( false, $trees ) );
493
- if ( $callback_filter ) {
494
$trees = $this->call_function( $callback_filter, '2.8.0', $trees );
495
} else {
496
array_multisort( array_map( 'count', $trees ), SORT_DESC, SORT_REGULAR, $trees );
497
}
498
endif;
499
500
- $item_type = $this->schema_listitem();
501
502
//* For each of the tree items, create a separated script.
503
- if ( $trees ) :
504
- foreach ( $trees as $tree_ids ) :
505
-
506
- if ( is_array( $tree_ids ) ) {
507
- //* Term has assigned children.
508
-
509
- /**
510
- * @staticvar int $item_cache : Used to prevent duplicated item re-generation.
511
- */
512
- static $item_cache = array();
513
-
514
- $items = '';
515
-
516
- //* Put the children in the right order.
517
- $tree_ids = array_reverse( $tree_ids, false );
518
-
519
- foreach ( $tree_ids as $position => $child_id ) :
520
- if ( in_array( $child_id, $assigned_ids, true ) ) :
521
- //* Cat has been assigned, continue.
522
-
523
- //* Fetch item from cache if available.
524
- if ( isset( $item_cache[ $child_id ] ) ) {
525
- $pos = $position + 2;
526
- $item_cache[ $child_id ]['pos'] = $pos;
527
- $items .= $this->make_breadcrumb( $item_cache[ $child_id ], true );
528
- } else {
529
- $pos = $position + 2;
530
-
531
- $cat = \get_term_by( 'id', $child_id, $cat_type, OBJECT, 'raw' );
532
- $data = $this->get_term_data( $cat, $child_id );
533
-
534
- $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'is_term' => true, 'term' => $cat ) ) );
535
-
536
- if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
537
- //* Note: WordPress Core translation.
538
- $cat_name = empty( $data['doctitle'] ) ? ( empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name ) : $data['doctitle'];
539
- } else {
540
- //* Note: WordPress Core translation.
541
- $cat_name = empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name;
542
- }
543
- $name = json_encode( $cat_name );
544
-
545
- $image = $this->schema_image( $child_id );
546
-
547
- //* Store in cache.
548
- $item_cache[ $child_id ] = array(
549
- 'type' => $item_type,
550
- 'pos' => (string) $pos,
551
- 'id' => $id,
552
- 'name' => $name,
553
- 'image' => $image,
554
- );
555
-
556
- $items .= $this->make_breadcrumb( $item_cache[ $child_id ], true );
557
- }
558
- endif;
559
- endforeach;
560
-
561
- if ( $items ) {
562
- $items = $this->ld_json_breadcrumb_first( $item_type ) . $items . $this->ld_json_breadcrumb_last( $item_type, $pos, $post_id );
563
- $output .= $this->make_breadcrumb_script( $items );
564
- }
565
- } else {
566
- //* No assigned children, single term item.
567
568
- //* The position of the current item is always static here.
569
- $pos = '2';
570
571
- $image = $this->schema_image( $tree_ids );
572
573
- //* $tree_ids is a single ID here.
574
- $cat = \get_term_by( 'id', $tree_ids, $cat_type, OBJECT, 'raw' );
575
- $data = $this->get_term_data( $cat, $tree_ids );
576
577
- $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'is_term' => true, 'external' => true, 'term' => $cat ) ) );
578
579
if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
580
//* Note: WordPress Core translation.
581
$cat_name = empty( $data['doctitle'] ) ? ( empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name ) : $data['doctitle'];
582
} else {
583
//* Note: WordPress Core translation.
584
$cat_name = empty( $cat->name ) ? \__( 'Uncategorized' ) : $cat->name;
585
}
586
- $name = json_encode( $cat_name );
587
-
588
- $item = array(
589
- 'type' => $item_type,
590
- 'pos' => (string) $pos,
591
- 'id' => $id,
592
- 'name' => $name,
593
- 'image' => $image,
594
- );
595
596
- $items = $this->make_breadcrumb( $item, true );
597
598
- if ( $items ) {
599
- $items = $this->ld_json_breadcrumb_first( $item_type ) . $items . $this->ld_json_breadcrumb_last( $item_type, $pos, $post_id );
600
- $output .= $this->make_breadcrumb_script( $items );
601
- }
602
}
603
endforeach;
604
- endif;
605
606
return $output;
607
}
608
609
/**
610
- * Generate page breadcrumb.
611
*
612
- * @since 2.6.0
613
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
614
*
615
- * @return string $output The breadcrumb script.
616
*/
617
- public function ld_json_breadcrumbs_page() {
618
-
619
- $output = '';
620
621
- $page_id = $this->get_the_real_ID();
622
-
623
- //* Get ancestors.
624
- $parents = \get_post_ancestors( $page_id );
625
-
626
- if ( $parents ) :
627
-
628
- $item_type = $this->schema_listitem();
629
-
630
- $items = '';
631
-
632
- $parents = array_reverse( $parents );
633
-
634
- foreach ( $parents as $position => $parent_id ) {
635
- $pos = $position + 2;
636
-
637
- $id = json_encode( $this->the_url( '', array( 'get_custom_field' => false, 'external' => true, 'id' => $parent_id ) ) );
638
-
639
- $title_args = array(
640
- 'term_id' => $parent_id,
641
- 'meta' => true,
642
- 'placeholder' => true,
643
- 'notagline' => true,
644
- 'description_title' => true,
645
- 'get_custom_field' => false,
646
- );
647
648
- if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
649
- $parent_name = $this->get_custom_field( '_genesis_title', $parent_id ) ?: $this->title( '', '', '', $title_args );
650
} else {
651
- $parent_name = $this->title( '', '', '', $title_args );
652
- }
653
-
654
- $name = json_encode( $parent_name );
655
- $image = $this->schema_image( $parent_id, true );
656
-
657
- $breadcrumb = array(
658
- 'type' => $item_type,
659
- 'pos' => (string) $pos,
660
- 'id' => $id,
661
- 'name' => $name,
662
- 'image' => $image,
663
- );
664
665
- $items .= $this->make_breadcrumb( $breadcrumb, true );
666
- }
667
668
- if ( $items ) {
669
670
- $items = $this->ld_json_breadcrumb_first( $item_type ) . $items . $this->ld_json_breadcrumb_last( $item_type, $pos, $page_id );
671
- $output = $this->make_breadcrumb_script( $items );
672
}
673
- endif;
674
675
- return $output;
676
}
677
678
/**
679
- * Return home page item for LD Json Breadcrumbs.
680
*
681
- * @since 2.4.2
682
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
683
- * @staticvar string $first_item.
684
*
685
- * @param string|null $item_type the breadcrumb item type.
686
- * @return string Home Breadcrumb item
687
*/
688
- public function ld_json_breadcrumb_first( $item_type = null ) {
689
690
- static $first_item = null;
691
692
- if ( isset( $first_item ) )
693
- return $first_item;
694
695
- if ( is_null( $item_type ) )
696
- $item_type = json_encode( 'ListItem' );
697
-
698
- $id = json_encode( $this->the_home_url_from_cache() );
699
700
if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
701
702
$home_title = $this->get_option( 'homepage_title' );
@@ -704,201 +700,110 @@ class Generate_Ldjson extends Generate_Image {
704
if ( $home_title ) {
705
$custom_name = $home_title;
706
} elseif ( $this->has_page_on_front() ) {
707
- $home_id = (int) \get_option( 'page_on_front' );
708
-
709
- $custom_name = $this->get_custom_field( '_genesis_title', $home_id ) ?: $this->get_blogname();
710
- } else {
711
- $custom_name = $this->get_blogname();
712
}
713
- } else {
714
- $custom_name = $this->get_blogname();
715
}
716
717
- $custom_name = json_encode( $custom_name );
718
- $image = $this->schema_image( $this->get_the_front_page_ID(), true );
719
720
- $breadcrumb = array(
721
- 'type' => $item_type,
722
- 'pos' => '1',
723
- 'id' => $id,
724
- 'name' => $custom_name,
725
- 'image' => $image,
726
);
727
728
- return $first_item = $this->make_breadcrumb( $breadcrumb, true );
729
}
730
731
/**
732
- * Return current page item for LD Json Breadcrumbs.
733
*
734
- * @since 2.4.2
735
- * @since 2.9.0 Now uses $this->ld_json_breadcrumbs_use_seo_title()
736
- * @staticvar string $last_item.
737
- * @staticvar string $type The breadcrumb item type.
738
- * @staticvar string $id The current post/page/archive url.
739
- * @staticvar string $name The current post/page/archive title.
740
*
741
- * @param string $item_type the breadcrumb item type.
742
- * @param int $pos Last known position.
743
- * @param int $post_id The current Post ID
744
- * @return string Last Breadcrumb item
745
*/
746
- public function ld_json_breadcrumb_last( $item_type = null, $pos = null, $post_id = null ) {
747
748
- /**
749
- * 2 (becomes 3) holds mostly true for single term items.
750
- * This shouldn't run anyway. Pos should always be provided.
751
- */
752
- if ( is_null( $pos ) )
753
- $pos = 2;
754
755
- //* Add current page.
756
- $pos = $pos + 1;
757
758
- if ( is_null( $item_type ) ) {
759
- static $type = null;
760
-
761
- if ( ! isset( $type ) )
762
- $type = json_encode( 'ListItem' );
763
-
764
- $item_type = $type;
765
}
766
767
- if ( empty( $post_id ) )
768
- $post_id = $this->get_the_real_ID();
769
-
770
- static $id = null;
771
- static $name = null;
772
-
773
- if ( ! isset( $id ) )
774
- $id = json_encode( $this->the_url_from_cache() );
775
-
776
- $title_args = array(
777
- 'term_id' => $post_id,
778
- 'placeholder' => true,
779
- 'meta' => true,
780
- 'notagline' => true,
781
- 'description_title' => true,
782
- 'get_custom_field' => false,
783
- );
784
785
- if ( ! isset( $name ) ) {
786
- if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
787
- $name = $this->get_custom_field( '_genesis_title', $post_id ) ?: $this->title( '', '', '', $title_args );
788
- } else {
789
- $name = $this->title( '', '', '', $title_args );
790
- }
791
- $name = json_encode( $name );
792
}
793
794
- $image = $this->schema_image( $post_id, true );
795
-
796
- $breadcrumb = array(
797
- 'type' => $item_type,
798
- 'pos' => (string) $pos,
799
- 'id' => $id,
800
- 'name' => $name,
801
- 'image' => $image,
802
);
803
804
- return $this->make_breadcrumb( $breadcrumb, false );
805
- }
806
807
- /**
808
- * Builds a breadcrumb.
809
- *
810
- * @since 2.6.0
811
- * @since 2.9.0 : No longer outputs image if it's not present.
812
- * @param array $item : {
813
- * 'type',
814
- * 'pos',
815
- * 'id',
816
- * 'name'
817
- * }
818
- * @param bool $comma Whether to add a trailing comma.
819
- * @return string The LD+Json breadcrumb.
820
- */
821
- public function make_breadcrumb( $item, $comma = true ) {
822
-
823
- $comma = $comma ? ',' : '';
824
-
825
- if ( $item['image'] && '""' !== $item['image'] ) {
826
- $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 );
827
- } else {
828
- $retval = sprintf( '{"@type":%s,"position":%s,"item":{"@id":%s,"name":%s}}%s', $item['type'], $item['pos'], $item['id'], $item['name'], $comma );
829
- }
830
-
831
- return $retval;
832
}
833
834
/**
835
- * Puts breadcrumb items in script wrapper.
836
*
837
* @since 2.9.0
838
*
839
- * @param string $items The breadcrumb items
840
- * @return string The breadcrumb script tag.
841
*/
842
- protected function make_breadcrumb_script( $items = '' ) {
843
-
844
- if ( $items ) {
845
- $context = $this->schema_context();
846
- $context_type = $this->schema_breadcrumblist();
847
-
848
- //* Put it all together.
849
- $breadcrumbhelper = sprintf( '{"@context":%s,"@type":%s,"itemListElement":[%s]}', $context, $context_type, $items );
850
- return '<script type="application/ld+json">' . $breadcrumbhelper . '</script>' . "\r\n";
851
- }
852
853
- return '';
854
- }
855
856
- /**
857
- * Builds breadcrumb trees.
858
- *
859
- * @since 2.6.0
860
- *
861
- * @param array $kittens The breadcrumb trees, with the key as parent.
862
- * @param array $previous_tree A previous set tree to compare to, if set.
863
- * @return array Trees in order.
864
- */
865
- protected function build_breadcrumb_trees( $kittens, array $previous_tree = array() ) {
866
867
- $trees = $previous_tree;
868
869
- foreach ( $kittens as $parent => $kitten ) {
870
- if ( empty( $kitten ) ) {
871
- //* Final cat.
872
- $trees[] = $parent;
873
- } else {
874
- if ( 1 === count( $kitten ) ) {
875
- //* Single tree.
876
- $trees[] = array( reset( $kitten ), $parent );
877
- } else {
878
- //* Nested categories.
879
- $add = array();
880
881
- foreach ( $kitten as $kit_id => $child_id ) {
882
- //* Only add if non-existent in $trees.
883
- if ( ! in_array( $child_id, $trees, true ) )
884
- $add[] = $child_id;
885
- }
886
887
- //* Put children in right order.
888
- $add = array_reverse( $add );
889
890
- $trees[] = array_merge( $add, array( $parent ) );
891
- }
892
- }
893
- }
894
895
- return $trees;
896
}
897
898
/**
899
* Determines whether to use the SEO title or only the fallback page title.
900
*
901
- * Does not affect cache.
902
*
903
* @since 2.9.0
904
* @staticvar bool $cache
@@ -915,137 +820,12 @@ class Generate_Ldjson extends Generate_Image {
915
* Determines whether to use the SEO title or only the fallback page title
916
* in breadcrumbs.
917
*
918
- * @param $retval bool
919
*/
920
return isset( $cache ) ? $cache : $cache = (bool) \apply_filters( 'the_seo_framework_use_breadcrumb_seo_title', true );
921
}
922
923
- /**
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
- */
931
- public function ld_json_knowledge() {
932
-
933
- if ( false === $this->enable_ld_json_knowledge() )
934
- return '';
935
-
936
- $knowledge_type = $this->get_option( 'knowledge_type' );
937
-
938
- /**
939
- * Forgot to add this.
940
- * @since 2.4.3
941
- */
942
- $knowledge_name = $this->get_option( 'knowledge_name' ) ?: $this->get_blogname();
943
-
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
-
951
- if ( $this->get_option( 'knowledge_logo' ) && 'organization' === $knowledge_type ) {
952
- $_logo = $this->get_site_logo() ?: $this->get_site_icon();
953
-
954
- if ( $_logo ) {
955
- $logourl = \esc_url_raw( $_logo );
956
-
957
- //* Add trailing comma
958
- $logo = '"logo":' . json_encode( $logourl );
959
- }
960
- }
961
-
962
- /**
963
- * Applies filters 'the_seo_framework_json_options' : array The option names
964
- * @since ???
965
- * @todo Document.
966
- */
967
- $options = (array) \apply_filters( 'the_seo_framework_json_options', array(
968
- 'knowledge_facebook',
969
- 'knowledge_twitter',
970
- 'knowledge_gplus',
971
- 'knowledge_instagram',
972
- 'knowledge_youtube',
973
- 'knowledge_linkedin',
974
- 'knowledge_pinterest',
975
- 'knowledge_soundcloud',
976
- 'knowledge_tumblr',
977
- ) );
978
-
979
- $sameurls = '';
980
- $comma = ',';
981
-
982
- //* Put the urls together from the options.
983
- if ( is_array( $options ) ) {
984
- foreach ( $options as $option ) {
985
- $the_option = $this->get_option( $option );
986
-
987
- if ( '' !== $the_option )
988
- $sameurls .= json_encode( $the_option ) . $comma;
989
- }
990
- }
991
-
992
- //* Remove trailing comma
993
- $sameurls = rtrim( $sameurls, $comma );
994
- $json = '';
995
-
996
- $logo = $logo ? ',' . $logo : '';
997
-
998
- if ( $sameurls ) {
999
- $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s%s,"sameAs":[%s]}', $context, $type, $name, $url, $logo, $sameurls );
1000
- } else {
1001
- $json = sprintf( '{"@context":%s,"@type":%s,"name":%s,"url":%s%s}', $context, $type, $name, $url, $logo );
1002
- }
1003
-
1004
- $output = '';
1005
- if ( $json )
1006
- $output = '<script type="application/ld+json">' . $json . '</script>' . "\r\n";
1007
-
1008
- return $output;
1009
- }
1010
-
1011
- /**
1012
- * Generate Site Name LD+Json script.
1013
- *
1014
- * @since 2.6.0
1015
- *
1016
- * @return string The LD+JSon Site Name script.
1017
- */
1018
- public function ld_json_name() {
1019
-
1020
- if ( false === $this->enable_ld_json_sitename() )
1021
- return '';
1022
-
1023
- $context = $this->schema_context();
1024
- $webtype = $this->schema_type();
1025
- $url = $this->schema_home_url();
1026
- $name = $this->schema_blog_name();
1027
- $alternate = '';
1028
-