Version Description
- Perfect =
Come with me, and you'll be in a world of pure imagination. - Gene Wilder, Anthony Newley, Leslie Bricusse
Release highlights
- This update brings new post-type-archive settings. You can now edit their titles, descriptions, social and visibility settings, and even add redirects on the SEO Settings page.
- Fancy a custom site title for SEO purposes only? Check out the new title settings.
- You will find that the sitemap's stylesheet now has its URLs centered; it also supports mobile devices.
- Developers can now enjoy using the new
tsf()
function -- an alias ofthe_seo_framework()
. - If you're a developer, you should also check out our perfectly tuned
memo()
.umemo()
, andfmemo()
functions, which help make TSF so performant.
Psst: Check out our Cyber Sale.
Perfect
TSF is finally what I (Sybre) envisioned it to become when I first named it "The SEO Framework": It's lightning-fast, hassle-free, and has all necessary options while giving you the best in class experience. I hope you enjoy what I believe is a perfect product!
To me, The SEO Framework is finished. Done. It's excellent. This doesn't mean its journey ends here. Now, it's time to add features you want. A restyled interface, migration support, custom title generation, more structured data fields, and many other community proposals are under consideration.
A perfect tip
This update comes with updated browser styles and scripts. Not all browsers get these for you; so, the interface might appear broken (and your "inputs" seem to be "removed"). Try a different browser, or clear your favorite browser's cache. That ought to do the trick.
Environment upgrade notes
WordPress 5.1 through 5.4 are no longer supported. Here's why:
- Over 66% of all WordPress sites are using WordPress v5.5 or later.
- Newer versions of WordPress are faster, more reliable, and easier to work with; for both you and us.
- Supporting past versions takes time away that's better used implementing new features.
PHP 5.6 through 7.1 are no longer supported. Here's why:
- Almost 80% of all WordPress sites are using PHP v7.2 or later.
- Newer versions of PHP are faster and more secure. For us, they're also easier to work with.
- Again, supporting past versions takes time away that's better used implementing new features.
Support the development
We hope you'll love this update as much as we do. Please consider supporting us by sharing a fantastic review, get a license, or do your friends and colleagues a favor by installing TSF for them.
Detailed log
Practice makes perfect. So does working 16 hours a day.
Release Info
Developer | Cybr |
Plugin | The SEO Framework |
Version | 4.2.0 |
Comparing to | |
See all releases |
Code changes from version 4.1.5.1 to 4.2.0
- autodescription.php +55 -50
- bootstrap/activation.php +2 -2
- bootstrap/deactivation.php +1 -1
- bootstrap/define.php +10 -2
- bootstrap/envtest.php +0 -157
- bootstrap/load.php +16 -11
- bootstrap/upgrade.php +89 -97
- inc/classes/admin-init.class.php +88 -89
- inc/classes/admin-pages.class.php +50 -158
- inc/classes/bridges/ajax.class.php +44 -54
- inc/classes/bridges/feed.class.php +13 -25
- inc/classes/bridges/index.php +3 -2
- inc/classes/bridges/listedit.class.php +22 -24
- inc/classes/bridges/listtable.class.php +15 -17
- inc/classes/bridges/ping.class.php +32 -15
- inc/classes/bridges/plugintable.class.php +6 -4
- inc/classes/bridges/postsettings.class.php +15 -14
- inc/classes/bridges/scripts.class.php +102 -216
- inc/classes/bridges/seobar.class.php +7 -7
- inc/classes/bridges/seosettings.class.php +173 -143
- inc/classes/bridges/sitemap.class.php +75 -81
- inc/classes/bridges/termsettings.class.php +1 -1
- inc/classes/bridges/usersettings.class.php +3 -3
- inc/classes/builders/coresitemaps/main.class.php +5 -7
- inc/classes/builders/coresitemaps/posts.class.php +23 -16
- inc/classes/builders/coresitemaps/taxonomies.class.php +38 -39
- inc/classes/builders/images.class.php +17 -15
- inc/classes/builders/robots/args.class.php +162 -0
- inc/classes/builders/robots/factory.class.php +160 -0
- inc/classes/builders/robots/index.php +9 -0
- inc/classes/builders/robots/main.class.php +220 -0
- inc/classes/builders/robots/query.class.php +260 -0
- inc/classes/builders/scripts.class.php +44 -60
- inc/classes/builders/seobar/index.php +6 -0
- inc/classes/builders/{seobar.class.php → seobar/main.class.php} +16 -21
- inc/classes/builders/{seobar-page.class.php → seobar/page.class.php} +85 -84
- inc/classes/builders/{seobar-term.class.php → seobar/term.class.php} +74 -69
- inc/classes/builders/sitemap.class.php +8 -251
- inc/classes/builders/{sitemap-base.class.php → sitemap/base.class.php} +83 -131
- inc/classes/builders/sitemap/index.php +0 -0
- inc/classes/builders/sitemap/main.class.php +280 -0
- inc/classes/cache.class.php +67 -71
- inc/classes/core.class.php +138 -235
- inc/classes/detect.class.php +426 -513
- inc/classes/generate-description.class.php +239 -189
- inc/classes/generate-image.class.php +44 -27
- inc/classes/generate-ldjson.class.php +43 -116
- inc/classes/generate-title.class.php +394 -344
- inc/classes/generate-url.class.php +255 -193
- inc/classes/generate.class.php +148 -457
- inc/classes/index.php +1 -11
- inc/classes/init.class.php +176 -126
- inc/classes/{debug.class.php → internal/debug.class.php} +44 -73
- inc/classes/{deprecated.class.php → internal/deprecated.class.php} +809 -269
- inc/classes/internal/index.php +7 -0
- inc/classes/{silencer.class.php → internal/silencer.class.php} +7 -6
- inc/classes/interpreters/form.class.php +48 -338
- inc/classes/interpreters/html.class.php +58 -38
- inc/classes/interpreters/markdown.class.php +6 -3
- inc/classes/interpreters/seobar.class.php +70 -55
- inc/classes/interpreters/settings-input.class.php +208 -0
- inc/classes/interpreters/sitemap-xsl.class.php +186 -0
- inc/classes/load.class.php +17 -10
- inc/classes/post-data.class.php +61 -153
- inc/classes/query.class.php +240 -517
- inc/classes/render.class.php +105 -109
- inc/classes/sanitize.class.php +127 -94
- inc/classes/site-options.class.php +385 -419
- inc/classes/term-data.class.php +51 -79
- inc/classes/user-data.class.php +34 -45
- inc/compat/plugin-bbpress.php +6 -6
- inc/compat/plugin-buddypress.php +2 -2
- inc/compat/plugin-edd.php +3 -3
- inc/compat/plugin-elementor.php +25 -0
- inc/compat/plugin-polylang.php +28 -18
- inc/compat/plugin-ultimatemember.php +30 -93
- inc/compat/plugin-woocommerce.php +65 -42
- inc/compat/plugin-wpforo.php +5 -5
- inc/compat/plugin-wpml.php +6 -4
- inc/compat/theme-genesis.php +1 -1
- inc/functions/api.php +209 -28
- inc/functions/upgrade-suggestion.php +15 -35
- inc/views/admin/wrap-content.php +0 -60
- inc/views/debug/output.php +19 -14
- inc/views/edit/seo-settings-singular-gutenberg-data.php +1 -1
- inc/views/edit/seo-settings-singular.php +93 -62
- inc/views/edit/seo-settings-tt.php +40 -16
- inc/views/edit/wrap-content.php +26 -13
- inc/views/edit/wrap-nav.php +19 -15
- inc/views/list/bulk-post.php +1 -1
- inc/views/list/quick-post.php +1 -1
- inc/views/list/quick-term.php +1 -1
- inc/views/notice/persistent.php +1 -1
- inc/views/profile/author.php +1 -1
- inc/views/{admin/seo-settings-columns.php → settings/columns.php} +1 -1
- inc/views/{admin → settings}/index.php +0 -0
- inc/views/{admin/metaboxes/description-metabox.php → settings/metaboxes/description.php} +8 -11
- inc/views/{admin/metaboxes/feed-metabox.php → settings/metaboxes/feed.php} +9 -12
- inc/views/{admin/metaboxes/general-metabox.php → settings/metaboxes/general.php} +65 -79
- inc/views/{admin/metaboxes/homepage-metabox.php → settings/metaboxes/homepage.php} +124 -118
- inc/views/{admin → settings}/metaboxes/index.php +0 -0
- inc/views/settings/metaboxes/post-type-archive.php +469 -0
- inc/views/{admin/metaboxes/robots-metabox.php → settings/metaboxes/robots.php} +64 -73
- inc/views/{admin/metaboxes/schema-metabox.php → settings/metaboxes/schema.php} +55 -57
- inc/views/{admin/metaboxes/sitemaps-metabox.php → settings/metaboxes/sitemaps.php} +73 -84
- inc/views/{admin/metaboxes/social-metabox.php → settings/metaboxes/social.php} +67 -69
- inc/views/{admin/metaboxes/title-metabox.php → settings/metaboxes/title.php} +24 -23
@@ -3,12 +3,14 @@
|
|
3 |
* Plugin Name: The SEO Framework
|
4 |
* Plugin URI: https://theseoframework.com/
|
5 |
* Description: An automated, advanced, accessible, unbranded and extremely fast SEO solution for your WordPress website.
|
6 |
-
* Version: 4.
|
7 |
* Author: The SEO Framework Team
|
8 |
* Author URI: https://theseoframework.com/
|
9 |
* License: GPLv3
|
10 |
* Text Domain: autodescription
|
11 |
* Domain Path: /language
|
|
|
|
|
12 |
*
|
13 |
* @package The_SEO_Framework\Bootstrap
|
14 |
*/
|
@@ -32,13 +34,6 @@ defined( 'ABSPATH' ) or die;
|
|
32 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
33 |
*/
|
34 |
|
35 |
-
/**
|
36 |
-
* @NOTE This file MUST be written according to WordPress's minimum PHP requirements.
|
37 |
-
* Which is PHP 5.2.
|
38 |
-
* When we only support WordPress 5.2+, it'll be PHP 5.6.
|
39 |
-
* When we only support WordPress 5.9?+, it'll be PHP 7.1.
|
40 |
-
*/
|
41 |
-
|
42 |
/**
|
43 |
* The plugin version.
|
44 |
*
|
@@ -46,7 +41,7 @@ defined( 'ABSPATH' ) or die;
|
|
46 |
*
|
47 |
* @since 2.3.5
|
48 |
*/
|
49 |
-
define( 'THE_SEO_FRAMEWORK_VERSION', '4.
|
50 |
|
51 |
/**
|
52 |
* The plugin Database version.
|
@@ -55,7 +50,7 @@ define( 'THE_SEO_FRAMEWORK_VERSION', '4.1.5' );
|
|
55 |
*
|
56 |
* @since 2.7.0
|
57 |
*/
|
58 |
-
define( 'THE_SEO_FRAMEWORK_DB_VERSION', '
|
59 |
|
60 |
/**
|
61 |
* The plugin file, absolute unix path.
|
@@ -71,45 +66,55 @@ define( 'THE_SEO_FRAMEWORK_PLUGIN_BASE_FILE', __FILE__ );
|
|
71 |
*/
|
72 |
define( 'THE_SEO_FRAMEWORK_BOOTSTRAP_PATH', dirname( THE_SEO_FRAMEWORK_PLUGIN_BASE_FILE ) . DIRECTORY_SEPARATOR . 'bootstrap' . DIRECTORY_SEPARATOR );
|
73 |
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
|
114 |
// phpcs:disable, Squiz.Commenting.InlineComment, Squiz.PHP.CommentedOutCode
|
115 |
//
|
@@ -126,8 +131,8 @@ function the_seo_framework_boot() {
|
|
126 |
// ( $_GET['reset_tsf_upgrade'] ?? 0 ) and delete_option( 'the_seo_framework_upgraded_db_version' ) and delete_option( 'the_seo_framework_initial_db_version' );
|
127 |
// ( $_GET['downgrade_tsf'] ?? 0 ) and update_option( 'the_seo_framework_upgraded_db_version', (string) (int) $_GET['downgrade_tsf'] );
|
128 |
// ( $_GET['downgrade_tsf_initial'] ?? 0 ) and update_option( 'the_seo_framework_initial_db_version', (string) (int) $_GET['downgrade_tsf_initial'] );
|
129 |
-
// ( $_GET['reset_tsf_tested'] ?? 0 ) and delete_option( 'the_seo_framework_tested_upgrade_version' );
|
130 |
// ( $_GET['tsf_headless'] ?? 0 ) and define( 'THE_SEO_FRAMEWORK_HEADLESS', $_GET['tsf_headless'] === 'true' ?: $_GET['tsf_headless'] );
|
|
|
131 |
// }
|
132 |
// }},0);
|
133 |
// phpcs:enable, Squiz.Commenting.InlineComment, Squiz.PHP.CommentedOutCode
|
3 |
* Plugin Name: The SEO Framework
|
4 |
* Plugin URI: https://theseoframework.com/
|
5 |
* Description: An automated, advanced, accessible, unbranded and extremely fast SEO solution for your WordPress website.
|
6 |
+
* Version: 4.2.0
|
7 |
* Author: The SEO Framework Team
|
8 |
* Author URI: https://theseoframework.com/
|
9 |
* License: GPLv3
|
10 |
* Text Domain: autodescription
|
11 |
* Domain Path: /language
|
12 |
+
* Requires at least: 5.5
|
13 |
+
* Requires PHP: 7.2.0
|
14 |
*
|
15 |
* @package The_SEO_Framework\Bootstrap
|
16 |
*/
|
34 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
35 |
*/
|
36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
/**
|
38 |
* The plugin version.
|
39 |
*
|
41 |
*
|
42 |
* @since 2.3.5
|
43 |
*/
|
44 |
+
define( 'THE_SEO_FRAMEWORK_VERSION', '4.2.0' );
|
45 |
|
46 |
/**
|
47 |
* The plugin Database version.
|
50 |
*
|
51 |
* @since 2.7.0
|
52 |
*/
|
53 |
+
define( 'THE_SEO_FRAMEWORK_DB_VERSION', '4200' );
|
54 |
|
55 |
/**
|
56 |
* The plugin file, absolute unix path.
|
66 |
*/
|
67 |
define( 'THE_SEO_FRAMEWORK_BOOTSTRAP_PATH', dirname( THE_SEO_FRAMEWORK_PLUGIN_BASE_FILE ) . DIRECTORY_SEPARATOR . 'bootstrap' . DIRECTORY_SEPARATOR );
|
68 |
|
69 |
+
// Defines environental constants.
|
70 |
+
require THE_SEO_FRAMEWORK_BOOTSTRAP_PATH . 'define.php';
|
71 |
+
|
72 |
+
// Load plugin API functions.
|
73 |
+
require THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'api.php';
|
74 |
+
|
75 |
+
// Prepare plugin upgrader before the plugin loads. This may also downgrade (3103 or higher).
|
76 |
+
the_seo_framework_db_version() !== THE_SEO_FRAMEWORK_DB_VERSION
|
77 |
+
and require THE_SEO_FRAMEWORK_BOOTSTRAP_PATH . 'upgrade.php';
|
78 |
+
|
79 |
+
// Load deprecated functions.
|
80 |
+
// require THE_SEO_FRAMEWORK_DIR_PATH_FUNCT . 'deprecated.php';
|
81 |
+
|
82 |
+
// Load plugin.
|
83 |
+
require THE_SEO_FRAMEWORK_BOOTSTRAP_PATH . 'load.php';
|
84 |
+
|
85 |
+
// # Zelda is here to protect your site from hackers.
|
86 |
+
// #
|
87 |
+
// # OLLLLLLLLL
|
88 |
+
// # GGOiiiiiiiilGGG
|
89 |
+
// # GGGOllttttttttttlllll
|
90 |
+
// # GG1111tt1;;;;;;lltttt..L
|
91 |
+
// # GttLLLLttiiiiiii;;tttl..,;
|
92 |
+
// # GGtLLLLLLLLLiiiiiiii;tttttt,,
|
93 |
+
// # GllLLLLLLLLLLLLiiiiiii;;tttt,,.
|
94 |
+
// # ,;OttLLLLLLtttLttiiii;;i;;:ttt::. ttttG
|
95 |
+
// # ;;Olll;;:::ittL::,;;;;;;ii;ttttt. i.iii..
|
96 |
+
// # ;,iiiii:LL:,,:iiiii;ii;ttttt. ;::iii0..
|
97 |
+
// # ,,...,,;;;,.....,ii;ii;...ll. :::OO,GG.
|
98 |
+
// # , L...........,::O::.00Gii;ii;ll.11. .,,G,,0..
|
99 |
+
// # , L..0000LL000LLL0::.00Gii,;;l..lll. ... ..,00,00.
|
100 |
+
// # , L..L;;;..1LLLLLLLL1iiiii,ll;ttt11t..:::. .,,0,,0..
|
101 |
+
// # , L..O;;i;;;;;LLLLLLiiiiii,;;L;;t11t..:ii.;;,0i:0;,
|
102 |
+
// # , L..Oiii;;;;;LLL1iiiii,::t,,t111::1:::00.,,,00L..
|
103 |
+
// # , L..Oiiiii:::t.........::tttt11tttttt:::.OOiii.
|
104 |
+
// # , L..Oiit00tttLlll11lttt;;tll1llllltttt..GGGO:::..
|
105 |
+
// # , L..L..;00tttOii...:tt;;;tll::::::lttttt.OO::::::.
|
106 |
+
// # , L..O;;L00:::011;..l::;tttll:.. ;::lll...:::0ii.
|
107 |
+
// # , L..L;;L00:::011;..llllttttt. :..:..LLL.......
|
108 |
+
// # , L..L::;GGLLL011;,,iGGGOOGGGG:: ;;;GG.....
|
109 |
+
// # , :LLiiiiiiiii.iiGOOOGGtttt.. ;;;::.
|
110 |
+
// # ,:LLiiiiiiiii.lltttttttttl.. :;
|
111 |
+
// # ::tiiiiiittllllllllllllll.
|
112 |
+
// # tt:ttiiit;;::::::::::::::::::
|
113 |
+
// # l::iii:..:OOO.. :::::0,,
|
114 |
+
// # 11;;;,;;:OO. ,::L;;:
|
115 |
+
// # 1..Lll;.. .ll1tt.
|
116 |
+
// # 11t11l11, .ll111l.. It's Link?! Not Zelda??
|
117 |
+
// # ll...... ........ - Sybre drew this by hand.
|
118 |
|
119 |
// phpcs:disable, Squiz.Commenting.InlineComment, Squiz.PHP.CommentedOutCode
|
120 |
//
|
131 |
// ( $_GET['reset_tsf_upgrade'] ?? 0 ) and delete_option( 'the_seo_framework_upgraded_db_version' ) and delete_option( 'the_seo_framework_initial_db_version' );
|
132 |
// ( $_GET['downgrade_tsf'] ?? 0 ) and update_option( 'the_seo_framework_upgraded_db_version', (string) (int) $_GET['downgrade_tsf'] );
|
133 |
// ( $_GET['downgrade_tsf_initial'] ?? 0 ) and update_option( 'the_seo_framework_initial_db_version', (string) (int) $_GET['downgrade_tsf_initial'] );
|
|
|
134 |
// ( $_GET['tsf_headless'] ?? 0 ) and define( 'THE_SEO_FRAMEWORK_HEADLESS', $_GET['tsf_headless'] === 'true' ?: $_GET['tsf_headless'] );
|
135 |
+
// add_action( 'admin_footer', function() { print( '<script>jQuery.migrateMute=true;</script>' ); } );
|
136 |
// }
|
137 |
// }},0);
|
138 |
// phpcs:enable, Squiz.Commenting.InlineComment, Squiz.PHP.CommentedOutCode
|
@@ -44,7 +44,7 @@ _activation_set_plugin_check_caches();
|
|
44 |
*/
|
45 |
function _activation_set_plugin_check_caches() {
|
46 |
|
47 |
-
$tsf = \
|
48 |
|
49 |
if ( $tsf->loaded ) {
|
50 |
$tsf->set_plugin_check_caches();
|
@@ -60,7 +60,7 @@ function _activation_set_plugin_check_caches() {
|
|
60 |
*/
|
61 |
function _activation_set_options_autoload() {
|
62 |
|
63 |
-
$tsf = \
|
64 |
|
65 |
if ( $tsf->loaded ) {
|
66 |
$options = $tsf->get_all_options();
|
44 |
*/
|
45 |
function _activation_set_plugin_check_caches() {
|
46 |
|
47 |
+
$tsf = \tsf();
|
48 |
|
49 |
if ( $tsf->loaded ) {
|
50 |
$tsf->set_plugin_check_caches();
|
60 |
*/
|
61 |
function _activation_set_options_autoload() {
|
62 |
|
63 |
+
$tsf = \tsf();
|
64 |
|
65 |
if ( $tsf->loaded ) {
|
66 |
$options = $tsf->get_all_options();
|
@@ -41,7 +41,7 @@ _deactivation_unset_options_autoload();
|
|
41 |
*/
|
42 |
function _deactivation_unset_options_autoload() {
|
43 |
|
44 |
-
$the_seo_framework = \
|
45 |
|
46 |
if ( $the_seo_framework->loaded ) {
|
47 |
$options = $the_seo_framework->get_all_options();
|
41 |
*/
|
42 |
function _deactivation_unset_options_autoload() {
|
43 |
|
44 |
+
$the_seo_framework = \tsf();
|
45 |
|
46 |
if ( $the_seo_framework->loaded ) {
|
47 |
$options = $the_seo_framework->get_all_options();
|
@@ -163,7 +163,7 @@ namespace The_SEO_Framework;
|
|
163 |
* @since 4.0.0
|
164 |
* @see \The_SEO_Framework\Generate\robots_meta()
|
165 |
*/
|
166 |
-
const ROBOTS_IGNORE_PROTECTION =
|
167 |
|
168 |
/**
|
169 |
* Robots setting, ignore settings.
|
@@ -171,4 +171,12 @@ const ROBOTS_IGNORE_PROTECTION = 0b01;
|
|
171 |
* @since 4.0.0
|
172 |
* @see \The_SEO_Framework\Generate\robots_meta()
|
173 |
*/
|
174 |
-
const ROBOTS_IGNORE_SETTINGS =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
* @since 4.0.0
|
164 |
* @see \The_SEO_Framework\Generate\robots_meta()
|
165 |
*/
|
166 |
+
const ROBOTS_IGNORE_PROTECTION = 0b001;
|
167 |
|
168 |
/**
|
169 |
* Robots setting, ignore settings.
|
171 |
* @since 4.0.0
|
172 |
* @see \The_SEO_Framework\Generate\robots_meta()
|
173 |
*/
|
174 |
+
const ROBOTS_IGNORE_SETTINGS = 0b010;
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Robots setting, enable asserting.
|
178 |
+
*
|
179 |
+
* @since 4.2.0
|
180 |
+
* @see \The_SEO_Framework\Generate\robots_meta()
|
181 |
+
*/
|
182 |
+
const ROBOTS_ASSERT = 0b100;
|
@@ -1,157 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* @package The_SEO_Framework\Bootstrap\Install
|
4 |
-
*
|
5 |
-
* @NOTE This file MUST be written according to WordPress's minimum PHP requirements.
|
6 |
-
* Which is PHP 5.2.
|
7 |
-
* When we only support WordPress 5.2+, it'll be PHP 5.6.
|
8 |
-
* When we only support WordPress 5.6?+, it'll be PHP 7.1.
|
9 |
-
*
|
10 |
-
* This file can be removed when we only support WordPress 5.2 or later. However, their
|
11 |
-
* onboarding message isn't as useful, informative, or even as friendly.
|
12 |
-
*
|
13 |
-
* To use that, we need to add these plugin headers in the plugin's main PHP file:
|
14 |
-
* Requires PHP: 5.6.5
|
15 |
-
* Requires at least: 5.1
|
16 |
-
*/
|
17 |
-
|
18 |
-
defined( 'THE_SEO_FRAMEWORK_DB_VERSION' ) or die;
|
19 |
-
|
20 |
-
/**
|
21 |
-
* The SEO Framework plugin
|
22 |
-
* Copyright (C) 2018 - 2021 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/)
|
23 |
-
*
|
24 |
-
* This program is free software: you can redistribute it and/or modify
|
25 |
-
* it under the terms of the GNU General Public License version 3 as published
|
26 |
-
* by the Free Software Foundation.
|
27 |
-
*
|
28 |
-
* This program is distributed in the hope that it will be useful,
|
29 |
-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
30 |
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
31 |
-
* GNU General Public License for more details.
|
32 |
-
*
|
33 |
-
* You should have received a copy of the GNU General Public License
|
34 |
-
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
35 |
-
*/
|
36 |
-
|
37 |
-
/**
|
38 |
-
* This file holds functions for testing the plugin after upgrade.
|
39 |
-
* This file will only be called ONCE if the required version option is lower
|
40 |
-
* compared to The SEO Framework version constant.
|
41 |
-
*
|
42 |
-
* @since 3.1.0
|
43 |
-
* @access private
|
44 |
-
*/
|
45 |
-
|
46 |
-
the_seo_framework_pre_boot_test();
|
47 |
-
/**
|
48 |
-
* Tests plugin upgrade.
|
49 |
-
*
|
50 |
-
* @since 3.1.0
|
51 |
-
* @since 4.0.5 No longer assumes the main blog (WP Multisite) has been tested, although that's very likely when updated via the interface.
|
52 |
-
* @access private
|
53 |
-
* @link http://php.net/eol.php
|
54 |
-
* @link https://codex.wordpress.org/WordPress_Versions
|
55 |
-
*/
|
56 |
-
function the_seo_framework_pre_boot_test() {
|
57 |
-
|
58 |
-
$ms = is_multisite();
|
59 |
-
|
60 |
-
if ( $ms && function_exists( 'get_network' ) ) {
|
61 |
-
// Try bypassing testing and deactivation gaming when the main blog has already been tested.
|
62 |
-
|
63 |
-
/**
|
64 |
-
* @since 2.9.4
|
65 |
-
* Delete old and redundant network option.
|
66 |
-
*/
|
67 |
-
delete_site_option( 'the_seo_framework_tested_upgrade_version' );
|
68 |
-
|
69 |
-
$nw = get_network();
|
70 |
-
if ( $nw instanceof WP_Network ) {
|
71 |
-
if ( get_blog_option( $nw->site_id, 'the_seo_framework_tested_upgrade_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION ) {
|
72 |
-
update_option( 'the_seo_framework_tested_upgrade_version', THE_SEO_FRAMEWORK_DB_VERSION );
|
73 |
-
return;
|
74 |
-
}
|
75 |
-
}
|
76 |
-
//= Free memory.
|
77 |
-
unset( $nw );
|
78 |
-
}
|
79 |
-
|
80 |
-
$requirements = array(
|
81 |
-
'php' => 50600,
|
82 |
-
'wp' => '5.1-dev',
|
83 |
-
);
|
84 |
-
|
85 |
-
// phpcs:disable, Generic.Formatting.MultipleStatementAlignment, WordPress.WhiteSpace.PrecisionAlignment
|
86 |
-
! defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < $requirements['php'] and $test = 1
|
87 |
-
or version_compare( $GLOBALS['wp_version'], $requirements['wp'], '<' ) and $test = 2
|
88 |
-
or $test = true;
|
89 |
-
// phpcs:enable, Generic.Formatting.MultipleStatementAlignment, WordPress.WhiteSpace.PrecisionAlignment
|
90 |
-
|
91 |
-
// All good.
|
92 |
-
if ( true === $test ) {
|
93 |
-
update_option( 'the_seo_framework_tested_upgrade_version', THE_SEO_FRAMEWORK_DB_VERSION );
|
94 |
-
return;
|
95 |
-
}
|
96 |
-
|
97 |
-
if ( $ms ) {
|
98 |
-
$_plugins = get_site_option( 'active_sitewide_plugins' );
|
99 |
-
$network_mode = isset( $_plugins[ plugin_basename( THE_SEO_FRAMEWORK_PLUGIN_BASE_FILE ) ] );
|
100 |
-
} else {
|
101 |
-
$network_mode = false;
|
102 |
-
}
|
103 |
-
|
104 |
-
if ( ! function_exists( 'deactivate_plugins' ) )
|
105 |
-
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
106 |
-
|
107 |
-
$admin = is_admin();
|
108 |
-
$silent = ! $admin;
|
109 |
-
|
110 |
-
// Not good. Deactivate plugin.
|
111 |
-
deactivate_plugins( plugin_basename( THE_SEO_FRAMEWORK_PLUGIN_BASE_FILE ), $silent, $network_mode );
|
112 |
-
|
113 |
-
// Don't die on front-end. Live, my friend.
|
114 |
-
if ( ! $admin )
|
115 |
-
return;
|
116 |
-
|
117 |
-
switch ( $test ) :
|
118 |
-
case 1:
|
119 |
-
// PHP requirements not met, always count up to encourage best standards.
|
120 |
-
$requirement = 'PHP 5.6.0 or later';
|
121 |
-
$issue = 'PHP version';
|
122 |
-
$version = PHP_VERSION;
|
123 |
-
$subtitle = 'Server Requirements';
|
124 |
-
break;
|
125 |
-
|
126 |
-
case 2:
|
127 |
-
// WordPress requirements not met.
|
128 |
-
$requirement = 'WordPress 5.1 or later';
|
129 |
-
$issue = 'WordPress version';
|
130 |
-
$version = $GLOBALS['wp_version'];
|
131 |
-
$subtitle = 'WordPress Requirements';
|
132 |
-
break;
|
133 |
-
|
134 |
-
default:
|
135 |
-
wp_die( 'oi' );
|
136 |
-
break;
|
137 |
-
endswitch;
|
138 |
-
|
139 |
-
// network_admin_url() falls back to admin_url() on single. But networks can enable single too.
|
140 |
-
$pluginspage = $network_mode ? network_admin_url( 'plugins.php' ) : admin_url( 'plugins.php' );
|
141 |
-
|
142 |
-
// Let's have some fun with teapots.
|
143 |
-
$response = floor( time() / DAY_IN_SECONDS ) === floor( strtotime( 'first day of April ' . gmdate( 'Y' ) ) / DAY_IN_SECONDS ) ? 418 : 500;
|
144 |
-
|
145 |
-
wp_die(
|
146 |
-
sprintf(
|
147 |
-
'<p><strong>The SEO Framework</strong> requires <em>%s</em>. Sorry about that!<br>Your %s is: <code>%s</code></p>
|
148 |
-
<p>Do you want to <strong><a onclick="window.history.back()" href="%s">go back</a></strong>?</p>',
|
149 |
-
esc_html( $requirement ),
|
150 |
-
esc_html( $issue ),
|
151 |
-
esc_html( $version ),
|
152 |
-
esc_url( $pluginspage )
|
153 |
-
),
|
154 |
-
esc_attr( sprintf( 'The SEO Framework « %s', $subtitle ) ),
|
155 |
-
array( 'response' => intval( $response ) )
|
156 |
-
);
|
157 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -52,7 +52,8 @@ function _init_locale() {
|
|
52 |
*
|
53 |
* @since 3.1.0
|
54 |
* @access private
|
55 |
-
* @see function
|
|
|
56 |
* @factory
|
57 |
*
|
58 |
* @return object|null The SEO Framework Facade class object. Null on failure.
|
@@ -94,13 +95,13 @@ function _init_tsf() {
|
|
94 |
*/
|
95 |
\do_action( 'the_seo_framework_loaded' );
|
96 |
} else {
|
97 |
-
$tsf = new Silencer();
|
98 |
$tsf->loaded = false;
|
99 |
}
|
100 |
|
101 |
// did_action() checks for current action too.
|
102 |
if ( ! \did_action( 'plugins_loaded' ) )
|
103 |
-
$tsf->_doing_it_wrong( 'the_seo_framework() or ' . __FUNCTION__, 'Use <code>
|
104 |
|
105 |
return $tsf;
|
106 |
}
|
@@ -111,11 +112,12 @@ spl_autoload_register( __NAMESPACE__ . '\\_autoload_classes', true, true );
|
|
111 |
* the plugin classes.
|
112 |
*
|
113 |
* @since 2.8.0
|
114 |
-
* @since 3.1.0
|
115 |
-
*
|
116 |
-
* @since 4.0.0
|
117 |
-
*
|
118 |
-
*
|
|
|
119 |
* @uses THE_SEO_FRAMEWORK_DIR_PATH_CLASS
|
120 |
* @access private
|
121 |
*
|
@@ -127,7 +129,10 @@ spl_autoload_register( __NAMESPACE__ . '\\_autoload_classes', true, true );
|
|
127 |
*/
|
128 |
function _autoload_classes( $class ) {
|
129 |
|
130 |
-
|
|
|
|
|
|
|
131 |
|
132 |
static $_timenow = true;
|
133 |
// Lock $_timenow to prevent stacking timers during class extending. This is released when the class stack loaded.
|
@@ -138,7 +143,7 @@ function _autoload_classes( $class ) {
|
|
138 |
$_bootstrap_timer = 0;
|
139 |
}
|
140 |
|
141 |
-
$_chunks = explode( '\\',
|
142 |
$_chunck_count = \count( $_chunks );
|
143 |
|
144 |
if ( $_chunck_count > 2 ) {
|
@@ -152,7 +157,7 @@ function _autoload_classes( $class ) {
|
|
152 |
$file = str_replace( '_', '-', end( $_chunks ) );
|
153 |
|
154 |
// The extension is deemed to be ".class.php" always. We may wish to alter this for traits?
|
155 |
-
require THE_SEO_FRAMEWORK_DIR_PATH_CLASS . $rel_dir
|
156 |
|
157 |
if ( $_bootstrap_timer ) {
|
158 |
_bootstrap_timer( microtime( true ) - $_bootstrap_timer );
|
52 |
*
|
53 |
* @since 3.1.0
|
54 |
* @access private
|
55 |
+
* @see function tsf().
|
56 |
+
* @see function tsf().
|
57 |
* @factory
|
58 |
*
|
59 |
* @return object|null The SEO Framework Facade class object. Null on failure.
|
95 |
*/
|
96 |
\do_action( 'the_seo_framework_loaded' );
|
97 |
} else {
|
98 |
+
$tsf = new Internal\Silencer();
|
99 |
$tsf->loaded = false;
|
100 |
}
|
101 |
|
102 |
// did_action() checks for current action too.
|
103 |
if ( ! \did_action( 'plugins_loaded' ) )
|
104 |
+
$tsf->_doing_it_wrong( 'tsf(), the_seo_framework(), or ' . __FUNCTION__, 'Use <code>tsf()</code> after action <code>plugins_loaded</code> priority 5.', '3.1' );
|
105 |
|
106 |
return $tsf;
|
107 |
}
|
112 |
* the plugin classes.
|
113 |
*
|
114 |
* @since 2.8.0
|
115 |
+
* @since 3.1.0 1. No longer maintains cache.
|
116 |
+
* 2. Now always returns void.
|
117 |
+
* @since 4.0.0 1. Streamlined folder lookup by more effectively using the namespace.
|
118 |
+
* 2. Added timing functionality
|
119 |
+
* 3. No longer loads interfaces automatically.
|
120 |
+
* @since 4.2.0 Now supports mixed class case.
|
121 |
* @uses THE_SEO_FRAMEWORK_DIR_PATH_CLASS
|
122 |
* @access private
|
123 |
*
|
129 |
*/
|
130 |
function _autoload_classes( $class ) {
|
131 |
|
132 |
+
$class = strtolower( $class );
|
133 |
+
|
134 |
+
// It's The_SEO_Framework, not the_seo_framework! -- Sybre's a nightmare, honestly! No wonder he hasn't gotten any friends.
|
135 |
+
if ( 0 !== strpos( $class, 'the_seo_framework\\', 0 ) ) return;
|
136 |
|
137 |
static $_timenow = true;
|
138 |
// Lock $_timenow to prevent stacking timers during class extending. This is released when the class stack loaded.
|
143 |
$_bootstrap_timer = 0;
|
144 |
}
|
145 |
|
146 |
+
$_chunks = explode( '\\', $class );
|
147 |
$_chunck_count = \count( $_chunks );
|
148 |
|
149 |
if ( $_chunck_count > 2 ) {
|
157 |
$file = str_replace( '_', '-', end( $_chunks ) );
|
158 |
|
159 |
// The extension is deemed to be ".class.php" always. We may wish to alter this for traits?
|
160 |
+
require THE_SEO_FRAMEWORK_DIR_PATH_CLASS . "{$rel_dir}{$file}.class.php";
|
161 |
|
162 |
if ( $_bootstrap_timer ) {
|
163 |
_bootstrap_timer( microtime( true ) - $_bootstrap_timer );
|
@@ -30,12 +30,11 @@ namespace The_SEO_Framework\Bootstrap;
|
|
30 |
* compared to The SEO Framework version constant.
|
31 |
*
|
32 |
* @since 2.7.0
|
|
|
33 |
* @since 4.1.1 No longer memoizes the previous version early. This should help bypass the cache flush.
|
34 |
* @access private
|
35 |
* @TODO convert to class, see \TSF_Extension_Manager\Upgrader
|
36 |
* It's a generator/iterator, so we must wait to PHP>5.5 support.
|
37 |
-
*
|
38 |
-
* @since 3.2.4 Applied namspacing to this file. All method names have changed.
|
39 |
*/
|
40 |
|
41 |
// phpcs:disable, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
|
@@ -45,12 +44,6 @@ namespace The_SEO_Framework\Bootstrap;
|
|
45 |
\add_action( 'the_seo_framework_upgraded', __NAMESPACE__ . '\\_prepare_upgrade_suggestion', 100, 2 );
|
46 |
\add_action( 'the_seo_framework_downgraded', __NAMESPACE__ . '\\_prepare_downgrade_notice', 99, 2 );
|
47 |
|
48 |
-
/**
|
49 |
-
* @since 4.1.0 Deprecated. We can no longer rely on this from WP 5.5.
|
50 |
-
* @deprecated Use persistent notifications, instead.
|
51 |
-
*/
|
52 |
-
\add_action( 'admin_notices', __NAMESPACE__ . '\\_output_upgrade_notices' );
|
53 |
-
|
54 |
/**
|
55 |
* Returns the default site options.
|
56 |
* Memoizes the return value.
|
@@ -60,8 +53,8 @@ namespace The_SEO_Framework\Bootstrap;
|
|
60 |
* @return array The default site options.
|
61 |
*/
|
62 |
function _upgrade_default_site_options() {
|
63 |
-
static $
|
64 |
-
return
|
65 |
}
|
66 |
|
67 |
/**
|
@@ -73,8 +66,8 @@ function _upgrade_default_site_options() {
|
|
73 |
* @return string The prior-to-upgrade TSF db version.
|
74 |
*/
|
75 |
function _previous_db_version() {
|
76 |
-
static $
|
77 |
-
return
|
78 |
}
|
79 |
|
80 |
/**
|
@@ -108,7 +101,7 @@ function _previous_db_version() {
|
|
108 |
*/
|
109 |
function _do_upgrade() {
|
110 |
|
111 |
-
$tsf = \
|
112 |
|
113 |
if ( ! $tsf->loaded ) return;
|
114 |
if ( \wp_doing_ajax() ) return;
|
@@ -216,12 +209,11 @@ function _upgrade( $previous_version ) {
|
|
216 |
//? This means no data may be erased for at least 1 major version, or 1 year, whichever is later.
|
217 |
//? We must manually delete settings that are no longer used; we merge them otherwise.
|
218 |
//? When a user upgrades beyond this scope, they aren't expected to roll back.
|
219 |
-
$versions = [ '1', '2701', '2802', '2900', '3001', '3103', '3300', '4051', '4103', '4110', '4120' ];
|
220 |
|
221 |
foreach ( $versions as $_version ) {
|
222 |
if ( $current_version < $_version ) {
|
223 |
-
|
224 |
-
call_user_func( __NAMESPACE__ . "\\_do_upgrade_{$_version}" ); // PHP 5.6 compat
|
225 |
$current_version = _set_version( $_version );
|
226 |
}
|
227 |
}
|
@@ -364,7 +356,7 @@ function _prepare_downgrade_notice( $previous_version, $current_version ) {
|
|
364 |
|
365 |
// phpcs:ignore, WordPress.PHP.StrictComparisons.LooseComparison -- might be mixed types.
|
366 |
if ( $previous_version && $previous_version != $current_version ) { // User successfully downgraded.
|
367 |
-
$tsf = \
|
368 |
|
369 |
$tsf->register_dismissible_persistent_notice(
|
370 |
$tsf->convert_markdown(
|
@@ -401,6 +393,7 @@ function _prepare_downgrade_notice( $previous_version, $current_version ) {
|
|
401 |
* @since 4.1.0 1. Moved admin notice user capability check here.
|
402 |
* 2. Now registers persistent notice for the update version.
|
403 |
* @since 4.1.2 No longer can accidentally show the install notice after stale upgrade.
|
|
|
404 |
* @TODO Add browser cache flush notice? Or set a pragma/cache-control header?
|
405 |
* Users that remove query strings (thanks to YSlow) are to blame, though.
|
406 |
* The authors of the plugin that allowed this to happen are even more to blame.
|
@@ -413,7 +406,7 @@ function _prepare_upgrade_notice( $previous_version, $current_version ) {
|
|
413 |
|
414 |
// phpcs:ignore, WordPress.PHP.StrictComparisons.LooseComparison -- might be mixed types.
|
415 |
if ( $previous_version && $previous_version != $current_version ) { // User successfully upgraded.
|
416 |
-
$tsf = \
|
417 |
|
418 |
$tsf->register_dismissible_persistent_notice(
|
419 |
$tsf->convert_markdown(
|
@@ -440,40 +433,43 @@ function _prepare_upgrade_notice( $previous_version, $current_version ) {
|
|
440 |
]
|
441 |
);
|
442 |
} elseif ( ! $previous_version && $current_version ) { // User successfully installed.
|
443 |
-
|
444 |
-
\add_action( 'admin_notices', __NAMESPACE__ . '\\_do_install_notice' );
|
445 |
-
}
|
446 |
-
}
|
447 |
-
}
|
448 |
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
* @since 4.1.0
|
453 |
-
*/
|
454 |
-
function _do_install_notice() {
|
455 |
-
|
456 |
-
$tsf = \the_seo_framework();
|
457 |
|
458 |
-
|
459 |
-
$tsf->do_dismissible_notice(
|
460 |
-
sprintf(
|
461 |
-
'<p>%s</p><p>%s</p>',
|
462 |
-
\esc_html__( 'The SEO Framework automatically optimizes your website for search engines and social media.', 'autodescription' ),
|
463 |
-
$tsf->convert_markdown(
|
464 |
sprintf(
|
465 |
-
|
466 |
-
\esc_html__( '
|
467 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
468 |
),
|
469 |
-
|
470 |
-
[
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
477 |
}
|
478 |
|
479 |
/**
|
@@ -499,41 +495,30 @@ function _prepare_upgrade_suggestion( $previous_version, $current_version ) { //
|
|
499 |
}
|
500 |
|
501 |
/**
|
502 |
-
*
|
503 |
*
|
504 |
* @since 2.9.0
|
505 |
* @since 4.1.0 Deprecated. We can no longer rely on this from WP 5.5.
|
506 |
-
* @
|
|
|
507 |
*
|
508 |
-
* @param string $notice The upgrade notice.
|
509 |
-
* @param bool $get Whether to return the upgrade notices.
|
510 |
-
* @return array|void The notices when $get is true.
|
511 |
*/
|
512 |
-
function _add_upgrade_notice( $notice = ''
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
return
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
* @since 3.0.0 Added prefix.
|
528 |
-
* @since 4.1.0 Deprecated. We can no longer rely on this from WP 5.5.
|
529 |
-
* @deprecated Use persistent notifications, instead.
|
530 |
-
* @uses _add_upgrade_notice()
|
531 |
-
*/
|
532 |
-
function _output_upgrade_notices() {
|
533 |
-
foreach ( _add_upgrade_notice( '', true ) as $notice ) {
|
534 |
-
// @TODO rtl?
|
535 |
-
\the_seo_framework()->do_dismissible_notice( 'SEO: ' . $notice, 'info' );
|
536 |
-
}
|
537 |
}
|
538 |
|
539 |
/**
|
@@ -542,7 +527,7 @@ function _output_upgrade_notices() {
|
|
542 |
* @since 3.1.0
|
543 |
*/
|
544 |
function _do_upgrade_1() {
|
545 |
-
\
|
546 |
}
|
547 |
|
548 |
/**
|
@@ -561,7 +546,7 @@ function _do_upgrade_2701() {
|
|
561 |
\add_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, $meta, true );
|
562 |
}
|
563 |
|
564 |
-
|
565 |
\update_option( 'the_seo_framework_initial_db_version', '2600', 'no' );
|
566 |
}
|
567 |
}
|
@@ -587,13 +572,13 @@ function _do_upgrade_2802() {
|
|
587 |
function _do_upgrade_2900() {
|
588 |
|
589 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '2900' ) {
|
590 |
-
$tsf = \
|
591 |
|
592 |
$card_type = trim( $tsf->get_option( 'twitter_card', false ) );
|
593 |
if ( 'photo' === $card_type ) {
|
594 |
$tsf->update_option( 'twitter_card', 'summary_large_image' );
|
595 |
_add_upgrade_notice(
|
596 |
-
\
|
597 |
);
|
598 |
}
|
599 |
}
|
@@ -611,14 +596,14 @@ function _do_upgrade_2900() {
|
|
611 |
function _do_upgrade_3001() {
|
612 |
|
613 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '3001' ) {
|
614 |
-
$tsf = \
|
615 |
|
616 |
-
|
617 |
$sitemap_timestamps = $tsf->get_option( 'sitemap_timestamps', false );
|
618 |
if ( '' !== $sitemap_timestamps ) {
|
619 |
$tsf->update_option( 'timestamps_format', (string) (int) $sitemap_timestamps );
|
620 |
_add_upgrade_notice(
|
621 |
-
\
|
622 |
);
|
623 |
} else {
|
624 |
$tsf->update_option( 'timestamps_format', '1' );
|
@@ -648,7 +633,7 @@ function _do_upgrade_3103() {
|
|
648 |
\add_option( THE_SEO_FRAMEWORK_SITE_CACHE, [] );
|
649 |
|
650 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '3103' ) {
|
651 |
-
$tsf = \
|
652 |
|
653 |
// Transport title separator (option name typo).
|
654 |
$tsf->update_option( 'title_separator', $tsf->get_option( 'title_seperator', false ) ?: 'hyphen' );
|
@@ -674,9 +659,6 @@ function _do_upgrade_3103() {
|
|
674 |
|
675 |
// Add non-default HTML stripping option. Defaulting to previous behavior.
|
676 |
$tsf->update_option( 'title_strip_tags', 0 ); // NOTE: Default is 1.
|
677 |
-
|
678 |
-
// Adds non-default priority option.
|
679 |
-
$tsf->update_option( 'sitemaps_priority', 1 ); // NOTE: Default is 0.
|
680 |
}
|
681 |
}
|
682 |
|
@@ -695,7 +677,7 @@ function _do_upgrade_3103() {
|
|
695 |
function _do_upgrade_3300() {
|
696 |
|
697 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '3300' ) {
|
698 |
-
$tsf = \
|
699 |
|
700 |
// Remove old rewrite rules.
|
701 |
unset(
|
@@ -713,7 +695,7 @@ function _do_upgrade_3300() {
|
|
713 |
|
714 |
if ( $tsf->get_option( 'ping_google', false ) || $tsf->get_option( 'ping_bing', false ) ) {
|
715 |
_add_upgrade_notice(
|
716 |
-
\
|
717 |
);
|
718 |
}
|
719 |
|
@@ -726,7 +708,7 @@ function _do_upgrade_3300() {
|
|
726 |
}
|
727 |
|
728 |
_add_upgrade_notice(
|
729 |
-
\
|
730 |
);
|
731 |
}
|
732 |
}
|
@@ -744,7 +726,7 @@ function _do_upgrade_3300() {
|
|
744 |
function _do_upgrade_4051() {
|
745 |
|
746 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4051' ) {
|
747 |
-
$tsf = \
|
748 |
|
749 |
$tsf->update_option( 'advanced_query_protection', 0 );
|
750 |
$tsf->update_option( 'index_the_feed', 0 );
|
@@ -767,7 +749,7 @@ function _do_upgrade_4051() {
|
|
767 |
function _do_upgrade_4103() {
|
768 |
|
769 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4103' ) {
|
770 |
-
$tsf = \
|
771 |
|
772 |
$tsf->update_option( 'disabled_taxonomies', [] );
|
773 |
$tsf->update_option( 'sitemap_logo_url', '' );
|
@@ -809,7 +791,7 @@ function _do_upgrade_4103() {
|
|
809 |
function _do_upgrade_4110() {
|
810 |
|
811 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4110' ) {
|
812 |
-
$tsf = \
|
813 |
|
814 |
$tsf->update_option( 'oembed_use_og_title', 0 );
|
815 |
$tsf->update_option( 'oembed_use_social_image', 0 ); // Defaults to 1 for new sites!
|
@@ -823,8 +805,18 @@ function _do_upgrade_4110() {
|
|
823 |
*/
|
824 |
function _do_upgrade_4120() {
|
825 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4120' ) {
|
826 |
-
$tsf = \
|
827 |
-
|
828 |
$tsf->update_option( 'ping_use_cron_prerender', 0 );
|
829 |
}
|
830 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
* compared to The SEO Framework version constant.
|
31 |
*
|
32 |
* @since 2.7.0
|
33 |
+
* @since 3.2.4 Applied namspacing to this file. All method names have changed.
|
34 |
* @since 4.1.1 No longer memoizes the previous version early. This should help bypass the cache flush.
|
35 |
* @access private
|
36 |
* @TODO convert to class, see \TSF_Extension_Manager\Upgrader
|
37 |
* It's a generator/iterator, so we must wait to PHP>5.5 support.
|
|
|
|
|
38 |
*/
|
39 |
|
40 |
// phpcs:disable, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
|
44 |
\add_action( 'the_seo_framework_upgraded', __NAMESPACE__ . '\\_prepare_upgrade_suggestion', 100, 2 );
|
45 |
\add_action( 'the_seo_framework_downgraded', __NAMESPACE__ . '\\_prepare_downgrade_notice', 99, 2 );
|
46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
/**
|
48 |
* Returns the default site options.
|
49 |
* Memoizes the return value.
|
53 |
* @return array The default site options.
|
54 |
*/
|
55 |
function _upgrade_default_site_options() {
|
56 |
+
static $memo;
|
57 |
+
return $memo ?? ( $memo = \tsf()->get_default_site_options() );
|
58 |
}
|
59 |
|
60 |
/**
|
66 |
* @return string The prior-to-upgrade TSF db version.
|
67 |
*/
|
68 |
function _previous_db_version() {
|
69 |
+
static $memo;
|
70 |
+
return $memo ?? ( $memo = \get_option( 'the_seo_framework_upgraded_db_version', '0' ) );
|
71 |
}
|
72 |
|
73 |
/**
|
101 |
*/
|
102 |
function _do_upgrade() {
|
103 |
|
104 |
+
$tsf = \tsf();
|
105 |
|
106 |
if ( ! $tsf->loaded ) return;
|
107 |
if ( \wp_doing_ajax() ) return;
|
209 |
//? This means no data may be erased for at least 1 major version, or 1 year, whichever is later.
|
210 |
//? We must manually delete settings that are no longer used; we merge them otherwise.
|
211 |
//? When a user upgrades beyond this scope, they aren't expected to roll back.
|
212 |
+
$versions = [ '1', '2701', '2802', '2900', '3001', '3103', '3300', '4051', '4103', '4110', '4120', '4200' ];
|
213 |
|
214 |
foreach ( $versions as $_version ) {
|
215 |
if ( $current_version < $_version ) {
|
216 |
+
( __NAMESPACE__ . "\\_do_upgrade_{$_version}" )(); // This is an undocumented method for variable functions.
|
|
|
217 |
$current_version = _set_version( $_version );
|
218 |
}
|
219 |
}
|
356 |
|
357 |
// phpcs:ignore, WordPress.PHP.StrictComparisons.LooseComparison -- might be mixed types.
|
358 |
if ( $previous_version && $previous_version != $current_version ) { // User successfully downgraded.
|
359 |
+
$tsf = \tsf();
|
360 |
|
361 |
$tsf->register_dismissible_persistent_notice(
|
362 |
$tsf->convert_markdown(
|
393 |
* @since 4.1.0 1. Moved admin notice user capability check here.
|
394 |
* 2. Now registers persistent notice for the update version.
|
395 |
* @since 4.1.2 No longer can accidentally show the install notice after stale upgrade.
|
396 |
+
* @since 4.2.0 The installation notice is now persistent, shown twice, to users with activate_plugins capability, on the main site.
|
397 |
* @TODO Add browser cache flush notice? Or set a pragma/cache-control header?
|
398 |
* Users that remove query strings (thanks to YSlow) are to blame, though.
|
399 |
* The authors of the plugin that allowed this to happen are even more to blame.
|
406 |
|
407 |
// phpcs:ignore, WordPress.PHP.StrictComparisons.LooseComparison -- might be mixed types.
|
408 |
if ( $previous_version && $previous_version != $current_version ) { // User successfully upgraded.
|
409 |
+
$tsf = \tsf();
|
410 |
|
411 |
$tsf->register_dismissible_persistent_notice(
|
412 |
$tsf->convert_markdown(
|
433 |
]
|
434 |
);
|
435 |
} elseif ( ! $previous_version && $current_version ) { // User successfully installed.
|
436 |
+
$network_mode = (bool) ( \get_site_option( 'active_sitewide_plugins' )[ THE_SEO_FRAMEWORK_PLUGIN_BASENAME ] ?? false );
|
|
|
|
|
|
|
|
|
437 |
|
438 |
+
// Only show notice when not in network mode, or on main site otherwise.
|
439 |
+
if ( ! $network_mode || \is_main_site() ) {
|
440 |
+
$tsf = \tsf();
|
|
|
|
|
|
|
|
|
|
|
441 |
|
442 |
+
$tsf->register_dismissible_persistent_notice(
|
|
|
|
|
|
|
|
|
|
|
443 |
sprintf(
|
444 |
+
'<p>%s</p><p>%s</p>',
|
445 |
+
\esc_html__( 'The SEO Framework automatically optimizes your website for search engines and social media.', 'autodescription' ),
|
446 |
+
$tsf->convert_markdown(
|
447 |
+
sprintf(
|
448 |
+
/* translators: %s = Link, markdown. */
|
449 |
+
\esc_html__( 'To take full advantage of all SEO features, please follow our [5-minute setup guide](%s).', 'autodescription' ),
|
450 |
+
'https://theseoframework.com/docs/seo-plugin-setup/' // Use https://tsf.fyi/docs/setup ? Needless redirection...
|
451 |
+
),
|
452 |
+
[ 'a' ],
|
453 |
+
[ 'a_internal' => false ]
|
454 |
+
)
|
455 |
),
|
456 |
+
'thank-you-installed',
|
457 |
+
[
|
458 |
+
'type' => 'info',
|
459 |
+
'icon' => false,
|
460 |
+
'escape' => false,
|
461 |
+
],
|
462 |
+
[
|
463 |
+
'screens' => [],
|
464 |
+
'excl_screens' => [ 'post', 'term', 'upload', 'media', 'plugin-editor', 'plugin-install', 'themes' ],
|
465 |
+
'capability' => 'activate_plugins',
|
466 |
+
'user' => 0,
|
467 |
+
'count' => 1,
|
468 |
+
'timeout' => 2 * MINUTE_IN_SECONDS,
|
469 |
+
]
|
470 |
+
);
|
471 |
+
}
|
472 |
+
}
|
473 |
}
|
474 |
|
475 |
/**
|
495 |
}
|
496 |
|
497 |
/**
|
498 |
+
* Registers upgrade notices.
|
499 |
*
|
500 |
* @since 2.9.0
|
501 |
* @since 4.1.0 Deprecated. We can no longer rely on this from WP 5.5.
|
502 |
+
* @since 4.2.0 1. Reinstated, and now forwards notices to the persistent-notice system.
|
503 |
+
* 2. No longer returns values. Removed pertaining second parameter.
|
504 |
*
|
505 |
+
* @param string $notice The upgrade notice. Doesn't need to be escaped.
|
|
|
|
|
506 |
*/
|
507 |
+
function _add_upgrade_notice( $notice = '' ) {
|
508 |
+
|
509 |
+
$tsf = \tsf();
|
510 |
+
|
511 |
+
$tsf->register_dismissible_persistent_notice(
|
512 |
+
"SEO: $notice",
|
513 |
+
'upgrade-' . ( hash( 'md5', $notice ) ?: uniqid( '', true ) ), // if md5 is unregistered, it'll return false
|
514 |
+
[
|
515 |
+
'type' => 'info',
|
516 |
+
],
|
517 |
+
[
|
518 |
+
'excl_screens' => [ 'post', 'term', 'upload', 'media', 'plugin-editor', 'plugin-install', 'themes' ],
|
519 |
+
'capability' => $tsf->get_settings_capability(),
|
520 |
+
]
|
521 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
522 |
}
|
523 |
|
524 |
/**
|
527 |
* @since 3.1.0
|
528 |
*/
|
529 |
function _do_upgrade_1() {
|
530 |
+
\tsf()->register_settings();
|
531 |
}
|
532 |
|
533 |
/**
|
546 |
\add_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, $meta, true );
|
547 |
}
|
548 |
|
549 |
+
// Rudimentary test for remaining ~300 users of earlier versions passed, set initial version to 2600.
|
550 |
\update_option( 'the_seo_framework_initial_db_version', '2600', 'no' );
|
551 |
}
|
552 |
}
|
572 |
function _do_upgrade_2900() {
|
573 |
|
574 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '2900' ) {
|
575 |
+
$tsf = \tsf();
|
576 |
|
577 |
$card_type = trim( $tsf->get_option( 'twitter_card', false ) );
|
578 |
if ( 'photo' === $card_type ) {
|
579 |
$tsf->update_option( 'twitter_card', 'summary_large_image' );
|
580 |
_add_upgrade_notice(
|
581 |
+
\__( 'Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable.', 'autodescription' )
|
582 |
);
|
583 |
}
|
584 |
}
|
596 |
function _do_upgrade_3001() {
|
597 |
|
598 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '3001' ) {
|
599 |
+
$tsf = \tsf();
|
600 |
|
601 |
+
// Only show notice if old option exists. Falls back to default upgrader otherwise.
|
602 |
$sitemap_timestamps = $tsf->get_option( 'sitemap_timestamps', false );
|
603 |
if ( '' !== $sitemap_timestamps ) {
|
604 |
$tsf->update_option( 'timestamps_format', (string) (int) $sitemap_timestamps );
|
605 |
_add_upgrade_notice(
|
606 |
+
\__( 'The previous sitemap timestamp settings have been converted into new global timestamp settings.', 'autodescription' )
|
607 |
);
|
608 |
} else {
|
609 |
$tsf->update_option( 'timestamps_format', '1' );
|
633 |
\add_option( THE_SEO_FRAMEWORK_SITE_CACHE, [] );
|
634 |
|
635 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '3103' ) {
|
636 |
+
$tsf = \tsf();
|
637 |
|
638 |
// Transport title separator (option name typo).
|
639 |
$tsf->update_option( 'title_separator', $tsf->get_option( 'title_seperator', false ) ?: 'hyphen' );
|
659 |
|
660 |
// Add non-default HTML stripping option. Defaulting to previous behavior.
|
661 |
$tsf->update_option( 'title_strip_tags', 0 ); // NOTE: Default is 1.
|
|
|
|
|
|
|
662 |
}
|
663 |
}
|
664 |
|
677 |
function _do_upgrade_3300() {
|
678 |
|
679 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '3300' ) {
|
680 |
+
$tsf = \tsf();
|
681 |
|
682 |
// Remove old rewrite rules.
|
683 |
unset(
|
695 |
|
696 |
if ( $tsf->get_option( 'ping_google', false ) || $tsf->get_option( 'ping_bing', false ) ) {
|
697 |
_add_upgrade_notice(
|
698 |
+
\__( 'A cronjob is now used to ping search engines, and it alerts them to changes in your sitemap.', 'autodescription' )
|
699 |
);
|
700 |
}
|
701 |
|
708 |
}
|
709 |
|
710 |
_add_upgrade_notice(
|
711 |
+
\__( 'The positions in the "Meta Title Additions Location" setting for the homepage have been reversed, left to right, but the output has not been changed. If you must downgrade for some reason, remember to switch the location back again.', 'autodescription' )
|
712 |
);
|
713 |
}
|
714 |
}
|
726 |
function _do_upgrade_4051() {
|
727 |
|
728 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4051' ) {
|
729 |
+
$tsf = \tsf();
|
730 |
|
731 |
$tsf->update_option( 'advanced_query_protection', 0 );
|
732 |
$tsf->update_option( 'index_the_feed', 0 );
|
749 |
function _do_upgrade_4103() {
|
750 |
|
751 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4103' ) {
|
752 |
+
$tsf = \tsf();
|
753 |
|
754 |
$tsf->update_option( 'disabled_taxonomies', [] );
|
755 |
$tsf->update_option( 'sitemap_logo_url', '' );
|
791 |
function _do_upgrade_4110() {
|
792 |
|
793 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4110' ) {
|
794 |
+
$tsf = \tsf();
|
795 |
|
796 |
$tsf->update_option( 'oembed_use_og_title', 0 );
|
797 |
$tsf->update_option( 'oembed_use_social_image', 0 ); // Defaults to 1 for new sites!
|
805 |
*/
|
806 |
function _do_upgrade_4120() {
|
807 |
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4120' ) {
|
808 |
+
$tsf = \tsf();
|
|
|
809 |
$tsf->update_option( 'ping_use_cron_prerender', 0 );
|
810 |
}
|
811 |
}
|
812 |
+
|
813 |
+
/**
|
814 |
+
* Removes the global `the_seo_framework_tested_upgrade_version` option.
|
815 |
+
*
|
816 |
+
* @since 4.2.0
|
817 |
+
*/
|
818 |
+
function _do_upgrade_4200() {
|
819 |
+
if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4200' ) {
|
820 |
+
\delete_option( 'the_seo_framework_tested_upgrade_version' );
|
821 |
+
}
|
822 |
+
}
|
@@ -43,7 +43,7 @@ class Admin_Init extends Init {
|
|
43 |
*/
|
44 |
public function _init_seo_bar_tables() {
|
45 |
if ( $this->get_option( 'display_seo_bar_tables' ) )
|
46 |
-
new Bridges\
|
47 |
}
|
48 |
|
49 |
/**
|
@@ -68,7 +68,7 @@ class Admin_Init extends Init {
|
|
68 |
*/
|
69 |
public function _add_post_state( $states = [], $post = null ) {
|
70 |
|
71 |
-
$post_id =
|
72 |
|
73 |
if ( $post_id ) {
|
74 |
$search_exclude = $this->get_option( 'alter_search_query' ) && $this->get_post_meta_item( 'exclude_local_search', $post_id );
|
@@ -177,15 +177,13 @@ class Admin_Init extends Init {
|
|
177 |
*/
|
178 |
public function get_input_guidelines( $locale = null ) {
|
179 |
|
180 |
-
static $guidelines = [];
|
181 |
-
|
182 |
$locale = $locale ?: \get_locale();
|
183 |
|
184 |
// Strip the "_formal" and other suffixes. 5 length: xx_YY
|
185 |
$locale = substr( $locale, 0, 5 );
|
186 |
|
187 |
-
|
188 |
-
|
189 |
|
190 |
// phpcs:disable, WordPress.WhiteSpace.OperatorSpacing.SpacingAfter
|
191 |
$character_adjustments = [
|
@@ -204,7 +202,7 @@ class Admin_Init extends Init {
|
|
204 |
];
|
205 |
// phpcs:enable, WordPress.WhiteSpace.OperatorSpacing.SpacingAfter
|
206 |
|
207 |
-
$c_adjust =
|
208 |
|
209 |
$pixel_adjustments = [
|
210 |
'ar' => 760 / 910, // Arabic (العربية)
|
@@ -215,7 +213,7 @@ class Admin_Init extends Init {
|
|
215 |
'ckb' => 760 / 910, // Central Kurdish (كوردی)
|
216 |
];
|
217 |
|
218 |
-
$p_adjust =
|
219 |
|
220 |
// phpcs:disable, WordPress.Arrays.MultipleStatementAlignment.DoubleArrowNotAligned
|
221 |
/**
|
@@ -223,78 +221,81 @@ class Admin_Init extends Init {
|
|
223 |
* @param array $guidelines The title and description guidelines.
|
224 |
* Don't alter the format. Only change the numeric values.
|
225 |
*/
|
226 |
-
return
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
'
|
231 |
-
'
|
232 |
-
'
|
233 |
-
|
234 |
-
|
235 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
],
|
237 |
-
'
|
238 |
-
'
|
239 |
-
|
240 |
-
|
241 |
-
|
|
|
|
|
|
|
242 |
],
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
|
|
250 |
],
|
251 |
-
'pixels' => [],
|
252 |
],
|
253 |
-
'
|
254 |
-
'
|
255 |
-
'
|
256 |
-
|
257 |
-
|
258 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
],
|
260 |
-
'
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
'
|
268 |
-
'goodUpper' => (int) ( 160 * $c_adjust ),
|
269 |
-
'upper' => (int) ( 320 * $c_adjust ),
|
270 |
],
|
271 |
-
'
|
272 |
-
'
|
273 |
-
|
274 |
-
|
275 |
-
|
|
|
|
|
|
|
276 |
],
|
277 |
],
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
'goodLower' => 80,
|
282 |
-
'goodUpper' => 200,
|
283 |
-
'upper' => 300,
|
284 |
-
],
|
285 |
-
'pixels' => [],
|
286 |
-
],
|
287 |
-
'twitter' => [
|
288 |
-
'chars' => [
|
289 |
-
'lower' => 45,
|
290 |
-
'goodLower' => 80,
|
291 |
-
'goodUpper' => 200,
|
292 |
-
'upper' => 200,
|
293 |
-
],
|
294 |
-
'pixels' => [],
|
295 |
-
],
|
296 |
-
],
|
297 |
-
]
|
298 |
);
|
299 |
// phpcs:enable, WordPress.Arrays.MultipleStatementAlignment.DoubleArrowNotAligned
|
300 |
}
|
@@ -306,6 +307,7 @@ class Admin_Init extends Init {
|
|
306 |
*
|
307 |
* @since 3.1.0
|
308 |
* @since 4.0.0 Now added a short leading-dot version for ARIA labels.
|
|
|
309 |
*
|
310 |
* @return array
|
311 |
*/
|
@@ -355,7 +357,7 @@ class Admin_Init extends Init {
|
|
355 |
* valid and generated between 12-24 hours ago.
|
356 |
*/
|
357 |
public function _check_tsf_ajax_referer( $capability ) {
|
358 |
-
return \check_ajax_referer(
|
359 |
}
|
360 |
|
361 |
/**
|
@@ -364,15 +366,16 @@ class Admin_Init extends Init {
|
|
364 |
*
|
365 |
* @since 2.2.2
|
366 |
* @since 2.9.2 Added user-friendly exception handling.
|
367 |
-
* @since 2.9.3
|
368 |
-
*
|
|
|
369 |
*
|
370 |
* @param string $page Menu slug. This slug must exist, or the redirect will loop back to the current page.
|
371 |
* @param array $query_args Optional. Associative array of query string arguments
|
372 |
* (key => value). Default is an empty array.
|
373 |
* @return null Return early if first argument is false.
|
374 |
*/
|
375 |
-
public function admin_redirect( $page,
|
376 |
|
377 |
if ( empty( $page ) ) return;
|
378 |
|
@@ -380,11 +383,7 @@ class Admin_Init extends Init {
|
|
380 |
// Might cause security issues... we _must_ exit, always? Show warning?
|
381 |
$url = html_entity_decode( \menu_page_url( $page, false ) );
|
382 |
|
383 |
-
|
384 |
-
if ( empty( $key ) || empty( $value ) )
|
385 |
-
unset( $query_args[ $key ] );
|
386 |
-
|
387 |
-
$target = \add_query_arg( $query_args, $url );
|
388 |
$target = \esc_url_raw( $target, [ 'https', 'http' ] );
|
389 |
|
390 |
// Predict white screen:
|
@@ -395,7 +394,7 @@ class Admin_Init extends Init {
|
|
395 |
* 1. Change 302 to 500 if you wish to test headers.
|
396 |
* 2. Also force handle_admin_redirect_error() to run.
|
397 |
*/
|
398 |
-
|
399 |
|
400 |
// White screen of death for non-debugging users. Let's make it friendlier.
|
401 |
if ( $headers_sent )
|
@@ -468,9 +467,10 @@ class Admin_Init extends Init {
|
|
468 |
* Do not input non-integer values (such as `false`), for those might cause adverse events.
|
469 |
* }
|
470 |
*/
|
471 |
-
public function register_dismissible_persistent_notice( $message, $key,
|
472 |
|
473 |
-
// We made this mistake ourselves. Let's test against it.
|
|
|
474 |
if ( ! is_scalar( $key ) || ! \strlen( $key ) ) return;
|
475 |
|
476 |
// Sanitize the key so that HTML, JS, and PHP can communicate easily via it.
|
@@ -595,18 +595,17 @@ class Admin_Init extends Init {
|
|
595 |
public function _dismiss_notice() {
|
596 |
|
597 |
// phpcs:ignore, WordPress.Security.NonceVerification.Missing -- We require the POST data to find locally stored nonces.
|
598 |
-
$key =
|
|
|
599 |
if ( ! $key ) return;
|
600 |
|
601 |
$notices = $this->get_static_cache( 'persistent_notices', [] );
|
602 |
// Notice was deleted already elsewhere, or key was faulty. Either way, ignore--should be self-resolving.
|
603 |
if ( empty( $notices[ $key ]['conditions']['capability'] ) ) return;
|
604 |
|
605 |
-
// phpcs:ignore, WordPress.Security.NonceVerification.Missing -- We require the POST data to find locally stored nonces.
|
606 |
-
$nonce = isset( $_POST['tsf_notice_nonce'] ) ? $_POST['tsf_notice_nonce'] : '';
|
607 |
-
|
608 |
if ( ! \current_user_can( $notices[ $key ]['conditions']['capability'] )
|
609 |
-
|
|
|
610 |
\wp_die( -1, 403 );
|
611 |
}
|
612 |
|
43 |
*/
|
44 |
public function _init_seo_bar_tables() {
|
45 |
if ( $this->get_option( 'display_seo_bar_tables' ) )
|
46 |
+
new Bridges\SEOBar;
|
47 |
}
|
48 |
|
49 |
/**
|
68 |
*/
|
69 |
public function _add_post_state( $states = [], $post = null ) {
|
70 |
|
71 |
+
$post_id = $post->ID ?? false;
|
72 |
|
73 |
if ( $post_id ) {
|
74 |
$search_exclude = $this->get_option( 'alter_search_query' ) && $this->get_post_meta_item( 'exclude_local_search', $post_id );
|
177 |
*/
|
178 |
public function get_input_guidelines( $locale = null ) {
|
179 |
|
|
|
|
|
180 |
$locale = $locale ?: \get_locale();
|
181 |
|
182 |
// Strip the "_formal" and other suffixes. 5 length: xx_YY
|
183 |
$locale = substr( $locale, 0, 5 );
|
184 |
|
185 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
186 |
+
if ( null !== $memo = memo( null, $locale ) ) return $memo;
|
187 |
|
188 |
// phpcs:disable, WordPress.WhiteSpace.OperatorSpacing.SpacingAfter
|
189 |
$character_adjustments = [
|
202 |
];
|
203 |
// phpcs:enable, WordPress.WhiteSpace.OperatorSpacing.SpacingAfter
|
204 |
|
205 |
+
$c_adjust = $character_adjustments[ $locale ] ?? 1;
|
206 |
|
207 |
$pixel_adjustments = [
|
208 |
'ar' => 760 / 910, // Arabic (العربية)
|
213 |
'ckb' => 760 / 910, // Central Kurdish (كوردی)
|
214 |
];
|
215 |
|
216 |
+
$p_adjust = $pixel_adjustments[ $locale ] ?? 1;
|
217 |
|
218 |
// phpcs:disable, WordPress.Arrays.MultipleStatementAlignment.DoubleArrowNotAligned
|
219 |
/**
|
221 |
* @param array $guidelines The title and description guidelines.
|
222 |
* Don't alter the format. Only change the numeric values.
|
223 |
*/
|
224 |
+
return memo(
|
225 |
+
(array) \apply_filters(
|
226 |
+
'the_seo_framework_input_guidelines',
|
227 |
+
[
|
228 |
+
'title' => [
|
229 |
+
'search' => [
|
230 |
+
'chars' => [
|
231 |
+
'lower' => (int) ( 25 * $c_adjust ),
|
232 |
+
'goodLower' => (int) ( 35 * $c_adjust ),
|
233 |
+
'goodUpper' => (int) ( 65 * $c_adjust ),
|
234 |
+
'upper' => (int) ( 75 * $c_adjust ),
|
235 |
+
],
|
236 |
+
'pixels' => [
|
237 |
+
'lower' => (int) ( 200 * $p_adjust ),
|
238 |
+
'goodLower' => (int) ( 280 * $p_adjust ),
|
239 |
+
'goodUpper' => (int) ( 520 * $p_adjust ),
|
240 |
+
'upper' => (int) ( 600 * $p_adjust ),
|
241 |
+
],
|
242 |
],
|
243 |
+
'opengraph' => [
|
244 |
+
'chars' => [
|
245 |
+
'lower' => 15,
|
246 |
+
'goodLower' => 25,
|
247 |
+
'goodUpper' => 88,
|
248 |
+
'upper' => 100,
|
249 |
+
],
|
250 |
+
'pixels' => [],
|
251 |
],
|
252 |
+
'twitter' => [
|
253 |
+
'chars' => [
|
254 |
+
'lower' => 15,
|
255 |
+
'goodLower' => 25,
|
256 |
+
'goodUpper' => 69,
|
257 |
+
'upper' => 70,
|
258 |
+
],
|
259 |
+
'pixels' => [],
|
260 |
],
|
|
|
261 |
],
|
262 |
+
'description' => [
|
263 |
+
'search' => [
|
264 |
+
'chars' => [
|
265 |
+
'lower' => (int) ( 45 * $c_adjust ),
|
266 |
+
'goodLower' => (int) ( 80 * $c_adjust ),
|
267 |
+
'goodUpper' => (int) ( 160 * $c_adjust ),
|
268 |
+
'upper' => (int) ( 320 * $c_adjust ),
|
269 |
+
],
|
270 |
+
'pixels' => [
|
271 |
+
'lower' => (int) ( 256 * $p_adjust ),
|
272 |
+
'goodLower' => (int) ( 455 * $p_adjust ),
|
273 |
+
'goodUpper' => (int) ( 910 * $p_adjust ),
|
274 |
+
'upper' => (int) ( 1820 * $p_adjust ),
|
275 |
+
],
|
276 |
],
|
277 |
+
'opengraph' => [
|
278 |
+
'chars' => [
|
279 |
+
'lower' => 45,
|
280 |
+
'goodLower' => 80,
|
281 |
+
'goodUpper' => 200,
|
282 |
+
'upper' => 300,
|
283 |
+
],
|
284 |
+
'pixels' => [],
|
|
|
|
|
285 |
],
|
286 |
+
'twitter' => [
|
287 |
+
'chars' => [
|
288 |
+
'lower' => 45,
|
289 |
+
'goodLower' => 80,
|
290 |
+
'goodUpper' => 200,
|
291 |
+
'upper' => 200,
|
292 |
+
],
|
293 |
+
'pixels' => [],
|
294 |
],
|
295 |
],
|
296 |
+
]
|
297 |
+
),
|
298 |
+
$locale
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
);
|
300 |
// phpcs:enable, WordPress.Arrays.MultipleStatementAlignment.DoubleArrowNotAligned
|
301 |
}
|
307 |
*
|
308 |
* @since 3.1.0
|
309 |
* @since 4.0.0 Now added a short leading-dot version for ARIA labels.
|
310 |
+
* @TODO move this to another object? -> i18n/guidelines
|
311 |
*
|
312 |
* @return array
|
313 |
*/
|
357 |
* valid and generated between 12-24 hours ago.
|
358 |
*/
|
359 |
public function _check_tsf_ajax_referer( $capability ) {
|
360 |
+
return \check_ajax_referer( "tsf-ajax-$capability", 'nonce', true );
|
361 |
}
|
362 |
|
363 |
/**
|
366 |
*
|
367 |
* @since 2.2.2
|
368 |
* @since 2.9.2 Added user-friendly exception handling.
|
369 |
+
* @since 2.9.3 1. Query arguments work again (regression 2.9.2).
|
370 |
+
* 2. Now only accepts http and https protocols.
|
371 |
+
* @since 4.2.0 Now allows query arguments with value 0|'0'.
|
372 |
*
|
373 |
* @param string $page Menu slug. This slug must exist, or the redirect will loop back to the current page.
|
374 |
* @param array $query_args Optional. Associative array of query string arguments
|
375 |
* (key => value). Default is an empty array.
|
376 |
* @return null Return early if first argument is false.
|
377 |
*/
|
378 |
+
public function admin_redirect( $page, $query_args = [] ) {
|
379 |
|
380 |
if ( empty( $page ) ) return;
|
381 |
|
383 |
// Might cause security issues... we _must_ exit, always? Show warning?
|
384 |
$url = html_entity_decode( \menu_page_url( $page, false ) );
|
385 |
|
386 |
+
$target = \add_query_arg( array_filter( $query_args, 'strlen' ), $url );
|
|
|
|
|
|
|
|
|
387 |
$target = \esc_url_raw( $target, [ 'https', 'http' ] );
|
388 |
|
389 |
// Predict white screen:
|
394 |
* 1. Change 302 to 500 if you wish to test headers.
|
395 |
* 2. Also force handle_admin_redirect_error() to run.
|
396 |
*/
|
397 |
+
\wp_safe_redirect( $target, 302 );
|
398 |
|
399 |
// White screen of death for non-debugging users. Let's make it friendlier.
|
400 |
if ( $headers_sent )
|
467 |
* Do not input non-integer values (such as `false`), for those might cause adverse events.
|
468 |
* }
|
469 |
*/
|
470 |
+
public function register_dismissible_persistent_notice( $message, $key, $args = [], $conditions = [] ) {
|
471 |
|
472 |
+
// We made this mistake ourselves. Let's test against it.
|
473 |
+
// We can't type $key to scalar, for PHP is dumb with that type.
|
474 |
if ( ! is_scalar( $key ) || ! \strlen( $key ) ) return;
|
475 |
|
476 |
// Sanitize the key so that HTML, JS, and PHP can communicate easily via it.
|
595 |
public function _dismiss_notice() {
|
596 |
|
597 |
// phpcs:ignore, WordPress.Security.NonceVerification.Missing -- We require the POST data to find locally stored nonces.
|
598 |
+
$key = $_POST['tsf-notice-submit'] ?? '';
|
599 |
+
|
600 |
if ( ! $key ) return;
|
601 |
|
602 |
$notices = $this->get_static_cache( 'persistent_notices', [] );
|
603 |
// Notice was deleted already elsewhere, or key was faulty. Either way, ignore--should be self-resolving.
|
604 |
if ( empty( $notices[ $key ]['conditions']['capability'] ) ) return;
|
605 |
|
|
|
|
|
|
|
606 |
if ( ! \current_user_can( $notices[ $key ]['conditions']['capability'] )
|
607 |
+
// phpcs:ignore, WordPress.Security.NonceVerification.Missing -- We require the POST data to find locally stored nonces.
|
608 |
+
|| ! \wp_verify_nonce( $_POST['tsf_notice_nonce'] ?? '', $this->_get_dismiss_notice_nonce_action( $key ) ) ) {
|
609 |
\wp_die( -1, 403 );
|
610 |
}
|
611 |
|
@@ -86,8 +86,8 @@ class Admin_Pages extends Generate_Ldjson {
|
|
86 |
);
|
87 |
|
88 |
// Enqueue scripts
|
89 |
-
\add_action(
|
90 |
-
\add_action(
|
91 |
}
|
92 |
|
93 |
/**
|
@@ -110,8 +110,8 @@ class Admin_Pages extends Generate_Ldjson {
|
|
110 |
public function _output_settings_wrap() {
|
111 |
|
112 |
\add_action(
|
113 |
-
$this->seo_settings_page_hook
|
114 |
-
Bridges\SeoSettings::class
|
115 |
);
|
116 |
|
117 |
Bridges\SeoSettings::_output_wrap();
|
@@ -139,7 +139,7 @@ class Admin_Pages extends Generate_Ldjson {
|
|
139 |
if ( $show_seobox )
|
140 |
\add_action(
|
141 |
'add_meta_boxes',
|
142 |
-
Bridges\PostSettings::class
|
143 |
);
|
144 |
}
|
145 |
|
@@ -164,8 +164,8 @@ class Admin_Pages extends Generate_Ldjson {
|
|
164 |
$priority = (int) \apply_filters( 'the_seo_framework_term_metabox_priority', 0 );
|
165 |
|
166 |
\add_action(
|
167 |
-
$taxonomy
|
168 |
-
Bridges\TermSettings::class
|
169 |
$priority,
|
170 |
2
|
171 |
);
|
@@ -184,8 +184,8 @@ class Admin_Pages extends Generate_Ldjson {
|
|
184 |
// WordPress made a mess of this. We can't reliably get a user future-proof. Load class for all users; check there.
|
185 |
// if ( ! $user->has_cap( THE_SEO_FRAMEWORK_AUTHOR_INFO_CAP ) ) return;
|
186 |
|
187 |
-
\add_action( 'show_user_profile', Bridges\UserSettings::class
|
188 |
-
\add_action( 'edit_user_profile', Bridges\UserSettings::class
|
189 |
}
|
190 |
|
191 |
/**
|
@@ -340,7 +340,7 @@ class Admin_Pages extends Generate_Ldjson {
|
|
340 |
* 'escape' => bool Optional. Whether to escape the $message. Default true.
|
341 |
* }
|
342 |
*/
|
343 |
-
protected function output_dismissible_persistent_notice( $message, $key,
|
344 |
$this->get_view( 'notice/persistent', get_defined_vars() );
|
345 |
}
|
346 |
|
@@ -355,9 +355,8 @@ class Admin_Pages extends Generate_Ldjson {
|
|
355 |
*/
|
356 |
protected function output_dismissible_persistent_notices() {
|
357 |
|
358 |
-
$notices
|
359 |
-
$
|
360 |
-
$base = isset( $current_screen->base ) ? $current_screen->base : '';
|
361 |
|
362 |
// Ideally, we don't want to output more than one on no-js. Alas, we can't anticipate the importance and order of the notices.
|
363 |
foreach ( $notices as $key => $notice ) {
|
@@ -365,8 +364,8 @@ class Admin_Pages extends Generate_Ldjson {
|
|
365 |
|
366 |
if ( ! \current_user_can( $cond['capability'] ) ) continue;
|
367 |
if ( $cond['user'] && $cond['user'] !== $this->get_user_id() ) continue;
|
368 |
-
if ( $cond['screens'] && ! \in_array( $
|
369 |
-
if ( $cond['excl_screens'] && \in_array( $
|
370 |
|
371 |
if ( -1 !== $cond['timeout'] && $cond['timeout'] < time() ) {
|
372 |
$this->clear_persistent_notice( $key );
|
@@ -384,7 +383,7 @@ class Admin_Pages extends Generate_Ldjson {
|
|
384 |
* Returns the SEO Bar.
|
385 |
*
|
386 |
* @since 4.0.0
|
387 |
-
* @uses \The_SEO_Framework\Interpreters\
|
388 |
*
|
389 |
* @param array $query : {
|
390 |
* int $id : Required. The current post or term ID.
|
@@ -394,8 +393,8 @@ class Admin_Pages extends Generate_Ldjson {
|
|
394 |
* }
|
395 |
* @return string The generated SEO bar, in HTML.
|
396 |
*/
|
397 |
-
public function get_generated_seo_bar(
|
398 |
-
return Interpreters\
|
399 |
}
|
400 |
|
401 |
/**
|
@@ -422,8 +421,8 @@ class Admin_Pages extends Generate_Ldjson {
|
|
422 |
* @param string $id The input ID.
|
423 |
* @param array $data The input data.
|
424 |
*/
|
425 |
-
public function output_js_title_data( $id,
|
426 |
-
|
427 |
implode(
|
428 |
'',
|
429 |
[
|
@@ -435,9 +434,30 @@ class Admin_Pages extends Generate_Ldjson {
|
|
435 |
'<span id="tsf-title-data_%1$s" class="hidden wp-exclude-emoji" data-for="%1$s" %2$s></span>',
|
436 |
]
|
437 |
),
|
438 |
-
|
439 |
-
|
440 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
441 |
);
|
442 |
}
|
443 |
|
@@ -464,8 +484,8 @@ class Admin_Pages extends Generate_Ldjson {
|
|
464 |
* @param string $id The description input ID.
|
465 |
* @param array $data The input data.
|
466 |
*/
|
467 |
-
public function output_js_description_data( $id,
|
468 |
-
|
469 |
implode(
|
470 |
'',
|
471 |
[
|
@@ -473,139 +493,11 @@ class Admin_Pages extends Generate_Ldjson {
|
|
473 |
'<span id="tsf-description-data_%1$s" class="hidden wp-exclude-emoji" data-for="%1$s" %2$s ></span>',
|
474 |
]
|
475 |
),
|
476 |
-
|
477 |
-
|
478 |
-
|
|
|
|
|
479 |
);
|
480 |
}
|
481 |
-
|
482 |
-
/**
|
483 |
-
* Calculates the social title and description placeholder values.
|
484 |
-
* This is intricated, voluminous, and convoluted; but, there's no other way :(
|
485 |
-
*
|
486 |
-
* @since 4.0.0
|
487 |
-
* @since 4.1.0 Now consistently applies escaping and transformation of the titles and descriptions.
|
488 |
-
* This was not a security issue, since we always escape properly at output for sanity.
|
489 |
-
* @access private
|
490 |
-
* @todo deprecate--let JS handle this.
|
491 |
-
*
|
492 |
-
* @param array $args An array of 'id' and 'taxonomy' values.
|
493 |
-
* @param string $for The screen it's for. Accepts 'edit' and 'settings'.
|
494 |
-
* @return array An array social of titles and descriptions.
|
495 |
-
*/
|
496 |
-
public function _get_social_placeholders( array $args, $for = 'edit' ) {
|
497 |
-
|
498 |
-
$desc_from_custom_field = $this->get_description_from_custom_field( $args, false );
|
499 |
-
|
500 |
-
if ( 'settings' === $for ) {
|
501 |
-
$pm_edit_og_title = $args['id'] ? $this->get_post_meta_item( '_open_graph_title', $args['id'] ) : '';
|
502 |
-
$pm_edit_og_desc = $args['id'] ? $this->get_post_meta_item( '_open_graph_description', $args['id'] ) : '';
|
503 |
-
$pm_edit_tw_title = $args['id'] ? $this->get_post_meta_item( '_twitter_title', $args['id'] ) : '';
|
504 |
-
$pm_edit_tw_desc = $args['id'] ? $this->get_post_meta_item( '_twitter_description', $args['id'] ) : '';
|
505 |
-
|
506 |
-
// Gets custom fields from SEO settings.
|
507 |
-
$home_og_title = $this->get_option( 'homepage_og_title' );
|
508 |
-
$home_og_desc = $this->get_option( 'homepage_og_description' );
|
509 |
-
|
510 |
-
//! OG title generator falls back to meta input. The description does not.
|
511 |
-
$og_tit_placeholder = $pm_edit_og_title
|
512 |
-
?: $this->get_generated_open_graph_title( $args, false );
|
513 |
-
$og_desc_placeholder = $pm_edit_og_desc
|
514 |
-
?: $desc_from_custom_field
|
515 |
-
?: $this->get_generated_open_graph_description( $args, false );
|
516 |
-
|
517 |
-
//! TW title generator falls back to meta input. The description does not.
|
518 |
-
$tw_tit_placeholder = $pm_edit_tw_title
|
519 |
-
?: $home_og_title
|
520 |
-
?: $pm_edit_og_title
|
521 |
-
?: $this->get_generated_twitter_title( $args, false );
|
522 |
-
$tw_desc_placeholder = $pm_edit_tw_desc
|
523 |
-
?: $home_og_desc
|
524 |
-
?: $pm_edit_og_desc
|
525 |
-
?: $desc_from_custom_field
|
526 |
-
?: $this->get_generated_twitter_description( $args, false );
|
527 |
-
} elseif ( 'edit' === $for ) {
|
528 |
-
if ( ! $args['taxonomy'] ) {
|
529 |
-
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
530 |
-
// Gets custom fields from SEO settings.
|
531 |
-
$home_desc = $this->get_option( 'homepage_description' );
|
532 |
-
|
533 |
-
$home_og_title = $this->get_option( 'homepage_og_title' );
|
534 |
-
$home_og_desc = $this->get_option( 'homepage_og_description' );
|
535 |
-
$home_tw_title = $this->get_option( 'homepage_twitter_title' );
|
536 |
-
$home_tw_desc = $this->get_option( 'homepage_twitter_description' );
|
537 |
-
|
538 |
-
// Gets custom fields from page.
|
539 |
-
$custom_og_title = $this->get_post_meta_item( '_open_graph_title', $args['id'] );
|
540 |
-
$custom_og_desc = $this->get_post_meta_item( '_open_graph_description', $args['id'] );
|
541 |
-
|
542 |
-
//! OG title generator falls back to meta input. The description does not.
|
543 |
-
$og_tit_placeholder = $home_og_title
|
544 |
-
?: $this->get_generated_open_graph_title( $args, false );
|
545 |
-
$og_desc_placeholder = $home_og_desc
|
546 |
-
?: $home_desc
|
547 |
-
?: $desc_from_custom_field
|
548 |
-
?: $this->get_generated_open_graph_description( $args, false );
|
549 |
-
|
550 |
-
//! TW title generator falls back to meta input. The description does not.
|
551 |
-
$tw_tit_placeholder = $home_tw_title
|
552 |
-
?: $home_og_title
|
553 |
-
?: $custom_og_title
|
554 |
-
?: $this->get_generated_twitter_title( $args, false );
|
555 |
-
$tw_desc_placeholder = $home_tw_desc
|
556 |
-
?: $home_og_desc
|
557 |
-
?: $custom_og_desc
|
558 |
-
?: $home_desc
|
559 |
-
?: $desc_from_custom_field
|
560 |
-
?: $this->get_generated_twitter_description( $args, false );
|
561 |
-
} else {
|
562 |
-
// Gets custom fields.
|
563 |
-
$custom_og_title = $this->get_post_meta_item( '_open_graph_title', $args['id'] );
|
564 |
-
$custom_og_desc = $this->get_post_meta_item( '_open_graph_description', $args['id'] );
|
565 |
-
|
566 |
-
//! OG title generator falls back to meta input. The description does not.
|
567 |
-
$og_tit_placeholder = $this->get_generated_open_graph_title( $args, false );
|
568 |
-
$og_desc_placeholder = $desc_from_custom_field
|
569 |
-
?: $this->get_generated_open_graph_description( $args, false );
|
570 |
-
|
571 |
-
//! TW title generator falls back to meta input. The description does not.
|
572 |
-
$tw_tit_placeholder = $custom_og_title
|
573 |
-
?: $this->get_generated_twitter_title( $args, false );
|
574 |
-
$tw_desc_placeholder = $custom_og_desc
|
575 |
-
?: $desc_from_custom_field
|
576 |
-
?: $this->get_generated_twitter_description( $args, false );
|
577 |
-
}
|
578 |
-
} else {
|
579 |
-
$meta = $this->get_term_meta( $args['id'] );
|
580 |
-
|
581 |
-
//! OG title generator falls back to meta input. The description does not.
|
582 |
-
$og_tit_placeholder = $this->get_generated_open_graph_title( $args, false );
|
583 |
-
$og_desc_placeholder = $desc_from_custom_field
|
584 |
-
?: $this->get_generated_open_graph_description( $args, false );
|
585 |
-
|
586 |
-
//! TW title generator falls back to meta input. The description does not.
|
587 |
-
$tw_tit_placeholder = $meta['og_title']
|
588 |
-
?: $og_tit_placeholder;
|
589 |
-
$tw_desc_placeholder = $meta['og_description']
|
590 |
-
?: $desc_from_custom_field
|
591 |
-
?: $this->get_generated_twitter_description( $args, false );
|
592 |
-
}
|
593 |
-
} else {
|
594 |
-
$og_tit_placeholder = '';
|
595 |
-
$tw_tit_placeholder = '';
|
596 |
-
$og_desc_placeholder = '';
|
597 |
-
$tw_desc_placeholder = '';
|
598 |
-
}
|
599 |
-
|
600 |
-
return [
|
601 |
-
'title' => [
|
602 |
-
'og' => $this->escape_title( $og_tit_placeholder ?: '' ),
|
603 |
-
'twitter' => $this->escape_title( $tw_tit_placeholder ?: '' ),
|
604 |
-
],
|
605 |
-
'description' => [
|
606 |
-
'og' => $this->escape_description( $og_desc_placeholder ?: '' ),
|
607 |
-
'twitter' => $this->escape_description( $tw_desc_placeholder ?: '' ),
|
608 |
-
],
|
609 |
-
];
|
610 |
-
}
|
611 |
}
|
86 |
);
|
87 |
|
88 |
// Enqueue scripts
|
89 |
+
\add_action( "admin_print_scripts-{$this->seo_settings_page_hook}", [ $this, '_init_admin_scripts' ], 11 );
|
90 |
+
\add_action( "load-{$this->seo_settings_page_hook}", [ $this, '_register_seo_settings_meta_boxes' ] );
|
91 |
}
|
92 |
|
93 |
/**
|
110 |
public function _output_settings_wrap() {
|
111 |
|
112 |
\add_action(
|
113 |
+
"{$this->seo_settings_page_hook}_settings_page_boxes",
|
114 |
+
[ Bridges\SeoSettings::class, '_output_columns' ]
|
115 |
);
|
116 |
|
117 |
Bridges\SeoSettings::_output_wrap();
|
139 |
if ( $show_seobox )
|
140 |
\add_action(
|
141 |
'add_meta_boxes',
|
142 |
+
[ Bridges\PostSettings::class, '_prepare_meta_box' ]
|
143 |
);
|
144 |
}
|
145 |
|
164 |
$priority = (int) \apply_filters( 'the_seo_framework_term_metabox_priority', 0 );
|
165 |
|
166 |
\add_action(
|
167 |
+
"{$taxonomy}_edit_form",
|
168 |
+
[ Bridges\TermSettings::class, '_prepare_setting_fields' ],
|
169 |
$priority,
|
170 |
2
|
171 |
);
|
184 |
// WordPress made a mess of this. We can't reliably get a user future-proof. Load class for all users; check there.
|
185 |
// if ( ! $user->has_cap( THE_SEO_FRAMEWORK_AUTHOR_INFO_CAP ) ) return;
|
186 |
|
187 |
+
\add_action( 'show_user_profile', [ Bridges\UserSettings::class, '_prepare_setting_fields' ], 0, 1 );
|
188 |
+
\add_action( 'edit_user_profile', [ Bridges\UserSettings::class, '_prepare_setting_fields' ], 0, 1 );
|
189 |
}
|
190 |
|
191 |
/**
|
340 |
* 'escape' => bool Optional. Whether to escape the $message. Default true.
|
341 |
* }
|
342 |
*/
|
343 |
+
protected function output_dismissible_persistent_notice( $message, $key, $args ) { // phpcs:ignore,VariableAnalysis.CodeAnalysis
|
344 |
$this->get_view( 'notice/persistent', get_defined_vars() );
|
345 |
}
|
346 |
|
355 |
*/
|
356 |
protected function output_dismissible_persistent_notices() {
|
357 |
|
358 |
+
$notices = $this->get_static_cache( 'persistent_notices', [] );
|
359 |
+
$screenbase = \get_current_screen()->base ?? '';
|
|
|
360 |
|
361 |
// Ideally, we don't want to output more than one on no-js. Alas, we can't anticipate the importance and order of the notices.
|
362 |
foreach ( $notices as $key => $notice ) {
|
364 |
|
365 |
if ( ! \current_user_can( $cond['capability'] ) ) continue;
|
366 |
if ( $cond['user'] && $cond['user'] !== $this->get_user_id() ) continue;
|
367 |
+
if ( $cond['screens'] && ! \in_array( $screenbase, $cond['screens'], true ) ) continue;
|
368 |
+
if ( $cond['excl_screens'] && \in_array( $screenbase, $cond['excl_screens'], true ) ) continue;
|
369 |
|
370 |
if ( -1 !== $cond['timeout'] && $cond['timeout'] < time() ) {
|
371 |
$this->clear_persistent_notice( $key );
|
383 |
* Returns the SEO Bar.
|
384 |
*
|
385 |
* @since 4.0.0
|
386 |
+
* @uses \The_SEO_Framework\Interpreters\SEOBar::generate_bar();
|
387 |
*
|
388 |
* @param array $query : {
|
389 |
* int $id : Required. The current post or term ID.
|
393 |
* }
|
394 |
* @return string The generated SEO bar, in HTML.
|
395 |
*/
|
396 |
+
public function get_generated_seo_bar( $query ) {
|
397 |
+
return Interpreters\SEOBar::generate_bar( $query );
|
398 |
}
|
399 |
|
400 |
/**
|
421 |
* @param string $id The input ID.
|
422 |
* @param array $data The input data.
|
423 |
*/
|
424 |
+
public function output_js_title_data( $id, $data ) {
|
425 |
+
vprintf(
|
426 |
implode(
|
427 |
'',
|
428 |
[
|
434 |
'<span id="tsf-title-data_%1$s" class="hidden wp-exclude-emoji" data-for="%1$s" %2$s></span>',
|
435 |
]
|
436 |
),
|
437 |
+
[
|
438 |
+
\esc_attr( $id ),
|
439 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput -- make_data_attributes escapes.
|
440 |
+
Interpreters\HTML::make_data_attributes( $data ),
|
441 |
+
]
|
442 |
+
);
|
443 |
+
}
|
444 |
+
|
445 |
+
/**
|
446 |
+
* Outputs reference social HTML elements for JavaScript for a specific ID.
|
447 |
+
*
|
448 |
+
* @since 4.2.0
|
449 |
+
*
|
450 |
+
* @param string $group The social input group ID.
|
451 |
+
* @param array[og,tw] $settings The input settings data.
|
452 |
+
*/
|
453 |
+
public function output_js_social_data( $group, $settings ) {
|
454 |
+
vprintf(
|
455 |
+
'<span id="tsf-social-data_%1$s" class="hidden wp-exclude-emoji" data-group="%1$s" %2$s></span>',
|
456 |
+
[
|
457 |
+
\esc_attr( $group ),
|
458 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput -- make_data_attributes escapes.
|
459 |
+
Interpreters\HTML::make_data_attributes( [ 'settings' => $settings ] ),
|
460 |
+
]
|
461 |
);
|
462 |
}
|
463 |
|
484 |
* @param string $id The description input ID.
|
485 |
* @param array $data The input data.
|
486 |
*/
|
487 |
+
public function output_js_description_data( $id, $data ) {
|
488 |
+
vprintf(
|
489 |
implode(
|
490 |
'',
|
491 |
[
|
493 |
'<span id="tsf-description-data_%1$s" class="hidden wp-exclude-emoji" data-for="%1$s" %2$s ></span>',
|
494 |
]
|
495 |
),
|
496 |
+
[
|
497 |
+
\esc_attr( $id ),
|
498 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput -- make_data_attributes escapes.
|
499 |
+
Interpreters\HTML::make_data_attributes( $data ),
|
500 |
+
]
|
501 |
);
|
502 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
503 |
}
|
@@ -42,19 +42,21 @@ final class AJAX {
|
|
42 |
*
|
43 |
* @since 4.1.0
|
44 |
* @since 4.1.4 Moved to \The_SEO_Framework\Bridges\AJAX and made static.
|
|
|
45 |
* Security check OK.
|
46 |
* @access private
|
47 |
*/
|
48 |
public static function _wp_ajax_dismiss_notice() {
|
49 |
|
|
|
|
|
|
|
50 |
// phpcs:ignore, WordPress.Security.NonceVerification.Missing -- We require the POST data to find locally stored nonces.
|
51 |
-
$key =
|
52 |
|
53 |
if ( ! $key )
|
54 |
\wp_send_json_error( null, 400 );
|
55 |
|
56 |
-
$tsf = \the_seo_framework();
|
57 |
-
|
58 |
$notices = $tsf->get_static_cache( 'persistent_notices', [] );
|
59 |
if ( empty( $notices[ $key ]['conditions']['capability'] ) ) {
|
60 |
// Notice was deleted already elsewhere, or key was faulty. Either way, ignore--should be self-resolving.
|
@@ -74,27 +76,22 @@ final class AJAX {
|
|
74 |
*
|
75 |
* @since 3.1.0 Introduced in 2.6.0, but the name changed.
|
76 |
* @since 4.1.4 Moved to \The_SEO_Framework\Bridges\AJAX and made static.
|
|
|
|
|
77 |
* @securitycheck 3.0.0 OK.
|
78 |
* @access private
|
79 |
*/
|
80 |
public static function _wp_ajax_update_counter_type() {
|
81 |
|
82 |
-
$tsf = \
|
|
|
83 |
|
84 |
// phpcs:disable, WordPress.Security.NonceVerification -- _check_tsf_ajax_referer() does this.
|
85 |
$tsf->_check_tsf_ajax_referer( 'edit_posts' );
|
86 |
|
87 |
-
// Remove output buffer. TODO why don't we do this consistently??
|
88 |
-
$tsf->clean_response_header();
|
89 |
-
|
90 |
// If current user isn't allowed to edit posts, don't do anything and kill PHP.
|
91 |
-
if ( ! \current_user_can( 'edit_posts' ) )
|
92 |
-
|
93 |
-
\wp_send_json( [
|
94 |
-
'type' => 'failure',
|
95 |
-
'value' => '',
|
96 |
-
] );
|
97 |
-
}
|
98 |
|
99 |
/**
|
100 |
* Count up, reset to 0 if needed. We have 4 options: 0, 1, 2, 3
|
@@ -111,16 +108,13 @@ final class AJAX {
|
|
111 |
$value = 0;
|
112 |
|
113 |
// Update the option and get results of action.
|
114 |
-
$
|
115 |
-
|
116 |
-
$results = [
|
117 |
-
'type' => $type,
|
118 |
-
'value' => $value,
|
119 |
-
];
|
120 |
|
121 |
// Encode and echo results. Requires JSON decode within JS.
|
122 |
-
\
|
123 |
-
|
|
|
|
|
124 |
// phpcs:enable, WordPress.Security.NonceVerification
|
125 |
}
|
126 |
|
@@ -142,13 +136,17 @@ final class AJAX {
|
|
142 |
*
|
143 |
* @since 3.1.0 Introduced in 2.9.0, but the name changed.
|
144 |
* @since 4.1.4 Moved to \The_SEO_Framework\Bridges\AJAX and made static.
|
|
|
145 |
* @securitycheck 3.0.0 OK.
|
146 |
* @access private
|
147 |
*/
|
148 |
public static function _wp_ajax_crop_image() {
|
149 |
|
|
|
|
|
|
|
150 |
// phpcs:disable, WordPress.Security.NonceVerification -- _check_tsf_ajax_referer does this.
|
151 |
-
|
152 |
|
153 |
if ( ! \current_user_can( 'upload_files' ) || ! isset( $_POST['id'], $_POST['context'], $_POST['cropDetails'] ) )
|
154 |
\wp_send_json_error();
|
@@ -156,7 +154,7 @@ final class AJAX {
|
|
156 |
$attachment_id = \absint( $_POST['id'] );
|
157 |
|
158 |
$context = str_replace( '_', '-', \sanitize_key( $_POST['context'] ) );
|
159 |
-
$data = array_map( '
|
160 |
$cropped = \wp_crop_image( $attachment_id, $data['x1'], $data['y1'], $data['width'], $data['height'], $data['dst_width'], $data['dst_height'] );
|
161 |
|
162 |
if ( ! $cropped || \is_wp_error( $cropped ) )
|
@@ -235,26 +233,21 @@ final class AJAX {
|
|
235 |
*
|
236 |
* @since 4.0.0
|
237 |
* @since 4.1.4 Moved to \The_SEO_Framework\Bridges\AJAX and made static.
|
|
|
238 |
* @access private
|
239 |
*/
|
240 |
public static function _wp_ajax_get_post_data() {
|
241 |
|
242 |
-
$tsf = \
|
|
|
243 |
|
244 |
// phpcs:disable, WordPress.Security.NonceVerification -- _check_tsf_ajax_referer() does this.
|
245 |
$tsf->_check_tsf_ajax_referer( 'edit_posts' );
|
246 |
|
247 |
-
// Clear output buffer.
|
248 |
-
$tsf->clean_response_header();
|
249 |
-
|
250 |
$post_id = \absint( $_POST['post_id'] );
|
251 |
|
252 |
-
if ( ! $post_id || ! \current_user_can( 'edit_post', $post_id ) )
|
253 |
-
\
|
254 |
-
'type' => 'failure',
|
255 |
-
'data' => [],
|
256 |
-
] );
|
257 |
-
}
|
258 |
|
259 |
$_get_defaults = [
|
260 |
'seobar' => false,
|
@@ -270,17 +263,14 @@ final class AJAX {
|
|
270 |
array_intersect_key(
|
271 |
array_merge(
|
272 |
$_get_defaults,
|
273 |
-
(array) (
|
274 |
),
|
275 |
$_get_defaults
|
276 |
)
|
277 |
)
|
278 |
);
|
279 |
|
280 |
-
$_generator_args = [
|
281 |
-
'id' => $post_id,
|
282 |
-
'taxonomy' => '',
|
283 |
-
];
|
284 |
|
285 |
$data = [];
|
286 |
|
@@ -296,23 +286,27 @@ final class AJAX {
|
|
296 |
switch ( $g ) {
|
297 |
case 'metadescription':
|
298 |
if ( $tsf->is_static_frontpage( $post_id ) ) {
|
299 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
300 |
$data[ $g ] = $tsf->get_option( 'homepage_description' )
|
301 |
?: $tsf->get_generated_description( $_generator_args, false );
|
302 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
303 |
} else {
|
304 |
$data[ $g ] = $tsf->get_generated_description( $_generator_args, false );
|
305 |
}
|
306 |
break;
|
307 |
case 'ogdescription':
|
308 |
-
|
309 |
-
|
310 |
-
|
|
|
|
|
|
|
311 |
break;
|
312 |
case 'twdescription':
|
313 |
-
|
314 |
-
|
315 |
-
|
|
|
|
|
|
|
316 |
break;
|
317 |
}
|
318 |
|
@@ -321,11 +315,9 @@ final class AJAX {
|
|
321 |
|
322 |
case 'imageurl':
|
323 |
if ( $tsf->is_static_frontpage( $post_id ) && $tsf->get_option( 'homepage_social_image_url' ) ) {
|
324 |
-
$
|
325 |
-
$data[ $g ] = isset( $image_details['url'] ) ? $image_details['url'] : '';
|
326 |
} else {
|
327 |
-
$
|
328 |
-
$data[ $g ] = isset( $image_details['url'] ) ? $image_details['url'] : '';
|
329 |
}
|
330 |
break;
|
331 |
|
@@ -334,12 +326,10 @@ final class AJAX {
|
|
334 |
}
|
335 |
endforeach;
|
336 |
|
337 |
-
\
|
338 |
-
'type' => 'success',
|
339 |
'data' => $data,
|
340 |
'processed' => $get,
|
341 |
] );
|
342 |
-
|
343 |
// phpcs:enable, WordPress.Security.NonceVerification
|
344 |
}
|
345 |
}
|
42 |
*
|
43 |
* @since 4.1.0
|
44 |
* @since 4.1.4 Moved to \The_SEO_Framework\Bridges\AJAX and made static.
|
45 |
+
* @since 4.2.0 Now cleans response header.
|
46 |
* Security check OK.
|
47 |
* @access private
|
48 |
*/
|
49 |
public static function _wp_ajax_dismiss_notice() {
|
50 |
|
51 |
+
$tsf = \tsf();
|
52 |
+
$tsf->clean_response_header();
|
53 |
+
|
54 |
// phpcs:ignore, WordPress.Security.NonceVerification.Missing -- We require the POST data to find locally stored nonces.
|
55 |
+
$key = $_POST['tsf_dismiss_key'] ?? '';
|
56 |
|
57 |
if ( ! $key )
|
58 |
\wp_send_json_error( null, 400 );
|
59 |
|
|
|
|
|
60 |
$notices = $tsf->get_static_cache( 'persistent_notices', [] );
|
61 |
if ( empty( $notices[ $key ]['conditions']['capability'] ) ) {
|
62 |
// Notice was deleted already elsewhere, or key was faulty. Either way, ignore--should be self-resolving.
|
76 |
*
|
77 |
* @since 3.1.0 Introduced in 2.6.0, but the name changed.
|
78 |
* @since 4.1.4 Moved to \The_SEO_Framework\Bridges\AJAX and made static.
|
79 |
+
* @since 4.2.0 1. Now uses wp.ajax instead of $.ajax.
|
80 |
+
* 2. No longer tests if settings-saving was successful.
|
81 |
* @securitycheck 3.0.0 OK.
|
82 |
* @access private
|
83 |
*/
|
84 |
public static function _wp_ajax_update_counter_type() {
|
85 |
|
86 |
+
$tsf = \tsf();
|
87 |
+
$tsf->clean_response_header();
|
88 |
|
89 |
// phpcs:disable, WordPress.Security.NonceVerification -- _check_tsf_ajax_referer() does this.
|
90 |
$tsf->_check_tsf_ajax_referer( 'edit_posts' );
|
91 |
|
|
|
|
|
|
|
92 |
// If current user isn't allowed to edit posts, don't do anything and kill PHP.
|
93 |
+
if ( ! \current_user_can( 'edit_posts' ) )
|
94 |
+
\wp_send_json_error();
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
/**
|
97 |
* Count up, reset to 0 if needed. We have 4 options: 0, 1, 2, 3
|
108 |
$value = 0;
|
109 |
|
110 |
// Update the option and get results of action.
|
111 |
+
$tsf->update_single_user_meta_item( $tsf->get_user_id(), 'counter_type', $value );
|
|
|
|
|
|
|
|
|
|
|
112 |
|
113 |
// Encode and echo results. Requires JSON decode within JS.
|
114 |
+
\wp_send_json_success( [
|
115 |
+
'type' => 'success',
|
116 |
+
'value' => $value,
|
117 |
+
] );
|
118 |
// phpcs:enable, WordPress.Security.NonceVerification
|
119 |
}
|
120 |
|
136 |
*
|
137 |
* @since 3.1.0 Introduced in 2.9.0, but the name changed.
|
138 |
* @since 4.1.4 Moved to \The_SEO_Framework\Bridges\AJAX and made static.
|
139 |
+
* @since 4.2.0 Now cleans response header.
|
140 |
* @securitycheck 3.0.0 OK.
|
141 |
* @access private
|
142 |
*/
|
143 |
public static function _wp_ajax_crop_image() {
|
144 |
|
145 |
+
$tsf = \tsf();
|
146 |
+
$tsf->clean_response_header();
|
147 |
+
|
148 |
// phpcs:disable, WordPress.Security.NonceVerification -- _check_tsf_ajax_referer does this.
|
149 |
+
$tsf->_check_tsf_ajax_referer( 'upload_files' );
|
150 |
|
151 |
if ( ! \current_user_can( 'upload_files' ) || ! isset( $_POST['id'], $_POST['context'], $_POST['cropDetails'] ) )
|
152 |
\wp_send_json_error();
|
154 |
$attachment_id = \absint( $_POST['id'] );
|
155 |
|
156 |
$context = str_replace( '_', '-', \sanitize_key( $_POST['context'] ) );
|
157 |
+
$data = array_map( 'absint', $_POST['cropDetails'] );
|
158 |
$cropped = \wp_crop_image( $attachment_id, $data['x1'], $data['y1'], $data['width'], $data['height'], $data['dst_width'], $data['dst_height'] );
|
159 |
|
160 |
if ( ! $cropped || \is_wp_error( $cropped ) )
|
233 |
*
|
234 |
* @since 4.0.0
|
235 |
* @since 4.1.4 Moved to \The_SEO_Framework\Bridges\AJAX and made static.
|
236 |
+
* @since 4.2.0 Now uses wp.ajax, instead of $.ajax
|
237 |
* @access private
|
238 |
*/
|
239 |
public static function _wp_ajax_get_post_data() {
|
240 |
|
241 |
+
$tsf = \tsf();
|
242 |
+
$tsf->clean_response_header();
|
243 |
|
244 |
// phpcs:disable, WordPress.Security.NonceVerification -- _check_tsf_ajax_referer() does this.
|
245 |
$tsf->_check_tsf_ajax_referer( 'edit_posts' );
|
246 |
|
|
|
|
|
|
|
247 |
$post_id = \absint( $_POST['post_id'] );
|
248 |
|
249 |
+
if ( ! $post_id || ! \current_user_can( 'edit_post', $post_id ) )
|
250 |
+
\wp_send_json_error();
|
|
|
|
|
|
|
|
|
251 |
|
252 |
$_get_defaults = [
|
253 |
'seobar' => false,
|
263 |
array_intersect_key(
|
264 |
array_merge(
|
265 |
$_get_defaults,
|
266 |
+
(array) ( $_POST['get'] ?? [] )
|
267 |
),
|
268 |
$_get_defaults
|
269 |
)
|
270 |
)
|
271 |
);
|
272 |
|
273 |
+
$_generator_args = [ 'id' => $post_id ];
|
|
|
|
|
|
|
274 |
|
275 |
$data = [];
|
276 |
|
286 |
switch ( $g ) {
|
287 |
case 'metadescription':
|
288 |
if ( $tsf->is_static_frontpage( $post_id ) ) {
|
|
|
289 |
$data[ $g ] = $tsf->get_option( 'homepage_description' )
|
290 |
?: $tsf->get_generated_description( $_generator_args, false );
|
|
|
291 |
} else {
|
292 |
$data[ $g ] = $tsf->get_generated_description( $_generator_args, false );
|
293 |
}
|
294 |
break;
|
295 |
case 'ogdescription':
|
296 |
+
if ( $tsf->is_static_frontpage( $post_id ) ) {
|
297 |
+
$data[ $g ] = $tsf->get_option( 'homepage_description' )
|
298 |
+
?: $tsf->get_generated_open_graph_description( $_generator_args, false );
|
299 |
+
} else {
|
300 |
+
$data[ $g ] = $tsf->get_generated_open_graph_description( $_generator_args, false );
|
301 |
+
}
|
302 |
break;
|
303 |
case 'twdescription':
|
304 |
+
if ( $tsf->is_static_frontpage( $post_id ) ) {
|
305 |
+
$data[ $g ] = $tsf->get_option( 'homepage_description' )
|
306 |
+
?: $tsf->get_generated_twitter_description( $_generator_args, false );
|
307 |
+
} else {
|
308 |
+
$data[ $g ] = $tsf->get_generated_twitter_description( $_generator_args, false );
|
309 |
+
}
|
310 |
break;
|
311 |
}
|
312 |
|
315 |
|
316 |
case 'imageurl':
|
317 |
if ( $tsf->is_static_frontpage( $post_id ) && $tsf->get_option( 'homepage_social_image_url' ) ) {
|
318 |
+
$data[ $g ] = current( $tsf->get_image_details( $_generator_args, true, 'social', true ) )['url'] ?? '';
|
|
|
319 |
} else {
|
320 |
+
$data[ $g ] = current( $tsf->get_generated_image_details( $_generator_args, true, 'social', true ) )['url'] ?? '';
|
|
|
321 |
}
|
322 |
break;
|
323 |
|
326 |
}
|
327 |
endforeach;
|
328 |
|
329 |
+
\wp_send_json_success( [
|
|
|
330 |
'data' => $data,
|
331 |
'processed' => $get,
|
332 |
] );
|
|
|
333 |
// phpcs:enable, WordPress.Security.NonceVerification
|
334 |
}
|
335 |
}
|
@@ -25,18 +25,6 @@ namespace The_SEO_Framework\Bridges;
|
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
-
/**
|
29 |
-
* Sets up class loader as file is loaded.
|
30 |
-
* This is done asynchronously, because static calls are handled prior and after.
|
31 |
-
*
|
32 |
-
* @see EOF. Because of the autoloader and (future) trait calling, we can't do it before the class is read.
|
33 |
-
* @link https://bugs.php.net/bug.php?id=75771
|
34 |
-
*/
|
35 |
-
$_load_feed_class = function() {
|
36 |
-
// phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
|
37 |
-
new Feed();
|
38 |
-
};
|
39 |
-
|
40 |
/**
|
41 |
* Prepares feed mofifications.
|
42 |
*
|
@@ -65,7 +53,7 @@ final class Feed {
|
|
65 |
* @return \The_SEO_Framework\Bridges\Feed $instance
|
66 |
*/
|
67 |
public static function get_instance() {
|
68 |
-
return static::$instance;
|
69 |
}
|
70 |
|
71 |
/**
|
@@ -76,7 +64,9 @@ final class Feed {
|
|
76 |
*
|
77 |
* @since 4.1.0
|
78 |
*/
|
79 |
-
public static function prepare() {
|
|
|
|
|
80 |
|
81 |
/**
|
82 |
* The constructor. Can't be instantiated externally from this file.
|
@@ -93,8 +83,7 @@ final class Feed {
|
|
93 |
static $count = 0;
|
94 |
0 === $count++ or \wp_die( 'Don\'t instance <code>' . __CLASS__ . '</code>.' );
|
95 |
|
96 |
-
static::$tsf
|
97 |
-
static::$instance = &$this;
|
98 |
}
|
99 |
|
100 |
/**
|
@@ -157,19 +146,20 @@ final class Feed {
|
|
157 |
|
158 |
if ( ! $content ) return '';
|
159 |
|
160 |
-
// Strip all code and lines.
|
161 |
-
$excerpt = static::$tsf->s_excerpt_raw( $content, false );
|
162 |
-
|
163 |
/**
|
164 |
* @since 2.5.2
|
165 |
* @param int $max_len The maximum feed (multibyte) string length.
|
166 |
*/
|
167 |
$max_len = (int) \apply_filters( 'the_seo_framework_max_content_feed_length', 400 );
|
168 |
|
169 |
-
//
|
170 |
-
$excerpt = static::$tsf->trim_excerpt(
|
|
|
|
|
|
|
|
|
171 |
|
172 |
-
return
|
173 |
}
|
174 |
|
175 |
/**
|
@@ -191,11 +181,9 @@ final class Feed {
|
|
191 |
);
|
192 |
|
193 |
return sprintf(
|
194 |
-
'<p><a href="%s" rel="nofollow">%s</a></p>',
|
195 |
\esc_url( \get_permalink() ),
|
196 |
\esc_html( $source_i18n )
|
197 |
);
|
198 |
}
|
199 |
}
|
200 |
-
|
201 |
-
$_load_feed_class();
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
/**
|
29 |
* Prepares feed mofifications.
|
30 |
*
|
53 |
* @return \The_SEO_Framework\Bridges\Feed $instance
|
54 |
*/
|
55 |
public static function get_instance() {
|
56 |
+
return static::$instance ?? ( static::$instance = new static );
|
57 |
}
|
58 |
|
59 |
/**
|
64 |
*
|
65 |
* @since 4.1.0
|
66 |
*/
|
67 |
+
public static function prepare() {
|
68 |
+
static::get_instance();
|
69 |
+
}
|
70 |
|
71 |
/**
|
72 |
* The constructor. Can't be instantiated externally from this file.
|
83 |
static $count = 0;
|
84 |
0 === $count++ or \wp_die( 'Don\'t instance <code>' . __CLASS__ . '</code>.' );
|
85 |
|
86 |
+
static::$tsf = \tsf();
|
|
|
87 |
}
|
88 |
|
89 |
/**
|
146 |
|
147 |
if ( ! $content ) return '';
|
148 |
|
|
|
|
|
|
|
149 |
/**
|
150 |
* @since 2.5.2
|
151 |
* @param int $max_len The maximum feed (multibyte) string length.
|
152 |
*/
|
153 |
$max_len = (int) \apply_filters( 'the_seo_framework_max_content_feed_length', 400 );
|
154 |
|
155 |
+
// Strip all code and lines, and AI-trim it.
|
156 |
+
$excerpt = static::$tsf->trim_excerpt(
|
157 |
+
static::$tsf->s_excerpt_raw( $content, false ),
|
158 |
+
0,
|
159 |
+
$max_len
|
160 |
+
);
|
161 |
|
162 |
+
return "<p>$excerpt</p>";
|
163 |
}
|
164 |
|
165 |
/**
|
181 |
);
|
182 |
|
183 |
return sprintf(
|
184 |
+
'<p><a href="%s" rel="nofollow">%s</a></p>', // Keep XHTML
|
185 |
\esc_url( \get_permalink() ),
|
186 |
\esc_html( $source_i18n )
|
187 |
);
|
188 |
}
|
189 |
}
|
|
|
|
@@ -4,6 +4,7 @@
|
|
4 |
*
|
5 |
* - David Seltzer
|
6 |
*
|
7 |
-
* (probably, uncredited:
|
8 |
-
*
|
|
|
9 |
*/
|
4 |
*
|
5 |
* - David Seltzer
|
6 |
*
|
7 |
+
* (probably, uncredited: quote's based on "Charlie and the Chocolate Factory" by
|
8 |
+
* Roald Dahl, but it's verbatim to the book; the screenwriting was edited so
|
9 |
+
* much that Roald ultimately decided to disown the film)
|
10 |
*/
|
@@ -65,9 +65,7 @@ final class ListEdit extends ListTable {
|
|
65 |
*/
|
66 |
public function _prepare_edit_box( $screen ) {
|
67 |
|
68 |
-
|
69 |
-
|
70 |
-
if ( ! $taxonomy ) {
|
71 |
// WordPress doesn't support this feature yet for taxonomies.
|
72 |
// Exclude it for when the time may come and faulty fields are displayed.
|
73 |
// Mind the "2".
|
@@ -125,7 +123,7 @@ final class ListEdit extends ListTable {
|
|
125 |
if ( $taxonomy ) {
|
126 |
// Not yet.
|
127 |
} else {
|
128 |
-
\
|
129 |
}
|
130 |
}
|
131 |
|
@@ -144,9 +142,9 @@ final class ListEdit extends ListTable {
|
|
144 |
if ( $this->column_name !== $column_name ) return;
|
145 |
|
146 |
if ( $taxonomy ) {
|
147 |
-
\
|
148 |
} else {
|
149 |
-
\
|
150 |
}
|
151 |
}
|
152 |
|
@@ -165,16 +163,13 @@ final class ListEdit extends ListTable {
|
|
165 |
if ( $this->column_name !== $column_name ) return;
|
166 |
if ( ! \current_user_can( 'edit_post', $post_id ) ) return;
|
167 |
|
168 |
-
$tsf = \
|
169 |
|
170 |
-
$query = [
|
171 |
-
'id' => $post_id,
|
172 |
-
'taxonomy' => '',
|
173 |
-
];
|
174 |
|
175 |
$r_defaults = $tsf->generate_robots_meta(
|
176 |
$query,
|
177 |
-
|
178 |
\The_SEO_Framework\ROBOTS_IGNORE_SETTINGS
|
179 |
);
|
180 |
|
@@ -224,7 +219,7 @@ final class ListEdit extends ListTable {
|
|
224 |
* @param string $default Optional. Only works when $isSelect is true. The default value to be set in select index 0.
|
225 |
* }
|
226 |
* }
|
227 |
-
* @param array $query The query data. Contains 'id'
|
228 |
*/
|
229 |
$data = \apply_filters_ref_array( 'the_seo_framework_list_table_data', [ $data, $query ] );
|
230 |
|
@@ -237,7 +232,6 @@ final class ListEdit extends ListTable {
|
|
237 |
);
|
238 |
|
239 |
if ( $tsf->is_static_frontpage( $query['id'] ) ) {
|
240 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
241 |
// When the homepage title is set, we can safely get the custom field.
|
242 |
$_has_home_title = (bool) $tsf->escape_title( $tsf->get_option( 'homepage_title' ) );
|
243 |
$default_title = $_has_home_title
|
@@ -253,7 +247,6 @@ final class ListEdit extends ListTable {
|
|
253 |
? $tsf->get_description_from_custom_field( $query )
|
254 |
: $tsf->get_generated_description( $query );
|
255 |
$is_desc_ref_locked = $_has_home_desc;
|
256 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
257 |
} else {
|
258 |
$default_title = $tsf->get_filtered_raw_generated_title( $query );
|
259 |
$addition = $tsf->get_blogname();
|
@@ -269,9 +262,9 @@ final class ListEdit extends ListTable {
|
|
269 |
];
|
270 |
$title_data = [
|
271 |
'refTitleLocked' => $is_title_ref_locked,
|
272 |
-
'defaultTitle' => $default_title,
|
273 |
'addAdditions' => $tsf->use_title_branding( $query ),
|
274 |
-
'additionValue' => $tsf->
|
275 |
'additionPlacement' => 'left' === $seplocation ? 'before' : 'after',
|
276 |
];
|
277 |
$desc_data = [
|
@@ -309,6 +302,7 @@ final class ListEdit extends ListTable {
|
|
309 |
* Returns the quick edit data for terms.
|
310 |
*
|
311 |
* @since 4.0.0
|
|
|
312 |
* @access private
|
313 |
* @abstract
|
314 |
* @NOTE Unlike `_output_column_post_data()`, this is a filter callback.
|
@@ -325,7 +319,7 @@ final class ListEdit extends ListTable {
|
|
325 |
if ( $this->column_name !== $column_name ) return $string;
|
326 |
if ( ! \current_user_can( 'edit_term', $term_id ) ) return $string;
|
327 |
|
328 |
-
$tsf = \
|
329 |
|
330 |
$query = [
|
331 |
'id' => $term_id,
|
@@ -334,7 +328,7 @@ final class ListEdit extends ListTable {
|
|
334 |
|
335 |
$r_defaults = $tsf->generate_robots_meta(
|
336 |
$query,
|
337 |
-
|
338 |
\The_SEO_Framework\ROBOTS_IGNORE_SETTINGS
|
339 |
);
|
340 |
|
@@ -397,15 +391,19 @@ final class ListEdit extends ListTable {
|
|
397 |
HTML::make_data_attributes( [ 'le' => $data ] )
|
398 |
);
|
399 |
|
400 |
-
$term_prefix = $tsf->use_generated_archive_prefix( \
|
401 |
-
?
|
|
|
|
|
|
|
|
|
402 |
: '';
|
403 |
|
404 |
$title_data = [
|
405 |
'refTitleLocked' => false,
|
406 |
-
'defaultTitle' => $tsf->get_filtered_raw_generated_title( $query ),
|
407 |
'addAdditions' => $tsf->use_title_branding( $query ),
|
408 |
-
'additionValue' => $tsf->
|
409 |
'additionPlacement' => 'left' === $tsf->get_title_seplocation() ? 'before' : 'after',
|
410 |
'termPrefix' => $term_prefix,
|
411 |
];
|
@@ -430,6 +428,6 @@ final class ListEdit extends ListTable {
|
|
430 |
if ( $this->doing_ajax )
|
431 |
$container .= $this->get_ajax_dispatch_updated_event();
|
432 |
|
433 |
-
return $string
|
434 |
}
|
435 |
}
|
65 |
*/
|
66 |
public function _prepare_edit_box( $screen ) {
|
67 |
|
68 |
+
if ( empty( $screen->taxonomy ) ) {
|
|
|
|
|
69 |
// WordPress doesn't support this feature yet for taxonomies.
|
70 |
// Exclude it for when the time may come and faulty fields are displayed.
|
71 |
// Mind the "2".
|
123 |
if ( $taxonomy ) {
|
124 |
// Not yet.
|
125 |
} else {
|
126 |
+
\tsf()->get_view( 'list/bulk-post', get_defined_vars() );
|
127 |
}
|
128 |
}
|
129 |
|
142 |
if ( $this->column_name !== $column_name ) return;
|
143 |
|
144 |
if ( $taxonomy ) {
|
145 |
+
\tsf()->get_view( 'list/quick-term', get_defined_vars() );
|
146 |
} else {
|
147 |
+
\tsf()->get_view( 'list/quick-post', get_defined_vars() );
|
148 |
}
|
149 |
}
|
150 |
|
163 |
if ( $this->column_name !== $column_name ) return;
|
164 |
if ( ! \current_user_can( 'edit_post', $post_id ) ) return;
|
165 |
|
166 |
+
$tsf = \tsf();
|
167 |
|
168 |
+
$query = [ 'id' => $post_id ];
|
|
|
|
|
|
|
169 |
|
170 |
$r_defaults = $tsf->generate_robots_meta(
|
171 |
$query,
|
172 |
+
[ 'noindex', 'nofollow', 'noarchive' ],
|
173 |
\The_SEO_Framework\ROBOTS_IGNORE_SETTINGS
|
174 |
);
|
175 |
|
219 |
* @param string $default Optional. Only works when $isSelect is true. The default value to be set in select index 0.
|
220 |
* }
|
221 |
* }
|
222 |
+
* @param array $query The query data. Contains 'id' or 'taxonomy'.
|
223 |
*/
|
224 |
$data = \apply_filters_ref_array( 'the_seo_framework_list_table_data', [ $data, $query ] );
|
225 |
|
232 |
);
|
233 |
|
234 |
if ( $tsf->is_static_frontpage( $query['id'] ) ) {
|
|
|
235 |
// When the homepage title is set, we can safely get the custom field.
|
236 |
$_has_home_title = (bool) $tsf->escape_title( $tsf->get_option( 'homepage_title' ) );
|
237 |
$default_title = $_has_home_title
|
247 |
? $tsf->get_description_from_custom_field( $query )
|
248 |
: $tsf->get_generated_description( $query );
|
249 |
$is_desc_ref_locked = $_has_home_desc;
|
|
|
250 |
} else {
|
251 |
$default_title = $tsf->get_filtered_raw_generated_title( $query );
|
252 |
$addition = $tsf->get_blogname();
|
262 |
];
|
263 |
$title_data = [
|
264 |
'refTitleLocked' => $is_title_ref_locked,
|
265 |
+
'defaultTitle' => $tsf->s_title( $default_title ),
|
266 |
'addAdditions' => $tsf->use_title_branding( $query ),
|
267 |
+
'additionValue' => $tsf->s_title( $addition ),
|
268 |
'additionPlacement' => 'left' === $seplocation ? 'before' : 'after',
|
269 |
];
|
270 |
$desc_data = [
|
302 |
* Returns the quick edit data for terms.
|
303 |
*
|
304 |
* @since 4.0.0
|
305 |
+
* @since 4.2.0 Now properly populates use_generated_archive_prefix() with a \WP_Term object.
|
306 |
* @access private
|
307 |
* @abstract
|
308 |
* @NOTE Unlike `_output_column_post_data()`, this is a filter callback.
|
319 |
if ( $this->column_name !== $column_name ) return $string;
|
320 |
if ( ! \current_user_can( 'edit_term', $term_id ) ) return $string;
|
321 |
|
322 |
+
$tsf = \tsf();
|
323 |
|
324 |
$query = [
|
325 |
'id' => $term_id,
|
328 |
|
329 |
$r_defaults = $tsf->generate_robots_meta(
|
330 |
$query,
|
331 |
+
[ 'noindex', 'nofollow', 'noarchive' ],
|
332 |
\The_SEO_Framework\ROBOTS_IGNORE_SETTINGS
|
333 |
);
|
334 |
|
391 |
HTML::make_data_attributes( [ 'le' => $data ] )
|
392 |
);
|
393 |
|
394 |
+
$term_prefix = $tsf->use_generated_archive_prefix( \get_term( $query['id'], $query['taxonomy'] ) )
|
395 |
+
? sprintf(
|
396 |
+
/* translators: %s: Taxonomy singular name. */
|
397 |
+
\_x( '%s:', 'taxonomy term archive title prefix', 'default' ),
|
398 |
+
$tsf->get_tax_type_label( $query['taxonomy'] )
|
399 |
+
)
|
400 |
: '';
|
401 |
|
402 |
$title_data = [
|
403 |
'refTitleLocked' => false,
|
404 |
+
'defaultTitle' => $tsf->s_title( $tsf->get_filtered_raw_generated_title( $query ) ),
|
405 |
'addAdditions' => $tsf->use_title_branding( $query ),
|
406 |
+
'additionValue' => $tsf->s_title( $tsf->get_blogname() ),
|
407 |
'additionPlacement' => 'left' === $tsf->get_title_seplocation() ? 'before' : 'after',
|
408 |
'termPrefix' => $term_prefix,
|
409 |
];
|
428 |
if ( $this->doing_ajax )
|
429 |
$container .= $this->get_ajax_dispatch_updated_event();
|
430 |
|
431 |
+
return "$string$container";
|
432 |
}
|
433 |
}
|
@@ -125,7 +125,7 @@ abstract class ListTable {
|
|
125 |
$pto = $post_type ? \get_post_type_object( $post_type ) : false;
|
126 |
|
127 |
// TODO shouldn't we just use `edit_post`? See _output_column_contents_for_post && get_post_type_capabilities
|
128 |
-
if ( $pto && \current_user_can(
|
129 |
$this->init_columns_ajax();
|
130 |
}
|
131 |
|
@@ -142,9 +142,7 @@ abstract class ListTable {
|
|
142 |
|| empty( $_POST['tax_ID'] ) )
|
143 |
return;
|
144 |
|
145 |
-
|
146 |
-
|
147 |
-
if ( \current_user_can( 'edit_term', $tax_id ) )
|
148 |
$this->init_columns_ajax();
|
149 |
}
|
150 |
|
@@ -157,18 +155,18 @@ abstract class ListTable {
|
|
157 |
*/
|
158 |
private function init_columns( $screen ) {
|
159 |
|
160 |
-
if ( ! \
|
161 |
|| empty( $screen->id ) )
|
162 |
return;
|
163 |
|
164 |
-
$post_type =
|
165 |
-
$taxonomy =
|
166 |
|
167 |
if ( $taxonomy ) {
|
168 |
-
if ( ! \
|
169 |
return;
|
170 |
} else {
|
171 |
-
if ( ! \
|
172 |
return;
|
173 |
}
|
174 |
|
@@ -176,9 +174,9 @@ abstract class ListTable {
|
|
176 |
$this->taxonomy = $taxonomy;
|
177 |
|
178 |
if ( $taxonomy )
|
179 |
-
\add_filter(
|
180 |
|
181 |
-
\add_filter(
|
182 |
/**
|
183 |
* Always load pages and posts.
|
184 |
* Many CPT plugins rely on these.
|
@@ -207,10 +205,10 @@ abstract class ListTable {
|
|
207 |
?: ( isset( $_POST['tax_type'] ) ? stripslashes( $_POST['tax_type'] ) : '' );
|
208 |
|
209 |
if ( $taxonomy ) {
|
210 |
-
if ( ! \
|
211 |
return;
|
212 |
} else {
|
213 |
-
if ( ! \
|
214 |
return;
|
215 |
}
|
216 |
|
@@ -222,11 +220,11 @@ abstract class ListTable {
|
|
222 |
|
223 |
// Not elseif; either request.
|
224 |
if ( $taxonomy )
|
225 |
-
\add_filter(
|
226 |
|
227 |
if ( $screen_id ) {
|
228 |
// Everything but inline-save-tax action.
|
229 |
-
\add_filter(
|
230 |
|
231 |
/**
|
232 |
* Always load pages and posts.
|
@@ -239,9 +237,9 @@ abstract class ListTable {
|
|
239 |
* Action "inline-save-tax" does not POST 'screen'.
|
240 |
*
|
241 |
* @see WP Core wp_ajax_inline_save_tax():
|
242 |
-
* `_get_list_table( 'WP_Terms_List_Table', array( 'screen' =>
|
243 |
*/
|
244 |
-
\add_filter(
|
245 |
}
|
246 |
// phpcs:enable, WordPress.Security.NonceVerification
|
247 |
}
|
125 |
$pto = $post_type ? \get_post_type_object( $post_type ) : false;
|
126 |
|
127 |
// TODO shouldn't we just use `edit_post`? See _output_column_contents_for_post && get_post_type_capabilities
|
128 |
+
if ( $pto && \current_user_can( "edit_{$pto->capability_type}", (int) $_POST['post_ID'] ) )
|
129 |
$this->init_columns_ajax();
|
130 |
}
|
131 |
|
142 |
|| empty( $_POST['tax_ID'] ) )
|
143 |
return;
|
144 |
|
145 |
+
if ( \current_user_can( 'edit_term', (int) $_POST['tax_ID'] ) )
|
|
|
|
|
146 |
$this->init_columns_ajax();
|
147 |
}
|
148 |
|
155 |
*/
|
156 |
private function init_columns( $screen ) {
|
157 |
|
158 |
+
if ( ! \tsf()->is_wp_lists_edit()
|
159 |
|| empty( $screen->id ) )
|
160 |
return;
|
161 |
|
162 |
+
$post_type = $screen->post_type ?? '';
|
163 |
+
$taxonomy = $screen->taxonomy ?? '';
|
164 |
|
165 |
if ( $taxonomy ) {
|
166 |
+
if ( ! \tsf()->is_taxonomy_supported( $taxonomy ) )
|
167 |
return;
|
168 |
} else {
|
169 |
+
if ( ! \tsf()->is_post_type_supported( $post_type ) )
|
170 |
return;
|
171 |
}
|
172 |
|
174 |
$this->taxonomy = $taxonomy;
|
175 |
|
176 |
if ( $taxonomy )
|
177 |
+
\add_filter( "manage_{$taxonomy}_custom_column", [ $this, '_output_column_contents_for_term' ], 1, 3 );
|
178 |
|
179 |
+
\add_filter( "manage_{$screen->id}_columns", [ $this, '_add_column' ], 10, 1 );
|
180 |
/**
|
181 |
* Always load pages and posts.
|
182 |
* Many CPT plugins rely on these.
|
205 |
?: ( isset( $_POST['tax_type'] ) ? stripslashes( $_POST['tax_type'] ) : '' );
|
206 |
|
207 |
if ( $taxonomy ) {
|
208 |
+
if ( ! \tsf()->is_taxonomy_supported( $taxonomy ) )
|
209 |
return;
|
210 |
} else {
|
211 |
+
if ( ! \tsf()->is_post_type_supported( $post_type ) )
|
212 |
return;
|
213 |
}
|
214 |
|
220 |
|
221 |
// Not elseif; either request.
|
222 |
if ( $taxonomy )
|
223 |
+
\add_filter( "manage_{$taxonomy}_custom_column", [ $this, '_output_column_contents_for_term' ], 1, 3 );
|
224 |
|
225 |
if ( $screen_id ) {
|
226 |
// Everything but inline-save-tax action.
|
227 |
+
\add_filter( "manage_{$screen_id}_columns", [ $this, '_add_column' ], 10, 1 );
|
228 |
|
229 |
/**
|
230 |
* Always load pages and posts.
|
237 |
* Action "inline-save-tax" does not POST 'screen'.
|
238 |
*
|
239 |
* @see WP Core wp_ajax_inline_save_tax():
|
240 |
+
* `_get_list_table( 'WP_Terms_List_Table', array( 'screen' => "edit-$taxonomy" ) );`
|
241 |
*/
|
242 |
+
\add_filter( "manage_edit-{$taxonomy}_columns", [ $this, '_add_column' ], 1, 1 );
|
243 |
}
|
244 |
// phpcs:enable, WordPress.Security.NonceVerification
|
245 |
}
|
@@ -25,6 +25,8 @@ namespace The_SEO_Framework\Bridges;
|
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
|
|
|
|
28 |
/**
|
29 |
* Pings search engines.
|
30 |
*
|
@@ -110,7 +112,7 @@ final class Ping {
|
|
110 |
*/
|
111 |
public static function ping_search_engines() {
|
112 |
|
113 |
-
$tsf = \
|
114 |
|
115 |
if ( $tsf->get_option( 'site_noindex' ) || ! $tsf->is_blog_public() ) return;
|
116 |
|
@@ -164,16 +166,14 @@ final class Ping {
|
|
164 |
*/
|
165 |
public static function ping_google() {
|
166 |
|
167 |
-
|
168 |
-
$url = \get_sitemap_url( 'index' );
|
169 |
-
} else {
|
170 |
-
$url = \The_SEO_Framework\Bridges\Sitemap::get_instance()->get_expected_sitemap_endpoint_url();
|
171 |
-
}
|
172 |
|
173 |
if ( ! $url ) return;
|
174 |
|
175 |
-
|
176 |
-
|
|
|
|
|
177 |
}
|
178 |
|
179 |
/**
|
@@ -188,15 +188,32 @@ final class Ping {
|
|
188 |
*/
|
189 |
public static function ping_bing() {
|
190 |
|
191 |
-
|
192 |
-
$url = \get_sitemap_url( 'index' );
|
193 |
-
} else {
|
194 |
-
$url = \The_SEO_Framework\Bridges\Sitemap::get_instance()->get_expected_sitemap_endpoint_url();
|
195 |
-
}
|
196 |
|
197 |
if ( ! $url ) return;
|
198 |
|
199 |
-
|
200 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
}
|
202 |
}
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
+
use function \The_SEO_Framework\memo;
|
29 |
+
|
30 |
/**
|
31 |
* Pings search engines.
|
32 |
*
|
112 |
*/
|
113 |
public static function ping_search_engines() {
|
114 |
|
115 |
+
$tsf = \tsf();
|
116 |
|
117 |
if ( $tsf->get_option( 'site_noindex' ) || ! $tsf->is_blog_public() ) return;
|
118 |
|
166 |
*/
|
167 |
public static function ping_google() {
|
168 |
|
169 |
+
$url = static::get_ping_url();
|
|
|
|
|
|
|
|
|
170 |
|
171 |
if ( ! $url ) return;
|
172 |
|
173 |
+
\wp_safe_remote_get(
|
174 |
+
'https://www.google.com/ping?sitemap=' . rawurlencode( $url ),
|
175 |
+
[ 'timeout' => 3 ]
|
176 |
+
);
|
177 |
}
|
178 |
|
179 |
/**
|
188 |
*/
|
189 |
public static function ping_bing() {
|
190 |
|
191 |
+
$url = static::get_ping_url();
|
|
|
|
|
|
|
|
|
192 |
|
193 |
if ( ! $url ) return;
|
194 |
|
195 |
+
\wp_safe_remote_get(
|
196 |
+
'https://www.bing.com/ping?sitemap=' . rawurlencode( $url ),
|
197 |
+
[ 'timeout' => 3 ]
|
198 |
+
);
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Return the base sitemap's ping URL.
|
203 |
+
* Memoizes the return value.
|
204 |
+
*
|
205 |
+
* @since 4.2.0
|
206 |
+
*
|
207 |
+
* @return string The ping URL. Empty string on failure.
|
208 |
+
*/
|
209 |
+
public static function get_ping_url() {
|
210 |
+
return memo() ?? memo(
|
211 |
+
(
|
212 |
+
\tsf()->use_core_sitemaps()
|
213 |
+
? \get_sitemap_url( 'index' )
|
214 |
+
: \The_SEO_Framework\Bridges\Sitemap::get_instance()->get_expected_sitemap_endpoint_url()
|
215 |
+
)
|
216 |
+
?: ''
|
217 |
+
);
|
218 |
}
|
219 |
}
|
@@ -48,12 +48,12 @@ final class PluginTable {
|
|
48 |
|
49 |
$tsf_links = [];
|
50 |
|
51 |
-
$tsf = \
|
52 |
|
53 |
-
if ( $tsf->
|
54 |
$tsf_links['settings'] = sprintf(
|
55 |
'<a href="%s">%s</a>',
|
56 |
-
\esc_url( \admin_url(
|
57 |
\esc_html__( 'Settings', 'autodescription' )
|
58 |
);
|
59 |
}
|
@@ -121,7 +121,9 @@ final class PluginTable {
|
|
121 |
'<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
|
122 |
[
|
123 |
'https://tsf.fyi/extension-manager',
|
124 |
-
$_get_em
|
|
|
|
|
125 |
]
|
126 |
),
|
127 |
]
|
48 |
|
49 |
$tsf_links = [];
|
50 |
|
51 |
+
$tsf = \tsf();
|
52 |
|
53 |
+
if ( ! $tsf->is_headless['settings'] ) {
|
54 |
$tsf_links['settings'] = sprintf(
|
55 |
'<a href="%s">%s</a>',
|
56 |
+
\esc_url( \admin_url( "admin.php?page={$tsf->seo_settings_page_slug}" ) ),
|
57 |
\esc_html__( 'Settings', 'autodescription' )
|
58 |
);
|
59 |
}
|
121 |
'<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
|
122 |
[
|
123 |
'https://tsf.fyi/extension-manager',
|
124 |
+
$_get_em
|
125 |
+
? \esc_html_x( 'Get Extension Manager', 'Extension Manager is a product name; do not translate it.', 'autodescription' )
|
126 |
+
: 'Extension Manager',
|
127 |
]
|
128 |
),
|
129 |
]
|
@@ -48,7 +48,7 @@ final class PostSettings {
|
|
48 |
*/
|
49 |
public static function _prepare_meta_box( $post_type ) {
|
50 |
|
51 |
-
$tsf = \
|
52 |
|
53 |
$label = $tsf->get_post_type_label( $post_type );
|
54 |
|
@@ -65,7 +65,7 @@ final class PostSettings {
|
|
65 |
*/
|
66 |
$priority = (string) \apply_filters( 'the_seo_framework_metabox_priority', 'high' );
|
67 |
|
68 |
-
if ( $tsf->
|
69 |
if ( $tsf->can_access_settings() ) {
|
70 |
$schema = \is_rtl() ? '%2$s - %1$s' : '%1$s - %2$s';
|
71 |
$title = sprintf(
|
@@ -73,7 +73,7 @@ final class PostSettings {
|
|
73 |
\esc_html__( 'Homepage SEO Settings', 'autodescription' ),
|
74 |
\The_SEO_Framework\Interpreters\HTML::make_info(
|
75 |
\__( 'The SEO Settings may take precedence over these settings.', 'autodescription' ),
|
76 |
-
$tsf->
|
77 |
false
|
78 |
)
|
79 |
);
|
@@ -89,8 +89,10 @@ final class PostSettings {
|
|
89 |
// Implies `\get_current_screen()->id`. Is always 'post'.
|
90 |
$screen_id = 'post';
|
91 |
|
92 |
-
|
93 |
-
|
|
|
|
|
94 |
}
|
95 |
|
96 |
/**
|
@@ -112,8 +114,8 @@ final class PostSettings {
|
|
112 |
* @param bool $use_tabs Whether to output tabs, only works when $tabs count is greater than 1.
|
113 |
*/
|
114 |
public static function _flex_nav_tab_wrapper( $id, $tabs = [], $use_tabs = true ) { // phpcs:ignore,VariableAnalysis
|
115 |
-
\
|
116 |
-
\
|
117 |
}
|
118 |
|
119 |
/**
|
@@ -125,7 +127,7 @@ final class PostSettings {
|
|
125 |
|
126 |
static::output_nonce_field();
|
127 |
|
128 |
-
$tsf = \
|
129 |
|
130 |
/**
|
131 |
* @since 2.9.0
|
@@ -153,9 +155,8 @@ final class PostSettings {
|
|
153 |
*/
|
154 |
public static function _add_postbox_class( $classes = [] ) {
|
155 |
|
156 |
-
if ( \
|
157 |
$classes[] = 'tsf-is-block-editor';
|
158 |
-
}
|
159 |
|
160 |
return $classes;
|
161 |
}
|
@@ -167,7 +168,7 @@ final class PostSettings {
|
|
167 |
* @since 4.0.0
|
168 |
*/
|
169 |
private static function output_nonce_field() {
|
170 |
-
$tsf = \
|
171 |
\wp_nonce_field( $tsf->inpost_nonce_field, $tsf->inpost_nonce_name );
|
172 |
}
|
173 |
|
@@ -181,7 +182,7 @@ final class PostSettings {
|
|
181 |
* @since 2.9.0
|
182 |
*/
|
183 |
\do_action( 'the_seo_framework_pre_page_inpost_general_tab' );
|
184 |
-
\
|
185 |
/**
|
186 |
* @since 2.9.0
|
187 |
*/
|
@@ -198,7 +199,7 @@ final class PostSettings {
|
|
198 |
* @since 2.9.0
|
199 |
*/
|
200 |
\do_action( 'the_seo_framework_pre_page_inpost_visibility_tab' );
|
201 |
-
\
|
202 |
/**
|
203 |
* @since 2.9.0
|
204 |
*/
|
@@ -215,7 +216,7 @@ final class PostSettings {
|
|
215 |
* @since 2.9.0
|
216 |
*/
|
217 |
\do_action( 'the_seo_framework_pre_page_inpost_social_tab' );
|
218 |
-
\
|
219 |
/**
|
220 |
* @since 2.9.0
|
221 |
*/
|
48 |
*/
|
49 |
public static function _prepare_meta_box( $post_type ) {
|
50 |
|
51 |
+
$tsf = \tsf();
|
52 |
|
53 |
$label = $tsf->get_post_type_label( $post_type );
|
54 |
|
65 |
*/
|
66 |
$priority = (string) \apply_filters( 'the_seo_framework_metabox_priority', 'high' );
|
67 |
|
68 |
+
if ( $tsf->is_real_front_page_by_id( $tsf->get_the_real_ID() ) ) {
|
69 |
if ( $tsf->can_access_settings() ) {
|
70 |
$schema = \is_rtl() ? '%2$s - %1$s' : '%1$s - %2$s';
|
71 |
$title = sprintf(
|
73 |
\esc_html__( 'Homepage SEO Settings', 'autodescription' ),
|
74 |
\The_SEO_Framework\Interpreters\HTML::make_info(
|
75 |
\__( 'The SEO Settings may take precedence over these settings.', 'autodescription' ),
|
76 |
+
$tsf->get_seo_settings_page_url(),
|
77 |
false
|
78 |
)
|
79 |
);
|
89 |
// Implies `\get_current_screen()->id`. Is always 'post'.
|
90 |
$screen_id = 'post';
|
91 |
|
92 |
+
$class = static::class;
|
93 |
+
|
94 |
+
\add_meta_box( $box_id, $title, "$class::_meta_box", $post_type, $context, $priority, [] );
|
95 |
+
\add_filter( "postbox_classes_{$screen_id}_{$box_id}", "$class::_add_postbox_class" );
|
96 |
}
|
97 |
|
98 |
/**
|
114 |
* @param bool $use_tabs Whether to output tabs, only works when $tabs count is greater than 1.
|
115 |
*/
|
116 |
public static function _flex_nav_tab_wrapper( $id, $tabs = [], $use_tabs = true ) { // phpcs:ignore,VariableAnalysis
|
117 |
+
\tsf()->get_view( 'edit/wrap-nav', get_defined_vars() );
|
118 |
+
\tsf()->get_view( 'edit/wrap-content', get_defined_vars() );
|
119 |
}
|
120 |
|
121 |
/**
|
127 |
|
128 |
static::output_nonce_field();
|
129 |
|
130 |
+
$tsf = \tsf();
|
131 |
|
132 |
/**
|
133 |
* @since 2.9.0
|
155 |
*/
|
156 |
public static function _add_postbox_class( $classes = [] ) {
|
157 |
|
158 |
+
if ( \tsf()->is_gutenberg_page() )
|
159 |
$classes[] = 'tsf-is-block-editor';
|
|
|
160 |
|
161 |
return $classes;
|
162 |
}
|
168 |
* @since 4.0.0
|
169 |
*/
|
170 |
private static function output_nonce_field() {
|
171 |
+
$tsf = \tsf();
|
172 |
\wp_nonce_field( $tsf->inpost_nonce_field, $tsf->inpost_nonce_name );
|
173 |
}
|
174 |
|
182 |
* @since 2.9.0
|
183 |
*/
|
184 |
\do_action( 'the_seo_framework_pre_page_inpost_general_tab' );
|
185 |
+
\tsf()->get_view( 'edit/seo-settings-singular', [], 'general_tab' );
|
186 |
/**
|
187 |
* @since 2.9.0
|
188 |
*/
|
199 |
* @since 2.9.0
|
200 |
*/
|
201 |
\do_action( 'the_seo_framework_pre_page_inpost_visibility_tab' );
|
202 |
+
\tsf()->get_view( 'edit/seo-settings-singular', [], 'visibility_tab' );
|
203 |
/**
|
204 |
* @since 2.9.0
|
205 |
*/
|
216 |
* @since 2.9.0
|
217 |
*/
|
218 |
\do_action( 'the_seo_framework_pre_page_inpost_social_tab' );
|
219 |
+
\tsf()->get_view( 'edit/seo-settings-singular', [], 'social_tab' );
|
220 |
/**
|
221 |
* @since 2.9.0
|
222 |
*/
|
@@ -25,18 +25,6 @@ namespace The_SEO_Framework\Bridges;
|
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
-
/**
|
29 |
-
* Sets up class loader as file is loaded.
|
30 |
-
* This is done asynchronously, because static calls are handled prior and after.
|
31 |
-
*
|
32 |
-
* @see EOF. Because of the autoloader and (future) trait calling, we can't do it before the class is read.
|
33 |
-
* @link https://bugs.php.net/bug.php?id=75771
|
34 |
-
*/
|
35 |
-
$_load_scripts_class = function() {
|
36 |
-
// phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
|
37 |
-
new Scripts();
|
38 |
-
};
|
39 |
-
|
40 |
/**
|
41 |
* Prepares admin GUI scripts. Auto-invokes everything the moment this file is required.
|
42 |
* Relies on \The_SEO_Framework\Builders\Scripts to register and load scripts.
|
@@ -48,17 +36,10 @@ $_load_scripts_class = function() {
|
|
48 |
* @since 4.0.0
|
49 |
* @see \The_SEO_Framework\Builders\Scripts
|
50 |
* @access protected
|
51 |
-
* Use static calls The_SEO_Framework\Bridges\Scripts::funcname()
|
52 |
* @final Can't be extended.
|
53 |
*/
|
54 |
final class Scripts {
|
55 |
|
56 |
-
/**
|
57 |
-
* @since 4.0.0
|
58 |
-
* @var \The_SEO_Framework\Bridges\Scripts $instance The instance.
|
59 |
-
*/
|
60 |
-
private static $instance;
|
61 |
-
|
62 |
/**
|
63 |
* Prepares the class and loads constructor.
|
64 |
*
|
@@ -66,12 +47,14 @@ final class Scripts {
|
|
66 |
* this class is needed yet.
|
67 |
*
|
68 |
* @since 4.0.0
|
|
|
|
|
69 |
*/
|
70 |
public static function prepare() {}
|
71 |
|
72 |
/**
|
73 |
-
* The constructor. Can't be instantiated
|
74 |
-
* Kills PHP
|
75 |
*
|
76 |
* This probably autoloads at action "admin_enqueue_scripts", priority "0".
|
77 |
*
|
@@ -79,13 +62,7 @@ final class Scripts {
|
|
79 |
* @access private
|
80 |
* @internal
|
81 |
*/
|
82 |
-
|
83 |
-
|
84 |
-
static $count = 0;
|
85 |
-
0 === $count++ or \wp_die( 'Don\'t instance <code>' . __CLASS__ . '</code>.' );
|
86 |
-
|
87 |
-
static::$instance = &$this;
|
88 |
-
}
|
89 |
|
90 |
/**
|
91 |
* Initializes scripts based on admin query.
|
@@ -96,7 +73,7 @@ final class Scripts {
|
|
96 |
*/
|
97 |
public static function _init() {
|
98 |
|
99 |
-
$tsf = \
|
100 |
|
101 |
$_scripts = [
|
102 |
static::get_tsf_scripts(),
|
@@ -201,9 +178,8 @@ final class Scripts {
|
|
201 |
if ( is_scalar( $values ) )
|
202 |
return static::decode_entities( $values );
|
203 |
|
204 |
-
foreach ( $values as &$v )
|
205 |
$v = static::decode_entities( $v );
|
206 |
-
}
|
207 |
|
208 |
return $values;
|
209 |
}
|
@@ -215,12 +191,11 @@ final class Scripts {
|
|
215 |
*/
|
216 |
public static function prepare_media_scripts() {
|
217 |
|
218 |
-
$tsf = \
|
219 |
$args = [];
|
220 |
|
221 |
-
if ( $tsf->is_post_edit() )
|
222 |
$args['post'] = $tsf->get_the_real_admin_ID();
|
223 |
-
}
|
224 |
|
225 |
\wp_enqueue_media( $args );
|
226 |
}
|
@@ -248,7 +223,7 @@ final class Scripts {
|
|
248 |
[
|
249 |
'id' => 'tsf',
|
250 |
'type' => 'css',
|
251 |
-
'deps' => [
|
252 |
'autoload' => true,
|
253 |
'hasrtl' => false,
|
254 |
'name' => 'tsf',
|
@@ -258,7 +233,7 @@ final class Scripts {
|
|
258 |
[
|
259 |
'id' => 'tsf',
|
260 |
'type' => 'js',
|
261 |
-
'deps' => [ 'jquery', '
|
262 |
'autoload' => true,
|
263 |
'name' => 'tsf',
|
264 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
@@ -277,8 +252,7 @@ final class Scripts {
|
|
277 |
'edit_posts' => \current_user_can( 'edit_posts' ) ? \wp_create_nonce( 'tsf-ajax-edit_posts' ) : false,
|
278 |
],
|
279 |
'states' => [
|
280 |
-
'
|
281 |
-
'debug' => \the_seo_framework()->script_debug,
|
282 |
],
|
283 |
],
|
284 |
],
|
@@ -323,7 +297,7 @@ final class Scripts {
|
|
323 |
[
|
324 |
'id' => 'tsf-tt',
|
325 |
'type' => 'js',
|
326 |
-
'deps' => [ '
|
327 |
'autoload' => true,
|
328 |
'name' => 'tt',
|
329 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
@@ -344,7 +318,7 @@ final class Scripts {
|
|
344 |
[
|
345 |
'id' => 'tsf-ays',
|
346 |
'type' => 'js',
|
347 |
-
'deps' => [ '
|
348 |
'autoload' => true,
|
349 |
'name' => 'ays',
|
350 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
@@ -366,6 +340,7 @@ final class Scripts {
|
|
366 |
*
|
367 |
* @since 4.0.0
|
368 |
* @since 4.1.0 Now depends on title and description scripts.
|
|
|
369 |
*
|
370 |
* @return array The script params.
|
371 |
*/
|
@@ -384,15 +359,11 @@ final class Scripts {
|
|
384 |
[
|
385 |
'id' => 'tsf-le',
|
386 |
'type' => 'js',
|
387 |
-
'deps' => [ '
|
388 |
'autoload' => true,
|
389 |
'name' => 'le',
|
390 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
391 |
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
392 |
-
'l10n' => [
|
393 |
-
'name' => 'tsfLeL10n',
|
394 |
-
'data' => [],
|
395 |
-
],
|
396 |
],
|
397 |
];
|
398 |
}
|
@@ -407,15 +378,25 @@ final class Scripts {
|
|
407 |
*/
|
408 |
public static function get_seo_settings_scripts() {
|
409 |
|
410 |
-
$tsf = \
|
411 |
|
412 |
$front_id = $tsf->get_the_front_page_ID();
|
413 |
|
414 |
return [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
415 |
[
|
416 |
'id' => 'tsf-settings',
|
417 |
'type' => 'js',
|
418 |
-
'deps' => [ 'jquery', 'tsf-ays', 'tsf-title', 'tsf-description', 'tsf', 'tsf-tabs', 'tsf-tt', 'wp-color-picker', 'wp-util' ],
|
419 |
'autoload' => true,
|
420 |
'name' => 'settings',
|
421 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
@@ -433,16 +414,6 @@ final class Scripts {
|
|
433 |
'file' => $tsf->get_view_location( 'templates/settings/settings' ),
|
434 |
],
|
435 |
],
|
436 |
-
[
|
437 |
-
'id' => 'tsf-settings',
|
438 |
-
'type' => 'css',
|
439 |
-
'deps' => [ 'tsf', 'tsf-tt', 'wp-color-picker' ],
|
440 |
-
'autoload' => true,
|
441 |
-
'hasrtl' => false,
|
442 |
-
'name' => 'settings',
|
443 |
-
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/css/',
|
444 |
-
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
445 |
-
],
|
446 |
];
|
447 |
}
|
448 |
|
@@ -456,7 +427,7 @@ final class Scripts {
|
|
456 |
*/
|
457 |
public static function get_post_edit_scripts() {
|
458 |
|
459 |
-
$tsf = \
|
460 |
$id = $tsf->get_the_real_ID();
|
461 |
|
462 |
$is_static_frontpage = $tsf->is_static_frontpage( $id );
|
@@ -470,6 +441,24 @@ final class Scripts {
|
|
470 |
}
|
471 |
|
472 |
return [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
473 |
[
|
474 |
'id' => 'tsf-post',
|
475 |
'type' => 'js',
|
@@ -495,24 +484,6 @@ final class Scripts {
|
|
495 |
],
|
496 |
],
|
497 |
],
|
498 |
-
[
|
499 |
-
'id' => 'tsf-post',
|
500 |
-
'type' => 'css',
|
501 |
-
'deps' => [ 'tsf-tt', 'tsf' ],
|
502 |
-
'autoload' => true,
|
503 |
-
'hasrtl' => false,
|
504 |
-
'name' => 'post',
|
505 |
-
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/css/',
|
506 |
-
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
507 |
-
'inline' => [
|
508 |
-
'.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked + .tsf-flex-nav-tab-label' => [
|
509 |
-
'box-shadow:0 -2px 0 0 {{$color_accent}} inset, 0 0 0 0 {{$color_accent}} inset',
|
510 |
-
],
|
511 |
-
'.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:focus + .tsf-flex-nav-tab-label:not(.tsf-no-focus-ring)' => [
|
512 |
-
'box-shadow:0 -2px 0 0 {{$color_accent}} inset, 0 0 0 1px {{$color_accent}} inset',
|
513 |
-
],
|
514 |
-
],
|
515 |
-
],
|
516 |
];
|
517 |
}
|
518 |
|
@@ -521,25 +492,41 @@ final class Scripts {
|
|
521 |
*
|
522 |
* @since 4.0.0
|
523 |
* @since 4.1.0 Updated l10n.data.
|
|
|
524 |
*
|
525 |
* @return array The script params.
|
526 |
*/
|
527 |
public static function get_term_edit_scripts() {
|
528 |
|
529 |
-
$tsf = \
|
530 |
$taxonomy = $tsf->get_current_taxonomy();
|
531 |
|
532 |
$additions_forced_disabled = (bool) $tsf->get_option( 'title_rem_additions' );
|
533 |
|
534 |
-
$term_prefix = $tsf->use_generated_archive_prefix( \
|
535 |
-
|
|
|
|
|
|
|
|
|
|
|
536 |
: '';
|
537 |
|
538 |
return [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
539 |
[
|
540 |
'id' => 'tsf-term',
|
541 |
'type' => 'js',
|
542 |
-
'deps' => [ '
|
543 |
'autoload' => true,
|
544 |
'name' => 'term',
|
545 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
@@ -554,16 +541,6 @@ final class Scripts {
|
|
554 |
],
|
555 |
],
|
556 |
],
|
557 |
-
[
|
558 |
-
'id' => 'tsf-term',
|
559 |
-
'type' => 'css',
|
560 |
-
'deps' => [ 'tsf-tt', 'tsf' ],
|
561 |
-
'autoload' => true,
|
562 |
-
'hasrtl' => false,
|
563 |
-
'name' => 'term',
|
564 |
-
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/css/',
|
565 |
-
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
566 |
-
],
|
567 |
];
|
568 |
}
|
569 |
|
@@ -571,6 +548,7 @@ final class Scripts {
|
|
571 |
* Returns Gutenberg compatibility scripts params.
|
572 |
*
|
573 |
* @since 4.0.0
|
|
|
574 |
*
|
575 |
* @return array The script params.
|
576 |
*/
|
@@ -579,15 +557,11 @@ final class Scripts {
|
|
579 |
[
|
580 |
'id' => 'tsf-gbc',
|
581 |
'type' => 'js',
|
582 |
-
'deps' => [ 'jquery', 'tsf', '
|
583 |
'autoload' => true,
|
584 |
'name' => 'gbc',
|
585 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
586 |
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
587 |
-
'l10n' => [
|
588 |
-
'name' => 'tsfGBCL10n',
|
589 |
-
'data' => [],
|
590 |
-
],
|
591 |
],
|
592 |
];
|
593 |
}
|
@@ -596,6 +570,7 @@ final class Scripts {
|
|
596 |
* Returns Tabs scripts params.
|
597 |
*
|
598 |
* @since 4.1.3
|
|
|
599 |
*
|
600 |
* @return array The script params.
|
601 |
*/
|
@@ -608,10 +583,6 @@ final class Scripts {
|
|
608 |
'name' => 'tabs',
|
609 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
610 |
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
611 |
-
'l10n' => [
|
612 |
-
'name' => 'tsfTabsL10n',
|
613 |
-
'data' => [],
|
614 |
-
],
|
615 |
];
|
616 |
}
|
617 |
|
@@ -671,12 +642,12 @@ final class Scripts {
|
|
671 |
*/
|
672 |
public static function get_title_scripts() {
|
673 |
|
674 |
-
$tsf = \
|
675 |
|
676 |
return [
|
677 |
'id' => 'tsf-title',
|
678 |
'type' => 'js',
|
679 |
-
'deps' => [ '
|
680 |
'autoload' => true,
|
681 |
'name' => 'title',
|
682 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
@@ -707,7 +678,7 @@ final class Scripts {
|
|
707 |
* Returns Description scripts params.
|
708 |
*
|
709 |
* @since 4.0.0
|
710 |
-
* @since 4.
|
711 |
*
|
712 |
* @return array The script params.
|
713 |
*/
|
@@ -715,7 +686,7 @@ final class Scripts {
|
|
715 |
return [
|
716 |
'id' => 'tsf-description',
|
717 |
'type' => 'js',
|
718 |
-
'deps' => [ '
|
719 |
'autoload' => true,
|
720 |
'name' => 'description',
|
721 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
@@ -727,102 +698,20 @@ final class Scripts {
|
|
727 |
* Returns Social scripts params.
|
728 |
*
|
729 |
* @since 4.0.0
|
|
|
730 |
*
|
731 |
* @return array The script params.
|
732 |
*/
|
733 |
public static function get_social_scripts() {
|
734 |
-
|
735 |
-
$tsf = \the_seo_framework();
|
736 |
-
|
737 |
-
$_query = [
|
738 |
-
'id' => $tsf->is_seo_settings_page() ? $tsf->get_the_front_page_ID() : $tsf->get_the_real_ID(),
|
739 |
-
'taxonomy' => $tsf->get_current_taxonomy(),
|
740 |
-
];
|
741 |
-
|
742 |
-
// These placeholders are required as there are three description lengths: search, og, twitter.
|
743 |
-
$settings_placeholders = [
|
744 |
-
'ogDesc' => '',
|
745 |
-
'twDesc' => '',
|
746 |
-
];
|
747 |
-
|
748 |
-
// These locks are required as we have an extra homepage metabox that can override social settings.
|
749 |
-
// PH = placeholder
|
750 |
-
$home_locks = array_fill_keys(
|
751 |
-
[
|
752 |
-
'ogTitleLock',
|
753 |
-
'ogTitlePHLock',
|
754 |
-
'ogDescriptionLock',
|
755 |
-
'ogDescriptionPHLock',
|
756 |
-
|
757 |
-
'twTitleLock',
|
758 |
-
'twTitlePHLock',
|
759 |
-
'twDescriptionLock',
|
760 |
-
'twDescriptionPHLock',
|
761 |
-
],
|
762 |
-
false
|
763 |
-
);
|
764 |
-
|
765 |
-
if ( $tsf->has_page_on_front() ) {
|
766 |
-
if ( $tsf->is_seo_settings_page() ) {
|
767 |
-
$home_locks = [
|
768 |
-
'ogTitlePHLock' => (bool) $tsf->get_post_meta_item( '_open_graph_title', $_query['id'] ),
|
769 |
-
'twTitlePHLock' => (bool) $tsf->get_post_meta_item( '_twitter_title', $_query['id'] ),
|
770 |
-
'twDescriptionPHLock' => (bool) $tsf->get_post_meta_item( '_twitter_description', $_query['id'] ),
|
771 |
-
'ogDescriptionPHLock' => (bool) $tsf->get_post_meta_item( '_open_graph_description', $_query['id'] ),
|
772 |
-
];
|
773 |
-
|
774 |
-
$_homepage_desc_placeholder = $tsf->get_post_meta_item( '_genesis_description', $_query['id'] );
|
775 |
-
|
776 |
-
$settings_placeholders = [
|
777 |
-
'ogDesc' => $_homepage_desc_placeholder,
|
778 |
-
'twDesc' => $_homepage_desc_placeholder,
|
779 |
-
];
|
780 |
-
} elseif ( ! $_query['taxonomy'] && $tsf->is_static_frontpage( $_query['id'] ) ) {
|
781 |
-
$home_locks = [
|
782 |
-
'ogTitleLock' => (bool) $tsf->get_option( 'homepage_og_title' ),
|
783 |
-
'ogDescriptionLock' => (bool) $tsf->get_option( 'homepage_og_description' ),
|
784 |
-
'twTitleLock' => (bool) $tsf->get_option( 'homepage_twitter_title' ),
|
785 |
-
'twDescriptionLock' => (bool) $tsf->get_option( 'homepage_twitter_description' ),
|
786 |
-
];
|
787 |
-
|
788 |
-
$_homepage_desc_placeholder = $tsf->get_option( 'homepage_description' );
|
789 |
-
|
790 |
-
$settings_placeholders = [
|
791 |
-
'ogDesc' => $_homepage_desc_placeholder,
|
792 |
-
'twDesc' => $_homepage_desc_placeholder,
|
793 |
-
];
|
794 |
-
}
|
795 |
-
}
|
796 |
-
|
797 |
-
$settings_placeholders['ogDesc'] = $tsf->s_description(
|
798 |
-
$settings_placeholders['ogDesc'] ?: $tsf->get_generated_open_graph_description( $_query, false )
|
799 |
-
);
|
800 |
-
|
801 |
-
$settings_placeholders['twDesc'] = $tsf->s_description(
|
802 |
-
$settings_placeholders['twDesc'] ?: $tsf->get_generated_twitter_description( $_query, false )
|
803 |
-
);
|
804 |
-
|
805 |
return [
|
806 |
'id' => 'tsf-social',
|
807 |
'type' => 'js',
|
808 |
-
'deps' => [ '
|
809 |
'autoload' => true,
|
810 |
'name' => 'social',
|
811 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
812 |
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
813 |
-
'l10n' => [
|
814 |
-
'name' => 'tsfSocialL10n',
|
815 |
-
'data' => [
|
816 |
-
'params' => [
|
817 |
-
'homeLocks' => $home_locks,
|
818 |
-
],
|
819 |
-
'states' => [
|
820 |
-
'placeholders' => static::decode_all_entities( $settings_placeholders ),
|
821 |
-
],
|
822 |
-
],
|
823 |
-
],
|
824 |
];
|
825 |
-
|
826 |
}
|
827 |
|
828 |
/**
|
@@ -835,7 +724,7 @@ final class Scripts {
|
|
835 |
*/
|
836 |
public static function get_primaryterm_scripts() {
|
837 |
|
838 |
-
$tsf = \
|
839 |
|
840 |
$id = $tsf->get_the_real_admin_ID();
|
841 |
|
@@ -848,8 +737,7 @@ final class Scripts {
|
|
848 |
foreach ( $_taxonomies as $_t ) {
|
849 |
if ( ! $tsf->is_taxonomy_supported( $_t->name ) ) continue;
|
850 |
|
851 |
-
$singular_name
|
852 |
-
|
853 |
$primary_term_id = $tsf->get_primary_term_id( $id, $_t->name ) ?: 0;
|
854 |
|
855 |
if ( ! $primary_term_id ) {
|
@@ -904,7 +792,7 @@ final class Scripts {
|
|
904 |
'id' => 'tsf-pt-gb',
|
905 |
'name' => 'pt-gb',
|
906 |
];
|
907 |
-
$deps = [ '
|
908 |
} else {
|
909 |
$vars = [
|
910 |
'id' => 'tsf-pt',
|
@@ -914,6 +802,17 @@ final class Scripts {
|
|
914 |
}
|
915 |
|
916 |
return [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
917 |
[
|
918 |
'id' => $vars['id'],
|
919 |
'type' => 'js',
|
@@ -932,17 +831,6 @@ final class Scripts {
|
|
932 |
'file' => $tsf->get_view_location( 'templates/inpost/primary-term-selector' ),
|
933 |
],
|
934 |
],
|
935 |
-
[
|
936 |
-
'id' => 'tsf-pt',
|
937 |
-
'type' => 'css',
|
938 |
-
'deps' => [ 'tsf-tt' ],
|
939 |
-
'autoload' => true,
|
940 |
-
'hasrtl' => false,
|
941 |
-
'name' => 'pt',
|
942 |
-
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/css/',
|
943 |
-
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
944 |
-
'inline' => $inline_css,
|
945 |
-
],
|
946 |
];
|
947 |
}
|
948 |
|
@@ -955,13 +843,23 @@ final class Scripts {
|
|
955 |
*/
|
956 |
public static function get_counter_scripts() {
|
957 |
|
958 |
-
$tsf = \
|
959 |
|
960 |
return [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
961 |
[
|
962 |
'id' => 'tsf-c',
|
963 |
'type' => 'js',
|
964 |
-
'deps' => [ '
|
965 |
'autoload' => true,
|
966 |
'name' => 'c',
|
967 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
@@ -979,18 +877,6 @@ final class Scripts {
|
|
979 |
],
|
980 |
],
|
981 |
],
|
982 |
-
[
|
983 |
-
'id' => 'tsf-c',
|
984 |
-
'type' => 'css',
|
985 |
-
'deps' => [ 'tsf-tt' ],
|
986 |
-
'autoload' => true,
|
987 |
-
'hasrtl' => false,
|
988 |
-
'name' => 'tsfc',
|
989 |
-
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/css/',
|
990 |
-
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
991 |
-
],
|
992 |
];
|
993 |
}
|
994 |
}
|
995 |
-
|
996 |
-
$_load_scripts_class();
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
/**
|
29 |
* Prepares admin GUI scripts. Auto-invokes everything the moment this file is required.
|
30 |
* Relies on \The_SEO_Framework\Builders\Scripts to register and load scripts.
|
36 |
* @since 4.0.0
|
37 |
* @see \The_SEO_Framework\Builders\Scripts
|
38 |
* @access protected
|
|
|
39 |
* @final Can't be extended.
|
40 |
*/
|
41 |
final class Scripts {
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
/**
|
44 |
* Prepares the class and loads constructor.
|
45 |
*
|
47 |
* this class is needed yet.
|
48 |
*
|
49 |
* @since 4.0.0
|
50 |
+
* @ignore
|
51 |
+
* @deprecated
|
52 |
*/
|
53 |
public static function prepare() {}
|
54 |
|
55 |
/**
|
56 |
+
* The constructor. Can't be instantiated.
|
57 |
+
* Kills PHP. Enforces singleton.
|
58 |
*
|
59 |
* This probably autoloads at action "admin_enqueue_scripts", priority "0".
|
60 |
*
|
62 |
* @access private
|
63 |
* @internal
|
64 |
*/
|
65 |
+
private function __construct() {}
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
|
67 |
/**
|
68 |
* Initializes scripts based on admin query.
|
73 |
*/
|
74 |
public static function _init() {
|
75 |
|
76 |
+
$tsf = \tsf();
|
77 |
|
78 |
$_scripts = [
|
79 |
static::get_tsf_scripts(),
|
178 |
if ( is_scalar( $values ) )
|
179 |
return static::decode_entities( $values );
|
180 |
|
181 |
+
foreach ( $values as &$v )
|
182 |
$v = static::decode_entities( $v );
|
|
|
183 |
|
184 |
return $values;
|
185 |
}
|
191 |
*/
|
192 |
public static function prepare_media_scripts() {
|
193 |
|
194 |
+
$tsf = \tsf();
|
195 |
$args = [];
|
196 |
|
197 |
+
if ( $tsf->is_post_edit() )
|
198 |
$args['post'] = $tsf->get_the_real_admin_ID();
|
|
|
199 |
|
200 |
\wp_enqueue_media( $args );
|
201 |
}
|
223 |
[
|
224 |
'id' => 'tsf',
|
225 |
'type' => 'css',
|
226 |
+
'deps' => [],
|
227 |
'autoload' => true,
|
228 |
'hasrtl' => false,
|
229 |
'name' => 'tsf',
|
233 |
[
|
234 |
'id' => 'tsf',
|
235 |
'type' => 'js',
|
236 |
+
'deps' => [ 'jquery', 'wp-util' ],
|
237 |
'autoload' => true,
|
238 |
'name' => 'tsf',
|
239 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
252 |
'edit_posts' => \current_user_can( 'edit_posts' ) ? \wp_create_nonce( 'tsf-ajax-edit_posts' ) : false,
|
253 |
],
|
254 |
'states' => [
|
255 |
+
'debug' => \tsf()->script_debug,
|
|
|
256 |
],
|
257 |
],
|
258 |
],
|
297 |
[
|
298 |
'id' => 'tsf-tt',
|
299 |
'type' => 'js',
|
300 |
+
'deps' => [ 'tsf' ],
|
301 |
'autoload' => true,
|
302 |
'name' => 'tt',
|
303 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
318 |
[
|
319 |
'id' => 'tsf-ays',
|
320 |
'type' => 'js',
|
321 |
+
'deps' => [ 'tsf' ],
|
322 |
'autoload' => true,
|
323 |
'name' => 'ays',
|
324 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
340 |
*
|
341 |
* @since 4.0.0
|
342 |
* @since 4.1.0 Now depends on title and description scripts.
|
343 |
+
* @since 4.2.0 No longer registers l10n (data).
|
344 |
*
|
345 |
* @return array The script params.
|
346 |
*/
|
359 |
[
|
360 |
'id' => 'tsf-le',
|
361 |
'type' => 'js',
|
362 |
+
'deps' => [ 'tsf-title', 'tsf-description', 'tsf' ],
|
363 |
'autoload' => true,
|
364 |
'name' => 'le',
|
365 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
366 |
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
|
|
|
|
|
|
|
|
367 |
],
|
368 |
];
|
369 |
}
|
378 |
*/
|
379 |
public static function get_seo_settings_scripts() {
|
380 |
|
381 |
+
$tsf = \tsf();
|
382 |
|
383 |
$front_id = $tsf->get_the_front_page_ID();
|
384 |
|
385 |
return [
|
386 |
+
[
|
387 |
+
'id' => 'tsf-settings',
|
388 |
+
'type' => 'css',
|
389 |
+
'deps' => [ 'tsf', 'tsf-tt', 'wp-color-picker' ],
|
390 |
+
'autoload' => true,
|
391 |
+
'hasrtl' => false,
|
392 |
+
'name' => 'settings',
|
393 |
+
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/css/',
|
394 |
+
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
395 |
+
],
|
396 |
[
|
397 |
'id' => 'tsf-settings',
|
398 |
'type' => 'js',
|
399 |
+
'deps' => [ 'jquery', 'tsf-ays', 'tsf-title', 'tsf-description', 'tsf-social', 'tsf', 'tsf-tabs', 'tsf-tt', 'wp-color-picker', 'wp-util' ],
|
400 |
'autoload' => true,
|
401 |
'name' => 'settings',
|
402 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
414 |
'file' => $tsf->get_view_location( 'templates/settings/settings' ),
|
415 |
],
|
416 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
];
|
418 |
}
|
419 |
|
427 |
*/
|
428 |
public static function get_post_edit_scripts() {
|
429 |
|
430 |
+
$tsf = \tsf();
|
431 |
$id = $tsf->get_the_real_ID();
|
432 |
|
433 |
$is_static_frontpage = $tsf->is_static_frontpage( $id );
|
441 |
}
|
442 |
|
443 |
return [
|
444 |
+
[
|
445 |
+
'id' => 'tsf-post',
|
446 |
+
'type' => 'css',
|
447 |
+
'deps' => [ 'tsf-tt', 'tsf' ],
|
448 |
+
'autoload' => true,
|
449 |
+
'hasrtl' => false,
|
450 |
+
'name' => 'post',
|
451 |
+
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/css/',
|
452 |
+
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
453 |
+
'inline' => [
|
454 |
+
'.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked + .tsf-flex-nav-tab-label' => [
|
455 |
+
'box-shadow:0 -2px 0 0 {{$color_accent}} inset, 0 0 0 0 {{$color_accent}} inset',
|
456 |
+
],
|
457 |
+
'.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:focus + .tsf-flex-nav-tab-label:not(.tsf-no-focus-ring)' => [
|
458 |
+
'box-shadow:0 -2px 0 0 {{$color_accent}} inset, 0 0 0 1px {{$color_accent}} inset',
|
459 |
+
],
|
460 |
+
],
|
461 |
+
],
|
462 |
[
|
463 |
'id' => 'tsf-post',
|
464 |
'type' => 'js',
|
484 |
],
|
485 |
],
|
486 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
];
|
488 |
}
|
489 |
|
492 |
*
|
493 |
* @since 4.0.0
|
494 |
* @since 4.1.0 Updated l10n.data.
|
495 |
+
* @since 4.2.0 Now properly populates use_generated_archive_prefix() with a \WP_Term object.
|
496 |
*
|
497 |
* @return array The script params.
|
498 |
*/
|
499 |
public static function get_term_edit_scripts() {
|
500 |
|
501 |
+
$tsf = \tsf();
|
502 |
$taxonomy = $tsf->get_current_taxonomy();
|
503 |
|
504 |
$additions_forced_disabled = (bool) $tsf->get_option( 'title_rem_additions' );
|
505 |
|
506 |
+
$term_prefix = $tsf->use_generated_archive_prefix( \get_term( $tsf->get_the_real_ID(), $taxonomy ) )
|
507 |
+
/* translators: %s: Taxonomy singular name. */
|
508 |
+
? sprintf(
|
509 |
+
/* translators: %s: Taxonomy singular name. */
|
510 |
+
\_x( '%s:', 'taxonomy term archive title prefix', 'default' ),
|
511 |
+
$tsf->get_tax_type_label( $taxonomy )
|
512 |
+
)
|
513 |
: '';
|
514 |
|
515 |
return [
|
516 |
+
[
|
517 |
+
'id' => 'tsf-term',
|
518 |
+
'type' => 'css',
|
519 |
+
'deps' => [ 'tsf-tt', 'tsf' ],
|
520 |
+
'autoload' => true,
|
521 |
+
'hasrtl' => false,
|
522 |
+
'name' => 'term',
|
523 |
+
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/css/',
|
524 |
+
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
525 |
+
],
|
526 |
[
|
527 |
'id' => 'tsf-term',
|
528 |
'type' => 'js',
|
529 |
+
'deps' => [ 'tsf-ays', 'tsf-title', 'tsf-description', 'tsf-social', 'tsf-tt', 'tsf' ],
|
530 |
'autoload' => true,
|
531 |
'name' => 'term',
|
532 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
541 |
],
|
542 |
],
|
543 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
544 |
];
|
545 |
}
|
546 |
|
548 |
* Returns Gutenberg compatibility scripts params.
|
549 |
*
|
550 |
* @since 4.0.0
|
551 |
+
* @since 4.2.0 No longer registers l10n (data).
|
552 |
*
|
553 |
* @return array The script params.
|
554 |
*/
|
557 |
[
|
558 |
'id' => 'tsf-gbc',
|
559 |
'type' => 'js',
|
560 |
+
'deps' => [ 'jquery', 'tsf', 'wp-editor', 'wp-data', 'lodash', 'react' ],
|
561 |
'autoload' => true,
|
562 |
'name' => 'gbc',
|
563 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
564 |
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
|
|
|
|
|
|
|
|
565 |
],
|
566 |
];
|
567 |
}
|
570 |
* Returns Tabs scripts params.
|
571 |
*
|
572 |
* @since 4.1.3
|
573 |
+
* @since 4.2.0 No longer registers l10n (data).
|
574 |
*
|
575 |
* @return array The script params.
|
576 |
*/
|
583 |
'name' => 'tabs',
|
584 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
585 |
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
|
|
|
|
|
|
|
|
586 |
];
|
587 |
}
|
588 |
|
642 |
*/
|
643 |
public static function get_title_scripts() {
|
644 |
|
645 |
+
$tsf = \tsf();
|
646 |
|
647 |
return [
|
648 |
'id' => 'tsf-title',
|
649 |
'type' => 'js',
|
650 |
+
'deps' => [ 'tsf' ],
|
651 |
'autoload' => true,
|
652 |
'name' => 'title',
|
653 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
678 |
* Returns Description scripts params.
|
679 |
*
|
680 |
* @since 4.0.0
|
681 |
+
* @since 4.2.0 No longer registers l10n (data).
|
682 |
*
|
683 |
* @return array The script params.
|
684 |
*/
|
686 |
return [
|
687 |
'id' => 'tsf-description',
|
688 |
'type' => 'js',
|
689 |
+
'deps' => [ 'tsf' ],
|
690 |
'autoload' => true,
|
691 |
'name' => 'description',
|
692 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
698 |
* Returns Social scripts params.
|
699 |
*
|
700 |
* @since 4.0.0
|
701 |
+
* @since 4.2.0 No longer registers l10n (data).
|
702 |
*
|
703 |
* @return array The script params.
|
704 |
*/
|
705 |
public static function get_social_scripts() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
706 |
return [
|
707 |
'id' => 'tsf-social',
|
708 |
'type' => 'js',
|
709 |
+
'deps' => [ 'tsf' ],
|
710 |
'autoload' => true,
|
711 |
'name' => 'social',
|
712 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
713 |
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
714 |
];
|
|
|
715 |
}
|
716 |
|
717 |
/**
|
724 |
*/
|
725 |
public static function get_primaryterm_scripts() {
|
726 |
|
727 |
+
$tsf = \tsf();
|
728 |
|
729 |
$id = $tsf->get_the_real_admin_ID();
|
730 |
|
737 |
foreach ( $_taxonomies as $_t ) {
|
738 |
if ( ! $tsf->is_taxonomy_supported( $_t->name ) ) continue;
|
739 |
|
740 |
+
$singular_name = $tsf->get_tax_type_label( $_t->name );
|
|
|
741 |
$primary_term_id = $tsf->get_primary_term_id( $id, $_t->name ) ?: 0;
|
742 |
|
743 |
if ( ! $primary_term_id ) {
|
792 |
'id' => 'tsf-pt-gb',
|
793 |
'name' => 'pt-gb',
|
794 |
];
|
795 |
+
$deps = [ 'tsf', 'wp-hooks', 'wp-element', 'wp-components', 'wp-url', 'wp-api-fetch', 'lodash', 'react', 'wp-util' ];
|
796 |
} else {
|
797 |
$vars = [
|
798 |
'id' => 'tsf-pt',
|
802 |
}
|
803 |
|
804 |
return [
|
805 |
+
[
|
806 |
+
'id' => 'tsf-pt',
|
807 |
+
'type' => 'css',
|
808 |
+
'deps' => [ 'tsf-tt' ],
|
809 |
+
'autoload' => true,
|
810 |
+
'hasrtl' => false,
|
811 |
+
'name' => 'pt',
|
812 |
+
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/css/',
|
813 |
+
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
814 |
+
'inline' => $inline_css,
|
815 |
+
],
|
816 |
[
|
817 |
'id' => $vars['id'],
|
818 |
'type' => 'js',
|
831 |
'file' => $tsf->get_view_location( 'templates/inpost/primary-term-selector' ),
|
832 |
],
|
833 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
834 |
];
|
835 |
}
|
836 |
|
843 |
*/
|
844 |
public static function get_counter_scripts() {
|
845 |
|
846 |
+
$tsf = \tsf();
|
847 |
|
848 |
return [
|
849 |
+
[
|
850 |
+
'id' => 'tsf-c',
|
851 |
+
'type' => 'css',
|
852 |
+
'deps' => [ 'tsf-tt' ],
|
853 |
+
'autoload' => true,
|
854 |
+
'hasrtl' => false,
|
855 |
+
'name' => 'tsfc',
|
856 |
+
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/css/',
|
857 |
+
'ver' => THE_SEO_FRAMEWORK_VERSION,
|
858 |
+
],
|
859 |
[
|
860 |
'id' => 'tsf-c',
|
861 |
'type' => 'js',
|
862 |
+
'deps' => [ 'tsf-tt', 'tsf' ],
|
863 |
'autoload' => true,
|
864 |
'name' => 'c',
|
865 |
'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
|
877 |
],
|
878 |
],
|
879 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
880 |
];
|
881 |
}
|
882 |
}
|
|
|
|
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* @package The_SEO_Framework\Classes\Bridges\
|
4 |
-
* @subpackage The_SEO_Framework\
|
5 |
*/
|
6 |
|
7 |
namespace The_SEO_Framework\Bridges;
|
@@ -29,12 +29,12 @@ namespace The_SEO_Framework\Bridges;
|
|
29 |
* Loads the SEO Bar for administrative tables.
|
30 |
*
|
31 |
* @since 4.0.0
|
32 |
-
* @uses \The_SEO_Framework\Interpreters\
|
33 |
-
* @see \The_SEO_Framework\Interpreters\
|
34 |
*
|
35 |
* @access private
|
36 |
*/
|
37 |
-
final class
|
38 |
|
39 |
/**
|
40 |
* @since 4.0.0
|
@@ -118,7 +118,7 @@ final class SeoBar extends ListTable {
|
|
118 |
if ( $this->column_name !== $column_name ) return;
|
119 |
|
120 |
// phpcs:ignore, WordPress.Security.EscapeOutput
|
121 |
-
echo \The_SEO_Framework\Interpreters\
|
122 |
'id' => $post_id,
|
123 |
'post_type' => $this->post_type,
|
124 |
] );
|
@@ -150,7 +150,7 @@ final class SeoBar extends ListTable {
|
|
150 |
if ( $this->doing_ajax )
|
151 |
$string .= $this->get_ajax_dispatch_updated_event();
|
152 |
|
153 |
-
return \The_SEO_Framework\Interpreters\
|
154 |
'id' => $term_id,
|
155 |
'taxonomy' => $this->taxonomy,
|
156 |
] ) . $string;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Bridges\SEOBar
|
4 |
+
* @subpackage The_SEO_Framework\SEOBar
|
5 |
*/
|
6 |
|
7 |
namespace The_SEO_Framework\Bridges;
|
29 |
* Loads the SEO Bar for administrative tables.
|
30 |
*
|
31 |
* @since 4.0.0
|
32 |
+
* @uses \The_SEO_Framework\Interpreters\SEOBar
|
33 |
+
* @see \The_SEO_Framework\Interpreters\SEOBar to generate a bar.
|
34 |
*
|
35 |
* @access private
|
36 |
*/
|
37 |
+
final class SEOBar extends ListTable {
|
38 |
|
39 |
/**
|
40 |
* @since 4.0.0
|
118 |
if ( $this->column_name !== $column_name ) return;
|
119 |
|
120 |
// phpcs:ignore, WordPress.Security.EscapeOutput
|
121 |
+
echo \The_SEO_Framework\Interpreters\SEOBar::generate_bar( [
|
122 |
'id' => $post_id,
|
123 |
'post_type' => $this->post_type,
|
124 |
] );
|
150 |
if ( $this->doing_ajax )
|
151 |
$string .= $this->get_ajax_dispatch_updated_event();
|
152 |
|
153 |
+
return \The_SEO_Framework\Interpreters\SEOBar::generate_bar( [
|
154 |
'id' => $term_id,
|
155 |
'taxonomy' => $this->taxonomy,
|
156 |
] ) . $string;
|
@@ -45,35 +45,40 @@ final class SeoSettings {
|
|
45 |
*/
|
46 |
public static function _register_seo_settings_meta_boxes() {
|
47 |
|
|
|
|
|
48 |
/**
|
49 |
* Various metabox filters.
|
50 |
* Set any to false if you wish the meta box to be removed.
|
51 |
*
|
52 |
* @since 2.2.4
|
53 |
* @since 2.8.0 Added `the_seo_framework_general_metabox` filter.
|
|
|
54 |
*/
|
55 |
-
$general
|
56 |
-
$title
|
57 |
-
$description
|
58 |
-
$robots
|
59 |
-
$home
|
60 |
-
$
|
61 |
-
$
|
62 |
-
$
|
63 |
-
$
|
64 |
-
$
|
65 |
-
|
66 |
-
|
|
|
|
|
|
|
67 |
|
68 |
// General Meta Box
|
69 |
if ( $general )
|
70 |
\add_meta_box(
|
71 |
'autodescription-general-settings',
|
72 |
\esc_html__( 'General Settings', 'autodescription' ),
|
73 |
-
|
74 |
$settings_page_hook,
|
75 |
-
'main'
|
76 |
-
[]
|
77 |
);
|
78 |
|
79 |
// Title Meta Box
|
@@ -81,10 +86,9 @@ final class SeoSettings {
|
|
81 |
\add_meta_box(
|
82 |
'autodescription-title-settings',
|
83 |
\esc_html__( 'Title Settings', 'autodescription' ),
|
84 |
-
|
85 |
$settings_page_hook,
|
86 |
-
'main'
|
87 |
-
[]
|
88 |
);
|
89 |
|
90 |
// Description Meta Box
|
@@ -92,10 +96,9 @@ final class SeoSettings {
|
|
92 |
\add_meta_box(
|
93 |
'autodescription-description-settings',
|
94 |
\esc_html__( 'Description Meta Settings', 'autodescription' ),
|
95 |
-
|
96 |
$settings_page_hook,
|
97 |
-
'main'
|
98 |
-
[]
|
99 |
);
|
100 |
|
101 |
// Homepage Meta Box
|
@@ -103,10 +106,18 @@ final class SeoSettings {
|
|
103 |
\add_meta_box(
|
104 |
'autodescription-homepage-settings',
|
105 |
\esc_html__( 'Homepage Settings', 'autodescription' ),
|
106 |
-
|
107 |
$settings_page_hook,
|
108 |
-
'main'
|
109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
);
|
111 |
|
112 |
// Social Meta Box
|
@@ -114,10 +125,9 @@ final class SeoSettings {
|
|
114 |
\add_meta_box(
|
115 |
'autodescription-social-settings',
|
116 |
\esc_html__( 'Social Meta Settings', 'autodescription' ),
|
117 |
-
|
118 |
$settings_page_hook,
|
119 |
-
'main'
|
120 |
-
[]
|
121 |
);
|
122 |
|
123 |
// Schema Meta Box
|
@@ -125,10 +135,9 @@ final class SeoSettings {
|
|
125 |
\add_meta_box(
|
126 |
'autodescription-schema-settings',
|
127 |
\esc_html__( 'Schema.org Settings', 'autodescription' ),
|
128 |
-
|
129 |
$settings_page_hook,
|
130 |
-
'main'
|
131 |
-
[]
|
132 |
);
|
133 |
|
134 |
// Robots Meta Box
|
@@ -136,10 +145,9 @@ final class SeoSettings {
|
|
136 |
\add_meta_box(
|
137 |
'autodescription-robots-settings',
|
138 |
\esc_html__( 'Robots Meta Settings', 'autodescription' ),
|
139 |
-
|
140 |
$settings_page_hook,
|
141 |
-
'main'
|
142 |
-
[]
|
143 |
);
|
144 |
|
145 |
// Webmaster Meta Box
|
@@ -147,10 +155,9 @@ final class SeoSettings {
|
|
147 |
\add_meta_box(
|
148 |
'autodescription-webmaster-settings',
|
149 |
\esc_html__( 'Webmaster Meta Settings', 'autodescription' ),
|
150 |
-
|
151 |
$settings_page_hook,
|
152 |
-
'main'
|
153 |
-
[]
|
154 |
);
|
155 |
|
156 |
// Sitemaps Meta Box
|
@@ -158,10 +165,9 @@ final class SeoSettings {
|
|
158 |
\add_meta_box(
|
159 |
'autodescription-sitemap-settings',
|
160 |
\esc_html__( 'Sitemap Settings', 'autodescription' ),
|
161 |
-
|
162 |
$settings_page_hook,
|
163 |
-
'main'
|
164 |
-
[]
|
165 |
);
|
166 |
|
167 |
// Feed Meta Box
|
@@ -169,10 +175,9 @@ final class SeoSettings {
|
|
169 |
\add_meta_box(
|
170 |
'autodescription-feed-settings',
|
171 |
\esc_html__( 'Feed Settings', 'autodescription' ),
|
172 |
-
|
173 |
$settings_page_hook,
|
174 |
-
'main'
|
175 |
-
[]
|
176 |
);
|
177 |
}
|
178 |
|
@@ -196,8 +201,9 @@ final class SeoSettings {
|
|
196 |
* @param bool $use_tabs Whether to output tabs, only works when $tabs count is greater than 1.
|
197 |
*/
|
198 |
public static function _nav_tab_wrapper( $id, $tabs = [], $use_tabs = true ) { // phpcs:ignore,VariableAnalysis
|
199 |
-
|
200 |
-
|
|
|
201 |
}
|
202 |
|
203 |
/**
|
@@ -211,7 +217,7 @@ final class SeoSettings {
|
|
211 |
* @since 3.0.0
|
212 |
*/
|
213 |
\do_action( 'the_seo_framework_pre_seo_settings' );
|
214 |
-
\
|
215 |
/**
|
216 |
* @since 3.0.0
|
217 |
*/
|
@@ -225,7 +231,7 @@ final class SeoSettings {
|
|
225 |
* @access private
|
226 |
*/
|
227 |
public static function _output_columns() {
|
228 |
-
\
|
229 |
}
|
230 |
|
231 |
/**
|
@@ -233,16 +239,13 @@ final class SeoSettings {
|
|
233 |
*
|
234 |
* @since 4.0.0
|
235 |
* @access private
|
236 |
-
*
|
237 |
-
* @param \WP_Post|null $post The current post object.
|
238 |
-
* @param array $args The metabox arguments.
|
239 |
*/
|
240 |
-
public static function _general_metabox(
|
241 |
/**
|
242 |
* @since 2.8.0
|
243 |
*/
|
244 |
\do_action( 'the_seo_framework_general_metabox_before' );
|
245 |
-
\
|
246 |
/**
|
247 |
* @since 2.8.0
|
248 |
*/
|
@@ -257,7 +260,7 @@ final class SeoSettings {
|
|
257 |
* @see static::general_metabox() : Callback for General Settings box.
|
258 |
*/
|
259 |
public static function _general_metabox_general_tab() {
|
260 |
-
\
|
261 |
}
|
262 |
|
263 |
/**
|
@@ -268,7 +271,7 @@ final class SeoSettings {
|
|
268 |
* @see static::general_metabox() : Callback for General Settings box.
|
269 |
*/
|
270 |
public static function _general_metabox_layout_tab() {
|
271 |
-
\
|
272 |
}
|
273 |
|
274 |
/**
|
@@ -279,7 +282,7 @@ final class SeoSettings {
|
|
279 |
* @see static::general_metabox() : Callback for General Settings box.
|
280 |
*/
|
281 |
public static function _general_metabox_performance_tab() {
|
282 |
-
\
|
283 |
}
|
284 |
|
285 |
/**
|
@@ -290,7 +293,7 @@ final class SeoSettings {
|
|
290 |
* @see static::general_metabox() : Callback for General Settings box.
|
291 |
*/
|
292 |
public static function _general_metabox_canonical_tab() {
|
293 |
-
\
|
294 |
}
|
295 |
|
296 |
/**
|
@@ -301,7 +304,7 @@ final class SeoSettings {
|
|
301 |
* @see static::general_metabox() : Callback for General Settings box.
|
302 |
*/
|
303 |
public static function _general_metabox_timestamps_tab() {
|
304 |
-
\
|
305 |
}
|
306 |
|
307 |
/**
|
@@ -312,7 +315,7 @@ final class SeoSettings {
|
|
312 |
* @see static::general_metabox() : Callback for General Settings box.
|
313 |
*/
|
314 |
public static function _general_metabox_exclusions_tab() {
|
315 |
-
\
|
316 |
}
|
317 |
|
318 |
/**
|
@@ -320,16 +323,13 @@ final class SeoSettings {
|
|
320 |
*
|
321 |
* @since 4.0.0
|
322 |
* @access private
|
323 |
-
*
|
324 |
-
* @param \WP_Post|null $post The current post object.
|
325 |
-
* @param array $args The metabox arguments.
|
326 |
*/
|
327 |
-
public static function _title_metabox(
|
328 |
/**
|
329 |
* @since 2.5.0 or earlier.
|
330 |
*/
|
331 |
\do_action( 'the_seo_framework_title_metabox_before' );
|
332 |
-
\
|
333 |
/**
|
334 |
* @since 2.5.0 or earlier.
|
335 |
*/
|
@@ -344,7 +344,7 @@ final class SeoSettings {
|
|
344 |
* @see static::title_metabox() : Callback for Title Settings box.
|
345 |
*/
|
346 |
public static function _title_metabox_general_tab() {
|
347 |
-
\
|
348 |
}
|
349 |
|
350 |
/**
|
@@ -357,7 +357,7 @@ final class SeoSettings {
|
|
357 |
* @param array $args The variables to pass to the metabox tab.
|
358 |
*/
|
359 |
public static function _title_metabox_additions_tab( $args ) {
|
360 |
-
\
|
361 |
}
|
362 |
|
363 |
/**
|
@@ -370,7 +370,7 @@ final class SeoSettings {
|
|
370 |
* @param array $args The variables to pass to the metabox tab.
|
371 |
*/
|
372 |
public static function _title_metabox_prefixes_tab( $args ) {
|
373 |
-
\
|
374 |
}
|
375 |
|
376 |
/**
|
@@ -378,16 +378,13 @@ final class SeoSettings {
|
|
378 |
*
|
379 |
* @since 4.0.0
|
380 |
* @access private
|
381 |
-
*
|
382 |
-
* @param \WP_Post|null $post The current post object.
|
383 |
-
* @param array $args The metabox arguments.
|
384 |
*/
|
385 |
-
public static function _description_metabox(
|
386 |
/**
|
387 |
* @since 2.5.0 or earlier.
|
388 |
*/
|
389 |
\do_action( 'the_seo_framework_description_metabox_before' );
|
390 |
-
\
|
391 |
/**
|
392 |
* @since 2.5.0 or earlier.
|
393 |
*/
|
@@ -399,16 +396,13 @@ final class SeoSettings {
|
|
399 |
*
|
400 |
* @since 4.0.0
|
401 |
* @access private
|
402 |
-
*
|
403 |
-
* @param \WP_Post|null $post The current post object.
|
404 |
-
* @param array $args The metabox arguments.
|
405 |
*/
|
406 |
-
public static function _robots_metabox(
|
407 |
/**
|
408 |
* @since 2.5.0 or earlier.
|
409 |
*/
|
410 |
\do_action( 'the_seo_framework_robots_metabox_before' );
|
411 |
-
\
|
412 |
/**
|
413 |
* @since 2.5.0 or earlier.
|
414 |
*/
|
@@ -416,18 +410,18 @@ final class SeoSettings {
|
|
416 |
}
|
417 |
|
418 |
/**
|
419 |
-
* Robots
|
420 |
*
|
421 |
* @since 4.0.0
|
422 |
* @access private
|
423 |
* @see static::robots_metabox() Callback for Robots Settings box.
|
424 |
*/
|
425 |
public static function _robots_metabox_general_tab() {
|
426 |
-
\
|
427 |
}
|
428 |
|
429 |
/**
|
430 |
-
* Robots
|
431 |
*
|
432 |
* @since 4.0.0
|
433 |
* @access private
|
@@ -436,7 +430,7 @@ final class SeoSettings {
|
|
436 |
* @param array $args The variables to pass to the metabox tab.
|
437 |
*/
|
438 |
public static function _robots_metabox_no_tab( $args ) {
|
439 |
-
\
|
440 |
}
|
441 |
|
442 |
/**
|
@@ -444,16 +438,13 @@ final class SeoSettings {
|
|
444 |
*
|
445 |
* @since 4.0.0
|
446 |
* @access private
|
447 |
-
*
|
448 |
-
* @param \WP_Post|null $post The current post object.
|
449 |
-
* @param array $args The navigation tabs args.
|
450 |
*/
|
451 |
-
public static function _homepage_metabox(
|
452 |
/**
|
453 |
* @since 2.5.0 or earlier.
|
454 |
*/
|
455 |
\do_action( 'the_seo_framework_homepage_metabox_before' );
|
456 |
-
\
|
457 |
/**
|
458 |
* @since 2.5.0 or earlier.
|
459 |
*/
|
@@ -461,47 +452,101 @@ final class SeoSettings {
|
|
461 |
}
|
462 |
|
463 |
/**
|
464 |
-
* Homepage
|
465 |
*
|
466 |
* @since 4.0.0
|
467 |
* @access private
|
468 |
* @see static::homepage_metabox() Callback for Homepage Settings box.
|
469 |
*/
|
470 |
public static function _homepage_metabox_general_tab() {
|
471 |
-
\
|
472 |
}
|
473 |
|
474 |
/**
|
475 |
-
* Homepage
|
476 |
*
|
477 |
* @since 4.0.0
|
478 |
* @access private
|
479 |
* @see static::homepage_metabox() Callback for Homepage Settings box.
|
480 |
*/
|
481 |
public static function _homepage_metabox_additions_tab() {
|
482 |
-
\
|
483 |
}
|
484 |
|
485 |
/**
|
486 |
-
* Homepage
|
487 |
*
|
488 |
* @since 4.0.0
|
489 |
* @access private
|
490 |
* @see static::homepage_metabox() Callback for Homepage Settings box.
|
491 |
*/
|
492 |
public static function _homepage_metabox_robots_tab() {
|
493 |
-
\
|
494 |
}
|
495 |
|
496 |
/**
|
497 |
-
* Homepage
|
498 |
*
|
499 |
* @since 4.0.0
|
500 |
* @access private
|
501 |
* @see static::homepage_metabox() Callback for Homepage Settings box.
|
502 |
*/
|
503 |
public static function _homepage_metabox_social_tab() {
|
504 |
-
\
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
505 |
}
|
506 |
|
507 |
/**
|
@@ -509,16 +554,13 @@ final class SeoSettings {
|
|
509 |
*
|
510 |
* @since 4.0.0
|
511 |
* @access private
|
512 |
-
*
|
513 |
-
* @param \WP_Post|null $post The current post object.
|
514 |
-
* @param array $args The navigation tabs args.
|
515 |
*/
|
516 |
-
public static function _social_metabox(
|
517 |
/**
|
518 |
* @since 2.5.0 or earlier.
|
519 |
*/
|
520 |
\do_action( 'the_seo_framework_social_metabox_before' );
|
521 |
-
\
|
522 |
/**
|
523 |
* @since 2.5.0 or earlier.
|
524 |
*/
|
@@ -526,58 +568,58 @@ final class SeoSettings {
|
|
526 |
}
|
527 |
|
528 |
/**
|
529 |
-
* Social
|
530 |
*
|
531 |
* @since 4.0.0
|
532 |
* @access private
|
533 |
* @see static::social_metabox() Callback for Social Settings box.
|
534 |
*/
|
535 |
public static function _social_metabox_general_tab() {
|
536 |
-
\
|
537 |
}
|
538 |
|
539 |
/**
|
540 |
-
* Social
|
541 |
*
|
542 |
* @since 4.0.0
|
543 |
* @access private
|
544 |
* @see static::social_metabox() Callback for Social Settings box.
|
545 |
*/
|
546 |
public static function _social_metabox_facebook_tab() {
|
547 |
-
\
|
548 |
}
|
549 |
|
550 |
/**
|
551 |
-
* Social
|
552 |
*
|
553 |
* @since 4.0.0
|
554 |
* @access private
|
555 |
* @see static::social_metabox() Callback for Social Settings box.
|
556 |
*/
|
557 |
public static function _social_metabox_twitter_tab() {
|
558 |
-
\
|
559 |
}
|
560 |
|
561 |
/**
|
562 |
-
* Social
|
563 |
*
|
564 |
* @since 4.0.5
|
565 |
* @access private
|
566 |
* @see static::social_metabox() Callback for Social Settings box.
|
567 |
*/
|
568 |
public static function _social_metabox_oembed_tab() {
|
569 |
-
\
|
570 |
}
|
571 |
|
572 |
/**
|
573 |
-
* Social
|
574 |
*
|
575 |
* @since 4.0.0
|
576 |
* @access private
|
577 |
* @see static::social_metabox() Callback for Social Settings box.
|
578 |
*/
|
579 |
public static function _social_metabox_postdates_tab() {
|
580 |
-
\
|
581 |
}
|
582 |
|
583 |
/**
|
@@ -585,16 +627,13 @@ final class SeoSettings {
|
|
585 |
*
|
586 |
* @since 4.0.0
|
587 |
* @access private
|
588 |
-
*
|
589 |
-
* @param \WP_Post|null $post The current post object.
|
590 |
-
* @param array $args The navigation tabs args.
|
591 |
*/
|
592 |
-
public static function _webmaster_metabox(
|
593 |
/**
|
594 |
* @since 2.5.0 or earlier.
|
595 |
*/
|
596 |
\do_action( 'the_seo_framework_webmaster_metabox_before' );
|
597 |
-
\
|
598 |
/**
|
599 |
* @since 2.5.0 or earlier.
|
600 |
*/
|
@@ -607,16 +646,13 @@ final class SeoSettings {
|
|
607 |
* @since 4.0.0
|
608 |
* @access private
|
609 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
610 |
-
*
|
611 |
-
* @param \WP_Post|null $post The current post object.
|
612 |
-
* @param array $args The navigation tabs args.
|
613 |
*/
|
614 |
-
public static function _sitemaps_metabox(
|
615 |
/**
|
616 |
* @since 2.5.0 or earlier.
|
617 |
*/
|
618 |
\do_action( 'the_seo_framework_sitemaps_metabox_before' );
|
619 |
-
\
|
620 |
/**
|
621 |
* @since 2.5.0 or earlier.
|
622 |
*/
|
@@ -624,75 +660,72 @@ final class SeoSettings {
|
|
624 |
}
|
625 |
|
626 |
/**
|
627 |
-
* Sitemaps
|
628 |
*
|
629 |
* @since 4.0.0
|
630 |
* @access private
|
631 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
632 |
*/
|
633 |
public static function _sitemaps_metabox_general_tab() {
|
634 |
-
\
|
635 |
}
|
636 |
|
637 |
/**
|
638 |
-
* Sitemaps
|
639 |
*
|
640 |
* @since 4.0.0
|
641 |
* @access private
|
642 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
643 |
*/
|
644 |
public static function _sitemaps_metabox_robots_tab() {
|
645 |
-
\
|
646 |
}
|
647 |
|
648 |
/**
|
649 |
-
* Sitemaps
|
650 |
*
|
651 |
* @since 4.0.0
|
652 |
* @access private
|
653 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
654 |
*/
|
655 |
public static function _sitemaps_metabox_metadata_tab() {
|
656 |
-
\
|
657 |
}
|
658 |
|
659 |
/**
|
660 |
-
* Sitemaps
|
661 |
*
|
662 |
* @since 4.0.0
|
663 |
* @access private
|
664 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
665 |
*/
|
666 |
public static function _sitemaps_metabox_notify_tab() {
|
667 |
-
\
|
668 |
}
|
669 |
|
670 |
/**
|
671 |
-
* Sitemaps
|
672 |
*
|
673 |
* @since 4.0.0
|
674 |
* @access private
|
675 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
676 |
*/
|
677 |
public static function _sitemaps_metabox_style_tab() {
|
678 |
-
\
|
679 |
}
|
680 |
|
681 |
/**
|
682 |
-
* Feed
|
683 |
*
|
684 |
* @since 4.0.0
|
685 |
* @access private
|
686 |
-
*
|
687 |
-
* @param \WP_Post|null $post The current post object.
|
688 |
-
* @param array $args The navigation tabs args.
|
689 |
*/
|
690 |
-
public static function _feed_metabox(
|
691 |
/**
|
692 |
* @since 2.5.2
|
693 |
*/
|
694 |
\do_action( 'the_seo_framework_feed_metabox_before' );
|
695 |
-
\
|
696 |
/**
|
697 |
* @since 2.5.2
|
698 |
*/
|
@@ -700,20 +733,17 @@ final class SeoSettings {
|
|
700 |
}
|
701 |
|
702 |
/**
|
703 |
-
* Schema
|
704 |
*
|
705 |
* @since 4.0.0
|
706 |
* @access private
|
707 |
-
*
|
708 |
-
* @param \WP_Post|null $post The current post object.
|
709 |
-
* @param array $args The navigation tabs args.
|
710 |
*/
|
711 |
-
public static function _schema_metabox(
|
712 |
/**
|
713 |
* @since 2.6.0
|
714 |
*/
|
715 |
\do_action( 'the_seo_framework_schema_metabox_before' );
|
716 |
-
\
|
717 |
/**
|
718 |
* @since 2.6.0
|
719 |
*/
|
@@ -721,24 +751,24 @@ final class SeoSettings {
|
|
721 |
}
|
722 |
|
723 |
/**
|
724 |
-
* Schema
|
725 |
*
|
726 |
* @since 4.0.0
|
727 |
* @access private
|
728 |
* @see static::schema_metabox() Callback for Schema.org Settings box.
|
729 |
*/
|
730 |
public static function _schema_metabox_structure_tab() {
|
731 |
-
\
|
732 |
}
|
733 |
|
734 |
/**
|
735 |
-
* Schema
|
736 |
*
|
737 |
* @since 4.0.0
|
738 |
* @access private
|
739 |
* @see static::schema_metabox() Callback for Schema.org Settings box.
|
740 |
*/
|
741 |
public static function _schema_metabox_presence_tab() {
|
742 |
-
\
|
743 |
}
|
744 |
}
|
45 |
*/
|
46 |
public static function _register_seo_settings_meta_boxes() {
|
47 |
|
48 |
+
$tsf = \tsf();
|
49 |
+
|
50 |
/**
|
51 |
* Various metabox filters.
|
52 |
* Set any to false if you wish the meta box to be removed.
|
53 |
*
|
54 |
* @since 2.2.4
|
55 |
* @since 2.8.0 Added `the_seo_framework_general_metabox` filter.
|
56 |
+
* @since 4.2.0 Added `the_seo_framework_post_type_archive_metabox` filter.
|
57 |
*/
|
58 |
+
$general = (bool) \apply_filters( 'the_seo_framework_general_metabox', true );
|
59 |
+
$title = (bool) \apply_filters( 'the_seo_framework_title_metabox', true );
|
60 |
+
$description = (bool) \apply_filters( 'the_seo_framework_description_metabox', true );
|
61 |
+
$robots = (bool) \apply_filters( 'the_seo_framework_robots_metabox', true );
|
62 |
+
$home = (bool) \apply_filters( 'the_seo_framework_home_metabox', true );
|
63 |
+
$post_type_archive = (bool) \apply_filters( 'the_seo_framework_post_type_archive_metabox', true );
|
64 |
+
$social = (bool) \apply_filters( 'the_seo_framework_social_metabox', true );
|
65 |
+
$schema = (bool) \apply_filters( 'the_seo_framework_schema_metabox', true );
|
66 |
+
$webmaster = (bool) \apply_filters( 'the_seo_framework_webmaster_metabox', true );
|
67 |
+
$sitemap = (bool) \apply_filters( 'the_seo_framework_sitemap_metabox', true );
|
68 |
+
$feed = (bool) \apply_filters( 'the_seo_framework_feed_metabox', true );
|
69 |
+
|
70 |
+
$settings_page_hook = $tsf->seo_settings_page_hook;
|
71 |
+
|
72 |
+
$class = static::class;
|
73 |
|
74 |
// General Meta Box
|
75 |
if ( $general )
|
76 |
\add_meta_box(
|
77 |
'autodescription-general-settings',
|
78 |
\esc_html__( 'General Settings', 'autodescription' ),
|
79 |
+
"$class::_general_metabox",
|
80 |
$settings_page_hook,
|
81 |
+
'main'
|
|
|
82 |
);
|
83 |
|
84 |
// Title Meta Box
|
86 |
\add_meta_box(
|
87 |
'autodescription-title-settings',
|
88 |
\esc_html__( 'Title Settings', 'autodescription' ),
|
89 |
+
"$class::_title_metabox",
|
90 |
$settings_page_hook,
|
91 |
+
'main'
|
|
|
92 |
);
|
93 |
|
94 |
// Description Meta Box
|
96 |
\add_meta_box(
|
97 |
'autodescription-description-settings',
|
98 |
\esc_html__( 'Description Meta Settings', 'autodescription' ),
|
99 |
+
"$class::_description_metabox",
|
100 |
$settings_page_hook,
|
101 |
+
'main'
|
|
|
102 |
);
|
103 |
|
104 |
// Homepage Meta Box
|
106 |
\add_meta_box(
|
107 |
'autodescription-homepage-settings',
|
108 |
\esc_html__( 'Homepage Settings', 'autodescription' ),
|
109 |
+
"$class::_homepage_metabox",
|
110 |
$settings_page_hook,
|
111 |
+
'main'
|
112 |
+
);
|
113 |
+
|
114 |
+
if ( $post_type_archive && $tsf->get_public_post_type_archives() )
|
115 |
+
\add_meta_box(
|
116 |
+
'autodescription-post-type-archive-settings',
|
117 |
+
\esc_html__( 'Post Type Archive Settings', 'autodescription' ),
|
118 |
+
"$class::_post_type_archive_metabox",
|
119 |
+
$settings_page_hook,
|
120 |
+
'main'
|
121 |
);
|
122 |
|
123 |
// Social Meta Box
|
125 |
\add_meta_box(
|
126 |
'autodescription-social-settings',
|
127 |
\esc_html__( 'Social Meta Settings', 'autodescription' ),
|
128 |
+
"$class::_social_metabox",
|
129 |
$settings_page_hook,
|
130 |
+
'main'
|
|
|
131 |
);
|
132 |
|
133 |
// Schema Meta Box
|
135 |
\add_meta_box(
|
136 |
'autodescription-schema-settings',
|
137 |
\esc_html__( 'Schema.org Settings', 'autodescription' ),
|
138 |
+
"$class::_schema_metabox",
|
139 |
$settings_page_hook,
|
140 |
+
'main'
|
|
|
141 |
);
|
142 |
|
143 |
// Robots Meta Box
|
145 |
\add_meta_box(
|
146 |
'autodescription-robots-settings',
|
147 |
\esc_html__( 'Robots Meta Settings', 'autodescription' ),
|
148 |
+
"$class::_robots_metabox",
|
149 |
$settings_page_hook,
|
150 |
+
'main'
|
|
|
151 |
);
|
152 |
|
153 |
// Webmaster Meta Box
|
155 |
\add_meta_box(
|
156 |
'autodescription-webmaster-settings',
|
157 |
\esc_html__( 'Webmaster Meta Settings', 'autodescription' ),
|
158 |
+
"$class::_webmaster_metabox",
|
159 |
$settings_page_hook,
|
160 |
+
'main'
|
|
|
161 |
);
|
162 |
|
163 |
// Sitemaps Meta Box
|
165 |
\add_meta_box(
|
166 |
'autodescription-sitemap-settings',
|
167 |
\esc_html__( 'Sitemap Settings', 'autodescription' ),
|
168 |
+
"$class::_sitemaps_metabox",
|
169 |
$settings_page_hook,
|
170 |
+
'main'
|
|
|
171 |
);
|
172 |
|
173 |
// Feed Meta Box
|
175 |
\add_meta_box(
|
176 |
'autodescription-feed-settings',
|
177 |
\esc_html__( 'Feed Settings', 'autodescription' ),
|
178 |
+
"$class::_feed_metabox",
|
179 |
$settings_page_hook,
|
180 |
+
'main'
|
|
|
181 |
);
|
182 |
}
|
183 |
|
201 |
* @param bool $use_tabs Whether to output tabs, only works when $tabs count is greater than 1.
|
202 |
*/
|
203 |
public static function _nav_tab_wrapper( $id, $tabs = [], $use_tabs = true ) { // phpcs:ignore,VariableAnalysis
|
204 |
+
$tsf = \tsf();
|
205 |
+
$tsf->get_view( 'settings/wrap-nav', get_defined_vars() );
|
206 |
+
$tsf->get_view( 'settings/wrap-content', get_defined_vars() );
|
207 |
}
|
208 |
|
209 |
/**
|
217 |
* @since 3.0.0
|
218 |
*/
|
219 |
\do_action( 'the_seo_framework_pre_seo_settings' );
|
220 |
+
\tsf()->get_view( 'settings/wrap' );
|
221 |
/**
|
222 |
* @since 3.0.0
|
223 |
*/
|
231 |
* @access private
|
232 |
*/
|
233 |
public static function _output_columns() {
|
234 |
+
\tsf()->get_view( 'settings/columns' );
|
235 |
}
|
236 |
|
237 |
/**
|
239 |
*
|
240 |
* @since 4.0.0
|
241 |
* @access private
|
|
|
|
|
|
|
242 |
*/
|
243 |
+
public static function _general_metabox() {
|
244 |
/**
|
245 |
* @since 2.8.0
|
246 |
*/
|
247 |
\do_action( 'the_seo_framework_general_metabox_before' );
|
248 |
+
\tsf()->get_view( 'settings/metaboxes/general' );
|
249 |
/**
|
250 |
* @since 2.8.0
|
251 |
*/
|
260 |
* @see static::general_metabox() : Callback for General Settings box.
|
261 |
*/
|
262 |
public static function _general_metabox_general_tab() {
|
263 |
+
\tsf()->get_view( 'settings/metaboxes/general', [], 'general_tab' );
|
264 |
}
|
265 |
|
266 |
/**
|
271 |
* @see static::general_metabox() : Callback for General Settings box.
|
272 |
*/
|
273 |
public static function _general_metabox_layout_tab() {
|
274 |
+
\tsf()->get_view( 'settings/metaboxes/general', [], 'layout_tab' );
|
275 |
}
|
276 |
|
277 |
/**
|
282 |
* @see static::general_metabox() : Callback for General Settings box.
|
283 |
*/
|
284 |
public static function _general_metabox_performance_tab() {
|
285 |
+
\tsf()->get_view( 'settings/metaboxes/general', [], 'performance_tab' );
|
286 |
}
|
287 |
|
288 |
/**
|
293 |
* @see static::general_metabox() : Callback for General Settings box.
|
294 |
*/
|
295 |
public static function _general_metabox_canonical_tab() {
|
296 |
+
\tsf()->get_view( 'settings/metaboxes/general', [], 'canonical_tab' );
|
297 |
}
|
298 |
|
299 |
/**
|
304 |
* @see static::general_metabox() : Callback for General Settings box.
|
305 |
*/
|
306 |
public static function _general_metabox_timestamps_tab() {
|
307 |
+
\tsf()->get_view( 'settings/metaboxes/general', [], 'timestamps_tab' );
|
308 |
}
|
309 |
|
310 |
/**
|
315 |
* @see static::general_metabox() : Callback for General Settings box.
|
316 |
*/
|
317 |
public static function _general_metabox_exclusions_tab() {
|
318 |
+
\tsf()->get_view( 'settings/metaboxes/general', [], 'exclusions_tab' );
|
319 |
}
|
320 |
|
321 |
/**
|
323 |
*
|
324 |
* @since 4.0.0
|
325 |
* @access private
|
|
|
|
|
|
|
326 |
*/
|
327 |
+
public static function _title_metabox() {
|
328 |
/**
|
329 |
* @since 2.5.0 or earlier.
|
330 |
*/
|
331 |
\do_action( 'the_seo_framework_title_metabox_before' );
|
332 |
+
\tsf()->get_view( 'settings/metaboxes/title' );
|
333 |
/**
|
334 |
* @since 2.5.0 or earlier.
|
335 |
*/
|
344 |
* @see static::title_metabox() : Callback for Title Settings box.
|
345 |
*/
|
346 |
public static function _title_metabox_general_tab() {
|
347 |
+
\tsf()->get_view( 'settings/metaboxes/title', [], 'general_tab' );
|
348 |
}
|
349 |
|
350 |
/**
|
357 |
* @param array $args The variables to pass to the metabox tab.
|
358 |
*/
|
359 |
public static function _title_metabox_additions_tab( $args ) {
|
360 |
+
\tsf()->get_view( 'settings/metaboxes/title', $args, 'additions_tab' );
|
361 |
}
|
362 |
|
363 |
/**
|
370 |
* @param array $args The variables to pass to the metabox tab.
|
371 |
*/
|
372 |
public static function _title_metabox_prefixes_tab( $args ) {
|
373 |
+
\tsf()->get_view( 'settings/metaboxes/title', $args, 'prefixes_tab' );
|
374 |
}
|
375 |
|
376 |
/**
|
378 |
*
|
379 |
* @since 4.0.0
|
380 |
* @access private
|
|
|
|
|
|
|
381 |
*/
|
382 |
+
public static function _description_metabox() {
|
383 |
/**
|
384 |
* @since 2.5.0 or earlier.
|
385 |
*/
|
386 |
\do_action( 'the_seo_framework_description_metabox_before' );
|
387 |
+
\tsf()->get_view( 'settings/metaboxes/description' );
|
388 |
/**
|
389 |
* @since 2.5.0 or earlier.
|
390 |
*/
|
396 |
*
|
397 |
* @since 4.0.0
|
398 |
* @access private
|
|
|
|
|
|
|
399 |
*/
|
400 |
+
public static function _robots_metabox() {
|
401 |
/**
|
402 |
* @since 2.5.0 or earlier.
|
403 |
*/
|
404 |
\do_action( 'the_seo_framework_robots_metabox_before' );
|
405 |
+
\tsf()->get_view( 'settings/metaboxes/robots' );
|
406 |
/**
|
407 |
* @since 2.5.0 or earlier.
|
408 |
*/
|
410 |
}
|
411 |
|
412 |
/**
|
413 |
+
* Robots Meta Box General Tab output.
|
414 |
*
|
415 |
* @since 4.0.0
|
416 |
* @access private
|
417 |
* @see static::robots_metabox() Callback for Robots Settings box.
|
418 |
*/
|
419 |
public static function _robots_metabox_general_tab() {
|
420 |
+
\tsf()->get_view( 'settings/metaboxes/robots', [], 'general_tab' );
|
421 |
}
|
422 |
|
423 |
/**
|
424 |
+
* Robots Meta Box "No-: Index/Follow/Archive" Tab output.
|
425 |
*
|
426 |
* @since 4.0.0
|
427 |
* @access private
|
430 |
* @param array $args The variables to pass to the metabox tab.
|
431 |
*/
|
432 |
public static function _robots_metabox_no_tab( $args ) {
|
433 |
+
\tsf()->get_view( 'settings/metaboxes/robots', $args, 'no_tab' );
|
434 |
}
|
435 |
|
436 |
/**
|
438 |
*
|
439 |
* @since 4.0.0
|
440 |
* @access private
|
|
|
|
|
|
|
441 |
*/
|
442 |
+
public static function _homepage_metabox() {
|
443 |
/**
|
444 |
* @since 2.5.0 or earlier.
|
445 |
*/
|
446 |
\do_action( 'the_seo_framework_homepage_metabox_before' );
|
447 |
+
\tsf()->get_view( 'settings/metaboxes/homepage' );
|
448 |
/**
|
449 |
* @since 2.5.0 or earlier.
|
450 |
*/
|
452 |
}
|
453 |
|
454 |
/**
|
455 |
+
* Homepage meta box General Tab Output.
|
456 |
*
|
457 |
* @since 4.0.0
|
458 |
* @access private
|
459 |
* @see static::homepage_metabox() Callback for Homepage Settings box.
|
460 |
*/
|
461 |
public static function _homepage_metabox_general_tab() {
|
462 |
+
\tsf()->get_view( 'settings/metaboxes/homepage', [], 'general_tab' );
|
463 |
}
|
464 |
|
465 |
/**
|
466 |
+
* Homepage meta box Additions Tab Output.
|
467 |
*
|
468 |
* @since 4.0.0
|
469 |
* @access private
|
470 |
* @see static::homepage_metabox() Callback for Homepage Settings box.
|
471 |
*/
|
472 |
public static function _homepage_metabox_additions_tab() {
|
473 |
+
\tsf()->get_view( 'settings/metaboxes/homepage', [], 'additions_tab' );
|
474 |
}
|
475 |
|
476 |
/**
|
477 |
+
* Homepage meta box Robots Tab Output
|
478 |
*
|
479 |
* @since 4.0.0
|
480 |
* @access private
|
481 |
* @see static::homepage_metabox() Callback for Homepage Settings box.
|
482 |
*/
|
483 |
public static function _homepage_metabox_robots_tab() {
|
484 |
+
\tsf()->get_view( 'settings/metaboxes/homepage', [], 'robots_tab' );
|
485 |
}
|
486 |
|
487 |
/**
|
488 |
+
* Homepage meta box Social Tab Output
|
489 |
*
|
490 |
* @since 4.0.0
|
491 |
* @access private
|
492 |
* @see static::homepage_metabox() Callback for Homepage Settings box.
|
493 |
*/
|
494 |
public static function _homepage_metabox_social_tab() {
|
495 |
+
\tsf()->get_view( 'settings/metaboxes/homepage', [], 'social_tab' );
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Post Type Archive meta box on the Site SEO Settings page.
|
500 |
+
*
|
501 |
+
* @since 4.2.0
|
502 |
+
* @access private
|
503 |
+
*/
|
504 |
+
public static function _post_type_archive_metabox() {
|
505 |
+
/**
|
506 |
+
* @since 4.2.0
|
507 |
+
*/
|
508 |
+
\do_action( 'the_seo_framework_post_type_archive_before' );
|
509 |
+
\tsf()->get_view( 'settings/metaboxes/post-type-archive' );
|
510 |
+
/**
|
511 |
+
* @since 4.2.0
|
512 |
+
*/
|
513 |
+
\do_action( 'the_seo_framework_post_type_archive_after' );
|
514 |
+
}
|
515 |
+
|
516 |
+
/**
|
517 |
+
* Social Meta Box General Tab output.
|
518 |
+
*
|
519 |
+
* @since 4.2.0
|
520 |
+
* @access private
|
521 |
+
*
|
522 |
+
* @param array $args The variables to pass to the metabox tab.
|
523 |
+
*/
|
524 |
+
public static function _post_type_archive_metabox_general_tab( $args ) {
|
525 |
+
\tsf()->get_view( 'settings/metaboxes/post-type-archive', $args, 'general_tab' );
|
526 |
+
}
|
527 |
+
|
528 |
+
/**
|
529 |
+
* Post Type Archive meta box on the Site SEO Settings page.
|
530 |
+
*
|
531 |
+
* @since 4.2.0
|
532 |
+
* @access private
|
533 |
+
*
|
534 |
+
* @param array $args The variables to pass to the metabox tab.
|
535 |
+
*/
|
536 |
+
public static function _post_type_archive_metabox_social_tab( $args ) {
|
537 |
+
\tsf()->get_view( 'settings/metaboxes/post-type-archive', $args, 'social_tab' );
|
538 |
+
}
|
539 |
+
|
540 |
+
/**
|
541 |
+
* Post Type Archive meta box on the Site SEO Settings page.
|
542 |
+
*
|
543 |
+
* @since 4.2.0
|
544 |
+
* @access private
|
545 |
+
*
|
546 |
+
* @param array $args The variables to pass to the metabox tab.
|
547 |
+
*/
|
548 |
+
public static function _post_type_archive_metabox_visibility_tab( $args ) {
|
549 |
+
\tsf()->get_view( 'settings/metaboxes/post-type-archive', $args, 'visibility_tab' );
|
550 |
}
|
551 |
|
552 |
/**
|
554 |
*
|
555 |
* @since 4.0.0
|
556 |
* @access private
|
|
|
|
|
|
|
557 |
*/
|
558 |
+
public static function _social_metabox() {
|
559 |
/**
|
560 |
* @since 2.5.0 or earlier.
|
561 |
*/
|
562 |
\do_action( 'the_seo_framework_social_metabox_before' );
|
563 |
+
\tsf()->get_view( 'settings/metaboxes/social' );
|
564 |
/**
|
565 |
* @since 2.5.0 or earlier.
|
566 |
*/
|
568 |
}
|
569 |
|
570 |
/**
|
571 |
+
* Social Meta Box General Tab output.
|
572 |
*
|
573 |
* @since 4.0.0
|
574 |
* @access private
|
575 |
* @see static::social_metabox() Callback for Social Settings box.
|
576 |
*/
|
577 |
public static function _social_metabox_general_tab() {
|
578 |
+
\tsf()->get_view( 'settings/metaboxes/social', [], 'general_tab' );
|
579 |
}
|
580 |
|
581 |
/**
|
582 |
+
* Social Meta Box Facebook Tab output.
|
583 |
*
|
584 |
* @since 4.0.0
|
585 |
* @access private
|
586 |
* @see static::social_metabox() Callback for Social Settings box.
|
587 |
*/
|
588 |
public static function _social_metabox_facebook_tab() {
|
589 |
+
\tsf()->get_view( 'settings/metaboxes/social', [], 'facebook_tab' );
|
590 |
}
|
591 |
|
592 |
/**
|
593 |
+
* Social Meta Box Twitter Tab output.
|
594 |
*
|
595 |
* @since 4.0.0
|
596 |
* @access private
|
597 |
* @see static::social_metabox() Callback for Social Settings box.
|
598 |
*/
|
599 |
public static function _social_metabox_twitter_tab() {
|
600 |
+
\tsf()->get_view( 'settings/metaboxes/social', [], 'twitter_tab' );
|
601 |
}
|
602 |
|
603 |
/**
|
604 |
+
* Social Meta Box oEmbed Tab output.
|
605 |
*
|
606 |
* @since 4.0.5
|
607 |
* @access private
|
608 |
* @see static::social_metabox() Callback for Social Settings box.
|
609 |
*/
|
610 |
public static function _social_metabox_oembed_tab() {
|
611 |
+
\tsf()->get_view( 'settings/metaboxes/social', [], 'oembed_tab' );
|
612 |
}
|
613 |
|
614 |
/**
|
615 |
+
* Social Meta Box PostDates Tab output.
|
616 |
*
|
617 |
* @since 4.0.0
|
618 |
* @access private
|
619 |
* @see static::social_metabox() Callback for Social Settings box.
|
620 |
*/
|
621 |
public static function _social_metabox_postdates_tab() {
|
622 |
+
\tsf()->get_view( 'settings/metaboxes/social', [], 'postdates_tab' );
|
623 |
}
|
624 |
|
625 |
/**
|
627 |
*
|
628 |
* @since 4.0.0
|
629 |
* @access private
|
|
|
|
|
|
|
630 |
*/
|
631 |
+
public static function _webmaster_metabox() {
|
632 |
/**
|
633 |
* @since 2.5.0 or earlier.
|
634 |
*/
|
635 |
\do_action( 'the_seo_framework_webmaster_metabox_before' );
|
636 |
+
\tsf()->get_view( 'settings/metaboxes/webmaster' );
|
637 |
/**
|
638 |
* @since 2.5.0 or earlier.
|
639 |
*/
|
646 |
* @since 4.0.0
|
647 |
* @access private
|
648 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
|
|
|
|
|
|
649 |
*/
|
650 |
+
public static function _sitemaps_metabox() {
|
651 |
/**
|
652 |
* @since 2.5.0 or earlier.
|
653 |
*/
|
654 |
\do_action( 'the_seo_framework_sitemaps_metabox_before' );
|
655 |
+
\tsf()->get_view( 'settings/metaboxes/sitemaps' );
|
656 |
/**
|
657 |
* @since 2.5.0 or earlier.
|
658 |
*/
|
660 |
}
|
661 |
|
662 |
/**
|
663 |
+
* Sitemaps Meta Box General Tab output.
|
664 |
*
|
665 |
* @since 4.0.0
|
666 |
* @access private
|
667 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
668 |
*/
|
669 |
public static function _sitemaps_metabox_general_tab() {
|
670 |
+
\tsf()->get_view( 'settings/metaboxes/sitemaps', [], 'general_tab' );
|
671 |
}
|
672 |
|
673 |
/**
|
674 |
+
* Sitemaps Meta Box Robots Tab output.
|
675 |
*
|
676 |
* @since 4.0.0
|
677 |
* @access private
|
678 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
679 |
*/
|
680 |
public static function _sitemaps_metabox_robots_tab() {
|
681 |
+
\tsf()->get_view( 'settings/metaboxes/sitemaps', [], 'robots_tab' );
|
682 |
}
|
683 |
|
684 |
/**
|
685 |
+
* Sitemaps Meta Box Metadata Tab output.
|
686 |
*
|
687 |
* @since 4.0.0
|
688 |
* @access private
|
689 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
690 |
*/
|
691 |
public static function _sitemaps_metabox_metadata_tab() {
|
692 |
+
\tsf()->get_view( 'settings/metaboxes/sitemaps', [], 'metadata_tab' );
|
693 |
}
|
694 |
|
695 |
/**
|
696 |
+
* Sitemaps Meta Box Notify Tab output.
|
697 |
*
|
698 |
* @since 4.0.0
|
699 |
* @access private
|
700 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
701 |
*/
|
702 |
public static function _sitemaps_metabox_notify_tab() {
|
703 |
+
\tsf()->get_view( 'settings/metaboxes/sitemaps', [], 'notify_tab' );
|
704 |
}
|
705 |
|
706 |
/**
|
707 |
+
* Sitemaps Meta Box Style Tab output.
|
708 |
*
|
709 |
* @since 4.0.0
|
710 |
* @access private
|
711 |
* @see static::sitemaps_metabox() Callback for Sitemaps Settings box.
|
712 |
*/
|
713 |
public static function _sitemaps_metabox_style_tab() {
|
714 |
+
\tsf()->get_view( 'settings/metaboxes/sitemaps', [], 'style_tab' );
|
715 |
}
|
716 |
|
717 |
/**
|
718 |
+
* Feed meta box on the Site SEO Settings page.
|
719 |
*
|
720 |
* @since 4.0.0
|
721 |
* @access private
|
|
|
|
|
|
|
722 |
*/
|
723 |
+
public static function _feed_metabox() {
|
724 |
/**
|
725 |
* @since 2.5.2
|
726 |
*/
|
727 |
\do_action( 'the_seo_framework_feed_metabox_before' );
|
728 |
+
\tsf()->get_view( 'settings/metaboxes/feed' );
|
729 |
/**
|
730 |
* @since 2.5.2
|
731 |
*/
|
733 |
}
|
734 |
|
735 |
/**
|
736 |
+
* Schema meta box on the Site SEO Settings page.
|
737 |
*
|
738 |
* @since 4.0.0
|
739 |
* @access private
|
|
|
|
|
|
|
740 |
*/
|
741 |
+
public static function _schema_metabox() {
|
742 |
/**
|
743 |
* @since 2.6.0
|
744 |
*/
|
745 |
\do_action( 'the_seo_framework_schema_metabox_before' );
|
746 |
+
\tsf()->get_view( 'settings/metaboxes/schema' );
|
747 |
/**
|
748 |
* @since 2.6.0
|
749 |
*/
|
751 |
}
|
752 |
|
753 |
/**
|
754 |
+
* Schema Meta Box Structure Tab output.
|
755 |
*
|
756 |
* @since 4.0.0
|
757 |
* @access private
|
758 |
* @see static::schema_metabox() Callback for Schema.org Settings box.
|
759 |
*/
|
760 |
public static function _schema_metabox_structure_tab() {
|
761 |
+
\tsf()->get_view( 'settings/metaboxes/schema', [], 'structure_tab' );
|
762 |
}
|
763 |
|
764 |
/**
|
765 |
+
* Schema Meta Box Presence Tab output.
|
766 |
*
|
767 |
* @since 4.0.0
|
768 |
* @access private
|
769 |
* @see static::schema_metabox() Callback for Schema.org Settings box.
|
770 |
*/
|
771 |
public static function _schema_metabox_presence_tab() {
|
772 |
+
\tsf()->get_view( 'settings/metaboxes/schema', [], 'presence_tab' );
|
773 |
}
|
774 |
}
|
@@ -25,16 +25,9 @@ namespace The_SEO_Framework\Bridges;
|
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
*
|
32 |
-
* @see EOF. Because of the autoloader and (future) trait calling, we can't do it before the class is read.
|
33 |
-
* @link https://bugs.php.net/bug.php?id=75771
|
34 |
-
*/
|
35 |
-
$_load_sitemap_class = function() {
|
36 |
-
// phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
|
37 |
-
new Sitemap();
|
38 |
};
|
39 |
|
40 |
/**
|
@@ -65,7 +58,7 @@ final class Sitemap {
|
|
65 |
* @return \The_SEO_Framework\Bridges\Sitemap $instance
|
66 |
*/
|
67 |
public static function get_instance() {
|
68 |
-
return static::$instance;
|
69 |
}
|
70 |
|
71 |
/**
|
@@ -76,7 +69,9 @@ final class Sitemap {
|
|
76 |
*
|
77 |
* @since 4.0.0
|
78 |
*/
|
79 |
-
public static function prepare() {
|
|
|
|
|
80 |
|
81 |
/**
|
82 |
* The constructor. Can't be instantiated externally from this file.
|
@@ -93,8 +88,7 @@ final class Sitemap {
|
|
93 |
static $count = 0;
|
94 |
0 === $count++ or \wp_die( 'Don\'t instance <code>' . __CLASS__ . '</code>.' );
|
95 |
|
96 |
-
static::$tsf
|
97 |
-
static::$instance = &$this;
|
98 |
}
|
99 |
|
100 |
/**
|
@@ -188,52 +182,53 @@ final class Sitemap {
|
|
188 |
* @return array The sitemap endpoints with their callbacks.
|
189 |
*/
|
190 |
public function get_sitemap_endpoint_list() {
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
|
|
237 |
);
|
238 |
}
|
239 |
|
@@ -289,7 +284,7 @@ final class Sitemap {
|
|
289 |
|
290 |
if ( ! isset( $ep_list[ $sitemap_id ] ) ) return false;
|
291 |
|
292 |
-
$lock_id =
|
293 |
|
294 |
return static::$tsf->generate_cache_key( 0, '', 'sitemap_lock' ) . "_{$lock_id}";
|
295 |
}
|
@@ -409,6 +404,8 @@ final class Sitemap {
|
|
409 |
header( 'Cache-Control: max-age=1800', true );
|
410 |
}
|
411 |
|
|
|
|
|
412 |
static::$tsf->get_view( 'sitemap/xsl-stylesheet' );
|
413 |
exit;
|
414 |
}
|
@@ -455,20 +452,15 @@ final class Sitemap {
|
|
455 |
*/
|
456 |
$schemas = (array) \apply_filters( 'the_seo_framework_sitemap_schemas', $schemas );
|
457 |
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
$urlset .= implode( ' ', $values );
|
463 |
-
} else {
|
464 |
-
$urlset .= $values;
|
465 |
}
|
466 |
-
|
467 |
-
}
|
468 |
-
$urlset .= '>';
|
469 |
|
470 |
-
// phpcs:ignore, WordPress.Security.EscapeOutput -- Output is
|
471 |
-
|
472 |
}
|
473 |
|
474 |
/**
|
@@ -495,7 +487,13 @@ final class Sitemap {
|
|
495 |
*/
|
496 |
return \apply_filters(
|
497 |
'the_seo_framework_sitemap_base_path',
|
498 |
-
rtrim(
|
|
|
|
|
|
|
|
|
|
|
|
|
499 |
);
|
500 |
}
|
501 |
|
@@ -624,16 +622,14 @@ final class Sitemap {
|
|
624 |
* @since 2.8.0 Renamed from clean_up_globals().
|
625 |
* @since 4.0.0 1. Moved to \The_SEO_Framework\Bridges\Sitemap
|
626 |
* 2. Renamed from clean_up_globals_for_sitemap()
|
|
|
627 |
*
|
628 |
* @param bool $get_freed_memory Whether to return the freed memory in bytes.
|
629 |
* @return int $freed_memory in bytes
|
630 |
*/
|
631 |
private function clean_up_globals( $get_freed_memory = false ) {
|
632 |
|
633 |
-
|
634 |
-
|
635 |
-
if ( $get_freed_memory )
|
636 |
-
return $freed_memory;
|
637 |
|
638 |
$memory = memory_get_usage();
|
639 |
|
@@ -667,8 +663,6 @@ final class Sitemap {
|
|
667 |
// This one requires to be an array for wp_texturize(). There's an API, let's use it:
|
668 |
\remove_all_shortcodes();
|
669 |
|
670 |
-
|
671 |
}
|
672 |
}
|
673 |
-
|
674 |
-
$_load_sitemap_class();
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
+
use function \The_SEO_Framework\{
|
29 |
+
memo,
|
30 |
+
umemo,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
};
|
32 |
|
33 |
/**
|
58 |
* @return \The_SEO_Framework\Bridges\Sitemap $instance
|
59 |
*/
|
60 |
public static function get_instance() {
|
61 |
+
return static::$instance ?? ( static::$instance = new static );
|
62 |
}
|
63 |
|
64 |
/**
|
69 |
*
|
70 |
* @since 4.0.0
|
71 |
*/
|
72 |
+
public static function prepare() {
|
73 |
+
static::get_instance();
|
74 |
+
}
|
75 |
|
76 |
/**
|
77 |
* The constructor. Can't be instantiated externally from this file.
|
88 |
static $count = 0;
|
89 |
0 === $count++ or \wp_die( 'Don\'t instance <code>' . __CLASS__ . '</code>.' );
|
90 |
|
91 |
+
static::$tsf = \tsf();
|
|
|
92 |
}
|
93 |
|
94 |
/**
|
182 |
* @return array The sitemap endpoints with their callbacks.
|
183 |
*/
|
184 |
public function get_sitemap_endpoint_list() {
|
185 |
+
return memo() ?? memo(
|
186 |
+
/**
|
187 |
+
* @since 4.0.0
|
188 |
+
* @since 4.0.2 Made the endpoints' regex case-insensitive.
|
189 |
+
* @link Example: https://github.com/sybrew/tsf-term-sitemap
|
190 |
+
* @param array $list The endpoints: {
|
191 |
+
* 'id' => array: {
|
192 |
+
* 'cache_id' => string Optional. The cache key to use for locking. Defaults to index 'id'.
|
193 |
+
* 'endpoint' => string The expected "pretty" endpoint, meant for administrative display.
|
194 |
+
* 'epregex' => string The endpoint regex, following the home path regex.
|
195 |
+
* N.B. Be wary of case sensitivity. Append the i-flag.
|
196 |
+
* N.B. Trailing slashes will cause the match to fail.
|
197 |
+
* N.B. Use ASCII-endpoints only. Don't play with UTF-8 or translation strings.
|
198 |
+
* 'callback' => callable The callback for the sitemap output.
|
199 |
+
* Tip: You can pass arbitrary indexes. Prefix them with an underscore to ensure forward compatibility.
|
200 |
+
* Tip: In the callback, use
|
201 |
+
* `\The_SEO_Framework\Bridges\Sitemap::get_instance()->get_sitemap_endpoint_list()[$sitemap_id]`
|
202 |
+
* It returns the arguments you've passed in this filter; including your arbitrary indexes.
|
203 |
+
* 'robots' => bool Whether the endpoint should be mentioned in the robots.txt file.
|
204 |
+
* }
|
205 |
+
* }
|
206 |
+
*/
|
207 |
+
\apply_filters(
|
208 |
+
'the_seo_framework_sitemap_endpoint_list',
|
209 |
+
[
|
210 |
+
'base' => [
|
211 |
+
'lock_id' => 'base',
|
212 |
+
'endpoint' => 'sitemap.xml',
|
213 |
+
'regex' => '/^sitemap\.xml/i',
|
214 |
+
'callback' => [ static::class, 'output_base_sitemap' ],
|
215 |
+
'robots' => true,
|
216 |
+
],
|
217 |
+
'index' => [
|
218 |
+
'lock_id' => 'base',
|
219 |
+
'endpoint' => 'sitemap_index.xml',
|
220 |
+
'regex' => '/^sitemap_index\.xml/i',
|
221 |
+
'callback' => [ static::class, 'output_base_sitemap' ],
|
222 |
+
'robots' => false,
|
223 |
+
],
|
224 |
+
'xsl-stylesheet' => [
|
225 |
+
'endpoint' => 'sitemap.xsl',
|
226 |
+
'regex' => '/^sitemap\.xsl/i',
|
227 |
+
'callback' => [ static::class, 'output_stylesheet' ],
|
228 |
+
'robots' => false,
|
229 |
+
],
|
230 |
+
]
|
231 |
+
)
|
232 |
);
|
233 |
}
|
234 |
|
284 |
|
285 |
if ( ! isset( $ep_list[ $sitemap_id ] ) ) return false;
|
286 |
|
287 |
+
$lock_id = $ep_list[ $sitemap_id ]['lock_id'] ?? $sitemap_id;
|
288 |
|
289 |
return static::$tsf->generate_cache_key( 0, '', 'sitemap_lock' ) . "_{$lock_id}";
|
290 |
}
|
404 |
header( 'Cache-Control: max-age=1800', true );
|
405 |
}
|
406 |
|
407 |
+
\The_SEO_Framework\Interpreters\Sitemap_XSL::prepare();
|
408 |
+
|
409 |
static::$tsf->get_view( 'sitemap/xsl-stylesheet' );
|
410 |
exit;
|
411 |
}
|
452 |
*/
|
453 |
$schemas = (array) \apply_filters( 'the_seo_framework_sitemap_schemas', $schemas );
|
454 |
|
455 |
+
array_walk(
|
456 |
+
$schemas,
|
457 |
+
static function( &$schema, $key ) {
|
458 |
+
$schema = sprintf( '%s="%s"', $key, implode( ' ', (array) $schema ) );
|
|
|
|
|
|
|
459 |
}
|
460 |
+
);
|
|
|
|
|
461 |
|
462 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput -- Output is expected to be escaped.
|
463 |
+
printf( "<urlset %s>\n", implode( ' ', $schemas ) );
|
464 |
}
|
465 |
|
466 |
/**
|
487 |
*/
|
488 |
return \apply_filters(
|
489 |
'the_seo_framework_sitemap_base_path',
|
490 |
+
rtrim(
|
491 |
+
parse_url(
|
492 |
+
static::$tsf->get_home_url(),
|
493 |
+
PHP_URL_PATH
|
494 |
+
),
|
495 |
+
'/'
|
496 |
+
)
|
497 |
);
|
498 |
}
|
499 |
|
622 |
* @since 2.8.0 Renamed from clean_up_globals().
|
623 |
* @since 4.0.0 1. Moved to \The_SEO_Framework\Bridges\Sitemap
|
624 |
* 2. Renamed from clean_up_globals_for_sitemap()
|
625 |
+
* @since 4.2.0 Now always returns the freed memory.
|
626 |
*
|
627 |
* @param bool $get_freed_memory Whether to return the freed memory in bytes.
|
628 |
* @return int $freed_memory in bytes
|
629 |
*/
|
630 |
private function clean_up_globals( $get_freed_memory = false ) {
|
631 |
|
632 |
+
if ( $get_freed_memory ) return memo() ?? 0;
|
|
|
|
|
|
|
633 |
|
634 |
$memory = memory_get_usage();
|
635 |
|
663 |
// This one requires to be an array for wp_texturize(). There's an API, let's use it:
|
664 |
\remove_all_shortcodes();
|
665 |
|
666 |
+
return memo( $memory - memory_get_usage() );
|
667 |
}
|
668 |
}
|
|
|
|
@@ -60,7 +60,7 @@ final class TermSettings {
|
|
60 |
* @since 2.9.0
|
61 |
*/
|
62 |
\do_action( 'the_seo_framework_pre_tt_inpost_box' );
|
63 |
-
\
|
64 |
/**
|
65 |
* @since 2.9.0
|
66 |
*/
|
60 |
* @since 2.9.0
|
61 |
*/
|
62 |
\do_action( 'the_seo_framework_pre_tt_inpost_box' );
|
63 |
+
\tsf()->get_view( 'edit/seo-settings-tt', get_defined_vars() );
|
64 |
/**
|
65 |
* @since 2.9.0
|
66 |
*/
|
@@ -43,7 +43,7 @@ final class UserSettings {
|
|
43 |
*
|
44 |
* @param \WP_User $user WP_User object.
|
45 |
*/
|
46 |
-
public static function _prepare_setting_fields(
|
47 |
|
48 |
if ( ! $user->has_cap( THE_SEO_FRAMEWORK_AUTHOR_INFO_CAP ) ) return;
|
49 |
|
@@ -57,12 +57,12 @@ final class UserSettings {
|
|
57 |
*
|
58 |
* @param \WP_User $user WP_User object.
|
59 |
*/
|
60 |
-
private static function add_user_author_fields(
|
61 |
/**
|
62 |
* @since 4.1.4
|
63 |
*/
|
64 |
\do_action( 'the_seo_framework_before_author_fields' );
|
65 |
-
\
|
66 |
/**
|
67 |
* @since 4.1.4
|
68 |
*/
|
43 |
*
|
44 |
* @param \WP_User $user WP_User object.
|
45 |
*/
|
46 |
+
public static function _prepare_setting_fields( $user ) {
|
47 |
|
48 |
if ( ! $user->has_cap( THE_SEO_FRAMEWORK_AUTHOR_INFO_CAP ) ) return;
|
49 |
|
57 |
*
|
58 |
* @param \WP_User $user WP_User object.
|
59 |
*/
|
60 |
+
private static function add_user_author_fields( $user ) { // phpcs:ignore, VariableAnalysis.CodeAnalysis.VariableAnalysis -- get_defined_vars() is used later.
|
61 |
/**
|
62 |
* @since 4.1.4
|
63 |
*/
|
64 |
\do_action( 'the_seo_framework_before_author_fields' );
|
65 |
+
\tsf()->get_view( 'profile/author', get_defined_vars() );
|
66 |
/**
|
67 |
* @since 4.1.4
|
68 |
*/
|
@@ -32,11 +32,11 @@ namespace The_SEO_Framework\Builders\CoreSitemaps;
|
|
32 |
*
|
33 |
* @access private
|
34 |
*/
|
35 |
-
class Main extends \The_SEO_Framework\Builders\Sitemap {
|
36 |
|
37 |
/**
|
38 |
* @since 4.1.2
|
39 |
-
* @var \The_SEO_Framework\Builders\Sitemap
|
40 |
*/
|
41 |
private static $instance;
|
42 |
|
@@ -45,7 +45,7 @@ class Main extends \The_SEO_Framework\Builders\Sitemap {
|
|
45 |
*
|
46 |
* @since 4.1.2
|
47 |
*
|
48 |
-
* @return \The_SEO_Framework\Builders\Sitemap $instance
|
49 |
*/
|
50 |
public static function get_instance() {
|
51 |
return static::$instance ?: ( static::$instance = new static );
|
@@ -77,9 +77,8 @@ class Main extends \The_SEO_Framework\Builders\Sitemap {
|
|
77 |
*/
|
78 |
public static function _filter_add_provider( $provider, $name ) {
|
79 |
|
80 |
-
if ( ! $provider instanceof \WP_Sitemaps_Provider )
|
81 |
return $provider;
|
82 |
-
}
|
83 |
|
84 |
switch ( $name ) {
|
85 |
case 'posts':
|
@@ -91,10 +90,9 @@ class Main extends \The_SEO_Framework\Builders\Sitemap {
|
|
91 |
case 'users':
|
92 |
// This option is not reversible through means other than filters.
|
93 |
// static::$tsf isn't set, because static doesn't require instantiation here.
|
94 |
-
if ( \
|
95 |
$provider = null;
|
96 |
break;
|
97 |
-
|
98 |
default:
|
99 |
break;
|
100 |
}
|
32 |
*
|
33 |
* @access private
|
34 |
*/
|
35 |
+
class Main extends \The_SEO_Framework\Builders\Sitemap\Main {
|
36 |
|
37 |
/**
|
38 |
* @since 4.1.2
|
39 |
+
* @var \The_SEO_Framework\Builders\Sitemap\Main
|
40 |
*/
|
41 |
private static $instance;
|
42 |
|
45 |
*
|
46 |
* @since 4.1.2
|
47 |
*
|
48 |
+
* @return \The_SEO_Framework\Builders\Sitemap\Main $instance
|
49 |
*/
|
50 |
public static function get_instance() {
|
51 |
return static::$instance ?: ( static::$instance = new static );
|
77 |
*/
|
78 |
public static function _filter_add_provider( $provider, $name ) {
|
79 |
|
80 |
+
if ( ! $provider instanceof \WP_Sitemaps_Provider )
|
81 |
return $provider;
|
|
|
82 |
|
83 |
switch ( $name ) {
|
84 |
case 'posts':
|
90 |
case 'users':
|
91 |
// This option is not reversible through means other than filters.
|
92 |
// static::$tsf isn't set, because static doesn't require instantiation here.
|
93 |
+
if ( \tsf()->get_option( 'author_noindex' ) )
|
94 |
$provider = null;
|
95 |
break;
|
|
|
96 |
default:
|
97 |
break;
|
98 |
}
|
@@ -40,21 +40,26 @@ class Posts extends \WP_Sitemaps_Posts {
|
|
40 |
* Copied from parent and augmented slightly to return
|
41 |
*
|
42 |
* @since 4.1.2
|
|
|
|
|
43 |
* @source \WP_Sitemaps_Posts\get_url_list()
|
44 |
* @TEMP https://wordpress.slack.com/archives/CTKTGNJJW/p1604995479019700
|
45 |
* @link <https://core.trac.wordpress.org/ticket/51860>
|
|
|
46 |
*
|
47 |
-
* @param int $page_num
|
48 |
-
* @param string $
|
49 |
* @return array Array of URLs for a sitemap.
|
50 |
*/
|
51 |
-
public function get_url_list( $page_num, $
|
|
|
|
|
|
|
52 |
// Bail early if the queried post type is not supported.
|
53 |
$supported_types = $this->get_object_subtypes();
|
54 |
|
55 |
-
if ( ! isset( $supported_types[ $post_type ] ) )
|
56 |
return [];
|
57 |
-
}
|
58 |
|
59 |
/**
|
60 |
* Filters the posts URL list before it is generated.
|
@@ -75,9 +80,8 @@ class Posts extends \WP_Sitemaps_Posts {
|
|
75 |
$page_num
|
76 |
);
|
77 |
|
78 |
-
if ( null !== $url_list )
|
79 |
return $url_list;
|
80 |
-
}
|
81 |
|
82 |
$args = $this->get_posts_query_args( $post_type );
|
83 |
$args['paged'] = $page_num;
|
@@ -89,7 +93,7 @@ class Posts extends \WP_Sitemaps_Posts {
|
|
89 |
/**
|
90 |
* @augmented This differs from the inherented.
|
91 |
*/
|
92 |
-
$tsf = \
|
93 |
$main = Main::get_instance();
|
94 |
$show_modified = (bool) $tsf->get_option( 'sitemaps_modified' );
|
95 |
$timestamp_format = $tsf->get_timestamp_format();
|
@@ -122,16 +126,19 @@ class Posts extends \WP_Sitemaps_Posts {
|
|
122 |
'order' => 'DESC',
|
123 |
'offset' => 0,
|
124 |
],
|
125 |
-
|
126 |
);
|
127 |
|
128 |
-
$lastmod = isset( $latests_posts[0]->post_date_gmt ) ? $latests_posts[0]->post_date_gmt : '0000-00-00 00:00:00';
|
129 |
-
|
130 |
/**
|
131 |
* @since 4.1.1
|
132 |
* @param string $lastmod The lastmod time in SQL notation (`Y-m-d H:i:s`). Expected to explicitly follow that format!
|
133 |
*/
|
134 |
-
$sitemap_entry['lastmod'] = (string) \
|
|
|
|
|
|
|
|
|
|
|
135 |
}
|
136 |
|
137 |
/**
|
@@ -146,7 +153,7 @@ class Posts extends \WP_Sitemaps_Posts {
|
|
146 |
}
|
147 |
}
|
148 |
|
149 |
-
foreach ( $query->posts as $post )
|
150 |
/**
|
151 |
* @augmented This if-statement prevents including the post in the sitemap when conditions apply.
|
152 |
*/
|
@@ -161,9 +168,9 @@ class Posts extends \WP_Sitemaps_Posts {
|
|
161 |
* @augmented Adds lastmod to sitemap entry.
|
162 |
*/
|
163 |
if ( $show_modified ) {
|
164 |
-
$lastmod =
|
165 |
|
166 |
-
if (
|
167 |
$sitemap_entry['lastmod'] = $tsf->gmt2date( $timestamp_format, $lastmod );
|
168 |
}
|
169 |
|
@@ -178,7 +185,7 @@ class Posts extends \WP_Sitemaps_Posts {
|
|
178 |
*/
|
179 |
$sitemap_entry = \apply_filters( 'wp_sitemaps_posts_entry', $sitemap_entry, $post, $post_type );
|
180 |
$url_list[] = $sitemap_entry;
|
181 |
-
|
182 |
|
183 |
return $url_list;
|
184 |
}
|
40 |
* Copied from parent and augmented slightly to return
|
41 |
*
|
42 |
* @since 4.1.2
|
43 |
+
* @since 4.2.0 Renamed `$post_type` to `$object_subtype` to match parent class
|
44 |
+
* for PHP 8 named parameter support. (Backport WP 5.9)
|
45 |
* @source \WP_Sitemaps_Posts\get_url_list()
|
46 |
* @TEMP https://wordpress.slack.com/archives/CTKTGNJJW/p1604995479019700
|
47 |
* @link <https://core.trac.wordpress.org/ticket/51860>
|
48 |
+
* @link <https://core.trac.wordpress.org/changeset/51787>
|
49 |
*
|
50 |
+
* @param int $page_num Page of results.
|
51 |
+
* @param string $object_subtype Optional. Post type name. Default empty.
|
52 |
* @return array Array of URLs for a sitemap.
|
53 |
*/
|
54 |
+
public function get_url_list( $page_num, $object_subtype = '' ) {
|
55 |
+
// Restores the more descriptive, specific name for use within this method.
|
56 |
+
$post_type = $object_subtype;
|
57 |
+
|
58 |
// Bail early if the queried post type is not supported.
|
59 |
$supported_types = $this->get_object_subtypes();
|
60 |
|
61 |
+
if ( ! isset( $supported_types[ $post_type ] ) )
|
62 |
return [];
|
|
|
63 |
|
64 |
/**
|
65 |
* Filters the posts URL list before it is generated.
|
80 |
$page_num
|
81 |
);
|
82 |
|
83 |
+
if ( null !== $url_list )
|
84 |
return $url_list;
|
|
|
85 |
|
86 |
$args = $this->get_posts_query_args( $post_type );
|
87 |
$args['paged'] = $page_num;
|
93 |
/**
|
94 |
* @augmented This differs from the inherented.
|
95 |
*/
|
96 |
+
$tsf = \tsf();
|
97 |
$main = Main::get_instance();
|
98 |
$show_modified = (bool) $tsf->get_option( 'sitemaps_modified' );
|
99 |
$timestamp_format = $tsf->get_timestamp_format();
|
126 |
'order' => 'DESC',
|
127 |
'offset' => 0,
|
128 |
],
|
129 |
+
OBJECT
|
130 |
);
|
131 |
|
|
|
|
|
132 |
/**
|
133 |
* @since 4.1.1
|
134 |
* @param string $lastmod The lastmod time in SQL notation (`Y-m-d H:i:s`). Expected to explicitly follow that format!
|
135 |
*/
|
136 |
+
$sitemap_entry['lastmod'] = (string) \apply_filters_ref_array(
|
137 |
+
'the_seo_framework_sitemap_blog_lastmod',
|
138 |
+
[
|
139 |
+
$latests_posts[0]->post_date_gmt ?? '0000-00-00 00:00:00',
|
140 |
+
]
|
141 |
+
);
|
142 |
}
|
143 |
|
144 |
/**
|
153 |
}
|
154 |
}
|
155 |
|
156 |
+
foreach ( $query->posts as $post ) :
|
157 |
/**
|
158 |
* @augmented This if-statement prevents including the post in the sitemap when conditions apply.
|
159 |
*/
|
168 |
* @augmented Adds lastmod to sitemap entry.
|
169 |
*/
|
170 |
if ( $show_modified ) {
|
171 |
+
$lastmod = $post->post_modified_gmt ?? '0000-00-00 00:00:00';
|
172 |
|
173 |
+
if ( '0000-00-00 00:00:00' !== $lastmod )
|
174 |
$sitemap_entry['lastmod'] = $tsf->gmt2date( $timestamp_format, $lastmod );
|
175 |
}
|
176 |
|
185 |
*/
|
186 |
$sitemap_entry = \apply_filters( 'wp_sitemaps_posts_entry', $sitemap_entry, $post, $post_type );
|
187 |
$url_list[] = $sitemap_entry;
|
188 |
+
endforeach;
|
189 |
|
190 |
return $url_list;
|
191 |
}
|
@@ -38,22 +38,25 @@ class Taxonomies extends \WP_Sitemaps_Taxonomies {
|
|
38 |
* Gets a URL list for a taxonomy sitemap.
|
39 |
*
|
40 |
* @since 4.1.2
|
|
|
|
|
41 |
* @source \WP_Sitemaps_Taxonomies\get_url_list()
|
42 |
* @TEMP https://wordpress.slack.com/archives/CTKTGNJJW/p1604995479019700
|
43 |
* @link <https://core.trac.wordpress.org/ticket/51860>
|
|
|
44 |
*
|
45 |
-
* @param int $page_num
|
46 |
-
* @param string $
|
47 |
* @return array Array of URLs for a sitemap.
|
48 |
*/
|
49 |
-
public function get_url_list( $page_num, $
|
50 |
-
|
|
|
51 |
$supported_types = $this->get_object_subtypes();
|
52 |
|
53 |
// Bail early if the queried taxonomy is not supported.
|
54 |
-
if ( ! isset( $supported_types[ $taxonomy ] ) )
|
55 |
return [];
|
56 |
-
}
|
57 |
|
58 |
/**
|
59 |
* Filters the taxonomies URL list before it is generated.
|
@@ -74,9 +77,8 @@ class Taxonomies extends \WP_Sitemaps_Taxonomies {
|
|
74 |
$page_num
|
75 |
);
|
76 |
|
77 |
-
if ( null !== $url_list )
|
78 |
return $url_list;
|
79 |
-
}
|
80 |
|
81 |
$url_list = [];
|
82 |
|
@@ -90,37 +92,34 @@ class Taxonomies extends \WP_Sitemaps_Taxonomies {
|
|
90 |
|
91 |
$taxonomy_terms = new \WP_Term_Query( $args );
|
92 |
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
$url_list[] = $sitemap_entry;
|
122 |
-
}
|
123 |
-
}
|
124 |
|
125 |
return $url_list;
|
126 |
}
|
38 |
* Gets a URL list for a taxonomy sitemap.
|
39 |
*
|
40 |
* @since 4.1.2
|
41 |
+
* @since 4.2.0 Renamed `$taxonomy` to `$object_subtype` to match parent class
|
42 |
+
* for PHP 8 named parameter support. (Backport WP 5.9)
|
43 |
* @source \WP_Sitemaps_Taxonomies\get_url_list()
|
44 |
* @TEMP https://wordpress.slack.com/archives/CTKTGNJJW/p1604995479019700
|
45 |
* @link <https://core.trac.wordpress.org/ticket/51860>
|
46 |
+
* @link <https://core.trac.wordpress.org/changeset/51787>
|
47 |
*
|
48 |
+
* @param int $page_num Page of results.
|
49 |
+
* @param string $object_subtype Optional. Taxonomy name. Default empty.
|
50 |
* @return array Array of URLs for a sitemap.
|
51 |
*/
|
52 |
+
public function get_url_list( $page_num, $object_subtype = '' ) {
|
53 |
+
// Restores the more descriptive, specific name for use within this method.
|
54 |
+
$taxonomy = $object_subtype;
|
55 |
$supported_types = $this->get_object_subtypes();
|
56 |
|
57 |
// Bail early if the queried taxonomy is not supported.
|
58 |
+
if ( ! isset( $supported_types[ $taxonomy ] ) )
|
59 |
return [];
|
|
|
60 |
|
61 |
/**
|
62 |
* Filters the taxonomies URL list before it is generated.
|
77 |
$page_num
|
78 |
);
|
79 |
|
80 |
+
if ( null !== $url_list )
|
81 |
return $url_list;
|
|
|
82 |
|
83 |
$url_list = [];
|
84 |
|
92 |
|
93 |
$taxonomy_terms = new \WP_Term_Query( $args );
|
94 |
|
95 |
+
foreach ( $taxonomy_terms->terms ?? [] as $term ) :
|
96 |
+
/**
|
97 |
+
* @augmented This if-statement prevents including the term in the sitemap when conditions apply.
|
98 |
+
*/
|
99 |
+
if ( ! $main->is_term_included_in_sitemap( $term, $taxonomy ) )
|
100 |
+
continue;
|
101 |
+
|
102 |
+
$term_link = \get_term_link( $term, $taxonomy );
|
103 |
+
|
104 |
+
if ( \is_wp_error( $term_link ) )
|
105 |
+
continue;
|
106 |
+
|
107 |
+
$sitemap_entry = [
|
108 |
+
'loc' => $term_link,
|
109 |
+
];
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Filters the sitemap entry for an individual term.
|
113 |
+
*
|
114 |
+
* @since WP Core 5.5.0
|
115 |
+
*
|
116 |
+
* @param array $sitemap_entry Sitemap entry for the term.
|
117 |
+
* @param WP_Term $term Term object.
|
118 |
+
* @param string $taxonomy Taxonomy name.
|
119 |
+
*/
|
120 |
+
$sitemap_entry = \apply_filters( 'wp_sitemaps_taxonomies_entry', $sitemap_entry, $term, $taxonomy );
|
121 |
+
$url_list[] = $sitemap_entry;
|
122 |
+
endforeach;
|
|
|
|
|
|
|
123 |
|
124 |
return $url_list;
|
125 |
}
|
@@ -37,7 +37,7 @@ final class Images {
|
|
37 |
* @internal
|
38 |
* @var int MAX_CONTENT_IMAGES The maximum number of images to get from the content.
|
39 |
*/
|
40 |
-
const MAX_CONTENT_IMAGES = 5;
|
41 |
|
42 |
/**
|
43 |
* The constructor. Or rather, the lack thereof.
|
@@ -52,7 +52,7 @@ final class Images {
|
|
52 |
* @since 4.0.0
|
53 |
* @generator
|
54 |
*
|
55 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
56 |
* Leave null to autodetermine query.
|
57 |
* @param string $size The size of the image to get.
|
58 |
* @yield array : {
|
@@ -62,7 +62,7 @@ final class Images {
|
|
62 |
*/
|
63 |
public static function get_attachment_image_details( $args = null, $size = 'full' ) {
|
64 |
|
65 |
-
$id =
|
66 |
|
67 |
if ( $id ) {
|
68 |
yield [
|
@@ -83,7 +83,7 @@ final class Images {
|
|
83 |
* @since 4.0.0
|
84 |
* @generator
|
85 |
*
|
86 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
87 |
* Leave null to autodetermine query.
|
88 |
* @param string $size The size of the image to get.
|
89 |
* @yield array : {
|
@@ -93,7 +93,7 @@ final class Images {
|
|
93 |
*/
|
94 |
public static function get_featured_image_details( $args = null, $size = 'full' ) {
|
95 |
|
96 |
-
$post_id =
|
97 |
$id = \get_post_thumbnail_id( $post_id );
|
98 |
|
99 |
if ( $id ) {
|
@@ -115,11 +115,13 @@ final class Images {
|
|
115 |
* @since 4.0.0
|
116 |
* @since 4.0.5 1. Now strips tags before looking for images.
|
117 |
* 2. Now only yields at most 5 images.
|
|
|
|
|
118 |
* @generator
|
119 |
* @TODO consider matching these images with wp-content/uploads items via database calls, which is heavy...
|
120 |
* Combine query, instead of using WP API? Only do that for the first image, instead?
|
121 |
*
|
122 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
123 |
* Leave null to autodetermine query.
|
124 |
* @param string $size The size of the image to get.
|
125 |
* @yield array : {
|
@@ -129,14 +131,14 @@ final class Images {
|
|
129 |
*/
|
130 |
public static function get_content_image_details( $args = null, $size = 'full' ) {
|
131 |
|
132 |
-
$tsf = \
|
133 |
|
134 |
if ( null === $args ) {
|
135 |
if ( $tsf->is_singular() ) {
|
136 |
$content = $tsf->get_post_content();
|
137 |
}
|
138 |
} else {
|
139 |
-
if ( $args['taxonomy'] ) {
|
140 |
$content = '';
|
141 |
} else {
|
142 |
$content = $tsf->get_post_content( $args['id'] );
|
@@ -158,7 +160,7 @@ final class Images {
|
|
158 |
);
|
159 |
// TODO can we somehow limit this search to static::MAX_CONTENT_IMAGES? -> We could, via preg_match(), but the opcodes won't help.
|
160 |
preg_match_all(
|
161 |
-
'/<img[^>]
|
162 |
$content,
|
163 |
$matches,
|
164 |
PREG_SET_ORDER
|
@@ -166,7 +168,7 @@ final class Images {
|
|
166 |
}
|
167 |
|
168 |
if ( $matches ) {
|
169 |
-
for ( $i = 0; $i
|
170 |
// Fewer than MAX_CONTENT_IMAGES matched.
|
171 |
if ( ! isset( $matches[ $i ][2] ) ) break;
|
172 |
|
@@ -195,7 +197,7 @@ final class Images {
|
|
195 |
* @since 4.0.0
|
196 |
* @generator
|
197 |
*
|
198 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
199 |
* Leave null to autodetermine query.
|
200 |
* @param string $size The size of the image to get.
|
201 |
* @yield array : {
|
@@ -205,7 +207,7 @@ final class Images {
|
|
205 |
*/
|
206 |
public static function get_fallback_image_details( $args = null, $size = 'full' ) {
|
207 |
|
208 |
-
$tsf = \
|
209 |
|
210 |
yield [
|
211 |
'url' => $tsf->get_option( 'social_image_fb_url' ) ?: '',
|
@@ -221,7 +223,7 @@ final class Images {
|
|
221 |
* @since 4.0.0
|
222 |
* @generator
|
223 |
*
|
224 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
225 |
* Leave null to autodetermine query.
|
226 |
* @param string $size The size of the image to get.
|
227 |
* @yield array : {
|
@@ -252,7 +254,7 @@ final class Images {
|
|
252 |
* @since 4.0.0
|
253 |
* @generator
|
254 |
*
|
255 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
256 |
* Leave null to autodetermine query.
|
257 |
* @param string $size The size of the image to get.
|
258 |
* @yield array : {
|
@@ -283,7 +285,7 @@ final class Images {
|
|
283 |
* @since 4.0.0
|
284 |
* @generator
|
285 |
*
|
286 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
287 |
* Leave null to autodetermine query.
|
288 |
* @param string $size The size of the image to get.
|
289 |
* @yield array : {
|
37 |
* @internal
|
38 |
* @var int MAX_CONTENT_IMAGES The maximum number of images to get from the content.
|
39 |
*/
|
40 |
+
private const MAX_CONTENT_IMAGES = 5;
|
41 |
|
42 |
/**
|
43 |
* The constructor. Or rather, the lack thereof.
|
52 |
* @since 4.0.0
|
53 |
* @generator
|
54 |
*
|
55 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
56 |
* Leave null to autodetermine query.
|
57 |
* @param string $size The size of the image to get.
|
58 |
* @yield array : {
|
62 |
*/
|
63 |
public static function get_attachment_image_details( $args = null, $size = 'full' ) {
|
64 |
|
65 |
+
$id = $args['id'] ?? \tsf()->get_the_real_ID();
|
66 |
|
67 |
if ( $id ) {
|
68 |
yield [
|
83 |
* @since 4.0.0
|
84 |
* @generator
|
85 |
*
|
86 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
87 |
* Leave null to autodetermine query.
|
88 |
* @param string $size The size of the image to get.
|
89 |
* @yield array : {
|
93 |
*/
|
94 |
public static function get_featured_image_details( $args = null, $size = 'full' ) {
|
95 |
|
96 |
+
$post_id = $args['id'] ?? \tsf()->get_the_real_ID();
|
97 |
$id = \get_post_thumbnail_id( $post_id );
|
98 |
|
99 |
if ( $id ) {
|
115 |
* @since 4.0.0
|
116 |
* @since 4.0.5 1. Now strips tags before looking for images.
|
117 |
* 2. Now only yields at most 5 images.
|
118 |
+
* @since 4.2.0 1. Fixed OB1 error causing the first image to be ignored.
|
119 |
+
* 2. Now supports the `$args['pta']` index.
|
120 |
* @generator
|
121 |
* @TODO consider matching these images with wp-content/uploads items via database calls, which is heavy...
|
122 |
* Combine query, instead of using WP API? Only do that for the first image, instead?
|
123 |
*
|
124 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
125 |
* Leave null to autodetermine query.
|
126 |
* @param string $size The size of the image to get.
|
127 |
* @yield array : {
|
131 |
*/
|
132 |
public static function get_content_image_details( $args = null, $size = 'full' ) {
|
133 |
|
134 |
+
$tsf = \tsf();
|
135 |
|
136 |
if ( null === $args ) {
|
137 |
if ( $tsf->is_singular() ) {
|
138 |
$content = $tsf->get_post_content();
|
139 |
}
|
140 |
} else {
|
141 |
+
if ( $args['taxonomy'] || $args['pta'] ) {
|
142 |
$content = '';
|
143 |
} else {
|
144 |
$content = $tsf->get_post_content( $args['id'] );
|
160 |
);
|
161 |
// TODO can we somehow limit this search to static::MAX_CONTENT_IMAGES? -> We could, via preg_match(), but the opcodes won't help.
|
162 |
preg_match_all(
|
163 |
+
'/<img[^>]+?src=(\"|\')?([^\"\'>\s]+)\1?[^>]*?>/mi',
|
164 |
$content,
|
165 |
$matches,
|
166 |
PREG_SET_ORDER
|
168 |
}
|
169 |
|
170 |
if ( $matches ) {
|
171 |
+
for ( $i = 0; $i < static::MAX_CONTENT_IMAGES; $i++ ) {
|
172 |
// Fewer than MAX_CONTENT_IMAGES matched.
|
173 |
if ( ! isset( $matches[ $i ][2] ) ) break;
|
174 |
|
197 |
* @since 4.0.0
|
198 |
* @generator
|
199 |
*
|
200 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
201 |
* Leave null to autodetermine query.
|
202 |
* @param string $size The size of the image to get.
|
203 |
* @yield array : {
|
207 |
*/
|
208 |
public static function get_fallback_image_details( $args = null, $size = 'full' ) {
|
209 |
|
210 |
+
$tsf = \tsf();
|
211 |
|
212 |
yield [
|
213 |
'url' => $tsf->get_option( 'social_image_fb_url' ) ?: '',
|
223 |
* @since 4.0.0
|
224 |
* @generator
|
225 |
*
|
226 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
227 |
* Leave null to autodetermine query.
|
228 |
* @param string $size The size of the image to get.
|
229 |
* @yield array : {
|
254 |
* @since 4.0.0
|
255 |
* @generator
|
256 |
*
|
257 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
258 |
* Leave null to autodetermine query.
|
259 |
* @param string $size The size of the image to get.
|
260 |
* @yield array : {
|
285 |
* @since 4.0.0
|
286 |
* @generator
|
287 |
*
|
288 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
289 |
* Leave null to autodetermine query.
|
290 |
* @param string $size The size of the image to get.
|
291 |
* @yield array : {
|
@@ -0,0 +1,162 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Builders\Robots\Args
|
4 |
+
* @subpackage The_SEO_Framework\Getter\Robots
|
5 |
+
*/
|
6 |
+
|
7 |
+
namespace The_SEO_Framework\Builders\Robots;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* The SEO Framework plugin
|
11 |
+
* Copyright (C) 2021 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/)
|
12 |
+
*
|
13 |
+
* This program is free software: you can redistribute it and/or modify
|
14 |
+
* it under the terms of the GNU General Public License version 3 as published
|
15 |
+
* by the Free Software Foundation.
|
16 |
+
*
|
17 |
+
* This program is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
* GNU General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU General Public License
|
23 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
+
*/
|
25 |
+
|
26 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Engine for robots generator by arguments.
|
30 |
+
*
|
31 |
+
* @since 4.2.0
|
32 |
+
* @access private
|
33 |
+
* Not part of the public API.
|
34 |
+
* @final Can't be extended.
|
35 |
+
*/
|
36 |
+
final class Args extends Factory {
|
37 |
+
|
38 |
+
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- You don't love PHP7.
|
39 |
+
// phpcs:disable, PSR2.ControlStructures.SwitchDeclaration.TerminatingComment -- You hate goto.
|
40 |
+
// phpcs:disable, Generic.WhiteSpace.ScopeIndent.IncorrectExact -- You hate gotoo.
|
41 |
+
/**
|
42 |
+
* Generates robots assertions for no[index|archive|follow].
|
43 |
+
*
|
44 |
+
* Yields true when "noindex/noarchive/nofollow", yields false when "index/archive/follow".
|
45 |
+
*
|
46 |
+
* @since 4.2.0
|
47 |
+
* @generator
|
48 |
+
*
|
49 |
+
* @param string $type The robots generator type (noindex, nofollow...).
|
50 |
+
*/
|
51 |
+
protected static function assert_no( $type ) {
|
52 |
+
|
53 |
+
// Remit FETCH_STATIC_PROP_R opcode calls every time we'd otherwise use static::$tsf/static::$args hereinafter.
|
54 |
+
$tsf = static::$tsf;
|
55 |
+
$args = static::$args;
|
56 |
+
|
57 |
+
$asserting_noindex = 'noindex' === $type;
|
58 |
+
|
59 |
+
meta_settings: {
|
60 |
+
// We assert options here for a jump to meta_settings might be unaware.
|
61 |
+
if ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_SETTINGS )
|
62 |
+
goto after_meta_settings;
|
63 |
+
|
64 |
+
$qubit = null;
|
65 |
+
|
66 |
+
if ( $args['taxonomy'] ) {
|
67 |
+
$qubit = (int) $tsf->get_term_meta_item( $type, $args['id'] );
|
68 |
+
} elseif ( $args['id'] ) {
|
69 |
+
$qubit = (int) $tsf->get_post_meta_item( "_genesis_$type", $args['id'] );
|
70 |
+
} elseif ( $args['pta'] ) {
|
71 |
+
$qubit = (int) $tsf->get_post_type_archive_meta_item( $type, $args['pta'] );
|
72 |
+
}
|
73 |
+
|
74 |
+
switch ( isset( $qubit ) ) :
|
75 |
+
case false:
|
76 |
+
// Page doesn't support metadata.
|
77 |
+
break;
|
78 |
+
case $qubit < -.33:
|
79 |
+
// 'Force' index.
|
80 |
+
yield 'meta_qubit_force' => false;
|
81 |
+
// Override with index protection.
|
82 |
+
goto index_protection;
|
83 |
+
case $qubit > .33:
|
84 |
+
// Force noindex.
|
85 |
+
yield 'meta_qubit_force' => true;
|
86 |
+
// We won't override this. Terminate generator. "goto end".
|
87 |
+
// No break, generator stops here anyway.
|
88 |
+
default:
|
89 |
+
// qubit is (closer to) 0. Assert we use _default, albeit false.
|
90 |
+
yield 'meta_qubit_default' => false;
|
91 |
+
endswitch;
|
92 |
+
}
|
93 |
+
after_meta_settings:;
|
94 |
+
|
95 |
+
globals: {
|
96 |
+
yield 'globals_site' => (bool) $tsf->get_option( "site_$type" );
|
97 |
+
|
98 |
+
if ( $args['taxonomy'] ) {
|
99 |
+
$asserting_noindex and yield from static::assert_noindex_query_pass( '404' );
|
100 |
+
|
101 |
+
yield 'globals_taxonomy' => $tsf->is_taxonomy_robots_set( $type, $args['taxonomy'] );
|
102 |
+
|
103 |
+
// Store values from each post type bound to the taxonomy.
|
104 |
+
foreach ( $tsf->get_post_types_from_taxonomy( $args['taxonomy'] ) as $post_type )
|
105 |
+
$_is_post_type_robots_set[] = $tsf->is_post_type_robots_set( $type, $post_type );
|
106 |
+
|
107 |
+
// Only enable if _all_ post types have been marked with 'no*'. Return false if no post types are found (corner case).
|
108 |
+
yield 'globals_post_type_all' => isset( $_is_post_type_robots_set ) && ! \in_array( false, $_is_post_type_robots_set, true );
|
109 |
+
} elseif ( $args['pta'] ) {
|
110 |
+
yield 'globals_post_type' => $tsf->is_post_type_robots_set( $type, $args['pta'] );
|
111 |
+
} else {
|
112 |
+
// $args['id'] can be empty, pointing to a plausible homepage query.
|
113 |
+
if ( $tsf->is_real_front_page_by_id( $args['id'] ) )
|
114 |
+
yield 'globals_homepage' => (bool) $tsf->get_option( "homepage_$type" );
|
115 |
+
|
116 |
+
if ( $args['id'] )
|
117 |
+
yield 'globals_post_type' => $tsf->is_post_type_robots_set( $type, \get_post_type( $args['id'] ) );
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
index_protection: if ( $asserting_noindex ) {
|
122 |
+
// We assert options here for a jump to index_protection might be unaware.
|
123 |
+
if ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION )
|
124 |
+
goto after_index_protection;
|
125 |
+
|
126 |
+
if ( ! $args['taxonomy'] )
|
127 |
+
yield from static::assert_noindex_query_pass( 'protected' );
|
128 |
+
}
|
129 |
+
after_index_protection:;
|
130 |
+
|
131 |
+
end:;
|
132 |
+
}
|
133 |
+
// phpcs:enable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
|
134 |
+
// phpcs:enable, PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
|
135 |
+
// phpcs:disable, Generic.WhiteSpace.ScopeIndent.IncorrectExact
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Generates robots assertions for noindex in passes.
|
139 |
+
*
|
140 |
+
* @since 4.2.0
|
141 |
+
* @generator
|
142 |
+
*
|
143 |
+
* @param string $pass The passage to assert.
|
144 |
+
*/
|
145 |
+
private static function assert_noindex_query_pass( $pass ) {
|
146 |
+
|
147 |
+
// Remit FETCH_STATIC_PROP_R opcode calls every time we'd otherwise use static::$tsf/static::$args hereinafter.
|
148 |
+
// $tsf = static::$tsf;
|
149 |
+
$args = static::$args;
|
150 |
+
|
151 |
+
switch ( $pass ) :
|
152 |
+
case '404':
|
153 |
+
yield '404' => empty( \get_term( $args['id'], $args['taxonomy'] )->count );
|
154 |
+
break;
|
155 |
+
|
156 |
+
case 'protected':
|
157 |
+
// We get the "real ID" for WordPress might fault parsing a nefariously forged request.
|
158 |
+
yield 'protected' => static::$tsf->is_protected( $args['id'] );
|
159 |
+
break;
|
160 |
+
endswitch;
|
161 |
+
}
|
162 |
+
}
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Builders\Robots\Factory
|
4 |
+
* @subpackage The_SEO_Framework\Getter\Robots
|
5 |
+
*/
|
6 |
+
|
7 |
+
namespace The_SEO_Framework\Builders\Robots;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* The SEO Framework plugin
|
11 |
+
* Copyright (C) 2021 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/)
|
12 |
+
*
|
13 |
+
* This program is free software: you can redistribute it and/or modify
|
14 |
+
* it under the terms of the GNU General Public License version 3 as published
|
15 |
+
* by the Free Software Foundation.
|
16 |
+
*
|
17 |
+
* This program is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
* GNU General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU General Public License
|
23 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
+
*/
|
25 |
+
|
26 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Factory engine for robots generator.
|
30 |
+
*
|
31 |
+
* @since 4.2.0
|
32 |
+
* @access private
|
33 |
+
* Not part of the public API.
|
34 |
+
*/
|
35 |
+
class Factory {
|
36 |
+
|
37 |
+
/**
|
38 |
+
* @since 4.2.0
|
39 |
+
* @param int The starter. A unique ID sent to start the generator switcher.
|
40 |
+
*/
|
41 |
+
public const START = 0b01000011011110010110001001110010;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* @since 4.2.0
|
45 |
+
* @param int The halter. A unique ID sent to stop the generator switcher.
|
46 |
+
*/
|
47 |
+
public const HALT = 0b01010111011010010111001001100101;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @since 4.2.0
|
51 |
+
* @var \The_SEO_Framework\Load The SEO Framework class.
|
52 |
+
*/
|
53 |
+
protected static $tsf;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @since 4.2.0
|
57 |
+
* @var array|null Null to autodetermine query, otherwise the query arguments. : {
|
58 |
+
* int $id The Post, Page or Term ID to generate robots for.
|
59 |
+
* string $taxonomy The taxonomy.
|
60 |
+
* }
|
61 |
+
*/
|
62 |
+
protected static $args;
|
63 |
+
|
64 |
+
/**
|
65 |
+
* @since 4.2.0
|
66 |
+
* @var int Modifies return values/assertions. See const ROBOTS_* at /bootstrap/define.php
|
67 |
+
*/
|
68 |
+
protected static $options;
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Contructor, does nothing but instigate TSF.
|
72 |
+
*
|
73 |
+
* @since 4.2.0
|
74 |
+
*/
|
75 |
+
public function __construct() {
|
76 |
+
static::$tsf = static::$tsf ?? \tsf();
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Sets parameters.
|
81 |
+
*
|
82 |
+
* @since 4.2.0
|
83 |
+
* @access private
|
84 |
+
*
|
85 |
+
* @param null|array $args The robots meta arguments, leave null to autodetermine query : {
|
86 |
+
* int $id The Post, Page or Term ID to generate the URL for.
|
87 |
+
* string $taxonomy The taxonomy.
|
88 |
+
* }
|
89 |
+
* @param int $options Modifies return values/assertions. See const ROBOTS_* at /bootstrap/define.php
|
90 |
+
* @return Factory $this
|
91 |
+
*/
|
92 |
+
public function set( $args = null, $options = 0 ) {
|
93 |
+
static::$args = $args;
|
94 |
+
static::$options = $options;
|
95 |
+
return $this;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Generates robots assertions.
|
100 |
+
*
|
101 |
+
* @since 4.2.0
|
102 |
+
* @access private
|
103 |
+
* @generator
|
104 |
+
*/
|
105 |
+
public static function generator() {
|
106 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition.Found -- Shhh. It's OK.
|
107 |
+
while ( true ) switch ( $sender = yield static::START ) :
|
108 |
+
case 'noindex':
|
109 |
+
case 'nofollow':
|
110 |
+
case 'noarchive':
|
111 |
+
foreach ( static::assert_no( $sender ) as $key => $value ) {
|
112 |
+
yield $key => $value;
|
113 |
+
if ( $value ) {
|
114 |
+
yield static::HALT;
|
115 |
+
break;
|
116 |
+
}
|
117 |
+
}
|
118 |
+
break;
|
119 |
+
|
120 |
+
case 'max_snippet':
|
121 |
+
case 'max_image_preview':
|
122 |
+
case 'max_video_preview':
|
123 |
+
yield from static::assert_copyright( $sender );
|
124 |
+
yield static::HALT;
|
125 |
+
break;
|
126 |
+
|
127 |
+
default:
|
128 |
+
static::$tsf->_doing_it_wrong(
|
129 |
+
__METHOD__,
|
130 |
+
sprintf( 'Unregistered robots-generator getter provided: <code>%s</code>.', \esc_html( $sender ) ),
|
131 |
+
'4.2.0'
|
132 |
+
);
|
133 |
+
yield static::HALT;
|
134 |
+
break;
|
135 |
+
endswitch;
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Generates robots assertions for copyright options.
|
140 |
+
*
|
141 |
+
* @since 4.2.0
|
142 |
+
* @access private
|
143 |
+
* @generator
|
144 |
+
*
|
145 |
+
* @param string $type The robots generator type (noindex, nofollow...).
|
146 |
+
*/
|
147 |
+
final protected static function assert_copyright( $type ) {
|
148 |
+
|
149 |
+
// Remit FETCH_STATIC_PROP_R opcode calls every time we'd otherwise use static::$tsf hereinafter.
|
150 |
+
$tsf = static::$tsf;
|
151 |
+
|
152 |
+
$option = $type;
|
153 |
+
|
154 |
+
if ( 'max_snippet' === $type )
|
155 |
+
$option = 'max_snippet_length';
|
156 |
+
|
157 |
+
$tsf->get_option( 'set_copyright_directives' )
|
158 |
+
and yield 'globals_copyright' => $tsf->get_option( $option );
|
159 |
+
}
|
160 |
+
}
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* People aren't that worried about what you're doing or what you're saying,
|
4 |
+
* so you can drift around the world relatively anonymously.
|
5 |
+
* You must not feel persecuted and examined.
|
6 |
+
* Liberate yourself from that idea that people are watching you.
|
7 |
+
*
|
8 |
+
* - Russell Brand
|
9 |
+
*/
|
@@ -0,0 +1,220 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Builders\Robots\Main
|
4 |
+
* @subpackage The_SEO_Framework\Getter\Robots
|
5 |
+
*/
|
6 |
+
|
7 |
+
namespace The_SEO_Framework\Builders\Robots;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* The SEO Framework plugin
|
11 |
+
* Copyright (C) 2021 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/)
|
12 |
+
*
|
13 |
+
* This program is free software: you can redistribute it and/or modify
|
14 |
+
* it under the terms of the GNU General Public License version 3 as published
|
15 |
+
* by the Free Software Foundation.
|
16 |
+
*
|
17 |
+
* This program is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
* GNU General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU General Public License
|
23 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
+
*/
|
25 |
+
|
26 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
+
|
28 |
+
use function \The_SEO_Framework\umemo;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Generates robots meta.
|
32 |
+
*
|
33 |
+
* @since 4.2.0
|
34 |
+
* @access protected
|
35 |
+
* Instantiation of class is not part of the public API.
|
36 |
+
* @final Can't be extended.
|
37 |
+
*/
|
38 |
+
final class Main {
|
39 |
+
|
40 |
+
/**
|
41 |
+
* @since 4.2.0
|
42 |
+
* @var array|null Null to autodetermine query, otherwise the query arguments. : {
|
43 |
+
* int $id The Post, Page or Term ID to generate robots for.
|
44 |
+
* string $taxonomy The taxonomy.
|
45 |
+
* }
|
46 |
+
*/
|
47 |
+
private $args;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @since 4.2.0
|
51 |
+
* @var int Modifies return values/assertions. See const ROBOTS_* at /bootstrap/define.php
|
52 |
+
*/
|
53 |
+
private $options;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* @since 4.2.0
|
57 |
+
* @var Main This instance.
|
58 |
+
*/
|
59 |
+
private static $instance;
|
60 |
+
|
61 |
+
/**
|
62 |
+
* @since 4.2.0
|
63 |
+
* @param array List of registered getters.
|
64 |
+
*/
|
65 |
+
private const GETTERS = [
|
66 |
+
'noindex',
|
67 |
+
'nofollow',
|
68 |
+
'noarchive',
|
69 |
+
'max_snippet',
|
70 |
+
'max_image_preview',
|
71 |
+
'max_video_preview',
|
72 |
+
];
|
73 |
+
|
74 |
+
/**
|
75 |
+
* The constructor. Or rather, the lack thereof.
|
76 |
+
*
|
77 |
+
* @since 4.2.0
|
78 |
+
* @access private
|
79 |
+
*/
|
80 |
+
private function __construct() { }
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Creates and returns the instance.
|
84 |
+
*
|
85 |
+
* @since 4.2.0
|
86 |
+
*
|
87 |
+
* @return Main
|
88 |
+
*/
|
89 |
+
public static function instance() {
|
90 |
+
return static::$instance ?? ( static::$instance = new static );
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Sets class parameters.
|
95 |
+
*
|
96 |
+
* @since 4.2.0
|
97 |
+
* @access private
|
98 |
+
*
|
99 |
+
* @param null|array $args The robots meta arguments, leave null to autodetermine query : {
|
100 |
+
* int $id The Post, Page or Term ID to generate the URL for.
|
101 |
+
* string $taxonomy The taxonomy.
|
102 |
+
* }
|
103 |
+
* @param int $options Modifies return values/assertions. See const ROBOTS_* at /bootstrap/define.php
|
104 |
+
* @return Main $this
|
105 |
+
*/
|
106 |
+
public function set( $args = null, $options = 0 ) {
|
107 |
+
$this->args = $args;
|
108 |
+
$this->options = $options;
|
109 |
+
return $this;
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Gets the robots values.
|
114 |
+
*
|
115 |
+
* @since 4.2.0
|
116 |
+
* @access public
|
117 |
+
*
|
118 |
+
* @param null|array $get The robots types to retrieve. See class constant GETTERS for valid values.
|
119 |
+
* @return array The robots-values results. Assert values may be true-esque.
|
120 |
+
*/
|
121 |
+
public function get( $get = null ) {
|
122 |
+
|
123 |
+
// If this leads to 0 getters, so be it: The dev might've used a deprecated value, which is fine. Continue method.
|
124 |
+
$get = ( $get ?? false )
|
125 |
+
? array_intersect( static::GETTERS, $get )
|
126 |
+
: static::GETTERS;
|
127 |
+
|
128 |
+
// Remit FETCH_OBJ_R opcode calls every time we'd otherwise use $this->options hereinafter.
|
129 |
+
$options = $this->options;
|
130 |
+
|
131 |
+
$options & \The_SEO_Framework\ROBOTS_ASSERT
|
132 |
+
and $this->reset_assertions();
|
133 |
+
|
134 |
+
$factory = $this->get_factory();
|
135 |
+
$halt = $factory::HALT;
|
136 |
+
$start = $factory::START;
|
137 |
+
$generator = $factory->set(
|
138 |
+
$this->args,
|
139 |
+
$options
|
140 |
+
)->generator();
|
141 |
+
|
142 |
+
$results = [];
|
143 |
+
|
144 |
+
foreach ( $get as $g ) {
|
145 |
+
$generator->send( $g );
|
146 |
+
|
147 |
+
do {
|
148 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition.Found -- Shhh. It's OK. I'm a professional.
|
149 |
+
if ( ( $r = $generator->current() ) === $halt ) continue; // goto while() -- motivating generator.
|
150 |
+
|
151 |
+
$results[ $g ] = $r;
|
152 |
+
|
153 |
+
$options & \The_SEO_Framework\ROBOTS_ASSERT
|
154 |
+
and $this->store_assertion( $g, $generator->key(), $r );
|
155 |
+
// We could send anything, really. But this is the only method that loops and yields at the same time.
|
156 |
+
} while ( $start !== $generator->send( true ) );
|
157 |
+
}
|
158 |
+
|
159 |
+
return $results;
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Returns the robots factory. Factory changes depending on input arguments.
|
164 |
+
*
|
165 |
+
* @since 4.2.0
|
166 |
+
* @factory
|
167 |
+
*
|
168 |
+
* @return The_SEO_Framework\Builders\Robots\<Args|Query>
|
169 |
+
*/
|
170 |
+
private function get_factory() {
|
171 |
+
return umemo( __METHOD__, null, isset( $this->args ) )
|
172 |
+
?? umemo(
|
173 |
+
__METHOD__,
|
174 |
+
isset( $this->args ) ? new Args : new Query,
|
175 |
+
isset( $this->args )
|
176 |
+
);
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Captures and returns the robots-assertions.
|
181 |
+
*
|
182 |
+
* @since 4.2.0
|
183 |
+
* @access public
|
184 |
+
*
|
185 |
+
* @collector
|
186 |
+
* @access protected
|
187 |
+
* Do not call this method by reference. Only use it to read the return value.
|
188 |
+
* @return array The collected assertions. Returned by reference.
|
189 |
+
*/
|
190 |
+
public function &collect_assertions() {
|
191 |
+
static $collection = [];
|
192 |
+
return $collection;
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Stores the robots-assertions.
|
197 |
+
*
|
198 |
+
* @since 4.2.0
|
199 |
+
* @see $this->collect_assertions()
|
200 |
+
*
|
201 |
+
* @param string $get The robots type getter name (noindex, nofollow...).
|
202 |
+
* @param string $assertion The assertion name (is_404, no_posts);
|
203 |
+
* @param string $result The assertion's result.
|
204 |
+
*/
|
205 |
+
private function store_assertion( $get, $assertion, $result ) {
|
206 |
+
$this->collect_assertions()[ $get ][ $assertion ] = $result;
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* Resets the robots-assertions.
|
211 |
+
*
|
212 |
+
* @since 4.2.0
|
213 |
+
* @see $this->collect_assertions()
|
214 |
+
*/
|
215 |
+
private function reset_assertions() {
|
216 |
+
// phpcs:ignore, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- No function by reference support?
|
217 |
+
$collection = &$this->collect_assertions();
|
218 |
+
$collection = [];
|
219 |
+
}
|
220 |
+
}
|
@@ -0,0 +1,260 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Builders\Robots\Query
|
4 |
+
* @subpackage The_SEO_Framework\Getter\Robots
|
5 |
+
*/
|
6 |
+
|
7 |
+
namespace The_SEO_Framework\Builders\Robots;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* The SEO Framework plugin
|
11 |
+
* Copyright (C) 2021 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/)
|
12 |
+
*
|
13 |
+
* This program is free software: you can redistribute it and/or modify
|
14 |
+
* it under the terms of the GNU General Public License version 3 as published
|
15 |
+
* by the Free Software Foundation.
|
16 |
+
*
|
17 |
+
* This program is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
* GNU General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU General Public License
|
23 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
+
*/
|
25 |
+
|
26 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Engine for robots generator via query.
|
30 |
+
*
|
31 |
+
* @since 4.2.0
|
32 |
+
* @access private
|
33 |
+
* Not part of the public API.
|
34 |
+
* @final Can't be extended.
|
35 |
+
*/
|
36 |
+
final class Query extends Factory {
|
37 |
+
|
38 |
+
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- You don't love PHP7.
|
39 |
+
// phpcs:disable, PSR2.ControlStructures.SwitchDeclaration.TerminatingComment -- You hate goto.
|
40 |
+
// phpcs:disable, Generic.WhiteSpace.ScopeIndent.IncorrectExact -- You hate gotoo.
|
41 |
+
/**
|
42 |
+
* Generates robots assertions for no[index|archive|follow].
|
43 |
+
*
|
44 |
+
* Yields true when "noindex/noarchive/nofollow", yields false when "index/archive/follow".
|
45 |
+
*
|
46 |
+
* @since 4.2.0
|
47 |
+
* @generator
|
48 |
+
*
|
49 |
+
* @param string $type The robots generator type (noindex, nofollow...).
|
50 |
+
*/
|
51 |
+
protected static function assert_no( $type ) {
|
52 |
+
|
53 |
+
// Remit FETCH_STATIC_PROP_R opcode calls every time we'd otherwise use static::$tsf hereinafter.
|
54 |
+
$tsf = static::$tsf;
|
55 |
+
|
56 |
+
$asserting_noindex = 'noindex' === $type;
|
57 |
+
|
58 |
+
meta_settings: {
|
59 |
+
// We assert options here for a jump to meta_settings might be unaware.
|
60 |
+
if ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_SETTINGS )
|
61 |
+
goto after_meta_settings;
|
62 |
+
|
63 |
+
$qubit = null;
|
64 |
+
|
65 |
+
if ( $tsf->is_term_meta_capable() ) {
|
66 |
+
$qubit = (int) $tsf->get_term_meta_item( $type );
|
67 |
+
} elseif ( $tsf->is_singular() ) {
|
68 |
+
$qubit = (int) $tsf->get_post_meta_item( "_genesis_$type" );
|
69 |
+
} elseif ( \is_post_type_archive() ) {
|
70 |
+
$qubit = (int) $tsf->get_post_type_archive_meta_item( $type );
|
71 |
+
}
|
72 |
+
|
73 |
+
switch ( isset( $qubit ) ) :
|
74 |
+
case false:
|
75 |
+
// Page doesn't support metadata.
|
76 |
+
break;
|
77 |
+
case $qubit < -.33:
|
78 |
+
// 'Force' index.
|
79 |
+
yield 'meta_qubit_force' => false;
|
80 |
+
// Override with index protection.
|
81 |
+
goto index_protection;
|
82 |
+
case $qubit > .33:
|
83 |
+
// Force noindex.
|
84 |
+
yield 'meta_qubit_force' => true;
|
85 |
+
// We won't override this. Terminate generator. "goto end".
|
86 |
+
// No break, generator stops here anyway.
|
87 |
+
default:
|
88 |
+
// qubit is (closer to) 0. Assert we use _default, albeit false.
|
89 |
+
yield 'meta_qubit_default' => false;
|
90 |
+
endswitch;
|
91 |
+
}
|
92 |
+
after_meta_settings:;
|
93 |
+
|
94 |
+
globals: {
|
95 |
+
yield 'globals_site' => (bool) $tsf->get_option( "site_$type" );
|
96 |
+
|
97 |
+
if ( $tsf->is_real_front_page() ) {
|
98 |
+
yield 'globals_homepage' => (bool) $tsf->get_option( "homepage_$type" );
|
99 |
+
|
100 |
+
if ( ! ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION ) )
|
101 |
+
$asserting_noindex and yield from static::assert_noindex_query_pass( 'paged_home' );
|
102 |
+
} else {
|
103 |
+
$asserting_noindex and yield from static::assert_noindex_query_pass( '404' );
|
104 |
+
|
105 |
+
if ( ! ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION ) )
|
106 |
+
if ( $asserting_noindex && ( $tsf->is_archive() || $tsf->is_singular_archive() ) )
|
107 |
+
yield from static::assert_noindex_query_pass( 'paged' );
|
108 |
+
|
109 |
+
if ( $tsf->is_archive() ) {
|
110 |
+
if ( $tsf->is_author() ) {
|
111 |
+
yield 'globals_author' => (bool) $tsf->get_option( "author_$type" );
|
112 |
+
} elseif ( $tsf->is_date() ) {
|
113 |
+
yield 'globals_date' => (bool) $tsf->get_option( "date_$type" );
|
114 |
+
}
|
115 |
+
} elseif ( $tsf->is_search() ) {
|
116 |
+
yield 'globals_search' => (bool) $tsf->get_option( "search_$type" );
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
// is_real_front_page() can still be singular or archive. Thus, this conditional block is split up.
|
121 |
+
if ( $tsf->is_archive() ) {
|
122 |
+
if ( $tsf->is_category() || $tsf->is_tag() || $tsf->is_tax() ) {
|
123 |
+
yield 'globals_taxonomy' => $tsf->is_taxonomy_robots_set( $type, $tsf->get_current_taxonomy() );
|
124 |
+
|
125 |
+
// Store values from each post type bound to the taxonomy.
|
126 |
+
foreach ( $tsf->get_post_types_from_taxonomy() as $post_type )
|
127 |
+
$_is_post_type_robots_set[] = $tsf->is_post_type_robots_set( $type, $post_type );
|
128 |
+
|
129 |
+
// Only enable if _all_ post types have been marked with 'no*'. Return false if no post types are found (corner case).
|
130 |
+
yield 'globals_post_type_all' => isset( $_is_post_type_robots_set ) && ! \in_array( false, $_is_post_type_robots_set, true );
|
131 |
+
} elseif ( \is_post_type_archive() ) {
|
132 |
+
yield 'globals_post_type' => $tsf->is_post_type_robots_set( $type, $tsf->get_current_post_type() );
|
133 |
+
}
|
134 |
+
} elseif ( $tsf->is_singular() ) {
|
135 |
+
yield 'globals_post_type' => $tsf->is_post_type_robots_set( $type, $tsf->get_current_post_type() );
|
136 |
+
}
|
137 |
+
}
|
138 |
+
|
139 |
+
index_protection: if ( $asserting_noindex ) {
|
140 |
+
// We assert options here for a jump to index_protection might be unaware.
|
141 |
+
if ( static::$options & \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION )
|
142 |
+
goto after_index_protection;
|
143 |
+
|
144 |
+
if ( $tsf->is_singular() ) {
|
145 |
+
// A reiteration of the very same code as above... but, homepage may not always be singular.
|
146 |
+
// The conditions below MUST overwrite this, too. So, this is the perfect placement.
|
147 |
+
if ( $tsf->is_real_front_page() )
|
148 |
+
yield from static::assert_noindex_query_pass( 'paged_home' );
|
149 |
+
|
150 |
+
yield from static::assert_noindex_query_pass( 'protected' );
|
151 |
+
|
152 |
+
/**
|
153 |
+
* N.B. WordPress protects this query variable with options 'page_comments'
|
154 |
+
* and 'default_comments_page' via `redirect_canonical()`, so we don't have to.
|
155 |
+
* For reference, it fires `remove_query_arg( 'cpage', $redirect['query'] )`;
|
156 |
+
*/
|
157 |
+
if ( (int) \get_query_var( 'cpage', 0 ) > 0 )
|
158 |
+
yield from static::assert_noindex_query_pass( 'cpage' );
|
159 |
+
}
|
160 |
+
}
|
161 |
+
after_index_protection:;
|
162 |
+
|
163 |
+
exploit_protection: if ( $tsf->is_query_exploited() ) {
|
164 |
+
if ( \in_array( $type, [ 'noindex', 'nofollow' ], true ) )
|
165 |
+
yield 'query_protection' => true;
|
166 |
+
}
|
167 |
+
after_exploit_protection:;
|
168 |
+
|
169 |
+
end:;
|
170 |
+
}
|
171 |
+
// phpcs:enable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
|
172 |
+
// phpcs:enable, PSR2.ControlStructures.SwitchDeclaration.TerminatingComment
|
173 |
+
// phpcs:enable, Generic.WhiteSpace.ScopeIndent.IncorrectExact
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Generates robots assertions for noindex in passes.
|
177 |
+
*
|
178 |
+
* @since 4.2.0
|
179 |
+
* @generator
|
180 |
+
*
|
181 |
+
* @param string $pass The passage to assert.
|
182 |
+
*/
|
183 |
+
private static function assert_noindex_query_pass( $pass ) {
|
184 |
+
// Remit FETCH_STATIC_PROP_R opcode calls every time we'd otherwise use static::$tsf hereinafter.
|
185 |
+
$tsf = static::$tsf;
|
186 |
+
|
187 |
+
switch ( $pass ) :
|
188 |
+
case 'paged_home':
|
189 |
+
yield 'paged_home' => ( $tsf->get_option( 'home_paged_noindex' ) && ( $tsf->page() > 1 || $tsf->paged() > 1 ) );
|
190 |
+
break;
|
191 |
+
|
192 |
+
case '404':
|
193 |
+
if ( $tsf->is_singular_archive() ) :
|
194 |
+
/**
|
195 |
+
* Pagination overflow protection via 404 test.
|
196 |
+
*
|
197 |
+
* When there are no posts, the first page will NOT relay 404;
|
198 |
+
* which is exactly as intended. All other pages will relay 404.
|
199 |
+
*
|
200 |
+
* We do not test the post_count here, because we want to have
|
201 |
+
* the first page indexable via user-intent only. Concordingly, too
|
202 |
+
* because we cannot assert this via the administrative dashboard.
|
203 |
+
*/
|
204 |
+
yield '404' => $tsf->is_404();
|
205 |
+
else :
|
206 |
+
/**
|
207 |
+
* Check for 404, or if archive is empty: set noindex for those.
|
208 |
+
*
|
209 |
+
* Don't check this on the homepage. The homepage is sacred in this regard,
|
210 |
+
* because page builders and templates can and will take over.
|
211 |
+
*
|
212 |
+
* Don't use empty(), null is regarded as indexable; it's why we coalesce to true whence null.
|
213 |
+
*
|
214 |
+
* post_count can be 0, which is false -> thus yield true -> noindex.
|
215 |
+
* post_count can be null, which is true -> thus yield false -> index.
|
216 |
+
* post count can be 5, which is true => thus yield false -> index.
|
217 |
+
*/
|
218 |
+
if ( $GLOBALS['wp_query']->post_count ?? true ) {
|
219 |
+
yield '404' => false;
|
220 |
+
} else {
|
221 |
+
/**
|
222 |
+
* We recommend using this filter ONLY for archives that have useful content but no "posts" attached.
|
223 |
+
* For example: a specially custom-developed author page for an author that never published a post.
|
224 |
+
*
|
225 |
+
* This filter won't run when a few other conditions for noindex have been met.
|
226 |
+
*
|
227 |
+
* @since 4.1.4
|
228 |
+
* @link <https://github.com/sybrew/the-seo-framework/issues/194#issuecomment-864298702>
|
229 |
+
* @param bool $noindex Whether to enable no posts protection.
|
230 |
+
*/
|
231 |
+
yield '404' => (bool) \apply_filters( 'the_seo_framework_enable_noindex_no_posts', true );
|
232 |
+
}
|
233 |
+
endif;
|
234 |
+
break;
|
235 |
+
|
236 |
+
case 'paged':
|
237 |
+
// Advanced Query Protection protects further against pagination attacks. No need to have that here.
|
238 |
+
yield 'paged' => $tsf->get_option( 'paged_noindex' ) && $tsf->paged() > 1;
|
239 |
+
break;
|
240 |
+
|
241 |
+
case 'protected':
|
242 |
+
// We get the "real ID" for WordPress might fault parsing a nefariously forged request.
|
243 |
+
yield 'protected' => $tsf->is_protected( $tsf->get_the_real_ID() );
|
244 |
+
break;
|
245 |
+
|
246 |
+
case 'cpage':
|
247 |
+
/**
|
248 |
+
* We do not recommend using this filter as it'll likely get those pages flagged as
|
249 |
+
* duplicated by Google anyway; unless the theme strips or trims the content.
|
250 |
+
*
|
251 |
+
* This filter won't run when other conditions for noindex have been met.
|
252 |
+
*
|
253 |
+
* @since 4.0.5
|
254 |
+
* @param bool $noindex Whether to enable comment pagination protection.
|
255 |
+
*/
|
256 |
+
yield 'cpage' => \apply_filters( 'the_seo_framework_enable_noindex_comment_pagination', true );
|
257 |
+
break;
|
258 |
+
endswitch;
|
259 |
+
}
|
260 |
+
}
|
@@ -25,17 +25,7 @@ namespace The_SEO_Framework\Builders;
|
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
-
|
29 |
-
* Sets up class loader as file is loaded.
|
30 |
-
* This is done asynchronously, because static calls are handled prior and after.
|
31 |
-
*
|
32 |
-
* @see EOF. Because of the autoloader and (future) trait calling, we can't do it before the class is read.
|
33 |
-
* @link https://bugs.php.net/bug.php?id=75771
|
34 |
-
*/
|
35 |
-
$_load_scripts_class = function() {
|
36 |
-
// phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
|
37 |
-
new Scripts();
|
38 |
-
};
|
39 |
|
40 |
/**
|
41 |
* Registers and outputs admin GUI scripts. Auto-invokes everything the moment
|
@@ -63,8 +53,8 @@ final class Scripts {
|
|
63 |
* @var int <bit 01> REGISTERED
|
64 |
* @var int <bit 10> LOADED (rather, enqueued)
|
65 |
*/
|
66 |
-
const REGISTERED = 0b01;
|
67 |
-
const LOADED = 0b10;
|
68 |
|
69 |
/**
|
70 |
* @since 3.1.0
|
@@ -106,11 +96,12 @@ final class Scripts {
|
|
106 |
*
|
107 |
* @since 3.1.0
|
108 |
*/
|
109 |
-
public static function prepare() {
|
|
|
|
|
110 |
|
111 |
/**
|
112 |
-
* The constructor.
|
113 |
-
* Kills PHP on subsequent duplicated request. Enforces singleton.
|
114 |
*
|
115 |
* This probably autoloads at action "admin_enqueue_scripts", priority "0".
|
116 |
*
|
@@ -118,19 +109,13 @@ final class Scripts {
|
|
118 |
* @access private
|
119 |
* @internal
|
120 |
*/
|
121 |
-
|
122 |
-
|
123 |
-
static $count = 0;
|
124 |
-
0 === $count++ or \wp_die( 'Don\'t instance <code>' . __CLASS__ . '</code>.' );
|
125 |
-
|
126 |
-
static::$instance = &$this;
|
127 |
-
|
128 |
// These fail when called in the body.
|
129 |
\add_filter( 'admin_body_class', [ $this, '_add_body_class' ] );
|
130 |
\add_action( 'in_admin_header', [ $this, '_print_tsfjs_script' ] );
|
131 |
|
132 |
-
\add_action( 'admin_enqueue_scripts', [ $this, '_prepare_admin_scripts' ], 1 );
|
133 |
-
\add_action( 'admin_footer', [ $this, '_output_templates' ], 999 );
|
134 |
}
|
135 |
|
136 |
/**
|
@@ -144,8 +129,8 @@ final class Scripts {
|
|
144 |
* @return string
|
145 |
*/
|
146 |
public function _add_body_class( $classes ) {
|
147 |
-
// Add spaces
|
148 |
-
return
|
149 |
}
|
150 |
|
151 |
/**
|
@@ -184,7 +169,7 @@ final class Scripts {
|
|
184 |
* @return int <bit>
|
185 |
*/
|
186 |
public static function get_status_of( $id, $type ) {
|
187 |
-
return
|
188 |
}
|
189 |
|
190 |
/**
|
@@ -208,7 +193,7 @@ final class Scripts {
|
|
208 |
|
209 |
if ( \The_SEO_Framework\_has_run( __METHOD__ ) ) return;
|
210 |
|
211 |
-
\add_action( 'admin_footer', [ static::class, 'enqueue' ], 998 );
|
212 |
}
|
213 |
|
214 |
/**
|
@@ -245,7 +230,7 @@ final class Scripts {
|
|
245 |
* }
|
246 |
* }
|
247 |
*/
|
248 |
-
public static function register(
|
249 |
if ( array_values( $script ) === $script ) {
|
250 |
foreach ( $script as $s ) static::register( $s );
|
251 |
return;
|
@@ -284,11 +269,10 @@ final class Scripts {
|
|
284 |
|
285 |
static::forward_known_script( $id, $type );
|
286 |
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
}
|
292 |
}
|
293 |
|
294 |
/**
|
@@ -316,7 +300,7 @@ final class Scripts {
|
|
316 |
* @uses static::egister_script()
|
317 |
*/
|
318 |
private function forward_known_scripts() {
|
319 |
-
|
320 |
foreach ( static::$scripts as $s ) {
|
321 |
if ( static::get_status_of( $s['id'], $s['type'] ) & static::REGISTERED ) continue;
|
322 |
static::forward_script( $s );
|
@@ -352,7 +336,7 @@ final class Scripts {
|
|
352 |
*
|
353 |
* @param array $s The script.
|
354 |
*/
|
355 |
-
private static function forward_script(
|
356 |
|
357 |
$instance = static::$instance;
|
358 |
$registered = false;
|
@@ -378,7 +362,7 @@ final class Scripts {
|
|
378 |
if ( $registered ) {
|
379 |
isset( static::$queue[ $s['type'] ][ $s['id'] ] )
|
380 |
and static::$queue[ $s['type'] ][ $s['id'] ] |= static::REGISTERED
|
381 |
-
or static::$queue[ $s['type'] ][ $s['id'] ] = static::REGISTERED;
|
382 |
}
|
383 |
}
|
384 |
|
@@ -409,7 +393,7 @@ final class Scripts {
|
|
409 |
if ( $loaded ) {
|
410 |
isset( static::$queue[ $type ][ $id ] )
|
411 |
and static::$queue[ $type ][ $id ] |= static::LOADED
|
412 |
-
or static::$queue[ $type ][ $id ] = static::LOADED;
|
413 |
}
|
414 |
}
|
415 |
|
@@ -423,12 +407,12 @@ final class Scripts {
|
|
423 |
* @param array $type Either 'js' or 'css'.
|
424 |
* @return string The file URL.
|
425 |
*/
|
426 |
-
private function generate_file_url(
|
427 |
|
428 |
static $min, $rtl;
|
429 |
|
430 |
if ( ! isset( $min, $rtl ) ) {
|
431 |
-
$min = \
|
432 |
$rtl = \is_rtl() ? '.rtl' : '';
|
433 |
}
|
434 |
|
@@ -449,14 +433,16 @@ final class Scripts {
|
|
449 |
* @since 3.1.0
|
450 |
* @uses $this->convert_color_css()
|
451 |
*
|
452 |
-
* @param
|
453 |
* @return string
|
454 |
*/
|
455 |
-
private function create_inline_css(
|
456 |
|
457 |
$out = '';
|
|
|
458 |
foreach ( $styles as $selector => $css ) {
|
459 |
-
$
|
|
|
460 |
}
|
461 |
|
462 |
return $out;
|
@@ -467,15 +453,15 @@ final class Scripts {
|
|
467 |
*
|
468 |
* @since 4.0.0
|
469 |
*
|
470 |
-
* @param
|
471 |
* @return string
|
472 |
*/
|
473 |
-
private function create_inline_js(
|
474 |
|
475 |
$out = '';
|
476 |
-
|
|
|
477 |
$out .= ";$script";
|
478 |
-
}
|
479 |
|
480 |
return $out;
|
481 |
}
|
@@ -488,7 +474,7 @@ final class Scripts {
|
|
488 |
* @param array $css The CSS to convert.
|
489 |
* @return array $css
|
490 |
*/
|
491 |
-
private function convert_color_css(
|
492 |
|
493 |
static $c_ck, $c_cv;
|
494 |
// Memoize the conversion types.
|
@@ -496,10 +482,10 @@ final class Scripts {
|
|
496 |
$_scheme = \get_user_option( 'admin_color' ) ?: 'fresh';
|
497 |
$_colors = $GLOBALS['_wp_admin_css_colors'];
|
498 |
|
499 |
-
$tsf = \
|
500 |
|
501 |
if (
|
502 |
-
! isset( $_colors[ $_scheme ]->colors )
|
503 |
|| ! \is_array( $_colors[ $_scheme ]->colors )
|
504 |
|| \count( $_colors[ $_scheme ]->colors ) < 4 // unexpected scheme, ignore and override.
|
505 |
) {
|
@@ -554,15 +540,15 @@ final class Scripts {
|
|
554 |
* 'args' => array $args. Optional,
|
555 |
* }
|
556 |
*/
|
557 |
-
private function register_template( $id,
|
558 |
-
|
559 |
if ( isset( $templates['file'] ) )
|
560 |
$templates = [ $templates ];
|
561 |
|
562 |
foreach ( $templates as $t ) {
|
563 |
static::$templates[ $id ][] = [
|
564 |
$t['file'],
|
565 |
-
|
566 |
];
|
567 |
}
|
568 |
}
|
@@ -606,21 +592,19 @@ final class Scripts {
|
|
606 |
* @since 3.2.4 Enabled entropy to prevent system sleep.
|
607 |
* @uses static::$include_secret
|
608 |
*
|
609 |
-
* @param string
|
610 |
-
* @param
|
611 |
*/
|
612 |
-
private function output_view( $file,
|
613 |
|
614 |
foreach ( $args as $_key => $_val )
|
615 |
$$_key = $_val;
|
616 |
unset( $_key, $_val, $args );
|
617 |
|
618 |
-
|
619 |
// phpcs:ignore, VariableAnalysis.CodeAnalysis.VariableAnalysis -- Read the include?
|
620 |
static::$include_secret = $_secret = mt_rand() . uniqid( '', true );
|
621 |
include $file;
|
622 |
static::$include_secret = null;
|
623 |
}
|
624 |
}
|
625 |
-
|
626 |
-
$_load_scripts_class();
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
+
Scripts::prepare();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
/**
|
31 |
* Registers and outputs admin GUI scripts. Auto-invokes everything the moment
|
53 |
* @var int <bit 01> REGISTERED
|
54 |
* @var int <bit 10> LOADED (rather, enqueued)
|
55 |
*/
|
56 |
+
private const REGISTERED = 0b01;
|
57 |
+
private const LOADED = 0b10;
|
58 |
|
59 |
/**
|
60 |
* @since 3.1.0
|
96 |
*
|
97 |
* @since 3.1.0
|
98 |
*/
|
99 |
+
public static function prepare() {
|
100 |
+
static::$instance ?? ( static::$instance = new static );
|
101 |
+
}
|
102 |
|
103 |
/**
|
104 |
+
* The constructor.
|
|
|
105 |
*
|
106 |
* This probably autoloads at action "admin_enqueue_scripts", priority "0".
|
107 |
*
|
109 |
* @access private
|
110 |
* @internal
|
111 |
*/
|
112 |
+
private function __construct() {
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
// These fail when called in the body.
|
114 |
\add_filter( 'admin_body_class', [ $this, '_add_body_class' ] );
|
115 |
\add_action( 'in_admin_header', [ $this, '_print_tsfjs_script' ] );
|
116 |
|
117 |
+
\add_action( 'admin_enqueue_scripts', [ $this, '_prepare_admin_scripts' ], 1 ); // Magic number: likely 1 after this is called.
|
118 |
+
\add_action( 'admin_footer', [ $this, '_output_templates' ], 999 ); // Magic number: later is less likely to collide?
|
119 |
}
|
120 |
|
121 |
/**
|
129 |
* @return string
|
130 |
*/
|
131 |
public function _add_body_class( $classes ) {
|
132 |
+
// Add spaces on both sides, because who knows what others do.
|
133 |
+
return " tsf-no-js $classes";
|
134 |
}
|
135 |
|
136 |
/**
|
169 |
* @return int <bit>
|
170 |
*/
|
171 |
public static function get_status_of( $id, $type ) {
|
172 |
+
return static::$queue[ $type ][ $id ] ?? 0b0;
|
173 |
}
|
174 |
|
175 |
/**
|
193 |
|
194 |
if ( \The_SEO_Framework\_has_run( __METHOD__ ) ) return;
|
195 |
|
196 |
+
\add_action( 'admin_footer', [ static::class, 'enqueue' ], 998 ); // Magic number: 1 before output_templates.
|
197 |
}
|
198 |
|
199 |
/**
|
230 |
* }
|
231 |
* }
|
232 |
*/
|
233 |
+
public static function register( $script ) {
|
234 |
if ( array_values( $script ) === $script ) {
|
235 |
foreach ( $script as $s ) static::register( $s );
|
236 |
return;
|
269 |
|
270 |
static::forward_known_script( $id, $type );
|
271 |
|
272 |
+
$status = static::get_status_of( $id, $type );
|
273 |
+
|
274 |
+
if ( ( $status & static::REGISTERED ) && ! ( $status & static::LOADED ) )
|
275 |
+
static::load_script( $id, $type );
|
|
|
276 |
}
|
277 |
|
278 |
/**
|
300 |
* @uses static::egister_script()
|
301 |
*/
|
302 |
private function forward_known_scripts() {
|
303 |
+
// Register them first to accomodate for dependencies.
|
304 |
foreach ( static::$scripts as $s ) {
|
305 |
if ( static::get_status_of( $s['id'], $s['type'] ) & static::REGISTERED ) continue;
|
306 |
static::forward_script( $s );
|
336 |
*
|
337 |
* @param array $s The script.
|
338 |
*/
|
339 |
+
private static function forward_script( $s ) {
|
340 |
|
341 |
$instance = static::$instance;
|
342 |
$registered = false;
|
362 |
if ( $registered ) {
|
363 |
isset( static::$queue[ $s['type'] ][ $s['id'] ] )
|
364 |
and static::$queue[ $s['type'] ][ $s['id'] ] |= static::REGISTERED
|
365 |
+
or static::$queue[ $s['type'] ][ $s['id'] ] = static::REGISTERED;
|
366 |
}
|
367 |
}
|
368 |
|
393 |
if ( $loaded ) {
|
394 |
isset( static::$queue[ $type ][ $id ] )
|
395 |
and static::$queue[ $type ][ $id ] |= static::LOADED
|
396 |
+
or static::$queue[ $type ][ $id ] = static::LOADED;
|
397 |
}
|
398 |
}
|
399 |
|
407 |
* @param array $type Either 'js' or 'css'.
|
408 |
* @return string The file URL.
|
409 |
*/
|
410 |
+
private function generate_file_url( $script, $type = 'js' ) {
|
411 |
|
412 |
static $min, $rtl;
|
413 |
|
414 |
if ( ! isset( $min, $rtl ) ) {
|
415 |
+
$min = \tsf()->script_debug ? '' : '.min';
|
416 |
$rtl = \is_rtl() ? '.rtl' : '';
|
417 |
}
|
418 |
|
433 |
* @since 3.1.0
|
434 |
* @uses $this->convert_color_css()
|
435 |
*
|
436 |
+
* @param iterable $styles The styles to add.
|
437 |
* @return string
|
438 |
*/
|
439 |
+
private function create_inline_css( $styles ) {
|
440 |
|
441 |
$out = '';
|
442 |
+
|
443 |
foreach ( $styles as $selector => $css ) {
|
444 |
+
$css = implode( ';', $this->convert_color_css( $css ) );
|
445 |
+
$out .= "$selector{$css}";
|
446 |
}
|
447 |
|
448 |
return $out;
|
453 |
*
|
454 |
* @since 4.0.0
|
455 |
*
|
456 |
+
* @param iterable $scripts The scripts to add.
|
457 |
* @return string
|
458 |
*/
|
459 |
+
private function create_inline_js( $scripts ) {
|
460 |
|
461 |
$out = '';
|
462 |
+
|
463 |
+
foreach ( $scripts as $script )
|
464 |
$out .= ";$script";
|
|
|
465 |
|
466 |
return $out;
|
467 |
}
|
474 |
* @param array $css The CSS to convert.
|
475 |
* @return array $css
|
476 |
*/
|
477 |
+
private function convert_color_css( $css ) {
|
478 |
|
479 |
static $c_ck, $c_cv;
|
480 |
// Memoize the conversion types.
|
482 |
$_scheme = \get_user_option( 'admin_color' ) ?: 'fresh';
|
483 |
$_colors = $GLOBALS['_wp_admin_css_colors'];
|
484 |
|
485 |
+
$tsf = \tsf();
|
486 |
|
487 |
if (
|
488 |
+
! isset( $_colors[ $_scheme ]->colors )
|
489 |
|| ! \is_array( $_colors[ $_scheme ]->colors )
|
490 |
|| \count( $_colors[ $_scheme ]->colors ) < 4 // unexpected scheme, ignore and override.
|
491 |
) {
|
540 |
* 'args' => array $args. Optional,
|
541 |
* }
|
542 |
*/
|
543 |
+
private function register_template( $id, $templates ) {
|
544 |
+
// Wrap template if it's only one on the base.
|
545 |
if ( isset( $templates['file'] ) )
|
546 |
$templates = [ $templates ];
|
547 |
|
548 |
foreach ( $templates as $t ) {
|
549 |
static::$templates[ $id ][] = [
|
550 |
$t['file'],
|
551 |
+
$t['args'] ?? [],
|
552 |
];
|
553 |
}
|
554 |
}
|
592 |
* @since 3.2.4 Enabled entropy to prevent system sleep.
|
593 |
* @uses static::$include_secret
|
594 |
*
|
595 |
+
* @param string $file The file location.
|
596 |
+
* @param iterable $args The registered view arguments.
|
597 |
*/
|
598 |
+
private function output_view( $file, $args ) {
|
599 |
|
600 |
foreach ( $args as $_key => $_val )
|
601 |
$$_key = $_val;
|
602 |
unset( $_key, $_val, $args );
|
603 |
|
604 |
+
// Prevents private-includes hijacking.
|
605 |
// phpcs:ignore, VariableAnalysis.CodeAnalysis.VariableAnalysis -- Read the include?
|
606 |
static::$include_secret = $_secret = mt_rand() . uniqid( '', true );
|
607 |
include $file;
|
608 |
static::$include_secret = null;
|
609 |
}
|
610 |
}
|
|
|
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Tell me and I forget. Teach me and I remember. Involve me and I learn.
|
4 |
+
*
|
5 |
+
* - Benjamin Franklin
|
6 |
+
*/
|
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* @package The_SEO_Framework\Classes\Builders\
|
4 |
-
* @subpackage The_SEO_Framework\
|
5 |
*/
|
6 |
|
7 |
-
namespace The_SEO_Framework\Builders;
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
@@ -29,17 +29,18 @@ namespace The_SEO_Framework\Builders;
|
|
29 |
* Generates the SEO Bar.
|
30 |
*
|
31 |
* @since 4.0.0
|
|
|
32 |
* Mind the late static binding. We use "self" if the variable is shared between instances.
|
33 |
* We use "static" if the variable isn't shared between instances.
|
34 |
* @link <https://www.php.net/manual/en/language.oop5.late-static-bindings.php>
|
35 |
*
|
36 |
* @access private
|
37 |
-
* Use \The_SEO_Framework\Interpreters\
|
38 |
* @internal
|
39 |
* @abstract Implements test_{$*}, see property $tests and method `_run_test()` for what * may be.
|
40 |
-
* @see \The_SEO_Framework\Interpreters\
|
41 |
*/
|
42 |
-
abstract class
|
43 |
|
44 |
/**
|
45 |
* @since 4.0.0
|
@@ -80,7 +81,7 @@ abstract class SeoBar {
|
|
80 |
/**
|
81 |
* @since 4.0.0
|
82 |
* Not shared between instances
|
83 |
-
* @var \The_SEO_Framework\Builders\
|
84 |
*/
|
85 |
protected static $instance;
|
86 |
|
@@ -92,8 +93,7 @@ abstract class SeoBar {
|
|
92 |
* @since 4.0.0
|
93 |
*/
|
94 |
final protected function __construct() {
|
95 |
-
|
96 |
-
self::$tsf = self::$tsf ?: \the_seo_framework();
|
97 |
$this->prime_cache();
|
98 |
}
|
99 |
|
@@ -105,8 +105,7 @@ abstract class SeoBar {
|
|
105 |
* @return static
|
106 |
*/
|
107 |
final public static function get_instance() {
|
108 |
-
static::$instance
|
109 |
-
return static::$instance;
|
110 |
}
|
111 |
|
112 |
/**
|
@@ -133,17 +132,15 @@ abstract class SeoBar {
|
|
133 |
* @return mixed|null The cache value. Null on failure.
|
134 |
*/
|
135 |
final protected static function get_cache( $key ) {
|
136 |
-
return
|
137 |
}
|
138 |
|
139 |
/**
|
140 |
* Runs all SEO bar tests.
|
141 |
*
|
142 |
-
* @since
|
143 |
* @access private
|
144 |
* @generator
|
145 |
-
* @TODO only available from PHP 7+
|
146 |
-
* @ignore
|
147 |
*
|
148 |
* @param array $query : {
|
149 |
* int $id : Required. The current post or term ID.
|
@@ -155,11 +152,9 @@ abstract class SeoBar {
|
|
155 |
* string $test => array The testing results.
|
156 |
* }
|
157 |
*/
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
// }
|
162 |
-
// phpcs:enable, Squiz.PHP.CommentedOutCode
|
163 |
|
164 |
/**
|
165 |
* Runs one or more SEO bar tests.
|
@@ -180,7 +175,7 @@ abstract class SeoBar {
|
|
180 |
* string $test => array $item The SEO Bar compatible results.
|
181 |
* }
|
182 |
*/
|
183 |
-
final public function _run_test( $tests,
|
184 |
|
185 |
$tests = array_intersect( static::$tests, (array) $tests );
|
186 |
|
1 |
<?php
|
2 |
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Builders\SEOBar\Main
|
4 |
+
* @subpackage The_SEO_Framework\SEOBar
|
5 |
*/
|
6 |
|
7 |
+
namespace The_SEO_Framework\Builders\SEOBar;
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
29 |
* Generates the SEO Bar.
|
30 |
*
|
31 |
* @since 4.0.0
|
32 |
+
* @since 4.2.0 Renamed to `The_SEO_Framework\Builders\SEOBar\Main` from `The_SEO_Framework\Builders\SeoBar`
|
33 |
* Mind the late static binding. We use "self" if the variable is shared between instances.
|
34 |
* We use "static" if the variable isn't shared between instances.
|
35 |
* @link <https://www.php.net/manual/en/language.oop5.late-static-bindings.php>
|
36 |
*
|
37 |
* @access private
|
38 |
+
* Use \The_SEO_Framework\Interpreters\SEOBar::generate_bar() instead.
|
39 |
* @internal
|
40 |
* @abstract Implements test_{$*}, see property $tests and method `_run_test()` for what * may be.
|
41 |
+
* @see \The_SEO_Framework\Interpreters\SEOBar
|
42 |
*/
|
43 |
+
abstract class Main {
|
44 |
|
45 |
/**
|
46 |
* @since 4.0.0
|
81 |
/**
|
82 |
* @since 4.0.0
|
83 |
* Not shared between instances
|
84 |
+
* @var \The_SEO_Framework\Builders\SEOBar_* $instance The instance.
|
85 |
*/
|
86 |
protected static $instance;
|
87 |
|
93 |
* @since 4.0.0
|
94 |
*/
|
95 |
final protected function __construct() {
|
96 |
+
self::$tsf = self::$tsf ?: \tsf();
|
|
|
97 |
$this->prime_cache();
|
98 |
}
|
99 |
|
105 |
* @return static
|
106 |
*/
|
107 |
final public static function get_instance() {
|
108 |
+
return static::$instance ?? ( static::$instance = new static );
|
|
|
109 |
}
|
110 |
|
111 |
/**
|
132 |
* @return mixed|null The cache value. Null on failure.
|
133 |
*/
|
134 |
final protected static function get_cache( $key ) {
|
135 |
+
return self::$cache[ $key ] ?? null;
|
136 |
}
|
137 |
|
138 |
/**
|
139 |
* Runs all SEO bar tests.
|
140 |
*
|
141 |
+
* @since 4.2.0
|
142 |
* @access private
|
143 |
* @generator
|
|
|
|
|
144 |
*
|
145 |
* @param array $query : {
|
146 |
* int $id : Required. The current post or term ID.
|
152 |
* string $test => array The testing results.
|
153 |
* }
|
154 |
*/
|
155 |
+
public function _run_all_tests( $query ) {
|
156 |
+
yield from $this->_run_test( static::$tests, $query );
|
157 |
+
}
|
|
|
|
|
158 |
|
159 |
/**
|
160 |
* Runs one or more SEO bar tests.
|
175 |
* string $test => array $item The SEO Bar compatible results.
|
176 |
* }
|
177 |
*/
|
178 |
+
final public function _run_test( $tests, $query ) {
|
179 |
|
180 |
$tests = array_intersect( static::$tests, (array) $tests );
|
181 |
|
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* @package The_SEO_Framework\Classes\Builders\
|
4 |
-
* @subpackage The_SEO_Framework\
|
5 |
*/
|
6 |
|
7 |
-
namespace The_SEO_Framework\Builders;
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
@@ -29,13 +29,14 @@ namespace The_SEO_Framework\Builders;
|
|
29 |
* Generates the SEO Bar for posts.
|
30 |
*
|
31 |
* @since 4.0.0
|
|
|
32 |
*
|
33 |
* @access private
|
34 |
* @internal
|
35 |
-
* @see \The_SEO_Framework\Interpreters\
|
36 |
-
* Use \The_SEO_Framework\Interpreters\
|
37 |
*/
|
38 |
-
final class
|
39 |
|
40 |
/**
|
41 |
* @since 4.0.0
|
@@ -92,21 +93,25 @@ final class SeoBar_Page extends SeoBar {
|
|
92 |
'post' => \get_post( static::$query['id'] ),
|
93 |
'meta' => static::$tsf->get_post_meta( static::$query['id'], true ), // Use TSF cache--TSF initializes it anyway.
|
94 |
'states' => [
|
95 |
-
'ishome'
|
96 |
-
'locale'
|
97 |
-
'isprotected'
|
98 |
-
'isdraft'
|
99 |
-
'robotsmeta'
|
100 |
[
|
101 |
'noindex' => false,
|
102 |
'nofollow' => false,
|
103 |
'noarchive' => false,
|
104 |
],
|
105 |
-
static::$tsf->generate_robots_meta(
|
106 |
-
'id'
|
107 |
-
'
|
108 |
-
|
|
|
109 |
),
|
|
|
|
|
|
|
110 |
],
|
111 |
];
|
112 |
}
|
@@ -132,7 +137,7 @@ final class SeoBar_Page extends SeoBar {
|
|
132 |
* @return array $item : {
|
133 |
* string $symbol : The displayed symbol that identifies your bar.
|
134 |
* string $title : The title of the assessment.
|
135 |
-
* int $status : Power of two. See \The_SEO_Framework\Interpreters\
|
136 |
* string $reason : The final assessment: The reason for the $status. The latest state-changing reason is used.
|
137 |
* string $assess : The assessments on why the reason is set. Keep it short and concise!
|
138 |
* Does not accept HTML for performant ARIA support.
|
@@ -168,7 +173,7 @@ final class SeoBar_Page extends SeoBar {
|
|
168 |
],
|
169 |
'reason' => [
|
170 |
'incomplete' => \__( 'Incomplete.', 'autodescription' ),
|
171 |
-
'duplicated' => \__( 'The branding is
|
172 |
'notbranded' => \__( 'Not branded.', 'autodescription' ),
|
173 |
'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
|
174 |
],
|
@@ -176,7 +181,7 @@ final class SeoBar_Page extends SeoBar {
|
|
176 |
'generated' => [
|
177 |
'symbol' => \_x( 'TG', 'Title Generated', 'autodescription' ),
|
178 |
'title' => \__( 'Title, generated', 'autodescription' ),
|
179 |
-
'status' => \The_SEO_Framework\Interpreters\
|
180 |
'reason' => \__( 'Automatically generated.', 'autodescription' ),
|
181 |
'assess' => [
|
182 |
'base' => \__( "It's built from the page title.", 'autodescription' ),
|
@@ -185,7 +190,7 @@ final class SeoBar_Page extends SeoBar {
|
|
185 |
'custom' => [
|
186 |
'symbol' => \_x( 'T', 'Title', 'autodescription' ),
|
187 |
'title' => \__( 'Title', 'autodescription' ),
|
188 |
-
'status' => \The_SEO_Framework\Interpreters\
|
189 |
'reason' => \__( 'Obtained from page SEO meta input.', 'autodescription' ),
|
190 |
'assess' => [
|
191 |
'base' => \__( "It's built from page SEO meta input.", 'autodescription' ),
|
@@ -195,14 +200,11 @@ final class SeoBar_Page extends SeoBar {
|
|
195 |
]
|
196 |
);
|
197 |
|
198 |
-
$title_args = [
|
199 |
-
'id' => static::$query['id'],
|
200 |
-
'taxonomy' => '',
|
201 |
-
];
|
202 |
|
203 |
// TODO instead of getting values from the options API, why don't we store the parameters and allow them to be modified?
|
204 |
// This way, we can implement real-time live-edit AJAX SEO bar items...
|
205 |
-
$title_part = static::$tsf->get_filtered_raw_custom_field_title( $title_args
|
206 |
|
207 |
if ( \strlen( $title_part ) ) {
|
208 |
$item = $cache['defaults']['custom'];
|
@@ -217,7 +219,7 @@ final class SeoBar_Page extends SeoBar {
|
|
217 |
}
|
218 |
|
219 |
if ( static::$tsf->has_yoast_syntax( $title_part ) ) {
|
220 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
221 |
$item['reason'] = $cache['reason']['syntax'];
|
222 |
$item['assess']['syntax'] = $cache['assess']['syntax'];
|
223 |
|
@@ -232,18 +234,18 @@ final class SeoBar_Page extends SeoBar {
|
|
232 |
$item['assess']['base'] = \__( "It's built using the site title.", 'autodescription' );
|
233 |
}
|
234 |
|
235 |
-
$title_part = static::$tsf->get_filtered_raw_generated_title( $title_args
|
236 |
}
|
237 |
|
238 |
if ( ! $title_part ) {
|
239 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
240 |
$item['reason'] = $cache['reason']['incomplete'];
|
241 |
$item['assess']['empty'] = $cache['assess']['empty'];
|
242 |
|
243 |
// Further assessments must be made later. Halt assertion here to prevent confusion.
|
244 |
return $item;
|
245 |
} elseif ( $title_part === $cache['params']['untitled'] ) {
|
246 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
247 |
$item['reason'] = $cache['reason']['incomplete'];
|
248 |
$item['assess']['untitled'] = $cache['assess']['untitled'];
|
249 |
|
@@ -283,24 +285,21 @@ final class SeoBar_Page extends SeoBar {
|
|
283 |
}
|
284 |
}
|
285 |
|
286 |
-
|
287 |
-
$brand_count =
|
288 |
-
\strlen( $cache['params']['blogname_quoted'] )
|
289 |
? preg_match_all(
|
290 |
"/{$cache['params']['blogname_quoted']}/ui",
|
291 |
$title,
|
292 |
$matches
|
293 |
)
|
294 |
: 0;
|
295 |
-
// phpcs:enable, PEAR.Functions.FunctionCallSignature.Indent
|
296 |
|
297 |
if ( ! $brand_count ) {
|
298 |
// Override branding state.
|
299 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
300 |
$item['reason'] = $cache['reason']['notbranded'];
|
301 |
$item['assess']['branding'] = $cache['assess']['branding']['not'];
|
302 |
} elseif ( $brand_count > 1 ) {
|
303 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
304 |
$item['reason'] = $cache['reason']['duplicated'];
|
305 |
$item['assess']['duplicated'] = $cache['assess']['duplicated'];
|
306 |
|
@@ -319,19 +318,19 @@ final class SeoBar_Page extends SeoBar {
|
|
319 |
$guidelines_i18n = static::get_cache( 'general/i18n/inputguidelines' );
|
320 |
|
321 |
if ( $title_len < $guidelines['lower'] ) {
|
322 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
323 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooShort'];
|
324 |
$length_i18n = $guidelines_i18n['long']['farTooShort'];
|
325 |
} elseif ( $title_len < $guidelines['goodLower'] ) {
|
326 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
327 |
$item['reason'] = $guidelines_i18n['shortdot']['tooShort'];
|
328 |
$length_i18n = $guidelines_i18n['long']['tooShort'];
|
329 |
} elseif ( $title_len > $guidelines['upper'] ) {
|
330 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
331 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooLong'];
|
332 |
$length_i18n = $guidelines_i18n['long']['farTooLong'];
|
333 |
} elseif ( $title_len > $guidelines['goodUpper'] ) {
|
334 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
335 |
$item['reason'] = $guidelines_i18n['shortdot']['tooLong'];
|
336 |
$length_i18n = $guidelines_i18n['long']['tooLong'];
|
337 |
} else {
|
@@ -377,21 +376,21 @@ final class SeoBar_Page extends SeoBar {
|
|
377 |
'builder' => \__( 'A page builder is used that renders content dynamically, so no description can be generated for performance and privacy reasons. Consider providing a custom description.', 'autodescription' ),
|
378 |
'protected' => \__( 'The page is protected, so no description is generated.', 'autodescription' ),
|
379 |
'excerpt' => \__( "It's built from the page excerpt field.", 'autodescription' ),
|
380 |
-
/* translators: %s = list of
|
381 |
-
'dupes' => \__( 'Found
|
382 |
'syntax' => \__( "Markup syntax was found that isn't transformed. Consider rewriting the custom description.", 'autodescription' ),
|
383 |
],
|
384 |
'reason' => [
|
385 |
'empty' => \__( 'Empty.', 'autodescription' ),
|
386 |
-
'founddupe' => \__( 'Found
|
387 |
-
'foundmanydupe' => \__( 'Found too many
|
388 |
'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
|
389 |
],
|
390 |
'defaults' => [
|
391 |
'generated' => [
|
392 |
'symbol' => \_x( 'DG', 'Description Generated', 'autodescription' ),
|
393 |
'title' => \__( 'Description, generated', 'autodescription' ),
|
394 |
-
'status' => \The_SEO_Framework\Interpreters\
|
395 |
'reason' => \__( 'Automatically generated.', 'autodescription' ),
|
396 |
'assess' => [
|
397 |
'base' => \__( "It's built from the page content.", 'autodescription' ),
|
@@ -400,7 +399,7 @@ final class SeoBar_Page extends SeoBar {
|
|
400 |
'emptynoauto' => [
|
401 |
'symbol' => \_x( 'D', 'Description', 'autodescription' ),
|
402 |
'title' => \__( 'Description', 'autodescription' ),
|
403 |
-
'status' => \The_SEO_Framework\Interpreters\
|
404 |
'reason' => \__( 'Empty.', 'autodescription' ),
|
405 |
'assess' => [
|
406 |
'noauto' => \__( 'No page description is set.', 'autodescription' ),
|
@@ -409,7 +408,7 @@ final class SeoBar_Page extends SeoBar {
|
|
409 |
'custom' => [
|
410 |
'symbol' => \_x( 'D', 'Description', 'autodescription' ),
|
411 |
'title' => \__( 'Description', 'autodescription' ),
|
412 |
-
'status' => \The_SEO_Framework\Interpreters\
|
413 |
'reason' => \__( 'Obtained from the page SEO meta input.', 'autodescription' ),
|
414 |
'assess' => [
|
415 |
'base' => \__( "It's built from the page SEO meta input.", 'autodescription' ),
|
@@ -419,10 +418,7 @@ final class SeoBar_Page extends SeoBar {
|
|
419 |
]
|
420 |
);
|
421 |
|
422 |
-
$desc_args = [
|
423 |
-
'id' => static::$query['id'],
|
424 |
-
'taxonomy' => '',
|
425 |
-
];
|
426 |
|
427 |
// TODO instead of getting values from the options API, why don't we store the parameters and allow them to be modified?
|
428 |
// This way, we can implement real-time live-edit AJAX SEO bar items...
|
@@ -441,7 +437,7 @@ final class SeoBar_Page extends SeoBar {
|
|
441 |
}
|
442 |
|
443 |
if ( static::$tsf->has_yoast_syntax( $desc ) ) {
|
444 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
445 |
$item['reason'] = $cache['reason']['syntax'];
|
446 |
$item['assess']['syntax'] = $cache['assess']['syntax'];
|
447 |
|
@@ -466,13 +462,13 @@ final class SeoBar_Page extends SeoBar {
|
|
466 |
unset( $item['assess']['base'] );
|
467 |
|
468 |
if ( static::$tsf->uses_non_html_page_builder( static::$query['id'] ) ) {
|
469 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
470 |
$item['assess']['empty'] = $cache['assess']['builder'];
|
471 |
} elseif ( static::$tsf->is_protected( static::$query['id'] ) ) {
|
472 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
473 |
$item['assess']['empty'] = $cache['assess']['protected'];
|
474 |
} else {
|
475 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
476 |
$item['assess']['empty'] = $cache['assess']['empty'];
|
477 |
}
|
478 |
|
@@ -486,11 +482,11 @@ final class SeoBar_Page extends SeoBar {
|
|
486 |
}
|
487 |
|
488 |
// Fetch words that are outputted more than 3 times.
|
489 |
-
$
|
490 |
|
491 |
-
if ( $
|
492 |
$dupes = [];
|
493 |
-
foreach ( $
|
494 |
// Keep abbreviations... WordPress, make multibyte support mandatory already.
|
495 |
// $_word = ctype_upper( reset( $_dw ) ) ? reset( $_dw ) : mb_strtolower( reset( $_dw ) );
|
496 |
|
@@ -504,18 +500,18 @@ final class SeoBar_Page extends SeoBar {
|
|
504 |
|
505 |
$item['assess']['dupe'] = implode( ' ', $dupes );
|
506 |
|
507 |
-
$max = max( $
|
508 |
$max = reset( $max );
|
509 |
|
510 |
// Warn when more than 3x triplet+/quintet+ words are found.
|
511 |
-
if ( $max > 3 || \count( $
|
512 |
// This must be resolved.
|
513 |
$item['reason'] = $cache['reason']['foundmanydupe'];
|
514 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
515 |
return $item;
|
516 |
} else {
|
517 |
$item['reason'] = $cache['reason']['founddupe'];
|
518 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
519 |
}
|
520 |
}
|
521 |
|
@@ -530,19 +526,19 @@ final class SeoBar_Page extends SeoBar {
|
|
530 |
);
|
531 |
|
532 |
if ( $desc_len < $guidelines['lower'] ) {
|
533 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
534 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooShort'];
|
535 |
$length_i18n = $guidelines_i18n['long']['farTooShort'];
|
536 |
} elseif ( $desc_len < $guidelines['goodLower'] ) {
|
537 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
538 |
$item['reason'] = $guidelines_i18n['shortdot']['tooShort'];
|
539 |
$length_i18n = $guidelines_i18n['long']['tooShort'];
|
540 |
} elseif ( $desc_len > $guidelines['upper'] ) {
|
541 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
542 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooLong'];
|
543 |
$length_i18n = $guidelines_i18n['long']['farTooLong'];
|
544 |
} elseif ( $desc_len > $guidelines['goodUpper'] ) {
|
545 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
546 |
$item['reason'] = $guidelines_i18n['shortdot']['tooLong'];
|
547 |
$length_i18n = $guidelines_i18n['long']['tooLong'];
|
548 |
} else {
|
@@ -592,7 +588,7 @@ final class SeoBar_Page extends SeoBar {
|
|
592 |
'index' => [
|
593 |
'symbol' => \_x( 'I', 'Indexing', 'autodescription' ),
|
594 |
'title' => \__( 'Indexing', 'autodescription' ),
|
595 |
-
'status' => \The_SEO_Framework\Interpreters\
|
596 |
'reason' => \__( 'Page may be indexed.', 'autodescription' ),
|
597 |
'assess' => [
|
598 |
'base' => \__( 'The robots meta tag allows indexing.', 'autodescription' ),
|
@@ -601,7 +597,7 @@ final class SeoBar_Page extends SeoBar {
|
|
601 |
'noindex' => [
|
602 |
'symbol' => \_x( 'I', 'Indexing', 'autodescription' ),
|
603 |
'title' => \__( 'Indexing', 'autodescription' ),
|
604 |
-
'status' => \The_SEO_Framework\Interpreters\
|
605 |
'reason' => \__( 'Page may not be indexed.', 'autodescription' ),
|
606 |
'assess' => [
|
607 |
'base' => \__( 'The robots meta tag does not allow indexing.', 'autodescription' ),
|
@@ -610,7 +606,7 @@ final class SeoBar_Page extends SeoBar {
|
|
610 |
'draft' => [
|
611 |
'symbol' => \_x( 'I', 'Indexing', 'autodescription' ),
|
612 |
'title' => \__( 'Indexing', 'autodescription' ),
|
613 |
-
'status' => \The_SEO_Framework\Interpreters\
|
614 |
'reason' => \__( 'Page is invisible.', 'autodescription' ),
|
615 |
'assess' => [
|
616 |
'base' => \__( "This page isn't published and can't be found publicly.", 'autodescription' ),
|
@@ -633,7 +629,7 @@ final class SeoBar_Page extends SeoBar {
|
|
633 |
$robots_global = static::get_cache( 'general/detect/robotsglobal' );
|
634 |
|
635 |
if ( ! $robots_global['blogpublic'] ) {
|
636 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
637 |
$item['reason'] = $cache['reason']['notpublic'];
|
638 |
|
639 |
unset( $item['assess']['base'] );
|
@@ -650,7 +646,7 @@ final class SeoBar_Page extends SeoBar {
|
|
650 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
651 |
// Don't trickle when noindex is not set, as this may be filtered.
|
652 |
if ( $this->query_cache['states']['isprotected'] ) {
|
653 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
654 |
$item['reason'] = $cache['reason']['protected'];
|
655 |
|
656 |
$item['assess']['protected'] = $cache['assess']['protected'];
|
@@ -688,7 +684,7 @@ final class SeoBar_Page extends SeoBar {
|
|
688 |
'get_custom_field' => true,
|
689 |
] );
|
690 |
if ( $permalink !== $canonical ) {
|
691 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
692 |
$item['reason'] = $cache['reason']['canonicalurl'];
|
693 |
|
694 |
$item['assess']['protected'] = $cache['assess']['canonicalurl'];
|
@@ -746,7 +742,7 @@ final class SeoBar_Page extends SeoBar {
|
|
746 |
'follow' => [
|
747 |
'symbol' => \_x( 'F', 'Following', 'autodescription' ),
|
748 |
'title' => \__( 'Following', 'autodescription' ),
|
749 |
-
'status' => \The_SEO_Framework\Interpreters\
|
750 |
'reason' => \__( 'Page links may be followed.', 'autodescription' ),
|
751 |
'assess' => [
|
752 |
'base' => \__( 'The robots meta tag allows link following.', 'autodescription' ),
|
@@ -755,7 +751,7 @@ final class SeoBar_Page extends SeoBar {
|
|
755 |
'nofollow' => [
|
756 |
'symbol' => \_x( 'F', 'Following', 'autodescription' ),
|
757 |
'title' => \__( 'Following', 'autodescription' ),
|
758 |
-
'status' => \The_SEO_Framework\Interpreters\
|
759 |
'reason' => \__( 'Page links may not be followed.', 'autodescription' ),
|
760 |
'assess' => [
|
761 |
'base' => \__( 'The robots meta tag does not allow link following.', 'autodescription' ),
|
@@ -764,7 +760,7 @@ final class SeoBar_Page extends SeoBar {
|
|
764 |
'draft' => [
|
765 |
'symbol' => \_x( 'F', 'Following', 'autodescription' ),
|
766 |
'title' => \__( 'Following', 'autodescription' ),
|
767 |
-
'status' => \The_SEO_Framework\Interpreters\
|
768 |
'reason' => \__( 'Page is invisible.', 'autodescription' ),
|
769 |
'assess' => [
|
770 |
'base' => \__( "This page isn't published and can't be found publicly.", 'autodescription' ),
|
@@ -787,7 +783,7 @@ final class SeoBar_Page extends SeoBar {
|
|
787 |
$robots_global = static::get_cache( 'general/detect/robotsglobal' );
|
788 |
|
789 |
if ( ! $robots_global['blogpublic'] ) {
|
790 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
791 |
$item['reason'] = $cache['reason']['notpublic'];
|
792 |
|
793 |
unset( $item['assess']['base'] );
|
@@ -834,7 +830,7 @@ final class SeoBar_Page extends SeoBar {
|
|
834 |
|
835 |
if ( ! $this->query_cache['states']['robotsmeta']['nofollow'] ) {
|
836 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
837 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
838 |
$item['assess']['noindex'] = $cache['assess']['noindex'];
|
839 |
}
|
840 |
|
@@ -877,7 +873,7 @@ final class SeoBar_Page extends SeoBar {
|
|
877 |
'archive' => [
|
878 |
'symbol' => \_x( 'A', 'Archiving', 'autodescription' ),
|
879 |
'title' => \__( 'Archiving', 'autodescription' ),
|
880 |
-
'status' => \The_SEO_Framework\Interpreters\
|
881 |
'reason' => \__( 'Page may be archived.', 'autodescription' ),
|
882 |
'assess' => [
|
883 |
'base' => \__( 'The robots meta tag allows archiving.', 'autodescription' ),
|
@@ -886,7 +882,7 @@ final class SeoBar_Page extends SeoBar {
|
|
886 |
'noarchive' => [
|
887 |
'symbol' => \_x( 'A', 'Archiving', 'autodescription' ),
|
888 |
'title' => \__( 'Archiving', 'autodescription' ),
|
889 |
-
'status' => \The_SEO_Framework\Interpreters\
|
890 |
'reason' => \__( 'Page may not be archived.', 'autodescription' ),
|
891 |
'assess' => [
|
892 |
'base' => \__( 'The robots meta tag does not allow archiving.', 'autodescription' ),
|
@@ -895,7 +891,7 @@ final class SeoBar_Page extends SeoBar {
|
|
895 |
'draft' => [
|
896 |
'symbol' => \_x( 'A', 'Archiving', 'autodescription' ),
|
897 |
'title' => \__( 'Archiving', 'autodescription' ),
|
898 |
-
'status' => \The_SEO_Framework\Interpreters\
|
899 |
'reason' => \__( 'Page is invisible.', 'autodescription' ),
|
900 |
'assess' => [
|
901 |
'base' => \__( "This page isn't published and can't be found publicly.", 'autodescription' ),
|
@@ -918,7 +914,7 @@ final class SeoBar_Page extends SeoBar {
|
|
918 |
$robots_global = static::get_cache( 'general/detect/robotsglobal' );
|
919 |
|
920 |
if ( ! $robots_global['blogpublic'] ) {
|
921 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
922 |
$item['reason'] = $cache['reason']['notpublic'];
|
923 |
|
924 |
unset( $item['assess']['base'] );
|
@@ -965,7 +961,7 @@ final class SeoBar_Page extends SeoBar {
|
|
965 |
|
966 |
if ( ! $this->query_cache['states']['robotsmeta']['noarchive'] ) {
|
967 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
968 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
969 |
$item['assess']['noindex'] = $cache['assess']['noindex'];
|
970 |
}
|
971 |
|
@@ -989,28 +985,33 @@ final class SeoBar_Page extends SeoBar {
|
|
989 |
protected function test_redirect() {
|
990 |
|
991 |
if ( empty( $this->query_cache['meta']['redirect'] ) ) {
|
992 |
-
|
993 |
'page/redirect/default/0',
|
994 |
[
|
995 |
'symbol' => \_x( 'R', 'Redirect', 'autodescription' ),
|
996 |
'title' => \__( 'Redirection', 'autodescription' ),
|
997 |
-
'status' => \The_SEO_Framework\Interpreters\
|
998 |
'reason' => \__( 'Page does not redirect visitors.', 'autodescription' ),
|
999 |
'assess' => [
|
1000 |
-
'redirect' => \__( '
|
1001 |
],
|
1002 |
'meta' => [
|
1003 |
'blocking' => false,
|
1004 |
],
|
1005 |
]
|
1006 |
);
|
|
|
|
|
|
|
|
|
|
|
1007 |
} else {
|
1008 |
return static::get_cache( 'post/redirect/default/1' ) ?: static::set_cache(
|
1009 |
'post/redirect/default/1',
|
1010 |
[
|
1011 |
'symbol' => \_x( 'R', 'Redirect', 'autodescription' ),
|
1012 |
'title' => \__( 'Redirection', 'autodescription' ),
|
1013 |
-
'status' => \The_SEO_Framework\Interpreters\
|
1014 |
'reason' => \__( 'Page redirects visitors.', 'autodescription' ),
|
1015 |
'assess' => [
|
1016 |
'redirect' => \__( 'All visitors and crawlers are being redirected. So, no other SEO enhancements are effective.', 'autodescription' ),
|
1 |
<?php
|
2 |
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Builders\SEOBar\Page
|
4 |
+
* @subpackage The_SEO_Framework\SEOBar
|
5 |
*/
|
6 |
|
7 |
+
namespace The_SEO_Framework\Builders\SEOBar;
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
29 |
* Generates the SEO Bar for posts.
|
30 |
*
|
31 |
* @since 4.0.0
|
32 |
+
* @since 4.2.0 Renamed to `The_SEO_Framework\Builders\SEOBar\Page` from `The_SEO_Framework\Builders\SeoBar_Page`
|
33 |
*
|
34 |
* @access private
|
35 |
* @internal
|
36 |
+
* @see \The_SEO_Framework\Interpreters\SEOBar
|
37 |
+
* Use \The_SEO_Framework\Interpreters\SEOBar::generate_bar() instead.
|
38 |
*/
|
39 |
+
final class Page extends Main {
|
40 |
|
41 |
/**
|
42 |
* @since 4.0.0
|
93 |
'post' => \get_post( static::$query['id'] ),
|
94 |
'meta' => static::$tsf->get_post_meta( static::$query['id'], true ), // Use TSF cache--TSF initializes it anyway.
|
95 |
'states' => [
|
96 |
+
'ishome' => static::$tsf->is_real_front_page_by_id( static::$query['id'] ),
|
97 |
+
'locale' => \get_locale(),
|
98 |
+
'isprotected' => static::$tsf->is_protected( static::$query['id'] ),
|
99 |
+
'isdraft' => static::$tsf->is_draft( static::$query['id'] ),
|
100 |
+
'robotsmeta' => array_merge(
|
101 |
[
|
102 |
'noindex' => false,
|
103 |
'nofollow' => false,
|
104 |
'noarchive' => false,
|
105 |
],
|
106 |
+
static::$tsf->generate_robots_meta(
|
107 |
+
[ 'id' => static::$query['id'] ],
|
108 |
+
[ 'noindex', 'nofollow', 'noarchive' ],
|
109 |
+
\The_SEO_Framework\ROBOTS_ASSERT
|
110 |
+
)
|
111 |
),
|
112 |
+
// We don't use this... yet. I couldn't find a way to properly implement the assertions in the right order.
|
113 |
+
// The asserter should be leading, but the SEO Bar should be readable.
|
114 |
+
'robotsassert' => static::$tsf->retrieve_robots_meta_assertions(),
|
115 |
],
|
116 |
];
|
117 |
}
|
137 |
* @return array $item : {
|
138 |
* string $symbol : The displayed symbol that identifies your bar.
|
139 |
* string $title : The title of the assessment.
|
140 |
+
* int $status : Power of two. See \The_SEO_Framework\Interpreters\SEOBar's class constants.
|
141 |
* string $reason : The final assessment: The reason for the $status. The latest state-changing reason is used.
|
142 |
* string $assess : The assessments on why the reason is set. Keep it short and concise!
|
143 |
* Does not accept HTML for performant ARIA support.
|
173 |
],
|
174 |
'reason' => [
|
175 |
'incomplete' => \__( 'Incomplete.', 'autodescription' ),
|
176 |
+
'duplicated' => \__( 'The branding is repeated.', 'autodescription' ),
|
177 |
'notbranded' => \__( 'Not branded.', 'autodescription' ),
|
178 |
'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
|
179 |
],
|
181 |
'generated' => [
|
182 |
'symbol' => \_x( 'TG', 'Title Generated', 'autodescription' ),
|
183 |
'title' => \__( 'Title, generated', 'autodescription' ),
|
184 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
185 |
'reason' => \__( 'Automatically generated.', 'autodescription' ),
|
186 |
'assess' => [
|
187 |
'base' => \__( "It's built from the page title.", 'autodescription' ),
|
190 |
'custom' => [
|
191 |
'symbol' => \_x( 'T', 'Title', 'autodescription' ),
|
192 |
'title' => \__( 'Title', 'autodescription' ),
|
193 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
194 |
'reason' => \__( 'Obtained from page SEO meta input.', 'autodescription' ),
|
195 |
'assess' => [
|
196 |
'base' => \__( "It's built from page SEO meta input.", 'autodescription' ),
|
200 |
]
|
201 |
);
|
202 |
|
203 |
+
$title_args = [ 'id' => static::$query['id'] ];
|
|
|
|
|
|
|
204 |
|
205 |
// TODO instead of getting values from the options API, why don't we store the parameters and allow them to be modified?
|
206 |
// This way, we can implement real-time live-edit AJAX SEO bar items...
|
207 |
+
$title_part = static::$tsf->get_filtered_raw_custom_field_title( $title_args );
|
208 |
|
209 |
if ( \strlen( $title_part ) ) {
|
210 |
$item = $cache['defaults']['custom'];
|
219 |
}
|
220 |
|
221 |
if ( static::$tsf->has_yoast_syntax( $title_part ) ) {
|
222 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
223 |
$item['reason'] = $cache['reason']['syntax'];
|
224 |
$item['assess']['syntax'] = $cache['assess']['syntax'];
|
225 |
|
234 |
$item['assess']['base'] = \__( "It's built using the site title.", 'autodescription' );
|
235 |
}
|
236 |
|
237 |
+
$title_part = static::$tsf->get_filtered_raw_generated_title( $title_args );
|
238 |
}
|
239 |
|
240 |
if ( ! $title_part ) {
|
241 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
242 |
$item['reason'] = $cache['reason']['incomplete'];
|
243 |
$item['assess']['empty'] = $cache['assess']['empty'];
|
244 |
|
245 |
// Further assessments must be made later. Halt assertion here to prevent confusion.
|
246 |
return $item;
|
247 |
} elseif ( $title_part === $cache['params']['untitled'] ) {
|
248 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
249 |
$item['reason'] = $cache['reason']['incomplete'];
|
250 |
$item['assess']['untitled'] = $cache['assess']['untitled'];
|
251 |
|
285 |
}
|
286 |
}
|
287 |
|
288 |
+
$brand_count = \strlen( $cache['params']['blogname_quoted'] )
|
|
|
|
|
289 |
? preg_match_all(
|
290 |
"/{$cache['params']['blogname_quoted']}/ui",
|
291 |
$title,
|
292 |
$matches
|
293 |
)
|
294 |
: 0;
|
|
|
295 |
|
296 |
if ( ! $brand_count ) {
|
297 |
// Override branding state.
|
298 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN;
|
299 |
$item['reason'] = $cache['reason']['notbranded'];
|
300 |
$item['assess']['branding'] = $cache['assess']['branding']['not'];
|
301 |
} elseif ( $brand_count > 1 ) {
|
302 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
303 |
$item['reason'] = $cache['reason']['duplicated'];
|
304 |
$item['assess']['duplicated'] = $cache['assess']['duplicated'];
|
305 |
|
318 |
$guidelines_i18n = static::get_cache( 'general/i18n/inputguidelines' );
|
319 |
|
320 |
if ( $title_len < $guidelines['lower'] ) {
|
321 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
322 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooShort'];
|
323 |
$length_i18n = $guidelines_i18n['long']['farTooShort'];
|
324 |
} elseif ( $title_len < $guidelines['goodLower'] ) {
|
325 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
326 |
$item['reason'] = $guidelines_i18n['shortdot']['tooShort'];
|
327 |
$length_i18n = $guidelines_i18n['long']['tooShort'];
|
328 |
} elseif ( $title_len > $guidelines['upper'] ) {
|
329 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
330 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooLong'];
|
331 |
$length_i18n = $guidelines_i18n['long']['farTooLong'];
|
332 |
} elseif ( $title_len > $guidelines['goodUpper'] ) {
|
333 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
334 |
$item['reason'] = $guidelines_i18n['shortdot']['tooLong'];
|
335 |
$length_i18n = $guidelines_i18n['long']['tooLong'];
|
336 |
} else {
|
376 |
'builder' => \__( 'A page builder is used that renders content dynamically, so no description can be generated for performance and privacy reasons. Consider providing a custom description.', 'autodescription' ),
|
377 |
'protected' => \__( 'The page is protected, so no description is generated.', 'autodescription' ),
|
378 |
'excerpt' => \__( "It's built from the page excerpt field.", 'autodescription' ),
|
379 |
+
/* translators: %s = list of repeated words */
|
380 |
+
'dupes' => \__( 'Found repeated words: %s', 'autodescription' ),
|
381 |
'syntax' => \__( "Markup syntax was found that isn't transformed. Consider rewriting the custom description.", 'autodescription' ),
|
382 |
],
|
383 |
'reason' => [
|
384 |
'empty' => \__( 'Empty.', 'autodescription' ),
|
385 |
+
'founddupe' => \__( 'Found repeated words.', 'autodescription' ),
|
386 |
+
'foundmanydupe' => \__( 'Found too many repeated words.', 'autodescription' ),
|
387 |
'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
|
388 |
],
|
389 |
'defaults' => [
|
390 |
'generated' => [
|
391 |
'symbol' => \_x( 'DG', 'Description Generated', 'autodescription' ),
|
392 |
'title' => \__( 'Description, generated', 'autodescription' ),
|
393 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
394 |
'reason' => \__( 'Automatically generated.', 'autodescription' ),
|
395 |
'assess' => [
|
396 |
'base' => \__( "It's built from the page content.", 'autodescription' ),
|
399 |
'emptynoauto' => [
|
400 |
'symbol' => \_x( 'D', 'Description', 'autodescription' ),
|
401 |
'title' => \__( 'Description', 'autodescription' ),
|
402 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
403 |
'reason' => \__( 'Empty.', 'autodescription' ),
|
404 |
'assess' => [
|
405 |
'noauto' => \__( 'No page description is set.', 'autodescription' ),
|
408 |
'custom' => [
|
409 |
'symbol' => \_x( 'D', 'Description', 'autodescription' ),
|
410 |
'title' => \__( 'Description', 'autodescription' ),
|
411 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
412 |
'reason' => \__( 'Obtained from the page SEO meta input.', 'autodescription' ),
|
413 |
'assess' => [
|
414 |
'base' => \__( "It's built from the page SEO meta input.", 'autodescription' ),
|
418 |
]
|
419 |
);
|
420 |
|
421 |
+
$desc_args = [ 'id' => static::$query['id'] ];
|
|
|
|
|
|
|
422 |
|
423 |
// TODO instead of getting values from the options API, why don't we store the parameters and allow them to be modified?
|
424 |
// This way, we can implement real-time live-edit AJAX SEO bar items...
|
437 |
}
|
438 |
|
439 |
if ( static::$tsf->has_yoast_syntax( $desc ) ) {
|
440 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
441 |
$item['reason'] = $cache['reason']['syntax'];
|
442 |
$item['assess']['syntax'] = $cache['assess']['syntax'];
|
443 |
|
462 |
unset( $item['assess']['base'] );
|
463 |
|
464 |
if ( static::$tsf->uses_non_html_page_builder( static::$query['id'] ) ) {
|
465 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN;
|
466 |
$item['assess']['empty'] = $cache['assess']['builder'];
|
467 |
} elseif ( static::$tsf->is_protected( static::$query['id'] ) ) {
|
468 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN;
|
469 |
$item['assess']['empty'] = $cache['assess']['protected'];
|
470 |
} else {
|
471 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_UNDEFINED;
|
472 |
$item['assess']['empty'] = $cache['assess']['empty'];
|
473 |
}
|
474 |
|
482 |
}
|
483 |
|
484 |
// Fetch words that are outputted more than 3 times.
|
485 |
+
$repeated_words = static::$tsf->get_word_count( $desc, 3, 5, $cache['params']['dupe_short'] );
|
486 |
|
487 |
+
if ( $repeated_words ) {
|
488 |
$dupes = [];
|
489 |
+
foreach ( $repeated_words as $_dw ) :
|
490 |
// Keep abbreviations... WordPress, make multibyte support mandatory already.
|
491 |
// $_word = ctype_upper( reset( $_dw ) ) ? reset( $_dw ) : mb_strtolower( reset( $_dw ) );
|
492 |
|
500 |
|
501 |
$item['assess']['dupe'] = implode( ' ', $dupes );
|
502 |
|
503 |
+
$max = max( $repeated_words );
|
504 |
$max = reset( $max );
|
505 |
|
506 |
// Warn when more than 3x triplet+/quintet+ words are found.
|
507 |
+
if ( $max > 3 || \count( $repeated_words ) > 1 ) {
|
508 |
// This must be resolved.
|
509 |
$item['reason'] = $cache['reason']['foundmanydupe'];
|
510 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
511 |
return $item;
|
512 |
} else {
|
513 |
$item['reason'] = $cache['reason']['founddupe'];
|
514 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
515 |
}
|
516 |
}
|
517 |
|
526 |
);
|
527 |
|
528 |
if ( $desc_len < $guidelines['lower'] ) {
|
529 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
530 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooShort'];
|
531 |
$length_i18n = $guidelines_i18n['long']['farTooShort'];
|
532 |
} elseif ( $desc_len < $guidelines['goodLower'] ) {
|
533 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
534 |
$item['reason'] = $guidelines_i18n['shortdot']['tooShort'];
|
535 |
$length_i18n = $guidelines_i18n['long']['tooShort'];
|
536 |
} elseif ( $desc_len > $guidelines['upper'] ) {
|
537 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
538 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooLong'];
|
539 |
$length_i18n = $guidelines_i18n['long']['farTooLong'];
|
540 |
} elseif ( $desc_len > $guidelines['goodUpper'] ) {
|
541 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
542 |
$item['reason'] = $guidelines_i18n['shortdot']['tooLong'];
|
543 |
$length_i18n = $guidelines_i18n['long']['tooLong'];
|
544 |
} else {
|
588 |
'index' => [
|
589 |
'symbol' => \_x( 'I', 'Indexing', 'autodescription' ),
|
590 |
'title' => \__( 'Indexing', 'autodescription' ),
|
591 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
592 |
'reason' => \__( 'Page may be indexed.', 'autodescription' ),
|
593 |
'assess' => [
|
594 |
'base' => \__( 'The robots meta tag allows indexing.', 'autodescription' ),
|
597 |
'noindex' => [
|
598 |
'symbol' => \_x( 'I', 'Indexing', 'autodescription' ),
|
599 |
'title' => \__( 'Indexing', 'autodescription' ),
|
600 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
601 |
'reason' => \__( 'Page may not be indexed.', 'autodescription' ),
|
602 |
'assess' => [
|
603 |
'base' => \__( 'The robots meta tag does not allow indexing.', 'autodescription' ),
|
606 |
'draft' => [
|
607 |
'symbol' => \_x( 'I', 'Indexing', 'autodescription' ),
|
608 |
'title' => \__( 'Indexing', 'autodescription' ),
|
609 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
610 |
'reason' => \__( 'Page is invisible.', 'autodescription' ),
|
611 |
'assess' => [
|
612 |
'base' => \__( "This page isn't published and can't be found publicly.", 'autodescription' ),
|
629 |
$robots_global = static::get_cache( 'general/detect/robotsglobal' );
|
630 |
|
631 |
if ( ! $robots_global['blogpublic'] ) {
|
632 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
633 |
$item['reason'] = $cache['reason']['notpublic'];
|
634 |
|
635 |
unset( $item['assess']['base'] );
|
646 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
647 |
// Don't trickle when noindex is not set, as this may be filtered.
|
648 |
if ( $this->query_cache['states']['isprotected'] ) {
|
649 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN;
|
650 |
$item['reason'] = $cache['reason']['protected'];
|
651 |
|
652 |
$item['assess']['protected'] = $cache['assess']['protected'];
|
684 |
'get_custom_field' => true,
|
685 |
] );
|
686 |
if ( $permalink !== $canonical ) {
|
687 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN;
|
688 |
$item['reason'] = $cache['reason']['canonicalurl'];
|
689 |
|
690 |
$item['assess']['protected'] = $cache['assess']['canonicalurl'];
|
742 |
'follow' => [
|
743 |
'symbol' => \_x( 'F', 'Following', 'autodescription' ),
|
744 |
'title' => \__( 'Following', 'autodescription' ),
|
745 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
746 |
'reason' => \__( 'Page links may be followed.', 'autodescription' ),
|
747 |
'assess' => [
|
748 |
'base' => \__( 'The robots meta tag allows link following.', 'autodescription' ),
|
751 |
'nofollow' => [
|
752 |
'symbol' => \_x( 'F', 'Following', 'autodescription' ),
|
753 |
'title' => \__( 'Following', 'autodescription' ),
|
754 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
755 |
'reason' => \__( 'Page links may not be followed.', 'autodescription' ),
|
756 |
'assess' => [
|
757 |
'base' => \__( 'The robots meta tag does not allow link following.', 'autodescription' ),
|
760 |
'draft' => [
|
761 |
'symbol' => \_x( 'F', 'Following', 'autodescription' ),
|
762 |
'title' => \__( 'Following', 'autodescription' ),
|
763 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
764 |
'reason' => \__( 'Page is invisible.', 'autodescription' ),
|
765 |
'assess' => [
|
766 |
'base' => \__( "This page isn't published and can't be found publicly.", 'autodescription' ),
|
783 |
$robots_global = static::get_cache( 'general/detect/robotsglobal' );
|
784 |
|
785 |
if ( ! $robots_global['blogpublic'] ) {
|
786 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
787 |
$item['reason'] = $cache['reason']['notpublic'];
|
788 |
|
789 |
unset( $item['assess']['base'] );
|
830 |
|
831 |
if ( ! $this->query_cache['states']['robotsmeta']['nofollow'] ) {
|
832 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
833 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
834 |
$item['assess']['noindex'] = $cache['assess']['noindex'];
|
835 |
}
|
836 |
|
873 |
'archive' => [
|
874 |
'symbol' => \_x( 'A', 'Archiving', 'autodescription' ),
|
875 |
'title' => \__( 'Archiving', 'autodescription' ),
|
876 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
877 |
'reason' => \__( 'Page may be archived.', 'autodescription' ),
|
878 |
'assess' => [
|
879 |
'base' => \__( 'The robots meta tag allows archiving.', 'autodescription' ),
|
882 |
'noarchive' => [
|
883 |
'symbol' => \_x( 'A', 'Archiving', 'autodescription' ),
|
884 |
'title' => \__( 'Archiving', 'autodescription' ),
|
885 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
886 |
'reason' => \__( 'Page may not be archived.', 'autodescription' ),
|
887 |
'assess' => [
|
888 |
'base' => \__( 'The robots meta tag does not allow archiving.', 'autodescription' ),
|
891 |
'draft' => [
|
892 |
'symbol' => \_x( 'A', 'Archiving', 'autodescription' ),
|
893 |
'title' => \__( 'Archiving', 'autodescription' ),
|
894 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
895 |
'reason' => \__( 'Page is invisible.', 'autodescription' ),
|
896 |
'assess' => [
|
897 |
'base' => \__( "This page isn't published and can't be found publicly.", 'autodescription' ),
|
914 |
$robots_global = static::get_cache( 'general/detect/robotsglobal' );
|
915 |
|
916 |
if ( ! $robots_global['blogpublic'] ) {
|
917 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
918 |
$item['reason'] = $cache['reason']['notpublic'];
|
919 |
|
920 |
unset( $item['assess']['base'] );
|
961 |
|
962 |
if ( ! $this->query_cache['states']['robotsmeta']['noarchive'] ) {
|
963 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
964 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
965 |
$item['assess']['noindex'] = $cache['assess']['noindex'];
|
966 |
}
|
967 |
|
985 |
protected function test_redirect() {
|
986 |
|
987 |
if ( empty( $this->query_cache['meta']['redirect'] ) ) {
|
988 |
+
$default = static::get_cache( 'page/redirect/default/0' ) ?: static::set_cache(
|
989 |
'page/redirect/default/0',
|
990 |
[
|
991 |
'symbol' => \_x( 'R', 'Redirect', 'autodescription' ),
|
992 |
'title' => \__( 'Redirection', 'autodescription' ),
|
993 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
994 |
'reason' => \__( 'Page does not redirect visitors.', 'autodescription' ),
|
995 |
'assess' => [
|
996 |
+
'redirect' => \__( 'Visitors and crawlers may view this page.', 'autodescription' ),
|
997 |
],
|
998 |
'meta' => [
|
999 |
'blocking' => false,
|
1000 |
],
|
1001 |
]
|
1002 |
);
|
1003 |
+
|
1004 |
+
if ( $this->query_cache['states']['isdraft'] )
|
1005 |
+
$default['assess']['redirect'] = \__( 'Visitors and crawlers may view this page once published.', 'autodescription' );
|
1006 |
+
|
1007 |
+
return $default;
|
1008 |
} else {
|
1009 |
return static::get_cache( 'post/redirect/default/1' ) ?: static::set_cache(
|
1010 |
'post/redirect/default/1',
|
1011 |
[
|
1012 |
'symbol' => \_x( 'R', 'Redirect', 'autodescription' ),
|
1013 |
'title' => \__( 'Redirection', 'autodescription' ),
|
1014 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
1015 |
'reason' => \__( 'Page redirects visitors.', 'autodescription' ),
|
1016 |
'assess' => [
|
1017 |
'redirect' => \__( 'All visitors and crawlers are being redirected. So, no other SEO enhancements are effective.', 'autodescription' ),
|
@@ -1,10 +1,10 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* @package The_SEO_Framework\Classes\Builders\
|
4 |
-
* @subpackage The_SEO_Framework\
|
5 |
*/
|
6 |
|
7 |
-
namespace The_SEO_Framework\Builders;
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
@@ -29,13 +29,14 @@ namespace The_SEO_Framework\Builders;
|
|
29 |
* Generates the SEO Bar for posts.
|
30 |
*
|
31 |
* @since 4.0.0
|
|
|
32 |
*
|
33 |
* @access private
|
34 |
* @internal
|
35 |
-
* @see \The_SEO_Framework\Interpreters\
|
36 |
-
* Use \The_SEO_Framework\Interpreters\
|
37 |
*/
|
38 |
-
final class
|
39 |
|
40 |
/**
|
41 |
* @since 4.0.0
|
@@ -100,20 +101,27 @@ final class SeoBar_Term extends SeoBar {
|
|
100 |
'term' => $term,
|
101 |
'meta' => static::$tsf->get_term_meta( static::$query['id'], true ), // Use TSF cache--TSF initializes it anyway.
|
102 |
'states' => [
|
103 |
-
'locale'
|
104 |
-
'isempty'
|
105 |
-
'posttypes'
|
106 |
-
'robotsmeta'
|
107 |
[
|
108 |
'noindex' => false,
|
109 |
'nofollow' => false,
|
110 |
'noarchive' => false,
|
111 |
],
|
112 |
-
static::$tsf->generate_robots_meta(
|
113 |
-
|
114 |
-
|
115 |
-
|
|
|
|
|
|
|
|
|
116 |
),
|
|
|
|
|
|
|
117 |
],
|
118 |
];
|
119 |
}
|
@@ -141,7 +149,7 @@ final class SeoBar_Term extends SeoBar {
|
|
141 |
* @return array $item : {
|
142 |
* string $symbol : The displayed symbol that identifies your bar.
|
143 |
* string $title : The title of the assessment.
|
144 |
-
* int $status : Power of two. See \The_SEO_Framework\Interpreters\
|
145 |
* string $reason : The final assessment: The reason for the $status. The latest state-changing reason is used.
|
146 |
* string $assess : The assessments on why the reason is set. Keep it short and concise!
|
147 |
* Does not accept HTML for performant ARIA support.
|
@@ -177,7 +185,7 @@ final class SeoBar_Term extends SeoBar {
|
|
177 |
],
|
178 |
'reason' => [
|
179 |
'incomplete' => \__( 'Incomplete.', 'autodescription' ),
|
180 |
-
'duplicated' => \__( 'The branding is
|
181 |
'notbranded' => \__( 'Not branded.', 'autodescription' ),
|
182 |
'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
|
183 |
],
|
@@ -185,7 +193,7 @@ final class SeoBar_Term extends SeoBar {
|
|
185 |
'generated' => [
|
186 |
'symbol' => \_x( 'TG', 'Title Generated', 'autodescription' ),
|
187 |
'title' => \__( 'Title, generated', 'autodescription' ),
|
188 |
-
'status' => \The_SEO_Framework\Interpreters\
|
189 |
'reason' => \__( 'Automatically generated.', 'autodescription' ),
|
190 |
'assess' => [
|
191 |
'base' => \__( "It's built from the term name.", 'autodescription' ),
|
@@ -194,7 +202,7 @@ final class SeoBar_Term extends SeoBar {
|
|
194 |
'custom' => [
|
195 |
'symbol' => \_x( 'T', 'Title', 'autodescription' ),
|
196 |
'title' => \__( 'Title', 'autodescription' ),
|
197 |
-
'status' => \The_SEO_Framework\Interpreters\
|
198 |
'reason' => \__( 'Obtained from term SEO meta input.', 'autodescription' ),
|
199 |
'assess' => [
|
200 |
'base' => \__( "It's built from term SEO meta input.", 'autodescription' ),
|
@@ -211,13 +219,13 @@ final class SeoBar_Term extends SeoBar {
|
|
211 |
|
212 |
// TODO instead of getting values from the options API, why don't we store the parameters and allow them to be modified?
|
213 |
// This way, we can implement real-time live-edit AJAX SEO bar items...
|
214 |
-
$title_part = static::$tsf->get_filtered_raw_custom_field_title( $title_args
|
215 |
|
216 |
if ( \strlen( $title_part ) ) {
|
217 |
$item = $cache['defaults']['custom'];
|
218 |
|
219 |
if ( static::$tsf->has_yoast_syntax( $title_part, false ) ) {
|
220 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
221 |
$item['reason'] = $cache['reason']['syntax'];
|
222 |
$item['assess']['syntax'] = $cache['assess']['syntax'];
|
223 |
|
@@ -231,18 +239,18 @@ final class SeoBar_Term extends SeoBar {
|
|
231 |
$item['assess']['prefixed'] = $cache['assess']['prefixed'];
|
232 |
}
|
233 |
|
234 |
-
$title_part = static::$tsf->get_filtered_raw_generated_title( $title_args
|
235 |
}
|
236 |
|
237 |
if ( ! $title_part ) {
|
238 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
239 |
$item['reason'] = $cache['reason']['incomplete'];
|
240 |
$item['assess']['empty'] = $cache['assess']['empty'];
|
241 |
|
242 |
// Further assessments must be made later. Halt assertion here to prevent confusion.
|
243 |
return $item;
|
244 |
} elseif ( $title_part === $cache['params']['untitled'] ) {
|
245 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
246 |
$item['reason'] = $cache['reason']['incomplete'];
|
247 |
$item['assess']['untitled'] = $cache['assess']['untitled'];
|
248 |
|
@@ -267,24 +275,21 @@ final class SeoBar_Term extends SeoBar {
|
|
267 |
$item['assess']['branding'] = $cache['assess']['branding']['manual'];
|
268 |
}
|
269 |
|
270 |
-
|
271 |
-
$brand_count =
|
272 |
-
\strlen( $cache['params']['blogname_quoted'] )
|
273 |
? preg_match_all(
|
274 |
"/{$cache['params']['blogname_quoted']}/ui",
|
275 |
$title,
|
276 |
$matches
|
277 |
)
|
278 |
: 0;
|
279 |
-
// phpcs:enable, PEAR.Functions.FunctionCallSignature.Indent
|
280 |
|
281 |
if ( ! $brand_count ) {
|
282 |
// Override branding state.
|
283 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
284 |
$item['reason'] = $cache['reason']['notbranded'];
|
285 |
$item['assess']['branding'] = $cache['assess']['branding']['not'];
|
286 |
} elseif ( $brand_count > 1 ) {
|
287 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
288 |
$item['reason'] = $cache['reason']['duplicated'];
|
289 |
$item['assess']['duplicated'] = $cache['assess']['duplicated'];
|
290 |
|
@@ -303,19 +308,19 @@ final class SeoBar_Term extends SeoBar {
|
|
303 |
$guidelines_i18n = static::get_cache( 'general/i18n/inputguidelines' );
|
304 |
|
305 |
if ( $title_len < $guidelines['lower'] ) {
|
306 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
307 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooShort'];
|
308 |
$length_i18n = $guidelines_i18n['long']['farTooShort'];
|
309 |
} elseif ( $title_len < $guidelines['goodLower'] ) {
|
310 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
311 |
$item['reason'] = $guidelines_i18n['shortdot']['tooShort'];
|
312 |
$length_i18n = $guidelines_i18n['long']['tooShort'];
|
313 |
} elseif ( $title_len > $guidelines['upper'] ) {
|
314 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
315 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooLong'];
|
316 |
$length_i18n = $guidelines_i18n['long']['farTooLong'];
|
317 |
} elseif ( $title_len > $guidelines['goodUpper'] ) {
|
318 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
319 |
$item['reason'] = $guidelines_i18n['shortdot']['tooLong'];
|
320 |
$length_i18n = $guidelines_i18n['long']['tooLong'];
|
321 |
} else {
|
@@ -358,21 +363,21 @@ final class SeoBar_Term extends SeoBar {
|
|
358 |
],
|
359 |
'assess' => [
|
360 |
'empty' => \__( 'No description could be generated.', 'autodescription' ),
|
361 |
-
/* translators: %s = list of
|
362 |
-
'dupes' => \__( 'Found
|
363 |
'syntax' => \__( "Markup syntax was found that isn't transformed. Consider rewriting the custom description.", 'autodescription' ),
|
364 |
],
|
365 |
'reason' => [
|
366 |
'empty' => \__( 'Empty.', 'autodescription' ),
|
367 |
-
'founddupe' => \__( 'Found
|
368 |
-
'foundmanydupe' => \__( 'Found too many
|
369 |
'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
|
370 |
],
|
371 |
'defaults' => [
|
372 |
'generated' => [
|
373 |
'symbol' => \_x( 'DG', 'Description Generated', 'autodescription' ),
|
374 |
'title' => \__( 'Description, generated', 'autodescription' ),
|
375 |
-
'status' => \The_SEO_Framework\Interpreters\
|
376 |
'reason' => \__( 'Automatically generated.', 'autodescription' ),
|
377 |
'assess' => [
|
378 |
'base' => \__( "It's built from the term description field.", 'autodescription' ),
|
@@ -381,7 +386,7 @@ final class SeoBar_Term extends SeoBar {
|
|
381 |
'emptynoauto' => [
|
382 |
'symbol' => \_x( 'D', 'Description', 'autodescription' ),
|
383 |
'title' => \__( 'Description', 'autodescription' ),
|
384 |
-
'status' => \The_SEO_Framework\Interpreters\
|
385 |
'reason' => \__( 'Empty.', 'autodescription' ),
|
386 |
'assess' => [
|
387 |
'noauto' => \__( 'No term description is set.', 'autodescription' ),
|
@@ -390,7 +395,7 @@ final class SeoBar_Term extends SeoBar {
|
|
390 |
'custom' => [
|
391 |
'symbol' => \_x( 'D', 'Description', 'autodescription' ),
|
392 |
'title' => \__( 'Description', 'autodescription' ),
|
393 |
-
'status' => \The_SEO_Framework\Interpreters\
|
394 |
'reason' => \__( 'Obtained from the term SEO meta input.', 'autodescription' ),
|
395 |
'assess' => [
|
396 |
'base' => \__( "It's built from the term SEO meta input.", 'autodescription' ),
|
@@ -413,7 +418,7 @@ final class SeoBar_Term extends SeoBar {
|
|
413 |
$item = $cache['defaults']['custom'];
|
414 |
|
415 |
if ( static::$tsf->has_yoast_syntax( $desc ) ) {
|
416 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
417 |
$item['reason'] = $cache['reason']['syntax'];
|
418 |
$item['assess']['syntax'] = $cache['assess']['syntax'];
|
419 |
|
@@ -431,7 +436,7 @@ final class SeoBar_Term extends SeoBar {
|
|
431 |
$desc = static::$tsf->get_generated_description( $desc_args, false );
|
432 |
|
433 |
if ( ! \strlen( $desc ) ) {
|
434 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
435 |
$item['reason'] = $cache['reason']['empty'];
|
436 |
|
437 |
// This is now inaccurate, purge it.
|
@@ -446,11 +451,11 @@ final class SeoBar_Term extends SeoBar {
|
|
446 |
}
|
447 |
|
448 |
// Fetch words that are outputted more than 3 times.
|
449 |
-
$
|
450 |
|
451 |
-
if ( $
|
452 |
$dupes = [];
|
453 |
-
foreach ( $
|
454 |
// Keep abbreviations... WordPress, make multibyte support mandatory already.
|
455 |
// $_word = ctype_upper( reset( $_dw ) ) ? reset( $_dw ) : mb_strtolower( reset( $_dw ) );
|
456 |
|
@@ -464,18 +469,18 @@ final class SeoBar_Term extends SeoBar {
|
|
464 |
|
465 |
$item['assess']['dupe'] = implode( ' ', $dupes );
|
466 |
|
467 |
-
$max = max( $
|
468 |
$max = reset( $max );
|
469 |
|
470 |
// Warn when more than 3x triplet+/quintet+ words are found.
|
471 |
-
if ( $max > 3 || \count( $
|
472 |
// This must be resolved.
|
473 |
$item['reason'] = $cache['reason']['foundmanydupe'];
|
474 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
475 |
return $item;
|
476 |
} else {
|
477 |
$item['reason'] = $cache['reason']['founddupe'];
|
478 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
479 |
}
|
480 |
}
|
481 |
|
@@ -490,19 +495,19 @@ final class SeoBar_Term extends SeoBar {
|
|
490 |
);
|
491 |
|
492 |
if ( $desc_len < $guidelines['lower'] ) {
|
493 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
494 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooShort'];
|
495 |
$length_i18n = $guidelines_i18n['long']['farTooShort'];
|
496 |
} elseif ( $desc_len < $guidelines['goodLower'] ) {
|
497 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
498 |
$item['reason'] = $guidelines_i18n['shortdot']['tooShort'];
|
499 |
$length_i18n = $guidelines_i18n['long']['tooShort'];
|
500 |
} elseif ( $desc_len > $guidelines['upper'] ) {
|
501 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
502 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooLong'];
|
503 |
$length_i18n = $guidelines_i18n['long']['farTooLong'];
|
504 |
} elseif ( $desc_len > $guidelines['goodUpper'] ) {
|
505 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
506 |
$item['reason'] = $guidelines_i18n['shortdot']['tooLong'];
|
507 |
$length_i18n = $guidelines_i18n['long']['tooLong'];
|
508 |
} else {
|
@@ -555,7 +560,7 @@ final class SeoBar_Term extends SeoBar {
|
|
555 |
'index' => [
|
556 |
'symbol' => \_x( 'I', 'Indexing', 'autodescription' ),
|
557 |
'title' => \__( 'Indexing', 'autodescription' ),
|
558 |
-
'status' => \The_SEO_Framework\Interpreters\
|
559 |
'reason' => \__( 'Term may be indexed.', 'autodescription' ),
|
560 |
'assess' => [
|
561 |
'base' => \__( 'The robots meta tag allows indexing.', 'autodescription' ),
|
@@ -564,7 +569,7 @@ final class SeoBar_Term extends SeoBar {
|
|
564 |
'noindex' => [
|
565 |
'symbol' => \_x( 'I', 'Indexing', 'autodescription' ),
|
566 |
'title' => \__( 'Indexing', 'autodescription' ),
|
567 |
-
'status' => \The_SEO_Framework\Interpreters\
|
568 |
'reason' => \__( 'Term may not be indexed.', 'autodescription' ),
|
569 |
'assess' => [
|
570 |
'base' => \__( 'The robots meta tag does not allow indexing.', 'autodescription' ),
|
@@ -583,7 +588,7 @@ final class SeoBar_Term extends SeoBar {
|
|
583 |
}
|
584 |
|
585 |
if ( ! $robots_global['blogpublic'] ) {
|
586 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
587 |
$item['reason'] = $cache['reason']['notpublic'];
|
588 |
|
589 |
unset( $item['assess']['base'] );
|
@@ -639,7 +644,7 @@ final class SeoBar_Term extends SeoBar {
|
|
639 |
'get_custom_field' => true,
|
640 |
] );
|
641 |
if ( $permalink !== $canonical ) {
|
642 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
643 |
$item['reason'] = $cache['reason']['canonicalurl'];
|
644 |
|
645 |
$item['assess']['protected'] = $cache['assess']['canonicalurl'];
|
@@ -649,13 +654,13 @@ final class SeoBar_Term extends SeoBar {
|
|
649 |
if ( $this->query_cache['states']['isempty'] ) {
|
650 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
651 |
// Everything's as intended...
|
652 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
653 |
$item['reason'] = $cache['reason']['empty'];
|
654 |
|
655 |
$item['assess']['empty'] = $cache['assess']['empty'];
|
656 |
} else {
|
657 |
// Something's wrong. Maybe override, maybe filter, maybe me.
|
658 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
659 |
|
660 |
$item['reason'] = $cache['reason']['emptyoverride'];
|
661 |
$item['assess']['empty'] = $cache['assess']['emptyoverride'];
|
@@ -701,7 +706,7 @@ final class SeoBar_Term extends SeoBar {
|
|
701 |
'follow' => [
|
702 |
'symbol' => \_x( 'F', 'Following', 'autodescription' ),
|
703 |
'title' => \__( 'Following', 'autodescription' ),
|
704 |
-
'status' => \The_SEO_Framework\Interpreters\
|
705 |
'reason' => \__( 'Term links may be followed.', 'autodescription' ),
|
706 |
'assess' => [
|
707 |
'base' => \__( 'The robots meta tag allows link following.', 'autodescription' ),
|
@@ -710,7 +715,7 @@ final class SeoBar_Term extends SeoBar {
|
|
710 |
'nofollow' => [
|
711 |
'symbol' => \_x( 'F', 'Following', 'autodescription' ),
|
712 |
'title' => \__( 'Following', 'autodescription' ),
|
713 |
-
'status' => \The_SEO_Framework\Interpreters\
|
714 |
'reason' => \__( 'Term links may not be followed.', 'autodescription' ),
|
715 |
'assess' => [
|
716 |
'base' => \__( 'The robots meta tag does not allow link following.', 'autodescription' ),
|
@@ -729,7 +734,7 @@ final class SeoBar_Term extends SeoBar {
|
|
729 |
}
|
730 |
|
731 |
if ( ! $robots_global['blogpublic'] ) {
|
732 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
733 |
$item['reason'] = $cache['reason']['notpublic'];
|
734 |
|
735 |
unset( $item['assess']['base'] );
|
@@ -774,7 +779,7 @@ final class SeoBar_Term extends SeoBar {
|
|
774 |
|
775 |
if ( ! $this->query_cache['states']['robotsmeta']['nofollow'] ) {
|
776 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
777 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
778 |
$item['assess']['noindex'] = $cache['assess']['noindex'];
|
779 |
}
|
780 |
|
@@ -818,7 +823,7 @@ final class SeoBar_Term extends SeoBar {
|
|
818 |
'archive' => [
|
819 |
'symbol' => \_x( 'A', 'Archiving', 'autodescription' ),
|
820 |
'title' => \__( 'Archiving', 'autodescription' ),
|
821 |
-
'status' => \The_SEO_Framework\Interpreters\
|
822 |
'reason' => \__( 'Term may be archived.', 'autodescription' ),
|
823 |
'assess' => [
|
824 |
'base' => \__( 'The robots meta tag allows archiving.', 'autodescription' ),
|
@@ -827,7 +832,7 @@ final class SeoBar_Term extends SeoBar {
|
|
827 |
'noarchive' => [
|
828 |
'symbol' => \_x( 'A', 'Archiving', 'autodescription' ),
|
829 |
'title' => \__( 'Archiving', 'autodescription' ),
|
830 |
-
'status' => \The_SEO_Framework\Interpreters\
|
831 |
'reason' => \__( 'Term may not be archived.', 'autodescription' ),
|
832 |
'assess' => [
|
833 |
'base' => \__( 'The robots meta tag does not allow archiving.', 'autodescription' ),
|
@@ -846,7 +851,7 @@ final class SeoBar_Term extends SeoBar {
|
|
846 |
}
|
847 |
|
848 |
if ( ! $robots_global['blogpublic'] ) {
|
849 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
850 |
$item['reason'] = $cache['reason']['notpublic'];
|
851 |
|
852 |
unset( $item['assess']['base'] );
|
@@ -891,7 +896,7 @@ final class SeoBar_Term extends SeoBar {
|
|
891 |
|
892 |
if ( ! $this->query_cache['states']['robotsmeta']['noarchive'] ) {
|
893 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
894 |
-
$item['status'] = \The_SEO_Framework\Interpreters\
|
895 |
$item['assess']['noindex'] = $cache['assess']['noindex'];
|
896 |
}
|
897 |
|
@@ -919,7 +924,7 @@ final class SeoBar_Term extends SeoBar {
|
|
919 |
[
|
920 |
'symbol' => \_x( 'R', 'Redirect', 'autodescription' ),
|
921 |
'title' => \__( 'Redirection', 'autodescription' ),
|
922 |
-
'status' => \The_SEO_Framework\Interpreters\
|
923 |
'reason' => \__( 'Term does not redirect visitors.', 'autodescription' ),
|
924 |
'assess' => [
|
925 |
'redirect' => \__( 'All visitors and crawlers may access this page.', 'autodescription' ),
|
@@ -935,7 +940,7 @@ final class SeoBar_Term extends SeoBar {
|
|
935 |
[
|
936 |
'symbol' => \_x( 'R', 'Redirect', 'autodescription' ),
|
937 |
'title' => \__( 'Redirection', 'autodescription' ),
|
938 |
-
'status' => \The_SEO_Framework\Interpreters\
|
939 |
'reason' => \__( 'Term redirects visitors.', 'autodescription' ),
|
940 |
'assess' => [
|
941 |
'redirect' => \__( 'All visitors and crawlers are being redirected. So, no other SEO enhancements are effective.', 'autodescription' ),
|
1 |
<?php
|
2 |
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Builders\SEOBar\Term
|
4 |
+
* @subpackage The_SEO_Framework\SEOBar
|
5 |
*/
|
6 |
|
7 |
+
namespace The_SEO_Framework\Builders\SEOBar;
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
29 |
* Generates the SEO Bar for posts.
|
30 |
*
|
31 |
* @since 4.0.0
|
32 |
+
* @since 4.2.0 Renamed to `The_SEO_Framework\Builders\SEOBar\Term` from `The_SEO_Framework\Builders\SeoBar_Term`
|
33 |
*
|
34 |
* @access private
|
35 |
* @internal
|
36 |
+
* @see \The_SEO_Framework\Interpreters\SEOBar
|
37 |
+
* Use \The_SEO_Framework\Interpreters\SEOBar::generate_bar() instead.
|
38 |
*/
|
39 |
+
final class Term extends Main {
|
40 |
|
41 |
/**
|
42 |
* @since 4.0.0
|
101 |
'term' => $term,
|
102 |
'meta' => static::$tsf->get_term_meta( static::$query['id'], true ), // Use TSF cache--TSF initializes it anyway.
|
103 |
'states' => [
|
104 |
+
'locale' => \get_locale(),
|
105 |
+
'isempty' => empty( $term->count ),
|
106 |
+
'posttypes' => static::$tsf->get_post_types_from_taxonomy( static::$query['taxonomy'] ),
|
107 |
+
'robotsmeta' => array_merge(
|
108 |
[
|
109 |
'noindex' => false,
|
110 |
'nofollow' => false,
|
111 |
'noarchive' => false,
|
112 |
],
|
113 |
+
static::$tsf->generate_robots_meta(
|
114 |
+
[
|
115 |
+
'id' => static::$query['id'],
|
116 |
+
'taxonomy' => static::$query['taxonomy'],
|
117 |
+
],
|
118 |
+
[ 'noindex', 'nofollow', 'noarchive' ],
|
119 |
+
\The_SEO_Framework\ROBOTS_ASSERT
|
120 |
+
)
|
121 |
),
|
122 |
+
// We don't use this... yet. I couldn't find a way to properly implement the assertions in the right order.
|
123 |
+
// The asserter should be leading, but the SEO Bar should be readable.
|
124 |
+
'robotsassert' => static::$tsf->retrieve_robots_meta_assertions(),
|
125 |
],
|
126 |
];
|
127 |
}
|
149 |
* @return array $item : {
|
150 |
* string $symbol : The displayed symbol that identifies your bar.
|
151 |
* string $title : The title of the assessment.
|
152 |
+
* int $status : Power of two. See \The_SEO_Framework\Interpreters\SEOBar's class constants.
|
153 |
* string $reason : The final assessment: The reason for the $status. The latest state-changing reason is used.
|
154 |
* string $assess : The assessments on why the reason is set. Keep it short and concise!
|
155 |
* Does not accept HTML for performant ARIA support.
|
185 |
],
|
186 |
'reason' => [
|
187 |
'incomplete' => \__( 'Incomplete.', 'autodescription' ),
|
188 |
+
'duplicated' => \__( 'The branding is repeated.', 'autodescription' ),
|
189 |
'notbranded' => \__( 'Not branded.', 'autodescription' ),
|
190 |
'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
|
191 |
],
|
193 |
'generated' => [
|
194 |
'symbol' => \_x( 'TG', 'Title Generated', 'autodescription' ),
|
195 |
'title' => \__( 'Title, generated', 'autodescription' ),
|
196 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
197 |
'reason' => \__( 'Automatically generated.', 'autodescription' ),
|
198 |
'assess' => [
|
199 |
'base' => \__( "It's built from the term name.", 'autodescription' ),
|
202 |
'custom' => [
|
203 |
'symbol' => \_x( 'T', 'Title', 'autodescription' ),
|
204 |
'title' => \__( 'Title', 'autodescription' ),
|
205 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
206 |
'reason' => \__( 'Obtained from term SEO meta input.', 'autodescription' ),
|
207 |
'assess' => [
|
208 |
'base' => \__( "It's built from term SEO meta input.", 'autodescription' ),
|
219 |
|
220 |
// TODO instead of getting values from the options API, why don't we store the parameters and allow them to be modified?
|
221 |
// This way, we can implement real-time live-edit AJAX SEO bar items...
|
222 |
+
$title_part = static::$tsf->get_filtered_raw_custom_field_title( $title_args );
|
223 |
|
224 |
if ( \strlen( $title_part ) ) {
|
225 |
$item = $cache['defaults']['custom'];
|
226 |
|
227 |
if ( static::$tsf->has_yoast_syntax( $title_part, false ) ) {
|
228 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
229 |
$item['reason'] = $cache['reason']['syntax'];
|
230 |
$item['assess']['syntax'] = $cache['assess']['syntax'];
|
231 |
|
239 |
$item['assess']['prefixed'] = $cache['assess']['prefixed'];
|
240 |
}
|
241 |
|
242 |
+
$title_part = static::$tsf->get_filtered_raw_generated_title( $title_args );
|
243 |
}
|
244 |
|
245 |
if ( ! $title_part ) {
|
246 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
247 |
$item['reason'] = $cache['reason']['incomplete'];
|
248 |
$item['assess']['empty'] = $cache['assess']['empty'];
|
249 |
|
250 |
// Further assessments must be made later. Halt assertion here to prevent confusion.
|
251 |
return $item;
|
252 |
} elseif ( $title_part === $cache['params']['untitled'] ) {
|
253 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
254 |
$item['reason'] = $cache['reason']['incomplete'];
|
255 |
$item['assess']['untitled'] = $cache['assess']['untitled'];
|
256 |
|
275 |
$item['assess']['branding'] = $cache['assess']['branding']['manual'];
|
276 |
}
|
277 |
|
278 |
+
$brand_count = \strlen( $cache['params']['blogname_quoted'] )
|
|
|
|
|
279 |
? preg_match_all(
|
280 |
"/{$cache['params']['blogname_quoted']}/ui",
|
281 |
$title,
|
282 |
$matches
|
283 |
)
|
284 |
: 0;
|
|
|
285 |
|
286 |
if ( ! $brand_count ) {
|
287 |
// Override branding state.
|
288 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN;
|
289 |
$item['reason'] = $cache['reason']['notbranded'];
|
290 |
$item['assess']['branding'] = $cache['assess']['branding']['not'];
|
291 |
} elseif ( $brand_count > 1 ) {
|
292 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
293 |
$item['reason'] = $cache['reason']['duplicated'];
|
294 |
$item['assess']['duplicated'] = $cache['assess']['duplicated'];
|
295 |
|
308 |
$guidelines_i18n = static::get_cache( 'general/i18n/inputguidelines' );
|
309 |
|
310 |
if ( $title_len < $guidelines['lower'] ) {
|
311 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
312 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooShort'];
|
313 |
$length_i18n = $guidelines_i18n['long']['farTooShort'];
|
314 |
} elseif ( $title_len < $guidelines['goodLower'] ) {
|
315 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
316 |
$item['reason'] = $guidelines_i18n['shortdot']['tooShort'];
|
317 |
$length_i18n = $guidelines_i18n['long']['tooShort'];
|
318 |
} elseif ( $title_len > $guidelines['upper'] ) {
|
319 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
320 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooLong'];
|
321 |
$length_i18n = $guidelines_i18n['long']['farTooLong'];
|
322 |
} elseif ( $title_len > $guidelines['goodUpper'] ) {
|
323 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
324 |
$item['reason'] = $guidelines_i18n['shortdot']['tooLong'];
|
325 |
$length_i18n = $guidelines_i18n['long']['tooLong'];
|
326 |
} else {
|
363 |
],
|
364 |
'assess' => [
|
365 |
'empty' => \__( 'No description could be generated.', 'autodescription' ),
|
366 |
+
/* translators: %s = list of repeated words */
|
367 |
+
'dupes' => \__( 'Found repeated words: %s', 'autodescription' ),
|
368 |
'syntax' => \__( "Markup syntax was found that isn't transformed. Consider rewriting the custom description.", 'autodescription' ),
|
369 |
],
|
370 |
'reason' => [
|
371 |
'empty' => \__( 'Empty.', 'autodescription' ),
|
372 |
+
'founddupe' => \__( 'Found repeated words.', 'autodescription' ),
|
373 |
+
'foundmanydupe' => \__( 'Found too many repeated words.', 'autodescription' ),
|
374 |
'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
|
375 |
],
|
376 |
'defaults' => [
|
377 |
'generated' => [
|
378 |
'symbol' => \_x( 'DG', 'Description Generated', 'autodescription' ),
|
379 |
'title' => \__( 'Description, generated', 'autodescription' ),
|
380 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
381 |
'reason' => \__( 'Automatically generated.', 'autodescription' ),
|
382 |
'assess' => [
|
383 |
'base' => \__( "It's built from the term description field.", 'autodescription' ),
|
386 |
'emptynoauto' => [
|
387 |
'symbol' => \_x( 'D', 'Description', 'autodescription' ),
|
388 |
'title' => \__( 'Description', 'autodescription' ),
|
389 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
390 |
'reason' => \__( 'Empty.', 'autodescription' ),
|
391 |
'assess' => [
|
392 |
'noauto' => \__( 'No term description is set.', 'autodescription' ),
|
395 |
'custom' => [
|
396 |
'symbol' => \_x( 'D', 'Description', 'autodescription' ),
|
397 |
'title' => \__( 'Description', 'autodescription' ),
|
398 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
399 |
'reason' => \__( 'Obtained from the term SEO meta input.', 'autodescription' ),
|
400 |
'assess' => [
|
401 |
'base' => \__( "It's built from the term SEO meta input.", 'autodescription' ),
|
418 |
$item = $cache['defaults']['custom'];
|
419 |
|
420 |
if ( static::$tsf->has_yoast_syntax( $desc ) ) {
|
421 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
422 |
$item['reason'] = $cache['reason']['syntax'];
|
423 |
$item['assess']['syntax'] = $cache['assess']['syntax'];
|
424 |
|
436 |
$desc = static::$tsf->get_generated_description( $desc_args, false );
|
437 |
|
438 |
if ( ! \strlen( $desc ) ) {
|
439 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_UNDEFINED;
|
440 |
$item['reason'] = $cache['reason']['empty'];
|
441 |
|
442 |
// This is now inaccurate, purge it.
|
451 |
}
|
452 |
|
453 |
// Fetch words that are outputted more than 3 times.
|
454 |
+
$repeated_words = static::$tsf->get_word_count( $desc, 3, 5, $cache['params']['dupe_short'] );
|
455 |
|
456 |
+
if ( $repeated_words ) {
|
457 |
$dupes = [];
|
458 |
+
foreach ( $repeated_words as $_dw ) :
|
459 |
// Keep abbreviations... WordPress, make multibyte support mandatory already.
|
460 |
// $_word = ctype_upper( reset( $_dw ) ) ? reset( $_dw ) : mb_strtolower( reset( $_dw ) );
|
461 |
|
469 |
|
470 |
$item['assess']['dupe'] = implode( ' ', $dupes );
|
471 |
|
472 |
+
$max = max( $repeated_words );
|
473 |
$max = reset( $max );
|
474 |
|
475 |
// Warn when more than 3x triplet+/quintet+ words are found.
|
476 |
+
if ( $max > 3 || \count( $repeated_words ) > 1 ) {
|
477 |
// This must be resolved.
|
478 |
$item['reason'] = $cache['reason']['foundmanydupe'];
|
479 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
480 |
return $item;
|
481 |
} else {
|
482 |
$item['reason'] = $cache['reason']['founddupe'];
|
483 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
484 |
}
|
485 |
}
|
486 |
|
495 |
);
|
496 |
|
497 |
if ( $desc_len < $guidelines['lower'] ) {
|
498 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
499 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooShort'];
|
500 |
$length_i18n = $guidelines_i18n['long']['farTooShort'];
|
501 |
} elseif ( $desc_len < $guidelines['goodLower'] ) {
|
502 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
503 |
$item['reason'] = $guidelines_i18n['shortdot']['tooShort'];
|
504 |
$length_i18n = $guidelines_i18n['long']['tooShort'];
|
505 |
} elseif ( $desc_len > $guidelines['upper'] ) {
|
506 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
507 |
$item['reason'] = $guidelines_i18n['shortdot']['farTooLong'];
|
508 |
$length_i18n = $guidelines_i18n['long']['farTooLong'];
|
509 |
} elseif ( $desc_len > $guidelines['goodUpper'] ) {
|
510 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
511 |
$item['reason'] = $guidelines_i18n['shortdot']['tooLong'];
|
512 |
$length_i18n = $guidelines_i18n['long']['tooLong'];
|
513 |
} else {
|
560 |
'index' => [
|
561 |
'symbol' => \_x( 'I', 'Indexing', 'autodescription' ),
|
562 |
'title' => \__( 'Indexing', 'autodescription' ),
|
563 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
564 |
'reason' => \__( 'Term may be indexed.', 'autodescription' ),
|
565 |
'assess' => [
|
566 |
'base' => \__( 'The robots meta tag allows indexing.', 'autodescription' ),
|
569 |
'noindex' => [
|
570 |
'symbol' => \_x( 'I', 'Indexing', 'autodescription' ),
|
571 |
'title' => \__( 'Indexing', 'autodescription' ),
|
572 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
573 |
'reason' => \__( 'Term may not be indexed.', 'autodescription' ),
|
574 |
'assess' => [
|
575 |
'base' => \__( 'The robots meta tag does not allow indexing.', 'autodescription' ),
|
588 |
}
|
589 |
|
590 |
if ( ! $robots_global['blogpublic'] ) {
|
591 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
592 |
$item['reason'] = $cache['reason']['notpublic'];
|
593 |
|
594 |
unset( $item['assess']['base'] );
|
644 |
'get_custom_field' => true,
|
645 |
] );
|
646 |
if ( $permalink !== $canonical ) {
|
647 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN;
|
648 |
$item['reason'] = $cache['reason']['canonicalurl'];
|
649 |
|
650 |
$item['assess']['protected'] = $cache['assess']['canonicalurl'];
|
654 |
if ( $this->query_cache['states']['isempty'] ) {
|
655 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
656 |
// Everything's as intended...
|
657 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN;
|
658 |
$item['reason'] = $cache['reason']['empty'];
|
659 |
|
660 |
$item['assess']['empty'] = $cache['assess']['empty'];
|
661 |
} else {
|
662 |
// Something's wrong. Maybe override, maybe filter, maybe me.
|
663 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
664 |
|
665 |
$item['reason'] = $cache['reason']['emptyoverride'];
|
666 |
$item['assess']['empty'] = $cache['assess']['emptyoverride'];
|
706 |
'follow' => [
|
707 |
'symbol' => \_x( 'F', 'Following', 'autodescription' ),
|
708 |
'title' => \__( 'Following', 'autodescription' ),
|
709 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
710 |
'reason' => \__( 'Term links may be followed.', 'autodescription' ),
|
711 |
'assess' => [
|
712 |
'base' => \__( 'The robots meta tag allows link following.', 'autodescription' ),
|
715 |
'nofollow' => [
|
716 |
'symbol' => \_x( 'F', 'Following', 'autodescription' ),
|
717 |
'title' => \__( 'Following', 'autodescription' ),
|
718 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
719 |
'reason' => \__( 'Term links may not be followed.', 'autodescription' ),
|
720 |
'assess' => [
|
721 |
'base' => \__( 'The robots meta tag does not allow link following.', 'autodescription' ),
|
734 |
}
|
735 |
|
736 |
if ( ! $robots_global['blogpublic'] ) {
|
737 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
738 |
$item['reason'] = $cache['reason']['notpublic'];
|
739 |
|
740 |
unset( $item['assess']['base'] );
|
779 |
|
780 |
if ( ! $this->query_cache['states']['robotsmeta']['nofollow'] ) {
|
781 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
782 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
783 |
$item['assess']['noindex'] = $cache['assess']['noindex'];
|
784 |
}
|
785 |
|
823 |
'archive' => [
|
824 |
'symbol' => \_x( 'A', 'Archiving', 'autodescription' ),
|
825 |
'title' => \__( 'Archiving', 'autodescription' ),
|
826 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
827 |
'reason' => \__( 'Term may be archived.', 'autodescription' ),
|
828 |
'assess' => [
|
829 |
'base' => \__( 'The robots meta tag allows archiving.', 'autodescription' ),
|
832 |
'noarchive' => [
|
833 |
'symbol' => \_x( 'A', 'Archiving', 'autodescription' ),
|
834 |
'title' => \__( 'Archiving', 'autodescription' ),
|
835 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
836 |
'reason' => \__( 'Term may not be archived.', 'autodescription' ),
|
837 |
'assess' => [
|
838 |
'base' => \__( 'The robots meta tag does not allow archiving.', 'autodescription' ),
|
851 |
}
|
852 |
|
853 |
if ( ! $robots_global['blogpublic'] ) {
|
854 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_BAD;
|
855 |
$item['reason'] = $cache['reason']['notpublic'];
|
856 |
|
857 |
unset( $item['assess']['base'] );
|
896 |
|
897 |
if ( ! $this->query_cache['states']['robotsmeta']['noarchive'] ) {
|
898 |
if ( $this->query_cache['states']['robotsmeta']['noindex'] ) {
|
899 |
+
$item['status'] = \The_SEO_Framework\Interpreters\SEOBar::STATE_OKAY;
|
900 |
$item['assess']['noindex'] = $cache['assess']['noindex'];
|
901 |
}
|
902 |
|
924 |
[
|
925 |
'symbol' => \_x( 'R', 'Redirect', 'autodescription' ),
|
926 |
'title' => \__( 'Redirection', 'autodescription' ),
|
927 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_GOOD,
|
928 |
'reason' => \__( 'Term does not redirect visitors.', 'autodescription' ),
|
929 |
'assess' => [
|
930 |
'redirect' => \__( 'All visitors and crawlers may access this page.', 'autodescription' ),
|
940 |
[
|
941 |
'symbol' => \_x( 'R', 'Redirect', 'autodescription' ),
|
942 |
'title' => \__( 'Redirection', 'autodescription' ),
|
943 |
+
'status' => \The_SEO_Framework\Interpreters\SEOBar::STATE_UNKNOWN,
|
944 |
'reason' => \__( 'Term redirects visitors.', 'autodescription' ),
|
945 |
'assess' => [
|
946 |
'redirect' => \__( 'All visitors and crawlers are being redirected. So, no other SEO enhancements are effective.', 'autodescription' ),
|
@@ -25,261 +25,18 @@ namespace The_SEO_Framework\Builders;
|
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
|
|
28 |
/**
|
29 |
* Generates the sitemap.
|
30 |
*
|
31 |
* @since 4.0.0
|
|
|
|
|
32 |
* @abstract
|
|
|
|
|
33 |
*
|
34 |
-
* @access
|
|
|
35 |
*/
|
36 |
-
|
37 |
-
|
38 |
-
/**
|
39 |
-
* @var null|\The_SEO_Framework\Load
|
40 |
-
*/
|
41 |
-
protected static $tsf = null;
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Constructor.
|
45 |
-
*
|
46 |
-
* @since 4.0.0
|
47 |
-
*/
|
48 |
-
final public function __construct() {
|
49 |
-
static::$tsf = \the_seo_framework();
|
50 |
-
}
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Destructor.
|
54 |
-
*
|
55 |
-
* @since 4.0.0
|
56 |
-
*/
|
57 |
-
final public function __destruct() {
|
58 |
-
static::$tsf = null;
|
59 |
-
}
|
60 |
-
|
61 |
-
/**
|
62 |
-
* Prepares sitemap generation by raising the memory limit and fixing the timezone.
|
63 |
-
*
|
64 |
-
* @since 4.0.0
|
65 |
-
* @since 4.0.4 Now sets timezone to UTC to fix WP 5.3 bug <https://core.trac.wordpress.org/ticket/48623>
|
66 |
-
*/
|
67 |
-
final public function prepare_generation() {
|
68 |
-
|
69 |
-
\wp_raise_memory_limit( 'sitemap' );
|
70 |
-
|
71 |
-
// Set timezone according to settings.
|
72 |
-
static::$tsf->set_timezone( 'UTC' );
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* Shuts down the sitemap generator.
|
77 |
-
*
|
78 |
-
* @since 4.0.0
|
79 |
-
*/
|
80 |
-
final public function shutdown_generation() {
|
81 |
-
static::$tsf->reset_timezone();
|
82 |
-
}
|
83 |
-
|
84 |
-
/**
|
85 |
-
* Generates and returns the sitemap content.
|
86 |
-
* We recommend you overwriting this method to include caching.
|
87 |
-
*
|
88 |
-
* @since 4.1.2
|
89 |
-
* @abstract
|
90 |
-
* TODO consider adding ...$args?
|
91 |
-
*
|
92 |
-
* @return string The sitemap content.
|
93 |
-
*/
|
94 |
-
public function generate_sitemap() {
|
95 |
-
|
96 |
-
$this->prepare_generation();
|
97 |
-
|
98 |
-
$sitemap = $this->build_sitemap();
|
99 |
-
|
100 |
-
$this->shutdown_generation();
|
101 |
-
|
102 |
-
return $sitemap;
|
103 |
-
}
|
104 |
-
|
105 |
-
/**
|
106 |
-
* Returns the sitemap content.
|
107 |
-
*
|
108 |
-
* @since 4.0.0
|
109 |
-
* @abstract
|
110 |
-
*
|
111 |
-
* @return string The sitemap content.
|
112 |
-
*/
|
113 |
-
abstract public function build_sitemap();
|
114 |
-
|
115 |
-
/**
|
116 |
-
* Creates XML entry from array input.
|
117 |
-
* Input is expected to be escaped and XML-safe.
|
118 |
-
*
|
119 |
-
* Note: Not final, other classes may overwrite this.
|
120 |
-
*
|
121 |
-
* @since 4.1.1
|
122 |
-
*
|
123 |
-
* @param array $data The data to create an XML item from. Expected to be escaped and XML-safe!
|
124 |
-
* @param int $level The iteration level. Default 1 (one level in from urlset).
|
125 |
-
* Affects non-mandatory tab indentation for readability.
|
126 |
-
* @return string The XML data.
|
127 |
-
*/
|
128 |
-
protected function create_xml_entry( $data, $level = 1 ) {
|
129 |
-
|
130 |
-
$out = '';
|
131 |
-
|
132 |
-
foreach ( $data as $key => $value ) {
|
133 |
-
$tabs = str_repeat( "\t", $level );
|
134 |
-
|
135 |
-
if ( \is_array( $value ) )
|
136 |
-
$value = "\n" . $this->create_xml_entry( $value, $level + 1 ) . $tabs;
|
137 |
-
|
138 |
-
$out .= "$tabs<$key>$value</$key>\n";
|
139 |
-
}
|
140 |
-
|
141 |
-
return $out;
|
142 |
-
}
|
143 |
-
|
144 |
-
/**
|
145 |
-
* Determines if post is possibly included in the sitemap.
|
146 |
-
*
|
147 |
-
* This is a weak check, as the filter might not be present outside of the sitemap's scope.
|
148 |
-
* The URL also isn't checked, nor the position.
|
149 |
-
*
|
150 |
-
* @since 3.0.4
|
151 |
-
* @since 3.0.6 First filter value now works as intended.
|
152 |
-
* @since 3.1.0 1. Resolved a PHP notice when ID is 0, resulting in returning false-esque unintentionally.
|
153 |
-
* 2. Now accepts 0 in the filter.
|
154 |
-
* @since 4.0.0 1. Now tests qubit options.
|
155 |
-
* 2. FALSE: Now tests for redirect settings. <- it never did! We did document this though...
|
156 |
-
* 3. First parameter can now be a post object.
|
157 |
-
* 4. If the first parameter is 0, it's now indicative of a home-as-blog page.
|
158 |
-
* 5. Moved to \The_SEO_Framework\Builders\Sitemap
|
159 |
-
* @since 4.1.4 TRUE: Now tests for redirect settings.
|
160 |
-
*
|
161 |
-
* @param int $post_id The Post ID to check.
|
162 |
-
* @return bool True if included, false otherwise.
|
163 |
-
*/
|
164 |
-
final public function is_post_included_in_sitemap( $post_id ) {
|
165 |
-
|
166 |
-
static $excluded = null;
|
167 |
-
if ( null === $excluded ) {
|
168 |
-
/**
|
169 |
-
* @since 2.5.2
|
170 |
-
* @since 2.8.0 No longer accepts '0' as entry.
|
171 |
-
* @since 3.1.0 '0' is accepted again.
|
172 |
-
* @param int[] $excluded Sequential list of excluded IDs: [ int ...post_id ]
|
173 |
-
*/
|
174 |
-
$excluded = (array) \apply_filters( 'the_seo_framework_sitemap_exclude_ids', [] );
|
175 |
-
|
176 |
-
if ( empty( $excluded ) ) {
|
177 |
-
$excluded = [];
|
178 |
-
} else {
|
179 |
-
// isset() is faster than in_array(). So, we flip it.
|
180 |
-
$excluded = array_flip( $excluded );
|
181 |
-
}
|
182 |
-
}
|
183 |
-
|
184 |
-
$included = ! isset( $excluded[ $post_id ] );
|
185 |
-
|
186 |
-
while ( $included ) :
|
187 |
-
$_args = [
|
188 |
-
'id' => $post_id,
|
189 |
-
'taxonomy' => '',
|
190 |
-
];
|
191 |
-
|
192 |
-
// ROBOTS_IGNORE_PROTECTION as we don't need to test 'private' (because of sole 'publish'), and 'password' (because of false 'has_password')
|
193 |
-
$meta = static::$tsf->generate_robots_meta( $_args, null, \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION );
|
194 |
-
$included = ! ( isset( $meta['noindex'] ) && 'noindex' === $meta['noindex'] );
|
195 |
-
|
196 |
-
if ( ! $included ) break;
|
197 |
-
|
198 |
-
$included = ! static::$tsf->get_redirect_url( $_args );
|
199 |
-
break;
|
200 |
-
endwhile;
|
201 |
-
|
202 |
-
return $included;
|
203 |
-
}
|
204 |
-
|
205 |
-
/**
|
206 |
-
* Determines if post is possibly included in the sitemap.
|
207 |
-
*
|
208 |
-
* This is a weak check, as the filter might not be present outside of the sitemap's scope.
|
209 |
-
* The URL also isn't checked, nor the position.
|
210 |
-
*
|
211 |
-
* @since 4.0.0
|
212 |
-
* @since 4.1.4 Now tests for redirect settings.
|
213 |
-
* @see https://github.com/sybrew/tsf-term-sitemap for example.
|
214 |
-
*
|
215 |
-
* @param int $term_id The Term ID to check.
|
216 |
-
* @param string $taxonomy The taxonomy.
|
217 |
-
* @return bool True if included, false otherwise.
|
218 |
-
*/
|
219 |
-
final public function is_term_included_in_sitemap( $term_id, $taxonomy ) {
|
220 |
-
|
221 |
-
static $excluded = null;
|
222 |
-
if ( null === $excluded ) {
|
223 |
-
/**
|
224 |
-
* @since 4.0.0
|
225 |
-
* @param int[] $excluded Sequential list of excluded IDs: [ int ...term_id ]
|
226 |
-
*/
|
227 |
-
$excluded = (array) \apply_filters( 'the_seo_framework_sitemap_exclude_term_ids', [] );
|
228 |
-
|
229 |
-
if ( empty( $excluded ) ) {
|
230 |
-
$excluded = [];
|
231 |
-
} else {
|
232 |
-
// isset() is faster than in_array(). So, we flip it.
|
233 |
-
$excluded = array_flip( $excluded );
|
234 |
-
}
|
235 |
-
}
|
236 |
-
|
237 |
-
$included = ! isset( $excluded[ $term_id ] );
|
238 |
-
|
239 |
-
// Yes, 90% of this code code isn't DRY. However, terms != posts. terms == posts, though :).
|
240 |
-
// Really: <https://core.trac.wordpress.org/ticket/50568>
|
241 |
-
while ( $included ) :
|
242 |
-
$_args = [
|
243 |
-
'id' => $term_id,
|
244 |
-
'taxonomy' => $taxonomy,
|
245 |
-
];
|
246 |
-
|
247 |
-
// ROBOTS_IGNORE_PROTECTION is not tested for terms. However, we may use that later.
|
248 |
-
$meta = static::$tsf->generate_robots_meta( $_args, null, \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION );
|
249 |
-
$included = ! ( isset( $meta['noindex'] ) && 'noindex' === $meta['noindex'] );
|
250 |
-
|
251 |
-
if ( ! $included ) break;
|
252 |
-
|
253 |
-
$included = ! static::$tsf->get_redirect_url( $_args );
|
254 |
-
break;
|
255 |
-
endwhile;
|
256 |
-
|
257 |
-
return $included;
|
258 |
-
}
|
259 |
-
|
260 |
-
/**
|
261 |
-
* Returns the sitemap post query limit.
|
262 |
-
*
|
263 |
-
* @since 3.1.0
|
264 |
-
* @since 4.0.0 Moved to \The_SEO_Framework\Builders\Sitemap
|
265 |
-
*
|
266 |
-
* @param bool $hierarchical Whether the query is for hierarchical post types or not.
|
267 |
-
* @return int The post limit
|
268 |
-
*/
|
269 |
-
final protected function get_sitemap_post_limit( $hierarchical = false ) {
|
270 |
-
/**
|
271 |
-
* @since 2.2.9
|
272 |
-
* @since 2.8.0 Increased to 1200 from 700.
|
273 |
-
* @since 3.1.0 Now returns an option value; it falls back to the default value if not set.
|
274 |
-
* @since 4.0.0 1. The default is now 3000, from 1200.
|
275 |
-
* 2. Now passes a second parameter.
|
276 |
-
* @param int $total_post_limit
|
277 |
-
* @param bool $hierarchical Whether the query is for hierarchical post types or not.
|
278 |
-
*/
|
279 |
-
return (int) \apply_filters(
|
280 |
-
'the_seo_framework_sitemap_post_limit',
|
281 |
-
static::$tsf->get_option( 'sitemap_query_limit' ),
|
282 |
-
$hierarchical
|
283 |
-
);
|
284 |
-
}
|
285 |
-
}
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
+
\tsf()->_deprecated_function( 'The_SEO_Framework\Builders\Sitemap', '4.2.0', 'The_SEO_Framework\Builders\Sitemap\Main' );
|
29 |
/**
|
30 |
* Generates the sitemap.
|
31 |
*
|
32 |
* @since 4.0.0
|
33 |
+
* @since 4.2.0 1. Moved to \The_SEO_Framework\Builders\Sitemap\Main
|
34 |
+
* 2. Deprecated.
|
35 |
* @abstract
|
36 |
+
* @deprecated
|
37 |
+
* @ignore
|
38 |
*
|
39 |
+
* @access protected
|
40 |
+
* Use \The_SEO_Framework\Builders\Sitemap\Main instead.
|
41 |
*/
|
42 |
+
class_alias( 'The_SEO_Framework\Builders\Sitemap\Main', 'The_SEO_Framework\Builders\Sitemap', true );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -4,7 +4,7 @@
|
|
4 |
* @subpackage The_SEO_Framework\Sitemap
|
5 |
*/
|
6 |
|
7 |
-
namespace The_SEO_Framework\Builders;
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
@@ -25,14 +25,17 @@ namespace The_SEO_Framework\Builders;
|
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
|
|
|
|
28 |
/**
|
29 |
* Generates the base sitemap.
|
30 |
*
|
31 |
* @since 4.0.0
|
|
|
32 |
*
|
33 |
* @access private
|
34 |
*/
|
35 |
-
class
|
36 |
|
37 |
/**
|
38 |
* @since 4.1.2
|
@@ -145,7 +148,7 @@ class Sitemap_Base extends Sitemap {
|
|
145 |
* @since 4.0.0 1. Now assesses all public post types, in favor of qubit options.
|
146 |
* 2. Improved performance by a factor of two+.
|
147 |
* 3. Renamed method from "generate_sitemap" to abstract extension "build_sitemap".
|
148 |
-
* 4. Moved to \The_SEO_Framework\Builders\
|
149 |
* @abstract
|
150 |
*
|
151 |
* @return string The sitemap content.
|
@@ -155,7 +158,6 @@ class Sitemap_Base extends Sitemap {
|
|
155 |
$content = '';
|
156 |
$count = 0;
|
157 |
|
158 |
-
$show_priority = (bool) static::$tsf->get_option( 'sitemaps_priority' );
|
159 |
$show_modified = (bool) static::$tsf->get_option( 'sitemaps_modified' );
|
160 |
|
161 |
/**
|
@@ -168,19 +170,17 @@ class Sitemap_Base extends Sitemap {
|
|
168 |
$content .= sprintf(
|
169 |
'<!-- %s -->',
|
170 |
sprintf(
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
: \esc_html__( 'Sitemap is generated on %s', 'autodescription' )
|
177 |
-
),
|
178 |
\current_time( 'Y-m-d H:i:s \G\M\T' )
|
179 |
)
|
180 |
) . "\n";
|
181 |
|
182 |
foreach ( $this->generate_front_and_blog_url_items(
|
183 |
-
compact( '
|
184 |
$count
|
185 |
) as $_values ) {
|
186 |
$content .= $this->build_url_item( $_values );
|
@@ -303,7 +303,7 @@ class Sitemap_Base extends Sitemap {
|
|
303 |
|
304 |
foreach ( $this->generate_url_item_values(
|
305 |
$_items,
|
306 |
-
compact( '
|
307 |
$count
|
308 |
) as $_values ) {
|
309 |
$content .= $this->build_url_item( $_values );
|
@@ -311,7 +311,7 @@ class Sitemap_Base extends Sitemap {
|
|
311 |
|
312 |
if ( \has_filter( 'the_seo_framework_sitemap_additional_urls' ) ) {
|
313 |
foreach ( $this->generate_additional_base_urls(
|
314 |
-
compact( '
|
315 |
$count
|
316 |
) as $_values ) {
|
317 |
$content .= $this->build_url_item( $_values );
|
@@ -324,9 +324,9 @@ class Sitemap_Base extends Sitemap {
|
|
324 |
*
|
325 |
* @since 2.5.2
|
326 |
* @since 4.0.0 Added $args parameter.
|
|
|
327 |
* @param string $extend Custom sitemap extension. Must be escaped.
|
328 |
* @param array $args : {
|
329 |
-
* bool $show_priority : Whether to display priority
|
330 |
* bool $show_modified : Whether to display modified date.
|
331 |
* int $total_itemns : Estimate: The total sitemap items before adding additional URLs.
|
332 |
* }
|
@@ -335,7 +335,7 @@ class Sitemap_Base extends Sitemap {
|
|
335 |
'the_seo_framework_sitemap_extend',
|
336 |
[
|
337 |
'',
|
338 |
-
compact( '
|
339 |
]
|
340 |
);
|
341 |
|
@@ -362,86 +362,59 @@ class Sitemap_Base extends Sitemap {
|
|
362 |
*/
|
363 |
protected function generate_front_and_blog_url_items( $args, &$count = 0 ) {
|
364 |
|
365 |
-
$front_page_id = (int) \get_option( 'page_on_front' );
|
366 |
-
$posts_page_id = (int) \get_option( 'page_for_posts' );
|
367 |
-
|
368 |
if ( static::$tsf->has_page_on_front() ) {
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
'id' => $front_page_id,
|
378 |
-
'taxonomy' => '',
|
379 |
-
]
|
380 |
);
|
381 |
-
|
382 |
-
if ( $args['show_modified'] ) {
|
383 |
-
$post = \get_post( $front_page_id );
|
384 |
-
$_values['lastmod'] = isset( $post->post_modified_gmt ) ? $post->post_modified_gmt : false;
|
385 |
-
}
|
386 |
-
|
387 |
-
if ( $args['show_priority'] ) {
|
388 |
-
$_values['priority'] = '1.0';
|
389 |
-
}
|
390 |
-
|
391 |
-
++$count;
|
392 |
-
yield $_values;
|
393 |
}
|
394 |
-
if ( $posts_page_id && $this->is_post_included_in_sitemap( $posts_page_id ) ) {
|
395 |
-
// Reset.
|
396 |
-
$_values = [];
|
397 |
-
$_values['loc'] = static::$tsf->create_canonical_url(
|
398 |
-
[
|
399 |
-
'id' => $posts_page_id,
|
400 |
-
'taxonomy' => '',
|
401 |
-
]
|
402 |
-
);
|
403 |
-
|
404 |
-
if ( $args['show_modified'] ) {
|
405 |
-
$latests_posts = \wp_get_recent_posts(
|
406 |
-
[
|
407 |
-
'numberposts' => 1,
|
408 |
-
'post_type' => 'post',
|
409 |
-
'post_status' => 'publish',
|
410 |
-
'has_password' => false,
|
411 |
-
'orderby' => 'post_date',
|
412 |
-
'order' => 'DESC',
|
413 |
-
'offset' => 0,
|
414 |
-
],
|
415 |
-
\OBJECT
|
416 |
-
);
|
417 |
-
$latest_post = isset( $latests_posts[0] ) ? $latests_posts[0] : null;
|
418 |
-
$_publish_post = isset( $latest_post->post_date_gmt ) ? $latest_post->post_date_gmt : '0000-00-00 00:00:00';
|
419 |
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
427 |
}
|
428 |
|
429 |
-
|
430 |
-
* @since 4.1.1
|
431 |
-
* @param string $lastmod The lastmod time in SQL notation (`Y-m-d H:i:s`). Expected to explicitly follow that format!
|
432 |
-
*/
|
433 |
-
$_values['lastmod'] = (string) \apply_filters( 'the_seo_framework_sitemap_blog_lastmod', $_values['lastmod'] );
|
434 |
-
}
|
435 |
-
|
436 |
-
if ( $args['show_priority'] ) {
|
437 |
-
$_values['priority'] = '1.0';
|
438 |
}
|
439 |
-
|
440 |
-
++$count;
|
441 |
-
yield $_values;
|
442 |
}
|
443 |
} else {
|
444 |
-
// Blog page as front.
|
445 |
if ( $this->is_post_included_in_sitemap( 0 ) ) {
|
446 |
// Reset.
|
447 |
$_values = [];
|
@@ -458,20 +431,19 @@ class Sitemap_Base extends Sitemap {
|
|
458 |
'order' => 'DESC',
|
459 |
'offset' => 0,
|
460 |
],
|
461 |
-
|
462 |
);
|
463 |
|
464 |
-
$_values['lastmod'] = isset( $latests_posts[0]->post_date_gmt ) ? $latests_posts[0]->post_date_gmt : '0000-00-00 00:00:00';
|
465 |
-
|
466 |
/**
|
467 |
* @since 4.1.1
|
468 |
* @param string $lastmod The lastmod time in SQL notation (`Y-m-d H:i:s`). Expected to explicitly follow that format!
|
469 |
*/
|
470 |
-
$_values['lastmod'] = (string) \
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
|
|
475 |
}
|
476 |
|
477 |
++$count;
|
@@ -499,36 +471,24 @@ class Sitemap_Base extends Sitemap {
|
|
499 |
*/
|
500 |
protected function generate_url_item_values( $post_ids, $args, &$count = 0 ) {
|
501 |
|
502 |
-
static $using_external_object_cache = null;
|
503 |
-
|
504 |
-
$using_external_object_cache = isset( $using_external_object_cache ) ? $using_external_object_cache : (bool) \wp_using_ext_object_cache();
|
505 |
-
|
506 |
foreach ( $post_ids as $post_id ) {
|
507 |
// Setup post cache, which is also used in is_post_included_in_sitemap() and create_canonical_url().
|
508 |
$post = \get_post( $post_id );
|
509 |
|
510 |
if ( $this->is_post_included_in_sitemap( $post_id ) ) {
|
511 |
-
$_values
|
512 |
-
|
513 |
-
|
514 |
-
'id' => $post_id,
|
515 |
-
'taxonomy' => '',
|
516 |
-
]
|
517 |
-
);
|
518 |
|
519 |
if ( $args['show_modified'] )
|
520 |
-
$_values['lastmod'] =
|
521 |
-
|
522 |
-
if ( $args['show_priority'] ) {
|
523 |
-
// Add at least 1 to prevent going negative. We added 8 extra (= 9) to smoothen the slope.
|
524 |
-
$_values['priority'] = .949999 - ( $count / ( $args['total_items'] + 9 ) );
|
525 |
-
}
|
526 |
|
527 |
++$count;
|
528 |
yield $_values;
|
529 |
}
|
530 |
|
531 |
-
|
|
|
532 |
}
|
533 |
}
|
534 |
|
@@ -549,20 +509,17 @@ class Sitemap_Base extends Sitemap {
|
|
549 |
|
550 |
if ( empty( $args['loc'] ) ) return '';
|
551 |
|
552 |
-
static $timestamp_format = null;
|
553 |
-
|
554 |
-
if ( ! isset( $timestamp_format ) )
|
555 |
-
$timestamp_format = static::$tsf->get_timestamp_format();
|
556 |
-
|
557 |
$xml = [
|
558 |
'loc' => $args['loc'], // Already escaped.
|
559 |
];
|
560 |
|
561 |
-
if ( isset( $args['lastmod'] ) && '0000-00-00 00:00:00' !== $args['lastmod'] )
|
562 |
-
|
563 |
|
564 |
-
|
565 |
-
|
|
|
|
|
566 |
|
567 |
return $this->create_xml_entry( [ 'url' => $xml ], 1 );
|
568 |
}
|
@@ -571,13 +528,12 @@ class Sitemap_Base extends Sitemap {
|
|
571 |
* Retrieves additional URLs and builds items from them.
|
572 |
*
|
573 |
* @since 4.0.0
|
574 |
-
* @since 4.0.1
|
575 |
-
*
|
576 |
* @generator
|
577 |
* @iterator
|
578 |
*
|
579 |
* @param array $args : {
|
580 |
-
* bool $show_priority : Whether to display priority
|
581 |
* bool $show_modified : Whether to display modified date.
|
582 |
* int $count : The total sitemap items before adding additional URLs.
|
583 |
* }
|
@@ -589,12 +545,12 @@ class Sitemap_Base extends Sitemap {
|
|
589 |
* }
|
590 |
*/
|
591 |
protected function generate_additional_base_urls( $args, &$count = 0 ) {
|
592 |
-
|
593 |
/**
|
594 |
* @since 2.5.2
|
595 |
* @since 3.2.2 Invalid URLs are now skipped.
|
596 |
* @since 4.0.0 Added $args parameter.
|
597 |
-
* @
|
|
|
598 |
* @param array $custom_urls : {
|
599 |
* string (key) $url The absolute url to the page. : array {
|
600 |
* string $lastmod : UNIXTIME <GMT+0> Last modified date, e.g. "2016-01-26 13:04:55"
|
@@ -602,7 +558,6 @@ class Sitemap_Base extends Sitemap {
|
|
602 |
* }
|
603 |
* }
|
604 |
* @param array $args : {
|
605 |
-
* bool $show_priority : Whether to display priority
|
606 |
* bool $show_modified : Whether to display modified date.
|
607 |
* int $count : Estimate: The total sitemap items before adding additional URLs.
|
608 |
* }
|
@@ -625,9 +580,6 @@ class Sitemap_Base extends Sitemap {
|
|
625 |
if ( $args['show_modified'] )
|
626 |
$_values['lastmod'] = ! empty( $values['lastmod'] ) ? $values['lastmod'] : '0000-00-00 00:00:00';
|
627 |
|
628 |
-
if ( $args['show_priority'] )
|
629 |
-
$_values['priority'] = ! empty( $values['priority'] ) ? $values['priority'] : 0.9;
|
630 |
-
|
631 |
++$count;
|
632 |
yield $_values;
|
633 |
}
|
4 |
* @subpackage The_SEO_Framework\Sitemap
|
5 |
*/
|
6 |
|
7 |
+
namespace The_SEO_Framework\Builders\Sitemap;
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
+
use function \The_SEO_Framework\umemo;
|
29 |
+
|
30 |
/**
|
31 |
* Generates the base sitemap.
|
32 |
*
|
33 |
* @since 4.0.0
|
34 |
+
* @since 4.2.0 Renamed to `The_SEO_Framework\Builders\Sitemap\Base` from `The_SEO_Framework\Builders\Sitemap_Base`
|
35 |
*
|
36 |
* @access private
|
37 |
*/
|
38 |
+
class Base extends Main {
|
39 |
|
40 |
/**
|
41 |
* @since 4.1.2
|
148 |
* @since 4.0.0 1. Now assesses all public post types, in favor of qubit options.
|
149 |
* 2. Improved performance by a factor of two+.
|
150 |
* 3. Renamed method from "generate_sitemap" to abstract extension "build_sitemap".
|
151 |
+
* 4. Moved to \The_SEO_Framework\Builders\Sitemap\Base
|
152 |
* @abstract
|
153 |
*
|
154 |
* @return string The sitemap content.
|
158 |
$content = '';
|
159 |
$count = 0;
|
160 |
|
|
|
161 |
$show_modified = (bool) static::$tsf->get_option( 'sitemaps_modified' );
|
162 |
|
163 |
/**
|
170 |
$content .= sprintf(
|
171 |
'<!-- %s -->',
|
172 |
sprintf(
|
173 |
+
$this->base_is_prerendering
|
174 |
+
/* translators: %s = timestamp */
|
175 |
+
? \esc_html__( 'Sitemap is prerendered on %s', 'autodescription' )
|
176 |
+
/* translators: %s = timestamp */
|
177 |
+
: \esc_html__( 'Sitemap is generated on %s', 'autodescription' ),
|
|
|
|
|
178 |
\current_time( 'Y-m-d H:i:s \G\M\T' )
|
179 |
)
|
180 |
) . "\n";
|
181 |
|
182 |
foreach ( $this->generate_front_and_blog_url_items(
|
183 |
+
compact( 'show_modified' ),
|
184 |
$count
|
185 |
) as $_values ) {
|
186 |
$content .= $this->build_url_item( $_values );
|
303 |
|
304 |
foreach ( $this->generate_url_item_values(
|
305 |
$_items,
|
306 |
+
compact( 'show_modified', 'total_items' ),
|
307 |
$count
|
308 |
) as $_values ) {
|
309 |
$content .= $this->build_url_item( $_values );
|
311 |
|
312 |
if ( \has_filter( 'the_seo_framework_sitemap_additional_urls' ) ) {
|
313 |
foreach ( $this->generate_additional_base_urls(
|
314 |
+
compact( 'show_modified', 'count' ),
|
315 |
$count
|
316 |
) as $_values ) {
|
317 |
$content .= $this->build_url_item( $_values );
|
324 |
*
|
325 |
* @since 2.5.2
|
326 |
* @since 4.0.0 Added $args parameter.
|
327 |
+
* @since 4.2.0 No longer forwards the 'show_priority' index in the second ($args) parameter.
|
328 |
* @param string $extend Custom sitemap extension. Must be escaped.
|
329 |
* @param array $args : {
|
|
|
330 |
* bool $show_modified : Whether to display modified date.
|
331 |
* int $total_itemns : Estimate: The total sitemap items before adding additional URLs.
|
332 |
* }
|
335 |
'the_seo_framework_sitemap_extend',
|
336 |
[
|
337 |
'',
|
338 |
+
compact( 'show_modified', 'count' ),
|
339 |
]
|
340 |
);
|
341 |
|
362 |
*/
|
363 |
protected function generate_front_and_blog_url_items( $args, &$count = 0 ) {
|
364 |
|
|
|
|
|
|
|
365 |
if ( static::$tsf->has_page_on_front() ) {
|
366 |
+
$front_page_id = (int) \get_option( 'page_on_front' );
|
367 |
+
$posts_page_id = (int) \get_option( 'page_for_posts' );
|
368 |
+
|
369 |
+
if ( $front_page_id ) {
|
370 |
+
yield from $this->generate_url_item_values(
|
371 |
+
[ $front_page_id ],
|
372 |
+
$args,
|
373 |
+
$count
|
|
|
|
|
|
|
374 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
375 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
376 |
|
377 |
+
if ( $posts_page_id && $this->is_post_included_in_sitemap( $posts_page_id ) ) {
|
378 |
+
foreach ( $this->generate_url_item_values(
|
379 |
+
[ $posts_page_id ],
|
380 |
+
$args,
|
381 |
+
$count
|
382 |
+
) as $_values ) {
|
383 |
+
if ( $_values['loc'] && $args['show_modified'] ) {
|
384 |
+
$latests_posts = \wp_get_recent_posts(
|
385 |
+
[
|
386 |
+
'numberposts' => 1,
|
387 |
+
'post_type' => 'post',
|
388 |
+
'post_status' => 'publish',
|
389 |
+
'has_password' => false,
|
390 |
+
'orderby' => 'post_date',
|
391 |
+
'order' => 'DESC',
|
392 |
+
'offset' => 0,
|
393 |
+
],
|
394 |
+
OBJECT
|
395 |
+
);
|
396 |
+
$_publish_post = $latests_posts[0]->post_date_gmt ?? '0000-00-00 00:00:00';
|
397 |
+
$_lastmod_blog = $_values['lastmod']; // Inferred from generator generate_url_item_values()
|
398 |
+
|
399 |
+
/**
|
400 |
+
* @since 4.1.1
|
401 |
+
* @param string $lastmod The lastmod time in SQL notation (`Y-m-d H:i:s`). Expected to explicitly follow that format!
|
402 |
+
*/
|
403 |
+
$_values['lastmod'] = (string) \apply_filters_ref_array(
|
404 |
+
'the_seo_framework_sitemap_blog_lastmod',
|
405 |
+
[
|
406 |
+
strtotime( $_publish_post ) > strtotime( $_lastmod_blog )
|
407 |
+
? $_publish_post
|
408 |
+
: $_lastmod_blog,
|
409 |
+
]
|
410 |
+
);
|
411 |
}
|
412 |
|
413 |
+
yield $_values;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
414 |
}
|
|
|
|
|
|
|
415 |
}
|
416 |
} else {
|
417 |
+
// Blog page as front. Unique; cannot go through generate_url_item_values().
|
418 |
if ( $this->is_post_included_in_sitemap( 0 ) ) {
|
419 |
// Reset.
|
420 |
$_values = [];
|
431 |
'order' => 'DESC',
|
432 |
'offset' => 0,
|
433 |
],
|
434 |
+
OBJECT
|
435 |
);
|
436 |
|
|
|
|
|
437 |
/**
|
438 |
* @since 4.1.1
|
439 |
* @param string $lastmod The lastmod time in SQL notation (`Y-m-d H:i:s`). Expected to explicitly follow that format!
|
440 |
*/
|
441 |
+
$_values['lastmod'] = (string) \apply_filters_ref_array(
|
442 |
+
'the_seo_framework_sitemap_blog_lastmod',
|
443 |
+
[
|
444 |
+
$latests_posts[0]->post_date_gmt ?? '0000-00-00 00:00:00',
|
445 |
+
]
|
446 |
+
);
|
447 |
}
|
448 |
|
449 |
++$count;
|
471 |
*/
|
472 |
protected function generate_url_item_values( $post_ids, $args, &$count = 0 ) {
|
473 |
|
|
|
|
|
|
|
|
|
474 |
foreach ( $post_ids as $post_id ) {
|
475 |
// Setup post cache, which is also used in is_post_included_in_sitemap() and create_canonical_url().
|
476 |
$post = \get_post( $post_id );
|
477 |
|
478 |
if ( $this->is_post_included_in_sitemap( $post_id ) ) {
|
479 |
+
$_values = [
|
480 |
+
'loc' => static::$tsf->create_canonical_url( [ 'id' => $post_id ] ),
|
481 |
+
];
|
|
|
|
|
|
|
|
|
482 |
|
483 |
if ( $args['show_modified'] )
|
484 |
+
$_values['lastmod'] = $post->post_modified_gmt ?? '0000-00-00 00:00:00';
|
|
|
|
|
|
|
|
|
|
|
485 |
|
486 |
++$count;
|
487 |
yield $_values;
|
488 |
}
|
489 |
|
490 |
+
// Only clean post cache when NOT using an external object caching plugin.
|
491 |
+
\wp_using_ext_object_cache() or \clean_post_cache( $post );
|
492 |
}
|
493 |
}
|
494 |
|
509 |
|
510 |
if ( empty( $args['loc'] ) ) return '';
|
511 |
|
|
|
|
|
|
|
|
|
|
|
512 |
$xml = [
|
513 |
'loc' => $args['loc'], // Already escaped.
|
514 |
];
|
515 |
|
516 |
+
if ( isset( $args['lastmod'] ) && '0000-00-00 00:00:00' !== $args['lastmod'] ) {
|
517 |
+
static $timestamp_format;
|
518 |
|
519 |
+
$timestamp_format = $timestamp_format ?? static::$tsf->get_timestamp_format();
|
520 |
+
|
521 |
+
$xml['lastmod'] = static::$tsf->gmt2date( $timestamp_format, $args['lastmod'] );
|
522 |
+
}
|
523 |
|
524 |
return $this->create_xml_entry( [ 'url' => $xml ], 1 );
|
525 |
}
|
528 |
* Retrieves additional URLs and builds items from them.
|
529 |
*
|
530 |
* @since 4.0.0
|
531 |
+
* @since 4.0.1 1. Converted to generator and iterator. Therefore, renamed function.
|
532 |
+
* 2. Now actually does something.
|
533 |
* @generator
|
534 |
* @iterator
|
535 |
*
|
536 |
* @param array $args : {
|
|
|
537 |
* bool $show_modified : Whether to display modified date.
|
538 |
* int $count : The total sitemap items before adding additional URLs.
|
539 |
* }
|
545 |
* }
|
546 |
*/
|
547 |
protected function generate_additional_base_urls( $args, &$count = 0 ) {
|
|
|
548 |
/**
|
549 |
* @since 2.5.2
|
550 |
* @since 3.2.2 Invalid URLs are now skipped.
|
551 |
* @since 4.0.0 Added $args parameter.
|
552 |
+
* @since 4.2.0 No longer forwards the 'show_priority' index in the second ($args) parameter.
|
553 |
+
* @example return value: [ 'http://example.com' => [ 'lastmod' => '14-01-2018' ] ]
|
554 |
* @param array $custom_urls : {
|
555 |
* string (key) $url The absolute url to the page. : array {
|
556 |
* string $lastmod : UNIXTIME <GMT+0> Last modified date, e.g. "2016-01-26 13:04:55"
|
558 |
* }
|
559 |
* }
|
560 |
* @param array $args : {
|
|
|
561 |
* bool $show_modified : Whether to display modified date.
|
562 |
* int $count : Estimate: The total sitemap items before adding additional URLs.
|
563 |
* }
|
580 |
if ( $args['show_modified'] )
|
581 |
$_values['lastmod'] = ! empty( $values['lastmod'] ) ? $values['lastmod'] : '0000-00-00 00:00:00';
|
582 |
|
|
|
|
|
|
|
583 |
++$count;
|
584 |
yield $_values;
|
585 |
}
|
File without changes
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Builders\Sitemap
|
4 |
+
* @subpackage The_SEO_Framework\Sitemap
|
5 |
+
*/
|
6 |
+
|
7 |
+
namespace The_SEO_Framework\Builders\Sitemap;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* The SEO Framework plugin
|
11 |
+
* Copyright (C) 2019 - 2021 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/)
|
12 |
+
*
|
13 |
+
* This program is free software: you can redistribute it and/or modify
|
14 |
+
* it under the terms of the GNU General Public License version 3 as published
|
15 |
+
* by the Free Software Foundation.
|
16 |
+
*
|
17 |
+
* This program is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
* GNU General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU General Public License
|
23 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
+
*/
|
25 |
+
|
26 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Generates the sitemap.
|
30 |
+
*
|
31 |
+
* @since 4.0.0
|
32 |
+
* @since 4.2.0 Renamed to `The_SEO_Framework\Builders\Sitemap\Main` from `The_SEO_Framework\Builders\Sitemap`
|
33 |
+
* @abstract
|
34 |
+
*
|
35 |
+
* @access public
|
36 |
+
*/
|
37 |
+
abstract class Main {
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @var null|\The_SEO_Framework\Load
|
41 |
+
*/
|
42 |
+
protected static $tsf = null;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Constructor.
|
46 |
+
*
|
47 |
+
* @since 4.0.0
|
48 |
+
*/
|
49 |
+
final public function __construct() {
|
50 |
+
static::$tsf = \tsf();
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Destructor.
|
55 |
+
*
|
56 |
+
* @since 4.0.0
|
57 |
+
*/
|
58 |
+
final public function __destruct() {
|
59 |
+
static::$tsf = null;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Prepares sitemap generation by raising the memory limit and fixing the timezone.
|
64 |
+
*
|
65 |
+
* @since 4.0.0
|
66 |
+
* @since 4.0.4 Now sets timezone to UTC to fix WP 5.3 bug <https://core.trac.wordpress.org/ticket/48623>
|
67 |
+
* @since 4.2.0 No longer sets timezone.
|
68 |
+
*/
|
69 |
+
final public function prepare_generation() {
|
70 |
+
\wp_raise_memory_limit( 'sitemap' );
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Shuts down the sitemap generator.
|
75 |
+
*
|
76 |
+
* @since 4.0.0
|
77 |
+
* @since 4.2.0 No longer resets timezone.
|
78 |
+
* @ignore
|
79 |
+
*/
|
80 |
+
final public function shutdown_generation() { }
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Generates and returns the sitemap content.
|
84 |
+
* We recommend you overwriting this method to include caching.
|
85 |
+
*
|
86 |
+
* @since 4.1.2
|
87 |
+
* @abstract
|
88 |
+
* TODO consider adding ...$args?
|
89 |
+
*
|
90 |
+
* @return string The sitemap content.
|
91 |
+
*/
|
92 |
+
public function generate_sitemap() {
|
93 |
+
|
94 |
+
$this->prepare_generation();
|
95 |
+
|
96 |
+
$sitemap = $this->build_sitemap();
|
97 |
+
|
98 |
+
$this->shutdown_generation();
|
99 |
+
|
100 |
+
return $sitemap;
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Returns the sitemap content.
|
105 |
+
*
|
106 |
+
* @since 4.0.0
|
107 |
+
* @abstract
|
108 |
+
*
|
109 |
+
* @return string The sitemap content.
|
110 |
+
*/
|
111 |
+
abstract public function build_sitemap();
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Creates XML entry from array input.
|
115 |
+
* Input is expected to be escaped and XML-safe.
|
116 |
+
*
|
117 |
+
* Note: Not final, other classes may overwrite this.
|
118 |
+
*
|
119 |
+
* @since 4.1.1
|
120 |
+
*
|
121 |
+
* @param iterable $data The data to create an XML item from. Expected to be escaped and XML-safe!
|
122 |
+
* @param int $level The iteration level. Default 1 (one level in from urlset).
|
123 |
+
* Affects non-mandatory tab indentation for readability.
|
124 |
+
* @return string The XML data.
|
125 |
+
*/
|
126 |
+
protected function create_xml_entry( $data, $level = 1 ) {
|
127 |
+
|
128 |
+
$out = '';
|
129 |
+
|
130 |
+
foreach ( $data as $key => $value ) {
|
131 |
+
$tabs = str_repeat( "\t", $level );
|
132 |
+
|
133 |
+
if ( \is_array( $value ) )
|
134 |
+
$value = "\n" . $this->create_xml_entry( $value, $level + 1 ) . $tabs;
|
135 |
+
|
136 |
+
$out .= "$tabs<$key>$value</$key>\n";
|
137 |
+
}
|
138 |
+
|
139 |
+
return $out;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Determines if post is possibly included in the sitemap.
|
144 |
+
*
|
145 |
+
* This is a weak check, as the filter might not be present outside of the sitemap's scope.
|
146 |
+
* The URL also isn't checked, nor the position.
|
147 |
+
*
|
148 |
+
* @since 3.0.4
|
149 |
+
* @since 3.0.6 First filter value now works as intended.
|
150 |
+
* @since 3.1.0 1. Resolved a PHP notice when ID is 0, resulting in returning false-esque unintentionally.
|
151 |
+
* 2. Now accepts 0 in the filter.
|
152 |
+
* @since 4.0.0 1. Now tests qubit options.
|
153 |
+
* 2. FALSE: Now tests for redirect settings. <- it never did! We did document this though...
|
154 |
+
* 3. First parameter can now be a post object.
|
155 |
+
* 4. If the first parameter is 0, it's now indicative of a home-as-blog page.
|
156 |
+
* 5. Moved to \The_SEO_Framework\Builders\Sitemap
|
157 |
+
* @since 4.1.4 TRUE: Now tests for redirect settings.
|
158 |
+
* @since 4.2.0 Now only asserts noindex robots-values, instead of all robots-values, improving performance.
|
159 |
+
*
|
160 |
+
* @param int $post_id The Post ID to check.
|
161 |
+
* @return bool True if included, false otherwise.
|
162 |
+
*/
|
163 |
+
final public function is_post_included_in_sitemap( $post_id ) {
|
164 |
+
|
165 |
+
static $excluded = null;
|
166 |
+
if ( null === $excluded ) {
|
167 |
+
/**
|
168 |
+
* @since 2.5.2
|
169 |
+
* @since 2.8.0 No longer accepts '0' as entry.
|
170 |
+
* @since 3.1.0 '0' is accepted again.
|
171 |
+
* @param int[] $excluded Sequential list of excluded IDs: [ int ...post_id ]
|
172 |
+
*/
|
173 |
+
$excluded = (array) \apply_filters( 'the_seo_framework_sitemap_exclude_ids', [] );
|
174 |
+
|
175 |
+
// isset() is faster than in_array(). So, we flip it.
|
176 |
+
$excluded = $excluded ? array_flip( $excluded ) : [];
|
177 |
+
}
|
178 |
+
|
179 |
+
$included = ! isset( $excluded[ $post_id ] );
|
180 |
+
|
181 |
+
while ( $included ) :
|
182 |
+
$_args = [ 'id' => $post_id ];
|
183 |
+
|
184 |
+
// ROBOTS_IGNORE_PROTECTION as we don't need to test 'private' ('post_status'=>'publish'), nor 'password' ('has_password'=>false)
|
185 |
+
$included = 'noindex'
|
186 |
+
!== (
|
187 |
+
static::$tsf->generate_robots_meta( $_args, [ 'noindex' ], \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION )['noindex']
|
188 |
+
?? false // We cast type false for Zend tests strict type before identical-string-comparing.
|
189 |
+
);
|
190 |
+
|
191 |
+
if ( ! $included ) break;
|
192 |
+
|
193 |
+
$included = ! static::$tsf->get_redirect_url( $_args );
|
194 |
+
break;
|
195 |
+
endwhile;
|
196 |
+
|
197 |
+
return $included;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Determines if post is possibly included in the sitemap.
|
202 |
+
*
|
203 |
+
* This is a weak check, as the filter might not be present outside of the sitemap's scope.
|
204 |
+
* The URL also isn't checked, nor the position.
|
205 |
+
*
|
206 |
+
* @since 4.0.0
|
207 |
+
* @since 4.1.4 Now tests for redirect settings.
|
208 |
+
* @since 4.2.0 Now only asserts noindex robots-values, instead of all robots-values, improving performance.
|
209 |
+
* @see https://github.com/sybrew/tsf-term-sitemap for example.
|
210 |
+
*
|
211 |
+
* @param int $term_id The Term ID to check.
|
212 |
+
* @param string $taxonomy The taxonomy.
|
213 |
+
* @return bool True if included, false otherwise.
|
214 |
+
*/
|
215 |
+
final public function is_term_included_in_sitemap( $term_id, $taxonomy ) {
|
216 |
+
|
217 |
+
static $excluded = null;
|
218 |
+
if ( null === $excluded ) {
|
219 |
+
/**
|
220 |
+
* @since 4.0.0
|
221 |
+
* @param int[] $excluded Sequential list of excluded IDs: [ int ...term_id ]
|
222 |
+
*/
|
223 |
+
$excluded = (array) \apply_filters( 'the_seo_framework_sitemap_exclude_term_ids', [] );
|
224 |
+
|
225 |
+
// isset() is faster than in_array(). So, we flip it.
|
226 |
+
$excluded = $excluded ? array_flip( $excluded ) : [];
|
227 |
+
}
|
228 |
+
|
229 |
+
$included = ! isset( $excluded[ $term_id ] );
|
230 |
+
|
231 |
+
// Yes, 90% of this code code isn't DRY. However, terms !== posts. terms == posts, though :).
|
232 |
+
// Really: <https://core.trac.wordpress.org/ticket/50568>
|
233 |
+
while ( $included ) :
|
234 |
+
$_args = [
|
235 |
+
'id' => $term_id,
|
236 |
+
'taxonomy' => $taxonomy,
|
237 |
+
];
|
238 |
+
|
239 |
+
// ROBOTS_IGNORE_PROTECTION is not tested for terms. However, we may use that later.
|
240 |
+
$included = 'noindex'
|
241 |
+
!== (
|
242 |
+
static::$tsf->generate_robots_meta( $_args, [ 'noindex' ], \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION )['noindex']
|
243 |
+
?? false // We cast type false for Zend tests strict type before identical-string-comparing.
|
244 |
+
);
|
245 |
+
|
246 |
+
if ( ! $included ) break;
|
247 |
+
|
248 |
+
$included = ! static::$tsf->get_redirect_url( $_args );
|
249 |
+
break;
|
250 |
+
endwhile;
|
251 |
+
|
252 |
+
return $included;
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Returns the sitemap post query limit.
|
257 |
+
*
|
258 |
+
* @since 3.1.0
|
259 |
+
* @since 4.0.0 Moved to \The_SEO_Framework\Builders\Sitemap
|
260 |
+
*
|
261 |
+
* @param bool $hierarchical Whether the query is for hierarchical post types or not.
|
262 |
+
* @return int The post limit
|
263 |
+
*/
|
264 |
+
final protected function get_sitemap_post_limit( $hierarchical = false ) {
|
265 |
+
/**
|
266 |
+
* @since 2.2.9
|
267 |
+
* @since 2.8.0 Increased to 1200 from 700.
|
268 |
+
* @since 3.1.0 Now returns an option value; it falls back to the default value if not set.
|
269 |
+
* @since 4.0.0 1. The default is now 3000, from 1200.
|
270 |
+
* 2. Now passes a second parameter.
|
271 |
+
* @param int $total_post_limit
|
272 |
+
* @param bool $hierarchical Whether the query is for hierarchical post types or not.
|
273 |
+
*/
|
274 |
+
return (int) \apply_filters(
|
275 |
+
'the_seo_framework_sitemap_post_limit',
|
276 |
+
static::$tsf->get_option( 'sitemap_query_limit' ),
|
277 |
+
$hierarchical
|
278 |
+
);
|
279 |
+
}
|
280 |
+
}
|
@@ -169,7 +169,7 @@ class Cache extends Site_Options {
|
|
169 |
* @param array $args Additional arguments. They can overwrite $type and $id.
|
170 |
* @return bool true on success, false on failure.
|
171 |
*/
|
172 |
-
public function delete_cache( $type, $id = 0,
|
173 |
|
174 |
$this->parse_delete_cache_keys( $type, $id, $args );
|
175 |
|
@@ -192,7 +192,7 @@ class Cache extends Site_Options {
|
|
192 |
* @since 3.1.0
|
193 |
*
|
194 |
* @param string $type The flush type. Comes in handy when you use a catch-all function.
|
195 |
-
* @param int $id The post, page or TT ID. Defaults to
|
196 |
* @param array $args Additional arguments. They can overwrite $type and $id.
|
197 |
* @param bool $success Whether the action cleared.
|
198 |
*/
|
@@ -212,7 +212,7 @@ class Cache extends Site_Options {
|
|
212 |
*/
|
213 |
protected function parse_delete_cache_keys( &$type, &$id, &$args ) {
|
214 |
|
215 |
-
|
216 |
$id = $id ?: $this->get_the_real_ID( false );
|
217 |
|
218 |
$defaults = [
|
@@ -249,9 +249,7 @@ class Cache extends Site_Options {
|
|
249 |
* @param int $expiration Transient expiration date, optional. Expected to not be SQL-escaped.
|
250 |
*/
|
251 |
public function set_transient( $transient, $value, $expiration = 0 ) {
|
252 |
-
|
253 |
-
if ( $this->the_seo_framework_use_transients )
|
254 |
-
\set_transient( $transient, $value, $expiration );
|
255 |
}
|
256 |
|
257 |
/**
|
@@ -288,7 +286,7 @@ class Cache extends Site_Options {
|
|
288 |
*/
|
289 |
public function get_exclusion_transient_name() {
|
290 |
$exclude_revision = '1'; // WARNING: SEE NOTE
|
291 |
-
return $this->add_cache_key_suffix(
|
292 |
}
|
293 |
|
294 |
/**
|
@@ -300,7 +298,7 @@ class Cache extends Site_Options {
|
|
300 |
*/
|
301 |
public function get_sitemap_transient_name() {
|
302 |
$sitemap_revision = '5';
|
303 |
-
return $this->get_option( 'cache_sitemap' ) ? $this->add_cache_key_suffix(
|
304 |
}
|
305 |
|
306 |
/**
|
@@ -310,8 +308,8 @@ class Cache extends Site_Options {
|
|
310 |
*
|
311 |
* @since 2.3.3
|
312 |
* @since 2.6.0 Refactored.
|
313 |
-
* @since 2.9.1
|
314 |
-
*
|
315 |
* @since 3.1.1 The first parameter is now optional.
|
316 |
* @since 4.1.4 No longer generates a cache key when no `$type` is supplied.
|
317 |
* @TODO since we only support by type, it'd be best to rework this into something simple.
|
@@ -322,11 +320,7 @@ class Cache extends Site_Options {
|
|
322 |
* @return string The generated cache key by query or type.
|
323 |
*/
|
324 |
public function generate_cache_key( $id = 0, $taxonomy = '', $type = null ) {
|
325 |
-
|
326 |
-
if ( isset( $type ) )
|
327 |
-
return $this->generate_cache_key_by_type( $id, $taxonomy, $type );
|
328 |
-
|
329 |
-
return '';
|
330 |
}
|
331 |
|
332 |
/**
|
@@ -354,7 +348,7 @@ class Cache extends Site_Options {
|
|
354 |
return $this->add_cache_key_suffix( 'tsf_sitemap_lock' );
|
355 |
default:
|
356 |
$this->_doing_it_wrong( __METHOD__, 'Third parameter must be a known type.', '2.6.5' );
|
357 |
-
return $this->add_cache_key_suffix( \esc_sql( $type
|
358 |
endswitch;
|
359 |
}
|
360 |
|
@@ -371,7 +365,10 @@ class Cache extends Site_Options {
|
|
371 |
* @return string
|
372 |
*/
|
373 |
protected function add_cache_key_suffix( $key = '' ) {
|
374 |
-
|
|
|
|
|
|
|
375 |
}
|
376 |
|
377 |
/**
|
@@ -425,11 +422,12 @@ class Cache extends Site_Options {
|
|
425 |
'the_seo_framework_sitemap_transient_cleared',
|
426 |
[
|
427 |
'ping_use_cron' => $ping_use_cron,
|
428 |
-
'ping_use_cron_prerender' => $ping_use_cron_prerender,
|
429 |
]
|
430 |
);
|
431 |
|
432 |
if ( $ping_use_cron ) {
|
|
|
433 |
\The_SEO_Framework\Bridges\Ping::engage_pinging_cron();
|
434 |
} else {
|
435 |
\The_SEO_Framework\Bridges\Ping::ping_search_engines();
|
@@ -453,62 +451,60 @@ class Cache extends Site_Options {
|
|
453 |
*/
|
454 |
public function get_excluded_ids_from_cache() {
|
455 |
|
456 |
-
if ( $this->is_headless['meta'] )
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
static $cache = null;
|
462 |
-
|
463 |
-
if ( null === $cache )
|
464 |
-
$cache = $this->get_transient( $this->get_exclusion_transient_name() );
|
465 |
-
|
466 |
-
if ( false === $cache ) {
|
467 |
-
global $wpdb;
|
468 |
-
|
469 |
-
$supported_post_types = $this->get_supported_post_types();
|
470 |
-
$public_post_types = $this->get_public_post_types();
|
471 |
-
|
472 |
-
$join = '';
|
473 |
-
$where = '';
|
474 |
-
if ( $supported_post_types !== $public_post_types ) {
|
475 |
-
// Post types can be registered arbitrarily through other plugins, even manually by non-super-admins. Prepare!
|
476 |
-
$post_type__in = "'" . implode( "','", array_map( '\\esc_sql', $supported_post_types ) ) . "'";
|
477 |
-
|
478 |
-
// This is as fast as I could make it. Yes, it uses IN, but only on a (tiny) subset of data.
|
479 |
-
$join = "LEFT JOIN {$wpdb->posts} ON {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID";
|
480 |
-
$where = "AND {$wpdb->posts}.post_type IN ($post_type__in)";
|
481 |
-
}
|
482 |
-
|
483 |
-
//= Two separated equals queries are faster than a single IN with 'meta_key'.
|
484 |
-
// phpcs:disable, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- We prepared our whole lives.
|
485 |
-
$cache = [
|
486 |
-
'archive' => $wpdb->get_results(
|
487 |
-
"SELECT post_id, meta_value FROM $wpdb->postmeta $join WHERE meta_key = 'exclude_from_archive' $where"
|
488 |
-
),
|
489 |
-
'search' => $wpdb->get_results(
|
490 |
-
"SELECT post_id, meta_value FROM $wpdb->postmeta $join WHERE meta_key = 'exclude_local_search' $where"
|
491 |
-
),
|
492 |
];
|
493 |
-
// phpcs:enable, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
494 |
-
|
495 |
-
foreach ( [ 'archive', 'search' ] as $type ) {
|
496 |
-
array_walk(
|
497 |
-
$cache[ $type ],
|
498 |
-
static function( &$v ) {
|
499 |
-
if ( isset( $v->meta_value, $v->post_id ) && $v->meta_value ) {
|
500 |
-
$v = (int) $v->post_id;
|
501 |
-
} else {
|
502 |
-
$v = false;
|
503 |
-
}
|
504 |
-
}
|
505 |
-
);
|
506 |
-
$cache[ $type ] = array_filter( $cache[ $type ] );
|
507 |
-
}
|
508 |
|
509 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
510 |
}
|
511 |
|
512 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
513 |
}
|
514 |
}
|
169 |
* @param array $args Additional arguments. They can overwrite $type and $id.
|
170 |
* @return bool true on success, false on failure.
|
171 |
*/
|
172 |
+
public function delete_cache( $type, $id = 0, $args = [] ) {
|
173 |
|
174 |
$this->parse_delete_cache_keys( $type, $id, $args );
|
175 |
|
192 |
* @since 3.1.0
|
193 |
*
|
194 |
* @param string $type The flush type. Comes in handy when you use a catch-all function.
|
195 |
+
* @param int $id The post, page or TT ID. Defaults to tsf()->get_the_real_ID().
|
196 |
* @param array $args Additional arguments. They can overwrite $type and $id.
|
197 |
* @param bool $success Whether the action cleared.
|
198 |
*/
|
212 |
*/
|
213 |
protected function parse_delete_cache_keys( &$type, &$id, &$args ) {
|
214 |
|
215 |
+
// Don't use cache on fetching ID.
|
216 |
$id = $id ?: $this->get_the_real_ID( false );
|
217 |
|
218 |
$defaults = [
|
249 |
* @param int $expiration Transient expiration date, optional. Expected to not be SQL-escaped.
|
250 |
*/
|
251 |
public function set_transient( $transient, $value, $expiration = 0 ) {
|
252 |
+
$this->the_seo_framework_use_transients and \set_transient( $transient, $value, $expiration );
|
|
|
|
|
253 |
}
|
254 |
|
255 |
/**
|
286 |
*/
|
287 |
public function get_exclusion_transient_name() {
|
288 |
$exclude_revision = '1'; // WARNING: SEE NOTE
|
289 |
+
return $this->add_cache_key_suffix( "tsf_exclude_{$exclude_revision}" );
|
290 |
}
|
291 |
|
292 |
/**
|
298 |
*/
|
299 |
public function get_sitemap_transient_name() {
|
300 |
$sitemap_revision = '5';
|
301 |
+
return $this->get_option( 'cache_sitemap' ) ? $this->add_cache_key_suffix( "tsf_sitemap_{$sitemap_revision}" ) : '';
|
302 |
}
|
303 |
|
304 |
/**
|
308 |
*
|
309 |
* @since 2.3.3
|
310 |
* @since 2.6.0 Refactored.
|
311 |
+
* @since 2.9.1 1. Added early singular type detection.
|
312 |
+
* 2. Moved generation into another method (v4.1.4: removed method).
|
313 |
* @since 3.1.1 The first parameter is now optional.
|
314 |
* @since 4.1.4 No longer generates a cache key when no `$type` is supplied.
|
315 |
* @TODO since we only support by type, it'd be best to rework this into something simple.
|
320 |
* @return string The generated cache key by query or type.
|
321 |
*/
|
322 |
public function generate_cache_key( $id = 0, $taxonomy = '', $type = null ) {
|
323 |
+
return isset( $type ) ? $this->generate_cache_key_by_type( $id, $taxonomy, $type ) : '';
|
|
|
|
|
|
|
|
|
324 |
}
|
325 |
|
326 |
/**
|
348 |
return $this->add_cache_key_suffix( 'tsf_sitemap_lock' );
|
349 |
default:
|
350 |
$this->_doing_it_wrong( __METHOD__, 'Third parameter must be a known type.', '2.6.5' );
|
351 |
+
return $this->add_cache_key_suffix( \esc_sql( "{$type}_{$page_id}_{$taxonomy}" ) );
|
352 |
endswitch;
|
353 |
}
|
354 |
|
365 |
* @return string
|
366 |
*/
|
367 |
protected function add_cache_key_suffix( $key = '' ) {
|
368 |
+
|
369 |
+
$locale = strtolower( \get_locale() );
|
370 |
+
|
371 |
+
return "{$key}_{$GLOBALS['blog_id']}_{$locale}";
|
372 |
}
|
373 |
|
374 |
/**
|
422 |
'the_seo_framework_sitemap_transient_cleared',
|
423 |
[
|
424 |
'ping_use_cron' => $ping_use_cron,
|
425 |
+
'ping_use_cron_prerender' => $ping_use_cron_prerender, // TODO migrate this so it can run regardless of pinging?
|
426 |
]
|
427 |
);
|
428 |
|
429 |
if ( $ping_use_cron ) {
|
430 |
+
// This name is wrong. It's not exclusively used for pinging.
|
431 |
\The_SEO_Framework\Bridges\Ping::engage_pinging_cron();
|
432 |
} else {
|
433 |
\The_SEO_Framework\Bridges\Ping::ping_search_engines();
|
451 |
*/
|
452 |
public function get_excluded_ids_from_cache() {
|
453 |
|
454 |
+
if ( $this->is_headless['meta'] )
|
455 |
+
return [
|
456 |
+
'archive' => '',
|
457 |
+
'search' => '',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
458 |
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
459 |
|
460 |
+
$cache = memo() ?? memo( $this->get_transient( $this->get_exclusion_transient_name() ) );
|
461 |
+
|
462 |
+
if ( false !== $cache ) return $cache;
|
463 |
+
|
464 |
+
global $wpdb;
|
465 |
+
|
466 |
+
$supported_post_types = $this->get_supported_post_types();
|
467 |
+
$public_post_types = $this->get_public_post_types();
|
468 |
+
|
469 |
+
$join = '';
|
470 |
+
$where = '';
|
471 |
+
if ( $supported_post_types !== $public_post_types ) {
|
472 |
+
// Post types can be registered arbitrarily through other plugins, even manually by non-super-admins. Prepare!
|
473 |
+
$post_type__in = "'" . implode( "','", array_map( 'esc_sql', $supported_post_types ) ) . "'";
|
474 |
+
|
475 |
+
// This is as fast as I could make it. Yes, it uses IN, but only on a (tiny) subset of data.
|
476 |
+
$join = "LEFT JOIN {$wpdb->posts} ON {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID";
|
477 |
+
$where = "AND {$wpdb->posts}.post_type IN ($post_type__in)";
|
478 |
}
|
479 |
|
480 |
+
// Two separated equals queries are faster than a single IN with 'meta_key'.
|
481 |
+
// phpcs:disable, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- We prepared our whole lives.
|
482 |
+
$cache = [
|
483 |
+
'archive' => $wpdb->get_results(
|
484 |
+
"SELECT post_id, meta_value FROM $wpdb->postmeta $join WHERE meta_key = 'exclude_from_archive' $where"
|
485 |
+
),
|
486 |
+
'search' => $wpdb->get_results(
|
487 |
+
"SELECT post_id, meta_value FROM $wpdb->postmeta $join WHERE meta_key = 'exclude_local_search' $where"
|
488 |
+
),
|
489 |
+
];
|
490 |
+
// phpcs:enable, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
491 |
+
|
492 |
+
foreach ( [ 'archive', 'search' ] as $type ) {
|
493 |
+
array_walk(
|
494 |
+
$cache[ $type ],
|
495 |
+
static function( &$v ) {
|
496 |
+
if ( isset( $v->meta_value, $v->post_id ) && $v->meta_value ) {
|
497 |
+
$v = (int) $v->post_id;
|
498 |
+
} else {
|
499 |
+
$v = false;
|
500 |
+
}
|
501 |
+
}
|
502 |
+
);
|
503 |
+
$cache[ $type ] = array_filter( $cache[ $type ] );
|
504 |
+
}
|
505 |
+
|
506 |
+
$this->set_transient( $this->get_exclusion_transient_name(), $cache, 0 );
|
507 |
+
|
508 |
+
return memo( $cache );
|
509 |
}
|
510 |
}
|
@@ -31,6 +31,7 @@ namespace The_SEO_Framework;
|
|
31 |
* Initializes the plugin & Holds plugin core functions.
|
32 |
*
|
33 |
* @since 2.8.0
|
|
|
34 |
*/
|
35 |
class Core {
|
36 |
|
@@ -66,7 +67,7 @@ class Core {
|
|
66 |
final public function __set( $name, $value ) {
|
67 |
|
68 |
if ( 'load_options' === $name ) {
|
69 |
-
|
70 |
$this->is_headless['settings'] = $value;
|
71 |
return;
|
72 |
}
|
@@ -74,7 +75,7 @@ class Core {
|
|
74 |
/**
|
75 |
* For now, no deprecation is being handled; as no properties have been deprecated. Just removed.
|
76 |
*/
|
77 |
-
$this->_inaccessible_p_or_m(
|
78 |
|
79 |
// Invoke default behavior: Write variable if it's not protected.
|
80 |
if ( ! isset( $this->$name ) )
|
@@ -96,11 +97,11 @@ class Core {
|
|
96 |
final public function __get( $name ) {
|
97 |
|
98 |
if ( 'load_options' === $name ) {
|
99 |
-
|
100 |
return ! $this->is_headless['settings'];
|
101 |
}
|
102 |
|
103 |
-
$this->_inaccessible_p_or_m(
|
104 |
}
|
105 |
|
106 |
/**
|
@@ -117,12 +118,12 @@ class Core {
|
|
117 |
static $depr_class = null;
|
118 |
|
119 |
if ( \is_null( $depr_class ) )
|
120 |
-
$depr_class = new Deprecated;
|
121 |
|
122 |
if ( \is_callable( [ $depr_class, $name ] ) )
|
123 |
return \call_user_func_array( [ $depr_class, $name ], $arguments );
|
124 |
|
125 |
-
$this->_inaccessible_p_or_m(
|
126 |
}
|
127 |
|
128 |
/**
|
@@ -158,16 +159,18 @@ class Core {
|
|
158 |
*/
|
159 |
public function _include_compat( $what, $type = 'plugin' ) {
|
160 |
|
161 |
-
|
|
|
|
|
162 |
|
163 |
-
|
164 |
-
|
165 |
-
$_secret = $this->create_view_secret( uniqid( '', true ) );
|
166 |
-
|
167 |
-
$included[ $what ][ $type ] = (bool) require THE_SEO_FRAMEWORK_DIR_PATH_COMPAT . $type . '-' . $what . '.php';
|
168 |
-
}
|
169 |
|
170 |
-
return
|
|
|
|
|
|
|
|
|
171 |
}
|
172 |
|
173 |
/**
|
@@ -178,12 +181,12 @@ class Core {
|
|
178 |
* @access private
|
179 |
* @credits Akismet For some code.
|
180 |
*
|
181 |
-
* @param string
|
182 |
-
* @param
|
183 |
-
*
|
184 |
-
* @param string
|
185 |
*/
|
186 |
-
public function get_view( $view,
|
187 |
|
188 |
//? A faster extract().
|
189 |
foreach ( $__args as $__k => $__v ) $$__k = $__v;
|
@@ -208,8 +211,7 @@ class Core {
|
|
208 |
* @return string|null The stored secret.
|
209 |
*/
|
210 |
protected function create_view_secret( $value = null ) {
|
211 |
-
|
212 |
-
return $secret = isset( $value ) ? $value : $secret;
|
213 |
}
|
214 |
|
215 |
/**
|
@@ -250,7 +252,10 @@ class Core {
|
|
250 |
* @return string The file instance case.
|
251 |
*/
|
252 |
protected function get_view_instance( $base, $instance = 'main' ) {
|
253 |
-
|
|
|
|
|
|
|
254 |
}
|
255 |
|
256 |
/**
|
@@ -262,13 +267,14 @@ class Core {
|
|
262 |
* @return array The public hierarchical post types.
|
263 |
*/
|
264 |
public function get_hierarchical_post_types() {
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
|
|
272 |
);
|
273 |
}
|
274 |
|
@@ -281,13 +287,14 @@ class Core {
|
|
281 |
* @return array The public nonhierarchical post types.
|
282 |
*/
|
283 |
public function get_nonhierarchical_post_types() {
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
|
|
291 |
);
|
292 |
}
|
293 |
|
@@ -300,12 +307,11 @@ class Core {
|
|
300 |
* @return bool Whether external redirect is allowed.
|
301 |
*/
|
302 |
public function allow_external_redirect() {
|
303 |
-
static $cache = null;
|
304 |
/**
|
305 |
* @since 2.1.0
|
306 |
* @param bool $allowed Whether external redirect is allowed.
|
307 |
*/
|
308 |
-
return
|
309 |
}
|
310 |
|
311 |
/**
|
@@ -318,10 +324,7 @@ class Core {
|
|
318 |
* @return bool True is blog is public.
|
319 |
*/
|
320 |
public function is_blog_public() {
|
321 |
-
|
322 |
-
static $cache = null;
|
323 |
-
|
324 |
-
return isset( $cache ) ? $cache : $cache = (bool) \get_option( 'blog_public' );
|
325 |
}
|
326 |
|
327 |
/**
|
@@ -359,10 +362,16 @@ class Core {
|
|
359 |
public function get_settings_capability() {
|
360 |
/**
|
361 |
* @since 2.6.0
|
362 |
-
* @
|
|
|
363 |
* @param string $capability The user capability required to adjust settings.
|
364 |
*/
|
365 |
-
return (string) \
|
|
|
|
|
|
|
|
|
|
|
366 |
}
|
367 |
|
368 |
/**
|
@@ -385,102 +394,14 @@ class Core {
|
|
385 |
* @return string The escaped SEO Settings page URL.
|
386 |
*/
|
387 |
public function get_seo_settings_page_url() {
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
/**
|
398 |
-
* Returns the PHP timezone compatible string.
|
399 |
-
* UTC offsets are unreliable.
|
400 |
-
*
|
401 |
-
* @since 2.6.0
|
402 |
-
*
|
403 |
-
* @param bool $guess If true, the timezone will be guessed from the
|
404 |
-
* WordPress core gmt_offset option.
|
405 |
-
* @return string PHP Timezone String. May be empty (thus invalid).
|
406 |
-
*/
|
407 |
-
public function get_timezone_string( $guess = false ) {
|
408 |
-
|
409 |
-
$tzstring = \get_option( 'timezone_string' );
|
410 |
-
|
411 |
-
if ( false !== strpos( $tzstring, 'Etc/GMT' ) )
|
412 |
-
$tzstring = '';
|
413 |
-
|
414 |
-
if ( $guess && empty( $tzstring ) ) {
|
415 |
-
$tzstring = $this->get_tzstring_from_offset( \get_option( 'gmt_offset' ) );
|
416 |
-
}
|
417 |
-
|
418 |
-
return $tzstring;
|
419 |
-
}
|
420 |
-
|
421 |
-
/**
|
422 |
-
* Fetches the Timezone String from given offset.
|
423 |
-
*
|
424 |
-
* @since 2.6.0
|
425 |
-
* @since 4.0.0 Removed PHP <5.6 support.
|
426 |
-
*
|
427 |
-
* @param int $offset The GMT offzet.
|
428 |
-
* @return string PHP Timezone String.
|
429 |
-
*/
|
430 |
-
protected function get_tzstring_from_offset( $offset = 0 ) {
|
431 |
-
$seconds = round( $offset * HOUR_IN_SECONDS );
|
432 |
-
return timezone_name_from_abbr( '', $seconds, 1 );
|
433 |
-
}
|
434 |
-
|
435 |
-
/**
|
436 |
-
* Sets and resets the timezone.
|
437 |
-
*
|
438 |
-
* NOTE: Always call reset_timezone() ASAP. Don't let changes linger, as they can be destructive.
|
439 |
-
*
|
440 |
-
* This exists because WordPress's current_time() adds discrepancies between UTC and GMT.
|
441 |
-
* This is also far more accurate than WordPress's tiny time table.
|
442 |
-
*
|
443 |
-
* @TODO Note that WordPress 5.3 no longer requires this, and that we should rely on wp_date() instead.
|
444 |
-
* So, we should remove this dependency ASAP.
|
445 |
-
*
|
446 |
-
* @since 2.6.0
|
447 |
-
* @since 3.0.6 Now uses the old timezone string when a new one can't be generated.
|
448 |
-
* @since 4.0.4 Now also unsets the stored timezone string on reset.
|
449 |
-
* @link http://php.net/manual/en/timezones.php
|
450 |
-
*
|
451 |
-
* @param string $tzstring Optional. The PHP Timezone string. Best to leave empty to always get a correct one.
|
452 |
-
* @param bool $reset Whether to reset to default. Ignoring first parameter.
|
453 |
-
* @return bool True on success. False on failure.
|
454 |
-
*/
|
455 |
-
public function set_timezone( $tzstring = '', $reset = false ) {
|
456 |
-
|
457 |
-
static $old_tz = null;
|
458 |
-
|
459 |
-
$old_tz = $old_tz ?: date_default_timezone_get() ?: 'UTC';
|
460 |
-
|
461 |
-
if ( $reset ) {
|
462 |
-
$_revert_tz = $old_tz;
|
463 |
-
$old_tz = null;
|
464 |
-
// phpcs:ignore, WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set
|
465 |
-
return date_default_timezone_set( $_revert_tz );
|
466 |
-
}
|
467 |
-
|
468 |
-
if ( empty( $tzstring ) )
|
469 |
-
$tzstring = $this->get_timezone_string( true ) ?: $old_tz;
|
470 |
-
|
471 |
-
// phpcs:ignore, WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set
|
472 |
-
return date_default_timezone_set( $tzstring );
|
473 |
-
}
|
474 |
-
|
475 |
-
/**
|
476 |
-
* Resets the timezone to default or UTC.
|
477 |
-
*
|
478 |
-
* @since 2.6.0
|
479 |
-
*
|
480 |
-
* @return bool True on success. False on failure.
|
481 |
-
*/
|
482 |
-
public function reset_timezone() {
|
483 |
-
return $this->set_timezone( '', true );
|
484 |
}
|
485 |
|
486 |
/**
|
@@ -488,27 +409,21 @@ class Core {
|
|
488 |
*
|
489 |
* @since 2.7.0
|
490 |
* @since 4.0.4 Now uses `gmdate()` instead of `date()`.
|
491 |
-
* @see `$this->set_timezone()`
|
492 |
-
* @see `$this->reset_timezone()`
|
493 |
*
|
494 |
* @param string $format The datetime format.
|
495 |
* @param string $time The GMT time. Expects timezone to be omitted.
|
496 |
* @return string The converted time. Empty string if no $time is given.
|
497 |
*/
|
498 |
public function gmt2date( $format = 'Y-m-d', $time = '' ) {
|
499 |
-
|
500 |
-
if ( $time )
|
501 |
-
return gmdate( $format, strtotime( $time . ' GMT' ) );
|
502 |
-
|
503 |
-
return '';
|
504 |
}
|
505 |
|
506 |
/**
|
507 |
* Returns timestamp format based on timestamp settings.
|
508 |
*
|
509 |
* @since 3.0.0
|
510 |
-
* @since 4.1.4
|
511 |
-
*
|
512 |
* @link https://www.w3.org/TR/NOTE-datetime
|
513 |
*
|
514 |
* @param null|bool $override_get_time Whether to override the $get_time from option value.
|
@@ -516,9 +431,7 @@ class Core {
|
|
516 |
*/
|
517 |
public function get_timestamp_format( $override_get_time = null ) {
|
518 |
|
519 |
-
$get_time =
|
520 |
-
? $override_get_time
|
521 |
-
: $this->uses_time_in_timestamp_format();
|
522 |
|
523 |
return \apply_filters_ref_array(
|
524 |
'the_seo_framework_timestamp_format',
|
@@ -545,6 +458,7 @@ class Core {
|
|
545 |
* Unlike PHP's `array_merge_recursive()`, this method doesn't convert non-unique keys as sequential.
|
546 |
*
|
547 |
* A do-while is faster than while. Sorry for the legibility.
|
|
|
548 |
*
|
549 |
* @since 4.1.4
|
550 |
*
|
@@ -556,8 +470,7 @@ class Core {
|
|
556 |
$i = \count( $arrays );
|
557 |
|
558 |
if ( 2 === $i ) foreach ( $arrays[1] as $key => $value ) {
|
559 |
-
$arrays[0][ $key ] =
|
560 |
-
isset( $arrays[0][ $key ] ) && \is_array( $arrays[0][ $key ] )
|
561 |
? $this->array_merge_recursive_distinct( $arrays[0][ $key ], $value )
|
562 |
: $value;
|
563 |
} else do {
|
@@ -572,6 +485,7 @@ class Core {
|
|
572 |
* Shortens string and adds ellipses when over a threshold in length.
|
573 |
*
|
574 |
* @since 3.1.0
|
|
|
575 |
*
|
576 |
* @param string $string The string to test and maybe trim
|
577 |
* @param int $over The character limit. Must be over 0 to have effect.
|
@@ -581,9 +495,8 @@ class Core {
|
|
581 |
*/
|
582 |
public function hellip_if_over( $string, $over = 0 ) {
|
583 |
|
584 |
-
if ( $over > 0 && \strlen( $string ) > $over )
|
585 |
-
$string = substr( $string, 0, abs( $over - 2 ) ) . '
|
586 |
-
}
|
587 |
|
588 |
return $string;
|
589 |
}
|
@@ -602,72 +515,67 @@ class Core {
|
|
602 |
* @since 4.0.0 1. Now expects PCRE UTF-8 encoding support.
|
603 |
* 2. Moved input-parameter alterting filters outside of this function.
|
604 |
* 3. Short length now works as intended, instead of comparing as less, it compares as less or equal to.
|
|
|
|
|
605 |
*
|
606 |
* @param string $string Required. The string to count words in.
|
607 |
-
* @param int $dupe_count
|
608 |
-
*
|
609 |
-
* @param int $dupe_short
|
610 |
-
*
|
611 |
-
* @param int $short_length
|
612 |
-
*
|
613 |
* @return array Containing arrays of words with their count.
|
614 |
*/
|
615 |
public function get_word_count( $string, $dupe_count = 3, $dupe_short = 5, $short_length = 3 ) {
|
616 |
|
617 |
-
$string = html_entity_decode( $string );
|
618 |
-
$string = \wp_check_invalid_utf8( $string );
|
619 |
|
620 |
if ( ! $string ) return [];
|
621 |
|
622 |
-
|
623 |
|
624 |
-
isset( $use_mb ) or ( $use_mb = \extension_loaded( 'mbstring' ) );
|
625 |
-
|
626 |
-
// TODO does this test well for "we're"? We haven't had any reports, though.
|
627 |
$word_list = preg_split(
|
628 |
-
'/[^\p{
|
629 |
$use_mb ? mb_strtolower( $string ) : strtolower( $string ),
|
630 |
-1,
|
631 |
PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_NO_EMPTY
|
632 |
);
|
633 |
|
634 |
-
$
|
635 |
|
636 |
-
|
637 |
-
$words = [];
|
638 |
-
foreach ( $word_list as $wli ) {
|
639 |
-
//= { $words[ int Offset ] => string Word }
|
640 |
-
$words[ $wli[1] ] = $wli[0];
|
641 |
-
}
|
642 |
|
643 |
-
|
|
|
644 |
|
645 |
-
|
646 |
-
|
647 |
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
|
662 |
-
|
663 |
|
664 |
-
|
665 |
-
|
666 |
-
}
|
667 |
}
|
668 |
-
|
669 |
|
670 |
-
|
|
|
|
|
671 |
}
|
672 |
|
673 |
/**
|
@@ -676,31 +584,33 @@ class Core {
|
|
676 |
* @since 2.8.0
|
677 |
* @since 2.9.0 Now adds a little more relative softness based on rel_lum.
|
678 |
* @since 2.9.2 (Typo): Renamed from 'get_relatitve_fontcolor' to 'get_relative_fontcolor'.
|
679 |
-
* @since 3.0.4 Now uses WCAG's relative luminance formula
|
|
|
|
|
680 |
* @link https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast
|
681 |
* @link https://www.w3.org/WAI/GL/wiki/Relative_luminance
|
682 |
*
|
683 |
* @param string $hex The 3 to 6 character RGB hex. The '#' prefix may be added.
|
|
|
684 |
* @return string The hexadecimal RGB relative font color, without '#' prefix.
|
685 |
*/
|
686 |
public function get_relative_fontcolor( $hex = '' ) {
|
687 |
|
688 |
$hex = ltrim( $hex, '#' );
|
689 |
|
690 |
-
//
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
$b = hexdec( $hex[2] );
|
700 |
|
701 |
$get_relative_luminance = static function( $v ) {
|
702 |
-
|
703 |
-
$v /=
|
704 |
|
705 |
if ( $v > .03928 ) {
|
706 |
$lum = ( ( $v + .055 ) / 1.055 ) ** 2.4;
|
@@ -710,32 +620,25 @@ class Core {
|
|
710 |
return $lum;
|
711 |
};
|
712 |
|
713 |
-
//
|
714 |
-
$
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
$rel_lum = ( $sr + $sg + $sb );
|
719 |
|
720 |
// Build light greyscale.
|
721 |
-
$gr = ( $r * 0.2989 / 8 ) * $
|
722 |
-
$gg = ( $g * 0.5870 / 8 ) * $
|
723 |
-
$gb = ( $b * 0.1140 / 8 ) * $
|
724 |
-
|
725 |
-
|
726 |
-
if ( $
|
727 |
-
// Build dark greyscale.
|
728 |
-
$gr
|
729 |
-
$gg
|
730 |
-
$gb
|
731 |
}
|
732 |
|
733 |
-
|
734 |
-
$retr = str_pad( dechex( round( $gr ) ), 2, '0', STR_PAD_LEFT );
|
735 |
-
$retg = str_pad( dechex( round( $gg ) ), 2, '0', STR_PAD_LEFT );
|
736 |
-
$retb = str_pad( dechex( round( $gb ) ), 2, '0', STR_PAD_LEFT );
|
737 |
-
|
738 |
-
return $retr . $retg . $retb;
|
739 |
}
|
740 |
|
741 |
/**
|
@@ -759,8 +662,8 @@ class Core {
|
|
759 |
$accent = $this->s_color_hex( $this->get_option( 'sitemap_color_accent' ) );
|
760 |
|
761 |
$options = [
|
762 |
-
'main' => $main ?
|
763 |
-
'accent' => $accent ?
|
764 |
];
|
765 |
|
766 |
$options = array_filter( $options );
|
31 |
* Initializes the plugin & Holds plugin core functions.
|
32 |
*
|
33 |
* @since 2.8.0
|
34 |
+
* @since 4.2.0 Deprecated $load_options
|
35 |
*/
|
36 |
class Core {
|
37 |
|
67 |
final public function __set( $name, $value ) {
|
68 |
|
69 |
if ( 'load_options' === $name ) {
|
70 |
+
$this->_inaccessible_p_or_m( 'tsf()->load_options', 'since 4.2.0; use constant THE_SEO_FRAMEWORK_HEADLESS' );
|
71 |
$this->is_headless['settings'] = $value;
|
72 |
return;
|
73 |
}
|
75 |
/**
|
76 |
* For now, no deprecation is being handled; as no properties have been deprecated. Just removed.
|
77 |
*/
|
78 |
+
$this->_inaccessible_p_or_m( "tsf()->$name", 'unknown' );
|
79 |
|
80 |
// Invoke default behavior: Write variable if it's not protected.
|
81 |
if ( ! isset( $this->$name ) )
|
97 |
final public function __get( $name ) {
|
98 |
|
99 |
if ( 'load_options' === $name ) {
|
100 |
+
$this->_inaccessible_p_or_m( 'tsf()->load_options', 'since 4.2.0; use constant THE_SEO_FRAMEWORK_HEADLESS' );
|
101 |
return ! $this->is_headless['settings'];
|
102 |
}
|
103 |
|
104 |
+
$this->_inaccessible_p_or_m( "tsf()->$name", 'unknown' );
|
105 |
}
|
106 |
|
107 |
/**
|
118 |
static $depr_class = null;
|
119 |
|
120 |
if ( \is_null( $depr_class ) )
|
121 |
+
$depr_class = new Internal\Deprecated;
|
122 |
|
123 |
if ( \is_callable( [ $depr_class, $name ] ) )
|
124 |
return \call_user_func_array( [ $depr_class, $name ], $arguments );
|
125 |
|
126 |
+
$this->_inaccessible_p_or_m( "tsf()->$name()" );
|
127 |
}
|
128 |
|
129 |
/**
|
159 |
*/
|
160 |
public function _include_compat( $what, $type = 'plugin' ) {
|
161 |
|
162 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
163 |
+
if ( null !== $memo = memo( null, $what, $type ) ) return $memo;
|
164 |
+
unset( $memo );
|
165 |
|
166 |
+
// phpcs:ignore, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- forwarded to include...
|
167 |
+
$_secret = $this->create_view_secret( uniqid( '', true ) );
|
|
|
|
|
|
|
|
|
168 |
|
169 |
+
return memo(
|
170 |
+
(bool) require THE_SEO_FRAMEWORK_DIR_PATH_COMPAT . "$type-$what.php",
|
171 |
+
$what,
|
172 |
+
$type
|
173 |
+
);
|
174 |
}
|
175 |
|
176 |
/**
|
181 |
* @access private
|
182 |
* @credits Akismet For some code.
|
183 |
*
|
184 |
+
* @param string $view The file name.
|
185 |
+
* @param iterable $__args The arguments to be supplied within the file name.
|
186 |
+
* Each array key is converted to a variable with its value attached.
|
187 |
+
* @param string $instance The instance suffix to call back upon.
|
188 |
*/
|
189 |
+
public function get_view( $view, $__args = [], $instance = 'main' ) {
|
190 |
|
191 |
//? A faster extract().
|
192 |
foreach ( $__args as $__k => $__v ) $$__k = $__v;
|
211 |
* @return string|null The stored secret.
|
212 |
*/
|
213 |
protected function create_view_secret( $value = null ) {
|
214 |
+
return memo( $value );
|
|
|
215 |
}
|
216 |
|
217 |
/**
|
252 |
* @return string The file instance case.
|
253 |
*/
|
254 |
protected function get_view_instance( $base, $instance = 'main' ) {
|
255 |
+
|
256 |
+
$instance = str_replace( '-', '_', $instance );
|
257 |
+
|
258 |
+
return "{$base}_{$instance}";
|
259 |
}
|
260 |
|
261 |
/**
|
267 |
* @return array The public hierarchical post types.
|
268 |
*/
|
269 |
public function get_hierarchical_post_types() {
|
270 |
+
return memo() ?: memo(
|
271 |
+
\get_post_types(
|
272 |
+
[
|
273 |
+
'hierarchical' => true,
|
274 |
+
'public' => true,
|
275 |
+
],
|
276 |
+
'names'
|
277 |
+
)
|
278 |
);
|
279 |
}
|
280 |
|
287 |
* @return array The public nonhierarchical post types.
|
288 |
*/
|
289 |
public function get_nonhierarchical_post_types() {
|
290 |
+
return memo() ?: memo(
|
291 |
+
\get_post_types(
|
292 |
+
[
|
293 |
+
'hierarchical' => false,
|
294 |
+
'public' => true,
|
295 |
+
],
|
296 |
+
'names'
|
297 |
+
)
|
298 |
);
|
299 |
}
|
300 |
|
307 |
* @return bool Whether external redirect is allowed.
|
308 |
*/
|
309 |
public function allow_external_redirect() {
|
|
|
310 |
/**
|
311 |
* @since 2.1.0
|
312 |
* @param bool $allowed Whether external redirect is allowed.
|
313 |
*/
|
314 |
+
return memo() ?? memo( (bool) \apply_filters( 'the_seo_framework_allow_external_redirect', true ) );
|
315 |
}
|
316 |
|
317 |
/**
|
324 |
* @return bool True is blog is public.
|
325 |
*/
|
326 |
public function is_blog_public() {
|
327 |
+
return memo() ?? memo( (bool) \get_option( 'blog_public' ) );
|
|
|
|
|
|
|
328 |
}
|
329 |
|
330 |
/**
|
362 |
public function get_settings_capability() {
|
363 |
/**
|
364 |
* @since 2.6.0
|
365 |
+
* @since 4.2.0 Deprecated. Define constant THE_SEO_FRAMEWORK_SETTINGS_CAP instead.
|
366 |
+
* @deprecated
|
367 |
* @param string $capability The user capability required to adjust settings.
|
368 |
*/
|
369 |
+
return (string) \apply_filters_deprecated(
|
370 |
+
'the_seo_framework_settings_capability',
|
371 |
+
[ THE_SEO_FRAMEWORK_SETTINGS_CAP ],
|
372 |
+
'4.2.0 of The SEO Framework',
|
373 |
+
'constant THE_SEO_FRAMEWORK_SETTINGS_CAP'
|
374 |
+
);
|
375 |
}
|
376 |
|
377 |
/**
|
394 |
* @return string The escaped SEO Settings page URL.
|
395 |
*/
|
396 |
public function get_seo_settings_page_url() {
|
397 |
+
return $this->is_headless['settings']
|
398 |
+
? ''
|
399 |
+
: \esc_url(
|
400 |
+
html_entity_decode(
|
401 |
+
\menu_page_url( $this->seo_settings_page_slug, false )
|
402 |
+
),
|
403 |
+
[ 'https', 'http' ]
|
404 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
}
|
406 |
|
407 |
/**
|
409 |
*
|
410 |
* @since 2.7.0
|
411 |
* @since 4.0.4 Now uses `gmdate()` instead of `date()`.
|
|
|
|
|
412 |
*
|
413 |
* @param string $format The datetime format.
|
414 |
* @param string $time The GMT time. Expects timezone to be omitted.
|
415 |
* @return string The converted time. Empty string if no $time is given.
|
416 |
*/
|
417 |
public function gmt2date( $format = 'Y-m-d', $time = '' ) {
|
418 |
+
return $time ? gmdate( $format, strtotime( $time . ' GMT' ) ) : '';
|
|
|
|
|
|
|
|
|
419 |
}
|
420 |
|
421 |
/**
|
422 |
* Returns timestamp format based on timestamp settings.
|
423 |
*
|
424 |
* @since 3.0.0
|
425 |
+
* @since 4.1.4 1. Added options-override parameter.
|
426 |
+
* 2. Added return value filter.
|
427 |
* @link https://www.w3.org/TR/NOTE-datetime
|
428 |
*
|
429 |
* @param null|bool $override_get_time Whether to override the $get_time from option value.
|
431 |
*/
|
432 |
public function get_timestamp_format( $override_get_time = null ) {
|
433 |
|
434 |
+
$get_time = $override_get_time ?? $this->uses_time_in_timestamp_format();
|
|
|
|
|
435 |
|
436 |
return \apply_filters_ref_array(
|
437 |
'the_seo_framework_timestamp_format',
|
458 |
* Unlike PHP's `array_merge_recursive()`, this method doesn't convert non-unique keys as sequential.
|
459 |
*
|
460 |
* A do-while is faster than while. Sorry for the legibility.
|
461 |
+
* TODO instead of calling thyself, would a goto not be better?
|
462 |
*
|
463 |
* @since 4.1.4
|
464 |
*
|
470 |
$i = \count( $arrays );
|
471 |
|
472 |
if ( 2 === $i ) foreach ( $arrays[1] as $key => $value ) {
|
473 |
+
$arrays[0][ $key ] = \is_array( $arrays[0][ $key ] ?? null )
|
|
|
474 |
? $this->array_merge_recursive_distinct( $arrays[0][ $key ], $value )
|
475 |
: $value;
|
476 |
} else do {
|
485 |
* Shortens string and adds ellipses when over a threshold in length.
|
486 |
*
|
487 |
* @since 3.1.0
|
488 |
+
* @since 4.2.0 No longer prepends a space before the hellip.
|
489 |
*
|
490 |
* @param string $string The string to test and maybe trim
|
491 |
* @param int $over The character limit. Must be over 0 to have effect.
|
495 |
*/
|
496 |
public function hellip_if_over( $string, $over = 0 ) {
|
497 |
|
498 |
+
if ( $over > 0 && \strlen( $string ) > $over )
|
499 |
+
$string = substr( $string, 0, abs( $over - 2 ) ) . '…';
|
|
|
500 |
|
501 |
return $string;
|
502 |
}
|
515 |
* @since 4.0.0 1. Now expects PCRE UTF-8 encoding support.
|
516 |
* 2. Moved input-parameter alterting filters outside of this function.
|
517 |
* 3. Short length now works as intended, instead of comparing as less, it compares as less or equal to.
|
518 |
+
* @since 4.2.0 Now supports detection of connector-dashes, connector-punctuation, and closing quotes,
|
519 |
+
* and recognizes those as whole words.
|
520 |
*
|
521 |
* @param string $string Required. The string to count words in.
|
522 |
+
* @param int $dupe_count Minimum amount of words to encounter in the string.
|
523 |
+
* Set to 0 to count all words longer than $short_length.
|
524 |
+
* @param int $dupe_short Minimum amount of words to encounter in the string that fall under the
|
525 |
+
* $short_length. Set to 0 to consider all words with $amount.
|
526 |
+
* @param int $short_length The maximum string length of a word to pass for $dupe_short
|
527 |
+
* instead of $count. Set to 0 to ignore $count, and use $dupe_short only.
|
528 |
* @return array Containing arrays of words with their count.
|
529 |
*/
|
530 |
public function get_word_count( $string, $dupe_count = 3, $dupe_short = 5, $short_length = 3 ) {
|
531 |
|
532 |
+
$string = \wp_check_invalid_utf8( html_entity_decode( $string ) );
|
|
|
533 |
|
534 |
if ( ! $string ) return [];
|
535 |
|
536 |
+
$use_mb = memo( null, 'use_mb' ) ?? memo( \extension_loaded( 'mbstring' ), 'use_mb' );
|
537 |
|
|
|
|
|
|
|
538 |
$word_list = preg_split(
|
539 |
+
'/[^\p{Cc}\p{L}\p{N}\p{Pc}\p{Pd}\p{Pf}\'"]+/mu',
|
540 |
$use_mb ? mb_strtolower( $string ) : strtolower( $string ),
|
541 |
-1,
|
542 |
PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_NO_EMPTY
|
543 |
);
|
544 |
|
545 |
+
if ( ! \count( $word_list ) ) goto end;
|
546 |
|
547 |
+
$words = [];
|
|
|
|
|
|
|
|
|
|
|
548 |
|
549 |
+
foreach ( $word_list as [ $_word, $_position ] )
|
550 |
+
$words[ $_position ] = $_word;
|
551 |
|
552 |
+
// We're going to fetch words based on position, and then flip it to become the key.
|
553 |
+
$word_keys = array_flip( array_reverse( $words, true ) );
|
554 |
|
555 |
+
foreach ( array_count_values( $words ) as $word => $count ) {
|
556 |
+
if ( ( $use_mb ? mb_strlen( $word ) : \strlen( $word ) ) <= $short_length ) {
|
557 |
+
$assert = $count >= $dupe_short;
|
558 |
+
} else {
|
559 |
+
$assert = $count >= $dupe_count;
|
560 |
+
}
|
561 |
|
562 |
+
if ( $assert ) {
|
563 |
+
//! Don't use mb_* here. preg_split's offset is in bytes, NOT multibytes.
|
564 |
+
$args = [
|
565 |
+
'pos' => $word_keys[ $word ],
|
566 |
+
'len' => \strlen( $word ),
|
567 |
+
];
|
568 |
|
569 |
+
$first_encountered_word = substr( $string, $args['pos'], $args['len'] );
|
570 |
|
571 |
+
// phpcs:ignore, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- You need more PHP7.
|
572 |
+
$words_too_many[] = [ $first_encountered_word => $count ];
|
|
|
573 |
}
|
574 |
+
}
|
575 |
|
576 |
+
end:;
|
577 |
+
// phpcs:ignore, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- You don't love PHP7.
|
578 |
+
return $words_too_many ?? [];
|
579 |
}
|
580 |
|
581 |
/**
|
584 |
* @since 2.8.0
|
585 |
* @since 2.9.0 Now adds a little more relative softness based on rel_lum.
|
586 |
* @since 2.9.2 (Typo): Renamed from 'get_relatitve_fontcolor' to 'get_relative_fontcolor'.
|
587 |
+
* @since 3.0.4 Now uses WCAG's relative luminance formula.
|
588 |
+
* @since 4.2.0 Optimized code, but it now has some rounding changes at the end. This could
|
589 |
+
* offset the returned values by 1/255th.
|
590 |
* @link https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast
|
591 |
* @link https://www.w3.org/WAI/GL/wiki/Relative_luminance
|
592 |
*
|
593 |
* @param string $hex The 3 to 6 character RGB hex. The '#' prefix may be added.
|
594 |
+
* RRGGBBAA is supported, but the Alpha channels won't be returned.
|
595 |
* @return string The hexadecimal RGB relative font color, without '#' prefix.
|
596 |
*/
|
597 |
public function get_relative_fontcolor( $hex = '' ) {
|
598 |
|
599 |
$hex = ltrim( $hex, '#' );
|
600 |
|
601 |
+
// Convert hex to usable numerics.
|
602 |
+
[ $r, $g, $b ] = array_map(
|
603 |
+
'hexdec',
|
604 |
+
str_split(
|
605 |
+
// rgb == rrggbb.
|
606 |
+
\strlen( $hex ) >= 6 ? $hex : "$hex[0]$hex[0]$hex[1]$hex[1]$hex[2]$hex[2]",
|
607 |
+
2
|
608 |
+
)
|
609 |
+
);
|
|
|
610 |
|
611 |
$get_relative_luminance = static function( $v ) {
|
612 |
+
// Convert to 0~1 value.
|
613 |
+
$v /= 0xFF;
|
614 |
|
615 |
if ( $v > .03928 ) {
|
616 |
$lum = ( ( $v + .055 ) / 1.055 ) ** 2.4;
|
620 |
return $lum;
|
621 |
};
|
622 |
|
623 |
+
// Create Relative Luminance via sRGB.
|
624 |
+
$rl = ( 0.2126 * $get_relative_luminance( $r ) )
|
625 |
+
+ ( 0.7152 * $get_relative_luminance( $g ) )
|
626 |
+
+ ( 0.0722 * $get_relative_luminance( $b ) );
|
|
|
|
|
627 |
|
628 |
// Build light greyscale.
|
629 |
+
$gr = ( $r * 0.2989 / 8 ) * $rl;
|
630 |
+
$gg = ( $g * 0.5870 / 8 ) * $rl;
|
631 |
+
$gb = ( $b * 0.1140 / 8 ) * $rl;
|
632 |
+
|
633 |
+
// Invert colors if they hit this luminance boundary.
|
634 |
+
if ( $rl < 0.5 ) {
|
635 |
+
// Build dark greyscale. bitwise operators round...
|
636 |
+
$gr ^= 0xFF;
|
637 |
+
$gg ^= 0xFF;
|
638 |
+
$gb ^= 0xFF;
|
639 |
}
|
640 |
|
641 |
+
return vsprintf( '%02x%02x%02x', [ $gr, $gg, $gb ] );
|
|
|
|
|
|
|
|
|
|
|
642 |
}
|
643 |
|
644 |
/**
|
662 |
$accent = $this->s_color_hex( $this->get_option( 'sitemap_color_accent' ) );
|
663 |
|
664 |
$options = [
|
665 |
+
'main' => $main ? "#$main" : '',
|
666 |
+
'accent' => $accent ? "#$accent" : '',
|
667 |
];
|
668 |
|
669 |
$options = array_filter( $options );
|
@@ -39,31 +39,29 @@ class Detect extends Render {
|
|
39 |
* Memoizes the return value.
|
40 |
*
|
41 |
* @since 2.6.1
|
42 |
-
* @credits Jetpack for
|
43 |
*
|
44 |
* @return array List of active plugins.
|
45 |
*/
|
46 |
public function active_plugins() {
|
47 |
|
48 |
-
|
49 |
-
|
50 |
-
if ( isset( $active_plugins ) )
|
51 |
-
return $active_plugins;
|
52 |
|
53 |
$active_plugins = (array) \get_option( 'active_plugins', [] );
|
54 |
|
55 |
if ( \is_multisite() ) {
|
56 |
// Due to legacy code, active_sitewide_plugins stores them in the keys,
|
57 |
-
// whereas active_plugins stores them in the values.
|
58 |
$network_plugins = array_keys( \get_site_option( 'active_sitewide_plugins', [] ) );
|
59 |
-
|
|
|
60 |
$active_plugins = array_merge( $active_plugins, $network_plugins );
|
61 |
-
}
|
62 |
}
|
63 |
|
64 |
sort( $active_plugins );
|
65 |
|
66 |
-
return
|
67 |
}
|
68 |
|
69 |
/**
|
@@ -78,34 +76,26 @@ class Detect extends Render {
|
|
78 |
|
79 |
$conflicting_plugins = [
|
80 |
'seo_tools' => [
|
81 |
-
'Yoast SEO'
|
82 |
-
'Yoast SEO Premium'
|
83 |
-
'All in One SEO Pack'
|
84 |
-
'SEO Ultimate'
|
85 |
-
'
|
86 |
-
'
|
87 |
-
'
|
88 |
-
'Smart Crawl' => 'smartcrawl-seo/wpmu-dev-seo.php',
|
89 |
],
|
90 |
'sitemaps' => [
|
91 |
-
'Google XML Sitemaps'
|
92 |
-
'
|
93 |
-
'Google
|
94 |
-
'
|
95 |
-
'Google Sitemap by BestWebSoft' => 'google-sitemap-plugin/google-sitemap-plugin.php',
|
96 |
-
'Simple Wp Sitemap' => 'simple-wp-sitemap/simple-wp-sitemap.php',
|
97 |
-
'XML Sitemaps' => 'xml-sitemaps/xml-sitemaps.php',
|
98 |
],
|
99 |
'open_graph' => [
|
100 |
'Facebook Open Graph Meta Tags for WordPress' => 'wonderm00ns-simple-facebook-open-graph-tags/wonderm00n-open-graph.php',
|
101 |
-
'
|
102 |
-
'
|
103 |
-
'Open Graph' => 'opengraph/opengraph.php',
|
104 |
-
'Open Graph Protocol Framework' => 'open-graph-protocol-framework/open-graph-protocol-framework.php',
|
105 |
'Shareaholic2' => 'shareaholic/sexy-bookmarks.php',
|
106 |
-
'Social Sharing Toolkit' => 'social-sharing-toolkit/social_sharing_toolkit.php',
|
107 |
'WordPress Social Sharing Optimization' => 'wpsso/wpsso.php',
|
108 |
-
'WP Facebook Open Graph protocol' => 'wp-facebook-open-graph-protocol/wp-facebook-ogp.php',
|
109 |
],
|
110 |
'twitter_card' => [],
|
111 |
];
|
@@ -114,25 +104,31 @@ class Detect extends Render {
|
|
114 |
* @since 2.6.0
|
115 |
* @param array $conflicting_plugins The conflicting plugin list.
|
116 |
*/
|
117 |
-
return (array) \
|
118 |
}
|
119 |
|
120 |
/**
|
121 |
* Fetches type of conflicting plugins.
|
122 |
*
|
123 |
* @since 2.6.0
|
|
|
124 |
*
|
125 |
* @param string $type The Key from $this->conflicting_plugins()
|
126 |
* @return array
|
127 |
*/
|
128 |
public function get_conflicting_plugins( $type = 'seo_tools' ) {
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
|
|
|
|
|
|
|
|
|
|
136 |
}
|
137 |
|
138 |
/**
|
@@ -141,8 +137,8 @@ class Detect extends Render {
|
|
141 |
* Note: Class check is 3 times as slow as defined check. Function check is 2 times as slow.
|
142 |
*
|
143 |
* @since 1.3.0
|
144 |
-
* @since 2.8.0
|
145 |
-
*
|
146 |
* @since 4.0.6 Can no longer autoload classes.
|
147 |
*
|
148 |
* @param array $plugins Array of array for constants, classes and / or functions to check for plugin existence.
|
@@ -150,41 +146,24 @@ class Detect extends Render {
|
|
150 |
*/
|
151 |
public function detect_plugin( $plugins ) {
|
152 |
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
return true;
|
157 |
-
}
|
158 |
-
}
|
159 |
-
}
|
160 |
|
161 |
// Check for constants
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
return true;
|
166 |
-
}
|
167 |
-
}
|
168 |
-
}
|
169 |
|
170 |
// Check for functions
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
return true;
|
175 |
-
}
|
176 |
-
}
|
177 |
-
}
|
178 |
|
179 |
// Check for classes
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
if ( class_exists( $name, false ) ) {
|
184 |
-
return true;
|
185 |
-
}
|
186 |
-
}
|
187 |
-
}
|
188 |
|
189 |
// No globals, constant, function, or class found to exist
|
190 |
return false;
|
@@ -197,40 +176,27 @@ class Detect extends Render {
|
|
197 |
*
|
198 |
* @since 2.5.2
|
199 |
* @since 4.1.4 Fixed sorting algorithm from fribbling-me to resolving-me. Nothing changed but legibility.
|
|
|
200 |
* @uses $this->detect_plugin_multi()
|
201 |
*
|
202 |
-
* @param array $plugins Array of array for globals, constants, classes
|
203 |
* and/or functions to check for plugin existence.
|
204 |
-
* @param bool
|
205 |
*/
|
206 |
-
public function can_i_use(
|
207 |
|
208 |
if ( ! $use_cache )
|
209 |
return $this->detect_plugin_multi( $plugins );
|
210 |
|
211 |
-
|
212 |
-
|
213 |
-
$mapped = [];
|
214 |
-
|
215 |
-
// Prepare multidimensional array for cache.
|
216 |
-
foreach ( $plugins as $type => $func ) {
|
217 |
-
if ( ! \is_array( $func ) )
|
218 |
-
return false; // doing it wrong...
|
219 |
|
220 |
-
|
|
|
221 |
|
222 |
-
// Glue with underscore and space for debugging purposes.
|
223 |
-
$mapped[ $type ] = $type . '_' . implode( ' ', $func );
|
224 |
-
}
|
225 |
-
|
226 |
-
ksort( $mapped );
|
227 |
// phpcs:ignore, WordPress.PHP.DiscouragedPHPFunctions -- No objects are inserted, nor is this ever unserialized.
|
228 |
-
$key = serialize( $
|
229 |
-
|
230 |
-
if ( isset( $cache[ $key ] ) )
|
231 |
-
return $cache[ $key ];
|
232 |
|
233 |
-
return
|
234 |
}
|
235 |
|
236 |
/**
|
@@ -238,53 +204,38 @@ class Detect extends Render {
|
|
238 |
* All parameters must match and return true.
|
239 |
*
|
240 |
* @since 2.5.2
|
241 |
-
* @since 4.0.6
|
242 |
-
*
|
243 |
-
*
|
244 |
* This method is only used by can_i_use(), and is only effective in the Ultimate Member compat file...
|
245 |
* @TODO deprecate?
|
246 |
*
|
247 |
-
* @param array $plugins Array of array for constants, classes
|
248 |
-
*
|
|
|
|
|
249 |
*/
|
250 |
-
public function detect_plugin_multi(
|
251 |
|
252 |
// Check for globals
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
return false;
|
257 |
-
}
|
258 |
-
}
|
259 |
-
}
|
260 |
|
261 |
// Check for constants
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
return false;
|
266 |
-
}
|
267 |
-
}
|
268 |
-
}
|
269 |
|
270 |
// Check for functions
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
return false;
|
275 |
-
}
|
276 |
-
}
|
277 |
-
}
|
278 |
|
279 |
// Check for classes
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
if ( ! class_exists( $name, false ) ) {
|
284 |
-
return false;
|
285 |
-
}
|
286 |
-
}
|
287 |
-
}
|
288 |
|
289 |
// All classes, functions and constant have been found to exist
|
290 |
return true;
|
@@ -294,32 +245,21 @@ class Detect extends Render {
|
|
294 |
* Checks if the (parent) theme name is loaded.
|
295 |
*
|
296 |
* @since 2.1.0
|
|
|
297 |
*
|
298 |
-
* @param string|array $themes
|
299 |
* @return bool is theme active.
|
300 |
*/
|
301 |
public function is_theme( $themes = '' ) {
|
302 |
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
$theme_parent = strtolower( $wp_get_theme->get( 'Template' ) );
|
309 |
-
$theme_name = strtolower( $wp_get_theme->get( 'Name' ) );
|
310 |
|
311 |
-
|
312 |
-
|
313 |
-
if ( $themes === $theme_parent || $themes === $theme_name )
|
314 |
return true;
|
315 |
-
} elseif ( \is_array( $themes ) ) {
|
316 |
-
foreach ( $themes as $theme ) {
|
317 |
-
$theme = strtolower( $theme );
|
318 |
-
if ( $theme === $theme_parent || $theme === $theme_name ) {
|
319 |
-
return true;
|
320 |
-
}
|
321 |
-
}
|
322 |
-
}
|
323 |
|
324 |
return false;
|
325 |
}
|
@@ -336,39 +276,37 @@ class Detect extends Render {
|
|
336 |
*/
|
337 |
public function detect_seo_plugins() {
|
338 |
|
339 |
-
|
340 |
-
|
341 |
-
if ( isset( $detected ) )
|
342 |
-
return $detected;
|
343 |
|
344 |
$active_plugins = $this->active_plugins();
|
345 |
|
346 |
-
if ( !
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
}
|
368 |
}
|
369 |
}
|
370 |
|
371 |
-
return
|
372 |
}
|
373 |
|
374 |
/**
|
@@ -383,43 +321,41 @@ class Detect extends Render {
|
|
383 |
*/
|
384 |
public function detect_og_plugin() {
|
385 |
|
386 |
-
static $detected = null;
|
387 |
-
|
388 |
-
if ( isset( $detected ) )
|
389 |
-
return $detected;
|
390 |
-
|
391 |
// Detect SEO plugins beforehand.
|
392 |
if ( $this->detect_seo_plugins() )
|
393 |
-
return
|
|
|
|
|
|
|
394 |
|
395 |
$active_plugins = $this->active_plugins();
|
396 |
|
397 |
-
if ( !
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
}
|
419 |
}
|
420 |
}
|
421 |
|
422 |
-
return
|
423 |
}
|
424 |
|
425 |
/**
|
@@ -433,42 +369,40 @@ class Detect extends Render {
|
|
433 |
*/
|
434 |
public function detect_twitter_card_plugin() {
|
435 |
|
436 |
-
static $detected = null;
|
437 |
-
|
438 |
-
if ( isset( $detected ) )
|
439 |
-
return $detected;
|
440 |
-
|
441 |
// Detect SEO plugins beforehand.
|
442 |
if ( $this->detect_seo_plugins() )
|
443 |
-
return
|
|
|
|
|
|
|
444 |
|
445 |
$active_plugins = $this->active_plugins();
|
446 |
|
447 |
-
if ( !
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
}
|
468 |
}
|
469 |
}
|
470 |
|
471 |
-
return
|
472 |
}
|
473 |
|
474 |
/**
|
@@ -499,42 +433,40 @@ class Detect extends Render {
|
|
499 |
*/
|
500 |
public function detect_sitemap_plugin() {
|
501 |
|
502 |
-
static $detected = null;
|
503 |
-
|
504 |
-
if ( isset( $detected ) )
|
505 |
-
return $detected;
|
506 |
-
|
507 |
// Detect SEO plugins beforehand.
|
508 |
if ( $this->detect_seo_plugins() )
|
509 |
-
return
|
|
|
|
|
|
|
510 |
|
511 |
$active_plugins = $this->active_plugins();
|
512 |
|
513 |
-
if ( !
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
}
|
534 |
}
|
535 |
}
|
536 |
|
537 |
-
return
|
538 |
}
|
539 |
|
540 |
/**
|
@@ -546,65 +478,18 @@ class Detect extends Render {
|
|
546 |
* @return bool
|
547 |
*/
|
548 |
public function use_core_sitemaps() {
|
549 |
-
static $use;
|
550 |
|
551 |
-
|
|
|
552 |
|
553 |
if ( $this->get_option( 'sitemaps_output' ) )
|
554 |
-
return
|
555 |
-
|
556 |
-
if ( \function_exists( '\\wp_sitemaps_get_server' ) ) {
|
557 |
-
$wp_sitemaps_server = \wp_sitemaps_get_server();
|
558 |
-
|
559 |
-
return $use =
|
560 |
-
method_exists( $wp_sitemaps_server, 'sitemaps_enabled' )
|
561 |
-
&& $wp_sitemaps_server->sitemaps_enabled();
|
562 |
-
}
|
563 |
|
564 |
-
|
565 |
-
}
|
566 |
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
*
|
571 |
-
* Detects the following builders:
|
572 |
-
* - Elementor by Elementor LTD
|
573 |
-
* - Divi Builder by Elegant Themes
|
574 |
-
* - Visual Composer by WPBakery
|
575 |
-
* - Page Builder by SiteOrigin
|
576 |
-
* - Beaver Builder by Fastline Media
|
577 |
-
*
|
578 |
-
* @since 4.0.0
|
579 |
-
* @since 4.0.6 The output is now filterable.
|
580 |
-
* @TODO deprecate?
|
581 |
-
* @ignore unused.
|
582 |
-
*
|
583 |
-
* @return bool
|
584 |
-
*/
|
585 |
-
public function detect_page_builder() {
|
586 |
-
|
587 |
-
static $detected = null;
|
588 |
-
|
589 |
-
if ( isset( $detected ) ) return $detected;
|
590 |
-
|
591 |
-
/**
|
592 |
-
* @since 4.0.6
|
593 |
-
* @param bool $detected Whether an active page builder is detected.
|
594 |
-
* @NOTE not to be confused with `the_seo_framework_detect_page_builder`, which tests
|
595 |
-
* the page builder status for each post individually.
|
596 |
-
*/
|
597 |
-
return $detected = (bool) \apply_filters(
|
598 |
-
'the_seo_framework_page_builder_active',
|
599 |
-
$this->detect_plugin( [
|
600 |
-
'constants' => [
|
601 |
-
'ELEMENTOR_VERSION',
|
602 |
-
'ET_BUILDER_VERSION',
|
603 |
-
'WPB_VC_VERSION',
|
604 |
-
'SITEORIGIN_PANELS_VERSION',
|
605 |
-
'FL_BUILDER_VERSION',
|
606 |
-
],
|
607 |
-
] )
|
608 |
);
|
609 |
}
|
610 |
|
@@ -620,25 +505,22 @@ class Detect extends Render {
|
|
620 |
* @return bool
|
621 |
*/
|
622 |
public function detect_non_html_page_builder() {
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
'WPB_VC_VERSION',
|
640 |
-
],
|
641 |
-
] )
|
642 |
);
|
643 |
}
|
644 |
|
@@ -652,11 +534,8 @@ class Detect extends Render {
|
|
652 |
* @return bool Whether the robots.txt file exists.
|
653 |
*/
|
654 |
public function has_robots_txt() {
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
if ( isset( $has_robots ) )
|
659 |
-
return $has_robots;
|
660 |
|
661 |
// Ensure get_home_path() is declared.
|
662 |
if ( ! \function_exists( '\\get_home_path' ) )
|
@@ -665,7 +544,7 @@ class Detect extends Render {
|
|
665 |
$path = \get_home_path() . 'robots.txt';
|
666 |
|
667 |
// phpcs:ignore, TSF.Performance.Functions.PHP -- we use path, not URL.
|
668 |
-
return
|
669 |
}
|
670 |
|
671 |
/**
|
@@ -678,11 +557,8 @@ class Detect extends Render {
|
|
678 |
* @return bool Whether the sitemap.xml file exists.
|
679 |
*/
|
680 |
public function has_sitemap_xml() {
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
if ( isset( $has_map ) )
|
685 |
-
return $has_map;
|
686 |
|
687 |
// Ensure get_home_path() is declared.
|
688 |
if ( ! \function_exists( '\\get_home_path' ) )
|
@@ -691,59 +567,7 @@ class Detect extends Render {
|
|
691 |
$path = \get_home_path() . 'sitemap.xml';
|
692 |
|
693 |
// phpcs:ignore, TSF.Performance.Functions.PHP -- we use path, not URL.
|
694 |
-
return
|
695 |
-
}
|
696 |
-
|
697 |
-
/**
|
698 |
-
* Determines if WP is above or below a version
|
699 |
-
*
|
700 |
-
* @since 2.2.1
|
701 |
-
* @since 2.3.8 Added caching
|
702 |
-
* @since 2.8.0 No longer overwrites global $wp_version
|
703 |
-
* @since 3.1.0 1. No longer caches.
|
704 |
-
* 2. Removed redundant parameter checks.
|
705 |
-
* 3. Now supports x.yy.zz WordPress versions.
|
706 |
-
*
|
707 |
-
* @param string $version the three part version to compare to WordPress
|
708 |
-
* @param string $compare the comparing operator, default "$version >= Current WP Version"
|
709 |
-
* @return bool True if the WordPress version comparison passes.
|
710 |
-
*/
|
711 |
-
public function wp_version( $version = '4.3.0', $compare = '>=' ) {
|
712 |
-
|
713 |
-
$wp_version = $GLOBALS['wp_version'];
|
714 |
-
|
715 |
-
/**
|
716 |
-
* Add a .0 if WP outputs something like 4.3 instead of 4.3.0
|
717 |
-
* Does consider 4.xx, which will become 4.xx.0
|
718 |
-
*/
|
719 |
-
if ( 1 === substr_count( $wp_version, '.' ) )
|
720 |
-
$wp_version = $wp_version . '.0';
|
721 |
-
|
722 |
-
return (bool) version_compare( $wp_version, $version, $compare );
|
723 |
-
}
|
724 |
-
|
725 |
-
/**
|
726 |
-
* Checks for current theme support.
|
727 |
-
*
|
728 |
-
* Maintains detection cache, array and strings are mixed through foreach loops.
|
729 |
-
*
|
730 |
-
* @since 2.2.5
|
731 |
-
* @since 3.1.0 Removed caching
|
732 |
-
* @TODO deprecate me.
|
733 |
-
*
|
734 |
-
* @param string|array required $features The features to check for.
|
735 |
-
* @return bool theme support.
|
736 |
-
*/
|
737 |
-
public function detect_theme_support( $features ) {
|
738 |
-
|
739 |
-
foreach ( (array) $features as $feature ) {
|
740 |
-
if ( \current_theme_supports( $feature ) ) {
|
741 |
-
return true;
|
742 |
-
}
|
743 |
-
continue;
|
744 |
-
}
|
745 |
-
|
746 |
-
return false;
|
747 |
}
|
748 |
|
749 |
/**
|
@@ -757,9 +581,8 @@ class Detect extends Render {
|
|
757 |
*/
|
758 |
public function query_supports_seo() {
|
759 |
|
760 |
-
|
761 |
-
|
762 |
-
if ( isset( $cache ) ) return $cache;
|
763 |
|
764 |
switch ( true ) :
|
765 |
case $this->is_feed():
|
@@ -793,15 +616,14 @@ class Detect extends Render {
|
|
793 |
* This protects against (accidental) negative-SEO bombarding.
|
794 |
* Support broken queries, so we can noindex them.
|
795 |
*/
|
796 |
-
if ( ! $supported && $this->is_query_exploited() )
|
797 |
$supported = true;
|
798 |
-
}
|
799 |
|
800 |
/**
|
801 |
* @since 4.0.0
|
802 |
* @param bool $supported Whether the query supports SEO.
|
803 |
*/
|
804 |
-
return
|
805 |
}
|
806 |
|
807 |
/**
|
@@ -843,16 +665,15 @@ class Detect extends Render {
|
|
843 |
*/
|
844 |
public function is_query_exploited() {
|
845 |
|
846 |
-
|
847 |
-
|
848 |
-
if ( isset( $exploited ) ) return $exploited;
|
849 |
|
850 |
if ( ! $this->get_option( 'advanced_query_protection' ) )
|
851 |
-
return
|
852 |
|
853 |
// When the page ID is not 0, a real page will always be returned.
|
854 |
if ( $this->get_the_real_ID() )
|
855 |
-
return
|
856 |
|
857 |
global $wp_query;
|
858 |
|
@@ -892,20 +713,17 @@ class Detect extends Render {
|
|
892 |
]
|
893 |
);
|
894 |
|
895 |
-
$query
|
896 |
-
$exploited = false;
|
897 |
|
898 |
foreach ( $exploitables as $type => $qvs ) :
|
899 |
foreach ( $qvs as $qv ) :
|
900 |
-
//
|
901 |
if ( ! isset( $query[ $qv ] ) ) continue;
|
902 |
|
903 |
switch ( $type ) :
|
904 |
case 'numeric':
|
905 |
-
if ( '0' === $query[ $qv ] || ! is_numeric( $query[ $qv ] ) )
|
906 |
-
|
907 |
-
break 3;
|
908 |
-
}
|
909 |
break;
|
910 |
|
911 |
case 'numeric_array':
|
@@ -914,17 +732,13 @@ class Detect extends Render {
|
|
914 |
|
915 |
// If WordPress didn't canonical_redirect() the user yet, it's exploited.
|
916 |
// WordPress mitigates this via a 404 query when a numeric value is found.
|
917 |
-
if ( ! preg_match( '/[0-9]/', $query[ $qv ] ) )
|
918 |
-
|
919 |
-
break 3;
|
920 |
-
}
|
921 |
break;
|
922 |
|
923 |
case 'requires_s':
|
924 |
-
if ( ! isset( $query['s'] ) )
|
925 |
-
|
926 |
-
break 3;
|
927 |
-
}
|
928 |
break;
|
929 |
|
930 |
default:
|
@@ -933,7 +747,36 @@ class Detect extends Render {
|
|
933 |
endforeach;
|
934 |
endforeach;
|
935 |
|
936 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
937 |
}
|
938 |
|
939 |
/**
|
@@ -1013,36 +856,69 @@ class Detect extends Render {
|
|
1013 |
*/
|
1014 |
public function post_type_supports_taxonomies( $post_type = '' ) {
|
1015 |
|
1016 |
-
|
1017 |
-
|
1018 |
-
if ( isset( $cache[ $post_type ] ) )
|
1019 |
-
return $cache[ $post_type ];
|
1020 |
|
1021 |
$post_type = $post_type ?: $this->get_current_post_type();
|
1022 |
-
if ( ! $post_type ) return false;
|
1023 |
|
1024 |
-
if
|
1025 |
-
|
|
|
1026 |
|
1027 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1028 |
}
|
1029 |
|
1030 |
/**
|
1031 |
* Returns a list of all supported post types.
|
1032 |
*
|
1033 |
* @since 3.1.0
|
1034 |
-
* @stativar array $cache
|
1035 |
*
|
1036 |
-
* @return
|
1037 |
*/
|
1038 |
public function get_supported_post_types() {
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
|
1044 |
-
return $cache = array_values(
|
1045 |
-
array_filter( $this->get_public_post_types(), [ $this, 'is_post_type_supported' ] )
|
1046 |
);
|
1047 |
}
|
1048 |
|
@@ -1053,47 +929,72 @@ class Detect extends Render {
|
|
1053 |
* @since 4.1.0
|
1054 |
* @since 4.1.4 Now resets the index keys of the return value.
|
1055 |
*
|
1056 |
-
* @return
|
1057 |
*/
|
1058 |
protected function get_public_post_types() {
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1069 |
)
|
1070 |
-
)
|
1071 |
-
|
1072 |
-
)
|
1073 |
-
);
|
1074 |
}
|
1075 |
|
1076 |
/**
|
1077 |
* Returns a list of builtin public post types.
|
1078 |
-
* Memoizes the return value.
|
1079 |
*
|
1080 |
* @since 3.1.0
|
|
|
1081 |
*
|
1082 |
-
* @return
|
1083 |
*/
|
1084 |
protected function get_forced_supported_post_types() {
|
1085 |
-
|
1086 |
-
static $cache = null;
|
1087 |
/**
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
1091 |
-
return
|
1092 |
'the_seo_framework_forced_supported_post_types',
|
1093 |
-
|
1094 |
-
|
1095 |
-
|
1096 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1097 |
);
|
1098 |
}
|
1099 |
|
@@ -1103,48 +1004,58 @@ class Detect extends Render {
|
|
1103 |
*
|
1104 |
* @since 4.1.0
|
1105 |
*
|
1106 |
-
* @return
|
1107 |
*/
|
1108 |
protected function get_public_taxonomies() {
|
1109 |
-
|
1110 |
-
|
1111 |
-
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1121 |
)
|
1122 |
-
)
|
1123 |
-
'\\is_taxonomy_viewable'
|
1124 |
-
);
|
1125 |
}
|
1126 |
|
1127 |
/**
|
1128 |
* Returns a list of builtin public taxonomies.
|
1129 |
-
* Memoizes the return value.
|
1130 |
*
|
1131 |
* @since 4.1.0
|
|
|
1132 |
*
|
1133 |
-
* @return
|
1134 |
*/
|
1135 |
protected function get_forced_supported_taxonomies() {
|
1136 |
-
|
1137 |
-
static $cache = null;
|
1138 |
/**
|
1139 |
* @since 4.1.0
|
1140 |
-
* @param
|
1141 |
*/
|
1142 |
-
return
|
1143 |
'the_seo_framework_forced_supported_taxonomies',
|
1144 |
-
|
1145 |
-
|
1146 |
-
|
1147 |
-
|
|
|
|
|
1148 |
);
|
1149 |
}
|
1150 |
|
@@ -1168,11 +1079,12 @@ class Detect extends Render {
|
|
1168 |
* @param bool $disabled
|
1169 |
* @param string $post_type
|
1170 |
*/
|
1171 |
-
return \
|
1172 |
-
|
1173 |
-
|
1174 |
-
|
1175 |
-
|
|
|
1176 |
);
|
1177 |
}
|
1178 |
|
@@ -1193,16 +1105,18 @@ class Detect extends Render {
|
|
1193 |
|
1194 |
$disabled = false;
|
1195 |
|
1196 |
-
|
|
|
1197 |
$disabled = true;
|
1198 |
} else {
|
|
|
|
|
1199 |
foreach ( $this->get_post_types_from_taxonomy( $taxonomy ) as $type ) {
|
1200 |
-
// Set here, because the taxonomy might not have post types at all.
|
1201 |
-
$disabled = true;
|
1202 |
if ( $this->is_post_type_supported( $type ) ) {
|
1203 |
$disabled = false;
|
1204 |
break;
|
1205 |
}
|
|
|
1206 |
}
|
1207 |
}
|
1208 |
|
@@ -1211,7 +1125,13 @@ class Detect extends Render {
|
|
1211 |
* @param bool $disabled
|
1212 |
* @param string $taxonomy
|
1213 |
*/
|
1214 |
-
return \
|
|
|
|
|
|
|
|
|
|
|
|
|
1215 |
}
|
1216 |
|
1217 |
/**
|
@@ -1230,8 +1150,8 @@ class Detect extends Render {
|
|
1230 |
* Detects if we're on a Gutenberg page.
|
1231 |
*
|
1232 |
* @since 3.1.0
|
1233 |
-
* @since 3.2.0
|
1234 |
-
*
|
1235 |
*
|
1236 |
* @return bool
|
1237 |
*/
|
@@ -1269,9 +1189,8 @@ class Detect extends Render {
|
|
1269 |
* @return string URL location of robots.txt. Unescaped.
|
1270 |
*/
|
1271 |
public function get_robots_txt_url() {
|
1272 |
-
global $wp_rewrite;
|
1273 |
|
1274 |
-
if ( $wp_rewrite->using_permalinks() && ! $this->is_subdirectory_installation() ) {
|
1275 |
$home = \trailingslashit( $this->set_preferred_url_scheme( $this->get_home_host() ) );
|
1276 |
$path = "{$home}robots.txt";
|
1277 |
} elseif ( $this->has_robots_txt() ) {
|
@@ -1293,15 +1212,11 @@ class Detect extends Render {
|
|
1293 |
* @return bool
|
1294 |
*/
|
1295 |
public function is_subdirectory_installation() {
|
1296 |
-
|
1297 |
-
|
1298 |
-
|
1299 |
-
|
1300 |
-
|
1301 |
-
|
1302 |
-
$parsed_url = parse_url( \get_option( 'home' ) );
|
1303 |
-
|
1304 |
-
return $cache = ! empty( $parsed_url['path'] ) && ltrim( $parsed_url['path'], ' \\/' );
|
1305 |
}
|
1306 |
|
1307 |
/**
|
@@ -1318,14 +1233,12 @@ class Detect extends Render {
|
|
1318 |
if ( false === strpos( $text, '%%' ) ) return false;
|
1319 |
|
1320 |
$tags_simple = [ 'date', 'title', 'parent_title', 'archive_title', 'sitename', 'sitedesc', 'excerpt', 'excerpt_only', 'tag', 'category', 'primary_category', 'category_description', 'tag_description', 'term_description', 'term_title', 'searchphrase', 'sep', 'pt_single', 'pt_plural', 'modified', 'id', 'name', 'user_description', 'page', 'pagetotal', 'pagenumber', 'caption', 'focuskw', 'term404', 'ct_product_cat', 'ct_product_tag', 'wc_shortdesc', 'wc_sku', 'wc_brand', 'wc_price' ];
|
1321 |
-
|
1322 |
-
$_regex = sprintf( '%%%s%%', implode( '|', $tags_simple ) );
|
1323 |
|
1324 |
if ( preg_match( "/$_regex/i", $text ) ) return true;
|
1325 |
|
1326 |
$tags_wildcard_end = [ 'cs_', 'ct_desc_', 'ct_pa_' ];
|
1327 |
-
|
1328 |
-
$_regex = sprintf( '%%(%s)[^\s]*?%%', implode( '|', $tags_wildcard_end ) );
|
1329 |
|
1330 |
if ( preg_match( "/$_regex/", $text ) ) return true;
|
1331 |
|
39 |
* Memoizes the return value.
|
40 |
*
|
41 |
* @since 2.6.1
|
42 |
+
* @credits Jetpack for some code.
|
43 |
*
|
44 |
* @return array List of active plugins.
|
45 |
*/
|
46 |
public function active_plugins() {
|
47 |
|
48 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
49 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
50 |
|
51 |
$active_plugins = (array) \get_option( 'active_plugins', [] );
|
52 |
|
53 |
if ( \is_multisite() ) {
|
54 |
// Due to legacy code, active_sitewide_plugins stores them in the keys,
|
55 |
+
// whereas active_plugins stores them in the values. array_keys() resolves the disparity.
|
56 |
$network_plugins = array_keys( \get_site_option( 'active_sitewide_plugins', [] ) );
|
57 |
+
|
58 |
+
if ( $network_plugins )
|
59 |
$active_plugins = array_merge( $active_plugins, $network_plugins );
|
|
|
60 |
}
|
61 |
|
62 |
sort( $active_plugins );
|
63 |
|
64 |
+
return memo( $active_plugins );
|
65 |
}
|
66 |
|
67 |
/**
|
76 |
|
77 |
$conflicting_plugins = [
|
78 |
'seo_tools' => [
|
79 |
+
'Yoast SEO' => 'wordpress-seo/wp-seo.php',
|
80 |
+
'Yoast SEO Premium' => 'wordpress-seo-premium/wp-seo-premium.php',
|
81 |
+
'All in One SEO Pack' => 'all-in-one-seo-pack/all_in_one_seo_pack.php',
|
82 |
+
'SEO Ultimate' => 'seo-ultimate/seo-ultimate.php',
|
83 |
+
'SEOPress' => 'wp-seopress/seopress.php',
|
84 |
+
'Rank Math' => 'seo-by-rank-math/rank-math.php',
|
85 |
+
'Smart Crawl' => 'smartcrawl-seo/wpmu-dev-seo.php',
|
|
|
86 |
],
|
87 |
'sitemaps' => [
|
88 |
+
'Google XML Sitemaps' => 'google-sitemap-generator/sitemap.php',
|
89 |
+
'XML Sitemap & Google News feeds' => 'xml-sitemap-feed/xml-sitemap.php',
|
90 |
+
'Google Sitemap by BestWebSoft' => 'google-sitemap-plugin/google-sitemap-plugin.php',
|
91 |
+
'Simple Wp Sitemap' => 'simple-wp-sitemap/simple-wp-sitemap.php', // Remove?
|
|
|
|
|
|
|
92 |
],
|
93 |
'open_graph' => [
|
94 |
'Facebook Open Graph Meta Tags for WordPress' => 'wonderm00ns-simple-facebook-open-graph-tags/wonderm00n-open-graph.php',
|
95 |
+
'Open Graph' => 'opengraph/opengraph.php', // Redundant.
|
96 |
+
'Open Graph Protocol Framework' => 'open-graph-protocol-framework/open-graph-protocol-framework.php', // Redundant.
|
|
|
|
|
97 |
'Shareaholic2' => 'shareaholic/sexy-bookmarks.php',
|
|
|
98 |
'WordPress Social Sharing Optimization' => 'wpsso/wpsso.php',
|
|
|
99 |
],
|
100 |
'twitter_card' => [],
|
101 |
];
|
104 |
* @since 2.6.0
|
105 |
* @param array $conflicting_plugins The conflicting plugin list.
|
106 |
*/
|
107 |
+
return (array) \apply_filters_ref_array( 'the_seo_framework_conflicting_plugins', [ $conflicting_plugins ] );
|
108 |
}
|
109 |
|
110 |
/**
|
111 |
* Fetches type of conflicting plugins.
|
112 |
*
|
113 |
* @since 2.6.0
|
114 |
+
* @since 4.2.0 Now always runs the filter, even when $type is not registered.
|
115 |
*
|
116 |
* @param string $type The Key from $this->conflicting_plugins()
|
117 |
* @return array
|
118 |
*/
|
119 |
public function get_conflicting_plugins( $type = 'seo_tools' ) {
|
120 |
+
/**
|
121 |
+
* @since 2.6.1
|
122 |
+
* @param array $conflicting_plugins Conflicting plugins
|
123 |
+
* @param string $type The type of plugins to get.
|
124 |
+
*/
|
125 |
+
return (array) \apply_filters_ref_array(
|
126 |
+
'the_seo_framework_conflicting_plugins_type',
|
127 |
+
[
|
128 |
+
$this->conflicting_plugins()[ $type ] ?? [],
|
129 |
+
$type,
|
130 |
+
]
|
131 |
+
);
|
132 |
}
|
133 |
|
134 |
/**
|
137 |
* Note: Class check is 3 times as slow as defined check. Function check is 2 times as slow.
|
138 |
*
|
139 |
* @since 1.3.0
|
140 |
+
* @since 2.8.0 1. Can now check for globals.
|
141 |
+
* 2. Switched detection order from FAST to SLOW.
|
142 |
* @since 4.0.6 Can no longer autoload classes.
|
143 |
*
|
144 |
* @param array $plugins Array of array for constants, classes and / or functions to check for plugin existence.
|
146 |
*/
|
147 |
public function detect_plugin( $plugins ) {
|
148 |
|
149 |
+
foreach ( $plugins['globals'] ?? [] as $name )
|
150 |
+
if ( isset( $GLOBALS[ $name ] ) )
|
151 |
+
return true;
|
|
|
|
|
|
|
|
|
152 |
|
153 |
// Check for constants
|
154 |
+
foreach ( $plugins['constants'] ?? [] as $name )
|
155 |
+
if ( \defined( $name ) )
|
156 |
+
return true;
|
|
|
|
|
|
|
|
|
157 |
|
158 |
// Check for functions
|
159 |
+
foreach ( $plugins['functions'] ?? [] as $name )
|
160 |
+
if ( \function_exists( $name ) )
|
161 |
+
return true;
|
|
|
|
|
|
|
|
|
162 |
|
163 |
// Check for classes
|
164 |
+
foreach ( $plugins['classes'] ?? [] as $name )
|
165 |
+
if ( class_exists( $name, false ) ) // phpcs:ignore, TSF.Performance.Functions.PHP -- we don't autoload.
|
166 |
+
return true;
|
|
|
|
|
|
|
|
|
|
|
167 |
|
168 |
// No globals, constant, function, or class found to exist
|
169 |
return false;
|
176 |
*
|
177 |
* @since 2.5.2
|
178 |
* @since 4.1.4 Fixed sorting algorithm from fribbling-me to resolving-me. Nothing changed but legibility.
|
179 |
+
* @since 4.2.0 Rewrote sorting algorithm; now, it's actually good.
|
180 |
* @uses $this->detect_plugin_multi()
|
181 |
*
|
182 |
+
* @param array[] $plugins Array of array for globals, constants, classes
|
183 |
* and/or functions to check for plugin existence.
|
184 |
+
* @param bool $use_cache Bypasses cache if false
|
185 |
*/
|
186 |
+
public function can_i_use( $plugins = [], $use_cache = true ) {
|
187 |
|
188 |
if ( ! $use_cache )
|
189 |
return $this->detect_plugin_multi( $plugins );
|
190 |
|
191 |
+
ksort( $plugins );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
|
193 |
+
foreach ( $plugins as &$test )
|
194 |
+
sort( $test );
|
195 |
|
|
|
|
|
|
|
|
|
|
|
196 |
// phpcs:ignore, WordPress.PHP.DiscouragedPHPFunctions -- No objects are inserted, nor is this ever unserialized.
|
197 |
+
$key = serialize( $test );
|
|
|
|
|
|
|
198 |
|
199 |
+
return memo( null, $key ) ?? memo( $this->detect_plugin_multi( $plugins ), $key );
|
200 |
}
|
201 |
|
202 |
/**
|
204 |
* All parameters must match and return true.
|
205 |
*
|
206 |
* @since 2.5.2
|
207 |
+
* @since 4.0.6 1. Can now check for globals.
|
208 |
+
* 2. Switched detection order from FAST to SLOW.
|
209 |
+
* 3. Can no longer autoload classes.
|
210 |
* This method is only used by can_i_use(), and is only effective in the Ultimate Member compat file...
|
211 |
* @TODO deprecate?
|
212 |
*
|
213 |
+
* @param array[] $plugins Array of array for constants, classes
|
214 |
+
* and / or functions to check for plugin existence.
|
215 |
+
* @return bool True if ALL functions classes and constants exists
|
216 |
+
* or false if plugin constant, class or function not detected.
|
217 |
*/
|
218 |
+
public function detect_plugin_multi( $plugins ) {
|
219 |
|
220 |
// Check for globals
|
221 |
+
foreach ( $plugins['globals'] ?? [] as $name )
|
222 |
+
if ( ! isset( $GLOBALS[ $name ] ) )
|
223 |
+
return false;
|
|
|
|
|
|
|
|
|
224 |
|
225 |
// Check for constants
|
226 |
+
foreach ( $plugins['constants'] ?? [] as $name )
|
227 |
+
if ( ! \defined( $name ) )
|
228 |
+
return false;
|
|
|
|
|
|
|
|
|
229 |
|
230 |
// Check for functions
|
231 |
+
foreach ( $plugins['functions'] ?? [] as $name )
|
232 |
+
if ( ! \function_exists( $name ) )
|
233 |
+
return false;
|
|
|
|
|
|
|
|
|
234 |
|
235 |
// Check for classes
|
236 |
+
foreach ( $plugins['classes'] ?? [] as $name )
|
237 |
+
if ( ! class_exists( $name, false ) ) // phpcs:ignore, TSF.Performance.Functions.PHP -- we don't autoload.
|
238 |
+
return false;
|
|
|
|
|
|
|
|
|
|
|
239 |
|
240 |
// All classes, functions and constant have been found to exist
|
241 |
return true;
|
245 |
* Checks if the (parent) theme name is loaded.
|
246 |
*
|
247 |
* @since 2.1.0
|
248 |
+
* @since 4.2.0 No longer "loads" the theme; instead, simply compares input to active theme options.
|
249 |
*
|
250 |
+
* @param string|array $themes The theme names to test.
|
251 |
* @return bool is theme active.
|
252 |
*/
|
253 |
public function is_theme( $themes = '' ) {
|
254 |
|
255 |
+
$active_theme = [
|
256 |
+
strtolower( \get_option( 'stylesheet' ) ), // Parent
|
257 |
+
strtolower( \get_option( 'template' ) ), // Child
|
258 |
+
];
|
|
|
|
|
|
|
259 |
|
260 |
+
foreach ( (array) $themes as $theme )
|
261 |
+
if ( \in_array( strtolower( $theme ), $active_theme, true ) )
|
|
|
262 |
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
263 |
|
264 |
return false;
|
265 |
}
|
276 |
*/
|
277 |
public function detect_seo_plugins() {
|
278 |
|
279 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
280 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
281 |
|
282 |
$active_plugins = $this->active_plugins();
|
283 |
|
284 |
+
if ( ! $active_plugins ) return memo( false );
|
285 |
+
|
286 |
+
foreach ( $this->get_conflicting_plugins( 'seo_tools' ) as $plugin_name => $plugin ) {
|
287 |
+
if ( \in_array( $plugin, $active_plugins, true ) ) {
|
288 |
+
/**
|
289 |
+
* @since 2.6.1
|
290 |
+
* @since 3.1.0 Added second and third parameters.
|
291 |
+
* @param bool $detected Whether the plugin should be detected.
|
292 |
+
* @param string $plugin_name The plugin name as defined in `$this->conflicting_plugins()`.
|
293 |
+
* @param string $plugin The plugin that's been detected.
|
294 |
+
*/
|
295 |
+
if ( \apply_filters_ref_array(
|
296 |
+
'the_seo_framework_seo_plugin_detected',
|
297 |
+
[
|
298 |
+
true,
|
299 |
+
$plugin_name,
|
300 |
+
$plugin,
|
301 |
+
]
|
302 |
+
) ) {
|
303 |
+
$detected = true;
|
304 |
+
break;
|
305 |
}
|
306 |
}
|
307 |
}
|
308 |
|
309 |
+
return memo( (bool) ( $detected ?? false ) );
|
310 |
}
|
311 |
|
312 |
/**
|
321 |
*/
|
322 |
public function detect_og_plugin() {
|
323 |
|
|
|
|
|
|
|
|
|
|
|
324 |
// Detect SEO plugins beforehand.
|
325 |
if ( $this->detect_seo_plugins() )
|
326 |
+
return true;
|
327 |
+
|
328 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
329 |
+
if ( null !== $memo = memo() ) return $memo;
|
330 |
|
331 |
$active_plugins = $this->active_plugins();
|
332 |
|
333 |
+
if ( ! $active_plugins ) return memo( false );
|
334 |
+
|
335 |
+
foreach ( $this->get_conflicting_plugins( 'open_graph' ) as $plugin_name => $plugin ) {
|
336 |
+
if ( \in_array( $plugin, $active_plugins, true ) ) {
|
337 |
+
/**
|
338 |
+
* @since 2.6.1
|
339 |
+
* @since 3.1.0 Added second and third parameters.
|
340 |
+
* @param bool $detected Whether the plugin should be detected.
|
341 |
+
* @param string $plugin_name The plugin name as defined in `$this->conflicting_plugins()`.
|
342 |
+
* @param string $plugin The plugin that's been detected.
|
343 |
+
*/
|
344 |
+
if ( \apply_filters_ref_array(
|
345 |
+
'the_seo_framework_og_plugin_detected',
|
346 |
+
[
|
347 |
+
true,
|
348 |
+
$plugin_name,
|
349 |
+
$plugin,
|
350 |
+
]
|
351 |
+
) ) {
|
352 |
+
$detected = true;
|
353 |
+
break;
|
354 |
}
|
355 |
}
|
356 |
}
|
357 |
|
358 |
+
return memo( (bool) ( $detected ?? false ) );
|
359 |
}
|
360 |
|
361 |
/**
|
369 |
*/
|
370 |
public function detect_twitter_card_plugin() {
|
371 |
|
|
|
|
|
|
|
|
|
|
|
372 |
// Detect SEO plugins beforehand.
|
373 |
if ( $this->detect_seo_plugins() )
|
374 |
+
return true;
|
375 |
+
|
376 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
377 |
+
if ( null !== $memo = memo() ) return $memo;
|
378 |
|
379 |
$active_plugins = $this->active_plugins();
|
380 |
|
381 |
+
if ( ! $active_plugins ) return memo( false );
|
382 |
+
|
383 |
+
foreach ( $this->get_conflicting_plugins( 'twitter_card' ) as $plugin_name => $plugin ) {
|
384 |
+
if ( \in_array( $plugin, $active_plugins, true ) ) {
|
385 |
+
/**
|
386 |
+
* @since 2.6.1
|
387 |
+
* @param bool $detected Whether the plugin should be detected.
|
388 |
+
* @param string $plugin_name The plugin name as defined in `$this->conflicting_plugins()`.
|
389 |
+
* @param string $plugin The plugin that's been detected.
|
390 |
+
*/
|
391 |
+
if ( \apply_filters_ref_array(
|
392 |
+
'the_seo_framework_twittercard_plugin_detected',
|
393 |
+
[
|
394 |
+
true,
|
395 |
+
$plugin_name,
|
396 |
+
$plugin,
|
397 |
+
]
|
398 |
+
) ) {
|
399 |
+
$detected = true;
|
400 |
+
break;
|
401 |
}
|
402 |
}
|
403 |
}
|
404 |
|
405 |
+
return memo( (bool) ( $detected ?? false ) );
|
406 |
}
|
407 |
|
408 |
/**
|
433 |
*/
|
434 |
public function detect_sitemap_plugin() {
|
435 |
|
|
|
|
|
|
|
|
|
|
|
436 |
// Detect SEO plugins beforehand.
|
437 |
if ( $this->detect_seo_plugins() )
|
438 |
+
return true;
|
439 |
+
|
440 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
441 |
+
if ( null !== $memo = memo() ) return $memo;
|
442 |
|
443 |
$active_plugins = $this->active_plugins();
|
444 |
|
445 |
+
if ( ! $active_plugins ) return memo( false );
|
446 |
+
|
447 |
+
foreach ( $this->get_conflicting_plugins( 'sitemaps' ) as $plugin_name => $plugin ) {
|
448 |
+
if ( \in_array( $plugin, $active_plugins, true ) ) {
|
449 |
+
/**
|
450 |
+
* @since 2.6.1
|
451 |
+
* @param bool $detected Whether the plugin should be detected.
|
452 |
+
* @param string $plugin_name The plugin name as defined in `$this->conflicting_plugins()`.
|
453 |
+
* @param string $plugin The plugin that's been detected.
|
454 |
+
*/
|
455 |
+
if ( \apply_filters(
|
456 |
+
'the_seo_framework_sitemap_plugin_detected',
|
457 |
+
[
|
458 |
+
true,
|
459 |
+
$plugin_name,
|
460 |
+
$plugin,
|
461 |
+
]
|
462 |
+
) ) {
|
463 |
+
$detected = true;
|
464 |
+
break;
|
465 |
}
|
466 |
}
|
467 |
}
|
468 |
|
469 |
+
return memo( (bool) ( $detected ?? false ) );
|
470 |
}
|
471 |
|
472 |
/**
|
478 |
* @return bool
|
479 |
*/
|
480 |
public function use_core_sitemaps() {
|
|
|
481 |
|
482 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
483 |
+
if ( null !== $memo = memo() ) return $memo;
|
484 |
|
485 |
if ( $this->get_option( 'sitemaps_output' ) )
|
486 |
+
return memo( false );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
487 |
|
488 |
+
$wp_sitemaps_server = \wp_sitemaps_get_server();
|
|
|
489 |
|
490 |
+
return memo(
|
491 |
+
method_exists( $wp_sitemaps_server, 'sitemaps_enabled' )
|
492 |
+
&& $wp_sitemaps_server->sitemaps_enabled()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
493 |
);
|
494 |
}
|
495 |
|
505 |
* @return bool
|
506 |
*/
|
507 |
public function detect_non_html_page_builder() {
|
508 |
+
return memo() ?? memo(
|
509 |
+
/**
|
510 |
+
* @since 4.1.0
|
511 |
+
* @param bool $detected Whether an active page builder that renders content dynamically is detected.
|
512 |
+
* @NOTE not to be confused with `the_seo_framework_detect_non_html_page_builder`, which tests
|
513 |
+
* the page builder status for each post individually.
|
514 |
+
*/
|
515 |
+
(bool) \apply_filters(
|
516 |
+
'the_seo_framework_shortcode_based_page_builder_active',
|
517 |
+
$this->detect_plugin( [
|
518 |
+
'constants' => [
|
519 |
+
'ET_BUILDER_VERSION',
|
520 |
+
'WPB_VC_VERSION',
|
521 |
+
],
|
522 |
+
] )
|
523 |
+
)
|
|
|
|
|
|
|
524 |
);
|
525 |
}
|
526 |
|
534 |
* @return bool Whether the robots.txt file exists.
|
535 |
*/
|
536 |
public function has_robots_txt() {
|
537 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
538 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
|
|
539 |
|
540 |
// Ensure get_home_path() is declared.
|
541 |
if ( ! \function_exists( '\\get_home_path' ) )
|
544 |
$path = \get_home_path() . 'robots.txt';
|
545 |
|
546 |
// phpcs:ignore, TSF.Performance.Functions.PHP -- we use path, not URL.
|
547 |
+
return memo( file_exists( $path ) );
|
548 |
}
|
549 |
|
550 |
/**
|
557 |
* @return bool Whether the sitemap.xml file exists.
|
558 |
*/
|
559 |
public function has_sitemap_xml() {
|
560 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
561 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
|
|
562 |
|
563 |
// Ensure get_home_path() is declared.
|
564 |
if ( ! \function_exists( '\\get_home_path' ) )
|
567 |
$path = \get_home_path() . 'sitemap.xml';
|
568 |
|
569 |
// phpcs:ignore, TSF.Performance.Functions.PHP -- we use path, not URL.
|
570 |
+
return memo( file_exists( $path ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
571 |
}
|
572 |
|
573 |
/**
|
581 |
*/
|
582 |
public function query_supports_seo() {
|
583 |
|
584 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
585 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
586 |
|
587 |
switch ( true ) :
|
588 |
case $this->is_feed():
|
616 |
* This protects against (accidental) negative-SEO bombarding.
|
617 |
* Support broken queries, so we can noindex them.
|
618 |
*/
|
619 |
+
if ( ! $supported && $this->is_query_exploited() )
|
620 |
$supported = true;
|
|
|
621 |
|
622 |
/**
|
623 |
* @since 4.0.0
|
624 |
* @param bool $supported Whether the query supports SEO.
|
625 |
*/
|
626 |
+
return memo( (bool) \apply_filters( 'the_seo_framework_query_supports_seo', $supported ) );
|
627 |
}
|
628 |
|
629 |
/**
|
665 |
*/
|
666 |
public function is_query_exploited() {
|
667 |
|
668 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
669 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
670 |
|
671 |
if ( ! $this->get_option( 'advanced_query_protection' ) )
|
672 |
+
return memo( false );
|
673 |
|
674 |
// When the page ID is not 0, a real page will always be returned.
|
675 |
if ( $this->get_the_real_ID() )
|
676 |
+
return memo( false );
|
677 |
|
678 |
global $wp_query;
|
679 |
|
713 |
]
|
714 |
);
|
715 |
|
716 |
+
$query = $wp_query->query;
|
|
|
717 |
|
718 |
foreach ( $exploitables as $type => $qvs ) :
|
719 |
foreach ( $qvs as $qv ) :
|
720 |
+
// Only test isset, because falsey or empty-array is what we need to test against.
|
721 |
if ( ! isset( $query[ $qv ] ) ) continue;
|
722 |
|
723 |
switch ( $type ) :
|
724 |
case 'numeric':
|
725 |
+
if ( '0' === $query[ $qv ] || ! is_numeric( $query[ $qv ] ) )
|
726 |
+
return memo( true );
|
|
|
|
|
727 |
break;
|
728 |
|
729 |
case 'numeric_array':
|
732 |
|
733 |
// If WordPress didn't canonical_redirect() the user yet, it's exploited.
|
734 |
// WordPress mitigates this via a 404 query when a numeric value is found.
|
735 |
+
if ( ! preg_match( '/[0-9]/', $query[ $qv ] ) )
|
736 |
+
return memo( true );
|
|
|
|
|
737 |
break;
|
738 |
|
739 |
case 'requires_s':
|
740 |
+
if ( ! isset( $query['s'] ) )
|
741 |
+
return memo( true );
|
|
|
|
|
742 |
break;
|
743 |
|
744 |
default:
|
747 |
endforeach;
|
748 |
endforeach;
|
749 |
|
750 |
+
return memo( false );
|
751 |
+
}
|
752 |
+
|
753 |
+
/**
|
754 |
+
* Tests if the post type archive of said post type contains public posts.
|
755 |
+
* Memoizes the return value.
|
756 |
+
*
|
757 |
+
* @since 4.2.0
|
758 |
+
*
|
759 |
+
* @param string $post_type The post type to test.
|
760 |
+
* @return bool True if a post is found in the archive, false otherwise.
|
761 |
+
*/
|
762 |
+
public function has_posts_in_post_type_archive( $post_type ) {
|
763 |
+
|
764 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
765 |
+
if ( null !== $memo = memo( null, $post_type ) ) return $memo;
|
766 |
+
|
767 |
+
$query = new \WP_Query( [
|
768 |
+
'posts_per_page' => 1,
|
769 |
+
'post_type' => [ $post_type ],
|
770 |
+
'orderby' => 'date',
|
771 |
+
'order' => 'ASC',
|
772 |
+
'post_status' => 'publish',
|
773 |
+
'has_password' => false,
|
774 |
+
'fields' => 'ids',
|
775 |
+
'cache_results' => false,
|
776 |
+
'no_found_rows' => true,
|
777 |
+
] );
|
778 |
+
|
779 |
+
return memo( ! empty( $query->posts ), $post_type );
|
780 |
}
|
781 |
|
782 |
/**
|
856 |
*/
|
857 |
public function post_type_supports_taxonomies( $post_type = '' ) {
|
858 |
|
859 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
860 |
+
if ( null !== $memo = memo( null, $post_type ) ) return $memo;
|
|
|
|
|
861 |
|
862 |
$post_type = $post_type ?: $this->get_current_post_type();
|
|
|
863 |
|
864 |
+
// Return false if no post type if found -- do not memo that, for query call might be too early.
|
865 |
+
return $post_type && memo( (bool) \get_object_taxonomies( $post_type, 'names' ), $post_type );
|
866 |
+
}
|
867 |
|
868 |
+
/**
|
869 |
+
* Returns a list of all supported post types with archives.
|
870 |
+
* Memoizes the return value.
|
871 |
+
*
|
872 |
+
* @since 4.2.0
|
873 |
+
*
|
874 |
+
* @return string[] Supported post types with post type archive support.
|
875 |
+
*/
|
876 |
+
public function get_supported_post_type_archives() {
|
877 |
+
return memo() ?? memo(
|
878 |
+
array_values(
|
879 |
+
array_filter(
|
880 |
+
$this->get_supported_post_types(),
|
881 |
+
static function( $post_type ) {
|
882 |
+
return \get_post_type_object( $post_type )->has_archive ?? false;
|
883 |
+
}
|
884 |
+
)
|
885 |
+
)
|
886 |
+
);
|
887 |
+
}
|
888 |
+
|
889 |
+
/**
|
890 |
+
* Gets all post types that have PTA and could possibly support SEO.
|
891 |
+
* Memoizes the return value.
|
892 |
+
*
|
893 |
+
* @since 4.2.0
|
894 |
+
*
|
895 |
+
* @return string[] Public post types with post type archive support.
|
896 |
+
*/
|
897 |
+
public function get_public_post_type_archives() {
|
898 |
+
return memo() ?? memo(
|
899 |
+
array_values(
|
900 |
+
array_filter(
|
901 |
+
$this->get_public_post_types(),
|
902 |
+
static function( $post_type ) {
|
903 |
+
return \get_post_type_object( $post_type )->has_archive ?? false;
|
904 |
+
}
|
905 |
+
)
|
906 |
+
)
|
907 |
+
);
|
908 |
}
|
909 |
|
910 |
/**
|
911 |
* Returns a list of all supported post types.
|
912 |
*
|
913 |
* @since 3.1.0
|
|
|
914 |
*
|
915 |
+
* @return string[] All supported post types.
|
916 |
*/
|
917 |
public function get_supported_post_types() {
|
918 |
+
return memo() ?? memo(
|
919 |
+
array_values(
|
920 |
+
array_filter( $this->get_public_post_types(), [ $this, 'is_post_type_supported' ] )
|
921 |
+
)
|
|
|
|
|
|
|
922 |
);
|
923 |
}
|
924 |
|
929 |
* @since 4.1.0
|
930 |
* @since 4.1.4 Now resets the index keys of the return value.
|
931 |
*
|
932 |
+
* @return string[] All public post types.
|
933 |
*/
|
934 |
protected function get_public_post_types() {
|
935 |
+
return umemo( __METHOD__ )
|
936 |
+
?? umemo(
|
937 |
+
__METHOD__,
|
938 |
+
/**
|
939 |
+
* Do not consider using this filter. Properly register your post type, noob.
|
940 |
+
*
|
941 |
+
* @since 4.2.0
|
942 |
+
* @param string[] $post_types The public post types.
|
943 |
+
*/
|
944 |
+
\apply_filters(
|
945 |
+
'the_seo_framework_public_post_types',
|
946 |
+
array_values(
|
947 |
+
array_filter(
|
948 |
+
array_unique(
|
949 |
+
array_merge(
|
950 |
+
$this->get_forced_supported_post_types(),
|
951 |
+
//? array_values() because get_post_types() gives a sequential array.
|
952 |
+
array_keys( (array) \get_post_types( [ 'public' => true ] ) )
|
953 |
+
)
|
954 |
+
),
|
955 |
+
'is_post_type_viewable'
|
956 |
+
)
|
957 |
)
|
958 |
+
)
|
959 |
+
);
|
|
|
|
|
960 |
}
|
961 |
|
962 |
/**
|
963 |
* Returns a list of builtin public post types.
|
|
|
964 |
*
|
965 |
* @since 3.1.0
|
966 |
+
* @since 4.2.0 Removed memoization.
|
967 |
*
|
968 |
+
* @return string[] Forced supported post types.
|
969 |
*/
|
970 |
protected function get_forced_supported_post_types() {
|
|
|
|
|
971 |
/**
|
972 |
+
* @since 3.1.0
|
973 |
+
* @param string[] $forced Forced supported post types
|
974 |
+
*/
|
975 |
+
return (array) \apply_filters_ref_array(
|
976 |
'the_seo_framework_forced_supported_post_types',
|
977 |
+
[
|
978 |
+
array_values( \get_post_types( [
|
979 |
+
'public' => true,
|
980 |
+
'_builtin' => true,
|
981 |
+
] ) ),
|
982 |
+
]
|
983 |
+
);
|
984 |
+
}
|
985 |
+
|
986 |
+
/**
|
987 |
+
* Returns a list of all supported taxonomies.
|
988 |
+
*
|
989 |
+
* @since 4.2.0
|
990 |
+
*
|
991 |
+
* @return string[] All supported taxonomies.
|
992 |
+
*/
|
993 |
+
public function get_supported_taxonomies() {
|
994 |
+
return memo() ?? memo(
|
995 |
+
array_values(
|
996 |
+
array_filter( $this->get_public_taxonomies(), [ $this, 'is_taxonomy_supported' ] )
|
997 |
+
)
|
998 |
);
|
999 |
}
|
1000 |
|
1004 |
*
|
1005 |
* @since 4.1.0
|
1006 |
*
|
1007 |
+
* @return string[] The taxonomies that are public.
|
1008 |
*/
|
1009 |
protected function get_public_taxonomies() {
|
1010 |
+
return umemo( __METHOD__ )
|
1011 |
+
?? umemo(
|
1012 |
+
__METHOD__,
|
1013 |
+
/**
|
1014 |
+
* Do not consider using this filter. Properly register your taxonomy, noob.
|
1015 |
+
*
|
1016 |
+
* @since 4.2.0
|
1017 |
+
* @param string[] $post_types The public post types.
|
1018 |
+
*/
|
1019 |
+
\apply_filters(
|
1020 |
+
'the_seo_framework_public_taxonomies',
|
1021 |
+
array_filter(
|
1022 |
+
array_unique(
|
1023 |
+
array_merge(
|
1024 |
+
$this->get_forced_supported_taxonomies(),
|
1025 |
+
//? array_values() because get_taxonomies() gives a sequential array.
|
1026 |
+
array_values( \get_taxonomies( [
|
1027 |
+
'public' => true,
|
1028 |
+
'_builtin' => false,
|
1029 |
+
] ) )
|
1030 |
+
)
|
1031 |
+
),
|
1032 |
+
'is_taxonomy_viewable'
|
1033 |
+
)
|
1034 |
)
|
1035 |
+
);
|
|
|
|
|
1036 |
}
|
1037 |
|
1038 |
/**
|
1039 |
* Returns a list of builtin public taxonomies.
|
|
|
1040 |
*
|
1041 |
* @since 4.1.0
|
1042 |
+
* @since 4.2.0 Removed memoization.
|
1043 |
*
|
1044 |
+
* @return string[] Forced supported taxonomies
|
1045 |
*/
|
1046 |
protected function get_forced_supported_taxonomies() {
|
|
|
|
|
1047 |
/**
|
1048 |
* @since 4.1.0
|
1049 |
+
* @param string[] $forced Forced supported post types
|
1050 |
*/
|
1051 |
+
return (array) \apply_filters_ref_array(
|
1052 |
'the_seo_framework_forced_supported_taxonomies',
|
1053 |
+
[
|
1054 |
+
array_values( \get_taxonomies( [
|
1055 |
+
'public' => true,
|
1056 |
+
'_builtin' => true,
|
1057 |
+
] ) ),
|
1058 |
+
]
|
1059 |
);
|
1060 |
}
|
1061 |
|
1079 |
* @param bool $disabled
|
1080 |
* @param string $post_type
|
1081 |
*/
|
1082 |
+
return \apply_filters_ref_array(
|
1083 |
+
'the_seo_framework_post_type_disabled',
|
1084 |
+
[
|
1085 |
+
isset( $this->get_option( 'disabled_post_types' )[ $post_type ] ),
|
1086 |
+
$post_type,
|
1087 |
+
]
|
1088 |
);
|
1089 |
}
|
1090 |
|
1105 |
|
1106 |
$disabled = false;
|
1107 |
|
1108 |
+
// First, test pertaining option directly.
|
1109 |
+
if ( $taxonomy && isset( $this->get_option( 'disabled_taxonomies' )[ $taxonomy ] ) ) {
|
1110 |
$disabled = true;
|
1111 |
} else {
|
1112 |
+
// Then, test some() post types.
|
1113 |
+
// Populate $disabled within loop, for the taxonomy might not have post types at all.
|
1114 |
foreach ( $this->get_post_types_from_taxonomy( $taxonomy ) as $type ) {
|
|
|
|
|
1115 |
if ( $this->is_post_type_supported( $type ) ) {
|
1116 |
$disabled = false;
|
1117 |
break;
|
1118 |
}
|
1119 |
+
$disabled = true;
|
1120 |
}
|
1121 |
}
|
1122 |
|
1125 |
* @param bool $disabled
|
1126 |
* @param string $taxonomy
|
1127 |
*/
|
1128 |
+
return \apply_filters_ref_array(
|
1129 |
+
'the_seo_framework_taxonomy_disabled',
|
1130 |
+
[
|
1131 |
+
$disabled,
|
1132 |
+
$taxonomy,
|
1133 |
+
]
|
1134 |
+
);
|
1135 |
}
|
1136 |
|
1137 |
/**
|
1150 |
* Detects if we're on a Gutenberg page.
|
1151 |
*
|
1152 |
* @since 3.1.0
|
1153 |
+
* @since 3.2.0 1. Now detects the WP 5.0 block editor.
|
1154 |
+
* 2. Method is now public.
|
1155 |
*
|
1156 |
* @return bool
|
1157 |
*/
|
1189 |
* @return string URL location of robots.txt. Unescaped.
|
1190 |
*/
|
1191 |
public function get_robots_txt_url() {
|
|
|
1192 |
|
1193 |
+
if ( $GLOBALS['wp_rewrite']->using_permalinks() && ! $this->is_subdirectory_installation() ) {
|
1194 |
$home = \trailingslashit( $this->set_preferred_url_scheme( $this->get_home_host() ) );
|
1195 |
$path = "{$home}robots.txt";
|
1196 |
} elseif ( $this->has_robots_txt() ) {
|
1212 |
* @return bool
|
1213 |
*/
|
1214 |
public function is_subdirectory_installation() {
|
1215 |
+
return memo() ?? memo(
|
1216 |
+
(bool) \strlen(
|
1217 |
+
ltrim( parse_url( \get_option( 'home' ), PHP_URL_PATH ), ' \\/' )
|
1218 |
+
)
|
1219 |
+
);
|
|
|
|
|
|
|
|
|
1220 |
}
|
1221 |
|
1222 |
/**
|
1233 |
if ( false === strpos( $text, '%%' ) ) return false;
|
1234 |
|
1235 |
$tags_simple = [ 'date', 'title', 'parent_title', 'archive_title', 'sitename', 'sitedesc', 'excerpt', 'excerpt_only', 'tag', 'category', 'primary_category', 'category_description', 'tag_description', 'term_description', 'term_title', 'searchphrase', 'sep', 'pt_single', 'pt_plural', 'modified', 'id', 'name', 'user_description', 'page', 'pagetotal', 'pagenumber', 'caption', 'focuskw', 'term404', 'ct_product_cat', 'ct_product_tag', 'wc_shortdesc', 'wc_sku', 'wc_brand', 'wc_price' ];
|
1236 |
+
$_regex = sprintf( '%%%s%%', implode( '|', $tags_simple ) );
|
|
|
1237 |
|
1238 |
if ( preg_match( "/$_regex/i", $text ) ) return true;
|
1239 |
|
1240 |
$tags_wildcard_end = [ 'cs_', 'ct_desc_', 'ct_pa_' ];
|
1241 |
+
$_regex = sprintf( '%%(%s)[^\s]*?%%', implode( '|', $tags_wildcard_end ) );
|
|
|
1242 |
|
1243 |
if ( preg_match( "/$_regex/", $text ) ) return true;
|
1244 |
|
@@ -39,20 +39,19 @@ class Generate_Description extends Generate {
|
|
39 |
*
|
40 |
* @since 3.0.6
|
41 |
* @since 3.1.0 The first argument now accepts an array, with "id" and "taxonomy" fields.
|
|
|
42 |
* @uses $this->get_description_from_custom_field()
|
43 |
* @uses $this->get_generated_description()
|
44 |
*
|
45 |
-
* @param array|null $args
|
46 |
-
*
|
47 |
* @param bool $escape Whether to escape the description.
|
48 |
* @return string The real description output.
|
49 |
*/
|
50 |
public function get_description( $args = null, $escape = true ) {
|
51 |
|
52 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
53 |
$desc = $this->get_description_from_custom_field( $args, false )
|
54 |
?: $this->get_generated_description( $args, false );
|
55 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
56 |
|
57 |
return $escape ? $this->escape_description( $desc ) : $desc;
|
58 |
}
|
@@ -61,22 +60,21 @@ class Generate_Description extends Generate {
|
|
61 |
* Returns the Open Graph meta description. Falls back to meta description.
|
62 |
*
|
63 |
* @since 3.0.4
|
64 |
-
* @since 3.1.0
|
65 |
-
*
|
|
|
66 |
* @uses $this->get_open_graph_description_from_custom_field()
|
67 |
* @uses $this->get_generated_open_graph_description()
|
68 |
*
|
69 |
-
* @param array|null $args
|
70 |
-
*
|
71 |
* @param bool $escape Whether to escape the description.
|
72 |
* @return string The real Open Graph description output.
|
73 |
*/
|
74 |
public function get_open_graph_description( $args = null, $escape = true ) {
|
75 |
|
76 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
77 |
$desc = $this->get_open_graph_description_from_custom_field( $args, false )
|
78 |
?: $this->get_generated_open_graph_description( $args, false );
|
79 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
80 |
|
81 |
return $escape ? $this->escape_description( $desc ) : $desc;
|
82 |
}
|
@@ -88,7 +86,7 @@ class Generate_Description extends Generate {
|
|
88 |
* @since 3.1.0
|
89 |
* @see $this->get_open_graph_description()
|
90 |
*
|
91 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
92 |
* Leave null to autodetermine query.
|
93 |
* @param bool $escape Whether to escape the title.
|
94 |
* @return string TwOpen Graphitter description.
|
@@ -112,6 +110,8 @@ class Generate_Description extends Generate {
|
|
112 |
* @since 3.1.0
|
113 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
114 |
* @since 4.0.0 Added term meta item checks.
|
|
|
|
|
115 |
* @see $this->get_open_graph_description()
|
116 |
* @see $this->get_open_graph_description_from_custom_field()
|
117 |
*
|
@@ -120,24 +120,25 @@ class Generate_Description extends Generate {
|
|
120 |
protected function get_custom_open_graph_description_from_query() {
|
121 |
|
122 |
$desc = '';
|
123 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
124 |
if ( $this->is_real_front_page() ) {
|
125 |
if ( $this->is_static_frontpage() ) {
|
126 |
$desc = $this->get_option( 'homepage_og_description' )
|
127 |
?: $this->get_post_meta_item( '_open_graph_description' )
|
128 |
-
?: $this->get_description_from_custom_field();
|
129 |
} else {
|
130 |
$desc = $this->get_option( 'homepage_og_description' )
|
131 |
-
?: $this->get_description_from_custom_field();
|
132 |
}
|
133 |
} elseif ( $this->is_singular() ) {
|
134 |
$desc = $this->get_post_meta_item( '_open_graph_description' )
|
135 |
-
?: $this->get_description_from_custom_field();
|
136 |
} elseif ( $this->is_term_meta_capable() ) {
|
137 |
$desc = $this->get_term_meta_item( 'og_description' )
|
138 |
-
?: $this->get_description_from_custom_field();
|
|
|
|
|
|
|
139 |
}
|
140 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
141 |
|
142 |
return $desc;
|
143 |
}
|
@@ -147,36 +148,39 @@ class Generate_Description extends Generate {
|
|
147 |
* Falls back to meta description.
|
148 |
*
|
149 |
* @since 3.1.0
|
150 |
-
* @since 3.2.2
|
151 |
-
*
|
152 |
* @since 4.0.0 Added term meta item checks.
|
|
|
|
|
153 |
* @see $this->get_open_graph_description()
|
154 |
* @see $this->get_open_graph_description_from_custom_field()
|
155 |
*
|
156 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
157 |
* @return string Open Graph description.
|
158 |
*/
|
159 |
-
protected function get_custom_open_graph_description_from_args(
|
160 |
|
161 |
$desc = '';
|
162 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
163 |
if ( $args['taxonomy'] ) {
|
164 |
$desc = $this->get_term_meta_item( 'og_description', $args['id'] )
|
165 |
-
?: $this->get_description_from_custom_field( $args );
|
|
|
|
|
|
|
166 |
} else {
|
167 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
168 |
$desc = $this->get_option( 'homepage_og_description' )
|
169 |
?: $this->get_post_meta_item( '_open_graph_description', $args['id'] )
|
170 |
-
?: $this->get_description_from_custom_field( $args );
|
171 |
} elseif ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
172 |
$desc = $this->get_option( 'homepage_og_description' )
|
173 |
-
?: $this->get_description_from_custom_field( $args );
|
174 |
} else {
|
175 |
$desc = $this->get_post_meta_item( '_open_graph_description', $args['id'] )
|
176 |
-
?: $this->get_description_from_custom_field( $args );
|
177 |
}
|
178 |
}
|
179 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
180 |
|
181 |
return $desc;
|
182 |
}
|
@@ -186,22 +190,21 @@ class Generate_Description extends Generate {
|
|
186 |
* Falls back to Open Graph description.
|
187 |
*
|
188 |
* @since 3.0.4
|
189 |
-
* @since 3.1.0
|
190 |
-
*
|
|
|
191 |
* @uses $this->get_twitter_description_from_custom_field()
|
192 |
* @uses $this->get_generated_twitter_description()
|
193 |
*
|
194 |
-
* @param array|null $args
|
195 |
-
*
|
196 |
* @param bool $escape Whether to escape the description.
|
197 |
* @return string The real Twitter description output.
|
198 |
*/
|
199 |
public function get_twitter_description( $args = null, $escape = true ) {
|
200 |
|
201 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
202 |
$desc = $this->get_twitter_description_from_custom_field( $args, false )
|
203 |
?: $this->get_generated_twitter_description( $args, false );
|
204 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
205 |
|
206 |
return $escape ? $this->escape_description( $desc ) : $desc;
|
207 |
}
|
@@ -213,7 +216,7 @@ class Generate_Description extends Generate {
|
|
213 |
* @since 3.1.0
|
214 |
* @see $this->get_twitter_description()
|
215 |
*
|
216 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
217 |
* Leave null to autodetermine query.
|
218 |
* @param bool $escape Whether to escape the title.
|
219 |
* @return string Twitter description.
|
@@ -235,9 +238,11 @@ class Generate_Description extends Generate {
|
|
235 |
* Falls back to Open Graph description.
|
236 |
*
|
237 |
* @since 3.1.0
|
238 |
-
* @since 3.2.2
|
239 |
-
*
|
240 |
* @since 4.0.0 Added term meta item checks.
|
|
|
|
|
241 |
* @see $this->get_twitter_description()
|
242 |
* @see $this->get_twitter_description_from_custom_field()
|
243 |
*
|
@@ -246,33 +251,36 @@ class Generate_Description extends Generate {
|
|
246 |
protected function get_custom_twitter_description_from_query() {
|
247 |
|
248 |
$desc = '';
|
249 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
250 |
if ( $this->is_real_front_page() ) {
|
251 |
if ( $this->is_static_frontpage() ) {
|
252 |
$desc = $this->get_option( 'homepage_twitter_description' )
|
253 |
?: $this->get_post_meta_item( '_twitter_description' )
|
254 |
?: $this->get_option( 'homepage_og_description' )
|
255 |
?: $this->get_post_meta_item( '_open_graph_description' )
|
256 |
-
?: $this->get_description_from_custom_field()
|
257 |
?: '';
|
258 |
} else {
|
259 |
$desc = $this->get_option( 'homepage_twitter_description' )
|
260 |
?: $this->get_option( 'homepage_og_description' )
|
261 |
-
?: $this->get_description_from_custom_field()
|
262 |
?: '';
|
263 |
}
|
264 |
} elseif ( $this->is_singular() ) {
|
265 |
$desc = $this->get_post_meta_item( '_twitter_description' )
|
266 |
?: $this->get_post_meta_item( '_open_graph_description' )
|
267 |
-
?: $this->get_description_from_custom_field()
|
268 |
?: '';
|
269 |
} elseif ( $this->is_term_meta_capable() ) {
|
270 |
$desc = $this->get_term_meta_item( 'tw_description' )
|
271 |
?: $this->get_term_meta_item( 'og_description' )
|
272 |
-
?: $this->get_description_from_custom_field()
|
|
|
|
|
|
|
|
|
|
|
273 |
?: '';
|
274 |
}
|
275 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
276 |
|
277 |
return $desc;
|
278 |
}
|
@@ -282,22 +290,28 @@ class Generate_Description extends Generate {
|
|
282 |
* Falls back to Open Graph description.
|
283 |
*
|
284 |
* @since 3.1.0
|
285 |
-
* @since 3.2.2
|
286 |
-
*
|
287 |
* @since 4.0.0 Added term meta item checks.
|
|
|
|
|
288 |
* @see $this->get_twitter_description()
|
289 |
* @see $this->get_twitter_description_from_custom_field()
|
290 |
*
|
291 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
292 |
* @return string Twitter description.
|
293 |
*/
|
294 |
-
protected function get_custom_twitter_description_from_args(
|
295 |
|
296 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
297 |
if ( $args['taxonomy'] ) {
|
298 |
$desc = $this->get_term_meta_item( 'tw_description', $args['id'] )
|
299 |
?: $this->get_term_meta_item( 'og_description', $args['id'] )
|
300 |
-
?: $this->get_description_from_custom_field( $args )
|
|
|
|
|
|
|
|
|
|
|
301 |
?: '';
|
302 |
} else {
|
303 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
@@ -305,21 +319,20 @@ class Generate_Description extends Generate {
|
|
305 |
?: $this->get_post_meta_item( '_twitter_description', $args['id'] )
|
306 |
?: $this->get_option( 'homepage_og_description' )
|
307 |
?: $this->get_post_meta_item( '_open_graph_description', $args['id'] )
|
308 |
-
?: $this->get_description_from_custom_field( $args )
|
309 |
?: '';
|
310 |
} elseif ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
311 |
$desc = $this->get_option( 'homepage_twitter_description' )
|
312 |
?: $this->get_option( 'homepage_og_description' )
|
313 |
-
?: $this->get_description_from_custom_field( $args )
|
314 |
?: '';
|
315 |
} else {
|
316 |
$desc = $this->get_post_meta_item( '_twitter_description', $args['id'] )
|
317 |
?: $this->get_post_meta_item( '_open_graph_description', $args['id'] )
|
318 |
-
?: $this->get_description_from_custom_field( $args )
|
319 |
?: '';
|
320 |
}
|
321 |
}
|
322 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
323 |
|
324 |
return $desc;
|
325 |
}
|
@@ -329,9 +342,10 @@ class Generate_Description extends Generate {
|
|
329 |
*
|
330 |
* @since 3.0.6
|
331 |
* @since 3.1.0 The first argument now accepts an array, with "id" and "taxonomy" fields.
|
|
|
332 |
*
|
333 |
-
* @param array|null $args
|
334 |
-
*
|
335 |
* @param bool $escape Whether to escape the description.
|
336 |
* @return string The custom field description.
|
337 |
*/
|
@@ -339,12 +353,6 @@ class Generate_Description extends Generate {
|
|
339 |
|
340 |
if ( null === $args ) {
|
341 |
$desc = $this->get_custom_description_from_query();
|
342 |
-
|
343 |
-
// Generated as backward compat for the filter...
|
344 |
-
$args = [
|
345 |
-
'id' => $this->get_the_real_ID(),
|
346 |
-
'taxonomy' => $this->get_current_taxonomy(),
|
347 |
-
];
|
348 |
} else {
|
349 |
$this->fix_generation_args( $args );
|
350 |
$desc = $this->get_custom_description_from_args( $args );
|
@@ -354,11 +362,19 @@ class Generate_Description extends Generate {
|
|
354 |
* @since 2.9.0
|
355 |
* @since 3.0.6 1. Duplicated from $this->generate_description() (deprecated)
|
356 |
* 2. Removed all arguments but the 'id' argument.
|
|
|
|
|
357 |
* @param string $desc The custom-field description.
|
358 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
359 |
* Is null when query is autodetermined.
|
360 |
*/
|
361 |
-
$desc = (string) \
|
|
|
|
|
|
|
|
|
|
|
|
|
362 |
|
363 |
return $escape ? $this->escape_description( $desc ) : $desc;
|
364 |
}
|
@@ -368,6 +384,7 @@ class Generate_Description extends Generate {
|
|
368 |
*
|
369 |
* @since 3.1.0
|
370 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
|
|
371 |
* @internal
|
372 |
* @see $this->get_description_from_custom_field()
|
373 |
*
|
@@ -377,7 +394,6 @@ class Generate_Description extends Generate {
|
|
377 |
|
378 |
$desc = '';
|
379 |
|
380 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
381 |
if ( $this->is_real_front_page() ) {
|
382 |
if ( $this->is_static_frontpage() ) {
|
383 |
$desc = $this->get_option( 'homepage_description' )
|
@@ -393,11 +409,16 @@ class Generate_Description extends Generate {
|
|
393 |
} elseif ( \is_post_type_archive() ) {
|
394 |
/**
|
395 |
* @since 4.0.6
|
|
|
|
|
396 |
* @param string $desc The post type archive description.
|
397 |
*/
|
398 |
-
$desc = (string) \
|
|
|
|
|
|
|
|
|
399 |
}
|
400 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
401 |
|
402 |
return $desc;
|
403 |
}
|
@@ -407,17 +428,19 @@ class Generate_Description extends Generate {
|
|
407 |
*
|
408 |
* @since 3.1.0
|
409 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
|
|
410 |
* @internal
|
411 |
* @see $this->get_description_from_custom_field()
|
412 |
*
|
413 |
* @param array $args Array of 'id' and 'taxonomy' values.
|
414 |
* @return string The custom description.
|
415 |
*/
|
416 |
-
protected function get_custom_description_from_args(
|
417 |
|
418 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
419 |
if ( $args['taxonomy'] ) {
|
420 |
$desc = $this->get_term_meta_item( 'description', $args['id'] ) ?: '';
|
|
|
|
|
421 |
} else {
|
422 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
423 |
$desc = $this->get_option( 'homepage_description' )
|
@@ -429,7 +452,6 @@ class Generate_Description extends Generate {
|
|
429 |
$desc = $this->get_post_meta_item( '_genesis_description', $args['id'] ) ?: '';
|
430 |
}
|
431 |
}
|
432 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
433 |
|
434 |
return $desc;
|
435 |
}
|
@@ -445,10 +467,14 @@ class Generate_Description extends Generate {
|
|
445 |
* @since 3.1.2 1. Now omits additions when the description will be deemed too short.
|
446 |
* 2. Now no longer converts additions into excerpt when no excerpt is found.
|
447 |
* @since 3.2.2 Now converts HTML characters prior trimming.
|
|
|
448 |
* @uses $this->generate_description()
|
|
|
|
|
|
|
449 |
*
|
450 |
-
* @param array|null $args
|
451 |
-
*
|
452 |
* @param bool $escape Whether to escape the description.
|
453 |
* @param string $type Type of description. Accepts 'search', 'opengraph', 'twitter'.
|
454 |
* @return string The generated description output.
|
@@ -472,18 +498,24 @@ class Generate_Description extends Generate {
|
|
472 |
* @since 3.1.0 No longer passes 3rd and 4th parameter.
|
473 |
* @since 4.0.0 1. Deprecated second parameter.
|
474 |
* 2. Added third parameter: $args.
|
|
|
475 |
* @param string $excerpt The excerpt to use.
|
476 |
* @param int $page_id Deprecated.
|
477 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
478 |
* Is null when query is autodetermined.
|
479 |
*/
|
480 |
-
$excerpt = (string) \
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
481 |
|
482 |
-
// TODO Should we enforce a minimum description length, where this result is ignored?
|
483 |
-
// e.g. use the input guidelines 'lower' value as a minimum, so that TSF won't ever generate "bad" descriptions?
|
484 |
// This page has a generated description that's far too short: https://theseoframework.com/em-changelog/1-0-0-amplified-seo/.
|
485 |
// A direct directory-'site:' query will accept the description outputted--anything else will ignore it...
|
486 |
-
// We should
|
487 |
$excerpt = $this->trim_excerpt(
|
488 |
$excerpt,
|
489 |
0,
|
@@ -493,11 +525,18 @@ class Generate_Description extends Generate {
|
|
493 |
/**
|
494 |
* @since 2.9.0
|
495 |
* @since 3.1.0 No longer passes 3rd and 4th parameter.
|
|
|
496 |
* @param string $desc The generated description.
|
497 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
498 |
* Is null when query is autodetermined.
|
499 |
*/
|
500 |
-
$desc = (string) \
|
|
|
|
|
|
|
|
|
|
|
|
|
501 |
|
502 |
return $escape ? $this->escape_description( $desc ) : $desc;
|
503 |
}
|
@@ -506,9 +545,10 @@ class Generate_Description extends Generate {
|
|
506 |
* Returns the autogenerated Twitter meta description. Falls back to meta description.
|
507 |
*
|
508 |
* @since 3.0.4
|
|
|
509 |
*
|
510 |
-
* @param array|null $args
|
511 |
-
*
|
512 |
* @param bool $escape Whether to escape the description.
|
513 |
* @return string The generated Twitter description output.
|
514 |
*/
|
@@ -520,10 +560,11 @@ class Generate_Description extends Generate {
|
|
520 |
* Returns the autogenerated Open Graph meta description. Falls back to meta description.
|
521 |
*
|
522 |
* @since 3.0.4
|
|
|
523 |
* @uses $this->generate_description()
|
524 |
*
|
525 |
-
* @param array|null $args
|
526 |
-
*
|
527 |
* @param bool $escape Whether to escape the description.
|
528 |
* @return string The generated Open Graph description output.
|
529 |
*/
|
@@ -535,6 +576,7 @@ class Generate_Description extends Generate {
|
|
535 |
* Returns a description excerpt for the current query.
|
536 |
*
|
537 |
* @since 3.1.0
|
|
|
538 |
*
|
539 |
* @return string
|
540 |
*/
|
@@ -547,14 +589,14 @@ class Generate_Description extends Generate {
|
|
547 |
|
548 |
$excerpt = '';
|
549 |
|
550 |
-
if ( $this->
|
551 |
-
$excerpt = $this->get_blog_page_description_excerpt();
|
552 |
-
} elseif ( $this->is_real_front_page() ) {
|
553 |
$excerpt = $this->get_front_page_description_excerpt();
|
554 |
-
} elseif ( $this->
|
555 |
-
$excerpt = $this->
|
556 |
} elseif ( $this->is_singular() ) {
|
557 |
$excerpt = $this->get_singular_description_excerpt();
|
|
|
|
|
558 |
}
|
559 |
|
560 |
return $excerpt;
|
@@ -565,21 +607,24 @@ class Generate_Description extends Generate {
|
|
565 |
*
|
566 |
* @since 3.1.0
|
567 |
* @since 3.2.2 Fixed front-page as blog logic.
|
|
|
568 |
*
|
569 |
-
* @param array
|
570 |
* @return string
|
571 |
*/
|
572 |
-
protected function get_description_excerpt_from_args(
|
573 |
|
574 |
$excerpt = '';
|
575 |
|
576 |
if ( $args['taxonomy'] ) {
|
577 |
$excerpt = $this->get_archival_description_excerpt( \get_term( $args['id'], $args['taxonomy'] ) );
|
|
|
|
|
578 |
} else {
|
579 |
-
if ( $this->
|
580 |
-
$excerpt = $this->get_blog_page_description_excerpt();
|
581 |
-
} elseif ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
582 |
$excerpt = $this->get_front_page_description_excerpt();
|
|
|
|
|
583 |
} else {
|
584 |
$excerpt = $this->get_singular_description_excerpt( $args['id'] );
|
585 |
}
|
@@ -596,10 +641,7 @@ class Generate_Description extends Generate {
|
|
596 |
* @return string
|
597 |
*/
|
598 |
protected function get_blog_page_description_excerpt() {
|
599 |
-
return $this->get_description_additions( [
|
600 |
-
'id' => (int) \get_option( 'page_for_posts' ),
|
601 |
-
'taxonomy' => '',
|
602 |
-
] );
|
603 |
}
|
604 |
|
605 |
/**
|
@@ -613,14 +655,8 @@ class Generate_Description extends Generate {
|
|
613 |
|
614 |
$id = $this->get_the_front_page_ID();
|
615 |
|
616 |
-
$excerpt = ''
|
617 |
-
|
618 |
-
$excerpt = $this->get_singular_description_excerpt( $id );
|
619 |
-
}
|
620 |
-
$excerpt = $excerpt ?: $this->get_description_additions( [
|
621 |
-
'id' => $id,
|
622 |
-
'taxonomy' => '',
|
623 |
-
] );
|
624 |
|
625 |
return $excerpt;
|
626 |
}
|
@@ -630,29 +666,37 @@ class Generate_Description extends Generate {
|
|
630 |
*
|
631 |
* @since 3.1.0
|
632 |
* @since 4.0.0 Now processes HTML tags via s_excerpt_raw() for the author descriptions.
|
|
|
|
|
633 |
*
|
634 |
-
* @param null|\WP_Term $
|
635 |
* @return string
|
636 |
*/
|
637 |
-
protected function get_archival_description_excerpt( $
|
638 |
|
639 |
-
if ( $
|
640 |
return '';
|
641 |
|
642 |
-
if ( \is_null( $
|
643 |
$in_the_loop = true;
|
644 |
-
$
|
645 |
} else {
|
646 |
$in_the_loop = false;
|
647 |
}
|
648 |
|
649 |
/**
|
650 |
* @since 3.1.0
|
651 |
-
* @see `\
|
652 |
-
* @param string
|
653 |
-
* @param \WP_Term $
|
654 |
*/
|
655 |
-
$excerpt = (string) \
|
|
|
|
|
|
|
|
|
|
|
|
|
656 |
|
657 |
if ( $excerpt ) return $excerpt;
|
658 |
|
@@ -662,29 +706,40 @@ class Generate_Description extends Generate {
|
|
662 |
if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
|
663 |
// WordPress DOES NOT allow HTML in term descriptions, not even if you're a super-administrator.
|
664 |
// See https://wpvulndb.com/vulnerabilities/9445. We won't parse HTMl tags unless WordPress adds native support.
|
665 |
-
$excerpt =
|
666 |
} elseif ( $this->is_author() ) {
|
667 |
$excerpt = $this->s_excerpt_raw( \get_the_author_meta( 'description', (int) \get_query_var( 'author' ) ) );
|
668 |
} elseif ( \is_post_type_archive() ) {
|
669 |
/**
|
670 |
-
* @TODO can we even obtain anything useful ourselves?
|
671 |
-
*
|
672 |
* @since 4.0.6
|
|
|
673 |
* @param string $excerpt The archive description excerpt.
|
674 |
-
* @param
|
675 |
*/
|
676 |
-
$excerpt = (string) \
|
|
|
|
|
|
|
|
|
|
|
|
|
677 |
} else {
|
678 |
/**
|
679 |
* @since 4.0.6
|
680 |
-
* @since 4.1.0 Added the $
|
681 |
* @param string $excerpt The fallback archive description excerpt.
|
682 |
-
* @param \WP_Term $
|
683 |
*/
|
684 |
-
$excerpt = (string) \
|
|
|
|
|
|
|
|
|
|
|
|
|
685 |
}
|
686 |
} else {
|
687 |
-
$excerpt =
|
688 |
}
|
689 |
|
690 |
return $excerpt;
|
@@ -700,8 +755,7 @@ class Generate_Description extends Generate {
|
|
700 |
*/
|
701 |
protected function get_singular_description_excerpt( $id = null ) {
|
702 |
|
703 |
-
|
704 |
-
$id = $this->get_the_real_ID();
|
705 |
|
706 |
// If the post is protected, don't generate a description.
|
707 |
if ( $this->is_protected( $id ) ) return '';
|
@@ -713,36 +767,29 @@ class Generate_Description extends Generate {
|
|
713 |
* Returns additions for "Title on Site Title".
|
714 |
*
|
715 |
* @since 3.1.0
|
716 |
-
* @since 3.2.0
|
717 |
-
*
|
718 |
* @since 3.2.2 Now works for homepages from external requests.
|
|
|
719 |
* @see $this->get_generated_description()
|
720 |
*
|
721 |
-
* @param array
|
722 |
-
*
|
723 |
-
* @param bool $forced Whether to force the additions, bypassing options and filters.
|
724 |
* @return string The description additions.
|
725 |
*/
|
726 |
-
protected function get_description_additions( $args
|
727 |
|
728 |
-
$this->
|
729 |
-
|
730 |
-
if ( $this->is_blog_page_by_id( $args['id'] ) ) {
|
731 |
-
$title = $this->get_filtered_raw_generated_title( $args );
|
732 |
-
/* translators: %s = Blog page title. Front-end output. */
|
733 |
-
$title = sprintf( \__( 'Latest posts: %s', 'autodescription' ), $title );
|
734 |
-
} elseif ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
735 |
$title = $this->get_home_title_additions();
|
|
|
|
|
|
|
|
|
|
|
|
|
736 |
}
|
737 |
|
738 |
-
|
739 |
-
return '';
|
740 |
-
|
741 |
-
$on = \_x( 'on', 'Placement. e.g. Post Title "on" Site Title', 'autodescription' );
|
742 |
-
$blogname = $this->get_blogname();
|
743 |
-
|
744 |
-
/* translators: 1: Title, 2: on, 3: Site Title */
|
745 |
-
return trim( sprintf( \_x( '%1$s %2$s %3$s', 'blog page description', 'autodescription' ), $title, $on, $blogname ) );
|
746 |
}
|
747 |
|
748 |
/**
|
@@ -750,8 +797,8 @@ class Generate_Description extends Generate {
|
|
750 |
*
|
751 |
* @since 1.0.0
|
752 |
* @since 2.8.2 Added 4th parameter for escaping.
|
753 |
-
* @since 3.1.0
|
754 |
-
*
|
755 |
* @since 4.0.1 The second parameter `$id` now defaults to int 0, instead of an empty string.
|
756 |
*
|
757 |
* @param string $excerpt The Excerpt.
|
@@ -818,33 +865,34 @@ class Generate_Description extends Generate {
|
|
818 |
* Warning: Returns with entities encoded. The output is not safe for printing.
|
819 |
*
|
820 |
* @since 2.6.0
|
821 |
-
* @since 3.1.0
|
822 |
-
*
|
823 |
-
*
|
824 |
-
*
|
825 |
-
*
|
826 |
-
* @since 4.0.0
|
827 |
-
*
|
828 |
-
*
|
829 |
-
* @since 4.0.5
|
830 |
-
*
|
831 |
-
* @since 4.1.0
|
832 |
-
*
|
833 |
-
*
|
834 |
-
*
|
835 |
-
*
|
836 |
-
*
|
837 |
-
*
|
838 |
-
*
|
839 |
-
*
|
840 |
-
*
|
841 |
-
*
|
842 |
-
*
|
843 |
-
* @since 4.1.5
|
844 |
-
*
|
845 |
-
*
|
846 |
-
*
|
847 |
-
*
|
|
|
848 |
* @see https://secure.php.net/manual/en/regexp.reference.unicode.php
|
849 |
*
|
850 |
* We use `[^\P{Po}\'\"]` because WordPress texturizes ' and " to fall under `\P{Po}`.
|
@@ -858,6 +906,9 @@ class Generate_Description extends Generate {
|
|
858 |
*/
|
859 |
public function trim_excerpt( $excerpt, $min_char_length = 1, $max_char_length = 4096 ) {
|
860 |
|
|
|
|
|
|
|
861 |
// We should _actually_ use mb_strlen, but that's wasteful on resources for something benign.
|
862 |
// We'll rectify that later, somewhat, where characters are transformed.
|
863 |
// We could also use preg_match_all( '/./u' ); or count( preg_split( '/./u', $excerpt, $min_char_length ) );
|
@@ -869,7 +920,7 @@ class Generate_Description extends Generate {
|
|
869 |
|
870 |
// Find all words with $max_char_length, and trim when the last word boundary or punctuation is found.
|
871 |
preg_match( sprintf( '/.{0,%d}([^\P{Po}\'\":]|[\p{Pc}\p{Pd}\p{Pf}\p{Z}]|\Z){1}/su', $max_char_length ), trim( $excerpt ), $matches );
|
872 |
-
$excerpt =
|
873 |
|
874 |
$excerpt = trim( $excerpt );
|
875 |
|
@@ -909,12 +960,12 @@ class Generate_Description extends Generate {
|
|
909 |
);
|
910 |
|
911 |
if ( isset( $matches[5] ) ) {
|
912 |
-
$excerpt = $matches[1]
|
913 |
// Skip 4. It's useless content without 5.
|
914 |
} elseif ( isset( $matches[3] ) ) {
|
915 |
-
$excerpt = $matches[1]
|
916 |
} elseif ( isset( $matches[2] ) ) {
|
917 |
-
$excerpt = $matches[1]
|
918 |
} elseif ( isset( $matches[1] ) ) {
|
919 |
$excerpt = $matches[1];
|
920 |
}
|
@@ -935,10 +986,10 @@ class Generate_Description extends Generate {
|
|
935 |
);
|
936 |
// Why can $matches[2] still be populated with 3 set? Does it populate empty results upward to last, always???
|
937 |
if ( isset( $matches[2] ) && \strlen( $matches[2] ) ) {
|
938 |
-
$excerpt = $matches[1]
|
939 |
} elseif ( isset( $matches[1] ) && \strlen( $matches[1] ) ) {
|
940 |
// Ignore useless [3], there's no [2], [1] is open-ended; so, add hellip.
|
941 |
-
$excerpt = $matches[1]
|
942 |
} else {
|
943 |
// If there's no matches[1], only some form of non-closing-leading punctuation was left in $excerpt. Empty it.
|
944 |
$excerpt = '';
|
@@ -953,29 +1004,28 @@ class Generate_Description extends Generate {
|
|
953 |
* Determines whether automated descriptions are enabled.
|
954 |
*
|
955 |
* @since 3.1.0
|
|
|
|
|
956 |
* @access private
|
957 |
* @see $this->get_the_real_ID()
|
958 |
* @see $this->get_current_taxonomy()
|
959 |
*
|
960 |
-
* @param array|null $args
|
961 |
-
*
|
962 |
* @return bool
|
963 |
*/
|
964 |
-
public function is_auto_description_enabled( $args ) {
|
965 |
|
966 |
-
if (
|
967 |
-
$args
|
968 |
-
'id' => $this->get_the_real_ID(),
|
969 |
-
'taxonomy' => $this->get_current_taxonomy(),
|
970 |
-
];
|
971 |
-
}
|
972 |
|
973 |
/**
|
974 |
* @since 2.5.0
|
975 |
* @since 3.0.0 Now passes $args as the second parameter.
|
976 |
* @since 3.1.0 Now listens to option.
|
|
|
977 |
* @param bool $autodescription Enable or disable the automated descriptions.
|
978 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
979 |
* Is null when query is autodetermined.
|
980 |
*/
|
981 |
return (bool) \apply_filters_ref_array(
|
39 |
*
|
40 |
* @since 3.0.6
|
41 |
* @since 3.1.0 The first argument now accepts an array, with "id" and "taxonomy" fields.
|
42 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
43 |
* @uses $this->get_description_from_custom_field()
|
44 |
* @uses $this->get_generated_description()
|
45 |
*
|
46 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
47 |
+
* Leave null to autodetermine query.
|
48 |
* @param bool $escape Whether to escape the description.
|
49 |
* @return string The real description output.
|
50 |
*/
|
51 |
public function get_description( $args = null, $escape = true ) {
|
52 |
|
|
|
53 |
$desc = $this->get_description_from_custom_field( $args, false )
|
54 |
?: $this->get_generated_description( $args, false );
|
|
|
55 |
|
56 |
return $escape ? $this->escape_description( $desc ) : $desc;
|
57 |
}
|
60 |
* Returns the Open Graph meta description. Falls back to meta description.
|
61 |
*
|
62 |
* @since 3.0.4
|
63 |
+
* @since 3.1.0 1. Now tries to get the homepage social descriptions.
|
64 |
+
* 2. The first argument now accepts an array, with "id" and "taxonomy" fields.
|
65 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
66 |
* @uses $this->get_open_graph_description_from_custom_field()
|
67 |
* @uses $this->get_generated_open_graph_description()
|
68 |
*
|
69 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
70 |
+
* Leave null to autodetermine query.
|
71 |
* @param bool $escape Whether to escape the description.
|
72 |
* @return string The real Open Graph description output.
|
73 |
*/
|
74 |
public function get_open_graph_description( $args = null, $escape = true ) {
|
75 |
|
|
|
76 |
$desc = $this->get_open_graph_description_from_custom_field( $args, false )
|
77 |
?: $this->get_generated_open_graph_description( $args, false );
|
|
|
78 |
|
79 |
return $escape ? $this->escape_description( $desc ) : $desc;
|
80 |
}
|
86 |
* @since 3.1.0
|
87 |
* @see $this->get_open_graph_description()
|
88 |
*
|
89 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
90 |
* Leave null to autodetermine query.
|
91 |
* @param bool $escape Whether to escape the title.
|
92 |
* @return string TwOpen Graphitter description.
|
110 |
* @since 3.1.0
|
111 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
112 |
* @since 4.0.0 Added term meta item checks.
|
113 |
+
* @since 4.2.0 1. No longer returns an escaped custom field description.
|
114 |
+
* 2. Now returns custom descriptions for post type archives.
|
115 |
* @see $this->get_open_graph_description()
|
116 |
* @see $this->get_open_graph_description_from_custom_field()
|
117 |
*
|
120 |
protected function get_custom_open_graph_description_from_query() {
|
121 |
|
122 |
$desc = '';
|
|
|
123 |
if ( $this->is_real_front_page() ) {
|
124 |
if ( $this->is_static_frontpage() ) {
|
125 |
$desc = $this->get_option( 'homepage_og_description' )
|
126 |
?: $this->get_post_meta_item( '_open_graph_description' )
|
127 |
+
?: $this->get_description_from_custom_field( null, false );
|
128 |
} else {
|
129 |
$desc = $this->get_option( 'homepage_og_description' )
|
130 |
+
?: $this->get_description_from_custom_field( null, false );
|
131 |
}
|
132 |
} elseif ( $this->is_singular() ) {
|
133 |
$desc = $this->get_post_meta_item( '_open_graph_description' )
|
134 |
+
?: $this->get_description_from_custom_field( null, false );
|
135 |
} elseif ( $this->is_term_meta_capable() ) {
|
136 |
$desc = $this->get_term_meta_item( 'og_description' )
|
137 |
+
?: $this->get_description_from_custom_field( null, false );
|
138 |
+
} elseif ( \is_post_type_archive() ) {
|
139 |
+
$desc = $this->get_post_type_archive_meta_item( 'og_description' )
|
140 |
+
?: $this->get_description_from_custom_field( null, false );
|
141 |
}
|
|
|
142 |
|
143 |
return $desc;
|
144 |
}
|
148 |
* Falls back to meta description.
|
149 |
*
|
150 |
* @since 3.1.0
|
151 |
+
* @since 3.2.2 1. Now tests for the homepage as page prior getting custom field data.
|
152 |
+
* 2. Now obtains custom field data for terms.
|
153 |
* @since 4.0.0 Added term meta item checks.
|
154 |
+
* @since 4.2.0 1. No longer returns an escaped custom field description.
|
155 |
+
* 2. Now supports the `$args['pta']` index.
|
156 |
* @see $this->get_open_graph_description()
|
157 |
* @see $this->get_open_graph_description_from_custom_field()
|
158 |
*
|
159 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
160 |
* @return string Open Graph description.
|
161 |
*/
|
162 |
+
protected function get_custom_open_graph_description_from_args( $args ) {
|
163 |
|
164 |
$desc = '';
|
|
|
165 |
if ( $args['taxonomy'] ) {
|
166 |
$desc = $this->get_term_meta_item( 'og_description', $args['id'] )
|
167 |
+
?: $this->get_description_from_custom_field( $args, false );
|
168 |
+
} elseif ( $args['pta'] ) {
|
169 |
+
$desc = $this->get_post_type_archive_meta_item( 'og_description', $args['pta'] )
|
170 |
+
?: $this->get_description_from_custom_field( $args, false );
|
171 |
} else {
|
172 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
173 |
$desc = $this->get_option( 'homepage_og_description' )
|
174 |
?: $this->get_post_meta_item( '_open_graph_description', $args['id'] )
|
175 |
+
?: $this->get_description_from_custom_field( $args, false );
|
176 |
} elseif ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
177 |
$desc = $this->get_option( 'homepage_og_description' )
|
178 |
+
?: $this->get_description_from_custom_field( $args, false );
|
179 |
} else {
|
180 |
$desc = $this->get_post_meta_item( '_open_graph_description', $args['id'] )
|
181 |
+
?: $this->get_description_from_custom_field( $args, false );
|
182 |
}
|
183 |
}
|
|
|
184 |
|
185 |
return $desc;
|
186 |
}
|
190 |
* Falls back to Open Graph description.
|
191 |
*
|
192 |
* @since 3.0.4
|
193 |
+
* @since 3.1.0 1. Now tries to get the homepage social descriptions.
|
194 |
+
* 2. The first argument now accepts an array, with "id" and "taxonomy" fields.
|
195 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
196 |
* @uses $this->get_twitter_description_from_custom_field()
|
197 |
* @uses $this->get_generated_twitter_description()
|
198 |
*
|
199 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
200 |
+
* Leave null to autodetermine query.
|
201 |
* @param bool $escape Whether to escape the description.
|
202 |
* @return string The real Twitter description output.
|
203 |
*/
|
204 |
public function get_twitter_description( $args = null, $escape = true ) {
|
205 |
|
|
|
206 |
$desc = $this->get_twitter_description_from_custom_field( $args, false )
|
207 |
?: $this->get_generated_twitter_description( $args, false );
|
|
|
208 |
|
209 |
return $escape ? $this->escape_description( $desc ) : $desc;
|
210 |
}
|
216 |
* @since 3.1.0
|
217 |
* @see $this->get_twitter_description()
|
218 |
*
|
219 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
220 |
* Leave null to autodetermine query.
|
221 |
* @param bool $escape Whether to escape the title.
|
222 |
* @return string Twitter description.
|
238 |
* Falls back to Open Graph description.
|
239 |
*
|
240 |
* @since 3.1.0
|
241 |
+
* @since 3.2.2 1. Now tests for the homepage as page prior getting custom field data.
|
242 |
+
* 2. Now obtains custom field data for terms.
|
243 |
* @since 4.0.0 Added term meta item checks.
|
244 |
+
* @since 4.2.0 1. No longer returns an escaped custom field description.
|
245 |
+
* 2. Now returns custom descriptions for post type archives.
|
246 |
* @see $this->get_twitter_description()
|
247 |
* @see $this->get_twitter_description_from_custom_field()
|
248 |
*
|
251 |
protected function get_custom_twitter_description_from_query() {
|
252 |
|
253 |
$desc = '';
|
|
|
254 |
if ( $this->is_real_front_page() ) {
|
255 |
if ( $this->is_static_frontpage() ) {
|
256 |
$desc = $this->get_option( 'homepage_twitter_description' )
|
257 |
?: $this->get_post_meta_item( '_twitter_description' )
|
258 |
?: $this->get_option( 'homepage_og_description' )
|
259 |
?: $this->get_post_meta_item( '_open_graph_description' )
|
260 |
+
?: $this->get_description_from_custom_field( null, false )
|
261 |
?: '';
|
262 |
} else {
|
263 |
$desc = $this->get_option( 'homepage_twitter_description' )
|
264 |
?: $this->get_option( 'homepage_og_description' )
|
265 |
+
?: $this->get_description_from_custom_field( null, false )
|
266 |
?: '';
|
267 |
}
|
268 |
} elseif ( $this->is_singular() ) {
|
269 |
$desc = $this->get_post_meta_item( '_twitter_description' )
|
270 |
?: $this->get_post_meta_item( '_open_graph_description' )
|
271 |
+
?: $this->get_description_from_custom_field( null, false )
|
272 |
?: '';
|
273 |
} elseif ( $this->is_term_meta_capable() ) {
|
274 |
$desc = $this->get_term_meta_item( 'tw_description' )
|
275 |
?: $this->get_term_meta_item( 'og_description' )
|
276 |
+
?: $this->get_description_from_custom_field( null, false )
|
277 |
+
?: '';
|
278 |
+
} elseif ( \is_post_type_archive() ) {
|
279 |
+
$desc = $this->get_post_type_archive_meta_item( 'tw_description' )
|
280 |
+
?: $this->get_post_type_archive_meta_item( 'og_description' )
|
281 |
+
?: $this->get_description_from_custom_field( null, false )
|
282 |
?: '';
|
283 |
}
|
|
|
284 |
|
285 |
return $desc;
|
286 |
}
|
290 |
* Falls back to Open Graph description.
|
291 |
*
|
292 |
* @since 3.1.0
|
293 |
+
* @since 3.2.2 1. Now tests for the homepage as page prior getting custom field data.
|
294 |
+
* 2. Now obtains custom field data for terms.
|
295 |
* @since 4.0.0 Added term meta item checks.
|
296 |
+
* @since 4.2.0 1. No longer returns an escaped custom field description.
|
297 |
+
* 2. Now supports the `$args['pta']` index.
|
298 |
* @see $this->get_twitter_description()
|
299 |
* @see $this->get_twitter_description_from_custom_field()
|
300 |
*
|
301 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
302 |
* @return string Twitter description.
|
303 |
*/
|
304 |
+
protected function get_custom_twitter_description_from_args( $args ) {
|
305 |
|
|
|
306 |
if ( $args['taxonomy'] ) {
|
307 |
$desc = $this->get_term_meta_item( 'tw_description', $args['id'] )
|
308 |
?: $this->get_term_meta_item( 'og_description', $args['id'] )
|
309 |
+
?: $this->get_description_from_custom_field( $args, false )
|
310 |
+
?: '';
|
311 |
+
} elseif ( $args['pta'] ) {
|
312 |
+
$desc = $this->get_post_type_archive_meta_item( 'tw_description', $args['pta'] )
|
313 |
+
?: $this->get_post_type_archive_meta_item( 'og_description', $args['pta'] )
|
314 |
+
?: $this->get_description_from_custom_field( $args, false )
|
315 |
?: '';
|
316 |
} else {
|
317 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
319 |
?: $this->get_post_meta_item( '_twitter_description', $args['id'] )
|
320 |
?: $this->get_option( 'homepage_og_description' )
|
321 |
?: $this->get_post_meta_item( '_open_graph_description', $args['id'] )
|
322 |
+
?: $this->get_description_from_custom_field( $args, false )
|
323 |
?: '';
|
324 |
} elseif ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
325 |
$desc = $this->get_option( 'homepage_twitter_description' )
|
326 |
?: $this->get_option( 'homepage_og_description' )
|
327 |
+
?: $this->get_description_from_custom_field( $args, false )
|
328 |
?: '';
|
329 |
} else {
|
330 |
$desc = $this->get_post_meta_item( '_twitter_description', $args['id'] )
|
331 |
?: $this->get_post_meta_item( '_open_graph_description', $args['id'] )
|
332 |
+
?: $this->get_description_from_custom_field( $args, false )
|
333 |
?: '';
|
334 |
}
|
335 |
}
|
|
|
336 |
|
337 |
return $desc;
|
338 |
}
|
342 |
*
|
343 |
* @since 3.0.6
|
344 |
* @since 3.1.0 The first argument now accepts an array, with "id" and "taxonomy" fields.
|
345 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
346 |
*
|
347 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
348 |
+
* Leave null to autodetermine query.
|
349 |
* @param bool $escape Whether to escape the description.
|
350 |
* @return string The custom field description.
|
351 |
*/
|
353 |
|
354 |
if ( null === $args ) {
|
355 |
$desc = $this->get_custom_description_from_query();
|
|
|
|
|
|
|
|
|
|
|
|
|
356 |
} else {
|
357 |
$this->fix_generation_args( $args );
|
358 |
$desc = $this->get_custom_description_from_args( $args );
|
362 |
* @since 2.9.0
|
363 |
* @since 3.0.6 1. Duplicated from $this->generate_description() (deprecated)
|
364 |
* 2. Removed all arguments but the 'id' argument.
|
365 |
+
* @since 4.2.0 1. No longer gets supplied custom query arguments when in the loop.
|
366 |
+
* 2. Now supports the `$args['pta']` index.
|
367 |
* @param string $desc The custom-field description.
|
368 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
369 |
* Is null when query is autodetermined.
|
370 |
*/
|
371 |
+
$desc = (string) \apply_filters_ref_array(
|
372 |
+
'the_seo_framework_custom_field_description',
|
373 |
+
[
|
374 |
+
$desc,
|
375 |
+
$args,
|
376 |
+
]
|
377 |
+
);
|
378 |
|
379 |
return $escape ? $this->escape_description( $desc ) : $desc;
|
380 |
}
|
384 |
*
|
385 |
* @since 3.1.0
|
386 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
387 |
+
* @since 4.2.0 Now returns custom descriptions for post type archives.
|
388 |
* @internal
|
389 |
* @see $this->get_description_from_custom_field()
|
390 |
*
|
394 |
|
395 |
$desc = '';
|
396 |
|
|
|
397 |
if ( $this->is_real_front_page() ) {
|
398 |
if ( $this->is_static_frontpage() ) {
|
399 |
$desc = $this->get_option( 'homepage_description' )
|
409 |
} elseif ( \is_post_type_archive() ) {
|
410 |
/**
|
411 |
* @since 4.0.6
|
412 |
+
* @since 4.2.0 Deprecated.
|
413 |
+
* @deprecated Use options instead.
|
414 |
* @param string $desc The post type archive description.
|
415 |
*/
|
416 |
+
$desc = (string) \apply_filters_deprecated(
|
417 |
+
'the_seo_framework_pta_description',
|
418 |
+
[ $this->get_post_type_archive_meta_item( 'description' ) ?: '' ],
|
419 |
+
'4.2.0 of The SEO Framework'
|
420 |
+
) ?: '';
|
421 |
}
|
|
|
422 |
|
423 |
return $desc;
|
424 |
}
|
428 |
*
|
429 |
* @since 3.1.0
|
430 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
431 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
432 |
* @internal
|
433 |
* @see $this->get_description_from_custom_field()
|
434 |
*
|
435 |
* @param array $args Array of 'id' and 'taxonomy' values.
|
436 |
* @return string The custom description.
|
437 |
*/
|
438 |
+
protected function get_custom_description_from_args( $args ) {
|
439 |
|
|
|
440 |
if ( $args['taxonomy'] ) {
|
441 |
$desc = $this->get_term_meta_item( 'description', $args['id'] ) ?: '';
|
442 |
+
} elseif ( $args['pta'] ) {
|
443 |
+
$desc = $this->get_post_type_archive_meta_item( 'description', $args['pta'] ) ?: '';
|
444 |
} else {
|
445 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
446 |
$desc = $this->get_option( 'homepage_description' )
|
452 |
$desc = $this->get_post_meta_item( '_genesis_description', $args['id'] ) ?: '';
|
453 |
}
|
454 |
}
|
|
|
455 |
|
456 |
return $desc;
|
457 |
}
|
467 |
* @since 3.1.2 1. Now omits additions when the description will be deemed too short.
|
468 |
* 2. Now no longer converts additions into excerpt when no excerpt is found.
|
469 |
* @since 3.2.2 Now converts HTML characters prior trimming.
|
470 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
471 |
* @uses $this->generate_description()
|
472 |
+
* @TODO Should we enforce a minimum description length, where this result is ignored? e.g., use the input
|
473 |
+
* guidelines' 'lower' value as a minimum, so that TSF won't ever generate "bad" descriptions?
|
474 |
+
* This isn't truly helpful, since then search engines can truly fetch whatever with zero guidance.
|
475 |
*
|
476 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
477 |
+
* Leave null to autodetermine query.
|
478 |
* @param bool $escape Whether to escape the description.
|
479 |
* @param string $type Type of description. Accepts 'search', 'opengraph', 'twitter'.
|
480 |
* @return string The generated description output.
|
498 |
* @since 3.1.0 No longer passes 3rd and 4th parameter.
|
499 |
* @since 4.0.0 1. Deprecated second parameter.
|
500 |
* 2. Added third parameter: $args.
|
501 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
502 |
* @param string $excerpt The excerpt to use.
|
503 |
* @param int $page_id Deprecated.
|
504 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
505 |
* Is null when query is autodetermined.
|
506 |
*/
|
507 |
+
$excerpt = (string) \apply_filters_ref_array(
|
508 |
+
'the_seo_framework_fetched_description_excerpt',
|
509 |
+
[
|
510 |
+
$excerpt,
|
511 |
+
0,
|
512 |
+
$args,
|
513 |
+
]
|
514 |
+
);
|
515 |
|
|
|
|
|
516 |
// This page has a generated description that's far too short: https://theseoframework.com/em-changelog/1-0-0-amplified-seo/.
|
517 |
// A direct directory-'site:' query will accept the description outputted--anything else will ignore it...
|
518 |
+
// We should not work around that, because it won't direct in the slightest what to display.
|
519 |
$excerpt = $this->trim_excerpt(
|
520 |
$excerpt,
|
521 |
0,
|
525 |
/**
|
526 |
* @since 2.9.0
|
527 |
* @since 3.1.0 No longer passes 3rd and 4th parameter.
|
528 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
529 |
* @param string $desc The generated description.
|
530 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
531 |
* Is null when query is autodetermined.
|
532 |
*/
|
533 |
+
$desc = (string) \apply_filters_ref_array(
|
534 |
+
'the_seo_framework_generated_description',
|
535 |
+
[
|
536 |
+
$excerpt,
|
537 |
+
$args,
|
538 |
+
]
|
539 |
+
);
|
540 |
|
541 |
return $escape ? $this->escape_description( $desc ) : $desc;
|
542 |
}
|
545 |
* Returns the autogenerated Twitter meta description. Falls back to meta description.
|
546 |
*
|
547 |
* @since 3.0.4
|
548 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
549 |
*
|
550 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
551 |
+
* Leave null to autodetermine query.
|
552 |
* @param bool $escape Whether to escape the description.
|
553 |
* @return string The generated Twitter description output.
|
554 |
*/
|
560 |
* Returns the autogenerated Open Graph meta description. Falls back to meta description.
|
561 |
*
|
562 |
* @since 3.0.4
|
563 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
564 |
* @uses $this->generate_description()
|
565 |
*
|
566 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
567 |
+
* Leave null to autodetermine query.
|
568 |
* @param bool $escape Whether to escape the description.
|
569 |
* @return string The generated Open Graph description output.
|
570 |
*/
|
576 |
* Returns a description excerpt for the current query.
|
577 |
*
|
578 |
* @since 3.1.0
|
579 |
+
* @since 4.2.0 Flipped order of query tests.
|
580 |
*
|
581 |
* @return string
|
582 |
*/
|
589 |
|
590 |
$excerpt = '';
|
591 |
|
592 |
+
if ( $this->is_real_front_page() ) {
|
|
|
|
|
593 |
$excerpt = $this->get_front_page_description_excerpt();
|
594 |
+
} elseif ( $this->is_home_as_page() ) {
|
595 |
+
$excerpt = $this->get_blog_page_description_excerpt();
|
596 |
} elseif ( $this->is_singular() ) {
|
597 |
$excerpt = $this->get_singular_description_excerpt();
|
598 |
+
} elseif ( $this->is_archive() ) {
|
599 |
+
$excerpt = $this->get_archival_description_excerpt();
|
600 |
}
|
601 |
|
602 |
return $excerpt;
|
607 |
*
|
608 |
* @since 3.1.0
|
609 |
* @since 3.2.2 Fixed front-page as blog logic.
|
610 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
611 |
*
|
612 |
+
* @param array $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
613 |
* @return string
|
614 |
*/
|
615 |
+
protected function get_description_excerpt_from_args( $args ) {
|
616 |
|
617 |
$excerpt = '';
|
618 |
|
619 |
if ( $args['taxonomy'] ) {
|
620 |
$excerpt = $this->get_archival_description_excerpt( \get_term( $args['id'], $args['taxonomy'] ) );
|
621 |
+
} elseif ( $args['pta'] ) {
|
622 |
+
$excerpt = $this->get_archival_description_excerpt( \get_post_type_object( $args['pta'] ) );
|
623 |
} else {
|
624 |
+
if ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
|
|
|
|
625 |
$excerpt = $this->get_front_page_description_excerpt();
|
626 |
+
} elseif ( $this->is_home_as_page( $args['id'] ) ) {
|
627 |
+
$excerpt = $this->get_blog_page_description_excerpt();
|
628 |
} else {
|
629 |
$excerpt = $this->get_singular_description_excerpt( $args['id'] );
|
630 |
}
|
641 |
* @return string
|
642 |
*/
|
643 |
protected function get_blog_page_description_excerpt() {
|
644 |
+
return $this->get_description_additions( [ 'id' => (int) \get_option( 'page_for_posts' ) ] );
|
|
|
|
|
|
|
645 |
}
|
646 |
|
647 |
/**
|
655 |
|
656 |
$id = $this->get_the_front_page_ID();
|
657 |
|
658 |
+
$excerpt = ( $id ? $this->get_singular_description_excerpt( $id ) : '' )
|
659 |
+
?: $this->get_description_additions( [ 'id' => $id ] );
|
|
|
|
|
|
|
|
|
|
|
|
|
660 |
|
661 |
return $excerpt;
|
662 |
}
|
666 |
*
|
667 |
* @since 3.1.0
|
668 |
* @since 4.0.0 Now processes HTML tags via s_excerpt_raw() for the author descriptions.
|
669 |
+
* @since 4.2.0 Now uses post type archive descriptions to prefill meta descriptions.
|
670 |
+
* @TODO fixme: why don't we parse filters? -> What did I mean when I wrote this?
|
671 |
*
|
672 |
+
* @param null|\WP_Term|\WP_Post_Type $object The term or post type object.
|
673 |
* @return string
|
674 |
*/
|
675 |
+
protected function get_archival_description_excerpt( $object = null ) {
|
676 |
|
677 |
+
if ( $object && \is_wp_error( $object ) )
|
678 |
return '';
|
679 |
|
680 |
+
if ( \is_null( $object ) ) {
|
681 |
$in_the_loop = true;
|
682 |
+
$object = \get_queried_object();
|
683 |
} else {
|
684 |
$in_the_loop = false;
|
685 |
}
|
686 |
|
687 |
/**
|
688 |
* @since 3.1.0
|
689 |
+
* @see `\tsf()->s_excerpt_raw()` to strip HTML tags neatly.
|
690 |
+
* @param string $excerpt The short circuit excerpt.
|
691 |
+
* @param \WP_Term|\WP_Post_Type $object The Term object or post type object.
|
692 |
*/
|
693 |
+
$excerpt = (string) \apply_filters_ref_array(
|
694 |
+
'the_seo_framework_generated_archive_excerpt',
|
695 |
+
[
|
696 |
+
'',
|
697 |
+
$object,
|
698 |
+
]
|
699 |
+
);
|
700 |
|
701 |
if ( $excerpt ) return $excerpt;
|
702 |
|
706 |
if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
|
707 |
// WordPress DOES NOT allow HTML in term descriptions, not even if you're a super-administrator.
|
708 |
// See https://wpvulndb.com/vulnerabilities/9445. We won't parse HTMl tags unless WordPress adds native support.
|
709 |
+
$excerpt = $this->s_description_raw( $object->description ?? '' );
|
710 |
} elseif ( $this->is_author() ) {
|
711 |
$excerpt = $this->s_excerpt_raw( \get_the_author_meta( 'description', (int) \get_query_var( 'author' ) ) );
|
712 |
} elseif ( \is_post_type_archive() ) {
|
713 |
/**
|
|
|
|
|
714 |
* @since 4.0.6
|
715 |
+
* @since 4.2.0 Now provides the post type object description, if assigned.
|
716 |
* @param string $excerpt The archive description excerpt.
|
717 |
+
* @param \WP_Term|\WP_Post_Type $object The post type object.
|
718 |
*/
|
719 |
+
$excerpt = (string) \apply_filters_ref_array(
|
720 |
+
'the_seo_framework_pta_description_excerpt',
|
721 |
+
[
|
722 |
+
$this->s_description_raw( $object->description ?? '' ),
|
723 |
+
$object,
|
724 |
+
]
|
725 |
+
);
|
726 |
} else {
|
727 |
/**
|
728 |
* @since 4.0.6
|
729 |
+
* @since 4.1.0 Added the $object object parameter.
|
730 |
* @param string $excerpt The fallback archive description excerpt.
|
731 |
+
* @param \WP_Term $object The Term object.
|
732 |
*/
|
733 |
+
$excerpt = (string) \apply_filters_ref_array(
|
734 |
+
'the_seo_framework_fallback_archive_description_excerpt',
|
735 |
+
[
|
736 |
+
'',
|
737 |
+
$object,
|
738 |
+
]
|
739 |
+
);
|
740 |
}
|
741 |
} else {
|
742 |
+
$excerpt = $this->s_description_raw( $object->description ?? '' );
|
743 |
}
|
744 |
|
745 |
return $excerpt;
|
755 |
*/
|
756 |
protected function get_singular_description_excerpt( $id = null ) {
|
757 |
|
758 |
+
$id = $id ?? $this->get_the_real_ID();
|
|
|
759 |
|
760 |
// If the post is protected, don't generate a description.
|
761 |
if ( $this->is_protected( $id ) ) return '';
|
767 |
* Returns additions for "Title on Site Title".
|
768 |
*
|
769 |
* @since 3.1.0
|
770 |
+
* @since 3.2.0 1. Now no longer listens to options.
|
771 |
+
* 2. Now only works for the front and blog pages.
|
772 |
* @since 3.2.2 Now works for homepages from external requests.
|
773 |
+
* @since 4.2.0 No longer adds "on Blogname".
|
774 |
* @see $this->get_generated_description()
|
775 |
*
|
776 |
+
* @param array $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
777 |
+
* This method should always have 'taxonomy' set to ''.
|
|
|
778 |
* @return string The description additions.
|
779 |
*/
|
780 |
+
protected function get_description_additions( $args ) {
|
781 |
|
782 |
+
if ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
783 |
$title = $this->get_home_title_additions();
|
784 |
+
} elseif ( $this->is_home_as_page( $args['id'] ) ) {
|
785 |
+
$title = sprintf(
|
786 |
+
/* translators: %s = Blog page title. Front-end output. */
|
787 |
+
\__( 'Latest posts: %s', 'autodescription' ),
|
788 |
+
$this->get_filtered_raw_generated_title( $args )
|
789 |
+
);
|
790 |
}
|
791 |
|
792 |
+
return ( $title ?? '' ) ?: '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
793 |
}
|
794 |
|
795 |
/**
|
797 |
*
|
798 |
* @since 1.0.0
|
799 |
* @since 2.8.2 Added 4th parameter for escaping.
|
800 |
+
* @since 3.1.0 1. No longer returns anything for terms.
|
801 |
+
* 2. Now strips plausible embeds URLs.
|
802 |
* @since 4.0.1 The second parameter `$id` now defaults to int 0, instead of an empty string.
|
803 |
*
|
804 |
* @param string $excerpt The Excerpt.
|
865 |
* Warning: Returns with entities encoded. The output is not safe for printing.
|
866 |
*
|
867 |
* @since 2.6.0
|
868 |
+
* @since 3.1.0 1. Now uses smarter trimming.
|
869 |
+
* 2. Deprecated 2nd parameter.
|
870 |
+
* 3. Now has unicode support for sentence closing.
|
871 |
+
* 4. Now strips last three words when preceded by a sentence closing separator.
|
872 |
+
* 5. Now always leads with (inviting) dots, even if the excerpt is shorter than $max_char_length.
|
873 |
+
* @since 4.0.0 1. Now stops parsing earlier on failure.
|
874 |
+
* 2. Now performs faster queries.
|
875 |
+
* 3. Now maintains last sentence with closing punctuations.
|
876 |
+
* @since 4.0.5 1. Now decodes the excerpt input, improving accuracy, and so that HTML entities at
|
877 |
+
* the end won't be transformed into gibberish.
|
878 |
+
* @since 4.1.0 1. Now texturizes the excerpt input, improving accuracy with included closing & final punctuation support.
|
879 |
+
* 2. Now performs even faster queries, in most situations. (0.2ms/0.02ms total (worst/best) @ PHP 7.3/PCRE 11).
|
880 |
+
* Mind you, this method probably boots PCRE and wptexturize; so, it'll be slower than what we noted--it's
|
881 |
+
* overhead that otherwise WP, the theme, or other plugin would cause anyway. So, deduct that.
|
882 |
+
* 3. Now recognizes connector and final punctuations for preliminary sentence bounding.
|
883 |
+
* 4. Leading punctuation now excludes symbols, special annotations, opening brackets and quotes,
|
884 |
+
* and marks used in some latin languages like ¡¿.
|
885 |
+
* 5. Is now able to always strip leading punctuation.
|
886 |
+
* 6. It will now strip leading colon characters.
|
887 |
+
* 7. It will now stop counting trailing words towards new sentences when a connector, dash, mark, or ¡¿ is found.
|
888 |
+
* 8. Now returns encoded entities once more. So that the return value can be treated the same as anything else
|
889 |
+
* revolving around descriptions--preventing double transcoding like `&amp; > & > &` instead of `&`.
|
890 |
+
* @since 4.1.5 1. The second parameter now accepts values again. From "current description length" to minimum accepted char length.
|
891 |
+
* 2. Can now return an empty string when the input string doesn't satisfy the minimum character length.
|
892 |
+
* 3. The third parameter now defaults to 4096, so no longer unexpected results are created.
|
893 |
+
* 4. Resolved some backtracking issues.
|
894 |
+
* 5. Resolved an issue where a character followed by punctuation would cause the match to fail.
|
895 |
+
* @since 4.2.0 Now enforces at least a character length of 1. This prevents needless processing.
|
896 |
* @see https://secure.php.net/manual/en/regexp.reference.unicode.php
|
897 |
*
|
898 |
* We use `[^\P{Po}\'\"]` because WordPress texturizes ' and " to fall under `\P{Po}`.
|
906 |
*/
|
907 |
public function trim_excerpt( $excerpt, $min_char_length = 1, $max_char_length = 4096 ) {
|
908 |
|
909 |
+
// At least 1.
|
910 |
+
$min_char_length = $min_char_length < 1 ? 1 : $min_char_length;
|
911 |
+
|
912 |
// We should _actually_ use mb_strlen, but that's wasteful on resources for something benign.
|
913 |
// We'll rectify that later, somewhat, where characters are transformed.
|
914 |
// We could also use preg_match_all( '/./u' ); or count( preg_split( '/./u', $excerpt, $min_char_length ) );
|
920 |
|
921 |
// Find all words with $max_char_length, and trim when the last word boundary or punctuation is found.
|
922 |
preg_match( sprintf( '/.{0,%d}([^\P{Po}\'\":]|[\p{Pc}\p{Pd}\p{Pf}\p{Z}]|\Z){1}/su', $max_char_length ), trim( $excerpt ), $matches );
|
923 |
+
$excerpt = trim( ( $matches[0] ?? '' ) ?: '' );
|
924 |
|
925 |
$excerpt = trim( $excerpt );
|
926 |
|
960 |
);
|
961 |
|
962 |
if ( isset( $matches[5] ) ) {
|
963 |
+
$excerpt = "$matches[1]$matches[3]$matches[4]$matches[5]";
|
964 |
// Skip 4. It's useless content without 5.
|
965 |
} elseif ( isset( $matches[3] ) ) {
|
966 |
+
$excerpt = "$matches[1]$matches[3]";
|
967 |
} elseif ( isset( $matches[2] ) ) {
|
968 |
+
$excerpt = "$matches[1]$matches[2]";
|
969 |
} elseif ( isset( $matches[1] ) ) {
|
970 |
$excerpt = $matches[1];
|
971 |
}
|
986 |
);
|
987 |
// Why can $matches[2] still be populated with 3 set? Does it populate empty results upward to last, always???
|
988 |
if ( isset( $matches[2] ) && \strlen( $matches[2] ) ) {
|
989 |
+
$excerpt = "$matches[1]$matches[2]";
|
990 |
} elseif ( isset( $matches[1] ) && \strlen( $matches[1] ) ) {
|
991 |
// Ignore useless [3], there's no [2], [1] is open-ended; so, add hellip.
|
992 |
+
$excerpt = "$matches[1]..."; // This should be texturized later to ….
|
993 |
} else {
|
994 |
// If there's no matches[1], only some form of non-closing-leading punctuation was left in $excerpt. Empty it.
|
995 |
$excerpt = '';
|
1004 |
* Determines whether automated descriptions are enabled.
|
1005 |
*
|
1006 |
* @since 3.1.0
|
1007 |
+
* @since 4.2.0 1. Now fixes the input arguments.
|
1008 |
+
* 2. Now supports the `$args['pta']` index.
|
1009 |
* @access private
|
1010 |
* @see $this->get_the_real_ID()
|
1011 |
* @see $this->get_current_taxonomy()
|
1012 |
*
|
1013 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
1014 |
+
* Leave null to autodetermine query.
|
1015 |
* @return bool
|
1016 |
*/
|
1017 |
+
public function is_auto_description_enabled( $args = null ) {
|
1018 |
|
1019 |
+
if ( null !== $args )
|
1020 |
+
$this->fix_generation_args( $args );
|
|
|
|
|
|
|
|
|
1021 |
|
1022 |
/**
|
1023 |
* @since 2.5.0
|
1024 |
* @since 3.0.0 Now passes $args as the second parameter.
|
1025 |
* @since 3.1.0 Now listens to option.
|
1026 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
1027 |
* @param bool $autodescription Enable or disable the automated descriptions.
|
1028 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
1029 |
* Is null when query is autodetermined.
|
1030 |
*/
|
1031 |
return (bool) \apply_filters_ref_array(
|
@@ -54,8 +54,7 @@ class Generate_Image extends Generate_Url {
|
|
54 |
* }
|
55 |
*/
|
56 |
public function get_image_details_from_cache( $single = false ) {
|
57 |
-
|
58 |
-
return isset( $cache[ $single ] ) ? $cache[ $single ] : $cache[ $single ] = $this->get_image_details( null, $single );
|
59 |
}
|
60 |
|
61 |
/**
|
@@ -63,8 +62,9 @@ class Generate_Image extends Generate_Url {
|
|
63 |
*
|
64 |
* @since 4.0.0
|
65 |
* @since 4.0.5 The output is now filterable.
|
|
|
66 |
*
|
67 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
68 |
* Leave null to autodetermine query.
|
69 |
* @param bool $single Whether to fetch one image, or multiple.
|
70 |
* @param string $context The filter context. Default 'social'.
|
@@ -94,6 +94,7 @@ class Generate_Image extends Generate_Url {
|
|
94 |
|
95 |
/**
|
96 |
* @since 4.0.5
|
|
|
97 |
* @param array $details The image details array, sequential: int => {
|
98 |
* string url: The image URL,
|
99 |
* int id: The image ID,
|
@@ -101,7 +102,7 @@ class Generate_Image extends Generate_Url {
|
|
101 |
* int height: The image height in pixels,
|
102 |
* string alt: The image alt tag,
|
103 |
* }
|
104 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
105 |
* Is null when query is autodetermined.
|
106 |
* @param bool $single Whether to fetch one image, or multiple.
|
107 |
* @param string $context The filter context. Default 'social'.
|
@@ -123,8 +124,9 @@ class Generate_Image extends Generate_Url {
|
|
123 |
* Returns single custom field image details.
|
124 |
*
|
125 |
* @since 4.0.0
|
|
|
126 |
*
|
127 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
128 |
* Leave null to autodetermine query.
|
129 |
* @param bool $single Whether to fetch one image, or multiple. Unused, reserved.
|
130 |
* @param bool $clean Whether to clean the image, like stripping duplicates and erroneous items.
|
@@ -153,8 +155,9 @@ class Generate_Image extends Generate_Url {
|
|
153 |
* Returns single or multiple generates image details.
|
154 |
*
|
155 |
* @since 4.0.0
|
|
|
156 |
*
|
157 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
158 |
* Leave null to autodetermine query.
|
159 |
* @param bool $single Whether to fetch one image, or multiple.
|
160 |
* @param string $context The filter context. Default 'social'.
|
@@ -184,6 +187,7 @@ class Generate_Image extends Generate_Url {
|
|
184 |
* Returns single custom field image details from query.
|
185 |
*
|
186 |
* @since 4.0.0
|
|
|
187 |
*
|
188 |
* @return array The image details array, sequential: int => {
|
189 |
* string url: The image URL,
|
@@ -223,6 +227,11 @@ class Generate_Image extends Generate_Url {
|
|
223 |
'url' => $this->get_term_meta_item( 'social_image_url' ),
|
224 |
'id' => $this->get_term_meta_item( 'social_image_id' ),
|
225 |
];
|
|
|
|
|
|
|
|
|
|
|
226 |
} else {
|
227 |
$details = [
|
228 |
'url' => '',
|
@@ -246,6 +255,7 @@ class Generate_Image extends Generate_Url {
|
|
246 |
* Returns single custom field image details from arguments.
|
247 |
*
|
248 |
* @since 4.0.0
|
|
|
249 |
*
|
250 |
* @param array $args The query arguments. Must have 'id' and 'taxonomy'.
|
251 |
* @return array The image details array, sequential: int => {
|
@@ -263,6 +273,11 @@ class Generate_Image extends Generate_Url {
|
|
263 |
'url' => $this->get_term_meta_item( 'social_image_url', $args['id'] ),
|
264 |
'id' => $this->get_term_meta_item( 'social_image_id', $args['id'] ),
|
265 |
];
|
|
|
|
|
|
|
|
|
|
|
266 |
} else {
|
267 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
268 |
$details = [
|
@@ -305,8 +320,9 @@ class Generate_Image extends Generate_Url {
|
|
305 |
*
|
306 |
* @since 4.0.0
|
307 |
* @since 4.1.1 Now only the 'social' context will fetch images from the content.
|
|
|
308 |
*
|
309 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
310 |
* Leave null to autodetermine query.
|
311 |
* @param string $context The filter context. Default 'social'.
|
312 |
* May be (for example) 'breadcrumb' or 'article' for structured data.
|
@@ -322,23 +338,20 @@ class Generate_Image extends Generate_Url {
|
|
322 |
*/
|
323 |
public function get_image_generation_params( $args = null, $context = 'social' ) {
|
324 |
|
325 |
-
if ( null !== $args )
|
326 |
-
$this->fix_generation_args( $args );
|
327 |
-
|
328 |
$builder = Builders\Images::class;
|
329 |
|
330 |
if ( null === $args ) {
|
331 |
if ( $this->is_singular() ) {
|
332 |
if ( $this->is_attachment() ) {
|
333 |
$cbs = [
|
334 |
-
'attachment' =>
|
335 |
];
|
336 |
} else {
|
337 |
$cbs = [
|
338 |
-
'featured' =>
|
339 |
];
|
340 |
if ( 'social' === $context ) {
|
341 |
-
$cbs['content'] =
|
342 |
}
|
343 |
}
|
344 |
} elseif ( $this->is_term_meta_capable() ) {
|
@@ -347,19 +360,21 @@ class Generate_Image extends Generate_Url {
|
|
347 |
$cbs = [];
|
348 |
}
|
349 |
} else {
|
350 |
-
|
|
|
|
|
351 |
$cbs = [];
|
352 |
} else {
|
353 |
if ( \wp_attachment_is_image( $args['id'] ) ) {
|
354 |
$cbs = [
|
355 |
-
'attachment' =>
|
356 |
];
|
357 |
} else {
|
358 |
$cbs = [
|
359 |
-
'featured' =>
|
360 |
];
|
361 |
if ( 'social' === $context ) {
|
362 |
-
$cbs['content'] =
|
363 |
}
|
364 |
}
|
365 |
}
|
@@ -367,10 +382,10 @@ class Generate_Image extends Generate_Url {
|
|
367 |
|
368 |
if ( 'social' === $context ) {
|
369 |
$fallback = [
|
370 |
-
'settings' =>
|
371 |
-
'header' =>
|
372 |
-
'logo' =>
|
373 |
-
'icon' =>
|
374 |
];
|
375 |
} else {
|
376 |
$fallback = [];
|
@@ -378,13 +393,14 @@ class Generate_Image extends Generate_Url {
|
|
378 |
|
379 |
/**
|
380 |
* @since 4.0.0
|
|
|
381 |
* @param array $params : [
|
382 |
* string size: The image size to use.
|
383 |
* boolean multi: Whether to allow multiple images to be returned. This may be overwritten by generators to 'false'.
|
384 |
* array cbs: The callbacks to parse. Ideally be generators, so we can halt remotely.
|
385 |
* array fallback: The callbacks to parse. Ideally be generators, so we can halt remotely.
|
386 |
* ];
|
387 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
388 |
* Is null when query is autodetermined.
|
389 |
* @param string $context The filter context. Default 'social'.
|
390 |
* May be (for example) 'breadcrumb' or 'article' for structured data.
|
@@ -409,7 +425,7 @@ class Generate_Image extends Generate_Url {
|
|
409 |
*
|
410 |
* @since 4.0.0
|
411 |
*
|
412 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
413 |
* Leave null to autodetermine query.
|
414 |
* @param bool $single Whether to fetch one image, or multiple.
|
415 |
* @param string $context The context of the image generation, albeit 'social', 'schema', etc.
|
@@ -438,7 +454,7 @@ class Generate_Image extends Generate_Url {
|
|
438 |
* @since 4.0.0
|
439 |
*
|
440 |
* @param array $cbs The callbacks to parse. Ideally be generators, so we can halt early.
|
441 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
442 |
* Leave null to autodetermine query.
|
443 |
* @param string $size The image size to use.
|
444 |
* @param bool $single Whether to fetch one image, or multiple.
|
@@ -459,8 +475,9 @@ class Generate_Image extends Generate_Url {
|
|
459 |
// This is one of the slowest calls in this plugin on PHP 5.6. However, PHP 7.0 optimized cuf(a). Neglegible.
|
460 |
foreach ( \call_user_func_array( $cb, [ $args, $size ] ) as $details ) {
|
461 |
if ( $details['url'] && $this->s_url_query( $details['url'] ) ) {
|
462 |
-
$items[ $i
|
463 |
if ( $single ) break 2;
|
|
|
464 |
}
|
465 |
}
|
466 |
}
|
@@ -486,7 +503,7 @@ class Generate_Image extends Generate_Url {
|
|
486 |
* string alt: The image alt tag,
|
487 |
* }
|
488 |
*/
|
489 |
-
public function merge_extra_image_details(
|
490 |
|
491 |
$details += $this->get_image_dimensions( $details['id'], $details['url'], $size );
|
492 |
$details += [ 'alt' => $this->get_image_alt_tag( $details['id'] ) ];
|
@@ -517,7 +534,7 @@ class Generate_Image extends Generate_Url {
|
|
517 |
];
|
518 |
|
519 |
if ( $image ) {
|
520 |
-
|
521 |
|
522 |
$test_src = \esc_url_raw( $this->set_url_scheme( $src, 'https' ), [ 'https', 'http' ] );
|
523 |
$test_url = \esc_url_raw( $this->set_url_scheme( $url, 'https' ), [ 'https', 'http' ] );
|
54 |
* }
|
55 |
*/
|
56 |
public function get_image_details_from_cache( $single = false ) {
|
57 |
+
return memo( null, $single ) ?? memo( $this->get_image_details( null, $single ), $single );
|
|
|
58 |
}
|
59 |
|
60 |
/**
|
62 |
*
|
63 |
* @since 4.0.0
|
64 |
* @since 4.0.5 The output is now filterable.
|
65 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
66 |
*
|
67 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
68 |
* Leave null to autodetermine query.
|
69 |
* @param bool $single Whether to fetch one image, or multiple.
|
70 |
* @param string $context The filter context. Default 'social'.
|
94 |
|
95 |
/**
|
96 |
* @since 4.0.5
|
97 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
98 |
* @param array $details The image details array, sequential: int => {
|
99 |
* string url: The image URL,
|
100 |
* int id: The image ID,
|
102 |
* int height: The image height in pixels,
|
103 |
* string alt: The image alt tag,
|
104 |
* }
|
105 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
106 |
* Is null when query is autodetermined.
|
107 |
* @param bool $single Whether to fetch one image, or multiple.
|
108 |
* @param string $context The filter context. Default 'social'.
|
124 |
* Returns single custom field image details.
|
125 |
*
|
126 |
* @since 4.0.0
|
127 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
128 |
*
|
129 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
130 |
* Leave null to autodetermine query.
|
131 |
* @param bool $single Whether to fetch one image, or multiple. Unused, reserved.
|
132 |
* @param bool $clean Whether to clean the image, like stripping duplicates and erroneous items.
|
155 |
* Returns single or multiple generates image details.
|
156 |
*
|
157 |
* @since 4.0.0
|
158 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
159 |
*
|
160 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
161 |
* Leave null to autodetermine query.
|
162 |
* @param bool $single Whether to fetch one image, or multiple.
|
163 |
* @param string $context The filter context. Default 'social'.
|
187 |
* Returns single custom field image details from query.
|
188 |
*
|
189 |
* @since 4.0.0
|
190 |
+
* @since 4.2.0 Can now return post type archive images from settings.
|
191 |
*
|
192 |
* @return array The image details array, sequential: int => {
|
193 |
* string url: The image URL,
|
227 |
'url' => $this->get_term_meta_item( 'social_image_url' ),
|
228 |
'id' => $this->get_term_meta_item( 'social_image_id' ),
|
229 |
];
|
230 |
+
} elseif ( \is_post_type_archive() ) {
|
231 |
+
$details = [
|
232 |
+
'url' => $this->get_post_type_archive_meta_item( 'social_image_url' ),
|
233 |
+
'id' => $this->get_post_type_archive_meta_item( 'social_image_id' ),
|
234 |
+
];
|
235 |
} else {
|
236 |
$details = [
|
237 |
'url' => '',
|
255 |
* Returns single custom field image details from arguments.
|
256 |
*
|
257 |
* @since 4.0.0
|
258 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
259 |
*
|
260 |
* @param array $args The query arguments. Must have 'id' and 'taxonomy'.
|
261 |
* @return array The image details array, sequential: int => {
|
273 |
'url' => $this->get_term_meta_item( 'social_image_url', $args['id'] ),
|
274 |
'id' => $this->get_term_meta_item( 'social_image_id', $args['id'] ),
|
275 |
];
|
276 |
+
} elseif ( $args['pta'] ) {
|
277 |
+
$details = [
|
278 |
+
'url' => $this->get_post_type_archive_meta_item( 'social_image_url', $args['pta'] ),
|
279 |
+
'id' => $this->get_post_type_archive_meta_item( 'social_image_id', $args['pta'] ),
|
280 |
+
];
|
281 |
} else {
|
282 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
283 |
$details = [
|
320 |
*
|
321 |
* @since 4.0.0
|
322 |
* @since 4.1.1 Now only the 'social' context will fetch images from the content.
|
323 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
324 |
*
|
325 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
326 |
* Leave null to autodetermine query.
|
327 |
* @param string $context The filter context. Default 'social'.
|
328 |
* May be (for example) 'breadcrumb' or 'article' for structured data.
|
338 |
*/
|
339 |
public function get_image_generation_params( $args = null, $context = 'social' ) {
|
340 |
|
|
|
|
|
|
|
341 |
$builder = Builders\Images::class;
|
342 |
|
343 |
if ( null === $args ) {
|
344 |
if ( $this->is_singular() ) {
|
345 |
if ( $this->is_attachment() ) {
|
346 |
$cbs = [
|
347 |
+
'attachment' => [ $builder, 'get_attachment_image_details' ],
|
348 |
];
|
349 |
} else {
|
350 |
$cbs = [
|
351 |
+
'featured' => [ $builder, 'get_featured_image_details' ],
|
352 |
];
|
353 |
if ( 'social' === $context ) {
|
354 |
+
$cbs['content'] = [ $builder, 'get_content_image_details' ];
|
355 |
}
|
356 |
}
|
357 |
} elseif ( $this->is_term_meta_capable() ) {
|
360 |
$cbs = [];
|
361 |
}
|
362 |
} else {
|
363 |
+
$this->fix_generation_args( $args );
|
364 |
+
|
365 |
+
if ( $args['taxonomy'] || $args['pta'] ) {
|
366 |
$cbs = [];
|
367 |
} else {
|
368 |
if ( \wp_attachment_is_image( $args['id'] ) ) {
|
369 |
$cbs = [
|
370 |
+
'attachment' => [ $builder, 'get_attachment_image_details' ],
|
371 |
];
|
372 |
} else {
|
373 |
$cbs = [
|
374 |
+
'featured' => [ $builder, 'get_featured_image_details' ],
|
375 |
];
|
376 |
if ( 'social' === $context ) {
|
377 |
+
$cbs['content'] = [ $builder, 'get_content_image_details' ];
|
378 |
}
|
379 |
}
|
380 |
}
|
382 |
|
383 |
if ( 'social' === $context ) {
|
384 |
$fallback = [
|
385 |
+
'settings' => [ $builder, 'get_fallback_image_details' ],
|
386 |
+
'header' => [ $builder, 'get_theme_header_image_details' ],
|
387 |
+
'logo' => [ $builder, 'get_site_logo_image_details' ],
|
388 |
+
'icon' => [ $builder, 'get_site_icon_image_details' ],
|
389 |
];
|
390 |
} else {
|
391 |
$fallback = [];
|
393 |
|
394 |
/**
|
395 |
* @since 4.0.0
|
396 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
397 |
* @param array $params : [
|
398 |
* string size: The image size to use.
|
399 |
* boolean multi: Whether to allow multiple images to be returned. This may be overwritten by generators to 'false'.
|
400 |
* array cbs: The callbacks to parse. Ideally be generators, so we can halt remotely.
|
401 |
* array fallback: The callbacks to parse. Ideally be generators, so we can halt remotely.
|
402 |
* ];
|
403 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
404 |
* Is null when query is autodetermined.
|
405 |
* @param string $context The filter context. Default 'social'.
|
406 |
* May be (for example) 'breadcrumb' or 'article' for structured data.
|
425 |
*
|
426 |
* @since 4.0.0
|
427 |
*
|
428 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
429 |
* Leave null to autodetermine query.
|
430 |
* @param bool $single Whether to fetch one image, or multiple.
|
431 |
* @param string $context The context of the image generation, albeit 'social', 'schema', etc.
|
454 |
* @since 4.0.0
|
455 |
*
|
456 |
* @param array $cbs The callbacks to parse. Ideally be generators, so we can halt early.
|
457 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
458 |
* Leave null to autodetermine query.
|
459 |
* @param string $size The image size to use.
|
460 |
* @param bool $single Whether to fetch one image, or multiple.
|
475 |
// This is one of the slowest calls in this plugin on PHP 5.6. However, PHP 7.0 optimized cuf(a). Neglegible.
|
476 |
foreach ( \call_user_func_array( $cb, [ $args, $size ] ) as $details ) {
|
477 |
if ( $details['url'] && $this->s_url_query( $details['url'] ) ) {
|
478 |
+
$items[ $i ] = $this->merge_extra_image_details( $details, $size );
|
479 |
if ( $single ) break 2;
|
480 |
+
$i++;
|
481 |
}
|
482 |
}
|
483 |
}
|
503 |
* string alt: The image alt tag,
|
504 |
* }
|
505 |
*/
|
506 |
+
public function merge_extra_image_details( $details, $size = 'full' ) {
|
507 |
|
508 |
$details += $this->get_image_dimensions( $details['id'], $details['url'], $size );
|
509 |
$details += [ 'alt' => $this->get_image_alt_tag( $details['id'] ) ];
|
534 |
];
|
535 |
|
536 |
if ( $image ) {
|
537 |
+
[ $src, $width, $height ] = $image;
|
538 |
|
539 |
$test_src = \esc_url_raw( $this->set_url_scheme( $src, 'https' ), [ 'https', 'http' ] );
|
540 |
$test_url = \esc_url_raw( $this->set_url_scheme( $url, 'https' ), [ 'https', 'http' ] );
|
@@ -45,10 +45,10 @@ class Generate_Ldjson extends Generate_Image {
|
|
45 |
* @see $this->receive_json_data()
|
46 |
* @uses $this->build_json_data_cache()
|
47 |
*
|
48 |
-
* @param string
|
49 |
-
* @param
|
50 |
*/
|
51 |
-
public function build_json_data( $key,
|
52 |
|
53 |
$key = \sanitize_key( $key );
|
54 |
$data = array_filter( $data );
|
@@ -107,7 +107,7 @@ class Generate_Ldjson extends Generate_Image {
|
|
107 |
* @param string $key The JSON data key.
|
108 |
* @param array $entry The JSON data entry.
|
109 |
*/
|
110 |
-
protected function build_json_data_cache( $key,
|
111 |
$this->cache_json_data( false, $key, $entry );
|
112 |
}
|
113 |
|
@@ -123,7 +123,7 @@ class Generate_Ldjson extends Generate_Image {
|
|
123 |
* @param array $entry The JSON data entry.
|
124 |
* @return array The JSON data for $key.
|
125 |
*/
|
126 |
-
protected function cache_json_data( $get = true, $key = '',
|
127 |
|
128 |
static $data = [];
|
129 |
|
@@ -147,13 +147,13 @@ class Generate_Ldjson extends Generate_Image {
|
|
147 |
public function render_ld_json_scripts() {
|
148 |
|
149 |
if ( $this->is_real_front_page() ) {
|
150 |
-
|
151 |
$output = '';
|
152 |
|
153 |
$output .= $this->get_ld_json_website() ?: '';
|
154 |
$output .= $this->get_ld_json_links() ?: '';
|
155 |
} else {
|
156 |
-
|
157 |
$output = $this->get_ld_json_breadcrumbs() ?: '';
|
158 |
}
|
159 |
|
@@ -180,7 +180,7 @@ class Generate_Ldjson extends Generate_Image {
|
|
180 |
'url' => $this->get_homepage_permalink(),
|
181 |
];
|
182 |
|
183 |
-
|
184 |
$blogname = $this->get_blogname();
|
185 |
$kname = $this->get_option( 'knowledge_name' );
|
186 |
|
@@ -191,7 +191,7 @@ class Generate_Ldjson extends Generate_Image {
|
|
191 |
'alternateName' => \strlen( $alternate_name ) ? $this->escape_title( $alternate_name ) : '',
|
192 |
];
|
193 |
|
194 |
-
|
195 |
$pattern = '%s{%s}';
|
196 |
$action_name = 'search_term_string';
|
197 |
$search_link = $this->pretty_permalinks ? \trailingslashit( \get_search_link() ) : \get_search_link();
|
@@ -215,7 +215,7 @@ class Generate_Ldjson extends Generate_Image {
|
|
215 |
],
|
216 |
];
|
217 |
|
218 |
-
|
219 |
$key = 'website';
|
220 |
$this->build_json_data( $key, $data );
|
221 |
$json = $this->receive_json_data( $key );
|
@@ -325,35 +325,6 @@ class Generate_Ldjson extends Generate_Image {
|
|
325 |
);
|
326 |
}
|
327 |
|
328 |
-
/**
|
329 |
-
* Returns image URL suitable for Schema items.
|
330 |
-
*
|
331 |
-
* These are images that are strictly assigned to the Post or Page, fallbacks are omitted.
|
332 |
-
* Themes should compliment these. If not, then Open Graph should at least compliment these.
|
333 |
-
* If that's not even true, then I don't know what happens. But then you're in a grey area...
|
334 |
-
*
|
335 |
-
* @since 4.0.0
|
336 |
-
* @uses $this->get_image_details()
|
337 |
-
* @api Not used internally, only externally.
|
338 |
-
*
|
339 |
-
* @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
|
340 |
-
* Leave null to autodetermine query.
|
341 |
-
* @param bool $details Whether to return all details, or just a simple URL.
|
342 |
-
* @return string|array $url The Schema.org safe image.
|
343 |
-
*/
|
344 |
-
public function get_safe_schema_image( $args = null, $details = false ) {
|
345 |
-
|
346 |
-
static $image_details = null;
|
347 |
-
|
348 |
-
if ( ! isset( $image_details ) )
|
349 |
-
$image_details = current( $this->get_image_details( $args, true, 'schema' ) );
|
350 |
-
|
351 |
-
if ( $details )
|
352 |
-
return $image_details;
|
353 |
-
|
354 |
-
return isset( $image_details['url'] ) ? $image_details['url'] : '';
|
355 |
-
}
|
356 |
-
|
357 |
/**
|
358 |
* Generates LD+JSON Breadcrumbs script.
|
359 |
*
|
@@ -398,10 +369,7 @@ class Generate_Ldjson extends Generate_Image {
|
|
398 |
foreach ( $parents as $parent_id ) {
|
399 |
++$position;
|
400 |
|
401 |
-
$_generator_args = [
|
402 |
-
'id' => $parent_id,
|
403 |
-
'taxonomy' => '',
|
404 |
-
];
|
405 |
|
406 |
if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
|
407 |
$parent_name = $this->get_filtered_raw_custom_field_title( $_generator_args )
|
@@ -436,8 +404,8 @@ class Generate_Ldjson extends Generate_Image {
|
|
436 |
* Generates LD+JSON Breadcrumbs script for Posts.
|
437 |
*
|
438 |
* @since 2.9.3
|
439 |
-
* @since 3.0.0
|
440 |
-
*
|
441 |
*
|
442 |
* @return string LD+JSON breadcrumbs script for Posts on success. Empty string on failure.
|
443 |
*/
|
@@ -504,14 +472,14 @@ class Generate_Ldjson extends Generate_Image {
|
|
504 |
// Check if they have parents (gets them all).
|
505 |
$ancestors = \get_ancestors( $term_id, $taxonomy );
|
506 |
if ( $ancestors ) {
|
507 |
-
|
508 |
$parents[ $term_id ] = $ancestors;
|
509 |
} else {
|
510 |
-
|
511 |
$parents[ $term_id ] = [];
|
512 |
}
|
513 |
endforeach;
|
514 |
-
|
515 |
unset( $terms );
|
516 |
|
517 |
if ( ! $parents )
|
@@ -548,7 +516,7 @@ class Generate_Ldjson extends Generate_Image {
|
|
548 |
}
|
549 |
}
|
550 |
if ( ! $filtered ) {
|
551 |
-
|
552 |
ksort( $assigned_ids, SORT_NUMERIC );
|
553 |
$tree_ids = $this->filter_ld_json_breadcrumb_trees( $tree_ids, key( $assigned_ids ) );
|
554 |
}
|
@@ -566,7 +534,6 @@ class Generate_Ldjson extends Generate_Image {
|
|
566 |
'taxonomy' => $taxonomy,
|
567 |
];
|
568 |
|
569 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
570 |
if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
|
571 |
$cat_name = $this->get_filtered_raw_custom_field_title( $_generator_args )
|
572 |
?: $this->get_generated_single_term_title( \get_term( $child_id, $taxonomy ) )
|
@@ -575,7 +542,6 @@ class Generate_Ldjson extends Generate_Image {
|
|
575 |
$cat_name = $this->get_generated_single_term_title( \get_term( $child_id, $taxonomy ) )
|
576 |
?: $this->get_static_untitled_title();
|
577 |
}
|
578 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
579 |
|
580 |
// Store in cache.
|
581 |
$items[] = [
|
@@ -610,7 +576,7 @@ class Generate_Ldjson extends Generate_Image {
|
|
610 |
* @param array $previous_tree A previous set tree to compare to, if set.
|
611 |
* @return array Trees in order.
|
612 |
*/
|
613 |
-
protected function build_ld_json_breadcrumb_trees( $cats,
|
614 |
|
615 |
$trees = $previous_tree;
|
616 |
|
@@ -682,40 +648,36 @@ class Generate_Ldjson extends Generate_Image {
|
|
682 |
* Memoizes the return value.
|
683 |
*
|
684 |
* @since 2.9.3
|
685 |
-
* @since 3.2.2
|
686 |
-
*
|
687 |
-
*
|
688 |
* @since 4.0.0 Removed the image input requirement.
|
689 |
*
|
690 |
* @return array The HomePage crumb entry.
|
691 |
*/
|
692 |
public function get_ld_json_breadcrumb_home_crumb() {
|
693 |
|
694 |
-
|
695 |
-
if (
|
696 |
-
return $crumb;
|
697 |
|
698 |
-
$_generator_args = [
|
699 |
-
'id' => $this->get_the_front_page_ID(),
|
700 |
-
'taxonomy' => '',
|
701 |
-
];
|
702 |
|
703 |
if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
|
704 |
-
$title = $this->get_filtered_raw_custom_field_title( $_generator_args )
|
|
|
705 |
} else {
|
706 |
-
$title = $this->get_filtered_raw_generated_title( $_generator_args )
|
|
|
707 |
}
|
708 |
|
709 |
-
|
710 |
'@type' => 'ListItem',
|
711 |
'position' => 1,
|
712 |
'item' => [
|
713 |
'@id' => $this->get_schema_url_id( 'breadcrumb', 'homepage' ),
|
714 |
'name' => $this->escape_title( $title ),
|
715 |
],
|
716 |
-
];
|
717 |
-
|
718 |
-
return $crumb;
|
719 |
}
|
720 |
|
721 |
/**
|
@@ -741,12 +703,8 @@ class Generate_Ldjson extends Generate_Image {
|
|
741 |
}
|
742 |
|
743 |
$post_id = $this->get_the_real_ID();
|
744 |
-
$_generator_args = [
|
745 |
-
'id' => $post_id,
|
746 |
-
'taxonomy' => '',
|
747 |
-
];
|
748 |
|
749 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
750 |
if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
|
751 |
$name = $this->get_filtered_raw_custom_field_title( $_generator_args )
|
752 |
?: $this->get_generated_single_post_title( $post_id )
|
@@ -755,7 +713,6 @@ class Generate_Ldjson extends Generate_Image {
|
|
755 |
$name = $this->get_generated_single_post_title( $post_id )
|
756 |
?: $this->get_static_untitled_title();
|
757 |
}
|
758 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
759 |
|
760 |
$crumb = [
|
761 |
'@type' => 'ListItem',
|
@@ -786,7 +743,7 @@ class Generate_Ldjson extends Generate_Image {
|
|
786 |
|
787 |
static $it = 0;
|
788 |
|
789 |
-
$key =
|
790 |
|
791 |
$data = [
|
792 |
'@context' => 'https://schema.org',
|
@@ -847,88 +804,58 @@ class Generate_Ldjson extends Generate_Image {
|
|
847 |
* @return bool
|
848 |
*/
|
849 |
public function ld_json_breadcrumbs_use_seo_title() {
|
850 |
-
|
851 |
-
static $cache = null;
|
852 |
-
|
853 |
/**
|
854 |
* @since 2.9.0
|
855 |
* @param bool $use_seo_title Whether to use the SEO title.
|
856 |
*/
|
857 |
-
return
|
858 |
}
|
859 |
|
860 |
/**
|
861 |
* Determines if breadcrumbs scripts are enabled.
|
862 |
-
* Memoizes the return value.
|
863 |
*
|
864 |
* @since 2.6.0
|
|
|
865 |
*
|
866 |
* @return bool
|
867 |
*/
|
868 |
public function enable_ld_json_breadcrumbs() {
|
869 |
-
|
870 |
-
static $cache = null;
|
871 |
-
|
872 |
-
if ( isset( $cache ) )
|
873 |
-
return $cache;
|
874 |
-
|
875 |
/**
|
876 |
* @since 2.4.2
|
877 |
-
* @param bool $
|
878 |
*/
|
879 |
-
|
880 |
-
$option = $this->get_option( 'ld_json_breadcrumbs' );
|
881 |
-
|
882 |
-
return $cache = $filter && $option;
|
883 |
}
|
884 |
|
885 |
/**
|
886 |
* Determines if searchbox script is enabled.
|
887 |
-
* Memoizes the return value.
|
888 |
*
|
889 |
* @since 2.6.0
|
|
|
890 |
*
|
891 |
* @return bool
|
892 |
*/
|
893 |
public function enable_ld_json_searchbox() {
|
894 |
-
|
895 |
-
static $cache = null;
|
896 |
-
|
897 |
-
if ( isset( $cache ) )
|
898 |
-
return $cache;
|
899 |
-
|
900 |
/**
|
901 |
* @since 2.3.9
|
902 |
-
* @param bool $
|
903 |
*/
|
904 |
-
|
905 |
-
$option = $this->get_option( 'ld_json_searchbox' );
|
906 |
-
|
907 |
-
return $cache = $filter && $option;
|
908 |
}
|
909 |
|
910 |
/**
|
911 |
* Determines if Knowledge Graph Script is enabled.
|
912 |
-
* Memoizes the return value.
|
913 |
*
|
914 |
* @since 2.6.5
|
|
|
915 |
*
|
916 |
* @return bool
|
917 |
*/
|
918 |
public function enable_ld_json_knowledge() {
|
919 |
-
|
920 |
-
static $cache = null;
|
921 |
-
|
922 |
-
if ( isset( $cache ) )
|
923 |
-
return $cache;
|
924 |
-
|
925 |
/**
|
926 |
-
* @since 2.
|
927 |
-
* @param bool $
|
928 |
*/
|
929 |
-
|
930 |
-
$option = $this->get_option( 'knowledge_output' );
|
931 |
-
|
932 |
-
return $cache = $filter && $option;
|
933 |
}
|
934 |
}
|
45 |
* @see $this->receive_json_data()
|
46 |
* @uses $this->build_json_data_cache()
|
47 |
*
|
48 |
+
* @param string $key The JSON data key.
|
49 |
+
* @param iterable $data The JSON data.
|
50 |
*/
|
51 |
+
public function build_json_data( $key, $data ) {
|
52 |
|
53 |
$key = \sanitize_key( $key );
|
54 |
$data = array_filter( $data );
|
107 |
* @param string $key The JSON data key.
|
108 |
* @param array $entry The JSON data entry.
|
109 |
*/
|
110 |
+
protected function build_json_data_cache( $key, $entry ) {
|
111 |
$this->cache_json_data( false, $key, $entry );
|
112 |
}
|
113 |
|
123 |
* @param array $entry The JSON data entry.
|
124 |
* @return array The JSON data for $key.
|
125 |
*/
|
126 |
+
protected function cache_json_data( $get = true, $key = '', $entry = [] ) {
|
127 |
|
128 |
static $data = [];
|
129 |
|
147 |
public function render_ld_json_scripts() {
|
148 |
|
149 |
if ( $this->is_real_front_page() ) {
|
150 |
+
// Homepage Schema.
|
151 |
$output = '';
|
152 |
|
153 |
$output .= $this->get_ld_json_website() ?: '';
|
154 |
$output .= $this->get_ld_json_links() ?: '';
|
155 |
} else {
|
156 |
+
// All other pages' Schema.
|
157 |
$output = $this->get_ld_json_breadcrumbs() ?: '';
|
158 |
}
|
159 |
|
180 |
'url' => $this->get_homepage_permalink(),
|
181 |
];
|
182 |
|
183 |
+
// The name part.
|
184 |
$blogname = $this->get_blogname();
|
185 |
$kname = $this->get_option( 'knowledge_name' );
|
186 |
|
191 |
'alternateName' => \strlen( $alternate_name ) ? $this->escape_title( $alternate_name ) : '',
|
192 |
];
|
193 |
|
194 |
+
// The searchbox part.
|
195 |
$pattern = '%s{%s}';
|
196 |
$action_name = 'search_term_string';
|
197 |
$search_link = $this->pretty_permalinks ? \trailingslashit( \get_search_link() ) : \get_search_link();
|
215 |
],
|
216 |
];
|
217 |
|
218 |
+
// Building
|
219 |
$key = 'website';
|
220 |
$this->build_json_data( $key, $data );
|
221 |
$json = $this->receive_json_data( $key );
|
325 |
);
|
326 |
}
|
327 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
/**
|
329 |
* Generates LD+JSON Breadcrumbs script.
|
330 |
*
|
369 |
foreach ( $parents as $parent_id ) {
|
370 |
++$position;
|
371 |
|
372 |
+
$_generator_args = [ 'id' => $parent_id ];
|
|
|
|
|
|
|
373 |
|
374 |
if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
|
375 |
$parent_name = $this->get_filtered_raw_custom_field_title( $_generator_args )
|
404 |
* Generates LD+JSON Breadcrumbs script for Posts.
|
405 |
*
|
406 |
* @since 2.9.3
|
407 |
+
* @since 3.0.0 1. Now only returns one crumb.
|
408 |
+
* 2. Now listens to primary term ID.
|
409 |
*
|
410 |
* @return string LD+JSON breadcrumbs script for Posts on success. Empty string on failure.
|
411 |
*/
|
472 |
// Check if they have parents (gets them all).
|
473 |
$ancestors = \get_ancestors( $term_id, $taxonomy );
|
474 |
if ( $ancestors ) {
|
475 |
+
// Save parents to find duplicates.
|
476 |
$parents[ $term_id ] = $ancestors;
|
477 |
} else {
|
478 |
+
// Save current only with empty parent id..
|
479 |
$parents[ $term_id ] = [];
|
480 |
}
|
481 |
endforeach;
|
482 |
+
// Circle of life...
|
483 |
unset( $terms );
|
484 |
|
485 |
if ( ! $parents )
|
516 |
}
|
517 |
}
|
518 |
if ( ! $filtered ) {
|
519 |
+
// Only get the first tree through numeric ordering.
|
520 |
ksort( $assigned_ids, SORT_NUMERIC );
|
521 |
$tree_ids = $this->filter_ld_json_breadcrumb_trees( $tree_ids, key( $assigned_ids ) );
|
522 |
}
|
534 |
'taxonomy' => $taxonomy,
|
535 |
];
|
536 |
|
|
|
537 |
if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
|
538 |
$cat_name = $this->get_filtered_raw_custom_field_title( $_generator_args )
|
539 |
?: $this->get_generated_single_term_title( \get_term( $child_id, $taxonomy ) )
|
542 |
$cat_name = $this->get_generated_single_term_title( \get_term( $child_id, $taxonomy ) )
|
543 |
?: $this->get_static_untitled_title();
|
544 |
}
|
|
|
545 |
|
546 |
// Store in cache.
|
547 |
$items[] = [
|
576 |
* @param array $previous_tree A previous set tree to compare to, if set.
|
577 |
* @return array Trees in order.
|
578 |
*/
|
579 |
+
protected function build_ld_json_breadcrumb_trees( $cats, $previous_tree = [] ) {
|
580 |
|
581 |
$trees = $previous_tree;
|
582 |
|
648 |
* Memoizes the return value.
|
649 |
*
|
650 |
* @since 2.9.3
|
651 |
+
* @since 3.2.2 1. The title now works for the homepage as blog.
|
652 |
+
* 2. The image has been disabled for the homepage as blog.
|
653 |
+
* i. I couldn't fix it without evading the API, which is bad.
|
654 |
* @since 4.0.0 Removed the image input requirement.
|
655 |
*
|
656 |
* @return array The HomePage crumb entry.
|
657 |
*/
|
658 |
public function get_ld_json_breadcrumb_home_crumb() {
|
659 |
|
660 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
661 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
662 |
|
663 |
+
$_generator_args = [ 'id' => $this->get_the_front_page_ID() ];
|
|
|
|
|
|
|
664 |
|
665 |
if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
|
666 |
+
$title = $this->get_filtered_raw_custom_field_title( $_generator_args )
|
667 |
+
?: $this->get_blogname();
|
668 |
} else {
|
669 |
+
$title = $this->get_filtered_raw_generated_title( $_generator_args )
|
670 |
+
?: $this->get_blogname();
|
671 |
}
|
672 |
|
673 |
+
return memo( [
|
674 |
'@type' => 'ListItem',
|
675 |
'position' => 1,
|
676 |
'item' => [
|
677 |
'@id' => $this->get_schema_url_id( 'breadcrumb', 'homepage' ),
|
678 |
'name' => $this->escape_title( $title ),
|
679 |
],
|
680 |
+
] );
|
|
|
|
|
681 |
}
|
682 |
|
683 |
/**
|
703 |
}
|
704 |
|
705 |
$post_id = $this->get_the_real_ID();
|
706 |
+
$_generator_args = [ 'id' => $post_id ];
|
|
|
|
|
|
|
707 |
|
|
|
708 |
if ( $this->ld_json_breadcrumbs_use_seo_title() ) {
|
709 |
$name = $this->get_filtered_raw_custom_field_title( $_generator_args )
|
710 |
?: $this->get_generated_single_post_title( $post_id )
|
713 |
$name = $this->get_generated_single_post_title( $post_id )
|
714 |
?: $this->get_static_untitled_title();
|
715 |
}
|
|
|
716 |
|
717 |
$crumb = [
|
718 |
'@type' => 'ListItem',
|
743 |
|
744 |
static $it = 0;
|
745 |
|
746 |
+
$key = "breadcrumbs_{$it}";
|
747 |
|
748 |
$data = [
|
749 |
'@context' => 'https://schema.org',
|
804 |
* @return bool
|
805 |
*/
|
806 |
public function ld_json_breadcrumbs_use_seo_title() {
|
|
|
|
|
|
|
807 |
/**
|
808 |
* @since 2.9.0
|
809 |
* @param bool $use_seo_title Whether to use the SEO title.
|
810 |
*/
|
811 |
+
return memo() ?? memo( (bool) \apply_filters( 'the_seo_framework_use_breadcrumb_seo_title', true ) );
|
812 |
}
|
813 |
|
814 |
/**
|
815 |
* Determines if breadcrumbs scripts are enabled.
|
|
|
816 |
*
|
817 |
* @since 2.6.0
|
818 |
+
* @since 4.2.0 No longer memoizes the return value.
|
819 |
*
|
820 |
* @return bool
|
821 |
*/
|
822 |
public function enable_ld_json_breadcrumbs() {
|
|
|
|
|
|
|
|
|
|
|
|
|
823 |
/**
|
824 |
* @since 2.4.2
|
825 |
+
* @param bool $enable Whether to force disable Schema.org breadcrumbs.
|
826 |
*/
|
827 |
+
return (bool) \apply_filters( 'the_seo_framework_json_breadcrumb_output', $this->get_option( 'ld_json_breadcrumbs' ) );
|
|
|
|
|
|
|
828 |
}
|
829 |
|
830 |
/**
|
831 |
* Determines if searchbox script is enabled.
|
|
|
832 |
*
|
833 |
* @since 2.6.0
|
834 |
+
* @since 4.2.0 No longer memoizes the return value.
|
835 |
*
|
836 |
* @return bool
|
837 |
*/
|
838 |
public function enable_ld_json_searchbox() {
|
|
|
|
|
|
|
|
|
|
|
|
|
839 |
/**
|
840 |
* @since 2.3.9
|
841 |
+
* @param bool $enable Whether to force disable Schema.org searchbox.
|
842 |
*/
|
843 |
+
return (bool) \apply_filters( 'the_seo_framework_json_search_output', $this->get_option( 'ld_json_searchbox' ) );
|
|
|
|
|
|
|
844 |
}
|
845 |
|
846 |
/**
|
847 |
* Determines if Knowledge Graph Script is enabled.
|
|
|
848 |
*
|
849 |
* @since 2.6.5
|
850 |
+
* @since 4.2.0 No longer memoizes the return value.
|
851 |
*
|
852 |
* @return bool
|
853 |
*/
|
854 |
public function enable_ld_json_knowledge() {
|
|
|
|
|
|
|
|
|
|
|
|
|
855 |
/**
|
856 |
+
* @since 2.3.9
|
857 |
+
* @param bool $enable Whether to force disable Schema.org knowledge.
|
858 |
*/
|
859 |
+
return (bool) \apply_filters( 'the_seo_framework_json_knowledge_output', $this->get_option( 'knowledge_output' ) );
|
|
|
|
|
|
|
860 |
}
|
861 |
}
|
@@ -43,10 +43,11 @@ class Generate_Title extends Generate_Description {
|
|
43 |
* @since 3.1.0
|
44 |
* @since 3.2.2 No longer double-escapes the custom field title.
|
45 |
* @since 4.1.0 Added the third $social parameter.
|
|
|
46 |
* @uses $this->get_custom_field_title()
|
47 |
* @uses $this->get_generated_title()
|
48 |
*
|
49 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
50 |
* Leave null to autodetermine query.
|
51 |
* @param bool $escape Whether to escape the title.
|
52 |
* @param bool $social Whether the title is meant for social display.
|
@@ -54,10 +55,8 @@ class Generate_Title extends Generate_Description {
|
|
54 |
*/
|
55 |
public function get_title( $args = null, $escape = true, $social = false ) {
|
56 |
|
57 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
58 |
$title = $this->get_custom_field_title( $args, false, $social )
|
59 |
?: $this->get_generated_title( $args, false, $social );
|
60 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
61 |
|
62 |
return $escape ? $this->escape_title( $title ) : $title;
|
63 |
}
|
@@ -68,8 +67,9 @@ class Generate_Title extends Generate_Description {
|
|
68 |
* @since 3.1.0
|
69 |
* @since 4.0.0 Moved the filter to a separated method.
|
70 |
* @since 4.1.0 Added the third $social parameter.
|
|
|
71 |
*
|
72 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
73 |
* Leave null to autodetermine query.
|
74 |
* @param bool $escape Whether to escape the title.
|
75 |
* @param bool $social Whether the title is meant for social display.
|
@@ -101,10 +101,11 @@ class Generate_Title extends Generate_Description {
|
|
101 |
* 2. Moved check for title pagination.
|
102 |
* @since 4.0.0 Moved the filter to a separated method.
|
103 |
* @since 4.1.0 Added the third $social parameter.
|
|
|
104 |
* @uses $this->s_title_raw() : This is the same method used to prepare custom title on save.
|
105 |
* @uses $this->get_filtered_raw_generated_title()
|
106 |
*
|
107 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
108 |
* Leave null to autodetermine query.
|
109 |
* @param bool $escape Whether to escape the title.
|
110 |
* @param bool $social Whether the title is meant for social display.
|
@@ -132,19 +133,27 @@ class Generate_Title extends Generate_Description {
|
|
132 |
* Returns the raw filtered custom field meta title.
|
133 |
*
|
134 |
* @since 4.0.0
|
|
|
|
|
|
|
135 |
*
|
136 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
137 |
* Leave null to autodetermine query.
|
138 |
* @return string The raw generated title output.
|
139 |
*/
|
140 |
-
public function get_filtered_raw_custom_field_title( $args ) {
|
|
|
|
|
|
|
|
|
141 |
/**
|
142 |
* Filters the title from custom field, if any.
|
143 |
*
|
144 |
* @since 3.1.0
|
|
|
145 |
*
|
146 |
* @param string $title The title.
|
147 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
148 |
* Is null when query is autodetermined.
|
149 |
*/
|
150 |
return (string) \apply_filters_ref_array(
|
@@ -160,20 +169,28 @@ class Generate_Title extends Generate_Description {
|
|
160 |
* Returns the raw filtered autogenerated meta title.
|
161 |
*
|
162 |
* @since 4.0.0
|
|
|
|
|
|
|
163 |
*
|
164 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
165 |
* Leave null to autodetermine query.
|
166 |
* @return string The raw generated title output.
|
167 |
*/
|
168 |
-
public function get_filtered_raw_generated_title( $args ) {
|
|
|
|
|
|
|
|
|
169 |
/**
|
170 |
* Filters the title from query.
|
171 |
*
|
172 |
* @NOTE: This filter doesn't consistently run on the SEO Settings page.
|
173 |
-
* You may want to avoid this filter for the homepage, by returning the default value.
|
174 |
* @since 3.1.0
|
|
|
175 |
* @param string $title The title.
|
176 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
177 |
* Is null when query is autodetermined.
|
178 |
*/
|
179 |
return (string) \apply_filters_ref_array(
|
@@ -190,20 +207,19 @@ class Generate_Title extends Generate_Description {
|
|
190 |
* Falls back to Open Graph title.
|
191 |
*
|
192 |
* @since 3.0.4
|
193 |
-
* @since 3.1.0
|
194 |
-
*
|
|
|
195 |
*
|
196 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
197 |
* Leave null to autodetermine query.
|
198 |
* @param bool $escape Whether to escape the title.
|
199 |
* @return string Twitter Title.
|
200 |
*/
|
201 |
public function get_twitter_title( $args = null, $escape = true ) {
|
202 |
|
203 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
204 |
$title = $this->get_twitter_title_from_custom_field( $args, false )
|
205 |
?: $this->get_generated_twitter_title( $args, false );
|
206 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
207 |
|
208 |
return $escape ? $this->escape_title( $title ) : $title;
|
209 |
}
|
@@ -215,7 +231,7 @@ class Generate_Title extends Generate_Description {
|
|
215 |
* @since 3.1.0
|
216 |
* @see $this->get_twitter_title()
|
217 |
*
|
218 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
219 |
* @param bool $escape Whether to escape the title.
|
220 |
* @return string Twitter Title.
|
221 |
*/
|
@@ -238,6 +254,7 @@ class Generate_Title extends Generate_Description {
|
|
238 |
* @since 3.1.0
|
239 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
240 |
* @since 4.0.0 Added term meta item checks.
|
|
|
241 |
* @see $this->get_twitter_title()
|
242 |
* @see $this->get_twitter_title_from_custom_field()
|
243 |
*
|
@@ -246,7 +263,7 @@ class Generate_Title extends Generate_Description {
|
|
246 |
protected function get_custom_twitter_title_from_query() {
|
247 |
|
248 |
$title = '';
|
249 |
-
|
250 |
if ( $this->is_real_front_page() ) {
|
251 |
if ( $this->is_static_frontpage() ) {
|
252 |
$title = $this->get_option( 'homepage_twitter_title' )
|
@@ -267,8 +284,11 @@ class Generate_Title extends Generate_Description {
|
|
267 |
$title = $this->get_term_meta_item( 'tw_title' )
|
268 |
?: $this->get_term_meta_item( 'og_title' )
|
269 |
?: '';
|
|
|
|
|
|
|
|
|
270 |
}
|
271 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
272 |
|
273 |
return $title;
|
274 |
}
|
@@ -280,19 +300,23 @@ class Generate_Title extends Generate_Description {
|
|
280 |
* @since 3.1.0
|
281 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
282 |
* @since 4.0.0 Added term meta item checks.
|
|
|
283 |
* @see $this->get_twitter_title()
|
284 |
* @see $this->get_twitter_title_from_custom_field()
|
285 |
*
|
286 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
287 |
* @return string Twitter Title.
|
288 |
*/
|
289 |
-
protected function get_custom_twitter_title_from_args(
|
290 |
|
291 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
292 |
if ( $args['taxonomy'] ) {
|
293 |
$title = $this->get_term_meta_item( 'tw_title', $args['id'] )
|
294 |
?: $this->get_term_meta_item( 'og_title', $args['id'] )
|
295 |
?: '';
|
|
|
|
|
|
|
|
|
296 |
} else {
|
297 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
298 |
$title = $this->get_option( 'homepage_twitter_title' )
|
@@ -310,7 +334,6 @@ class Generate_Title extends Generate_Description {
|
|
310 |
?: '';
|
311 |
}
|
312 |
}
|
313 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
314 |
|
315 |
return $title;
|
316 |
}
|
@@ -322,9 +345,10 @@ class Generate_Title extends Generate_Description {
|
|
322 |
* @since 3.0.4
|
323 |
* @since 3.1.0 The first parameter now expects an array.
|
324 |
* @since 4.1.0 Now appends the "social" argument when getting the title.
|
|
|
325 |
* @uses $this->get_title()
|
326 |
*
|
327 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
328 |
* Leave null to autodetermine query.
|
329 |
* @param bool $escape Whether to escape the title.
|
330 |
* @return string The generated Twitter Title.
|
@@ -338,21 +362,20 @@ class Generate_Title extends Generate_Description {
|
|
338 |
* Falls back to meta title.
|
339 |
*
|
340 |
* @since 3.0.4
|
341 |
-
* @since 3.1.0
|
342 |
-
*
|
|
|
343 |
* @uses $this->get_generated_open_graph_title()
|
344 |
*
|
345 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
346 |
* Leave null to autodetermine query.
|
347 |
* @param bool $escape Whether to escape the title.
|
348 |
* @return string Open Graph Title.
|
349 |
*/
|
350 |
public function get_open_graph_title( $args = null, $escape = true ) {
|
351 |
|
352 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
353 |
$title = $this->get_open_graph_title_from_custom_field( $args, false )
|
354 |
?: $this->get_generated_open_graph_title( $args, false );
|
355 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
356 |
|
357 |
return $escape ? $this->escape_title( $title ) : $title;
|
358 |
}
|
@@ -364,7 +387,7 @@ class Generate_Title extends Generate_Description {
|
|
364 |
* @since 3.1.0
|
365 |
* @see $this->get_open_graph_title()
|
366 |
*
|
367 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
368 |
* @param bool $escape Whether to escape the title.
|
369 |
* @return string Open Graph Title.
|
370 |
*/
|
@@ -387,6 +410,7 @@ class Generate_Title extends Generate_Description {
|
|
387 |
* @since 3.1.0
|
388 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
389 |
* @since 4.0.0 Added term meta item checks.
|
|
|
390 |
* @see $this->get_open_graph_title()
|
391 |
* @see $this->get_open_graph_title_from_custom_field()
|
392 |
*
|
@@ -395,7 +419,6 @@ class Generate_Title extends Generate_Description {
|
|
395 |
protected function get_custom_open_graph_title_from_query() {
|
396 |
|
397 |
$title = '';
|
398 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
399 |
if ( $this->is_real_front_page() ) {
|
400 |
if ( $this->is_static_frontpage() ) {
|
401 |
$title = $this->get_option( 'homepage_og_title' )
|
@@ -408,8 +431,9 @@ class Generate_Title extends Generate_Description {
|
|
408 |
$title = $this->get_post_meta_item( '_open_graph_title' ) ?: '';
|
409 |
} elseif ( $this->is_term_meta_capable() ) {
|
410 |
$title = $this->get_term_meta_item( 'og_title' ) ?: '';
|
|
|
|
|
411 |
}
|
412 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
413 |
|
414 |
return $title;
|
415 |
}
|
@@ -421,18 +445,19 @@ class Generate_Title extends Generate_Description {
|
|
421 |
* @since 3.1.0
|
422 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
423 |
* @since 4.0.0 Added term meta item checks.
|
|
|
424 |
* @see $this->get_open_graph_title()
|
425 |
* @see $this->get_open_graph_title_from_custom_field()
|
426 |
*
|
427 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
428 |
* @return string Open Graph Title.
|
429 |
*/
|
430 |
-
protected function get_custom_open_graph_title_from_args(
|
431 |
|
432 |
-
$title = '';
|
433 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
434 |
if ( $args['taxonomy'] ) {
|
435 |
$title = $this->get_term_meta_item( 'og_title', $args['id'] ) ?: '';
|
|
|
|
|
436 |
} else {
|
437 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
438 |
$title = $this->get_option( 'homepage_og_title' )
|
@@ -444,7 +469,6 @@ class Generate_Title extends Generate_Description {
|
|
444 |
$title = $this->get_post_meta_item( '_open_graph_title', $args['id'] ) ?: '';
|
445 |
}
|
446 |
}
|
447 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
448 |
|
449 |
return $title;
|
450 |
}
|
@@ -456,9 +480,10 @@ class Generate_Title extends Generate_Description {
|
|
456 |
* @since 3.0.4
|
457 |
* @since 3.1.0 The first parameter now expects an array.
|
458 |
* @since 4.1.0 Now appends the "social" argument when getting the title.
|
|
|
459 |
* @uses $this->get_title()
|
460 |
*
|
461 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
462 |
* Leave null to autodetermine query.
|
463 |
* @param bool $escape Whether to escape the title.
|
464 |
* @return string The generated Open Graph Title.
|
@@ -474,9 +499,10 @@ class Generate_Title extends Generate_Description {
|
|
474 |
* finally admits through their code that terms can be queried using only IDs.
|
475 |
*
|
476 |
* @since 3.1.0
|
|
|
477 |
* @internal But, feel free to use it.
|
478 |
*
|
479 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
480 |
* Leave null to autodetermine query.
|
481 |
* @return string The custom field title, if it exists.
|
482 |
*/
|
@@ -499,6 +525,7 @@ class Generate_Title extends Generate_Description {
|
|
499 |
*
|
500 |
* @since 3.1.0
|
501 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
|
|
502 |
* @internal
|
503 |
* @see $this->get_raw_custom_field_title()
|
504 |
*
|
@@ -507,7 +534,7 @@ class Generate_Title extends Generate_Description {
|
|
507 |
protected function get_custom_field_title_from_query() {
|
508 |
|
509 |
$title = '';
|
510 |
-
|
511 |
if ( $this->is_real_front_page() ) {
|
512 |
if ( $this->is_static_frontpage() ) {
|
513 |
$title = $this->get_option( 'homepage_title' )
|
@@ -523,11 +550,16 @@ class Generate_Title extends Generate_Description {
|
|
523 |
} elseif ( \is_post_type_archive() ) {
|
524 |
/**
|
525 |
* @since 4.0.6
|
|
|
|
|
526 |
* @param string $title The post type archive title.
|
527 |
*/
|
528 |
-
$title = (string) \
|
|
|
|
|
|
|
|
|
529 |
}
|
530 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
531 |
|
532 |
return $title;
|
533 |
}
|
@@ -538,18 +570,19 @@ class Generate_Title extends Generate_Description {
|
|
538 |
* @since 3.1.0
|
539 |
* @since 3.1.4 Now uses the 'id' to get custom singular title.
|
540 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
|
|
541 |
* @internal
|
542 |
* @see $this->get_raw_custom_field_title()
|
543 |
*
|
544 |
-
* @param array $args The query arguments. Accepts 'id' and '
|
545 |
* @return string The custom title.
|
546 |
*/
|
547 |
-
protected function get_custom_field_title_from_args(
|
548 |
|
549 |
-
$title = '';
|
550 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
551 |
if ( $args['taxonomy'] ) {
|
552 |
$title = $this->get_term_meta_item( 'doctitle', $args['id'] ) ?: '';
|
|
|
|
|
553 |
} else {
|
554 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
555 |
$title = $this->get_option( 'homepage_title' )
|
@@ -561,7 +594,6 @@ class Generate_Title extends Generate_Description {
|
|
561 |
$title = $this->get_post_meta_item( '_genesis_title', $args['id'] ) ?: '';
|
562 |
}
|
563 |
}
|
564 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
565 |
|
566 |
return $title;
|
567 |
}
|
@@ -570,15 +602,20 @@ class Generate_Title extends Generate_Description {
|
|
570 |
* Generates a title, based on expected or current query, without additions or prefixes.
|
571 |
*
|
572 |
* @since 3.1.0
|
|
|
|
|
573 |
* @uses $this->generate_title_from_query()
|
574 |
* @uses $this->generate_title_from_args()
|
575 |
*
|
576 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
577 |
* Leave null to autodetermine query.
|
578 |
* @return string The generated title.
|
579 |
*/
|
580 |
public function get_raw_generated_title( $args = null ) {
|
581 |
|
|
|
|
|
|
|
582 |
$this->remove_default_title_filters( false, $args );
|
583 |
|
584 |
if ( null === $args ) {
|
@@ -590,7 +627,7 @@ class Generate_Title extends Generate_Description {
|
|
590 |
|
591 |
$this->reset_default_title_filters();
|
592 |
|
593 |
-
return $title ?: $this->get_static_untitled_title();
|
594 |
}
|
595 |
|
596 |
/**
|
@@ -604,7 +641,7 @@ class Generate_Title extends Generate_Description {
|
|
604 |
* @internal Only to be used within $this->get_raw_generated_title()
|
605 |
*
|
606 |
* @param bool $reset Whether to reset the removed filters.
|
607 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
608 |
* Leave null to autodetermine query.
|
609 |
*/
|
610 |
protected function remove_default_title_filters( $reset = false, $args = null ) {
|
@@ -624,6 +661,7 @@ class Generate_Title extends Generate_Description {
|
|
624 |
$filters = [ 'single_post_title', 'single_cat_title', 'single_tag_title' ];
|
625 |
} else {
|
626 |
$this->fix_generation_args( $args );
|
|
|
627 |
if ( 'category' === $args['taxonomy'] ) {
|
628 |
$filters = [ 'single_cat_title' ];
|
629 |
} elseif ( 'post_tag' === $args['taxonomy'] ) {
|
@@ -674,6 +712,7 @@ class Generate_Title extends Generate_Description {
|
|
674 |
* Generates a title, based on current query, without additions or prefixes.
|
675 |
*
|
676 |
* @since 3.1.0
|
|
|
677 |
* @internal
|
678 |
* @see $this->get_raw_generated_title()
|
679 |
*
|
@@ -689,10 +728,10 @@ class Generate_Title extends Generate_Description {
|
|
689 |
$title = $this->get_generated_search_query_title();
|
690 |
} elseif ( $this->is_real_front_page() ) {
|
691 |
$title = $this->get_static_front_page_title();
|
692 |
-
} elseif ( $this->is_archive() ) {
|
693 |
-
$title = $this->get_generated_archive_title();
|
694 |
} elseif ( $this->is_singular() ) {
|
695 |
$title = $this->get_generated_single_post_title();
|
|
|
|
|
696 |
}
|
697 |
|
698 |
return $title;
|
@@ -702,18 +741,21 @@ class Generate_Title extends Generate_Description {
|
|
702 |
* Generates a title, based on expected query, without additions or prefixes.
|
703 |
*
|
704 |
* @since 3.1.0
|
|
|
705 |
* @internal
|
706 |
* @see $this->get_raw_generated_title()
|
707 |
*
|
708 |
-
* @param array $args The query arguments. Required. Accepts 'id' and '
|
709 |
* @return string The generated title. Empty if query can't be replicated.
|
710 |
*/
|
711 |
-
protected function generate_title_from_args(
|
712 |
|
713 |
$title = '';
|
714 |
|
715 |
if ( $args['taxonomy'] ) {
|
716 |
$title = $this->get_generated_archive_title( \get_term( $args['id'], $args['taxonomy'] ) );
|
|
|
|
|
717 |
} else {
|
718 |
if ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
719 |
$title = $this->get_static_front_page_title();
|
@@ -728,32 +770,17 @@ class Generate_Title extends Generate_Description {
|
|
728 |
/**
|
729 |
* Generates front page title.
|
730 |
*
|
|
|
|
|
|
|
731 |
* @since 3.1.0
|
732 |
-
* @
|
|
|
733 |
*
|
734 |
* @return string The generated front page title.
|
735 |
*/
|
736 |
public function get_static_front_page_title() {
|
737 |
-
return
|
738 |
-
}
|
739 |
-
|
740 |
-
/**
|
741 |
-
* Combobulates archive title prefixes for WP 5.5+.
|
742 |
-
*
|
743 |
-
* @since 4.1.2
|
744 |
-
* @TEMP
|
745 |
-
*
|
746 |
-
* @param string $prefix The archive prefix.
|
747 |
-
* @param string $title The archive title.
|
748 |
-
* @return string The archive title.
|
749 |
-
*/
|
750 |
-
protected function _combobulate_wp550_archive_title( $prefix, $title ) {
|
751 |
-
return sprintf(
|
752 |
-
/* translators: 1: Title prefix. 2: Title. */
|
753 |
-
\_x( '%1$s %2$s', 'archive title', 'default' ),
|
754 |
-
$prefix,
|
755 |
-
$title
|
756 |
-
);
|
757 |
}
|
758 |
|
759 |
/**
|
@@ -769,207 +796,231 @@ class Generate_Title extends Generate_Description {
|
|
769 |
* 2: The first parameter now accepts `\WP_User` objects.
|
770 |
* @since 4.1.2 Now supports WP 5.5 archive titles.
|
771 |
*
|
772 |
-
* @param \WP_Term|\WP_User|\WP_Error|null $
|
773 |
-
*
|
|
|
|
|
774 |
*/
|
775 |
-
public function get_generated_archive_title( $
|
776 |
|
777 |
-
if ( $
|
778 |
return '';
|
779 |
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
786 |
|
787 |
/**
|
788 |
* @since 2.6.0
|
789 |
*
|
790 |
-
* @param string
|
791 |
-
* @param \WP_Term|\WP_User $
|
792 |
*/
|
793 |
-
$title = (string) \
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
794 |
|
795 |
if ( $title )
|
796 |
-
return $title;
|
797 |
-
|
798 |
-
$_tax = isset( $term->taxonomy ) ? $term->taxonomy : '';
|
799 |
-
$use_prefix = $this->use_generated_archive_prefix( $term );
|
800 |
-
|
801 |
-
// TEMP hack. Let's clean this up later.
|
802 |
-
$use_new_string_prefixes = $use_prefix && version_compare( \get_bloginfo( 'version' ), '5.5', '>=' );
|
803 |
-
|
804 |
-
if ( ! $_query ) {
|
805 |
-
if ( $_tax ) {
|
806 |
-
if ( 'category' === $_tax ) {
|
807 |
-
$title = $this->get_generated_single_term_title( $term );
|
808 |
-
|
809 |
-
if ( $use_new_string_prefixes ) {
|
810 |
-
$title = $this->_combobulate_wp550_archive_title(
|
811 |
-
\_x( 'Category:', 'category archive title prefix', 'default' ),
|
812 |
-
$title
|
813 |
-
);
|
814 |
-
} else {
|
815 |
-
/* translators: Category archive title. 1: Category name */
|
816 |
-
$title = $use_prefix ? sprintf( \__( 'Category: %s', 'default' ), $title ) : $title;
|
817 |
-
}
|
818 |
-
} elseif ( 'post_tag' === $_tax ) {
|
819 |
-
$title = $this->get_generated_single_term_title( $term );
|
820 |
-
|
821 |
-
if ( $use_new_string_prefixes ) {
|
822 |
-
$title = $this->_combobulate_wp550_archive_title(
|
823 |
-
\_x( 'Tag:', 'tag archive title prefix', 'default' ),
|
824 |
-
$title
|
825 |
-
);
|
826 |
-
} else {
|
827 |
-
/* translators: Tag archive title. 1: Tag name */
|
828 |
-
$title = $use_prefix ? sprintf( \__( 'Tag: %s', 'default' ), $title ) : $title;
|
829 |
-
}
|
830 |
-
} else {
|
831 |
-
$title = $this->get_generated_single_term_title( $term );
|
832 |
-
$title = $use_prefix ? $this->prepend_tax_label_prefix( $title, $_tax ) : $title;
|
833 |
-
}
|
834 |
-
} elseif ( $term instanceof \WP_User && isset( $term->display_name ) ) {
|
835 |
-
$title = $term->display_name;
|
836 |
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
$title
|
841 |
-
);
|
842 |
-
} else {
|
843 |
-
/* translators: Author archive title. 1: Author name */
|
844 |
-
$title = $use_prefix ? sprintf( \__( 'Author: %s', 'default' ), $title ) : $title;
|
845 |
-
}
|
846 |
-
} else {
|
847 |
-
$title = \__( 'Archives', 'default' );
|
848 |
-
}
|
849 |
-
} else {
|
850 |
-
if ( $this->is_category() ) {
|
851 |
-
$title = $this->get_generated_single_term_title( $term );
|
852 |
-
|
853 |
-
if ( $use_new_string_prefixes ) {
|
854 |
-
$title = $this->_combobulate_wp550_archive_title(
|
855 |
-
\_x( 'Category:', 'category archive title prefix', 'default' ),
|
856 |
-
$title
|
857 |
-
);
|
858 |
-
} else {
|
859 |
-
/* translators: Category archive title. 1: Category name */
|
860 |
-
$title = $use_prefix ? sprintf( \__( 'Category: %s', 'default' ), $title ) : $title;
|
861 |
-
}
|
862 |
-
} elseif ( $this->is_tag() ) {
|
863 |
-
$title = $this->get_generated_single_term_title( $term );
|
864 |
|
865 |
-
|
866 |
-
$title = $this->_combobulate_wp550_archive_title(
|
867 |
-
\_x( 'Tag:', 'tag archive title prefix', 'default' ),
|
868 |
-
$title
|
869 |
-
);
|
870 |
-
} else {
|
871 |
-
/* translators: Tag archive title. 1: Tag name */
|
872 |
-
$title = $use_prefix ? sprintf( \__( 'Tag: %s', 'default' ), $title ) : $title;
|
873 |
-
}
|
874 |
-
} elseif ( $this->is_author() ) {
|
875 |
-
$title = isset( $term->display_name ) ? $term->display_name : '';
|
876 |
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
/* translators: Yearly archive title. 1: Year */
|
897 |
-
$title = $use_prefix ? sprintf( \__( 'Year: %s', 'default' ), $title ) : $title;
|
898 |
-
}
|
899 |
-
} elseif ( $this->is_month() ) {
|
900 |
-
$title = \get_the_date( \_x( 'F Y', 'monthly archives date format', 'default' ) );
|
901 |
-
|
902 |
-
if ( $use_new_string_prefixes ) {
|
903 |
-
$title = $this->_combobulate_wp550_archive_title(
|
904 |
-
\_x( 'Month:', 'date archive title prefix', 'default' ),
|
905 |
-
$title
|
906 |
-
);
|
907 |
-
} else {
|
908 |
-
/* translators: Monthly archive title. 1: Month name and year */
|
909 |
-
$title = $use_prefix ? sprintf( \__( 'Month: %s', 'default' ), $title ) : $title;
|
910 |
-
}
|
911 |
-
} elseif ( $this->is_day() ) {
|
912 |
-
$title = \get_the_date( \_x( 'F j, Y', 'daily archives date format', 'default' ) );
|
913 |
-
|
914 |
-
if ( $use_new_string_prefixes ) {
|
915 |
-
$title = $this->_combobulate_wp550_archive_title(
|
916 |
-
\_x( 'Day:', 'date archive title prefix', 'default' ),
|
917 |
-
$title
|
918 |
-
);
|
919 |
-
} else {
|
920 |
-
/* translators: Daily archive title. 1: Date */
|
921 |
-
$title = $use_prefix ? sprintf( \__( 'Day: %s', 'default' ), $title ) : $title;
|
922 |
-
}
|
923 |
-
}
|
924 |
-
} elseif ( \is_tax( 'post_format' ) ) {
|
925 |
-
if ( \is_tax( 'post_format', 'post-format-aside' ) ) {
|
926 |
-
$title = \_x( 'Asides', 'post format archive title', 'default' );
|
927 |
-
} elseif ( \is_tax( 'post_format', 'post-format-gallery' ) ) {
|
928 |
-
$title = \_x( 'Galleries', 'post format archive title', 'default' );
|
929 |
-
} elseif ( \is_tax( 'post_format', 'post-format-image' ) ) {
|
930 |
-
$title = \_x( 'Images', 'post format archive title', 'default' );
|
931 |
-
} elseif ( \is_tax( 'post_format', 'post-format-video' ) ) {
|
932 |
-
$title = \_x( 'Videos', 'post format archive title', 'default' );
|
933 |
-
} elseif ( \is_tax( 'post_format', 'post-format-quote' ) ) {
|
934 |
-
$title = \_x( 'Quotes', 'post format archive title', 'default' );
|
935 |
-
} elseif ( \is_tax( 'post_format', 'post-format-link' ) ) {
|
936 |
-
$title = \_x( 'Links', 'post format archive title', 'default' );
|
937 |
-
} elseif ( \is_tax( 'post_format', 'post-format-status' ) ) {
|
938 |
-
$title = \_x( 'Statuses', 'post format archive title', 'default' );
|
939 |
-
} elseif ( \is_tax( 'post_format', 'post-format-audio' ) ) {
|
940 |
-
$title = \_x( 'Audio', 'post format archive title', 'default' );
|
941 |
-
} elseif ( \is_tax( 'post_format', 'post-format-chat' ) ) {
|
942 |
-
$title = \_x( 'Chats', 'post format archive title', 'default' );
|
943 |
-
}
|
944 |
-
} elseif ( \is_post_type_archive() ) {
|
945 |
-
$title = $this->get_generated_post_type_archive_title() ?: $this->get_tax_type_label( $_tax, false );
|
946 |
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
$title = $use_prefix ? sprintf( \__( 'Archives: %s', 'default' ), $title ) : $title;
|
955 |
-
}
|
956 |
-
} elseif ( $this->is_tax() ) {
|
957 |
-
$title = $this->get_generated_single_term_title( $term );
|
958 |
-
$title = $use_prefix ? $this->prepend_tax_label_prefix( $title, $_tax ) : $title;
|
959 |
-
} else {
|
960 |
-
$title = \__( 'Archives', 'default' );
|
961 |
}
|
962 |
}
|
963 |
|
964 |
/**
|
965 |
* Filters the archive title.
|
|
|
|
|
966 |
*
|
967 |
* @since 3.0.4
|
|
|
968 |
*
|
969 |
-
* @param string
|
970 |
-
* @param \WP_Term $
|
|
|
|
|
971 |
*/
|
972 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
973 |
}
|
974 |
|
975 |
/**
|
@@ -987,7 +1038,6 @@ class Generate_Title extends Generate_Description {
|
|
987 |
|
988 |
//? Home queries can be tricky. Use get_the_real_ID to be certain.
|
989 |
$_post = \get_post( $id ?: $this->get_the_real_ID() );
|
990 |
-
$title = '';
|
991 |
|
992 |
if ( isset( $_post->post_title ) ) {
|
993 |
/**
|
@@ -1001,7 +1051,7 @@ class Generate_Title extends Generate_Description {
|
|
1001 |
$title = \apply_filters( 'single_post_title', $_post->post_title, $_post );
|
1002 |
}
|
1003 |
|
1004 |
-
return $title;
|
1005 |
}
|
1006 |
|
1007 |
/**
|
@@ -1009,10 +1059,9 @@ class Generate_Title extends Generate_Description {
|
|
1009 |
*
|
1010 |
* It can autodetermine the term; so, perform your checks prior calling.
|
1011 |
*
|
1012 |
-
*
|
|
|
1013 |
* @see WP Core single_term_title()
|
1014 |
-
* TODO Term names may not be empty. But, if you insert illegal characters when updating/creating a term (e.g. `<tag>`)
|
1015 |
-
* the term name will be empty. When prefixes are added to the term (e.g. `Category:`), only that will be shown.
|
1016 |
*
|
1017 |
* @since 3.1.0
|
1018 |
* @since 4.0.0 No longer redundantly tests the query, now only uses the term input or queried object.
|
@@ -1026,10 +1075,10 @@ class Generate_Title extends Generate_Description {
|
|
1026 |
if ( \is_null( $term ) )
|
1027 |
$term = \get_queried_object();
|
1028 |
|
1029 |
-
$
|
1030 |
|
1031 |
-
|
1032 |
-
|
1033 |
/**
|
1034 |
* Filter the category archive page title.
|
1035 |
*
|
@@ -1038,7 +1087,8 @@ class Generate_Title extends Generate_Description {
|
|
1038 |
* @param string $term_name Category name for archive being displayed.
|
1039 |
*/
|
1040 |
$term_name = \apply_filters( 'single_cat_title', $term->name );
|
1041 |
-
|
|
|
1042 |
/**
|
1043 |
* Filter the tag archive page title.
|
1044 |
*
|
@@ -1047,7 +1097,8 @@ class Generate_Title extends Generate_Description {
|
|
1047 |
* @param string $term_name Tag name for archive being displayed.
|
1048 |
*/
|
1049 |
$term_name = \apply_filters( 'single_tag_title', $term->name );
|
1050 |
-
|
|
|
1051 |
/**
|
1052 |
* Filter the custom taxonomy archive page title.
|
1053 |
*
|
@@ -1056,12 +1107,9 @@ class Generate_Title extends Generate_Description {
|
|
1056 |
* @param string $term_name Term name for archive being displayed.
|
1057 |
*/
|
1058 |
$term_name = \apply_filters( 'single_term_title', $term->name );
|
1059 |
-
|
1060 |
-
|
1061 |
|
1062 |
-
// Store the prefix sprintf at get_generated_archive_title() instead and set this on title capture failure?
|
1063 |
-
// We're working around a bug in WordPress here. This should be fixed inside WordPress! Forgo.
|
1064 |
-
// return strlen( $term_name ) ? $term_name : $this->get_static_untitled_title();
|
1065 |
return $term_name;
|
1066 |
}
|
1067 |
|
@@ -1072,21 +1120,23 @@ class Generate_Title extends Generate_Description {
|
|
1072 |
* @see WP Core post_type_archive_title()
|
1073 |
*
|
1074 |
* @since 3.1.0
|
|
|
1075 |
*
|
1076 |
* @param string $post_type The post type.
|
1077 |
* @return string The generated post type archive title.
|
1078 |
*/
|
1079 |
public function get_generated_post_type_archive_title( $post_type = '' ) {
|
1080 |
|
1081 |
-
|
1082 |
-
|
1083 |
-
if ( ! \is_post_type_archive( $post_type ) )
|
1084 |
return '';
|
1085 |
|
|
|
|
|
1086 |
if ( \is_array( $post_type ) )
|
1087 |
$post_type = reset( $post_type );
|
1088 |
|
1089 |
-
|
|
|
1090 |
|
1091 |
/**
|
1092 |
* Filters the post type archive title.
|
@@ -1096,7 +1146,13 @@ class Generate_Title extends Generate_Description {
|
|
1096 |
* @param string $post_type_name Post type 'name' label.
|
1097 |
* @param string $post_type Post type.
|
1098 |
*/
|
1099 |
-
$title = \
|
|
|
|
|
|
|
|
|
|
|
|
|
1100 |
|
1101 |
return $title;
|
1102 |
}
|
@@ -1146,11 +1202,12 @@ class Generate_Title extends Generate_Description {
|
|
1146 |
* @since 3.1.0
|
1147 |
* @since 3.1.2 Added strict taxonomical check.
|
1148 |
* @since 3.1.3 Fixed conditional logic.
|
|
|
1149 |
* @uses $this->get_title_branding_from_query()
|
1150 |
* @uses $this->get_title_branding_from_args()
|
1151 |
*
|
1152 |
* @param string $title The title. Passed by reference.
|
1153 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
1154 |
* Leave null to autodetermine query.
|
1155 |
*/
|
1156 |
public function merge_title_branding( &$title, $args = null ) {
|
@@ -1201,14 +1258,15 @@ class Generate_Title extends Generate_Description {
|
|
1201 |
* Returns the addition and seplocation from arguments.
|
1202 |
*
|
1203 |
* @since 3.2.2
|
|
|
1204 |
* @see $this->merge_title_branding();
|
1205 |
*
|
1206 |
-
* @param array $args The query arguments. Accepts 'id' and '
|
1207 |
* @return array { 'addition', 'seplocation' }
|
1208 |
*/
|
1209 |
-
protected function get_title_branding_from_args(
|
1210 |
|
1211 |
-
if ( ! $args['taxonomy'] && $this->is_real_front_page_by_id( $args['id'] ) ) {
|
1212 |
$addition = $this->get_home_title_additions();
|
1213 |
$seplocation = $this->get_home_title_seplocation();
|
1214 |
} else {
|
@@ -1252,10 +1310,11 @@ class Generate_Title extends Generate_Description {
|
|
1252 |
* @since 3.1.0
|
1253 |
* @since 3.1.2 Added strict taxonomical checks for title protection.
|
1254 |
* @since 3.1.3 Fixed conditional logic.
|
|
|
1255 |
* @see $this->merge_title_prefixes()
|
1256 |
*
|
1257 |
* @param string $title The title. Passed by reference.
|
1258 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
1259 |
* Leave null to autodetermine query.
|
1260 |
* @return void
|
1261 |
*/
|
@@ -1263,14 +1322,14 @@ class Generate_Title extends Generate_Description {
|
|
1263 |
|
1264 |
if ( null === $args ) {
|
1265 |
$id = $this->get_the_real_ID();
|
1266 |
-
$
|
1267 |
} else {
|
1268 |
$this->fix_generation_args( $args );
|
1269 |
$id = $args['id'];
|
1270 |
-
$
|
1271 |
}
|
1272 |
|
1273 |
-
if ( $
|
1274 |
|
1275 |
$post = $id ? \get_post( $id ) : null;
|
1276 |
|
@@ -1356,50 +1415,15 @@ class Generate_Title extends Generate_Description {
|
|
1356 |
return $this->get_title_seplocation( true );
|
1357 |
}
|
1358 |
|
1359 |
-
/**
|
1360 |
-
* Prepends the taxonomy label to the title.
|
1361 |
-
*
|
1362 |
-
* @since 4.1.0
|
1363 |
-
* @since 4.1.2 Now supports WP 5.5 archive titles.
|
1364 |
-
*
|
1365 |
-
* @param string $title The title to prepend taxonomy label to.
|
1366 |
-
* @param string $taxonomy The taxonomy to get label from.
|
1367 |
-
* @return string The title with possibly prepended tax-label.
|
1368 |
-
*/
|
1369 |
-
public function prepend_tax_label_prefix( $title, $taxonomy ) {
|
1370 |
-
|
1371 |
-
$prefix = $this->get_tax_type_label( $taxonomy ) ?: '';
|
1372 |
-
|
1373 |
-
if ( $prefix ) {
|
1374 |
-
$use_new_string_prefixes = version_compare( \get_bloginfo( 'version' ), '5.5', '>=' );
|
1375 |
-
|
1376 |
-
if ( $use_new_string_prefixes ) {
|
1377 |
-
$title = $this->_combobulate_wp550_archive_title(
|
1378 |
-
/* translators: %s: Taxonomy singular name. */
|
1379 |
-
sprintf( \_x( '%s:', 'taxonomy term archive title prefix', 'default' ), $prefix ),
|
1380 |
-
$title
|
1381 |
-
);
|
1382 |
-
} else {
|
1383 |
-
$title = sprintf(
|
1384 |
-
/* translators: Taxonomy term archive title. 1: Taxonomy singular name, 2: Current taxonomy term. */
|
1385 |
-
\__( '%1$s: %2$s', 'default' ),
|
1386 |
-
$prefix,
|
1387 |
-
$title
|
1388 |
-
);
|
1389 |
-
}
|
1390 |
-
}
|
1391 |
-
|
1392 |
-
return $title;
|
1393 |
-
}
|
1394 |
-
|
1395 |
/**
|
1396 |
* Determines whether to add or remove title protection prefixes.
|
1397 |
*
|
1398 |
* @since 3.2.4
|
|
|
1399 |
* NOTE: This does not guarantee that protection is to be added. Only that it will be considered. Bad method name.
|
1400 |
* @see $this->merge_title_protection()
|
1401 |
*
|
1402 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
1403 |
* Leave null to autodetermine query.
|
1404 |
* @return bool True when prefixes are allowed.
|
1405 |
*/
|
@@ -1408,8 +1432,8 @@ class Generate_Title extends Generate_Description {
|
|
1408 |
if ( null === $args ) {
|
1409 |
$use = $this->is_singular();
|
1410 |
} else {
|
1411 |
-
$this->fix_generation_args( $args );
|
1412 |
-
$use = $args && ! $args['taxonomy'];
|
1413 |
}
|
1414 |
|
1415 |
return $use;
|
@@ -1422,7 +1446,7 @@ class Generate_Title extends Generate_Description {
|
|
1422 |
* NOTE: This does not guarantee that pagination is to be added. Only that it will be considered. Bad method name.
|
1423 |
* @see $this->merge_title_pagination()
|
1424 |
*
|
1425 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
1426 |
* Leave null to autodetermine query.
|
1427 |
* @return bool True when additions are allowed.
|
1428 |
*/
|
@@ -1446,28 +1470,27 @@ class Generate_Title extends Generate_Description {
|
|
1446 |
* Determines whether to add or remove title branding additions.
|
1447 |
*
|
1448 |
* @since 3.1.0
|
1449 |
-
* @since 3.1.2
|
1450 |
-
*
|
1451 |
* @since 3.2.2 Now differentiates from query and parameter input.
|
1452 |
* @since 4.1.0 Added the second $social parameter.
|
|
|
1453 |
* @see $this->merge_title_branding()
|
1454 |
* @uses $this->use_title_branding_from_query()
|
1455 |
* @uses $this->use_title_branding_from_args()
|
1456 |
*
|
1457 |
-
* @param array|null
|
1458 |
* Leave null to autodetermine query.
|
1459 |
-
* @param bool
|
|
|
1460 |
* @return bool True when additions are allowed.
|
1461 |
*/
|
1462 |
public function use_title_branding( $args = null, $social = false ) {
|
1463 |
|
1464 |
-
|
1465 |
-
|
1466 |
-
if ( $social ) {
|
1467 |
-
$use = ! $this->get_option( 'social_title_rem_additions' );
|
1468 |
-
}
|
1469 |
|
1470 |
-
//
|
1471 |
if ( $use ) {
|
1472 |
if ( null === $args ) {
|
1473 |
$use = $this->use_title_branding_from_query();
|
@@ -1481,11 +1504,18 @@ class Generate_Title extends Generate_Description {
|
|
1481 |
* @since 3.1.2
|
1482 |
* @since 4.1.0 Added the third $social parameter.
|
1483 |
* @param string $use Whether to use branding.
|
1484 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
1485 |
* Is null when query is autodetermined.
|
1486 |
* @param bool $social Whether the title is meant for social display.
|
1487 |
*/
|
1488 |
-
return \apply_filters_ref_array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1489 |
}
|
1490 |
|
1491 |
/**
|
@@ -1494,6 +1524,7 @@ class Generate_Title extends Generate_Description {
|
|
1494 |
* @since 3.2.2
|
1495 |
* @since 4.0.0 Added use_taxonomical_title_branding() check.
|
1496 |
* @since 4.0.2 Removed contemned \is_post_type_archive() check for taxonomical branding.
|
|
|
1497 |
* @see $this->use_title_branding()
|
1498 |
*
|
1499 |
* @return bool
|
@@ -1506,6 +1537,8 @@ class Generate_Title extends Generate_Description {
|
|
1506 |
$use = $this->use_singular_title_branding();
|
1507 |
} elseif ( $this->is_term_meta_capable() ) {
|
1508 |
$use = $this->use_taxonomical_title_branding();
|
|
|
|
|
1509 |
} else {
|
1510 |
$use = ! $this->get_option( 'title_rem_additions' );
|
1511 |
}
|
@@ -1518,15 +1551,19 @@ class Generate_Title extends Generate_Description {
|
|
1518 |
*
|
1519 |
* @since 3.2.2
|
1520 |
* @since 4.0.0 Added use_taxonomical_title_branding() check.
|
|
|
|
|
1521 |
* @see $this->use_title_branding()
|
1522 |
*
|
1523 |
-
* @param array $args The query arguments. Accepts 'id' and '
|
1524 |
* @return bool
|
1525 |
*/
|
1526 |
-
protected function use_title_branding_from_args(
|
1527 |
|
1528 |
if ( $args['taxonomy'] ) {
|
1529 |
$use = $this->use_taxonomical_title_branding( $args['id'] );
|
|
|
|
|
1530 |
} else {
|
1531 |
if ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
1532 |
$use = $this->use_home_page_title_tagline();
|
@@ -1545,18 +1582,18 @@ class Generate_Title extends Generate_Description {
|
|
1545 |
* @since 4.0.5 1: Added first parameter `$term`.
|
1546 |
* 2: Added filter.
|
1547 |
*
|
1548 |
-
* @param \WP_Term|\WP_User|null $term The Term object. Leave null to autodermine query.
|
1549 |
* @return bool
|
1550 |
*/
|
1551 |
public function use_generated_archive_prefix( $term = null ) {
|
1552 |
|
1553 |
-
$term =
|
1554 |
$use = ! $this->get_option( 'title_rem_prefixes' );
|
1555 |
|
1556 |
/**
|
1557 |
* @since 4.0.5
|
1558 |
-
* @param string
|
1559 |
-
* @param \WP_Term|\WP_User $term The current term.
|
1560 |
*/
|
1561 |
return \apply_filters_ref_array( 'the_seo_framework_use_archive_prefix', [ $use, $term ] );
|
1562 |
}
|
@@ -1597,6 +1634,18 @@ class Generate_Title extends Generate_Description {
|
|
1597 |
return ! $this->get_term_meta_item( 'title_no_blog_name', $id ) && ! $this->get_option( 'title_rem_additions' );
|
1598 |
}
|
1599 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1600 |
/**
|
1601 |
* Returns the homepage additions (tagline) from option or bloginfo, when set.
|
1602 |
* Memoizes the return value.
|
@@ -1607,11 +1656,12 @@ class Generate_Title extends Generate_Description {
|
|
1607 |
* @return string The trimmed tagline.
|
1608 |
*/
|
1609 |
public function get_home_title_additions() {
|
1610 |
-
|
1611 |
-
|
1612 |
-
|
1613 |
-
|
1614 |
-
|
|
|
1615 |
);
|
1616 |
}
|
1617 |
}
|
43 |
* @since 3.1.0
|
44 |
* @since 3.2.2 No longer double-escapes the custom field title.
|
45 |
* @since 4.1.0 Added the third $social parameter.
|
46 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
47 |
* @uses $this->get_custom_field_title()
|
48 |
* @uses $this->get_generated_title()
|
49 |
*
|
50 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
51 |
* Leave null to autodetermine query.
|
52 |
* @param bool $escape Whether to escape the title.
|
53 |
* @param bool $social Whether the title is meant for social display.
|
55 |
*/
|
56 |
public function get_title( $args = null, $escape = true, $social = false ) {
|
57 |
|
|
|
58 |
$title = $this->get_custom_field_title( $args, false, $social )
|
59 |
?: $this->get_generated_title( $args, false, $social );
|
|
|
60 |
|
61 |
return $escape ? $this->escape_title( $title ) : $title;
|
62 |
}
|
67 |
* @since 3.1.0
|
68 |
* @since 4.0.0 Moved the filter to a separated method.
|
69 |
* @since 4.1.0 Added the third $social parameter.
|
70 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
71 |
*
|
72 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
73 |
* Leave null to autodetermine query.
|
74 |
* @param bool $escape Whether to escape the title.
|
75 |
* @param bool $social Whether the title is meant for social display.
|
101 |
* 2. Moved check for title pagination.
|
102 |
* @since 4.0.0 Moved the filter to a separated method.
|
103 |
* @since 4.1.0 Added the third $social parameter.
|
104 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
105 |
* @uses $this->s_title_raw() : This is the same method used to prepare custom title on save.
|
106 |
* @uses $this->get_filtered_raw_generated_title()
|
107 |
*
|
108 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
109 |
* Leave null to autodetermine query.
|
110 |
* @param bool $escape Whether to escape the title.
|
111 |
* @param bool $social Whether the title is meant for social display.
|
133 |
* Returns the raw filtered custom field meta title.
|
134 |
*
|
135 |
* @since 4.0.0
|
136 |
+
* @since 4.2.0 1. The first parameter can now be voided.
|
137 |
+
* 2. The first parameter is now rectified, so you can leave out indexes.
|
138 |
+
* 3. Now supports the `$args['pta']` index.
|
139 |
*
|
140 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
141 |
* Leave null to autodetermine query.
|
142 |
* @return string The raw generated title output.
|
143 |
*/
|
144 |
+
public function get_filtered_raw_custom_field_title( $args = null ) {
|
145 |
+
|
146 |
+
if ( null !== $args )
|
147 |
+
$this->fix_generation_args( $args );
|
148 |
+
|
149 |
/**
|
150 |
* Filters the title from custom field, if any.
|
151 |
*
|
152 |
* @since 3.1.0
|
153 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
154 |
*
|
155 |
* @param string $title The title.
|
156 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
157 |
* Is null when query is autodetermined.
|
158 |
*/
|
159 |
return (string) \apply_filters_ref_array(
|
169 |
* Returns the raw filtered autogenerated meta title.
|
170 |
*
|
171 |
* @since 4.0.0
|
172 |
+
* @since 4.2.0 1. The first parameter can now be voided.
|
173 |
+
* 2. The first parameter is now rectified, so you can leave out indexes.
|
174 |
+
* 3. Now supports the `$args['pta']` index.
|
175 |
*
|
176 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
177 |
* Leave null to autodetermine query.
|
178 |
* @return string The raw generated title output.
|
179 |
*/
|
180 |
+
public function get_filtered_raw_generated_title( $args = null ) {
|
181 |
+
|
182 |
+
if ( null !== $args )
|
183 |
+
$this->fix_generation_args( $args );
|
184 |
+
|
185 |
/**
|
186 |
* Filters the title from query.
|
187 |
*
|
188 |
* @NOTE: This filter doesn't consistently run on the SEO Settings page.
|
189 |
+
* You may want to avoid this filter for the homepage and pta, by returning the default value.
|
190 |
* @since 3.1.0
|
191 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
192 |
* @param string $title The title.
|
193 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
194 |
* Is null when query is autodetermined.
|
195 |
*/
|
196 |
return (string) \apply_filters_ref_array(
|
207 |
* Falls back to Open Graph title.
|
208 |
*
|
209 |
* @since 3.0.4
|
210 |
+
* @since 3.1.0 1. The first parameter now expects an array.
|
211 |
+
* 2. Now tries to get the homepage social titles.
|
212 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
213 |
*
|
214 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
215 |
* Leave null to autodetermine query.
|
216 |
* @param bool $escape Whether to escape the title.
|
217 |
* @return string Twitter Title.
|
218 |
*/
|
219 |
public function get_twitter_title( $args = null, $escape = true ) {
|
220 |
|
|
|
221 |
$title = $this->get_twitter_title_from_custom_field( $args, false )
|
222 |
?: $this->get_generated_twitter_title( $args, false );
|
|
|
223 |
|
224 |
return $escape ? $this->escape_title( $title ) : $title;
|
225 |
}
|
231 |
* @since 3.1.0
|
232 |
* @see $this->get_twitter_title()
|
233 |
*
|
234 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
235 |
* @param bool $escape Whether to escape the title.
|
236 |
* @return string Twitter Title.
|
237 |
*/
|
254 |
* @since 3.1.0
|
255 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
256 |
* @since 4.0.0 Added term meta item checks.
|
257 |
+
* @since 4.2.0 Can now return custom post type archive titles.
|
258 |
* @see $this->get_twitter_title()
|
259 |
* @see $this->get_twitter_title_from_custom_field()
|
260 |
*
|
263 |
protected function get_custom_twitter_title_from_query() {
|
264 |
|
265 |
$title = '';
|
266 |
+
|
267 |
if ( $this->is_real_front_page() ) {
|
268 |
if ( $this->is_static_frontpage() ) {
|
269 |
$title = $this->get_option( 'homepage_twitter_title' )
|
284 |
$title = $this->get_term_meta_item( 'tw_title' )
|
285 |
?: $this->get_term_meta_item( 'og_title' )
|
286 |
?: '';
|
287 |
+
} elseif ( \is_post_type_archive() ) {
|
288 |
+
$title = $this->get_post_type_archive_meta_item( 'tw_title' )
|
289 |
+
?: $this->get_post_type_archive_meta_item( 'og_title' )
|
290 |
+
?: '';
|
291 |
}
|
|
|
292 |
|
293 |
return $title;
|
294 |
}
|
300 |
* @since 3.1.0
|
301 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
302 |
* @since 4.0.0 Added term meta item checks.
|
303 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
304 |
* @see $this->get_twitter_title()
|
305 |
* @see $this->get_twitter_title_from_custom_field()
|
306 |
*
|
307 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
308 |
* @return string Twitter Title.
|
309 |
*/
|
310 |
+
protected function get_custom_twitter_title_from_args( $args ) {
|
311 |
|
|
|
312 |
if ( $args['taxonomy'] ) {
|
313 |
$title = $this->get_term_meta_item( 'tw_title', $args['id'] )
|
314 |
?: $this->get_term_meta_item( 'og_title', $args['id'] )
|
315 |
?: '';
|
316 |
+
} elseif ( $args['pta'] ) {
|
317 |
+
$title = $this->get_post_type_archive_meta_item( 'tw_title', $args['pta'] )
|
318 |
+
?: $this->get_post_type_archive_meta_item( 'og_title', $args['pta'] )
|
319 |
+
?: '';
|
320 |
} else {
|
321 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
322 |
$title = $this->get_option( 'homepage_twitter_title' )
|
334 |
?: '';
|
335 |
}
|
336 |
}
|
|
|
337 |
|
338 |
return $title;
|
339 |
}
|
345 |
* @since 3.0.4
|
346 |
* @since 3.1.0 The first parameter now expects an array.
|
347 |
* @since 4.1.0 Now appends the "social" argument when getting the title.
|
348 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
349 |
* @uses $this->get_title()
|
350 |
*
|
351 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
352 |
* Leave null to autodetermine query.
|
353 |
* @param bool $escape Whether to escape the title.
|
354 |
* @return string The generated Twitter Title.
|
362 |
* Falls back to meta title.
|
363 |
*
|
364 |
* @since 3.0.4
|
365 |
+
* @since 3.1.0 1. The first parameter now expects an array.
|
366 |
+
* 2. Now tries to get the homepage social title.
|
367 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
368 |
* @uses $this->get_generated_open_graph_title()
|
369 |
*
|
370 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
371 |
* Leave null to autodetermine query.
|
372 |
* @param bool $escape Whether to escape the title.
|
373 |
* @return string Open Graph Title.
|
374 |
*/
|
375 |
public function get_open_graph_title( $args = null, $escape = true ) {
|
376 |
|
|
|
377 |
$title = $this->get_open_graph_title_from_custom_field( $args, false )
|
378 |
?: $this->get_generated_open_graph_title( $args, false );
|
|
|
379 |
|
380 |
return $escape ? $this->escape_title( $title ) : $title;
|
381 |
}
|
387 |
* @since 3.1.0
|
388 |
* @see $this->get_open_graph_title()
|
389 |
*
|
390 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
391 |
* @param bool $escape Whether to escape the title.
|
392 |
* @return string Open Graph Title.
|
393 |
*/
|
410 |
* @since 3.1.0
|
411 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
412 |
* @since 4.0.0 Added term meta item checks.
|
413 |
+
* @since 4.2.0 Can now return custom post type archive titles.
|
414 |
* @see $this->get_open_graph_title()
|
415 |
* @see $this->get_open_graph_title_from_custom_field()
|
416 |
*
|
419 |
protected function get_custom_open_graph_title_from_query() {
|
420 |
|
421 |
$title = '';
|
|
|
422 |
if ( $this->is_real_front_page() ) {
|
423 |
if ( $this->is_static_frontpage() ) {
|
424 |
$title = $this->get_option( 'homepage_og_title' )
|
431 |
$title = $this->get_post_meta_item( '_open_graph_title' ) ?: '';
|
432 |
} elseif ( $this->is_term_meta_capable() ) {
|
433 |
$title = $this->get_term_meta_item( 'og_title' ) ?: '';
|
434 |
+
} elseif ( \is_post_type_archive() ) {
|
435 |
+
$title = $this->get_post_type_archive_meta_item( 'og_title' ) ?: '';
|
436 |
}
|
|
|
437 |
|
438 |
return $title;
|
439 |
}
|
445 |
* @since 3.1.0
|
446 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
447 |
* @since 4.0.0 Added term meta item checks.
|
448 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
449 |
* @see $this->get_open_graph_title()
|
450 |
* @see $this->get_open_graph_title_from_custom_field()
|
451 |
*
|
452 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
453 |
* @return string Open Graph Title.
|
454 |
*/
|
455 |
+
protected function get_custom_open_graph_title_from_args( $args ) {
|
456 |
|
|
|
|
|
457 |
if ( $args['taxonomy'] ) {
|
458 |
$title = $this->get_term_meta_item( 'og_title', $args['id'] ) ?: '';
|
459 |
+
} elseif ( $args['pta'] ) {
|
460 |
+
$title = $this->get_post_type_archive_meta_item( 'og_title', $args['pta'] ) ?: '';
|
461 |
} else {
|
462 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
463 |
$title = $this->get_option( 'homepage_og_title' )
|
469 |
$title = $this->get_post_meta_item( '_open_graph_title', $args['id'] ) ?: '';
|
470 |
}
|
471 |
}
|
|
|
472 |
|
473 |
return $title;
|
474 |
}
|
480 |
* @since 3.0.4
|
481 |
* @since 3.1.0 The first parameter now expects an array.
|
482 |
* @since 4.1.0 Now appends the "social" argument when getting the title.
|
483 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
484 |
* @uses $this->get_title()
|
485 |
*
|
486 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
487 |
* Leave null to autodetermine query.
|
488 |
* @param bool $escape Whether to escape the title.
|
489 |
* @return string The generated Open Graph Title.
|
499 |
* finally admits through their code that terms can be queried using only IDs.
|
500 |
*
|
501 |
* @since 3.1.0
|
502 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
503 |
* @internal But, feel free to use it.
|
504 |
*
|
505 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
506 |
* Leave null to autodetermine query.
|
507 |
* @return string The custom field title, if it exists.
|
508 |
*/
|
525 |
*
|
526 |
* @since 3.1.0
|
527 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
528 |
+
* @since 4.2.0 Can now return custom post type archive titles.
|
529 |
* @internal
|
530 |
* @see $this->get_raw_custom_field_title()
|
531 |
*
|
534 |
protected function get_custom_field_title_from_query() {
|
535 |
|
536 |
$title = '';
|
537 |
+
|
538 |
if ( $this->is_real_front_page() ) {
|
539 |
if ( $this->is_static_frontpage() ) {
|
540 |
$title = $this->get_option( 'homepage_title' )
|
550 |
} elseif ( \is_post_type_archive() ) {
|
551 |
/**
|
552 |
* @since 4.0.6
|
553 |
+
* @since 4.2.0 Deprecated.
|
554 |
+
* @deprecated Use options instead.
|
555 |
* @param string $title The post type archive title.
|
556 |
*/
|
557 |
+
$title = (string) \apply_filters_deprecated(
|
558 |
+
'the_seo_framework_pta_title',
|
559 |
+
[ $this->get_post_type_archive_meta_item( 'doctitle' ) ],
|
560 |
+
'4.2.0 of The SEO Framework'
|
561 |
+
) ?: '';
|
562 |
}
|
|
|
563 |
|
564 |
return $title;
|
565 |
}
|
570 |
* @since 3.1.0
|
571 |
* @since 3.1.4 Now uses the 'id' to get custom singular title.
|
572 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
573 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
574 |
* @internal
|
575 |
* @see $this->get_raw_custom_field_title()
|
576 |
*
|
577 |
+
* @param array $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
578 |
* @return string The custom title.
|
579 |
*/
|
580 |
+
protected function get_custom_field_title_from_args( $args ) {
|
581 |
|
|
|
|
|
582 |
if ( $args['taxonomy'] ) {
|
583 |
$title = $this->get_term_meta_item( 'doctitle', $args['id'] ) ?: '';
|
584 |
+
} elseif ( $args['pta'] ) {
|
585 |
+
$title = $this->get_post_type_archive_meta_item( 'doctitle', $args['pta'] ) ?: '';
|
586 |
} else {
|
587 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
588 |
$title = $this->get_option( 'homepage_title' )
|
594 |
$title = $this->get_post_meta_item( '_genesis_title', $args['id'] ) ?: '';
|
595 |
}
|
596 |
}
|
|
|
597 |
|
598 |
return $title;
|
599 |
}
|
602 |
* Generates a title, based on expected or current query, without additions or prefixes.
|
603 |
*
|
604 |
* @since 3.1.0
|
605 |
+
* @since 4.2.0 1. Added memoization.
|
606 |
+
* 2. Now supports the `$args['pta']` index.
|
607 |
* @uses $this->generate_title_from_query()
|
608 |
* @uses $this->generate_title_from_args()
|
609 |
*
|
610 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
611 |
* Leave null to autodetermine query.
|
612 |
* @return string The generated title.
|
613 |
*/
|
614 |
public function get_raw_generated_title( $args = null ) {
|
615 |
|
616 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
617 |
+
if ( null !== $memo = memo( null, $args ) ) return $memo;
|
618 |
+
|
619 |
$this->remove_default_title_filters( false, $args );
|
620 |
|
621 |
if ( null === $args ) {
|
627 |
|
628 |
$this->reset_default_title_filters();
|
629 |
|
630 |
+
return memo( $title ?: $this->get_static_untitled_title(), $args );
|
631 |
}
|
632 |
|
633 |
/**
|
641 |
* @internal Only to be used within $this->get_raw_generated_title()
|
642 |
*
|
643 |
* @param bool $reset Whether to reset the removed filters.
|
644 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
645 |
* Leave null to autodetermine query.
|
646 |
*/
|
647 |
protected function remove_default_title_filters( $reset = false, $args = null ) {
|
661 |
$filters = [ 'single_post_title', 'single_cat_title', 'single_tag_title' ];
|
662 |
} else {
|
663 |
$this->fix_generation_args( $args );
|
664 |
+
|
665 |
if ( 'category' === $args['taxonomy'] ) {
|
666 |
$filters = [ 'single_cat_title' ];
|
667 |
} elseif ( 'post_tag' === $args['taxonomy'] ) {
|
712 |
* Generates a title, based on current query, without additions or prefixes.
|
713 |
*
|
714 |
* @since 3.1.0
|
715 |
+
* @since 4.2.0 Flipped order of query tests.
|
716 |
* @internal
|
717 |
* @see $this->get_raw_generated_title()
|
718 |
*
|
728 |
$title = $this->get_generated_search_query_title();
|
729 |
} elseif ( $this->is_real_front_page() ) {
|
730 |
$title = $this->get_static_front_page_title();
|
|
|
|
|
731 |
} elseif ( $this->is_singular() ) {
|
732 |
$title = $this->get_generated_single_post_title();
|
733 |
+
} elseif ( $this->is_archive() ) {
|
734 |
+
$title = $this->get_generated_archive_title();
|
735 |
}
|
736 |
|
737 |
return $title;
|
741 |
* Generates a title, based on expected query, without additions or prefixes.
|
742 |
*
|
743 |
* @since 3.1.0
|
744 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
745 |
* @internal
|
746 |
* @see $this->get_raw_generated_title()
|
747 |
*
|
748 |
+
* @param array $args The query arguments. Required. Accepts 'id', 'taxonomy', and 'pta'.
|
749 |
* @return string The generated title. Empty if query can't be replicated.
|
750 |
*/
|
751 |
+
protected function generate_title_from_args( $args ) {
|
752 |
|
753 |
$title = '';
|
754 |
|
755 |
if ( $args['taxonomy'] ) {
|
756 |
$title = $this->get_generated_archive_title( \get_term( $args['id'], $args['taxonomy'] ) );
|
757 |
+
} elseif ( $args['pta'] ) {
|
758 |
+
$title = $this->get_generated_archive_title( \get_post_type_object( $args['pta'] ) );
|
759 |
} else {
|
760 |
if ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
761 |
$title = $this->get_static_front_page_title();
|
770 |
/**
|
771 |
* Generates front page title.
|
772 |
*
|
773 |
+
* This is an alias of get_blogname(). The difference is that this is used for
|
774 |
+
* the front-page title output solely, whereas the other one has a mixed usage.
|
775 |
+
*
|
776 |
* @since 3.1.0
|
777 |
+
* @since 4.2.0 1. Now listens to the new `site_title` option.
|
778 |
+
* 2. Now applies filters.
|
779 |
*
|
780 |
* @return string The generated front page title.
|
781 |
*/
|
782 |
public function get_static_front_page_title() {
|
783 |
+
return $this->get_blogname();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
784 |
}
|
785 |
|
786 |
/**
|
796 |
* 2: The first parameter now accepts `\WP_User` objects.
|
797 |
* @since 4.1.2 Now supports WP 5.5 archive titles.
|
798 |
*
|
799 |
+
* @param \WP_Term|\WP_User|\WP_Post_Type|\WP_Error|null $object The Term object or error.
|
800 |
+
* Leave null to autodetermine query.
|
801 |
+
* @return string|string[] The generated archive title, not escaped.
|
802 |
+
* When $get is 'admin', it returns an map of [prefix,title].
|
803 |
*/
|
804 |
+
public function get_generated_archive_title( $object = null ) {
|
805 |
|
806 |
+
if ( $object && \is_wp_error( $object ) )
|
807 |
return '';
|
808 |
|
809 |
+
[ $title ] = $this->get_raw_generated_archive_title_items( $object );
|
810 |
+
|
811 |
+
return $title;
|
812 |
+
}
|
813 |
+
|
814 |
+
/**
|
815 |
+
* Returns the archive title items. Also works in admin.
|
816 |
+
*
|
817 |
+
* @NOTE Taken from WordPress core. Altered to work for metadata.
|
818 |
+
* @see WP Core get_the_archive_title()
|
819 |
+
*
|
820 |
+
* @since 4.2.0
|
821 |
+
*
|
822 |
+
* @param \WP_Term|\WP_User|\WP_Post_Type|null $object The Term object.
|
823 |
+
* Leave null to autodetermine query.
|
824 |
+
* @return String[$title,$prefix,$title_without_prefix] The generated archive title items, not escaped.
|
825 |
+
*/
|
826 |
+
public function get_raw_generated_archive_title_items( $object = null ) {
|
827 |
+
|
828 |
+
$filterobject = $object ?? \get_queried_object();
|
829 |
|
830 |
/**
|
831 |
* @since 2.6.0
|
832 |
*
|
833 |
+
* @param string $title The short circuit title.
|
834 |
+
* @param \WP_Term|\WP_User|\WP_Post_Type $object The archive object.
|
835 |
*/
|
836 |
+
$title = (string) \apply_filters_deprecated(
|
837 |
+
'the_seo_framework_the_archive_title',
|
838 |
+
[
|
839 |
+
'',
|
840 |
+
$filterobject,
|
841 |
+
],
|
842 |
+
'4.2.0 of The SEO Framework',
|
843 |
+
'the_seo_framework_generated_archive_title_prefix and the_seo_framework_generated_archive_title'
|
844 |
+
);
|
845 |
|
846 |
if ( $title )
|
847 |
+
return [ $title, '', $title ];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
848 |
|
849 |
+
[ $title, $prefix ] = $object
|
850 |
+
? $this->get_generate_archive_title_from_term( $object )
|
851 |
+
: $this->get_generate_archive_title_from_query();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
852 |
|
853 |
+
$title_without_prefix = $title;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
854 |
|
855 |
+
if ( $this->use_generated_archive_prefix( $object ) ) {
|
856 |
+
/**
|
857 |
+
* Filters the archive title prefix.
|
858 |
+
* This is a sibling of WordPress's `get_the_archive_title_prefix`,
|
859 |
+
* but then without the HTML, and runs optionally, based on site-settings,
|
860 |
+
* and then with the second paramter: `$object`.
|
861 |
+
*
|
862 |
+
* @since 4.2.0
|
863 |
+
*
|
864 |
+
* @param string $prefix Archive title prefix.
|
865 |
+
* @param \WP_Term|\WP_User|\WP_Post_Type $object The archive object.
|
866 |
+
*/
|
867 |
+
$prefix = \apply_filters_ref_array(
|
868 |
+
'the_seo_framework_generated_archive_title_prefix',
|
869 |
+
[
|
870 |
+
$prefix,
|
871 |
+
$filterobject,
|
872 |
+
]
|
873 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
874 |
|
875 |
+
if ( $prefix ) {
|
876 |
+
$title = sprintf(
|
877 |
+
/* translators: 1: Title prefix. 2: Title. */
|
878 |
+
\_x( '%1$s %2$s', 'archive title', 'default' ),
|
879 |
+
$prefix,
|
880 |
+
$title
|
881 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
882 |
}
|
883 |
}
|
884 |
|
885 |
/**
|
886 |
* Filters the archive title.
|
887 |
+
* This is a sibling of WordPress's `get_the_archive_title`,
|
888 |
+
* but then without the HTML.
|
889 |
*
|
890 |
* @since 3.0.4
|
891 |
+
* @since 4.2.0 Added the `$prefix` and `$origintitle_without_prefixal_title` parameters.
|
892 |
*
|
893 |
+
* @param string $title Archive title to be displayed.
|
894 |
+
* @param \WP_Term|\WP_User|\WP_Post_Type $object The archive object.
|
895 |
+
* @param string $title_without_prefix Archive title without prefix.
|
896 |
+
* @param string $prefix Archive title prefix.
|
897 |
*/
|
898 |
+
$title = \apply_filters_ref_array(
|
899 |
+
'the_seo_framework_generated_archive_title',
|
900 |
+
[
|
901 |
+
$title,
|
902 |
+
$filterobject,
|
903 |
+
$title_without_prefix,
|
904 |
+
$prefix,
|
905 |
+
]
|
906 |
+
);
|
907 |
+
|
908 |
+
return [ $title, $prefix, $title_without_prefix ];
|
909 |
+
}
|
910 |
+
|
911 |
+
/**
|
912 |
+
* Returns the generated archive title by evaluating the input Term only.
|
913 |
+
*
|
914 |
+
* @since 4.2.0
|
915 |
+
* @see $this->get_generate_archive_title_from_term() which evaluates from arguments.
|
916 |
+
*
|
917 |
+
* @return string[$title,$prefix] The title and prefix.
|
918 |
+
*/
|
919 |
+
protected function get_generate_archive_title_from_query() {
|
920 |
+
|
921 |
+
$title = \__( 'Archives', 'default' );
|
922 |
+
$prefix = '';
|
923 |
+
|
924 |
+
if ( $this->is_category() ) {
|
925 |
+
$title = $this->get_generated_single_term_title( \get_queried_object() );
|
926 |
+
$prefix = \_x( 'Category:', 'category archive title prefix', 'default' );
|
927 |
+
} elseif ( $this->is_tag() ) {
|
928 |
+
$title = $this->get_generated_single_term_title( \get_queried_object() );
|
929 |
+
$prefix = \_x( 'Tag:', 'tag archive title prefix', 'default' );
|
930 |
+
} elseif ( $this->is_author() ) {
|
931 |
+
$title = \get_queried_object()->display_name ?? '';
|
932 |
+
$prefix = \_x( 'Author:', 'author archive title prefix', 'default' );
|
933 |
+
} elseif ( $this->is_date() ) {
|
934 |
+
if ( $this->is_year() ) {
|
935 |
+
$title = \get_the_date( \_x( 'Y', 'yearly archives date format', 'default' ) );
|
936 |
+
$prefix = \_x( 'Year:', 'date archive title prefix', 'default' );
|
937 |
+
} elseif ( $this->is_month() ) {
|
938 |
+
$title = \get_the_date( \_x( 'F Y', 'monthly archives date format', 'default' ) );
|
939 |
+
$prefix = \_x( 'Month:', 'date archive title prefix', 'default' );
|
940 |
+
} elseif ( $this->is_day() ) {
|
941 |
+
$title = \get_the_date( \_x( 'F j, Y', 'daily archives date format', 'default' ) );
|
942 |
+
$prefix = \_x( 'Day:', 'date archive title prefix', 'default' );
|
943 |
+
}
|
944 |
+
} elseif ( \is_tax( 'post_format' ) ) {
|
945 |
+
if ( \is_tax( 'post_format', 'post-format-aside' ) ) {
|
946 |
+
$title = \_x( 'Asides', 'post format archive title', 'default' );
|
947 |
+
} elseif ( \is_tax( 'post_format', 'post-format-gallery' ) ) {
|
948 |
+
$title = \_x( 'Galleries', 'post format archive title', 'default' );
|
949 |
+
} elseif ( \is_tax( 'post_format', 'post-format-image' ) ) {
|
950 |
+
$title = \_x( 'Images', 'post format archive title', 'default' );
|
951 |
+
} elseif ( \is_tax( 'post_format', 'post-format-video' ) ) {
|
952 |
+
$title = \_x( 'Videos', 'post format archive title', 'default' );
|
953 |
+
} elseif ( \is_tax( 'post_format', 'post-format-quote' ) ) {
|
954 |
+
$title = \_x( 'Quotes', 'post format archive title', 'default' );
|
955 |
+
} elseif ( \is_tax( 'post_format', 'post-format-link' ) ) {
|
956 |
+
$title = \_x( 'Links', 'post format archive title', 'default' );
|
957 |
+
} elseif ( \is_tax( 'post_format', 'post-format-status' ) ) {
|
958 |
+
$title = \_x( 'Statuses', 'post format archive title', 'default' );
|
959 |
+
} elseif ( \is_tax( 'post_format', 'post-format-audio' ) ) {
|
960 |
+
$title = \_x( 'Audio', 'post format archive title', 'default' );
|
961 |
+
} elseif ( \is_tax( 'post_format', 'post-format-chat' ) ) {
|
962 |
+
$title = \_x( 'Chats', 'post format archive title', 'default' );
|
963 |
+
}
|
964 |
+
} elseif ( \is_post_type_archive() ) {
|
965 |
+
$title = $this->get_generated_post_type_archive_title();
|
966 |
+
$prefix = \_x( 'Archives:', 'post type archive title prefix', 'default' );
|
967 |
+
} elseif ( $this->is_tax() ) {
|
968 |
+
$term = \get_queried_object();
|
969 |
+
|
970 |
+
if ( $term ) {
|
971 |
+
$title = $this->get_generated_single_term_title( $term );
|
972 |
+
$prefix = sprintf(
|
973 |
+
/* translators: %s: Taxonomy singular name. */
|
974 |
+
\_x( '%s:', 'taxonomy term archive title prefix', 'default' ),
|
975 |
+
$this->get_tax_type_label( $term->taxonomy ?? '' )
|
976 |
+
);
|
977 |
+
}
|
978 |
+
}
|
979 |
+
|
980 |
+
return [ $title, $prefix ];
|
981 |
+
}
|
982 |
+
|
983 |
+
/**
|
984 |
+
* Returns the generated archive title by evaluating the input Term only.
|
985 |
+
*
|
986 |
+
* @since 4.2.0
|
987 |
+
* @see $this->get_generate_archive_title_from_query() which evalutates the query only.
|
988 |
+
*
|
989 |
+
* @param \WP_Term|\WP_User $term The Term object.
|
990 |
+
* @return string[$title,$prefix] The title and prefix.
|
991 |
+
*/
|
992 |
+
protected function get_generate_archive_title_from_term( $term ) {
|
993 |
+
|
994 |
+
$title = \__( 'Archives', 'default' );
|
995 |
+
$prefix = '';
|
996 |
+
|
997 |
+
if ( ! empty( $term->taxonomy ) ) {
|
998 |
+
$title = $this->get_generated_single_term_title( $term );
|
999 |
+
|
1000 |
+
switch ( $term->taxonomy ) :
|
1001 |
+
case 'category':
|
1002 |
+
$prefix = \_x( 'Category:', 'category archive title prefix', 'default' );
|
1003 |
+
break;
|
1004 |
+
case 'post_tag':
|
1005 |
+
$prefix = \_x( 'Tag:', 'tag archive title prefix', 'default' );
|
1006 |
+
break;
|
1007 |
+
default:
|
1008 |
+
$prefix = sprintf(
|
1009 |
+
/* translators: %s: Taxonomy singular name. */
|
1010 |
+
\_x( '%s:', 'taxonomy term archive title prefix', 'default' ),
|
1011 |
+
$this->get_tax_type_label( $term->taxonomy )
|
1012 |
+
);
|
1013 |
+
break;
|
1014 |
+
endswitch;
|
1015 |
+
} elseif ( $term instanceof \WP_User && isset( $term->display_name ) ) {
|
1016 |
+
$title = $term->display_name;
|
1017 |
+
$prefix = \_x( 'Author:', 'author archive title prefix', 'default' );
|
1018 |
+
} elseif ( $term instanceof \WP_Post_Type && isset( $term->name ) ) {
|
1019 |
+
$title = $this->get_generated_post_type_archive_title( $term->name );
|
1020 |
+
$prefix = \_x( 'Archives:', 'post type archive title prefix', 'default' );
|
1021 |
+
}
|
1022 |
+
|
1023 |
+
return [ $title, $prefix ];
|
1024 |
}
|
1025 |
|
1026 |
/**
|
1038 |
|
1039 |
//? Home queries can be tricky. Use get_the_real_ID to be certain.
|
1040 |
$_post = \get_post( $id ?: $this->get_the_real_ID() );
|
|
|
1041 |
|
1042 |
if ( isset( $_post->post_title ) ) {
|
1043 |
/**
|
1051 |
$title = \apply_filters( 'single_post_title', $_post->post_title, $_post );
|
1052 |
}
|
1053 |
|
1054 |
+
return $title ?? '';
|
1055 |
}
|
1056 |
|
1057 |
/**
|
1059 |
*
|
1060 |
* It can autodetermine the term; so, perform your checks prior calling.
|
1061 |
*
|
1062 |
+
* Taken from WordPress core. Altered to work in the Admin area.
|
1063 |
+
*
|
1064 |
* @see WP Core single_term_title()
|
|
|
|
|
1065 |
*
|
1066 |
* @since 3.1.0
|
1067 |
* @since 4.0.0 No longer redundantly tests the query, now only uses the term input or queried object.
|
1075 |
if ( \is_null( $term ) )
|
1076 |
$term = \get_queried_object();
|
1077 |
|
1078 |
+
if ( ! isset( $term->name ) ) return '';
|
1079 |
|
1080 |
+
switch ( $term->category ) :
|
1081 |
+
case 'category':
|
1082 |
/**
|
1083 |
* Filter the category archive page title.
|
1084 |
*
|
1087 |
* @param string $term_name Category name for archive being displayed.
|
1088 |
*/
|
1089 |
$term_name = \apply_filters( 'single_cat_title', $term->name );
|
1090 |
+
break;
|
1091 |
+
case 'post_tag':
|
1092 |
/**
|
1093 |
* Filter the tag archive page title.
|
1094 |
*
|
1097 |
* @param string $term_name Tag name for archive being displayed.
|
1098 |
*/
|
1099 |
$term_name = \apply_filters( 'single_tag_title', $term->name );
|
1100 |
+
break;
|
1101 |
+
default:
|
1102 |
/**
|
1103 |
* Filter the custom taxonomy archive page title.
|
1104 |
*
|
1107 |
* @param string $term_name Term name for archive being displayed.
|
1108 |
*/
|
1109 |
$term_name = \apply_filters( 'single_term_title', $term->name );
|
1110 |
+
break;
|
1111 |
+
endswitch;
|
1112 |
|
|
|
|
|
|
|
1113 |
return $term_name;
|
1114 |
}
|
1115 |
|
1120 |
* @see WP Core post_type_archive_title()
|
1121 |
*
|
1122 |
* @since 3.1.0
|
1123 |
+
* @since 4.2.0 Now actually works in the admin area, provided you forward $post_type.
|
1124 |
*
|
1125 |
* @param string $post_type The post type.
|
1126 |
* @return string The generated post type archive title.
|
1127 |
*/
|
1128 |
public function get_generated_post_type_archive_title( $post_type = '' ) {
|
1129 |
|
1130 |
+
if ( ! $post_type && ! \is_post_type_archive() )
|
|
|
|
|
1131 |
return '';
|
1132 |
|
1133 |
+
$post_type = $post_type ?: $this->get_current_post_type();
|
1134 |
+
|
1135 |
if ( \is_array( $post_type ) )
|
1136 |
$post_type = reset( $post_type );
|
1137 |
|
1138 |
+
if ( ! \in_array( $post_type, $this->get_public_post_type_archives(), true ) )
|
1139 |
+
return '';
|
1140 |
|
1141 |
/**
|
1142 |
* Filters the post type archive title.
|
1146 |
* @param string $post_type_name Post type 'name' label.
|
1147 |
* @param string $post_type Post type.
|
1148 |
*/
|
1149 |
+
$title = \apply_filters_ref_array(
|
1150 |
+
'post_type_archive_title',
|
1151 |
+
[
|
1152 |
+
$this->get_post_type_label( $post_type, false ),
|
1153 |
+
$post_type,
|
1154 |
+
]
|
1155 |
+
);
|
1156 |
|
1157 |
return $title;
|
1158 |
}
|
1202 |
* @since 3.1.0
|
1203 |
* @since 3.1.2 Added strict taxonomical check.
|
1204 |
* @since 3.1.3 Fixed conditional logic.
|
1205 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
1206 |
* @uses $this->get_title_branding_from_query()
|
1207 |
* @uses $this->get_title_branding_from_args()
|
1208 |
*
|
1209 |
* @param string $title The title. Passed by reference.
|
1210 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
1211 |
* Leave null to autodetermine query.
|
1212 |
*/
|
1213 |
public function merge_title_branding( &$title, $args = null ) {
|
1258 |
* Returns the addition and seplocation from arguments.
|
1259 |
*
|
1260 |
* @since 3.2.2
|
1261 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
1262 |
* @see $this->merge_title_branding();
|
1263 |
*
|
1264 |
+
* @param array $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
1265 |
* @return array { 'addition', 'seplocation' }
|
1266 |
*/
|
1267 |
+
protected function get_title_branding_from_args( $args ) {
|
1268 |
|
1269 |
+
if ( ! $args['taxonomy'] && ! $args['pta'] && $this->is_real_front_page_by_id( $args['id'] ) ) {
|
1270 |
$addition = $this->get_home_title_additions();
|
1271 |
$seplocation = $this->get_home_title_seplocation();
|
1272 |
} else {
|
1310 |
* @since 3.1.0
|
1311 |
* @since 3.1.2 Added strict taxonomical checks for title protection.
|
1312 |
* @since 3.1.3 Fixed conditional logic.
|
1313 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
1314 |
* @see $this->merge_title_prefixes()
|
1315 |
*
|
1316 |
* @param string $title The title. Passed by reference.
|
1317 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
1318 |
* Leave null to autodetermine query.
|
1319 |
* @return void
|
1320 |
*/
|
1322 |
|
1323 |
if ( null === $args ) {
|
1324 |
$id = $this->get_the_real_ID();
|
1325 |
+
$run = $this->is_singular();
|
1326 |
} else {
|
1327 |
$this->fix_generation_args( $args );
|
1328 |
$id = $args['id'];
|
1329 |
+
$run = ! $args['taxonomy'] && ! $args['pta'];
|
1330 |
}
|
1331 |
|
1332 |
+
if ( $run ) return;
|
1333 |
|
1334 |
$post = $id ? \get_post( $id ) : null;
|
1335 |
|
1415 |
return $this->get_title_seplocation( true );
|
1416 |
}
|
1417 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1418 |
/**
|
1419 |
* Determines whether to add or remove title protection prefixes.
|
1420 |
*
|
1421 |
* @since 3.2.4
|
1422 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
1423 |
* NOTE: This does not guarantee that protection is to be added. Only that it will be considered. Bad method name.
|
1424 |
* @see $this->merge_title_protection()
|
1425 |
*
|
1426 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
1427 |
* Leave null to autodetermine query.
|
1428 |
* @return bool True when prefixes are allowed.
|
1429 |
*/
|
1432 |
if ( null === $args ) {
|
1433 |
$use = $this->is_singular();
|
1434 |
} else {
|
1435 |
+
$this->fix_generation_args( $args );
|
1436 |
+
$use = $args && ! $args['taxonomy'] && ! $args['pta'];
|
1437 |
}
|
1438 |
|
1439 |
return $use;
|
1446 |
* NOTE: This does not guarantee that pagination is to be added. Only that it will be considered. Bad method name.
|
1447 |
* @see $this->merge_title_pagination()
|
1448 |
*
|
1449 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
1450 |
* Leave null to autodetermine query.
|
1451 |
* @return bool True when additions are allowed.
|
1452 |
*/
|
1470 |
* Determines whether to add or remove title branding additions.
|
1471 |
*
|
1472 |
* @since 3.1.0
|
1473 |
+
* @since 3.1.2 1. Added filter.
|
1474 |
+
* 2. Added strict taxonomical check.
|
1475 |
* @since 3.2.2 Now differentiates from query and parameter input.
|
1476 |
* @since 4.1.0 Added the second $social parameter.
|
1477 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
1478 |
* @see $this->merge_title_branding()
|
1479 |
* @uses $this->use_title_branding_from_query()
|
1480 |
* @uses $this->use_title_branding_from_args()
|
1481 |
*
|
1482 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
1483 |
* Leave null to autodetermine query.
|
1484 |
+
* @param bool|string $social Whether the title is meant for social display.
|
1485 |
+
* Also accepts string 'og' and 'twitter' for future proofing.
|
1486 |
* @return bool True when additions are allowed.
|
1487 |
*/
|
1488 |
public function use_title_branding( $args = null, $social = false ) {
|
1489 |
|
1490 |
+
// If social, test its option first.
|
1491 |
+
$use = $social ? ! $this->get_option( 'social_title_rem_additions' ) : true;
|
|
|
|
|
|
|
1492 |
|
1493 |
+
// Reevaluate from general title settings, overriding social.
|
1494 |
if ( $use ) {
|
1495 |
if ( null === $args ) {
|
1496 |
$use = $this->use_title_branding_from_query();
|
1504 |
* @since 3.1.2
|
1505 |
* @since 4.1.0 Added the third $social parameter.
|
1506 |
* @param string $use Whether to use branding.
|
1507 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
1508 |
* Is null when query is autodetermined.
|
1509 |
* @param bool $social Whether the title is meant for social display.
|
1510 |
*/
|
1511 |
+
return \apply_filters_ref_array(
|
1512 |
+
'the_seo_framework_use_title_branding',
|
1513 |
+
[
|
1514 |
+
$use,
|
1515 |
+
$args,
|
1516 |
+
(bool) $social,
|
1517 |
+
]
|
1518 |
+
);
|
1519 |
}
|
1520 |
|
1521 |
/**
|
1524 |
* @since 3.2.2
|
1525 |
* @since 4.0.0 Added use_taxonomical_title_branding() check.
|
1526 |
* @since 4.0.2 Removed contemned \is_post_type_archive() check for taxonomical branding.
|
1527 |
+
* @since 4.2.0 Can now test for custom post type archive branding.
|
1528 |
* @see $this->use_title_branding()
|
1529 |
*
|
1530 |
* @return bool
|
1537 |
$use = $this->use_singular_title_branding();
|
1538 |
} elseif ( $this->is_term_meta_capable() ) {
|
1539 |
$use = $this->use_taxonomical_title_branding();
|
1540 |
+
} elseif ( \is_post_type_archive() ) {
|
1541 |
+
$use = $this->use_post_type_archive_title_branding();
|
1542 |
} else {
|
1543 |
$use = ! $this->get_option( 'title_rem_additions' );
|
1544 |
}
|
1551 |
*
|
1552 |
* @since 3.2.2
|
1553 |
* @since 4.0.0 Added use_taxonomical_title_branding() check.
|
1554 |
+
* @since 4.2.0 1. Now supports the `$args['pta']` index.
|
1555 |
+
* 2. Now tests for custom post type archive branding.
|
1556 |
* @see $this->use_title_branding()
|
1557 |
*
|
1558 |
+
* @param array $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
1559 |
* @return bool
|
1560 |
*/
|
1561 |
+
protected function use_title_branding_from_args( $args ) {
|
1562 |
|
1563 |
if ( $args['taxonomy'] ) {
|
1564 |
$use = $this->use_taxonomical_title_branding( $args['id'] );
|
1565 |
+
} elseif ( $args['pta'] ) {
|
1566 |
+
$use = $this->use_post_type_archive_title_branding( $args['pta'] );
|
1567 |
} else {
|
1568 |
if ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
1569 |
$use = $this->use_home_page_title_tagline();
|
1582 |
* @since 4.0.5 1: Added first parameter `$term`.
|
1583 |
* 2: Added filter.
|
1584 |
*
|
1585 |
+
* @param \WP_Term|\WP_User|\WP_Post_Type|null $term The Term object. Leave null to autodermine query.
|
1586 |
* @return bool
|
1587 |
*/
|
1588 |
public function use_generated_archive_prefix( $term = null ) {
|
1589 |
|
1590 |
+
$term = $term ?? \get_queried_object();
|
1591 |
$use = ! $this->get_option( 'title_rem_prefixes' );
|
1592 |
|
1593 |
/**
|
1594 |
* @since 4.0.5
|
1595 |
+
* @param string $use Whether to use branding.
|
1596 |
+
* @param \WP_Term|\WP_User|\WP_Post_Type $term The current term.
|
1597 |
*/
|
1598 |
return \apply_filters_ref_array( 'the_seo_framework_use_archive_prefix', [ $use, $term ] );
|
1599 |
}
|
1634 |
return ! $this->get_term_meta_item( 'title_no_blog_name', $id ) && ! $this->get_option( 'title_rem_additions' );
|
1635 |
}
|
1636 |
|
1637 |
+
/**
|
1638 |
+
* Determines whether to add the title tagline for the pta.
|
1639 |
+
*
|
1640 |
+
* @since 4.2.0
|
1641 |
+
*
|
1642 |
+
* @param string $pta The post type archive. Optional.
|
1643 |
+
* @return bool
|
1644 |
+
*/
|
1645 |
+
public function use_post_type_archive_title_branding( $pta = '' ) {
|
1646 |
+
return ! $this->get_post_type_archive_meta_item( 'title_no_blog_name', $pta ) && ! $this->get_option( 'title_rem_additions' );
|
1647 |
+
}
|
1648 |
+
|
1649 |
/**
|
1650 |
* Returns the homepage additions (tagline) from option or bloginfo, when set.
|
1651 |
* Memoizes the return value.
|
1656 |
* @return string The trimmed tagline.
|
1657 |
*/
|
1658 |
public function get_home_title_additions() {
|
1659 |
+
return memo() ?? memo(
|
1660 |
+
$this->s_title_raw(
|
1661 |
+
$this->get_option( 'homepage_title_tagline' )
|
1662 |
+
?: $this->get_blogdescription()
|
1663 |
+
?: ''
|
1664 |
+
)
|
1665 |
);
|
1666 |
}
|
1667 |
}
|
@@ -38,25 +38,34 @@ class Generate_Url extends Generate_Title {
|
|
38 |
* Determines if the given page has a custom canonical URL.
|
39 |
*
|
40 |
* @since 3.2.4
|
|
|
|
|
|
|
41 |
*
|
42 |
* @param null|array $args The canonical URL arguments, leave null to autodetermine query : {
|
43 |
-
* int $id
|
44 |
-
* string $taxonomy
|
45 |
* }
|
46 |
* @return bool
|
47 |
*/
|
48 |
public function has_custom_canonical_url( $args = null ) {
|
49 |
|
50 |
-
if (
|
51 |
if ( $this->is_singular() ) {
|
52 |
-
$has = $this->get_singular_custom_canonical_url(
|
|
|
|
|
|
|
|
|
53 |
} else {
|
54 |
$has = false;
|
55 |
}
|
56 |
} else {
|
57 |
$this->fix_generation_args( $args );
|
58 |
-
if (
|
59 |
-
$has =
|
|
|
|
|
60 |
} else {
|
61 |
$has = $this->get_singular_custom_canonical_url( $args['id'] );
|
62 |
}
|
@@ -74,8 +83,7 @@ class Generate_Url extends Generate_Title {
|
|
74 |
* @return string The current URL.
|
75 |
*/
|
76 |
public function get_current_canonical_url() {
|
77 |
-
|
78 |
-
return isset( $cache ) ? $cache : $cache = $this->get_canonical_url();
|
79 |
}
|
80 |
|
81 |
/**
|
@@ -91,11 +99,12 @@ class Generate_Url extends Generate_Title {
|
|
91 |
* @return string The current permalink.
|
92 |
*/
|
93 |
public function get_current_permalink() {
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
|
|
99 |
}
|
100 |
|
101 |
/**
|
@@ -107,11 +116,9 @@ class Generate_Url extends Generate_Title {
|
|
107 |
* @return string The home URL.
|
108 |
*/
|
109 |
public function get_homepage_permalink() {
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
'taxonomy' => '',
|
114 |
-
] );
|
115 |
}
|
116 |
|
117 |
/**
|
@@ -120,27 +127,27 @@ class Generate_Url extends Generate_Title {
|
|
120 |
*
|
121 |
* @since 3.0.0
|
122 |
* @since 4.0.0 Now preemptively fixes the generation arguments, for easier implementation.
|
|
|
123 |
* @uses $this->get_canonical_url()
|
124 |
*
|
125 |
* @param array $args The canonical URL arguments : {
|
126 |
* int $id The Post, Page or Term ID to generate the URL for.
|
127 |
* string $taxonomy The taxonomy.
|
|
|
128 |
* bool $get_custom_field Whether to get custom canonical URLs from user settings.
|
129 |
* }
|
130 |
* @return string The canonical URL, if any.
|
131 |
*/
|
132 |
public function create_canonical_url( $args = [] ) {
|
133 |
|
134 |
-
$
|
135 |
-
$args = $args ?: [];
|
136 |
-
|
137 |
-
$defaults = [
|
138 |
'id' => 0,
|
139 |
'taxonomy' => '',
|
|
|
140 |
'get_custom_field' => false,
|
141 |
];
|
142 |
|
143 |
-
return $this->get_canonical_url(
|
144 |
}
|
145 |
|
146 |
/**
|
@@ -148,9 +155,10 @@ class Generate_Url extends Generate_Title {
|
|
148 |
* Removes pagination if the URL isn't obtained via the query.
|
149 |
*
|
150 |
* @since 3.0.0
|
|
|
151 |
* @see $this->create_canonical_url()
|
152 |
*
|
153 |
-
* @param array|null $args
|
154 |
* @return string The canonical URL, if any.
|
155 |
*/
|
156 |
public function get_canonical_url( $args = null ) {
|
@@ -167,12 +175,11 @@ class Generate_Url extends Generate_Title {
|
|
167 |
if ( ! $canonical_url )
|
168 |
return '';
|
169 |
|
170 |
-
if ( ! $query && $args['id'] === $this->get_the_real_ID() )
|
171 |
$canonical_url = $this->remove_pagination_from_url( $canonical_url );
|
172 |
-
|
173 |
-
if ( $this->matches_this_domain( $canonical_url ) )
|
174 |
$canonical_url = $this->set_preferred_url_scheme( $canonical_url );
|
175 |
-
}
|
176 |
|
177 |
return $this->clean_canonical_url( $canonical_url );
|
178 |
}
|
@@ -183,33 +190,43 @@ class Generate_Url extends Generate_Title {
|
|
183 |
* @since 3.0.0
|
184 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
185 |
* @since 4.0.0 Can now fetch custom canonical URL for terms.
|
|
|
186 |
* @see $this->create_canonical_url()
|
187 |
*
|
188 |
-
* @param array $args Use $this->create_canonical_url().
|
189 |
* @return string The canonical URL.
|
190 |
*/
|
191 |
-
protected function build_canonical_url(
|
192 |
|
193 |
$url = '';
|
194 |
|
195 |
if ( $args['taxonomy'] ) {
|
196 |
-
|
197 |
-
$
|
198 |
-
|
199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
} else {
|
201 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
202 |
-
|
203 |
-
$
|
204 |
-
|
205 |
-
|
|
|
206 |
} elseif ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
207 |
-
$url = $this->
|
208 |
} elseif ( $args['id'] ) {
|
209 |
-
|
210 |
-
$
|
211 |
-
|
212 |
-
|
|
|
213 |
}
|
214 |
}
|
215 |
|
@@ -221,34 +238,33 @@ class Generate_Url extends Generate_Title {
|
|
221 |
*
|
222 |
* @since 3.0.0
|
223 |
* @since 4.0.0 Can now fetch custom canonical URL for terms.
|
224 |
-
* @
|
|
|
225 |
* @see $this->get_canonical_url()
|
226 |
*
|
227 |
* @return string The canonical URL.
|
228 |
*/
|
229 |
protected function generate_canonical_url() {
|
230 |
|
231 |
-
$id = $this->get_the_real_ID();
|
232 |
-
$url = '';
|
233 |
-
|
234 |
if ( $this->is_real_front_page() ) {
|
235 |
if ( $this->has_page_on_front() ) {
|
236 |
-
$url = $this->get_singular_custom_canonical_url(
|
237 |
?: $this->get_home_canonical_url();
|
238 |
} else {
|
239 |
$url = $this->get_home_canonical_url();
|
240 |
}
|
241 |
} elseif ( $this->is_singular() ) {
|
242 |
-
$url = $this->get_singular_custom_canonical_url(
|
243 |
-
?: $this->get_singular_canonical_url(
|
244 |
} elseif ( $this->is_archive() ) {
|
245 |
if ( $this->is_term_meta_capable() ) {
|
246 |
-
$url = $this->get_taxonomical_custom_canonical_url(
|
247 |
-
?: $this->get_taxonomical_canonical_url(
|
248 |
} elseif ( \is_post_type_archive() ) {
|
249 |
-
$url = $this->
|
|
|
250 |
} elseif ( $this->is_author() ) {
|
251 |
-
$url = $this->get_author_canonical_url(
|
252 |
} elseif ( $this->is_date() ) {
|
253 |
if ( $this->is_day() ) {
|
254 |
$url = $this->get_date_canonical_url( \get_query_var( 'year' ), \get_query_var( 'monthnum' ), \get_query_var( 'day' ) );
|
@@ -262,7 +278,7 @@ class Generate_Url extends Generate_Title {
|
|
262 |
$url = $this->get_search_canonical_url();
|
263 |
}
|
264 |
|
265 |
-
return $url;
|
266 |
}
|
267 |
|
268 |
/**
|
@@ -276,14 +292,11 @@ class Generate_Url extends Generate_Title {
|
|
276 |
*/
|
277 |
public function clean_canonical_url( $url ) {
|
278 |
|
279 |
-
if ( $this->pretty_permalinks )
|
280 |
-
|
281 |
-
} else {
|
282 |
-
//= Keep the &'s more readable.
|
283 |
-
$url = \esc_url_raw( $url, [ 'https', 'http' ] );
|
284 |
-
}
|
285 |
|
286 |
-
|
|
|
287 |
}
|
288 |
|
289 |
/**
|
@@ -299,8 +312,7 @@ class Generate_Url extends Generate_Title {
|
|
299 |
*/
|
300 |
public function get_home_canonical_url() {
|
301 |
|
302 |
-
|
303 |
-
$url = \get_home_url( null, '', $this->get_preferred_scheme() );
|
304 |
|
305 |
if ( ! $url ) return '';
|
306 |
|
@@ -329,15 +341,27 @@ class Generate_Url extends Generate_Title {
|
|
329 |
return $url;
|
330 |
}
|
331 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
/**
|
333 |
* Returns singular custom field's canonical URL.
|
334 |
*
|
335 |
* @since 3.0.0
|
|
|
336 |
*
|
337 |
-
* @param int $id The page ID.
|
338 |
* @return string The custom canonical URL, if any.
|
339 |
*/
|
340 |
-
public function get_singular_custom_canonical_url( $id ) {
|
341 |
return $this->get_post_meta_item( '_genesis_canonical_uri', $id ) ?: '';
|
342 |
}
|
343 |
|
@@ -348,74 +372,108 @@ class Generate_Url extends Generate_Title {
|
|
348 |
* @since 3.1.0 Added WC Shop and WP Blog (as page) pagination integration via $this->paged().
|
349 |
* @since 3.2.4 Removed pagination support for singular posts, as the SEO attack is now mitigated via WordPress.
|
350 |
* @since 4.0.5 Now passes the `$id` to `is_singular_archive()`
|
|
|
|
|
351 |
*
|
352 |
-
* @param int|null $id The page ID.
|
353 |
* @return string The custom canonical URL, if any.
|
354 |
*/
|
355 |
public function get_singular_canonical_url( $id = null ) {
|
356 |
|
357 |
-
|
|
|
358 |
|
359 |
-
$
|
360 |
-
|
361 |
-
|
362 |
-
$url = $this->remove_pagination_from_url( $url, $_page, false );
|
363 |
-
}
|
364 |
|
365 |
-
if ( $url
|
366 |
-
|
367 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
368 |
}
|
369 |
|
370 |
-
return $url;
|
371 |
}
|
372 |
|
373 |
/**
|
374 |
* Returns taxonomical custom field's canonical URL.
|
375 |
*
|
376 |
* @since 4.0.0
|
|
|
377 |
*
|
378 |
* @param int $term_id The term ID.
|
379 |
* @return string The custom canonical URL, if any.
|
380 |
*/
|
381 |
-
public function get_taxonomical_custom_canonical_url( $term_id ) {
|
382 |
return $this->get_term_meta_item( 'canonical', $term_id ) ?: '';
|
383 |
}
|
384 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
/**
|
386 |
* Returns taxonomical canonical URL.
|
387 |
* Automatically adds pagination if the ID matches the query.
|
388 |
*
|
389 |
* @since 3.0.0
|
390 |
-
* @since 4.0.0 1. Renamed from "
|
391 |
* 2. Now works on the admin-screens.
|
|
|
|
|
392 |
*
|
393 |
-
* @param int
|
394 |
-
* @param string
|
395 |
* @return string The taxonomical canonical URL, if any.
|
396 |
*/
|
397 |
-
public function get_taxonomical_canonical_url( $term_id, $taxonomy ) {
|
398 |
|
399 |
-
|
400 |
-
$
|
|
|
401 |
|
402 |
-
|
403 |
-
return '';
|
404 |
|
405 |
-
if ( $
|
406 |
-
|
407 |
-
|
|
|
|
|
|
|
|
|
|
|
408 |
}
|
409 |
|
410 |
-
return $
|
411 |
}
|
412 |
|
413 |
/**
|
414 |
* Returns post type archive canonical URL.
|
415 |
*
|
416 |
* @since 3.0.0
|
417 |
-
* @since 4.0.0
|
418 |
-
*
|
|
|
|
|
419 |
*
|
420 |
* @param null|string $post_type The post type archive's post type.
|
421 |
* Leave null to use query, and allow pagination.
|
@@ -423,26 +481,19 @@ class Generate_Url extends Generate_Title {
|
|
423 |
*/
|
424 |
public function get_post_type_archive_canonical_url( $post_type = null ) {
|
425 |
|
426 |
-
if (
|
427 |
-
$this->
|
428 |
-
$
|
429 |
-
}
|
430 |
-
|
431 |
-
$query = true;
|
432 |
-
|
433 |
-
if ( null === $post_type ) {
|
434 |
-
$post_type = \get_query_var( 'post_type' );
|
435 |
-
$post_type = \is_array( $post_type ) ? reset( $post_type ) : $post_type;
|
436 |
-
|
437 |
-
$query = false;
|
438 |
}
|
439 |
|
440 |
-
$
|
441 |
|
442 |
-
if ( $
|
443 |
-
$
|
444 |
|
445 |
-
return $
|
446 |
}
|
447 |
|
448 |
/**
|
@@ -450,23 +501,21 @@ class Generate_Url extends Generate_Title {
|
|
450 |
* Automatically adds pagination if the ID matches the query.
|
451 |
*
|
452 |
* @since 3.0.0
|
|
|
|
|
453 |
*
|
454 |
-
* @param int $
|
455 |
* @return string The author canonical URL, if any.
|
456 |
*/
|
457 |
-
public function get_author_canonical_url( $
|
458 |
-
|
459 |
-
$link = \get_author_posts_url( $author_id );
|
460 |
|
461 |
-
|
462 |
-
return '';
|
463 |
|
464 |
-
if (
|
465 |
-
//= Adds pagination if ID matches query.
|
466 |
-
$link = $this->add_url_pagination( $link, $this->paged(), true );
|
467 |
-
}
|
468 |
|
469 |
-
return $
|
|
|
|
|
470 |
}
|
471 |
|
472 |
/**
|
@@ -514,7 +563,7 @@ class Generate_Url extends Generate_Title {
|
|
514 |
}
|
515 |
|
516 |
if ( $_paginate ) {
|
517 |
-
|
518 |
$link = $this->add_url_pagination( $link, $this->paged(), true );
|
519 |
}
|
520 |
|
@@ -526,9 +575,9 @@ class Generate_Url extends Generate_Title {
|
|
526 |
* Automatically adds pagination if the input matches the query.
|
527 |
*
|
528 |
* @since 3.0.0
|
529 |
-
* @since 3.1.0
|
530 |
-
*
|
531 |
-
*
|
532 |
*
|
533 |
* @param string $query The search query. Mustn't be escaped.
|
534 |
* When left empty, the current query will be used.
|
@@ -546,7 +595,7 @@ class Generate_Url extends Generate_Title {
|
|
546 |
$link = \get_search_link( $query );
|
547 |
|
548 |
if ( $_paginate ) {
|
549 |
-
|
550 |
$link = $this->add_url_pagination( $link, $this->paged(), true );
|
551 |
}
|
552 |
|
@@ -565,10 +614,8 @@ class Generate_Url extends Generate_Title {
|
|
565 |
*/
|
566 |
public function get_preferred_scheme() {
|
567 |
|
568 |
-
|
569 |
-
|
570 |
-
if ( isset( $scheme ) )
|
571 |
-
return $scheme;
|
572 |
|
573 |
switch ( $this->get_option( 'canonical_scheme' ) ) :
|
574 |
case 'https':
|
@@ -589,9 +636,7 @@ class Generate_Url extends Generate_Title {
|
|
589 |
* @since 2.8.0
|
590 |
* @param string $scheme The current URL scheme.
|
591 |
*/
|
592 |
-
|
593 |
-
|
594 |
-
return $scheme;
|
595 |
}
|
596 |
|
597 |
/**
|
@@ -610,7 +655,12 @@ class Generate_Url extends Generate_Title {
|
|
610 |
* @return string The detected URl scheme, lowercase.
|
611 |
*/
|
612 |
public function detect_site_url_scheme() {
|
613 |
-
return strtolower( parse_url(
|
|
|
|
|
|
|
|
|
|
|
614 |
}
|
615 |
|
616 |
/**
|
@@ -669,6 +719,8 @@ class Generate_Url extends Generate_Title {
|
|
669 |
* @since 3.0.0
|
670 |
* @since 3.2.4 1. Now considers query arguments when using pretty permalinks.
|
671 |
* 2. The second and third parameters are now optional.
|
|
|
|
|
672 |
*
|
673 |
* @param string $url The fully qualified URL.
|
674 |
* @param int $page The page number. Should be bigger than 1 to paginate.
|
@@ -680,13 +732,14 @@ class Generate_Url extends Generate_Title {
|
|
680 |
*/
|
681 |
public function add_url_pagination( $url, $page = null, $use_base = null ) {
|
682 |
|
683 |
-
$_page =
|
684 |
|
685 |
if ( $_page < 2 )
|
686 |
return $url;
|
687 |
|
688 |
-
$_use_base =
|
689 |
-
$this->
|
|
|
690 |
|
691 |
if ( $this->pretty_permalinks ) {
|
692 |
|
@@ -699,7 +752,7 @@ class Generate_Url extends Generate_Title {
|
|
699 |
$base = $base ?: $GLOBALS['wp_rewrite']->pagination_base;
|
700 |
|
701 |
if ( $_use_base ) {
|
702 |
-
$url = \user_trailingslashit( \trailingslashit( $url ) . $base
|
703 |
} else {
|
704 |
$url = \user_trailingslashit( \trailingslashit( $url ) . $_page, 'single_paged' );
|
705 |
}
|
@@ -728,6 +781,7 @@ class Generate_Url extends Generate_Title {
|
|
728 |
* 4. Now supports pretty permalinks with query parameters.
|
729 |
* 5. Is now public.
|
730 |
* @since 4.1.2 Now correctly reappends query when pagination isn't removed.
|
|
|
731 |
*
|
732 |
* @param string $url The fully qualified URL to remove pagination from.
|
733 |
* @param int|null $page The page number to remove. If null, it will get number from query.
|
@@ -740,24 +794,22 @@ class Generate_Url extends Generate_Title {
|
|
740 |
public function remove_pagination_from_url( $url, $page = null, $use_base = null ) {
|
741 |
|
742 |
if ( $this->pretty_permalinks ) {
|
743 |
-
// Defensive programming...
|
744 |
-
static $user_slash, $base;
|
745 |
-
$user_slash = isset( $user_slash ) ? $user_slash :
|
746 |
-
( $GLOBALS['wp_rewrite']->use_trailing_slashes ? '/' : '' );
|
747 |
-
$base = isset( $base ) ? $base : $GLOBALS['wp_rewrite']->pagination_base;
|
748 |
|
749 |
-
$_page =
|
750 |
|
751 |
if ( $_page > 1 ) {
|
752 |
$_url = $url;
|
753 |
|
754 |
-
$_use_base =
|
755 |
-
|
|
|
|
|
|
|
756 |
|
757 |
if ( $_use_base ) {
|
758 |
-
$find =
|
759 |
} else {
|
760 |
-
$find =
|
761 |
}
|
762 |
|
763 |
$_query = parse_url( $_url, PHP_URL_QUERY );
|
@@ -838,9 +890,9 @@ class Generate_Url extends Generate_Title {
|
|
838 |
// FIXME: Core Report: WP doesn't accept paged parameters w/ date parameters. It'll lead to the homepage.
|
839 |
$_query = $GLOBALS['wp_query']->query;
|
840 |
$_date = [
|
841 |
-
'y' =>
|
842 |
-
'm' =>
|
843 |
-
'd' =>
|
844 |
];
|
845 |
|
846 |
$url = \add_query_arg( [ 'm' => implode( '', $_date ) ], $home );
|
@@ -850,12 +902,11 @@ class Generate_Url extends Generate_Title {
|
|
850 |
// Generate shortlink for object type and slug.
|
851 |
$object = \get_queried_object();
|
852 |
|
853 |
-
$tax =
|
854 |
-
$slug =
|
855 |
|
856 |
-
if ( $tax && $slug )
|
857 |
$url = \add_query_arg( [ $tax => $slug ], $home );
|
858 |
-
}
|
859 |
}
|
860 |
} elseif ( $this->is_search() ) {
|
861 |
$url = \add_query_arg( [ 's' => \get_search_query( false ) ], $home );
|
@@ -918,15 +969,13 @@ class Generate_Url extends Generate_Title {
|
|
918 |
*/
|
919 |
public function get_paged_urls() {
|
920 |
|
921 |
-
|
922 |
-
|
923 |
-
if ( isset( $prev, $next ) ) goto end;
|
924 |
|
925 |
$prev = $next = '';
|
926 |
|
927 |
if ( $this->has_custom_canonical_url() ) goto end;
|
928 |
|
929 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
930 |
if ( $this->is_singular() && ! $this->is_singular_archive() && $this->is_multipage() ) {
|
931 |
$_run = $this->is_real_front_page()
|
932 |
? $this->get_option( 'prev_next_frontpage' )
|
@@ -948,25 +997,27 @@ class Generate_Url extends Generate_Title {
|
|
948 |
} else {
|
949 |
goto end;
|
950 |
}
|
951 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
952 |
|
953 |
// See if-statements below.
|
954 |
if ( ! ( $page + 1 <= $_numpages || $page > 1 ) ) goto end;
|
955 |
|
956 |
-
$
|
|
|
|
|
|
|
|
|
957 |
|
958 |
// If this page is not the last, create a next-URL.
|
959 |
-
if ( $page + 1 <= $_numpages )
|
960 |
-
$next = $this->add_url_pagination( $
|
961 |
-
|
962 |
// If this page is not the first, create a prev-URL.
|
963 |
-
if ( $page > 1 )
|
964 |
-
$prev = $this->add_url_pagination( $
|
965 |
-
}
|
966 |
|
967 |
end:;
|
968 |
|
969 |
-
return compact( 'next', 'prev' );
|
970 |
}
|
971 |
|
972 |
/**
|
@@ -975,26 +1026,26 @@ class Generate_Url extends Generate_Title {
|
|
975 |
* Memoizes the return value.
|
976 |
*
|
977 |
* @since 2.7.0
|
978 |
-
* @since 2.9.2
|
979 |
-
*
|
980 |
*
|
981 |
* @return string The home URL host.
|
982 |
*/
|
983 |
public function get_home_host() {
|
984 |
|
985 |
-
|
986 |
-
|
987 |
-
if ( isset( $cache ) )
|
988 |
-
return $cache;
|
989 |
|
990 |
-
$parsed_url = parse_url(
|
|
|
|
|
991 |
|
992 |
-
$host =
|
993 |
|
994 |
if ( $host && isset( $parsed_url['port'] ) )
|
995 |
-
$host .=
|
996 |
|
997 |
-
return
|
998 |
}
|
999 |
|
1000 |
/**
|
@@ -1039,9 +1090,9 @@ class Generate_Url extends Generate_Title {
|
|
1039 |
public function make_fully_qualified_url( $url ) {
|
1040 |
|
1041 |
if ( '//' === substr( $url, 0, 2 ) ) {
|
1042 |
-
$url =
|
1043 |
} elseif ( 'http' !== substr( $url, 0, 4 ) ) {
|
1044 |
-
$url =
|
1045 |
}
|
1046 |
|
1047 |
return $url;
|
@@ -1089,7 +1140,7 @@ class Generate_Url extends Generate_Title {
|
|
1089 |
$url = \add_query_arg( $results, $url );
|
1090 |
|
1091 |
if ( $_fragment )
|
1092 |
-
$url .=
|
1093 |
|
1094 |
return $url;
|
1095 |
}
|
@@ -1108,26 +1159,37 @@ class Generate_Url extends Generate_Title {
|
|
1108 |
if ( ! $url )
|
1109 |
return false;
|
1110 |
|
1111 |
-
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
}
|
1118 |
|
1119 |
// Test for likely match early, before transforming.
|
1120 |
if ( 0 === stripos( $url, $home_domain ) )
|
1121 |
return true;
|
1122 |
|
1123 |
-
$url = \esc_url_raw(
|
1124 |
-
|
1125 |
-
|
|
|
1126 |
|
1127 |
-
|
1128 |
-
|
1129 |
-
|
1130 |
|
1131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1132 |
}
|
1133 |
}
|
38 |
* Determines if the given page has a custom canonical URL.
|
39 |
*
|
40 |
* @since 3.2.4
|
41 |
+
* @since 4.2.0 1. Now also detects canonical URLs for taxonomies.
|
42 |
+
* 2. Now also detects canonical URLs for PTAs.
|
43 |
+
* 3. Now supports the `$args['pta']` index.
|
44 |
*
|
45 |
* @param null|array $args The canonical URL arguments, leave null to autodetermine query : {
|
46 |
+
* int $id The Post, Page or Term ID to generate the URL for.
|
47 |
+
* string $taxonomy The taxonomy.
|
48 |
* }
|
49 |
* @return bool
|
50 |
*/
|
51 |
public function has_custom_canonical_url( $args = null ) {
|
52 |
|
53 |
+
if ( null === $args ) {
|
54 |
if ( $this->is_singular() ) {
|
55 |
+
$has = $this->get_singular_custom_canonical_url();
|
56 |
+
} elseif ( $this->is_term_meta_capable() ) {
|
57 |
+
$has = $this->get_taxonomical_custom_canonical_url();
|
58 |
+
} elseif ( \is_post_type_archive() ) {
|
59 |
+
$has = $this->get_post_type_archive_custom_canonical_url();
|
60 |
} else {
|
61 |
$has = false;
|
62 |
}
|
63 |
} else {
|
64 |
$this->fix_generation_args( $args );
|
65 |
+
if ( $args['taxonomy'] ) {
|
66 |
+
$has = $this->get_taxonomical_custom_canonical_url( $args['id'] );
|
67 |
+
} elseif ( $args['pta'] ) {
|
68 |
+
$has = $this->get_post_type_archive_custom_canonical_url( $args['pta'] );
|
69 |
} else {
|
70 |
$has = $this->get_singular_custom_canonical_url( $args['id'] );
|
71 |
}
|
83 |
* @return string The current URL.
|
84 |
*/
|
85 |
public function get_current_canonical_url() {
|
86 |
+
return memo() ?? memo( $this->get_canonical_url() );
|
|
|
87 |
}
|
88 |
|
89 |
/**
|
99 |
* @return string The current permalink.
|
100 |
*/
|
101 |
public function get_current_permalink() {
|
102 |
+
return memo() ?? memo(
|
103 |
+
$this->create_canonical_url( [
|
104 |
+
'id' => $this->get_the_real_ID(),
|
105 |
+
'taxonomy' => $this->get_current_taxonomy(),
|
106 |
+
] )
|
107 |
+
);
|
108 |
}
|
109 |
|
110 |
/**
|
116 |
* @return string The home URL.
|
117 |
*/
|
118 |
public function get_homepage_permalink() {
|
119 |
+
return memo() ?? memo(
|
120 |
+
$this->create_canonical_url( [ 'id' => $this->get_the_front_page_ID() ] )
|
121 |
+
);
|
|
|
|
|
122 |
}
|
123 |
|
124 |
/**
|
127 |
*
|
128 |
* @since 3.0.0
|
129 |
* @since 4.0.0 Now preemptively fixes the generation arguments, for easier implementation.
|
130 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
131 |
* @uses $this->get_canonical_url()
|
132 |
*
|
133 |
* @param array $args The canonical URL arguments : {
|
134 |
* int $id The Post, Page or Term ID to generate the URL for.
|
135 |
* string $taxonomy The taxonomy.
|
136 |
+
* string $pta The pta.
|
137 |
* bool $get_custom_field Whether to get custom canonical URLs from user settings.
|
138 |
* }
|
139 |
* @return string The canonical URL, if any.
|
140 |
*/
|
141 |
public function create_canonical_url( $args = [] ) {
|
142 |
|
143 |
+
$args += [
|
|
|
|
|
|
|
144 |
'id' => 0,
|
145 |
'taxonomy' => '',
|
146 |
+
'pta' => '',
|
147 |
'get_custom_field' => false,
|
148 |
];
|
149 |
|
150 |
+
return $this->get_canonical_url( $args );
|
151 |
}
|
152 |
|
153 |
/**
|
155 |
* Removes pagination if the URL isn't obtained via the query.
|
156 |
*
|
157 |
* @since 3.0.0
|
158 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
159 |
* @see $this->create_canonical_url()
|
160 |
*
|
161 |
+
* @param array|null $args Private variable! Use `$this->create_canonical_url()` instead.
|
162 |
* @return string The canonical URL, if any.
|
163 |
*/
|
164 |
public function get_canonical_url( $args = null ) {
|
175 |
if ( ! $canonical_url )
|
176 |
return '';
|
177 |
|
178 |
+
if ( ! $query && $args['id'] === $this->get_the_real_ID() )
|
179 |
$canonical_url = $this->remove_pagination_from_url( $canonical_url );
|
180 |
+
|
181 |
+
if ( $this->matches_this_domain( $canonical_url ) )
|
182 |
$canonical_url = $this->set_preferred_url_scheme( $canonical_url );
|
|
|
183 |
|
184 |
return $this->clean_canonical_url( $canonical_url );
|
185 |
}
|
190 |
* @since 3.0.0
|
191 |
* @since 3.2.2 Now tests for the homepage as page prior getting custom field data.
|
192 |
* @since 4.0.0 Can now fetch custom canonical URL for terms.
|
193 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
194 |
* @see $this->create_canonical_url()
|
195 |
*
|
196 |
+
* @param array $args Required. Use $this->create_canonical_url().
|
197 |
* @return string The canonical URL.
|
198 |
*/
|
199 |
+
protected function build_canonical_url( $args ) {
|
200 |
|
201 |
$url = '';
|
202 |
|
203 |
if ( $args['taxonomy'] ) {
|
204 |
+
$url = (
|
205 |
+
$args['get_custom_field']
|
206 |
+
? $this->get_taxonomical_custom_canonical_url( $args['id'] )
|
207 |
+
: ''
|
208 |
+
) ?: $this->get_taxonomical_canonical_url( $args['id'], $args['taxonomy'] );
|
209 |
+
} elseif ( $args['pta'] ) {
|
210 |
+
$url = (
|
211 |
+
$args['get_custom_field']
|
212 |
+
? $this->get_post_type_archive_custom_canonical_url( $args['pta'] )
|
213 |
+
: ''
|
214 |
+
) ?: $this->get_post_type_archive_canonical_url( $args['pta'] );
|
215 |
} else {
|
216 |
if ( $this->is_static_frontpage( $args['id'] ) ) {
|
217 |
+
$url = (
|
218 |
+
$args['get_custom_field']
|
219 |
+
? $this->get_singular_custom_canonical_url( $args['id'] )
|
220 |
+
: ''
|
221 |
+
) ?: $this->get_raw_home_canonical_url();
|
222 |
} elseif ( $this->is_real_front_page_by_id( $args['id'] ) ) {
|
223 |
+
$url = $this->get_raw_home_canonical_url();
|
224 |
} elseif ( $args['id'] ) {
|
225 |
+
$url = (
|
226 |
+
$args['get_custom_field']
|
227 |
+
? $this->get_singular_custom_canonical_url( $args['id'] )
|
228 |
+
: ''
|
229 |
+
) ?: $this->get_singular_canonical_url( $args['id'] );
|
230 |
}
|
231 |
}
|
232 |
|
238 |
*
|
239 |
* @since 3.0.0
|
240 |
* @since 4.0.0 Can now fetch custom canonical URL for terms.
|
241 |
+
* @since 4.2.0 1. No longer relies on passing through the page ID.
|
242 |
+
* 2. Can now return custom canonical URLs for post type archives.
|
243 |
* @see $this->get_canonical_url()
|
244 |
*
|
245 |
* @return string The canonical URL.
|
246 |
*/
|
247 |
protected function generate_canonical_url() {
|
248 |
|
|
|
|
|
|
|
249 |
if ( $this->is_real_front_page() ) {
|
250 |
if ( $this->has_page_on_front() ) {
|
251 |
+
$url = $this->get_singular_custom_canonical_url()
|
252 |
?: $this->get_home_canonical_url();
|
253 |
} else {
|
254 |
$url = $this->get_home_canonical_url();
|
255 |
}
|
256 |
} elseif ( $this->is_singular() ) {
|
257 |
+
$url = $this->get_singular_custom_canonical_url()
|
258 |
+
?: $this->get_singular_canonical_url();
|
259 |
} elseif ( $this->is_archive() ) {
|
260 |
if ( $this->is_term_meta_capable() ) {
|
261 |
+
$url = $this->get_taxonomical_custom_canonical_url()
|
262 |
+
?: $this->get_taxonomical_canonical_url();
|
263 |
} elseif ( \is_post_type_archive() ) {
|
264 |
+
$url = $this->get_post_type_archive_custom_canonical_url()
|
265 |
+
?: $this->get_post_type_archive_canonical_url();
|
266 |
} elseif ( $this->is_author() ) {
|
267 |
+
$url = $this->get_author_canonical_url();
|
268 |
} elseif ( $this->is_date() ) {
|
269 |
if ( $this->is_day() ) {
|
270 |
$url = $this->get_date_canonical_url( \get_query_var( 'year' ), \get_query_var( 'monthnum' ), \get_query_var( 'day' ) );
|
278 |
$url = $this->get_search_canonical_url();
|
279 |
}
|
280 |
|
281 |
+
return $url ?? '';
|
282 |
}
|
283 |
|
284 |
/**
|
292 |
*/
|
293 |
public function clean_canonical_url( $url ) {
|
294 |
|
295 |
+
if ( $this->pretty_permalinks )
|
296 |
+
return \esc_url( $url, [ 'https', 'http' ] );
|
|
|
|
|
|
|
|
|
297 |
|
298 |
+
// Keep the &'s more readable when using query-parameters.
|
299 |
+
return \esc_url_raw( $url, [ 'https', 'http' ] );
|
300 |
}
|
301 |
|
302 |
/**
|
312 |
*/
|
313 |
public function get_home_canonical_url() {
|
314 |
|
315 |
+
$url = $this->get_raw_home_canonical_url();
|
|
|
316 |
|
317 |
if ( ! $url ) return '';
|
318 |
|
341 |
return $url;
|
342 |
}
|
343 |
|
344 |
+
/**
|
345 |
+
* Returns home canonical URL without pagination or slashing.
|
346 |
+
*
|
347 |
+
* @since 4.2.0
|
348 |
+
*
|
349 |
+
* @return string The home canonical URL without pagination.
|
350 |
+
*/
|
351 |
+
public function get_raw_home_canonical_url() {
|
352 |
+
return $this->set_preferred_url_scheme( $this->get_home_url() );
|
353 |
+
}
|
354 |
+
|
355 |
/**
|
356 |
* Returns singular custom field's canonical URL.
|
357 |
*
|
358 |
* @since 3.0.0
|
359 |
+
* @since 4.2.0 The first parameter is now optional.
|
360 |
*
|
361 |
+
* @param int|null $id The page ID.
|
362 |
* @return string The custom canonical URL, if any.
|
363 |
*/
|
364 |
+
public function get_singular_custom_canonical_url( $id = null ) {
|
365 |
return $this->get_post_meta_item( '_genesis_canonical_uri', $id ) ?: '';
|
366 |
}
|
367 |
|
372 |
* @since 3.1.0 Added WC Shop and WP Blog (as page) pagination integration via $this->paged().
|
373 |
* @since 3.2.4 Removed pagination support for singular posts, as the SEO attack is now mitigated via WordPress.
|
374 |
* @since 4.0.5 Now passes the `$id` to `is_singular_archive()`
|
375 |
+
* @since 4.2.0 1. Added memoization.
|
376 |
+
* 2. When the $id isn't set, the URL won't get tested for pagination issues.
|
377 |
*
|
378 |
+
* @param int|null $id The page ID. Leave null to autodetermine.
|
379 |
* @return string The custom canonical URL, if any.
|
380 |
*/
|
381 |
public function get_singular_canonical_url( $id = null ) {
|
382 |
|
383 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
384 |
+
if ( null !== $memo = umemo( __METHOD__, null, $id ) ) return $memo;
|
385 |
|
386 |
+
$url = \wp_get_canonical_url(
|
387 |
+
$id ?? $this->get_the_real_ID()
|
388 |
+
) ?: '';
|
|
|
|
|
389 |
|
390 |
+
if ( ! $url ) return '';
|
391 |
+
|
392 |
+
if ( null !== $id ) {
|
393 |
+
$_page = \get_query_var( 'page', 1 ) ?: 1;
|
394 |
+
|
395 |
+
if ( $_page > 1 && $_page !== $this->page() ) {
|
396 |
+
/** @link https://core.trac.wordpress.org/ticket/37505 */
|
397 |
+
$url = $this->remove_pagination_from_url( $url, $_page, false );
|
398 |
+
}
|
399 |
+
|
400 |
+
if ( $this->is_singular_archive( $id ) ) {
|
401 |
+
// Singular archives, like blog pages and shop pages, use the pagination base with paged.
|
402 |
+
$url = $this->add_url_pagination( $url, $this->paged(), true );
|
403 |
+
}
|
404 |
}
|
405 |
|
406 |
+
return umemo( __METHOD__, $url, $id );
|
407 |
}
|
408 |
|
409 |
/**
|
410 |
* Returns taxonomical custom field's canonical URL.
|
411 |
*
|
412 |
* @since 4.0.0
|
413 |
+
* @since 4.2.0 The first parameter is now optional.
|
414 |
*
|
415 |
* @param int $term_id The term ID.
|
416 |
* @return string The custom canonical URL, if any.
|
417 |
*/
|
418 |
+
public function get_taxonomical_custom_canonical_url( $term_id = null ) {
|
419 |
return $this->get_term_meta_item( 'canonical', $term_id ) ?: '';
|
420 |
}
|
421 |
|
422 |
+
/**
|
423 |
+
* Returns post type archive custom field's canonical URL.
|
424 |
+
*
|
425 |
+
* @since 4.2.0
|
426 |
+
*
|
427 |
+
* @param string $pta The post type.
|
428 |
+
* @return string The custom canonical URL, if any.
|
429 |
+
*/
|
430 |
+
public function get_post_type_archive_custom_canonical_url( $pta = '' ) {
|
431 |
+
return $this->get_post_type_archive_meta_item( 'canonical', $pta ) ?: '';
|
432 |
+
}
|
433 |
+
|
434 |
/**
|
435 |
* Returns taxonomical canonical URL.
|
436 |
* Automatically adds pagination if the ID matches the query.
|
437 |
*
|
438 |
* @since 3.0.0
|
439 |
+
* @since 4.0.0 1. Renamed from "get_taxonomial_canonical_url" (note the typo)
|
440 |
* 2. Now works on the admin-screens.
|
441 |
+
* @since 4.2.0 1. Added memoization.
|
442 |
+
* 2. The parameters are now optional.
|
443 |
*
|
444 |
+
* @param int|null $term_id The term ID. Leave null to autodetermine.
|
445 |
+
* @param string $taxonomy The taxonomy. Leave empty to autodetermine.
|
446 |
* @return string The taxonomical canonical URL, if any.
|
447 |
*/
|
448 |
+
public function get_taxonomical_canonical_url( $term_id = null, $taxonomy = '' ) {
|
449 |
|
450 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
451 |
+
if ( null !== $memo = umemo( __METHOD__, null, $term_id, $taxonomy ) )
|
452 |
+
return $memo;
|
453 |
|
454 |
+
$url = \get_term_link( $term_id ?: $this->get_the_real_ID(), $taxonomy );
|
|
|
455 |
|
456 |
+
if ( \is_wp_error( $url ) )
|
457 |
+
return umemo( __METHOD__, '', $term_id, $taxonomy );
|
458 |
+
|
459 |
+
if ( null !== $term_id ) {
|
460 |
+
$paged = $this->paged();
|
461 |
+
|
462 |
+
if ( $paged > 1 )
|
463 |
+
$url = $this->add_url_pagination( $url, $paged, true );
|
464 |
}
|
465 |
|
466 |
+
return umemo( __METHOD__, $url, $term_id, $taxonomy );
|
467 |
}
|
468 |
|
469 |
/**
|
470 |
* Returns post type archive canonical URL.
|
471 |
*
|
472 |
* @since 3.0.0
|
473 |
+
* @since 4.0.0 1. Deprecated first parameter as integer. Use strings or null.
|
474 |
+
* 2. Now forwards post type object calling to WordPress's function.
|
475 |
+
* @since 4.2.0 1. Now correctly adds pagination to the URL.
|
476 |
+
* 2. Removed argument type deprecation doing it wrong warning.
|
477 |
*
|
478 |
* @param null|string $post_type The post type archive's post type.
|
479 |
* Leave null to use query, and allow pagination.
|
481 |
*/
|
482 |
public function get_post_type_archive_canonical_url( $post_type = null ) {
|
483 |
|
484 |
+
if ( ! $post_type ) {
|
485 |
+
$post_type = $this->get_current_post_type();
|
486 |
+
$is_query = true;
|
487 |
+
} else {
|
488 |
+
$is_query = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
489 |
}
|
490 |
|
491 |
+
$url = \get_post_type_archive_link( $post_type ) ?: '';
|
492 |
|
493 |
+
if ( $is_query && $url )
|
494 |
+
$url = $this->add_url_pagination( $url, $this->paged(), true );
|
495 |
|
496 |
+
return $url;
|
497 |
}
|
498 |
|
499 |
/**
|
501 |
* Automatically adds pagination if the ID matches the query.
|
502 |
*
|
503 |
* @since 3.0.0
|
504 |
+
* @since 4.2.0 1. The first parameter is now optional.
|
505 |
+
* 2. When the $id isn't set, the URL won't get tested for pagination issues.
|
506 |
*
|
507 |
+
* @param int|null $id The author ID. Leave null to autodetermine.
|
508 |
* @return string The author canonical URL, if any.
|
509 |
*/
|
510 |
+
public function get_author_canonical_url( $id = null ) {
|
|
|
|
|
511 |
|
512 |
+
$url = \get_author_posts_url( $id ?? $this->get_the_real_ID() );
|
|
|
513 |
|
514 |
+
if ( ! $url ) return '';
|
|
|
|
|
|
|
515 |
|
516 |
+
return null === $id
|
517 |
+
? $this->add_url_pagination( $url, $this->paged(), true )
|
518 |
+
: $url;
|
519 |
}
|
520 |
|
521 |
/**
|
563 |
}
|
564 |
|
565 |
if ( $_paginate ) {
|
566 |
+
// Adds pagination if input matches query.
|
567 |
$link = $this->add_url_pagination( $link, $this->paged(), true );
|
568 |
}
|
569 |
|
575 |
* Automatically adds pagination if the input matches the query.
|
576 |
*
|
577 |
* @since 3.0.0
|
578 |
+
* @since 3.1.0 1. The first parameter now defaults to null.
|
579 |
+
* 2. The search term is now matched with the input query if not set,
|
580 |
+
* instead of it being empty.
|
581 |
*
|
582 |
* @param string $query The search query. Mustn't be escaped.
|
583 |
* When left empty, the current query will be used.
|
595 |
$link = \get_search_link( $query );
|
596 |
|
597 |
if ( $_paginate ) {
|
598 |
+
// Adds pagination if input query isn't null.
|
599 |
$link = $this->add_url_pagination( $link, $this->paged(), true );
|
600 |
}
|
601 |
|
614 |
*/
|
615 |
public function get_preferred_scheme() {
|
616 |
|
617 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
618 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
619 |
|
620 |
switch ( $this->get_option( 'canonical_scheme' ) ) :
|
621 |
case 'https':
|
636 |
* @since 2.8.0
|
637 |
* @param string $scheme The current URL scheme.
|
638 |
*/
|
639 |
+
return memo( (string) \apply_filters( 'the_seo_framework_preferred_url_scheme', $scheme ) );
|
|
|
|
|
640 |
}
|
641 |
|
642 |
/**
|
655 |
* @return string The detected URl scheme, lowercase.
|
656 |
*/
|
657 |
public function detect_site_url_scheme() {
|
658 |
+
return strtolower( parse_url(
|
659 |
+
$this->get_home_url(),
|
660 |
+
PHP_URL_SCHEME
|
661 |
+
) ) ?: (
|
662 |
+
$this->is_ssl() ? 'https' : 'http'
|
663 |
+
);
|
664 |
}
|
665 |
|
666 |
/**
|
719 |
* @since 3.0.0
|
720 |
* @since 3.2.4 1. Now considers query arguments when using pretty permalinks.
|
721 |
* 2. The second and third parameters are now optional.
|
722 |
+
* @since 4.2.0 Now properly adds pagination to search links.
|
723 |
+
* @TODO call this add_pagination_to_url()? Or call remove_pagination_from_url() remove_url_pagination()?
|
724 |
*
|
725 |
* @param string $url The fully qualified URL.
|
726 |
* @param int $page The page number. Should be bigger than 1 to paginate.
|
732 |
*/
|
733 |
public function add_url_pagination( $url, $page = null, $use_base = null ) {
|
734 |
|
735 |
+
$_page = $page ?? max( $this->paged(), $this->page() );
|
736 |
|
737 |
if ( $_page < 2 )
|
738 |
return $url;
|
739 |
|
740 |
+
$_use_base = $use_base ?? (
|
741 |
+
$this->is_real_front_page() || $this->is_archive() || $this->is_singular_archive() || $this->is_search()
|
742 |
+
);
|
743 |
|
744 |
if ( $this->pretty_permalinks ) {
|
745 |
|
752 |
$base = $base ?: $GLOBALS['wp_rewrite']->pagination_base;
|
753 |
|
754 |
if ( $_use_base ) {
|
755 |
+
$url = \user_trailingslashit( \trailingslashit( $url ) . "$base/$_page", 'paged' );
|
756 |
} else {
|
757 |
$url = \user_trailingslashit( \trailingslashit( $url ) . $_page, 'single_paged' );
|
758 |
}
|
781 |
* 4. Now supports pretty permalinks with query parameters.
|
782 |
* 5. Is now public.
|
783 |
* @since 4.1.2 Now correctly reappends query when pagination isn't removed.
|
784 |
+
* @since 4.2.0 Now properly removes pagination from search links.
|
785 |
*
|
786 |
* @param string $url The fully qualified URL to remove pagination from.
|
787 |
* @param int|null $page The page number to remove. If null, it will get number from query.
|
794 |
public function remove_pagination_from_url( $url, $page = null, $use_base = null ) {
|
795 |
|
796 |
if ( $this->pretty_permalinks ) {
|
|
|
|
|
|
|
|
|
|
|
797 |
|
798 |
+
$_page = $page ?? max( $this->paged(), $this->page() );
|
799 |
|
800 |
if ( $_page > 1 ) {
|
801 |
$_url = $url;
|
802 |
|
803 |
+
$_use_base = $use_base ?? (
|
804 |
+
$this->is_real_front_page() || $this->is_archive() || $this->is_singular_archive() || $this->is_search()
|
805 |
+
);
|
806 |
+
|
807 |
+
$user_slash = ( $GLOBALS['wp_rewrite']->use_trailing_slashes ? '/' : '' );
|
808 |
|
809 |
if ( $_use_base ) {
|
810 |
+
$find = "/{$GLOBALS['wp_rewrite']->pagination_base}/{$_page}{$user_slash}";
|
811 |
} else {
|
812 |
+
$find = "/{$_page}{$user_slash}";
|
813 |
}
|
814 |
|
815 |
$_query = parse_url( $_url, PHP_URL_QUERY );
|
890 |
// FIXME: Core Report: WP doesn't accept paged parameters w/ date parameters. It'll lead to the homepage.
|
891 |
$_query = $GLOBALS['wp_query']->query;
|
892 |
$_date = [
|
893 |
+
'y' => $_query['year'] ?? '',
|
894 |
+
'm' => $_query['monthnum'] ?? '',
|
895 |
+
'd' => $_query['day'] ?? '',
|
896 |
];
|
897 |
|
898 |
$url = \add_query_arg( [ 'm' => implode( '', $_date ) ], $home );
|
902 |
// Generate shortlink for object type and slug.
|
903 |
$object = \get_queried_object();
|
904 |
|
905 |
+
$tax = $object->taxonomy ?? '';
|
906 |
+
$slug = $object->slug ?? '';
|
907 |
|
908 |
+
if ( $tax && $slug )
|
909 |
$url = \add_query_arg( [ $tax => $slug ], $home );
|
|
|
910 |
}
|
911 |
} elseif ( $this->is_search() ) {
|
912 |
$url = \add_query_arg( [ 's' => \get_search_query( false ) ], $home );
|
969 |
*/
|
970 |
public function get_paged_urls() {
|
971 |
|
972 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
973 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
974 |
|
975 |
$prev = $next = '';
|
976 |
|
977 |
if ( $this->has_custom_canonical_url() ) goto end;
|
978 |
|
|
|
979 |
if ( $this->is_singular() && ! $this->is_singular_archive() && $this->is_multipage() ) {
|
980 |
$_run = $this->is_real_front_page()
|
981 |
? $this->get_option( 'prev_next_frontpage' )
|
997 |
} else {
|
998 |
goto end;
|
999 |
}
|
|
|
1000 |
|
1001 |
// See if-statements below.
|
1002 |
if ( ! ( $page + 1 <= $_numpages || $page > 1 ) ) goto end;
|
1003 |
|
1004 |
+
$canonical_url = memo( null, 'canonical' )
|
1005 |
+
?? memo(
|
1006 |
+
$this->remove_pagination_from_url( $this->get_current_canonical_url() ),
|
1007 |
+
'canonical'
|
1008 |
+
);
|
1009 |
|
1010 |
// If this page is not the last, create a next-URL.
|
1011 |
+
if ( $page + 1 <= $_numpages )
|
1012 |
+
$next = $this->add_url_pagination( $canonical_url, $page + 1 );
|
1013 |
+
|
1014 |
// If this page is not the first, create a prev-URL.
|
1015 |
+
if ( $page > 1 )
|
1016 |
+
$prev = $this->add_url_pagination( $canonical_url, $page - 1 );
|
|
|
1017 |
|
1018 |
end:;
|
1019 |
|
1020 |
+
return memo( compact( 'next', 'prev' ) );
|
1021 |
}
|
1022 |
|
1023 |
/**
|
1026 |
* Memoizes the return value.
|
1027 |
*
|
1028 |
* @since 2.7.0
|
1029 |
+
* @since 2.9.2 1. Now considers port too.
|
1030 |
+
* 2. Now uses get_home_url(), rather than get_option('home').
|
1031 |
*
|
1032 |
* @return string The home URL host.
|
1033 |
*/
|
1034 |
public function get_home_host() {
|
1035 |
|
1036 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
1037 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
1038 |
|
1039 |
+
$parsed_url = parse_url(
|
1040 |
+
$this->get_home_url()
|
1041 |
+
);
|
1042 |
|
1043 |
+
$host = $parsed_url['host'] ?? '';
|
1044 |
|
1045 |
if ( $host && isset( $parsed_url['port'] ) )
|
1046 |
+
$host .= ":{$parsed_url['port']}";
|
1047 |
|
1048 |
+
return memo( $host );
|
1049 |
}
|
1050 |
|
1051 |
/**
|
1090 |
public function make_fully_qualified_url( $url ) {
|
1091 |
|
1092 |
if ( '//' === substr( $url, 0, 2 ) ) {
|
1093 |
+
$url = "http:$url";
|
1094 |
} elseif ( 'http' !== substr( $url, 0, 4 ) ) {
|
1095 |
+
$url = "http://{$url}";
|
1096 |
}
|
1097 |
|
1098 |
return $url;
|
1140 |
$url = \add_query_arg( $results, $url );
|
1141 |
|
1142 |
if ( $_fragment )
|
1143 |
+
$url .= "#$_fragment";
|
1144 |
|
1145 |
return $url;
|
1146 |
}
|
1159 |
if ( ! $url )
|
1160 |
return false;
|
1161 |
|
1162 |
+
$home_domain = memo() ?? memo(
|
1163 |
+
$this->set_url_scheme( \esc_url_raw(
|
1164 |
+
$this->get_home_url(),
|
1165 |
+
[ 'https', 'http' ]
|
1166 |
+
) )
|
1167 |
+
);
|
|
|
1168 |
|
1169 |
// Test for likely match early, before transforming.
|
1170 |
if ( 0 === stripos( $url, $home_domain ) )
|
1171 |
return true;
|
1172 |
|
1173 |
+
$url = $this->set_url_scheme( \esc_url_raw(
|
1174 |
+
$url,
|
1175 |
+
[ 'https', 'http' ]
|
1176 |
+
) );
|
1177 |
|
1178 |
+
// If they start with the same, we can assume it's the same domain.
|
1179 |
+
return 0 === stripos( $url, $home_domain );
|
1180 |
+
}
|
1181 |
|
1182 |
+
/**
|
1183 |
+
* Returns the home URL. Created for the WordPress method is slow for it
|
1184 |
+
* performs "set_url_scheme" calls slowly. We rely on this method for some
|
1185 |
+
* plugins filter `home_url`.
|
1186 |
+
* Memoized.
|
1187 |
+
*
|
1188 |
+
* @since 4.2.0
|
1189 |
+
*
|
1190 |
+
* @return string The home URL.
|
1191 |
+
*/
|
1192 |
+
public function get_home_url() {
|
1193 |
+
return umemo( __METHOD__ ) ?? umemo( __METHOD__, \get_home_url() );
|
1194 |
}
|
1195 |
}
|
@@ -38,8 +38,11 @@ class Generate extends User_Data {
|
|
38 |
* Fixes generation arguments, to prevent ID conflicts with taxonomies.
|
39 |
*
|
40 |
* @since 3.1.0
|
41 |
-
* @since 4.1.0 1
|
42 |
-
* 2
|
|
|
|
|
|
|
43 |
* @internal
|
44 |
*
|
45 |
* @param array|int|null $args The arguments, passed by reference.
|
@@ -49,72 +52,72 @@ class Generate extends User_Data {
|
|
49 |
if ( null === $args ) return;
|
50 |
|
51 |
if ( \is_array( $args ) ) {
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
],
|
58 |
-
$args
|
59 |
-
);
|
60 |
-
}
|
61 |
} elseif ( is_numeric( $args ) ) {
|
62 |
$args = [
|
63 |
'id' => (int) $args,
|
64 |
'taxonomy' => '',
|
|
|
65 |
];
|
66 |
} else {
|
67 |
$args = null;
|
68 |
}
|
69 |
}
|
70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
/**
|
72 |
* Returns the `noindex`, `nofollow`, `noarchive` robots meta code array.
|
73 |
*
|
74 |
* @since 4.1.4
|
|
|
|
|
75 |
*
|
76 |
-
* @param array|null $args
|
77 |
-
* @param null
|
78 |
-
*
|
79 |
-
*
|
80 |
-
*
|
81 |
-
*
|
82 |
-
*
|
|
|
|
|
83 |
* }
|
84 |
* @return array Only values actualized for display: {
|
85 |
* string index : string value
|
86 |
* }
|
87 |
*/
|
88 |
-
public function generate_robots_meta( $args = null, $get = null, $
|
89 |
|
90 |
-
|
91 |
-
$_meta = $this->get_robots_meta_by_query( $ignore );
|
92 |
-
|
93 |
-
if ( $this->is_query_exploited() ) {
|
94 |
-
$_meta['noindex'] = true;
|
95 |
-
$_meta['nofollow'] = true;
|
96 |
-
}
|
97 |
-
} else {
|
98 |
-
$this->fix_generation_args( $args );
|
99 |
-
$_meta = $this->get_robots_meta_by_args( $args, $ignore );
|
100 |
-
}
|
101 |
|
102 |
-
$meta =
|
103 |
-
'noindex' => '',
|
104 |
-
'nofollow' => '',
|
105 |
-
'noarchive' => '',
|
106 |
-
'max_snippet' => '',
|
107 |
-
'max_image_preview' => '',
|
108 |
-
'max_video_preview' => '',
|
109 |
-
];
|
110 |
|
|
|
111 |
foreach (
|
112 |
-
array_intersect_key( $
|
113 |
as $k => $v
|
114 |
) $v and $meta[ $k ] = $k;
|
115 |
|
|
|
116 |
foreach (
|
117 |
-
array_intersect_key( $
|
118 |
as $k => $v
|
119 |
) false !== $v and $meta[ $k ] = str_replace( '_', '-', $k ) . ":$v";
|
120 |
|
@@ -125,6 +128,7 @@ class Generate extends User_Data {
|
|
125 |
* @since 4.0.0 Added two parameters ($args and $ignore).
|
126 |
* @since 4.0.2 Now contains the copyright diretive values.
|
127 |
* @since 4.0.3 Changed `$meta` key `max_snippet_length` to `max_snippet`
|
|
|
128 |
*
|
129 |
* @param array $meta The current robots meta. {
|
130 |
* 'noindex' : 'noindex'|''
|
@@ -134,13 +138,13 @@ class Generate extends User_Data {
|
|
134 |
* 'max_image_preview' : 'max-image-preview:<string>'|''
|
135 |
* 'max_video_preview' : 'max-video-preview:<string>'|''
|
136 |
* }
|
137 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
138 |
* Is null when query is autodetermined.
|
139 |
-
* @param int <bit> $
|
140 |
-
* 0 =
|
141 |
-
* 1 =
|
142 |
-
* 2 =
|
143 |
-
*
|
144 |
* }
|
145 |
*/
|
146 |
return array_filter(
|
@@ -149,320 +153,12 @@ class Generate extends User_Data {
|
|
149 |
[
|
150 |
$meta,
|
151 |
$args,
|
152 |
-
$
|
153 |
]
|
154 |
)
|
155 |
);
|
156 |
}
|
157 |
|
158 |
-
/**
|
159 |
-
* Generates the `noindex`, `nofollow`, `noarchive` robots meta code array from query.
|
160 |
-
*
|
161 |
-
* @since 4.0.0
|
162 |
-
* @since 4.0.2 Added new copyright directive tags.
|
163 |
-
* @since 4.0.3 Changed `max_snippet_length` to `max_snippet`
|
164 |
-
* @since 4.0.5 1. The `$post_type` test now uses a real query ID, instead of `$GLOBALS['post']`;
|
165 |
-
* mitigating issues with singular-archives pages (blog, shop, etc.).
|
166 |
-
* 2. Now disregards empty blog pages for automatic `noindex`; although this protection is necessary,
|
167 |
-
* it can not be reflected in the SEO Bar.
|
168 |
-
* @since 4.1.0 Now uses the new taxonomy robots settings.
|
169 |
-
* @global \WP_Query $wp_query
|
170 |
-
*
|
171 |
-
* @param int <bit> $ignore The ignore level. {
|
172 |
-
* 0 = 0b00: Ignore nothing.
|
173 |
-
* 1 = 0b01: Ignore protection. (\The_SEO_Framework\ROBOTS_IGNORE_PROTECTION)
|
174 |
-
* 2 = 0b10: Ignore post/term meta settings. (\The_SEO_Framework\ROBOTS_IGNORE_SETTINGS)
|
175 |
-
* 3 = 0b11: Ignore protection and post/term meta setting.
|
176 |
-
* }
|
177 |
-
* @return array|null robots : {
|
178 |
-
* bool 'noindex'
|
179 |
-
* bool 'nofollow'
|
180 |
-
* bool 'noarchive'
|
181 |
-
* false|int <R>=-1<=600> 'max_snippet'
|
182 |
-
* false|string 'max_image_preview'
|
183 |
-
* fasle|int <R>=-1<=600> 'max_video_preview'
|
184 |
-
* }
|
185 |
-
*/
|
186 |
-
protected function get_robots_meta_by_query( $ignore = 0b00 ) {
|
187 |
-
|
188 |
-
$noindex = (bool) $this->get_option( 'site_noindex' );
|
189 |
-
$nofollow = (bool) $this->get_option( 'site_nofollow' );
|
190 |
-
$noarchive = (bool) $this->get_option( 'site_noarchive' );
|
191 |
-
|
192 |
-
$max_snippet = $max_image_preview = $max_video_preview = false;
|
193 |
-
|
194 |
-
if ( $this->get_option( 'set_copyright_directives' ) ) {
|
195 |
-
$max_snippet = $this->get_option( 'max_snippet_length' );
|
196 |
-
$max_image_preview = $this->get_option( 'max_image_preview' );
|
197 |
-
$max_video_preview = $this->get_option( 'max_video_preview' );
|
198 |
-
}
|
199 |
-
|
200 |
-
// Check homepage SEO settings, set noindex, nofollow and noarchive
|
201 |
-
if ( $this->is_real_front_page() ) {
|
202 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r )
|
203 |
-
$$r = $$r || $this->get_option( "homepage_$r" );
|
204 |
-
|
205 |
-
if ( ! ( $ignore & ROBOTS_IGNORE_PROTECTION ) ) :
|
206 |
-
$noindex = $noindex
|
207 |
-
|| ( $this->get_option( 'home_paged_noindex' ) && ( $this->page() > 1 || $this->paged() > 1 ) );
|
208 |
-
endif;
|
209 |
-
} else {
|
210 |
-
global $wp_query;
|
211 |
-
|
212 |
-
if ( $this->is_singular_archive() ) {
|
213 |
-
/**
|
214 |
-
* Pagination overflow protection via 404 test.
|
215 |
-
*
|
216 |
-
* When there are no posts, the first page will NOT relay 404;
|
217 |
-
* which is exactly as intended. All other pages will relay 404.
|
218 |
-
*
|
219 |
-
* We do not test the post_count here, because we want to have
|
220 |
-
* the first page indexable via user-intent only.
|
221 |
-
*/
|
222 |
-
$noindex = $noindex || $this->is_404();
|
223 |
-
} else {
|
224 |
-
/**
|
225 |
-
* Check for 404, or if archive is empty: set noindex for those.
|
226 |
-
*
|
227 |
-
* Don't check this on the homepage. The homepage is sacred in this regard,
|
228 |
-
* because page builders and templates can and will take over.
|
229 |
-
*
|
230 |
-
* Don't use empty(), null is regarded as indexable.
|
231 |
-
*/
|
232 |
-
if ( isset( $wp_query->post_count ) && ! $wp_query->post_count ) {
|
233 |
-
/**
|
234 |
-
* We recommend using this filter ONLY for archives that have useful content but no "posts" attached.
|
235 |
-
* For example: a specially custom-developed author page for an author that never published a post.
|
236 |
-
*
|
237 |
-
* This filter won't run when a few other conditions for noindex have been met.
|
238 |
-
*
|
239 |
-
* @since 4.1.4
|
240 |
-
* @link <https://github.com/sybrew/the-seo-framework/issues/194#issuecomment-864298702>
|
241 |
-
* @param bool $noindex Whether to enable no posts protection.
|
242 |
-
*/
|
243 |
-
$noindex = $noindex || \apply_filters( 'the_seo_framework_enable_noindex_no_posts', true );
|
244 |
-
}
|
245 |
-
}
|
246 |
-
|
247 |
-
if (
|
248 |
-
! $noindex
|
249 |
-
&& $this->get_option( 'paged_noindex' )
|
250 |
-
&& ( $this->is_archive() || $this->is_singular_archive() )
|
251 |
-
&& $this->paged() > 1
|
252 |
-
) {
|
253 |
-
$noindex = true;
|
254 |
-
}
|
255 |
-
|
256 |
-
if ( $this->is_archive() ) {
|
257 |
-
if ( $this->is_author() ) {
|
258 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r )
|
259 |
-
$$r = $$r || $this->get_option( "author_$r" );
|
260 |
-
} elseif ( $this->is_date() ) {
|
261 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r )
|
262 |
-
$$r = $$r || $this->get_option( "date_$r" );
|
263 |
-
}
|
264 |
-
} elseif ( $this->is_search() ) {
|
265 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r )
|
266 |
-
$$r = $$r || $this->get_option( "search_$r" );
|
267 |
-
}
|
268 |
-
}
|
269 |
-
|
270 |
-
if ( $this->is_archive() ) {
|
271 |
-
$taxonomy = $this->get_current_taxonomy();
|
272 |
-
|
273 |
-
$_post_type_meta = [];
|
274 |
-
// Store values from each post type bound to the taxonomy.
|
275 |
-
foreach ( $this->get_post_types_from_taxonomy() as $post_type ) {
|
276 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) {
|
277 |
-
// SECURITY: Put in array to circumvent GLOBALS injection in sequenting loop.
|
278 |
-
$_post_type_meta[ $r ][] = $$r || $this->is_post_type_robots_set( $r, $post_type );
|
279 |
-
}
|
280 |
-
}
|
281 |
-
// Only enable if all post types have the value ticked.
|
282 |
-
foreach ( $_post_type_meta as $r => $_values )
|
283 |
-
$$r = $$r || ! \in_array( false, $_values, true );
|
284 |
-
|
285 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r )
|
286 |
-
$$r = $$r || $this->is_taxonomy_robots_set( $r, $taxonomy );
|
287 |
-
|
288 |
-
if ( ! ( $ignore & ROBOTS_IGNORE_SETTINGS ) ) :
|
289 |
-
$term_meta = $this->get_current_term_meta();
|
290 |
-
|
291 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) {
|
292 |
-
if ( isset( $term_meta[ $r ] ) ) {
|
293 |
-
// Test qubit
|
294 |
-
$$r = ( $$r | (int) $term_meta[ $r ] ) > .33;
|
295 |
-
}
|
296 |
-
}
|
297 |
-
endif;
|
298 |
-
} elseif ( $this->is_singular() ) {
|
299 |
-
$post_type = $this->get_current_post_type();
|
300 |
-
|
301 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r )
|
302 |
-
$$r = $$r || $this->is_post_type_robots_set( $r, $post_type );
|
303 |
-
|
304 |
-
if ( ! ( $ignore & ROBOTS_IGNORE_SETTINGS ) ) :
|
305 |
-
$post_meta = [
|
306 |
-
'noindex' => $this->get_post_meta_item( '_genesis_noindex' ),
|
307 |
-
'nofollow' => $this->get_post_meta_item( '_genesis_nofollow' ),
|
308 |
-
'noarchive' => $this->get_post_meta_item( '_genesis_noarchive' ),
|
309 |
-
];
|
310 |
-
|
311 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) {
|
312 |
-
// Test qubit
|
313 |
-
$$r = ( $$r | (int) $post_meta[ $r ] ) > .33;
|
314 |
-
}
|
315 |
-
endif;
|
316 |
-
|
317 |
-
// I hate this reiteration of the very same code as above... but, homepage may not always be singular.
|
318 |
-
// The conditions below MUST overwrite this, too. So, this is the perfect placement.
|
319 |
-
if ( $this->is_real_front_page() ) {
|
320 |
-
if ( ! ( $ignore & ROBOTS_IGNORE_PROTECTION ) ) :
|
321 |
-
$noindex = $noindex
|
322 |
-
|| ( $this->get_option( 'home_paged_noindex' ) && ( $this->page() > 1 || $this->paged() > 1 ) );
|
323 |
-
endif;
|
324 |
-
}
|
325 |
-
|
326 |
-
// Overwrite and ignore the user's settings, regardless; unless ignore is set.
|
327 |
-
if ( ! ( $ignore & ROBOTS_IGNORE_PROTECTION ) ) :
|
328 |
-
$noindex = $noindex || $this->is_protected( $this->get_the_real_ID() );
|
329 |
-
endif;
|
330 |
-
|
331 |
-
/**
|
332 |
-
* Noindex on comment pagination.
|
333 |
-
* Overwrites and ignores the user's settings, always.
|
334 |
-
*
|
335 |
-
* N.B. WordPress protects this query variable with options 'page_comments'
|
336 |
-
* and 'default_comments_page' via `redirect_canonical()`, so we don't have to.
|
337 |
-
* For reference, it fires `remove_query_arg( 'cpage', $redirect['query'] )`;
|
338 |
-
*/
|
339 |
-
if ( (int) \get_query_var( 'cpage', 0 ) > 0 ) {
|
340 |
-
/**
|
341 |
-
* We do not recommend using this filter as it'll likely get those pages flagged as
|
342 |
-
* duplicated by Google anyway; unless the theme strips or trims the content.
|
343 |
-
*
|
344 |
-
* This filter won't run when other conditions for noindex have been met.
|
345 |
-
*
|
346 |
-
* @since 4.0.5
|
347 |
-
* @param bool $noindex Whether to enable comment pagination protection.
|
348 |
-
*/
|
349 |
-
$noindex = $noindex || \apply_filters( 'the_seo_framework_enable_noindex_comment_pagination', true );
|
350 |
-
}
|
351 |
-
}
|
352 |
-
|
353 |
-
return compact( 'noindex', 'nofollow', 'noarchive', 'max_snippet', 'max_image_preview', 'max_video_preview' );
|
354 |
-
}
|
355 |
-
|
356 |
-
/**
|
357 |
-
* Generates the `noindex`, `nofollow`, `noarchive` robots meta code array from arguments.
|
358 |
-
*
|
359 |
-
* Note that the home-as-blog page can be used for this method.
|
360 |
-
*
|
361 |
-
* @since 4.0.0
|
362 |
-
* @since 4.0.2 Added new copyright directive tags.
|
363 |
-
* @since 4.0.3 Changed `max_snippet_length` to `max_snippet`
|
364 |
-
* @since 4.1.0 Now uses the new taxonomy robots settings.
|
365 |
-
*
|
366 |
-
* @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
|
367 |
-
* @param int <bit> $ignore The ignore level. {
|
368 |
-
* 0 = 0b00: Ignore nothing.
|
369 |
-
* 1 = 0b01: Ignore protection. (\The_SEO_Framework\ROBOTS_IGNORE_PROTECTION)
|
370 |
-
* 2 = 0b10: Ignore post/term meta setting. (\The_SEO_Framework\ROBOTS_IGNORE_SETTINGS)
|
371 |
-
* 3 = 0b11: Ignore protection and post/term meta setting.
|
372 |
-
* }
|
373 |
-
* @return array|null robots : {
|
374 |
-
* bool 'noindex'
|
375 |
-
* bool 'nofollow'
|
376 |
-
* bool 'noarchive'
|
377 |
-
* false|int <R>=-1> 'max_snippet'
|
378 |
-
* false|string 'max_image_preview'
|
379 |
-
* fasle|int <R>=-1> 'max_video_preview'
|
380 |
-
* }
|
381 |
-
*/
|
382 |
-
protected function get_robots_meta_by_args( $args, $ignore = 0b00 ) {
|
383 |
-
|
384 |
-
$noindex = (bool) $this->get_option( 'site_noindex' );
|
385 |
-
$nofollow = (bool) $this->get_option( 'site_nofollow' );
|
386 |
-
$noarchive = (bool) $this->get_option( 'site_noarchive' );
|
387 |
-
|
388 |
-
$max_snippet = $max_image_preview = $max_video_preview = false;
|
389 |
-
|
390 |
-
if ( $this->get_option( 'set_copyright_directives' ) ) {
|
391 |
-
$max_snippet = $this->get_option( 'max_snippet_length' );
|
392 |
-
$max_image_preview = $this->get_option( 'max_image_preview' );
|
393 |
-
$max_video_preview = $this->get_option( 'max_video_preview' );
|
394 |
-
}
|
395 |
-
|
396 |
-
// Put outside the loop, id=0 may be used here for home-as-blog.
|
397 |
-
if ( ! $args['taxonomy'] && $this->is_real_front_page_by_id( $args['id'] ) ) {
|
398 |
-
$noindex = $noindex || $this->get_option( 'homepage_noindex' );
|
399 |
-
$nofollow = $nofollow || $this->get_option( 'homepage_nofollow' );
|
400 |
-
$noarchive = $noarchive || $this->get_option( 'homepage_noarchive' );
|
401 |
-
}
|
402 |
-
|
403 |
-
if ( $args['taxonomy'] ) {
|
404 |
-
$term = \get_term( $args['id'], $args['taxonomy'] );
|
405 |
-
/**
|
406 |
-
* Check if archive is empty: set noindex for those.
|
407 |
-
*/
|
408 |
-
if ( empty( $term->count ) )
|
409 |
-
$noindex = true;
|
410 |
-
|
411 |
-
$_post_type_meta = [];
|
412 |
-
// Store values from each post type bound to the taxonomy.
|
413 |
-
foreach ( $this->get_post_types_from_taxonomy( $args['taxonomy'] ) as $post_type ) {
|
414 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) {
|
415 |
-
// SECURITY: Put in array to circumvent GLOBALS injection.
|
416 |
-
$_post_type_meta[ $r ][] = $$r || $this->is_post_type_robots_set( $r, $post_type );
|
417 |
-
}
|
418 |
-
}
|
419 |
-
// Only enable if all post types have the value ticked.
|
420 |
-
foreach ( $_post_type_meta as $r => $_values ) {
|
421 |
-
$$r = $$r || ! \in_array( false, $_values, true );
|
422 |
-
}
|
423 |
-
|
424 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) {
|
425 |
-
$$r = $$r || $this->is_taxonomy_robots_set( $r, $args['taxonomy'] );
|
426 |
-
}
|
427 |
-
|
428 |
-
if ( ! ( $ignore & ROBOTS_IGNORE_SETTINGS ) ) :
|
429 |
-
$term_meta = $this->get_term_meta( $args['id'] );
|
430 |
-
|
431 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) {
|
432 |
-
if ( isset( $term_meta[ $r ] ) ) {
|
433 |
-
// Test qubit
|
434 |
-
$$r = ( $$r | (int) $term_meta[ $r ] ) > .33;
|
435 |
-
}
|
436 |
-
}
|
437 |
-
endif;
|
438 |
-
} elseif ( $args['id'] ) {
|
439 |
-
$post_type = \get_post_type( $args['id'] );
|
440 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) {
|
441 |
-
$$r = $$r || $this->is_post_type_robots_set( $r, $post_type );
|
442 |
-
}
|
443 |
-
|
444 |
-
if ( ! ( $ignore & ROBOTS_IGNORE_SETTINGS ) ) :
|
445 |
-
$post_meta = [
|
446 |
-
'noindex' => $this->get_post_meta_item( '_genesis_noindex', $args['id'] ),
|
447 |
-
'nofollow' => $this->get_post_meta_item( '_genesis_nofollow', $args['id'] ),
|
448 |
-
'noarchive' => $this->get_post_meta_item( '_genesis_noarchive', $args['id'] ),
|
449 |
-
];
|
450 |
-
|
451 |
-
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) {
|
452 |
-
// Test qubit
|
453 |
-
$$r = ( $$r | (int) $post_meta[ $r ] ) > .33;
|
454 |
-
}
|
455 |
-
endif;
|
456 |
-
|
457 |
-
// Overwrite and ignore the user's settings, regardless; unless ignore is set.
|
458 |
-
if ( ! ( $ignore & ROBOTS_IGNORE_PROTECTION ) ) :
|
459 |
-
$noindex = $noindex || $this->is_protected( $args['id'] );
|
460 |
-
endif;
|
461 |
-
}
|
462 |
-
|
463 |
-
return compact( 'noindex', 'nofollow', 'noarchive', 'max_snippet', 'max_image_preview', 'max_video_preview' );
|
464 |
-
}
|
465 |
-
|
466 |
/**
|
467 |
* Determines if the post type has a robots value set.
|
468 |
*
|
@@ -515,39 +211,63 @@ class Generate extends User_Data {
|
|
515 |
* @return string The separator.
|
516 |
*/
|
517 |
public function get_separator( $type = 'title' ) {
|
518 |
-
|
519 |
-
$sep_option = $this->get_option( $type . '_separator' );
|
520 |
-
$sep_list = $this->get_separator_list();
|
521 |
-
|
522 |
-
return isset( $sep_list[ $sep_option ] ) ? $sep_list[ $sep_option ] : '-';
|
523 |
}
|
524 |
|
525 |
/**
|
526 |
-
* Fetches blogname (site title).
|
527 |
* Memoizes the return value.
|
528 |
*
|
|
|
|
|
529 |
* @since 2.5.2
|
530 |
-
*
|
|
|
531 |
*
|
532 |
-
* @return string $blogname The
|
533 |
*/
|
534 |
public function get_blogname() {
|
535 |
-
|
536 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
537 |
}
|
538 |
|
539 |
/**
|
540 |
* Fetch blog description.
|
541 |
* Memoizes the return value.
|
542 |
*
|
|
|
|
|
|
|
|
|
543 |
* @since 2.5.2
|
544 |
* @since 3.0.0 No longer returns untitled when empty, instead, it just returns an empty string.
|
545 |
*
|
546 |
-
* @return string $blogname The
|
547 |
*/
|
548 |
public function get_blogdescription() {
|
549 |
-
|
550 |
-
return isset( $description ) ? $description : $description = trim( \get_bloginfo( 'description', 'display' ) );
|
551 |
}
|
552 |
|
553 |
/**
|
@@ -565,18 +285,17 @@ class Generate extends User_Data {
|
|
565 |
$match = \get_locale();
|
566 |
|
567 |
$match_len = \strlen( $match );
|
568 |
-
$valid_locales = $this->
|
569 |
|
570 |
if ( $match_len > 5 ) {
|
571 |
$match_len = 5;
|
572 |
-
// More than standard-full locale
|
573 |
$match = substr( $match, 0, $match_len );
|
574 |
}
|
575 |
|
576 |
if ( 5 === $match_len ) {
|
577 |
-
// Full locale is used.
|
578 |
-
|
579 |
-
if ( \in_array( $match, $valid_locales, true ) )
|
580 |
return $match;
|
581 |
|
582 |
// Convert to only language portion.
|
@@ -585,17 +304,14 @@ class Generate extends User_Data {
|
|
585 |
}
|
586 |
|
587 |
if ( 2 === $match_len ) {
|
588 |
-
// Only
|
589 |
-
|
590 |
-
// Find first matching key.
|
591 |
-
$key = array_search( $match, $this->language_keys(), true );
|
592 |
|
593 |
-
if ( $key )
|
594 |
-
return $
|
595 |
-
}
|
596 |
}
|
597 |
|
598 |
-
// Return default locale.
|
599 |
return 'en_US';
|
600 |
}
|
601 |
|
@@ -630,24 +346,20 @@ class Generate extends User_Data {
|
|
630 |
* @return string
|
631 |
*/
|
632 |
public function get_og_type() {
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
[
|
648 |
-
$this->generate_og_type(),
|
649 |
-
$this->get_the_real_ID(),
|
650 |
-
]
|
651 |
);
|
652 |
}
|
653 |
|
@@ -661,42 +373,33 @@ class Generate extends User_Data {
|
|
661 |
*/
|
662 |
public function get_modified_time() {
|
663 |
|
664 |
-
|
665 |
-
|
666 |
-
if ( isset( $time ) )
|
667 |
-
return $time;
|
668 |
|
669 |
$id = $this->get_the_real_ID();
|
670 |
|
671 |
$post = \get_post( $id );
|
672 |
$post_modified_gmt = $post->post_modified_gmt;
|
673 |
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
|
|
689 |
);
|
690 |
}
|
691 |
|
692 |
-
/**
|
693 |
-
* @since 3.1.0
|
694 |
-
* @TODO use this
|
695 |
-
* @see get_available_twitter_cards
|
696 |
-
* @ignore
|
697 |
-
*/
|
698 |
-
public function get_available_open_graph_types() { }
|
699 |
-
|
700 |
/**
|
701 |
* Generates the Twitter Card type.
|
702 |
*
|
@@ -717,15 +420,7 @@ class Generate extends User_Data {
|
|
717 |
$option = $this->get_option( 'twitter_card' );
|
718 |
|
719 |
// Option is equal to found cards. Output option.
|
720 |
-
|
721 |
-
if ( 'summary_large_image' === $option ) {
|
722 |
-
$type = 'summary_large_image';
|
723 |
-
} elseif ( 'summary' === $option ) {
|
724 |
-
$type = 'summary';
|
725 |
-
}
|
726 |
-
} else {
|
727 |
-
$type = 'summary';
|
728 |
-
}
|
729 |
|
730 |
/**
|
731 |
* @since 2.3.0
|
@@ -744,34 +439,24 @@ class Generate extends User_Data {
|
|
744 |
|
745 |
/**
|
746 |
* Determines which Twitter cards can be used.
|
747 |
-
* Memoizes the return value.
|
748 |
*
|
749 |
* @since 2.9.0
|
750 |
* @since 4.0.0 1. Now only asserts the social titles as required.
|
751 |
* 2. Now always returns an array, instead of a boolean (false) on failure.
|
|
|
|
|
752 |
*
|
753 |
* @return array False when it shouldn't be used. Array of available cards otherwise.
|
754 |
*/
|
755 |
public function get_available_twitter_cards() {
|
756 |
-
|
757 |
-
static $cache = null;
|
758 |
-
|
759 |
-
if ( isset( $cache ) )
|
760 |
-
return $cache;
|
761 |
-
|
762 |
-
if ( ! $this->get_twitter_title() ) {
|
763 |
-
$retval = [];
|
764 |
-
} else {
|
765 |
-
$retval = [ 'summary_large_image', 'summary' ];
|
766 |
-
}
|
767 |
-
|
768 |
/**
|
769 |
* @since 2.9.0
|
770 |
-
* @param array $
|
771 |
*/
|
772 |
-
|
773 |
-
|
774 |
-
|
|
|
775 |
}
|
776 |
|
777 |
/**
|
@@ -833,10 +518,12 @@ class Generate extends User_Data {
|
|
833 |
* Returns the redirect URL, if any.
|
834 |
*
|
835 |
* @since 4.1.4
|
|
|
|
|
836 |
*
|
837 |
* @param null|array $args The redirect URL arguments, leave null to autodetermine query : {
|
838 |
-
* int $id
|
839 |
-
* string $taxonomy
|
840 |
* }
|
841 |
* @return string The canonical URL if found, empty string otherwise.
|
842 |
*/
|
@@ -849,13 +536,17 @@ class Generate extends User_Data {
|
|
849 |
$url = $this->get_post_meta_item( 'redirect' ) ?: '';
|
850 |
} elseif ( $this->is_term_meta_capable() ) {
|
851 |
$url = $this->get_term_meta_item( 'redirect' ) ?: '';
|
|
|
|
|
852 |
}
|
853 |
} else {
|
854 |
$this->fix_generation_args( $args );
|
855 |
-
if (
|
856 |
-
$url = $this->get_post_meta_item( 'redirect', $args['id'] ) ?: '';
|
857 |
-
} else {
|
858 |
$url = $this->get_term_meta_item( 'redirect', $args['id'] ) ?: '';
|
|
|
|
|
|
|
|
|
859 |
}
|
860 |
}
|
861 |
|
38 |
* Fixes generation arguments, to prevent ID conflicts with taxonomies.
|
39 |
*
|
40 |
* @since 3.1.0
|
41 |
+
* @since 4.1.0 1. Improved performance by testing for null first.
|
42 |
+
* 2. Improved performance by testing argument keys prior array merge.
|
43 |
+
* @since 4.2.0 1. Added support for the 'pta' index.
|
44 |
+
* 2. Removed isset() check -- we now expect incomplete $args, always.
|
45 |
+
* 3. Improved performance by 60% switching from array_merge to array_union.
|
46 |
* @internal
|
47 |
*
|
48 |
* @param array|int|null $args The arguments, passed by reference.
|
52 |
if ( null === $args ) return;
|
53 |
|
54 |
if ( \is_array( $args ) ) {
|
55 |
+
$args += [
|
56 |
+
'id' => 0,
|
57 |
+
'taxonomy' => '',
|
58 |
+
'pta' => '',
|
59 |
+
];
|
|
|
|
|
|
|
|
|
60 |
} elseif ( is_numeric( $args ) ) {
|
61 |
$args = [
|
62 |
'id' => (int) $args,
|
63 |
'taxonomy' => '',
|
64 |
+
'pta' => '',
|
65 |
];
|
66 |
} else {
|
67 |
$args = null;
|
68 |
}
|
69 |
}
|
70 |
|
71 |
+
/**
|
72 |
+
* Returns an array of the collected robots meta assertions.
|
73 |
+
*
|
74 |
+
* This only works when generate_robots_meta()'s $options value was given:
|
75 |
+
* The_SEO_Framework\ROBOTS_ASSERT (0b100);
|
76 |
+
*
|
77 |
+
* @since 4.2.0
|
78 |
+
*
|
79 |
+
* @return array
|
80 |
+
*/
|
81 |
+
public function retrieve_robots_meta_assertions() {
|
82 |
+
return Builders\Robots\Main::instance()->collect_assertions();
|
83 |
+
}
|
84 |
+
|
85 |
/**
|
86 |
* Returns the `noindex`, `nofollow`, `noarchive` robots meta code array.
|
87 |
*
|
88 |
* @since 4.1.4
|
89 |
+
* @since 4.2.0 1. Now offloads metadata generation to an actual generator.
|
90 |
+
* 2. Now supports the `$args['pta']` index.
|
91 |
*
|
92 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
93 |
+
* @param null|array $get The robots types to retrieve. Leave null to get all. Set array to pick: {
|
94 |
+
* 'noindex', 'nofollow', 'noarchive', 'max_snippet', 'max_image_preview', 'max_video_preview'
|
95 |
+
* }
|
96 |
+
* @param int <bit> $options The options level. {
|
97 |
+
* 0 = 0b000: Ignore nothing. Collect no assertions. (Default front-end.)
|
98 |
+
* 1 = 0b001: Ignore protection. (\The_SEO_Framework\ROBOTS_IGNORE_PROTECTION)
|
99 |
+
* 2 = 0b010: Ignore post/term setting. (\The_SEO_Framework\ROBOTS_IGNORE_SETTINGS)
|
100 |
+
* 4 = 0b100: Collect assertions. (\The_SEO_Framework\ROBOTS_ASSERT)
|
101 |
* }
|
102 |
* @return array Only values actualized for display: {
|
103 |
* string index : string value
|
104 |
* }
|
105 |
*/
|
106 |
+
public function generate_robots_meta( $args = null, $get = null, $options = 0b00 ) {
|
107 |
|
108 |
+
$this->fix_generation_args( $args );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
|
110 |
+
$meta = Builders\Robots\Main::instance()->set( $args, $options )->get( $get );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
|
112 |
+
// Convert the [ 'noindex' => true ] to [ 'noindex' => 'noindex' ]
|
113 |
foreach (
|
114 |
+
array_intersect_key( $meta, array_flip( [ 'noindex', 'nofollow', 'noarchive' ] ) )
|
115 |
as $k => $v
|
116 |
) $v and $meta[ $k ] = $k;
|
117 |
|
118 |
+
// Convert the [ 'max_snippet' => x ] to [ 'max-snippet' => 'max-snippet:x' ]
|
119 |
foreach (
|
120 |
+
array_intersect_key( $meta, array_flip( [ 'max_snippet', 'max_image_preview', 'max_video_preview' ] ) )
|
121 |
as $k => $v
|
122 |
) false !== $v and $meta[ $k ] = str_replace( '_', '-', $k ) . ":$v";
|
123 |
|
128 |
* @since 4.0.0 Added two parameters ($args and $ignore).
|
129 |
* @since 4.0.2 Now contains the copyright diretive values.
|
130 |
* @since 4.0.3 Changed `$meta` key `max_snippet_length` to `max_snippet`
|
131 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
132 |
*
|
133 |
* @param array $meta The current robots meta. {
|
134 |
* 'noindex' : 'noindex'|''
|
138 |
* 'max_image_preview' : 'max-image-preview:<string>'|''
|
139 |
* 'max_video_preview' : 'max-video-preview:<string>'|''
|
140 |
* }
|
141 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
142 |
* Is null when query is autodetermined.
|
143 |
+
* @param int <bit> $options The ignore level. {
|
144 |
+
* 0 = 0b000: Ignore nothing. Collect nothing. (Default front-end.)
|
145 |
+
* 1 = 0b001: Ignore protection. (\The_SEO_Framework\ROBOTS_IGNORE_PROTECTION)
|
146 |
+
* 2 = 0b010: Ignore post/term setting. (\The_SEO_Framework\ROBOTS_IGNORE_SETTINGS)
|
147 |
+
* 4 = 0b100: Collect assertions.
|
148 |
* }
|
149 |
*/
|
150 |
return array_filter(
|
153 |
[
|
154 |
$meta,
|
155 |
$args,
|
156 |
+
$options,
|
157 |
]
|
158 |
)
|
159 |
);
|
160 |
}
|
161 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
/**
|
163 |
* Determines if the post type has a robots value set.
|
164 |
*
|
211 |
* @return string The separator.
|
212 |
*/
|
213 |
public function get_separator( $type = 'title' ) {
|
214 |
+
return $this->get_separator_list()[ $this->get_option( $type . '_separator' ) ] ?? '-';
|
|
|
|
|
|
|
|
|
215 |
}
|
216 |
|
217 |
/**
|
218 |
+
* Fetches public blogname (site title).
|
219 |
* Memoizes the return value.
|
220 |
*
|
221 |
+
* Do not consider this function safe for printing!
|
222 |
+
*
|
223 |
* @since 2.5.2
|
224 |
+
* @since 4.2.0 1. Now listens to the new `site_title` option.
|
225 |
+
* 2. Now applies filters.
|
226 |
*
|
227 |
+
* @return string $blogname The sanitized blogname.
|
228 |
*/
|
229 |
public function get_blogname() {
|
230 |
+
return memo()
|
231 |
+
?? memo( $this->get_option( 'site_title' ) ?: $this->get_filtered_raw_blogname() );
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Fetches blogname (site title).
|
236 |
+
*
|
237 |
+
* Do not consider this function safe for printing!
|
238 |
+
*
|
239 |
+
* We use get_bloginfo( ..., 'display' ), even though it escapes needlessly, because it applies filters.
|
240 |
+
*
|
241 |
+
* @since 4.2.0
|
242 |
+
*
|
243 |
+
* @return string $blogname The sanitized blogname.
|
244 |
+
*/
|
245 |
+
public function get_filtered_raw_blogname() {
|
246 |
+
/**
|
247 |
+
* @since 4.2.0
|
248 |
+
* @param string The blog name.
|
249 |
+
*/
|
250 |
+
return (string) \apply_filters(
|
251 |
+
'the_seo_framework_blog_name',
|
252 |
+
trim( \get_bloginfo( 'name', 'display' ) )
|
253 |
+
);
|
254 |
}
|
255 |
|
256 |
/**
|
257 |
* Fetch blog description.
|
258 |
* Memoizes the return value.
|
259 |
*
|
260 |
+
* Do not consider this function safe for printing!
|
261 |
+
*
|
262 |
+
* We use get_bloginfo( ..., 'display' ), even though it escapes needlessly, because it applies filters.
|
263 |
+
*
|
264 |
* @since 2.5.2
|
265 |
* @since 3.0.0 No longer returns untitled when empty, instead, it just returns an empty string.
|
266 |
*
|
267 |
+
* @return string $blogname The sanitized blog description.
|
268 |
*/
|
269 |
public function get_blogdescription() {
|
270 |
+
return memo() ?? memo( trim( \get_bloginfo( 'description', 'display' ) ) );
|
|
|
271 |
}
|
272 |
|
273 |
/**
|
285 |
$match = \get_locale();
|
286 |
|
287 |
$match_len = \strlen( $match );
|
288 |
+
$valid_locales = $this->supported_social_locales(); // [ ll_LL => ll ]
|
289 |
|
290 |
if ( $match_len > 5 ) {
|
291 |
$match_len = 5;
|
292 |
+
// More than standard-full locale type is used. Make it just full.
|
293 |
$match = substr( $match, 0, $match_len );
|
294 |
}
|
295 |
|
296 |
if ( 5 === $match_len ) {
|
297 |
+
// Full locale is used. See if it's valid and return it.
|
298 |
+
if ( isset( $valid_locales[ $match ] ) )
|
|
|
299 |
return $match;
|
300 |
|
301 |
// Convert to only language portion.
|
304 |
}
|
305 |
|
306 |
if ( 2 === $match_len ) {
|
307 |
+
// Only two letters of the lang are provided. Find first match and return it.
|
308 |
+
$key = array_search( $match, $valid_locales, true );
|
|
|
|
|
309 |
|
310 |
+
if ( $key )
|
311 |
+
return $key;
|
|
|
312 |
}
|
313 |
|
314 |
+
// Return default WordPress locale.
|
315 |
return 'en_US';
|
316 |
}
|
317 |
|
346 |
* @return string
|
347 |
*/
|
348 |
public function get_og_type() {
|
349 |
+
return memo() ?? memo(
|
350 |
+
/**
|
351 |
+
* @since 2.3.0
|
352 |
+
* @since 2.7.0 Added output within filter.
|
353 |
+
* @param string $type The OG type.
|
354 |
+
* @param int $id The page/term/object ID.
|
355 |
+
*/
|
356 |
+
(string) \apply_filters_ref_array(
|
357 |
+
'the_seo_framework_ogtype_output',
|
358 |
+
[
|
359 |
+
$this->generate_og_type(),
|
360 |
+
$this->get_the_real_ID(),
|
361 |
+
]
|
362 |
+
)
|
|
|
|
|
|
|
|
|
363 |
);
|
364 |
}
|
365 |
|
373 |
*/
|
374 |
public function get_modified_time() {
|
375 |
|
376 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
377 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
378 |
|
379 |
$id = $this->get_the_real_ID();
|
380 |
|
381 |
$post = \get_post( $id );
|
382 |
$post_modified_gmt = $post->post_modified_gmt;
|
383 |
|
384 |
+
return memo(
|
385 |
+
'0000-00-00 00:00:00' === $post_modified_gmt
|
386 |
+
? ''
|
387 |
+
/**
|
388 |
+
* @since 2.3.0
|
389 |
+
* @since 2.7.0 Added output within filter.
|
390 |
+
* @param string $time The article modified time.
|
391 |
+
* @param int $id The current page or term ID.
|
392 |
+
*/
|
393 |
+
: (string) \apply_filters_ref_array(
|
394 |
+
'the_seo_framework_modifiedtime_output',
|
395 |
+
[
|
396 |
+
$this->gmt2date( $this->get_timestamp_format(), $post_modified_gmt ),
|
397 |
+
$id,
|
398 |
+
]
|
399 |
+
)
|
400 |
);
|
401 |
}
|
402 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
403 |
/**
|
404 |
* Generates the Twitter Card type.
|
405 |
*
|
420 |
$option = $this->get_option( 'twitter_card' );
|
421 |
|
422 |
// Option is equal to found cards. Output option.
|
423 |
+
$type = \in_array( $option, $available_cards, true ) ? $option : 'summary';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
424 |
|
425 |
/**
|
426 |
* @since 2.3.0
|
439 |
|
440 |
/**
|
441 |
* Determines which Twitter cards can be used.
|
|
|
442 |
*
|
443 |
* @since 2.9.0
|
444 |
* @since 4.0.0 1. Now only asserts the social titles as required.
|
445 |
* 2. Now always returns an array, instead of a boolean (false) on failure.
|
446 |
+
* @since 4.2.0 1. No longer memoizes the return value.
|
447 |
+
* 2. No longer tests for the Twitter title.
|
448 |
*
|
449 |
* @return array False when it shouldn't be used. Array of available cards otherwise.
|
450 |
*/
|
451 |
public function get_available_twitter_cards() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
452 |
/**
|
453 |
* @since 2.9.0
|
454 |
+
* @param array $cards The available Twitter cards. Use empty array to invalidate Twitter card.
|
455 |
*/
|
456 |
+
return (array) \apply_filters(
|
457 |
+
'the_seo_framework_available_twitter_cards',
|
458 |
+
[ 'summary_large_image', 'summary' ]
|
459 |
+
);
|
460 |
}
|
461 |
|
462 |
/**
|
518 |
* Returns the redirect URL, if any.
|
519 |
*
|
520 |
* @since 4.1.4
|
521 |
+
* @since 4.2.0 1. Now supports the `$args['pta']` index.
|
522 |
+
* 2. Now redirects post type archives.
|
523 |
*
|
524 |
* @param null|array $args The redirect URL arguments, leave null to autodetermine query : {
|
525 |
+
* int $id The Post, Page or Term ID to generate the URL for.
|
526 |
+
* string $taxonomy The taxonomy.
|
527 |
* }
|
528 |
* @return string The canonical URL if found, empty string otherwise.
|
529 |
*/
|
536 |
$url = $this->get_post_meta_item( 'redirect' ) ?: '';
|
537 |
} elseif ( $this->is_term_meta_capable() ) {
|
538 |
$url = $this->get_term_meta_item( 'redirect' ) ?: '';
|
539 |
+
} elseif ( \is_post_type_archive() ) {
|
540 |
+
$url = $this->get_post_type_archive_meta_item( 'redirect' ) ?: '';
|
541 |
}
|
542 |
} else {
|
543 |
$this->fix_generation_args( $args );
|
544 |
+
if ( $args['taxonomy'] ) {
|
|
|
|
|
545 |
$url = $this->get_term_meta_item( 'redirect', $args['id'] ) ?: '';
|
546 |
+
} elseif ( $args['pta'] ) {
|
547 |
+
$url = $this->get_post_type_archive_meta_item( 'redirect', $args['pta'] ) ?: '';
|
548 |
+
} else {
|
549 |
+
$url = $this->get_post_meta_item( 'redirect', $args['id'] ) ?: '';
|
550 |
}
|
551 |
}
|
552 |
|
@@ -4,16 +4,6 @@
|
|
4 |
*
|
5 |
* # Namespace: The_SEO_Framework
|
6 |
*
|
7 |
-
* ## Separated:
|
8 |
-
* - Deprecated
|
9 |
-
* |-> Final
|
10 |
-
* - Debug
|
11 |
-
* |-> Final
|
12 |
-
*
|
13 |
-
* ## Failsafe:
|
14 |
-
* - Silencer
|
15 |
-
* |-> Final
|
16 |
-
*
|
17 |
* ## Façade (bottom is called first):
|
18 |
* - | Core
|
19 |
* | Query
|
@@ -37,5 +27,5 @@
|
|
37 |
* | Cache
|
38 |
* | Load
|
39 |
* |-> Final
|
40 |
-
* |-> Instanced in function `the_seo_framework()`
|
41 |
*/
|
4 |
*
|
5 |
* # Namespace: The_SEO_Framework
|
6 |
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
* ## Façade (bottom is called first):
|
8 |
* - | Core
|
9 |
* | Query
|
27 |
* | Cache
|
28 |
* | Load
|
29 |
* |-> Final
|
30 |
+
* |-> Instanced in function `tsf()`|`the_seo_framework()`|`The_SEO_Framework\_init_tsf()`
|
31 |
*/
|
@@ -106,19 +106,20 @@ class Init extends Query {
|
|
106 |
* @since 2.8.0
|
107 |
* @since 4.1.2 1. Added hook for sitemap prerender.
|
108 |
* 2. Added hook for ping retry.
|
109 |
-
*
|
|
|
110 |
*/
|
111 |
-
|
112 |
// Init post update/delete caching actions which may occur during cronjobs.
|
113 |
$this->init_post_cache_actions();
|
114 |
|
115 |
// Ping searchengines.
|
116 |
if ( $this->get_option( 'ping_use_cron' ) ) {
|
117 |
if ( $this->get_option( 'sitemaps_output' ) && $this->get_option( 'ping_use_cron_prerender' ) )
|
118 |
-
\add_action( 'tsf_sitemap_cron_hook_before', [ new Builders\
|
119 |
|
120 |
-
\add_action( 'tsf_sitemap_cron_hook', Bridges\Ping::class
|
121 |
-
\add_action( 'tsf_sitemap_cron_hook_retry', Bridges\Ping::class
|
122 |
}
|
123 |
}
|
124 |
|
@@ -130,16 +131,16 @@ class Init extends Query {
|
|
130 |
protected function init_ajax_actions() {
|
131 |
|
132 |
// Admin AJAX for notice dismissal.
|
133 |
-
\add_action( 'wp_ajax_tsf_dismiss_notice',
|
134 |
|
135 |
// Admin AJAX for TSF Cropper
|
136 |
-
\add_action( 'wp_ajax_tsf_crop_image',
|
137 |
|
138 |
// Admin AJAX for counter options.
|
139 |
-
\add_action( 'wp_ajax_tsf_update_counter',
|
140 |
|
141 |
// Admin AJAX for Gutenberg SEO Bar update.
|
142 |
-
\add_action( 'wp_ajax_tsf_update_post_data',
|
143 |
}
|
144 |
|
145 |
/**
|
@@ -155,14 +156,14 @@ class Init extends Query {
|
|
155 |
*/
|
156 |
\do_action( 'the_seo_framework_admin_init' );
|
157 |
|
158 |
-
|
159 |
$this->init_admin_caching_actions();
|
160 |
|
161 |
if ( ! $this->is_headless['meta'] ) {
|
162 |
-
|
163 |
$this->init_term_meta();
|
164 |
|
165 |
-
|
166 |
$this->init_post_meta();
|
167 |
|
168 |
// Enqueue Post meta boxes.
|
@@ -176,15 +177,15 @@ class Init extends Query {
|
|
176 |
|
177 |
// Initialize the SEO Bar for tables.
|
178 |
\add_action( 'admin_init', [ $this, '_init_seo_bar_tables' ] );
|
|
|
|
|
|
|
179 |
}
|
180 |
|
181 |
if ( ! $this->is_headless['settings'] ) {
|
182 |
// Set up site settings and allow saving resetting them.
|
183 |
\add_action( 'admin_init', [ $this, 'register_settings' ], 5 );
|
184 |
|
185 |
-
// Initialize List Edit for tables.
|
186 |
-
\add_action( 'admin_init', [ $this, '_init_list_edit' ] );
|
187 |
-
|
188 |
// Loads setting notices.
|
189 |
\add_action( 'the_seo_framework_setting_notices', [ $this, '_do_settings_page_notices' ] );
|
190 |
|
@@ -193,7 +194,7 @@ class Init extends Query {
|
|
193 |
}
|
194 |
|
195 |
if ( ! $this->is_headless['user'] ) {
|
196 |
-
|
197 |
$this->init_user_meta();
|
198 |
|
199 |
// Enqueue user meta output.
|
@@ -212,8 +213,18 @@ class Init extends Query {
|
|
212 |
}
|
213 |
|
214 |
// Add plugin links to the plugin activation page.
|
215 |
-
\add_filter(
|
216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
|
218 |
/**
|
219 |
* @since 2.9.4
|
@@ -253,7 +264,6 @@ class Init extends Query {
|
|
253 |
|
254 |
// Prepares sitemap or stylesheet output.
|
255 |
if ( $this->can_run_sitemap() ) {
|
256 |
-
// We can use action `set_404` when we support WP 5.5+...?
|
257 |
\add_action( 'template_redirect', [ $this, '_init_sitemap' ], 1 );
|
258 |
\add_filter( 'wp_sitemaps_enabled', '__return_false' );
|
259 |
} else {
|
@@ -267,6 +277,9 @@ class Init extends Query {
|
|
267 |
// Prepares requisite robots headers to avoid low-quality content penalties.
|
268 |
$this->prepare_robots_headers();
|
269 |
|
|
|
|
|
|
|
270 |
// Output meta tags.
|
271 |
\add_action( 'wp_head', [ $this, 'html_output' ], 1 );
|
272 |
|
@@ -311,17 +324,20 @@ class Init extends Query {
|
|
311 |
|
312 |
// New WordPress 4.4.0 filter. Hurray! It's also much faster :)
|
313 |
\add_filter( 'pre_get_document_title', [ $this, 'get_document_title' ], 10 );
|
314 |
-
// Override WooThemes Title TODO move this to wc compat file.
|
315 |
-
\add_filter( 'woo_title', [ $this, 'get_document_title' ], 99 );
|
316 |
|
317 |
/**
|
318 |
* @since 2.4.1
|
319 |
* @param bool $overwrite_titles Whether to enable legacy title overwriting.
|
|
|
|
|
|
|
320 |
*/
|
321 |
if ( \apply_filters( 'the_seo_framework_manipulate_title', true ) ) {
|
322 |
\remove_all_filters( 'wp_title', false );
|
323 |
// Override WordPress Title
|
324 |
\add_filter( 'wp_title', [ $this, 'get_wp_title' ], 9 );
|
|
|
|
|
325 |
}
|
326 |
}
|
327 |
|
@@ -331,6 +347,8 @@ class Init extends Query {
|
|
331 |
*/
|
332 |
if ( \apply_filters( 'the_seo_framework_kill_core_robots', true ) ) {
|
333 |
\remove_filter( 'wp_robots', 'wp_robots_max_image_preview_large' );
|
|
|
|
|
334 |
}
|
335 |
|
336 |
if ( $this->get_option( 'og_tags' ) ) { // independent from filter at use_og_tags--let that be deciding later.
|
@@ -364,35 +382,89 @@ class Init extends Query {
|
|
364 |
}
|
365 |
|
366 |
/**
|
367 |
-
*
|
368 |
-
*
|
369 |
-
* @since 3.1.0
|
370 |
*
|
371 |
-
* @
|
372 |
-
* @
|
|
|
373 |
*/
|
374 |
-
public function
|
375 |
-
|
376 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
377 |
|
378 |
/**
|
379 |
* @since 2.2.6
|
|
|
380 |
* @param array $functions {
|
381 |
* 'callback' => string|array The function to call.
|
382 |
* 'args' => scalar|array Arguments. When array, each key is a new argument.
|
383 |
* }
|
384 |
*/
|
385 |
-
$functions = (array) \
|
|
|
|
|
|
|
|
|
|
|
386 |
|
387 |
foreach ( $functions as $function ) {
|
388 |
-
if ( ! empty( $function['callback'] ) )
|
389 |
-
|
|
|
|
|
|
|
390 |
|
391 |
-
|
392 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
393 |
}
|
394 |
|
395 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
}
|
397 |
|
398 |
/**
|
@@ -406,43 +478,40 @@ class Init extends Query {
|
|
406 |
* @since 4.0.0 Now no longer outputs anything on Customizer.
|
407 |
* @since 4.0.4 1. Now sets timezone to UTC to fix WP 5.3 bug <https://core.trac.wordpress.org/ticket/48623>
|
408 |
* 2. Now always sets timezone regardless of settings, because, again, bug.
|
|
|
409 |
* @access private
|
410 |
*/
|
411 |
public function html_output() {
|
412 |
|
413 |
if ( $this->is_preview() || $this->is_customize_preview() || ! $this->query_supports_seo() ) return;
|
414 |
|
415 |
-
/**
|
416 |
-
* We added this filter a second time, for this method is conditional (see two lines above).
|
417 |
-
* When the query doesn't support TSF's SEO, we want default behavior to ensue.
|
418 |
-
*
|
419 |
-
* @since 4.1.4
|
420 |
-
* @param bool $kill_core_robots Whether you feel sympathy for rocks tricked to think.
|
421 |
-
*/
|
422 |
-
if ( \apply_filters( 'the_seo_framework_kill_core_robots', true ) ) {
|
423 |
-
\remove_filter( 'wp_robots', 'wp_robots_noindex_search' );
|
424 |
-
}
|
425 |
-
|
426 |
/**
|
427 |
* @since 2.6.0
|
428 |
*/
|
429 |
\do_action( 'the_seo_framework_do_before_output' );
|
430 |
|
431 |
/**
|
432 |
-
*
|
433 |
-
*
|
434 |
-
*
|
435 |
-
|
|
|
|
|
|
|
|
|
436 |
*/
|
437 |
$init_start = microtime( true );
|
438 |
|
439 |
// phpcs:disable, WordPress.Security.EscapeOutput -- Output is escaped.
|
440 |
-
// phpcs:ignore Squiz.WhiteSpace.LanguageConstructSpacing -- We're fancy here.
|
441 |
echo PHP_EOL, $this->get_plugin_indicator( 'before' );
|
442 |
|
443 |
$this->do_meta_output();
|
444 |
|
445 |
-
echo $this->get_plugin_indicator(
|
|
|
|
|
|
|
|
|
446 |
// phpcs:enable, WordPress.Security.EscapeOutput
|
447 |
|
448 |
/**
|
@@ -455,23 +524,17 @@ class Init extends Query {
|
|
455 |
* Outputs all meta tags for the current query.
|
456 |
*
|
457 |
* @since 4.1.4
|
|
|
|
|
458 |
*/
|
459 |
public function do_meta_output() {
|
460 |
|
461 |
-
// phpcs:disable, WordPress.Security.EscapeOutput -- Everything we produce is escaped.
|
462 |
-
|
463 |
-
$get = [ 'robots' ];
|
464 |
-
|
465 |
-
/** @since 4.0.4 Added as WP 5.3 patch. */
|
466 |
-
$this->set_timezone( 'UTC' );
|
467 |
-
|
468 |
/**
|
469 |
-
* @since 2.
|
470 |
-
* @param string $before The content before the SEO output.
|
471 |
*/
|
472 |
-
|
473 |
|
474 |
-
|
475 |
|
476 |
// Limit processing and redundant tags on 404 and search.
|
477 |
if ( $this->is_search() ) :
|
@@ -546,34 +609,26 @@ class Init extends Query {
|
|
546 |
);
|
547 |
endif;
|
548 |
|
549 |
-
// TODO add filter? It won't last a few major updates though...
|
550 |
// But that's why I created this method like so... anyway... tough luck.
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
echo $this->get_legacy_header_filters_output( 'after' );
|
555 |
|
556 |
/**
|
557 |
-
* @since 2.
|
558 |
-
* @param string $after The content after the SEO output.
|
559 |
*/
|
560 |
-
|
561 |
-
|
562 |
-
/** @since 4.0.4 Added as WP 5.3 patch. */
|
563 |
-
$this->reset_timezone();
|
564 |
-
|
565 |
-
// phpcs:enable, WordPress.Security.EscapeOutput
|
566 |
}
|
567 |
|
568 |
/**
|
569 |
* Redirects singular page to an alternate URL.
|
570 |
*
|
571 |
* @since 2.9.0
|
572 |
-
* @since 3.1.0
|
573 |
-
*
|
574 |
-
* @since 4.0.0
|
575 |
-
*
|
576 |
-
*
|
577 |
* @access private
|
578 |
*
|
579 |
* @return void early on non-singular pages.
|
@@ -590,6 +645,7 @@ class Init extends Query {
|
|
590 |
* @param string $url The URL we're redirecting to.
|
591 |
*/
|
592 |
\do_action( 'the_seo_framework_before_redirect', $url );
|
|
|
593 |
$this->do_redirect( $url );
|
594 |
}
|
595 |
}
|
@@ -609,7 +665,7 @@ class Init extends Query {
|
|
609 |
return;
|
610 |
}
|
611 |
|
612 |
-
|
613 |
$url = \esc_url_raw( $url );
|
614 |
|
615 |
if ( empty( $url ) ) {
|
@@ -627,7 +683,7 @@ class Init extends Query {
|
|
627 |
$this->_doing_it_wrong( __METHOD__, 'You should use 3xx HTTP Status Codes. Recommended 301 and 302.', '2.8.0' );
|
628 |
|
629 |
if ( ! $this->allow_external_redirect() ) {
|
630 |
-
|
631 |
$path = $this->set_url_scheme( $url, 'relative' );
|
632 |
$url = \trailingslashit( $this->get_home_host() ) . ltrim( $path, ' /' );
|
633 |
|
@@ -660,11 +716,9 @@ class Init extends Query {
|
|
660 |
* @access private
|
661 |
*/
|
662 |
public function _init_core_sitemap() {
|
663 |
-
// It's not a bridge, don't treat it like one:
|
664 |
-
|
665 |
-
|
666 |
-
\add_filter( 'wp_sitemaps_add_provider', "{$builder_class}::_filter_add_provider", 9, 2 );
|
667 |
-
\add_filter( 'wp_sitemaps_max_urls', "{$builder_class}::_filter_max_urls", 9 );
|
668 |
}
|
669 |
|
670 |
/**
|
@@ -689,10 +743,10 @@ class Init extends Query {
|
|
689 |
*
|
690 |
* @since 2.2.9
|
691 |
* @since 2.9.3 Casts $public to string for check.
|
692 |
-
* @since 4.0.5
|
693 |
-
*
|
694 |
-
*
|
695 |
-
*
|
696 |
* @since 4.1.0 Now adds the WordPress Core sitemap URL.
|
697 |
* @since 4.1.2 Now only adds the WP Core sitemap URL when the provider tells us it's enabled.
|
698 |
* @since 4.1.4 Removed object caching support.
|
@@ -726,9 +780,8 @@ class Init extends Query {
|
|
726 |
* @since 2.5.0
|
727 |
* @param bool $disallow Whether to disallow robots queries.
|
728 |
*/
|
729 |
-
if ( \apply_filters( 'the_seo_framework_robots_disallow_queries', false ) )
|
730 |
$output .= "Disallow: /*?*\r\n";
|
731 |
-
}
|
732 |
|
733 |
/**
|
734 |
* @since 2.5.0
|
@@ -741,11 +794,11 @@ class Init extends Query {
|
|
741 |
if ( $this->get_option( 'sitemaps_robots' ) ) {
|
742 |
if ( $this->get_option( 'sitemaps_output' ) ) {
|
743 |
$sitemaps = Bridges\Sitemap::get_instance();
|
744 |
-
|
745 |
-
|
|
|
746 |
$output .= sprintf( "\r\nSitemap: %s", \esc_url( $sitemaps->get_expected_sitemap_endpoint_url( $id ) ) );
|
747 |
-
|
748 |
-
}
|
749 |
$output .= "\r\n";
|
750 |
} elseif ( ! $this->detect_sitemap_plugin() ) { // detect_sitemap_plugin() temp backward compat.
|
751 |
if ( $this->use_core_sitemaps() ) {
|
@@ -771,7 +824,7 @@ class Init extends Query {
|
|
771 |
'# This is an invalid robots.txt location.',
|
772 |
'# Please visit: ' . \esc_url( \trailingslashit( $this->set_preferred_url_scheme( $this->get_home_host() ) ) . 'robots.txt' )
|
773 |
);
|
774 |
-
$output = $error
|
775 |
}
|
776 |
|
777 |
/**
|
@@ -896,8 +949,9 @@ class Init extends Query {
|
|
896 |
$post__not_in = $wp_query->get( 'post__not_in' );
|
897 |
|
898 |
if ( ! empty( $post__not_in ) ) {
|
899 |
-
$excluded =
|
900 |
-
|
|
|
901 |
}
|
902 |
|
903 |
$wp_query->set( 'post__not_in', $excluded );
|
@@ -929,8 +983,9 @@ class Init extends Query {
|
|
929 |
$post__not_in = $wp_query->get( 'post__not_in' );
|
930 |
|
931 |
if ( ! empty( $post__not_in ) ) {
|
932 |
-
$excluded =
|
933 |
-
|
|
|
934 |
}
|
935 |
|
936 |
$wp_query->set( 'post__not_in', $excluded );
|
@@ -957,7 +1012,7 @@ class Init extends Query {
|
|
957 |
if ( $this->get_post_meta_item( 'exclude_local_search', $post->ID ) )
|
958 |
unset( $posts[ $n ] );
|
959 |
}
|
960 |
-
|
961 |
$posts = array_values( $posts );
|
962 |
}
|
963 |
|
@@ -984,7 +1039,7 @@ class Init extends Query {
|
|
984 |
if ( $this->get_post_meta_item( 'exclude_from_archive', $post->ID ) )
|
985 |
unset( $posts[ $n ] );
|
986 |
}
|
987 |
-
|
988 |
$posts = array_values( $posts );
|
989 |
}
|
990 |
|
@@ -1010,6 +1065,7 @@ class Init extends Query {
|
|
1010 |
* @since 4.1.4 1. Renamed from `is_archive_query_adjustment_blocked()`
|
1011 |
* 2. Added taxonomy-supported lookups.
|
1012 |
* 3. Added WP Rest checks for the Block Editor.
|
|
|
1013 |
*
|
1014 |
* @param \WP_Query $wp_query WP_Query object.
|
1015 |
* @return bool
|
@@ -1018,9 +1074,9 @@ class Init extends Query {
|
|
1018 |
|
1019 |
static $has_filter = null;
|
1020 |
|
1021 |
-
if ( null === $has_filter )
|
1022 |
$has_filter = \has_filter( 'the_seo_framework_do_adjust_archive_query' );
|
1023 |
-
|
1024 |
if ( $has_filter ) {
|
1025 |
/**
|
1026 |
* This filter affects both 'search-"archives"' and terms/taxonomies.
|
@@ -1051,15 +1107,17 @@ class Init extends Query {
|
|
1051 |
|
1052 |
// This primarily affects 'terms'.
|
1053 |
if ( ! empty( $wp_query->tax_query->queries ) ) :
|
1054 |
-
$
|
1055 |
|
1056 |
foreach ( $wp_query->tax_query->queries as $_query ) {
|
1057 |
-
if ( isset( $_query['taxonomy'] ) )
|
1058 |
-
$
|
|
|
|
|
|
|
1059 |
}
|
1060 |
|
1061 |
-
|
1062 |
-
if ( $unsupported && ! \in_array( false, $unsupported, true ) )
|
1063 |
return true;
|
1064 |
endif;
|
1065 |
|
@@ -1084,21 +1142,13 @@ class Init extends Query {
|
|
1084 |
public function _alter_oembed_response_data( $data = [], $post = null, $width = 0, $height = 0 ) {
|
1085 |
|
1086 |
// Don't use cache. See @WARNING in doc comment.
|
1087 |
-
if ( $this->get_option( 'oembed_use_og_title', false ) )
|
1088 |
-
$data['title'] = $this->get_open_graph_title(
|
1089 |
-
|
1090 |
-
'id' => $post->ID,
|
1091 |
-
'taxonomy' => '',
|
1092 |
-
]
|
1093 |
-
) ?: $data['title'];
|
1094 |
-
}
|
1095 |
// Don't use cache. See @WARNING in doc comment.
|
1096 |
if ( $this->get_option( 'oembed_use_social_image', false ) ) {
|
1097 |
$image_details = current( $this->get_image_details(
|
1098 |
-
[
|
1099 |
-
'id' => $post->ID,
|
1100 |
-
'taxonomy' => '',
|
1101 |
-
],
|
1102 |
true,
|
1103 |
'oembed',
|
1104 |
true
|
@@ -1111,10 +1161,10 @@ class Init extends Query {
|
|
1111 |
$data['thumbnail_height'] = $image_details['height'];
|
1112 |
}
|
1113 |
}
|
|
|
1114 |
// Don't use cache. See @WARNING in doc comment.
|
1115 |
-
if ( $this->get_option( 'oembed_remove_author', false ) )
|
1116 |
unset( $data['author_url'], $data['author_name'] );
|
1117 |
-
}
|
1118 |
|
1119 |
return $data;
|
1120 |
}
|
106 |
* @since 2.8.0
|
107 |
* @since 4.1.2 1. Added hook for sitemap prerender.
|
108 |
* 2. Added hook for ping retry.
|
109 |
+
* @since 4.2.0 Is now protexted
|
110 |
+
* @access protected
|
111 |
*/
|
112 |
+
protected function init_cron_actions() {
|
113 |
// Init post update/delete caching actions which may occur during cronjobs.
|
114 |
$this->init_post_cache_actions();
|
115 |
|
116 |
// Ping searchengines.
|
117 |
if ( $this->get_option( 'ping_use_cron' ) ) {
|
118 |
if ( $this->get_option( 'sitemaps_output' ) && $this->get_option( 'ping_use_cron_prerender' ) )
|
119 |
+
\add_action( 'tsf_sitemap_cron_hook_before', [ new Builders\Sitemap\Base, 'prerender_sitemap' ] );
|
120 |
|
121 |
+
\add_action( 'tsf_sitemap_cron_hook', [ Bridges\Ping::class, 'ping_search_engines' ] );
|
122 |
+
\add_action( 'tsf_sitemap_cron_hook_retry', [ Bridges\Ping::class, 'retry_ping_search_engines' ] );
|
123 |
}
|
124 |
}
|
125 |
|
131 |
protected function init_ajax_actions() {
|
132 |
|
133 |
// Admin AJAX for notice dismissal.
|
134 |
+
\add_action( 'wp_ajax_tsf_dismiss_notice', [ Bridges\AJAX::class, '_wp_ajax_dismiss_notice' ] );
|
135 |
|
136 |
// Admin AJAX for TSF Cropper
|
137 |
+
\add_action( 'wp_ajax_tsf_crop_image', [ Bridges\AJAX::class, '_wp_ajax_crop_image' ] );
|
138 |
|
139 |
// Admin AJAX for counter options.
|
140 |
+
\add_action( 'wp_ajax_tsf_update_counter', [ Bridges\AJAX::class, '_wp_ajax_update_counter_type' ] );
|
141 |
|
142 |
// Admin AJAX for Gutenberg SEO Bar update.
|
143 |
+
\add_action( 'wp_ajax_tsf_update_post_data', [ Bridges\AJAX::class, '_wp_ajax_get_post_data' ] );
|
144 |
}
|
145 |
|
146 |
/**
|
156 |
*/
|
157 |
\do_action( 'the_seo_framework_admin_init' );
|
158 |
|
159 |
+
// Initialize caching actions.
|
160 |
$this->init_admin_caching_actions();
|
161 |
|
162 |
if ( ! $this->is_headless['meta'] ) {
|
163 |
+
// Initialize term meta filters and actions.
|
164 |
$this->init_term_meta();
|
165 |
|
166 |
+
// Initialize term meta filters and actions.
|
167 |
$this->init_post_meta();
|
168 |
|
169 |
// Enqueue Post meta boxes.
|
177 |
|
178 |
// Initialize the SEO Bar for tables.
|
179 |
\add_action( 'admin_init', [ $this, '_init_seo_bar_tables' ] );
|
180 |
+
|
181 |
+
// Initialize List Edit for tables.
|
182 |
+
\add_action( 'admin_init', [ $this, '_init_list_edit' ] );
|
183 |
}
|
184 |
|
185 |
if ( ! $this->is_headless['settings'] ) {
|
186 |
// Set up site settings and allow saving resetting them.
|
187 |
\add_action( 'admin_init', [ $this, 'register_settings' ], 5 );
|
188 |
|
|
|
|
|
|
|
189 |
// Loads setting notices.
|
190 |
\add_action( 'the_seo_framework_setting_notices', [ $this, '_do_settings_page_notices' ] );
|
191 |
|
194 |
}
|
195 |
|
196 |
if ( ! $this->is_headless['user'] ) {
|
197 |
+
// Initialize user meta filters and actions.
|
198 |
$this->init_user_meta();
|
199 |
|
200 |
// Enqueue user meta output.
|
213 |
}
|
214 |
|
215 |
// Add plugin links to the plugin activation page.
|
216 |
+
\add_filter(
|
217 |
+
'plugin_action_links_' . THE_SEO_FRAMEWORK_PLUGIN_BASENAME,
|
218 |
+
[ '\The_SEO_Framework\Bridges\PluginTable', '_add_plugin_action_links' ],
|
219 |
+
10,
|
220 |
+
2
|
221 |
+
);
|
222 |
+
\add_filter(
|
223 |
+
'plugin_row_meta',
|
224 |
+
[ '\The_SEO_Framework\Bridges\PluginTable', '_add_plugin_row_meta' ],
|
225 |
+
10,
|
226 |
+
2
|
227 |
+
);
|
228 |
|
229 |
/**
|
230 |
* @since 2.9.4
|
264 |
|
265 |
// Prepares sitemap or stylesheet output.
|
266 |
if ( $this->can_run_sitemap() ) {
|
|
|
267 |
\add_action( 'template_redirect', [ $this, '_init_sitemap' ], 1 );
|
268 |
\add_filter( 'wp_sitemaps_enabled', '__return_false' );
|
269 |
} else {
|
277 |
// Prepares requisite robots headers to avoid low-quality content penalties.
|
278 |
$this->prepare_robots_headers();
|
279 |
|
280 |
+
\add_action( 'the_seo_framework_before_meta_output', [ $this, '_do_deprecated_output_hooks_before' ], 5 );
|
281 |
+
\add_action( 'the_seo_framework_after_meta_output', [ $this, '_do_deprecated_output_hooks_after' ], 15 );
|
282 |
+
|
283 |
// Output meta tags.
|
284 |
\add_action( 'wp_head', [ $this, 'html_output' ], 1 );
|
285 |
|
324 |
|
325 |
// New WordPress 4.4.0 filter. Hurray! It's also much faster :)
|
326 |
\add_filter( 'pre_get_document_title', [ $this, 'get_document_title' ], 10 );
|
|
|
|
|
327 |
|
328 |
/**
|
329 |
* @since 2.4.1
|
330 |
* @param bool $overwrite_titles Whether to enable legacy title overwriting.
|
331 |
+
*
|
332 |
+
* TODO remove this block? -- it's been 6 years...
|
333 |
+
* <https://make.wordpress.org/core/2015/10/20/document-title-in-4-4/>
|
334 |
*/
|
335 |
if ( \apply_filters( 'the_seo_framework_manipulate_title', true ) ) {
|
336 |
\remove_all_filters( 'wp_title', false );
|
337 |
// Override WordPress Title
|
338 |
\add_filter( 'wp_title', [ $this, 'get_wp_title' ], 9 );
|
339 |
+
// Override WooThemes Title TODO move this to wc compat file.
|
340 |
+
\add_filter( 'woo_title', [ $this, 'get_document_title' ], 99 );
|
341 |
}
|
342 |
}
|
343 |
|
347 |
*/
|
348 |
if ( \apply_filters( 'the_seo_framework_kill_core_robots', true ) ) {
|
349 |
\remove_filter( 'wp_robots', 'wp_robots_max_image_preview_large' );
|
350 |
+
// Reconsider readding this to "supported" queries only?
|
351 |
+
\remove_filter( 'wp_robots', 'wp_robots_noindex_search' );
|
352 |
}
|
353 |
|
354 |
if ( $this->get_option( 'og_tags' ) ) { // independent from filter at use_og_tags--let that be deciding later.
|
382 |
}
|
383 |
|
384 |
/**
|
385 |
+
* Outputs deprecated output hooks.
|
|
|
|
|
386 |
*
|
387 |
+
* @since 4.2.0
|
388 |
+
* @access private
|
389 |
+
* @TODO delete me. v5.0.0+
|
390 |
*/
|
391 |
+
public function _do_deprecated_output_hooks_before() {
|
392 |
+
// phpcs:disable, WordPress.Security.EscapeOutput -- Everything we produce is escaped.
|
393 |
+
/**
|
394 |
+
* @since 2.6.0
|
395 |
+
* @since 4.2.0 Deprecated.
|
396 |
+
* @param string $before The content before the SEO output.
|
397 |
+
*/
|
398 |
+
echo \apply_filters_deprecated(
|
399 |
+
'the_seo_framework_pre',
|
400 |
+
[ '' ],
|
401 |
+
'4.2.0 of The SEO Framework',
|
402 |
+
'Action the_seo_framework_before_meta_output'
|
403 |
+
);
|
404 |
|
405 |
/**
|
406 |
* @since 2.2.6
|
407 |
+
* @since 4.2.0 Deprecated
|
408 |
* @param array $functions {
|
409 |
* 'callback' => string|array The function to call.
|
410 |
* 'args' => scalar|array Arguments. When array, each key is a new argument.
|
411 |
* }
|
412 |
*/
|
413 |
+
$functions = (array) \apply_filters_deprecated(
|
414 |
+
'the_seo_framework_before_output',
|
415 |
+
[ [] ],
|
416 |
+
'4.2.0 of The SEO Framework',
|
417 |
+
'Action the_seo_framework_before_meta_output'
|
418 |
+
);
|
419 |
|
420 |
foreach ( $functions as $function ) {
|
421 |
+
if ( ! empty( $function['callback'] ) )
|
422 |
+
echo \call_user_func_array( $function['callback'], [ ( $function['args'] ?? null ) ] );
|
423 |
+
}
|
424 |
+
// phpcs:enable, WordPress.Security.EscapeOutput
|
425 |
+
}
|
426 |
|
427 |
+
/**
|
428 |
+
* Outputs deprecated output hooks.
|
429 |
+
*
|
430 |
+
* @since 4.2.0
|
431 |
+
* @access private
|
432 |
+
* @TODO delete me. v5.0.0+
|
433 |
+
*/
|
434 |
+
public function _do_deprecated_output_hooks_after() {
|
435 |
+
// phpcs:disable, WordPress.Security.EscapeOutput -- Everything we produce is escaped.
|
436 |
+
/**
|
437 |
+
* @since 2.2.6
|
438 |
+
* @since 4.2.0 Deprecated
|
439 |
+
* @param array $functions {
|
440 |
+
* 'callback' => string|array The function to call.
|
441 |
+
* 'args' => scalar|array Arguments. When array, each key is a new argument.
|
442 |
+
* }
|
443 |
+
*/
|
444 |
+
$functions = (array) \apply_filters_deprecated(
|
445 |
+
'the_seo_framework_after_output',
|
446 |
+
[ [] ],
|
447 |
+
'4.2.0 of The SEO Framework',
|
448 |
+
'Action the_seo_framework_after_meta_output'
|
449 |
+
);
|
450 |
+
|
451 |
+
foreach ( $functions as $function ) {
|
452 |
+
if ( ! empty( $function['callback'] ) )
|
453 |
+
echo \call_user_func_array( $function['callback'], [ ( $function['args'] ?? null ) ] );
|
454 |
}
|
455 |
|
456 |
+
/**
|
457 |
+
* @since 2.6.0
|
458 |
+
* @since 4.2.0 Deprecated.
|
459 |
+
* @param string $after The content after the SEO output.
|
460 |
+
*/
|
461 |
+
echo \apply_filters_deprecated(
|
462 |
+
'the_seo_framework_pro',
|
463 |
+
[ '' ],
|
464 |
+
'4.2.0 of The SEO Framework',
|
465 |
+
'Action the_seo_framework_after_meta_output'
|
466 |
+
);
|
467 |
+
// phpcs:enable, WordPress.Security.EscapeOutput
|
468 |
}
|
469 |
|
470 |
/**
|
478 |
* @since 4.0.0 Now no longer outputs anything on Customizer.
|
479 |
* @since 4.0.4 1. Now sets timezone to UTC to fix WP 5.3 bug <https://core.trac.wordpress.org/ticket/48623>
|
480 |
* 2. Now always sets timezone regardless of settings, because, again, bug.
|
481 |
+
* @since 4.2.0 No longer sets timezone.
|
482 |
* @access private
|
483 |
*/
|
484 |
public function html_output() {
|
485 |
|
486 |
if ( $this->is_preview() || $this->is_customize_preview() || ! $this->query_supports_seo() ) return;
|
487 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
488 |
/**
|
489 |
* @since 2.6.0
|
490 |
*/
|
491 |
\do_action( 'the_seo_framework_do_before_output' );
|
492 |
|
493 |
/**
|
494 |
+
* The bootstrap timer keeps adding when metadata is strapping.
|
495 |
+
* This causes both timers to increase simultaneously.
|
496 |
+
* We catch the bootstrap here, and let the meta-timer take over.
|
497 |
+
*/
|
498 |
+
$bootstrap_timer = _bootstrap_timer();
|
499 |
+
/**
|
500 |
+
* Start the meta timer here. This also catches file inclusions,
|
501 |
+
* which is also caught by the _bootstrap_timer().
|
502 |
*/
|
503 |
$init_start = microtime( true );
|
504 |
|
505 |
// phpcs:disable, WordPress.Security.EscapeOutput -- Output is escaped.
|
|
|
506 |
echo PHP_EOL, $this->get_plugin_indicator( 'before' );
|
507 |
|
508 |
$this->do_meta_output();
|
509 |
|
510 |
+
echo $this->get_plugin_indicator(
|
511 |
+
'after',
|
512 |
+
microtime( true ) - $init_start,
|
513 |
+
$bootstrap_timer
|
514 |
+
), PHP_EOL;
|
515 |
// phpcs:enable, WordPress.Security.EscapeOutput
|
516 |
|
517 |
/**
|
524 |
* Outputs all meta tags for the current query.
|
525 |
*
|
526 |
* @since 4.1.4
|
527 |
+
* @since 4.2.0 1. Now invokes two actions before and after output.
|
528 |
+
* 2. No longer rectifies timezones.
|
529 |
*/
|
530 |
public function do_meta_output() {
|
531 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
532 |
/**
|
533 |
+
* @since 4.2.0
|
|
|
534 |
*/
|
535 |
+
\do_action( 'the_seo_framework_before_meta_output' );
|
536 |
|
537 |
+
$get = [ 'robots' ];
|
538 |
|
539 |
// Limit processing and redundant tags on 404 and search.
|
540 |
if ( $this->is_search() ) :
|
609 |
);
|
610 |
endif;
|
611 |
|
612 |
+
// TODO add filter to $get? It won't last a few major updates though...
|
613 |
// But that's why I created this method like so... anyway... tough luck.
|
614 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput -- Everything we produce is escaped.
|
615 |
+
foreach ( $get as $method ) echo $this->{$method}();
|
|
|
|
|
616 |
|
617 |
/**
|
618 |
+
* @since 4.2.0
|
|
|
619 |
*/
|
620 |
+
\do_action( 'the_seo_framework_after_meta_output' );
|
|
|
|
|
|
|
|
|
|
|
621 |
}
|
622 |
|
623 |
/**
|
624 |
* Redirects singular page to an alternate URL.
|
625 |
*
|
626 |
* @since 2.9.0
|
627 |
+
* @since 3.1.0 1. Now no longer redirects on preview.
|
628 |
+
* 2. Now listens to post type settings.
|
629 |
+
* @since 4.0.0 1. No longer tries to redirect on "search".
|
630 |
+
* 2. Added term redirect support.
|
631 |
+
* 3. No longer redirects on Customizer.
|
632 |
* @access private
|
633 |
*
|
634 |
* @return void early on non-singular pages.
|
645 |
* @param string $url The URL we're redirecting to.
|
646 |
*/
|
647 |
\do_action( 'the_seo_framework_before_redirect', $url );
|
648 |
+
|
649 |
$this->do_redirect( $url );
|
650 |
}
|
651 |
}
|
665 |
return;
|
666 |
}
|
667 |
|
668 |
+
// All WP defined protocols are allowed.
|
669 |
$url = \esc_url_raw( $url );
|
670 |
|
671 |
if ( empty( $url ) ) {
|
683 |
$this->_doing_it_wrong( __METHOD__, 'You should use 3xx HTTP Status Codes. Recommended 301 and 302.', '2.8.0' );
|
684 |
|
685 |
if ( ! $this->allow_external_redirect() ) {
|
686 |
+
// Only HTTP/HTTPS and home URLs are allowed.
|
687 |
$path = $this->set_url_scheme( $url, 'relative' );
|
688 |
$url = \trailingslashit( $this->get_home_host() ) . ltrim( $path, ' /' );
|
689 |
|
716 |
* @access private
|
717 |
*/
|
718 |
public function _init_core_sitemap() {
|
719 |
+
// It's not a bridge, don't treat it like one: So, submit hooks here... But, clean me up?
|
720 |
+
\add_filter( 'wp_sitemaps_add_provider', [ Builders\CoreSitemaps\Main::class, '_filter_add_provider' ], 9, 2 );
|
721 |
+
\add_filter( 'wp_sitemaps_max_urls', [ Builders\CoreSitemaps\Main::class, '_filter_max_urls' ], 9 );
|
|
|
|
|
722 |
}
|
723 |
|
724 |
/**
|
743 |
*
|
744 |
* @since 2.2.9
|
745 |
* @since 2.9.3 Casts $public to string for check.
|
746 |
+
* @since 4.0.5 1. The output is now filterable.
|
747 |
+
* 2. Improved invalid location test.
|
748 |
+
* 3. No longer shortcircuits on non-public sites.
|
749 |
+
* 4. Now marked as private. Will be renamed to `_robots_txt()` in the future.
|
750 |
* @since 4.1.0 Now adds the WordPress Core sitemap URL.
|
751 |
* @since 4.1.2 Now only adds the WP Core sitemap URL when the provider tells us it's enabled.
|
752 |
* @since 4.1.4 Removed object caching support.
|
780 |
* @since 2.5.0
|
781 |
* @param bool $disallow Whether to disallow robots queries.
|
782 |
*/
|
783 |
+
if ( \apply_filters( 'the_seo_framework_robots_disallow_queries', false ) )
|
784 |
$output .= "Disallow: /*?*\r\n";
|
|
|
785 |
|
786 |
/**
|
787 |
* @since 2.5.0
|
794 |
if ( $this->get_option( 'sitemaps_robots' ) ) {
|
795 |
if ( $this->get_option( 'sitemaps_output' ) ) {
|
796 |
$sitemaps = Bridges\Sitemap::get_instance();
|
797 |
+
|
798 |
+
foreach ( $sitemaps->get_sitemap_endpoint_list() as $id => $data )
|
799 |
+
if ( ! empty( $data['robots'] ) )
|
800 |
$output .= sprintf( "\r\nSitemap: %s", \esc_url( $sitemaps->get_expected_sitemap_endpoint_url( $id ) ) );
|
801 |
+
|
|
|
802 |
$output .= "\r\n";
|
803 |
} elseif ( ! $this->detect_sitemap_plugin() ) { // detect_sitemap_plugin() temp backward compat.
|
804 |
if ( $this->use_core_sitemaps() ) {
|
824 |
'# This is an invalid robots.txt location.',
|
825 |
'# Please visit: ' . \esc_url( \trailingslashit( $this->set_preferred_url_scheme( $this->get_home_host() ) ) . 'robots.txt' )
|
826 |
);
|
827 |
+
$output = "$error$output";
|
828 |
}
|
829 |
|
830 |
/**
|
949 |
$post__not_in = $wp_query->get( 'post__not_in' );
|
950 |
|
951 |
if ( ! empty( $post__not_in ) ) {
|
952 |
+
$excluded = array_unique(
|
953 |
+
array_merge( (array) $post__not_in, $excluded )
|
954 |
+
);
|
955 |
}
|
956 |
|
957 |
$wp_query->set( 'post__not_in', $excluded );
|
983 |
$post__not_in = $wp_query->get( 'post__not_in' );
|
984 |
|
985 |
if ( ! empty( $post__not_in ) ) {
|
986 |
+
$excluded = array_unique(
|
987 |
+
array_merge( (array) $post__not_in, $excluded )
|
988 |
+
);
|
989 |
}
|
990 |
|
991 |
$wp_query->set( 'post__not_in', $excluded );
|
1012 |
if ( $this->get_post_meta_item( 'exclude_local_search', $post->ID ) )
|
1013 |
unset( $posts[ $n ] );
|
1014 |
}
|
1015 |
+
// Reset numeric index.
|
1016 |
$posts = array_values( $posts );
|
1017 |
}
|
1018 |
|
1039 |
if ( $this->get_post_meta_item( 'exclude_from_archive', $post->ID ) )
|
1040 |
unset( $posts[ $n ] );
|
1041 |
}
|
1042 |
+
// Reset numeric index.
|
1043 |
$posts = array_values( $posts );
|
1044 |
}
|
1045 |
|
1065 |
* @since 4.1.4 1. Renamed from `is_archive_query_adjustment_blocked()`
|
1066 |
* 2. Added taxonomy-supported lookups.
|
1067 |
* 3. Added WP Rest checks for the Block Editor.
|
1068 |
+
* @since 4.2.0 Improved supported taxonomy loop.
|
1069 |
*
|
1070 |
* @param \WP_Query $wp_query WP_Query object.
|
1071 |
* @return bool
|
1074 |
|
1075 |
static $has_filter = null;
|
1076 |
|
1077 |
+
if ( null === $has_filter )
|
1078 |
$has_filter = \has_filter( 'the_seo_framework_do_adjust_archive_query' );
|
1079 |
+
|
1080 |
if ( $has_filter ) {
|
1081 |
/**
|
1082 |
* This filter affects both 'search-"archives"' and terms/taxonomies.
|
1107 |
|
1108 |
// This primarily affects 'terms'.
|
1109 |
if ( ! empty( $wp_query->tax_query->queries ) ) :
|
1110 |
+
$supported = true;
|
1111 |
|
1112 |
foreach ( $wp_query->tax_query->queries as $_query ) {
|
1113 |
+
if ( isset( $_query['taxonomy'] ) ) {
|
1114 |
+
$supported = $this->is_taxonomy_supported( $_query['taxonomy'] );
|
1115 |
+
// If just one tax is supported for this query, greenlight it: all must be blocking.
|
1116 |
+
if ( $supported ) break;
|
1117 |
+
}
|
1118 |
}
|
1119 |
|
1120 |
+
if ( ! $supported )
|
|
|
1121 |
return true;
|
1122 |
endif;
|
1123 |
|
1142 |
public function _alter_oembed_response_data( $data = [], $post = null, $width = 0, $height = 0 ) {
|
1143 |
|
1144 |
// Don't use cache. See @WARNING in doc comment.
|
1145 |
+
if ( $this->get_option( 'oembed_use_og_title', false ) )
|
1146 |
+
$data['title'] = $this->get_open_graph_title( [ 'id' => $post->ID ] ) ?: $data['title'];
|
1147 |
+
|
|
|
|
|
|
|
|
|
|
|
1148 |
// Don't use cache. See @WARNING in doc comment.
|
1149 |
if ( $this->get_option( 'oembed_use_social_image', false ) ) {
|
1150 |
$image_details = current( $this->get_image_details(
|
1151 |
+
[ 'id' => $post->ID ],
|
|
|
|
|
|
|
1152 |
true,
|
1153 |
'oembed',
|
1154 |
true
|
1161 |
$data['thumbnail_height'] = $image_details['height'];
|
1162 |
}
|
1163 |
}
|
1164 |
+
|
1165 |
// Don't use cache. See @WARNING in doc comment.
|
1166 |
+
if ( $this->get_option( 'oembed_remove_author', false ) )
|
1167 |
unset( $data['author_url'], $data['author_name'] );
|
|
|
1168 |
|
1169 |
return $data;
|
1170 |
}
|
@@ -1,14 +1,10 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* @package The_SEO_Framework\Classes\Debug
|
4 |
* @subpackage The_SEO_Framework\Debug
|
5 |
*/
|
6 |
|
7 |
-
namespace The_SEO_Framework;
|
8 |
-
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
10 |
-
|
11 |
-
// phpcs:disable, WordPress.PHP.DevelopmentFunctions -- This whole class is meant for development.
|
12 |
|
13 |
/**
|
14 |
* The SEO Framework plugin
|
@@ -27,13 +23,20 @@ namespace The_SEO_Framework;
|
|
27 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
28 |
*/
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
/**
|
31 |
-
* Singleton class The_SEO_Framework\Debug
|
32 |
*
|
33 |
* Holds plugin debug functions.
|
34 |
*
|
35 |
* @since 2.8.0
|
36 |
* @since 4.0.0 No longer implements an interface. It's implied.
|
|
|
37 |
*/
|
38 |
final class Debug {
|
39 |
|
@@ -64,13 +67,11 @@ final class Debug {
|
|
64 |
*/
|
65 |
public static function _set_instance( $debug = null ) {
|
66 |
|
67 |
-
if ( \is_null( static::$instance ) )
|
68 |
static::$instance = new static();
|
69 |
-
}
|
70 |
|
71 |
-
if ( isset( $debug ) )
|
72 |
static::$instance->the_seo_framework_debug = (bool) $debug;
|
73 |
-
}
|
74 |
}
|
75 |
|
76 |
/**
|
@@ -82,9 +83,8 @@ final class Debug {
|
|
82 |
*/
|
83 |
public static function get_instance() {
|
84 |
|
85 |
-
if ( \is_null( static::$instance ) )
|
86 |
static::_set_instance();
|
87 |
-
}
|
88 |
|
89 |
return static::$instance;
|
90 |
}
|
@@ -248,7 +248,7 @@ final class Debug {
|
|
248 |
/* translators: 1: Method or Property name, 2: The SEO Framework class. 3: Message */
|
249 |
\esc_html__( '%1$s is not accessible in %2$s. %3$s', 'autodescription' ),
|
250 |
'<code>' . \esc_html( $p_or_m ) . '</code>',
|
251 |
-
'<code>
|
252 |
\esc_html( $message )
|
253 |
);
|
254 |
|
@@ -287,10 +287,10 @@ final class Debug {
|
|
287 |
* 1 = Error handler (This class).
|
288 |
* 2 = Error forwarder (TSF class).
|
289 |
*/
|
290 |
-
if ( isset( $backtrace[4]['args'][0][0] ) && is_a( $backtrace[4]['args'][0][0], 'The_SEO_Framework\Deprecated', false ) ) {
|
291 |
/**
|
292 |
* 3 = Deprecated call.
|
293 |
-
* 4 = TSF deprecation class
|
294 |
* 5 = User mistake.
|
295 |
*/
|
296 |
$error = $backtrace[5];
|
@@ -334,9 +334,6 @@ final class Debug {
|
|
334 |
*/
|
335 |
protected function combobulate_error_message( $error, $message, $code ) {
|
336 |
|
337 |
-
$file = isset( $error['file'] ) ? $error['file'] : '';
|
338 |
-
$line = isset( $error['line'] ) ? $error['line'] : '';
|
339 |
-
|
340 |
switch ( $code ) :
|
341 |
case E_USER_ERROR:
|
342 |
$type = 'Error';
|
@@ -356,8 +353,8 @@ final class Debug {
|
|
356 |
break;
|
357 |
endswitch;
|
358 |
|
359 |
-
$file = \esc_html( $file );
|
360 |
-
$line = \esc_html( $line );
|
361 |
|
362 |
$_message = "'<span><strong>$type:</strong> $message";
|
363 |
$_message .= $file ? " In $file" : '';
|
@@ -375,7 +372,7 @@ final class Debug {
|
|
375 |
* @access private
|
376 |
*/
|
377 |
public function _debug_output() {
|
378 |
-
\
|
379 |
}
|
380 |
|
381 |
/**
|
@@ -389,7 +386,7 @@ final class Debug {
|
|
389 |
* @return string
|
390 |
*/
|
391 |
protected function debug_key_wrapper( $key ) {
|
392 |
-
return '<font color="chucknorris">' . \
|
393 |
}
|
394 |
|
395 |
/**
|
@@ -407,30 +404,7 @@ final class Debug {
|
|
407 |
if ( ! is_scalar( $value ) )
|
408 |
return '<em>Debug message: not scalar</em>';
|
409 |
|
410 |
-
return '<span class="wp-ui-notification">' . \
|
411 |
-
}
|
412 |
-
|
413 |
-
/**
|
414 |
-
* Times code until it's called again.
|
415 |
-
*
|
416 |
-
* @since 2.6.0
|
417 |
-
* @since 3.1.0 Now is protected.
|
418 |
-
*
|
419 |
-
* @param bool $reset Whether to reset the timer.
|
420 |
-
* @return float The time it took for code execution.
|
421 |
-
*/
|
422 |
-
protected function timer( $reset = false ) {
|
423 |
-
|
424 |
-
static $previous = null;
|
425 |
-
|
426 |
-
if ( isset( $previous ) && false === $reset ) {
|
427 |
-
$output = microtime( true ) - $previous;
|
428 |
-
$previous = null;
|
429 |
-
} else {
|
430 |
-
$output = $previous = microtime( true );
|
431 |
-
}
|
432 |
-
|
433 |
-
return $output;
|
434 |
}
|
435 |
|
436 |
/**
|
@@ -455,7 +429,7 @@ final class Debug {
|
|
455 |
*/
|
456 |
protected function get_debug_header_output() {
|
457 |
|
458 |
-
$tsf = \
|
459 |
|
460 |
if ( \is_admin() && ! $tsf->is_term_edit() && ! $tsf->is_post_edit() && ! $tsf->is_seo_settings_page( true ) )
|
461 |
return;
|
@@ -464,11 +438,14 @@ final class Debug {
|
|
464 |
\add_filter( 'the_seo_framework_current_object_id', [ $tsf, 'get_the_front_page_ID' ] );
|
465 |
|
466 |
// Start timer.
|
467 |
-
$
|
468 |
|
469 |
-
|
|
|
|
|
|
|
470 |
|
471 |
-
$timer = '<div style="display:inline-block;width:100%;padding:20px;border-bottom:1px solid #ccc;">Generated in: ' . number_format(
|
472 |
|
473 |
$title = \is_admin() ? 'Expected SEO Output' : 'Determined SEO Output';
|
474 |
$title = '<div style="display:inline-block;width:100%;padding:20px;margin:0 auto;border-bottom:1px solid #ccc;"><h2 style="color:#ddd;font-size:22px;padding:0;margin:0">' . $title . '</h2></div>';
|
@@ -525,13 +502,7 @@ final class Debug {
|
|
525 |
* @return string Wrapped Query State debug output.
|
526 |
*/
|
527 |
protected function get_debug_query_output_from_cache() {
|
528 |
-
|
529 |
-
static $cache = null;
|
530 |
-
|
531 |
-
if ( isset( $cache ) )
|
532 |
-
return $cache;
|
533 |
-
|
534 |
-
return $cache = $this->get_debug_query_output( 'yup' );
|
535 |
}
|
536 |
|
537 |
/**
|
@@ -547,13 +518,12 @@ final class Debug {
|
|
547 |
protected function get_debug_query_output( $cache_version = 'nope' ) {
|
548 |
|
549 |
// Start timer.
|
550 |
-
$
|
551 |
|
552 |
-
$tsf = \
|
553 |
|
554 |
// phpcs:disable, WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase -- Not this file's issue.
|
555 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- get_defined_vars() is used later.
|
556 |
-
// Only get true/false values.
|
557 |
$page_id = $tsf->get_the_real_ID();
|
558 |
$is_query_exploited = $tsf->is_query_exploited();
|
559 |
$query_supports_seo = $tsf->query_supports_seo() ? 'yes' : 'no';
|
@@ -565,7 +535,6 @@ final class Debug {
|
|
565 |
$is_post_edit = $tsf->is_post_edit();
|
566 |
$is_wp_lists_edit = $tsf->is_wp_lists_edit();
|
567 |
$is_author = $tsf->is_author();
|
568 |
-
$is_blog_page = $tsf->is_blog_page();
|
569 |
$is_category = $tsf->is_category();
|
570 |
$is_date = $tsf->is_date();
|
571 |
$is_year = $tsf->is_year();
|
@@ -573,8 +542,8 @@ final class Debug {
|
|
573 |
$is_day = $tsf->is_day();
|
574 |
$is_feed = $tsf->is_feed();
|
575 |
$is_real_front_page = $tsf->is_real_front_page();
|
576 |
-
$is_front_page_by_id = $tsf->is_front_page_by_id( $page_id );
|
577 |
$is_home = $tsf->is_home();
|
|
|
578 |
$is_page = $tsf->is_page();
|
579 |
$page = $tsf->page();
|
580 |
$paged = $tsf->paged();
|
@@ -599,25 +568,27 @@ final class Debug {
|
|
599 |
$get_post_type_real_ID = $tsf->get_post_type_real_ID();
|
600 |
$admin_post_type = $tsf->get_admin_post_type();
|
601 |
$current_taxonomy = $tsf->get_current_taxonomy();
|
|
|
602 |
$is_taxonomy_disabled = $tsf->is_taxonomy_disabled();
|
603 |
$is_post_type_archive = \is_post_type_archive();
|
604 |
$is_protected = $tsf->is_protected( $page_id );
|
605 |
// phpcs:enable, WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
|
606 |
// phpcs:enable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
607 |
|
608 |
-
|
609 |
-
unset( $tsf );
|
610 |
|
611 |
// Get all above vars, split them in two (true and false) and sort them by key names.
|
612 |
-
$vars
|
|
|
|
|
|
|
|
|
613 |
$current = array_filter( $vars );
|
614 |
$not_current = array_diff_key( $vars, $current );
|
615 |
|
616 |
ksort( $current );
|
617 |
ksort( $not_current );
|
618 |
|
619 |
-
$timer = $this->timer();
|
620 |
-
|
621 |
$output = '';
|
622 |
foreach ( $current as $name => $value ) {
|
623 |
$type = '(' . \gettype( $value ) . ')';
|
@@ -625,10 +596,10 @@ final class Debug {
|
|
625 |
if ( \is_bool( $value ) ) {
|
626 |
$value = $value ? 'true' : 'false';
|
627 |
} else {
|
628 |
-
$value = \
|
629 |
}
|
630 |
|
631 |
-
$value = '<font color="harrisonford">' . $type
|
632 |
$out = \esc_html( $name ) . ' => ' . $value;
|
633 |
$output .= '<span style="background:#dadada">' . $out . '</span>' . PHP_EOL;
|
634 |
}
|
@@ -639,10 +610,10 @@ final class Debug {
|
|
639 |
if ( \is_bool( $value ) ) {
|
640 |
$value = $value ? 'true' : 'false';
|
641 |
} else {
|
642 |
-
$value = \
|
643 |
}
|
644 |
|
645 |
-
$value = '<font color="harrisonford">' . $type
|
646 |
$out = \esc_html( $name ) . ' => ' . $value;
|
647 |
|
648 |
$output .= $out . PHP_EOL;
|
@@ -663,7 +634,7 @@ final class Debug {
|
|
663 |
),
|
664 |
sprintf(
|
665 |
'<div style="display:inline-block;width:100%%;padding:20px;border-bottom:1px solid #666;">Generated in: %s seconds</div>',
|
666 |
-
number_format( $timer, 5 )
|
667 |
),
|
668 |
sprintf(
|
669 |
'<div style="display:inline-block;width:100%%;padding:20px;font-family:Consolas,Monaco,monospace;font-size:14px;">%s</div>',
|
1 |
<?php
|
2 |
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Internal\Debug
|
4 |
* @subpackage The_SEO_Framework\Debug
|
5 |
*/
|
6 |
|
7 |
+
namespace The_SEO_Framework\Internal;
|
|
|
|
|
|
|
|
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
23 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
*/
|
25 |
|
26 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
+
|
28 |
+
// phpcs:disable, WordPress.PHP.DevelopmentFunctions -- This whole class is meant for development.
|
29 |
+
|
30 |
+
use function \The_SEO_Framework\memo;
|
31 |
+
|
32 |
/**
|
33 |
+
* Singleton class The_SEO_Framework\Internal\Debug
|
34 |
*
|
35 |
* Holds plugin debug functions.
|
36 |
*
|
37 |
* @since 2.8.0
|
38 |
* @since 4.0.0 No longer implements an interface. It's implied.
|
39 |
+
* @since 4.2.0 Changed namespace from \The_SEO_Framework to \The_SEO_Framework\Internal
|
40 |
*/
|
41 |
final class Debug {
|
42 |
|
67 |
*/
|
68 |
public static function _set_instance( $debug = null ) {
|
69 |
|
70 |
+
if ( \is_null( static::$instance ) )
|
71 |
static::$instance = new static();
|
|
|
72 |
|
73 |
+
if ( isset( $debug ) )
|
74 |
static::$instance->the_seo_framework_debug = (bool) $debug;
|
|
|
75 |
}
|
76 |
|
77 |
/**
|
83 |
*/
|
84 |
public static function get_instance() {
|
85 |
|
86 |
+
if ( \is_null( static::$instance ) )
|
87 |
static::_set_instance();
|
|
|
88 |
|
89 |
return static::$instance;
|
90 |
}
|
248 |
/* translators: 1: Method or Property name, 2: The SEO Framework class. 3: Message */
|
249 |
\esc_html__( '%1$s is not accessible in %2$s. %3$s', 'autodescription' ),
|
250 |
'<code>' . \esc_html( $p_or_m ) . '</code>',
|
251 |
+
'<code>tsf()</code>',
|
252 |
\esc_html( $message )
|
253 |
);
|
254 |
|
287 |
* 1 = Error handler (This class).
|
288 |
* 2 = Error forwarder (TSF class).
|
289 |
*/
|
290 |
+
if ( isset( $backtrace[4]['args'][0][0] ) && is_a( $backtrace[4]['args'][0][0], 'The_SEO_Framework\Internal\Deprecated', false ) ) {
|
291 |
/**
|
292 |
* 3 = Deprecated call.
|
293 |
+
* 4 = TSF deprecation class forwarder.
|
294 |
* 5 = User mistake.
|
295 |
*/
|
296 |
$error = $backtrace[5];
|
334 |
*/
|
335 |
protected function combobulate_error_message( $error, $message, $code ) {
|
336 |
|
|
|
|
|
|
|
337 |
switch ( $code ) :
|
338 |
case E_USER_ERROR:
|
339 |
$type = 'Error';
|
353 |
break;
|
354 |
endswitch;
|
355 |
|
356 |
+
$file = \esc_html( $error['file'] ?? '' );
|
357 |
+
$line = \esc_html( $error['line'] ?? '' );
|
358 |
|
359 |
$_message = "'<span><strong>$type:</strong> $message";
|
360 |
$_message .= $file ? " In $file" : '';
|
372 |
* @access private
|
373 |
*/
|
374 |
public function _debug_output() {
|
375 |
+
\tsf()->get_view( 'debug/output' );
|
376 |
}
|
377 |
|
378 |
/**
|
386 |
* @return string
|
387 |
*/
|
388 |
protected function debug_key_wrapper( $key ) {
|
389 |
+
return '<font color="chucknorris">' . \esc_html( $key ) . '</font>';
|
390 |
}
|
391 |
|
392 |
/**
|
404 |
if ( ! is_scalar( $value ) )
|
405 |
return '<em>Debug message: not scalar</em>';
|
406 |
|
407 |
+
return '<span class="wp-ui-notification">' . \esc_html( trim( $value ) ) . '</span>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
408 |
}
|
409 |
|
410 |
/**
|
429 |
*/
|
430 |
protected function get_debug_header_output() {
|
431 |
|
432 |
+
$tsf = \tsf();
|
433 |
|
434 |
if ( \is_admin() && ! $tsf->is_term_edit() && ! $tsf->is_post_edit() && ! $tsf->is_seo_settings_page( true ) )
|
435 |
return;
|
438 |
\add_filter( 'the_seo_framework_current_object_id', [ $tsf, 'get_the_front_page_ID' ] );
|
439 |
|
440 |
// Start timer.
|
441 |
+
$t = microtime( true );
|
442 |
|
443 |
+
// I hate ob_*.
|
444 |
+
ob_start();
|
445 |
+
$tsf->html_output();
|
446 |
+
$output = ob_get_clean();
|
447 |
|
448 |
+
$timer = '<div style="display:inline-block;width:100%;padding:20px;border-bottom:1px solid #ccc;">Generated in: ' . number_format( microtime( true ) - $t, 5 ) . ' seconds</div>';
|
449 |
|
450 |
$title = \is_admin() ? 'Expected SEO Output' : 'Determined SEO Output';
|
451 |
$title = '<div style="display:inline-block;width:100%;padding:20px;margin:0 auto;border-bottom:1px solid #ccc;"><h2 style="color:#ddd;font-size:22px;padding:0;margin:0">' . $title . '</h2></div>';
|
502 |
* @return string Wrapped Query State debug output.
|
503 |
*/
|
504 |
protected function get_debug_query_output_from_cache() {
|
505 |
+
return memo() ?? memo( $this->get_debug_query_output( 'yup' ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
506 |
}
|
507 |
|
508 |
/**
|
518 |
protected function get_debug_query_output( $cache_version = 'nope' ) {
|
519 |
|
520 |
// Start timer.
|
521 |
+
$_t = microtime( true );
|
522 |
|
523 |
+
$tsf = \tsf();
|
524 |
|
525 |
// phpcs:disable, WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase -- Not this file's issue.
|
526 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- get_defined_vars() is used later.
|
|
|
527 |
$page_id = $tsf->get_the_real_ID();
|
528 |
$is_query_exploited = $tsf->is_query_exploited();
|
529 |
$query_supports_seo = $tsf->query_supports_seo() ? 'yes' : 'no';
|
535 |
$is_post_edit = $tsf->is_post_edit();
|
536 |
$is_wp_lists_edit = $tsf->is_wp_lists_edit();
|
537 |
$is_author = $tsf->is_author();
|
|
|
538 |
$is_category = $tsf->is_category();
|
539 |
$is_date = $tsf->is_date();
|
540 |
$is_year = $tsf->is_year();
|
542 |
$is_day = $tsf->is_day();
|
543 |
$is_feed = $tsf->is_feed();
|
544 |
$is_real_front_page = $tsf->is_real_front_page();
|
|
|
545 |
$is_home = $tsf->is_home();
|
546 |
+
$is_home_as_page = $tsf->is_home_as_page();
|
547 |
$is_page = $tsf->is_page();
|
548 |
$page = $tsf->page();
|
549 |
$paged = $tsf->paged();
|
568 |
$get_post_type_real_ID = $tsf->get_post_type_real_ID();
|
569 |
$admin_post_type = $tsf->get_admin_post_type();
|
570 |
$current_taxonomy = $tsf->get_current_taxonomy();
|
571 |
+
$current_post_type = $tsf->get_current_post_type();
|
572 |
$is_taxonomy_disabled = $tsf->is_taxonomy_disabled();
|
573 |
$is_post_type_archive = \is_post_type_archive();
|
574 |
$is_protected = $tsf->is_protected( $page_id );
|
575 |
// phpcs:enable, WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
|
576 |
// phpcs:enable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
577 |
|
578 |
+
$timer = microtime( true ) - $_t;
|
|
|
579 |
|
580 |
// Get all above vars, split them in two (true and false) and sort them by key names.
|
581 |
+
$vars = get_defined_vars();
|
582 |
+
|
583 |
+
// Don't debug the class object nor timer.
|
584 |
+
unset( $vars['tsf'], $vars['timer'], $vars['_t'] );
|
585 |
+
|
586 |
$current = array_filter( $vars );
|
587 |
$not_current = array_diff_key( $vars, $current );
|
588 |
|
589 |
ksort( $current );
|
590 |
ksort( $not_current );
|
591 |
|
|
|
|
|
592 |
$output = '';
|
593 |
foreach ( $current as $name => $value ) {
|
594 |
$type = '(' . \gettype( $value ) . ')';
|
596 |
if ( \is_bool( $value ) ) {
|
597 |
$value = $value ? 'true' : 'false';
|
598 |
} else {
|
599 |
+
$value = \esc_html( var_export( $value, true ) );
|
600 |
}
|
601 |
|
602 |
+
$value = '<font color="harrisonford">' . "$type $value" . '</font>';
|
603 |
$out = \esc_html( $name ) . ' => ' . $value;
|
604 |
$output .= '<span style="background:#dadada">' . $out . '</span>' . PHP_EOL;
|
605 |
}
|
610 |
if ( \is_bool( $value ) ) {
|
611 |
$value = $value ? 'true' : 'false';
|
612 |
} else {
|
613 |
+
$value = \esc_html( var_export( $value, true ) );
|
614 |
}
|
615 |
|
616 |
+
$value = '<font color="harrisonford">' . "$type $value" . '</font>';
|
617 |
$out = \esc_html( $name ) . ' => ' . $value;
|
618 |
|
619 |
$output .= $out . PHP_EOL;
|
634 |
),
|
635 |
sprintf(
|
636 |
'<div style="display:inline-block;width:100%%;padding:20px;border-bottom:1px solid #666;">Generated in: %s seconds</div>',
|
637 |
+
number_format( number_format( $timer, 5 ), 5 )
|
638 |
),
|
639 |
sprintf(
|
640 |
'<div style="display:inline-block;width:100%%;padding:20px;font-family:Consolas,Monaco,monospace;font-size:14px;">%s</div>',
|
@@ -1,12 +1,10 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* @package The_SEO_Framework\Classes\Deprecated
|
4 |
* @subpackage The_SEO_Framework\Debug\Deprecated
|
5 |
*/
|
6 |
|
7 |
-
namespace The_SEO_Framework;
|
8 |
-
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
10 |
|
11 |
/**
|
12 |
* The SEO Framework plugin
|
@@ -25,8 +23,15 @@ namespace The_SEO_Framework;
|
|
25 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
26 |
*/
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
/**
|
29 |
-
* Class The_SEO_Framework\Deprecated
|
30 |
*
|
31 |
* Contains all deprecated functions.
|
32 |
*
|
@@ -34,166 +39,68 @@ namespace The_SEO_Framework;
|
|
34 |
* @since 3.1.0 Removed all methods deprecated in 3.0.0.
|
35 |
* @since 4.0.0 Removed all methods deprecated in 3.1.0.
|
36 |
* @since 4.1.4 Removed all methods deprecated in 4.0.0.
|
|
|
|
|
37 |
* @ignore
|
38 |
*/
|
39 |
final class Deprecated {
|
40 |
|
41 |
/**
|
42 |
-
*
|
43 |
-
* Memoizes the return value.
|
44 |
*
|
45 |
-
* @since
|
46 |
-
* @since
|
|
|
|
|
47 |
* @deprecated
|
48 |
*
|
49 |
-
* @param string $
|
50 |
-
* @
|
|
|
51 |
*/
|
52 |
-
public function
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
if ( isset( $is_page[ $type ] ) )
|
57 |
-
return $is_page[ $type ];
|
58 |
-
|
59 |
-
$tsf = \the_seo_framework();
|
60 |
-
|
61 |
-
$tsf->_deprecated_function( 'the_seo_framework()->is_post_type_page()', '4.1.0' );
|
62 |
-
|
63 |
-
$post_page = (array) \get_post_types( [ 'public' => true ] );
|
64 |
-
|
65 |
-
foreach ( $post_page as $screen ) {
|
66 |
-
if ( $type === $screen ) {
|
67 |
-
return $is_page[ $type ] = true;
|
68 |
-
}
|
69 |
-
}
|
70 |
-
|
71 |
-
return $is_page[ $type ] = false;
|
72 |
}
|
73 |
|
74 |
/**
|
75 |
-
*
|
76 |
*
|
77 |
* @since 3.1.0
|
78 |
-
* @since 4.
|
79 |
-
* 2: Deprecated.
|
80 |
* @deprecated
|
81 |
*
|
82 |
-
* @param string $
|
83 |
-
* @return
|
84 |
-
*/
|
85 |
-
public function is_taxonomy_public( $taxonomy = '' ) {
|
86 |
-
|
87 |
-
$tsf = \the_seo_framework();
|
88 |
-
|
89 |
-
$tsf->_deprecated_function( 'the_seo_framework()->is_taxonomy_public()', '4.1.0', 'the_seo_framework()->is_taxonomy_supported()' );
|
90 |
-
|
91 |
-
$taxonomy = $taxonomy ?: $tsf->get_current_taxonomy();
|
92 |
-
if ( ! $taxonomy ) return false;
|
93 |
-
|
94 |
-
$tax = \get_taxonomy( $taxonomy );
|
95 |
-
|
96 |
-
if ( false === $tax ) return false;
|
97 |
-
|
98 |
-
return ! empty( $tax->public );
|
99 |
-
}
|
100 |
-
|
101 |
-
/**
|
102 |
-
* Return option from the options table and cache result.
|
103 |
-
* Memoizes the return value.
|
104 |
-
*
|
105 |
-
* Values pulled from the database are cached on each request, so a second request for the same value won't cause a
|
106 |
-
* second DB interaction.
|
107 |
-
*
|
108 |
-
* @since 2.0.0
|
109 |
-
* @since 2.8.2 No longer decodes entities on request.
|
110 |
-
* @since 3.1.0 Now uses the filterable call when caching is disabled.
|
111 |
-
* @since 4.1.0 Deprecated.
|
112 |
-
* @thanks StudioPress (http://www.studiopress.com/) for some code.
|
113 |
-
* @deprecated
|
114 |
-
*
|
115 |
-
* @param string $key Option name.
|
116 |
-
* @param string $setting Optional. Settings field name. Eventually defaults to null if not passed as an argument.
|
117 |
-
* @param boolean $use_cache Optional. Whether to use the cache value or not.
|
118 |
-
* @return mixed The value of this $key in the database. Empty string on failure.
|
119 |
*/
|
120 |
-
public function
|
121 |
|
122 |
-
|
123 |
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
}
|
132 |
|
133 |
-
|
134 |
-
|
135 |
-
if ( ! isset( $cache[ $setting ] ) )
|
136 |
-
$cache[ $setting ] = \stripslashes_deep( $tsf->get_all_options( $setting ) );
|
137 |
-
|
138 |
-
return isset( $cache[ $setting ][ $key ] ) ? $cache[ $setting ][ $key ] : '';
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Returns the homepage tagline from option or bloginfo, when set.
|
143 |
-
*
|
144 |
-
* @since 3.0.4
|
145 |
-
* @since 4.0.0 Added caching.
|
146 |
-
* @since 4.1.0 Deprecated.
|
147 |
-
* @uses $this->get_blogdescription(), this method already trims.
|
148 |
-
* @deprecated
|
149 |
-
*
|
150 |
-
* @return string The trimmed tagline.
|
151 |
-
*/
|
152 |
-
public function get_home_page_tagline() {
|
153 |
-
|
154 |
-
$tsf = \the_seo_framework();
|
155 |
-
|
156 |
-
$tsf->_deprecated_function( 'the_seo_framework()->get_home_page_tagline()', '4.1.0', 'the_seo_framework()->get_home_title_additions()' );
|
157 |
-
|
158 |
-
return $tsf->get_home_title_additions();
|
159 |
-
}
|
160 |
-
|
161 |
-
/**
|
162 |
-
* Cached WordPress permalink structure settings.
|
163 |
-
*
|
164 |
-
* @since 2.6.0
|
165 |
-
* @since 3.1.0 Removed caching.
|
166 |
-
* @since 4.1.0 Deprecated.
|
167 |
-
* @deprecated
|
168 |
-
*
|
169 |
-
* @return string permalink structure.
|
170 |
-
*/
|
171 |
-
public function permalink_structure() {
|
172 |
-
|
173 |
-
$tsf = \the_seo_framework();
|
174 |
-
|
175 |
-
$tsf->_deprecated_function( 'the_seo_framework()->permalink_structure()', '4.1.0', "get_option( 'permalink_structure' )" );
|
176 |
-
|
177 |
-
return \get_option( 'permalink_structure' );
|
178 |
-
}
|
179 |
-
|
180 |
-
/**
|
181 |
-
* Appends given query to given URL.
|
182 |
-
*
|
183 |
-
* @since 3.0.0
|
184 |
-
* @since 3.1.0 Now uses parse_str and add_query_arg, preventing duplicated entries.
|
185 |
-
* @since 4.1.4 Deprecated silently.
|
186 |
-
* @since 4.2.0 Hard deprecation.
|
187 |
-
* @deprecated
|
188 |
-
*
|
189 |
-
* @param string $url A fully qualified URL.
|
190 |
-
* @param string $query A fully qualified query taken from parse_url( $url, PHP_URL_QUERY );
|
191 |
-
* @return string A fully qualified URL with appended $query.
|
192 |
-
*/
|
193 |
-
public function append_php_query( $url, $query = '' ) {
|
194 |
-
$tsf = \the_seo_framework();
|
195 |
-
// $tsf->_deprecated_function( 'the_seo_framework()->append_php_query()', '4.2.0', 'the_seo_framework()->append_url_query()' );
|
196 |
-
return $tsf->append_url_query( $url, $query );
|
197 |
}
|
198 |
|
199 |
/**
|
@@ -208,15 +115,11 @@ final class Deprecated {
|
|
208 |
*/
|
209 |
public function get_html_output() {
|
210 |
|
211 |
-
$tsf = \
|
212 |
-
|
213 |
-
// $tsf->_deprecated_function( 'the_seo_framework()->get_html_output()', '4.2.0' );
|
214 |
|
215 |
$robots = $tsf->robots();
|
216 |
|
217 |
-
/** @since 4.0.4 Added as WP 5.3 patch. */
|
218 |
-
$tsf->set_timezone( 'UTC' );
|
219 |
-
|
220 |
/**
|
221 |
* @since 2.6.0
|
222 |
* @param string $before The content before the SEO output.
|
@@ -292,9 +195,6 @@ final class Deprecated {
|
|
292 |
*/
|
293 |
$after = (string) \apply_filters( 'the_seo_framework_pro', '' );
|
294 |
|
295 |
-
/** @since 4.0.4 Added as WP 5.3 patch. */
|
296 |
-
$tsf->reset_timezone();
|
297 |
-
|
298 |
return "{$robots}{$before}{$before_legacy}{$output}{$after_legacy}{$after}";
|
299 |
}
|
300 |
|
@@ -312,10 +212,11 @@ final class Deprecated {
|
|
312 |
* @since 4.0.0
|
313 |
* @since 4.1.0 Now uses the new taxonomy robots settings.
|
314 |
* @since 4.1.4 Soft deprecated. Use 'robots_meta' instead.
|
315 |
-
* @since 4.2.0 Hard deprecation.
|
|
|
316 |
* @deprecated
|
317 |
*
|
318 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
319 |
* @param int <bit> $ignore The ignore level. {
|
320 |
* 0 = 0b00: Ignore nothing.
|
321 |
* 1 = 0b01: Ignore protection. (\The_SEO_Framework\ROBOTS_IGNORE_PROTECTION)
|
@@ -325,8 +226,8 @@ final class Deprecated {
|
|
325 |
* @return bool Whether noindex is set or not
|
326 |
*/
|
327 |
public function is_robots_meta_noindex_set_by_args( $args, $ignore = 0b00 ) {
|
328 |
-
$tsf = \
|
329 |
-
|
330 |
$meta = $tsf->generate_robots_meta( $args, null, $ignore );
|
331 |
return isset( $meta['noindex'] ) && 'noindex' === $meta['noindex'];
|
332 |
}
|
@@ -338,24 +239,26 @@ final class Deprecated {
|
|
338 |
* @since 2.2.4 Added robots SEO settings check.
|
339 |
* @since 2.2.8 Added check for empty archives.
|
340 |
* @since 2.8.0 Added check for protected/private posts.
|
341 |
-
* @since 3.0.0
|
342 |
-
*
|
343 |
-
* @since 3.1.0
|
344 |
-
*
|
345 |
-
*
|
346 |
-
* @since 4.0.0
|
347 |
-
*
|
348 |
-
*
|
349 |
-
* @since 4.0.2
|
350 |
-
*
|
351 |
-
* @since 4.0.3
|
352 |
-
*
|
353 |
-
* @since 4.0.5
|
354 |
-
*
|
355 |
* @since 4.1.4 Deprecated silently. Use generate_robots_meta() instead.
|
356 |
-
* @since 4.2.0 Hard deprecation.
|
|
|
|
|
357 |
*
|
358 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
359 |
* @param int <bit> $ignore The ignore level. {
|
360 |
* 0 = 0b00: Ignore nothing.
|
361 |
* 1 = 0b01: Ignore protection. (\The_SEO_Framework\ROBOTS_IGNORE_PROTECTION)
|
@@ -367,8 +270,8 @@ final class Deprecated {
|
|
367 |
* }
|
368 |
*/
|
369 |
public function robots_meta( $args = null, $ignore = 0b00 ) {
|
370 |
-
$tsf = \
|
371 |
-
|
372 |
return $tsf->generate_robots_meta( $args, null, $ignore );
|
373 |
}
|
374 |
|
@@ -381,9 +284,8 @@ final class Deprecated {
|
|
381 |
* @since 2.9.2 Now also checks for permalinks.
|
382 |
* @since 2.9.3 Now also checks for sitemap_robots option.
|
383 |
* @since 3.1.0 Removed Jetpack's sitemap check -- it's no longer valid.
|
384 |
-
* @since 4.0.0
|
385 |
-
*
|
386 |
-
* FIXME This method also checks for file existence (and location...), but is only used when the file definitely doesn't exist.
|
387 |
* @since 4.1.4 Soft deprecated.
|
388 |
* @since 4.2.0 Hard deprecation.
|
389 |
* @deprecated
|
@@ -393,9 +295,8 @@ final class Deprecated {
|
|
393 |
*/
|
394 |
public function can_do_sitemap_robots( $check_option = true ) {
|
395 |
|
396 |
-
$tsf = \
|
397 |
-
|
398 |
-
// $tsf->_deprecated_function( 'the_seo_framework()->is_robots_meta_noindex_set_by_args()', '4.2.0' );
|
399 |
|
400 |
if ( $check_option ) {
|
401 |
if ( ! $tsf->get_option( 'sitemaps_output' )
|
@@ -431,7 +332,7 @@ final class Deprecated {
|
|
431 |
* @param bool $use_tabs Whether to output tabs, only works when $tabs count is greater than 1.
|
432 |
*/
|
433 |
public function nav_tab_wrapper( $id, $tabs = [], $depr = null, $use_tabs = true ) {
|
434 |
-
|
435 |
\The_SEO_Framework\Bridges\SeoSettings::_nav_tab_wrapper( $id, $tabs, $use_tabs );
|
436 |
}
|
437 |
|
@@ -458,7 +359,7 @@ final class Deprecated {
|
|
458 |
* @param bool $use_tabs Whether to output tabs, only works when $tabs count is greater than 1.
|
459 |
*/
|
460 |
public function inpost_flex_nav_tab_wrapper( $id, $tabs = [], $_depr = null, $use_tabs = true ) {
|
461 |
-
|
462 |
\The_SEO_Framework\Bridges\PostSettings::_flex_nav_tab_wrapper( $id, $tabs, $use_tabs );
|
463 |
}
|
464 |
|
@@ -478,7 +379,7 @@ final class Deprecated {
|
|
478 |
* @return string The image uploader button.
|
479 |
*/
|
480 |
public function get_social_image_uploader_form( $input_id ) {
|
481 |
-
|
482 |
return \The_SEO_Framework\Interpreters\Form::get_image_uploader_form( [ 'id' => $input_id ] );
|
483 |
}
|
484 |
|
@@ -497,7 +398,7 @@ final class Deprecated {
|
|
497 |
* @return string The image uploader button.
|
498 |
*/
|
499 |
public function get_logo_uploader_form( $input_id ) {
|
500 |
-
|
501 |
return \The_SEO_Framework\Interpreters\Form::get_image_uploader_form( [
|
502 |
'id' => $input_id,
|
503 |
'data' => [
|
@@ -523,7 +424,8 @@ final class Deprecated {
|
|
523 |
* @ignore Unused. The relying methods were yeeted off in 4.0.0.
|
524 |
* "We no longer automatically resize images when they’re deemed too large."
|
525 |
* @since 4.1.4 Deprecated silently. Marked for quick deletion.
|
526 |
-
* @
|
|
|
527 |
*
|
528 |
* @param int $i The dimension to resize.
|
529 |
* @param int $r1 The dimension that determines the ratio.
|
@@ -531,6 +433,8 @@ final class Deprecated {
|
|
531 |
* @return int The proportional dimension, rounded.
|
532 |
*/
|
533 |
public function proportionate_dimensions( $i, $r1, $r2 ) {
|
|
|
|
|
534 |
return round( $i / ( $r1 / $r2 ) );
|
535 |
}
|
536 |
|
@@ -545,8 +449,8 @@ final class Deprecated {
|
|
545 |
* @return string The escaped SEO Settings page URL.
|
546 |
*/
|
547 |
public function seo_settings_page_url() {
|
548 |
-
$tsf = \
|
549 |
-
|
550 |
return $tsf->get_seo_settings_page_url();
|
551 |
}
|
552 |
|
@@ -556,12 +460,13 @@ final class Deprecated {
|
|
556 |
* @since 3.0.0
|
557 |
* @since 4.1.4 Deprecated silently. Use `get_user_meta_defaults()` instead.
|
558 |
* @since 4.2.0 Hard deprecation.
|
|
|
559 |
*
|
560 |
* @return array The default user meta index and values.
|
561 |
*/
|
562 |
public function get_default_user_data() {
|
563 |
-
$tsf = \
|
564 |
-
|
565 |
return $tsf->get_user_meta_defaults();
|
566 |
}
|
567 |
|
@@ -578,6 +483,7 @@ final class Deprecated {
|
|
578 |
* 3. Added not-found cache.
|
579 |
* @since 4.1.4 Deprecated silently. Use `get_user_meta()` instead.
|
580 |
* @since 4.2.0 Hard deprecation.
|
|
|
581 |
*
|
582 |
* @param int $user_id The user ID. When empty, it will try to fetch the current user.
|
583 |
* @param string $option The option name.
|
@@ -585,8 +491,8 @@ final class Deprecated {
|
|
585 |
* @return mixed The metadata value.
|
586 |
*/
|
587 |
public function get_user_option( $user_id = 0, $option = '', $default = null ) {
|
588 |
-
$tsf = \
|
589 |
-
|
590 |
return $tsf->get_user_meta_item( $user_id ?: $tsf->get_user_id(), $option ) ?: $default;
|
591 |
}
|
592 |
|
@@ -596,6 +502,7 @@ final class Deprecated {
|
|
596 |
* @since 3.0.0
|
597 |
* @since 4.1.4 Silently deprecated. use `get_current_post_author_id()` instead.
|
598 |
* @since 4.2.0 Hard deprecation.
|
|
|
599 |
*
|
600 |
* @param int $author_id The author ID. When empty, it will return $default.
|
601 |
* @param string $option The option name. When empty, it will return $default.
|
@@ -603,8 +510,8 @@ final class Deprecated {
|
|
603 |
* @return mixed The metadata value
|
604 |
*/
|
605 |
public function get_author_option( $author_id, $option, $default = null ) {
|
606 |
-
$tsf = \
|
607 |
-
|
608 |
return $tsf->get_user_meta_item( $option, $author_id ?: $tsf->get_current_post_author_id() ) ?: $default;
|
609 |
}
|
610 |
|
@@ -614,14 +521,15 @@ final class Deprecated {
|
|
614 |
* @since 3.0.0
|
615 |
* @since 4.1.4 Silently deprecated. Use `get_current_post_author_meta_item()` instead.
|
616 |
* @since 4.2.0 Hard deprecation.
|
|
|
617 |
*
|
618 |
* @param string $option The option name.
|
619 |
* @param mixed $default The default value to return when the data doesn't exist.
|
620 |
* @return mixed The metadata value
|
621 |
*/
|
622 |
public function get_current_author_option( $option, $default = null ) {
|
623 |
-
$tsf = \
|
624 |
-
|
625 |
return $tsf->get_current_post_author_meta_item( $option ) ?: $default;
|
626 |
}
|
627 |
|
@@ -642,7 +550,7 @@ final class Deprecated {
|
|
642 |
*/
|
643 |
public function is_wc_shop( $post = null ) {
|
644 |
|
645 |
-
|
646 |
|
647 |
if ( isset( $post ) ) {
|
648 |
$post = \get_post( $post );
|
@@ -664,8 +572,8 @@ final class Deprecated {
|
|
664 |
* Determines if the page is the WooCommerce plugin Product page.
|
665 |
*
|
666 |
* @since 2.5.2
|
667 |
-
* @since 4.0.0
|
668 |
-
*
|
669 |
* @since 4.0.5 Soft deprecated.
|
670 |
* @since 4.1.4 1. Another silent deprecation. Use `is_product()` instead.
|
671 |
* 2. Removed output memoization.
|
@@ -678,8 +586,8 @@ final class Deprecated {
|
|
678 |
*/
|
679 |
public function is_wc_product( $post = 0 ) {
|
680 |
|
681 |
-
$tsf = \
|
682 |
-
|
683 |
|
684 |
if ( \is_admin() )
|
685 |
return $tsf->is_wc_product_admin();
|
@@ -708,8 +616,8 @@ final class Deprecated {
|
|
708 |
* @return bool
|
709 |
*/
|
710 |
public function is_wc_product_admin() {
|
711 |
-
$tsf = \
|
712 |
-
|
713 |
// Checks for "is_singular_admin()" because the post type is non-hierarchical.
|
714 |
return $tsf->is_singular_admin() && 'product' === $tsf->get_admin_post_type();
|
715 |
}
|
@@ -720,6 +628,8 @@ final class Deprecated {
|
|
720 |
* @since 2.7.0
|
721 |
* @since 2.8.0 New users now get a new array assigned.
|
722 |
* @since 4.1.4 Deprecated silently. Use `update_single_user_meta_item()` instead.
|
|
|
|
|
723 |
*
|
724 |
* @param int $user_id The user ID.
|
725 |
* @param string $option The user's SEO metadata option.
|
@@ -728,8 +638,8 @@ final class Deprecated {
|
|
728 |
*/
|
729 |
public function update_user_option( $user_id = 0, $option = '', $value = '' ) {
|
730 |
|
731 |
-
$tsf = \
|
732 |
-
|
733 |
|
734 |
if ( ! $option )
|
735 |
return false;
|
@@ -760,15 +670,15 @@ final class Deprecated {
|
|
760 |
*
|
761 |
* @since 2.2.2
|
762 |
* @since 4.1.4 Deprecated silently.
|
763 |
-
* @since
|
764 |
* @deprecated
|
765 |
*
|
766 |
* @param string $name Field name base
|
767 |
* @return string Full field name
|
768 |
*/
|
769 |
public function get_field_name( $name ) {
|
770 |
-
|
771 |
-
return \The_SEO_Framework\Interpreters\
|
772 |
}
|
773 |
|
774 |
/**
|
@@ -776,14 +686,15 @@ final class Deprecated {
|
|
776 |
*
|
777 |
* @since 2.2.2
|
778 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
779 |
-
* @since
|
|
|
780 |
* @uses $this->get_field_name() Construct name attributes for use in form fields.
|
781 |
*
|
782 |
* @param string $name Field name base
|
783 |
*/
|
784 |
public function field_name( $name ) {
|
785 |
-
|
786 |
-
return \The_SEO_Framework\Interpreters\
|
787 |
}
|
788 |
|
789 |
/**
|
@@ -791,14 +702,15 @@ final class Deprecated {
|
|
791 |
*
|
792 |
* @since 2.2.2
|
793 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
794 |
-
* @since
|
|
|
795 |
*
|
796 |
* @param string $id Field id base
|
797 |
* @return string Full field id
|
798 |
*/
|
799 |
public function get_field_id( $id ) {
|
800 |
-
|
801 |
-
return \The_SEO_Framework\Interpreters\
|
802 |
}
|
803 |
|
804 |
/**
|
@@ -806,7 +718,8 @@ final class Deprecated {
|
|
806 |
*
|
807 |
* @since 2.2.2
|
808 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
809 |
-
* @since
|
|
|
810 |
* @uses $this->get_field_id() Constructs id attributes for use in form fields.
|
811 |
*
|
812 |
* @param string $id Field id base.
|
@@ -814,8 +727,13 @@ final class Deprecated {
|
|
814 |
* @return string Full field id
|
815 |
*/
|
816 |
public function field_id( $id, $echo = true ) {
|
817 |
-
|
818 |
-
|
|
|
|
|
|
|
|
|
|
|
819 |
}
|
820 |
|
821 |
/**
|
@@ -824,13 +742,14 @@ final class Deprecated {
|
|
824 |
*
|
825 |
* @since 2.0.0
|
826 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
827 |
-
* @since
|
|
|
828 |
*
|
829 |
* @param string $content Content to be wrapped in code tags.
|
830 |
* @return string Content wrapped in code tags.
|
831 |
*/
|
832 |
public function code_wrap( $content ) {
|
833 |
-
|
834 |
return \The_SEO_Framework\Interpreters\HTML::code_wrap( $content );
|
835 |
}
|
836 |
|
@@ -840,13 +759,14 @@ final class Deprecated {
|
|
840 |
*
|
841 |
* @since 2.2.2
|
842 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
843 |
-
* @since
|
|
|
844 |
*
|
845 |
* @param string $content Content to be wrapped in code tags.
|
846 |
* @return string Content wrapped in code tags.
|
847 |
*/
|
848 |
public function code_wrap_noesc( $content ) {
|
849 |
-
|
850 |
return \The_SEO_Framework\Interpreters\HTML::code_wrap_noesc( $content );
|
851 |
}
|
852 |
|
@@ -856,13 +776,14 @@ final class Deprecated {
|
|
856 |
*
|
857 |
* @since 2.7.0
|
858 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
859 |
-
* @since
|
|
|
860 |
*
|
861 |
* @param string $content Content to be wrapped in the description wrap.
|
862 |
* @param bool $block Whether to wrap the content in <p> tags.
|
863 |
*/
|
864 |
public function description( $content, $block = true ) {
|
865 |
-
|
866 |
return \The_SEO_Framework\Interpreters\HTML::description( $content, $block );
|
867 |
}
|
868 |
|
@@ -871,13 +792,14 @@ final class Deprecated {
|
|
871 |
*
|
872 |
* @since 2.7.0
|
873 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
874 |
-
* @since
|
|
|
875 |
*
|
876 |
* @param string $content Content to be wrapped in the description wrap. Expected to be escaped.
|
877 |
* @param bool $block Whether to wrap the content in <p> tags.
|
878 |
*/
|
879 |
public function description_noesc( $content, $block = true ) {
|
880 |
-
|
881 |
return \The_SEO_Framework\Interpreters\HTML::description_noesc( $content, $block );
|
882 |
}
|
883 |
|
@@ -887,13 +809,14 @@ final class Deprecated {
|
|
887 |
*
|
888 |
* @since 3.1.0
|
889 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
890 |
-
* @since
|
|
|
891 |
*
|
892 |
* @param string $content Content to be wrapped in the attention wrap.
|
893 |
* @param bool $block Whether to wrap the content in <p> tags.
|
894 |
*/
|
895 |
public function attention( $content, $block = true ) {
|
896 |
-
|
897 |
return \The_SEO_Framework\Interpreters\HTML::attention( $content, $block );
|
898 |
}
|
899 |
|
@@ -902,13 +825,14 @@ final class Deprecated {
|
|
902 |
*
|
903 |
* @since 3.1.0
|
904 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
905 |
-
* @since
|
|
|
906 |
*
|
907 |
* @param string $content Content to be wrapped in the attention wrap. Expected to be escaped.
|
908 |
* @param bool $block Whether to wrap the content in <p> tags.
|
909 |
*/
|
910 |
public function attention_noesc( $content, $block = true ) {
|
911 |
-
|
912 |
return \The_SEO_Framework\Interpreters\HTML::attention_noesc( $content, $block );
|
913 |
}
|
914 |
|
@@ -918,13 +842,14 @@ final class Deprecated {
|
|
918 |
*
|
919 |
* @since 3.1.0
|
920 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
921 |
-
* @since
|
|
|
922 |
*
|
923 |
* @param string $content Content to be wrapped in the wrap. Expected to be escaped.
|
924 |
* @param bool $block Whether to wrap the content in <p> tags.
|
925 |
*/
|
926 |
public function attention_description( $content, $block = true ) {
|
927 |
-
|
928 |
return \The_SEO_Framework\Interpreters\HTML::attention_description( $content, $block );
|
929 |
}
|
930 |
|
@@ -933,13 +858,14 @@ final class Deprecated {
|
|
933 |
*
|
934 |
* @since 3.1.0
|
935 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
936 |
-
* @since
|
|
|
937 |
*
|
938 |
* @param string $content Content to be wrapped in the wrap. Expected to be escaped.
|
939 |
* @param bool $block Whether to wrap the content in <p> tags.
|
940 |
*/
|
941 |
public function attention_description_noesc( $content, $block = true ) {
|
942 |
-
|
943 |
return \The_SEO_Framework\Interpreters\HTML::attention_description_noesc( $content, $block );
|
944 |
}
|
945 |
|
@@ -950,14 +876,15 @@ final class Deprecated {
|
|
950 |
*
|
951 |
* @since 2.6.0
|
952 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
953 |
-
* @since
|
|
|
954 |
*
|
955 |
* @param string $input The input to wrap. Should already be escaped.
|
956 |
* @param bool $echo Whether to escape echo or just return.
|
957 |
* @return string|void Wrapped $input.
|
958 |
*/
|
959 |
public function wrap_fields( $input = '', $echo = false ) {
|
960 |
-
|
961 |
return \The_SEO_Framework\Interpreters\HTML::wrap_fields( $input, $echo );
|
962 |
}
|
963 |
|
@@ -968,7 +895,8 @@ final class Deprecated {
|
|
968 |
* @since 3.0.0 Links are now no longer followed, referred or bound to opener.
|
969 |
* @since 4.0.0 Now adds a tabindex to the span tag, so you can focus it using keyboard navigation.
|
970 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
971 |
-
* @since
|
|
|
972 |
*
|
973 |
* @param string $description The descriptive on-hover title.
|
974 |
* @param string $link The non-escaped link.
|
@@ -976,7 +904,7 @@ final class Deprecated {
|
|
976 |
* @return string HTML checkbox output if $echo is false.
|
977 |
*/
|
978 |
public function make_info( $description = '', $link = '', $echo = true ) {
|
979 |
-
|
980 |
return \The_SEO_Framework\Interpreters\HTML::make_info( $description, $link, $echo );
|
981 |
}
|
982 |
|
@@ -986,16 +914,17 @@ final class Deprecated {
|
|
986 |
* @since 4.0.0
|
987 |
* @since 4.1.0 No longer adds an extra space in front of the return value when no data is generated.
|
988 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
989 |
-
* @since
|
990 |
* @internal
|
|
|
991 |
*
|
992 |
* @param array $data : {
|
993 |
* string $k => mixed $v
|
994 |
* }
|
995 |
* @return string The HTML data attributes, with added space to the start.
|
996 |
*/
|
997 |
-
public function make_data_attributes(
|
998 |
-
|
999 |
return \The_SEO_Framework\Interpreters\HTML::make_data_attributes( $data );
|
1000 |
}
|
1001 |
|
@@ -1006,7 +935,8 @@ final class Deprecated {
|
|
1006 |
* @since 2.7.0 Added escape parameter. Defaults to true.
|
1007 |
* @since 3.0.3 Added $disabled parameter. Defaults to false.
|
1008 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1009 |
-
* @since
|
|
|
1010 |
*
|
1011 |
* @param string $field_id The option ID. Must be within the Autodescription settings.
|
1012 |
* @param string $label The checkbox description label.
|
@@ -1016,8 +946,8 @@ final class Deprecated {
|
|
1016 |
* @return string HTML checkbox output.
|
1017 |
*/
|
1018 |
public function make_checkbox( $field_id = '', $label = '', $description = '', $escape = true, $disabled = false ) {
|
1019 |
-
|
1020 |
-
return \The_SEO_Framework\Interpreters\
|
1021 |
'id' => $field_id,
|
1022 |
'index' => '',
|
1023 |
'label' => $label,
|
@@ -1033,7 +963,8 @@ final class Deprecated {
|
|
1033 |
*
|
1034 |
* @since 4.0.0
|
1035 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1036 |
-
* @since
|
|
|
1037 |
*
|
1038 |
* @param array $args : {
|
1039 |
* string $id The select field ID.
|
@@ -1048,8 +979,8 @@ final class Deprecated {
|
|
1048 |
* }
|
1049 |
* @return string The option field.
|
1050 |
*/
|
1051 |
-
public function make_single_select_form(
|
1052 |
-
|
1053 |
return \The_SEO_Framework\Interpreters\Form::make_single_select_form( $args );
|
1054 |
}
|
1055 |
|
@@ -1062,7 +993,9 @@ final class Deprecated {
|
|
1062 |
* @since 2.2.5
|
1063 |
* @since 3.1.0 Deprecated second parameter.
|
1064 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1065 |
-
* @since
|
|
|
|
|
1066 |
*
|
1067 |
* @param string $key The option name which returns boolean.
|
1068 |
* @param string $depr Deprecated
|
@@ -1070,17 +1003,20 @@ final class Deprecated {
|
|
1070 |
* @param bool $echo Whether to echo or return the output.
|
1071 |
* @return string Empty on echo or the class name with an optional wrapper.
|
1072 |
*/
|
1073 |
-
public function is_default_checked( $key, $depr = '', $wrap = true, $echo = true ) {
|
1074 |
-
|
1075 |
-
return
|
1076 |
}
|
|
|
1077 |
/**
|
1078 |
* Returns the HTML class wrap for warning Checkbox options.
|
1079 |
*
|
1080 |
* @since 2.3.4
|
1081 |
* @since 3.1.0 Deprecated second parameter.
|
1082 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1083 |
-
* @since
|
|
|
|
|
1084 |
*
|
1085 |
* @param string $key The option name which returns boolean.
|
1086 |
* @param string $deprecated Deprecated.
|
@@ -1088,24 +1024,27 @@ final class Deprecated {
|
|
1088 |
* @param bool $echo Whether to echo or return the output.
|
1089 |
* @return string Empty on echo or the class name with an optional wrapper.
|
1090 |
*/
|
1091 |
-
public function is_warning_checked( $key, $deprecated = '', $wrap = true, $echo = true ) {
|
1092 |
-
|
1093 |
-
return
|
1094 |
}
|
|
|
1095 |
/**
|
1096 |
* Returns the HTML class wrap for warning/default Checkbox options.
|
1097 |
*
|
1098 |
* @since 2.6.0
|
1099 |
* @since 3.1.0 Added the $wrap parameter.
|
1100 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1101 |
-
* @since
|
|
|
|
|
1102 |
*
|
1103 |
* @param string $key The option name which returns boolean.
|
1104 |
* @param bool $wrap Whether to wrap the class name in `class="%s"`
|
1105 |
*/
|
1106 |
-
public function get_is_conditional_checked( $key, $wrap = true ) {
|
1107 |
-
|
1108 |
-
return
|
1109 |
}
|
1110 |
|
1111 |
/**
|
@@ -1114,7 +1053,9 @@ final class Deprecated {
|
|
1114 |
* @since 2.3.4
|
1115 |
* @since 3.1.0 Deprecated second parameter.
|
1116 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1117 |
-
* @since
|
|
|
|
|
1118 |
*
|
1119 |
* @param string $key The option name which returns boolean.
|
1120 |
* @param string $deprecated Deprecated. Used to be the settings field.
|
@@ -1122,28 +1063,29 @@ final class Deprecated {
|
|
1122 |
* @param bool $echo Whether to echo or return the output.
|
1123 |
* @return string Empty on echo or the class name with an optional wrapper.
|
1124 |
*/
|
1125 |
-
public function is_conditional_checked( $key, $deprecated = '', $wrap = true, $echo = true ) {
|
1126 |
-
|
1127 |
-
return
|
1128 |
}
|
1129 |
|
1130 |
/**
|
1131 |
* Outputs character counter wrap for both JavaScript and no-Javascript.
|
1132 |
*
|
1133 |
* @since 3.0.0
|
1134 |
-
* @since 3.1.0
|
1135 |
-
*
|
1136 |
-
*
|
1137 |
* @since 4.1.0 No longer marks up the counter with the `description` HTML class.
|
1138 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1139 |
-
* @since
|
|
|
1140 |
*
|
1141 |
* @param string $for The input ID it's for.
|
1142 |
* @param string $depr The initial value for no-JS. Deprecated.
|
1143 |
* @param bool $display Whether to display the counter. (options page gimmick)
|
1144 |
*/
|
1145 |
public function output_character_counter_wrap( $for, $depr = '', $display = true ) {
|
1146 |
-
|
1147 |
return \The_SEO_Framework\Interpreters\Form::output_character_counter_wrap( $for, $display );
|
1148 |
}
|
1149 |
|
@@ -1152,14 +1094,612 @@ final class Deprecated {
|
|
1152 |
*
|
1153 |
* @since 3.0.0
|
1154 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1155 |
-
* @since
|
|
|
1156 |
*
|
1157 |
* @param string $for The input ID it's for.
|
1158 |
* @param string $type Whether it's a 'title' or 'description' counter.
|
1159 |
* @param bool $display Whether to display the counter. (options page gimmick)
|
1160 |
*/
|
1161 |
public function output_pixel_counter_wrap( $for, $type, $display = true ) {
|
1162 |
-
|
1163 |
return \The_SEO_Framework\Interpreters\Form::output_pixel_counter_wrap( $for, $type, $display );
|
1164 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1165 |
}
|
1 |
<?php
|
2 |
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Internal\Deprecated
|
4 |
* @subpackage The_SEO_Framework\Debug\Deprecated
|
5 |
*/
|
6 |
|
7 |
+
namespace The_SEO_Framework\Internal;
|
|
|
|
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
23 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
*/
|
25 |
|
26 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
+
|
28 |
+
use function \The_SEO_Framework\{
|
29 |
+
memo, // Precautionary.
|
30 |
+
umemo, // Precautionary.
|
31 |
+
};
|
32 |
+
|
33 |
/**
|
34 |
+
* Class The_SEO_Framework\Internal\Deprecated
|
35 |
*
|
36 |
* Contains all deprecated functions.
|
37 |
*
|
39 |
* @since 3.1.0 Removed all methods deprecated in 3.0.0.
|
40 |
* @since 4.0.0 Removed all methods deprecated in 3.1.0.
|
41 |
* @since 4.1.4 Removed all methods deprecated in 4.0.0.
|
42 |
+
* @since 4.2.0 1. Changed namespace from \The_SEO_Framework to \The_SEO_Framework\Internal
|
43 |
+
* 2. Removed all methods deprecated in 4.1.0.
|
44 |
* @ignore
|
45 |
*/
|
46 |
final class Deprecated {
|
47 |
|
48 |
/**
|
49 |
+
* Appends given query to given URL.
|
|
|
50 |
*
|
51 |
+
* @since 3.0.0
|
52 |
+
* @since 3.1.0 Now uses parse_str and add_query_arg, preventing duplicated entries.
|
53 |
+
* @since 4.1.4 Deprecated silently.
|
54 |
+
* @since 4.2.0 Hard deprecation.
|
55 |
* @deprecated
|
56 |
*
|
57 |
+
* @param string $url A fully qualified URL.
|
58 |
+
* @param string $query A fully qualified query taken from parse_url( $url, PHP_URL_QUERY );
|
59 |
+
* @return string A fully qualified URL with appended $query.
|
60 |
*/
|
61 |
+
public function append_php_query( $url, $query = '' ) {
|
62 |
+
$tsf = \tsf();
|
63 |
+
$tsf->_deprecated_function( 'tsf()->append_php_query()', '4.2.0', 'tsf()->append_url_query()' );
|
64 |
+
return $tsf->append_url_query( $url, $query );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
}
|
66 |
|
67 |
/**
|
68 |
+
* Runs header actions.
|
69 |
*
|
70 |
* @since 3.1.0
|
71 |
+
* @since 4.2.0 Deprecated
|
|
|
72 |
* @deprecated
|
73 |
*
|
74 |
+
* @param string $location Either 'before' or 'after'.
|
75 |
+
* @return string The filter output.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
*/
|
77 |
+
public function get_legacy_header_filters_output( $location = 'before' ) {
|
78 |
|
79 |
+
$output = '';
|
80 |
|
81 |
+
/**
|
82 |
+
* @since 2.2.6
|
83 |
+
* @since 4.2.0 Deprecated
|
84 |
+
* @deprecated
|
85 |
+
* @param array $functions {
|
86 |
+
* 'callback' => string|array The function to call.
|
87 |
+
* 'args' => scalar|array Arguments. When array, each key is a new argument.
|
88 |
+
* }
|
89 |
+
*/
|
90 |
+
$functions = (array) \apply_filters_deprecated(
|
91 |
+
"the_seo_framework_{$location}_output",
|
92 |
+
[ [] ],
|
93 |
+
'4.2.0 of The SEO Framework',
|
94 |
+
"Action the_seo_framework_{$location}_meta"
|
95 |
+
);
|
96 |
+
|
97 |
+
foreach ( $functions as $function ) {
|
98 |
+
if ( ! empty( $function['callback'] ) ) {
|
99 |
+
$output .= \call_user_func_array( $function['callback'], (array) ( $function['args'] ?? '' ) );
|
100 |
+
}
|
101 |
}
|
102 |
|
103 |
+
return $output;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
}
|
105 |
|
106 |
/**
|
115 |
*/
|
116 |
public function get_html_output() {
|
117 |
|
118 |
+
$tsf = \tsf();
|
119 |
+
$tsf->_deprecated_function( 'tsf()->get_html_output()', '4.2.0' );
|
|
|
120 |
|
121 |
$robots = $tsf->robots();
|
122 |
|
|
|
|
|
|
|
123 |
/**
|
124 |
* @since 2.6.0
|
125 |
* @param string $before The content before the SEO output.
|
195 |
*/
|
196 |
$after = (string) \apply_filters( 'the_seo_framework_pro', '' );
|
197 |
|
|
|
|
|
|
|
198 |
return "{$robots}{$before}{$before_legacy}{$output}{$after_legacy}{$after}";
|
199 |
}
|
200 |
|
212 |
* @since 4.0.0
|
213 |
* @since 4.1.0 Now uses the new taxonomy robots settings.
|
214 |
* @since 4.1.4 Soft deprecated. Use 'robots_meta' instead.
|
215 |
+
* @since 4.2.0 1. Hard deprecation.
|
216 |
+
* 2. Now supports the `$args['pta']` index. (inferred)
|
217 |
* @deprecated
|
218 |
*
|
219 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
220 |
* @param int <bit> $ignore The ignore level. {
|
221 |
* 0 = 0b00: Ignore nothing.
|
222 |
* 1 = 0b01: Ignore protection. (\The_SEO_Framework\ROBOTS_IGNORE_PROTECTION)
|
226 |
* @return bool Whether noindex is set or not
|
227 |
*/
|
228 |
public function is_robots_meta_noindex_set_by_args( $args, $ignore = 0b00 ) {
|
229 |
+
$tsf = \tsf();
|
230 |
+
$tsf->_deprecated_function( 'tsf()->is_robots_meta_noindex_set_by_args()', '4.2.0', 'tsf()->generate_robots_meta()' );
|
231 |
$meta = $tsf->generate_robots_meta( $args, null, $ignore );
|
232 |
return isset( $meta['noindex'] ) && 'noindex' === $meta['noindex'];
|
233 |
}
|
239 |
* @since 2.2.4 Added robots SEO settings check.
|
240 |
* @since 2.2.8 Added check for empty archives.
|
241 |
* @since 2.8.0 Added check for protected/private posts.
|
242 |
+
* @since 3.0.0 1. Removed noodp.
|
243 |
+
* 2. Improved efficiency by grouping if statements.
|
244 |
+
* @since 3.1.0 1. Simplified statements, often (not always) speeding things up.
|
245 |
+
* 2. Now checks for wc_shop and blog types for pagination.
|
246 |
+
* 3. Removed noydir.
|
247 |
+
* @since 4.0.0 1. Now tests for qubit metadata.
|
248 |
+
* 2. Added custom query support.
|
249 |
+
* 3. Added two parameters.
|
250 |
+
* @since 4.0.2 1. Added new copyright directive tags.
|
251 |
+
* 2. Now strictly parses the validity of robots directives via a boolean check.
|
252 |
+
* @since 4.0.3 1. Changed `max_snippet_length` to `max_snippet`
|
253 |
+
* 2. Changed the copyright directive's spacer from `=` to `:`.
|
254 |
+
* @since 4.0.5 1. Removed copyright directive bug workaround. <https://kb.theseoframework.com/kb/why-is-max-image-preview-none-purged/>
|
255 |
+
* 2. Now sets noindex and nofollow when queries are exploited (requires option enabled).
|
256 |
* @since 4.1.4 Deprecated silently. Use generate_robots_meta() instead.
|
257 |
+
* @since 4.2.0 1. Hard deprecation.
|
258 |
+
* 2. Now supports the `$args['pta']` index. (inferred)
|
259 |
+
* @deprecated
|
260 |
*
|
261 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
262 |
* @param int <bit> $ignore The ignore level. {
|
263 |
* 0 = 0b00: Ignore nothing.
|
264 |
* 1 = 0b01: Ignore protection. (\The_SEO_Framework\ROBOTS_IGNORE_PROTECTION)
|
270 |
* }
|
271 |
*/
|
272 |
public function robots_meta( $args = null, $ignore = 0b00 ) {
|
273 |
+
$tsf = \tsf();
|
274 |
+
$tsf->_deprecated_function( 'tsf()->robots_meta()', '4.2.0', 'tsf()->generate_robots_meta()' );
|
275 |
return $tsf->generate_robots_meta( $args, null, $ignore );
|
276 |
}
|
277 |
|
284 |
* @since 2.9.2 Now also checks for permalinks.
|
285 |
* @since 2.9.3 Now also checks for sitemap_robots option.
|
286 |
* @since 3.1.0 Removed Jetpack's sitemap check -- it's no longer valid.
|
287 |
+
* @since 4.0.0 1. Now uses has_robots_txt()
|
288 |
+
* 2. Now uses the get_robots_txt_url() to determine validity.
|
|
|
289 |
* @since 4.1.4 Soft deprecated.
|
290 |
* @since 4.2.0 Hard deprecation.
|
291 |
* @deprecated
|
295 |
*/
|
296 |
public function can_do_sitemap_robots( $check_option = true ) {
|
297 |
|
298 |
+
$tsf = \tsf();
|
299 |
+
$tsf->_deprecated_function( 'tsf()->can_do_sitemap_robots()', '4.2.0' );
|
|
|
300 |
|
301 |
if ( $check_option ) {
|
302 |
if ( ! $tsf->get_option( 'sitemaps_output' )
|
332 |
* @param bool $use_tabs Whether to output tabs, only works when $tabs count is greater than 1.
|
333 |
*/
|
334 |
public function nav_tab_wrapper( $id, $tabs = [], $depr = null, $use_tabs = true ) {
|
335 |
+
\tsf()->_deprecated_function( 'tsf()->nav_tab_wrapper()', '4.2.0', '\The_SEO_Framework\Bridges\SeoSettings::_nav_tab_wrapper' );
|
336 |
\The_SEO_Framework\Bridges\SeoSettings::_nav_tab_wrapper( $id, $tabs, $use_tabs );
|
337 |
}
|
338 |
|
359 |
* @param bool $use_tabs Whether to output tabs, only works when $tabs count is greater than 1.
|
360 |
*/
|
361 |
public function inpost_flex_nav_tab_wrapper( $id, $tabs = [], $_depr = null, $use_tabs = true ) {
|
362 |
+
\tsf()->_deprecated_function( 'tsf()->inpost_flex_nav_tab_wrapper()', '4.2.0', '\The_SEO_Framework\Bridges\PostSettings::_flex_nav_tab_wrapper' );
|
363 |
\The_SEO_Framework\Bridges\PostSettings::_flex_nav_tab_wrapper( $id, $tabs, $use_tabs );
|
364 |
}
|
365 |
|
379 |
* @return string The image uploader button.
|
380 |
*/
|
381 |
public function get_social_image_uploader_form( $input_id ) {
|
382 |
+
\tsf()->_deprecated_function( 'tsf()->get_social_image_uploader_form()', '4.2.0', 'The_SEO_Framework\Interpreters\Form::get_image_uploader_form()' );
|
383 |
return \The_SEO_Framework\Interpreters\Form::get_image_uploader_form( [ 'id' => $input_id ] );
|
384 |
}
|
385 |
|
398 |
* @return string The image uploader button.
|
399 |
*/
|
400 |
public function get_logo_uploader_form( $input_id ) {
|
401 |
+
\tsf()->_deprecated_function( 'tsf()->get_logo_uploader_form()', '4.2.0', 'The_SEO_Framework\Interpreters\Form::get_image_uploader_form()' );
|
402 |
return \The_SEO_Framework\Interpreters\Form::get_image_uploader_form( [
|
403 |
'id' => $input_id,
|
404 |
'data' => [
|
424 |
* @ignore Unused. The relying methods were yeeted off in 4.0.0.
|
425 |
* "We no longer automatically resize images when they’re deemed too large."
|
426 |
* @since 4.1.4 Deprecated silently. Marked for quick deletion.
|
427 |
+
* @since 4.2.0 Hard deprecation.
|
428 |
+
* @deprecated
|
429 |
*
|
430 |
* @param int $i The dimension to resize.
|
431 |
* @param int $r1 The dimension that determines the ratio.
|
433 |
* @return int The proportional dimension, rounded.
|
434 |
*/
|
435 |
public function proportionate_dimensions( $i, $r1, $r2 ) {
|
436 |
+
$tsf = \tsf();
|
437 |
+
$tsf->_deprecated_function( 'tsf()->proportionate_dimensions()', '4.2.0' );
|
438 |
return round( $i / ( $r1 / $r2 ) );
|
439 |
}
|
440 |
|
449 |
* @return string The escaped SEO Settings page URL.
|
450 |
*/
|
451 |
public function seo_settings_page_url() {
|
452 |
+
$tsf = \tsf();
|
453 |
+
$tsf->_deprecated_function( 'tsf()->seo_settings_page_url()', '4.2.0', 'tsf()->get_seo_settings_page_url()' );
|
454 |
return $tsf->get_seo_settings_page_url();
|
455 |
}
|
456 |
|
460 |
* @since 3.0.0
|
461 |
* @since 4.1.4 Deprecated silently. Use `get_user_meta_defaults()` instead.
|
462 |
* @since 4.2.0 Hard deprecation.
|
463 |
+
* @deprecated
|
464 |
*
|
465 |
* @return array The default user meta index and values.
|
466 |
*/
|
467 |
public function get_default_user_data() {
|
468 |
+
$tsf = \tsf();
|
469 |
+
$tsf->_deprecated_function( 'tsf()->get_default_user_data()', '4.2.0', 'tsf()->get_user_meta_defaults()' );
|
470 |
return $tsf->get_user_meta_defaults();
|
471 |
}
|
472 |
|
483 |
* 3. Added not-found cache.
|
484 |
* @since 4.1.4 Deprecated silently. Use `get_user_meta()` instead.
|
485 |
* @since 4.2.0 Hard deprecation.
|
486 |
+
* @deprecated
|
487 |
*
|
488 |
* @param int $user_id The user ID. When empty, it will try to fetch the current user.
|
489 |
* @param string $option The option name.
|
491 |
* @return mixed The metadata value.
|
492 |
*/
|
493 |
public function get_user_option( $user_id = 0, $option = '', $default = null ) {
|
494 |
+
$tsf = \tsf();
|
495 |
+
$tsf->_deprecated_function( 'tsf()->get_user_option()', '4.2.0', 'tsf()->get_user_meta_item()' );
|
496 |
return $tsf->get_user_meta_item( $user_id ?: $tsf->get_user_id(), $option ) ?: $default;
|
497 |
}
|
498 |
|
502 |
* @since 3.0.0
|
503 |
* @since 4.1.4 Silently deprecated. use `get_current_post_author_id()` instead.
|
504 |
* @since 4.2.0 Hard deprecation.
|
505 |
+
* @deprecated
|
506 |
*
|
507 |
* @param int $author_id The author ID. When empty, it will return $default.
|
508 |
* @param string $option The option name. When empty, it will return $default.
|
510 |
* @return mixed The metadata value
|
511 |
*/
|
512 |
public function get_author_option( $author_id, $option, $default = null ) {
|
513 |
+
$tsf = \tsf();
|
514 |
+
$tsf->_deprecated_function( 'tsf()->get_author_option()', '4.2.0', 'tsf()->get_current_post_author_id()' );
|
515 |
return $tsf->get_user_meta_item( $option, $author_id ?: $tsf->get_current_post_author_id() ) ?: $default;
|
516 |
}
|
517 |
|
521 |
* @since 3.0.0
|
522 |
* @since 4.1.4 Silently deprecated. Use `get_current_post_author_meta_item()` instead.
|
523 |
* @since 4.2.0 Hard deprecation.
|
524 |
+
* @deprecated
|
525 |
*
|
526 |
* @param string $option The option name.
|
527 |
* @param mixed $default The default value to return when the data doesn't exist.
|
528 |
* @return mixed The metadata value
|
529 |
*/
|
530 |
public function get_current_author_option( $option, $default = null ) {
|
531 |
+
$tsf = \tsf();
|
532 |
+
$tsf->_deprecated_function( 'tsf()->get_current_author_option()', '4.2.0', 'tsf()->get_current_post_author_meta_item()' );
|
533 |
return $tsf->get_current_post_author_meta_item( $option ) ?: $default;
|
534 |
}
|
535 |
|
550 |
*/
|
551 |
public function is_wc_shop( $post = null ) {
|
552 |
|
553 |
+
\tsf()->_deprecated_function( 'tsf()->is_wc_shop()', '4.2.0', 'tsf()->is_shop()' );
|
554 |
|
555 |
if ( isset( $post ) ) {
|
556 |
$post = \get_post( $post );
|
572 |
* Determines if the page is the WooCommerce plugin Product page.
|
573 |
*
|
574 |
* @since 2.5.2
|
575 |
+
* @since 4.0.0 1. Added admin support.
|
576 |
+
* 2. Added parameter for the Post ID or post to test.
|
577 |
* @since 4.0.5 Soft deprecated.
|
578 |
* @since 4.1.4 1. Another silent deprecation. Use `is_product()` instead.
|
579 |
* 2. Removed output memoization.
|
586 |
*/
|
587 |
public function is_wc_product( $post = 0 ) {
|
588 |
|
589 |
+
$tsf = \tsf();
|
590 |
+
$tsf->_deprecated_function( 'tsf()->is_wc_product()', '4.2.0', 'tsf()->is_product()' );
|
591 |
|
592 |
if ( \is_admin() )
|
593 |
return $tsf->is_wc_product_admin();
|
616 |
* @return bool
|
617 |
*/
|
618 |
public function is_wc_product_admin() {
|
619 |
+
$tsf = \tsf();
|
620 |
+
$tsf->_deprecated_function( 'tsf()->is_wc_product_admin()', '4.2.0', 'tsf()->is_product_admin()' );
|
621 |
// Checks for "is_singular_admin()" because the post type is non-hierarchical.
|
622 |
return $tsf->is_singular_admin() && 'product' === $tsf->get_admin_post_type();
|
623 |
}
|
628 |
* @since 2.7.0
|
629 |
* @since 2.8.0 New users now get a new array assigned.
|
630 |
* @since 4.1.4 Deprecated silently. Use `update_single_user_meta_item()` instead.
|
631 |
+
* @since 4.2.0 Hard deprecation.
|
632 |
+
* @deprecated
|
633 |
*
|
634 |
* @param int $user_id The user ID.
|
635 |
* @param string $option The user's SEO metadata option.
|
638 |
*/
|
639 |
public function update_user_option( $user_id = 0, $option = '', $value = '' ) {
|
640 |
|
641 |
+
$tsf = \tsf();
|
642 |
+
$tsf->_deprecated_function( 'tsf()->update_user_option()', '4.2.0', 'tsf()->update_single_user_meta_item()' );
|
643 |
|
644 |
if ( ! $option )
|
645 |
return false;
|
670 |
*
|
671 |
* @since 2.2.2
|
672 |
* @since 4.1.4 Deprecated silently.
|
673 |
+
* @since 4.2.0 Hard deprecation.
|
674 |
* @deprecated
|
675 |
*
|
676 |
* @param string $name Field name base
|
677 |
* @return string Full field name
|
678 |
*/
|
679 |
public function get_field_name( $name ) {
|
680 |
+
\tsf()->_deprecated_function( 'tsf()->get_field_name()', '4.2.0' );
|
681 |
+
return \The_SEO_Framework\Interpreters\Settings_Input::get_field_name( $name );
|
682 |
}
|
683 |
|
684 |
/**
|
686 |
*
|
687 |
* @since 2.2.2
|
688 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
689 |
+
* @since 4.2.0 Hard deprecation.
|
690 |
+
* @deprecated
|
691 |
* @uses $this->get_field_name() Construct name attributes for use in form fields.
|
692 |
*
|
693 |
* @param string $name Field name base
|
694 |
*/
|
695 |
public function field_name( $name ) {
|
696 |
+
\tsf()->_deprecated_function( 'tsf()->field_name()', '4.2.0' );
|
697 |
+
return \The_SEO_Framework\Interpreters\Settings_Input::field_name( $name );
|
698 |
}
|
699 |
|
700 |
/**
|
702 |
*
|
703 |
* @since 2.2.2
|
704 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
705 |
+
* @since 4.2.0 Hard deprecation.
|
706 |
+
* @deprecated
|
707 |
*
|
708 |
* @param string $id Field id base
|
709 |
* @return string Full field id
|
710 |
*/
|
711 |
public function get_field_id( $id ) {
|
712 |
+
\tsf()->_deprecated_function( 'tsf()->get_field_id()', '4.2.0' );
|
713 |
+
return \The_SEO_Framework\Interpreters\Settings_Input::get_field_id( $id );
|
714 |
}
|
715 |
|
716 |
/**
|
718 |
*
|
719 |
* @since 2.2.2
|
720 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
721 |
+
* @since 4.2.0 Hard deprecation.
|
722 |
+
* @deprecated
|
723 |
* @uses $this->get_field_id() Constructs id attributes for use in form fields.
|
724 |
*
|
725 |
* @param string $id Field id base.
|
727 |
* @return string Full field id
|
728 |
*/
|
729 |
public function field_id( $id, $echo = true ) {
|
730 |
+
\tsf()->_deprecated_function( 'tsf()->field_id()', '4.2.0' );
|
731 |
+
if ( $echo ) {
|
732 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- this escapes.
|
733 |
+
echo \The_SEO_Framework\Interpreters\Settings_Input::field_id( $id );
|
734 |
+
} else {
|
735 |
+
return \The_SEO_Framework\Interpreters\Settings_Input::field_id( $id );
|
736 |
+
}
|
737 |
}
|
738 |
|
739 |
/**
|
742 |
*
|
743 |
* @since 2.0.0
|
744 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
745 |
+
* @since 4.2.0 Hard deprecation.
|
746 |
+
* @deprecated
|
747 |
*
|
748 |
* @param string $content Content to be wrapped in code tags.
|
749 |
* @return string Content wrapped in code tags.
|
750 |
*/
|
751 |
public function code_wrap( $content ) {
|
752 |
+
\tsf()->_deprecated_function( 'tsf()->code_wrap()', '4.2.0' );
|
753 |
return \The_SEO_Framework\Interpreters\HTML::code_wrap( $content );
|
754 |
}
|
755 |
|
759 |
*
|
760 |
* @since 2.2.2
|
761 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
762 |
+
* @since 4.2.0 Hard deprecation.
|
763 |
+
* @deprecated
|
764 |
*
|
765 |
* @param string $content Content to be wrapped in code tags.
|
766 |
* @return string Content wrapped in code tags.
|
767 |
*/
|
768 |
public function code_wrap_noesc( $content ) {
|
769 |
+
\tsf()->_deprecated_function( 'tsf()->code_wrap_noesc()', '4.2.0' );
|
770 |
return \The_SEO_Framework\Interpreters\HTML::code_wrap_noesc( $content );
|
771 |
}
|
772 |
|
776 |
*
|
777 |
* @since 2.7.0
|
778 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
779 |
+
* @since 4.2.0 Hard deprecation.
|
780 |
+
* @deprecated
|
781 |
*
|
782 |
* @param string $content Content to be wrapped in the description wrap.
|
783 |
* @param bool $block Whether to wrap the content in <p> tags.
|
784 |
*/
|
785 |
public function description( $content, $block = true ) {
|
786 |
+
\tsf()->_deprecated_function( 'tsf()->description()', '4.2.0' );
|
787 |
return \The_SEO_Framework\Interpreters\HTML::description( $content, $block );
|
788 |
}
|
789 |
|
792 |
*
|
793 |
* @since 2.7.0
|
794 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
795 |
+
* @since 4.2.0 Hard deprecation.
|
796 |
+
* @deprecated
|
797 |
*
|
798 |
* @param string $content Content to be wrapped in the description wrap. Expected to be escaped.
|
799 |
* @param bool $block Whether to wrap the content in <p> tags.
|
800 |
*/
|
801 |
public function description_noesc( $content, $block = true ) {
|
802 |
+
\tsf()->_deprecated_function( 'tsf()->description_noesc()', '4.2.0' );
|
803 |
return \The_SEO_Framework\Interpreters\HTML::description_noesc( $content, $block );
|
804 |
}
|
805 |
|
809 |
*
|
810 |
* @since 3.1.0
|
811 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
812 |
+
* @since 4.2.0 Hard deprecation.
|
813 |
+
* @deprecated
|
814 |
*
|
815 |
* @param string $content Content to be wrapped in the attention wrap.
|
816 |
* @param bool $block Whether to wrap the content in <p> tags.
|
817 |
*/
|
818 |
public function attention( $content, $block = true ) {
|
819 |
+
\tsf()->_deprecated_function( 'tsf()->attention()', '4.2.0' );
|
820 |
return \The_SEO_Framework\Interpreters\HTML::attention( $content, $block );
|
821 |
}
|
822 |
|
825 |
*
|
826 |
* @since 3.1.0
|
827 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
828 |
+
* @since 4.2.0 Hard deprecation.
|
829 |
+
* @deprecated
|
830 |
*
|
831 |
* @param string $content Content to be wrapped in the attention wrap. Expected to be escaped.
|
832 |
* @param bool $block Whether to wrap the content in <p> tags.
|
833 |
*/
|
834 |
public function attention_noesc( $content, $block = true ) {
|
835 |
+
\tsf()->_deprecated_function( 'tsf()->attention_noesc()', '4.2.0' );
|
836 |
return \The_SEO_Framework\Interpreters\HTML::attention_noesc( $content, $block );
|
837 |
}
|
838 |
|
842 |
*
|
843 |
* @since 3.1.0
|
844 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
845 |
+
* @since 4.2.0 Hard deprecation.
|
846 |
+
* @deprecated
|
847 |
*
|
848 |
* @param string $content Content to be wrapped in the wrap. Expected to be escaped.
|
849 |
* @param bool $block Whether to wrap the content in <p> tags.
|
850 |
*/
|
851 |
public function attention_description( $content, $block = true ) {
|
852 |
+
\tsf()->_deprecated_function( 'tsf()->attention_description()', '4.2.0' );
|
853 |
return \The_SEO_Framework\Interpreters\HTML::attention_description( $content, $block );
|
854 |
}
|
855 |
|
858 |
*
|
859 |
* @since 3.1.0
|
860 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
861 |
+
* @since 4.2.0 Hard deprecation.
|
862 |
+
* @deprecated
|
863 |
*
|
864 |
* @param string $content Content to be wrapped in the wrap. Expected to be escaped.
|
865 |
* @param bool $block Whether to wrap the content in <p> tags.
|
866 |
*/
|
867 |
public function attention_description_noesc( $content, $block = true ) {
|
868 |
+
\tsf()->_deprecated_function( 'tsf()->attention_description_noesc()', '4.2.0' );
|
869 |
return \The_SEO_Framework\Interpreters\HTML::attention_description_noesc( $content, $block );
|
870 |
}
|
871 |
|
876 |
*
|
877 |
* @since 2.6.0
|
878 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
879 |
+
* @since 4.2.0 Hard deprecation.
|
880 |
+
* @deprecated
|
881 |
*
|
882 |
* @param string $input The input to wrap. Should already be escaped.
|
883 |
* @param bool $echo Whether to escape echo or just return.
|
884 |
* @return string|void Wrapped $input.
|
885 |
*/
|
886 |
public function wrap_fields( $input = '', $echo = false ) {
|
887 |
+
\tsf()->_deprecated_function( 'tsf()->wrap_fields()', '4.2.0' );
|
888 |
return \The_SEO_Framework\Interpreters\HTML::wrap_fields( $input, $echo );
|
889 |
}
|
890 |
|
895 |
* @since 3.0.0 Links are now no longer followed, referred or bound to opener.
|
896 |
* @since 4.0.0 Now adds a tabindex to the span tag, so you can focus it using keyboard navigation.
|
897 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
898 |
+
* @since 4.2.0 Hard deprecation.
|
899 |
+
* @deprecated
|
900 |
*
|
901 |
* @param string $description The descriptive on-hover title.
|
902 |
* @param string $link The non-escaped link.
|
904 |
* @return string HTML checkbox output if $echo is false.
|
905 |
*/
|
906 |
public function make_info( $description = '', $link = '', $echo = true ) {
|
907 |
+
\tsf()->_deprecated_function( 'tsf()->make_info()', '4.2.0', '\The_SEO_Framework\Interpreters\HTML::make_info()' );
|
908 |
return \The_SEO_Framework\Interpreters\HTML::make_info( $description, $link, $echo );
|
909 |
}
|
910 |
|
914 |
* @since 4.0.0
|
915 |
* @since 4.1.0 No longer adds an extra space in front of the return value when no data is generated.
|
916 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
917 |
+
* @since 4.2.0 Hard deprecation.
|
918 |
* @internal
|
919 |
+
* @deprecated
|
920 |
*
|
921 |
* @param array $data : {
|
922 |
* string $k => mixed $v
|
923 |
* }
|
924 |
* @return string The HTML data attributes, with added space to the start.
|
925 |
*/
|
926 |
+
public function make_data_attributes( $data ) {
|
927 |
+
\tsf()->_deprecated_function( 'tsf()->make_data_attributes()', '4.2.0' );
|
928 |
return \The_SEO_Framework\Interpreters\HTML::make_data_attributes( $data );
|
929 |
}
|
930 |
|
935 |
* @since 2.7.0 Added escape parameter. Defaults to true.
|
936 |
* @since 3.0.3 Added $disabled parameter. Defaults to false.
|
937 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
938 |
+
* @since 4.2.0 Hard deprecation.
|
939 |
+
* @deprecated
|
940 |
*
|
941 |
* @param string $field_id The option ID. Must be within the Autodescription settings.
|
942 |
* @param string $label The checkbox description label.
|
946 |
* @return string HTML checkbox output.
|
947 |
*/
|
948 |
public function make_checkbox( $field_id = '', $label = '', $description = '', $escape = true, $disabled = false ) {
|
949 |
+
\tsf()->_deprecated_function( 'tsf()->make_checkbox()', '4.2.0' );
|
950 |
+
return \The_SEO_Framework\Interpreters\Settings_Input::make_checkbox( [
|
951 |
'id' => $field_id,
|
952 |
'index' => '',
|
953 |
'label' => $label,
|
963 |
*
|
964 |
* @since 4.0.0
|
965 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
966 |
+
* @since 4.2.0 Hard deprecation.
|
967 |
+
* @deprecated
|
968 |
*
|
969 |
* @param array $args : {
|
970 |
* string $id The select field ID.
|
979 |
* }
|
980 |
* @return string The option field.
|
981 |
*/
|
982 |
+
public function make_single_select_form( $args ) {
|
983 |
+
\tsf()->_deprecated_function( 'tsf()->make_single_select_form()', '4.2.0', 'The_SEO_Framework\Interpreters\Form::make_single_select_form()' );
|
984 |
return \The_SEO_Framework\Interpreters\Form::make_single_select_form( $args );
|
985 |
}
|
986 |
|
993 |
* @since 2.2.5
|
994 |
* @since 3.1.0 Deprecated second parameter.
|
995 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
996 |
+
* @since 4.2.0 1. Hard deprecation.
|
997 |
+
* 2. Now always returns an empty string.
|
998 |
+
* @deprecated
|
999 |
*
|
1000 |
* @param string $key The option name which returns boolean.
|
1001 |
* @param string $depr Deprecated
|
1003 |
* @param bool $echo Whether to echo or return the output.
|
1004 |
* @return string Empty on echo or the class name with an optional wrapper.
|
1005 |
*/
|
1006 |
+
public function is_default_checked( $key, $depr = '', $wrap = true, $echo = true ) { // phpcs:ignore, VariableAnalysis.CodeAnalysis
|
1007 |
+
\tsf()->_deprecated_function( 'tsf()->is_default_checked()', '4.2.0' );
|
1008 |
+
return '';
|
1009 |
}
|
1010 |
+
|
1011 |
/**
|
1012 |
* Returns the HTML class wrap for warning Checkbox options.
|
1013 |
*
|
1014 |
* @since 2.3.4
|
1015 |
* @since 3.1.0 Deprecated second parameter.
|
1016 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1017 |
+
* @since 4.2.0 10 Hard deprecation.
|
1018 |
+
* 2. Now always returns an empty string.
|
1019 |
+
* @deprecated
|
1020 |
*
|
1021 |
* @param string $key The option name which returns boolean.
|
1022 |
* @param string $deprecated Deprecated.
|
1024 |
* @param bool $echo Whether to echo or return the output.
|
1025 |
* @return string Empty on echo or the class name with an optional wrapper.
|
1026 |
*/
|
1027 |
+
public function is_warning_checked( $key, $deprecated = '', $wrap = true, $echo = true ) { // phpcs:ignore, VariableAnalysis.CodeAnalysis
|
1028 |
+
\tsf()->_deprecated_function( 'tsf()->is_warning_checked()', '4.2.0' );
|
1029 |
+
return '';
|
1030 |
}
|
1031 |
+
|
1032 |
/**
|
1033 |
* Returns the HTML class wrap for warning/default Checkbox options.
|
1034 |
*
|
1035 |
* @since 2.6.0
|
1036 |
* @since 3.1.0 Added the $wrap parameter.
|
1037 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1038 |
+
* @since 4.2.0 1. Hard deprecation.
|
1039 |
+
* 2. Now always returns false.
|
1040 |
+
* @deprecated
|
1041 |
*
|
1042 |
* @param string $key The option name which returns boolean.
|
1043 |
* @param bool $wrap Whether to wrap the class name in `class="%s"`
|
1044 |
*/
|
1045 |
+
public function get_is_conditional_checked( $key, $wrap = true ) { // phpcs:ignore, VariableAnalysis.CodeAnalysis
|
1046 |
+
\tsf()->_deprecated_function( 'tsf()->get_is_conditional_checked()', '4.2.0' );
|
1047 |
+
return false;
|
1048 |
}
|
1049 |
|
1050 |
/**
|
1053 |
* @since 2.3.4
|
1054 |
* @since 3.1.0 Deprecated second parameter.
|
1055 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1056 |
+
* @since 4.2.0 1. Hard deprecation.
|
1057 |
+
* 2. Now always returns false.
|
1058 |
+
* @deprecated
|
1059 |
*
|
1060 |
* @param string $key The option name which returns boolean.
|
1061 |
* @param string $deprecated Deprecated. Used to be the settings field.
|
1063 |
* @param bool $echo Whether to echo or return the output.
|
1064 |
* @return string Empty on echo or the class name with an optional wrapper.
|
1065 |
*/
|
1066 |
+
public function is_conditional_checked( $key, $deprecated = '', $wrap = true, $echo = true ) { // phpcs:ignore, VariableAnalysis.CodeAnalysis
|
1067 |
+
\tsf()->_deprecated_function( 'tsf()->is_conditional_checked()', '4.2.0' );
|
1068 |
+
return false;
|
1069 |
}
|
1070 |
|
1071 |
/**
|
1072 |
* Outputs character counter wrap for both JavaScript and no-Javascript.
|
1073 |
*
|
1074 |
* @since 3.0.0
|
1075 |
+
* @since 3.1.0 1. Added an "what if you click" onhover-title.
|
1076 |
+
* 2. Removed second parameter's usage. For passing the expected string.
|
1077 |
+
* 3. The whole output is now hidden from no-js.
|
1078 |
* @since 4.1.0 No longer marks up the counter with the `description` HTML class.
|
1079 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1080 |
+
* @since 4.2.0 Hard deprecation.
|
1081 |
+
* @deprecated
|
1082 |
*
|
1083 |
* @param string $for The input ID it's for.
|
1084 |
* @param string $depr The initial value for no-JS. Deprecated.
|
1085 |
* @param bool $display Whether to display the counter. (options page gimmick)
|
1086 |
*/
|
1087 |
public function output_character_counter_wrap( $for, $depr = '', $display = true ) {
|
1088 |
+
\tsf()->_deprecated_function( 'tsf()->output_character_counter_wrap()', '4.2.0' );
|
1089 |
return \The_SEO_Framework\Interpreters\Form::output_character_counter_wrap( $for, $display );
|
1090 |
}
|
1091 |
|
1094 |
*
|
1095 |
* @since 3.0.0
|
1096 |
* @since 4.1.4 Deprecated silently. Alternative marked for deletion.
|
1097 |
+
* @since 4.2.0 Hard deprecation.
|
1098 |
+
* @deprecated
|
1099 |
*
|
1100 |
* @param string $for The input ID it's for.
|
1101 |
* @param string $type Whether it's a 'title' or 'description' counter.
|
1102 |
* @param bool $display Whether to display the counter. (options page gimmick)
|
1103 |
*/
|
1104 |
public function output_pixel_counter_wrap( $for, $type, $display = true ) {
|
1105 |
+
\tsf()->_deprecated_function( 'tsf()->output_pixel_counter_wrap()', '4.2.0' );
|
1106 |
return \The_SEO_Framework\Interpreters\Form::output_pixel_counter_wrap( $for, $type, $display );
|
1107 |
}
|
1108 |
+
|
1109 |
+
/**
|
1110 |
+
* Determines if WP is above or below a version
|
1111 |
+
*
|
1112 |
+
* @since 2.2.1
|
1113 |
+
* @since 2.3.8 Added caching
|
1114 |
+
* @since 2.8.0 No longer overwrites global $wp_version
|
1115 |
+
* @since 3.1.0 1. No longer caches.
|
1116 |
+
* 2. Removed redundant parameter checks.
|
1117 |
+
* 3. Now supports x.yy.zz WordPress versions.
|
1118 |
+
* @since 4.2.0 Deprecated. Use your own method instead.
|
1119 |
+
*
|
1120 |
+
* @param string $version the three part version to compare to WordPress
|
1121 |
+
* @param string $compare the comparing operator, default "$version >= Current WP Version"
|
1122 |
+
* @return bool True if the WordPress version comparison passes.
|
1123 |
+
*/
|
1124 |
+
public function wp_version( $version = '4.3.0', $compare = '>=' ) {
|
1125 |
+
|
1126 |
+
\tsf()->_deprecated_function( 'tsf()->wp_version()', '4.2.0' );
|
1127 |
+
|
1128 |
+
$wp_version = $GLOBALS['wp_version'];
|
1129 |
+
|
1130 |
+
/**
|
1131 |
+
* Add a .0 if WP outputs something like 4.3 instead of 4.3.0
|
1132 |
+
* Does consider 4.xx, which will become 4.xx.0.
|
1133 |
+
* Does not consider 4.xx-dev, which will become 4.xx-dev.0. Oh well.
|
1134 |
+
*/
|
1135 |
+
if ( 1 === substr_count( $wp_version, '.' ) )
|
1136 |
+
$wp_version .= '.0';
|
1137 |
+
|
1138 |
+
return (bool) version_compare( $wp_version, $version, $compare );
|
1139 |
+
}
|
1140 |
+
|
1141 |
+
/**
|
1142 |
+
* Checks for current theme support.
|
1143 |
+
*
|
1144 |
+
* Maintains detection cache, array and strings are mixed through foreach loops.
|
1145 |
+
*
|
1146 |
+
* @since 2.2.5
|
1147 |
+
* @since 3.1.0 Removed caching
|
1148 |
+
* @since 4.2.0 Deprecated. Use WP core `current_theme_supports()` instead.
|
1149 |
+
*
|
1150 |
+
* @param string|array required $features The features to check for.
|
1151 |
+
* @return bool theme support.
|
1152 |
+
*/
|
1153 |
+
public function detect_theme_support( $features ) {
|
1154 |
+
|
1155 |
+
\tsf()->_deprecated_function( 'tsf()->detect_theme_support()', '4.2.0', 'current_theme_supports()' );
|
1156 |
+
|
1157 |
+
foreach ( (array) $features as $feature ) {
|
1158 |
+
if ( \current_theme_supports( $feature ) ) {
|
1159 |
+
return true;
|
1160 |
+
}
|
1161 |
+
continue;
|
1162 |
+
}
|
1163 |
+
|
1164 |
+
return false;
|
1165 |
+
}
|
1166 |
+
|
1167 |
+
/**
|
1168 |
+
* Detects presence of a page builder.
|
1169 |
+
* Memoizes the return value.
|
1170 |
+
*
|
1171 |
+
* Detects the following builders:
|
1172 |
+
* - Elementor by Elementor LTD
|
1173 |
+
* - Divi Builder by Elegant Themes
|
1174 |
+
* - Visual Composer by WPBakery
|
1175 |
+
* - Page Builder by SiteOrigin
|
1176 |
+
* - Beaver Builder by Fastline Media
|
1177 |
+
*
|
1178 |
+
* @since 4.0.0
|
1179 |
+
* @since 4.0.6 The output is now filterable.
|
1180 |
+
* @since 4.2.0 Deprecated
|
1181 |
+
* @ignore unused.
|
1182 |
+
* @deprecated
|
1183 |
+
*
|
1184 |
+
* @return bool
|
1185 |
+
*/
|
1186 |
+
public function detect_page_builder() {
|
1187 |
+
|
1188 |
+
$tsf = \tsf();
|
1189 |
+
$tsf->_deprecated_function( 'tsf()->detect_page_builder()', '4.2.0' );
|
1190 |
+
|
1191 |
+
static $detected = null;
|
1192 |
+
|
1193 |
+
if ( isset( $detected ) ) return $detected;
|
1194 |
+
|
1195 |
+
/**
|
1196 |
+
* @since 4.0.6
|
1197 |
+
* @param bool $detected Whether an active page builder is detected.
|
1198 |
+
* @NOTE not to be confused with `the_seo_framework_detect_page_builder`, which tests
|
1199 |
+
* the page builder status for each post individually.
|
1200 |
+
*/
|
1201 |
+
return $detected = (bool) \apply_filters(
|
1202 |
+
'the_seo_framework_page_builder_active',
|
1203 |
+
$tsf->detect_plugin( [
|
1204 |
+
'constants' => [
|
1205 |
+
'ELEMENTOR_VERSION',
|
1206 |
+
'ET_BUILDER_VERSION',
|
1207 |
+
'WPB_VC_VERSION',
|
1208 |
+
'SITEORIGIN_PANELS_VERSION',
|
1209 |
+
'FL_BUILDER_VERSION',
|
1210 |
+
],
|
1211 |
+
] )
|
1212 |
+
);
|
1213 |
+
}
|
1214 |
+
|
1215 |
+
/**
|
1216 |
+
* Determines whether the post has a page builder attached to it.
|
1217 |
+
* Doesn't use plugin detection features as some builders might be incorporated within themes.
|
1218 |
+
*
|
1219 |
+
* Detects the following builders:
|
1220 |
+
* - Elementor by Elementor LTD
|
1221 |
+
* - Divi Builder by Elegant Themes
|
1222 |
+
* - Visual Composer by WPBakery
|
1223 |
+
* - Page Builder by SiteOrigin
|
1224 |
+
* - Beaver Builder by Fastline Media
|
1225 |
+
*
|
1226 |
+
* @since 2.6.6
|
1227 |
+
* @since 3.1.0 Added Elementor detection
|
1228 |
+
* @since 4.0.0 Now detects page builders before looping over the meta.
|
1229 |
+
* @since 4.2.0 Deprecated.
|
1230 |
+
* @TODO -> We may use this data for they have FSE builders. We may want to interface with those, some day.
|
1231 |
+
* -> We'd want to return the TYPE of pagebuilder used, if anything. Just deprecate this.
|
1232 |
+
* @ignore unused.
|
1233 |
+
* @deprecated
|
1234 |
+
*
|
1235 |
+
* @param int $post_id The post ID to check.
|
1236 |
+
* @return bool
|
1237 |
+
*/
|
1238 |
+
public function uses_page_builder( $post_id ) {
|
1239 |
+
|
1240 |
+
$tsf = \tsf();
|
1241 |
+
$tsf->_deprecated_function( 'tsf()->uses_page_builder()', '4.2.0' );
|
1242 |
+
|
1243 |
+
$meta = \get_post_meta( $post_id );
|
1244 |
+
|
1245 |
+
/**
|
1246 |
+
* @since 2.6.6
|
1247 |
+
* @since 3.1.0 1. Now defaults to `null`
|
1248 |
+
* 2. Now, when a boolean (either true or false) is defined, it'll short-circuit this function.
|
1249 |
+
* @param boolean|null $detected Whether a builder should be detected.
|
1250 |
+
* @param int $post_id The current Post ID.
|
1251 |
+
* @param array $meta The current post meta.
|
1252 |
+
*/
|
1253 |
+
$detected = \apply_filters( 'the_seo_framework_detect_page_builder', null, $post_id, $meta );
|
1254 |
+
|
1255 |
+
if ( \is_bool( $detected ) )
|
1256 |
+
return $detected;
|
1257 |
+
|
1258 |
+
if ( ! $tsf->detect_page_builder() )
|
1259 |
+
return false;
|
1260 |
+
|
1261 |
+
if ( empty( $meta ) )
|
1262 |
+
return false;
|
1263 |
+
|
1264 |
+
if ( isset( $meta['_elementor_edit_mode'][0] ) && '' !== $meta['_elementor_edit_mode'][0] && \defined( 'ELEMENTOR_VERSION' ) ) :
|
1265 |
+
// Elementor by Elementor LTD
|
1266 |
+
return true;
|
1267 |
+
elseif ( isset( $meta['_et_pb_use_builder'][0] ) && 'on' === $meta['_et_pb_use_builder'][0] && \defined( 'ET_BUILDER_VERSION' ) ) :
|
1268 |
+
// Divi Builder by Elegant Themes
|
1269 |
+
return true;
|
1270 |
+
elseif ( isset( $meta['_wpb_vc_js_status'][0] ) && 'true' === $meta['_wpb_vc_js_status'][0] && \defined( 'WPB_VC_VERSION' ) ) :
|
1271 |
+
// Visual Composer by WPBakery
|
1272 |
+
return true;
|
1273 |
+
elseif ( isset( $meta['panels_data'][0] ) && '' !== $meta['panels_data'][0] && \defined( 'SITEORIGIN_PANELS_VERSION' ) ) :
|
1274 |
+
// Page Builder by SiteOrigin
|
1275 |
+
return true;
|
1276 |
+
elseif ( isset( $meta['_fl_builder_enabled'][0] ) && '1' === $meta['_fl_builder_enabled'][0] && \defined( 'FL_BUILDER_VERSION' ) ) :
|
1277 |
+
// Beaver Builder by Fastline Media...
|
1278 |
+
return true;
|
1279 |
+
endif;
|
1280 |
+
|
1281 |
+
return false;
|
1282 |
+
}
|
1283 |
+
|
1284 |
+
/**
|
1285 |
+
* Returns Facebook locales array values.
|
1286 |
+
*
|
1287 |
+
* @since 2.5.2
|
1288 |
+
* @TODO deprecate me.
|
1289 |
+
*
|
1290 |
+
* @see https://www.facebook.com/translations/FacebookLocales.xml (deprecated)
|
1291 |
+
* @see https://wordpress.org/support/topic/oglocale-problem/#post-11456346
|
1292 |
+
* mirror: http://web.archive.org/web/20190601043836/https://wordpress.org/support/topic/oglocale-problem/
|
1293 |
+
* @see $this->language_keys() for the associative array keys.
|
1294 |
+
*
|
1295 |
+
* @return array Valid Facebook locales
|
1296 |
+
*/
|
1297 |
+
public function fb_locales() {
|
1298 |
+
$tsf = \tsf();
|
1299 |
+
$tsf->_deprecated_function( 'tsf()->fb_locales()', '4.2.0', 'tsf()->supported_social_locales()' );
|
1300 |
+
return \array_keys( $tsf->supported_social_locales() );
|
1301 |
+
}
|
1302 |
+
|
1303 |
+
/**
|
1304 |
+
* Returns Facebook locales' associative array keys.
|
1305 |
+
*
|
1306 |
+
* This is apart from the fb_locales array since there are "duplicated" keys.
|
1307 |
+
* Use this to compare the numeric key position.
|
1308 |
+
*
|
1309 |
+
* @since 2.5.2
|
1310 |
+
* @TODO deprecate me.
|
1311 |
+
* @see https://www.facebook.com/translations/FacebookLocales.xml (deprecated)
|
1312 |
+
* @see https://wordpress.org/support/topic/oglocale-problem/#post-11456346
|
1313 |
+
* mirror: http://web.archive.org/web/20190601043836/https://wordpress.org/support/topic/oglocale-problem/
|
1314 |
+
*
|
1315 |
+
* @return array Valid Facebook locale keys
|
1316 |
+
*/
|
1317 |
+
public function language_keys() {
|
1318 |
+
$tsf = \tsf();
|
1319 |
+
$tsf->_deprecated_function( 'tsf()->language_keys()', '4.2.0', 'tsf()->supported_social_locales()' );
|
1320 |
+
return \array_values( $tsf->supported_social_locales() );
|
1321 |
+
}
|
1322 |
+
|
1323 |
+
/**
|
1324 |
+
* Returns the PHP timezone compatible string.
|
1325 |
+
* UTC offsets are unreliable.
|
1326 |
+
*
|
1327 |
+
* @since 2.6.0
|
1328 |
+
* @since 4.2.0 Deprecated.
|
1329 |
+
* @deprecated
|
1330 |
+
*
|
1331 |
+
* @param bool $guess If true, the timezone will be guessed from the
|
1332 |
+
* WordPress core gmt_offset option.
|
1333 |
+
* @return string PHP Timezone String. May be empty (thus invalid).
|
1334 |
+
*/
|
1335 |
+
public function get_timezone_string( $guess = false ) {
|
1336 |
+
|
1337 |
+
$tsf = \tsf();
|
1338 |
+
$tsf->_deprecated_function( 'tsf()->get_timezone_string()', '4.2.0' );
|
1339 |
+
|
1340 |
+
$tzstring = \get_option( 'timezone_string' );
|
1341 |
+
|
1342 |
+
if ( false !== strpos( $tzstring, 'Etc/GMT' ) )
|
1343 |
+
$tzstring = '';
|
1344 |
+
|
1345 |
+
if ( $guess && empty( $tzstring ) ) {
|
1346 |
+
$tzstring = timezone_name_from_abbr( '', round( \get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ), 1 );
|
1347 |
+
}
|
1348 |
+
|
1349 |
+
return $tzstring;
|
1350 |
+
}
|
1351 |
+
|
1352 |
+
/**
|
1353 |
+
* Sets and resets the timezone.
|
1354 |
+
*
|
1355 |
+
* NOTE: Always call reset_timezone() ASAP. Don't let changes linger, as they can be destructive.
|
1356 |
+
*
|
1357 |
+
* This exists because WordPress's current_time() adds discrepancies between UTC and GMT.
|
1358 |
+
* This is also far more accurate than WordPress's tiny time table.
|
1359 |
+
*
|
1360 |
+
* @TODO Note that WordPress 5.3 no longer requires this, and that we should rely on wp_date() instead.
|
1361 |
+
* So, we should remove this dependency ASAP.
|
1362 |
+
*
|
1363 |
+
* @since 2.6.0
|
1364 |
+
* @since 3.0.6 Now uses the old timezone string when a new one can't be generated.
|
1365 |
+
* @since 4.0.4 Now also unsets the stored timezone string on reset.
|
1366 |
+
* @since 4.2.0 Deprecated.
|
1367 |
+
* @link http://php.net/manual/en/timezones.php
|
1368 |
+
* @deprecated
|
1369 |
+
*
|
1370 |
+
* @param string $tzstring Optional. The PHP Timezone string. Best to leave empty to always get a correct one.
|
1371 |
+
* @param bool $reset Whether to reset to default. Ignoring first parameter.
|
1372 |
+
* @return bool True on success. False on failure.
|
1373 |
+
*/
|
1374 |
+
public function set_timezone( $tzstring = '', $reset = false ) {
|
1375 |
+
|
1376 |
+
$tsf = \tsf();
|
1377 |
+
$tsf->_deprecated_function( 'tsf()->set_timezone()', '4.2.0' );
|
1378 |
+
|
1379 |
+
static $old_tz = null;
|
1380 |
+
|
1381 |
+
$old_tz = $old_tz ?: date_default_timezone_get() ?: 'UTC';
|
1382 |
+
|
1383 |
+
if ( $reset ) {
|
1384 |
+
$_revert_tz = $old_tz;
|
1385 |
+
$old_tz = null;
|
1386 |
+
// phpcs:ignore, WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set
|
1387 |
+
return date_default_timezone_set( $_revert_tz );
|
1388 |
+
}
|
1389 |
+
|
1390 |
+
if ( empty( $tzstring ) )
|
1391 |
+
$tzstring = $tsf->get_timezone_string( true ) ?: $old_tz;
|
1392 |
+
|
1393 |
+
// phpcs:ignore, WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set
|
1394 |
+
return date_default_timezone_set( $tzstring );
|
1395 |
+
}
|
1396 |
+
|
1397 |
+
/**
|
1398 |
+
* Resets the timezone to default or UTC.
|
1399 |
+
*
|
1400 |
+
* @since 2.6.0
|
1401 |
+
* @since 4.2.0 Deprecated.
|
1402 |
+
* @deprecated
|
1403 |
+
*
|
1404 |
+
* @return bool True on success. False on failure.
|
1405 |
+
*/
|
1406 |
+
public function reset_timezone() {
|
1407 |
+
$tsf = \tsf();
|
1408 |
+
$tsf->_deprecated_function( 'tsf()->reset_timezone()', '4.2.0' );
|
1409 |
+
return $tsf->set_timezone( '', true );
|
1410 |
+
}
|
1411 |
+
|
1412 |
+
/**
|
1413 |
+
* Returns and caches term meta for the current query.
|
1414 |
+
* Memoizes the return value for the current request.
|
1415 |
+
*
|
1416 |
+
* @since 3.0.0
|
1417 |
+
* @since 4.0.1 Now uses the filterable `get_the_real_ID()`
|
1418 |
+
* @since 4.2.0 Deprecated. Use get_term_meta() or get_term_meta_item() instead.
|
1419 |
+
* @deprecated
|
1420 |
+
*
|
1421 |
+
* @return array The current term meta.
|
1422 |
+
*/
|
1423 |
+
public function get_current_term_meta() {
|
1424 |
+
|
1425 |
+
$tsf = \tsf();
|
1426 |
+
$tsf->_deprecated_function( 'tsf()->get_current_term_meta()', '4.2.0', 'tsf()->get_term_meta()' );
|
1427 |
+
|
1428 |
+
static $cache;
|
1429 |
+
|
1430 |
+
if ( isset( $cache ) )
|
1431 |
+
return $cache;
|
1432 |
+
|
1433 |
+
if ( $tsf->is_term_meta_capable() ) {
|
1434 |
+
$cache = $tsf->get_term_meta( $tsf->get_the_real_ID() ) ?: [];
|
1435 |
+
} else {
|
1436 |
+
$cache = [];
|
1437 |
+
}
|
1438 |
+
|
1439 |
+
return $cache;
|
1440 |
+
}
|
1441 |
+
|
1442 |
+
/**
|
1443 |
+
* Detect the non-home blog page by query (ID).
|
1444 |
+
*
|
1445 |
+
* @since 2.3.4
|
1446 |
+
* @since 4.2.0 Deprecated. Use is_home_as_page() instead.
|
1447 |
+
* @deprecated
|
1448 |
+
* @see is_wc_shop() -- that's the correct implementation. However, we're dealing with erratic queries here (ET & legacy WP)
|
1449 |
+
*
|
1450 |
+
* @param int $id the Page ID.
|
1451 |
+
* @return bool true if is blog page. Always false if blog page is homepage.
|
1452 |
+
*/
|
1453 |
+
public function is_blog_page( $id = 0 ) {
|
1454 |
+
|
1455 |
+
$tsf = \tsf();
|
1456 |
+
$tsf->_deprecated_function( 'tsf()->is_blog_page()', '4.2.0', 'tsf()->is_home_as_page()' );
|
1457 |
+
|
1458 |
+
// When the blog page is the front page, treat it as front instead of blog.
|
1459 |
+
if ( ! $tsf->has_page_on_front() )
|
1460 |
+
return false;
|
1461 |
+
|
1462 |
+
$id = $id ?: $tsf->get_the_real_ID();
|
1463 |
+
|
1464 |
+
static $pfp;
|
1465 |
+
|
1466 |
+
$pfp = $pfp ?? (int) \get_option( 'page_for_posts' );
|
1467 |
+
|
1468 |
+
return ( $id && $id === $pfp && false === \is_archive() ) || \is_home();
|
1469 |
+
}
|
1470 |
+
|
1471 |
+
/**
|
1472 |
+
* Checks blog page by sole ID.
|
1473 |
+
*
|
1474 |
+
* @since 4.0.0
|
1475 |
+
* @since 4.1.4 1. Improved performance by switching the conditional.
|
1476 |
+
* 2. Improved performance by adding memoization.
|
1477 |
+
* @since 4.2.0 1. Removed memoization.
|
1478 |
+
* 2. Deprecated. Use is_home() instead.
|
1479 |
+
* @deprecated
|
1480 |
+
* @see is_wc_shop() -- that's the correct implementation.
|
1481 |
+
*
|
1482 |
+
* @param int $id The ID to check
|
1483 |
+
* @return bool
|
1484 |
+
*/
|
1485 |
+
public function is_blog_page_by_id( $id ) {
|
1486 |
+
\tsf()->_deprecated_function( 'tsf()->is_blog_page()', '4.2.0', 'tsf()->is_home()' );
|
1487 |
+
|
1488 |
+
// ID 0 cannot be a blog page.
|
1489 |
+
if ( ! $id ) return false;
|
1490 |
+
|
1491 |
+
return (int) \get_option( 'page_for_posts' ) === $id;
|
1492 |
+
}
|
1493 |
+
|
1494 |
+
/**
|
1495 |
+
* Checks for front page by input ID.
|
1496 |
+
*
|
1497 |
+
* NOTE: Doesn't always return true when the ID is 0, although the homepage might be.
|
1498 |
+
* This is because it checks for the query, to prevent conflicts.
|
1499 |
+
*
|
1500 |
+
* @see $this->is_real_front_page_by_id(); Alternative to NOTE.
|
1501 |
+
*
|
1502 |
+
* @since 2.9.0
|
1503 |
+
* @since 2.9.3 Now tests for archive and 404 before testing homepage as blog.
|
1504 |
+
* @since 3.2.2 Removed SEO settings page check. This now returns false on that page.
|
1505 |
+
* @since 4.2.0 1. No longer casts input $id to integer.
|
1506 |
+
* 2. Deprecated.
|
1507 |
+
* @deprecated
|
1508 |
+
*
|
1509 |
+
* @param int $id The page ID, required. Can be 0.
|
1510 |
+
* @return bool True if ID if for the homepage.
|
1511 |
+
*/
|
1512 |
+
public function is_front_page_by_id( $id ) {
|
1513 |
+
\tsf()->_deprecated_function( 'tsf()->is_front_page_by_id()', '4.2.0', 'tsf()->is_real_front_page_by_id()' );
|
1514 |
+
|
1515 |
+
$pof = (int) \get_option( 'page_on_front' );
|
1516 |
+
|
1517 |
+
switch ( \get_option( 'show_on_front' ) ) :
|
1518 |
+
case 'page':
|
1519 |
+
$is_front_page = $pof === $id;
|
1520 |
+
break;
|
1521 |
+
|
1522 |
+
case 'posts':
|
1523 |
+
$is_front_page =
|
1524 |
+
( 0 === $pof && $this->is_home() )
|
1525 |
+
|| $pof === $id;
|
1526 |
+
break;
|
1527 |
+
|
1528 |
+
default:
|
1529 |
+
// Elegant Themes's Extra support
|
1530 |
+
$is_front_page = 0 === $id && $this->is_home();
|
1531 |
+
break;
|
1532 |
+
endswitch;
|
1533 |
+
|
1534 |
+
return $is_front_page;
|
1535 |
+
}
|
1536 |
+
|
1537 |
+
/**
|
1538 |
+
* Prepends the taxonomy label to the title.
|
1539 |
+
*
|
1540 |
+
* @since 4.1.0
|
1541 |
+
* @since 4.1.2 Now supports WP 5.5 archive titles.
|
1542 |
+
* @since 4.2.0 Deprecated
|
1543 |
+
* @deprecated
|
1544 |
+
*
|
1545 |
+
* @param string $title The title to prepend taxonomy label to.
|
1546 |
+
* @param string $taxonomy The taxonomy to get label from.
|
1547 |
+
* @return string The title with possibly prepended tax-label.
|
1548 |
+
*/
|
1549 |
+
public function prepend_tax_label_prefix( $title, $taxonomy ) {
|
1550 |
+
|
1551 |
+
$tsf = \tsf();
|
1552 |
+
\tsf()->_deprecated_function( 'tsf()->prepend_tax_label_prefix()', '4.2.0' );
|
1553 |
+
|
1554 |
+
$prefix = $tsf->get_tax_type_label( $taxonomy ) ?: '';
|
1555 |
+
|
1556 |
+
if ( $prefix ) {
|
1557 |
+
$title = sprintf(
|
1558 |
+
/* translators: 1: Title prefix. 2: Title. */
|
1559 |
+
\_x( '%1$s %2$s', 'archive title', 'default' ),
|
1560 |
+
/* translators: %s: Taxonomy singular name. */
|
1561 |
+
sprintf( \_x( '%s:', 'taxonomy term archive title prefix', 'default' ), $prefix ),
|
1562 |
+
$title
|
1563 |
+
);
|
1564 |
+
}
|
1565 |
+
|
1566 |
+
return $title;
|
1567 |
+
}
|
1568 |
+
|
1569 |
+
/**
|
1570 |
+
* Get the real ID from plugins.
|
1571 |
+
*
|
1572 |
+
* Only works on front-end as there's no need to check for inconsistent
|
1573 |
+
* functions for the current ID in the admin.
|
1574 |
+
*
|
1575 |
+
* @since 2.5.0
|
1576 |
+
* @since 3.1.0 1. Now checks for the feed.
|
1577 |
+
* 2. No longer caches.
|
1578 |
+
* @since 4.0.5 1. The shop ID is now handled via the filter.
|
1579 |
+
* 2. The question ID (AnsPress) is no longer called. This should work out-of-the-box since AnsPress 4.1.
|
1580 |
+
* @since 4.2.0 Deprecated
|
1581 |
+
* @deprecated
|
1582 |
+
*
|
1583 |
+
* @return int The admin ID.
|
1584 |
+
*/
|
1585 |
+
public function check_the_real_ID() { // phpcs:ignore -- ID is capitalized because WordPress does that too: get_the_ID().
|
1586 |
+
|
1587 |
+
\tsf()->_deprecated_function( 'tsf()->check_the_real_ID()', '4.2.0', 'tsf()->get_the_real_ID()' );
|
1588 |
+
|
1589 |
+
/**
|
1590 |
+
* @since 2.5.0
|
1591 |
+
* @param int $id
|
1592 |
+
*/
|
1593 |
+
return (int) \apply_filters(
|
1594 |
+
'the_seo_framework_real_id',
|
1595 |
+
$this->is_feed() ? \get_the_ID() : 0
|
1596 |
+
);
|
1597 |
+
}
|
1598 |
+
|
1599 |
+
/**
|
1600 |
+
* Get the default of any of the The SEO Framework settings.
|
1601 |
+
*
|
1602 |
+
* @since 2.2.4
|
1603 |
+
* @since 2.8.2 No longer decodes entities on request.
|
1604 |
+
* @since 3.1.0 1. Now returns null if the option doesn't exist, instead of -1.
|
1605 |
+
* 2. Is now influenced by filters.
|
1606 |
+
* 3. Now also strips slashes when using cache.
|
1607 |
+
* 4. The second parameter is deprecated.
|
1608 |
+
* @since 4.2.0 Deprecated
|
1609 |
+
* @deprecated
|
1610 |
+
* @uses $this->get_default_site_options()
|
1611 |
+
*
|
1612 |
+
* @param string $key Required. The option name.
|
1613 |
+
* @param string $depr Deprecated. Leave empty.
|
1614 |
+
* @param bool $use_cache Optional. Whether to use the options cache or bypass it.
|
1615 |
+
* @return mixed default option
|
1616 |
+
* null If option doesn't exist.
|
1617 |
+
*/
|
1618 |
+
public function get_default_settings( $key, $depr = '', $use_cache = true ) {
|
1619 |
+
|
1620 |
+
$tsf = \tsf();
|
1621 |
+
$tsf->_deprecated_function( 'tsf()->get_default_settings()', '4.2.0', 'tsf()->get_default_option()' );
|
1622 |
+
|
1623 |
+
if ( ! $key ) return false;
|
1624 |
+
|
1625 |
+
if ( $depr )
|
1626 |
+
$tsf->_doing_it_wrong( __METHOD__, 'The second parameter is deprecated.', '3.1.0' );
|
1627 |
+
|
1628 |
+
if ( ! $use_cache ) {
|
1629 |
+
$defaults = $tsf->get_default_site_options();
|
1630 |
+
return isset( $defaults[ $key ] ) ? \stripslashes_deep( $defaults[ $key ] ) : null;
|
1631 |
+
}
|
1632 |
+
|
1633 |
+
static $cache;
|
1634 |
+
|
1635 |
+
return (
|
1636 |
+
$cache = $cache ?? \stripslashes_deep( $tsf->get_default_site_options() )
|
1637 |
+
)[ $key ] ?? null;
|
1638 |
+
}
|
1639 |
+
|
1640 |
+
/**
|
1641 |
+
* Get the warned setting of any of the The SEO Framework settings.
|
1642 |
+
*
|
1643 |
+
* @since 2.3.4
|
1644 |
+
* @since 3.1.0 Now returns 0 if the option doesn't exist, instead of -1.
|
1645 |
+
* @since 4.2.0 Deprecated
|
1646 |
+
* @deprecated
|
1647 |
+
* @uses THE_SEO_FRAMEWORK_SITE_OPTIONS
|
1648 |
+
* @uses $this->get_warned_site_options()
|
1649 |
+
*
|
1650 |
+
* @param string $key Required. The option name.
|
1651 |
+
* @param string $depr Deprecated. Leave empty.
|
1652 |
+
* @param bool $use_cache Optional. Whether to use the options cache or bypass it.
|
1653 |
+
* @return int 0|1 Whether the option is flagged as dangerous for SEO.
|
1654 |
+
*/
|
1655 |
+
public function get_warned_settings( $key, $depr = '', $use_cache = true ) {
|
1656 |
+
|
1657 |
+
$tsf = \tsf();
|
1658 |
+
$tsf->_deprecated_function( 'tsf()->get_warned_settings()', '4.2.0', 'tsf()->get_warned_option()' );
|
1659 |
+
|
1660 |
+
if ( empty( $key ) )
|
1661 |
+
return false;
|
1662 |
+
|
1663 |
+
if ( $depr )
|
1664 |
+
$tsf->_doing_it_wrong( __METHOD__, 'The second parameter is deprecated.', '3.1.0' );
|
1665 |
+
|
1666 |
+
if ( ! $use_cache )
|
1667 |
+
return $tsf->s_one_zero( ! empty( $tsf->get_warned_site_options()[ $key ] ) );
|
1668 |
+
|
1669 |
+
static $cache;
|
1670 |
+
|
1671 |
+
if ( ! isset( $cache ) )
|
1672 |
+
$cache = $tsf->get_warned_site_options();
|
1673 |
+
|
1674 |
+
return $tsf->s_one_zero( ! empty( $cache[ $key ] ) );
|
1675 |
+
}
|
1676 |
+
|
1677 |
+
/**
|
1678 |
+
* Returns image URL suitable for Schema items.
|
1679 |
+
*
|
1680 |
+
* These are images that are strictly assigned to the Post or Page, fallbacks are omitted.
|
1681 |
+
* Themes should compliment these. If not, then Open Graph should at least compliment these.
|
1682 |
+
* If that's not even true, then I don't know what happens. But then you're in a grey area...
|
1683 |
+
*
|
1684 |
+
* @since 4.0.0
|
1685 |
+
* @since 4.2.0 1. Now gets correctly separated results when $args changes.
|
1686 |
+
* 2. Now supports the `$args['pta']` index.
|
1687 |
+
* 3. Deprecated.
|
1688 |
+
* @uses $this->get_image_details()
|
1689 |
+
* @deprecated
|
1690 |
+
*
|
1691 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
1692 |
+
* Leave null to autodetermine query.
|
1693 |
+
* @param bool $details Whether to return all details, or just a simple URL.
|
1694 |
+
* @return string|array $url The Schema.org safe image.
|
1695 |
+
*/
|
1696 |
+
public function get_safe_schema_image( $args = null, $details = false ) {
|
1697 |
+
|
1698 |
+
$tsf = \tsf();
|
1699 |
+
$tsf->_deprecated_function( 'tsf()->get_safe_schema_image()', '4.2.0', 'tsf()->get_image_details()' );
|
1700 |
+
|
1701 |
+
$image_details = memo( null, $args ) ?? memo( current( $tsf->get_image_details( $args, true, 'schema' ), $args ) );
|
1702 |
+
|
1703 |
+
return $details ? $image_details : ( $image_details['url'] ?? '' );
|
1704 |
+
}
|
1705 |
}
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* They say that God is everywhere,
|
4 |
+
* and yet we always think of Him as somewhat of a recluse.
|
5 |
+
*
|
6 |
+
* - Emily Dickinson
|
7 |
+
*/
|
@@ -1,12 +1,10 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* @package The_SEO_Framework\Classes\Silencer
|
4 |
* @subpackage The_SEO_Framework\Classes\Facade
|
5 |
*/
|
6 |
|
7 |
-
namespace The_SEO_Framework;
|
8 |
-
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
10 |
|
11 |
/**
|
12 |
* The SEO Framework plugin
|
@@ -25,15 +23,18 @@ namespace The_SEO_Framework;
|
|
25 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
26 |
*/
|
27 |
|
|
|
|
|
28 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- That's the whole premise of this file.
|
29 |
|
30 |
/**
|
31 |
-
* Class The_SEO_Framework\Silencer
|
32 |
*
|
33 |
* This is an empty class to silence invalid API calls when the plugin is soft-disabled.
|
34 |
* This alleviates redundant checks throughout the plugin API.
|
35 |
*
|
36 |
* @since 3.1.0
|
|
|
37 |
* @ignore
|
38 |
* @property false $loaded
|
39 |
*/
|
@@ -46,7 +47,7 @@ final class Silencer {
|
|
46 |
*
|
47 |
* @since 3.1.0
|
48 |
* @access protected
|
49 |
-
* Don't alter this variable
|
50 |
* @var boolean $loaded
|
51 |
*/
|
52 |
public $loaded = false;
|
1 |
<?php
|
2 |
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Internal\Silencer
|
4 |
* @subpackage The_SEO_Framework\Classes\Facade
|
5 |
*/
|
6 |
|
7 |
+
namespace The_SEO_Framework\Internal;
|
|
|
|
|
8 |
|
9 |
/**
|
10 |
* The SEO Framework plugin
|
23 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
*/
|
25 |
|
26 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
+
|
28 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- That's the whole premise of this file.
|
29 |
|
30 |
/**
|
31 |
+
* Class The_SEO_Framework\Internal\Silencer
|
32 |
*
|
33 |
* This is an empty class to silence invalid API calls when the plugin is soft-disabled.
|
34 |
* This alleviates redundant checks throughout the plugin API.
|
35 |
*
|
36 |
* @since 3.1.0
|
37 |
+
* @since 4.2.0 Changed namespace from \The_SEO_Framework to \The_SEO_Framework\Internal
|
38 |
* @ignore
|
39 |
* @property false $loaded
|
40 |
*/
|
47 |
*
|
48 |
* @since 3.1.0
|
49 |
* @access protected
|
50 |
+
* Don't alter this variable.
|
51 |
* @var boolean $loaded
|
52 |
*/
|
53 |
public $loaded = false;
|
@@ -26,7 +26,7 @@ namespace The_SEO_Framework\Interpreters;
|
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
/**
|
29 |
-
* Interprets anything you send here into HTML. Or so it should.
|
30 |
*
|
31 |
* @since 4.1.4
|
32 |
*
|
@@ -37,184 +37,11 @@ namespace The_SEO_Framework\Interpreters;
|
|
37 |
*/
|
38 |
final class Form {
|
39 |
|
40 |
-
/**
|
41 |
-
* Helper function that constructs header elements.
|
42 |
-
*
|
43 |
-
* @since 4.1.4
|
44 |
-
*
|
45 |
-
* @param string $title The header title.
|
46 |
-
*/
|
47 |
-
public static function header_title( $title ) {
|
48 |
-
printf( '<h4>%s</h4>', \esc_html( $title ) );
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Helper function that constructs name attributes for use in form fields.
|
53 |
-
*
|
54 |
-
* Other page implementation classes may wish to construct and use a
|
55 |
-
* get_field_id() method, if the naming format needs to be different.
|
56 |
-
*
|
57 |
-
* @since 4.1.4
|
58 |
-
*
|
59 |
-
* @param string $name Field name base
|
60 |
-
* @return string Full field name
|
61 |
-
*/
|
62 |
-
public static function get_field_name( $name ) {
|
63 |
-
return sprintf( '%s[%s]', THE_SEO_FRAMEWORK_SITE_OPTIONS, $name );
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Echo constructed name attributes in form fields.
|
68 |
-
*
|
69 |
-
* @since 4.1.4
|
70 |
-
* @uses static::get_field_name() Construct name attributes for use in form fields.
|
71 |
-
*
|
72 |
-
* @param string $name Field name base
|
73 |
-
*/
|
74 |
-
public static function field_name( $name ) {
|
75 |
-
echo \esc_attr( static::get_field_name( $name ) );
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Helper function that constructs id attributes for use in form fields.
|
80 |
-
*
|
81 |
-
* @since 4.1.4
|
82 |
-
*
|
83 |
-
* @param string $id Field id base
|
84 |
-
* @return string Full field id
|
85 |
-
*/
|
86 |
-
public static function get_field_id( $id ) {
|
87 |
-
return sprintf( '%s[%s]', THE_SEO_FRAMEWORK_SITE_OPTIONS, $id );
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Echo constructed id attributes in form fields.
|
92 |
-
*
|
93 |
-
* @since 4.1.4
|
94 |
-
* @uses static::get_field_id() Constructs id attributes for use in form fields.
|
95 |
-
*
|
96 |
-
* @param string $id Field id base.
|
97 |
-
* @param boolean $echo Whether to escape echo or just return.
|
98 |
-
* @return string Full field id
|
99 |
-
*/
|
100 |
-
public static function field_id( $id, $echo = true ) {
|
101 |
-
if ( $echo ) {
|
102 |
-
echo \esc_attr( static::get_field_id( $id ) );
|
103 |
-
} else {
|
104 |
-
return static::get_field_id( $id );
|
105 |
-
}
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Returns a chechbox wrapper.
|
110 |
-
*
|
111 |
-
* @since 4.1.4
|
112 |
-
*
|
113 |
-
* @param array $args : {
|
114 |
-
* string $id The option name, used as field ID.
|
115 |
-
* string $class The checkbox class.
|
116 |
-
* string $index The option index, used when the option is an array.
|
117 |
-
* string $label The checkbox label description, placed inline of the checkbox.
|
118 |
-
* string $description The checkbox additional description, placed underneat.
|
119 |
-
* array $data The checkbox field data. Sub-items are expected to be escaped if they're not an array.
|
120 |
-
* bool $escape Whether to enable escaping of the $label and $description.
|
121 |
-
* bool $disabled Whether to disable the checkbox field.
|
122 |
-
* bool $default Whether to display-as-default. This is autodetermined when no $index is set.
|
123 |
-
* bool $warned Whether to warn the checkbox field value.
|
124 |
-
* }
|
125 |
-
* @return string HTML checkbox output.
|
126 |
-
*/
|
127 |
-
public static function make_checkbox( array $args = [] ) {
|
128 |
-
|
129 |
-
$args = array_merge(
|
130 |
-
[
|
131 |
-
'id' => '',
|
132 |
-
'class' => '',
|
133 |
-
'index' => '',
|
134 |
-
'label' => '',
|
135 |
-
'description' => '',
|
136 |
-
'data' => [],
|
137 |
-
'escape' => true,
|
138 |
-
'disabled' => false,
|
139 |
-
'default' => false,
|
140 |
-
'warned' => false,
|
141 |
-
],
|
142 |
-
$args
|
143 |
-
);
|
144 |
-
|
145 |
-
if ( $args['escape'] ) {
|
146 |
-
$args['description'] = \esc_html( $args['description'] );
|
147 |
-
$args['label'] = \esc_html( $args['label'] );
|
148 |
-
}
|
149 |
-
|
150 |
-
$tsf = \the_seo_framework();
|
151 |
-
|
152 |
-
$index = $args['index'] ? $tsf->s_field_id( $args['index'] ?: '' ) : '';
|
153 |
-
|
154 |
-
$field_id = $field_name = \esc_attr( sprintf(
|
155 |
-
'%s%s',
|
156 |
-
Form::get_field_id( $args['id'] ),
|
157 |
-
$index ? sprintf( '[%s]', $index ) : ''
|
158 |
-
) );
|
159 |
-
|
160 |
-
$value = $tsf->get_option( $args['id'] );
|
161 |
-
if ( $index ) {
|
162 |
-
$value = isset( $value[ $index ] ) ? $value[ $index ] : '';
|
163 |
-
}
|
164 |
-
|
165 |
-
$cb_classes = [];
|
166 |
-
|
167 |
-
if ( $args['class'] ) {
|
168 |
-
$cb_classes[] = $args['class'];
|
169 |
-
}
|
170 |
-
|
171 |
-
if ( $args['disabled'] ) {
|
172 |
-
$cb_classes[] = 'tsf-disabled';
|
173 |
-
} elseif ( ! $args['index'] ) {
|
174 |
-
// Can't fetch conditionals in index.
|
175 |
-
$cb_classes[] = static::get_is_conditional_checked( $args['id'], false );
|
176 |
-
} else {
|
177 |
-
if ( $args['default'] ) {
|
178 |
-
$cb_classes[] = 'tsf-default-selected';
|
179 |
-
} elseif ( $args['warned'] ) {
|
180 |
-
$cb_classes[] = 'tsf-warning-selected';
|
181 |
-
}
|
182 |
-
}
|
183 |
-
|
184 |
-
$output = sprintf(
|
185 |
-
'<span class="tsf-toblock">%s</span>',
|
186 |
-
vsprintf(
|
187 |
-
'<label for="%s" %s>%s</label>',
|
188 |
-
[
|
189 |
-
$field_id,
|
190 |
-
( $args['disabled'] ? 'class="tsf-disabled"' : '' ),
|
191 |
-
vsprintf(
|
192 |
-
'<input type=checkbox class="%s" name="%s" id="%s" value="1" %s %s %s /> %s',
|
193 |
-
[
|
194 |
-
\esc_attr( implode( ' ', $cb_classes ) ),
|
195 |
-
$field_name,
|
196 |
-
$field_id,
|
197 |
-
\checked( $value, true, false ),
|
198 |
-
( $args['disabled'] ? 'disabled' : '' ),
|
199 |
-
$args['data'] ? HTML::make_data_attributes( $args['data'] ) : '',
|
200 |
-
$args['label'],
|
201 |
-
]
|
202 |
-
),
|
203 |
-
]
|
204 |
-
)
|
205 |
-
);
|
206 |
-
|
207 |
-
$output .= $args['description'] ? sprintf( '<p class="description tsf-option-spacer">%s</p>', $args['description'] ) : '';
|
208 |
-
|
209 |
-
return $output;
|
210 |
-
}
|
211 |
-
|
212 |
/**
|
213 |
* Returns a HTML select form elements for qubit options: -1, 0, or 1.
|
214 |
* Does not support "multiple" field selections.
|
215 |
*
|
216 |
* @since 4.1.4
|
217 |
-
* @TODO allow arrays as index, so we can support multidimensional options easily? @see is_conditional_checked
|
218 |
*
|
219 |
* @param array $args : {
|
220 |
* string $id The select field ID.
|
@@ -229,18 +56,19 @@ final class Form {
|
|
229 |
* }
|
230 |
* @return string The option field.
|
231 |
*/
|
232 |
-
public static function make_single_select_form(
|
233 |
|
234 |
$defaults = [
|
235 |
-
'id'
|
236 |
-
'class'
|
237 |
-
'name'
|
238 |
-
'default'
|
239 |
-
'options'
|
240 |
-
'label'
|
241 |
-
'
|
242 |
-
'
|
243 |
-
'
|
|
|
244 |
];
|
245 |
|
246 |
$args = array_merge( $defaults, $args );
|
@@ -262,7 +90,7 @@ final class Form {
|
|
262 |
};
|
263 |
array_walk( $html_options, $create_option, $args['default'] );
|
264 |
|
265 |
-
$tsf = \
|
266 |
|
267 |
return vsprintf(
|
268 |
sprintf( '<div class="%s">%s</div>',
|
@@ -271,22 +99,25 @@ final class Form {
|
|
271 |
),
|
272 |
[
|
273 |
$args['label'] ? sprintf(
|
274 |
-
'<label for
|
275 |
$tsf->s_field_id( $args['id'] ),
|
276 |
-
|
|
|
|
|
|
|
277 |
) : '',
|
278 |
-
$args['info'] ?
|
279 |
$args['info'][0],
|
280 |
-
|
281 |
false
|
282 |
-
) : '',
|
283 |
vsprintf(
|
284 |
-
'<select id
|
285 |
[
|
286 |
$tsf->s_field_id( $args['id'] ),
|
287 |
\esc_attr( $args['name'] ),
|
288 |
-
$args['required'] ? 'required' : '',
|
289 |
-
|
290 |
implode( $html_options ),
|
291 |
]
|
292 |
),
|
@@ -294,126 +125,6 @@ final class Form {
|
|
294 |
);
|
295 |
}
|
296 |
|
297 |
-
/**
|
298 |
-
* Returns the HTML class wrap for default Checkbox options.
|
299 |
-
*
|
300 |
-
* This function does nothing special. But is merely a simple wrapper.
|
301 |
-
* Just like code_wrap.
|
302 |
-
*
|
303 |
-
* @since 4.1.4
|
304 |
-
*
|
305 |
-
* @param string $key The option name which returns boolean.
|
306 |
-
* @param bool $wrap Whether to wrap the class name in `class="%s"`
|
307 |
-
* @param bool $echo Whether to echo or return the output.
|
308 |
-
* @return string Empty on echo or the class name with an optional wrapper.
|
309 |
-
*/
|
310 |
-
public static function is_default_checked( $key, $wrap = true, $echo = true ) {
|
311 |
-
|
312 |
-
$class = '';
|
313 |
-
|
314 |
-
$default = \the_seo_framework()->get_default_settings( $key );
|
315 |
-
|
316 |
-
if ( 1 === $default )
|
317 |
-
$class = 'tsf-default-selected';
|
318 |
-
|
319 |
-
if ( $echo ) {
|
320 |
-
if ( $wrap ) {
|
321 |
-
printf( 'class="%s"', \esc_attr( $class ) );
|
322 |
-
} else {
|
323 |
-
echo \esc_attr( $class );
|
324 |
-
}
|
325 |
-
} else {
|
326 |
-
if ( $wrap )
|
327 |
-
return sprintf( 'class="%s"', $class );
|
328 |
-
|
329 |
-
return $class;
|
330 |
-
}
|
331 |
-
}
|
332 |
-
|
333 |
-
/**
|
334 |
-
* Returns the HTML class wrap for warning Checkbox options.
|
335 |
-
*
|
336 |
-
* @since 4.1.4
|
337 |
-
*
|
338 |
-
* @param string $key The option name which returns boolean.
|
339 |
-
* @param bool $wrap Whether to wrap the class name in `class="%s"`
|
340 |
-
* @param bool $echo Whether to echo or return the output.
|
341 |
-
* @return string Empty on echo or the class name with an optional wrapper.
|
342 |
-
*/
|
343 |
-
public static function is_warning_checked( $key, $wrap = true, $echo = true ) {
|
344 |
-
|
345 |
-
$class = '';
|
346 |
-
|
347 |
-
$warned = \the_seo_framework()->get_warned_settings( $key );
|
348 |
-
|
349 |
-
if ( 1 === $warned )
|
350 |
-
$class = 'tsf-warning-selected';
|
351 |
-
|
352 |
-
if ( $echo ) {
|
353 |
-
if ( $wrap ) {
|
354 |
-
printf( 'class="%s"', \esc_attr( $class ) );
|
355 |
-
} else {
|
356 |
-
echo \esc_attr( $class );
|
357 |
-
}
|
358 |
-
} else {
|
359 |
-
if ( $wrap )
|
360 |
-
return sprintf( 'class="%s"', $class );
|
361 |
-
|
362 |
-
return $class;
|
363 |
-
}
|
364 |
-
}
|
365 |
-
|
366 |
-
/**
|
367 |
-
* Returns the HTML class wrap for warning/default Checkbox options.
|
368 |
-
*
|
369 |
-
* @since 4.1.4
|
370 |
-
*
|
371 |
-
* @param string $key The option name which returns boolean.
|
372 |
-
* @param bool $wrap Whether to wrap the class name in `class="%s"`
|
373 |
-
*/
|
374 |
-
public static function get_is_conditional_checked( $key, $wrap = true ) {
|
375 |
-
return static::is_conditional_checked( $key, '', $wrap, false );
|
376 |
-
}
|
377 |
-
|
378 |
-
/**
|
379 |
-
* Returns the HTML class wrap for warning/default Checkbox options.
|
380 |
-
*
|
381 |
-
* @since 4.1.4
|
382 |
-
*
|
383 |
-
* @param string $key The option name which returns boolean.
|
384 |
-
* @param bool $wrap Whether to wrap the class name in `class="%s"`
|
385 |
-
* @param bool $echo Whether to echo or return the output.
|
386 |
-
* @return string Empty on echo or the class name with an optional wrapper.
|
387 |
-
*/
|
388 |
-
public static function is_conditional_checked( $key, $wrap = true, $echo = true ) {
|
389 |
-
|
390 |
-
$class = '';
|
391 |
-
|
392 |
-
$default = static::is_default_checked( $key, false, false );
|
393 |
-
$warned = static::is_warning_checked( $key, false, false );
|
394 |
-
|
395 |
-
if ( '' !== $default && '' !== $warned ) {
|
396 |
-
$class = $default . ' ' . $warned;
|
397 |
-
} elseif ( '' !== $default ) {
|
398 |
-
$class = $default;
|
399 |
-
} elseif ( '' !== $warned ) {
|
400 |
-
$class = $warned;
|
401 |
-
}
|
402 |
-
|
403 |
-
if ( $echo ) {
|
404 |
-
if ( $wrap ) {
|
405 |
-
printf( 'class="%s"', \esc_attr( $class ) );
|
406 |
-
} else {
|
407 |
-
echo \esc_attr( $class );
|
408 |
-
}
|
409 |
-
} else {
|
410 |
-
if ( $wrap )
|
411 |
-
return sprintf( 'class="%s"', $class );
|
412 |
-
|
413 |
-
return $class;
|
414 |
-
}
|
415 |
-
}
|
416 |
-
|
417 |
/**
|
418 |
* Outputs character counter wrap for both JavaScript and no-Javascript.
|
419 |
*
|
@@ -448,7 +159,7 @@ final class Form {
|
|
448 |
*
|
449 |
* @param string $for The input ID it's for.
|
450 |
* @param string $type Whether it's a 'title' or 'description' counter.
|
451 |
-
* @param bool $display Whether to display the counter. (options page gimmick)
|
452 |
*/
|
453 |
public static function output_pixel_counter_wrap( $for, $type, $display = true ) {
|
454 |
vprintf(
|
@@ -495,38 +206,37 @@ final class Form {
|
|
495 |
* }
|
496 |
* @return string The image uploader button.
|
497 |
*/
|
498 |
-
public static function get_image_uploader_form(
|
499 |
|
500 |
-
|
501 |
-
$
|
502 |
|
503 |
-
$tsf = \
|
504 |
|
505 |
-
$
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
'
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
'
|
518 |
-
|
|
|
|
|
519 |
],
|
520 |
-
|
521 |
-
|
522 |
-
$args = $tsf->array_merge_recursive_distinct( $defaults, $args );
|
523 |
-
|
524 |
-
if ( ! $args['id'] ) return '';
|
525 |
|
526 |
$content = vsprintf(
|
527 |
'<button type=button data-href="%s" class="tsf-set-image-button button button-primary button-small" title="%s" id="%s-select" %s>%s</button>',
|
528 |
[
|
529 |
-
\esc_url( \get_upload_iframe_src( 'image', $
|
530 |
\esc_attr( $args['i18n']['button_title'] ),
|
531 |
\esc_attr( $args['id'] ),
|
532 |
HTML::make_data_attributes(
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
/**
|
29 |
+
* Interprets anything you send here into Form HTML. Or so it should.
|
30 |
*
|
31 |
* @since 4.1.4
|
32 |
*
|
37 |
*/
|
38 |
final class Form {
|
39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
/**
|
41 |
* Returns a HTML select form elements for qubit options: -1, 0, or 1.
|
42 |
* Does not support "multiple" field selections.
|
43 |
*
|
44 |
* @since 4.1.4
|
|
|
45 |
*
|
46 |
* @param array $args : {
|
47 |
* string $id The select field ID.
|
56 |
* }
|
57 |
* @return string The option field.
|
58 |
*/
|
59 |
+
public static function make_single_select_form( $args ) {
|
60 |
|
61 |
$defaults = [
|
62 |
+
'id' => '',
|
63 |
+
'class' => '',
|
64 |
+
'name' => '',
|
65 |
+
'default' => '',
|
66 |
+
'options' => [],
|
67 |
+
'label' => '',
|
68 |
+
'labelstrong' => false,
|
69 |
+
'required' => false,
|
70 |
+
'data' => [],
|
71 |
+
'info' => [],
|
72 |
];
|
73 |
|
74 |
$args = array_merge( $defaults, $args );
|
90 |
};
|
91 |
array_walk( $html_options, $create_option, $args['default'] );
|
92 |
|
93 |
+
$tsf = \tsf();
|
94 |
|
95 |
return vsprintf(
|
96 |
sprintf( '<div class="%s">%s</div>',
|
99 |
),
|
100 |
[
|
101 |
$args['label'] ? sprintf(
|
102 |
+
'<label for="%s">%s</label> ', // superfluous space!
|
103 |
$tsf->s_field_id( $args['id'] ),
|
104 |
+
sprintf(
|
105 |
+
$args['labelstrong'] ? '<strong>%s</strong>' : '%s',
|
106 |
+
\esc_html( $args['label'] )
|
107 |
+
)
|
108 |
) : '',
|
109 |
+
$args['info'] ? HTML::make_info(
|
110 |
$args['info'][0],
|
111 |
+
$args['info'][1] ?? '',
|
112 |
false
|
113 |
+
) . ' ' : '',
|
114 |
vsprintf(
|
115 |
+
'<select id="%s" name="%s"%s %s>%s</select>',
|
116 |
[
|
117 |
$tsf->s_field_id( $args['id'] ),
|
118 |
\esc_attr( $args['name'] ),
|
119 |
+
$args['required'] ? ' required' : '',
|
120 |
+
HTML::make_data_attributes( $args['data'] ),
|
121 |
implode( $html_options ),
|
122 |
]
|
123 |
),
|
125 |
);
|
126 |
}
|
127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
/**
|
129 |
* Outputs character counter wrap for both JavaScript and no-Javascript.
|
130 |
*
|
159 |
*
|
160 |
* @param string $for The input ID it's for.
|
161 |
* @param string $type Whether it's a 'title' or 'description' counter.
|
162 |
+
* @param bool $display Whether to display the counter. (Used as options page gimmick)
|
163 |
*/
|
164 |
public static function output_pixel_counter_wrap( $for, $type, $display = true ) {
|
165 |
vprintf(
|
206 |
* }
|
207 |
* @return string The image uploader button.
|
208 |
*/
|
209 |
+
public static function get_image_uploader_form( $args ) {
|
210 |
|
211 |
+
// Required.
|
212 |
+
if ( empty( $args['id'] ) ) return '';
|
213 |
|
214 |
+
$tsf = \tsf();
|
215 |
|
216 |
+
$args = $tsf->array_merge_recursive_distinct(
|
217 |
+
[
|
218 |
+
'id' => '',
|
219 |
+
'post_id' => $tsf->get_the_real_ID(), // TODO why? Introduced <https://github.com/sybrew/the-seo-framework/commit/6ca4425abf3edafd75d7d47e60e54eb8bca91cc2>
|
220 |
+
'data' => [
|
221 |
+
'inputType' => 'social',
|
222 |
+
'width' => 1200, // TODO make 1280 - 80px overflow margin? It'd be better for mixed platforms.
|
223 |
+
'height' => 630, // TODO make 640 - 80px overflow margin? It'd be better for mixed platforms.
|
224 |
+
'minWidth' => 200,
|
225 |
+
'minHeight' => 200,
|
226 |
+
'flex' => true,
|
227 |
+
],
|
228 |
+
'i18n' => [
|
229 |
+
'button_title' => '', // Redundant.
|
230 |
+
'button_text' => \__( 'Select Image', 'autodescription' ),
|
231 |
+
],
|
232 |
],
|
233 |
+
$args
|
234 |
+
);
|
|
|
|
|
|
|
235 |
|
236 |
$content = vsprintf(
|
237 |
'<button type=button data-href="%s" class="tsf-set-image-button button button-primary button-small" title="%s" id="%s-select" %s>%s</button>',
|
238 |
[
|
239 |
+
\esc_url( \get_upload_iframe_src( 'image', $args['post_id'] ) ),
|
240 |
\esc_attr( $args['i18n']['button_title'] ),
|
241 |
\esc_attr( $args['id'] ),
|
242 |
HTML::make_data_attributes(
|
@@ -37,6 +37,30 @@ namespace The_SEO_Framework\Interpreters;
|
|
37 |
*/
|
38 |
final class HTML {
|
39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
/**
|
41 |
* Mark up content with code tags.
|
42 |
* Escapes all HTML, so `<` gets changed to `<` and displays correctly.
|
@@ -60,7 +84,7 @@ final class HTML {
|
|
60 |
* @return string Content wrapped in code tags.
|
61 |
*/
|
62 |
public static function code_wrap_noesc( $content ) {
|
63 |
-
return
|
64 |
}
|
65 |
|
66 |
/**
|
@@ -85,9 +109,11 @@ final class HTML {
|
|
85 |
* @param bool $block Whether to wrap the content in <p> tags.
|
86 |
*/
|
87 |
public static function description_noesc( $content, $block = true ) {
|
88 |
-
|
89 |
-
|
90 |
-
|
|
|
|
|
91 |
}
|
92 |
|
93 |
/**
|
@@ -112,9 +138,11 @@ final class HTML {
|
|
112 |
* @param bool $block Whether to wrap the content in <p> tags.
|
113 |
*/
|
114 |
public static function attention_noesc( $content, $block = true ) {
|
115 |
-
|
116 |
-
|
117 |
-
|
|
|
|
|
118 |
}
|
119 |
|
120 |
/**
|
@@ -139,9 +167,11 @@ final class HTML {
|
|
139 |
* @param bool $block Whether to wrap the content in <p> tags.
|
140 |
*/
|
141 |
public static function attention_description_noesc( $content, $block = true ) {
|
142 |
-
|
143 |
-
|
144 |
-
|
|
|
|
|
145 |
}
|
146 |
|
147 |
/**
|
@@ -160,11 +190,13 @@ final class HTML {
|
|
160 |
if ( \is_array( $input ) )
|
161 |
$input = implode( PHP_EOL, $input );
|
162 |
|
|
|
|
|
163 |
if ( $echo ) {
|
164 |
// phpcs:ignore, WordPress.Security.EscapeOutput -- Escape your $input prior!
|
165 |
-
echo
|
166 |
} else {
|
167 |
-
return
|
168 |
}
|
169 |
}
|
170 |
|
@@ -184,7 +216,7 @@ final class HTML {
|
|
184 |
|
185 |
if ( $link ) {
|
186 |
$output = sprintf(
|
187 |
-
'<a href="%1$s" class="tsf-tooltip-item tsf-help" target=
|
188 |
\esc_url( $link, [ 'https', 'http' ] ),
|
189 |
\esc_attr( $description )
|
190 |
);
|
@@ -195,7 +227,7 @@ final class HTML {
|
|
195 |
);
|
196 |
}
|
197 |
|
198 |
-
$output = sprintf( '<span class=
|
199 |
|
200 |
if ( $echo ) {
|
201 |
// phpcs:ignore, WordPress.Security.EscapeOutput
|
@@ -212,37 +244,25 @@ final class HTML {
|
|
212 |
* @since 4.1.0 No longer adds an extra space in front of the return value when no data is generated.
|
213 |
* @internal
|
214 |
*
|
215 |
-
* @param
|
216 |
* string $k => mixed $v
|
217 |
* }
|
218 |
-
* @return string The HTML data attributes, with added space to the start.
|
219 |
*/
|
220 |
-
public static function make_data_attributes(
|
221 |
|
222 |
$ret = [];
|
223 |
|
224 |
foreach ( $data as $k => $v ) {
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
);
|
235 |
-
} else {
|
236 |
-
$ret[] = sprintf(
|
237 |
-
'data-%s="%s"',
|
238 |
-
strtolower( preg_replace(
|
239 |
-
'/([A-Z])/',
|
240 |
-
'-$1',
|
241 |
-
preg_replace( '/[^a-z0-9_\-]/i', '', $k )
|
242 |
-
) ), // dash case.
|
243 |
-
\esc_attr( $v )
|
244 |
-
);
|
245 |
-
}
|
246 |
}
|
247 |
|
248 |
return $ret ? ' ' . implode( ' ', $ret ) : '';
|
37 |
*/
|
38 |
final class HTML {
|
39 |
|
40 |
+
/**
|
41 |
+
* Helper function that constructs header elements. Does not escape.
|
42 |
+
*
|
43 |
+
* @since 4.1.4
|
44 |
+
*
|
45 |
+
* @param string $title The header title.
|
46 |
+
* @return string The header title.
|
47 |
+
*/
|
48 |
+
public static function get_header_title( $title ) {
|
49 |
+
return sprintf( '<h4>%s</h4>', $title );
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Helper function that constructs header elements.
|
54 |
+
*
|
55 |
+
* @since 4.1.4
|
56 |
+
*
|
57 |
+
* @param string $title The header title.
|
58 |
+
*/
|
59 |
+
public static function header_title( $title ) {
|
60 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- it is.
|
61 |
+
echo static::get_header_title( \esc_html( $title ) );
|
62 |
+
}
|
63 |
+
|
64 |
/**
|
65 |
* Mark up content with code tags.
|
66 |
* Escapes all HTML, so `<` gets changed to `<` and displays correctly.
|
84 |
* @return string Content wrapped in code tags.
|
85 |
*/
|
86 |
public static function code_wrap_noesc( $content ) {
|
87 |
+
return "<code>$content</code>";
|
88 |
}
|
89 |
|
90 |
/**
|
109 |
* @param bool $block Whether to wrap the content in <p> tags.
|
110 |
*/
|
111 |
public static function description_noesc( $content, $block = true ) {
|
112 |
+
printf(
|
113 |
+
( $block ? '<p>%s</p>' : '%s' ),
|
114 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput -- Method clearly states it's not escaped.
|
115 |
+
"<span class=description>$content</span>"
|
116 |
+
);
|
117 |
}
|
118 |
|
119 |
/**
|
138 |
* @param bool $block Whether to wrap the content in <p> tags.
|
139 |
*/
|
140 |
public static function attention_noesc( $content, $block = true ) {
|
141 |
+
printf(
|
142 |
+
( $block ? '<p>%s</p>' : '%s' ),
|
143 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput -- Method clearly states it's not escaped.
|
144 |
+
"<span class=attention>$content</span>"
|
145 |
+
);
|
146 |
}
|
147 |
|
148 |
/**
|
167 |
* @param bool $block Whether to wrap the content in <p> tags.
|
168 |
*/
|
169 |
public static function attention_description_noesc( $content, $block = true ) {
|
170 |
+
printf(
|
171 |
+
( $block ? '<p>%s</p>' : '%s' ),
|
172 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput -- Method clearly states it's not escaped.
|
173 |
+
"<span class=\"description attention\">$content</span>"
|
174 |
+
);
|
175 |
}
|
176 |
|
177 |
/**
|
190 |
if ( \is_array( $input ) )
|
191 |
$input = implode( PHP_EOL, $input );
|
192 |
|
193 |
+
$output = "<div class=tsf-fields>$input</div>";
|
194 |
+
|
195 |
if ( $echo ) {
|
196 |
// phpcs:ignore, WordPress.Security.EscapeOutput -- Escape your $input prior!
|
197 |
+
echo $output;
|
198 |
} else {
|
199 |
+
return $output;
|
200 |
}
|
201 |
}
|
202 |
|
216 |
|
217 |
if ( $link ) {
|
218 |
$output = sprintf(
|
219 |
+
'<a href="%1$s" class="tsf-tooltip-item tsf-help" target=_blank rel="nofollow noreferrer noopener" title="%2$s" data-desc="%2$s">[?]</a>',
|
220 |
\esc_url( $link, [ 'https', 'http' ] ),
|
221 |
\esc_attr( $description )
|
222 |
);
|
227 |
);
|
228 |
}
|
229 |
|
230 |
+
$output = sprintf( '<span class=tsf-tooltip-wrap>%s</span>', $output );
|
231 |
|
232 |
if ( $echo ) {
|
233 |
// phpcs:ignore, WordPress.Security.EscapeOutput
|
244 |
* @since 4.1.0 No longer adds an extra space in front of the return value when no data is generated.
|
245 |
* @internal
|
246 |
*
|
247 |
+
* @param iterable $data : {
|
248 |
* string $k => mixed $v
|
249 |
* }
|
250 |
+
* @return string The HTML data attributes, with added space to the start if something's created.
|
251 |
*/
|
252 |
+
public static function make_data_attributes( $data ) {
|
253 |
|
254 |
$ret = [];
|
255 |
|
256 |
foreach ( $data as $k => $v ) {
|
257 |
+
$ret[] = sprintf(
|
258 |
+
'data-%s="%s"',
|
259 |
+
strtolower( preg_replace(
|
260 |
+
'/([A-Z])/',
|
261 |
+
'-$1',
|
262 |
+
preg_replace( '/[^a-z0-9_\-]/i', '', $k )
|
263 |
+
) ), // dash case.
|
264 |
+
is_scalar( $v ) ? \esc_attr( $v ) : htmlspecialchars( json_encode( $v, JSON_UNESCAPED_SLASHES ), ENT_COMPAT, 'UTF-8' )
|
265 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
266 |
}
|
267 |
|
268 |
return $ret ? ' ' . implode( ' ', $ret ) : '';
|
@@ -29,7 +29,9 @@ namespace The_SEO_Framework\Interpreters;
|
|
29 |
* Interprets anything you send here into Markdown. Or so it should.
|
30 |
*
|
31 |
* @since 4.1.4
|
32 |
-
* @note Use `
|
|
|
|
|
33 |
*
|
34 |
* @access protected
|
35 |
* Everything in this class is subject to change or deletion.
|
@@ -85,9 +87,8 @@ final class Markdown {
|
|
85 |
|
86 |
$md_types = empty( $convert ) ? $conversions : array_intersect( $conversions, $convert );
|
87 |
|
88 |
-
if (
|
89 |
$text = static::strong_em( $text );
|
90 |
-
endif;
|
91 |
|
92 |
foreach ( $md_types as $type ) :
|
93 |
switch ( $type ) :
|
@@ -136,6 +137,7 @@ final class Markdown {
|
|
136 |
private static function strong_em( $text ) {
|
137 |
|
138 |
$count = preg_match_all( '/(?:\*{3})([^\*{\3}]+)(?:\*{3})/', $text, $matches, PREG_PATTERN_ORDER );
|
|
|
139 |
for ( $i = 0; $i < $count; $i++ ) {
|
140 |
$text = str_replace(
|
141 |
$matches[0][ $i ],
|
@@ -259,6 +261,7 @@ final class Markdown {
|
|
259 |
|
260 |
$count = preg_match_all( '/(?:(?:\[{1})([^\]]+)(?:\]{1})(?:\({1})([^\)\(]+)(?:\){1}))/', $text, $matches, PREG_PATTERN_ORDER );
|
261 |
|
|
|
262 |
$_string = $internal ? '<a href="%s">%s</a>' : '<a href="%s" target="_blank" rel="nofollow noreferrer noopener">%s</a>';
|
263 |
|
264 |
for ( $i = 0; $i < $count; $i++ ) {
|
29 |
* Interprets anything you send here into Markdown. Or so it should.
|
30 |
*
|
31 |
* @since 4.1.4
|
32 |
+
* @note Use `tsf()->convert_markdown() for easy access.
|
33 |
+
*
|
34 |
+
* @NOTE to self: This is also used in XHTML configurations. Keep it strict!
|
35 |
*
|
36 |
* @access protected
|
37 |
* Everything in this class is subject to change or deletion.
|
87 |
|
88 |
$md_types = empty( $convert ) ? $conversions : array_intersect( $conversions, $convert );
|
89 |
|
90 |
+
if ( isset( $md_types['*'], $md_types['**'] ) )
|
91 |
$text = static::strong_em( $text );
|
|
|
92 |
|
93 |
foreach ( $md_types as $type ) :
|
94 |
switch ( $type ) :
|
137 |
private static function strong_em( $text ) {
|
138 |
|
139 |
$count = preg_match_all( '/(?:\*{3})([^\*{\3}]+)(?:\*{3})/', $text, $matches, PREG_PATTERN_ORDER );
|
140 |
+
|
141 |
for ( $i = 0; $i < $count; $i++ ) {
|
142 |
$text = str_replace(
|
143 |
$matches[0][ $i ],
|
261 |
|
262 |
$count = preg_match_all( '/(?:(?:\[{1})([^\]]+)(?:\]{1})(?:\({1})([^\)\(]+)(?:\){1}))/', $text, $matches, PREG_PATTERN_ORDER );
|
263 |
|
264 |
+
// Keep this XHTML compatible!
|
265 |
$_string = $internal ? '<a href="%s">%s</a>' : '<a href="%s" target="_blank" rel="nofollow noreferrer noopener">%s</a>';
|
266 |
|
267 |
for ( $i = 0; $i < $count; $i++ ) {
|
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
/**
|
3 |
-
* @package The_SEO_Framework\Classes\Interpreters\
|
4 |
-
* @subpackage The_SEO_Framework\
|
5 |
*/
|
6 |
|
7 |
namespace The_SEO_Framework\Interpreters;
|
@@ -25,23 +25,37 @@ namespace The_SEO_Framework\Interpreters;
|
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
|
|
|
|
28 |
/**
|
29 |
* Interprets the SEO Bar into an HTML item.
|
30 |
*
|
31 |
* @since 4.0.0
|
32 |
-
* @see \
|
33 |
*
|
34 |
* @access public
|
35 |
* Note that you can't instance this class. Only static methods and properties are accessible.
|
36 |
* @final Can't be extended.
|
37 |
*/
|
38 |
-
final class
|
39 |
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
/**
|
47 |
* @since 4.0.0
|
@@ -51,27 +65,23 @@ final class SeoBar {
|
|
51 |
|
52 |
/**
|
53 |
* @since 4.0.0
|
54 |
-
* @var \The_SEO_Framework\Interpreters\
|
55 |
*/
|
56 |
private static $instance;
|
57 |
|
58 |
/**
|
59 |
* @since 4.0.0
|
60 |
-
* @var array $item The current SEO Bar item list
|
61 |
-
*
|
|
|
|
|
|
|
|
|
|
|
62 |
* }
|
63 |
*/
|
64 |
private static $items = [];
|
65 |
|
66 |
-
/**
|
67 |
-
* Constructor.
|
68 |
-
*
|
69 |
-
* @since 4.0.0
|
70 |
-
*/
|
71 |
-
private function __construct() {
|
72 |
-
static::$instance = &$this;
|
73 |
-
}
|
74 |
-
|
75 |
/**
|
76 |
* Returns this instance.
|
77 |
*
|
@@ -80,8 +90,7 @@ final class SeoBar {
|
|
80 |
* @return static
|
81 |
*/
|
82 |
private static function get_instance() {
|
83 |
-
static::$instance
|
84 |
-
return static::$instance;
|
85 |
}
|
86 |
|
87 |
/**
|
@@ -93,21 +102,22 @@ final class SeoBar {
|
|
93 |
* @param array $query : {
|
94 |
* int $id : Required. The current post or term ID.
|
95 |
* string $taxonomy : Optional. If not set, this will interpret it as a post.
|
|
|
96 |
* string $post_type : Optional. If not set, this will be automatically filled.
|
97 |
* This parameter is ignored for taxonomies.
|
|
|
|
|
98 |
* }
|
99 |
* @return string The SEO Bar.
|
100 |
*/
|
101 |
-
public static function generate_bar(
|
102 |
-
|
103 |
-
static::$query =
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
$query
|
110 |
-
);
|
111 |
|
112 |
if ( ! static::$query['id'] ) return '';
|
113 |
|
@@ -115,13 +125,13 @@ final class SeoBar {
|
|
115 |
static::$query['post_type'] = static::$query['post_type'] ?: \get_post_type( static::$query['id'] );
|
116 |
|
117 |
if ( static::$query['taxonomy'] ) {
|
118 |
-
$builder = \The_SEO_Framework\Builders\
|
119 |
} else {
|
120 |
-
$builder = \The_SEO_Framework\Builders\
|
121 |
}
|
122 |
|
123 |
$instance = static::get_instance();
|
124 |
-
$instance->
|
125 |
|
126 |
/**
|
127 |
* Add or adjust SEO Bar items here, after the tests have run.
|
@@ -148,7 +158,14 @@ final class SeoBar {
|
|
148 |
* @since 4.1.1 Is now static.
|
149 |
* @collector
|
150 |
*
|
151 |
-
* @return array SEO Bar items. Passed by reference.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
*/
|
153 |
public static function &collect_seo_bar_items() {
|
154 |
return static::$items;
|
@@ -169,7 +186,7 @@ final class SeoBar {
|
|
169 |
* Does not accept HTML for performant ARIA support.
|
170 |
* }
|
171 |
*/
|
172 |
-
public static function register_seo_bar_item( $key,
|
173 |
static::$items[ $key ] = $item;
|
174 |
}
|
175 |
|
@@ -217,9 +234,9 @@ final class SeoBar {
|
|
217 |
* @since 4.1.4 Offloaded the builder's instantiation.
|
218 |
* @factory
|
219 |
*
|
220 |
-
* @param \The_SEO_Framework\Builders\
|
221 |
*/
|
222 |
-
private function
|
223 |
|
224 |
/**
|
225 |
* Adjust interpreter and builder items here, before the tests have run.
|
@@ -230,14 +247,14 @@ final class SeoBar {
|
|
230 |
* @link Example: https://gist.github.com/sybrew/03dd428deadc860309879e1d5208e1c4
|
231 |
* @see related (recommended) action 'the_seo_framework_seo_bar'
|
232 |
* @since 4.0.0
|
233 |
-
* @param string
|
234 |
-
* @param \The_SEO_Framework\Builders\
|
235 |
*/
|
236 |
\do_action_ref_array( 'the_seo_framework_prepare_seo_bar', [ static::class, $builder ] );
|
237 |
|
238 |
$items = &$this->collect_seo_bar_items();
|
239 |
|
240 |
-
foreach ( $builder->
|
241 |
$items[ $key ] = $data;
|
242 |
}
|
243 |
|
@@ -246,10 +263,10 @@ final class SeoBar {
|
|
246 |
*
|
247 |
* @since 4.0.0
|
248 |
*
|
249 |
-
* @param
|
250 |
* @return string The SEO Bar
|
251 |
*/
|
252 |
-
private function create_seo_bar(
|
253 |
|
254 |
$blocks = [];
|
255 |
|
@@ -274,10 +291,10 @@ final class SeoBar {
|
|
274 |
* WordPress still hangs on tight to their PHP5.2 roots, where HTML4+ escaping wasn't supported well. Updating that requires
|
275 |
* a whole lot of time, and paves way for potential security issues due to oversight. But, that'd speed up escaping for everyone.
|
276 |
*
|
277 |
-
* @param
|
278 |
* @yield The SEO Bar HTML item.
|
279 |
*/
|
280 |
-
private function generate_seo_bar_blocks(
|
281 |
foreach ( $items as $item )
|
282 |
yield vsprintf(
|
283 |
'<span class="tsf-seo-bar-section-wrap tsf-tooltip-wrap"><span class="tsf-seo-bar-item tsf-tooltip-item tsf-seo-bar-%1$s" title="%2$s" aria-label="%2$s" data-desc="%3$s" tabindex=0>%4$s</span></span>',
|
@@ -300,7 +317,7 @@ final class SeoBar {
|
|
300 |
* @param string $type The description type. Accepts 'html' or 'aria'.
|
301 |
* @return string The SEO Bar item description.
|
302 |
*/
|
303 |
-
private function build_item_description(
|
304 |
|
305 |
static $gettext = null;
|
306 |
if ( null === $gettext ) {
|
@@ -341,7 +358,7 @@ final class SeoBar {
|
|
341 |
* @param array $item See `$this->register_seo_bar_item()`
|
342 |
* @return string The SEO Bar item assessment, in plaintext.
|
343 |
*/
|
344 |
-
private function enumerate_assessment_list(
|
345 |
|
346 |
$count = \count( $item['assess'] );
|
347 |
$assessments = [];
|
@@ -425,14 +442,12 @@ final class SeoBar {
|
|
425 |
* @param array $item See `$this->register_seo_bar_item()`
|
426 |
* @return string The SEO Bar item assessment, in plaintext.
|
427 |
*/
|
428 |
-
private function interpret_status_to_symbol(
|
429 |
|
430 |
-
|
431 |
-
|
432 |
-
$use_symbols = (bool) \the_seo_framework()->get_option( 'seo_bar_symbols' );
|
433 |
-
}
|
434 |
|
435 |
-
if ( $
|
436 |
switch ( $item['status'] ) :
|
437 |
case static::STATE_OKAY:
|
438 |
$symbol = '!?';
|
1 |
<?php
|
2 |
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Interpreters\SEOBar
|
4 |
+
* @subpackage The_SEO_Framework\SEOBar
|
5 |
*/
|
6 |
|
7 |
namespace The_SEO_Framework\Interpreters;
|
25 |
|
26 |
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
|
28 |
+
use function \The_SEO_Framework\umemo;
|
29 |
+
|
30 |
/**
|
31 |
* Interprets the SEO Bar into an HTML item.
|
32 |
*
|
33 |
* @since 4.0.0
|
34 |
+
* @see \tsf()->get_generated_seo_bar( $args ) for easy access.
|
35 |
*
|
36 |
* @access public
|
37 |
* Note that you can't instance this class. Only static methods and properties are accessible.
|
38 |
* @final Can't be extended.
|
39 |
*/
|
40 |
+
final class SEOBar {
|
41 |
|
42 |
+
/**
|
43 |
+
* The recognized SEO Bar item states.
|
44 |
+
* Mixed types will fall back to 'undefined'.
|
45 |
+
*
|
46 |
+
* @since 4.1.0
|
47 |
+
* @access public
|
48 |
+
* @var int <bit 0> STATE_UNDEFINED
|
49 |
+
* @var int <bit 1> STATE_UNKNOWN
|
50 |
+
* @var int <bit 10> STATE_BAD
|
51 |
+
* @var int <bit 100> STATE_OKAY
|
52 |
+
* @var int <bit 1000> STATE_GOOD
|
53 |
+
*/
|
54 |
+
public const STATE_UNDEFINED = 0b0000;
|
55 |
+
public const STATE_UNKNOWN = 0b0001;
|
56 |
+
public const STATE_BAD = 0b0010;
|
57 |
+
public const STATE_OKAY = 0b0100;
|
58 |
+
public const STATE_GOOD = 0b1000;
|
59 |
|
60 |
/**
|
61 |
* @since 4.0.0
|
65 |
|
66 |
/**
|
67 |
* @since 4.0.0
|
68 |
+
* @var \The_SEO_Framework\Interpreters\SEOBar $instance The instance.
|
69 |
*/
|
70 |
private static $instance;
|
71 |
|
72 |
/**
|
73 |
* @since 4.0.0
|
74 |
+
* @var array $item The current SEO Bar item list. {
|
75 |
+
* string $symbol : The displayed symbol that identifies your bar.
|
76 |
+
* string $title : The title of the assessment.
|
77 |
+
* string $status : Accepts 'good', 'okay', 'bad', 'unknown'.
|
78 |
+
* string $reason : The final assessment: The reason for the $status.
|
79 |
+
* string $assess : The assessments on why the reason is set. Keep it short and concise!
|
80 |
+
* Does not accept HTML for performant ARIA support.
|
81 |
* }
|
82 |
*/
|
83 |
private static $items = [];
|
84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
/**
|
86 |
* Returns this instance.
|
87 |
*
|
90 |
* @return static
|
91 |
*/
|
92 |
private static function get_instance() {
|
93 |
+
return static::$instance ?? ( static::$instance = new static );
|
|
|
94 |
}
|
95 |
|
96 |
/**
|
102 |
* @param array $query : {
|
103 |
* int $id : Required. The current post or term ID.
|
104 |
* string $taxonomy : Optional. If not set, this will interpret it as a post.
|
105 |
+
* string $pta : Not implemented. Do not populate.
|
106 |
* string $post_type : Optional. If not set, this will be automatically filled.
|
107 |
* This parameter is ignored for taxonomies.
|
108 |
+
* This parameter will become obsolete once WP fixes its post cache.
|
109 |
+
* <https://core.trac.wordpress.org/ticket/50567>
|
110 |
* }
|
111 |
* @return string The SEO Bar.
|
112 |
*/
|
113 |
+
public static function generate_bar( $query ) {
|
114 |
+
|
115 |
+
static::$query = $query + [
|
116 |
+
'id' => 0,
|
117 |
+
'taxonomy' => '',
|
118 |
+
'pta' => '',
|
119 |
+
'post_type' => '',
|
120 |
+
];
|
|
|
|
|
121 |
|
122 |
if ( ! static::$query['id'] ) return '';
|
123 |
|
125 |
static::$query['post_type'] = static::$query['post_type'] ?: \get_post_type( static::$query['id'] );
|
126 |
|
127 |
if ( static::$query['taxonomy'] ) {
|
128 |
+
$builder = \The_SEO_Framework\Builders\SEOBar\Term::get_instance();
|
129 |
} else {
|
130 |
+
$builder = \The_SEO_Framework\Builders\SEOBar\Page::get_instance();
|
131 |
}
|
132 |
|
133 |
$instance = static::get_instance();
|
134 |
+
$instance->store_seo_bar_items( $builder );
|
135 |
|
136 |
/**
|
137 |
* Add or adjust SEO Bar items here, after the tests have run.
|
158 |
* @since 4.1.1 Is now static.
|
159 |
* @collector
|
160 |
*
|
161 |
+
* @return array SEO Bar items. Passed by reference. {
|
162 |
+
* string $symbol : The displayed symbol that identifies your bar.
|
163 |
+
* string $title : The title of the assessment.
|
164 |
+
* string $status : Accepts 'good', 'okay', 'bad', 'unknown'.
|
165 |
+
* string $reason : The final assessment: The reason for the $status.
|
166 |
+
* string $assess : The assessments on why the reason is set. Keep it short and concise!
|
167 |
+
* Does not accept HTML for performant ARIA support.
|
168 |
+
* }
|
169 |
*/
|
170 |
public static function &collect_seo_bar_items() {
|
171 |
return static::$items;
|
186 |
* Does not accept HTML for performant ARIA support.
|
187 |
* }
|
188 |
*/
|
189 |
+
public static function register_seo_bar_item( $key, $item ) {
|
190 |
static::$items[ $key ] = $item;
|
191 |
}
|
192 |
|
234 |
* @since 4.1.4 Offloaded the builder's instantiation.
|
235 |
* @factory
|
236 |
*
|
237 |
+
* @param \The_SEO_Framework\Builders\SEOBar\Main $builder The builder instance.
|
238 |
*/
|
239 |
+
private function store_seo_bar_items( $builder ) {
|
240 |
|
241 |
/**
|
242 |
* Adjust interpreter and builder items here, before the tests have run.
|
247 |
* @link Example: https://gist.github.com/sybrew/03dd428deadc860309879e1d5208e1c4
|
248 |
* @see related (recommended) action 'the_seo_framework_seo_bar'
|
249 |
* @since 4.0.0
|
250 |
+
* @param string $interpreter The current class name.
|
251 |
+
* @param \The_SEO_Framework\Builders\SEOBar\Main $builder The builder object.
|
252 |
*/
|
253 |
\do_action_ref_array( 'the_seo_framework_prepare_seo_bar', [ static::class, $builder ] );
|
254 |
|
255 |
$items = &$this->collect_seo_bar_items();
|
256 |
|
257 |
+
foreach ( $builder->_run_all_tests( static::$query ) as $key => $data )
|
258 |
$items[ $key ] = $data;
|
259 |
}
|
260 |
|
263 |
*
|
264 |
* @since 4.0.0
|
265 |
*
|
266 |
+
* @param iterable $items The SEO Bar items.
|
267 |
* @return string The SEO Bar
|
268 |
*/
|
269 |
+
private function create_seo_bar( $items ) {
|
270 |
|
271 |
$blocks = [];
|
272 |
|
291 |
* WordPress still hangs on tight to their PHP5.2 roots, where HTML4+ escaping wasn't supported well. Updating that requires
|
292 |
* a whole lot of time, and paves way for potential security issues due to oversight. But, that'd speed up escaping for everyone.
|
293 |
*
|
294 |
+
* @param iterable $items The SEO Bar items.
|
295 |
* @yield The SEO Bar HTML item.
|
296 |
*/
|
297 |
+
private function generate_seo_bar_blocks( $items ) {
|
298 |
foreach ( $items as $item )
|
299 |
yield vsprintf(
|
300 |
'<span class="tsf-seo-bar-section-wrap tsf-tooltip-wrap"><span class="tsf-seo-bar-item tsf-tooltip-item tsf-seo-bar-%1$s" title="%2$s" aria-label="%2$s" data-desc="%3$s" tabindex=0>%4$s</span></span>',
|
317 |
* @param string $type The description type. Accepts 'html' or 'aria'.
|
318 |
* @return string The SEO Bar item description.
|
319 |
*/
|
320 |
+
private function build_item_description( $item, $type ) {
|
321 |
|
322 |
static $gettext = null;
|
323 |
if ( null === $gettext ) {
|
358 |
* @param array $item See `$this->register_seo_bar_item()`
|
359 |
* @return string The SEO Bar item assessment, in plaintext.
|
360 |
*/
|
361 |
+
private function enumerate_assessment_list( $item ) {
|
362 |
|
363 |
$count = \count( $item['assess'] );
|
364 |
$assessments = [];
|
442 |
* @param array $item See `$this->register_seo_bar_item()`
|
443 |
* @return string The SEO Bar item assessment, in plaintext.
|
444 |
*/
|
445 |
+
private function interpret_status_to_symbol( $item ) {
|
446 |
|
447 |
+
$symbols = umemo( __METHOD__ . '/use_symbols' )
|
448 |
+
?? umemo( __METHOD__ . '/use_symbols', (bool) \tsf()->get_option( 'seo_bar_symbols' ) );
|
|
|
|
|
449 |
|
450 |
+
if ( $symbols && $item['status'] ^ static::STATE_GOOD ) {
|
451 |
switch ( $item['status'] ) :
|
452 |
case static::STATE_OKAY:
|
453 |
$symbol = '!?';
|
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Interpreters\Settings_Input
|
4 |
+
* @subpackage The_SEO_Framework\Admin\Settings
|
5 |
+
*/
|
6 |
+
|
7 |
+
namespace The_SEO_Framework\Interpreters;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* The SEO Framework plugin
|
11 |
+
* Copyright (C) 2021 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/)
|
12 |
+
*
|
13 |
+
* This program is free software: you can redistribute it and/or modify
|
14 |
+
* it under the terms of the GNU General Public License version 3 as published
|
15 |
+
* by the Free Software Foundation.
|
16 |
+
*
|
17 |
+
* This program is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
* GNU General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU General Public License
|
23 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
+
*/
|
25 |
+
|
26 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Interprets anything you send here into Form HTML. Or so it should.
|
30 |
+
* Meant for the SEO Settings page, only.
|
31 |
+
*
|
32 |
+
* @since 4.2.0
|
33 |
+
*
|
34 |
+
* @access protected
|
35 |
+
* Everything in this class is subject to change or deletion.
|
36 |
+
* @internal
|
37 |
+
* @final Can't be extended.
|
38 |
+
*/
|
39 |
+
final class Settings_Input {
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Helper function that constructs id attributes for use in form fields.
|
43 |
+
*
|
44 |
+
* One-liner I forwent:
|
45 |
+
* return THE_SEO_FRAMEWORK_SITE_OPTIONS . '['. implode( '][', $id ) . ']';
|
46 |
+
*
|
47 |
+
* @since 4.2.0
|
48 |
+
*
|
49 |
+
* @param string|string[] $id The field id, or a map of indexes therefor.
|
50 |
+
* @return string Full field id
|
51 |
+
*/
|
52 |
+
public static function get_field_id( $id ) {
|
53 |
+
|
54 |
+
$field_id = THE_SEO_FRAMEWORK_SITE_OPTIONS;
|
55 |
+
|
56 |
+
foreach ( (array) $id as $subid )
|
57 |
+
$field_id .= "[$subid]";
|
58 |
+
|
59 |
+
return $field_id;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Echo constructed id attributes in form fields.
|
64 |
+
*
|
65 |
+
* @since 4.2.0
|
66 |
+
* @uses static::get_field_id() Constructs id attributes for use in form fields.
|
67 |
+
*
|
68 |
+
* @param string|string[] $id The field id, or a map of indexes therefor.
|
69 |
+
*/
|
70 |
+
public static function field_id( $id ) {
|
71 |
+
echo \esc_attr( static::get_field_id( $id ) );
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Helper function that constructs name attributes for use in form fields.
|
76 |
+
*
|
77 |
+
* Alias of field_id.
|
78 |
+
*
|
79 |
+
* @since 4.2.0
|
80 |
+
* @ignore
|
81 |
+
*
|
82 |
+
* @param string|string[] $name The field name, or a map of indexes therefor.
|
83 |
+
* @return string Full field name
|
84 |
+
*/
|
85 |
+
public static function get_field_name( $name ) {
|
86 |
+
return static::get_field_id( $name );
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Echo constructed name attributes in form fields.
|
91 |
+
*
|
92 |
+
* Alias of field_id.
|
93 |
+
*
|
94 |
+
* @since 4.2.0
|
95 |
+
* @uses static::get_field_name() Construct name attributes for use in form fields.
|
96 |
+
* @ignore
|
97 |
+
*
|
98 |
+
* @param string|string[] $name The field name, or a map of indexes therefor.
|
99 |
+
*/
|
100 |
+
public static function field_name( $name ) {
|
101 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- field_id escapes.
|
102 |
+
echo static::field_id( $name );
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Returns a chechbox wrapper.
|
107 |
+
*
|
108 |
+
* This is put in this class, instead of Form, because
|
109 |
+
* 1) Retrieves the global settings ID from input.
|
110 |
+
* 2) Retrieves the default-state of the checkbox via the global settings.
|
111 |
+
*
|
112 |
+
* @since 4.2.0
|
113 |
+
*
|
114 |
+
* @param array $args : {
|
115 |
+
* string|map $id The option index or map of indexes therefor, used as field ID.
|
116 |
+
* string $class The checkbox class.
|
117 |
+
* string $label The checkbox label description, placed inline of the checkbox.
|
118 |
+
* null|mixed $value The option value. If not set, it'll try to retrieve the value based on $id.
|
119 |
+
* string $description The checkbox additional description, placed underneat.
|
120 |
+
* array $data The checkbox field data. Sub-items are expected to be escaped if they're not an array.
|
121 |
+
* bool $escape Whether to enable escaping of the $label and $description.
|
122 |
+
* bool $disabled Whether to disable the checkbox field.
|
123 |
+
* }
|
124 |
+
* @return string HTML checkbox output.
|
125 |
+
*/
|
126 |
+
public static function make_checkbox( $args = [] ) {
|
127 |
+
|
128 |
+
$args = array_merge(
|
129 |
+
[
|
130 |
+
'id' => '',
|
131 |
+
'class' => '',
|
132 |
+
'label' => '',
|
133 |
+
'value' => null,
|
134 |
+
'description' => '',
|
135 |
+
'data' => [],
|
136 |
+
'escape' => true,
|
137 |
+
'disabled' => false,
|
138 |
+
],
|
139 |
+
$args
|
140 |
+
);
|
141 |
+
|
142 |
+
if ( $args['escape'] ) {
|
143 |
+
$args['description'] = \esc_html( $args['description'] );
|
144 |
+
$args['label'] = \esc_html( $args['label'] );
|
145 |
+
}
|
146 |
+
|
147 |
+
$tsf = \tsf();
|
148 |
+
|
149 |
+
$field_id = $field_name = static::get_field_id( $args['id'] );
|
150 |
+
$value = $args['value'] ?? $tsf->get_option( $args['id'] );
|
151 |
+
|
152 |
+
$cb_classes = [];
|
153 |
+
|
154 |
+
if ( $args['class'] )
|
155 |
+
$cb_classes[] = $args['class'];
|
156 |
+
|
157 |
+
if ( $args['disabled'] ) {
|
158 |
+
$cb_classes[] = 'tsf-disabled';
|
159 |
+
} else {
|
160 |
+
array_push( $cb_classes, ...static::get_conditional_checked_classes( $args['id'] ) );
|
161 |
+
}
|
162 |
+
|
163 |
+
$output = sprintf(
|
164 |
+
'<span class="tsf-toblock">%s</span>',
|
165 |
+
vsprintf(
|
166 |
+
'<label for="%s"%s>%s</label>',
|
167 |
+
[
|
168 |
+
$tsf->s_field_id( $field_id ),
|
169 |
+
( $args['disabled'] ? ' class="tsf-disabled"' : '' ),
|
170 |
+
vsprintf(
|
171 |
+
'<input type=checkbox class="%s" name="%s" id="%s" value="1" %s%s %s /> %s',
|
172 |
+
[
|
173 |
+
\esc_attr( implode( ' ', array_filter( $cb_classes ) ) ),
|
174 |
+
$tsf->s_field_id( $field_name ),
|
175 |
+
$tsf->s_field_id( $field_id ),
|
176 |
+
\checked( $value, true, false ),
|
177 |
+
( $args['disabled'] ? ' disabled' : '' ),
|
178 |
+
HTML::make_data_attributes( $args['data'] ),
|
179 |
+
$args['label'],
|
180 |
+
]
|
181 |
+
),
|
182 |
+
]
|
183 |
+
)
|
184 |
+
);
|
185 |
+
|
186 |
+
return $output .= (
|
187 |
+
$args['description']
|
188 |
+
? sprintf( '<p class="description tsf-option-spacer">%s</p>', $args['description'] )
|
189 |
+
: ''
|
190 |
+
);
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Returns the HTML class wrap for warning/default Checkbox options.
|
195 |
+
*
|
196 |
+
* @since 4.2.0
|
197 |
+
*
|
198 |
+
* @param string|string[] $key Required. The option name, or a map of indexes therefor.
|
199 |
+
* @return string[] The conditional checked classes.
|
200 |
+
*/
|
201 |
+
public static function get_conditional_checked_classes( $key ) {
|
202 |
+
$tsf = \tsf();
|
203 |
+
return [
|
204 |
+
$tsf->get_default_option( $key ) ? 'tsf-default-selected' : '',
|
205 |
+
$tsf->get_warned_option( $key ) ? 'tsf-warning-selected' : '',
|
206 |
+
];
|
207 |
+
}
|
208 |
+
}
|
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package The_SEO_Framework\Classes\Interpreters\Sitemap\XSL
|
4 |
+
* @subpackage The_SEO_Framework\Sitemap\XSL
|
5 |
+
*/
|
6 |
+
|
7 |
+
namespace The_SEO_Framework\Interpreters;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* The SEO Framework plugin
|
11 |
+
* Copyright (C) 2021 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/)
|
12 |
+
*
|
13 |
+
* This program is free software: you can redistribute it and/or modify
|
14 |
+
* it under the terms of the GNU General Public License version 3 as published
|
15 |
+
* by the Free Software Foundation.
|
16 |
+
*
|
17 |
+
* This program is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
+
* GNU General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU General Public License
|
23 |
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24 |
+
*/
|
25 |
+
|
26 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
|
27 |
+
|
28 |
+
use function \The_SEO_Framework\umemo;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Interprets the Sitemap Stylesheet of the optimized Sitemap.
|
32 |
+
*
|
33 |
+
* @since 4.2.0
|
34 |
+
*
|
35 |
+
* @access private
|
36 |
+
* @final Can't be extended.
|
37 |
+
*/
|
38 |
+
final class Sitemap_XSL {
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Prepares the sitemap stylesheet: loads all actions.
|
42 |
+
*
|
43 |
+
* @since 4.2.0
|
44 |
+
*/
|
45 |
+
public static function prepare() {
|
46 |
+
|
47 |
+
$class = static::class;
|
48 |
+
|
49 |
+
// Adds site icon tags to the sitemap stylesheet.
|
50 |
+
\add_action( 'the_seo_framework_xsl_head', 'wp_site_icon', 99 );
|
51 |
+
|
52 |
+
\add_action( 'the_seo_framework_xsl_head', "$class::_print_xsl_global_variables", 0 );
|
53 |
+
\add_action( 'the_seo_framework_xsl_head', "$class::_print_xsl_title" );
|
54 |
+
\add_action( 'the_seo_framework_xsl_head', "$class::_print_xsl_styles" );
|
55 |
+
|
56 |
+
\add_action( 'the_seo_framework_xsl_description', "$class::_print_xsl_description" );
|
57 |
+
|
58 |
+
\add_action( 'the_seo_framework_xsl_content', "$class::_print_xsl_content" );
|
59 |
+
|
60 |
+
\add_action( 'the_seo_framework_xsl_footer', "$class::_print_xsl_footer" );
|
61 |
+
\add_action( 'site_icon_meta_tags', "$class::_convert_site_icon_meta_tags", PHP_INT_MAX );
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Prints global XSL variables.
|
66 |
+
*
|
67 |
+
* @since 3.1.0
|
68 |
+
* @since 4.2.0 1. $tableMinWidth no longer adds 'px'.
|
69 |
+
* 2. Moved to class.
|
70 |
+
* @access private
|
71 |
+
* @param \The_SEO_Framework\Load $tsf tsf() object.
|
72 |
+
*/
|
73 |
+
public static function _print_xsl_global_variables( $tsf ) {
|
74 |
+
$tsf->get_view( 'sitemap/xsl/vars' );
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Prints XSL title.
|
79 |
+
*
|
80 |
+
* @since 3.1.0
|
81 |
+
* @since 4.0.0 Now uses a consistent titling scheme.
|
82 |
+
* @since 4.2.0 Moved to class
|
83 |
+
* @access private
|
84 |
+
* @param \The_SEO_Framework\Load $tsf tsf() object.
|
85 |
+
*/
|
86 |
+
public static function _print_xsl_title( $tsf ) {
|
87 |
+
$tsf->get_view( 'sitemap/xsl/title' );
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Prints XSL styles.
|
92 |
+
*
|
93 |
+
* @since 3.1.0
|
94 |
+
* @since 4.2.0 1. Centered sitemap.
|
95 |
+
* 2. Moved to class.
|
96 |
+
* @access private
|
97 |
+
* @param \The_SEO_Framework\Load $tsf tsf() object.
|
98 |
+
*/
|
99 |
+
public static function _print_xsl_styles( $tsf ) {
|
100 |
+
$tsf->get_view( 'sitemap/xsl/styles' );
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Prints XSL description.
|
105 |
+
*
|
106 |
+
* @since 3.1.0
|
107 |
+
* @since 4.2.0 Moved to class;
|
108 |
+
*
|
109 |
+
* @access private
|
110 |
+
* @param \The_SEO_Framework\Load $tsf tsf() object.
|
111 |
+
*/
|
112 |
+
public static function _print_xsl_description( $tsf ) {
|
113 |
+
$tsf->get_view( 'sitemap/xsl/description' );
|
114 |
+
}
|
115 |
+
/**
|
116 |
+
* Prints XSL content.
|
117 |
+
*
|
118 |
+
* @since 3.1.0
|
119 |
+
* @since 4.2.0 Moved to class.
|
120 |
+
*
|
121 |
+
* @param \The_SEO_Framework\Load $tsf tsf() object.
|
122 |
+
*/
|
123 |
+
public static function _print_xsl_content( $tsf ) {
|
124 |
+
$tsf->get_view( 'sitemap/xsl/table' );
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Prints XSL footer.
|
129 |
+
*
|
130 |
+
* @since 3.1.0
|
131 |
+
* @since 4.2.0 Moved to class
|
132 |
+
* @access private
|
133 |
+
*
|
134 |
+
* @param \The_SEO_Framework\Load $tsf tsf() object.
|
135 |
+
*/
|
136 |
+
public static function _print_xsl_footer( $tsf ) {
|
137 |
+
/**
|
138 |
+
* @since 2.8.0
|
139 |
+
* @param bool $indicator
|
140 |
+
*/
|
141 |
+
\apply_filters( 'the_seo_framework_indicator_sitemap', true )
|
142 |
+
and $tsf->get_view( 'sitemap/xsl/footer' );
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Converts meta tags that aren't XHTML to XHTML, loosely.
|
147 |
+
* Doesn't fix attribute minimization. TODO?..
|
148 |
+
*
|
149 |
+
* @since 3.1.4
|
150 |
+
* @since 4.2.0 Moved to class.
|
151 |
+
*
|
152 |
+
* @param array $tags Site Icon meta elements.
|
153 |
+
* @return array The converted meta tags.
|
154 |
+
*/
|
155 |
+
public static function _convert_site_icon_meta_tags( $tags ) {
|
156 |
+
|
157 |
+
foreach ( $tags as &$tag ) {
|
158 |
+
$tag = \wp_kses(
|
159 |
+
\force_balance_tags( $tag ),
|
160 |
+
[
|
161 |
+
'link' => [
|
162 |
+
'charset' => [],
|
163 |
+
'rel' => [],
|
164 |
+
'sizes' => [],
|
165 |
+
'href' => [],
|
166 |
+
'hreflang' => [],
|
167 |
+
'media' => [],
|
168 |
+
'rev' => [],
|
169 |
+
'target' => [],
|
170 |
+
'type' => [],
|
171 |
+
],
|
172 |
+
'meta' => [
|
173 |
+
'content' => [],
|
174 |
+
'property' => [],
|
175 |
+
'http-equiv' => [],
|
176 |
+
'name' => [],
|
177 |
+
'scheme' => [],
|
178 |
+
],
|
179 |
+
],
|
180 |
+
[]
|
181 |
+
);
|
182 |
+
}
|
183 |
+
|
184 |
+
return $tags;
|
185 |
+
}
|
186 |
+
}
|
@@ -86,27 +86,27 @@ final class Load extends Cache {
|
|
86 |
|
87 |
if ( _has_run( __METHOD__ ) ) {
|
88 |
// Don't construct twice, warn developer.
|
89 |
-
$this->_doing_it_wrong( __METHOD__, 'Do not instance this class. Use function <code>
|
90 |
return null;
|
91 |
}
|
92 |
|
93 |
-
|
94 |
$this->init_debug_vars();
|
95 |
|
96 |
if ( $this->the_seo_framework_debug ) {
|
97 |
-
$debug_instance = Debug::get_instance();
|
98 |
|
99 |
\add_action( 'the_seo_framework_do_before_output', [ $debug_instance, '_set_debug_query_output_cache' ] );
|
100 |
\add_action( 'admin_footer', [ $debug_instance, '_debug_output' ] );
|
101 |
\add_action( 'wp_footer', [ $debug_instance, '_debug_output' ] );
|
102 |
}
|
103 |
|
104 |
-
|
105 |
\add_filter( 'option_page_capability_' . THE_SEO_FRAMEWORK_SITE_OPTIONS, [ $this, 'get_settings_capability' ] );
|
106 |
|
107 |
$this->pretty_permalinks = '' !== \get_option( 'permalink_structure' );
|
108 |
|
109 |
-
|
110 |
\add_action( 'init', [ $this, 'init_the_seo_framework' ], 0 );
|
111 |
|
112 |
$this->is_headless = [
|
@@ -122,7 +122,7 @@ final class Load extends Cache {
|
|
122 |
'constant THE_SEO_FRAMEWORK_HEADLESS'
|
123 |
) ) \defined( 'THE_SEO_FRAMEWORK_HEADLESS' ) or \define( 'THE_SEO_FRAMEWORK_HEADLESS', true );
|
124 |
|
125 |
-
|
126 |
if ( \defined( 'THE_SEO_FRAMEWORK_HEADLESS' ) ) {
|
127 |
$this->is_headless = [
|
128 |
'meta' => true,
|
@@ -147,7 +147,7 @@ final class Load extends Cache {
|
|
147 |
|
148 |
$this->the_seo_framework_debug = \defined( 'THE_SEO_FRAMEWORK_DEBUG' ) && THE_SEO_FRAMEWORK_DEBUG ?: $this->the_seo_framework_debug;
|
149 |
if ( $this->the_seo_framework_debug )
|
150 |
-
\
|
151 |
|
152 |
$this->the_seo_framework_use_transients = \defined( 'THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS' ) && THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS ? false : $this->the_seo_framework_use_transients;
|
153 |
|
@@ -207,6 +207,11 @@ final class Load extends Cache {
|
|
207 |
// Easy Digital Downloads.
|
208 |
$this->_include_compat( 'edd', 'plugin' );
|
209 |
}
|
|
|
|
|
|
|
|
|
|
|
210 |
}
|
211 |
|
212 |
/**
|
@@ -222,7 +227,8 @@ final class Load extends Cache {
|
|
222 |
* @param string $replacement Optional. The function that should have been called. Default null.
|
223 |
*/
|
224 |
public function _deprecated_function( $function, $version, $replacement = null ) { // phpcs:ignore -- Wrong asserts, copied method name.
|
225 |
-
|
|
|
226 |
}
|
227 |
|
228 |
/**
|
@@ -238,7 +244,8 @@ final class Load extends Cache {
|
|
238 |
* @param string $version The version of WordPress where the message was added.
|
239 |
*/
|
240 |
public function _doing_it_wrong( $function, $message, $version = null ) { // phpcs:ignore -- Wrong asserts, copied method name.
|
241 |
-
|
|
|
242 |
}
|
243 |
|
244 |
/**
|
@@ -252,6 +259,6 @@ final class Load extends Cache {
|
|
252 |
* @param string $message A message explaining what has been done incorrectly.
|
253 |
*/
|
254 |
public function _inaccessible_p_or_m( $p_or_m, $message = '' ) {
|
255 |
-
Debug::get_instance()->_inaccessible_p_or_m( $p_or_m, $message );
|
256 |
}
|
257 |
}
|
86 |
|
87 |
if ( _has_run( __METHOD__ ) ) {
|
88 |
// Don't construct twice, warn developer.
|
89 |
+
$this->_doing_it_wrong( __METHOD__, 'Do not instance this class. Use function <code>tsf()</code> instead.', '3.1.0' );
|
90 |
return null;
|
91 |
}
|
92 |
|
93 |
+
// Setup debug vars before initializing anything else.
|
94 |
$this->init_debug_vars();
|
95 |
|
96 |
if ( $this->the_seo_framework_debug ) {
|
97 |
+
$debug_instance = Internal\Debug::get_instance();
|
98 |
|
99 |
\add_action( 'the_seo_framework_do_before_output', [ $debug_instance, '_set_debug_query_output_cache' ] );
|
100 |
\add_action( 'admin_footer', [ $debug_instance, '_debug_output' ] );
|
101 |
\add_action( 'wp_footer', [ $debug_instance, '_debug_output' ] );
|
102 |
}
|
103 |
|
104 |
+
// Register the capabilities early.
|
105 |
\add_filter( 'option_page_capability_' . THE_SEO_FRAMEWORK_SITE_OPTIONS, [ $this, 'get_settings_capability' ] );
|
106 |
|
107 |
$this->pretty_permalinks = '' !== \get_option( 'permalink_structure' );
|
108 |
|
109 |
+
// Load plugin at init 0.
|
110 |
\add_action( 'init', [ $this, 'init_the_seo_framework' ], 0 );
|
111 |
|
112 |
$this->is_headless = [
|
122 |
'constant THE_SEO_FRAMEWORK_HEADLESS'
|
123 |
) ) \defined( 'THE_SEO_FRAMEWORK_HEADLESS' ) or \define( 'THE_SEO_FRAMEWORK_HEADLESS', true );
|
124 |
|
125 |
+
// A headless boi is a good boi. Far less annoying, they are.
|
126 |
if ( \defined( 'THE_SEO_FRAMEWORK_HEADLESS' ) ) {
|
127 |
$this->is_headless = [
|
128 |
'meta' => true,
|
147 |
|
148 |
$this->the_seo_framework_debug = \defined( 'THE_SEO_FRAMEWORK_DEBUG' ) && THE_SEO_FRAMEWORK_DEBUG ?: $this->the_seo_framework_debug;
|
149 |
if ( $this->the_seo_framework_debug )
|
150 |
+
Internal\Debug::_set_instance( $this->the_seo_framework_debug );
|
151 |
|
152 |
$this->the_seo_framework_use_transients = \defined( 'THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS' ) && THE_SEO_FRAMEWORK_DISABLE_TRANSIENTS ? false : $this->the_seo_framework_use_transients;
|
153 |
|
207 |
// Easy Digital Downloads.
|
208 |
$this->_include_compat( 'edd', 'plugin' );
|
209 |
}
|
210 |
+
|
211 |
+
if ( $this->detect_plugin( [ 'constants' => [ 'ELEMENTOR_VERSION' ] ] ) ) {
|
212 |
+
// Elementor
|
213 |
+
$this->_include_compat( 'elementor', 'plugin' );
|
214 |
+
}
|
215 |
}
|
216 |
|
217 |
/**
|
227 |
* @param string $replacement Optional. The function that should have been called. Default null.
|
228 |
*/
|
229 |
public function _deprecated_function( $function, $version, $replacement = null ) { // phpcs:ignore -- Wrong asserts, copied method name.
|
230 |
+
// phpcs:ignore -- Wrong asserts, copied method name.
|
231 |
+
Internal\Debug::get_instance()->_deprecated_function( $function, $version, $replacement );
|
232 |
}
|
233 |
|
234 |
/**
|
244 |
* @param string $version The version of WordPress where the message was added.
|
245 |
*/
|
246 |
public function _doing_it_wrong( $function, $message, $version = null ) { // phpcs:ignore -- Wrong asserts, copied method name.
|
247 |
+
// phpcs:ignore -- Wrong asserts, copied method name.
|
248 |
+
Internal\Debug::get_instance()->_doing_it_wrong( $function, $message, $version );
|
249 |
}
|
250 |
|
251 |
/**
|
259 |
* @param string $message A message explaining what has been done incorrectly.
|
260 |
*/
|
261 |
public function _inaccessible_p_or_m( $p_or_m, $message = '' ) {
|
262 |
+
Internal\Debug::get_instance()->_inaccessible_p_or_m( $p_or_m, $message );
|
263 |
}
|
264 |
}
|
@@ -74,12 +74,10 @@ class Post_Data extends Detect {
|
|
74 |
* @param string $item The item to get.
|
75 |
* @param int $post_id The post ID.
|
76 |
* @param bool $use_cache Whether to use caching.
|
|
|
77 |
*/
|
78 |
public function get_post_meta_item( $item, $post_id = 0, $use_cache = true ) {
|
79 |
-
|
80 |
-
$meta = $this->get_post_meta( $post_id ?: $this->get_the_real_ID(), $use_cache );
|
81 |
-
|
82 |
-
return isset( $meta[ $item ] ) ? $meta[ $item ] : null;
|
83 |
}
|
84 |
|
85 |
/**
|
@@ -103,18 +101,17 @@ class Post_Data extends Detect {
|
|
103 |
*/
|
104 |
public function get_post_meta( $post_id, $use_cache = true ) {
|
105 |
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
if ( isset( $cache[ $post_id ] ) )
|
110 |
-
return $cache[ $post_id ];
|
111 |
-
}
|
112 |
|
113 |
// get_post_meta() requires a valid post ID. Make sure that post exists.
|
114 |
$post = \get_post( $post_id );
|
115 |
|
116 |
-
|
117 |
-
|
|
|
|
|
|
|
118 |
|
119 |
/**
|
120 |
* We can't trust the filter to always contain the expected keys.
|
@@ -129,14 +126,15 @@ class Post_Data extends Detect {
|
|
129 |
$meta = [];
|
130 |
} else {
|
131 |
// Filter the post meta items based on defaults' keys.
|
|
|
132 |
$meta = array_intersect_key(
|
133 |
\get_post_meta( $post->ID ), // Gets all post meta. This is a discrepancy with get_term_meta()!
|
134 |
$defaults
|
135 |
);
|
136 |
|
137 |
// WP converts all entries to arrays, because we got ALL entries. Disarray!
|
138 |
-
foreach ( $meta as
|
139 |
-
$
|
140 |
}
|
141 |
|
142 |
/**
|
@@ -157,8 +155,9 @@ class Post_Data extends Detect {
|
|
157 |
]
|
158 |
);
|
159 |
|
160 |
-
// Cache using
|
161 |
-
|
|
|
162 |
}
|
163 |
|
164 |
/**
|
@@ -176,36 +175,21 @@ class Post_Data extends Detect {
|
|
176 |
* @return array The default post meta.
|
177 |
*/
|
178 |
public function get_post_meta_defaults( $post_id = 0 ) {
|
179 |
-
|
180 |
/**
|
181 |
* @since 4.1.4
|
|
|
|
|
182 |
* @param array $defaults
|
183 |
* @param integer $post_id Post ID.
|
184 |
* @param \WP_Post $post Post object.
|
185 |
*/
|
186 |
-
|
187 |
'the_seo_framework_post_meta_defaults',
|
188 |
[
|
189 |
$this->get_unfiltered_post_meta_defaults(),
|
190 |
-
$post_id,
|
191 |
-
$post = \get_post( $post_id ),
|
192 |
]
|
193 |
);
|
194 |
-
|
195 |
-
/**
|
196 |
-
* @since 3.1.0
|
197 |
-
* @since 4.1.4 Deprecated. Use filter `the_seo_framework_post_meta_defaults` instead.
|
198 |
-
* @deprecated
|
199 |
-
* @param array $defaults
|
200 |
-
* @param integer $post_id Post ID.
|
201 |
-
* @param \WP_Post $post Post object.
|
202 |
-
*/
|
203 |
-
return (array) \apply_filters_deprecated(
|
204 |
-
'the_seo_framework_inpost_seo_save_defaults',
|
205 |
-
[ $defaults, $post_id, $post ],
|
206 |
-
'4.1.4 of The SEO Framework',
|
207 |
-
'the_seo_framework_post_meta_defaults'
|
208 |
-
);
|
209 |
}
|
210 |
|
211 |
/**
|
@@ -270,7 +254,7 @@ class Post_Data extends Detect {
|
|
270 |
* @param \WP_Post|integer $post The post object or post ID.
|
271 |
* @param array $data The post meta fields, will be merged with the defaults.
|
272 |
*/
|
273 |
-
public function save_post_meta( $post,
|
274 |
|
275 |
$post = \get_post( $post );
|
276 |
|
@@ -545,23 +529,18 @@ class Post_Data extends Detect {
|
|
545 |
// Can this even fail?
|
546 |
if ( ! $post_type ) return;
|
547 |
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
foreach ( $values as $_taxonomy => $v ) {
|
562 |
-
if ( ! isset( $_POST[ $v['name'] ] ) ) continue;
|
563 |
-
if ( \wp_verify_nonce( $_POST[ $v['name'] ], $v['action'] ) ) { // Redundant. Fortified.
|
564 |
-
$this->update_primary_term_id( $post->ID, $_taxonomy, $v['value'] );
|
565 |
}
|
566 |
}
|
567 |
}
|
@@ -571,17 +550,15 @@ class Post_Data extends Detect {
|
|
571 |
* Memoizes the return value.
|
572 |
*
|
573 |
* @since 2.4.3
|
574 |
-
* @since 2.9.3
|
575 |
-
*
|
576 |
*
|
577 |
* @return int Latest Post ID.
|
578 |
*/
|
579 |
public function get_latest_post_id() {
|
580 |
|
581 |
-
|
582 |
-
|
583 |
-
if ( null !== $post_id )
|
584 |
-
return $post_id;
|
585 |
|
586 |
$query = new \WP_Query( [
|
587 |
'posts_per_page' => 1,
|
@@ -595,7 +572,7 @@ class Post_Data extends Detect {
|
|
595 |
'no_found_rows' => true,
|
596 |
] );
|
597 |
|
598 |
-
return
|
599 |
}
|
600 |
|
601 |
/**
|
@@ -608,71 +585,8 @@ class Post_Data extends Detect {
|
|
608 |
* @return string The post content.
|
609 |
*/
|
610 |
public function get_post_content( $id = 0 ) {
|
611 |
-
|
612 |
-
return
|
613 |
-
}
|
614 |
-
|
615 |
-
/**
|
616 |
-
* Determines whether the post has a page builder attached to it.
|
617 |
-
* Doesn't use plugin detection features as some builders might be incorporated within themes.
|
618 |
-
*
|
619 |
-
* Detects the following builders:
|
620 |
-
* - Elementor by Elementor LTD
|
621 |
-
* - Divi Builder by Elegant Themes
|
622 |
-
* - Visual Composer by WPBakery
|
623 |
-
* - Page Builder by SiteOrigin
|
624 |
-
* - Beaver Builder by Fastline Media
|
625 |
-
*
|
626 |
-
* @since 2.6.6
|
627 |
-
* @since 3.1.0 Added Elementor detection
|
628 |
-
* @since 4.0.0 Now detects page builders before looping over the meta.
|
629 |
-
* @TODO deprecate? -> We may use this data for they have FSE builders. We may want to interface with those, some day.
|
630 |
-
* @ignore unused.
|
631 |
-
*
|
632 |
-
* @param int $post_id The post ID to check.
|
633 |
-
* @return bool
|
634 |
-
*/
|
635 |
-
public function uses_page_builder( $post_id ) {
|
636 |
-
|
637 |
-
$meta = \get_post_meta( $post_id );
|
638 |
-
|
639 |
-
/**
|
640 |
-
* @since 2.6.6
|
641 |
-
* @since 3.1.0 : 1. Now defaults to `null`
|
642 |
-
* 2. Now, when a boolean (either true or false) is defined, it'll short-circuit this function.
|
643 |
-
* @param boolean|null $detected Whether a builder should be detected.
|
644 |
-
* @param int $post_id The current Post ID.
|
645 |
-
* @param array $meta The current post meta.
|
646 |
-
*/
|
647 |
-
$detected = \apply_filters( 'the_seo_framework_detect_page_builder', null, $post_id, $meta );
|
648 |
-
|
649 |
-
if ( \is_bool( $detected ) )
|
650 |
-
return $detected;
|
651 |
-
|
652 |
-
if ( ! $this->detect_page_builder() )
|
653 |
-
return false;
|
654 |
-
|
655 |
-
if ( empty( $meta ) )
|
656 |
-
return false;
|
657 |
-
|
658 |
-
if ( isset( $meta['_elementor_edit_mode'][0] ) && '' !== $meta['_elementor_edit_mode'][0] && \defined( 'ELEMENTOR_VERSION' ) ) :
|
659 |
-
// Elementor by Elementor LTD
|
660 |
-
return true;
|
661 |
-
elseif ( isset( $meta['_et_pb_use_builder'][0] ) && 'on' === $meta['_et_pb_use_builder'][0] && \defined( 'ET_BUILDER_VERSION' ) ) :
|
662 |
-
// Divi Builder by Elegant Themes
|
663 |
-
return true;
|
664 |
-
elseif ( isset( $meta['_wpb_vc_js_status'][0] ) && 'true' === $meta['_wpb_vc_js_status'][0] && \defined( 'WPB_VC_VERSION' ) ) :
|
665 |
-
// Visual Composer by WPBakery
|
666 |
-
return true;
|
667 |
-
elseif ( isset( $meta['panels_data'][0] ) && '' !== $meta['panels_data'][0] && \defined( 'SITEORIGIN_PANELS_VERSION' ) ) :
|
668 |
-
// Page Builder by SiteOrigin
|
669 |
-
return true;
|
670 |
-
elseif ( isset( $meta['_fl_builder_enabled'][0] ) && '1' === $meta['_fl_builder_enabled'][0] && \defined( 'FL_BUILDER_VERSION' ) ) :
|
671 |
-
// Beaver Builder by Fastline Media...
|
672 |
-
return true;
|
673 |
-
endif;
|
674 |
-
|
675 |
-
return false;
|
676 |
}
|
677 |
|
678 |
/**
|
@@ -703,16 +617,14 @@ class Post_Data extends Detect {
|
|
703 |
if ( \is_bool( $detected ) )
|
704 |
return $detected;
|
705 |
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
if ( empty( $meta ) )
|
710 |
return false;
|
711 |
|
712 |
-
if (
|
713 |
// Divi Builder by Elegant Themes
|
714 |
return true;
|
715 |
-
elseif (
|
716 |
// Visual Composer by WPBakery
|
717 |
return true;
|
718 |
endif;
|
@@ -728,12 +640,13 @@ class Post_Data extends Detect {
|
|
728 |
* @since 3.0.0 1. No longer checks for current query.
|
729 |
* 2. Input parameter now default to null.
|
730 |
* This currently doesn't affect how it works.
|
|
|
731 |
*
|
732 |
* @param int|null|\WP_Post $post The post ID or WP Post object.
|
733 |
* @return bool True if protected or private, false otherwise.
|
734 |
*/
|
735 |
public function is_protected( $post = null ) {
|
736 |
-
$post = \get_post( $post ); // This is here so we don't have to create another instance
|
737 |
return $this->is_password_protected( $post ) || $this->is_private( $post );
|
738 |
}
|
739 |
|
@@ -746,8 +659,8 @@ class Post_Data extends Detect {
|
|
746 |
* @return bool True if protected, false otherwise.
|
747 |
*/
|
748 |
public function is_password_protected( $post = null ) {
|
749 |
-
|
750 |
-
return
|
751 |
}
|
752 |
|
753 |
/**
|
@@ -759,8 +672,8 @@ class Post_Data extends Detect {
|
|
759 |
* @return bool True if private, false otherwise.
|
760 |
*/
|
761 |
public function is_private( $post = null ) {
|
762 |
-
|
763 |
-
return
|
764 |
}
|
765 |
|
766 |
/**
|
@@ -772,8 +685,7 @@ class Post_Data extends Detect {
|
|
772 |
* @return bool True if draft, false otherwise.
|
773 |
*/
|
774 |
public function is_draft( $post = null ) {
|
775 |
-
|
776 |
-
return isset( $post->post_status ) && \in_array( $post->post_status, [ 'draft', 'auto-draft', 'pending' ], true );
|
777 |
}
|
778 |
|
779 |
/**
|
@@ -809,12 +721,9 @@ class Post_Data extends Detect {
|
|
809 |
* @return string The Post Type name/label, if found.
|
810 |
*/
|
811 |
public function get_post_type_label( $post_type, $singular = true ) {
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
return $singular
|
816 |
-
? ( isset( $pto->labels->singular_name ) ? $pto->labels->singular_name : '' )
|
817 |
-
: ( isset( $pto->labels->name ) ? $pto->labels->name : '' );
|
818 |
}
|
819 |
|
820 |
/**
|
@@ -834,12 +743,12 @@ class Post_Data extends Detect {
|
|
834 |
|
835 |
static $primary_terms = [];
|
836 |
|
837 |
-
|
838 |
-
|
839 |
|
840 |
-
$primary_id = (int) \get_post_meta( $post_id,
|
841 |
|
842 |
-
if ( ! $primary_id ) return
|
843 |
|
844 |
// Users can alter the term list via quick/bulk edit, but cannot set a primary term that way.
|
845 |
// Users can also delete a term from the site that was previously assigned as primary.
|
@@ -859,7 +768,7 @@ class Post_Data extends Detect {
|
|
859 |
}
|
860 |
}
|
861 |
|
862 |
-
return $
|
863 |
}
|
864 |
|
865 |
/**
|
@@ -874,8 +783,7 @@ class Post_Data extends Detect {
|
|
874 |
* @return int The primary term ID. 0 if not found.
|
875 |
*/
|
876 |
public function get_primary_term_id( $post_id, $taxonomy ) {
|
877 |
-
|
878 |
-
return isset( $primary_term->term_id ) ? $primary_term->term_id : 0;
|
879 |
}
|
880 |
|
881 |
/**
|
@@ -890,9 +798,9 @@ class Post_Data extends Detect {
|
|
890 |
*/
|
891 |
public function update_primary_term_id( $post_id = null, $taxonomy = '', $value = 0 ) {
|
892 |
if ( ! $value ) {
|
893 |
-
$success = \delete_post_meta( $post_id,
|
894 |
} else {
|
895 |
-
$success = \update_post_meta( $post_id,
|
896 |
}
|
897 |
return $success;
|
898 |
}
|
74 |
* @param string $item The item to get.
|
75 |
* @param int $post_id The post ID.
|
76 |
* @param bool $use_cache Whether to use caching.
|
77 |
+
* @return mixed The post meta item's value. Null when item isn't registered.
|
78 |
*/
|
79 |
public function get_post_meta_item( $item, $post_id = 0, $use_cache = true ) {
|
80 |
+
return $this->get_post_meta( $post_id ?: $this->get_the_real_ID(), $use_cache )[ $item ] ?? null;
|
|
|
|
|
|
|
81 |
}
|
82 |
|
83 |
/**
|
101 |
*/
|
102 |
public function get_post_meta( $post_id, $use_cache = true ) {
|
103 |
|
104 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
105 |
+
if ( $use_cache && ( $memo = umemo( __METHOD__, null, $post_id ) ) ) return $memo;
|
|
|
|
|
|
|
|
|
106 |
|
107 |
// get_post_meta() requires a valid post ID. Make sure that post exists.
|
108 |
$post = \get_post( $post_id );
|
109 |
|
110 |
+
// We test post type support for "post_query"-queries might get past this point.
|
111 |
+
if ( empty( $post->ID ) || ! $this->is_post_type_supported( $post->post_type ) ) {
|
112 |
+
// Do not overwrite cache when not requested. Otherwise, we'd have two "initial" states, causing incongruities.
|
113 |
+
return $use_cache ? umemo( __METHOD__, [], $post_id ) : [];
|
114 |
+
}
|
115 |
|
116 |
/**
|
117 |
* We can't trust the filter to always contain the expected keys.
|
126 |
$meta = [];
|
127 |
} else {
|
128 |
// Filter the post meta items based on defaults' keys.
|
129 |
+
// Fix: <https://github.com/sybrew/the-seo-framework/issues/185>
|
130 |
$meta = array_intersect_key(
|
131 |
\get_post_meta( $post->ID ), // Gets all post meta. This is a discrepancy with get_term_meta()!
|
132 |
$defaults
|
133 |
);
|
134 |
|
135 |
// WP converts all entries to arrays, because we got ALL entries. Disarray!
|
136 |
+
foreach ( $meta as &$value )
|
137 |
+
$value = $value[0];
|
138 |
}
|
139 |
|
140 |
/**
|
155 |
]
|
156 |
);
|
157 |
|
158 |
+
// Cache using $post_id, not $post->ID, otherwise invalid queries can bypass the cache.
|
159 |
+
// Do not overwrite cache when not requested. Otherwise, we'd have two "initial" states, causing incongruities.
|
160 |
+
return $use_cache ? umemo( __METHOD__, $meta, $post_id ) : $meta;
|
161 |
}
|
162 |
|
163 |
/**
|
175 |
* @return array The default post meta.
|
176 |
*/
|
177 |
public function get_post_meta_defaults( $post_id = 0 ) {
|
|
|
178 |
/**
|
179 |
* @since 4.1.4
|
180 |
+
* @since 4.2.0 1. Now corrects the $post_id when none is supplied.
|
181 |
+
* 2. No longer returns the third parameter.
|
182 |
* @param array $defaults
|
183 |
* @param integer $post_id Post ID.
|
184 |
* @param \WP_Post $post Post object.
|
185 |
*/
|
186 |
+
return (array) \apply_filters_ref_array(
|
187 |
'the_seo_framework_post_meta_defaults',
|
188 |
[
|
189 |
$this->get_unfiltered_post_meta_defaults(),
|
190 |
+
$post_id ?: $this->get_the_real_ID(),
|
|
|
191 |
]
|
192 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
}
|
194 |
|
195 |
/**
|
254 |
* @param \WP_Post|integer $post The post object or post ID.
|
255 |
* @param array $data The post meta fields, will be merged with the defaults.
|
256 |
*/
|
257 |
+
public function save_post_meta( $post, $data ) {
|
258 |
|
259 |
$post = \get_post( $post );
|
260 |
|
529 |
// Can this even fail?
|
530 |
if ( ! $post_type ) return;
|
531 |
|
532 |
+
foreach ( $this->get_hierarchical_taxonomies_as( 'names', $post_type ) as $_taxonomy ) {
|
533 |
+
$_post_key = "_primary_term_{$_taxonomy}";
|
534 |
+
|
535 |
+
if ( \wp_verify_nonce(
|
536 |
+
$_POST[ "{$this->inpost_nonce_name}_pt_{$_taxonomy}" ] ?? '', // If empty, wp_verify_nonce will return false.
|
537 |
+
$this->inpost_nonce_field . '_pt'
|
538 |
+
) ) { // Redundant. Fortified.
|
539 |
+
$this->update_primary_term_id(
|
540 |
+
$post->ID,
|
541 |
+
$_taxonomy,
|
542 |
+
\absint( $_POST['autodescription'][ $_post_key ] ?? 0 )
|
543 |
+
);
|
|
|
|
|
|
|
|
|
|
|
544 |
}
|
545 |
}
|
546 |
}
|
550 |
* Memoizes the return value.
|
551 |
*
|
552 |
* @since 2.4.3
|
553 |
+
* @since 2.9.3 1. Removed object caching.
|
554 |
+
* 2. It now uses WP_Query, instead of wpdb.
|
555 |
*
|
556 |
* @return int Latest Post ID.
|
557 |
*/
|
558 |
public function get_latest_post_id() {
|
559 |
|
560 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
561 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
562 |
|
563 |
$query = new \WP_Query( [
|
564 |
'posts_per_page' => 1,
|
572 |
'no_found_rows' => true,
|
573 |
] );
|
574 |
|
575 |
+
return memo( reset( $query->posts ) );
|
576 |
}
|
577 |
|
578 |
/**
|
585 |
* @return string The post content.
|
586 |
*/
|
587 |
public function get_post_content( $id = 0 ) {
|
588 |
+
// '0' is not deemed content. Return empty string for it's a slippery slope.
|
589 |
+
return ( \get_post( $id ?: $this->get_the_real_ID() )->post_content ?? '' ) ?: '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
590 |
}
|
591 |
|
592 |
/**
|
617 |
if ( \is_bool( $detected ) )
|
618 |
return $detected;
|
619 |
|
620 |
+
// If there's no meta, or no builder active, it doesn't use a builder.
|
621 |
+
if ( empty( $meta ) || ! $this->detect_non_html_page_builder() )
|
|
|
|
|
622 |
return false;
|
623 |
|
624 |
+
if ( 'on' === ( $meta['_et_pb_use_builder'][0] ?? '' ) && \defined( 'ET_BUILDER_VERSION' ) ) :
|
625 |
// Divi Builder by Elegant Themes
|
626 |
return true;
|
627 |
+
elseif ( 'true' === ( $meta['_wpb_vc_js_status'][0] ?? '' ) && \defined( 'WPB_VC_VERSION' ) ) :
|
628 |
// Visual Composer by WPBakery
|
629 |
return true;
|
630 |
endif;
|
640 |
* @since 3.0.0 1. No longer checks for current query.
|
641 |
* 2. Input parameter now default to null.
|
642 |
* This currently doesn't affect how it works.
|
643 |
+
* @since 4.2.0 Added caching. Can be reversed if https://core.trac.wordpress.org/ticket/50567 is fixed.
|
644 |
*
|
645 |
* @param int|null|\WP_Post $post The post ID or WP Post object.
|
646 |
* @return bool True if protected or private, false otherwise.
|
647 |
*/
|
648 |
public function is_protected( $post = null ) {
|
649 |
+
$post = \get_post( $post ); // This is here so we don't have to create another instance hereinafter.
|
650 |
return $this->is_password_protected( $post ) || $this->is_private( $post );
|
651 |
}
|
652 |
|
659 |
* @return bool True if protected, false otherwise.
|
660 |
*/
|
661 |
public function is_password_protected( $post = null ) {
|
662 |
+
// return '' !== ( \get_post( $post )->post_password ?? '' ); // https://core.trac.wordpress.org/ticket/50567
|
663 |
+
return '' !== ( $post->post_password ?? \get_post( $post )->post_password ?? '' );
|
664 |
}
|
665 |
|
666 |
/**
|
672 |
* @return bool True if private, false otherwise.
|
673 |
*/
|
674 |
public function is_private( $post = null ) {
|
675 |
+
// return 'private' === ( \get_post( $post )->post_status ?? '' ); // https://core.trac.wordpress.org/ticket/50567
|
676 |
+
return 'private' === ( $post->post_status ?? \get_post( $post )->post_status ?? '' );
|
677 |
}
|
678 |
|
679 |
/**
|
685 |
* @return bool True if draft, false otherwise.
|
686 |
*/
|
687 |
public function is_draft( $post = null ) {
|
688 |
+
return \in_array( \get_post( $post )->post_status ?? '', [ 'draft', 'auto-draft', 'pending' ], true );
|
|
|
689 |
}
|
690 |
|
691 |
/**
|
721 |
* @return string The Post Type name/label, if found.
|
722 |
*/
|
723 |
public function get_post_type_label( $post_type, $singular = true ) {
|
724 |
+
return \get_post_type_object( $post_type )->labels->{
|
725 |
+
$singular ? 'singular_name' : 'name'
|
726 |
+
} ?? '';
|
|
|
|
|
|
|
727 |
}
|
728 |
|
729 |
/**
|
743 |
|
744 |
static $primary_terms = [];
|
745 |
|
746 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
747 |
+
if ( null !== $memo = memo( null, $post_id, $taxonomy ) ) return $memo;
|
748 |
|
749 |
+
$primary_id = (int) \get_post_meta( $post_id, "_primary_term_{$taxonomy}", true ) ?: 0;
|
750 |
|
751 |
+
if ( ! $primary_id ) return memo( false, $post_id, $taxonomy );
|
752 |
|
753 |
// Users can alter the term list via quick/bulk edit, but cannot set a primary term that way.
|
754 |
// Users can also delete a term from the site that was previously assigned as primary.
|
768 |
}
|
769 |
}
|
770 |
|
771 |
+
return memo( $primary_term, $post_id, $taxonomy );
|
772 |
}
|
773 |
|
774 |
/**
|
783 |
* @return int The primary term ID. 0 if not found.
|
784 |
*/
|
785 |
public function get_primary_term_id( $post_id, $taxonomy ) {
|
786 |
+
return $this->get_primary_term( $post_id, $taxonomy )->term_id ?? 0;
|
|
|
787 |
}
|
788 |
|
789 |
/**
|
798 |
*/
|
799 |
public function update_primary_term_id( $post_id = null, $taxonomy = '', $value = 0 ) {
|
800 |
if ( ! $value ) {
|
801 |
+
$success = \delete_post_meta( $post_id, "_primary_term_{$taxonomy}" );
|
802 |
} else {
|
803 |
+
$success = \update_post_meta( $post_id, "_primary_term_{$taxonomy}", $value );
|
804 |
}
|
805 |
return $success;
|
806 |
}
|
@@ -61,16 +61,15 @@ class Query extends Core {
|
|
61 |
*/
|
62 |
protected function can_cache_query( $method ) {
|
63 |
|
64 |
-
|
|
|
65 |
|
66 |
-
if ( isset( $
|
67 |
-
return $cache;
|
68 |
|
69 |
if ( \defined( 'WP_CLI' ) && WP_CLI )
|
70 |
-
return $
|
71 |
-
|
72 |
if ( isset( $GLOBALS['wp_query']->query ) || isset( $GLOBALS['current_screen'] ) )
|
73 |
-
return $
|
74 |
|
75 |
$this->the_seo_framework_debug
|
76 |
and $this->do_query_error_notice( $method );
|
@@ -92,8 +91,8 @@ class Query extends Core {
|
|
92 |
|
93 |
$trace = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 4 );
|
94 |
if ( ! empty( $trace[3] ) ) {
|
95 |
-
$message .=
|
96 |
-
$message .=
|
97 |
}
|
98 |
|
99 |
$this->_doing_it_wrong( \esc_html( $method ), \esc_html( $message ), '2.9.0' );
|
@@ -112,15 +111,32 @@ class Query extends Core {
|
|
112 |
* Returns the post type name from query input or real ID.
|
113 |
*
|
114 |
* @since 4.0.5
|
|
|
115 |
*
|
116 |
* @param int|WP_Post|null $post (Optional) Post ID or post object.
|
117 |
* @return string|false Post type on success, false on failure.
|
118 |
*/
|
119 |
public function get_post_type_real_ID( $post = null ) {
|
120 |
|
121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
|
123 |
-
return
|
124 |
}
|
125 |
|
126 |
/**
|
@@ -132,8 +148,7 @@ class Query extends Core {
|
|
132 |
* @return string
|
133 |
*/
|
134 |
public function get_admin_post_type() {
|
135 |
-
|
136 |
-
return isset( $current_screen->post_type ) ? $current_screen->post_type : '';
|
137 |
}
|
138 |
|
139 |
/**
|
@@ -149,7 +164,7 @@ class Query extends Core {
|
|
149 |
$taxonomy = $taxonomy ?: $this->get_current_taxonomy();
|
150 |
$tax = $taxonomy ? \get_taxonomy( $taxonomy ) : null;
|
151 |
|
152 |
-
return
|
153 |
}
|
154 |
|
155 |
/**
|
@@ -167,29 +182,39 @@ class Query extends Core {
|
|
167 |
if ( \is_admin() )
|
168 |
return $this->get_the_real_admin_ID();
|
169 |
|
|
|
|
|
|
|
170 |
$use_cache = $use_cache && $this->can_cache_query( __METHOD__ );
|
171 |
|
|
|
172 |
if ( $use_cache ) {
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
if ( ! $id ) {
|
183 |
-
// This catches most IDs. Even Post IDs.
|
184 |
-
$id = \get_queried_object_id();
|
185 |
}
|
186 |
|
187 |
/**
|
188 |
* @since 2.6.2
|
189 |
-
* @param int
|
190 |
-
* @param bool
|
191 |
*/
|
192 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
}
|
194 |
|
195 |
/**
|
@@ -212,31 +237,6 @@ class Query extends Core {
|
|
212 |
return (int) \apply_filters( 'the_seo_framework_current_admin_id', $id );
|
213 |
}
|
214 |
|
215 |
-
/**
|
216 |
-
* Get the real ID from plugins.
|
217 |
-
*
|
218 |
-
* Only works on front-end as there's no need to check for inconsistent
|
219 |
-
* functions for the current ID in the admin.
|
220 |
-
*
|
221 |
-
* @since 2.5.0
|
222 |
-
* @since 3.1.0 1. Now checks for the feed.
|
223 |
-
* 2. No longer caches.
|
224 |
-
* @since 4.0.5 1. The shop ID is now handled via the filter.
|
225 |
-
* 2. The question ID (AnsPress) is no longer called. This should work out-of-the-box since AnsPress 4.1.
|
226 |
-
*
|
227 |
-
* @return int The admin ID.
|
228 |
-
*/
|
229 |
-
public function check_the_real_ID() { // phpcs:ignore -- ID is capitalized because WordPress does that too: get_the_ID().
|
230 |
-
|
231 |
-
$id = $this->is_feed() ? \get_the_ID() : 0;
|
232 |
-
|
233 |
-
/**
|
234 |
-
* @since 2.5.0
|
235 |
-
* @param int $id
|
236 |
-
*/
|
237 |
-
return (int) \apply_filters( 'the_seo_framework_real_id', $id );
|
238 |
-
}
|
239 |
-
|
240 |
/**
|
241 |
* Returns the front page ID, if home is a page.
|
242 |
*
|
@@ -245,10 +245,11 @@ class Query extends Core {
|
|
245 |
* @return int the ID.
|
246 |
*/
|
247 |
public function get_the_front_page_ID() { // phpcs:ignore -- ID is capitalized because WordPress does that too: get_the_ID().
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
|
|
252 |
}
|
253 |
|
254 |
/**
|
@@ -286,14 +287,11 @@ class Query extends Core {
|
|
286 |
* @return string The queried taxonomy type.
|
287 |
*/
|
288 |
public function get_current_taxonomy() {
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
$_object = \is_admin() ? $GLOBALS['current_screen'] : \get_queried_object();
|
295 |
-
|
296 |
-
return $cache = ! empty( $_object->taxonomy ) ? $_object->taxonomy : '';
|
297 |
}
|
298 |
|
299 |
/**
|
@@ -346,17 +344,8 @@ class Query extends Core {
|
|
346 |
if ( ! $attachment )
|
347 |
return \is_attachment();
|
348 |
|
349 |
-
|
350 |
-
|
351 |
-
return $cache;
|
352 |
-
|
353 |
-
$this->set_query_cache(
|
354 |
-
__METHOD__,
|
355 |
-
$is_attachment = \is_attachment( $attachment ),
|
356 |
-
$attachment
|
357 |
-
);
|
358 |
-
|
359 |
-
return $is_attachment;
|
360 |
}
|
361 |
|
362 |
/**
|
@@ -388,37 +377,30 @@ class Query extends Core {
|
|
388 |
public function is_singular_archive( $post = null ) {
|
389 |
|
390 |
if ( isset( $post ) ) {
|
391 |
-
$
|
392 |
-
|
|
|
393 |
} else {
|
394 |
$id = null;
|
395 |
}
|
396 |
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
$this->set_query_cache(
|
416 |
-
__METHOD__,
|
417 |
-
$is_singular_archive,
|
418 |
-
$id
|
419 |
-
);
|
420 |
-
|
421 |
-
return $is_singular_archive;
|
422 |
}
|
423 |
|
424 |
/**
|
@@ -434,17 +416,23 @@ class Query extends Core {
|
|
434 |
if ( \is_admin() )
|
435 |
return $this->is_archive_admin();
|
436 |
|
|
|
|
|
|
|
|
|
|
|
437 |
if ( \is_archive() && false === $this->is_singular() )
|
438 |
-
return true;
|
439 |
|
440 |
-
|
|
|
441 |
global $wp_query;
|
442 |
|
443 |
-
if ( $wp_query->
|
444 |
-
return true;
|
445 |
}
|
446 |
|
447 |
-
return false;
|
448 |
}
|
449 |
|
450 |
/**
|
@@ -456,8 +444,7 @@ class Query extends Core {
|
|
456 |
* @return bool Post Type is archive
|
457 |
*/
|
458 |
public function is_archive_admin() {
|
459 |
-
|
460 |
-
return isset( $current_screen->base ) && \in_array( $current_screen->base, [ 'edit-tags', 'term' ], true );
|
461 |
}
|
462 |
|
463 |
/**
|
@@ -469,19 +456,7 @@ class Query extends Core {
|
|
469 |
* @return bool True if on Term Edit screen. False otherwise.
|
470 |
*/
|
471 |
public function is_term_edit() {
|
472 |
-
|
473 |
-
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
474 |
-
if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
|
475 |
-
return $cache;
|
476 |
-
|
477 |
-
global $current_screen;
|
478 |
-
|
479 |
-
$this->set_query_cache(
|
480 |
-
__METHOD__,
|
481 |
-
$is_term_edit = isset( $current_screen->base ) && ( 'term' === $current_screen->base )
|
482 |
-
);
|
483 |
-
|
484 |
-
return $is_term_edit;
|
485 |
}
|
486 |
|
487 |
/**
|
@@ -493,8 +468,7 @@ class Query extends Core {
|
|
493 |
* @return bool We're on Post Edit screen.
|
494 |
*/
|
495 |
public function is_post_edit() {
|
496 |
-
|
497 |
-
return isset( $current_screen->base ) && 'post' === $current_screen->base;
|
498 |
}
|
499 |
|
500 |
/**
|
@@ -506,8 +480,7 @@ class Query extends Core {
|
|
506 |
* @return bool We're on the edit screen.
|
507 |
*/
|
508 |
public function is_wp_lists_edit() {
|
509 |
-
|
510 |
-
return isset( $current_screen->base ) && \in_array( $current_screen->base, [ 'edit-tags', 'edit' ], true );
|
511 |
}
|
512 |
|
513 |
/**
|
@@ -519,8 +492,7 @@ class Query extends Core {
|
|
519 |
* @return bool True if on Profile Edit screen. False otherwise.
|
520 |
*/
|
521 |
public function is_profile_edit() {
|
522 |
-
|
523 |
-
return isset( $current_screen->base ) && \in_array( $current_screen->base, [ 'profile', 'user-edit' ], true );
|
524 |
}
|
525 |
|
526 |
/**
|
@@ -534,89 +506,50 @@ class Query extends Core {
|
|
534 |
*/
|
535 |
public function is_author( $author = '' ) {
|
536 |
|
537 |
-
if (
|
538 |
return \is_author();
|
539 |
|
540 |
-
|
541 |
-
|
542 |
-
return $cache;
|
543 |
-
|
544 |
-
$this->set_query_cache(
|
545 |
-
__METHOD__,
|
546 |
-
$is_author = \is_author( $author ),
|
547 |
-
$author
|
548 |
-
);
|
549 |
-
|
550 |
-
return $is_author;
|
551 |
}
|
552 |
|
553 |
/**
|
554 |
-
*
|
555 |
*
|
556 |
-
* @since 2.
|
557 |
-
* @
|
558 |
-
* @see is_wc_shop() -- that's the correct implementation. However, we're dealing with erratic queries here (ET & legacy WP)
|
559 |
*
|
560 |
-
* @param int $
|
561 |
-
*
|
|
|
562 |
*/
|
563 |
-
public function
|
564 |
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
$id = $id ?: $this->get_the_real_ID();
|
570 |
-
|
571 |
-
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
572 |
-
if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $id ) )
|
573 |
-
return $cache;
|
574 |
-
|
575 |
-
$is_blog_page = false;
|
576 |
-
|
577 |
-
static $pfp = null;
|
578 |
-
|
579 |
-
if ( \is_null( $pfp ) )
|
580 |
-
$pfp = (int) \get_option( 'page_for_posts' );
|
581 |
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
$is_blog_page = true;
|
586 |
}
|
587 |
|
588 |
-
$
|
589 |
-
__METHOD__,
|
590 |
-
$is_blog_page,
|
591 |
-
$id
|
592 |
-
);
|
593 |
-
|
594 |
-
return $is_blog_page;
|
595 |
}
|
596 |
|
597 |
/**
|
598 |
-
*
|
599 |
*
|
600 |
-
* @since 4.
|
601 |
-
* @since 4.1.4 1. Improved performance by switching the conditional.
|
602 |
-
* 2. Improved performance by adding memoization.
|
603 |
-
* @todo deprecate
|
604 |
-
* @see is_wc_shop() -- that's the correct implementation.
|
605 |
*
|
606 |
-
* @param int $
|
|
|
607 |
* @return bool
|
608 |
*/
|
609 |
-
public function
|
610 |
-
|
611 |
-
|
612 |
-
if ( ! $id ) return false;
|
613 |
-
|
614 |
-
static $pfp = null;
|
615 |
-
|
616 |
-
if ( \is_null( $pfp ) )
|
617 |
-
$pfp = (int) \get_option( 'page_for_posts' );
|
618 |
-
|
619 |
-
return $pfp === $id;
|
620 |
}
|
621 |
|
622 |
/**
|
@@ -633,17 +566,8 @@ class Query extends Core {
|
|
633 |
if ( \is_admin() )
|
634 |
return $this->is_category_admin();
|
635 |
|
636 |
-
|
637 |
-
|
638 |
-
return $cache;
|
639 |
-
|
640 |
-
$this->set_query_cache(
|
641 |
-
__METHOD__,
|
642 |
-
$is_category = \is_category( $category ),
|
643 |
-
$category
|
644 |
-
);
|
645 |
-
|
646 |
-
return $is_category;
|
647 |
}
|
648 |
|
649 |
/**
|
@@ -718,28 +642,18 @@ class Query extends Core {
|
|
718 |
public function is_real_front_page() {
|
719 |
|
720 |
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
721 |
-
if ( null !== $cache = $this->
|
722 |
return $cache;
|
723 |
|
724 |
-
$is_front_page =
|
725 |
-
|
726 |
-
if ( \is_front_page() )
|
727 |
-
$is_front_page = true;
|
728 |
|
729 |
-
|
730 |
-
|
731 |
-
$
|
732 |
-
|
733 |
-
if ( 'page' !== $sof && 'posts' !== $sof )
|
734 |
-
$is_front_page = true;
|
735 |
}
|
736 |
|
737 |
-
$this->
|
738 |
-
__METHOD__,
|
739 |
-
$is_front_page
|
740 |
-
);
|
741 |
-
|
742 |
-
return $is_front_page;
|
743 |
}
|
744 |
|
745 |
/**
|
@@ -761,74 +675,6 @@ class Query extends Core {
|
|
761 |
return $id === $this->get_the_front_page_ID();
|
762 |
}
|
763 |
|
764 |
-
/**
|
765 |
-
* Checks for front page by input ID.
|
766 |
-
*
|
767 |
-
* NOTE: Doesn't always return true when the ID is 0, although the homepage might be.
|
768 |
-
* This is because it checks for the query, to prevent conflicts.
|
769 |
-
*
|
770 |
-
* @see $this->is_real_front_page_by_id(); Alternative to NOTE above.
|
771 |
-
*
|
772 |
-
* @since 2.9.0
|
773 |
-
* @since 2.9.3 Now tests for archive and 404 before testing homepage as blog.
|
774 |
-
* @since 3.2.2 Removed SEO settings page check. This now returns false on that page.
|
775 |
-
*
|
776 |
-
* @param int $id The page ID, required. Can be 0.
|
777 |
-
* @return bool True if ID if for the homepage.
|
778 |
-
*/
|
779 |
-
public function is_front_page_by_id( $id ) {
|
780 |
-
|
781 |
-
$id = (int) $id;
|
782 |
-
|
783 |
-
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
784 |
-
if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $id ) )
|
785 |
-
return $cache;
|
786 |
-
|
787 |
-
$is_front_page = false;
|
788 |
-
|
789 |
-
$sof = \get_option( 'show_on_front' );
|
790 |
-
|
791 |
-
// Compare against $id
|
792 |
-
if ( 'page' === $sof ) {
|
793 |
-
if ( (int) \get_option( 'page_on_front' ) === $id ) {
|
794 |
-
$is_front_page = true;
|
795 |
-
}
|
796 |
-
} elseif ( 'posts' === $sof ) {
|
797 |
-
if ( 0 === $id ) {
|
798 |
-
// 0 as ID causes many issues. Just test for is_home().
|
799 |
-
if ( $this->is_home() ) {
|
800 |
-
$is_front_page = true;
|
801 |
-
}
|
802 |
-
} elseif ( (int) \get_option( 'page_for_posts' ) === $id ) {
|
803 |
-
$is_front_page = true;
|
804 |
-
}
|
805 |
-
} else {
|
806 |
-
// Elegant Themes' Extra support
|
807 |
-
if ( 0 === $id && $this->is_home() ) {
|
808 |
-
$is_front_page = true;
|
809 |
-
}
|
810 |
-
}
|
811 |
-
|
812 |
-
$this->set_query_cache(
|
813 |
-
__METHOD__,
|
814 |
-
$is_front_page,
|
815 |
-
$id
|
816 |
-
);
|
817 |
-
|
818 |
-
return $is_front_page;
|
819 |
-
}
|
820 |
-
|
821 |
-
/**
|
822 |
-
* Determines whether the query is for the blog page.
|
823 |
-
*
|
824 |
-
* @since 2.6.0
|
825 |
-
*
|
826 |
-
* @return bool
|
827 |
-
*/
|
828 |
-
public function is_home() {
|
829 |
-
return \is_home();
|
830 |
-
}
|
831 |
-
|
832 |
/**
|
833 |
* Detects month archives.
|
834 |
*
|
@@ -860,23 +706,13 @@ class Query extends Core {
|
|
860 |
if ( empty( $page ) )
|
861 |
return \is_page();
|
862 |
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
$is_page = \is_page( $page );
|
871 |
-
}
|
872 |
-
|
873 |
-
$this->set_query_cache(
|
874 |
-
__METHOD__,
|
875 |
-
$is_page,
|
876 |
-
$page
|
877 |
-
);
|
878 |
-
|
879 |
-
return $is_page;
|
880 |
}
|
881 |
|
882 |
/**
|
@@ -909,11 +745,11 @@ class Query extends Core {
|
|
909 |
$is_preview = false;
|
910 |
|
911 |
if ( \is_preview()
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
) {
|
918 |
$is_preview = true;
|
919 |
}
|
@@ -949,23 +785,13 @@ class Query extends Core {
|
|
949 |
if ( \is_admin() )
|
950 |
return $this->is_single_admin();
|
951 |
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
$is_single = \is_single( $post );
|
960 |
-
}
|
961 |
-
|
962 |
-
$this->set_query_cache(
|
963 |
-
__METHOD__,
|
964 |
-
$is_single,
|
965 |
-
$post
|
966 |
-
);
|
967 |
-
|
968 |
-
return $is_single;
|
969 |
}
|
970 |
|
971 |
/**
|
@@ -1008,18 +834,8 @@ class Query extends Core {
|
|
1008 |
if ( $post_types )
|
1009 |
return \is_singular( $post_types );
|
1010 |
|
1011 |
-
|
1012 |
-
|
1013 |
-
return $cache;
|
1014 |
-
|
1015 |
-
$is_singular = \is_singular() || $this->is_singular_archive();
|
1016 |
-
|
1017 |
-
$this->set_query_cache(
|
1018 |
-
__METHOD__,
|
1019 |
-
$is_singular
|
1020 |
-
);
|
1021 |
-
|
1022 |
-
return $is_singular;
|
1023 |
}
|
1024 |
|
1025 |
/**
|
@@ -1033,8 +849,7 @@ class Query extends Core {
|
|
1033 |
* @return bool Post Type is singular
|
1034 |
*/
|
1035 |
public function is_singular_admin() {
|
1036 |
-
|
1037 |
-
return isset( $current_screen->base ) && \in_array( $current_screen->base, [ 'edit', 'post' ], true );
|
1038 |
}
|
1039 |
|
1040 |
/**
|
@@ -1048,10 +863,11 @@ class Query extends Core {
|
|
1048 |
*/
|
1049 |
public function is_static_frontpage( $id = 0 ) {
|
1050 |
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
|
|
1055 |
|
1056 |
return false !== $front_id && ( $id ?: $this->get_the_real_ID() ) === $front_id;
|
1057 |
}
|
@@ -1071,17 +887,8 @@ class Query extends Core {
|
|
1071 |
if ( \is_admin() )
|
1072 |
return $this->is_tag_admin();
|
1073 |
|
1074 |
-
|
1075 |
-
|
1076 |
-
return $cache;
|
1077 |
-
|
1078 |
-
$this->set_query_cache(
|
1079 |
-
__METHOD__,
|
1080 |
-
$is_tag = \is_tag( $tag ),
|
1081 |
-
$tag
|
1082 |
-
);
|
1083 |
-
|
1084 |
-
return $is_tag;
|
1085 |
}
|
1086 |
|
1087 |
/**
|
@@ -1108,19 +915,8 @@ class Query extends Core {
|
|
1108 |
* @return bool
|
1109 |
*/
|
1110 |
public function is_tax( $taxonomy = '', $term = '' ) {
|
1111 |
-
|
1112 |
-
|
1113 |
-
if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $taxonomy, $term ) )
|
1114 |
-
return $cache;
|
1115 |
-
|
1116 |
-
$this->set_query_cache(
|
1117 |
-
__METHOD__,
|
1118 |
-
$is_tax = \is_tax( $taxonomy, $term ),
|
1119 |
-
$taxonomy,
|
1120 |
-
$term
|
1121 |
-
);
|
1122 |
-
|
1123 |
-
return $is_tax;
|
1124 |
}
|
1125 |
|
1126 |
/**
|
@@ -1133,22 +929,17 @@ class Query extends Core {
|
|
1133 |
* @return bool
|
1134 |
*/
|
1135 |
public function is_shop( $post = null ) {
|
1136 |
-
|
1137 |
-
|
1138 |
-
|
1139 |
-
|
1140 |
-
|
1141 |
-
|
1142 |
-
|
1143 |
-
|
1144 |
-
|
1145 |
-
|
1146 |
-
|
1147 |
-
$is_shop = \apply_filters_ref_array( 'the_seo_framework_is_shop', [ false, $post ] );
|
1148 |
-
|
1149 |
-
$this->set_query_cache( __METHOD__, $is_shop, $post );
|
1150 |
-
|
1151 |
-
return $is_shop;
|
1152 |
}
|
1153 |
|
1154 |
/**
|
@@ -1165,21 +956,17 @@ class Query extends Core {
|
|
1165 |
if ( \is_admin() )
|
1166 |
return $this->is_product_admin();
|
1167 |
|
1168 |
-
|
1169 |
-
|
1170 |
-
|
1171 |
-
|
1172 |
-
|
1173 |
-
|
1174 |
-
|
1175 |
-
|
1176 |
-
|
1177 |
-
|
1178 |
-
|
1179 |
-
|
1180 |
-
$this->set_query_cache( __METHOD__, $is_product, $post );
|
1181 |
-
|
1182 |
-
return $is_product;
|
1183 |
}
|
1184 |
|
1185 |
/**
|
@@ -1191,21 +978,15 @@ class Query extends Core {
|
|
1191 |
* @return bool
|
1192 |
*/
|
1193 |
public function is_product_admin() {
|
1194 |
-
|
1195 |
-
|
1196 |
-
|
1197 |
-
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
|
1202 |
-
|
1203 |
-
*/
|
1204 |
-
$is_product_admin = (bool) \apply_filters( 'the_seo_framework_is_product_admin', false );
|
1205 |
-
|
1206 |
-
$this->set_query_cache( __METHOD__, $is_product_admin );
|
1207 |
-
|
1208 |
-
return $is_product_admin;
|
1209 |
}
|
1210 |
|
1211 |
/**
|
@@ -1228,10 +1009,8 @@ class Query extends Core {
|
|
1228 |
* @return bool True if SSL, false otherwise.
|
1229 |
*/
|
1230 |
public function is_ssl() {
|
1231 |
-
|
1232 |
-
|
1233 |
-
|
1234 |
-
return isset( $cache ) ? $cache : $cache = \is_ssl();
|
1235 |
}
|
1236 |
|
1237 |
/**
|
@@ -1254,16 +1033,8 @@ class Query extends Core {
|
|
1254 |
if ( ! $secure )
|
1255 |
return $this->is_menu_page( $this->seo_settings_page_hook, $this->seo_settings_page_slug );
|
1256 |
|
1257 |
-
|
1258 |
-
|
1259 |
-
return $cache;
|
1260 |
-
|
1261 |
-
$this->set_query_cache(
|
1262 |
-
__METHOD__,
|
1263 |
-
$page = $this->is_menu_page( $this->seo_settings_page_hook )
|
1264 |
-
);
|
1265 |
-
|
1266 |
-
return $page;
|
1267 |
}
|
1268 |
|
1269 |
/**
|
@@ -1295,29 +1066,30 @@ class Query extends Core {
|
|
1295 |
return $page_hook === $pagehook;
|
1296 |
} elseif ( \is_admin() && $pageslug ) {
|
1297 |
// N.B. $_GET['page'] === $plugin_page after admin_init...
|
1298 |
-
|
1299 |
// phpcs:ignore, WordPress.Security.NonceVerification -- This is a public variable, no data is processed.
|
1300 |
-
return
|
1301 |
}
|
1302 |
|
1303 |
return false;
|
1304 |
}
|
1305 |
|
1306 |
/**
|
1307 |
-
*
|
1308 |
-
* Fetches global
|
1309 |
*
|
1310 |
* @since 2.6.0
|
1311 |
* @since 3.2.4 1. Added overflow protection.
|
1312 |
* 2. Now always returns 1 on the admin screens.
|
|
|
|
|
1313 |
*
|
1314 |
* @return int (R>0) $page Always a positive number.
|
1315 |
*/
|
1316 |
public function page() {
|
1317 |
|
1318 |
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
1319 |
-
if ( null !== $
|
1320 |
-
return $
|
1321 |
|
1322 |
if ( $this->is_multipage() ) {
|
1323 |
$page = (int) \get_query_var( 'page' );
|
@@ -1330,17 +1102,12 @@ class Query extends Core {
|
|
1330 |
$page = 1;
|
1331 |
}
|
1332 |
|
1333 |
-
$this->
|
1334 |
-
__METHOD__,
|
1335 |
-
$page = $page ?: 1
|
1336 |
-
);
|
1337 |
-
|
1338 |
-
return $page;
|
1339 |
}
|
1340 |
|
1341 |
/**
|
1342 |
-
*
|
1343 |
-
* Fetches global
|
1344 |
*
|
1345 |
* @since 2.6.0
|
1346 |
* @since 3.2.4 1. Added overflow protection.
|
@@ -1351,8 +1118,8 @@ class Query extends Core {
|
|
1351 |
public function paged() {
|
1352 |
|
1353 |
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
1354 |
-
if ( null !== $
|
1355 |
-
return $
|
1356 |
|
1357 |
if ( $this->is_multipage() ) {
|
1358 |
$paged = (int) \get_query_var( 'paged' );
|
@@ -1366,12 +1133,7 @@ class Query extends Core {
|
|
1366 |
$paged = 1;
|
1367 |
}
|
1368 |
|
1369 |
-
$this->
|
1370 |
-
__METHOD__,
|
1371 |
-
$paged = $paged ?: 1
|
1372 |
-
);
|
1373 |
-
|
1374 |
-
return $paged;
|
1375 |
}
|
1376 |
|
1377 |
/**
|
@@ -1389,19 +1151,16 @@ class Query extends Core {
|
|
1389 |
public function numpages() {
|
1390 |
|
1391 |
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
1392 |
-
if ( null !== $
|
1393 |
-
return $
|
1394 |
|
1395 |
if ( \is_admin() ) {
|
1396 |
-
|
1397 |
-
$this->
|
1398 |
-
return $numpages;
|
1399 |
}
|
1400 |
|
1401 |
global $wp_query;
|
1402 |
|
1403 |
-
$post = null;
|
1404 |
-
|
1405 |
if ( $this->is_singular() && ! $this->is_singular_archive() )
|
1406 |
$post = \get_post( $this->get_the_real_ID() );
|
1407 |
|
@@ -1441,9 +1200,7 @@ class Query extends Core {
|
|
1441 |
$numpages = 0;
|
1442 |
}
|
1443 |
|
1444 |
-
$this->
|
1445 |
-
|
1446 |
-
return $numpages;
|
1447 |
}
|
1448 |
|
1449 |
/**
|
@@ -1465,18 +1222,13 @@ class Query extends Core {
|
|
1465 |
* Memoizes the return value once set.
|
1466 |
*
|
1467 |
* @since 2.9.2
|
1468 |
-
* @since 4.0.0 Now
|
1469 |
*
|
1470 |
* @param bool $set Whether to set "doing sitemap".
|
1471 |
* @return bool
|
1472 |
*/
|
1473 |
public function is_sitemap( $set = false ) {
|
1474 |
-
|
1475 |
-
static $doing_sitemap = false;
|
1476 |
-
|
1477 |
-
if ( $set ) $doing_sitemap = true;
|
1478 |
-
|
1479 |
-
return $doing_sitemap;
|
1480 |
}
|
1481 |
|
1482 |
/**
|
@@ -1491,64 +1243,35 @@ class Query extends Core {
|
|
1491 |
}
|
1492 |
|
1493 |
/**
|
1494 |
-
*
|
|
|
1495 |
*
|
1496 |
-
*
|
1497 |
-
*
|
1498 |
-
*
|
1499 |
-
* @
|
1500 |
-
*
|
1501 |
-
* @param mixed
|
1502 |
-
* @
|
1503 |
-
*
|
1504 |
-
*
|
1505 |
-
*
|
1506 |
-
* true If the value is being set for the first time.
|
1507 |
-
* false If the value has been set and $value_to_set is being overwritten.
|
1508 |
-
* }
|
1509 |
-
* }
|
1510 |
*/
|
1511 |
-
|
1512 |
|
1513 |
static $can_cache_query = null;
|
1514 |
|
|
|
|
|
|
|
1515 |
if ( null === $can_cache_query ) {
|
1516 |
-
if ( $this->can_cache_query( $
|
1517 |
$can_cache_query = true;
|
1518 |
} else {
|
1519 |
-
return
|
1520 |
}
|
1521 |
}
|
1522 |
|
1523 |
-
|
1524 |
-
|
1525 |
-
// phpcs:ignore, WordPress.PHP.DiscouragedPHPFunctions -- No objects are inserted, nor is this ever unserialized.
|
1526 |
-
$hash = $hash ? serialize( $hash ) : false;
|
1527 |
-
|
1528 |
-
if ( isset( $value_to_set ) ) {
|
1529 |
-
$fresh_set = ! isset( $cache[ $method ][ $hash ] );
|
1530 |
-
$cache[ $method ][ $hash ] = $value_to_set;
|
1531 |
-
return $fresh_set;
|
1532 |
-
}
|
1533 |
-
|
1534 |
-
return isset( $cache[ $method ][ $hash ] ) ? $cache[ $method ][ $hash ] : null;
|
1535 |
-
}
|
1536 |
-
|
1537 |
-
/**
|
1538 |
-
* Object cache handler for the query class.
|
1539 |
-
*
|
1540 |
-
* @since 2.7.0
|
1541 |
-
* @see $this->get_query_cache()
|
1542 |
-
*
|
1543 |
-
* @param string $method The method that wants to set. Used as a caching key.
|
1544 |
-
* @param mixed $value_to_set If null, no cache will be set.
|
1545 |
-
* @param mixed ...$hash Extra arguments, that will be used to generate an alternative cache key.
|
1546 |
-
* @return bool : {
|
1547 |
-
* true If the value is being set for the first time.
|
1548 |
-
* false If the value has been set and $value_to_set is being overwritten.
|
1549 |
-
* }
|
1550 |
-
*/
|
1551 |
-
public function set_query_cache( $method, $value_to_set, ...$hash ) {
|
1552 |
-
return $this->get_query_cache( $method, $value_to_set, ...$hash );
|
1553 |
}
|
1554 |
}
|
61 |
*/
|
62 |
protected function can_cache_query( $method ) {
|
63 |
|
64 |
+
// Don't use method memo() here for this method is called over 85 times per page.
|
65 |
+
static $memo;
|
66 |
|
67 |
+
if ( isset( $memo ) ) return $memo;
|
|
|
68 |
|
69 |
if ( \defined( 'WP_CLI' ) && WP_CLI )
|
70 |
+
return $memo = false;
|
|
|
71 |
if ( isset( $GLOBALS['wp_query']->query ) || isset( $GLOBALS['current_screen'] ) )
|
72 |
+
return $memo = true;
|
73 |
|
74 |
$this->the_seo_framework_debug
|
75 |
and $this->do_query_error_notice( $method );
|
91 |
|
92 |
$trace = debug_backtrace( DEBUG_BACKTRACE_PROVIDE_OBJECT, 4 );
|
93 |
if ( ! empty( $trace[3] ) ) {
|
94 |
+
$message .= " - In file: {$trace[3]['file']}";
|
95 |
+
$message .= " - On line: {$trace[3]['line']}";
|
96 |
}
|
97 |
|
98 |
$this->_doing_it_wrong( \esc_html( $method ), \esc_html( $message ), '2.9.0' );
|
111 |
* Returns the post type name from query input or real ID.
|
112 |
*
|
113 |
* @since 4.0.5
|
114 |
+
* @since 4.2.0 Now supports common archives without relying on the first post.
|
115 |
*
|
116 |
* @param int|WP_Post|null $post (Optional) Post ID or post object.
|
117 |
* @return string|false Post type on success, false on failure.
|
118 |
*/
|
119 |
public function get_post_type_real_ID( $post = null ) {
|
120 |
|
121 |
+
if ( isset( $post ) )
|
122 |
+
return \get_post_type( $post );
|
123 |
+
|
124 |
+
if ( $this->is_archive() ) {
|
125 |
+
if ( $this->is_category() || $this->is_tag() || $this->is_tax() ) {
|
126 |
+
$post_type = $this->get_post_types_from_taxonomy();
|
127 |
+
$post_type = \is_array( $post_type ) ? reset( $post_type ) : $post_type;
|
128 |
+
} elseif ( \is_post_type_archive() ) {
|
129 |
+
$post_type = \get_query_var( 'post_type' );
|
130 |
+
$post_type = \is_array( $post_type ) ? reset( $post_type ) : $post_type;
|
131 |
+
} else {
|
132 |
+
// Let WP guess for us. This works reliable (enough) on non-404 queries.
|
133 |
+
$post_type = \get_post_type();
|
134 |
+
}
|
135 |
+
} else {
|
136 |
+
$post_type = \get_post_type( $this->get_the_real_ID() );
|
137 |
+
}
|
138 |
|
139 |
+
return $post_type;
|
140 |
}
|
141 |
|
142 |
/**
|
148 |
* @return string
|
149 |
*/
|
150 |
public function get_admin_post_type() {
|
151 |
+
return $GLOBALS['current_screen']->post_type ?? '';
|
|
|
152 |
}
|
153 |
|
154 |
/**
|
164 |
$taxonomy = $taxonomy ?: $this->get_current_taxonomy();
|
165 |
$tax = $taxonomy ? \get_taxonomy( $taxonomy ) : null;
|
166 |
|
167 |
+
return $tax->object_type ?? [];
|
168 |
}
|
169 |
|
170 |
/**
|
182 |
if ( \is_admin() )
|
183 |
return $this->get_the_real_admin_ID();
|
184 |
|
185 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
186 |
+
if ( $use_cache && null !== $memo = umemo( __METHOD__ ) ) return $memo;
|
187 |
+
|
188 |
$use_cache = $use_cache && $this->can_cache_query( __METHOD__ );
|
189 |
|
190 |
+
// Try to get ID from plugins or feed when caching is available.
|
191 |
if ( $use_cache ) {
|
192 |
+
/**
|
193 |
+
* @since 2.5.0
|
194 |
+
* @param int $id
|
195 |
+
*/
|
196 |
+
$id = \apply_filters(
|
197 |
+
'the_seo_framework_real_id',
|
198 |
+
$this->is_feed() ? \get_the_ID() : 0
|
199 |
+
);
|
|
|
|
|
|
|
|
|
200 |
}
|
201 |
|
202 |
/**
|
203 |
* @since 2.6.2
|
204 |
+
* @param int $id Can be either the Post ID, or the Term ID.
|
205 |
+
* @param bool $use_cache Whether this value is stored in runtime caching.
|
206 |
*/
|
207 |
+
$id = (int) \apply_filters_ref_array(
|
208 |
+
'the_seo_framework_current_object_id',
|
209 |
+
[
|
210 |
+
// This catches most IDs. Even Post IDs.
|
211 |
+
( $id ?? 0 ) ?: \get_queried_object_id(),
|
212 |
+
$use_cache,
|
213 |
+
]
|
214 |
+
);
|
215 |
+
|
216 |
+
// Do not overwrite cache when not requested. Otherwise, we'd have two "initial" states, causing incongruities.
|
217 |
+
return $use_cache ? umemo( __METHOD__, $id ) : $id;
|
218 |
}
|
219 |
|
220 |
/**
|
237 |
return (int) \apply_filters( 'the_seo_framework_current_admin_id', $id );
|
238 |
}
|
239 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
/**
|
241 |
* Returns the front page ID, if home is a page.
|
242 |
*
|
245 |
* @return int the ID.
|
246 |
*/
|
247 |
public function get_the_front_page_ID() { // phpcs:ignore -- ID is capitalized because WordPress does that too: get_the_ID().
|
248 |
+
return umemo( __METHOD__ )
|
249 |
+
?? umemo(
|
250 |
+
__METHOD__,
|
251 |
+
$this->has_page_on_front() ? (int) \get_option( 'page_on_front' ) : 0
|
252 |
+
);
|
253 |
}
|
254 |
|
255 |
/**
|
287 |
* @return string The queried taxonomy type.
|
288 |
*/
|
289 |
public function get_current_taxonomy() {
|
290 |
+
return $this->memo_query()
|
291 |
+
?? $this->memo_query(
|
292 |
+
( \is_admin() ? $GLOBALS['current_screen'] : \get_queried_object() )
|
293 |
+
->taxonomy ?? ''
|
294 |
+
);
|
|
|
|
|
|
|
295 |
}
|
296 |
|
297 |
/**
|
344 |
if ( ! $attachment )
|
345 |
return \is_attachment();
|
346 |
|
347 |
+
return $this->memo_query( null, $attachment )
|
348 |
+
?? $this->memo_query( \is_attachment( $attachment ), $attachment );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
349 |
}
|
350 |
|
351 |
/**
|
377 |
public function is_singular_archive( $post = null ) {
|
378 |
|
379 |
if ( isset( $post ) ) {
|
380 |
+
$id = \is_int( $post )
|
381 |
+
? $post
|
382 |
+
: ( \get_post( $post )->ID ?? 0 );
|
383 |
} else {
|
384 |
$id = null;
|
385 |
}
|
386 |
|
387 |
+
return $this->memo_query( null, $id )
|
388 |
+
?? $this->memo_query(
|
389 |
+
/**
|
390 |
+
* @since 4.0.5
|
391 |
+
* @since 4.0.7 The $id can now be null, when no post is given.
|
392 |
+
* @param bool $is_singular_archive Whether the post ID is a singular archive.
|
393 |
+
* @param int|null $id The supplied post ID. Null when in the loop.
|
394 |
+
*/
|
395 |
+
\apply_filters_ref_array(
|
396 |
+
'the_seo_framework_is_singular_archive',
|
397 |
+
[
|
398 |
+
$this->is_home_as_page( $id ),
|
399 |
+
$id,
|
400 |
+
]
|
401 |
+
),
|
402 |
+
$id
|
403 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
404 |
}
|
405 |
|
406 |
/**
|
416 |
if ( \is_admin() )
|
417 |
return $this->is_archive_admin();
|
418 |
|
419 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
420 |
+
if ( null !== $memo = $this->memo_query() ) return $memo;
|
421 |
+
|
422 |
+
$can_cache = $this->can_cache_query( __METHOD__ );
|
423 |
+
|
424 |
if ( \is_archive() && false === $this->is_singular() )
|
425 |
+
return $can_cache ? $this->memo_query( true ) : true;
|
426 |
|
427 |
+
// The $can_cache check is used here because it asserted $wp_query is valid on the front-end.
|
428 |
+
if ( $can_cache && false === $this->is_singular() ) {
|
429 |
global $wp_query;
|
430 |
|
431 |
+
if ( $wp_query->is_category || $wp_query->is_tag || $wp_query->is_tax || $wp_query->is_post_type_archive || $wp_query->is_date || $wp_query->is_author )
|
432 |
+
return $this->memo_query( true );
|
433 |
}
|
434 |
|
435 |
+
return $can_cache ? $this->memo_query( false ) : false;
|
436 |
}
|
437 |
|
438 |
/**
|
444 |
* @return bool Post Type is archive
|
445 |
*/
|
446 |
public function is_archive_admin() {
|
447 |
+
return \in_array( $GLOBALS['current_screen']->base ?? '', [ 'edit-tags', 'term' ], true );
|
|
|
448 |
}
|
449 |
|
450 |
/**
|
456 |
* @return bool True if on Term Edit screen. False otherwise.
|
457 |
*/
|
458 |
public function is_term_edit() {
|
459 |
+
return 'term' === ( $GLOBALS['current_screen']->base ?? '' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
460 |
}
|
461 |
|
462 |
/**
|
468 |
* @return bool We're on Post Edit screen.
|
469 |
*/
|
470 |
public function is_post_edit() {
|
471 |
+
return 'post' === ( $GLOBALS['current_screen']->base ?? '' );
|
|
|
472 |
}
|
473 |
|
474 |
/**
|
480 |
* @return bool We're on the edit screen.
|
481 |
*/
|
482 |
public function is_wp_lists_edit() {
|
483 |
+
return \in_array( $GLOBALS['current_screen']->base ?? '', [ 'edit-tags', 'edit' ], true );
|
|
|
484 |
}
|
485 |
|
486 |
/**
|
492 |
* @return bool True if on Profile Edit screen. False otherwise.
|
493 |
*/
|
494 |
public function is_profile_edit() {
|
495 |
+
return \in_array( $GLOBALS['current_screen']->base ?? '', [ 'profile', 'user-edit' ], true );
|
|
|
496 |
}
|
497 |
|
498 |
/**
|
506 |
*/
|
507 |
public function is_author( $author = '' ) {
|
508 |
|
509 |
+
if ( ! $author )
|
510 |
return \is_author();
|
511 |
|
512 |
+
return $this->memo_query( null, $author )
|
513 |
+
?? $this->memo_query( \is_author( $author ), $author );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
514 |
}
|
515 |
|
516 |
/**
|
517 |
+
* Detects the blog page.
|
518 |
*
|
519 |
+
* @since 2.6.0
|
520 |
+
* @since 4.2.0 Added the first parameter to allow custom query testing.
|
|
|
521 |
*
|
522 |
+
* @param int|WP_Post|null $post Optional. Post ID or post object.
|
523 |
+
* Do not supply from WP_Query's main loop-query.
|
524 |
+
* @return bool
|
525 |
*/
|
526 |
+
public function is_home( $post = null ) {
|
527 |
|
528 |
+
if ( isset( $post ) ) {
|
529 |
+
$id = \is_int( $post )
|
530 |
+
? $post
|
531 |
+
: ( \get_post( $post )->ID ?? 0 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
532 |
|
533 |
+
$is_pfp = (int) \get_option( 'page_for_posts' ) === $id;
|
534 |
+
} else {
|
535 |
+
$is_pfp = \is_home();
|
|
|
536 |
}
|
537 |
|
538 |
+
return $is_pfp;
|
|
|
|
|
|
|
|
|
|
|
|
|
539 |
}
|
540 |
|
541 |
/**
|
542 |
+
* Detects the non-front blog page.
|
543 |
*
|
544 |
+
* @since 4.2.0
|
|
|
|
|
|
|
|
|
545 |
*
|
546 |
+
* @param int|WP_Post|null $post Optional. Post ID or post object.
|
547 |
+
* Do not supply from WP_Query's main loop-query.
|
548 |
* @return bool
|
549 |
*/
|
550 |
+
public function is_home_as_page( $post = null ) {
|
551 |
+
// If front is a blog, the blog is never a page.
|
552 |
+
return $this->has_page_on_front() ? $this->is_home( $post ) : false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
553 |
}
|
554 |
|
555 |
/**
|
566 |
if ( \is_admin() )
|
567 |
return $this->is_category_admin();
|
568 |
|
569 |
+
return $this->memo_query( null, $category )
|
570 |
+
?? $this->memo_query( \is_category( $category ), $category );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
571 |
}
|
572 |
|
573 |
/**
|
642 |
public function is_real_front_page() {
|
643 |
|
644 |
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
645 |
+
if ( null !== $cache = $this->memo_query() )
|
646 |
return $cache;
|
647 |
|
648 |
+
$is_front_page = \is_front_page();
|
|
|
|
|
|
|
649 |
|
650 |
+
if ( ! $is_front_page ) {
|
651 |
+
// Elegant Themes's Extra Support: Assert home, but only when it's not registered as such.
|
652 |
+
$is_front_page = $this->is_home() && 0 === $this->get_the_real_ID()
|
653 |
+
&& ! \in_array( \get_option( 'show_on_front' ), [ 'page', 'post' ], true );
|
|
|
|
|
654 |
}
|
655 |
|
656 |
+
return $this->memo_query( $is_front_page );
|
|
|
|
|
|
|
|
|
|
|
657 |
}
|
658 |
|
659 |
/**
|
675 |
return $id === $this->get_the_front_page_ID();
|
676 |
}
|
677 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
678 |
/**
|
679 |
* Detects month archives.
|
680 |
*
|
706 |
if ( empty( $page ) )
|
707 |
return \is_page();
|
708 |
|
709 |
+
return $this->memo_query( null, $page )
|
710 |
+
?? $this->memo_query(
|
711 |
+
\is_int( $page ) || $page instanceof \WP_Post
|
712 |
+
? \in_array( \get_post_type( $page ), $this->get_hierarchical_post_types(), true )
|
713 |
+
: \is_page( $page ),
|
714 |
+
$page
|
715 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
716 |
}
|
717 |
|
718 |
/**
|
745 |
$is_preview = false;
|
746 |
|
747 |
if ( \is_preview()
|
748 |
+
&& \is_user_logged_in()
|
749 |
+
&& \is_singular()
|
750 |
+
&& \current_user_can( 'edit_post', \get_the_ID() )
|
751 |
+
&& isset( $_GET['preview_id'], $_GET['preview_nonce'] )
|
752 |
+
&& \wp_verify_nonce( $_GET['preview_nonce'], 'post_preview_' . (int) $_GET['preview_id'] )
|
753 |
) {
|
754 |
$is_preview = true;
|
755 |
}
|
785 |
if ( \is_admin() )
|
786 |
return $this->is_single_admin();
|
787 |
|
788 |
+
return $this->memo_query( null, $post )
|
789 |
+
?? $this->memo_query(
|
790 |
+
\is_int( $post ) || $post instanceof \WP_Post
|
791 |
+
? \in_array( \get_post_type( $post ), $this->get_nonhierarchical_post_types(), true )
|
792 |
+
: \is_single( $post ),
|
793 |
+
$post
|
794 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
795 |
}
|
796 |
|
797 |
/**
|
834 |
if ( $post_types )
|
835 |
return \is_singular( $post_types );
|
836 |
|
837 |
+
return $this->memo_query()
|
838 |
+
?? $this->memo_query( \is_singular() || $this->is_singular_archive() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
839 |
}
|
840 |
|
841 |
/**
|
849 |
* @return bool Post Type is singular
|
850 |
*/
|
851 |
public function is_singular_admin() {
|
852 |
+
return \in_array( $GLOBALS['current_screen']->base ?? '', [ 'edit', 'post' ], true );
|
|
|
853 |
}
|
854 |
|
855 |
/**
|
863 |
*/
|
864 |
public function is_static_frontpage( $id = 0 ) {
|
865 |
|
866 |
+
$front_id = umemo( __METHOD__ )
|
867 |
+
?? umemo(
|
868 |
+
__METHOD__,
|
869 |
+
'page' === \get_option( 'show_on_front' ) ? (int) \get_option( 'page_on_front' ) : false
|
870 |
+
);
|
871 |
|
872 |
return false !== $front_id && ( $id ?: $this->get_the_real_ID() ) === $front_id;
|
873 |
}
|
887 |
if ( \is_admin() )
|
888 |
return $this->is_tag_admin();
|
889 |
|
890 |
+
return $this->memo_query( null, $tag )
|
891 |
+
?? $this->memo_query( \is_tag( $tag ), $tag );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
892 |
}
|
893 |
|
894 |
/**
|
915 |
* @return bool
|
916 |
*/
|
917 |
public function is_tax( $taxonomy = '', $term = '' ) {
|
918 |
+
return $this->memo_query( null, $taxonomy, $term )
|
919 |
+
?? $this->memo_query( \is_tax( $taxonomy, $term ), $taxonomy, $term );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
920 |
}
|
921 |
|
922 |
/**
|
929 |
* @return bool
|
930 |
*/
|
931 |
public function is_shop( $post = null ) {
|
932 |
+
return $this->memo_query( null, $post )
|
933 |
+
?? $this->memo_query(
|
934 |
+
/**
|
935 |
+
* @since 4.0.5
|
936 |
+
* @since 4.1.4 Now has its return value memoized.
|
937 |
+
* @param bool $is_shop Whether the post ID is a shop.
|
938 |
+
* @param int $id The current or supplied post ID.
|
939 |
+
*/
|
940 |
+
\apply_filters_ref_array( 'the_seo_framework_is_shop', [ false, $post ] ),
|
941 |
+
$post
|
942 |
+
);
|
|
|
|
|
|
|
|
|
|
|
943 |
}
|
944 |
|
945 |
/**
|
956 |
if ( \is_admin() )
|
957 |
return $this->is_product_admin();
|
958 |
|
959 |
+
return $this->memo_query( null, $post )
|
960 |
+
?? $this->memo_query(
|
961 |
+
/**
|
962 |
+
* @since 4.0.5
|
963 |
+
* @since 4.1.4 Now has its return value memoized.
|
964 |
+
* @param bool $is_product
|
965 |
+
* @param int|WP_Post|null $post (Optional) Post ID or post object.
|
966 |
+
*/
|
967 |
+
(bool) \apply_filters_ref_array( 'the_seo_framework_is_product', [ false, $post ] ),
|
968 |
+
$post
|
969 |
+
);
|
|
|
|
|
|
|
|
|
970 |
}
|
971 |
|
972 |
/**
|
978 |
* @return bool
|
979 |
*/
|
980 |
public function is_product_admin() {
|
981 |
+
return $this->memo_query()
|
982 |
+
?? $this->memo_query(
|
983 |
+
/**
|
984 |
+
* @since 4.0.5
|
985 |
+
* @since 4.1.4 Now has its return value memoized.
|
986 |
+
* @param bool $is_product_admin
|
987 |
+
*/
|
988 |
+
(bool) \apply_filters( 'the_seo_framework_is_product_admin', false )
|
989 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
990 |
}
|
991 |
|
992 |
/**
|
1009 |
* @return bool True if SSL, false otherwise.
|
1010 |
*/
|
1011 |
public function is_ssl() {
|
1012 |
+
return umemo( __METHOD__ )
|
1013 |
+
?? umemo( __METHOD__, \is_ssl() );
|
|
|
|
|
1014 |
}
|
1015 |
|
1016 |
/**
|
1033 |
if ( ! $secure )
|
1034 |
return $this->is_menu_page( $this->seo_settings_page_hook, $this->seo_settings_page_slug );
|
1035 |
|
1036 |
+
return $this->memo_query()
|
1037 |
+
?? $this->memo_query( $this->is_menu_page( $this->seo_settings_page_hook ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1038 |
}
|
1039 |
|
1040 |
/**
|
1066 |
return $page_hook === $pagehook;
|
1067 |
} elseif ( \is_admin() && $pageslug ) {
|
1068 |
// N.B. $_GET['page'] === $plugin_page after admin_init...
|
|
|
1069 |
// phpcs:ignore, WordPress.Security.NonceVerification -- This is a public variable, no data is processed.
|
1070 |
+
return ( $_GET['page'] ?? '' ) === $pageslug;
|
1071 |
}
|
1072 |
|
1073 |
return false;
|
1074 |
}
|
1075 |
|
1076 |
/**
|
1077 |
+
* Returns the current page number.
|
1078 |
+
* Fetches global `$page` from `WP_Query` to prevent conflicts.
|
1079 |
*
|
1080 |
* @since 2.6.0
|
1081 |
* @since 3.2.4 1. Added overflow protection.
|
1082 |
* 2. Now always returns 1 on the admin screens.
|
1083 |
+
* @TODO Add better protection? This can get filled by users when is_paged() is true.
|
1084 |
+
* WordPress has no protection/test for this, either.
|
1085 |
*
|
1086 |
* @return int (R>0) $page Always a positive number.
|
1087 |
*/
|
1088 |
public function page() {
|
1089 |
|
1090 |
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
1091 |
+
if ( null !== $memo = $this->memo_query() )
|
1092 |
+
return $memo;
|
1093 |
|
1094 |
if ( $this->is_multipage() ) {
|
1095 |
$page = (int) \get_query_var( 'page' );
|
1102 |
$page = 1;
|
1103 |
}
|
1104 |
|
1105 |
+
return $this->memo_query( $page ?: 1 );
|
|
|
|
|
|
|
|
|
|
|
1106 |
}
|
1107 |
|
1108 |
/**
|
1109 |
+
* Returns the current page number.
|
1110 |
+
* Fetches global `$paged` from `WP_Query` to prevent conflicts.
|
1111 |
*
|
1112 |
* @since 2.6.0
|
1113 |
* @since 3.2.4 1. Added overflow protection.
|
1118 |
public function paged() {
|
1119 |
|
1120 |
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
1121 |
+
if ( null !== $memo = $this->memo_query() )
|
1122 |
+
return $memo;
|
1123 |
|
1124 |
if ( $this->is_multipage() ) {
|
1125 |
$paged = (int) \get_query_var( 'paged' );
|
1133 |
$paged = 1;
|
1134 |
}
|
1135 |
|
1136 |
+
return $this->memo_query( $paged ?: 1 );
|
|
|
|
|
|
|
|
|
|
|
1137 |
}
|
1138 |
|
1139 |
/**
|
1151 |
public function numpages() {
|
1152 |
|
1153 |
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
|
1154 |
+
if ( null !== $memo = $this->memo_query() )
|
1155 |
+
return $memo;
|
1156 |
|
1157 |
if ( \is_admin() ) {
|
1158 |
+
// Disable pagination detection in admin: Always on page 1.
|
1159 |
+
return $this->memo_query( 1 );
|
|
|
1160 |
}
|
1161 |
|
1162 |
global $wp_query;
|
1163 |
|
|
|
|
|
1164 |
if ( $this->is_singular() && ! $this->is_singular_archive() )
|
1165 |
$post = \get_post( $this->get_the_real_ID() );
|
1166 |
|
1200 |
$numpages = 0;
|
1201 |
}
|
1202 |
|
1203 |
+
return $this->memo_query( $numpages );
|
|
|
|
|
1204 |
}
|
1205 |
|
1206 |
/**
|
1222 |
* Memoizes the return value once set.
|
1223 |
*
|
1224 |
* @since 2.9.2
|
1225 |
+
* @since 4.0.0 Now memoizes instead of populating class properties.
|
1226 |
*
|
1227 |
* @param bool $set Whether to set "doing sitemap".
|
1228 |
* @return bool
|
1229 |
*/
|
1230 |
public function is_sitemap( $set = false ) {
|
1231 |
+
return memo( $set ?: null ) ?? false;
|
|
|
|
|
|
|
|
|
|
|
1232 |
}
|
1233 |
|
1234 |
/**
|
1243 |
}
|
1244 |
|
1245 |
/**
|
1246 |
+
* Memoizes queries.
|
1247 |
+
* Should not be used on methods that aren't final.
|
1248 |
*
|
1249 |
+
* The first parameter might not get retrieved in a later call, for this method
|
1250 |
+
* also tests whether the query is setup correctly at the time of the call.
|
1251 |
+
*
|
1252 |
+
* @since 4.2.0
|
1253 |
+
*
|
1254 |
+
* @param mixed $value_to_set The value to set.
|
1255 |
+
* @param mixed ...$args Extra arguments, that are used to differentiaty queries.
|
1256 |
+
* @return mixed $value_to_set when provided.
|
1257 |
+
* Otherwise, the previously sent $value_to_set.
|
1258 |
+
* When that's not set either, null.
|
|
|
|
|
|
|
|
|
1259 |
*/
|
1260 |
+
protected function memo_query( $value_to_set = null, ...$args ) {
|
1261 |
|
1262 |
static $can_cache_query = null;
|
1263 |
|
1264 |
+
// phpcs:ignore, WordPress.PHP.DevelopmentFunctions -- This is the only efficient way.
|
1265 |
+
$caller = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 )[1]['function'] ?? '';
|
1266 |
+
|
1267 |
if ( null === $can_cache_query ) {
|
1268 |
+
if ( $this->can_cache_query( $caller ) ) {
|
1269 |
$can_cache_query = true;
|
1270 |
} else {
|
1271 |
+
return $value_to_set;
|
1272 |
}
|
1273 |
}
|
1274 |
|
1275 |
+
return umemo( __METHOD__, $value_to_set, $caller, ...$args );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1276 |
}
|
1277 |
}
|
@@ -38,7 +38,7 @@ class Render extends Admin_Init {
|
|
38 |
* Returns the document title.
|
39 |
*
|
40 |
* This method serves as a callback for filter `pre_get_document_title`.
|
41 |
-
* Use
|
42 |
*
|
43 |
* @since 3.1.0
|
44 |
* @see $this->get_title()
|
@@ -69,7 +69,7 @@ class Render extends Admin_Init {
|
|
69 |
* Returns the document title.
|
70 |
*
|
71 |
* This method serves as a callback for filter `wp_title`.
|
72 |
-
* Use
|
73 |
*
|
74 |
* @since 3.1.0
|
75 |
* @since 4.0.0 Removed extraneous, unused parameters.
|
@@ -112,14 +112,12 @@ class Render extends Admin_Init {
|
|
112 |
*/
|
113 |
public function get_image_from_cache() {
|
114 |
|
115 |
-
$url = '';
|
116 |
-
|
117 |
foreach ( $this->get_image_details_from_cache( ! $this->get_option( 'multi_og_image' ) ) as $image ) {
|
118 |
$url = $image['url'];
|
119 |
if ( $url ) break;
|
120 |
}
|
121 |
|
122 |
-
return $url;
|
123 |
}
|
124 |
|
125 |
/**
|
@@ -132,8 +130,7 @@ class Render extends Admin_Init {
|
|
132 |
* @return string The cached Twitter card.
|
133 |
*/
|
134 |
public function get_current_twitter_card_type() {
|
135 |
-
|
136 |
-
return isset( $cache ) ? $cache : $cache = $this->generate_twitter_card_type();
|
137 |
}
|
138 |
|
139 |
/**
|
@@ -158,7 +155,7 @@ class Render extends Admin_Init {
|
|
158 |
* @param bool|string $text The element's contents, if any.
|
159 |
* @param bool $new_line Whether to add a new line to the end of the element.
|
160 |
*/
|
161 |
-
public function render_element(
|
162 |
|
163 |
$attr = '';
|
164 |
|
@@ -817,9 +814,9 @@ class Render extends Admin_Init {
|
|
817 |
*
|
818 |
* @since 2.2.2
|
819 |
* @since 2.8.0 Returns empty on product pages.
|
820 |
-
* @since 3.0.0
|
821 |
-
*
|
822 |
-
*
|
823 |
*
|
824 |
* @return string The Article Publishing Time meta tag.
|
825 |
*/
|
@@ -861,8 +858,8 @@ class Render extends Admin_Init {
|
|
861 |
* @since 2.2.2
|
862 |
* @since 2.7.0 Listens to $this->get_the_real_ID() instead of WordPress Core ID determination.
|
863 |
* @since 2.8.0 Returns empty on product pages.
|
864 |
-
* @since 3.0.0
|
865 |
-
*
|
866 |
* @since 4.1.4 No longer renders the Open Graph Updated Time meta tag.
|
867 |
* @see og_updated_time()
|
868 |
*
|
@@ -1143,20 +1140,19 @@ class Render extends Admin_Init {
|
|
1143 |
* @return array
|
1144 |
*/
|
1145 |
public function get_robots_meta() {
|
1146 |
-
|
1147 |
-
|
1148 |
-
|
1149 |
-
|
1150 |
-
|
1151 |
-
|
1152 |
-
|
1153 |
-
|
1154 |
-
|
1155 |
-
|
1156 |
-
|
1157 |
-
|
1158 |
-
|
1159 |
-
]
|
1160 |
);
|
1161 |
}
|
1162 |
|
@@ -1203,9 +1199,8 @@ class Render extends Admin_Init {
|
|
1203 |
*/
|
1204 |
public function paged_urls() {
|
1205 |
|
1206 |
-
$id = $this->get_the_real_ID();
|
1207 |
-
|
1208 |
$paged_urls = $this->get_paged_urls();
|
|
|
1209 |
|
1210 |
/**
|
1211 |
* @since 2.6.0
|
@@ -1256,60 +1251,65 @@ class Render extends Admin_Init {
|
|
1256 |
*
|
1257 |
* @since 2.9.2
|
1258 |
* @since 4.0.0 Added boot timers.
|
1259 |
-
*
|
1260 |
-
*
|
1261 |
-
*
|
1262 |
-
*
|
|
|
|
|
|
|
|
|
1263 |
* @return string The SEO Framework's HTML plugin indicator.
|
1264 |
*/
|
1265 |
-
|
1266 |
-
|
1267 |
-
|
1268 |
-
|
1269 |
-
|
1270 |
-
|
1271 |
-
|
1272 |
-
|
1273 |
-
|
1274 |
-
|
1275 |
-
|
1276 |
-
|
1277 |
-
|
1278 |
-
|
1279 |
-
|
1280 |
-
|
1281 |
-
|
1282 |
-
|
1283 |
-
|
1284 |
-
|
1285 |
-
|
1286 |
-
|
1287 |
-
|
1288 |
-
|
1289 |
-
|
1290 |
-
|
1291 |
-
|
1292 |
-
|
1293 |
-
if ( 'before' === $where ) {
|
1294 |
-
/* translators: 1 = The SEO Framework, 2 = 'by Sybre Waaijer */
|
1295 |
-
$output = sprintf( '%1$s %2$s', 'The SEO Framework', $cache['author'] );
|
1296 |
-
|
1297 |
-
return sprintf( '<!-- %s -->', trim( $output ) ) . PHP_EOL;
|
1298 |
-
} else {
|
1299 |
-
if ( $cache['show_timer'] && $timing ) {
|
1300 |
-
$timers = sprintf(
|
1301 |
-
' | %s meta | %s boot',
|
1302 |
-
number_format( ( microtime( true ) - $timing ) * 1e3, 2, null, '' ) . 'ms',
|
1303 |
-
number_format( _bootstrap_timer() * 1e3, 2, null, '' ) . 'ms'
|
1304 |
-
);
|
1305 |
-
} else {
|
1306 |
-
$timers = '';
|
1307 |
-
}
|
1308 |
-
/* translators: 1 = The SEO Framework, 2 = 'by Sybre Waaijer */
|
1309 |
-
$output = sprintf( '%1$s %2$s', 'The SEO Framework', $cache['author'] ) . $timers;
|
1310 |
|
1311 |
-
|
1312 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1313 |
}
|
1314 |
|
1315 |
/**
|
@@ -1350,21 +1350,23 @@ class Render extends Admin_Init {
|
|
1350 |
*
|
1351 |
* @since 2.6.0
|
1352 |
* @since 3.1.0 Removed cache.
|
1353 |
-
* @since 3.1.4
|
1354 |
-
*
|
1355 |
-
* @TODO add facebook validation.
|
|
|
1356 |
*
|
1357 |
* @return bool
|
1358 |
*/
|
1359 |
public function use_og_tags() {
|
1360 |
-
|
1361 |
-
|
1362 |
-
|
1363 |
-
|
1364 |
-
|
1365 |
-
|
1366 |
-
|
1367 |
-
|
|
|
1368 |
);
|
1369 |
}
|
1370 |
|
@@ -1374,20 +1376,17 @@ class Render extends Admin_Init {
|
|
1374 |
*
|
1375 |
* @since 2.6.0
|
1376 |
* @since 3.1.0 Removed cache.
|
1377 |
-
* @since 3.1.4
|
1378 |
-
*
|
1379 |
*
|
1380 |
* @return bool
|
1381 |
*/
|
1382 |
public function use_facebook_tags() {
|
1383 |
-
|
1384 |
-
|
1385 |
-
|
1386 |
-
|
1387 |
-
|
1388 |
-
return isset( $cache ) ? $cache : $cache = (bool) \apply_filters(
|
1389 |
-
'the_seo_framework_use_facebook_tags',
|
1390 |
-
(bool) $this->get_option( 'facebook_tags' )
|
1391 |
);
|
1392 |
}
|
1393 |
|
@@ -1402,14 +1401,11 @@ class Render extends Admin_Init {
|
|
1402 |
* @return bool
|
1403 |
*/
|
1404 |
public function use_twitter_tags() {
|
1405 |
-
|
1406 |
-
|
1407 |
-
|
1408 |
-
|
1409 |
-
|
1410 |
-
return isset( $cache ) ? $cache : $cache = (bool) \apply_filters(
|
1411 |
-
'the_seo_framework_use_twitter_tags',
|
1412 |
-
$this->get_option( 'twitter_tags' ) && $this->get_current_twitter_card_type()
|
1413 |
);
|
1414 |
}
|
1415 |
}
|
38 |
* Returns the document title.
|
39 |
*
|
40 |
* This method serves as a callback for filter `pre_get_document_title`.
|
41 |
+
* Use tsf()->get_title() instead.
|
42 |
*
|
43 |
* @since 3.1.0
|
44 |
* @see $this->get_title()
|
69 |
* Returns the document title.
|
70 |
*
|
71 |
* This method serves as a callback for filter `wp_title`.
|
72 |
+
* Use tsf()->get_title() instead.
|
73 |
*
|
74 |
* @since 3.1.0
|
75 |
* @since 4.0.0 Removed extraneous, unused parameters.
|
112 |
*/
|
113 |
public function get_image_from_cache() {
|
114 |
|
|
|
|
|
115 |
foreach ( $this->get_image_details_from_cache( ! $this->get_option( 'multi_og_image' ) ) as $image ) {
|
116 |
$url = $image['url'];
|
117 |
if ( $url ) break;
|
118 |
}
|
119 |
|
120 |
+
return $url ?? '';
|
121 |
}
|
122 |
|
123 |
/**
|
130 |
* @return string The cached Twitter card.
|
131 |
*/
|
132 |
public function get_current_twitter_card_type() {
|
133 |
+
return memo() ?? memo( $this->generate_twitter_card_type() );
|
|
|
134 |
}
|
135 |
|
136 |
/**
|
155 |
* @param bool|string $text The element's contents, if any.
|
156 |
* @param bool $new_line Whether to add a new line to the end of the element.
|
157 |
*/
|
158 |
+
public function render_element( $attributes = [], $tag = 'meta', $text = false, $new_line = true ) {
|
159 |
|
160 |
$attr = '';
|
161 |
|
814 |
*
|
815 |
* @since 2.2.2
|
816 |
* @since 2.8.0 Returns empty on product pages.
|
817 |
+
* @since 3.0.0 1. Now checks for 0000 timestamps.
|
818 |
+
* 2. Now uses timestamp formats.
|
819 |
+
* 3. Now uses GMT time.
|
820 |
*
|
821 |
* @return string The Article Publishing Time meta tag.
|
822 |
*/
|
858 |
* @since 2.2.2
|
859 |
* @since 2.7.0 Listens to $this->get_the_real_ID() instead of WordPress Core ID determination.
|
860 |
* @since 2.8.0 Returns empty on product pages.
|
861 |
+
* @since 3.0.0 1. Now checks for 0000 timestamps.
|
862 |
+
* 2. Now uses timestamp formats.
|
863 |
* @since 4.1.4 No longer renders the Open Graph Updated Time meta tag.
|
864 |
* @see og_updated_time()
|
865 |
*
|
1140 |
* @return array
|
1141 |
*/
|
1142 |
public function get_robots_meta() {
|
1143 |
+
return memo() ?? memo(
|
1144 |
+
/**
|
1145 |
+
* @since 2.6.0
|
1146 |
+
* @param array $meta The robots meta.
|
1147 |
+
* @param int $id The current post or term ID.
|
1148 |
+
*/
|
1149 |
+
(array) \apply_filters_ref_array(
|
1150 |
+
'the_seo_framework_robots_meta',
|
1151 |
+
[
|
1152 |
+
$this->generate_robots_meta(),
|
1153 |
+
$this->get_the_real_ID(),
|
1154 |
+
]
|
1155 |
+
)
|
|
|
1156 |
);
|
1157 |
}
|
1158 |
|
1199 |
*/
|
1200 |
public function paged_urls() {
|
1201 |
|
|
|
|
|
1202 |
$paged_urls = $this->get_paged_urls();
|
1203 |
+
$id = $this->get_the_real_ID();
|
1204 |
|
1205 |
/**
|
1206 |
* @since 2.6.0
|
1251 |
*
|
1252 |
* @since 2.9.2
|
1253 |
* @since 4.0.0 Added boot timers.
|
1254 |
+
* @since 4.2.0 1. The annotation is translatable again (regressed in 4.0.0).
|
1255 |
+
* 2. Is now a protected function.
|
1256 |
+
* @access private
|
1257 |
+
*
|
1258 |
+
* @param string $where Determines the position of the indicator.
|
1259 |
+
* Accepts 'before' for before, anything else for after.
|
1260 |
+
* @param int $meta_timer Total meta time.
|
1261 |
+
* @param int $bootstrap_timer Total bootstrap time.
|
1262 |
* @return string The SEO Framework's HTML plugin indicator.
|
1263 |
*/
|
1264 |
+
protected function get_plugin_indicator( $where = 'before', $meta_timer = 0, $bootstrap_timer = 0 ) {
|
1265 |
+
|
1266 |
+
$cache = memo() ?? memo( [
|
1267 |
+
/**
|
1268 |
+
* @since 2.0.0
|
1269 |
+
* @param bool $run Whether to run and show the plugin indicator.
|
1270 |
+
*/
|
1271 |
+
'run' => (bool) \apply_filters( 'the_seo_framework_indicator', true ),
|
1272 |
+
/**
|
1273 |
+
* @since 2.4.0
|
1274 |
+
* @param bool $show_timer Whether to show the generation time in the indicator.
|
1275 |
+
*/
|
1276 |
+
'show_timer' => (bool) \apply_filters( 'the_seo_framework_indicator_timing', true ),
|
1277 |
+
'annotation' => trim( vsprintf(
|
1278 |
+
/* translators: 1 = The SEO Framework, 2 = 'by Sybre Waaijer */
|
1279 |
+
\esc_html__( '%1$s %2$s', 'autodescription' ),
|
1280 |
+
[
|
1281 |
+
'The SEO Framework',
|
1282 |
+
/**
|
1283 |
+
* @since 2.4.0
|
1284 |
+
* @param bool $sybre Whether to show the author name in the indicator.
|
1285 |
+
*/
|
1286 |
+
\apply_filters( 'sybre_waaijer_<3', true ) // phpcs:ignore, WordPress.NamingConventions.ValidHookName -- Easter egg.
|
1287 |
+
? \esc_html__( 'by Sybre Waaijer', 'autodescription' )
|
1288 |
+
: '',
|
1289 |
+
]
|
1290 |
+
) ),
|
1291 |
+
] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1292 |
|
1293 |
+
if ( ! $cache['run'] ) return '';
|
1294 |
+
|
1295 |
+
switch ( $where ) :
|
1296 |
+
case 'before':
|
1297 |
+
return "<!-- {$cache['annotation']} -->\n";
|
1298 |
+
|
1299 |
+
case 'after':
|
1300 |
+
default:
|
1301 |
+
if ( $cache['show_timer'] && $meta_timer && $bootstrap_timer ) {
|
1302 |
+
$timers = sprintf(
|
1303 |
+
' | %s meta | %s boot',
|
1304 |
+
number_format( $meta_timer * 1e3, 2, null, '' ) . 'ms',
|
1305 |
+
number_format( $bootstrap_timer * 1e3, 2, null, '' ) . 'ms'
|
1306 |
+
);
|
1307 |
+
} else {
|
1308 |
+
$timers = '';
|
1309 |
+
}
|
1310 |
+
|
1311 |
+
return "<!-- / {$cache['annotation']}{$timers} -->\n";
|
1312 |
+
endswitch;
|
1313 |
}
|
1314 |
|
1315 |
/**
|
1350 |
*
|
1351 |
* @since 2.6.0
|
1352 |
* @since 3.1.0 Removed cache.
|
1353 |
+
* @since 3.1.4 1. Added filter.
|
1354 |
+
* 2. Reintroduced cache because of filter.
|
1355 |
+
* @TODO add facebook validation? -> Not all services that use OG tags are called Facebook.
|
1356 |
+
* And not all of those services require the same standards as Facebook.
|
1357 |
*
|
1358 |
* @return bool
|
1359 |
*/
|
1360 |
public function use_og_tags() {
|
1361 |
+
return memo() ?? memo(
|
1362 |
+
/**
|
1363 |
+
* @since 3.1.4
|
1364 |
+
* @param bool $use
|
1365 |
+
*/
|
1366 |
+
(bool) \apply_filters(
|
1367 |
+
'the_seo_framework_use_og_tags',
|
1368 |
+
(bool) $this->get_option( 'og_tags' )
|
1369 |
+
)
|
1370 |
);
|
1371 |
}
|
1372 |
|
1376 |
*
|
1377 |
* @since 2.6.0
|
1378 |
* @since 3.1.0 Removed cache.
|
1379 |
+
* @since 3.1.4 1. Added filter.
|
1380 |
+
* 2. Reintroduced cache because of filter.
|
1381 |
*
|
1382 |
* @return bool
|
1383 |
*/
|
1384 |
public function use_facebook_tags() {
|
1385 |
+
return memo() ?? memo(
|
1386 |
+
(bool) \apply_filters(
|
1387 |
+
'the_seo_framework_use_facebook_tags',
|
1388 |
+
(bool) $this->get_option( 'facebook_tags' )
|
1389 |
+
)
|
|
|
|
|
|
|
1390 |
);
|
1391 |
}
|
1392 |
|
1401 |
* @return bool
|
1402 |
*/
|
1403 |
public function use_twitter_tags() {
|
1404 |
+
return memo() ?? memo(
|
1405 |
+
(bool) \apply_filters(
|
1406 |
+
'the_seo_framework_use_twitter_tags',
|
1407 |
+
$this->get_option( 'twitter_tags' ) && $this->get_current_twitter_card_type()
|
1408 |
+
)
|
|
|
|
|
|
|
1409 |
);
|
1410 |
}
|
1411 |
}
|
@@ -51,10 +51,8 @@ class Sanitize extends Admin_Pages {
|
|
51 |
*/
|
52 |
protected function verify_seo_settings_nonce() {
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
if ( isset( $validated ) )
|
57 |
-
return $validated;
|
58 |
|
59 |
/**
|
60 |
* If this page doesn't parse the site options,
|
@@ -65,17 +63,17 @@ class Sanitize extends Admin_Pages {
|
|
65 |
*/
|
66 |
if ( empty( $_POST[ THE_SEO_FRAMEWORK_SITE_OPTIONS ] )
|
67 |
|| ! \is_array( $_POST[ THE_SEO_FRAMEWORK_SITE_OPTIONS ] ) )
|
68 |
-
return
|
69 |
|
70 |
// This is also handled in /wp-admin/options.php. Nevertheless, one might register outside of scope.
|
71 |
if ( ! \current_user_can( $this->get_settings_capability() ) )
|
72 |
-
return
|
73 |
|
74 |
// This is also handled in /wp-admin/options.php. Nevertheless, one might register outside of scope.
|
75 |
// This also checks the nonce: `_wpnonce`.
|
76 |
\check_admin_referer( THE_SEO_FRAMEWORK_SITE_OPTIONS . '-options' );
|
77 |
|
78 |
-
return
|
79 |
}
|
80 |
|
81 |
/**
|
@@ -141,8 +139,8 @@ class Sanitize extends Admin_Pages {
|
|
141 |
*
|
142 |
* @since 3.1.0
|
143 |
* @since 4.0.0 Emptied and is no longer enqueued.
|
144 |
-
* @since 4.1.0
|
145 |
-
*
|
146 |
* @access private
|
147 |
*
|
148 |
* @param mixed $new_value The new, unserialized, and filtered option value.
|
@@ -151,13 +149,13 @@ class Sanitize extends Admin_Pages {
|
|
151 |
public function _set_backward_compatibility( $new_value ) {
|
152 |
|
153 |
db_4103:
|
154 |
-
|
155 |
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) :
|
156 |
$robots_option_id = $this->get_robots_taxonomy_option_id( $r );
|
157 |
-
$new_robots_options =
|
158 |
|
159 |
-
$new_category_option =
|
160 |
-
$new_tag_option =
|
161 |
|
162 |
// Don't compare to old option--it's never reliably set; it might skip otherwise, although it's always correct.
|
163 |
// Do not resanitize. Others might've overwritten that, let's keep their value.
|
@@ -198,18 +196,12 @@ class Sanitize extends Admin_Pages {
|
|
198 |
]
|
199 |
);
|
200 |
|
201 |
-
$this->add_option_filter(
|
202 |
-
's_title',
|
203 |
-
THE_SEO_FRAMEWORK_SITE_OPTIONS,
|
204 |
-
[
|
205 |
-
'knowledge_name',
|
206 |
-
]
|
207 |
-
);
|
208 |
-
|
209 |
$this->add_option_filter(
|
210 |
's_title_raw',
|
211 |
THE_SEO_FRAMEWORK_SITE_OPTIONS,
|
212 |
[
|
|
|
|
|
213 |
'homepage_title',
|
214 |
'homepage_title_tagline',
|
215 |
'homepage_og_title',
|
@@ -341,7 +333,6 @@ class Sanitize extends Admin_Pages {
|
|
341 |
'sitemaps_output',
|
342 |
'sitemaps_robots',
|
343 |
'sitemaps_modified',
|
344 |
-
'sitemaps_priority',
|
345 |
'sitemap_styles',
|
346 |
'sitemap_logo',
|
347 |
]
|
@@ -402,6 +393,14 @@ class Sanitize extends Admin_Pages {
|
|
402 |
]
|
403 |
);
|
404 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
/**
|
406 |
* @todo create content="code" stripper in PHP (redundant from JS's)
|
407 |
*/
|
@@ -541,7 +540,7 @@ class Sanitize extends Admin_Pages {
|
|
541 |
|
542 |
// Memoize whether a filter has been set for the option already. Should only run once internally.
|
543 |
if ( ! isset( $registered[ $option ] ) ) {
|
544 |
-
\add_filter(
|
545 |
$registered[ $option ] = true;
|
546 |
}
|
547 |
|
@@ -620,8 +619,8 @@ class Sanitize extends Admin_Pages {
|
|
620 |
// Array of suboption values to loop through
|
621 |
$old_value = \get_option( $option, [] );
|
622 |
foreach ( $filters[ $option ] as $suboption => $filter ) {
|
623 |
-
$old_value[ $suboption ] =
|
624 |
-
$new_value[ $suboption ] =
|
625 |
$new_value[ $suboption ] = $this->do_filter( $filter, $new_value[ $suboption ], $old_value[ $suboption ], $option, $suboption );
|
626 |
}
|
627 |
return $new_value;
|
@@ -684,38 +683,74 @@ class Sanitize extends Admin_Pages {
|
|
684 |
return (array) \apply_filters(
|
685 |
'the_seo_framework_available_sanitizer_filters',
|
686 |
[
|
687 |
-
's_left_right'
|
688 |
-
's_left_right_home'
|
689 |
-
's_title_separator'
|
690 |
-
's_description'
|
691 |
-
's_description_raw'
|
692 |
-
's_title'
|
693 |
-
's_title_raw'
|
694 |
-
's_knowledge_type'
|
695 |
-
's_alter_query_type'
|
696 |
-
's_one_zero'
|
697 |
-
's_disabled_post_types'
|
698 |
-
's_disabled_taxonomies'
|
699 |
-
's_post_types'
|
700 |
-
's_taxonomies'
|
701 |
-
'
|
702 |
-
'
|
703 |
-
'
|
704 |
-
'
|
705 |
-
'
|
706 |
-
'
|
707 |
-
'
|
708 |
-
'
|
709 |
-
'
|
710 |
-
'
|
711 |
-
'
|
712 |
-
'
|
713 |
-
'
|
714 |
-
'
|
|
|
715 |
]
|
716 |
);
|
717 |
}
|
718 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
719 |
/**
|
720 |
* Sanitizes term meta.
|
721 |
*
|
@@ -724,7 +759,7 @@ class Sanitize extends Admin_Pages {
|
|
724 |
* @param array $data The term meta to sanitize.
|
725 |
* @return array The sanitized term meta.
|
726 |
*/
|
727 |
-
public function s_term_meta(
|
728 |
|
729 |
foreach ( $data as $key => &$value ) :
|
730 |
switch ( $key ) :
|
@@ -781,7 +816,7 @@ class Sanitize extends Admin_Pages {
|
|
781 |
* @param array $data The post meta to sanitize.
|
782 |
* @return array The sanitized post meta.
|
783 |
*/
|
784 |
-
public function s_post_meta(
|
785 |
|
786 |
foreach ( $data as $key => &$value ) :
|
787 |
switch ( $key ) :
|
@@ -837,11 +872,12 @@ class Sanitize extends Admin_Pages {
|
|
837 |
* Sanitizes user meta.
|
838 |
*
|
839 |
* @since 4.1.4
|
|
|
840 |
*
|
841 |
* @param array $data The user meta to sanitize.
|
842 |
* @return array The sanitized user meta.
|
843 |
*/
|
844 |
-
public function s_user_meta(
|
845 |
|
846 |
foreach ( $data as $key => &$value ) :
|
847 |
switch ( $key ) :
|
@@ -853,6 +889,13 @@ class Sanitize extends Admin_Pages {
|
|
853 |
$value = $this->s_twitter_name( $value );
|
854 |
continue 2;
|
855 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
856 |
default:
|
857 |
unset( $data[ $key ] );
|
858 |
break;
|
@@ -1006,8 +1049,8 @@ class Sanitize extends Admin_Pages {
|
|
1006 |
* Sanitizes input excerpt.
|
1007 |
*
|
1008 |
* @since 2.8.0
|
1009 |
-
* @since 2.8.2
|
1010 |
-
*
|
1011 |
* @since 3.2.4 Now selectively clears tags.
|
1012 |
* @since 4.1.0 Moved `figcaption`, `figure`, `footer`, and `tfoot`, from `space` to `clear`.
|
1013 |
* @see `$this->strip_tags_cs()`
|
@@ -1253,9 +1296,8 @@ class Sanitize extends Admin_Pages {
|
|
1253 |
|
1254 |
if ( ! \is_array( $new_values ) ) return [];
|
1255 |
|
1256 |
-
foreach ( $this->get_forced_supported_post_types() as $forced )
|
1257 |
unset( $new_values[ $forced ] );
|
1258 |
-
}
|
1259 |
|
1260 |
return $this->s_post_types( $new_values );
|
1261 |
}
|
@@ -1274,9 +1316,8 @@ class Sanitize extends Admin_Pages {
|
|
1274 |
|
1275 |
if ( ! \is_array( $new_values ) ) return [];
|
1276 |
|
1277 |
-
foreach ( $new_values as $index => &$value )
|
1278 |
$value = $this->s_one_zero( $value );
|
1279 |
-
}
|
1280 |
|
1281 |
return $new_values;
|
1282 |
}
|
@@ -1295,9 +1336,8 @@ class Sanitize extends Admin_Pages {
|
|
1295 |
|
1296 |
if ( ! \is_array( $new_values ) ) return [];
|
1297 |
|
1298 |
-
foreach ( $this->get_forced_supported_taxonomies() as $forced )
|
1299 |
unset( $new_values[ $forced ] );
|
1300 |
-
}
|
1301 |
|
1302 |
return $this->s_taxonomies( $new_values );
|
1303 |
}
|
@@ -1476,10 +1516,10 @@ class Sanitize extends Admin_Pages {
|
|
1476 |
*
|
1477 |
* @since 2.2.2
|
1478 |
* @since 2.8.0 Method is now public.
|
1479 |
-
* @since 3.0.0
|
1480 |
-
*
|
1481 |
-
* @since 4.0.0
|
1482 |
-
*
|
1483 |
*
|
1484 |
* @param string $new_value String with potentially wrong Twitter username.
|
1485 |
* @return string String with 'correct' Twitter username
|
@@ -1500,7 +1540,7 @@ class Sanitize extends Admin_Pages {
|
|
1500 |
if ( '@' === $profile ) return '';
|
1501 |
|
1502 |
if ( '@' !== substr( $profile, 0, 1 ) )
|
1503 |
-
$profile =
|
1504 |
|
1505 |
return str_replace( [ ' ', "\t" ], '', $profile );
|
1506 |
}
|
@@ -1511,8 +1551,8 @@ class Sanitize extends Admin_Pages {
|
|
1511 |
* @since 2.2.2
|
1512 |
* @since 2.8.0 Method is now public.
|
1513 |
* @since 3.0.6 Now allows a sole query argument when profile.php is used.
|
1514 |
-
* @since 4.0.0
|
1515 |
-
*
|
1516 |
*
|
1517 |
* @param string $new_value String with potentially wrong Facebook profile URL.
|
1518 |
* @return string String with 'correct' Facebook profile URL.
|
@@ -1532,10 +1572,10 @@ class Sanitize extends Admin_Pages {
|
|
1532 |
|
1533 |
if ( ! $path ) return '';
|
1534 |
|
1535 |
-
$link =
|
1536 |
|
1537 |
if ( strpos( $link, 'profile.php' ) ) {
|
1538 |
-
|
1539 |
parse_str( parse_url( $link, PHP_URL_QUERY ), $r );
|
1540 |
if ( isset( $r['id'] ) ) {
|
1541 |
$link = 'https://www.facebook.com/profile.php?id=' . \absint( $r['id'] );
|
@@ -1598,11 +1638,11 @@ class Sanitize extends Admin_Pages {
|
|
1598 |
* @since 2.2.4
|
1599 |
* @since 2.8.0 Method is now public.
|
1600 |
* @since 3.0.6 Noqueries is now disabled by default.
|
1601 |
-
* @since 4.0.0
|
1602 |
-
*
|
1603 |
-
*
|
1604 |
-
*
|
1605 |
-
*
|
1606 |
*
|
1607 |
* @param string $new_value String with potentially unwanted redirect URL.
|
1608 |
* @return string The Sanitized Redirect URL
|
@@ -1837,7 +1877,7 @@ class Sanitize extends Admin_Pages {
|
|
1837 |
/**
|
1838 |
* Strips all URLs that are placed on new lines. These are prone to be embeds.
|
1839 |
*
|
1840 |
-
* This might leave stray line feeds. Use `
|
1841 |
*
|
1842 |
* @since 3.1.0
|
1843 |
* @see \WP_Embed::autoembed()
|
@@ -1852,7 +1892,7 @@ class Sanitize extends Admin_Pages {
|
|
1852 |
/**
|
1853 |
* Strips all URLs that are placed in paragraphs on their own. These are prone to be embeds.
|
1854 |
*
|
1855 |
-
* This might leave stray line feeds. Use `
|
1856 |
*
|
1857 |
* @since 3.1.0
|
1858 |
* @see \WP_Embed::autoembed()
|
@@ -1916,15 +1956,10 @@ class Sanitize extends Admin_Pages {
|
|
1916 |
$args = $default_args;
|
1917 |
} else {
|
1918 |
foreach ( [ 'space', 'clear' ] as $type ) {
|
1919 |
-
if ( isset( $args[ $type ] ) )
|
1920 |
-
|
1921 |
-
$args[ $type ] = [];
|
1922 |
-
} else {
|
1923 |
-
$args[ $type ] = (array) $args[ $type ];
|
1924 |
-
}
|
1925 |
-
}
|
1926 |
}
|
1927 |
-
$args['strip'] =
|
1928 |
}
|
1929 |
|
1930 |
// Clear first, so there's less to process; then add spaces.
|
@@ -1933,11 +1968,9 @@ class Sanitize extends Admin_Pages {
|
|
1933 |
|
1934 |
// void = element without content.
|
1935 |
$void_query = array_intersect( $args[ $type ], $void );
|
1936 |
-
// fill =
|
1937 |
$fill_query = array_diff( $args[ $type ], $void );
|
1938 |
|
1939 |
-
$_regex = sprintf( '<(%s)\b[^>]*?>', implode( '|', $args[ $type ] ) );
|
1940 |
-
|
1941 |
if ( $void_query ) {
|
1942 |
$_regex = sprintf( '<(%s)\b[^>]*?>', implode( '|', $void_query ) );
|
1943 |
$_replace = 'space' === $type ? ' ' : '';
|
@@ -1973,7 +2006,7 @@ class Sanitize extends Admin_Pages {
|
|
1973 |
* string alt: The image alt tag,
|
1974 |
* }
|
1975 |
*/
|
1976 |
-
public function s_image_details(
|
1977 |
|
1978 |
if ( array_values( $details ) === $details )
|
1979 |
return $this->s_image_details_deep( $details );
|
@@ -1986,7 +2019,7 @@ class Sanitize extends Admin_Pages {
|
|
1986 |
'alt' => '',
|
1987 |
];
|
1988 |
|
1989 |
-
|
1990 |
|
1991 |
if ( ! $url ) return $defaults;
|
1992 |
|
@@ -2053,7 +2086,7 @@ class Sanitize extends Admin_Pages {
|
|
2053 |
* string alt: The image alt tag,
|
2054 |
* }
|
2055 |
*/
|
2056 |
-
public function s_image_details_deep(
|
2057 |
|
2058 |
$cleaned_details = [];
|
2059 |
|
51 |
*/
|
52 |
protected function verify_seo_settings_nonce() {
|
53 |
|
54 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
55 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
56 |
|
57 |
/**
|
58 |
* If this page doesn't parse the site options,
|
63 |
*/
|
64 |
if ( empty( $_POST[ THE_SEO_FRAMEWORK_SITE_OPTIONS ] )
|
65 |
|| ! \is_array( $_POST[ THE_SEO_FRAMEWORK_SITE_OPTIONS ] ) )
|
66 |
+
return memo( false );
|
67 |
|
68 |
// This is also handled in /wp-admin/options.php. Nevertheless, one might register outside of scope.
|
69 |
if ( ! \current_user_can( $this->get_settings_capability() ) )
|
70 |
+
return memo( false );
|
71 |
|
72 |
// This is also handled in /wp-admin/options.php. Nevertheless, one might register outside of scope.
|
73 |
// This also checks the nonce: `_wpnonce`.
|
74 |
\check_admin_referer( THE_SEO_FRAMEWORK_SITE_OPTIONS . '-options' );
|
75 |
|
76 |
+
return memo( true );
|
77 |
}
|
78 |
|
79 |
/**
|
139 |
*
|
140 |
* @since 3.1.0
|
141 |
* @since 4.0.0 Emptied and is no longer enqueued.
|
142 |
+
* @since 4.1.0 1. Added taxonomical robots options backward compat.
|
143 |
+
* 2. Added the first two parameters.
|
144 |
* @access private
|
145 |
*
|
146 |
* @param mixed $new_value The new, unserialized, and filtered option value.
|
149 |
public function _set_backward_compatibility( $new_value ) {
|
150 |
|
151 |
db_4103:
|
152 |
+
// Category and Tag robots backward compat.
|
153 |
foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) :
|
154 |
$robots_option_id = $this->get_robots_taxonomy_option_id( $r );
|
155 |
+
$new_robots_options = $new_value[ $robots_option_id ] ?? [];
|
156 |
|
157 |
+
$new_category_option = $new_robots_options['category'] ?? 0;
|
158 |
+
$new_tag_option = $new_robots_options['post_tag'] ?? 0;
|
159 |
|
160 |
// Don't compare to old option--it's never reliably set; it might skip otherwise, although it's always correct.
|
161 |
// Do not resanitize. Others might've overwritten that, let's keep their value.
|
196 |
]
|
197 |
);
|
198 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
$this->add_option_filter(
|
200 |
's_title_raw',
|
201 |
THE_SEO_FRAMEWORK_SITE_OPTIONS,
|
202 |
[
|
203 |
+
'site_title',
|
204 |
+
'knowledge_name',
|
205 |
'homepage_title',
|
206 |
'homepage_title_tagline',
|
207 |
'homepage_og_title',
|
333 |
'sitemaps_output',
|
334 |
'sitemaps_robots',
|
335 |
'sitemaps_modified',
|
|
|
336 |
'sitemap_styles',
|
337 |
'sitemap_logo',
|
338 |
]
|
393 |
]
|
394 |
);
|
395 |
|
396 |
+
$this->add_option_filter(
|
397 |
+
's_all_post_type_archive_meta',
|
398 |
+
THE_SEO_FRAMEWORK_SITE_OPTIONS,
|
399 |
+
[
|
400 |
+
'pta',
|
401 |
+
]
|
402 |
+
);
|
403 |
+
|
404 |
/**
|
405 |
* @todo create content="code" stripper in PHP (redundant from JS's)
|
406 |
*/
|
540 |
|
541 |
// Memoize whether a filter has been set for the option already. Should only run once internally.
|
542 |
if ( ! isset( $registered[ $option ] ) ) {
|
543 |
+
\add_filter( "sanitize_option_{$option}", [ $this, 'sanitize' ], 10, 2 );
|
544 |
$registered[ $option ] = true;
|
545 |
}
|
546 |
|
619 |
// Array of suboption values to loop through
|
620 |
$old_value = \get_option( $option, [] );
|
621 |
foreach ( $filters[ $option ] as $suboption => $filter ) {
|
622 |
+
$old_value[ $suboption ] = $old_value[ $suboption ] ?? '';
|
623 |
+
$new_value[ $suboption ] = $new_value[ $suboption ] ?? '';
|
624 |
$new_value[ $suboption ] = $this->do_filter( $filter, $new_value[ $suboption ], $old_value[ $suboption ], $option, $suboption );
|
625 |
}
|
626 |
return $new_value;
|
683 |
return (array) \apply_filters(
|
684 |
'the_seo_framework_available_sanitizer_filters',
|
685 |
[
|
686 |
+
's_left_right' => [ $this, 's_left_right' ],
|
687 |
+
's_left_right_home' => [ $this, 's_left_right_home' ],
|
688 |
+
's_title_separator' => [ $this, 's_title_separator' ],
|
689 |
+
's_description' => [ $this, 's_description' ],
|
690 |
+
's_description_raw' => [ $this, 's_description_raw' ],
|
691 |
+
's_title' => [ $this, 's_title' ],
|
692 |
+
's_title_raw' => [ $this, 's_title_raw' ],
|
693 |
+
's_knowledge_type' => [ $this, 's_knowledge_type' ],
|
694 |
+
's_alter_query_type' => [ $this, 's_alter_query_type' ],
|
695 |
+
's_one_zero' => [ $this, 's_one_zero' ],
|
696 |
+
's_disabled_post_types' => [ $this, 's_disabled_post_types' ],
|
697 |
+
's_disabled_taxonomies' => [ $this, 's_disabled_taxonomies' ],
|
698 |
+
's_post_types' => [ $this, 's_post_types' ],
|
699 |
+
's_taxonomies' => [ $this, 's_taxonomies' ],
|
700 |
+
's_all_post_type_archive_meta' => [ $this, 's_all_post_type_archive_meta' ],
|
701 |
+
's_numeric_string' => [ $this, 's_numeric_string' ],
|
702 |
+
's_no_html' => [ $this, 's_no_html' ],
|
703 |
+
's_no_html_space' => [ $this, 's_no_html_space' ],
|
704 |
+
's_absint' => [ $this, 's_absint' ],
|
705 |
+
's_safe_html' => [ $this, 's_safe_html' ],
|
706 |
+
's_url' => [ $this, 's_url' ],
|
707 |
+
's_url_query' => [ $this, 's_url_query' ],
|
708 |
+
's_facebook_profile' => [ $this, 's_facebook_profile' ],
|
709 |
+
's_twitter_name' => [ $this, 's_twitter_name' ],
|
710 |
+
's_twitter_card' => [ $this, 's_twitter_card' ],
|
711 |
+
's_canonical_scheme' => [ $this, 's_canonical_scheme' ],
|
712 |
+
's_min_max_sitemap' => [ $this, 's_min_max_sitemap' ],
|
713 |
+
's_image_preview' => [ $this, 's_image_preview' ],
|
714 |
+
's_snippet_length' => [ $this, 's_snippet_length' ],
|
715 |
]
|
716 |
);
|
717 |
}
|
718 |
|
719 |
+
/**
|
720 |
+
* Sanitizes post type archive meta.
|
721 |
+
*
|
722 |
+
* @since 4.2.0
|
723 |
+
*
|
724 |
+
* @param array $data The post type archive meta to sanitize : {
|
725 |
+
* string $post_type => array $data
|
726 |
+
* }
|
727 |
+
* @return array The sanitized post type archive meta.
|
728 |
+
*/
|
729 |
+
public function s_all_post_type_archive_meta( $data ) {
|
730 |
+
|
731 |
+
if ( ! $data )
|
732 |
+
return [];
|
733 |
+
|
734 |
+
// Do NOT test for post type's existence -- it might be registered incorrectly.
|
735 |
+
// If the metadata yields empty -- do not unset key! It'll override "defaults" that way.
|
736 |
+
foreach ( $data as $_post_type => &$meta )
|
737 |
+
$meta = $this->s_post_type_archive_meta( $meta );
|
738 |
+
|
739 |
+
return $data;
|
740 |
+
}
|
741 |
+
|
742 |
+
/**
|
743 |
+
* Sanitizes post type archive meta.
|
744 |
+
*
|
745 |
+
* @since 4.2.0
|
746 |
+
*
|
747 |
+
* @param array $data The post type archive meta to sanitize.
|
748 |
+
* @return array The sanitized post type archive meta.
|
749 |
+
*/
|
750 |
+
public function s_post_type_archive_meta( $data ) {
|
751 |
+
return $this->s_term_meta( $data ); // Coincidence? I think not.
|
752 |
+
}
|
753 |
+
|
754 |
/**
|
755 |
* Sanitizes term meta.
|
756 |
*
|
759 |
* @param array $data The term meta to sanitize.
|
760 |
* @return array The sanitized term meta.
|
761 |
*/
|
762 |
+
public function s_term_meta( $data ) {
|
763 |
|
764 |
foreach ( $data as $key => &$value ) :
|
765 |
switch ( $key ) :
|
816 |
* @param array $data The post meta to sanitize.
|
817 |
* @return array The sanitized post meta.
|
818 |
*/
|
819 |
+
public function s_post_meta( $data ) {
|
820 |
|
821 |
foreach ( $data as $key => &$value ) :
|
822 |
switch ( $key ) :
|
872 |
* Sanitizes user meta.
|
873 |
*
|
874 |
* @since 4.1.4
|
875 |
+
* @since 4.2.0 Now accepts and sanitizes the 'counter_type' index.
|
876 |
*
|
877 |
* @param array $data The user meta to sanitize.
|
878 |
* @return array The sanitized user meta.
|
879 |
*/
|
880 |
+
public function s_user_meta( $data ) {
|
881 |
|
882 |
foreach ( $data as $key => &$value ) :
|
883 |
switch ( $key ) :
|
889 |
$value = $this->s_twitter_name( $value );
|
890 |
continue 2;
|
891 |
|
892 |
+
case 'counter_type':
|
893 |
+
$value = \absint( $value );
|
894 |
+
|
895 |
+
if ( $value > 3 )
|
896 |
+
$value = 0;
|
897 |
+
continue 2;
|
898 |
+
|
899 |
default:
|
900 |
unset( $data[ $key ] );
|
901 |
break;
|
1049 |
* Sanitizes input excerpt.
|
1050 |
*
|
1051 |
* @since 2.8.0
|
1052 |
+
* @since 2.8.2 1. Added $allow_shortcodes parameter.
|
1053 |
+
* 2. Added $escape parameter.
|
1054 |
* @since 3.2.4 Now selectively clears tags.
|
1055 |
* @since 4.1.0 Moved `figcaption`, `figure`, `footer`, and `tfoot`, from `space` to `clear`.
|
1056 |
* @see `$this->strip_tags_cs()`
|
1296 |
|
1297 |
if ( ! \is_array( $new_values ) ) return [];
|
1298 |
|
1299 |
+
foreach ( $this->get_forced_supported_post_types() as $forced )
|
1300 |
unset( $new_values[ $forced ] );
|
|
|
1301 |
|
1302 |
return $this->s_post_types( $new_values );
|
1303 |
}
|
1316 |
|
1317 |
if ( ! \is_array( $new_values ) ) return [];
|
1318 |
|
1319 |
+
foreach ( $new_values as $index => &$value )
|
1320 |
$value = $this->s_one_zero( $value );
|
|
|
1321 |
|
1322 |
return $new_values;
|
1323 |
}
|
1336 |
|
1337 |
if ( ! \is_array( $new_values ) ) return [];
|
1338 |
|
1339 |
+
foreach ( $this->get_forced_supported_taxonomies() as $forced )
|
1340 |
unset( $new_values[ $forced ] );
|
|
|
1341 |
|
1342 |
return $this->s_taxonomies( $new_values );
|
1343 |
}
|
1516 |
*
|
1517 |
* @since 2.2.2
|
1518 |
* @since 2.8.0 Method is now public.
|
1519 |
+
* @since 3.0.0 1. Now removes '@' from the URL path.
|
1520 |
+
* 2. Now removes spaces and tabs.
|
1521 |
+
* @since 4.0.0 1. Now returns empty on lone `@` entries.
|
1522 |
+
* 2. Now returns empty when using only spaces and tabs.
|
1523 |
*
|
1524 |
* @param string $new_value String with potentially wrong Twitter username.
|
1525 |
* @return string String with 'correct' Twitter username
|
1540 |
if ( '@' === $profile ) return '';
|
1541 |
|
1542 |
if ( '@' !== substr( $profile, 0, 1 ) )
|
1543 |
+
$profile = "@$profile";
|
1544 |
|
1545 |
return str_replace( [ ' ', "\t" ], '', $profile );
|
1546 |
}
|
1551 |
* @since 2.2.2
|
1552 |
* @since 2.8.0 Method is now public.
|
1553 |
* @since 3.0.6 Now allows a sole query argument when profile.php is used.
|
1554 |
+
* @since 4.0.0 1. No longer returns a plain Facebook URL when the entry path is sanitized to become empty.
|
1555 |
+
* 2. Now returns empty when using only spaces and tabs.
|
1556 |
*
|
1557 |
* @param string $new_value String with potentially wrong Facebook profile URL.
|
1558 |
* @return string String with 'correct' Facebook profile URL.
|
1572 |
|
1573 |
if ( ! $path ) return '';
|
1574 |
|
1575 |
+
$link = "https://www.facebook.com/{$path}";
|
1576 |
|
1577 |
if ( strpos( $link, 'profile.php' ) ) {
|
1578 |
+
// Gets query parameters.
|
1579 |
parse_str( parse_url( $link, PHP_URL_QUERY ), $r );
|
1580 |
if ( isset( $r['id'] ) ) {
|
1581 |
$link = 'https://www.facebook.com/profile.php?id=' . \absint( $r['id'] );
|
1638 |
* @since 2.2.4
|
1639 |
* @since 2.8.0 Method is now public.
|
1640 |
* @since 3.0.6 Noqueries is now disabled by default.
|
1641 |
+
* @since 4.0.0 1. Removed rudimentary relative URL testing.
|
1642 |
+
* 2. Removed input transformation filters, and with that, removed redundant multisite spam protection.
|
1643 |
+
* 3. Now allows all protocols. Enjoy!
|
1644 |
+
* 4. Now no longer lets through double-absolute URLs (e.g. `https://google.com/https://google.com/path/to/file/`)
|
1645 |
+
* when filter `the_seo_framework_allow_external_redirect` is set to false.
|
1646 |
*
|
1647 |
* @param string $new_value String with potentially unwanted redirect URL.
|
1648 |
* @return string The Sanitized Redirect URL
|
1877 |
/**
|
1878 |
* Strips all URLs that are placed on new lines. These are prone to be embeds.
|
1879 |
*
|
1880 |
+
* This might leave stray line feeds. Use `tsf()->s_singleline()` to fix that.
|
1881 |
*
|
1882 |
* @since 3.1.0
|
1883 |
* @see \WP_Embed::autoembed()
|
1892 |
/**
|
1893 |
* Strips all URLs that are placed in paragraphs on their own. These are prone to be embeds.
|
1894 |
*
|
1895 |
+
* This might leave stray line feeds. Use `tsf()->s_singleline()` to fix that.
|
1896 |
*
|
1897 |
* @since 3.1.0
|
1898 |
* @see \WP_Embed::autoembed()
|
1956 |
$args = $default_args;
|
1957 |
} else {
|
1958 |
foreach ( [ 'space', 'clear' ] as $type ) {
|
1959 |
+
if ( isset( $args[ $type ] ) )
|
1960 |
+
$args[ $type ] = $args[ $type ] ? (array) $args[ $type ] : [];
|
|
|
|
|
|
|
|
|
|
|
1961 |
}
|
1962 |
+
$args['strip'] = $args['strip'] ?? $default_args['strip'];
|
1963 |
}
|
1964 |
|
1965 |
// Clear first, so there's less to process; then add spaces.
|
1968 |
|
1969 |
// void = element without content.
|
1970 |
$void_query = array_intersect( $args[ $type ], $void );
|
1971 |
+
// fill = <normal | template | raw text | escapable text | foreign> element.
|
1972 |
$fill_query = array_diff( $args[ $type ], $void );
|
1973 |
|
|
|
|
|
1974 |
if ( $void_query ) {
|
1975 |
$_regex = sprintf( '<(%s)\b[^>]*?>', implode( '|', $void_query ) );
|
1976 |
$_replace = 'space' === $type ? ' ' : '';
|
2006 |
* string alt: The image alt tag,
|
2007 |
* }
|
2008 |
*/
|
2009 |
+
public function s_image_details( $details ) {
|
2010 |
|
2011 |
if ( array_values( $details ) === $details )
|
2012 |
return $this->s_image_details_deep( $details );
|
2019 |
'alt' => '',
|
2020 |
];
|
2021 |
|
2022 |
+
[ $url, $id, $width, $height, $alt ] = array_values( array_merge( $defaults, $details ) );
|
2023 |
|
2024 |
if ( ! $url ) return $defaults;
|
2025 |
|
2086 |
* string alt: The image alt tag,
|
2087 |
* }
|
2088 |
*/
|
2089 |
+
public function s_image_details_deep( $details_array ) {
|
2090 |
|
2091 |
$cleaned_details = [];
|
2092 |
|
@@ -99,7 +99,8 @@ class Site_Options extends Sanitize {
|
|
99 |
'disabled_taxonomies' => [], // Taxonomy support.
|
100 |
|
101 |
// Title.
|
102 |
-
'
|
|
|
103 |
'title_location' => $titleloc, // Title separation location
|
104 |
'title_rem_additions' => 0, // Remove title additions
|
105 |
'title_rem_prefixes' => 0, // Remove title prefixes from archives.
|
@@ -170,6 +171,9 @@ class Site_Options extends Sanitize {
|
|
170 |
'homepage_social_image_url' => '',
|
171 |
'homepage_social_image_id' => 0,
|
172 |
|
|
|
|
|
|
|
173 |
// Relationships.
|
174 |
'shortlink_tag' => 0, // Adds shortlink tag
|
175 |
'prev_next_posts' => 1, // Adds next/prev tags
|
@@ -249,7 +253,6 @@ class Site_Options extends Sanitize {
|
|
249 |
'sitemap_query_limit' => 1000, // Sitemap post limit.
|
250 |
|
251 |
'sitemaps_modified' => 1, // Add sitemap modified time.
|
252 |
-
'sitemaps_priority' => 0, // Add sitemap priorities.
|
253 |
|
254 |
'sitemaps_robots' => 1, // Add sitemap location to robots.txt
|
255 |
|
@@ -286,40 +289,43 @@ class Site_Options extends Sanitize {
|
|
286 |
* @since 3.1.0 Now applies the "the_seo_framework_warned_site_options" filter.
|
287 |
* @since 4.1.0 Added robots' post type setting warnings.
|
288 |
* @since 4.1.2 Added `ping_use_cron_prerender`.
|
|
|
289 |
*
|
290 |
* @return array $options.
|
291 |
*/
|
292 |
public function get_warned_site_options() {
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
'
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
'
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
|
|
|
|
323 |
);
|
324 |
}
|
325 |
|
@@ -329,32 +335,53 @@ class Site_Options extends Sanitize {
|
|
329 |
* @since 2.2.2
|
330 |
* @since 2.8.2 No longer decodes entities on request.
|
331 |
* @since 3.1.0 Now uses the filterable call when caching is disabled.
|
|
|
332 |
* @uses THE_SEO_FRAMEWORK_SITE_OPTIONS
|
333 |
*
|
334 |
-
* @param string
|
335 |
-
*
|
|
|
336 |
* @return mixed The value of this $key in the database. Empty string when not set.
|
337 |
*/
|
338 |
public function get_option( $key, $use_cache = true ) {
|
339 |
|
340 |
if ( ! $use_cache ) {
|
341 |
-
|
342 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
343 |
}
|
344 |
|
345 |
-
static $cache
|
|
|
|
|
|
|
|
|
|
|
|
|
346 |
|
347 |
-
|
348 |
-
|
|
|
349 |
|
350 |
-
|
351 |
-
return isset( $cache[ THE_SEO_FRAMEWORK_SITE_OPTIONS ][ $key ] ) ? $cache[ THE_SEO_FRAMEWORK_SITE_OPTIONS ][ $key ] : '';
|
352 |
}
|
353 |
|
354 |
/**
|
355 |
* Return current option array.
|
356 |
* Memoizes the return value, can be bypassed and reset with second parameter.
|
357 |
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
358 |
* @since 2.6.0
|
359 |
* @since 2.9.2 Added $use_current parameter.
|
360 |
*
|
@@ -367,12 +394,12 @@ class Site_Options extends Sanitize {
|
|
367 |
|
368 |
static $cache = [];
|
369 |
|
370 |
-
if ( ! $reset && isset( $cache[ $setting ] ) )
|
371 |
-
return $cache[ $setting ];
|
372 |
-
|
373 |
if ( ! $setting )
|
374 |
$setting = THE_SEO_FRAMEWORK_SITE_OPTIONS;
|
375 |
|
|
|
|
|
|
|
376 |
/**
|
377 |
* @since 2.0.0
|
378 |
* @since 4.1.4 1. Now considers headlessness.
|
@@ -398,15 +425,47 @@ class Site_Options extends Sanitize {
|
|
398 |
* Return Default SEO options from the SEO options array.
|
399 |
*
|
400 |
* @since 2.2.5
|
|
|
|
|
|
|
401 |
* @uses $this->get_default_settings() Return option from the options table and cache result.
|
402 |
* @uses THE_SEO_FRAMEWORK_SITE_OPTIONS
|
403 |
*
|
404 |
-
* @param string
|
405 |
-
* @
|
406 |
-
* @return mixed The value of this $key in the database.
|
407 |
*/
|
408 |
-
public function get_default_option( $key
|
409 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
410 |
}
|
411 |
|
412 |
/**
|
@@ -444,8 +503,7 @@ class Site_Options extends Sanitize {
|
|
444 |
* @return mixed Cache value on success, $default if non-existent.
|
445 |
*/
|
446 |
public function get_static_cache( $key, $default = false ) {
|
447 |
-
|
448 |
-
return isset( $cache[ $key ] ) ? $cache[ $key ] : $default;
|
449 |
}
|
450 |
|
451 |
/**
|
@@ -544,415 +602,323 @@ class Site_Options extends Sanitize {
|
|
544 |
}
|
545 |
|
546 |
/**
|
547 |
-
*
|
548 |
*
|
549 |
-
* @since
|
550 |
-
* @since 2.
|
551 |
-
*
|
552 |
-
*
|
553 |
-
*
|
554 |
-
* 4. The second parameter is deprecated.
|
555 |
-
* @uses $this->get_default_site_options()
|
556 |
-
*
|
557 |
-
* @param string $key Required. The option name.
|
558 |
-
* @param string $depr Deprecated. Leave empty.
|
559 |
-
* @param bool $use_cache Optional. Whether to use the options cache or bypass it.
|
560 |
-
* @return mixed default option
|
561 |
-
* null If option doesn't exist.
|
562 |
*/
|
563 |
-
public function
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
if ( $depr )
|
568 |
-
$this->_doing_it_wrong( __METHOD__, 'The second parameter is deprecated.', '3.1.0' );
|
569 |
-
|
570 |
-
// If we need to bypass the cache
|
571 |
-
if ( ! $use_cache ) {
|
572 |
-
$defaults = $this->get_default_site_options();
|
573 |
-
return isset( $defaults[ $key ] ) ? \stripslashes_deep( $defaults[ $key ] ) : null;
|
574 |
-
}
|
575 |
-
|
576 |
-
static $cache;
|
577 |
|
578 |
-
|
579 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
580 |
|
581 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
582 |
}
|
583 |
|
584 |
/**
|
585 |
-
*
|
586 |
*
|
587 |
-
*
|
588 |
-
*
|
589 |
-
*
|
590 |
-
*
|
|
|
591 |
*
|
592 |
-
* @param string $
|
593 |
-
* @param
|
594 |
-
* @
|
595 |
-
* @return int 0|1 Whether the option is flagged as dangerous for SEO.
|
596 |
*/
|
597 |
-
public function
|
598 |
|
599 |
-
|
600 |
-
|
601 |
|
602 |
-
|
603 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
604 |
|
605 |
-
//
|
606 |
-
if (
|
607 |
-
$
|
608 |
-
|
|
|
|
|
|
|
609 |
}
|
610 |
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
615 |
|
616 |
-
|
|
|
617 |
}
|
618 |
|
619 |
/**
|
620 |
-
* Returns
|
621 |
*
|
622 |
-
* @since
|
623 |
*
|
624 |
-
* @param string $
|
625 |
-
* @
|
|
|
|
|
626 |
*/
|
627 |
-
public function
|
628 |
-
return $this->
|
|
|
|
|
|
|
629 |
}
|
630 |
|
|
|
631 |
/**
|
632 |
-
* Returns
|
633 |
*
|
634 |
-
* @since 4.
|
635 |
*
|
636 |
-
* @
|
637 |
-
*
|
638 |
*/
|
639 |
-
public function
|
640 |
-
|
|
|
|
|
|
|
|
|
641 |
}
|
|
|
642 |
|
643 |
/**
|
644 |
-
* Returns
|
645 |
*
|
646 |
-
* @since 2.
|
647 |
-
* TODO collapse this with language_keys(), ll_CC => ll?, return array_keys here, array_values there?
|
648 |
*
|
649 |
-
* @
|
650 |
-
* @
|
651 |
-
* mirror: http://web.archive.org/web/20190601043836/https://wordpress.org/support/topic/oglocale-problem/
|
652 |
-
* @see $this->language_keys() for the associative array keys.
|
653 |
-
*
|
654 |
-
* @return array Valid Facebook locales
|
655 |
*/
|
656 |
-
public function
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
'
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
'bs_BA', // Bosnian
|
670 |
-
'ca_ES', // Catalan
|
671 |
-
'cb_IQ', // Sorani Kurdish
|
672 |
-
'ck_US', // Cherokee
|
673 |
-
'co_FR', // Corsican
|
674 |
-
'cs_CZ', // Czech
|
675 |
-
'cx_PH', // Cebuano
|
676 |
-
'cy_GB', // Welsh
|
677 |
-
'da_DK', // Danish
|
678 |
-
'de_DE', // German
|
679 |
-
'el_GR', // Greek
|
680 |
-
'en_GB', // English (UK)
|
681 |
-
'en_IN', // English (India)
|
682 |
-
'en_PI', // English (Pirate)
|
683 |
-
'en_UD', // English (Upside Down)
|
684 |
-
'en_US', // English (US)
|
685 |
-
'eo_EO', // Esperanto
|
686 |
-
'es_CL', // Spanish (Chile)
|
687 |
-
'es_CO', // Spanish (Colombia)
|
688 |
-
'es_ES', // Spanish (Spain)
|
689 |
-
'es_LA', // Spanish
|
690 |
-
'es_MX', // Spanish (Mexico)
|
691 |
-
'es_VE', // Spanish (Venezuela)
|
692 |
-
'et_EE', // Estonian
|
693 |
-
'eu_ES', // Basque
|
694 |
-
'fa_IR', // Persian
|
695 |
-
'fb_LT', // Leet Speak
|
696 |
-
'ff_NG', // Fulah
|
697 |
-
'fi_FI', // Finnish
|
698 |
-
'fo_FO', // Faroese
|
699 |
-
'fr_CA', // French (Canada)
|
700 |
-
'fr_FR', // French (France)
|
701 |
-
'fy_NL', // Frisian
|
702 |
-
'ga_IE', // Irish
|
703 |
-
'gl_ES', // Galician
|
704 |
-
'gn_PY', // Guarani
|
705 |
-
'gu_IN', // Gujarati
|
706 |
-
'gx_GR', // Classical Greek
|
707 |
-
'ha_NG', // Hausa
|
708 |
-
'he_IL', // Hebrew
|
709 |
-
'hi_IN', // Hindi
|
710 |
-
'hr_HR', // Croatian
|
711 |
-
'hu_HU', // Hungarian
|
712 |
-
'hy_AM', // Armenian
|
713 |
-
'id_ID', // Indonesian
|
714 |
-
'ig_NG', // Igbo
|
715 |
-
'is_IS', // Icelandic
|
716 |
-
'it_IT', // Italian
|
717 |
-
'ja_JP', // Japanese
|
718 |
-
'ja_KS', // Japanese (Kansai)
|
719 |
-
'jv_ID', // Javanese
|
720 |
-
'ka_GE', // Georgian
|
721 |
-
'kk_KZ', // Kazakh
|
722 |
-
'km_KH', // Khmer
|
723 |
-
'kn_IN', // Kannada
|
724 |
-
'ko_KR', // Korean
|
725 |
-
'ku_TR', // Kurdish (Kurmanji)
|
726 |
-
'ky_KG', // Kyrgyz
|
727 |
-
'la_VA', // Latin
|
728 |
-
'lg_UG', // Ganda
|
729 |
-
'li_NL', // Limburgish
|
730 |
-
'ln_CD', // Lingala
|
731 |
-
'lo_LA', // Lao
|
732 |
-
'lt_LT', // Lithuanian
|
733 |
-
'lv_LV', // Latvian
|
734 |
-
'mg_MG', // Malagasy
|
735 |
-
'mi_NZ', // Māori
|
736 |
-
'mk_MK', // Macedonian
|
737 |
-
'ml_IN', // Malayalam
|
738 |
-
'mn_MN', // Mongolian
|
739 |
-
'mr_IN', // Marathi
|
740 |
-
'ms_MY', // Malay
|
741 |
-
'mt_MT', // Maltese
|
742 |
-
'my_MM', // Burmese
|
743 |
-
'nb_NO', // Norwegian (bokmal)
|
744 |
-
'nd_ZW', // Ndebele
|
745 |
-
'ne_NP', // Nepali
|
746 |
-
'nl_BE', // Dutch (België)
|
747 |
-
'nl_NL', // Dutch
|
748 |
-
'nn_NO', // Norwegian (nynorsk)
|
749 |
-
'ny_MW', // Chewa
|
750 |
-
'or_IN', // Oriya
|
751 |
-
'pa_IN', // Punjabi
|
752 |
-
'pl_PL', // Polish
|
753 |
-
'ps_AF', // Pashto
|
754 |
-
'pt_BR', // Portuguese (Brazil)
|
755 |
-
'pt_PT', // Portuguese (Portugal)
|
756 |
-
'qu_PE', // Quechua
|
757 |
-
'rm_CH', // Romansh
|
758 |
-
'ro_RO', // Romanian
|
759 |
-
'ru_RU', // Russian
|
760 |
-
'rw_RW', // Kinyarwanda
|
761 |
-
'sa_IN', // Sanskrit
|
762 |
-
'sc_IT', // Sardinian
|
763 |
-
'se_NO', // Northern Sámi
|
764 |
-
'si_LK', // Sinhala
|
765 |
-
'sk_SK', // Slovak
|
766 |
-
'sl_SI', // Slovenian
|
767 |
-
'sn_ZW', // Shona
|
768 |
-
'so_SO', // Somali
|
769 |
-
'sq_AL', // Albanian
|
770 |
-
'sr_RS', // Serbian
|
771 |
-
'sv_SE', // Swedish
|
772 |
-
'sy_SY', // Swahili
|
773 |
-
'sw_KE', // Syriac
|
774 |
-
'sz_PL', // Silesian
|
775 |
-
'ta_IN', // Tamil
|
776 |
-
'te_IN', // Telugu
|
777 |
-
'tg_TJ', // Tajik
|
778 |
-
'th_TH', // Thai
|
779 |
-
'tk_TM', // Turkmen
|
780 |
-
'tl_PH', // Filipino
|
781 |
-
'tl_ST', // Klingon
|
782 |
-
'tr_TR', // Turkish
|
783 |
-
'tt_RU', // Tatar
|
784 |
-
'tz_MA', // Tamazight
|
785 |
-
'uk_UA', // Ukrainian
|
786 |
-
'ur_PK', // Urdu
|
787 |
-
'uz_UZ', // Uzbek
|
788 |
-
'vi_VN', // Vietnamese
|
789 |
-
'wo_SN', // Wolof
|
790 |
-
'xh_ZA', // Xhosa
|
791 |
-
'yi_DE', // Yiddish
|
792 |
-
'yo_NG', // Yoruba
|
793 |
-
'zh_CN', // Simplified Chinese (China)
|
794 |
-
'zh_HK', // Traditional Chinese (Hong Kong)
|
795 |
-
'zh_TW', // Traditional Chinese (Taiwan)
|
796 |
-
'zu_ZA', // Zulu
|
797 |
-
'zz_TR', // Zazaki
|
798 |
-
];
|
799 |
}
|
800 |
|
801 |
/**
|
802 |
-
* Returns
|
803 |
-
*
|
804 |
-
* This is apart from the fb_locales array since there are "duplicated" keys.
|
805 |
-
* Use this to compare the numeric key position.
|
806 |
*
|
807 |
-
* @since 2.
|
808 |
-
* @see https://www.facebook.com/translations/FacebookLocales.xml (deprecated)
|
809 |
-
* @see https://wordpress.org/support/topic/oglocale-problem/#post-11456346
|
810 |
-
* mirror: http://web.archive.org/web/20190601043836/https://wordpress.org/support/topic/oglocale-problem/
|
811 |
*
|
812 |
-
* @return array
|
813 |
*/
|
814 |
-
|
815 |
return [
|
816 |
-
'
|
817 |
-
'
|
818 |
-
'
|
819 |
-
'
|
820 |
-
'
|
821 |
-
'
|
822 |
-
'
|
823 |
-
'
|
824 |
-
'
|
825 |
-
'
|
826 |
-
'
|
827 |
-
'
|
828 |
-
'
|
829 |
-
'
|
830 |
-
'ck', // Cherokee
|
831 |
-
'co', // Corsican
|
832 |
-
'cs', // Czech
|
833 |
-
'cx', // Cebuano
|
834 |
-
'cy', // Welsh
|
835 |
-
'da', // Danish
|
836 |
-
'de', // German
|
837 |
-
'el', // Greek
|
838 |
-
'en', // English (UK)
|
839 |
-
'en', // English (India)
|
840 |
-
'en', // English (Pirate)
|
841 |
-
'en', // English (Upside Down)
|
842 |
-
'en', // English (US)
|
843 |
-
'eo', // Esperanto
|
844 |
-
'es', // Spanish (Chile)
|
845 |
-
'es', // Spanish (Colombia)
|
846 |
-
'es', // Spanish (Spain)
|
847 |
-
'es', // Spanish
|
848 |
-
'es', // Spanish (Mexico)
|
849 |
-
'es', // Spanish (Venezuela)
|
850 |
-
'et', // Estonian
|
851 |
-
'eu', // Basque
|
852 |
-
'fa', // Persian
|
853 |
-
'fb', // Leet Speak
|
854 |
-
'ff', // Fulah
|
855 |
-
'fi', // Finnish
|
856 |
-
'fo', // Faroese
|
857 |
-
'fr', // French (Canada)
|
858 |
-
'fr', // French (France)
|
859 |
-
'fy', // Frisian
|
860 |
-
'ga', // Irish
|
861 |
-
'gl', // Galician
|
862 |
-
'gn', // Guarani
|
863 |
-
'gu', // Gujarati
|
864 |
-
'gx', // Classical Greek
|
865 |
-
'ha', // Hausa
|
866 |
-
'he', // Hebrew
|
867 |
-
'hi', // Hindi
|
868 |
-
'hr', // Croatian
|
869 |
-
'hu', // Hungarian
|
870 |
-
'hy', // Armenian
|
871 |
-
'id', // Indonesian
|
872 |
-
'ig', // Igbo
|
873 |
-
'is', // Icelandic
|
874 |
-
'it', // Italian
|
875 |
-
'ja', // Japanese
|
876 |
-
'ja', // Japanese (Kansai)
|
877 |
-
'jv', // Javanese
|
878 |
-
'ka', // Georgian
|
879 |
-
'kk', // Kazakh
|
880 |
-
'km', // Khmer
|
881 |
-
'kn', // Kannada
|
882 |
-
'ko', // Korean
|
883 |
-
'ku', // Kurdish (Kurmanji)
|
884 |
-
'ky', // Kyrgyz
|
885 |
-
'la', // Latin
|
886 |
-
'lg', // Ganda
|
887 |
-
'li', // Limburgish
|
888 |
-
'ln', // Lingala
|
889 |
-
'lo', // Lao
|
890 |
-
'lt', // Lithuanian
|
891 |
-
'lv', // Latvian
|
892 |
-
'mg', // Malagasy
|
893 |
-
'mi', // Māori
|
894 |
-
'mk', // Macedonian
|
895 |
-
'ml', // Malayalam
|
896 |
-
'mn', // Mongolian
|
897 |
-
'mr', // Marathi
|
898 |
-
'ms', // Malay
|
899 |
-
'mt', // Maltese
|
900 |
-
'my', // Burmese
|
901 |
-
'nb', // Norwegian (bokmal)
|
902 |
-
'nd', // Ndebele
|
903 |
-
'ne', // Nepali
|
904 |
-
'nl', // Dutch (België)
|
905 |
-
'nl', // Dutch
|
906 |
-
'nn', // Norwegian (nynorsk)
|
907 |
-
'ny', // Chewa
|
908 |
-
'or', // Oriya
|
909 |
-
'pa', // Punjabi
|
910 |
-
'pl', // Polish
|
911 |
-
'ps', // Pashto
|
912 |
-
'pt', // Portuguese (Brazil)
|
913 |
-
'pt', // Portuguese (Portugal)
|
914 |
-
'qu', // Quechua
|
915 |
-
'rm', // Romansh
|
916 |
-
'ro', // Romanian
|
917 |
-
'ru', // Russian
|
918 |
-
'rw', // Kinyarwanda
|
919 |
-
'sa', // Sanskrit
|
920 |
-
'sc', // Sardinian
|
921 |
-
'se', // Northern Sámi
|
922 |
-
'si', // Sinhala
|
923 |
-
'sk', // Slovak
|
924 |
-
'sl', // Slovenian
|
925 |
-
'sn', // Shona
|
926 |
-
'so', // Somali
|
927 |
-
'sq', // Albanian
|
928 |
-
'sr', // Serbian
|
929 |
-
'sv', // Swedish
|
930 |
-
'sy', // Swahili
|
931 |
-
'sw', // Syriac
|
932 |
-
'sz', // Silesian
|
933 |
-
'ta', // Tamil
|
934 |
-
'te', // Telugu
|
935 |
-
'tg', // Tajik
|
936 |
-
'th', // Thai
|
937 |
-
'tk', // Turkmen
|
938 |
-
'tl', // Filipino
|
939 |
-
'tl', // Klingon
|
940 |
-
'tr', // Turkish
|
941 |
-
'tt', // Tatar
|
942 |
-
'tz', // Tamazight
|
943 |
-
'uk', // Ukrainian
|
944 |
-
'ur', // Urdu
|
945 |
-
'uz', // Uzbek
|
946 |
-
'vi', // Vietnamese
|
947 |
-
'wo', // Wolof
|
948 |
-
'xh', // Xhosa
|
949 |
-
'yi', // Yiddish
|
950 |
-
'yo', // Yoruba
|
951 |
-
'zh', // Simplified Chinese (China)
|
952 |
-
'zh', // Traditional Chinese (Hong Kong)
|
953 |
-
'zh', // Traditional Chinese (Taiwan)
|
954 |
-
'zu', // Zulu
|
955 |
-
'zz', // Zazaki
|
956 |
];
|
957 |
}
|
958 |
}
|
99 |
'disabled_taxonomies' => [], // Taxonomy support.
|
100 |
|
101 |
// Title.
|
102 |
+
'site_title' => '', // Blog name.
|
103 |
+
'title_separator' => 'hyphen', // Title separator, radio selection.
|
104 |
'title_location' => $titleloc, // Title separation location
|
105 |
'title_rem_additions' => 0, // Remove title additions
|
106 |
'title_rem_prefixes' => 0, // Remove title prefixes from archives.
|
171 |
'homepage_social_image_url' => '',
|
172 |
'homepage_social_image_id' => 0,
|
173 |
|
174 |
+
// Post Type Archives.
|
175 |
+
'pta' => $this->get_all_post_type_archive_meta_defaults(), // All of it. See $this->get_post_type_archive_meta(), which calls this index.
|
176 |
+
|
177 |
// Relationships.
|
178 |
'shortlink_tag' => 0, // Adds shortlink tag
|
179 |
'prev_next_posts' => 1, // Adds next/prev tags
|
253 |
'sitemap_query_limit' => 1000, // Sitemap post limit.
|
254 |
|
255 |
'sitemaps_modified' => 1, // Add sitemap modified time.
|
|
|
256 |
|
257 |
'sitemaps_robots' => 1, // Add sitemap location to robots.txt
|
258 |
|
289 |
* @since 3.1.0 Now applies the "the_seo_framework_warned_site_options" filter.
|
290 |
* @since 4.1.0 Added robots' post type setting warnings.
|
291 |
* @since 4.1.2 Added `ping_use_cron_prerender`.
|
292 |
+
* @since 4.2.0 Now memoizes its return value.
|
293 |
*
|
294 |
* @return array $options.
|
295 |
*/
|
296 |
public function get_warned_site_options() {
|
297 |
+
return memo() ?? memo(
|
298 |
+
/**
|
299 |
+
* Warned site settings. Only accepts checkbox options.
|
300 |
+
* When listed as 1, it's a feature which can destroy your website's SEO value when checked.
|
301 |
+
*
|
302 |
+
* Unchecking a box is simply "I'm not active." - Removing features generally do not negatively impact SEO value.
|
303 |
+
* Since it's all about the content.
|
304 |
+
*
|
305 |
+
* Only used within the SEO Settings page.
|
306 |
+
*
|
307 |
+
* @since 2.3.4
|
308 |
+
* @param array $options The warned site options.
|
309 |
+
*/
|
310 |
+
(array) \apply_filters(
|
311 |
+
'the_seo_framework_warned_site_options',
|
312 |
+
[
|
313 |
+
'title_rem_additions' => 1, // Title remove additions.
|
314 |
+
'site_noindex' => 1, // Site Page robots noindex.
|
315 |
+
'site_nofollow' => 1, // Site Page robots nofollow.
|
316 |
+
'homepage_noindex' => 1, // Homepage robots noindex.
|
317 |
+
'homepage_nofollow' => 1, // Homepage robots noarchive.
|
318 |
+
$this->get_robots_post_type_option_id( 'noindex' ) => [
|
319 |
+
'post' => 1,
|
320 |
+
'page' => 1,
|
321 |
+
],
|
322 |
+
$this->get_robots_post_type_option_id( 'nofollow' ) => [
|
323 |
+
'post' => 1,
|
324 |
+
'page' => 1,
|
325 |
+
],
|
326 |
+
'ping_use_cron_prerender' => 1, // Sitemap cron-ping prerender.
|
327 |
+
]
|
328 |
+
)
|
329 |
);
|
330 |
}
|
331 |
|
335 |
* @since 2.2.2
|
336 |
* @since 2.8.2 No longer decodes entities on request.
|
337 |
* @since 3.1.0 Now uses the filterable call when caching is disabled.
|
338 |
+
* @since 4.2.0 Now supports an option index as a $key.
|
339 |
* @uses THE_SEO_FRAMEWORK_SITE_OPTIONS
|
340 |
*
|
341 |
+
* @param string|string[] $key Option name, or a map of indexes therefor.
|
342 |
+
* If you send an empty array, you'll get all options. Don't.
|
343 |
+
* @param boolean $use_cache Optional. Whether to use the cache value or not. Defaults to true.
|
344 |
* @return mixed The value of this $key in the database. Empty string when not set.
|
345 |
*/
|
346 |
public function get_option( $key, $use_cache = true ) {
|
347 |
|
348 |
if ( ! $use_cache ) {
|
349 |
+
// Preassign all options to $val so we can loop through it.
|
350 |
+
$val = $this->get_all_options( THE_SEO_FRAMEWORK_SITE_OPTIONS, true );
|
351 |
+
|
352 |
+
// This loop digs through itself: $val[ $index ][ $index ]... etc.
|
353 |
+
foreach ( (array) $key as $k )
|
354 |
+
$val = $val[ $k ] ?? '';
|
355 |
+
|
356 |
+
return ! empty( $val ) ? \stripslashes_deep( $val ) : '';
|
357 |
}
|
358 |
|
359 |
+
static $cache;
|
360 |
+
|
361 |
+
// PHP 7.4: null coalesce equal operator: ??=
|
362 |
+
if ( ! isset( $cache ) )
|
363 |
+
$cache = \stripslashes_deep( $this->get_all_options( THE_SEO_FRAMEWORK_SITE_OPTIONS ) );
|
364 |
+
|
365 |
+
$val = $cache;
|
366 |
|
367 |
+
// This loop digs through itself: $val[ $index ][ $index ]... etc.
|
368 |
+
foreach ( (array) $key as $k )
|
369 |
+
$val = $val[ $k ] ?? '';
|
370 |
|
371 |
+
return $val;
|
|
|
372 |
}
|
373 |
|
374 |
/**
|
375 |
* Return current option array.
|
376 |
* Memoizes the return value, can be bypassed and reset with second parameter.
|
377 |
*
|
378 |
+
* This method does NOT merge the default post options.
|
379 |
+
*
|
380 |
+
* @TODO Should we fall back to default options when one isn't registered (correctly)?
|
381 |
+
* See get_term_meta(), which falls back to default term meta.
|
382 |
+
* We'd need our fancy in-house array_merge_recursive_distinct() though.
|
383 |
+
* BLOCKER: This method always runs BEFORE 'pta' can be filled by other plugins.
|
384 |
+
*
|
385 |
* @since 2.6.0
|
386 |
* @since 2.9.2 Added $use_current parameter.
|
387 |
*
|
394 |
|
395 |
static $cache = [];
|
396 |
|
|
|
|
|
|
|
397 |
if ( ! $setting )
|
398 |
$setting = THE_SEO_FRAMEWORK_SITE_OPTIONS;
|
399 |
|
400 |
+
if ( ! $reset && isset( $cache[ $setting ] ) )
|
401 |
+
return $cache[ $setting ];
|
402 |
+
|
403 |
/**
|
404 |
* @since 2.0.0
|
405 |
* @since 4.1.4 1. Now considers headlessness.
|
425 |
* Return Default SEO options from the SEO options array.
|
426 |
*
|
427 |
* @since 2.2.5
|
428 |
+
* @since 4.2.0 1. Now supports an option index as `$key`.
|
429 |
+
* 2. Removed second parameter (`$use_cache`).
|
430 |
+
* 3. Now always memoizes.
|
431 |
* @uses $this->get_default_settings() Return option from the options table and cache result.
|
432 |
* @uses THE_SEO_FRAMEWORK_SITE_OPTIONS
|
433 |
*
|
434 |
+
* @param string|string[] $key Required. The option name, or a map of indexes.
|
435 |
+
* @return mixed The default option. Null if it's not registered.
|
|
|
436 |
*/
|
437 |
+
public function get_default_option( $key ) {
|
438 |
+
|
439 |
+
$val = umemo( __METHOD__ )
|
440 |
+
?? umemo( __METHOD__, \stripslashes_deep( $this->get_default_site_options() ) );
|
441 |
+
|
442 |
+
// This loop digs through itself: $val[ $index ][ $index ]... etc.
|
443 |
+
foreach ( (array) $key as $k )
|
444 |
+
$val = $val[ $k ] ?? null;
|
445 |
+
|
446 |
+
return $val ?? null;
|
447 |
+
}
|
448 |
+
|
449 |
+
/**
|
450 |
+
* Return Warned SEO options from the SEO options array.
|
451 |
+
*
|
452 |
+
* @since 4.2.0
|
453 |
+
* @uses $this->get_default_settings() Return option from the options table and cache result.
|
454 |
+
* @uses THE_SEO_FRAMEWORK_SITE_OPTIONS
|
455 |
+
*
|
456 |
+
* @param string|string[] $key Required. The option name, or a map of indexes.
|
457 |
+
* @return bool True if warning is registered. False otherwise.
|
458 |
+
*/
|
459 |
+
public function get_warned_option( $key ) {
|
460 |
+
|
461 |
+
$val = umemo( __METHOD__ )
|
462 |
+
?? umemo( __METHOD__, \stripslashes_deep( $this->get_warned_site_options() ) );
|
463 |
+
|
464 |
+
// This loop digs through itself: $val[ $index ][ $index ]... etc.
|
465 |
+
foreach ( (array) $key as $k )
|
466 |
+
$val = $val[ $k ] ?? null;
|
467 |
+
|
468 |
+
return (bool) ( $val ?? false );
|
469 |
}
|
470 |
|
471 |
/**
|
503 |
* @return mixed Cache value on success, $default if non-existent.
|
504 |
*/
|
505 |
public function get_static_cache( $key, $default = false ) {
|
506 |
+
return \get_option( THE_SEO_FRAMEWORK_SITE_CACHE, [] )[ $key ] ?? $default;
|
|
|
507 |
}
|
508 |
|
509 |
/**
|
602 |
}
|
603 |
|
604 |
/**
|
605 |
+
* Returns the option value for Post Type robots settings.
|
606 |
*
|
607 |
+
* @since 3.1.0
|
608 |
+
* @since 4.2.0 No longer sanitizes the input parameter.
|
609 |
+
*
|
610 |
+
* @param string $type Accepts 'noindex', 'nofollow', 'noarchive'.
|
611 |
+
* @return string
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
612 |
*/
|
613 |
+
public function get_robots_post_type_option_id( $type ) {
|
614 |
+
return "{$type}_post_types";
|
615 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
616 |
|
617 |
+
/**
|
618 |
+
* Returns the option value for Taxonomy robots settings.
|
619 |
+
*
|
620 |
+
* @since 4.1.0
|
621 |
+
* @since 4.2.0 No longer sanitizes the input parameter.
|
622 |
+
*
|
623 |
+
* @param string $type Accepts 'noindex', 'nofollow', 'noarchive'.
|
624 |
+
* @return string
|
625 |
+
*/
|
626 |
+
public function get_robots_taxonomy_option_id( $type ) {
|
627 |
+
return "{$type}_taxonomies";
|
628 |
+
}
|
629 |
|
630 |
+
/**
|
631 |
+
* Returns supported social site locales.
|
632 |
+
*
|
633 |
+
* @since 4.2.0
|
634 |
+
* @see https://www.facebook.com/translations/FacebookLocales.xml (deprecated)
|
635 |
+
* @see https://wordpress.org/support/topic/oglocale-problem/#post-11456346
|
636 |
+
* mirror: http://web.archive.org/web/20190601043836/https://wordpress.org/support/topic/oglocale-problem/
|
637 |
+
*
|
638 |
+
* @return array Valid social locales
|
639 |
+
*/
|
640 |
+
public function supported_social_locales() {
|
641 |
+
return [
|
642 |
+
'af_ZA' => 'af', // Afrikaans
|
643 |
+
'ak_GH' => 'ak', // Akan
|
644 |
+
'am_ET' => 'am', // Amharic
|
645 |
+
'ar_AR' => 'ar', // Arabic
|
646 |
+
'as_IN' => 'as', // Assamese
|
647 |
+
'ay_BO' => 'ay', // Aymara
|
648 |
+
'az_AZ' => 'az', // Azerbaijani
|
649 |
+
'be_BY' => 'be', // Belarusian
|
650 |
+
'bg_BG' => 'bg', // Bulgarian
|
651 |
+
'bn_IN' => 'bn', // Bengali
|
652 |
+
'br_FR' => 'br', // Breton
|
653 |
+
'bs_BA' => 'bs', // Bosnian
|
654 |
+
'ca_ES' => 'ca', // Catalan
|
655 |
+
'cb_IQ' => 'cb', // Sorani Kurdish
|
656 |
+
'ck_US' => 'ck', // Cherokee
|
657 |
+
'co_FR' => 'co', // Corsican
|
658 |
+
'cs_CZ' => 'cs', // Czech
|
659 |
+
'cx_PH' => 'cx', // Cebuano
|
660 |
+
'cy_GB' => 'cy', // Welsh
|
661 |
+
'da_DK' => 'da', // Danish
|
662 |
+
'de_DE' => 'de', // German
|
663 |
+
'el_GR' => 'el', // Greek
|
664 |
+
'en_GB' => 'en', // English (UK)
|
665 |
+
'en_IN' => 'en', // English (India)
|
666 |
+
'en_PI' => 'en', // English (Pirate)
|
667 |
+
'en_UD' => 'en', // English (Upside Down)
|
668 |
+
'en_US' => 'en', // English (US)
|
669 |
+
'eo_EO' => 'eo', // Esperanto
|
670 |
+
'es_CL' => 'es', // Spanish (Chile)
|
671 |
+
'es_CO' => 'es', // Spanish (Colombia)
|
672 |
+
'es_ES' => 'es', // Spanish (Spain)
|
673 |
+
'es_LA' => 'es', // Spanish
|
674 |
+
'es_MX' => 'es', // Spanish (Mexico)
|
675 |
+
'es_VE' => 'es', // Spanish (Venezuela)
|
676 |
+
'et_EE' => 'et', // Estonian
|
677 |
+
'eu_ES' => 'eu', // Basque
|
678 |
+
'fa_IR' => 'fa', // Persian
|
679 |
+
'fb_LT' => 'fb', // Leet Speak
|
680 |
+
'ff_NG' => 'ff', // Fulah
|
681 |
+
'fi_FI' => 'fi', // Finnish
|
682 |
+
'fo_FO' => 'fo', // Faroese
|
683 |
+
'fr_CA' => 'fr', // French (Canada)
|
684 |
+
'fr_FR' => 'fr', // French (France)
|
685 |
+
'fy_NL' => 'fy', // Frisian
|
686 |
+
'ga_IE' => 'ga', // Irish
|
687 |
+
'gl_ES' => 'gl', // Galician
|
688 |
+
'gn_PY' => 'gn', // Guarani
|
689 |
+
'gu_IN' => 'gu', // Gujarati
|
690 |
+
'gx_GR' => 'gx', // Classical Greek
|
691 |
+
'ha_NG' => 'ha', // Hausa
|
692 |
+
'he_IL' => 'he', // Hebrew
|
693 |
+
'hi_IN' => 'hi', // Hindi
|
694 |
+
'hr_HR' => 'hr', // Croatian
|
695 |
+
'hu_HU' => 'hu', // Hungarian
|
696 |
+
'hy_AM' => 'hy', // Armenian
|
697 |
+
'id_ID' => 'id', // Indonesian
|
698 |
+
'ig_NG' => 'ig', // Igbo
|
699 |
+
'is_IS' => 'is', // Icelandic
|
700 |
+
'it_IT' => 'it', // Italian
|
701 |
+
'ja_JP' => 'ja', // Japanese
|
702 |
+
'ja_KS' => 'ja', // Japanese (Kansai)
|
703 |
+
'jv_ID' => 'jv', // Javanese
|
704 |
+
'ka_GE' => 'ka', // Georgian
|
705 |
+
'kk_KZ' => 'kk', // Kazakh
|
706 |
+
'km_KH' => 'km', // Khmer
|
707 |
+
'kn_IN' => 'kn', // Kannada
|
708 |
+
'ko_KR' => 'ko', // Korean
|
709 |
+
'ku_TR' => 'ku', // Kurdish (Kurmanji)
|
710 |
+
'ky_KG' => 'ky', // Kyrgyz
|
711 |
+
'la_VA' => 'la', // Latin
|
712 |
+
'lg_UG' => 'lg', // Ganda
|
713 |
+
'li_NL' => 'li', // Limburgish
|
714 |
+
'ln_CD' => 'ln', // Lingala
|
715 |
+
'lo_LA' => 'lo', // Lao
|
716 |
+
'lt_LT' => 'lt', // Lithuanian
|
717 |
+
'lv_LV' => 'lv', // Latvian
|
718 |
+
'mg_MG' => 'mg', // Malagasy
|
719 |
+
'mi_NZ' => 'mi', // Māori
|
720 |
+
'mk_MK' => 'mk', // Macedonian
|
721 |
+
'ml_IN' => 'ml', // Malayalam
|
722 |
+
'mn_MN' => 'mn', // Mongolian
|
723 |
+
'mr_IN' => 'mr', // Marathi
|
724 |
+
'ms_MY' => 'ms', // Malay
|
725 |
+
'mt_MT' => 'mt', // Maltese
|
726 |
+
'my_MM' => 'my', // Burmese
|
727 |
+
'nb_NO' => 'nb', // Norwegian (bokmal)
|
728 |
+
'nd_ZW' => 'nd', // Ndebele
|
729 |
+
'ne_NP' => 'ne', // Nepali
|
730 |
+
'nl_BE' => 'nl', // Dutch (België)
|
731 |
+
'nl_NL' => 'nl', // Dutch
|
732 |
+
'nn_NO' => 'nn', // Norwegian (nynorsk)
|
733 |
+
'ny_MW' => 'ny', // Chewa
|
734 |
+
'or_IN' => 'or', // Oriya
|
735 |
+
'pa_IN' => 'pa', // Punjabi
|
736 |
+
'pl_PL' => 'pl', // Polish
|
737 |
+
'ps_AF' => 'ps', // Pashto
|
738 |
+
'pt_BR' => 'pt', // Portuguese (Brazil)
|
739 |
+
'pt_PT' => 'pt', // Portuguese (Portugal)
|
740 |
+
'qu_PE' => 'qu', // Quechua
|
741 |
+
'rm_CH' => 'rm', // Romansh
|
742 |
+
'ro_RO' => 'ro', // Romanian
|
743 |
+
'ru_RU' => 'ru', // Russian
|
744 |
+
'rw_RW' => 'rw', // Kinyarwanda
|
745 |
+
'sa_IN' => 'sa', // Sanskrit
|
746 |
+
'sc_IT' => 'sc', // Sardinian
|
747 |
+
'se_NO' => 'se', // Northern Sámi
|
748 |
+
'si_LK' => 'si', // Sinhala
|
749 |
+
'sk_SK' => 'sk', // Slovak
|
750 |
+
'sl_SI' => 'sl', // Slovenian
|
751 |
+
'sn_ZW' => 'sn', // Shona
|
752 |
+
'so_SO' => 'so', // Somali
|
753 |
+
'sq_AL' => 'sq', // Albanian
|
754 |
+
'sr_RS' => 'sr', // Serbian
|
755 |
+
'sv_SE' => 'sv', // Swedish
|
756 |
+
'sy_SY' => 'sy', // Swahili
|
757 |
+
'sw_KE' => 'sw', // Syriac
|
758 |
+
'sz_PL' => 'sz', // Silesian
|
759 |
+
'ta_IN' => 'ta', // Tamil
|
760 |
+
'te_IN' => 'te', // Telugu
|
761 |
+
'tg_TJ' => 'tg', // Tajik
|
762 |
+
'th_TH' => 'th', // Thai
|
763 |
+
'tk_TM' => 'tk', // Turkmen
|
764 |
+
'tl_PH' => 'tl', // Filipino
|
765 |
+
'tl_ST' => 'tl', // Klingon
|
766 |
+
'tr_TR' => 'tr', // Turkish
|
767 |
+
'tt_RU' => 'tt', // Tatar
|
768 |
+
'tz_MA' => 'tz', // Tamazight
|
769 |
+
'uk_UA' => 'uk', // Ukrainian
|
770 |
+
'ur_PK' => 'ur', // Urdu
|
771 |
+
'uz_UZ' => 'uz', // Uzbek
|
772 |
+
'vi_VN' => 'vi', // Vietnamese
|
773 |
+
'wo_SN' => 'wo', // Wolof
|
774 |
+
'xh_ZA' => 'xh', // Xhosa
|
775 |
+
'yi_DE' => 'yi', // Yiddish
|
776 |
+
'yo_NG' => 'yo', // Yoruba
|
777 |
+
'zh_CN' => 'zh', // Simplified Chinese (China)
|
778 |
+
'zh_HK' => 'zh', // Traditional Chinese (Hong Kong)
|
779 |
+
'zh_TW' => 'zh', // Traditional Chinese (Taiwan)
|
780 |
+
'zu_ZA' => 'zu', // Zulu
|
781 |
+
'zz_TR' => 'zz', // Zazaki
|
782 |
+
];
|
783 |
}
|
784 |
|
785 |
/**
|
786 |
+
* Returns all post type archive meta.
|
787 |
*
|
788 |
+
* We do not test whether a post type is supported, for it'll conflict with data-fills on the
|
789 |
+
* SEO settings page. This meta should never get called on the front-end if the post type is
|
790 |
+
* disabled, anyway, for we never query post types externally, aside from the SEO settings page.
|
791 |
+
*
|
792 |
+
* @since 4.2.0
|
793 |
*
|
794 |
+
* @param string $post_type The post type.
|
795 |
+
* @param bool $use_cache Whether to use caching.
|
796 |
+
* @return array The post type archive's meta item's values.
|
|
|
797 |
*/
|
798 |
+
public function get_post_type_archive_meta( $post_type, $use_cache = true ) {
|
799 |
|
800 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
801 |
+
if ( $use_cache && ( $memo = memo( null, $post_type ) ) ) return $memo;
|
802 |
|
803 |
+
/**
|
804 |
+
* We can't trust the filter to always contain the expected keys.
|
805 |
+
* However, it may contain more keys than we anticipated. Merge them.
|
806 |
+
*/
|
807 |
+
$defaults = array_merge(
|
808 |
+
$this->get_unfiltered_post_type_archive_meta_defaults(),
|
809 |
+
$this->get_post_type_archive_meta_defaults( $post_type )
|
810 |
+
);
|
811 |
|
812 |
+
// Yes, we abide by "settings". WordPress never gave us Post Type Archive settings-pages.
|
813 |
+
if ( $this->is_headless['settings'] ) {
|
814 |
+
$meta = [];
|
815 |
+
} else {
|
816 |
+
// Unlike get_post_meta(), we need not filter here.
|
817 |
+
// See: <https://github.com/sybrew/the-seo-framework/issues/185>
|
818 |
+
$meta = $this->get_option( [ 'pta', $post_type ], $use_cache ) ?: [];
|
819 |
}
|
820 |
|
821 |
+
/**
|
822 |
+
* @since 4.2.0
|
823 |
+
* @note Do not delete/unset/add indexes! It'll cause errors.
|
824 |
+
* @param array $meta The current post type archive meta.
|
825 |
+
* @param int $post_type The post type.
|
826 |
+
* @param bool $headless Whether the meta are headless.
|
827 |
+
*/
|
828 |
+
$meta = \apply_filters_ref_array(
|
829 |
+
'the_seo_framework_post_type_archive_meta',
|
830 |
+
[
|
831 |
+
array_merge( $defaults, $meta ),
|
832 |
+
$post_type,
|
833 |
+
$this->is_headless['settings'],
|
834 |
+
]
|
835 |
+
);
|
836 |
|
837 |
+
// Do not overwrite cache when not requested. Otherwise, we'd have two "initial" states, causing incongruities.
|
838 |
+
return $use_cache ? memo( $meta, $post_type ) : $meta;
|
839 |
}
|
840 |
|
841 |
/**
|
842 |
+
* Returns a single post type archive item's value.
|
843 |
*
|
844 |
+
* @since 4.2.0
|
845 |
*
|
846 |
+
* @param string $item The item to get.
|
847 |
+
* @param string $post_type The post type.
|
848 |
+
* @param bool $use_cache Whether to use caching.
|
849 |
+
* @return array|null The post type archive's meta item's value. Null when item isn't registered.
|
850 |
*/
|
851 |
+
public function get_post_type_archive_meta_item( $item, $post_type = '', $use_cache = true ) {
|
852 |
+
return $this->get_post_type_archive_meta(
|
853 |
+
$post_type ?: $this->get_current_post_type(),
|
854 |
+
$use_cache
|
855 |
+
)[ $item ] ?? null;
|
856 |
}
|
857 |
|
858 |
+
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- You don't love PHP 7.
|
859 |
/**
|
860 |
+
* Returns an array of all public post type archive option defaults.
|
861 |
*
|
862 |
+
* @since 4.2.0
|
863 |
*
|
864 |
+
* @return array[] The Post Type Archive Metadata default options
|
865 |
+
* of all public Post Type archives.
|
866 |
*/
|
867 |
+
public function get_all_post_type_archive_meta_defaults() {
|
868 |
+
|
869 |
+
foreach ( $this->get_public_post_type_archives() as $pta )
|
870 |
+
$defaults[ $pta ] = $this->get_post_type_archive_meta_defaults( $pta );
|
871 |
+
|
872 |
+
return $defaults ?? [];
|
873 |
}
|
874 |
+
// phpcs:enable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
|
875 |
|
876 |
/**
|
877 |
+
* Returns an array of default post type archive meta.
|
878 |
*
|
879 |
+
* @since 4.2.0
|
|
|
880 |
*
|
881 |
+
* @param int $post_type The post type.
|
882 |
+
* @return array The Post Type Archive Metadata default options.
|
|
|
|
|
|
|
|
|
883 |
*/
|
884 |
+
public function get_post_type_archive_meta_defaults( $post_type = '' ) {
|
885 |
+
/**
|
886 |
+
* @since 4.2.0
|
887 |
+
* @param array $defaults
|
888 |
+
* @param int $term_id The current term ID.
|
889 |
+
*/
|
890 |
+
return (array) \apply_filters_ref_array(
|
891 |
+
'the_seo_framework_get_post_type_archive_meta_defaults',
|
892 |
+
[
|
893 |
+
$this->get_unfiltered_post_type_archive_meta_defaults(),
|
894 |
+
$post_type ?: $this->get_current_post_type(),
|
895 |
+
]
|
896 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
897 |
}
|
898 |
|
899 |
/**
|
900 |
+
* Returns the unfiltered post type archive meta defaults.
|
|
|
|
|
|
|
901 |
*
|
902 |
+
* @since 4.2.0
|
|
|
|
|
|
|
903 |
*
|
904 |
+
* @return array The default, unfiltered, post type archive meta.
|
905 |
*/
|
906 |
+
protected function get_unfiltered_post_type_archive_meta_defaults() {
|
907 |
return [
|
908 |
+
'doctitle' => '',
|
909 |
+
'title_no_blog_name' => 0,
|
910 |
+
'description' => '',
|
911 |
+
'og_title' => '',
|
912 |
+
'og_description' => '',
|
913 |
+
'tw_title' => '',
|
914 |
+
'tw_description' => '',
|
915 |
+
'social_image_url' => '',
|
916 |
+
'social_image_id' => 0,
|
917 |
+
'canonical' => '',
|
918 |
+
'noindex' => 0,
|
919 |
+
'nofollow' => 0,
|
920 |
+
'noarchive' => 0,
|
921 |
+
'redirect' => '',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
922 |
];
|
923 |
}
|
924 |
}
|
@@ -60,6 +60,7 @@ class Term_Data extends Post_Data {
|
|
60 |
* Returns the term meta item by key.
|
61 |
*
|
62 |
* @since 4.0.0
|
|
|
63 |
*
|
64 |
* @param string $item The item to get.
|
65 |
* @param int $term_id The Term ID.
|
@@ -67,39 +68,7 @@ class Term_Data extends Post_Data {
|
|
67 |
* @return mixed The term meta item. Null when not found.
|
68 |
*/
|
69 |
public function get_term_meta_item( $item, $term_id = 0, $use_cache = true ) {
|
70 |
-
|
71 |
-
if ( ! $term_id ) {
|
72 |
-
$meta = $this->get_current_term_meta();
|
73 |
-
} else {
|
74 |
-
$meta = $this->get_term_meta( $term_id, $use_cache );
|
75 |
-
}
|
76 |
-
|
77 |
-
return isset( $meta[ $item ] ) ? $meta[ $item ] : null;
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Returns and caches term meta for the current query.
|
82 |
-
* Memoizes the return value for the current request.
|
83 |
-
*
|
84 |
-
* @since 3.0.0
|
85 |
-
* @since 4.0.1 Now uses the filterable `get_the_real_ID()`
|
86 |
-
*
|
87 |
-
* @return array The current term meta.
|
88 |
-
*/
|
89 |
-
public function get_current_term_meta() {
|
90 |
-
|
91 |
-
static $cache;
|
92 |
-
|
93 |
-
if ( isset( $cache ) )
|
94 |
-
return $cache;
|
95 |
-
|
96 |
-
if ( $this->is_term_meta_capable() ) {
|
97 |
-
$cache = $this->get_term_meta( $this->get_the_real_ID() ) ?: [];
|
98 |
-
} else {
|
99 |
-
$cache = [];
|
100 |
-
}
|
101 |
-
|
102 |
-
return $cache;
|
103 |
}
|
104 |
|
105 |
/**
|
@@ -116,6 +85,7 @@ class Term_Data extends Post_Data {
|
|
116 |
* 2. Now fills in defaults.
|
117 |
* @since 4.1.4 1. Removed deprecated filter.
|
118 |
* 2. Now considers headlessness.
|
|
|
119 |
*
|
120 |
* @param int $term_id The Term ID.
|
121 |
* @param bool $use_cache Whether to use caching.
|
@@ -123,11 +93,15 @@ class Term_Data extends Post_Data {
|
|
123 |
*/
|
124 |
public function get_term_meta( $term_id, $use_cache = true ) {
|
125 |
|
126 |
-
|
127 |
-
|
128 |
|
129 |
-
|
130 |
-
|
|
|
|
|
|
|
|
|
131 |
}
|
132 |
|
133 |
/**
|
@@ -136,13 +110,15 @@ class Term_Data extends Post_Data {
|
|
136 |
*/
|
137 |
$defaults = array_merge(
|
138 |
$this->get_unfiltered_term_meta_defaults(),
|
139 |
-
$this->get_term_meta_defaults( $term_id )
|
140 |
);
|
141 |
|
142 |
if ( $this->is_headless['meta'] ) {
|
143 |
$meta = [];
|
144 |
} else {
|
145 |
-
|
|
|
|
|
146 |
}
|
147 |
|
148 |
/**
|
@@ -158,12 +134,14 @@ class Term_Data extends Post_Data {
|
|
158 |
'the_seo_framework_term_meta',
|
159 |
[
|
160 |
array_merge( $defaults, $meta ),
|
161 |
-
$term_id,
|
162 |
$this->is_headless['meta'],
|
163 |
]
|
164 |
);
|
165 |
|
166 |
-
|
|
|
|
|
167 |
}
|
168 |
|
169 |
/**
|
@@ -171,10 +149,10 @@ class Term_Data extends Post_Data {
|
|
171 |
*
|
172 |
* @since 2.7.0
|
173 |
* @since 3.1.0 This is now always used.
|
174 |
-
* @since 4.0.0
|
175 |
-
*
|
176 |
-
*
|
177 |
-
*
|
178 |
*
|
179 |
* @param int $term_id The term ID.
|
180 |
* @return array The Term Metadata default options.
|
@@ -199,7 +177,7 @@ class Term_Data extends Post_Data {
|
|
199 |
*
|
200 |
* @since 4.0.0
|
201 |
*
|
202 |
-
* @return array The default, unfiltered,
|
203 |
*/
|
204 |
protected function get_unfiltered_term_meta_defaults() {
|
205 |
return [
|
@@ -224,15 +202,15 @@ class Term_Data extends Post_Data {
|
|
224 |
* Sanitizes and saves term meta data when a term is altered.
|
225 |
*
|
226 |
* @since 2.7.0
|
227 |
-
* @since 4.0.0
|
228 |
-
*
|
229 |
-
*
|
230 |
-
*
|
231 |
-
*
|
232 |
-
*
|
233 |
-
*
|
234 |
-
*
|
235 |
-
*
|
236 |
* @securitycheck 3.0.0 OK.
|
237 |
* @access private
|
238 |
* Use $this->save_term_meta() instead.
|
@@ -257,8 +235,8 @@ class Term_Data extends Post_Data {
|
|
257 |
* Overwrites all of the term meta on term-edit.
|
258 |
*
|
259 |
* @since 4.0.0
|
260 |
-
* @since 4.0.2
|
261 |
-
*
|
262 |
*
|
263 |
* @param int $term_id Term ID.
|
264 |
* @param int $tt_id Term taxonomy ID.
|
@@ -276,7 +254,7 @@ class Term_Data extends Post_Data {
|
|
276 |
// Note, however: function wp_update_term() already performs all these checks for us before firing this callback's action.
|
277 |
if ( ! \current_user_can( 'edit_term', $term->term_id ) ) return;
|
278 |
if ( ! isset( $_POST['_wpnonce'] ) ) return;
|
279 |
-
if ( ! \wp_verify_nonce( $_POST['_wpnonce'],
|
280 |
|
281 |
$data = (array) $_POST['autodescription-meta'];
|
282 |
|
@@ -288,8 +266,8 @@ class Term_Data extends Post_Data {
|
|
288 |
* Overwrites a part of the term meta on quick-edit.
|
289 |
*
|
290 |
* @since 4.0.0
|
291 |
-
* @since 4.0.2
|
292 |
-
*
|
293 |
*
|
294 |
* @param int $term_id Term ID.
|
295 |
* @param int $tt_id Term taxonomy ID.
|
@@ -326,8 +304,8 @@ class Term_Data extends Post_Data {
|
|
326 |
* as it reprocesses all term meta.
|
327 |
*
|
328 |
* @since 4.0.0
|
329 |
-
* @since 4.0.2
|
330 |
-
*
|
331 |
* @uses $this->save_term_meta() to process all data.
|
332 |
*
|
333 |
* @param string $item The item to update.
|
@@ -353,15 +331,15 @@ class Term_Data extends Post_Data {
|
|
353 |
* Updates term meta from input.
|
354 |
*
|
355 |
* @since 4.0.0
|
356 |
-
* @since 4.0.2
|
357 |
-
*
|
358 |
*
|
359 |
* @param int $term_id Term ID.
|
360 |
* @param int $tt_id Term Taxonomy ID.
|
361 |
* @param string $taxonomy Taxonomy slug.
|
362 |
* @param array $data The data to save.
|
363 |
*/
|
364 |
-
public function save_term_meta( $term_id, $tt_id, $taxonomy,
|
365 |
|
366 |
$term = \get_term( $term_id, $taxonomy );
|
367 |
|
@@ -407,9 +385,8 @@ class Term_Data extends Post_Data {
|
|
407 |
$data = \get_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, true );
|
408 |
|
409 |
if ( \is_array( $data ) ) {
|
410 |
-
foreach ( $this->get_term_meta_defaults( $term_id ) as $key => $value )
|
411 |
unset( $data[ $key ] );
|
412 |
-
}
|
413 |
}
|
414 |
|
415 |
// Only delete when no values are left, because someone else might've filtered it.
|
@@ -430,10 +407,8 @@ class Term_Data extends Post_Data {
|
|
430 |
*/
|
431 |
public function get_latest_category_id() {
|
432 |
|
433 |
-
|
434 |
-
|
435 |
-
if ( null !== $cat_id )
|
436 |
-
return $cat_id;
|
437 |
|
438 |
$cats = \get_terms( [
|
439 |
'taxonomy' => 'category',
|
@@ -444,7 +419,7 @@ class Term_Data extends Post_Data {
|
|
444 |
'number' => 1,
|
445 |
] );
|
446 |
|
447 |
-
return
|
448 |
}
|
449 |
|
450 |
/**
|
@@ -458,12 +433,9 @@ class Term_Data extends Post_Data {
|
|
458 |
* @return string The Taxonomy Type name/label, if found.
|
459 |
*/
|
460 |
public function get_tax_type_label( $tax_type, $singular = true ) {
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
return $singular
|
465 |
-
? ( isset( $tto->labels->singular_name ) ? $tto->labels->singular_name : '' )
|
466 |
-
: ( isset( $tto->labels->name ) ? $tto->labels->name : '' );
|
467 |
}
|
468 |
|
469 |
/**
|
@@ -479,7 +451,7 @@ class Term_Data extends Post_Data {
|
|
479 |
*/
|
480 |
public function get_hierarchical_taxonomies_as( $get = 'objects', $post_type = '' ) {
|
481 |
|
482 |
-
$post_type = $post_type ?: $this->
|
483 |
|
484 |
if ( ! $post_type )
|
485 |
return [];
|
60 |
* Returns the term meta item by key.
|
61 |
*
|
62 |
* @since 4.0.0
|
63 |
+
* @since 4.2.0 No longer accidentally returns an empty array on failure.
|
64 |
*
|
65 |
* @param string $item The item to get.
|
66 |
* @param int $term_id The Term ID.
|
68 |
* @return mixed The term meta item. Null when not found.
|
69 |
*/
|
70 |
public function get_term_meta_item( $item, $term_id = 0, $use_cache = true ) {
|
71 |
+
return $this->get_term_meta( $term_id ?: $this->get_the_real_ID(), $use_cache )[ $item ] ?? null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
}
|
73 |
|
74 |
/**
|
85 |
* 2. Now fills in defaults.
|
86 |
* @since 4.1.4 1. Removed deprecated filter.
|
87 |
* 2. Now considers headlessness.
|
88 |
+
* @since 4.2.0 Now returns an empty array when the term's taxonomy isn't supported.
|
89 |
*
|
90 |
* @param int $term_id The Term ID.
|
91 |
* @param bool $use_cache Whether to use caching.
|
93 |
*/
|
94 |
public function get_term_meta( $term_id, $use_cache = true ) {
|
95 |
|
96 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
97 |
+
if ( $use_cache && ( $memo = memo( null, $term_id ) ) ) return $memo;
|
98 |
|
99 |
+
$term = \get_term( $term_id );
|
100 |
+
|
101 |
+
// We test taxonomy support to be consistent with `get_post_meta()`.
|
102 |
+
if ( empty( $term->term_id ) || ! $this->is_taxonomy_supported( $term->taxonomy ) ) {
|
103 |
+
// Do not overwrite cache when not requested. Otherwise, we'd have two "initial" states, causing incongruities.
|
104 |
+
return $use_cache ? memo( [], $term_id ) : [];
|
105 |
}
|
106 |
|
107 |
/**
|
110 |
*/
|
111 |
$defaults = array_merge(
|
112 |
$this->get_unfiltered_term_meta_defaults(),
|
113 |
+
$this->get_term_meta_defaults( $term->term_id )
|
114 |
);
|
115 |
|
116 |
if ( $this->is_headless['meta'] ) {
|
117 |
$meta = [];
|
118 |
} else {
|
119 |
+
// Unlike get_post_meta(), we need not filter here.
|
120 |
+
// See: <https://github.com/sybrew/the-seo-framework/issues/185>
|
121 |
+
$meta = \get_term_meta( $term->term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, true ) ?: [];
|
122 |
}
|
123 |
|
124 |
/**
|
134 |
'the_seo_framework_term_meta',
|
135 |
[
|
136 |
array_merge( $defaults, $meta ),
|
137 |
+
$term->term_id,
|
138 |
$this->is_headless['meta'],
|
139 |
]
|
140 |
);
|
141 |
|
142 |
+
// Cache using $term_id, not $term->term_id, otherwise invalid queries can bypass the cache.
|
143 |
+
// Do not overwrite cache when not requested. Otherwise, we'd have two "initial" states, causing incongruities.
|
144 |
+
return $use_cache ? memo( $meta, $term_id ) : $meta;
|
145 |
}
|
146 |
|
147 |
/**
|
149 |
*
|
150 |
* @since 2.7.0
|
151 |
* @since 3.1.0 This is now always used.
|
152 |
+
* @since 4.0.0 1. Added $term_id parameter.
|
153 |
+
* 2. Added 'redirect' value.
|
154 |
+
* 3. Added 'title_no_blog_name' value.
|
155 |
+
* 4. Removed 'saved_flag' value.
|
156 |
*
|
157 |
* @param int $term_id The term ID.
|
158 |
* @return array The Term Metadata default options.
|
177 |
*
|
178 |
* @since 4.0.0
|
179 |
*
|
180 |
+
* @return array The default, unfiltered, term meta.
|
181 |
*/
|
182 |
protected function get_unfiltered_term_meta_defaults() {
|
183 |
return [
|
202 |
* Sanitizes and saves term meta data when a term is altered.
|
203 |
*
|
204 |
* @since 2.7.0
|
205 |
+
* @since 4.0.0 1. Renamed from `update_term_meta`
|
206 |
+
* 2. noindex, nofollow, noarchive are now converted to qubits.
|
207 |
+
* 3. Added new keys to sanitize.
|
208 |
+
* 4. Now marked as private.
|
209 |
+
* 5. Added more sanity protection.
|
210 |
+
* 6. No longer runs when no `autodescription-meta` POST data is sent.
|
211 |
+
* 7. Now uses the current term meta to set new values.
|
212 |
+
* 8. No longer deletes meta from abstracting plugins on save when they're deactivated.
|
213 |
+
* 9. Now allows updating during `WP_AJAX`.
|
214 |
* @securitycheck 3.0.0 OK.
|
215 |
* @access private
|
216 |
* Use $this->save_term_meta() instead.
|
235 |
* Overwrites all of the term meta on term-edit.
|
236 |
*
|
237 |
* @since 4.0.0
|
238 |
+
* @since 4.0.2 1. Now tests for valid term ID in the term object.
|
239 |
+
* 2. Now continues using the filtered term object.
|
240 |
*
|
241 |
* @param int $term_id Term ID.
|
242 |
* @param int $tt_id Term taxonomy ID.
|
254 |
// Note, however: function wp_update_term() already performs all these checks for us before firing this callback's action.
|
255 |
if ( ! \current_user_can( 'edit_term', $term->term_id ) ) return;
|
256 |
if ( ! isset( $_POST['_wpnonce'] ) ) return;
|
257 |
+
if ( ! \wp_verify_nonce( $_POST['_wpnonce'], "update-tag_{$term->term_id}" ) ) return;
|
258 |
|
259 |
$data = (array) $_POST['autodescription-meta'];
|
260 |
|
266 |
* Overwrites a part of the term meta on quick-edit.
|
267 |
*
|
268 |
* @since 4.0.0
|
269 |
+
* @since 4.0.2 1. Now tests for valid term ID in the term object.
|
270 |
+
* 2. Now continues using the filtered term object.
|
271 |
*
|
272 |
* @param int $term_id Term ID.
|
273 |
* @param int $tt_id Term taxonomy ID.
|
304 |
* as it reprocesses all term meta.
|
305 |
*
|
306 |
* @since 4.0.0
|
307 |
+
* @since 4.0.2 1. Now tests for valid term ID in the term object.
|
308 |
+
* 2. Now continues using the filtered term object.
|
309 |
* @uses $this->save_term_meta() to process all data.
|
310 |
*
|
311 |
* @param string $item The item to update.
|
331 |
* Updates term meta from input.
|
332 |
*
|
333 |
* @since 4.0.0
|
334 |
+
* @since 4.0.2 1. Now tests for valid term ID in the term object.
|
335 |
+
* 2. Now continues using the filtered term object.
|
336 |
*
|
337 |
* @param int $term_id Term ID.
|
338 |
* @param int $tt_id Term Taxonomy ID.
|
339 |
* @param string $taxonomy Taxonomy slug.
|
340 |
* @param array $data The data to save.
|
341 |
*/
|
342 |
+
public function save_term_meta( $term_id, $tt_id, $taxonomy, $data ) {
|
343 |
|
344 |
$term = \get_term( $term_id, $taxonomy );
|
345 |
|
385 |
$data = \get_term_meta( $term_id, THE_SEO_FRAMEWORK_TERM_OPTIONS, true );
|
386 |
|
387 |
if ( \is_array( $data ) ) {
|
388 |
+
foreach ( $this->get_term_meta_defaults( $term_id ) as $key => $value )
|
389 |
unset( $data[ $key ] );
|
|
|
390 |
}
|
391 |
|
392 |
// Only delete when no values are left, because someone else might've filtered it.
|
407 |
*/
|
408 |
public function get_latest_category_id() {
|
409 |
|
410 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
411 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
412 |
|
413 |
$cats = \get_terms( [
|
414 |
'taxonomy' => 'category',
|
419 |
'number' => 1,
|
420 |
] );
|
421 |
|
422 |
+
return memo( reset( $cats ) );
|
423 |
}
|
424 |
|
425 |
/**
|
433 |
* @return string The Taxonomy Type name/label, if found.
|
434 |
*/
|
435 |
public function get_tax_type_label( $tax_type, $singular = true ) {
|
436 |
+
return \get_taxonomy( $tax_type )->labels->{
|
437 |
+
$singular ? 'singular_name' : 'name'
|
438 |
+
} ?? '';
|
|
|
|
|
|
|
439 |
}
|
440 |
|
441 |
/**
|
451 |
*/
|
452 |
public function get_hierarchical_taxonomies_as( $get = 'objects', $post_type = '' ) {
|
453 |
|
454 |
+
$post_type = $post_type ?: $this->get_current_post_type();
|
455 |
|
456 |
if ( ! $post_type )
|
457 |
return [];
|
@@ -55,14 +55,7 @@ class User_Data extends Term_Data {
|
|
55 |
* @return mixed The user meta item. Null when not found.
|
56 |
*/
|
57 |
public function get_user_meta_item( $item, $user_id = 0, $use_cache = true ) {
|
58 |
-
|
59 |
-
if ( ! $user_id ) {
|
60 |
-
$meta = $this->get_user_meta( $this->get_user_id(), $use_cache );
|
61 |
-
} else {
|
62 |
-
$meta = $this->get_user_meta( $user_id, $use_cache );
|
63 |
-
}
|
64 |
-
|
65 |
-
return isset( $meta[ $item ] ) ? $meta[ $item ] : null;
|
66 |
}
|
67 |
|
68 |
/**
|
@@ -83,12 +76,12 @@ class User_Data extends Term_Data {
|
|
83 |
* Memoizes the return value for the current request.
|
84 |
*
|
85 |
* @since 4.1.4
|
|
|
86 |
*
|
87 |
* @return array The current author meta.
|
88 |
*/
|
89 |
public function get_current_post_author_meta() {
|
90 |
-
|
91 |
-
return isset( $cache ) ? $cache : $cache = $this->get_user_meta( $this->get_current_post_author_id() );
|
92 |
}
|
93 |
|
94 |
/**
|
@@ -99,7 +92,8 @@ class User_Data extends Term_Data {
|
|
99 |
* @since 2.8.0 Always returns array, even if no value is assigned.
|
100 |
* @since 4.1.4 1. Now returns default values when custom values are missing.
|
101 |
* 2. Now listens to headlessness.
|
102 |
-
* 3. Deprecated the
|
|
|
103 |
*
|
104 |
* @param int $user_id The user ID.
|
105 |
* @param bool $use_cache Whether to store and use options from cache, or bypass it.
|
@@ -112,12 +106,9 @@ class User_Data extends Term_Data {
|
|
112 |
|
113 |
$user_id = $user_id ?: $this->get_user_id();
|
114 |
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
if ( isset( $cache[ $user_id ] ) )
|
119 |
-
return $cache[ $user_id ];
|
120 |
-
}
|
121 |
|
122 |
/**
|
123 |
* We can't trust the filter to always contain the expected keys.
|
@@ -165,7 +156,8 @@ class User_Data extends Term_Data {
|
|
165 |
]
|
166 |
);
|
167 |
|
168 |
-
|
|
|
169 |
}
|
170 |
|
171 |
/**
|
@@ -210,6 +202,7 @@ class User_Data extends Term_Data {
|
|
210 |
* Saves user profile fields.
|
211 |
*
|
212 |
* @since 4.1.4
|
|
|
213 |
* @access private
|
214 |
*
|
215 |
* @param int $user_id The user ID.
|
@@ -218,20 +211,23 @@ class User_Data extends Term_Data {
|
|
218 |
|
219 |
if ( empty( $_POST ) ) return;
|
220 |
|
221 |
-
\check_admin_referer(
|
222 |
if ( ! \current_user_can( 'edit_user', $user_id ) ) return;
|
223 |
|
224 |
$user = \get_userdata( $user_id );
|
225 |
|
226 |
if ( ! $user->has_cap( THE_SEO_FRAMEWORK_AUTHOR_INFO_CAP ) ) return;
|
227 |
|
228 |
-
$data = (
|
|
|
|
|
|
|
229 |
|
230 |
$this->save_user_meta( $user_id, $data );
|
231 |
}
|
232 |
|
233 |
/**
|
234 |
-
* Updates user
|
235 |
*
|
236 |
* @since 4.1.4
|
237 |
*
|
@@ -256,20 +252,18 @@ class User_Data extends Term_Data {
|
|
256 |
* Updates users meta from input.
|
257 |
*
|
258 |
* @since 4.1.4
|
|
|
259 |
*
|
260 |
* @param int $user_id The user ID.
|
261 |
* @param array $data The data to save.
|
262 |
*/
|
263 |
-
public function save_user_meta( $user_id,
|
264 |
|
265 |
$user = \get_userdata( $user_id );
|
266 |
|
267 |
// We could test for !$user, but this is more to the point.
|
268 |
if ( empty( $user->ID ) ) return;
|
269 |
|
270 |
-
$data = (array) \wp_parse_args( $data, $this->get_user_meta_defaults( $user->ID ) );
|
271 |
-
$data = $this->s_user_meta( $data );
|
272 |
-
|
273 |
/**
|
274 |
* @since 4.1.4
|
275 |
* @param array $data The data that's going to be saved.
|
@@ -278,12 +272,15 @@ class User_Data extends Term_Data {
|
|
278 |
$data = (array) \apply_filters_ref_array(
|
279 |
'the_seo_framework_save_user_data',
|
280 |
[
|
281 |
-
$
|
|
|
|
|
|
|
282 |
$user->ID,
|
283 |
]
|
284 |
);
|
285 |
|
286 |
-
|
287 |
}
|
288 |
|
289 |
/**
|
@@ -291,23 +288,17 @@ class User_Data extends Term_Data {
|
|
291 |
* Memoizes the return value for the current request.
|
292 |
*
|
293 |
* @since 3.0.0
|
294 |
-
* @since 3.2.2
|
295 |
-
*
|
296 |
*
|
297 |
* @return int Post author ID on success, 0 on failure.
|
298 |
*/
|
299 |
public function get_current_post_author_id() {
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
if ( $this->is_singular() ) {
|
306 |
-
$post = \get_post( $this->get_the_real_ID() );
|
307 |
-
$cache = isset( $post->post_author ) ? (int) $post->post_author : 0;
|
308 |
-
}
|
309 |
-
|
310 |
-
return $cache ?: ( $cache = 0 );
|
311 |
}
|
312 |
|
313 |
/**
|
@@ -320,14 +311,12 @@ class User_Data extends Term_Data {
|
|
320 |
*/
|
321 |
public function get_user_id() {
|
322 |
|
323 |
-
|
324 |
-
|
325 |
-
if ( isset( $user_id ) )
|
326 |
-
return $user_id;
|
327 |
|
328 |
$user = \wp_get_current_user();
|
329 |
|
330 |
-
return
|
331 |
}
|
332 |
|
333 |
/**
|
55 |
* @return mixed The user meta item. Null when not found.
|
56 |
*/
|
57 |
public function get_user_meta_item( $item, $user_id = 0, $use_cache = true ) {
|
58 |
+
return $this->get_user_meta( $user_id ?: $this->get_user_id(), $use_cache )[ $item ] ?? null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
|
61 |
/**
|
76 |
* Memoizes the return value for the current request.
|
77 |
*
|
78 |
* @since 4.1.4
|
79 |
+
* @TODO Throw this away? We do not use it... never have.
|
80 |
*
|
81 |
* @return array The current author meta.
|
82 |
*/
|
83 |
public function get_current_post_author_meta() {
|
84 |
+
return memo() ?? memo( $this->get_user_meta( $this->get_current_post_author_id() ) );
|
|
|
85 |
}
|
86 |
|
87 |
/**
|
92 |
* @since 2.8.0 Always returns array, even if no value is assigned.
|
93 |
* @since 4.1.4 1. Now returns default values when custom values are missing.
|
94 |
* 2. Now listens to headlessness.
|
95 |
+
* 3. Deprecated the third argument, and moved it to the second.
|
96 |
+
* @todo Send deprecation warning for 3rd parameter
|
97 |
*
|
98 |
* @param int $user_id The user ID.
|
99 |
* @param bool $use_cache Whether to store and use options from cache, or bypass it.
|
106 |
|
107 |
$user_id = $user_id ?: $this->get_user_id();
|
108 |
|
109 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
110 |
+
if ( $use_cache && null !== $memo = memo( null, $user_id ) )
|
111 |
+
return $memo;
|
|
|
|
|
|
|
112 |
|
113 |
/**
|
114 |
* We can't trust the filter to always contain the expected keys.
|
156 |
]
|
157 |
);
|
158 |
|
159 |
+
// Do not overwrite cache when not requested. Otherwise, we'd have two "initial" states, causing incongruities.
|
160 |
+
return $use_cache ? memo( $meta, $user_id ) : $meta;
|
161 |
}
|
162 |
|
163 |
/**
|
202 |
* Saves user profile fields.
|
203 |
*
|
204 |
* @since 4.1.4
|
205 |
+
* @since 4.2.0 Now repopulates not-posted user metadata.
|
206 |
* @access private
|
207 |
*
|
208 |
* @param int $user_id The user ID.
|
211 |
|
212 |
if ( empty( $_POST ) ) return;
|
213 |
|
214 |
+
\check_admin_referer( "update-user_{$user_id}" );
|
215 |
if ( ! \current_user_can( 'edit_user', $user_id ) ) return;
|
216 |
|
217 |
$user = \get_userdata( $user_id );
|
218 |
|
219 |
if ( ! $user->has_cap( THE_SEO_FRAMEWORK_AUTHOR_INFO_CAP ) ) return;
|
220 |
|
221 |
+
$data = \wp_parse_args(
|
222 |
+
(array) $_POST['tsf-user-meta'],
|
223 |
+
$this->get_user_meta( $user_id )
|
224 |
+
);
|
225 |
|
226 |
$this->save_user_meta( $user_id, $data );
|
227 |
}
|
228 |
|
229 |
/**
|
230 |
+
* Updates user TSF-meta option.
|
231 |
*
|
232 |
* @since 4.1.4
|
233 |
*
|
252 |
* Updates users meta from input.
|
253 |
*
|
254 |
* @since 4.1.4
|
255 |
+
* @since 4.2.0 No longer returns the update success state.
|
256 |
*
|
257 |
* @param int $user_id The user ID.
|
258 |
* @param array $data The data to save.
|
259 |
*/
|
260 |
+
public function save_user_meta( $user_id, $data ) {
|
261 |
|
262 |
$user = \get_userdata( $user_id );
|
263 |
|
264 |
// We could test for !$user, but this is more to the point.
|
265 |
if ( empty( $user->ID ) ) return;
|
266 |
|
|
|
|
|
|
|
267 |
/**
|
268 |
* @since 4.1.4
|
269 |
* @param array $data The data that's going to be saved.
|
272 |
$data = (array) \apply_filters_ref_array(
|
273 |
'the_seo_framework_save_user_data',
|
274 |
[
|
275 |
+
$this->s_user_meta( (array) \wp_parse_args(
|
276 |
+
$data,
|
277 |
+
$this->get_user_meta_defaults( $user->ID )
|
278 |
+
) ),
|
279 |
$user->ID,
|
280 |
]
|
281 |
);
|
282 |
|
283 |
+
\update_user_meta( $user->ID, THE_SEO_FRAMEWORK_USER_OPTIONS, $data );
|
284 |
}
|
285 |
|
286 |
/**
|
288 |
* Memoizes the return value for the current request.
|
289 |
*
|
290 |
* @since 3.0.0
|
291 |
+
* @since 3.2.2 1. Now no longer returns the latest post author ID on home-as-blog pages.
|
292 |
+
* 2. Now always returns an integer.
|
293 |
*
|
294 |
* @return int Post author ID on success, 0 on failure.
|
295 |
*/
|
296 |
public function get_current_post_author_id() {
|
297 |
+
return memo() ?? memo(
|
298 |
+
$this->is_singular()
|
299 |
+
? (int) ( \get_post( $this->get_the_real_ID() )->post_author ?? 0 )
|
300 |
+
: 0
|
301 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
302 |
}
|
303 |
|
304 |
/**
|
311 |
*/
|
312 |
public function get_user_id() {
|
313 |
|
314 |
+
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- I know.
|
315 |
+
if ( null !== $memo = memo() ) return $memo;
|
|
|
|
|
316 |
|
317 |
$user = \wp_get_current_user();
|
318 |
|
319 |
+
return memo( $user->exists() ? (int) $user->ID : 0 );
|
320 |
}
|
321 |
|
322 |
/**
|
@@ -6,7 +6,7 @@
|
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \
|
10 |
|
11 |
/**
|
12 |
* Override wp_title's bbPress title with the one generated by The SEO Framework.
|
@@ -254,7 +254,7 @@ function _bbpress_filter_pre_title( $title = '', $args = null ) {
|
|
254 |
if ( null === $args && \is_bbpress() ) {
|
255 |
if ( \bbp_is_topic_tag() ) {
|
256 |
$term = \get_queried_object();
|
257 |
-
$title =
|
258 |
}
|
259 |
}
|
260 |
|
@@ -278,7 +278,7 @@ function _bbpress_filter_pre_title( $title = '', $args = null ) {
|
|
278 |
*
|
279 |
* @param string $excerpt The excerpt to use.
|
280 |
* @param int $page_id Deprecated.
|
281 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
282 |
* Is null when query is autodetermined.
|
283 |
* @return string The excerpt.
|
284 |
*/
|
@@ -290,7 +290,7 @@ function _bbpress_filter_excerpt_generation( $excerpt = '', $page_id = 0, $args
|
|
290 |
$description = $term->description ?: '';
|
291 |
|
292 |
// Always overwrite, even when none is found.
|
293 |
-
$excerpt = \
|
294 |
}
|
295 |
}
|
296 |
|
@@ -310,7 +310,7 @@ function _bbpress_filter_excerpt_generation( $excerpt = '', $page_id = 0, $args
|
|
310 |
* @access private
|
311 |
*
|
312 |
* @param string $desc The custom-field description.
|
313 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
314 |
* Is null when query is autodetermined.
|
315 |
* @return string The custom description.
|
316 |
*/
|
@@ -318,7 +318,7 @@ function _bbpress_filter_custom_field_description( $desc = '', $args = null ) {
|
|
318 |
|
319 |
if ( null === $args && \is_bbpress() ) {
|
320 |
if ( \bbp_is_topic_tag() ) {
|
321 |
-
$data = \
|
322 |
if ( ! empty( $data['description'] ) ) {
|
323 |
$desc = $data['description'];
|
324 |
} else {
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \tsf()->_verify_include_secret( $_secret ) or die;
|
10 |
|
11 |
/**
|
12 |
* Override wp_title's bbPress title with the one generated by The SEO Framework.
|
254 |
if ( null === $args && \is_bbpress() ) {
|
255 |
if ( \bbp_is_topic_tag() ) {
|
256 |
$term = \get_queried_object();
|
257 |
+
$title = $term->name ?? \tsf()->get_static_untitled_title();
|
258 |
}
|
259 |
}
|
260 |
|
278 |
*
|
279 |
* @param string $excerpt The excerpt to use.
|
280 |
* @param int $page_id Deprecated.
|
281 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
282 |
* Is null when query is autodetermined.
|
283 |
* @return string The excerpt.
|
284 |
*/
|
290 |
$description = $term->description ?: '';
|
291 |
|
292 |
// Always overwrite, even when none is found.
|
293 |
+
$excerpt = \tsf()->s_description_raw( $description );
|
294 |
}
|
295 |
}
|
296 |
|
310 |
* @access private
|
311 |
*
|
312 |
* @param string $desc The custom-field description.
|
313 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
314 |
* Is null when query is autodetermined.
|
315 |
* @return string The custom description.
|
316 |
*/
|
318 |
|
319 |
if ( null === $args && \is_bbpress() ) {
|
320 |
if ( \bbp_is_topic_tag() ) {
|
321 |
+
$data = \tsf()->get_term_meta( \get_queried_object_id() );
|
322 |
if ( ! empty( $data['description'] ) ) {
|
323 |
$desc = $data['description'];
|
324 |
} else {
|
@@ -6,7 +6,7 @@
|
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \
|
10 |
|
11 |
\add_filter( 'wp_head', __NAMESPACE__ . '\\_buddypress_init_compat', 0 );
|
12 |
/**
|
@@ -18,7 +18,7 @@ namespace The_SEO_Framework;
|
|
18 |
*/
|
19 |
function _buddypress_init_compat() {
|
20 |
if ( \is_buddypress() ) {
|
21 |
-
|
22 |
\add_filter( 'the_seo_framework_rel_canonical_output', '__return_empty_string' );
|
23 |
}
|
24 |
}
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \tsf()->_verify_include_secret( $_secret ) or die;
|
10 |
|
11 |
\add_filter( 'wp_head', __NAMESPACE__ . '\\_buddypress_init_compat', 0 );
|
12 |
/**
|
18 |
*/
|
19 |
function _buddypress_init_compat() {
|
20 |
if ( \is_buddypress() ) {
|
21 |
+
// Remove TSF canonical URL, and let BuddyPress handle it.
|
22 |
\add_filter( 'the_seo_framework_rel_canonical_output', '__return_empty_string' );
|
23 |
}
|
24 |
}
|
@@ -6,7 +6,7 @@
|
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \
|
10 |
|
11 |
\add_filter( 'the_seo_framework_is_product', __NAMESPACE__ . '\\_set_edd_is_product', 10, 2 );
|
12 |
/**
|
@@ -24,7 +24,7 @@ function _set_edd_is_product( $is_product, $post ) {
|
|
24 |
if ( ! $is_product ) {
|
25 |
if ( \function_exists( 'edd_get_download' ) ) {
|
26 |
$download = \edd_get_download(
|
27 |
-
$post ? \get_post( $post ) : \
|
28 |
);
|
29 |
|
30 |
$is_product = ! empty( $download->ID );
|
@@ -48,7 +48,7 @@ function _set_edd_is_product( $is_product, $post ) {
|
|
48 |
function _set_edd_is_product_admin( $is_product_admin ) {
|
49 |
|
50 |
if ( ! $is_product_admin ) {
|
51 |
-
$tsf = \
|
52 |
// Checks for "is_singular_admin()" because the post type is non-hierarchical.
|
53 |
$is_product_admin = $tsf->is_singular_admin() && 'download' === $tsf->get_admin_post_type();
|
54 |
}
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \tsf()->_verify_include_secret( $_secret ) or die;
|
10 |
|
11 |
\add_filter( 'the_seo_framework_is_product', __NAMESPACE__ . '\\_set_edd_is_product', 10, 2 );
|
12 |
/**
|
24 |
if ( ! $is_product ) {
|
25 |
if ( \function_exists( 'edd_get_download' ) ) {
|
26 |
$download = \edd_get_download(
|
27 |
+
$post ? \get_post( $post ) : \tsf()->get_the_real_ID()
|
28 |
);
|
29 |
|
30 |
$is_product = ! empty( $download->ID );
|
48 |
function _set_edd_is_product_admin( $is_product_admin ) {
|
49 |
|
50 |
if ( ! $is_product_admin ) {
|
51 |
+
$tsf = \tsf();
|
52 |
// Checks for "is_singular_admin()" because the post type is non-hierarchical.
|
53 |
$is_product_admin = $tsf->is_singular_admin() && 'download' === $tsf->get_admin_post_type();
|
54 |
}
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package The_SEO_Framework\Compat\Plugin\Elementor
|
4 |
+
* @subpackage The_SEO_Framework\Compatibility
|
5 |
+
*/
|
6 |
+
|
7 |
+
namespace The_SEO_Framework;
|
8 |
+
|
9 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \tsf()->_verify_include_secret( $_secret ) or die;
|
10 |
+
|
11 |
+
\add_filter( 'the_seo_framework_public_post_types', __NAMESPACE__ . '\\_elementor_fix_dumb_post_types' );
|
12 |
+
/**
|
13 |
+
* Does the job Elementor was sought to do by everyone back in 2016, by chiseling
|
14 |
+
* off their non-public post types purported as public.
|
15 |
+
*
|
16 |
+
* This solely affects The SEO Framework.
|
17 |
+
*
|
18 |
+
* @since 4.2.0
|
19 |
+
*
|
20 |
+
* @param string[] $post_types The list of should-be public post types.
|
21 |
+
* @return string[] The list of actual public post types.
|
22 |
+
*/
|
23 |
+
function _elementor_fix_dumb_post_types( $post_types ) {
|
24 |
+
return array_diff( $post_types, [ 'e-landing-page', 'elementor_library' ] );
|
25 |
+
}
|
@@ -6,7 +6,7 @@
|
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \
|
10 |
|
11 |
\add_filter( 'the_seo_framework_sitemap_base_path', __NAMESPACE__ . '\\_polylang_fix_sitemap_base_bath' );
|
12 |
/**
|
@@ -62,7 +62,7 @@ function _polylang_set_sitemap_language() {
|
|
62 |
if ( ! ( \PLL() instanceof \PLL_Frontend ) ) return;
|
63 |
|
64 |
// phpcs:ignore, WordPress.Security.NonceVerification.Recommended -- Arbitrary input expected.
|
65 |
-
$lang =
|
66 |
|
67 |
// Language codes are user-definable: copy Polylang's filtering.
|
68 |
// The preg_match's source: \PLL_Admin_Model::validate_lang();
|
@@ -88,13 +88,22 @@ function _polylang_set_sitemap_language() {
|
|
88 |
\PLL()->curlang = $new_lang;
|
89 |
}
|
90 |
|
91 |
-
\
|
92 |
-
\
|
93 |
/**
|
94 |
* Appends nontranslatable post types to the sitemap query arguments.
|
95 |
* Only appends when the default sitemap language is displayed.
|
96 |
*
|
|
|
|
|
|
|
|
|
97 |
* @since 4.1.2
|
|
|
|
|
|
|
|
|
|
|
98 |
* @access private
|
99 |
*
|
100 |
* @param array $args The query arguments.
|
@@ -102,7 +111,7 @@ function _polylang_set_sitemap_language() {
|
|
102 |
*/
|
103 |
function _polylang_sitemap_append_non_translatables( $args ) {
|
104 |
|
105 |
-
if ( ! \
|
106 |
'functions' => [
|
107 |
'PLL',
|
108 |
'pll_languages_list',
|
@@ -112,11 +121,12 @@ function _polylang_sitemap_append_non_translatables( $args ) {
|
|
112 |
|
113 |
if ( ! ( \PLL() instanceof \PLL_Frontend ) ) return $args;
|
114 |
|
|
|
115 |
$default_lang = \pll_default_language( \OBJECT );
|
116 |
|
117 |
-
if ( ! isset( $default_lang->slug, $default_lang->
|
118 |
|
119 |
-
if ( \PLL()->curlang->slug === $default_lang->slug ) {
|
120 |
$args['lang'] = ''; // Select all lang, so that Polylang doesn't affect the query below with an AND (we need OR).
|
121 |
$args['tax_query'] = [
|
122 |
'relation' => 'OR',
|
@@ -127,7 +137,7 @@ function _polylang_sitemap_append_non_translatables( $args ) {
|
|
127 |
],
|
128 |
[
|
129 |
'taxonomy' => 'language',
|
130 |
-
'terms' => $default_lang->
|
131 |
'operator' => 'IN',
|
132 |
],
|
133 |
];
|
@@ -143,6 +153,7 @@ function _polylang_sitemap_append_non_translatables( $args ) {
|
|
143 |
*/
|
144 |
\add_filter( 'the_seo_framework_warn_homepage_global_title', '__return_true' );
|
145 |
\add_filter( 'the_seo_framework_warn_homepage_global_description', '__return_true' );
|
|
|
146 |
|
147 |
\add_filter( 'the_seo_framework_title_from_custom_field', __NAMESPACE__ . '\\pll__' );
|
148 |
\add_filter( 'the_seo_framework_title_from_generation', __NAMESPACE__ . '\\pll__' );
|
@@ -158,11 +169,10 @@ function _polylang_sitemap_append_non_translatables( $args ) {
|
|
158 |
* @return string
|
159 |
*/
|
160 |
function pll__( $string ) {
|
161 |
-
if ( \function_exists( 'PLL' ) && \function_exists( '\\pll__' ) )
|
162 |
-
if ( \PLL() instanceof \PLL_Frontend )
|
163 |
return \pll__( $string );
|
164 |
-
|
165 |
-
}
|
166 |
return $string;
|
167 |
}
|
168 |
|
@@ -202,22 +212,22 @@ function _polylang_blocklist_tsf_urls( $blocklist ) {
|
|
202 |
return $blocklist;
|
203 |
}
|
204 |
|
205 |
-
\add_filter( 'the_seo_framework_rel_canonical_output', __NAMESPACE__ . '\\_polylang_fix_home_url', 10,
|
206 |
-
\add_filter( 'the_seo_framework_ogurl_output', __NAMESPACE__ . '\\_polylang_fix_home_url', 10,
|
207 |
/**
|
208 |
* Adds a trailing slash to whatever's deemed as the homepage URL.
|
209 |
* This fixes user_trailingslashit() issues.
|
210 |
*
|
211 |
* @since 3.2.4
|
212 |
* @since 4.1.2 Prefixed function name with _polylang.
|
|
|
213 |
* @access private
|
214 |
*
|
215 |
* @param string $url The url to fix.
|
216 |
-
* @param int $id The page or term ID.
|
217 |
* @return string The fixed home URL.
|
218 |
*/
|
219 |
-
function _polylang_fix_home_url( $url
|
220 |
-
return \
|
221 |
}
|
222 |
|
223 |
\add_action( 'the_seo_framework_delete_cache_sitemap', __NAMESPACE__ . '\\_polylang_flush_sitemap', 10, 4 );
|
@@ -230,7 +240,7 @@ function _polylang_fix_home_url( $url, $id ) {
|
|
230 |
* @access private
|
231 |
*
|
232 |
* @param string $type The flush type. Comes in handy when you use a catch-all function.
|
233 |
-
* @param int $id The post, page or TT ID. Defaults to
|
234 |
* @param array $args Additional arguments. They can overwrite $type and $id.
|
235 |
* @param bool $success Whether the action cleared.
|
236 |
*/
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \tsf()->_verify_include_secret( $_secret ) or die;
|
10 |
|
11 |
\add_filter( 'the_seo_framework_sitemap_base_path', __NAMESPACE__ . '\\_polylang_fix_sitemap_base_bath' );
|
12 |
/**
|
62 |
if ( ! ( \PLL() instanceof \PLL_Frontend ) ) return;
|
63 |
|
64 |
// phpcs:ignore, WordPress.Security.NonceVerification.Recommended -- Arbitrary input expected.
|
65 |
+
$lang = $_GET['lang'] ?? '';
|
66 |
|
67 |
// Language codes are user-definable: copy Polylang's filtering.
|
68 |
// The preg_match's source: \PLL_Admin_Model::validate_lang();
|
88 |
\PLL()->curlang = $new_lang;
|
89 |
}
|
90 |
|
91 |
+
\add_filter( 'the_seo_framework_sitemap_hpt_query_args', __NAMESPACE__ . '\\_polylang_sitemap_append_non_translatables' );
|
92 |
+
\add_filter( 'the_seo_framework_sitemap_nhpt_query_args', __NAMESPACE__ . '\\_polylang_sitemap_append_non_translatables' );
|
93 |
/**
|
94 |
* Appends nontranslatable post types to the sitemap query arguments.
|
95 |
* Only appends when the default sitemap language is displayed.
|
96 |
*
|
97 |
+
* TODO Should we fix this? If user unassigns a post type as translatable, previously "translated" posts are still
|
98 |
+
* found "translated" by this query. This query, however, is forwarded to WP_Query, which Polylang can filter.
|
99 |
+
* It wouldn't surprise me if they added another black/white list for that. So, my investigation stops here.
|
100 |
+
*
|
101 |
* @since 4.1.2
|
102 |
+
* @since 4.2.0 Now relies on the term_id, instead of mixing term_taxonomy_id and term_id.
|
103 |
+
* This is unlike Polylang, which relies on term_taxonomy_id somewhat consistently; however,
|
104 |
+
* in this case we can use term_id since we're specifying the taxonomy directly.
|
105 |
+
* WordPress 4.4.0 and later also rectifies term_id/term_taxonomy_id stratification, which is
|
106 |
+
* why we couldn't find an issue whilst introducing this filter.
|
107 |
* @access private
|
108 |
*
|
109 |
* @param array $args The query arguments.
|
111 |
*/
|
112 |
function _polylang_sitemap_append_non_translatables( $args ) {
|
113 |
|
114 |
+
if ( ! \tsf()->can_i_use( [
|
115 |
'functions' => [
|
116 |
'PLL',
|
117 |
'pll_languages_list',
|
121 |
|
122 |
if ( ! ( \PLL() instanceof \PLL_Frontend ) ) return $args;
|
123 |
|
124 |
+
// Redundantly prefixed \, OBJECT is actually a constant; however, the linter derps out, thinking it's a cast.
|
125 |
$default_lang = \pll_default_language( \OBJECT );
|
126 |
|
127 |
+
if ( ! isset( $default_lang->slug, $default_lang->term_id ) ) return $args;
|
128 |
|
129 |
+
if ( ( \PLL()->curlang->slug ?? null ) === $default_lang->slug ) {
|
130 |
$args['lang'] = ''; // Select all lang, so that Polylang doesn't affect the query below with an AND (we need OR).
|
131 |
$args['tax_query'] = [
|
132 |
'relation' => 'OR',
|
137 |
],
|
138 |
[
|
139 |
'taxonomy' => 'language',
|
140 |
+
'terms' => $default_lang->term_id,
|
141 |
'operator' => 'IN',
|
142 |
],
|
143 |
];
|
153 |
*/
|
154 |
\add_filter( 'the_seo_framework_warn_homepage_global_title', '__return_true' );
|
155 |
\add_filter( 'the_seo_framework_warn_homepage_global_description', '__return_true' );
|
156 |
+
\add_filter( 'the_seo_framework_tell_multilingual_sitemap', '__return_true' );
|
157 |
|
158 |
\add_filter( 'the_seo_framework_title_from_custom_field', __NAMESPACE__ . '\\pll__' );
|
159 |
\add_filter( 'the_seo_framework_title_from_generation', __NAMESPACE__ . '\\pll__' );
|
169 |
* @return string
|
170 |
*/
|
171 |
function pll__( $string ) {
|
172 |
+
if ( \function_exists( 'PLL' ) && \function_exists( '\\pll__' ) )
|
173 |
+
if ( \PLL() instanceof \PLL_Frontend )
|
174 |
return \pll__( $string );
|
175 |
+
|
|
|
176 |
return $string;
|
177 |
}
|
178 |
|
212 |
return $blocklist;
|
213 |
}
|
214 |
|
215 |
+
\add_filter( 'the_seo_framework_rel_canonical_output', __NAMESPACE__ . '\\_polylang_fix_home_url', 10, 1 );
|
216 |
+
\add_filter( 'the_seo_framework_ogurl_output', __NAMESPACE__ . '\\_polylang_fix_home_url', 10, 1 );
|
217 |
/**
|
218 |
* Adds a trailing slash to whatever's deemed as the homepage URL.
|
219 |
* This fixes user_trailingslashit() issues.
|
220 |
*
|
221 |
* @since 3.2.4
|
222 |
* @since 4.1.2 Prefixed function name with _polylang.
|
223 |
+
* @since 4.2.0 No longer uses the second parameter, and relies on theq query to find the homepage, instead.
|
224 |
* @access private
|
225 |
*
|
226 |
* @param string $url The url to fix.
|
|
|
227 |
* @return string The fixed home URL.
|
228 |
*/
|
229 |
+
function _polylang_fix_home_url( $url ) {
|
230 |
+
return \tsf()->is_real_front_page() && \get_option( 'permalink_structure' ) ? \trailingslashit( $url ) : $url;
|
231 |
}
|
232 |
|
233 |
\add_action( 'the_seo_framework_delete_cache_sitemap', __NAMESPACE__ . '\\_polylang_flush_sitemap', 10, 4 );
|
240 |
* @access private
|
241 |
*
|
242 |
* @param string $type The flush type. Comes in handy when you use a catch-all function.
|
243 |
+
* @param int $id The post, page or TT ID. Defaults to tsf()->get_the_real_ID().
|
244 |
* @param array $args Additional arguments. They can overwrite $type and $id.
|
245 |
* @param bool $success Whether the action cleared.
|
246 |
*/
|
@@ -6,122 +6,59 @@
|
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \
|
10 |
|
|
|
|
|
11 |
/**
|
12 |
-
*
|
13 |
-
* We're replacing it, using their API.
|
14 |
-
*/
|
15 |
-
\remove_action( 'wp_head', 'um_profile_dynamic_meta_desc', 9999999 );
|
16 |
-
|
17 |
-
\add_filter( 'the_seo_framework_title_from_generation', __NAMESPACE__ . '\\_um_filter_generated_title', 10, 2 );
|
18 |
-
/**
|
19 |
-
* Filters the custom title for UM.
|
20 |
*
|
21 |
-
* @since
|
22 |
-
* @since 4.0.0 No longer overrules external queries.
|
23 |
* @access private
|
24 |
-
*
|
25 |
-
* @param string $title The filter title.
|
26 |
-
* @param array|null $args The query arguments. Contains 'id' and 'taxonomy'.
|
27 |
-
* Is null when query is autodetermined.
|
28 |
-
* @return string The filtered title.
|
29 |
*/
|
30 |
-
function
|
31 |
|
32 |
-
if (
|
33 |
'functions' => [
|
34 |
'um_is_core_page',
|
35 |
'um_get_requested_user',
|
36 |
-
'um_fetch_user',
|
37 |
-
'um_reset_user',
|
38 |
-
'um_user',
|
39 |
-
'um_get_display_name',
|
40 |
],
|
41 |
-
] ) )
|
42 |
-
if ( \um_is_core_page( 'user' ) && \um_get_requested_user() ) {
|
43 |
-
\um_fetch_user( \um_get_requested_user() );
|
44 |
-
$user_id = \um_user( 'ID' );
|
45 |
-
\um_reset_user();
|
46 |
|
47 |
-
|
48 |
-
|
|
|
|
|
49 |
}
|
50 |
-
|
51 |
-
return $title;
|
52 |
}
|
53 |
|
54 |
-
\add_filter( '
|
55 |
-
\add_filter( 'the_seo_framework_rel_canonical_output', __NAMESPACE__ . '\\_um_filter_generated_url', 10, 1 );
|
56 |
/**
|
57 |
-
* Filters
|
58 |
*
|
59 |
-
* @since
|
60 |
* @access private
|
61 |
*
|
62 |
-
* @param
|
63 |
-
* @return string The filtered
|
64 |
*/
|
65 |
-
function
|
66 |
|
67 |
-
if
|
68 |
-
|
69 |
-
'um_is_core_page',
|
70 |
-
'um_get_requested_user',
|
71 |
-
'um_fetch_user',
|
72 |
-
'um_reset_user',
|
73 |
-
'um_user_profile_url',
|
74 |
-
],
|
75 |
-
] ) ) {
|
76 |
-
if ( \um_is_core_page( 'user' ) && \um_get_requested_user() ) {
|
77 |
-
\um_fetch_user( \um_get_requested_user() );
|
78 |
-
$url = \um_user_profile_url();
|
79 |
-
\um_reset_user();
|
80 |
-
}
|
81 |
-
}
|
82 |
|
83 |
-
|
84 |
-
}
|
85 |
-
|
86 |
-
\add_filter( 'the_seo_framework_generated_description', __NAMESPACE__ . '\\_um_filter_generated_description', 10, 2 );
|
87 |
-
/**
|
88 |
-
* Filters the generated description for UM.
|
89 |
-
*
|
90 |
-
* @since 3.1.0
|
91 |
-
* @since 4.0.0 No longer overrules external queries.
|
92 |
-
* @access private
|
93 |
-
*
|
94 |
-
* @param string $desc The generated description.
|
95 |
-
* @param array|null $args The query arguments. Contains 'id' and 'taxonomy'.
|
96 |
-
* Is null when query is autodetermined.
|
97 |
-
* @return string The filtered description.
|
98 |
-
*/
|
99 |
-
function _um_filter_generated_description( $desc = '', $args = null ) {
|
100 |
-
|
101 |
-
if ( null === $args && \the_seo_framework()->can_i_use( [
|
102 |
'functions' => [
|
|
|
103 |
'um_is_core_page',
|
104 |
-
'um_get_requested_user',
|
105 |
-
'um_fetch_user',
|
106 |
-
'um_reset_user',
|
107 |
-
'um_convert_tags',
|
108 |
-
'UM',
|
109 |
],
|
110 |
-
] ) )
|
111 |
-
if ( \um_is_core_page( 'user' ) && \um_get_requested_user() ) {
|
112 |
-
\um_fetch_user( \um_get_requested_user() );
|
113 |
-
|
114 |
-
//!! PHP 7 won't fail on the exception. On other versions, an is_callable() loop is too expensive.
|
115 |
-
//? However, their deprecated "um_get_option()" short API function tells us to use this.
|
116 |
-
try {
|
117 |
-
$_description = \um_convert_tags( \UM()->options()->get( 'profile_desc' ) );
|
118 |
-
} catch ( \Exception $e ) {
|
119 |
-
$_description = '';
|
120 |
-
}
|
121 |
-
$desc = $_description ?: $desc;
|
122 |
-
\um_reset_user();
|
123 |
-
}
|
124 |
-
}
|
125 |
|
126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
}
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \tsf()->_verify_include_secret( $_secret ) or die;
|
10 |
|
11 |
+
// At 9999 the user query should be registered (um\core\Rewrite::locate_user_profile). So, we use 9999+1 = 100000.
|
12 |
+
\add_action( 'template_redirect', __NAMESPACE__ . '\\_um_reinstate_title_support', 100000 );
|
13 |
/**
|
14 |
+
* Reinstates title support if a UM-controlled profile page is detected.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
*
|
16 |
+
* @since 4.2.0
|
|
|
17 |
* @access private
|
|
|
|
|
|
|
|
|
|
|
18 |
*/
|
19 |
+
function _um_reinstate_title_support() {
|
20 |
|
21 |
+
if ( ! \tsf()->can_i_use( [
|
22 |
'functions' => [
|
23 |
'um_is_core_page',
|
24 |
'um_get_requested_user',
|
|
|
|
|
|
|
|
|
25 |
],
|
26 |
+
] ) ) return;
|
|
|
|
|
|
|
|
|
27 |
|
28 |
+
if ( \um_is_core_page( 'user' ) && \um_get_requested_user() ) {
|
29 |
+
// This number has nothing to do with the reasoning hereinbefore -- merely to reflect their API.
|
30 |
+
\add_filter( 'wp_title', 'um_dynamic_user_profile_pagetitle', 100000, 2 );
|
31 |
+
\add_filter( 'pre_get_document_title', 'um_dynamic_user_profile_pagetitle', 100000, 2 );
|
32 |
}
|
|
|
|
|
33 |
}
|
34 |
|
35 |
+
\add_filter( 'the_seo_framework_query_supports_seo', __NAMESPACE__ . '\\_um_determine_support' );
|
|
|
36 |
/**
|
37 |
+
* Filters query support on UM pages.
|
38 |
*
|
39 |
+
* @since 4.2.0
|
40 |
* @access private
|
41 |
*
|
42 |
+
* @param bool $supported Whether the query supports SEO.
|
43 |
+
* @return string The filtered title.
|
44 |
*/
|
45 |
+
function _um_determine_support( $supported = true ) {
|
46 |
|
47 |
+
// No need to modify support if it's already not supported.
|
48 |
+
if ( ! $supported ) return $supported;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
|
50 |
+
if ( ! \tsf()->can_i_use( [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
'functions' => [
|
52 |
+
'um_queried_user',
|
53 |
'um_is_core_page',
|
|
|
|
|
|
|
|
|
|
|
54 |
],
|
55 |
+
] ) ) return $supported;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
|
57 |
+
/**
|
58 |
+
* We do not test for 'um_get_requested_user()' -- but this is safe.
|
59 |
+
* If `um_queried_user() && um_is_core_page( 'user' ) is true, UM forces um_get_requested_user()
|
60 |
+
* to return something, or otherwise redirects the visitor. This means we
|
61 |
+
* can safely hand over SEO-support to Ultimate Member.
|
62 |
+
*/
|
63 |
+
return ! ( \um_queried_user() && \um_is_core_page( 'user' ) );
|
64 |
}
|
@@ -6,7 +6,7 @@
|
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \
|
10 |
|
11 |
\add_action( 'woocommerce_init', __NAMESPACE__ . '\\_init_wc_compat' );
|
12 |
/**
|
@@ -24,7 +24,7 @@ namespace The_SEO_Framework;
|
|
24 |
function _init_wc_compat() {
|
25 |
\add_action(
|
26 |
'the_seo_framework_do_before_output',
|
27 |
-
function() {
|
28 |
/**
|
29 |
* Removes TSF breadcrumbs. WooCommerce outputs theirs.
|
30 |
*/
|
@@ -34,7 +34,7 @@ function _init_wc_compat() {
|
|
34 |
}
|
35 |
);
|
36 |
|
37 |
-
$tsf = \
|
38 |
|
39 |
// Adjust the product link acknowledging the primary category.
|
40 |
\add_filter( 'wc_product_post_type_link_product_cat', [ $tsf, '_adjust_post_link_category' ], 10, 3 );
|
@@ -51,6 +51,30 @@ function _init_wc_compat() {
|
|
51 |
\remove_filter( 'wp_robots', 'wc_page_no_robots' );
|
52 |
}
|
53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
\add_filter( 'the_seo_framework_real_id', __NAMESPACE__ . '\\_set_real_id_wc_shop' );
|
55 |
/**
|
56 |
* Sets the correct shop ID on the shop page.
|
@@ -63,7 +87,8 @@ function _init_wc_compat() {
|
|
63 |
*/
|
64 |
function _set_real_id_wc_shop( $id ) {
|
65 |
|
66 |
-
|
|
|
67 |
$id = (int) \get_option( 'woocommerce_shop_page_id' );
|
68 |
|
69 |
return $id;
|
@@ -81,7 +106,8 @@ function _set_real_id_wc_shop( $id ) {
|
|
81 |
* @return bool
|
82 |
*/
|
83 |
function _set_shop_singular_archive( $is_singular_archive, $id ) {
|
84 |
-
|
|
|
85 |
}
|
86 |
|
87 |
\add_filter( 'the_seo_framework_is_shop', __NAMESPACE__ . '\\_set_wc_is_shop', 10, 2 );
|
@@ -98,19 +124,8 @@ function _set_shop_singular_archive( $is_singular_archive, $id ) {
|
|
98 |
* @return bool
|
99 |
*/
|
100 |
function _set_wc_is_shop( $is_shop, $post ) {
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
if ( isset( $post ) ) {
|
105 |
-
$post = \get_post( $post );
|
106 |
-
$id = $post ? $post->ID : 0;
|
107 |
-
|
108 |
-
$is_shop = (int) \get_option( 'woocommerce_shop_page_id' ) === $id;
|
109 |
-
} else {
|
110 |
-
$is_shop = ! \is_admin() && \function_exists( 'is_shop' ) && \is_shop();
|
111 |
-
}
|
112 |
-
|
113 |
-
return $is_shop;
|
114 |
}
|
115 |
|
116 |
\add_filter( 'the_seo_framework_is_product', __NAMESPACE__ . '\\_set_wc_is_product', 10, 2 );
|
@@ -153,7 +168,7 @@ function _set_wc_is_product_admin( $is_product_admin ) {
|
|
153 |
|
154 |
if ( $is_product_admin ) return $is_product_admin;
|
155 |
|
156 |
-
$tsf = \
|
157 |
|
158 |
return $tsf->is_singular_admin() && 'product' === $tsf->get_admin_post_type();
|
159 |
}
|
@@ -173,9 +188,9 @@ function _set_wc_is_product_admin( $is_product_admin ) {
|
|
173 |
* string 'max_image_preview', ideally be empty or 'max-image-preview:<none|standard|large>'
|
174 |
* string 'max_video_preview', ideally be empty or 'max-video-preview:<R>=-1>'
|
175 |
* }
|
176 |
-
* @param array|null $args
|
177 |
-
*
|
178 |
-
* @param int <bit> $
|
179 |
* 0 = 0b00: Ignore nothing.
|
180 |
* 1 = 0b01: Ignore protection. (\The_SEO_Framework\ROBOTS_IGNORE_PROTECTION)
|
181 |
* 2 = 0b10: Ignore post/term setting. (\The_SEO_Framework\ROBOTS_IGNORE_SETTINGS)
|
@@ -183,12 +198,12 @@ function _set_wc_is_product_admin( $is_product_admin ) {
|
|
183 |
* }
|
184 |
* @return array
|
185 |
*/
|
186 |
-
function _set_wc_noindex_defaults( $meta, $args, $
|
187 |
|
188 |
// Nothing to do here...
|
189 |
if ( 'noindex' === $meta['noindex'] ) return $meta;
|
190 |
|
191 |
-
$tsf = \
|
192 |
|
193 |
if ( null === $args ) {
|
194 |
if ( \is_singular() )
|
@@ -213,7 +228,7 @@ function _set_wc_noindex_defaults( $meta, $args, $ignore ) {
|
|
213 |
if ( ! \in_array( $page_id, $page_ids, true ) ) return $meta;
|
214 |
|
215 |
// Set the default.
|
216 |
-
if ( $
|
217 |
$meta['noindex'] = 'noindex';
|
218 |
} elseif ( 0 === $tsf->s_qubit( $tsf->get_post_meta_item( '_genesis_noindex', $page_id ) ) ) {
|
219 |
$meta['noindex'] = 'noindex';
|
@@ -249,11 +264,11 @@ function _assert_wc_noindex_defaults_seo_bar( $interpreter ) {
|
|
249 |
|
250 |
$index_item = &$interpreter::edit_seo_bar_item( 'indexing' );
|
251 |
$index_item['status'] =
|
252 |
-
0 !== \
|
253 |
-
\The_SEO_Framework\Builders\
|
254 |
)
|
255 |
-
|
256 |
-
|
257 |
$index_item['assess']['recommends'] = \__( 'WooCommerce recommends not indexing this dynamic page.', 'autodescription' );
|
258 |
}
|
259 |
|
@@ -261,7 +276,8 @@ function _assert_wc_noindex_defaults_seo_bar( $interpreter ) {
|
|
261 |
/**
|
262 |
* Adjusts image generation parameters.
|
263 |
*
|
264 |
-
* @since 4.0.5 (introduced @ 4.0.0, renamed to prevent conflict)
|
|
|
265 |
* @access private
|
266 |
*
|
267 |
* @param array $params : [
|
@@ -270,7 +286,7 @@ function _assert_wc_noindex_defaults_seo_bar( $interpreter ) {
|
|
270 |
* array cbs: The callbacks to parse. Ideally be generators, so we can halt remotely.
|
271 |
* array fallback: The callbacks to parse. Ideally be generators, so we can halt remotely.
|
272 |
* ];
|
273 |
-
* @param array|null $args The query arguments. Contains 'id' and '
|
274 |
* Is null when query is autodetermined.
|
275 |
* @return array $params
|
276 |
*/
|
@@ -280,7 +296,7 @@ function _adjust_wc_image_generation_params( $params, $args ) {
|
|
280 |
$is_product_category = false;
|
281 |
|
282 |
if ( null === $args ) {
|
283 |
-
$is_product = \
|
284 |
$is_product_category = \function_exists( '\\is_product_category' ) && \is_product_category();
|
285 |
} else {
|
286 |
if ( $args['taxonomy'] ) {
|
@@ -288,8 +304,10 @@ function _adjust_wc_image_generation_params( $params, $args ) {
|
|
288 |
$term = \get_term( $args['id'], $args['taxonomy'] );
|
289 |
$is_product_category = $term && \is_product_category( $term );
|
290 |
}
|
|
|
|
|
291 |
} else {
|
292 |
-
$is_product = \
|
293 |
}
|
294 |
}
|
295 |
|
@@ -308,10 +326,11 @@ function _adjust_wc_image_generation_params( $params, $args ) {
|
|
308 |
* Generates image URLs and IDs from the WooCommerce product gallary entries.
|
309 |
*
|
310 |
* @since 4.0.0
|
|
|
311 |
* @access private
|
312 |
* @generator
|
313 |
*
|
314 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
315 |
* Leave null to autodetermine query.
|
316 |
* @param string $size The size of the image to get.
|
317 |
* @yield array : {
|
@@ -321,14 +340,19 @@ function _adjust_wc_image_generation_params( $params, $args ) {
|
|
321 |
*/
|
322 |
function _get_product_gallery_image_details( $args = null, $size = 'full' ) {
|
323 |
|
324 |
-
$post_id
|
325 |
-
|
326 |
$attachment_ids = [];
|
327 |
|
328 |
if ( $post_id && \metadata_exists( 'post', $post_id, '_product_image_gallery' ) ) {
|
329 |
-
$
|
330 |
-
|
331 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
}
|
333 |
|
334 |
if ( $attachment_ids ) {
|
@@ -353,7 +377,7 @@ function _get_product_gallery_image_details( $args = null, $size = 'full' ) {
|
|
353 |
* @access private
|
354 |
* @generator
|
355 |
*
|
356 |
-
* @param array|null $args The query arguments. Accepts 'id' and '
|
357 |
* Leave null to autodetermine query.
|
358 |
* @param string $size The size of the image to get.
|
359 |
* @yield array : {
|
@@ -363,8 +387,7 @@ function _get_product_gallery_image_details( $args = null, $size = 'full' ) {
|
|
363 |
*/
|
364 |
function _get_product_category_thumbnail_image_details( $args = null, $size = 'full' ) {
|
365 |
|
366 |
-
$term_id
|
367 |
-
|
368 |
$thumbnail_id = \get_term_meta( $term_id, 'thumbnail_id', true ) ?: 0;
|
369 |
|
370 |
if ( $thumbnail_id ) {
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \tsf()->_verify_include_secret( $_secret ) or die;
|
10 |
|
11 |
\add_action( 'woocommerce_init', __NAMESPACE__ . '\\_init_wc_compat' );
|
12 |
/**
|
24 |
function _init_wc_compat() {
|
25 |
\add_action(
|
26 |
'the_seo_framework_do_before_output',
|
27 |
+
static function() {
|
28 |
/**
|
29 |
* Removes TSF breadcrumbs. WooCommerce outputs theirs.
|
30 |
*/
|
34 |
}
|
35 |
);
|
36 |
|
37 |
+
$tsf = \tsf();
|
38 |
|
39 |
// Adjust the product link acknowledging the primary category.
|
40 |
\add_filter( 'wc_product_post_type_link_product_cat', [ $tsf, '_adjust_post_link_category' ], 10, 3 );
|
51 |
\remove_filter( 'wp_robots', 'wc_page_no_robots' );
|
52 |
}
|
53 |
|
54 |
+
/**
|
55 |
+
* Sets the correct shop ID on the shop page.
|
56 |
+
*
|
57 |
+
* @since 4.2.0
|
58 |
+
* @access private
|
59 |
+
*
|
60 |
+
* @param int|WP_Post|null $post Post ID or post object.
|
61 |
+
* @return bool
|
62 |
+
*/
|
63 |
+
function _is_shop( $post = null ) {
|
64 |
+
|
65 |
+
if ( isset( $post ) ) {
|
66 |
+
$id = \is_int( $post )
|
67 |
+
? $post
|
68 |
+
: ( \get_post( $post )->ID ?? 0 );
|
69 |
+
|
70 |
+
$is_shop = (int) \get_option( 'woocommerce_shop_page_id' ) === $id;
|
71 |
+
} else {
|
72 |
+
$is_shop = ! \is_admin() && \function_exists( 'is_shop' ) && \is_shop();
|
73 |
+
}
|
74 |
+
|
75 |
+
return $is_shop;
|
76 |
+
}
|
77 |
+
|
78 |
\add_filter( 'the_seo_framework_real_id', __NAMESPACE__ . '\\_set_real_id_wc_shop' );
|
79 |
/**
|
80 |
* Sets the correct shop ID on the shop page.
|
87 |
*/
|
88 |
function _set_real_id_wc_shop( $id ) {
|
89 |
|
90 |
+
// phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape -- local func
|
91 |
+
if ( _is_shop() )
|
92 |
$id = (int) \get_option( 'woocommerce_shop_page_id' );
|
93 |
|
94 |
return $id;
|
106 |
* @return bool
|
107 |
*/
|
108 |
function _set_shop_singular_archive( $is_singular_archive, $id ) {
|
109 |
+
// phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape -- local func
|
110 |
+
return $is_singular_archive || _is_shop( $id );
|
111 |
}
|
112 |
|
113 |
\add_filter( 'the_seo_framework_is_shop', __NAMESPACE__ . '\\_set_wc_is_shop', 10, 2 );
|
124 |
* @return bool
|
125 |
*/
|
126 |
function _set_wc_is_shop( $is_shop, $post ) {
|
127 |
+
// phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape -- local func
|
128 |
+
return $is_shop || _is_shop( $post );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
}
|
130 |
|
131 |
\add_filter( 'the_seo_framework_is_product', __NAMESPACE__ . '\\_set_wc_is_product', 10, 2 );
|
168 |
|
169 |
if ( $is_product_admin ) return $is_product_admin;
|
170 |
|
171 |
+
$tsf = \tsf();
|
172 |
|
173 |
return $tsf->is_singular_admin() && 'product' === $tsf->get_admin_post_type();
|
174 |
}
|
188 |
* string 'max_image_preview', ideally be empty or 'max-image-preview:<none|standard|large>'
|
189 |
* string 'max_video_preview', ideally be empty or 'max-video-preview:<R>=-1>'
|
190 |
* }
|
191 |
+
* @param array|null $args The query arguments. Contains 'id' and 'taxonomy'.
|
192 |
+
* Is null when query is autodetermined.
|
193 |
+
* @param int <bit> $options The generator settings. {
|
194 |
* 0 = 0b00: Ignore nothing.
|
195 |
* 1 = 0b01: Ignore protection. (\The_SEO_Framework\ROBOTS_IGNORE_PROTECTION)
|
196 |
* 2 = 0b10: Ignore post/term setting. (\The_SEO_Framework\ROBOTS_IGNORE_SETTINGS)
|
198 |
* }
|
199 |
* @return array
|
200 |
*/
|
201 |
+
function _set_wc_noindex_defaults( $meta, $args, $options ) {
|
202 |
|
203 |
// Nothing to do here...
|
204 |
if ( 'noindex' === $meta['noindex'] ) return $meta;
|
205 |
|
206 |
+
$tsf = \tsf();
|
207 |
|
208 |
if ( null === $args ) {
|
209 |
if ( \is_singular() )
|
228 |
if ( ! \in_array( $page_id, $page_ids, true ) ) return $meta;
|
229 |
|
230 |
// Set the default.
|
231 |
+
if ( $options & \The_SEO_Framework\ROBOTS_IGNORE_SETTINGS ) {
|
232 |
$meta['noindex'] = 'noindex';
|
233 |
} elseif ( 0 === $tsf->s_qubit( $tsf->get_post_meta_item( '_genesis_noindex', $page_id ) ) ) {
|
234 |
$meta['noindex'] = 'noindex';
|
264 |
|
265 |
$index_item = &$interpreter::edit_seo_bar_item( 'indexing' );
|
266 |
$index_item['status'] =
|
267 |
+
0 !== \tsf()->s_qubit(
|
268 |
+
\The_SEO_Framework\Builders\SEOBar\Page::get_instance()->get_query_cache()['meta']['_genesis_noindex']
|
269 |
)
|
270 |
+
? $interpreter::STATE_OKAY
|
271 |
+
: $interpreter::STATE_UNKNOWN;
|
272 |
$index_item['assess']['recommends'] = \__( 'WooCommerce recommends not indexing this dynamic page.', 'autodescription' );
|
273 |
}
|
274 |
|
276 |
/**
|
277 |
* Adjusts image generation parameters.
|
278 |
*
|
279 |
+
* @since 4.0.5 (introduced @ 4.0.0, renamed to prevent conflict).
|
280 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
281 |
* @access private
|
282 |
*
|
283 |
* @param array $params : [
|
286 |
* array cbs: The callbacks to parse. Ideally be generators, so we can halt remotely.
|
287 |
* array fallback: The callbacks to parse. Ideally be generators, so we can halt remotely.
|
288 |
* ];
|
289 |
+
* @param array|null $args The query arguments. Contains 'id', 'taxonomy', and 'pta'.
|
290 |
* Is null when query is autodetermined.
|
291 |
* @return array $params
|
292 |
*/
|
296 |
$is_product_category = false;
|
297 |
|
298 |
if ( null === $args ) {
|
299 |
+
$is_product = \tsf()->is_product();
|
300 |
$is_product_category = \function_exists( '\\is_product_category' ) && \is_product_category();
|
301 |
} else {
|
302 |
if ( $args['taxonomy'] ) {
|
304 |
$term = \get_term( $args['id'], $args['taxonomy'] );
|
305 |
$is_product_category = $term && \is_product_category( $term );
|
306 |
}
|
307 |
+
} elseif ( $args['pta'] ) { // phpcs:ignore, Generic.CodeAnalysis.EmptyStatement.DetectedElseif
|
308 |
+
// TODO ? Which public non-page-PTA does WC have, actually?
|
309 |
} else {
|
310 |
+
$is_product = \tsf()->is_product( $args['id'] );
|
311 |
}
|
312 |
}
|
313 |
|
326 |
* Generates image URLs and IDs from the WooCommerce product gallary entries.
|
327 |
*
|
328 |
* @since 4.0.0
|
329 |
+
* @since 4.2.0 Now supports the `$args['pta']` index.
|
330 |
* @access private
|
331 |
* @generator
|
332 |
*
|
333 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
334 |
* Leave null to autodetermine query.
|
335 |
* @param string $size The size of the image to get.
|
336 |
* @yield array : {
|
340 |
*/
|
341 |
function _get_product_gallery_image_details( $args = null, $size = 'full' ) {
|
342 |
|
343 |
+
$post_id = $args['id'] ?? \tsf()->get_the_real_ID();
|
|
|
344 |
$attachment_ids = [];
|
345 |
|
346 |
if ( $post_id && \metadata_exists( 'post', $post_id, '_product_image_gallery' ) ) {
|
347 |
+
$attachment_ids = array_map(
|
348 |
+
'absint',
|
349 |
+
array_filter(
|
350 |
+
explode(
|
351 |
+
',',
|
352 |
+
\get_post_meta( $post_id, '_product_image_gallery', true )
|
353 |
+
)
|
354 |
+
)
|
355 |
+
);
|
356 |
}
|
357 |
|
358 |
if ( $attachment_ids ) {
|
377 |
* @access private
|
378 |
* @generator
|
379 |
*
|
380 |
+
* @param array|null $args The query arguments. Accepts 'id', 'taxonomy', and 'pta'.
|
381 |
* Leave null to autodetermine query.
|
382 |
* @param string $size The size of the image to get.
|
383 |
* @yield array : {
|
387 |
*/
|
388 |
function _get_product_category_thumbnail_image_details( $args = null, $size = 'full' ) {
|
389 |
|
390 |
+
$term_id = $args['id'] ?? \tsf()->get_the_real_ID();
|
|
|
391 |
$thumbnail_id = \get_term_meta( $term_id, 'thumbnail_id', true ) ?: 0;
|
392 |
|
393 |
if ( $thumbnail_id ) {
|
@@ -6,15 +6,15 @@
|
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \
|
10 |
|
11 |
\add_action( 'the_seo_framework_init', __NAMESPACE__ . '\\_wpforo_fix_page' );
|
12 |
/**
|
13 |
* Initializes wpForo page fixes.
|
14 |
*
|
15 |
* @since 2.9.2
|
16 |
-
* @since 3.1.2
|
17 |
-
*
|
18 |
*/
|
19 |
function _wpforo_fix_page() {
|
20 |
|
@@ -56,7 +56,7 @@ function _wpforo_fix_page() {
|
|
56 |
* @access private
|
57 |
*/
|
58 |
function _wpforo_disable_html_output() {
|
59 |
-
\remove_action( 'wp_head', [ \
|
60 |
}
|
61 |
|
62 |
/**
|
@@ -91,7 +91,7 @@ function _wpforo_filter_canonical_url( $canonical_url, $post ) { // phpcs:ignore
|
|
91 |
function _wpforo_filter_pre_title( $title = '', $args = null ) {
|
92 |
|
93 |
if ( null === $args ) {
|
94 |
-
$wpforo_title = \wpforo_meta_title( '' );
|
95 |
$title = \is_array( $wpforo_title ) && ! empty( $wpforo_title[0] ) ? $wpforo_title[0] : $title;
|
96 |
}
|
97 |
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \tsf()->_verify_include_secret( $_secret ) or die;
|
10 |
|
11 |
\add_action( 'the_seo_framework_init', __NAMESPACE__ . '\\_wpforo_fix_page' );
|
12 |
/**
|
13 |
* Initializes wpForo page fixes.
|
14 |
*
|
15 |
* @since 2.9.2
|
16 |
+
* @since 3.1.2 1. Now disables HTML output when wpForo SEO is enabled.
|
17 |
+
* 2. Now disables title override when wpForo Title SEO is enabled.
|
18 |
*/
|
19 |
function _wpforo_fix_page() {
|
20 |
|
56 |
* @access private
|
57 |
*/
|
58 |
function _wpforo_disable_html_output() {
|
59 |
+
\remove_action( 'wp_head', [ \tsf(), 'html_output' ], 1 );
|
60 |
}
|
61 |
|
62 |
/**
|
91 |
function _wpforo_filter_pre_title( $title = '', $args = null ) {
|
92 |
|
93 |
if ( null === $args ) {
|
94 |
+
$wpforo_title = \wpforo_meta_title( '' ); // This is either &$title or [ $title, ... ];
|
95 |
$title = \is_array( $wpforo_title ) && ! empty( $wpforo_title[0] ) ? $wpforo_title[0] : $title;
|
96 |
}
|
97 |
|
@@ -6,7 +6,7 @@
|
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \
|
10 |
|
11 |
/**
|
12 |
* Warns homepage global title and description about receiving input.
|
@@ -15,6 +15,7 @@ namespace The_SEO_Framework;
|
|
15 |
*/
|
16 |
\add_filter( 'the_seo_framework_warn_homepage_global_title', '__return_true' );
|
17 |
\add_filter( 'the_seo_framework_warn_homepage_global_description', '__return_true' );
|
|
|
18 |
|
19 |
\add_action( 'current_screen', __NAMESPACE__ . '\\_wpml_do_current_screen_action' );
|
20 |
/**
|
@@ -25,7 +26,7 @@ namespace The_SEO_Framework;
|
|
25 |
*/
|
26 |
function _wpml_do_current_screen_action() {
|
27 |
|
28 |
-
if ( \
|
29 |
\add_filter( 'wpml_admin_language_switcher_items', __NAMESPACE__ . '\\_wpml_remove_all_languages' );
|
30 |
}
|
31 |
}
|
@@ -58,7 +59,7 @@ function _wpml_remove_all_languages( $languages_links = [] ) {
|
|
58 |
* @access private
|
59 |
*
|
60 |
* @param string $type The flush type. Comes in handy when you use a catch-all function.
|
61 |
-
* @param int $id The post, page or TT ID. Defaults to
|
62 |
* @param array $args Additional arguments. They can overwrite $type and $id.
|
63 |
* @param bool $success Whether the action cleared.
|
64 |
*/
|
@@ -122,7 +123,8 @@ function _wpml_sitemap_filter_non_translatables( $args ) {
|
|
122 |
if ( empty( $sitepress )
|
123 |
|| ! method_exists( $sitepress, 'get_default_language' )
|
124 |
|| ! method_exists( $sitepress, 'get_current_language' )
|
125 |
-
|| ! method_exists( $sitepress, 'is_translated_post_type' ) )
|
|
|
126 |
|
127 |
if ( $sitepress->get_default_language() === $sitepress->get_current_language() ) return $args;
|
128 |
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \tsf()->_verify_include_secret( $_secret ) or die;
|
10 |
|
11 |
/**
|
12 |
* Warns homepage global title and description about receiving input.
|
15 |
*/
|
16 |
\add_filter( 'the_seo_framework_warn_homepage_global_title', '__return_true' );
|
17 |
\add_filter( 'the_seo_framework_warn_homepage_global_description', '__return_true' );
|
18 |
+
\add_filter( 'the_seo_framework_tell_multilingual_sitemap', '__return_true' );
|
19 |
|
20 |
\add_action( 'current_screen', __NAMESPACE__ . '\\_wpml_do_current_screen_action' );
|
21 |
/**
|
26 |
*/
|
27 |
function _wpml_do_current_screen_action() {
|
28 |
|
29 |
+
if ( \tsf()->is_seo_settings_page() ) {
|
30 |
\add_filter( 'wpml_admin_language_switcher_items', __NAMESPACE__ . '\\_wpml_remove_all_languages' );
|
31 |
}
|
32 |
}
|
59 |
* @access private
|
60 |
*
|
61 |
* @param string $type The flush type. Comes in handy when you use a catch-all function.
|
62 |
+
* @param int $id The post, page or TT ID. Defaults to tsf()->get_the_real_ID().
|
63 |
* @param array $args Additional arguments. They can overwrite $type and $id.
|
64 |
* @param bool $success Whether the action cleared.
|
65 |
*/
|
123 |
if ( empty( $sitepress )
|
124 |
|| ! method_exists( $sitepress, 'get_default_language' )
|
125 |
|| ! method_exists( $sitepress, 'get_current_language' )
|
126 |
+
|| ! method_exists( $sitepress, 'is_translated_post_type' ) )
|
127 |
+
return $args;
|
128 |
|
129 |
if ( $sitepress->get_default_language() === $sitepress->get_current_language() ) return $args;
|
130 |
|
@@ -6,7 +6,7 @@
|
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
-
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \
|
10 |
|
11 |
// Disable Genesis SEO.
|
12 |
\add_filter( 'genesis_detect_seo_plugins', __NAMESPACE__ . '\\_disable_genesis_seo', 10, 1 );
|
6 |
|
7 |
namespace The_SEO_Framework;
|
8 |
|
9 |
+
\defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and \tsf()->_verify_include_secret( $_secret ) or die;
|
10 |
|
11 |
// Disable Genesis SEO.
|
12 |
\add_filter( 'genesis_detect_seo_plugins', __NAMESPACE__ . '\\_disable_genesis_seo', 10, 1 );
|
@@ -29,10 +29,27 @@ namespace {
|
|
29 |
* Returns the class from cache.
|
30 |
*
|
31 |
* This is the recommended way of calling the class, if needed.
|
32 |
-
* Call this after action '
|
33 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
*
|
35 |
* @since 2.2.5
|
|
|
36 |
*
|
37 |
* @return null|object The plugin class object.
|
38 |
*/
|
@@ -57,21 +74,17 @@ namespace {
|
|
57 |
*
|
58 |
* @since 2.7.0
|
59 |
* @since 2.8.0 Added `did_action()` check.
|
|
|
60 |
*
|
61 |
* @return string|bool The SEO Framework class name. False if The SEO Framework isn't loaded (yet).
|
62 |
*/
|
63 |
function the_seo_framework_class() {
|
64 |
|
65 |
-
|
66 |
-
|
67 |
-
if ( isset( $class ) )
|
68 |
-
return $class;
|
69 |
-
|
70 |
-
// did_action() checks for current action too.
|
71 |
if ( ! did_action( 'plugins_loaded' ) )
|
72 |
return false;
|
73 |
|
74 |
-
return
|
75 |
}
|
76 |
}
|
77 |
|
@@ -87,17 +100,12 @@ namespace The_SEO_Framework {
|
|
87 |
* @return bool Whether to allow loading of plugin.
|
88 |
*/
|
89 |
function _can_load() {
|
90 |
-
|
91 |
static $load = null;
|
92 |
-
|
93 |
-
if ( isset( $load ) )
|
94 |
-
return $load;
|
95 |
-
|
96 |
/**
|
97 |
* @since 2.3.7
|
98 |
* @param bool $load
|
99 |
*/
|
100 |
-
return $load = (bool) \apply_filters( 'the_seo_framework_load', true );
|
101 |
}
|
102 |
|
103 |
/**
|
@@ -111,15 +119,9 @@ namespace The_SEO_Framework {
|
|
111 |
* @return bool True if loaded, false otherwise.
|
112 |
*/
|
113 |
function _load_trait( $file ) {
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
if ( isset( $loaded[ $file ] ) )
|
118 |
-
return $loaded[ $file ];
|
119 |
-
|
120 |
-
$_file = str_replace( '/', DIRECTORY_SEPARATOR, $file );
|
121 |
-
|
122 |
-
return $loaded[ $file ] = (bool) require THE_SEO_FRAMEWORK_DIR_PATH_TRAIT . $_file . '.trait.php';
|
123 |
}
|
124 |
|
125 |
/**
|
@@ -132,10 +134,8 @@ namespace The_SEO_Framework {
|
|
132 |
* @return bool True if already called, false otherwise.
|
133 |
*/
|
134 |
function _has_run( $caller ) {
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
return isset( $cache[ $caller ] ) ?: ( ( $cache[ $caller ] = true ) && false );
|
139 |
}
|
140 |
|
141 |
/**
|
@@ -151,4 +151,185 @@ namespace The_SEO_Framework {
|
|
151 |
static $time = 0;
|
152 |
return $time += $add;
|
153 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
}
|
29 |
* Returns the class from cache.
|
30 |
*
|
31 |
* This is the recommended way of calling the class, if needed.
|
32 |
+
* Call this after action 'plugins_loaded' priority 5 otherwise you'll cause
|
33 |
+
* unforeseen issues.
|
34 |
+
*
|
35 |
+
* @since 4.2.0
|
36 |
+
* @see `the_seo_framework()` alias.
|
37 |
+
*
|
38 |
+
* @return null|object The plugin class object.
|
39 |
+
*/
|
40 |
+
function tsf() {
|
41 |
+
return The_SEO_Framework\_init_tsf();
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Returns the class from cache.
|
46 |
+
*
|
47 |
+
* This is the recommended way of calling the class, if needed.
|
48 |
+
* Call this after action 'plugins_loaded' priority 5 otherwise you'll cause
|
49 |
+
* unforeseen issues.
|
50 |
*
|
51 |
* @since 2.2.5
|
52 |
+
* @see `tsf()` alias.
|
53 |
*
|
54 |
* @return null|object The plugin class object.
|
55 |
*/
|
74 |
*
|
75 |
* @since 2.7.0
|
76 |
* @since 2.8.0 Added `did_action()` check.
|
77 |
+
* @since 4.2.0 Removed memoization.
|
78 |
*
|
79 |
* @return string|bool The SEO Framework class name. False if The SEO Framework isn't loaded (yet).
|
80 |
*/
|
81 |
function the_seo_framework_class() {
|
82 |
|
83 |
+
// did_action() returns true for current action match, too.
|
|
|
|
|
|
|
|
|
|
|
84 |
if ( ! did_action( 'plugins_loaded' ) )
|
85 |
return false;
|
86 |
|
87 |
+
return get_class( tsf() );
|
88 |
}
|
89 |
}
|
90 |
|
100 |
* @return bool Whether to allow loading of plugin.
|
101 |
*/
|
102 |
function _can_load() {
|
|
|
103 |
static $load = null;
|
|
|
|
|
|
|
|
|
104 |
/**
|
105 |
* @since 2.3.7
|
106 |
* @param bool $load
|
107 |
*/
|
108 |
+
return $load = $load ?? (bool) \apply_filters( 'the_seo_framework_load', true );
|
109 |
}
|
110 |
|
111 |
/**
|
119 |
* @return bool True if loaded, false otherwise.
|
120 |
*/
|
121 |
function _load_trait( $file ) {
|
122 |
+
static $loaded = [];
|
123 |
+
return $loaded[ $file ] = $loaded[ $file ]
|
124 |
+
?? (bool) require THE_SEO_FRAMEWORK_DIR_PATH_TRAIT . str_replace( '/', DIRECTORY_SEPARATOR, $file ) . '.trait.php';
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
}
|
126 |
|
127 |
/**
|
134 |
* @return bool True if already called, false otherwise.
|
135 |
*/
|
136 |
function _has_run( $caller ) {
|
137 |
+
static $runners = [];
|
138 |
+
return $runners[ $caller ] ?? ! ( $runners[ $caller ] = true );
|
|
|
|
|
139 |
}
|
140 |
|
141 |
/**
|
151 |
static $time = 0;
|
152 |
return $time += $add;
|
153 |
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Stores and returns memoized values for the caller.
|
157 |
+
*
|
158 |
+
* This method is not forward-compatible with PHP: It expects values it doesn't want populated,
|
159 |
+
* instead of filtering what's actually useful for memoization. For example, it expects `file`
|
160 |
+
* and `line` from debug_backtrace() -- those are expected to be dynamic from the caller, and
|
161 |
+
* we set them to `0` to prevent a few opcode calls, rather than telling which array indexes
|
162 |
+
* we want exactly. The chance this failing in a future update is slim, for all useful data of
|
163 |
+
* the callee is given already via debug_backtrace().
|
164 |
+
* We also populate the `args` value "manually" for it's faster than using debug_backtrace()'s
|
165 |
+
* `DEBUG_BACKTRACE_PROVIDE_OBJECT` option.
|
166 |
+
*
|
167 |
+
* We should keep a tap on debug_backtrace changes. Hopefully, they allow us to ignore
|
168 |
+
* more than just args.
|
169 |
+
*
|
170 |
+
* This method does not memoize the object via debug_backtrace. This means that the
|
171 |
+
* objects will have values memoized cross-instantiations.
|
172 |
+
*
|
173 |
+
* Example usage:
|
174 |
+
* ```
|
175 |
+
* function expensive_call( $arg ) {
|
176 |
+
* print( "expensive $arg!" );
|
177 |
+
* return $arg * 2;
|
178 |
+
* }
|
179 |
+
* function my_function( $arg ) {
|
180 |
+
* return memo( null, $arg );
|
181 |
+
* ?? memo( expensive_call( $arg ), $arg );
|
182 |
+
* }
|
183 |
+
* my_function( 1 ); // prints "expensive 1!", returns 2.
|
184 |
+
* my_function( 1 ); // returns 2.
|
185 |
+
* my_function( 2 ); // prints "expensive 2!", returns 4.
|
186 |
+
*
|
187 |
+
* function test() {
|
188 |
+
* return memo() ?? memo( expensive_call( 42 ) );
|
189 |
+
* }
|
190 |
+
* test(); // prints "expensive 42", returns 84.
|
191 |
+
* test(); // returns 84.
|
192 |
+
* ```
|
193 |
+
*
|
194 |
+
* @since 4.2.0
|
195 |
+
* @see umemo() -- sacrifices cleanliness for performance.
|
196 |
+
* @see fmemo() -- sacrifices everything for readability.
|
197 |
+
*
|
198 |
+
* @param mixed $value_to_set The value to set.
|
199 |
+
* @param mixed ...$args Extra arguments, that are used to differentiaty callbacks.
|
200 |
+
* Arguments may not contain \Closure()s.
|
201 |
+
* @return mixed : {
|
202 |
+
* mixed The cached value if set and $value_to_set is null.
|
203 |
+
* null When no value has been set.
|
204 |
+
* If $value_to_set is set, the new value.
|
205 |
+
* }
|
206 |
+
*/
|
207 |
+
function memo( $value_to_set = null, ...$args ) {
|
208 |
+
|
209 |
+
static $memo = [];
|
210 |
+
|
211 |
+
// phpcs:ignore, WordPress.PHP.DiscouragedPHPFunctions -- No objects inserted, nor ever unserialized.
|
212 |
+
$hash = serialize(
|
213 |
+
[
|
214 |
+
'args' => $args,
|
215 |
+
'file' => 0,
|
216 |
+
'line' => 0,
|
217 |
+
]
|
218 |
+
// phpcs:ignore, WordPress.PHP.DevelopmentFunctions -- This is the only efficient way.
|
219 |
+
+ debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 )[1]
|
220 |
+
);
|
221 |
+
|
222 |
+
if ( isset( $value_to_set ) )
|
223 |
+
return $memo[ $hash ] = $value_to_set;
|
224 |
+
|
225 |
+
return $memo[ $hash ] ?? null;
|
226 |
+
}
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Stores and returns memoized values for the caller.
|
230 |
+
* This is 10 times faster than memo(), but requires from you a $key.
|
231 |
+
*
|
232 |
+
* We're talking milliseconds over thousands of iterations, though.
|
233 |
+
*
|
234 |
+
* Example usage:
|
235 |
+
* ```
|
236 |
+
* function expensive_call( $arg ) {
|
237 |
+
* print( "expensive $arg!" );
|
238 |
+
* return $arg * 2;
|
239 |
+
* }
|
240 |
+
* function my_function( $arg ) {
|
241 |
+
* return umemo( 'something', null, $arg );
|
242 |
+
* ?? umemo( __METHOD__, expensive_call( $arg ), $arg );
|
243 |
+
* }
|
244 |
+
* my_function( 1 ); // prints "expensive 1!", returns 2.
|
245 |
+
* my_function( 1 ); // returns 2.
|
246 |
+
* my_function( 2 ); // prints "expensive 2!", returns 4.
|
247 |
+
* ```
|
248 |
+
*
|
249 |
+
* @since 4.2.0
|
250 |
+
* @see memo() -- sacrifices performance for cleanliness.
|
251 |
+
* @see fmemo() -- sacrifices everything for readability.
|
252 |
+
*
|
253 |
+
* @param string $key The key you want to use to memoize. It's best to use the method name.
|
254 |
+
* @param mixed $value_to_set The value to set.
|
255 |
+
* @param mixed ...$args Extra arguments, that are used to differentiate callbacks.
|
256 |
+
* Arguments may not contain \Closure()s.
|
257 |
+
* @return mixed : {
|
258 |
+
* mixed The cached value if set and $value_to_set is null.
|
259 |
+
* null When no value has been set.
|
260 |
+
* If $value_to_set is set, the new value.
|
261 |
+
* }
|
262 |
+
*/
|
263 |
+
function umemo( $key, $value_to_set = null, ...$args ) {
|
264 |
+
|
265 |
+
static $memo = [];
|
266 |
+
|
267 |
+
// phpcs:ignore, WordPress.PHP.DiscouragedPHPFunctions -- No objects are inserted, nor is this ever unserialized.
|
268 |
+
$hash = serialize( [ $key, $args ] );
|
269 |
+
|
270 |
+
if ( isset( $value_to_set ) )
|
271 |
+
return $memo[ $hash ] = $value_to_set;
|
272 |
+
|
273 |
+
return $memo[ $hash ] ?? null;
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Stores and returns memoized values for the Closure caller. This helps wrap
|
278 |
+
* a whole function inside a single memoization call.
|
279 |
+
*
|
280 |
+
* This method does not memoize the object via debug_backtrace. This means that the
|
281 |
+
* objects will have values memoized cross-instantiations.
|
282 |
+
*
|
283 |
+
* Example usage, PHP7.4+:
|
284 |
+
* ```
|
285 |
+
* function my_function( $arg ) { return fmemo( fn() => print( $arg ) + 5 ); }
|
286 |
+
* my_function( 1 ); // prints '1', returns 6.
|
287 |
+
* my_function( 1 ); // does not print, returns 6.
|
288 |
+
* ```
|
289 |
+
* Arrow functions are neat with this for they automatically register only necessary arguments to fmemo().
|
290 |
+
* This way, callers of my_function() won't bust the cache by sending unregistered superfluous arguments.
|
291 |
+
*
|
292 |
+
* ```
|
293 |
+
* function printer() { print( 69 ); }
|
294 |
+
* function print_once() { fmemo( 'printer' ); }
|
295 |
+
* print_once(); // 69
|
296 |
+
* print_once(); // *cricket noises*
|
297 |
+
* ```
|
298 |
+
*
|
299 |
+
* @since 4.2.0
|
300 |
+
* @see memo() -- sacrifices performance for cleanliness.
|
301 |
+
* @see umemo() -- sacrifices cleanliness for performance.
|
302 |
+
* @ignore We couldn't find a use for this... yet. Probably once we support only PHP7.4+
|
303 |
+
*
|
304 |
+
* @param \Closure $fn The Closure or function to memoize.
|
305 |
+
* @return mixed : {
|
306 |
+
* mixed The cached value if set and $value_to_set is null.
|
307 |
+
* null When no value has been set.
|
308 |
+
* If $value_to_set is set, the new value.
|
309 |
+
* }
|
310 |
+
*/
|
311 |
+
function fmemo( $fn ) {
|
312 |
+
|
313 |
+
static $memo = [];
|
314 |
+
|
315 |
+
// phpcs:ignore, WordPress.PHP.DiscouragedPHPFunctions -- This is ever unserialized.
|
316 |
+
$hash = serialize(
|
317 |
+
[
|
318 |
+
'file' => '',
|
319 |
+
'line' => 0,
|
320 |
+
]
|
321 |
+
// phpcs:ignore, WordPress.PHP.DevelopmentFunctions -- This is the only efficient way.
|
322 |
+
+ debug_backtrace( 0, 2 )[1]
|
323 |
+
);
|
324 |
+
|
325 |
+
// If the hash is stored, return null back to the caller.
|
326 |
+
if ( isset( $memo[ $hash ] ) )
|
327 |
+
return $memo[ $hash ] === $hash ? null : $memo[ $hash ];
|
328 |
+
|
329 |
+
// Store the result of the function. If that's null/void, store hash.
|
330 |
+
$memo[ $hash ] = \call_user_func( $fn ) ?? $hash;
|
331 |
+
|
332 |
+
// If the hash is stored, return null back to the caller.
|
333 |
+
return $memo[ $hash ] === $hash ? null : $memo[ $hash ];
|
334 |
+
}
|
335 |
}
|
@@ -45,7 +45,6 @@ _prepare( $previous_version, $current_version );
|
|
45 |
* 1. The constant 'TSF_DISABLE_SUGGESTIONS' is not defined or false.
|
46 |
* 2. The current dashboard is the main site's.
|
47 |
* 3. TSFEM isn't already installed.
|
48 |
-
* 4. PHP and WP requirements of TSFEM are met.
|
49 |
*
|
50 |
* The notice is automatically dismissed after X views, and it can be ignored without reappearing.
|
51 |
*
|
@@ -57,6 +56,7 @@ _prepare( $previous_version, $current_version );
|
|
57 |
* 5. Now tests if the upgrade actually happened, before invoking the suggestion.
|
58 |
* @since 4.1.2 Can now communicate with Extension Manager for the edge-case sale.
|
59 |
* @since 4.1.3 Commented out sale notification conditions, as those can't be met anyway.
|
|
|
60 |
* @access private
|
61 |
*
|
62 |
* @param string $previous_version The previous version the site upgraded from, if any.
|
@@ -72,17 +72,14 @@ function _prepare( $previous_version, $current_version ) {
|
|
72 |
//? 2
|
73 |
if ( ! \is_main_site() ) return;
|
74 |
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
// _suggest_temp_sale( $previous_version, $current_version );
|
84 |
-
// }
|
85 |
-
// phpcs:enable, Squiz.PHP.CommentedOutCode, Squiz.Commenting.InlineComment
|
86 |
|
87 |
//? 3a
|
88 |
if ( \defined( 'TSF_EXTENSION_MANAGER_VERSION' ) ) return;
|
@@ -93,23 +90,6 @@ function _prepare( $previous_version, $current_version ) {
|
|
93 |
//? 3b
|
94 |
if ( ! empty( \get_plugins()['the-seo-framework-extension-manager/the-seo-framework-extension-manager.php'] ) ) return;
|
95 |
|
96 |
-
/** @source https://github.com/sybrew/The-SEO-Framework-Extension-Manager/blob/08db1ab7410874c47d8f05b15479ce923857c35e/bootstrap/envtest.php#L68-L77 */
|
97 |
-
// We can forgo this test, since TSF has a higher requirement. We'll probably keep the plugins in line henceforth...
|
98 |
-
$requirements = [
|
99 |
-
'php' => 50605,
|
100 |
-
'wp' => '4.9-dev',
|
101 |
-
];
|
102 |
-
|
103 |
-
// phpcs:disable, Generic.Formatting.MultipleStatementAlignment, WordPress.WhiteSpace.PrecisionAlignment
|
104 |
-
//? PHP_VERSION_ID is definitely defined, but let's keep it homonymous with the envtest of TSFEM.
|
105 |
-
! \defined( 'PHP_VERSION_ID' ) || PHP_VERSION_ID < $requirements['php'] and $test = 1
|
106 |
-
or version_compare( $GLOBALS['wp_version'], $requirements['wp'], '<' ) and $test = 2
|
107 |
-
or $test = true;
|
108 |
-
// phpcs:enable, Generic.Formatting.MultipleStatementAlignment, WordPress.WhiteSpace.PrecisionAlignment
|
109 |
-
|
110 |
-
//? 4
|
111 |
-
if ( true !== $test ) return;
|
112 |
-
|
113 |
// phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
|
114 |
_suggest_extension_manager( $previous_version, $current_version );
|
115 |
}
|
@@ -126,7 +106,7 @@ function _prepare( $previous_version, $current_version ) {
|
|
126 |
*/
|
127 |
function _suggest_extension_manager( $previous_version, $current_version ) {
|
128 |
|
129 |
-
$tsf = \
|
130 |
|
131 |
$suggest_key = 'suggest-extension-manager';
|
132 |
$suggest_args = [
|
@@ -180,7 +160,7 @@ function _suggest_extension_manager( $previous_version, $current_version ) {
|
|
180 |
*/
|
181 |
function _suggest_temp_sale( $previous_version, $current_version ) {
|
182 |
|
183 |
-
$tsf = \
|
184 |
|
185 |
$suggest_key = 'suggest-sale';
|
186 |
$suggest_args = [
|
@@ -193,15 +173,15 @@ function _suggest_temp_sale( $previous_version, $current_version ) {
|
|
193 |
'excl_screens' => [ 'update-core', 'post', 'term', 'upload', 'media', 'plugin-editor', 'plugin-install', 'themes', 'widgets', 'user', 'nav-menus', 'theme-editor', 'profile', 'export', 'site-health', 'export-personal-data', 'erase-personal-data' ],
|
194 |
'capability' => 'install_plugins',
|
195 |
'user' => 0,
|
196 |
-
'count' =>
|
197 |
-
'timeout' => strtotime( 'December 6th,
|
198 |
];
|
199 |
|
200 |
-
if ( $previous_version < '
|
201 |
$tsf->register_dismissible_persistent_notice(
|
202 |
$tsf->convert_markdown(
|
203 |
sprintf(
|
204 |
-
'<p>The SEO Framework: Cyber
|
205 |
'https://theseoframework.com/?p=3527'
|
206 |
),
|
207 |
[ 'a', 'em', 'strong' ],
|
45 |
* 1. The constant 'TSF_DISABLE_SUGGESTIONS' is not defined or false.
|
46 |
* 2. The current dashboard is the main site's.
|
47 |
* 3. TSFEM isn't already installed.
|
|
|
48 |
*
|
49 |
* The notice is automatically dismissed after X views, and it can be ignored without reappearing.
|
50 |
*
|
56 |
* 5. Now tests if the upgrade actually happened, before invoking the suggestion.
|
57 |
* @since 4.1.2 Can now communicate with Extension Manager for the edge-case sale.
|
58 |
* @since 4.1.3 Commented out sale notification conditions, as those can't be met anyway.
|
59 |
+
* @since 4.2.1 No longer tests WP and PHP requirements for Extension Manager.
|
60 |
* @access private
|
61 |
*
|
62 |
* @param string $previous_version The previous version the site upgraded from, if any.
|
72 |
//? 2
|
73 |
if ( ! \is_main_site() ) return;
|
74 |
|
75 |
+
$show_sale = true;
|
76 |
+
if ( \function_exists( '\\tsf_extension_manager' ) && method_exists( \tsf_extension_manager(), 'is_connected_user' ) ) {
|
77 |
+
$show_sale = ! \tsf_extension_manager()->is_connected_user();
|
78 |
+
}
|
79 |
+
if ( $show_sale ) {
|
80 |
+
// phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
|
81 |
+
_suggest_temp_sale( $previous_version, $current_version );
|
82 |
+
}
|
|
|
|
|
|
|
83 |
|
84 |
//? 3a
|
85 |
if ( \defined( 'TSF_EXTENSION_MANAGER_VERSION' ) ) return;
|
90 |
//? 3b
|
91 |
if ( ! empty( \get_plugins()['the-seo-framework-extension-manager/the-seo-framework-extension-manager.php'] ) ) return;
|
92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
// phpcs:ignore, TSF.Performance.Opcodes.ShouldHaveNamespaceEscape
|
94 |
_suggest_extension_manager( $previous_version, $current_version );
|
95 |
}
|
106 |
*/
|
107 |
function _suggest_extension_manager( $previous_version, $current_version ) {
|
108 |
|
109 |
+
$tsf = \tsf();
|
110 |
|
111 |
$suggest_key = 'suggest-extension-manager';
|
112 |
$suggest_args = [
|
160 |
*/
|
161 |
function _suggest_temp_sale( $previous_version, $current_version ) {
|
162 |
|
163 |
+
$tsf = \tsf();
|
164 |
|
165 |
$suggest_key = 'suggest-sale';
|
166 |
$suggest_args = [
|
173 |
'excl_screens' => [ 'update-core', 'post', 'term', 'upload', 'media', 'plugin-editor', 'plugin-install', 'themes', 'widgets', 'user', 'nav-menus', 'theme-editor', 'profile', 'export', 'site-health', 'export-personal-data', 'erase-personal-data' ],
|
174 |
'capability' => 'install_plugins',
|
175 |
'user' => 0,
|
176 |
+
'count' => 3,
|
177 |
+
'timeout' => strtotime( 'December 6th, 2021, 22:50GMT+1' ) - time(),
|
178 |
];
|
179 |
|
180 |
+
if ( $previous_version < '4200' && $current_version < '4201' )
|
181 |
$tsf->register_dismissible_persistent_notice(
|
182 |
$tsf->convert_markdown(
|
183 |
sprintf(
|
184 |
+
'<p>The SEO Framework: [Cyber Sale – 60%% off](%s). This notification will self-destruct when the sale ends, or when you dismiss it.</p>',
|
185 |
'https://theseoframework.com/?p=3527'
|
186 |
),
|
187 |
[ 'a', 'em', 'strong' ],
|
@@ -1,60 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* @package The_SEO_Framework\Views\Admin
|
4 |
-
* @subpackage The_SEO_Framework\Admin\Settings
|
5 |
-
*/
|
6 |
-
|
7 |
-
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
-
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
-
|
10 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and the_seo_framework()->_verify_include_secret( $_secret ) or die;
|
11 |
-
|
12 |
-
// Whether tabs are active.
|
13 |
-
$use_tabs = $use_tabs && count( $tabs ) > 1;
|
14 |
-
$count = 1;
|
15 |
-
|
16 |
-
/**
|
17 |
-
* Start Content.
|
18 |
-
*
|
19 |
-
* The content is relative to the navigation and outputs navigational tabs too, but uses CSS to become invisible on JS.
|
20 |
-
*/
|
21 |
-
foreach ( $tabs as $tab => $value ) :
|
22 |
-
|
23 |
-
$the_id = 'tsf-' . $id . '-tab-' . $tab . '-content';
|
24 |
-
$the_name = 'tsf-' . $id . '-tabs-content';
|
25 |
-
|
26 |
-
// Current tab for JS.
|
27 |
-
$current = 1 === $count ? ' tsf-active-tab-content' : '';
|
28 |
-
|
29 |
-
?>
|
30 |
-
<div class="tsf-tabs-content <?php echo esc_attr( $the_name . $current ); ?>" id="<?php echo esc_attr( $the_id ); ?>" >
|
31 |
-
<?php
|
32 |
-
// No-JS tabs.
|
33 |
-
if ( $use_tabs ) :
|
34 |
-
$dashicon = isset( $value['dashicon'] ) ? $value['dashicon'] : '';
|
35 |
-
$name = isset( $value['name'] ) ? $value['name'] : '';
|
36 |
-
|
37 |
-
?>
|
38 |
-
<div class="hide-if-tsf-js tsf-content-no-js">
|
39 |
-
<div class="tsf-tab tsf-tab-no-js">
|
40 |
-
<span class="tsf-nav-tab tsf-active-tab">
|
41 |
-
<?php echo $dashicon ? '<span class="dashicons dashicons-' . esc_attr( $dashicon ) . ' tsf-dashicons-tabs"></span>' : ''; ?>
|
42 |
-
<?php echo $name ? '<span>' . esc_attr( $name ) . '</span>' : ''; ?>
|
43 |
-
</span>
|
44 |
-
</div>
|
45 |
-
</div>
|
46 |
-
<?php
|
47 |
-
endif;
|
48 |
-
|
49 |
-
$callback = isset( $value['callback'] ) ? $value['callback'] : '';
|
50 |
-
|
51 |
-
if ( $callback ) {
|
52 |
-
$params = isset( $value['args'] ) ? [ $value['args'] ] : [];
|
53 |
-
call_user_func_array( $callback, $params );
|
54 |
-
}
|
55 |
-
?>
|
56 |
-
</div>
|
57 |
-
<?php
|
58 |
-
|
59 |
-
$count++;
|
60 |
-
endforeach;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -7,27 +7,32 @@
|
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
-
|
11 |
|
12 |
-
|
13 |
-
|
14 |
-
$
|
|
|
|
|
|
|
15 |
|
16 |
// This will return 'Page' on all non-archive types (except the homepage)
|
17 |
-
if (
|
18 |
$type = 'Front Page';
|
19 |
} elseif ( $taxonomy ) {
|
20 |
$type = $this->get_tax_type_label( $taxonomy );
|
|
|
|
|
21 |
} else {
|
22 |
-
$type =
|
23 |
}
|
24 |
|
25 |
$cache_key = $this->generate_cache_key( $id, $taxonomy );
|
26 |
|
27 |
if ( is_admin() ) {
|
28 |
$bstyle = is_rtl()
|
29 |
-
|
30 |
-
|
31 |
?>
|
32 |
<div style="<?php echo $bstyle; // phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped ?>">
|
33 |
<h3 style="font-size:14px;padding:0 12px;margin:0;line-height:39px;border-bottom:2px solid #aaa;position:absolute;z-index:9002;width:100%;right:0;left:0;top:0;background:#fff;border-radius:3px 3px 0 0;height:39px;">
|
@@ -35,7 +40,7 @@ if ( is_admin() ) {
|
|
35 |
<?php
|
36 |
if ( $this->is_post_edit() || $this->is_term_edit() ) :
|
37 |
echo ' :: ';
|
38 |
-
echo esc_html(
|
39 |
echo esc_html( $mdash . 'ID: ' . $id );
|
40 |
echo esc_html( $mdash . 'Cache key: ' . ( $cache_key ?: 'N/A' ) );
|
41 |
echo esc_html( $mdash . 'Plugin version: ' . THE_SEO_FRAMEWORK_VERSION );
|
@@ -45,8 +50,8 @@ if ( is_admin() ) {
|
|
45 |
</h3>
|
46 |
<div style="position:absolute;bottom:0;right:0;left:0;top:39px;margin:0;padding:0;background:#fff;border-radius:3px;overflow-x:hidden;z-index:9001">
|
47 |
<?php
|
48 |
-
|
49 |
-
|
50 |
?>
|
51 |
</div>
|
52 |
</div>
|
@@ -68,15 +73,15 @@ if ( is_admin() ) {
|
|
68 |
</h3>
|
69 |
<div style="position:absolute;bottom:0;right:0;left:0;top:39px;margin:0;padding:0;background:#fff;border-radius:3px;overflow-x:hidden;z-index:9001">
|
70 |
<?php
|
71 |
-
|
72 |
?>
|
73 |
<div style="width:50%;float:left;">
|
74 |
<?php
|
75 |
-
|
76 |
?>
|
77 |
</div><div style="width:50%;float:right;">
|
78 |
<?php
|
79 |
-
|
80 |
?>
|
81 |
</div>
|
82 |
</div>
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
+
use The_SEO_Framework\Internal\Debug;
|
11 |
|
12 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
13 |
+
|
14 |
+
$id = $this->get_the_real_ID();
|
15 |
+
$mdash = ' — ';
|
16 |
+
$taxonomy = $this->get_current_taxonomy();
|
17 |
+
$post_type = $this->get_current_post_type();
|
18 |
|
19 |
// This will return 'Page' on all non-archive types (except the homepage)
|
20 |
+
if ( $this->is_real_front_page() ) {
|
21 |
$type = 'Front Page';
|
22 |
} elseif ( $taxonomy ) {
|
23 |
$type = $this->get_tax_type_label( $taxonomy );
|
24 |
+
} elseif ( $post_type ) {
|
25 |
+
$type = $this->get_post_type_label( $post_type );
|
26 |
} else {
|
27 |
+
$type = 'Unknown';
|
28 |
}
|
29 |
|
30 |
$cache_key = $this->generate_cache_key( $id, $taxonomy );
|
31 |
|
32 |
if ( is_admin() ) {
|
33 |
$bstyle = is_rtl()
|
34 |
+
? 'direction:ltr;color:#444;font-family:Georgio,sans-serif;font-size:14px;clear:both;float:left;position:relative;width:calc( 100% - 200px );min-height:700px;padding:0;margin:20px 180px 40px 20px;overflow:hidden;border:1px solid #ccc;border-radius:3px;line-height:18pxfont-feature-settings:normal;font-variant:normal'
|
35 |
+
: 'direction:ltr;color:#444;font-family:Georgio,sans-serif;font-size:14px;clear:both;float:left;position:relative;width:calc( 100% - 200px );min-height:700px;padding:0;margin:20px 20px 40px 180px;overflow:hidden;border:1px solid #ccc;border-radius:3px;line-height:18pxfont-feature-settings:normal;font-variant:normal';
|
36 |
?>
|
37 |
<div style="<?php echo $bstyle; // phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped ?>">
|
38 |
<h3 style="font-size:14px;padding:0 12px;margin:0;line-height:39px;border-bottom:2px solid #aaa;position:absolute;z-index:9002;width:100%;right:0;left:0;top:0;background:#fff;border-radius:3px 3px 0 0;height:39px;">
|
40 |
<?php
|
41 |
if ( $this->is_post_edit() || $this->is_term_edit() ) :
|
42 |
echo ' :: ';
|
43 |
+
echo esc_html( "Type: $type" );
|
44 |
echo esc_html( $mdash . 'ID: ' . $id );
|
45 |
echo esc_html( $mdash . 'Cache key: ' . ( $cache_key ?: 'N/A' ) );
|
46 |
echo esc_html( $mdash . 'Plugin version: ' . THE_SEO_FRAMEWORK_VERSION );
|
50 |
</h3>
|
51 |
<div style="position:absolute;bottom:0;right:0;left:0;top:39px;margin:0;padding:0;background:#fff;border-radius:3px;overflow-x:hidden;z-index:9001">
|
52 |
<?php
|
53 |
+
Debug::_output_debug_header();
|
54 |
+
Debug::_output_debug_query();
|
55 |
?>
|
56 |
</div>
|
57 |
</div>
|
73 |
</h3>
|
74 |
<div style="position:absolute;bottom:0;right:0;left:0;top:39px;margin:0;padding:0;background:#fff;border-radius:3px;overflow-x:hidden;z-index:9001">
|
75 |
<?php
|
76 |
+
Debug::_output_debug_header();
|
77 |
?>
|
78 |
<div style="width:50%;float:left;">
|
79 |
<?php
|
80 |
+
Debug::_output_debug_query_from_cache();
|
81 |
?>
|
82 |
</div><div style="width:50%;float:right;">
|
83 |
<?php
|
84 |
+
Debug::_output_debug_query();
|
85 |
?>
|
86 |
</div>
|
87 |
</div>
|
@@ -7,7 +7,7 @@
|
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
11 |
|
12 |
printf(
|
13 |
'<div id=%s data-post-id=%d class=hidden></div>',
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
11 |
|
12 |
printf(
|
13 |
'<div id=%s data-post-id=%d class=hidden></div>',
|
@@ -11,35 +11,33 @@ use The_SEO_Framework\Bridges\PostSettings,
|
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
The_SEO_Framework\Interpreters\Form;
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
-
|
16 |
-
// Fetch the required instance within this file.
|
17 |
-
$instance = $this->get_view_instance( 'inpost', $instance );
|
18 |
|
19 |
// Setup default vars.
|
20 |
$post_id = $this->get_the_real_ID(); // We also have access to object $post at the main call...
|
21 |
|
22 |
-
$_generator_args = [
|
23 |
-
|
24 |
-
|
25 |
-
];
|
26 |
|
27 |
-
switch ( $instance ) :
|
28 |
case 'inpost_main':
|
|
|
|
|
29 |
$default_tabs = [
|
30 |
'general' => [
|
31 |
'name' => __( 'General', 'autodescription' ),
|
32 |
-
'callback' =>
|
33 |
'dashicon' => 'admin-generic',
|
34 |
],
|
35 |
'social' => [
|
36 |
'name' => __( 'Social', 'autodescription' ),
|
37 |
-
'callback' =>
|
38 |
'dashicon' => 'share',
|
39 |
],
|
40 |
'visibility' => [
|
41 |
'name' => __( 'Visibility', 'autodescription' ),
|
42 |
-
'callback' =>
|
43 |
'dashicon' => 'visibility',
|
44 |
],
|
45 |
];
|
@@ -60,7 +58,7 @@ switch ( $instance ) :
|
|
60 |
echo '</div>';
|
61 |
break;
|
62 |
|
63 |
-
case '
|
64 |
if ( $this->get_option( 'display_seo_bar_metabox' ) ) :
|
65 |
?>
|
66 |
<div class="tsf-flex-setting tsf-flex" id="tsf-doing-it-right-wrap">
|
@@ -84,25 +82,23 @@ switch ( $instance ) :
|
|
84 |
<?php
|
85 |
endif;
|
86 |
|
87 |
-
if ( $
|
88 |
$_has_home_title = (bool) $this->escape_title( $this->get_option( 'homepage_title' ) );
|
89 |
$_has_home_desc = (bool) $this->escape_title( $this->get_option( 'homepage_description' ) );
|
90 |
|
91 |
-
// phpcs:disable, WordPress.WhiteSpace.PrecisionAlignment
|
92 |
// When the homepage title is set, we can safely get the custom field.
|
93 |
$default_title = $_has_home_title
|
94 |
-
|
95 |
-
|
96 |
$title_ref_locked = $_has_home_title;
|
97 |
$title_additions = $this->get_home_title_additions();
|
98 |
$title_seplocation = $this->get_home_title_seplocation();
|
99 |
|
100 |
// When the homepage description is set, we can safely get the custom field.
|
101 |
$default_description = $_has_home_desc
|
102 |
-
|
103 |
-
|
104 |
$description_ref_locked = $_has_home_desc;
|
105 |
-
// phpcs:enable, WordPress.WhiteSpace.PrecisionAlignment
|
106 |
} else {
|
107 |
$default_title = $this->get_filtered_raw_generated_title( $_generator_args );
|
108 |
$title_ref_locked = false;
|
@@ -138,7 +134,7 @@ switch ( $instance ) :
|
|
138 |
</div>
|
139 |
<div class="tsf-flex-setting-input tsf-flex">
|
140 |
<div class=tsf-title-wrap>
|
141 |
-
<input class="large-text" type="text" name="autodescription[_genesis_title]" id="autodescription_title" value="<?php echo $this->esc_attr_preserve_amp( $this->get_post_meta_item( '_genesis_title'
|
142 |
<?php
|
143 |
$this->output_js_title_elements(); // legacy
|
144 |
$this->output_js_title_data(
|
@@ -146,10 +142,10 @@ switch ( $instance ) :
|
|
146 |
[
|
147 |
'state' => [
|
148 |
'refTitleLocked' => $title_ref_locked,
|
149 |
-
'defaultTitle' => $default_title,
|
150 |
'addAdditions' => $this->use_title_branding( $_generator_args ),
|
151 |
'useSocialTagline' => $this->use_title_branding( $_generator_args, true ),
|
152 |
-
'additionValue' => $this->
|
153 |
'additionPlacement' => 'left' === $title_seplocation ? 'before' : 'after',
|
154 |
'hasLegacy' => true,
|
155 |
],
|
@@ -161,7 +157,7 @@ switch ( $instance ) :
|
|
161 |
<div class="tsf-checkbox-wrapper">
|
162 |
<label for="autodescription_title_no_blogname">
|
163 |
<?php
|
164 |
-
if ( $
|
165 |
// Disable the input, and hide the previously stored value.
|
166 |
?>
|
167 |
<input type="checkbox" id="autodescription_title_no_blogname" value="1" <?php checked( $this->get_post_meta_item( '_tsf_title_no_blogname' ) ); ?> disabled />
|
@@ -207,14 +203,14 @@ switch ( $instance ) :
|
|
207 |
</div>
|
208 |
</div>
|
209 |
<div class="tsf-flex-setting-input tsf-flex">
|
210 |
-
<textarea class="large-text" name="autodescription[_genesis_description]" id="autodescription_description" rows="4" cols="4" autocomplete=off><?php echo $this->esc_attr_preserve_amp( $this->get_post_meta_item( '_genesis_description'
|
211 |
<?php
|
212 |
$this->output_js_description_elements(); // legacy
|
213 |
$this->output_js_description_data(
|
214 |
'autodescription_description',
|
215 |
[
|
216 |
'state' => [
|
217 |
-
'defaultDescription' => $default_description,
|
218 |
'refDescriptionLocked' => $description_ref_locked,
|
219 |
'hasLegacy' => true,
|
220 |
],
|
@@ -226,14 +222,14 @@ switch ( $instance ) :
|
|
226 |
<?php
|
227 |
break;
|
228 |
|
229 |
-
case '
|
230 |
$canonical = $this->get_post_meta_item( '_genesis_canonical_uri' );
|
231 |
$canonical_placeholder = $this->create_canonical_url( $_generator_args );
|
232 |
|
233 |
// Get robots defaults.
|
234 |
$r_defaults = $this->generate_robots_meta(
|
235 |
$_generator_args,
|
236 |
-
|
237 |
The_SEO_Framework\ROBOTS_IGNORE_SETTINGS | The_SEO_Framework\ROBOTS_IGNORE_PROTECTION
|
238 |
);
|
239 |
$r_settings = [
|
@@ -300,7 +296,7 @@ switch ( $instance ) :
|
|
300 |
</div>
|
301 |
</div>
|
302 |
<?php
|
303 |
-
if ( $
|
304 |
printf(
|
305 |
'<div class=tsf-flex-setting-label-sub-item><span class="description attention">%s</span></div>',
|
306 |
esc_html__( 'Warning: No public site should ever apply "noindex" or "nofollow" to the homepage.', 'autodescription' )
|
@@ -418,23 +414,71 @@ switch ( $instance ) :
|
|
418 |
<?php
|
419 |
break;
|
420 |
|
421 |
-
case '
|
422 |
-
$social_placeholders = $this->_get_social_placeholders( $_generator_args );
|
423 |
-
|
424 |
// Yes, this is hacky, but we don't want to lose the user's input.
|
425 |
$show_og = (bool) $this->get_option( 'og_tags' );
|
426 |
$show_tw = (bool) $this->get_option( 'twitter_tags' );
|
427 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
428 |
?>
|
429 |
<div class="tsf-flex-setting tsf-flex" <?php echo $show_og ? '' : 'style=display:none'; ?>>
|
430 |
<div class="tsf-flex-setting-label tsf-flex">
|
431 |
<div class="tsf-flex-setting-label-inner-wrap tsf-flex">
|
432 |
<label for="autodescription_og_title" class="tsf-flex-setting-label-item tsf-flex">
|
433 |
-
<div><strong>
|
434 |
-
<?php
|
435 |
-
esc_html_e( 'Open Graph Title', 'autodescription' );
|
436 |
-
?>
|
437 |
-
</strong></div>
|
438 |
</label>
|
439 |
<?php
|
440 |
$this->get_option( 'display_character_counter' )
|
@@ -444,7 +488,7 @@ switch ( $instance ) :
|
|
444 |
</div>
|
445 |
<div class="tsf-flex-setting-input tsf-flex">
|
446 |
<div id="tsf-og-title-wrap">
|
447 |
-
<input class="large-text" type="text" name="autodescription[_open_graph_title]" id="autodescription_og_title"
|
448 |
</div>
|
449 |
</div>
|
450 |
</div>
|
@@ -453,11 +497,7 @@ switch ( $instance ) :
|
|
453 |
<div class="tsf-flex-setting-label tsf-flex">
|
454 |
<div class="tsf-flex-setting-label-inner-wrap tsf-flex">
|
455 |
<label for="autodescription_og_description" class="tsf-flex-setting-label-item tsf-flex">
|
456 |
-
<div><strong>
|
457 |
-
<?php
|
458 |
-
esc_html_e( 'Open Graph Description', 'autodescription' );
|
459 |
-
?>
|
460 |
-
</strong></div>
|
461 |
</label>
|
462 |
<?php
|
463 |
$this->get_option( 'display_character_counter' )
|
@@ -466,7 +506,7 @@ switch ( $instance ) :
|
|
466 |
</div>
|
467 |
</div>
|
468 |
<div class="tsf-flex-setting-input tsf-flex">
|
469 |
-
<textarea class="large-text" name="autodescription[_open_graph_description]" id="autodescription_og_description"
|
470 |
</div>
|
471 |
</div>
|
472 |
|
@@ -474,11 +514,7 @@ switch ( $instance ) :
|
|
474 |
<div class="tsf-flex-setting-label tsf-flex">
|
475 |
<div class="tsf-flex-setting-label-inner-wrap tsf-flex">
|
476 |
<label for="autodescription_twitter_title" class="tsf-flex-setting-label-item tsf-flex">
|
477 |
-
<div><strong>
|
478 |
-
<?php
|
479 |
-
esc_html_e( 'Twitter Title', 'autodescription' );
|
480 |
-
?>
|
481 |
-
</strong></div>
|
482 |
</label>
|
483 |
<?php
|
484 |
$this->get_option( 'display_character_counter' )
|
@@ -488,7 +524,7 @@ switch ( $instance ) :
|
|
488 |
</div>
|
489 |
<div class="tsf-flex-setting-input tsf-flex">
|
490 |
<div id="tsf-twitter-title-wrap">
|
491 |
-
<input class="large-text" type="text" name="autodescription[_twitter_title]" id="autodescription_twitter_title"
|
492 |
</div>
|
493 |
</div>
|
494 |
</div>
|
@@ -497,11 +533,7 @@ switch ( $instance ) :
|
|
497 |
<div class="tsf-flex-setting-label tsf-flex">
|
498 |
<div class="tsf-flex-setting-label-inner-wrap tsf-flex">
|
499 |
<label for="autodescription_twitter_description" class="tsf-flex-setting-label-item tsf-flex">
|
500 |
-
<div><strong>
|
501 |
-
<?php
|
502 |
-
esc_html_e( 'Twitter Description', 'autodescription' );
|
503 |
-
?>
|
504 |
-
</strong></div>
|
505 |
</label>
|
506 |
<?php
|
507 |
$this->get_option( 'display_character_counter' )
|
@@ -510,21 +542,20 @@ switch ( $instance ) :
|
|
510 |
</div>
|
511 |
</div>
|
512 |
<div class="tsf-flex-setting-input tsf-flex">
|
513 |
-
<textarea class="large-text" name="autodescription[_twitter_description]" id="autodescription_twitter_description"
|
514 |
// Textareas don't require sanitization in HTML5... other than removing the closing </textarea> tag...?
|
515 |
echo $this->esc_attr_preserve_amp( $this->get_post_meta_item( '_twitter_description' ) );
|
516 |
-
|
|
|
517 |
</div>
|
518 |
</div>
|
519 |
<?php
|
520 |
|
521 |
// Fetch image placeholder.
|
522 |
-
if ( $
|
523 |
-
$
|
524 |
-
$image_placeholder = isset( $image_details['url'] ) ? $image_details['url'] : '';
|
525 |
} else {
|
526 |
-
$
|
527 |
-
$image_placeholder = isset( $image_details['url'] ) ? $image_details['url'] : '';
|
528 |
}
|
529 |
|
530 |
?>
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
The_SEO_Framework\Interpreters\Form;
|
13 |
|
14 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
|
|
|
|
|
|
15 |
|
16 |
// Setup default vars.
|
17 |
$post_id = $this->get_the_real_ID(); // We also have access to object $post at the main call...
|
18 |
|
19 |
+
$_generator_args = [ 'id' => $post_id ];
|
20 |
+
|
21 |
+
$_is_static_frontpage = $this->is_static_frontpage( $post_id );
|
|
|
22 |
|
23 |
+
switch ( $this->get_view_instance( 'inpost', $instance ) ) :
|
24 |
case 'inpost_main':
|
25 |
+
$post_settings_class = PostSettings::class;
|
26 |
+
|
27 |
$default_tabs = [
|
28 |
'general' => [
|
29 |
'name' => __( 'General', 'autodescription' ),
|
30 |
+
'callback' => "$post_settings_class::_general_tab",
|
31 |
'dashicon' => 'admin-generic',
|
32 |
],
|
33 |
'social' => [
|
34 |
'name' => __( 'Social', 'autodescription' ),
|
35 |
+
'callback' => "$post_settings_class::_social_tab",
|
36 |
'dashicon' => 'share',
|
37 |
],
|
38 |
'visibility' => [
|
39 |
'name' => __( 'Visibility', 'autodescription' ),
|
40 |
+
'callback' => "$post_settings_class::_visibility_tab",
|
41 |
'dashicon' => 'visibility',
|
42 |
],
|
43 |
];
|
58 |
echo '</div>';
|
59 |
break;
|
60 |
|
61 |
+
case 'inpost_general_tab':
|
62 |
if ( $this->get_option( 'display_seo_bar_metabox' ) ) :
|
63 |
?>
|
64 |
<div class="tsf-flex-setting tsf-flex" id="tsf-doing-it-right-wrap">
|
82 |
<?php
|
83 |
endif;
|
84 |
|
85 |
+
if ( $_is_static_frontpage ) {
|
86 |
$_has_home_title = (bool) $this->escape_title( $this->get_option( 'homepage_title' ) );
|
87 |
$_has_home_desc = (bool) $this->escape_title( $this->get_option( 'homepage_description' ) );
|
88 |
|
|
|
89 |
// When the homepage title is set, we can safely get the custom field.
|
90 |
$default_title = $_has_home_title
|
91 |
+
? $this->get_custom_field_title( $_generator_args )
|
92 |
+
: $this->get_filtered_raw_generated_title( $_generator_args );
|
93 |
$title_ref_locked = $_has_home_title;
|
94 |
$title_additions = $this->get_home_title_additions();
|
95 |
$title_seplocation = $this->get_home_title_seplocation();
|
96 |
|
97 |
// When the homepage description is set, we can safely get the custom field.
|
98 |
$default_description = $_has_home_desc
|
99 |
+
? $this->get_description_from_custom_field( $_generator_args )
|
100 |
+
: $this->get_generated_description( $_generator_args );
|
101 |
$description_ref_locked = $_has_home_desc;
|
|
|
102 |
} else {
|
103 |
$default_title = $this->get_filtered_raw_generated_title( $_generator_args );
|
104 |
$title_ref_locked = false;
|
134 |
</div>
|
135 |
<div class="tsf-flex-setting-input tsf-flex">
|
136 |
<div class=tsf-title-wrap>
|
137 |
+
<input class="large-text" type="text" name="autodescription[_genesis_title]" id="autodescription_title" value="<?php echo $this->esc_attr_preserve_amp( $this->get_post_meta_item( '_genesis_title' ) ); ?>" autocomplete=off />
|
138 |
<?php
|
139 |
$this->output_js_title_elements(); // legacy
|
140 |
$this->output_js_title_data(
|
142 |
[
|
143 |
'state' => [
|
144 |
'refTitleLocked' => $title_ref_locked,
|
145 |
+
'defaultTitle' => $this->s_title( $default_title ),
|
146 |
'addAdditions' => $this->use_title_branding( $_generator_args ),
|
147 |
'useSocialTagline' => $this->use_title_branding( $_generator_args, true ),
|
148 |
+
'additionValue' => $this->s_title( $title_additions ),
|
149 |
'additionPlacement' => 'left' === $title_seplocation ? 'before' : 'after',
|
150 |
'hasLegacy' => true,
|
151 |
],
|
157 |
<div class="tsf-checkbox-wrapper">
|
158 |
<label for="autodescription_title_no_blogname">
|
159 |
<?php
|
160 |
+
if ( $_is_static_frontpage ) :
|
161 |
// Disable the input, and hide the previously stored value.
|
162 |
?>
|
163 |
<input type="checkbox" id="autodescription_title_no_blogname" value="1" <?php checked( $this->get_post_meta_item( '_tsf_title_no_blogname' ) ); ?> disabled />
|
203 |
</div>
|
204 |
</div>
|
205 |
<div class="tsf-flex-setting-input tsf-flex">
|
206 |
+
<textarea class="large-text" name="autodescription[_genesis_description]" id="autodescription_description" rows="4" cols="4" autocomplete=off><?php echo $this->esc_attr_preserve_amp( $this->get_post_meta_item( '_genesis_description' ) ); ?></textarea>
|
207 |
<?php
|
208 |
$this->output_js_description_elements(); // legacy
|
209 |
$this->output_js_description_data(
|
210 |
'autodescription_description',
|
211 |
[
|
212 |
'state' => [
|
213 |
+
'defaultDescription' => $this->s_description( $default_description ),
|
214 |
'refDescriptionLocked' => $description_ref_locked,
|
215 |
'hasLegacy' => true,
|
216 |
],
|
222 |
<?php
|
223 |
break;
|
224 |
|
225 |
+
case 'inpost_visibility_tab':
|
226 |
$canonical = $this->get_post_meta_item( '_genesis_canonical_uri' );
|
227 |
$canonical_placeholder = $this->create_canonical_url( $_generator_args );
|
228 |
|
229 |
// Get robots defaults.
|
230 |
$r_defaults = $this->generate_robots_meta(
|
231 |
$_generator_args,
|
232 |
+
[ 'noindex', 'nofollow', 'noarchive' ],
|
233 |
The_SEO_Framework\ROBOTS_IGNORE_SETTINGS | The_SEO_Framework\ROBOTS_IGNORE_PROTECTION
|
234 |
);
|
235 |
$r_settings = [
|
296 |
</div>
|
297 |
</div>
|
298 |
<?php
|
299 |
+
if ( $_is_static_frontpage ) {
|
300 |
printf(
|
301 |
'<div class=tsf-flex-setting-label-sub-item><span class="description attention">%s</span></div>',
|
302 |
esc_html__( 'Warning: No public site should ever apply "noindex" or "nofollow" to the homepage.', 'autodescription' )
|
414 |
<?php
|
415 |
break;
|
416 |
|
417 |
+
case 'inpost_social_tab':
|
|
|
|
|
418 |
// Yes, this is hacky, but we don't want to lose the user's input.
|
419 |
$show_og = (bool) $this->get_option( 'og_tags' );
|
420 |
$show_tw = (bool) $this->get_option( 'twitter_tags' );
|
421 |
|
422 |
+
if ( $_is_static_frontpage ) {
|
423 |
+
$_social_title = [
|
424 |
+
'og' => $this->get_option( 'homepage_og_title' )
|
425 |
+
?: $this->get_option( 'homepage_title' )
|
426 |
+
?: $this->get_generated_open_graph_title( $_generator_args, false ),
|
427 |
+
'tw' => $this->get_option( 'homepage_twitter_title' )
|
428 |
+
?: $this->get_option( 'homepage_og_title' )
|
429 |
+
?: $this->get_option( 'homepage_title' )
|
430 |
+
?: $this->get_generated_twitter_title( $_generator_args, false ),
|
431 |
+
];
|
432 |
+
$_social_description = [
|
433 |
+
'og' => $this->get_option( 'homepage_og_description' )
|
434 |
+
?: $this->get_option( 'homepage_description' )
|
435 |
+
?: $this->get_generated_open_graph_description( $_generator_args, false ),
|
436 |
+
'tw' => $this->get_option( 'homepage_twitter_description' )
|
437 |
+
?: $this->get_option( 'homepage_og_description' )
|
438 |
+
?: $this->get_option( 'homepage_description' )
|
439 |
+
?: $this->get_generated_twitter_description( $_generator_args, false ),
|
440 |
+
];
|
441 |
+
} else {
|
442 |
+
$_social_title = [
|
443 |
+
'og' => $this->get_generated_open_graph_title( $_generator_args, false ),
|
444 |
+
'tw' => $this->get_generated_twitter_title( $_generator_args, false ),
|
445 |
+
];
|
446 |
+
$_social_description = [
|
447 |
+
'og' => $this->get_generated_open_graph_description( $_generator_args, false ),
|
448 |
+
'tw' => $this->get_generated_twitter_description( $_generator_args, false ),
|
449 |
+
];
|
450 |
+
}
|
451 |
+
|
452 |
+
$this->output_js_social_data(
|
453 |
+
'autodescription_social_singular',
|
454 |
+
[
|
455 |
+
'og' => [
|
456 |
+
'state' => [
|
457 |
+
'defaultTitle' => $this->s_title( $_social_title['og'] ),
|
458 |
+
'addAdditions' => $this->use_title_branding( $_generator_args, 'og' ),
|
459 |
+
'defaultDesc' => $this->s_description( $_social_description['og'] ),
|
460 |
+
'titleLock' => $_is_static_frontpage && $this->get_option( 'homepage_og_title' ),
|
461 |
+
'descLock' => $_is_static_frontpage && $this->get_option( 'homepage_og_description' ),
|
462 |
+
],
|
463 |
+
],
|
464 |
+
'tw' => [
|
465 |
+
'state' => [
|
466 |
+
'defaultTitle' => $this->s_title( $_social_title['tw'] ),
|
467 |
+
'addAdditions' => $this->use_title_branding( $_generator_args, 'twitter' ),
|
468 |
+
'defaultDesc' => $this->s_description( $_social_description['tw'] ),
|
469 |
+
'titleLock' => $_is_static_frontpage && (bool) $this->get_option( 'homepage_twitter_title' ),
|
470 |
+
'descLock' => $_is_static_frontpage && (bool) $this->get_option( 'homepage_twitter_description' ),
|
471 |
+
],
|
472 |
+
],
|
473 |
+
]
|
474 |
+
);
|
475 |
+
|
476 |
?>
|
477 |
<div class="tsf-flex-setting tsf-flex" <?php echo $show_og ? '' : 'style=display:none'; ?>>
|
478 |
<div class="tsf-flex-setting-label tsf-flex">
|
479 |
<div class="tsf-flex-setting-label-inner-wrap tsf-flex">
|
480 |
<label for="autodescription_og_title" class="tsf-flex-setting-label-item tsf-flex">
|
481 |
+
<div><strong><?php esc_html_e( 'Open Graph Title', 'autodescription' ); ?></strong></div>
|
|
|
|
|
|
|
|
|
482 |
</label>
|
483 |
<?php
|
484 |
$this->get_option( 'display_character_counter' )
|
488 |
</div>
|
489 |
<div class="tsf-flex-setting-input tsf-flex">
|
490 |
<div id="tsf-og-title-wrap">
|
491 |
+
<input class="large-text" type="text" name="autodescription[_open_graph_title]" id="autodescription_og_title" value="<?php echo $this->esc_attr_preserve_amp( $this->get_post_meta_item( '_open_graph_title' ) ); ?>" autocomplete=off data-tsf-social-group=autodescription_social_singular data-tsf-social-type=ogTitle />
|
492 |
</div>
|
493 |
</div>
|
494 |
</div>
|
497 |
<div class="tsf-flex-setting-label tsf-flex">
|
498 |
<div class="tsf-flex-setting-label-inner-wrap tsf-flex">
|
499 |
<label for="autodescription_og_description" class="tsf-flex-setting-label-item tsf-flex">
|
500 |
+
<div><strong><?php esc_html_e( 'Open Graph Description', 'autodescription' ); ?></strong></div>
|
|
|
|
|
|
|
|
|
501 |
</label>
|
502 |
<?php
|
503 |
$this->get_option( 'display_character_counter' )
|
506 |
</div>
|
507 |
</div>
|
508 |
<div class="tsf-flex-setting-input tsf-flex">
|
509 |
+
<textarea class="large-text" name="autodescription[_open_graph_description]" id="autodescription_og_description" rows="3" cols="4" autocomplete=off data-tsf-social-group=autodescription_social_singular data-tsf-social-type=ogDesc><?php echo $this->esc_attr_preserve_amp( $this->get_post_meta_item( '_open_graph_description' ) ); ?></textarea>
|
510 |
</div>
|
511 |
</div>
|
512 |
|
514 |
<div class="tsf-flex-setting-label tsf-flex">
|
515 |
<div class="tsf-flex-setting-label-inner-wrap tsf-flex">
|
516 |
<label for="autodescription_twitter_title" class="tsf-flex-setting-label-item tsf-flex">
|
517 |
+
<div><strong><?php esc_html_e( 'Twitter Title', 'autodescription' ); ?></strong></div>
|
|
|
|
|
|
|
|
|
518 |
</label>
|
519 |
<?php
|
520 |
$this->get_option( 'display_character_counter' )
|
524 |
</div>
|
525 |
<div class="tsf-flex-setting-input tsf-flex">
|
526 |
<div id="tsf-twitter-title-wrap">
|
527 |
+
<input class="large-text" type="text" name="autodescription[_twitter_title]" id="autodescription_twitter_title" value="<?php echo $this->esc_attr_preserve_amp( $this->get_post_meta_item( '_twitter_title' ) ); ?>" autocomplete=off data-tsf-social-group=autodescription_social_singular data-tsf-social-type=twTitle />
|
528 |
</div>
|
529 |
</div>
|
530 |
</div>
|
533 |
<div class="tsf-flex-setting-label tsf-flex">
|
534 |
<div class="tsf-flex-setting-label-inner-wrap tsf-flex">
|
535 |
<label for="autodescription_twitter_description" class="tsf-flex-setting-label-item tsf-flex">
|
536 |
+
<div><strong><?php esc_html_e( 'Twitter Description', 'autodescription' ); ?></strong></div>
|
|
|
|
|
|
|
|
|
537 |
</label>
|
538 |
<?php
|
539 |
$this->get_option( 'display_character_counter' )
|
542 |
</div>
|
543 |
</div>
|
544 |
<div class="tsf-flex-setting-input tsf-flex">
|
545 |
+
<textarea class="large-text" name="autodescription[_twitter_description]" id="autodescription_twitter_description" rows="3" cols="4" autocomplete=off data-tsf-social-group=autodescription_social_singular data-tsf-social-type=twDesc><?php // phpcs:ignore, Squiz.PHP.EmbeddedPhp -- textarea element's content is input. Do not add spaces/tabs/lines: the php tag should stick to >.
|
546 |
// Textareas don't require sanitization in HTML5... other than removing the closing </textarea> tag...?
|
547 |
echo $this->esc_attr_preserve_amp( $this->get_post_meta_item( '_twitter_description' ) );
|
548 |
+
// phpcs:ignore, Squiz.PHP.EmbeddedPhp
|
549 |
+
?></textarea>
|
550 |
</div>
|
551 |
</div>
|
552 |
<?php
|
553 |
|
554 |
// Fetch image placeholder.
|
555 |
+
if ( $_is_static_frontpage && $this->get_option( 'homepage_social_image_url' ) ) {
|
556 |
+
$image_placeholder = current( $this->get_image_details( $_generator_args, true, 'social', true ) )['url'] ?? '';
|
|
|
557 |
} else {
|
558 |
+
$image_placeholder = current( $this->get_generated_image_details( $_generator_args, true, 'social', true ) )['url'] ?? '';
|
|
|
559 |
}
|
560 |
|
561 |
?>
|
@@ -11,7 +11,7 @@ use The_SEO_Framework\Bridges\TermSettings,
|
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
The_SEO_Framework\Interpreters\Form;
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
|
16 |
// Fetch Term ID and taxonomy.
|
17 |
$term_id = $term->term_id;
|
@@ -41,14 +41,16 @@ $_generator_args = [
|
|
41 |
$show_og = (bool) $this->get_option( 'og_tags' );
|
42 |
$show_tw = (bool) $this->get_option( 'twitter_tags' );
|
43 |
|
44 |
-
$social_placeholders = $this->_get_social_placeholders( $_generator_args );
|
45 |
-
|
46 |
//! Social image placeholder.
|
47 |
$image_details = current( $this->get_generated_image_details( $_generator_args, true, 'social', true ) );
|
48 |
-
$image_placeholder =
|
49 |
|
50 |
$canonical_placeholder = $this->create_canonical_url( $_generator_args ); // implies get_custom_field = false
|
51 |
-
$robots_defaults = $this->generate_robots_meta(
|
|
|
|
|
|
|
|
|
52 |
|
53 |
// TODO reintroduce the info blocks, and place the labels at the left, instead??
|
54 |
$robots_settings = [
|
@@ -131,7 +133,7 @@ $robots_settings = [
|
|
131 |
</th>
|
132 |
<td>
|
133 |
<div class=tsf-title-wrap>
|
134 |
-
<input name="autodescription-meta[doctitle]" id="autodescription-meta[doctitle]"
|
135 |
<?php
|
136 |
$this->output_js_title_elements(); // legacy
|
137 |
$this->output_js_title_data(
|
@@ -139,10 +141,10 @@ $robots_settings = [
|
|
139 |
[
|
140 |
'state' => [
|
141 |
'refTitleLocked' => false,
|
142 |
-
'defaultTitle' => $this->get_filtered_raw_generated_title( $_generator_args ),
|
143 |
'addAdditions' => $this->use_title_branding( $_generator_args ),
|
144 |
'useSocialTagline' => $this->use_title_branding( $_generator_args, true ),
|
145 |
-
'additionValue' => $this->
|
146 |
'additionPlacement' => 'left' === $this->get_title_seplocation() ? 'before' : 'after',
|
147 |
'hasLegacy' => true,
|
148 |
],
|
@@ -151,7 +153,7 @@ $robots_settings = [
|
|
151 |
?>
|
152 |
</div>
|
153 |
<label for="autodescription-meta[title_no_blog_name]" class="tsf-term-checkbox-wrap">
|
154 |
-
<input type="checkbox" name="autodescription-meta[title_no_blog_name]" id="autodescription-meta[title_no_blog_name]" value="1" <?php checked( $this->get_term_meta_item( 'title_no_blog_name'
|
155 |
<?php
|
156 |
esc_html_e( 'Remove the site title?', 'autodescription' );
|
157 |
echo ' ';
|
@@ -200,6 +202,28 @@ $robots_settings = [
|
|
200 |
</table>
|
201 |
|
202 |
<h2><?php esc_html_e( 'Social SEO Settings', 'autodescription' ); ?></h2>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
|
204 |
<table class="form-table tsf-term-meta">
|
205 |
<tbody>
|
@@ -215,7 +239,7 @@ $robots_settings = [
|
|
215 |
</th>
|
216 |
<td>
|
217 |
<div id="tsf-og-title-wrap">
|
218 |
-
<input name="autodescription-meta[og_title]" id="autodescription-meta[og_title]" type="text"
|
219 |
</div>
|
220 |
</td>
|
221 |
</tr>
|
@@ -231,7 +255,7 @@ $robots_settings = [
|
|
231 |
?>
|
232 |
</th>
|
233 |
<td>
|
234 |
-
<textarea name="autodescription-meta[og_description]" id="autodescription-meta[og_description]"
|
235 |
</td>
|
236 |
</tr>
|
237 |
|
@@ -247,7 +271,7 @@ $robots_settings = [
|
|
247 |
</th>
|
248 |
<td>
|
249 |
<div id="tsf-tw-title-wrap">
|
250 |
-
<input name="autodescription-meta[tw_title]" id="autodescription-meta[tw_title]" type="text"
|
251 |
</div>
|
252 |
</td>
|
253 |
</tr>
|
@@ -263,7 +287,7 @@ $robots_settings = [
|
|
263 |
?>
|
264 |
</th>
|
265 |
<td>
|
266 |
-
<textarea name="autodescription-meta[tw_description]" id="autodescription-meta[tw_description]"
|
267 |
</td>
|
268 |
</tr>
|
269 |
|
@@ -281,7 +305,7 @@ $robots_settings = [
|
|
281 |
</label>
|
282 |
</th>
|
283 |
<td>
|
284 |
-
<input name="autodescription-meta[social_image_url]" id="autodescription_meta_socialimage-url"
|
285 |
<input type="hidden" name="autodescription-meta[social_image_id]" id="autodescription_meta_socialimage-id" value="<?php echo absint( $social_image_id ); ?>" disabled class="tsf-enable-media-if-js" />
|
286 |
<div class="hide-if-no-tsf-js tsf-term-button-wrap">
|
287 |
<?php
|
@@ -312,7 +336,7 @@ $robots_settings = [
|
|
312 |
</label>
|
313 |
</th>
|
314 |
<td>
|
315 |
-
<input name="autodescription-meta[canonical]" id="autodescription-meta[canonical]"
|
316 |
</td>
|
317 |
</tr>
|
318 |
|
@@ -370,7 +394,7 @@ $robots_settings = [
|
|
370 |
</label>
|
371 |
</th>
|
372 |
<td>
|
373 |
-
<input name="autodescription-meta[redirect]" id="autodescription-meta[redirect]"
|
374 |
</td>
|
375 |
</tr>
|
376 |
</tbody>
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
The_SEO_Framework\Interpreters\Form;
|
13 |
|
14 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
15 |
|
16 |
// Fetch Term ID and taxonomy.
|
17 |
$term_id = $term->term_id;
|
41 |
$show_og = (bool) $this->get_option( 'og_tags' );
|
42 |
$show_tw = (bool) $this->get_option( 'twitter_tags' );
|
43 |
|
|
|
|
|
44 |
//! Social image placeholder.
|
45 |
$image_details = current( $this->get_generated_image_details( $_generator_args, true, 'social', true ) );
|
46 |
+
$image_placeholder = $image_details['url'] ?? '';
|
47 |
|
48 |
$canonical_placeholder = $this->create_canonical_url( $_generator_args ); // implies get_custom_field = false
|
49 |
+
$robots_defaults = $this->generate_robots_meta(
|
50 |
+
$_generator_args,
|
51 |
+
[ 'noindex', 'nofollow', 'noarchive' ],
|
52 |
+
The_SEO_Framework\ROBOTS_IGNORE_SETTINGS
|
53 |
+
);
|
54 |
|
55 |
// TODO reintroduce the info blocks, and place the labels at the left, instead??
|
56 |
$robots_settings = [
|
133 |
</th>
|
134 |
<td>
|
135 |
<div class=tsf-title-wrap>
|
136 |
+
<input type="text" name="autodescription-meta[doctitle]" id="autodescription-meta[doctitle]" value="<?php echo $this->esc_attr_preserve_amp( $title ); ?>" size="40" autocomplete=off />
|
137 |
<?php
|
138 |
$this->output_js_title_elements(); // legacy
|
139 |
$this->output_js_title_data(
|
141 |
[
|
142 |
'state' => [
|
143 |
'refTitleLocked' => false,
|
144 |
+
'defaultTitle' => $this->s_title( $this->get_filtered_raw_generated_title( $_generator_args ) ),
|
145 |
'addAdditions' => $this->use_title_branding( $_generator_args ),
|
146 |
'useSocialTagline' => $this->use_title_branding( $_generator_args, true ),
|
147 |
+
'additionValue' => $this->s_title( $this->get_blogname() ),
|
148 |
'additionPlacement' => 'left' === $this->get_title_seplocation() ? 'before' : 'after',
|
149 |
'hasLegacy' => true,
|
150 |
],
|
153 |
?>
|
154 |
</div>
|
155 |
<label for="autodescription-meta[title_no_blog_name]" class="tsf-term-checkbox-wrap">
|
156 |
+
<input type="checkbox" name="autodescription-meta[title_no_blog_name]" id="autodescription-meta[title_no_blog_name]" value="1" <?php checked( $this->get_term_meta_item( 'title_no_blog_name' ) ); ?> />
|
157 |
<?php
|
158 |
esc_html_e( 'Remove the site title?', 'autodescription' );
|
159 |
echo ' ';
|
202 |
</table>
|
203 |
|
204 |
<h2><?php esc_html_e( 'Social SEO Settings', 'autodescription' ); ?></h2>
|
205 |
+
<?php
|
206 |
+
|
207 |
+
$this->output_js_social_data(
|
208 |
+
'autodescription_social_tt',
|
209 |
+
[
|
210 |
+
'og' => [
|
211 |
+
'state' => [
|
212 |
+
'defaultTitle' => $this->s_title( $this->get_generated_open_graph_title( $_generator_args, false ) ),
|
213 |
+
'addAdditions' => $this->use_title_branding( $_generator_args, 'og' ),
|
214 |
+
'defaultDesc' => $this->s_description( $this->get_generated_open_graph_description( $_generator_args, false ) ),
|
215 |
+
],
|
216 |
+
],
|
217 |
+
'tw' => [
|
218 |
+
'state' => [
|
219 |
+
'defaultTitle' => $this->s_title( $this->get_generated_twitter_title( $_generator_args, false ) ),
|
220 |
+
'addAdditions' => $this->use_title_branding( $_generator_args, 'twitter' ),
|
221 |
+
'defaultDesc' => $this->s_description( $this->get_generated_twitter_description( $_generator_args, false ) ),
|
222 |
+
],
|
223 |
+
],
|
224 |
+
]
|
225 |
+
);
|
226 |
+
?>
|
227 |
|
228 |
<table class="form-table tsf-term-meta">
|
229 |
<tbody>
|
239 |
</th>
|
240 |
<td>
|
241 |
<div id="tsf-og-title-wrap">
|
242 |
+
<input name="autodescription-meta[og_title]" id="autodescription-meta[og_title]" type="text" value="<?php echo $this->esc_attr_preserve_amp( $og_title ); ?>" size="40" autocomplete=off data-tsf-social-group=autodescription_social_tt data-tsf-social-type=ogTitle />
|
243 |
</div>
|
244 |
</td>
|
245 |
</tr>
|
255 |
?>
|
256 |
</th>
|
257 |
<td>
|
258 |
+
<textarea name="autodescription-meta[og_description]" id="autodescription-meta[og_description]" rows="4" cols="50" class="large-text" autocomplete=off data-tsf-social-group=autodescription_social_tt data-tsf-social-type=ogDesc><?php echo $this->esc_attr_preserve_amp( $og_description ); ?></textarea>
|
259 |
</td>
|
260 |
</tr>
|
261 |
|
271 |
</th>
|
272 |
<td>
|
273 |
<div id="tsf-tw-title-wrap">
|
274 |
+
<input name="autodescription-meta[tw_title]" id="autodescription-meta[tw_title]" type="text" value="<?php echo $this->esc_attr_preserve_amp( $tw_title ); ?>" size="40" autocomplete=off data-tsf-social-group=autodescription_social_tt data-tsf-social-type=twTitle />
|
275 |
</div>
|
276 |
</td>
|
277 |
</tr>
|
287 |
?>
|
288 |
</th>
|
289 |
<td>
|
290 |
+
<textarea name="autodescription-meta[tw_description]" id="autodescription-meta[tw_description]" rows="4" cols="50" class="large-text" autocomplete=off data-tsf-social-group=autodescription_social_tt data-tsf-social-type=twDesc><?php echo $this->esc_attr_preserve_amp( $tw_description ); ?></textarea>
|
291 |
</td>
|
292 |
</tr>
|
293 |
|
305 |
</label>
|
306 |
</th>
|
307 |
<td>
|
308 |
+
<input type="url" name="autodescription-meta[social_image_url]" id="autodescription_meta_socialimage-url" placeholder="<?php echo esc_attr( $image_placeholder ); ?>" value="<?php echo esc_attr( $social_image_url ); ?>" size="40" autocomplete=off />
|
309 |
<input type="hidden" name="autodescription-meta[social_image_id]" id="autodescription_meta_socialimage-id" value="<?php echo absint( $social_image_id ); ?>" disabled class="tsf-enable-media-if-js" />
|
310 |
<div class="hide-if-no-tsf-js tsf-term-button-wrap">
|
311 |
<?php
|
336 |
</label>
|
337 |
</th>
|
338 |
<td>
|
339 |
+
<input type=url name="autodescription-meta[canonical]" id="autodescription-meta[canonical]" placeholder="<?php echo esc_attr( $canonical_placeholder ); ?>" value="<?php echo esc_attr( $canonical ); ?>" size="40" autocomplete=off />
|
340 |
</td>
|
341 |
</tr>
|
342 |
|
394 |
</label>
|
395 |
</th>
|
396 |
<td>
|
397 |
+
<input type=url name="autodescription-meta[redirect]" id="autodescription-meta[redirect]" value="<?php echo esc_attr( $redirect ); ?>" size="40" autocomplete=off />
|
398 |
</td>
|
399 |
</tr>
|
400 |
</tbody>
|
@@ -7,7 +7,7 @@
|
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
11 |
|
12 |
// Whether tabs are active.
|
13 |
$use_tabs = $use_tabs && count( $tabs ) > 1;
|
@@ -18,10 +18,10 @@ $count = 1;
|
|
18 |
*
|
19 |
* The content is relative to the navigation, and uses CSS to become visible.
|
20 |
*/
|
21 |
-
foreach ( $tabs as $tab => $
|
22 |
|
23 |
-
$radio_id =
|
24 |
-
$radio_class =
|
25 |
|
26 |
// Current tab for JS.
|
27 |
$current_class = 1 === $count ? ' tsf-flex-tab-content-active' : '';
|
@@ -31,28 +31,41 @@ foreach ( $tabs as $tab => $value ) :
|
|
31 |
<?php
|
32 |
// No-JS tabs.
|
33 |
if ( $use_tabs ) :
|
34 |
-
$dashicon =
|
35 |
-
$label_name =
|
36 |
|
37 |
?>
|
38 |
<div class="tsf-flex tsf-flex-hide-if-js tsf-flex-tabs-content-no-js">
|
39 |
<div class="tsf-flex tsf-flex-nav-tab tsf-flex-tab-no-js">
|
40 |
<span class="tsf-flex tsf-flex-nav-tab">
|
41 |
<?php echo $dashicon ? '<span class="tsf-flex dashicons dashicons-' . esc_attr( $dashicon ) . ' tsf-flex-nav-dashicon"></span>' : ''; ?>
|
42 |
-
<?php echo $label_name ? '<span class="tsf-flex tsf-flex-nav-name">' .
|
43 |
</span>
|
44 |
</div>
|
45 |
</div>
|
46 |
<?php
|
47 |
endif;
|
48 |
|
49 |
-
|
|
|
50 |
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
</div>
|
57 |
<?php
|
58 |
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
11 |
|
12 |
// Whether tabs are active.
|
13 |
$use_tabs = $use_tabs && count( $tabs ) > 1;
|
18 |
*
|
19 |
* The content is relative to the navigation, and uses CSS to become visible.
|
20 |
*/
|
21 |
+
foreach ( $tabs as $tab => $params ) :
|
22 |
|
23 |
+
$radio_id = "tsf-flex-{$id}-tab-{$tab}-content";
|
24 |
+
$radio_class = "tsf-flex-{$id}-tabs-content";
|
25 |
|
26 |
// Current tab for JS.
|
27 |
$current_class = 1 === $count ? ' tsf-flex-tab-content-active' : '';
|
31 |
<?php
|
32 |
// No-JS tabs.
|
33 |
if ( $use_tabs ) :
|
34 |
+
$dashicon = $params['dashicon'] ?? '';
|
35 |
+
$label_name = $params['name'] ?? '';
|
36 |
|
37 |
?>
|
38 |
<div class="tsf-flex tsf-flex-hide-if-js tsf-flex-tabs-content-no-js">
|
39 |
<div class="tsf-flex tsf-flex-nav-tab tsf-flex-tab-no-js">
|
40 |
<span class="tsf-flex tsf-flex-nav-tab">
|
41 |
<?php echo $dashicon ? '<span class="tsf-flex dashicons dashicons-' . esc_attr( $dashicon ) . ' tsf-flex-nav-dashicon"></span>' : ''; ?>
|
42 |
+
<?php echo $label_name ? '<span class="tsf-flex tsf-flex-nav-name">' . esc_html( $label_name ) . '</span>' : ''; ?>
|
43 |
</span>
|
44 |
</div>
|
45 |
</div>
|
46 |
<?php
|
47 |
endif;
|
48 |
|
49 |
+
if ( ! empty( $params['callback'] ) )
|
50 |
+
call_user_func_array( $params['callback'], ( $params['args'] ?? [] ) );
|
51 |
|
52 |
+
/**
|
53 |
+
* @since 4.2.0
|
54 |
+
* @param array $args The tab arguments: {
|
55 |
+
* @param string id
|
56 |
+
* @param string tab
|
57 |
+
* @param array params
|
58 |
+
* }
|
59 |
+
*/
|
60 |
+
do_action(
|
61 |
+
'the_seo_framework_flex_tab_content',
|
62 |
+
[
|
63 |
+
'id' => $id,
|
64 |
+
'tab' => $tab,
|
65 |
+
'params' => $params,
|
66 |
+
]
|
67 |
+
);
|
68 |
+
?>
|
69 |
</div>
|
70 |
<?php
|
71 |
|
@@ -7,7 +7,7 @@
|
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
11 |
|
12 |
// Whether tabs are active.
|
13 |
$use_tabs = $use_tabs && count( $tabs ) > 1;
|
@@ -24,29 +24,33 @@ if ( $use_tabs ) :
|
|
24 |
<div class="tsf-flex tsf-flex-nav-tab-inner">
|
25 |
<?php
|
26 |
foreach ( $tabs as $tab => $value ) :
|
27 |
-
$dashicon =
|
28 |
-
$label_name =
|
29 |
|
30 |
$wrapper_id = esc_attr( "tsf-flex-nav-tab-{$tab}" );
|
31 |
-
$wrapper_active = 1 === $count ? '
|
32 |
|
33 |
$input_checked = 1 === $count ? 'checked' : '';
|
34 |
$input_id = esc_attr( "tsf-flex-{$id}-tab-{$tab}" );
|
35 |
$input_name = esc_attr( "tsf-flex-{$id}-tabs" );
|
36 |
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
|
|
|
|
|
|
|
|
46 |
</label>
|
47 |
</div>
|
48 |
-
|
49 |
-
//
|
50 |
|
51 |
$count++;
|
52 |
endforeach;
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
11 |
|
12 |
// Whether tabs are active.
|
13 |
$use_tabs = $use_tabs && count( $tabs ) > 1;
|
24 |
<div class="tsf-flex tsf-flex-nav-tab-inner">
|
25 |
<?php
|
26 |
foreach ( $tabs as $tab => $value ) :
|
27 |
+
$dashicon = $value['dashicon'] ?? '';
|
28 |
+
$label_name = $value['name'] ?? '';
|
29 |
|
30 |
$wrapper_id = esc_attr( "tsf-flex-nav-tab-{$tab}" );
|
31 |
+
$wrapper_active = 1 === $count ? 'tsf-flex-nav-tab-active' : '';
|
32 |
|
33 |
$input_checked = 1 === $count ? 'checked' : '';
|
34 |
$input_id = esc_attr( "tsf-flex-{$id}-tab-{$tab}" );
|
35 |
$input_name = esc_attr( "tsf-flex-{$id}-tabs" );
|
36 |
|
37 |
+
if ( $dashicon )
|
38 |
+
$dashicon = sprintf( '<span class="tsf-flex dashicons %s tsf-flex-nav-dashicon"></span>', esc_attr( "dashicons-$dashicon" ) );
|
39 |
+
|
40 |
+
if ( $label_name )
|
41 |
+
$label_name = sprintf( '<span class="tsf-flex tsf-flex-nav-name">%s</span>', esc_attr( $label_name ) );
|
42 |
+
|
43 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- All output below is escaped.
|
44 |
+
echo <<<HTML
|
45 |
+
<div class="tsf-flex tsf-flex-nav-tab tsf-flex $wrapper_active" id="$wrapper_id">
|
46 |
+
<input type="radio" class="tsf-flex-nav-tab-radio tsf-input-not-saved" id="$input_id" name="$input_name" $input_checked>
|
47 |
+
<label for="$input_id" class="tsf-flex tsf-flex-nav-tab-label">
|
48 |
+
$dashicon
|
49 |
+
$label_name
|
50 |
</label>
|
51 |
</div>
|
52 |
+
HTML;
|
53 |
+
// ^ At PHP 7.3+ we can indent this.
|
54 |
|
55 |
$count++;
|
56 |
endforeach;
|
@@ -11,7 +11,7 @@ use The_SEO_Framework\Interpreters\Form;
|
|
11 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
12 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
|
16 |
$robots_settings = [
|
17 |
'noindex' => [
|
11 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
12 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
13 |
|
14 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
15 |
|
16 |
$robots_settings = [
|
17 |
'noindex' => [
|
@@ -11,7 +11,7 @@
|
|
11 |
|
12 |
use The_SEO_Framework\Interpreters\Form;
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
|
16 |
$robots_settings = [
|
17 |
'noindex' => [
|
11 |
|
12 |
use The_SEO_Framework\Interpreters\Form;
|
13 |
|
14 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
15 |
|
16 |
$robots_settings = [
|
17 |
'noindex' => [
|
@@ -11,7 +11,7 @@
|
|
11 |
|
12 |
use The_SEO_Framework\Interpreters\Form;
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
|
16 |
$robots_settings = [
|
17 |
'noindex' => [
|
11 |
|
12 |
use The_SEO_Framework\Interpreters\Form;
|
13 |
|
14 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
15 |
|
16 |
$robots_settings = [
|
17 |
'noindex' => [
|
@@ -9,7 +9,7 @@
|
|
9 |
|
10 |
use The_SEO_Framework\Interpreters\HTML;
|
11 |
|
12 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
13 |
|
14 |
if ( ! $message ) return;
|
15 |
|
9 |
|
10 |
use The_SEO_Framework\Interpreters\HTML;
|
11 |
|
12 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
13 |
|
14 |
if ( ! $message ) return;
|
15 |
|
@@ -7,7 +7,7 @@
|
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
11 |
|
12 |
$fields = [
|
13 |
'tsf-user-meta[facebook_page]' => [
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
11 |
|
12 |
$fields = [
|
13 |
'tsf-user-meta[facebook_page]' => [
|
@@ -7,7 +7,7 @@
|
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
11 |
|
12 |
?>
|
13 |
<div class="metabox-holder columns-2">
|
7 |
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
11 |
|
12 |
?>
|
13 |
<div class="metabox-holder columns-2">
|
File without changes
|
@@ -8,16 +8,13 @@
|
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
use The_SEO_Framework\Interpreters\HTML,
|
11 |
-
The_SEO_Framework\Interpreters\
|
12 |
|
13 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
14 |
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
switch ( $instance ) :
|
19 |
-
case 'the_seo_framework_description_metabox_main':
|
20 |
-
Form::header_title( __( 'Description Settings', 'autodescription' ) );
|
21 |
HTML::description(
|
22 |
__( 'The meta description can be used to determine the text used under the title on search engine results pages.', 'autodescription' )
|
23 |
);
|
@@ -25,7 +22,7 @@ switch ( $instance ) :
|
|
25 |
?>
|
26 |
<hr>
|
27 |
<?php
|
28 |
-
|
29 |
HTML::description(
|
30 |
__( 'A description can be automatically generated for every page.', 'autodescription' )
|
31 |
);
|
@@ -40,9 +37,9 @@ switch ( $instance ) :
|
|
40 |
);
|
41 |
|
42 |
HTML::wrap_fields(
|
43 |
-
|
44 |
'id' => 'auto_description',
|
45 |
-
'label' => esc_html__( 'Automatically generate descriptions?', 'autodescription' ) .
|
46 |
'escape' => false,
|
47 |
] ),
|
48 |
true
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
use The_SEO_Framework\Interpreters\HTML,
|
11 |
+
The_SEO_Framework\Interpreters\Settings_Input as Input;
|
12 |
|
13 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
14 |
|
15 |
+
switch ( $this->get_view_instance( 'description', $instance ) ) :
|
16 |
+
case 'description_main':
|
17 |
+
HTML::header_title( __( 'Description Settings', 'autodescription' ) );
|
|
|
|
|
|
|
18 |
HTML::description(
|
19 |
__( 'The meta description can be used to determine the text used under the title on search engine results pages.', 'autodescription' )
|
20 |
);
|
22 |
?>
|
23 |
<hr>
|
24 |
<?php
|
25 |
+
HTML::header_title( __( 'Automated Description Settings', 'autodescription' ) );
|
26 |
HTML::description(
|
27 |
__( 'A description can be automatically generated for every page.', 'autodescription' )
|
28 |
);
|
37 |
);
|
38 |
|
39 |
HTML::wrap_fields(
|
40 |
+
Input::make_checkbox( [
|
41 |
'id' => 'auto_description',
|
42 |
+
'label' => esc_html__( 'Automatically generate descriptions?', 'autodescription' ) . " $info",
|
43 |
'escape' => false,
|
44 |
] ),
|
45 |
true
|
@@ -8,23 +8,20 @@
|
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
use The_SEO_Framework\Interpreters\HTML,
|
11 |
-
The_SEO_Framework\Interpreters\
|
12 |
|
13 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
14 |
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
switch ( $instance ) :
|
19 |
-
case 'the_seo_framework_feed_metabox_main':
|
20 |
-
Form::header_title( __( 'Content Feed Settings', 'autodescription' ) );
|
21 |
HTML::description( __( "Sometimes, your content can get stolen by robots through the WordPress feeds. This can cause duplicate content issues. To prevent this from happening, it's recommended to convert the feed's content into an excerpt.", 'autodescription' ) );
|
22 |
HTML::description( __( 'Adding a backlink below the feed entries will also let the visitors know where the content came from.', 'autodescription' ) );
|
23 |
|
24 |
?>
|
25 |
<hr>
|
26 |
<?php
|
27 |
-
|
28 |
$excerpt_the_feed_label = esc_html__( 'Convert feed entries into excerpts?', 'autodescription' );
|
29 |
$excerpt_the_feed_label .= ' ' . HTML::make_info( __( 'By default the excerpt will be at most 400 characters long.', 'autodescription' ), '', false );
|
30 |
|
@@ -36,17 +33,17 @@ switch ( $instance ) :
|
|
36 |
|
37 |
HTML::wrap_fields(
|
38 |
[
|
39 |
-
|
40 |
'id' => 'excerpt_the_feed',
|
41 |
'label' => $excerpt_the_feed_label,
|
42 |
'escape' => false,
|
43 |
] ),
|
44 |
-
|
45 |
'id' => 'source_the_feed',
|
46 |
'label' => $source_the_feed_label,
|
47 |
'escape' => false,
|
48 |
] ),
|
49 |
-
|
50 |
'id' => 'index_the_feed',
|
51 |
'label' => $index_the_feed_label,
|
52 |
'escape' => false,
|
8 |
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
|
10 |
use The_SEO_Framework\Interpreters\HTML,
|
11 |
+
The_SEO_Framework\Interpreters\Settings_Input as Input;
|
12 |
|
13 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
14 |
|
15 |
+
switch ( $this->get_view_instance( 'feed', $instance ) ) :
|
16 |
+
case 'feed_main':
|
17 |
+
HTML::header_title( __( 'Content Feed Settings', 'autodescription' ) );
|
|
|
|
|
|
|
18 |
HTML::description( __( "Sometimes, your content can get stolen by robots through the WordPress feeds. This can cause duplicate content issues. To prevent this from happening, it's recommended to convert the feed's content into an excerpt.", 'autodescription' ) );
|
19 |
HTML::description( __( 'Adding a backlink below the feed entries will also let the visitors know where the content came from.', 'autodescription' ) );
|
20 |
|
21 |
?>
|
22 |
<hr>
|
23 |
<?php
|
24 |
+
HTML::header_title( __( 'Change Feed Settings', 'autodescription' ) );
|
25 |
$excerpt_the_feed_label = esc_html__( 'Convert feed entries into excerpts?', 'autodescription' );
|
26 |
$excerpt_the_feed_label .= ' ' . HTML::make_info( __( 'By default the excerpt will be at most 400 characters long.', 'autodescription' ), '', false );
|
27 |
|
33 |
|
34 |
HTML::wrap_fields(
|
35 |
[
|
36 |
+
Input::make_checkbox( [
|
37 |
'id' => 'excerpt_the_feed',
|
38 |
'label' => $excerpt_the_feed_label,
|
39 |
'escape' => false,
|
40 |
] ),
|
41 |
+
Input::make_checkbox( [
|
42 |
'id' => 'source_the_feed',
|
43 |
'label' => $source_the_feed_label,
|
44 |
'escape' => false,
|
45 |
] ),
|
46 |
+
Input::make_checkbox( [
|
47 |
'id' => 'index_the_feed',
|
48 |
'label' => $index_the_feed_label,
|
49 |
'escape' => false,
|
@@ -9,76 +9,73 @@
|
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
-
The_SEO_Framework\Interpreters\
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
|
16 |
-
|
17 |
-
|
|
|
18 |
|
19 |
-
|
20 |
-
case 'the_seo_framework_general_metabox_main':
|
21 |
-
$default_tabs = [
|
22 |
'layout' => [
|
23 |
'name' => __( 'Layout', 'autodescription' ),
|
24 |
-
'callback' =>
|
25 |
'dashicon' => 'screenoptions',
|
26 |
],
|
27 |
'performance' => [
|
28 |
'name' => __( 'Performance', 'autodescription' ),
|
29 |
-
'callback' =>
|
30 |
'dashicon' => 'performance',
|
31 |
],
|
32 |
'canonical' => [
|
33 |
'name' => __( 'Canonical', 'autodescription' ),
|
34 |
-
'callback' =>
|
35 |
'dashicon' => 'external',
|
36 |
],
|
37 |
'timestamps' => [
|
38 |
'name' => __( 'Timestamps', 'autodescription' ),
|
39 |
-
'callback' =>
|
40 |
'dashicon' => 'clock',
|
41 |
],
|
42 |
'exclusions' => [
|
43 |
'name' => __( 'Exclusions', 'autodescription' ),
|
44 |
-
'callback' =>
|
45 |
'dashicon' => 'editor-unlink',
|
46 |
],
|
47 |
];
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
SeoSettings::_nav_tab_wrapper( 'general', $tabs );
|
59 |
break;
|
60 |
|
61 |
-
case '
|
62 |
-
|
63 |
HTML::description( __( 'SEO hints can be visually displayed throughout the dashboard.', 'autodescription' ) );
|
64 |
|
65 |
?>
|
66 |
<hr>
|
67 |
<?php
|
68 |
-
|
69 |
HTML::wrap_fields(
|
70 |
[
|
71 |
-
|
72 |
'id' => 'display_seo_bar_tables',
|
73 |
'label' => esc_html__( 'Display the SEO Bar in overview tables?', 'autodescription' ),
|
74 |
'escape' => false,
|
75 |
] ),
|
76 |
-
|
77 |
'id' => 'display_seo_bar_metabox',
|
78 |
'label' => esc_html__( 'Display the SEO Bar in the SEO Settings metabox?', 'autodescription' ),
|
79 |
'escape' => false,
|
80 |
] ),
|
81 |
-
|
82 |
'id' => 'seo_bar_symbols',
|
83 |
'label' => esc_html__( 'Use symbols for warnings?', 'autodescription' ) . ' ' . HTML::make_info(
|
84 |
__( 'If you have difficulty discerning colors, this may help you spot issues more easily.', 'autodescription' ),
|
@@ -94,7 +91,7 @@ switch ( $instance ) :
|
|
94 |
?>
|
95 |
<hr>
|
96 |
<?php
|
97 |
-
|
98 |
|
99 |
$pixel_info = HTML::make_info(
|
100 |
__( 'The pixel counter computes whether the input will fit on search engine result pages.', 'autodescription' ),
|
@@ -110,14 +107,14 @@ switch ( $instance ) :
|
|
110 |
|
111 |
HTML::wrap_fields(
|
112 |
[
|
113 |
-
|
114 |
'id' => 'display_pixel_counter',
|
115 |
-
'label' => esc_html__( 'Display pixel counters?', 'autodescription' ) .
|
116 |
'escape' => false,
|
117 |
] ),
|
118 |
-
|
119 |
'id' => 'display_character_counter',
|
120 |
-
'label' => esc_html__( 'Display character counters?', 'autodescription' ) .
|
121 |
'escape' => false,
|
122 |
] ),
|
123 |
],
|
@@ -125,14 +122,14 @@ switch ( $instance ) :
|
|
125 |
);
|
126 |
break;
|
127 |
|
128 |
-
case '
|
129 |
-
|
130 |
HTML::description( __( "Depending on your server's configuration, adjusting these settings can affect performance.", 'autodescription' ) );
|
131 |
|
132 |
?>
|
133 |
<hr>
|
134 |
<?php
|
135 |
-
|
136 |
HTML::description_noesc(
|
137 |
esc_html__( "Altering the query allows for more control of the site's hierarchy.", 'autodescription' )
|
138 |
. '<br>' .
|
@@ -185,9 +182,9 @@ switch ( $instance ) :
|
|
185 |
'<label for="%1$s">%2$s</label>
|
186 |
<select name="%3$s" id="%1$s">%4$s</select>',
|
187 |
[
|
188 |
-
|
189 |
$perform_alteration_i18n,
|
190 |
-
|
191 |
$search_query_select_options,
|
192 |
]
|
193 |
);
|
@@ -196,16 +193,16 @@ switch ( $instance ) :
|
|
196 |
'<label for="%1$s">%2$s</label>
|
197 |
<select name="%3$s" id="%1$s">%4$s</select>',
|
198 |
[
|
199 |
-
|
200 |
$perform_alteration_i18n,
|
201 |
-
|
202 |
$archive_query_select_options,
|
203 |
]
|
204 |
);
|
205 |
|
206 |
HTML::wrap_fields(
|
207 |
[
|
208 |
-
|
209 |
'id' => 'alter_search_query',
|
210 |
'label' => esc_html__( 'Enable search query alteration?', 'autodescription' )
|
211 |
. ' ' . HTML::make_info( __( 'This allows you to exclude pages from on-site search results.', 'autodescription' ), '', false ),
|
@@ -218,7 +215,7 @@ switch ( $instance ) :
|
|
218 |
|
219 |
HTML::wrap_fields(
|
220 |
[
|
221 |
-
|
222 |
'id' => 'alter_archive_query',
|
223 |
'label' => esc_html__( 'Enable archive query alteration?', 'autodescription' )
|
224 |
. ' ' . HTML::make_info( __( 'This allows you to exclude pages from on-site archive listings.', 'autodescription' ), '', false ),
|
@@ -231,11 +228,11 @@ switch ( $instance ) :
|
|
231 |
?>
|
232 |
<hr>
|
233 |
<?php
|
234 |
-
|
235 |
HTML::description( __( 'To improve performance, generated output can be stored in the database as transient cache.', 'autodescription' ) );
|
236 |
|
237 |
HTML::wrap_fields(
|
238 |
-
|
239 |
'id' => 'cache_sitemap',
|
240 |
'label' => esc_html__( 'Enable optimized sitemap generation cache?', 'autodescription' )
|
241 |
. ' ' . HTML::make_info( __( 'Generating the sitemap can use a lot of server resources.', 'autodescription' ), '', false ),
|
@@ -245,18 +242,18 @@ switch ( $instance ) :
|
|
245 |
);
|
246 |
break;
|
247 |
|
248 |
-
case '
|
249 |
-
|
250 |
HTML::description( __( 'The canonical URL meta tag urges search engines to go to the outputted URL.', 'autodescription' ) );
|
251 |
HTML::description( __( 'If the canonical URL meta tag represents the visited page, then the search engine will crawl the visited page. Otherwise, the search engine may go to the outputted URL.', 'autodescription' ) );
|
252 |
?>
|
253 |
<hr>
|
254 |
<?php
|
255 |
-
|
256 |
HTML::description( __( 'If your website is accessible via both HTTP as HTTPS, you may want to set this to HTTPS if not detected automatically. Secure connections are preferred by search engines.', 'autodescription' ) );
|
257 |
?>
|
258 |
-
<label for="<?php
|
259 |
-
<select name="<?php
|
260 |
<?php
|
261 |
$scheme_types = (array) apply_filters(
|
262 |
'the_seo_framework_canonical_scheme_types',
|
@@ -277,11 +274,11 @@ switch ( $instance ) :
|
|
277 |
|
278 |
<hr>
|
279 |
<?php
|
280 |
-
|
281 |
HTML::description( __( 'Some search engines look for relations between the content of your pages. If you have pagination on a post or page, or have archives indexed, these options will help search engines look for the right page to display in the search results.', 'autodescription' ) );
|
282 |
HTML::description( __( "It's recommended to turn these options on for better SEO consistency and to prevent duplicated content issues.", 'autodescription' ) );
|
283 |
|
284 |
-
$prev_next_posts_checkbox =
|
285 |
'id' => 'prev_next_posts',
|
286 |
'label' => $this->convert_markdown(
|
287 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
@@ -291,7 +288,7 @@ switch ( $instance ) :
|
|
291 |
'escape' => false,
|
292 |
] );
|
293 |
|
294 |
-
$prev_next_archives_checkbox =
|
295 |
'id' => 'prev_next_archives',
|
296 |
'label' => $this->convert_markdown(
|
297 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
@@ -301,7 +298,7 @@ switch ( $instance ) :
|
|
301 |
'escape' => false,
|
302 |
] );
|
303 |
|
304 |
-
$prev_next_frontpage_checkbox =
|
305 |
'id' => 'prev_next_frontpage',
|
306 |
'label' => $this->convert_markdown(
|
307 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
@@ -314,23 +311,23 @@ switch ( $instance ) :
|
|
314 |
HTML::wrap_fields( $prev_next_posts_checkbox . $prev_next_archives_checkbox . $prev_next_frontpage_checkbox, true );
|
315 |
break;
|
316 |
|
317 |
-
case '
|
318 |
$timestamp_0 = gmdate( $this->get_timestamp_format( false ) );
|
319 |
$timestamp_1 = gmdate( $this->get_timestamp_format( true ) );
|
320 |
|
321 |
-
|
322 |
HTML::description( __( 'Timestamps help indicate when a page has been published and modified.', 'autodescription' ) );
|
323 |
?>
|
324 |
<hr>
|
325 |
|
326 |
<fieldset>
|
327 |
-
<legend><?php
|
328 |
<?php HTML::description( __( 'This setting determines how specific the timestamp is.', 'autodescription' ) ); ?>
|
329 |
|
330 |
<p id="sitemaps-timestamp-format" class="tsf-fields">
|
331 |
<span class="tsf-toblock">
|
332 |
-
<input type="radio" name="<?php
|
333 |
-
<label for="<?php
|
334 |
<?php
|
335 |
// phpcs:ignore, WordPress.Security.EscapeOutput -- code_wrap escapes.
|
336 |
echo HTML::code_wrap( $timestamp_0 ), ' ', HTML::make_info(
|
@@ -340,8 +337,8 @@ switch ( $instance ) :
|
|
340 |
</label>
|
341 |
</span>
|
342 |
<span class="tsf-toblock">
|
343 |
-
<input type="radio" name="<?php
|
344 |
-
<label for="<?php
|
345 |
<?php
|
346 |
// phpcs:ignore, WordPress.Security.EscapeOutput -- code_wrap escapes.
|
347 |
echo HTML::code_wrap( $timestamp_1 ), ' ', HTML::make_info(
|
@@ -355,11 +352,8 @@ switch ( $instance ) :
|
|
355 |
<?php
|
356 |
break;
|
357 |
|
358 |
-
case '
|
359 |
-
|
360 |
-
$warned_options = $this->get_warned_site_options();
|
361 |
-
|
362 |
-
Form::header_title( __( 'Exclusion Settings', 'autodescription' ) );
|
363 |
HTML::description( __( 'When checked, these options will remove meta optimizations, SEO suggestions, and sitemap inclusions for the selected post types and taxonomies. This will allow search engines to crawl the post type and taxonomies without advanced restrictions or directions.', 'autodescription' ) );
|
364 |
HTML::attention_description_noesc(
|
365 |
$this->convert_markdown(
|
@@ -373,15 +367,13 @@ switch ( $instance ) :
|
|
373 |
|
374 |
<hr>
|
375 |
<?php
|
376 |
-
|
377 |
HTML::description( __( 'Select post types which should be excluded.', 'autodescription' ) );
|
378 |
HTML::description( __( 'These settings apply to the post type pages and their terms. When terms are shared between post types, all their post types should be checked for this to have an effect.', 'autodescription' ) );
|
379 |
|
380 |
$forced_pt = $this->get_forced_supported_post_types();
|
381 |
$boxes = [];
|
382 |
|
383 |
-
$pt_option_id = 'disabled_post_types';
|
384 |
-
|
385 |
foreach ( $this->get_public_post_types() as $post_type ) {
|
386 |
$_label = $this->get_post_type_label( $post_type, false );
|
387 |
if ( ! strlen( $_label ) ) continue;
|
@@ -392,15 +384,12 @@ switch ( $instance ) :
|
|
392 |
esc_html( $post_type )
|
393 |
);
|
394 |
|
395 |
-
$boxes[] =
|
396 |
-
'id' => $
|
397 |
'class' => 'tsf-excluded-post-types',
|
398 |
-
'index' => $post_type,
|
399 |
'label' => $_label,
|
400 |
'escape' => false,
|
401 |
'disabled' => in_array( $post_type, $forced_pt, true ),
|
402 |
-
'default' => ! empty( $default_options[ $pt_option_id ][ $post_type ] ),
|
403 |
-
'warned' => ! empty( $warned_options[ $pt_option_id ][ $post_type ] ),
|
404 |
] );
|
405 |
}
|
406 |
|
@@ -409,7 +398,7 @@ switch ( $instance ) :
|
|
409 |
?>
|
410 |
<hr>
|
411 |
<?php
|
412 |
-
|
413 |
HTML::description( __( 'Select taxonomies which should be excluded.', 'autodescription' ) );
|
414 |
HTML::description( __( 'When taxonomies have all their bound post types excluded, they will inherit their exclusion status.', 'autodescription' ) );
|
415 |
|
@@ -428,15 +417,12 @@ switch ( $instance ) :
|
|
428 |
esc_html( $taxonomy )
|
429 |
);
|
430 |
|
431 |
-
$boxes[] =
|
432 |
-
'id' => 'disabled_taxonomies',
|
433 |
'class' => 'tsf-excluded-taxonomies',
|
434 |
-
'index' => $taxonomy,
|
435 |
'label' => $_label,
|
436 |
'escape' => false,
|
437 |
'disabled' => in_array( $taxonomy, $forced_tax, true ),
|
438 |
-
'default' => ! empty( $default_options[ $tax_option_id ][ $taxonomy ] ),
|
439 |
-
'warned' => ! empty( $warned_options[ $tax_option_id ][ $taxonomy ] ),
|
440 |
'data' => [
|
441 |
'postTypes' => $this->get_post_types_from_taxonomy( $taxonomy ),
|
442 |
],
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
+
The_SEO_Framework\Interpreters\Settings_Input as Input;
|
13 |
|
14 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
15 |
|
16 |
+
switch ( $this->get_view_instance( 'general', $instance ) ) :
|
17 |
+
case 'general_main':
|
18 |
+
$_settings_class = SeoSettings::class;
|
19 |
|
20 |
+
$tabs = [
|
|
|
|
|
21 |
'layout' => [
|
22 |
'name' => __( 'Layout', 'autodescription' ),
|
23 |
+
'callback' => [ $_settings_class, '_general_metabox_layout_tab' ],
|
24 |
'dashicon' => 'screenoptions',
|
25 |
],
|
26 |
'performance' => [
|
27 |
'name' => __( 'Performance', 'autodescription' ),
|
28 |
+
'callback' => [ $_settings_class, '_general_metabox_performance_tab' ],
|
29 |
'dashicon' => 'performance',
|
30 |
],
|
31 |
'canonical' => [
|
32 |
'name' => __( 'Canonical', 'autodescription' ),
|
33 |
+
'callback' => [ $_settings_class, '_general_metabox_canonical_tab' ],
|
34 |
'dashicon' => 'external',
|
35 |
],
|
36 |
'timestamps' => [
|
37 |
'name' => __( 'Timestamps', 'autodescription' ),
|
38 |
+
'callback' => [ $_settings_class, '_general_metabox_timestamps_tab' ],
|
39 |
'dashicon' => 'clock',
|
40 |
],
|
41 |
'exclusions' => [
|
42 |
'name' => __( 'Exclusions', 'autodescription' ),
|
43 |
+
'callback' => [ $_settings_class, '_general_metabox_exclusions_tab' ],
|
44 |
'dashicon' => 'editor-unlink',
|
45 |
],
|
46 |
];
|
47 |
|
48 |
+
SeoSettings::_nav_tab_wrapper(
|
49 |
+
'general',
|
50 |
+
/**
|
51 |
+
* @since 2.8.0
|
52 |
+
* @param array $tabs The default tabs.
|
53 |
+
*/
|
54 |
+
(array) apply_filters( 'the_seo_framework_general_settings_tabs', $tabs )
|
55 |
+
);
|
|
|
|
|
56 |
break;
|
57 |
|
58 |
+
case 'general_layout_tab':
|
59 |
+
HTML::header_title( __( 'Administrative Layout Settings', 'autodescription' ) );
|
60 |
HTML::description( __( 'SEO hints can be visually displayed throughout the dashboard.', 'autodescription' ) );
|
61 |
|
62 |
?>
|
63 |
<hr>
|
64 |
<?php
|
65 |
+
HTML::header_title( __( 'SEO Bar Settings', 'autodescription' ) );
|
66 |
HTML::wrap_fields(
|
67 |
[
|
68 |
+
Input::make_checkbox( [
|
69 |
'id' => 'display_seo_bar_tables',
|
70 |
'label' => esc_html__( 'Display the SEO Bar in overview tables?', 'autodescription' ),
|
71 |
'escape' => false,
|
72 |
] ),
|
73 |
+
Input::make_checkbox( [
|
74 |
'id' => 'display_seo_bar_metabox',
|
75 |
'label' => esc_html__( 'Display the SEO Bar in the SEO Settings metabox?', 'autodescription' ),
|
76 |
'escape' => false,
|
77 |
] ),
|
78 |
+
Input::make_checkbox( [
|
79 |
'id' => 'seo_bar_symbols',
|
80 |
'label' => esc_html__( 'Use symbols for warnings?', 'autodescription' ) . ' ' . HTML::make_info(
|
81 |
__( 'If you have difficulty discerning colors, this may help you spot issues more easily.', 'autodescription' ),
|
91 |
?>
|
92 |
<hr>
|
93 |
<?php
|
94 |
+
HTML::header_title( __( 'Counter Settings', 'autodescription' ) );
|
95 |
|
96 |
$pixel_info = HTML::make_info(
|
97 |
__( 'The pixel counter computes whether the input will fit on search engine result pages.', 'autodescription' ),
|
107 |
|
108 |
HTML::wrap_fields(
|
109 |
[
|
110 |
+
Input::make_checkbox( [
|
111 |
'id' => 'display_pixel_counter',
|
112 |
+
'label' => esc_html__( 'Display pixel counters?', 'autodescription' ) . " $pixel_info",
|
113 |
'escape' => false,
|
114 |
] ),
|
115 |
+
Input::make_checkbox( [
|
116 |
'id' => 'display_character_counter',
|
117 |
+
'label' => esc_html__( 'Display character counters?', 'autodescription' ) . " $character_info",
|
118 |
'escape' => false,
|
119 |
] ),
|
120 |
],
|
122 |
);
|
123 |
break;
|
124 |
|
125 |
+
case 'general_performance_tab':
|
126 |
+
HTML::header_title( __( 'Performance Settings', 'autodescription' ) );
|
127 |
HTML::description( __( "Depending on your server's configuration, adjusting these settings can affect performance.", 'autodescription' ) );
|
128 |
|
129 |
?>
|
130 |
<hr>
|
131 |
<?php
|
132 |
+
HTML::header_title( __( 'Query Alteration Settings', 'autodescription' ) );
|
133 |
HTML::description_noesc(
|
134 |
esc_html__( "Altering the query allows for more control of the site's hierarchy.", 'autodescription' )
|
135 |
. '<br>' .
|
182 |
'<label for="%1$s">%2$s</label>
|
183 |
<select name="%3$s" id="%1$s">%4$s</select>',
|
184 |
[
|
185 |
+
Input::get_field_id( 'alter_search_query_type' ),
|
186 |
$perform_alteration_i18n,
|
187 |
+
Input::get_field_name( 'alter_search_query_type' ),
|
188 |
$search_query_select_options,
|
189 |
]
|
190 |
);
|
193 |
'<label for="%1$s">%2$s</label>
|
194 |
<select name="%3$s" id="%1$s">%4$s</select>',
|
195 |
[
|
196 |
+
Input::get_field_id( 'alter_archive_query_type' ),
|
197 |
$perform_alteration_i18n,
|
198 |
+
Input::get_field_name( 'alter_archive_query_type' ),
|
199 |
$archive_query_select_options,
|
200 |
]
|
201 |
);
|
202 |
|
203 |
HTML::wrap_fields(
|
204 |
[
|
205 |
+
Input::make_checkbox( [
|
206 |
'id' => 'alter_search_query',
|
207 |
'label' => esc_html__( 'Enable search query alteration?', 'autodescription' )
|
208 |
. ' ' . HTML::make_info( __( 'This allows you to exclude pages from on-site search results.', 'autodescription' ), '', false ),
|
215 |
|
216 |
HTML::wrap_fields(
|
217 |
[
|
218 |
+
Input::make_checkbox( [
|
219 |
'id' => 'alter_archive_query',
|
220 |
'label' => esc_html__( 'Enable archive query alteration?', 'autodescription' )
|
221 |
. ' ' . HTML::make_info( __( 'This allows you to exclude pages from on-site archive listings.', 'autodescription' ), '', false ),
|
228 |
?>
|
229 |
<hr>
|
230 |
<?php
|
231 |
+
HTML::header_title( __( 'Transient Cache Settings', 'autodescription' ) );
|
232 |
HTML::description( __( 'To improve performance, generated output can be stored in the database as transient cache.', 'autodescription' ) );
|
233 |
|
234 |
HTML::wrap_fields(
|
235 |
+
Input::make_checkbox( [
|
236 |
'id' => 'cache_sitemap',
|
237 |
'label' => esc_html__( 'Enable optimized sitemap generation cache?', 'autodescription' )
|
238 |
. ' ' . HTML::make_info( __( 'Generating the sitemap can use a lot of server resources.', 'autodescription' ), '', false ),
|
242 |
);
|
243 |
break;
|
244 |
|
245 |
+
case 'general_canonical_tab':
|
246 |
+
HTML::header_title( __( 'Canonical URL Settings', 'autodescription' ) );
|
247 |
HTML::description( __( 'The canonical URL meta tag urges search engines to go to the outputted URL.', 'autodescription' ) );
|
248 |
HTML::description( __( 'If the canonical URL meta tag represents the visited page, then the search engine will crawl the visited page. Otherwise, the search engine may go to the outputted URL.', 'autodescription' ) );
|
249 |
?>
|
250 |
<hr>
|
251 |
<?php
|
252 |
+
HTML::header_title( __( 'Scheme Settings', 'autodescription' ) );
|
253 |
HTML::description( __( 'If your website is accessible via both HTTP as HTTPS, you may want to set this to HTTPS if not detected automatically. Secure connections are preferred by search engines.', 'autodescription' ) );
|
254 |
?>
|
255 |
+
<label for="<?php Input::field_id( 'canonical_scheme' ); ?>"><?php echo esc_html_x( 'Preferred canonical URL scheme:', '= Detect Automatically, HTTPS, HTTP', 'autodescription' ); ?></label>
|
256 |
+
<select name="<?php Input::field_name( 'canonical_scheme' ); ?>" id="<?php Input::field_id( 'canonical_scheme' ); ?>">
|
257 |
<?php
|
258 |
$scheme_types = (array) apply_filters(
|
259 |
'the_seo_framework_canonical_scheme_types',
|
274 |
|
275 |
<hr>
|
276 |
<?php
|
277 |
+
HTML::header_title( __( 'Link Relationship Settings', 'autodescription' ) );
|
278 |
HTML::description( __( 'Some search engines look for relations between the content of your pages. If you have pagination on a post or page, or have archives indexed, these options will help search engines look for the right page to display in the search results.', 'autodescription' ) );
|
279 |
HTML::description( __( "It's recommended to turn these options on for better SEO consistency and to prevent duplicated content issues.", 'autodescription' ) );
|
280 |
|
281 |
+
$prev_next_posts_checkbox = Input::make_checkbox( [
|
282 |
'id' => 'prev_next_posts',
|
283 |
'label' => $this->convert_markdown(
|
284 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
288 |
'escape' => false,
|
289 |
] );
|
290 |
|
291 |
+
$prev_next_archives_checkbox = Input::make_checkbox( [
|
292 |
'id' => 'prev_next_archives',
|
293 |
'label' => $this->convert_markdown(
|
294 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
298 |
'escape' => false,
|
299 |
] );
|
300 |
|
301 |
+
$prev_next_frontpage_checkbox = Input::make_checkbox( [
|
302 |
'id' => 'prev_next_frontpage',
|
303 |
'label' => $this->convert_markdown(
|
304 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
311 |
HTML::wrap_fields( $prev_next_posts_checkbox . $prev_next_archives_checkbox . $prev_next_frontpage_checkbox, true );
|
312 |
break;
|
313 |
|
314 |
+
case 'general_timestamps_tab':
|
315 |
$timestamp_0 = gmdate( $this->get_timestamp_format( false ) );
|
316 |
$timestamp_1 = gmdate( $this->get_timestamp_format( true ) );
|
317 |
|
318 |
+
HTML::header_title( __( 'Timestamp Settings', 'autodescription' ) );
|
319 |
HTML::description( __( 'Timestamps help indicate when a page has been published and modified.', 'autodescription' ) );
|
320 |
?>
|
321 |
<hr>
|
322 |
|
323 |
<fieldset>
|
324 |
+
<legend><?php HTML::header_title( __( 'Timestamp Format Settings', 'autodescription' ) ); ?></legend>
|
325 |
<?php HTML::description( __( 'This setting determines how specific the timestamp is.', 'autodescription' ) ); ?>
|
326 |
|
327 |
<p id="sitemaps-timestamp-format" class="tsf-fields">
|
328 |
<span class="tsf-toblock">
|
329 |
+
<input type="radio" name="<?php Input::field_name( 'timestamps_format' ); ?>" id="<?php Input::field_id( 'timestamps_format_0' ); ?>" value="0" <?php checked( $this->get_option( 'timestamps_format' ), '0' ); ?> />
|
330 |
+
<label for="<?php Input::field_id( 'timestamps_format_0' ); ?>">
|
331 |
<?php
|
332 |
// phpcs:ignore, WordPress.Security.EscapeOutput -- code_wrap escapes.
|
333 |
echo HTML::code_wrap( $timestamp_0 ), ' ', HTML::make_info(
|
337 |
</label>
|
338 |
</span>
|
339 |
<span class="tsf-toblock">
|
340 |
+
<input type="radio" name="<?php Input::field_name( 'timestamps_format' ); ?>" id="<?php Input::field_id( 'timestamps_format_1' ); ?>" value="1" <?php checked( $this->get_option( 'timestamps_format' ), '1' ); ?> />
|
341 |
+
<label for="<?php Input::field_id( 'timestamps_format_1' ); ?>">
|
342 |
<?php
|
343 |
// phpcs:ignore, WordPress.Security.EscapeOutput -- code_wrap escapes.
|
344 |
echo HTML::code_wrap( $timestamp_1 ), ' ', HTML::make_info(
|
352 |
<?php
|
353 |
break;
|
354 |
|
355 |
+
case 'general_exclusions_tab':
|
356 |
+
HTML::header_title( __( 'Exclusion Settings', 'autodescription' ) );
|
|
|
|
|
|
|
357 |
HTML::description( __( 'When checked, these options will remove meta optimizations, SEO suggestions, and sitemap inclusions for the selected post types and taxonomies. This will allow search engines to crawl the post type and taxonomies without advanced restrictions or directions.', 'autodescription' ) );
|
358 |
HTML::attention_description_noesc(
|
359 |
$this->convert_markdown(
|
367 |
|
368 |
<hr>
|
369 |
<?php
|
370 |
+
HTML::header_title( __( 'Post Type Exclusions', 'autodescription' ) );
|
371 |
HTML::description( __( 'Select post types which should be excluded.', 'autodescription' ) );
|
372 |
HTML::description( __( 'These settings apply to the post type pages and their terms. When terms are shared between post types, all their post types should be checked for this to have an effect.', 'autodescription' ) );
|
373 |
|
374 |
$forced_pt = $this->get_forced_supported_post_types();
|
375 |
$boxes = [];
|
376 |
|
|
|
|
|
377 |
foreach ( $this->get_public_post_types() as $post_type ) {
|
378 |
$_label = $this->get_post_type_label( $post_type, false );
|
379 |
if ( ! strlen( $_label ) ) continue;
|
384 |
esc_html( $post_type )
|
385 |
);
|
386 |
|
387 |
+
$boxes[] = Input::make_checkbox( [
|
388 |
+
'id' => [ 'disabled_post_types', $post_type ],
|
389 |
'class' => 'tsf-excluded-post-types',
|
|
|
390 |
'label' => $_label,
|
391 |
'escape' => false,
|
392 |
'disabled' => in_array( $post_type, $forced_pt, true ),
|
|
|
|
|
393 |
] );
|
394 |
}
|
395 |
|
398 |
?>
|
399 |
<hr>
|
400 |
<?php
|
401 |
+
HTML::header_title( __( 'Taxonomy Exclusions', 'autodescription' ) );
|
402 |
HTML::description( __( 'Select taxonomies which should be excluded.', 'autodescription' ) );
|
403 |
HTML::description( __( 'When taxonomies have all their bound post types excluded, they will inherit their exclusion status.', 'autodescription' ) );
|
404 |
|
417 |
esc_html( $taxonomy )
|
418 |
);
|
419 |
|
420 |
+
$boxes[] = Input::make_checkbox( [
|
421 |
+
'id' => [ 'disabled_taxonomies', $taxonomy ],
|
422 |
'class' => 'tsf-excluded-taxonomies',
|
|
|
423 |
'label' => $_label,
|
424 |
'escape' => false,
|
425 |
'disabled' => in_array( $taxonomy, $forced_tax, true ),
|
|
|
|
|
426 |
'data' => [
|
427 |
'postTypes' => $this->get_post_types_from_taxonomy( $taxonomy ),
|
428 |
],
|
@@ -9,66 +9,60 @@
|
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
-
The_SEO_Framework\Interpreters\Form
|
|
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
-
|
16 |
-
// Fetch the required instance within this file.
|
17 |
-
$instance = $this->get_view_instance( 'the_seo_framework_homepage_metabox', $instance );
|
18 |
|
19 |
$home_id = $this->get_the_front_page_ID();
|
20 |
|
21 |
-
$_generator_args = [
|
22 |
-
'id' => $home_id,
|
23 |
-
'taxonomy' => '',
|
24 |
-
];
|
25 |
|
26 |
-
switch ( $instance ) :
|
27 |
-
case '
|
28 |
HTML::description( __( 'These settings will take precedence over the settings set within the homepage edit screen, if any.', 'autodescription' ) );
|
29 |
?>
|
30 |
<hr>
|
31 |
<?php
|
|
|
32 |
|
33 |
-
$
|
34 |
'general' => [
|
35 |
'name' => __( 'General', 'autodescription' ),
|
36 |
-
'callback' =>
|
37 |
'dashicon' => 'admin-generic',
|
38 |
],
|
39 |
'additions' => [
|
40 |
'name' => __( 'Additions', 'autodescription' ),
|
41 |
-
'callback' =>
|
42 |
-
'dashicon' => 'plus',
|
43 |
],
|
44 |
'social' => [
|
45 |
'name' => __( 'Social', 'autodescription' ),
|
46 |
-
'callback' =>
|
47 |
'dashicon' => 'share',
|
48 |
],
|
49 |
'robots' => [
|
50 |
'name' => __( 'Robots', 'autodescription' ),
|
51 |
-
'callback' =>
|
52 |
'dashicon' => 'visibility',
|
53 |
],
|
54 |
];
|
55 |
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
SeoSettings::_nav_tab_wrapper( 'homepage', $tabs );
|
66 |
break;
|
67 |
|
68 |
-
case '
|
69 |
?>
|
70 |
<p>
|
71 |
-
<label for="<?php
|
72 |
<strong><?php esc_html_e( 'Meta Title', 'autodescription' ); ?></strong>
|
73 |
<?php
|
74 |
echo ' ';
|
@@ -81,24 +75,25 @@ switch ( $instance ) :
|
|
81 |
</p>
|
82 |
<?php
|
83 |
// Output these unconditionally, with inline CSS attached to allow reacting on settings.
|
84 |
-
Form::output_character_counter_wrap(
|
85 |
-
Form::output_pixel_counter_wrap(
|
86 |
?>
|
87 |
<p class=tsf-title-wrap>
|
88 |
-
<input type="text" name="<?php
|
89 |
<?php
|
90 |
$this->output_js_title_elements(); // legacy
|
91 |
$this->output_js_title_data(
|
92 |
-
|
93 |
[
|
94 |
'state' => [
|
95 |
'refTitleLocked' => false,
|
96 |
-
'defaultTitle' =>
|
97 |
( $home_id ? $this->get_post_meta_item( '_genesis_title', $home_id ) : '' )
|
98 |
-
?: $this->get_filtered_raw_generated_title( $_generator_args )
|
|
|
99 |
'addAdditions' => $this->use_title_branding( $_generator_args ),
|
100 |
'useSocialTagline' => $this->use_title_branding( $_generator_args, true ),
|
101 |
-
'additionValue' => $this->get_home_title_additions(),
|
102 |
'additionPlacement' => 'left' === $this->get_home_title_seplocation() ? 'before' : 'after',
|
103 |
'hasLegacy' => true,
|
104 |
],
|
@@ -109,9 +104,8 @@ switch ( $instance ) :
|
|
109 |
<?php
|
110 |
HTML::description( __( 'Note: The input value of this field may be used to describe the name of the site elsewhere.', 'autodescription' ) );
|
111 |
|
112 |
-
if ( $home_id && $this->get_post_meta_item( '_genesis_title', $home_id ) )
|
113 |
HTML::description( __( 'Note: The title placeholder is fetched from the Page SEO Settings on the homepage.', 'autodescription' ) );
|
114 |
-
}
|
115 |
|
116 |
/**
|
117 |
* @since 2.8.0
|
@@ -124,7 +118,7 @@ switch ( $instance ) :
|
|
124 |
sprintf(
|
125 |
/* translators: %s = Homepage URL markdown */
|
126 |
esc_html__( 'A plugin has been detected that suggests to maintain this option on the [homepage](%s).', 'autodescription' ),
|
127 |
-
esc_url( admin_url(
|
128 |
),
|
129 |
[ 'a' ],
|
130 |
[ 'a_internal' => false ] // opens in new tab.
|
@@ -135,7 +129,7 @@ switch ( $instance ) :
|
|
135 |
<hr>
|
136 |
|
137 |
<p>
|
138 |
-
<label for="<?php
|
139 |
<strong><?php esc_html_e( 'Meta Description', 'autodescription' ); ?></strong>
|
140 |
<?php
|
141 |
echo ' ';
|
@@ -148,15 +142,15 @@ switch ( $instance ) :
|
|
148 |
</p>
|
149 |
<?php
|
150 |
// Output these unconditionally, with inline CSS attached to allow reacting on settings.
|
151 |
-
Form::output_character_counter_wrap(
|
152 |
-
Form::output_pixel_counter_wrap(
|
153 |
?>
|
154 |
<p>
|
155 |
-
<textarea name="<?php
|
156 |
<?php
|
157 |
$this->output_js_description_elements(); // legacy
|
158 |
$this->output_js_description_data(
|
159 |
-
|
160 |
[
|
161 |
'state' => [
|
162 |
'defaultDescription' =>
|
@@ -187,7 +181,7 @@ switch ( $instance ) :
|
|
187 |
sprintf(
|
188 |
/* translators: %s = Homepage URL markdown */
|
189 |
esc_html__( 'A plugin has been detected that suggests to maintain this option on the [homepage](%s).', 'autodescription' ),
|
190 |
-
esc_url( admin_url(
|
191 |
),
|
192 |
[ 'a' ],
|
193 |
[ 'a_internal' => false ] // opens in new tab.
|
@@ -196,37 +190,38 @@ switch ( $instance ) :
|
|
196 |
}
|
197 |
break;
|
198 |
|
199 |
-
case '
|
200 |
-
$tagline_placeholder = $this->s_title_raw( $this->get_blogdescription() );
|
201 |
-
|
202 |
// Fetches escaped title parts.
|
203 |
$_example_title = $this->escape_title(
|
204 |
-
$this->get_filtered_raw_custom_field_title( $_generator_args )
|
|
|
205 |
);
|
206 |
// On JS: The 'Untitled' title will disappear, this is intentional. On no-JS one will see 'Untitled'.
|
207 |
// TODO: Deprecate no-JS support? WordPress doesn't function without JS since 5.0 anyway...
|
208 |
-
$_example_blogname = $this->escape_title(
|
|
|
|
|
|
|
209 |
$_example_separator = esc_html( $this->get_separator( 'title' ) );
|
210 |
|
211 |
// TODO very readable.
|
212 |
-
$example_left =
|
213 |
-
$example_right =
|
214 |
|
215 |
?>
|
216 |
-
|
217 |
<p>
|
218 |
-
<label for="<?php
|
219 |
<strong><?php esc_html_e( 'Meta Title Additions', 'autodescription' ); ?></strong>
|
220 |
</label>
|
221 |
</p>
|
222 |
<p>
|
223 |
-
<input type="text" name="<?php
|
224 |
</p>
|
225 |
|
226 |
-
<div
|
227 |
<?php
|
228 |
HTML::wrap_fields(
|
229 |
-
|
230 |
'id' => 'homepage_tagline',
|
231 |
'label' => __( 'Add Meta Title Additions to the homepage title?', 'autodescription' ),
|
232 |
] ),
|
@@ -238,12 +233,12 @@ switch ( $instance ) :
|
|
238 |
<hr>
|
239 |
|
240 |
<fieldset>
|
241 |
-
<legend><?php
|
242 |
|
243 |
<p id="tsf-home-title-location" class="tsf-fields">
|
244 |
<span class="tsf-toblock">
|
245 |
-
<input type="radio" name="<?php
|
246 |
-
<label for="<?php
|
247 |
<span><?php esc_html_e( 'Left:', 'autodescription' ); ?></span>
|
248 |
<?php
|
249 |
// phpcs:ignore, WordPress.Security.EscapeOutput -- $example_left is already escaped.
|
@@ -252,8 +247,8 @@ switch ( $instance ) :
|
|
252 |
</label>
|
253 |
</span>
|
254 |
<span class="tsf-toblock">
|
255 |
-
<input type="radio" name="<?php
|
256 |
-
<label for="<?php
|
257 |
<span><?php esc_html_e( 'Right:', 'autodescription' ); ?></span>
|
258 |
<?php
|
259 |
// phpcs:ignore, WordPress.Security.EscapeOutput -- $example_right is already escaped.
|
@@ -266,31 +261,60 @@ switch ( $instance ) :
|
|
266 |
<?php
|
267 |
break;
|
268 |
|
269 |
-
case '
|
|
|
|
|
|
|
|
|
|
|
270 |
// Gets custom fields from page.
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
|
|
|
|
275 |
|
276 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
277 |
|
278 |
?>
|
279 |
<p>
|
280 |
-
<label for="<?php
|
281 |
-
<strong>
|
282 |
-
<?php
|
283 |
-
esc_html_e( 'Open Graph Title', 'autodescription' );
|
284 |
-
?>
|
285 |
-
</strong>
|
286 |
</label>
|
287 |
</p>
|
288 |
<?php
|
289 |
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
290 |
-
Form::output_character_counter_wrap(
|
291 |
?>
|
292 |
<p>
|
293 |
-
<input type="text" name="<?php
|
294 |
</p>
|
295 |
<?php
|
296 |
if ( $this->has_page_on_front() && $custom_og_title ) {
|
@@ -301,20 +325,16 @@ switch ( $instance ) :
|
|
301 |
?>
|
302 |
|
303 |
<p>
|
304 |
-
<label for="<?php
|
305 |
-
<strong>
|
306 |
-
<?php
|
307 |
-
esc_html_e( 'Open Graph Description', 'autodescription' );
|
308 |
-
?>
|
309 |
-
</strong>
|
310 |
</label>
|
311 |
</p>
|
312 |
<?php
|
313 |
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
314 |
-
Form::output_character_counter_wrap(
|
315 |
?>
|
316 |
<p>
|
317 |
-
<textarea name="<?php
|
318 |
</p>
|
319 |
<?php
|
320 |
if ( $this->has_page_on_front() && $custom_og_desc ) {
|
@@ -326,20 +346,16 @@ switch ( $instance ) :
|
|
326 |
<hr>
|
327 |
|
328 |
<p>
|
329 |
-
<label for="<?php
|
330 |
-
<strong>
|
331 |
-
<?php
|
332 |
-
esc_html_e( 'Twitter Title', 'autodescription' );
|
333 |
-
?>
|
334 |
-
</strong>
|
335 |
</label>
|
336 |
</p>
|
337 |
<?php
|
338 |
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
339 |
-
Form::output_character_counter_wrap(
|
340 |
?>
|
341 |
<p>
|
342 |
-
<input type="text" name="<?php
|
343 |
</p>
|
344 |
<?php
|
345 |
if ( $this->has_page_on_front() && ( $custom_og_title || $custom_tw_title ) ) {
|
@@ -350,20 +366,16 @@ switch ( $instance ) :
|
|
350 |
?>
|
351 |
|
352 |
<p>
|
353 |
-
<label for="<?php
|
354 |
-
<strong>
|
355 |
-
<?php
|
356 |
-
esc_html_e( 'Twitter Description', 'autodescription' );
|
357 |
-
?>
|
358 |
-
</strong>
|
359 |
</label>
|
360 |
</p>
|
361 |
<?php
|
362 |
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
363 |
-
Form::output_character_counter_wrap(
|
364 |
?>
|
365 |
<p>
|
366 |
-
<textarea name="<?php
|
367 |
</p>
|
368 |
<?php
|
369 |
if ( $this->has_page_on_front() && ( $custom_og_desc || $custom_tw_desc ) ) {
|
@@ -374,13 +386,8 @@ switch ( $instance ) :
|
|
374 |
?>
|
375 |
<hr>
|
376 |
<?php
|
377 |
-
|
378 |
HTML::description( __( 'A social image can be displayed when your homepage is shared. It is a great way to grab attention.', 'autodescription' ) );
|
379 |
-
|
380 |
-
// Fetch image placeholder.
|
381 |
-
$image_details = current( $this->get_generated_image_details( $_generator_args, true, 'social', true ) );
|
382 |
-
$image_placeholder = isset( $image_details['url'] ) ? $image_details['url'] : '';
|
383 |
-
|
384 |
?>
|
385 |
<p>
|
386 |
<label for="tsf_homepage_socialimage-url">
|
@@ -394,8 +401,8 @@ switch ( $instance ) :
|
|
394 |
</label>
|
395 |
</p>
|
396 |
<p>
|
397 |
-
<input class="large-text" type="url" name="<?php
|
398 |
-
<input type="hidden" name="<?php
|
399 |
</p>
|
400 |
<p class="hide-if-no-tsf-js">
|
401 |
<?php
|
@@ -406,7 +413,7 @@ switch ( $instance ) :
|
|
406 |
<?php
|
407 |
break;
|
408 |
|
409 |
-
case '
|
410 |
$noindex_post = $home_id ? $this->get_post_meta_item( '_genesis_noindex', $home_id ) : '';
|
411 |
$nofollow_post = $home_id ? $this->get_post_meta_item( '_genesis_nofollow', $home_id ) : '';
|
412 |
$noarchive_post = $home_id ? $this->get_post_meta_item( '_genesis_noarchive', $home_id ) : '';
|
@@ -424,7 +431,7 @@ switch ( $instance ) :
|
|
424 |
vsprintf(
|
425 |
'<a href="%s" title="%s" target=_blank class=attention>%s</a>',
|
426 |
[
|
427 |
-
esc_url( admin_url(
|
428 |
esc_attr_x( 'Edit homepage page settings', 'Bear with me: the homepage can be edited globally, or via its page. Thus "homepage page".', 'autodescription' ),
|
429 |
esc_html__( 'Overwritten by page settings', 'autodescription' ),
|
430 |
]
|
@@ -432,7 +439,7 @@ switch ( $instance ) :
|
|
432 |
);
|
433 |
}
|
434 |
|
435 |
-
|
436 |
|
437 |
$i_label = sprintf(
|
438 |
/* translators: 1: Option label, 2: [?] option info note, 3: Optional warning */
|
@@ -486,17 +493,17 @@ switch ( $instance ) :
|
|
486 |
|
487 |
HTML::wrap_fields(
|
488 |
[
|
489 |
-
|
490 |
'id' => 'homepage_noindex',
|
491 |
'label' => $i_label,
|
492 |
'escape' => false,
|
493 |
] ),
|
494 |
-
|
495 |
'id' => 'homepage_nofollow',
|
496 |
'label' => $f_label,
|
497 |
'escape' => false,
|
498 |
] ),
|
499 |
-
|
500 |
'id' => 'homepage_noarchive',
|
501 |
'label' => $a_label,
|
502 |
'escape' => false,
|
@@ -511,7 +518,7 @@ switch ( $instance ) :
|
|
511 |
sprintf(
|
512 |
/* translators: %s = Homepage URL markdown */
|
513 |
esc_html__( 'Note: These options may be overwritten by the [page settings](%s).', 'autodescription' ),
|
514 |
-
esc_url( admin_url(
|
515 |
),
|
516 |
[ 'a' ],
|
517 |
[ 'a_internal' => false ]
|
@@ -522,12 +529,11 @@ switch ( $instance ) :
|
|
522 |
|
523 |
<hr>
|
524 |
<?php
|
525 |
-
|
526 |
HTML::description( __( "If your homepage is paginated and outputs content that's also found elsewhere on the website, enabling this option may prevent duplicate content.", 'autodescription' ) );
|
527 |
|
528 |
-
// Echo checkbox.
|
529 |
HTML::wrap_fields(
|
530 |
-
|
531 |
'id' => 'home_paged_noindex',
|
532 |
'label' => $this->convert_markdown(
|
533 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
+
The_SEO_Framework\Interpreters\Form,
|
13 |
+
The_SEO_Framework\Interpreters\Settings_Input as Input;
|
14 |
|
15 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
|
|
|
|
|
|
16 |
|
17 |
$home_id = $this->get_the_front_page_ID();
|
18 |
|
19 |
+
$_generator_args = [ 'id' => $home_id ];
|
|
|
|
|
|
|
20 |
|
21 |
+
switch ( $this->get_view_instance( 'homepage', $instance ) ) :
|
22 |
+
case 'homepage_main':
|
23 |
HTML::description( __( 'These settings will take precedence over the settings set within the homepage edit screen, if any.', 'autodescription' ) );
|
24 |
?>
|
25 |
<hr>
|
26 |
<?php
|
27 |
+
$_settings_class = SeoSettings::class;
|
28 |
|
29 |
+
$tabs = [
|
30 |
'general' => [
|
31 |
'name' => __( 'General', 'autodescription' ),
|
32 |
+
'callback' => [ $_settings_class, '_homepage_metabox_general_tab' ],
|
33 |
'dashicon' => 'admin-generic',
|
34 |
],
|
35 |
'additions' => [
|
36 |
'name' => __( 'Additions', 'autodescription' ),
|
37 |
+
'callback' => [ $_settings_class, '_homepage_metabox_additions_tab' ],
|
38 |
+
'dashicon' => 'plus-alt2',
|
39 |
],
|
40 |
'social' => [
|
41 |
'name' => __( 'Social', 'autodescription' ),
|
42 |
+
'callback' => [ $_settings_class, '_homepage_metabox_social_tab' ],
|
43 |
'dashicon' => 'share',
|
44 |
],
|
45 |
'robots' => [
|
46 |
'name' => __( 'Robots', 'autodescription' ),
|
47 |
+
'callback' => [ $_settings_class, '_homepage_metabox_robots_tab' ],
|
48 |
'dashicon' => 'visibility',
|
49 |
],
|
50 |
];
|
51 |
|
52 |
+
SeoSettings::_nav_tab_wrapper(
|
53 |
+
'homepage',
|
54 |
+
/**
|
55 |
+
* @since 2.6.0
|
56 |
+
* @param array $tabs The default tabs.
|
57 |
+
*/
|
58 |
+
(array) apply_filters( 'the_seo_framework_homepage_settings_tabs', $tabs )
|
59 |
+
);
|
|
|
|
|
60 |
break;
|
61 |
|
62 |
+
case 'homepage_general_tab':
|
63 |
?>
|
64 |
<p>
|
65 |
+
<label for="<?php Input::field_id( 'homepage_title' ); ?>" class="tsf-toblock">
|
66 |
<strong><?php esc_html_e( 'Meta Title', 'autodescription' ); ?></strong>
|
67 |
<?php
|
68 |
echo ' ';
|
75 |
</p>
|
76 |
<?php
|
77 |
// Output these unconditionally, with inline CSS attached to allow reacting on settings.
|
78 |
+
Form::output_character_counter_wrap( Input::get_field_id( 'homepage_title' ), (bool) $this->get_option( 'display_character_counter' ) );
|
79 |
+
Form::output_pixel_counter_wrap( Input::get_field_id( 'homepage_title' ), 'title', (bool) $this->get_option( 'display_pixel_counter' ) );
|
80 |
?>
|
81 |
<p class=tsf-title-wrap>
|
82 |
+
<input type="text" name="<?php Input::field_name( 'homepage_title' ); ?>" class="large-text" id="<?php Input::field_id( 'homepage_title' ); ?>" value="<?php echo $this->esc_attr_preserve_amp( $this->get_option( 'homepage_title' ) ); ?>" autocomplete=off />
|
83 |
<?php
|
84 |
$this->output_js_title_elements(); // legacy
|
85 |
$this->output_js_title_data(
|
86 |
+
Input::get_field_id( 'homepage_title' ),
|
87 |
[
|
88 |
'state' => [
|
89 |
'refTitleLocked' => false,
|
90 |
+
'defaultTitle' => $this->s_title(
|
91 |
( $home_id ? $this->get_post_meta_item( '_genesis_title', $home_id ) : '' )
|
92 |
+
?: $this->get_filtered_raw_generated_title( $_generator_args )
|
93 |
+
),
|
94 |
'addAdditions' => $this->use_title_branding( $_generator_args ),
|
95 |
'useSocialTagline' => $this->use_title_branding( $_generator_args, true ),
|
96 |
+
'additionValue' => $this->s_title( $this->get_home_title_additions() ),
|
97 |
'additionPlacement' => 'left' === $this->get_home_title_seplocation() ? 'before' : 'after',
|
98 |
'hasLegacy' => true,
|
99 |
],
|
104 |
<?php
|
105 |
HTML::description( __( 'Note: The input value of this field may be used to describe the name of the site elsewhere.', 'autodescription' ) );
|
106 |
|
107 |
+
if ( $home_id && $this->get_post_meta_item( '_genesis_title', $home_id ) )
|
108 |
HTML::description( __( 'Note: The title placeholder is fetched from the Page SEO Settings on the homepage.', 'autodescription' ) );
|
|
|
109 |
|
110 |
/**
|
111 |
* @since 2.8.0
|
118 |
sprintf(
|
119 |
/* translators: %s = Homepage URL markdown */
|
120 |
esc_html__( 'A plugin has been detected that suggests to maintain this option on the [homepage](%s).', 'autodescription' ),
|
121 |
+
esc_url( admin_url( "post.php?post={$home_id}&action=edit#tsf-inpost-box" ) )
|
122 |
),
|
123 |
[ 'a' ],
|
124 |
[ 'a_internal' => false ] // opens in new tab.
|
129 |
<hr>
|
130 |
|
131 |
<p>
|
132 |
+
<label for="<?php Input::field_id( 'homepage_description' ); ?>" class="tsf-toblock">
|
133 |
<strong><?php esc_html_e( 'Meta Description', 'autodescription' ); ?></strong>
|
134 |
<?php
|
135 |
echo ' ';
|
142 |
</p>
|
143 |
<?php
|
144 |
// Output these unconditionally, with inline CSS attached to allow reacting on settings.
|
145 |
+
Form::output_character_counter_wrap( Input::get_field_id( 'homepage_description' ), (bool) $this->get_option( 'display_character_counter' ) );
|
146 |
+
Form::output_pixel_counter_wrap( Input::get_field_id( 'homepage_description' ), 'description', (bool) $this->get_option( 'display_pixel_counter' ) );
|
147 |
?>
|
148 |
<p>
|
149 |
+
<textarea name="<?php Input::field_name( 'homepage_description' ); ?>" class="large-text" id="<?php Input::field_id( 'homepage_description' ); ?>" rows="3" cols="70"><?php echo esc_attr( $this->get_option( 'homepage_description' ) ); ?></textarea>
|
150 |
<?php
|
151 |
$this->output_js_description_elements(); // legacy
|
152 |
$this->output_js_description_data(
|
153 |
+
Input::get_field_id( 'homepage_description' ),
|
154 |
[
|
155 |
'state' => [
|
156 |
'defaultDescription' =>
|
181 |
sprintf(
|
182 |
/* translators: %s = Homepage URL markdown */
|
183 |
esc_html__( 'A plugin has been detected that suggests to maintain this option on the [homepage](%s).', 'autodescription' ),
|
184 |
+
esc_url( admin_url( "post.php?post=$home_id&action=edit#tsf-inpost-box" ) )
|
185 |
),
|
186 |
[ 'a' ],
|
187 |
[ 'a_internal' => false ] // opens in new tab.
|
190 |
}
|
191 |
break;
|
192 |
|
193 |
+
case 'homepage_additions_tab':
|
|
|
|
|
194 |
// Fetches escaped title parts.
|
195 |
$_example_title = $this->escape_title(
|
196 |
+
$this->get_filtered_raw_custom_field_title( $_generator_args )
|
197 |
+
?: $this->get_filtered_raw_generated_title( $_generator_args )
|
198 |
);
|
199 |
// On JS: The 'Untitled' title will disappear, this is intentional. On no-JS one will see 'Untitled'.
|
200 |
// TODO: Deprecate no-JS support? WordPress doesn't function without JS since 5.0 anyway...
|
201 |
+
$_example_blogname = $this->escape_title(
|
202 |
+
$this->get_home_title_additions()
|
203 |
+
?: $this->get_static_untitled_title()
|
204 |
+
);
|
205 |
$_example_separator = esc_html( $this->get_separator( 'title' ) );
|
206 |
|
207 |
// TODO very readable.
|
208 |
+
$example_left = "<em><span class=tsf-custom-blogname-js><span class=tsf-custom-tagline-js>$_example_blogname</span><span class=tsf-sep-js> $_example_separator </span></span><span class=tsf-custom-title-js>$_example_title</span></em>";
|
209 |
+
$example_right = "<em><span class=tsf-custom-title-js>$_example_title</span><span class=tsf-custom-blogname-js><span class=tsf-sep-js> $_example_separator </span><span class=tsf-custom-tagline-js>$_example_blogname</span></span></em>";
|
210 |
|
211 |
?>
|
|
|
212 |
<p>
|
213 |
+
<label for="<?php Input::field_id( 'homepage_title_tagline' ); ?>" class="tsf-toblock">
|
214 |
<strong><?php esc_html_e( 'Meta Title Additions', 'autodescription' ); ?></strong>
|
215 |
</label>
|
216 |
</p>
|
217 |
<p>
|
218 |
+
<input type="text" name="<?php Input::field_name( 'homepage_title_tagline' ); ?>" class="large-text" id="<?php Input::field_id( 'homepage_title_tagline' ); ?>" placeholder="<?php echo esc_attr( $this->s_title_raw( $this->get_blogdescription() ) ); ?>" value="<?php echo $this->esc_attr_preserve_amp( $this->get_option( 'homepage_title_tagline' ) ); ?>" autocomplete=off />
|
219 |
</p>
|
220 |
|
221 |
+
<div class=tsf-title-tagline-toggle>
|
222 |
<?php
|
223 |
HTML::wrap_fields(
|
224 |
+
Input::make_checkbox( [
|
225 |
'id' => 'homepage_tagline',
|
226 |
'label' => __( 'Add Meta Title Additions to the homepage title?', 'autodescription' ),
|
227 |
] ),
|
233 |
<hr>
|
234 |
|
235 |
<fieldset>
|
236 |
+
<legend><?php HTML::header_title( __( 'Meta Title Additions Location', 'autodescription' ) ); ?></legend>
|
237 |
|
238 |
<p id="tsf-home-title-location" class="tsf-fields">
|
239 |
<span class="tsf-toblock">
|
240 |
+
<input type="radio" name="<?php Input::field_name( 'home_title_location' ); ?>" id="<?php Input::field_id( 'home_title_location_left' ); ?>" value="left" <?php checked( $this->get_option( 'home_title_location' ), 'left' ); ?> />
|
241 |
+
<label for="<?php Input::field_id( 'home_title_location_left' ); ?>">
|
242 |
<span><?php esc_html_e( 'Left:', 'autodescription' ); ?></span>
|
243 |
<?php
|
244 |
// phpcs:ignore, WordPress.Security.EscapeOutput -- $example_left is already escaped.
|
247 |
</label>
|
248 |
</span>
|
249 |
<span class="tsf-toblock">
|
250 |
+
<input type="radio" name="<?php Input::field_name( 'home_title_location' ); ?>" id="<?php Input::field_id( 'home_title_location_right' ); ?>" value="right" <?php checked( $this->get_option( 'home_title_location' ), 'right' ); ?> />
|
251 |
+
<label for="<?php Input::field_id( 'home_title_location_right' ); ?>">
|
252 |
<span><?php esc_html_e( 'Right:', 'autodescription' ); ?></span>
|
253 |
<?php
|
254 |
// phpcs:ignore, WordPress.Security.EscapeOutput -- $example_right is already escaped.
|
261 |
<?php
|
262 |
break;
|
263 |
|
264 |
+
case 'homepage_social_tab':
|
265 |
+
$custom_og_title = '';
|
266 |
+
$custom_og_desc = '';
|
267 |
+
$custom_tw_title = '';
|
268 |
+
$custom_tw_desc = '';
|
269 |
+
|
270 |
// Gets custom fields from page.
|
271 |
+
if ( $home_id ) {
|
272 |
+
$custom_og_title = $this->get_post_meta_item( '_open_graph_title', $home_id );
|
273 |
+
$custom_og_desc = $this->get_post_meta_item( '_open_graph_description', $home_id );
|
274 |
+
$custom_tw_title = $this->get_post_meta_item( '_twitter_title', $home_id );
|
275 |
+
$custom_tw_desc = $this->get_post_meta_item( '_twitter_description', $home_id );
|
276 |
+
}
|
277 |
|
278 |
+
$this->output_js_social_data(
|
279 |
+
'homepage_social_settings',
|
280 |
+
[
|
281 |
+
'og' => [
|
282 |
+
'state' => [
|
283 |
+
'defaultTitle' => $this->s_title( $custom_og_title ?: $this->get_generated_open_graph_title( $_generator_args, false ) ),
|
284 |
+
'addAdditions' => $this->use_title_branding( $_generator_args, 'og' ),
|
285 |
+
'defaultDesc' => $this->s_description(
|
286 |
+
$custom_og_desc ?: $this->get_generated_open_graph_description( $_generator_args, false )
|
287 |
+
),
|
288 |
+
'titlePhLock' => (bool) $custom_og_title,
|
289 |
+
'descPhLock' => (bool) $custom_og_desc,
|
290 |
+
],
|
291 |
+
],
|
292 |
+
'tw' => [
|
293 |
+
'state' => [
|
294 |
+
'defaultTitle' => $this->s_title( $custom_tw_title ?: $this->get_generated_twitter_title( $_generator_args, false ) ),
|
295 |
+
'addAdditions' => $this->use_title_branding( $_generator_args, 'twitter' ),
|
296 |
+
'defaultDesc' => $this->s_description(
|
297 |
+
$custom_tw_desc ?: $this->get_generated_twitter_description( $_generator_args, false )
|
298 |
+
),
|
299 |
+
'titlePhLock' => (bool) $custom_tw_title,
|
300 |
+
'descPhLock' => (bool) $custom_tw_desc,
|
301 |
+
],
|
302 |
+
],
|
303 |
+
]
|
304 |
+
);
|
305 |
|
306 |
?>
|
307 |
<p>
|
308 |
+
<label for="<?php Input::field_id( 'homepage_og_title' ); ?>" class="tsf-toblock">
|
309 |
+
<strong><?php esc_html_e( 'Open Graph Title', 'autodescription' ); ?></strong>
|
|
|
|
|
|
|
|
|
310 |
</label>
|
311 |
</p>
|
312 |
<?php
|
313 |
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
314 |
+
Form::output_character_counter_wrap( Input::get_field_id( 'homepage_og_title' ), (bool) $this->get_option( 'display_character_counter' ) );
|
315 |
?>
|
316 |
<p>
|
317 |
+
<input type="text" name="<?php Input::field_name( 'homepage_og_title' ); ?>" class="large-text" id="<?php Input::field_id( 'homepage_og_title' ); ?>" value="<?php echo $this->esc_attr_preserve_amp( $this->get_option( 'homepage_og_title' ) ); ?>" autocomplete=off data-tsf-social-group=homepage_social_settings data-tsf-social-type=ogTitle />
|
318 |
</p>
|
319 |
<?php
|
320 |
if ( $this->has_page_on_front() && $custom_og_title ) {
|
325 |
?>
|
326 |
|
327 |
<p>
|
328 |
+
<label for="<?php Input::field_id( 'homepage_og_description' ); ?>" class="tsf-toblock">
|
329 |
+
<strong><?php esc_html_e( 'Open Graph Description', 'autodescription' ); ?></strong>
|
|
|
|
|
|
|
|
|
330 |
</label>
|
331 |
</p>
|
332 |
<?php
|
333 |
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
334 |
+
Form::output_character_counter_wrap( Input::get_field_id( 'homepage_og_description' ), (bool) $this->get_option( 'display_character_counter' ) );
|
335 |
?>
|
336 |
<p>
|
337 |
+
<textarea name="<?php Input::field_name( 'homepage_og_description' ); ?>" class="large-text" id="<?php Input::field_id( 'homepage_og_description' ); ?>" rows="3" cols="70" autocomplete=off data-tsf-social-group=homepage_social_settings data-tsf-social-type=ogDesc><?php echo esc_attr( $this->get_option( 'homepage_og_description' ) ); ?></textarea>
|
338 |
</p>
|
339 |
<?php
|
340 |
if ( $this->has_page_on_front() && $custom_og_desc ) {
|
346 |
<hr>
|
347 |
|
348 |
<p>
|
349 |
+
<label for="<?php Input::field_id( 'homepage_twitter_title' ); ?>" class="tsf-toblock">
|
350 |
+
<strong><?php esc_html_e( 'Twitter Title', 'autodescription' ); ?></strong>
|
|
|
|
|
|
|
|
|
351 |
</label>
|
352 |
</p>
|
353 |
<?php
|
354 |
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
355 |
+
Form::output_character_counter_wrap( Input::get_field_id( 'homepage_twitter_title' ), (bool) $this->get_option( 'display_character_counter' ) );
|
356 |
?>
|
357 |
<p>
|
358 |
+
<input type="text" name="<?php Input::field_name( 'homepage_twitter_title' ); ?>" class="large-text" id="<?php Input::field_id( 'homepage_twitter_title' ); ?>" value="<?php echo $this->esc_attr_preserve_amp( $this->get_option( 'homepage_twitter_title' ) ); ?>" autocomplete=off data-tsf-social-group=homepage_social_settings data-tsf-social-type=twTitle />
|
359 |
</p>
|
360 |
<?php
|
361 |
if ( $this->has_page_on_front() && ( $custom_og_title || $custom_tw_title ) ) {
|
366 |
?>
|
367 |
|
368 |
<p>
|
369 |
+
<label for="<?php Input::field_id( 'homepage_twitter_description' ); ?>" class="tsf-toblock">
|
370 |
+
<strong><?php esc_html_e( 'Twitter Description', 'autodescription' ); ?></strong>
|
|
|
|
|
|
|
|
|
371 |
</label>
|
372 |
</p>
|
373 |
<?php
|
374 |
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
375 |
+
Form::output_character_counter_wrap( Input::get_field_id( 'homepage_twitter_description' ), (bool) $this->get_option( 'display_character_counter' ) );
|
376 |
?>
|
377 |
<p>
|
378 |
+
<textarea name="<?php Input::field_name( 'homepage_twitter_description' ); ?>" class="large-text" id="<?php Input::field_id( 'homepage_twitter_description' ); ?>" rows="3" cols="70" autocomplete=off data-tsf-social-group=homepage_social_settings data-tsf-social-type=twDesc><?php echo esc_attr( $this->get_option( 'homepage_twitter_description' ) ); ?></textarea>
|
379 |
</p>
|
380 |
<?php
|
381 |
if ( $this->has_page_on_front() && ( $custom_og_desc || $custom_tw_desc ) ) {
|
386 |
?>
|
387 |
<hr>
|
388 |
<?php
|
389 |
+
HTML::header_title( __( 'Social Image Settings', 'autodescription' ) );
|
390 |
HTML::description( __( 'A social image can be displayed when your homepage is shared. It is a great way to grab attention.', 'autodescription' ) );
|
|
|
|
|
|
|
|
|
|
|
391 |
?>
|
392 |
<p>
|
393 |
<label for="tsf_homepage_socialimage-url">
|
401 |
</label>
|
402 |
</p>
|
403 |
<p>
|
404 |
+
<input class="large-text" type="url" name="<?php Input::field_name( 'homepage_social_image_url' ); ?>" id="tsf_homepage_socialimage-url" placeholder="<?php echo esc_url( current( $this->get_generated_image_details( $_generator_args, true, 'social', true ) )['url'] ?? '' ); ?>" value="<?php echo esc_url( $this->get_option( 'homepage_social_image_url' ) ); ?>" />
|
405 |
+
<input type="hidden" name="<?php Input::field_name( 'homepage_social_image_id' ); ?>" id="tsf_homepage_socialimage-id" value="<?php echo absint( $this->get_option( 'homepage_social_image_id' ) ); ?>" disabled class="tsf-enable-media-if-js" />
|
406 |
</p>
|
407 |
<p class="hide-if-no-tsf-js">
|
408 |
<?php
|
413 |
<?php
|
414 |
break;
|
415 |
|
416 |
+
case 'homepage_robots_tab':
|
417 |
$noindex_post = $home_id ? $this->get_post_meta_item( '_genesis_noindex', $home_id ) : '';
|
418 |
$nofollow_post = $home_id ? $this->get_post_meta_item( '_genesis_nofollow', $home_id ) : '';
|
419 |
$noarchive_post = $home_id ? $this->get_post_meta_item( '_genesis_noarchive', $home_id ) : '';
|
431 |
vsprintf(
|
432 |
'<a href="%s" title="%s" target=_blank class=attention>%s</a>',
|
433 |
[
|
434 |
+
esc_url( admin_url( "post.php?post=$home_id&action=edit#tsf-inpost-box" ) ),
|
435 |
esc_attr_x( 'Edit homepage page settings', 'Bear with me: the homepage can be edited globally, or via its page. Thus "homepage page".', 'autodescription' ),
|
436 |
esc_html__( 'Overwritten by page settings', 'autodescription' ),
|
437 |
]
|
439 |
);
|
440 |
}
|
441 |
|
442 |
+
HTML::header_title( __( 'Robots Meta Settings', 'autodescription' ) );
|
443 |
|
444 |
$i_label = sprintf(
|
445 |
/* translators: 1: Option label, 2: [?] option info note, 3: Optional warning */
|
493 |
|
494 |
HTML::wrap_fields(
|
495 |
[
|
496 |
+
Input::make_checkbox( [
|
497 |
'id' => 'homepage_noindex',
|
498 |
'label' => $i_label,
|
499 |
'escape' => false,
|
500 |
] ),
|
501 |
+
Input::make_checkbox( [
|
502 |
'id' => 'homepage_nofollow',
|
503 |
'label' => $f_label,
|
504 |
'escape' => false,
|
505 |
] ),
|
506 |
+
Input::make_checkbox( [
|
507 |
'id' => 'homepage_noarchive',
|
508 |
'label' => $a_label,
|
509 |
'escape' => false,
|
518 |
sprintf(
|
519 |
/* translators: %s = Homepage URL markdown */
|
520 |
esc_html__( 'Note: These options may be overwritten by the [page settings](%s).', 'autodescription' ),
|
521 |
+
esc_url( admin_url( "post.php?post=$home_id&action=edit#tsf-inpost-box" ) )
|
522 |
),
|
523 |
[ 'a' ],
|
524 |
[ 'a_internal' => false ]
|
529 |
|
530 |
<hr>
|
531 |
<?php
|
532 |
+
HTML::header_title( __( 'Homepage Pagination Robots Settings', 'autodescription' ) );
|
533 |
HTML::description( __( "If your homepage is paginated and outputs content that's also found elsewhere on the website, enabling this option may prevent duplicate content.", 'autodescription' ) );
|
534 |
|
|
|
535 |
HTML::wrap_fields(
|
536 |
+
Input::make_checkbox( [
|
537 |
'id' => 'home_paged_noindex',
|
538 |
'label' => $this->convert_markdown(
|
539 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
File without changes
|
@@ -0,0 +1,469 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package The_SEO_Framework\Views\Admin\Metaboxes
|
4 |
+
* @subpackage The_SEO_Framework\Admin\Settings
|
5 |
+
*/
|
6 |
+
|
7 |
+
// phpcs:disable, VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- includes.
|
8 |
+
// phpcs:disable, WordPress.WP.GlobalVariablesOverride -- This isn't the global scope.
|
9 |
+
|
10 |
+
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
+
The_SEO_Framework\Interpreters\HTML,
|
12 |
+
The_SEO_Framework\Interpreters\Form,
|
13 |
+
The_SEO_Framework\Interpreters\Settings_Input as Input;
|
14 |
+
|
15 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
16 |
+
|
17 |
+
// Fetch the required instance within this file.
|
18 |
+
switch ( $this->get_view_instance( 'post_type_archive', $instance ) ) :
|
19 |
+
case 'post_type_archive_main':
|
20 |
+
$_settings_class = SeoSettings::class;
|
21 |
+
$post_types = $this->get_public_post_type_archives();
|
22 |
+
|
23 |
+
$post_types_data = [];
|
24 |
+
foreach ( $post_types as $post_type ) {
|
25 |
+
$post_types_data[ $post_type ] = [
|
26 |
+
'label' => $this->get_post_type_label( $post_type ),
|
27 |
+
'url' => $this->create_canonical_url( [ 'pta' => $post_type ] ),
|
28 |
+
'hasPosts' => $this->has_posts_in_post_type_archive( $post_type ),
|
29 |
+
];
|
30 |
+
}
|
31 |
+
|
32 |
+
printf(
|
33 |
+
'<span class=hidden id=tsf-post-type-archive-data %s></span>',
|
34 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- This escapes.
|
35 |
+
HTML::make_data_attributes( [ 'postTypes' => $post_types_data ] )
|
36 |
+
);
|
37 |
+
|
38 |
+
?>
|
39 |
+
<div id=tsf-post-type-archive-header-wrap class=tsf-fields style=display:none>
|
40 |
+
<div id=tsf-post-type-archive-select-wrap>
|
41 |
+
<label for=tsf-post-type-archive-selector><?php esc_html_e( 'Select post type:', 'autodescription' ); ?></label>
|
42 |
+
<select id=tsf-post-type-archive-selector></select>
|
43 |
+
</div>
|
44 |
+
</div>
|
45 |
+
<?php
|
46 |
+
$i = 0;
|
47 |
+
foreach ( $post_types as $post_type ) {
|
48 |
+
$_generator_args = [ 'pta' => $post_type ];
|
49 |
+
|
50 |
+
// Create `[ 'doctitle' => [ 'pta', $post_type ] ];`
|
51 |
+
$_option_map = array_fill_keys(
|
52 |
+
array_keys( $this->get_unfiltered_post_type_archive_meta_defaults() ),
|
53 |
+
[ 'pta', $post_type ]
|
54 |
+
);
|
55 |
+
// Create: `[ 'doctitle' => [ 'pta', $post_type, 'doctitle' ] ];`
|
56 |
+
array_walk(
|
57 |
+
$_option_map,
|
58 |
+
static function( &$input_id, $key ) {
|
59 |
+
$input_id = array_merge( $input_id, [ $key ] );
|
60 |
+
}
|
61 |
+
);
|
62 |
+
|
63 |
+
$tabs = [
|
64 |
+
'general' => [
|
65 |
+
'name' => __( 'General', 'autodescription' ),
|
66 |
+
'callback' => [ $_settings_class, '_post_type_archive_metabox_general_tab' ],
|
67 |
+
'dashicon' => 'admin-generic',
|
68 |
+
'args' => compact( 'post_type', '_generator_args', '_option_map' ),
|
69 |
+
],
|
70 |
+
'social' => [
|
71 |
+
'name' => __( 'Social', 'autodescription' ),
|
72 |
+
'callback' => [ $_settings_class, '_post_type_archive_metabox_social_tab' ],
|
73 |
+
'dashicon' => 'share',
|
74 |
+
'args' => compact( 'post_type', '_generator_args', '_option_map' ),
|
75 |
+
],
|
76 |
+
'visibility' => [
|
77 |
+
'name' => __( 'Visibility', 'autodescription' ),
|
78 |
+
'callback' => [ $_settings_class, '_post_type_archive_metabox_visibility_tab' ],
|
79 |
+
'dashicon' => 'visibility',
|
80 |
+
'args' => compact( 'post_type', '_generator_args', '_option_map' ),
|
81 |
+
],
|
82 |
+
];
|
83 |
+
|
84 |
+
// Hide subsequent wraps to prevent layout shifts (bounce) during load: They get hidden by JS anyway.
|
85 |
+
printf(
|
86 |
+
'<div class="tsf-post-type-archive-wrap%s" %s>',
|
87 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- Shut it, noob.
|
88 |
+
$i ? ' hide-if-tsf-js' : '',
|
89 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- This escapes.
|
90 |
+
HTML::make_data_attributes( [ 'postType' => $post_type ] )
|
91 |
+
);
|
92 |
+
?>
|
93 |
+
<div class=tsf-post-type-header>
|
94 |
+
<?php
|
95 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- it is.
|
96 |
+
echo HTML::get_header_title(
|
97 |
+
vsprintf(
|
98 |
+
'%s – <span class=tsf-post-type-archive-details><code>%s</code> %s</span>',
|
99 |
+
[
|
100 |
+
sprintf(
|
101 |
+
/* translators: 1 = Post Type Archive name */
|
102 |
+
esc_html__( 'Archive of %s', 'autodescription' ),
|
103 |
+
esc_html( $post_types_data[ $post_type ]['label'] )
|
104 |
+
),
|
105 |
+
esc_html( $post_type ),
|
106 |
+
sprintf(
|
107 |
+
'<span class=tsf-post-type-archive-link><a href="%s" target=_blank rel=noopener>[%s]</a></span>',
|
108 |
+
esc_url( $post_types_data[ $post_type ]['url'] ),
|
109 |
+
esc_html__( 'View archive', 'autodescription' )
|
110 |
+
),
|
111 |
+
]
|
112 |
+
)
|
113 |
+
);
|
114 |
+
?>
|
115 |
+
</div>
|
116 |
+
<div class="tsf-post-type-archive-if-excluded hidden">
|
117 |
+
<?php
|
118 |
+
HTML::attention_description(
|
119 |
+
__( "This post type is excluded, so settings won't have any effect.", 'autodescription' )
|
120 |
+
)
|
121 |
+
?>
|
122 |
+
</div>
|
123 |
+
<div class=tsf-post-type-archive-if-not-excluded>
|
124 |
+
<?php
|
125 |
+
SeoSettings::_nav_tab_wrapper(
|
126 |
+
"post_type_archive_{$post_type}",
|
127 |
+
/**
|
128 |
+
* @since 4.2.0
|
129 |
+
* @param array $tabs The default tabs.
|
130 |
+
* @param strring $post_type The post type archive's name.
|
131 |
+
*/
|
132 |
+
(array) apply_filters_ref_array(
|
133 |
+
'the_seo_framework_post_type_archive_settings_tabs',
|
134 |
+
[
|
135 |
+
$tabs,
|
136 |
+
$post_type,
|
137 |
+
]
|
138 |
+
)
|
139 |
+
);
|
140 |
+
?>
|
141 |
+
</div>
|
142 |
+
</div>
|
143 |
+
<?php
|
144 |
+
$i++ or print( '<hr class=hide-if-tsf-js>' );
|
145 |
+
}
|
146 |
+
break;
|
147 |
+
|
148 |
+
case 'post_type_archive_general_tab':
|
149 |
+
?>
|
150 |
+
<p>
|
151 |
+
<label for="<?php Input::field_id( $_option_map['doctitle'] ); ?>" class=tsf-toblock>
|
152 |
+
<strong><?php esc_html_e( 'Meta Title', 'autodescription' ); ?></strong>
|
153 |
+
<?php
|
154 |
+
echo ' ';
|
155 |
+
HTML::make_info(
|
156 |
+
__( 'The meta title can be used to determine the title used on search engine result pages.', 'autodescription' ),
|
157 |
+
'https://developers.google.com/search/docs/advanced/appearance/good-titles-snippets#page-titles'
|
158 |
+
);
|
159 |
+
?>
|
160 |
+
</label>
|
161 |
+
</p>
|
162 |
+
<?php
|
163 |
+
// Output these unconditionally, with inline CSS attached to allow reacting on settings.
|
164 |
+
Form::output_character_counter_wrap(
|
165 |
+
Input::get_field_id( $_option_map['doctitle'] ),
|
166 |
+
(bool) $this->get_option( 'display_character_counter' )
|
167 |
+
);
|
168 |
+
Form::output_pixel_counter_wrap(
|
169 |
+
Input::get_field_id( $_option_map['doctitle'] ),
|
170 |
+
'title',
|
171 |
+
(bool) $this->get_option( 'display_pixel_counter' )
|
172 |
+
);
|
173 |
+
?>
|
174 |
+
<p class=tsf-title-wrap>
|
175 |
+
<input type="text" name="<?php Input::field_name( $_option_map['doctitle'] ); ?>" class="large-text" id="<?php Input::field_id( $_option_map['doctitle'] ); ?>" value="<?php echo $this->esc_attr_preserve_amp( $this->get_post_type_archive_meta_item( 'doctitle', $post_type ) ); ?>" autocomplete=off />
|
176 |
+
<?php
|
177 |
+
[ $_full_title, $_prefix_value, $_default_title ] =
|
178 |
+
$this->get_raw_generated_archive_title_items( get_post_type_object( $post_type ), 'admin' );
|
179 |
+
|
180 |
+
$this->output_js_title_data(
|
181 |
+
Input::get_field_id( $_option_map['doctitle'] ),
|
182 |
+
[
|
183 |
+
'state' => [
|
184 |
+
'defaultTitle' => $this->s_title( $_default_title ),
|
185 |
+
'addAdditions' => $this->use_title_branding( $_generator_args ),
|
186 |
+
'useSocialTagline' => $this->use_title_branding( $_generator_args, true ),
|
187 |
+
'additionValue' => $this->s_title( $this->get_blogname() ),
|
188 |
+
'additionPlacement' => 'left' === $this->get_title_seplocation() ? 'before' : 'after',
|
189 |
+
'prefixValue' => $this->s_title( $_prefix_value ),
|
190 |
+
'showPrefix' => $this->use_generated_archive_prefix( get_post_type_object( $post_type ) ),
|
191 |
+
],
|
192 |
+
]
|
193 |
+
);
|
194 |
+
?>
|
195 |
+
</p>
|
196 |
+
|
197 |
+
<div class=tsf-title-tagline-toggle>
|
198 |
+
<?php
|
199 |
+
$info = HTML::make_info(
|
200 |
+
__( 'Use this when you want to rearrange the title parts manually.', 'autodescription' ),
|
201 |
+
'',
|
202 |
+
false
|
203 |
+
);
|
204 |
+
|
205 |
+
HTML::wrap_fields(
|
206 |
+
Input::make_checkbox( [
|
207 |
+
'id' => $_option_map['title_no_blog_name'],
|
208 |
+
'label' => esc_html__( 'Remove the site title?', 'autodescription' ) . " $info",
|
209 |
+
'value' => $this->get_post_type_archive_meta_item( 'title_no_blog_name', $post_type ),
|
210 |
+
'escape' => false,
|
211 |
+
] ),
|
212 |
+
true
|
213 |
+
);
|
214 |
+
?>
|
215 |
+
</div>
|
216 |
+
|
217 |
+
<hr>
|
218 |
+
|
219 |
+
<p>
|
220 |
+
<label for="<?php Input::field_id( $_option_map['description'] ); ?>" class="tsf-toblock">
|
221 |
+
<strong><?php esc_html_e( 'Meta Description', 'autodescription' ); ?></strong>
|
222 |
+
<?php
|
223 |
+
echo ' ';
|
224 |
+
HTML::make_info(
|
225 |
+
__( 'The meta description can be used to determine the text used under the title on search engine results pages.', 'autodescription' ),
|
226 |
+
'https://developers.google.com/search/docs/advanced/appearance/good-titles-snippets#meta-descriptions'
|
227 |
+
);
|
228 |
+
?>
|
229 |
+
</label>
|
230 |
+
</p>
|
231 |
+
<?php
|
232 |
+
// Output these unconditionally, with inline CSS attached to allow reacting on settings.
|
233 |
+
Form::output_character_counter_wrap( Input::get_field_id( $_option_map['description'] ), (bool) $this->get_option( 'display_character_counter' ) );
|
234 |
+
Form::output_pixel_counter_wrap( Input::get_field_id( $_option_map['description'] ), 'description', (bool) $this->get_option( 'display_pixel_counter' ) );
|
235 |
+
?>
|
236 |
+
<p>
|
237 |
+
<textarea name="<?php Input::field_name( $_option_map['description'] ); ?>" class="large-text" id="<?php Input::field_id( $_option_map['description'] ); ?>" rows="3" cols="70"><?php echo esc_attr( $this->get_post_type_archive_meta_item( 'description', $post_type ) ); ?></textarea>
|
238 |
+
<?php
|
239 |
+
$this->output_js_description_elements(); // legacy
|
240 |
+
$this->output_js_description_data(
|
241 |
+
Input::get_field_id( $_option_map['description'] ),
|
242 |
+
[
|
243 |
+
'state' => [
|
244 |
+
'defaultDescription' => $this->get_generated_description( $_generator_args ),
|
245 |
+
],
|
246 |
+
]
|
247 |
+
);
|
248 |
+
?>
|
249 |
+
</p>
|
250 |
+
<?php
|
251 |
+
break;
|
252 |
+
case 'post_type_archive_social_tab':
|
253 |
+
$this->output_js_social_data(
|
254 |
+
"pta_social_settings_{$post_type}",
|
255 |
+
[
|
256 |
+
'og' => [
|
257 |
+
'state' => [
|
258 |
+
'defaultTitle' => $this->s_title( $this->get_generated_open_graph_title( $_generator_args, false ) ),
|
259 |
+
'addAdditions' => $this->use_title_branding( $_generator_args, 'og' ),
|
260 |
+
'defaultDesc' => $this->s_description( $this->get_generated_open_graph_description( $_generator_args, false ) ),
|
261 |
+
],
|
262 |
+
],
|
263 |
+
'tw' => [
|
264 |
+
'state' => [
|
265 |
+
'defaultTitle' => $this->s_title( $this->get_generated_twitter_title( $_generator_args, false ) ),
|
266 |
+
'addAdditions' => $this->use_title_branding( $_generator_args, 'twitter' ),
|
267 |
+
'defaultDesc' => $this->s_description( $this->get_generated_twitter_description( $_generator_args, false ) ),
|
268 |
+
],
|
269 |
+
],
|
270 |
+
]
|
271 |
+
);
|
272 |
+
|
273 |
+
?>
|
274 |
+
<p>
|
275 |
+
<label for="<?php Input::field_id( $_option_map['og_title'] ); ?>" class="tsf-toblock">
|
276 |
+
<strong><?php esc_html_e( 'Open Graph Title', 'autodescription' ); ?></strong>
|
277 |
+
</label>
|
278 |
+
</p>
|
279 |
+
<?php
|
280 |
+
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
281 |
+
Form::output_character_counter_wrap( Input::get_field_id( $_option_map['og_title'] ), (bool) $this->get_option( 'display_character_counter' ) );
|
282 |
+
?>
|
283 |
+
<p>
|
284 |
+
<input type="text" name="<?php Input::field_name( $_option_map['og_title'] ); ?>" class="large-text" id="<?php Input::field_id( $_option_map['og_title'] ); ?>" value="<?php echo $this->esc_attr_preserve_amp( $this->get_post_type_archive_meta_item( 'og_title', $post_type ) ); ?>" autocomplete=off data-tsf-social-group=<?php echo esc_attr( "pta_social_settings_{$post_type}" ); ?> data-tsf-social-type=ogTitle />
|
285 |
+
</p>
|
286 |
+
|
287 |
+
<p>
|
288 |
+
<label for="<?php Input::field_id( $_option_map['og_description'] ); ?>" class="tsf-toblock">
|
289 |
+
<strong><?php esc_html_e( 'Open Graph Description', 'autodescription' ); ?></strong>
|
290 |
+
</label>
|
291 |
+
</p>
|
292 |
+
<?php
|
293 |
+
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
294 |
+
Form::output_character_counter_wrap( Input::get_field_id( $_option_map['og_description'] ), (bool) $this->get_option( 'display_character_counter' ) );
|
295 |
+
?>
|
296 |
+
<p>
|
297 |
+
<textarea name="<?php Input::field_name( $_option_map['og_description'] ); ?>" class="large-text" id="<?php Input::field_id( $_option_map['og_description'] ); ?>" rows="3" cols="70" autocomplete=off data-tsf-social-group=<?php echo esc_attr( "pta_social_settings_{$post_type}" ); ?> data-tsf-social-type=ogDesc><?php echo esc_attr( $this->get_post_type_archive_meta_item( 'og_description', $post_type ) ); ?></textarea>
|
298 |
+
</p>
|
299 |
+
|
300 |
+
<hr>
|
301 |
+
|
302 |
+
<p>
|
303 |
+
<label for="<?php Input::field_id( $_option_map['tw_title'] ); ?>" class="tsf-toblock">
|
304 |
+
<strong><?php esc_html_e( 'Twitter Title', 'autodescription' ); ?></strong>
|
305 |
+
</label>
|
306 |
+
</p>
|
307 |
+
<?php
|
308 |
+
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
309 |
+
Form::output_character_counter_wrap( Input::get_field_id( $_option_map['tw_title'] ), (bool) $this->get_option( 'display_character_counter' ) );
|
310 |
+
?>
|
311 |
+
<p>
|
312 |
+
<input type="text" name="<?php Input::field_name( $_option_map['tw_title'] ); ?>" class="large-text" id="<?php Input::field_id( $_option_map['tw_title'] ); ?>" value="<?php echo $this->esc_attr_preserve_amp( $this->get_post_type_archive_meta_item( 'tw_title', $post_type ) ); ?>" autocomplete=off data-tsf-social-group=<?php echo esc_attr( "pta_social_settings_{$post_type}" ); ?> data-tsf-social-type=twTitle />
|
313 |
+
</p>
|
314 |
+
|
315 |
+
<p>
|
316 |
+
<label for="<?php Input::field_id( $_option_map['tw_description'] ); ?>" class="tsf-toblock">
|
317 |
+
<strong><?php esc_html_e( 'Twitter Description', 'autodescription' ); ?></strong>
|
318 |
+
</label>
|
319 |
+
</p>
|
320 |
+
<?php
|
321 |
+
// Output this unconditionally, with inline CSS attached to allow reacting on settings.
|
322 |
+
Form::output_character_counter_wrap( Input::get_field_id( $_option_map['tw_description'] ), (bool) $this->get_option( 'display_character_counter' ) );
|
323 |
+
?>
|
324 |
+
<p>
|
325 |
+
<textarea name="<?php Input::field_name( $_option_map['tw_description'] ); ?>" class="large-text" id="<?php Input::field_id( $_option_map['tw_description'] ); ?>" rows="3" cols="70" autocomplete=off data-tsf-social-group=<?php echo esc_attr( "pta_social_settings_{$post_type}" ); ?> data-tsf-social-type=twDesc><?php echo esc_attr( $this->get_post_type_archive_meta_item( 'tw_description', $post_type ) ); ?></textarea>
|
326 |
+
</p>
|
327 |
+
|
328 |
+
<hr>
|
329 |
+
|
330 |
+
<p>
|
331 |
+
<label for="<?php echo esc_attr( "tsf_pta_socialimage_{$post_type}" ); ?>-url">
|
332 |
+
<strong><?php esc_html_e( 'Social Image URL', 'autodescription' ); ?></strong>
|
333 |
+
<?php
|
334 |
+
HTML::make_info(
|
335 |
+
__( "The social image URL can be used by search engines and social networks alike. It's best to use an image with a 1.91:1 aspect ratio that is at least 1200px wide for universal support.", 'autodescription' ),
|
336 |
+
'https://developers.facebook.com/docs/sharing/best-practices#images'
|
337 |
+
);
|
338 |
+
?>
|
339 |
+
</label>
|
340 |
+
</p>
|
341 |
+
<p>
|
342 |
+
<input class="large-text" type="url" name="<?php Input::field_name( $_option_map['social_image_url'] ); ?>" id="<?php echo esc_attr( "tsf_pta_socialimage_{$post_type}" ); ?>-url" placeholder="<?php echo esc_url( current( $this->get_generated_image_details( $_generator_args, true, 'social', true ) )['url'] ?? '' ); ?>" value="<?php echo esc_url( $this->get_post_type_archive_meta_item( 'social_image_url', $post_type ) ); ?>" />
|
343 |
+
<input type="hidden" name="<?php Input::field_name( $_option_map['social_image_id'] ); ?>" id="<?php echo esc_attr( "tsf_pta_socialimage_{$post_type}" ); ?>-id" value="<?php echo absint( $this->get_post_type_archive_meta_item( 'social_image_id', $post_type ) ); ?>" disabled class="tsf-enable-media-if-js" />
|
344 |
+
</p>
|
345 |
+
<p class="hide-if-no-tsf-js">
|
346 |
+
<?php
|
347 |
+
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- already escaped.
|
348 |
+
echo Form::get_image_uploader_form( [ 'id' => "tsf_pta_socialimage_{$post_type}" ] );
|
349 |
+
?>
|
350 |
+
</p>
|
351 |
+
<?php
|
352 |
+
break;
|
353 |
+
case 'post_type_archive_visibility_tab':
|
354 |
+
?>
|
355 |
+
<p>
|
356 |
+
<label for="<?php Input::field_id( $_option_map['canonical'] ); ?>" class="tsf-toblock">
|
357 |
+
<strong><?php esc_html_e( 'Canonical URL', 'autodescription' ); ?></strong>
|
358 |
+
<?php
|
359 |
+
echo ' ';
|
360 |
+
HTML::make_info(
|
361 |
+
__( 'This urges search engines to go to the outputted URL.', 'autodescription' ),
|
362 |
+
'https://developers.google.com/search/docs/advanced/crawling/consolidate-duplicate-urls'
|
363 |
+
);
|
364 |
+
?>
|
365 |
+
</label>
|
366 |
+
</p>
|
367 |
+
<p>
|
368 |
+
<input type="url" name="<?php Input::field_name( $_option_map['canonical'] ); ?>" class="large-text" id="<?php Input::field_id( $_option_map['canonical'] ); ?>" placeholder="<?php echo esc_url( $this->create_canonical_url( $_generator_args ) ); ?>" value="<?php echo esc_url( $this->get_post_type_archive_meta_item( 'canonical', $post_type ) ); ?>" autocomplete=off />
|
369 |
+
</p>
|
370 |
+
|
371 |
+
<hr>
|
372 |
+
<?php
|
373 |
+
$robots_settings = [
|
374 |
+
'noindex' => [
|
375 |
+
'force_on' => 'index',
|
376 |
+
'force_off' => 'noindex',
|
377 |
+
'label' => __( 'Indexing', 'autodescription' ),
|
378 |
+
'_defaultOn' => 'index',
|
379 |
+
'_defaultOff' => 'noindex',
|
380 |
+
'_value' => $this->get_post_type_archive_meta_item( 'noindex', $post_type ),
|
381 |
+
'_info' => [
|
382 |
+
__( 'This tells search engines not to show this term in their search results.', 'autodescription' ),
|
383 |
+
'https://developers.google.com/search/docs/advanced/crawling/block-indexing',
|
384 |
+
],
|
385 |
+
],
|
386 |
+
'nofollow' => [
|
387 |
+
'force_on' => 'follow',
|
388 |
+
'force_off' => 'nofollow',
|
389 |
+
'label' => __( 'Link following', 'autodescription' ),
|
390 |
+
'_defaultOn' => 'follow',
|
391 |
+
'_defaultOff' => 'nofollow',
|
392 |
+
'_value' => $this->get_post_type_archive_meta_item( 'nofollow', $post_type ),
|
393 |
+
'_info' => [
|
394 |
+
__( 'This tells search engines not to follow links on this term.', 'autodescription' ),
|
395 |
+
'https://developers.google.com/search/docs/advanced/guidelines/qualify-outbound-links',
|
396 |
+
],
|
397 |
+
],
|
398 |
+
'noarchive' => [
|
399 |
+
'force_on' => 'archive',
|
400 |
+
'force_off' => 'noarchive',
|
401 |
+
'label' => __( 'Archiving', 'autodescription' ),
|
402 |
+
'_defaultOn' => 'archive',
|
403 |
+
'_defaultOff' => 'noarchive',
|
404 |
+
'_value' => $this->get_post_type_archive_meta_item( 'noarchive', $post_type ),
|
405 |
+
'_info' => [
|
406 |
+
__( 'This tells search engines not to save a cached copy of this term.', 'autodescription' ),
|
407 |
+
'https://developers.google.com/search/docs/advanced/robots/robots_meta_tag#directives',
|
408 |
+
],
|
409 |
+
],
|
410 |
+
];
|
411 |
+
|
412 |
+
foreach ( $robots_settings as $_r_type => $_rs ) :
|
413 |
+
// phpcs:enable, WordPress.Security.EscapeOutput
|
414 |
+
HTML::wrap_fields(
|
415 |
+
vsprintf(
|
416 |
+
'<p><label for="%1$s"><strong>%2$s</strong> %3$s</label></p>',
|
417 |
+
[
|
418 |
+
Input::get_field_id( $_option_map[ $_r_type ] ),
|
419 |
+
esc_html( $_rs['label'] ),
|
420 |
+
HTML::make_info(
|
421 |
+
$_rs['_info'][0],
|
422 |
+
$_rs['_info'][1] ?? '',
|
423 |
+
false
|
424 |
+
),
|
425 |
+
]
|
426 |
+
),
|
427 |
+
true
|
428 |
+
);
|
429 |
+
// phpcs:disable, WordPress.Security.EscapeOutput -- make_single_select_form() escapes.
|
430 |
+
echo Form::make_single_select_form( [
|
431 |
+
'id' => Input::get_field_id( $_option_map[ $_r_type ] ),
|
432 |
+
'class' => 'tsf-select-block',
|
433 |
+
'name' => Input::get_field_name( $_option_map[ $_r_type ] ),
|
434 |
+
'label' => '',
|
435 |
+
'options' => [
|
436 |
+
0 => __( 'Default (unknown)', 'autodescription' ),
|
437 |
+
-1 => $_rs['force_on'],
|
438 |
+
1 => $_rs['force_off'],
|
439 |
+
],
|
440 |
+
'default' => $_rs['_value'],
|
441 |
+
'data' => [
|
442 |
+
/* translators: %s = default option value */
|
443 |
+
'defaultI18n' => __( 'Default (%s)', 'autodescription' ),
|
444 |
+
'defaultOn' => $_rs['_defaultOn'],
|
445 |
+
'defaultOff' => $_rs['_defaultOff'],
|
446 |
+
],
|
447 |
+
] );
|
448 |
+
endforeach;
|
449 |
+
?>
|
450 |
+
<hr>
|
451 |
+
|
452 |
+
<p>
|
453 |
+
<label for="<?php Input::field_id( $_option_map['redirect'] ); ?>" class="tsf-toblock">
|
454 |
+
<strong><?php esc_html_e( '301 Redirect URL', 'autodescription' ); ?></strong>
|
455 |
+
<?php
|
456 |
+
echo ' ';
|
457 |
+
HTML::make_info(
|
458 |
+
__( 'This will force visitors to go to another URL.', 'autodescription' ),
|
459 |
+
'https://developers.google.com/search/docs/advanced/crawling/301-redirects'
|
460 |
+
);
|
461 |
+
?>
|
462 |
+
</label>
|
463 |
+
</p>
|
464 |
+
<p>
|
465 |
+
<input type="url" name="<?php Input::field_name( $_option_map['redirect'] ); ?>" class="large-text" id="<?php Input::field_id( $_option_map['redirect'] ); ?>" value="<?php echo esc_url( $this->get_post_type_archive_meta_item( 'redirect', $post_type ) ); ?>" autocomplete=off />
|
466 |
+
</p>
|
467 |
+
<?php
|
468 |
+
break;
|
469 |
+
endswitch;
|
@@ -9,15 +9,12 @@
|
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
-
The_SEO_Framework\Interpreters\
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
switch ( $instance ) :
|
20 |
-
case 'the_seo_framework_robots_metabox_main':
|
21 |
$global_types = [
|
22 |
'author' => [
|
23 |
'i18n' => __( 'Author pages', 'autodescription' ),
|
@@ -31,6 +28,7 @@ switch ( $instance ) :
|
|
31 |
'i18n' => __( 'Search pages', 'autodescription' ),
|
32 |
'i18ntype' => 'plural',
|
33 |
],
|
|
|
34 |
'site' => [
|
35 |
'i18n' => _x( 'the entire site', '...for the entire site', 'autodescription' ),
|
36 |
'i18ntype' => 'singular',
|
@@ -56,16 +54,18 @@ switch ( $instance ) :
|
|
56 |
],
|
57 |
];
|
58 |
|
59 |
-
$
|
|
|
|
|
60 |
'general' => [
|
61 |
'name' => __( 'General', 'autodescription' ),
|
62 |
-
'callback' =>
|
63 |
'dashicon' => 'admin-generic',
|
64 |
'args' => '',
|
65 |
],
|
66 |
'index' => [
|
67 |
'name' => __( 'Indexing', 'autodescription' ),
|
68 |
-
'callback' =>
|
69 |
'dashicon' => 'filter',
|
70 |
'args' => [
|
71 |
'global_types' => $global_types,
|
@@ -76,7 +76,7 @@ switch ( $instance ) :
|
|
76 |
],
|
77 |
'follow' => [
|
78 |
'name' => __( 'Following', 'autodescription' ),
|
79 |
-
'callback' =>
|
80 |
'dashicon' => 'editor-unlink',
|
81 |
'args' => [
|
82 |
'global_types' => $global_types,
|
@@ -87,7 +87,7 @@ switch ( $instance ) :
|
|
87 |
],
|
88 |
'archive' => [
|
89 |
'name' => __( 'Archiving', 'autodescription' ),
|
90 |
-
'callback' =>
|
91 |
'dashicon' => 'download',
|
92 |
'args' => [
|
93 |
'global_types' => $global_types,
|
@@ -98,24 +98,22 @@ switch ( $instance ) :
|
|
98 |
],
|
99 |
];
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
SeoSettings::_nav_tab_wrapper( 'robots', $tabs );
|
111 |
break;
|
112 |
|
113 |
-
case '
|
114 |
-
|
115 |
HTML::description( __( 'Some URL queries can cause WordPress to show faux archives. When search engines spot these, they will crawl and index them, which may cause a drop in ranking. Advanced query protection will prevent robots from indexing these archives.', 'autodescription' ) );
|
116 |
|
117 |
HTML::wrap_fields(
|
118 |
-
|
119 |
'id' => 'advanced_query_protection',
|
120 |
'label' => __( 'Enable advanced query protection?', 'autodescription' ),
|
121 |
] ),
|
@@ -124,11 +122,11 @@ switch ( $instance ) :
|
|
124 |
?>
|
125 |
<hr>
|
126 |
<?php
|
127 |
-
|
128 |
HTML::description( __( "Indexing the second or later page of any archive might cause duplication errors. Search engines look down upon them; therefore, it's recommended to disable indexing of those pages.", 'autodescription' ) );
|
129 |
|
130 |
HTML::wrap_fields(
|
131 |
-
|
132 |
'id' => 'paged_noindex',
|
133 |
'label' => $this->convert_markdown(
|
134 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
@@ -142,11 +140,11 @@ switch ( $instance ) :
|
|
142 |
?>
|
143 |
<hr>
|
144 |
<?php
|
145 |
-
|
146 |
HTML::description( __( "Some search engines allow you to control copyright directives on the content they aggregate. It's best to allow some content to be taken by these aggregators, as that can improve contextualized exposure via snippets and previews. When left unspecified, regional regulations may apply. It is up to the aggregator to honor these requests.", 'autodescription' ) );
|
147 |
|
148 |
HTML::wrap_fields(
|
149 |
-
|
150 |
'id' => 'set_copyright_directives',
|
151 |
'label' => __( 'Specify aggregator copyright compliance directives?', 'autodescription' ),
|
152 |
] ),
|
@@ -165,8 +163,8 @@ switch ( $instance ) :
|
|
165 |
$_current = $this->get_option( 'max_snippet_length' );
|
166 |
foreach ( $_text_snippet_types as $_type => $_values ) {
|
167 |
$_label = 'default' === $_type
|
168 |
-
|
169 |
-
|
170 |
|
171 |
$_options = '';
|
172 |
foreach ( $_values as $_value => $_name ) {
|
@@ -188,9 +186,9 @@ switch ( $instance ) :
|
|
188 |
<p><select name="%3$s" id="%1$s">%4$s</select></p>
|
189 |
<p class=description>%6$s</p>',
|
190 |
[
|
191 |
-
|
192 |
esc_html__( 'Maximum text snippet length', 'autodescription' ),
|
193 |
-
|
194 |
$text_snippet_options,
|
195 |
HTML::make_info(
|
196 |
__( 'This may limit the text snippet length for all pages on this site.', 'autodescription' ),
|
@@ -225,9 +223,9 @@ switch ( $instance ) :
|
|
225 |
'<p><label for="%1$s"><strong>%2$s</strong> %5$s</label></p>
|
226 |
<p><select name="%3$s" id="%1$s">%4$s</select></p>',
|
227 |
[
|
228 |
-
|
229 |
esc_html__( 'Maximum image preview size', 'autodescription' ),
|
230 |
-
|
231 |
$image_preview_options,
|
232 |
HTML::make_info(
|
233 |
__( 'This may limit the image preview size for all images from this site.', 'autodescription' ),
|
@@ -251,8 +249,8 @@ switch ( $instance ) :
|
|
251 |
$_current = $this->get_option( 'max_video_preview' );
|
252 |
foreach ( $_video_snippet_types as $_type => $_values ) {
|
253 |
$_label = 'default' === $_type
|
254 |
-
|
255 |
-
|
256 |
|
257 |
$_options = '';
|
258 |
foreach ( $_values as $_value => $_name ) {
|
@@ -273,9 +271,9 @@ switch ( $instance ) :
|
|
273 |
'<p><label for="%1$s"><strong>%2$s</strong> %5$s</label></p>
|
274 |
<p><select name="%3$s" id="%1$s">%4$s</select></p>',
|
275 |
[
|
276 |
-
|
277 |
esc_html__( 'Maximum video preview length', 'autodescription' ),
|
278 |
-
|
279 |
$video_preview_options,
|
280 |
HTML::make_info(
|
281 |
__( 'This may limit the video preview length for all videos on this site.', 'autodescription' ),
|
@@ -288,7 +286,7 @@ switch ( $instance ) :
|
|
288 |
);
|
289 |
break;
|
290 |
|
291 |
-
case '
|
292 |
$ro_value = $robots['value'];
|
293 |
$ro_i18n = $robots['desc'];
|
294 |
|
@@ -299,42 +297,34 @@ switch ( $instance ) :
|
|
299 |
|
300 |
$ro_name_wrapped = HTML::code_wrap( $ro_value );
|
301 |
|
302 |
-
|
303 |
-
$warned_options = $this->get_warned_site_options();
|
304 |
-
|
305 |
-
Form::header_title( __( 'Robots Settings', 'autodescription' ) );
|
306 |
HTML::description( $ro_i18n );
|
307 |
?>
|
308 |
<hr>
|
309 |
<?php
|
310 |
-
|
311 |
HTML::description( __( 'These settings apply to the post type pages and their terms. When terms are shared between post types, all their post types should be checked for this to have an effect.', 'autodescription' ) );
|
312 |
|
313 |
-
$pt_option_id = $this->get_robots_post_type_option_id( $ro_value );
|
314 |
-
|
315 |
// When the post OR page post types are available, show this warning.
|
316 |
if ( in_array( $ro_value, [ 'noindex', 'nofollow' ], true ) && array_intersect( $post_types, [ 'post', 'page' ] ) )
|
317 |
HTML::attention_description( __( 'Warning: No site should enable these options for Posts and Pages.', 'autodescription' ) );
|
318 |
|
319 |
-
// TODO can we assume that there's at least one post type at all times? Can WP be used in this way, albeit headless?
|
320 |
$checkboxes = [];
|
321 |
|
|
|
|
|
322 |
foreach ( $post_types as $post_type ) {
|
323 |
-
$checkboxes[] =
|
324 |
-
'id'
|
325 |
-
'class'
|
326 |
-
'
|
327 |
-
'label' => sprintf(
|
328 |
// RTL supported: Because the post types are Roman, browsers enforce the order.
|
329 |
'%s – <code>%s</code>',
|
330 |
sprintf( $apply_x_to_y_i18n_plural, $ro_name_wrapped, esc_html( $this->get_post_type_label( $post_type, false ) ) ),
|
331 |
esc_html( $post_type )
|
332 |
),
|
333 |
-
'escape'
|
334 |
-
'
|
335 |
-
'default' => ! empty( $default_options[ $pt_option_id ][ $post_type ] ),
|
336 |
-
'warned' => ! empty( $warned_options[ $pt_option_id ][ $post_type ] ),
|
337 |
-
'data' => [
|
338 |
'robots' => $ro_value,
|
339 |
],
|
340 |
] );
|
@@ -345,42 +335,38 @@ switch ( $instance ) :
|
|
345 |
?>
|
346 |
<hr>
|
347 |
<?php
|
348 |
-
|
349 |
HTML::description( __( "These settings apply to the taxonomies of post types. When taxonomies have all their bound post types' options checked, they will inherit their status.", 'autodescription' ) );
|
350 |
|
351 |
$tax_option_id = $this->get_robots_taxonomy_option_id( $ro_value );
|
352 |
|
353 |
-
// TODO can we assume that there's at least one taxonomy at all times? Can WP be used in this way, albeit headless?
|
354 |
$checkboxes = [];
|
355 |
|
356 |
foreach ( $taxonomies as $taxonomy ) {
|
357 |
-
$checkboxes[] =
|
358 |
-
'id'
|
359 |
-
'class'
|
360 |
-
'
|
361 |
-
'label' => sprintf(
|
362 |
// RTL supported: Because the post types are Roman, browsers enforce the order.
|
363 |
'%s – <code>%s</code>',
|
364 |
sprintf( $apply_x_to_y_i18n_plural, $ro_name_wrapped, esc_html( $this->get_tax_type_label( $taxonomy, false ) ) ),
|
365 |
esc_html( $taxonomy )
|
366 |
),
|
367 |
-
'escape'
|
368 |
-
'
|
369 |
-
'default' => ! empty( $default_options[ $tax_option_id ][ $taxonomy ] ),
|
370 |
-
'warned' => ! empty( $warned_options[ $tax_option_id ][ $taxonomy ] ),
|
371 |
-
'data' => [
|
372 |
'postTypes' => $this->get_post_types_from_taxonomy( $taxonomy ),
|
373 |
'robots' => $ro_value,
|
374 |
],
|
375 |
] );
|
376 |
}
|
377 |
|
|
|
378 |
HTML::wrap_fields( $checkboxes, true );
|
379 |
|
380 |
?>
|
381 |
<hr>
|
382 |
<?php
|
383 |
-
|
384 |
HTML::description( __( 'These settings apply to other globally registered content types.', 'autodescription' ) );
|
385 |
|
386 |
$checkboxes = '';
|
@@ -392,7 +378,8 @@ switch ( $instance ) :
|
|
392 |
esc_html( $data['i18n'] )
|
393 |
);
|
394 |
|
395 |
-
|
|
|
396 |
|
397 |
// Add warning if it's 'site'.
|
398 |
if ( 'site' === $type ) {
|
@@ -405,10 +392,14 @@ switch ( $instance ) :
|
|
405 |
);
|
406 |
}
|
407 |
|
408 |
-
$checkboxes .=
|
409 |
'id' => $id,
|
|
|
410 |
'label' => $label,
|
411 |
'escape' => false,
|
|
|
|
|
|
|
412 |
] );
|
413 |
}
|
414 |
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
+
The_SEO_Framework\Interpreters\Settings_Input as Input;
|
13 |
|
14 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
15 |
|
16 |
+
switch ( $this->get_view_instance( 'robots', $instance ) ) :
|
17 |
+
case 'robots_main':
|
|
|
|
|
|
|
18 |
$global_types = [
|
19 |
'author' => [
|
20 |
'i18n' => __( 'Author pages', 'autodescription' ),
|
28 |
'i18n' => __( 'Search pages', 'autodescription' ),
|
29 |
'i18ntype' => 'plural',
|
30 |
],
|
31 |
+
// Must be last for proper <hr> styling!
|
32 |
'site' => [
|
33 |
'i18n' => _x( 'the entire site', '...for the entire site', 'autodescription' ),
|
34 |
'i18ntype' => 'singular',
|
54 |
],
|
55 |
];
|
56 |
|
57 |
+
$_settings_class = SeoSettings::class;
|
58 |
+
|
59 |
+
$tabs = [
|
60 |
'general' => [
|
61 |
'name' => __( 'General', 'autodescription' ),
|
62 |
+
'callback' => [ $_settings_class, '_robots_metabox_general_tab' ],
|
63 |
'dashicon' => 'admin-generic',
|
64 |
'args' => '',
|
65 |
],
|
66 |
'index' => [
|
67 |
'name' => __( 'Indexing', 'autodescription' ),
|
68 |
+
'callback' => [ $_settings_class, '_robots_metabox_no_tab' ],
|
69 |
'dashicon' => 'filter',
|
70 |
'args' => [
|
71 |
'global_types' => $global_types,
|
76 |
],
|
77 |
'follow' => [
|
78 |
'name' => __( 'Following', 'autodescription' ),
|
79 |
+
'callback' => [ $_settings_class, '_robots_metabox_no_tab' ],
|
80 |
'dashicon' => 'editor-unlink',
|
81 |
'args' => [
|
82 |
'global_types' => $global_types,
|
87 |
],
|
88 |
'archive' => [
|
89 |
'name' => __( 'Archiving', 'autodescription' ),
|
90 |
+
'callback' => [ $_settings_class, '_robots_metabox_no_tab' ],
|
91 |
'dashicon' => 'download',
|
92 |
'args' => [
|
93 |
'global_types' => $global_types,
|
98 |
],
|
99 |
];
|
100 |
|
101 |
+
SeoSettings::_nav_tab_wrapper(
|
102 |
+
'robots',
|
103 |
+
/**
|
104 |
+
* @since 2.2.4
|
105 |
+
* @param array $tabs The default tabs.
|
106 |
+
*/
|
107 |
+
(array) apply_filters( 'the_seo_framework_robots_settings_tabs', $tabs )
|
108 |
+
);
|
|
|
|
|
109 |
break;
|
110 |
|
111 |
+
case 'robots_general_tab':
|
112 |
+
HTML::header_title( __( 'Advanced Query Protection', 'autodescription' ) );
|
113 |
HTML::description( __( 'Some URL queries can cause WordPress to show faux archives. When search engines spot these, they will crawl and index them, which may cause a drop in ranking. Advanced query protection will prevent robots from indexing these archives.', 'autodescription' ) );
|
114 |
|
115 |
HTML::wrap_fields(
|
116 |
+
Input::make_checkbox( [
|
117 |
'id' => 'advanced_query_protection',
|
118 |
'label' => __( 'Enable advanced query protection?', 'autodescription' ),
|
119 |
] ),
|
122 |
?>
|
123 |
<hr>
|
124 |
<?php
|
125 |
+
HTML::header_title( __( 'Paginated Archive Settings', 'autodescription' ) );
|
126 |
HTML::description( __( "Indexing the second or later page of any archive might cause duplication errors. Search engines look down upon them; therefore, it's recommended to disable indexing of those pages.", 'autodescription' ) );
|
127 |
|
128 |
HTML::wrap_fields(
|
129 |
+
Input::make_checkbox( [
|
130 |
'id' => 'paged_noindex',
|
131 |
'label' => $this->convert_markdown(
|
132 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
140 |
?>
|
141 |
<hr>
|
142 |
<?php
|
143 |
+
HTML::header_title( __( 'Copyright Directive Settings', 'autodescription' ) );
|
144 |
HTML::description( __( "Some search engines allow you to control copyright directives on the content they aggregate. It's best to allow some content to be taken by these aggregators, as that can improve contextualized exposure via snippets and previews. When left unspecified, regional regulations may apply. It is up to the aggregator to honor these requests.", 'autodescription' ) );
|
145 |
|
146 |
HTML::wrap_fields(
|
147 |
+
Input::make_checkbox( [
|
148 |
'id' => 'set_copyright_directives',
|
149 |
'label' => __( 'Specify aggregator copyright compliance directives?', 'autodescription' ),
|
150 |
] ),
|
163 |
$_current = $this->get_option( 'max_snippet_length' );
|
164 |
foreach ( $_text_snippet_types as $_type => $_values ) {
|
165 |
$_label = 'default' === $_type
|
166 |
+
? __( 'Standard directive', 'autodescription' )
|
167 |
+
: __( 'Granular directive', 'autodescription' );
|
168 |
|
169 |
$_options = '';
|
170 |
foreach ( $_values as $_value => $_name ) {
|
186 |
<p><select name="%3$s" id="%1$s">%4$s</select></p>
|
187 |
<p class=description>%6$s</p>',
|
188 |
[
|
189 |
+
Input::get_field_id( 'max_snippet_length' ),
|
190 |
esc_html__( 'Maximum text snippet length', 'autodescription' ),
|
191 |
+
Input::get_field_name( 'max_snippet_length' ),
|
192 |
$text_snippet_options,
|
193 |
HTML::make_info(
|
194 |
__( 'This may limit the text snippet length for all pages on this site.', 'autodescription' ),
|
223 |
'<p><label for="%1$s"><strong>%2$s</strong> %5$s</label></p>
|
224 |
<p><select name="%3$s" id="%1$s">%4$s</select></p>',
|
225 |
[
|
226 |
+
Input::get_field_id( 'max_image_preview' ),
|
227 |
esc_html__( 'Maximum image preview size', 'autodescription' ),
|
228 |
+
Input::get_field_name( 'max_image_preview' ),
|
229 |
$image_preview_options,
|
230 |
HTML::make_info(
|
231 |
__( 'This may limit the image preview size for all images from this site.', 'autodescription' ),
|
249 |
$_current = $this->get_option( 'max_video_preview' );
|
250 |
foreach ( $_video_snippet_types as $_type => $_values ) {
|
251 |
$_label = 'default' === $_type
|
252 |
+
? __( 'Standard directive', 'autodescription' )
|
253 |
+
: __( 'Granular directive', 'autodescription' );
|
254 |
|
255 |
$_options = '';
|
256 |
foreach ( $_values as $_value => $_name ) {
|
271 |
'<p><label for="%1$s"><strong>%2$s</strong> %5$s</label></p>
|
272 |
<p><select name="%3$s" id="%1$s">%4$s</select></p>',
|
273 |
[
|
274 |
+
Input::get_field_id( 'max_video_preview' ),
|
275 |
esc_html__( 'Maximum video preview length', 'autodescription' ),
|
276 |
+
Input::get_field_name( 'max_video_preview' ),
|
277 |
$video_preview_options,
|
278 |
HTML::make_info(
|
279 |
__( 'This may limit the video preview length for all videos on this site.', 'autodescription' ),
|
286 |
);
|
287 |
break;
|
288 |
|
289 |
+
case 'robots_no_tab':
|
290 |
$ro_value = $robots['value'];
|
291 |
$ro_i18n = $robots['desc'];
|
292 |
|
297 |
|
298 |
$ro_name_wrapped = HTML::code_wrap( $ro_value );
|
299 |
|
300 |
+
HTML::header_title( __( 'Robots Settings', 'autodescription' ) );
|
|
|
|
|
|
|
301 |
HTML::description( $ro_i18n );
|
302 |
?>
|
303 |
<hr>
|
304 |
<?php
|
305 |
+
HTML::header_title( __( 'Post Type Settings', 'autodescription' ) );
|
306 |
HTML::description( __( 'These settings apply to the post type pages and their terms. When terms are shared between post types, all their post types should be checked for this to have an effect.', 'autodescription' ) );
|
307 |
|
|
|
|
|
308 |
// When the post OR page post types are available, show this warning.
|
309 |
if ( in_array( $ro_value, [ 'noindex', 'nofollow' ], true ) && array_intersect( $post_types, [ 'post', 'page' ] ) )
|
310 |
HTML::attention_description( __( 'Warning: No site should enable these options for Posts and Pages.', 'autodescription' ) );
|
311 |
|
|
|
312 |
$checkboxes = [];
|
313 |
|
314 |
+
$pt_option_id = $this->get_robots_post_type_option_id( $ro_value );
|
315 |
+
|
316 |
foreach ( $post_types as $post_type ) {
|
317 |
+
$checkboxes[] = Input::make_checkbox( [
|
318 |
+
'id' => [ $pt_option_id, $post_type ],
|
319 |
+
'class' => 'tsf-robots-post-types',
|
320 |
+
'label' => sprintf(
|
|
|
321 |
// RTL supported: Because the post types are Roman, browsers enforce the order.
|
322 |
'%s – <code>%s</code>',
|
323 |
sprintf( $apply_x_to_y_i18n_plural, $ro_name_wrapped, esc_html( $this->get_post_type_label( $post_type, false ) ) ),
|
324 |
esc_html( $post_type )
|
325 |
),
|
326 |
+
'escape' => false,
|
327 |
+
'data' => [
|
|
|
|
|
|
|
328 |
'robots' => $ro_value,
|
329 |
],
|
330 |
] );
|
335 |
?>
|
336 |
<hr>
|
337 |
<?php
|
338 |
+
HTML::header_title( __( 'Taxonomy Settings', 'autodescription' ) );
|
339 |
HTML::description( __( "These settings apply to the taxonomies of post types. When taxonomies have all their bound post types' options checked, they will inherit their status.", 'autodescription' ) );
|
340 |
|
341 |
$tax_option_id = $this->get_robots_taxonomy_option_id( $ro_value );
|
342 |
|
|
|
343 |
$checkboxes = [];
|
344 |
|
345 |
foreach ( $taxonomies as $taxonomy ) {
|
346 |
+
$checkboxes[] = Input::make_checkbox( [
|
347 |
+
'id' => [ $tax_option_id, $taxonomy ],
|
348 |
+
'class' => 'tsf-robots-taxonomies',
|
349 |
+
'label' => sprintf(
|
|
|
350 |
// RTL supported: Because the post types are Roman, browsers enforce the order.
|
351 |
'%s – <code>%s</code>',
|
352 |
sprintf( $apply_x_to_y_i18n_plural, $ro_name_wrapped, esc_html( $this->get_tax_type_label( $taxonomy, false ) ) ),
|
353 |
esc_html( $taxonomy )
|
354 |
),
|
355 |
+
'escape' => false,
|
356 |
+
'data' => [
|
|
|
|
|
|
|
357 |
'postTypes' => $this->get_post_types_from_taxonomy( $taxonomy ),
|
358 |
'robots' => $ro_value,
|
359 |
],
|
360 |
] );
|
361 |
}
|
362 |
|
363 |
+
// TODO can we assume that there's at least one taxonomy at all times? Can WP be used in this way, albeit headless?
|
364 |
HTML::wrap_fields( $checkboxes, true );
|
365 |
|
366 |
?>
|
367 |
<hr>
|
368 |
<?php
|
369 |
+
HTML::header_title( __( 'Global Settings', 'autodescription' ) );
|
370 |
HTML::description( __( 'These settings apply to other globally registered content types.', 'autodescription' ) );
|
371 |
|
372 |
$checkboxes = '';
|
378 |
esc_html( $data['i18n'] )
|
379 |
);
|
380 |
|
381 |
+
// Legacy.
|
382 |
+
$id = $this->s_field_id( "{$type}_{$ro_value}" );
|
383 |
|
384 |
// Add warning if it's 'site'.
|
385 |
if ( 'site' === $type ) {
|
392 |
);
|
393 |
}
|
394 |
|
395 |
+
$checkboxes .= Input::make_checkbox( [
|
396 |
'id' => $id,
|
397 |
+
'class' => 'site' === $type ? 'tsf-robots-site' : 'tsf-robots-globals',
|
398 |
'label' => $label,
|
399 |
'escape' => false,
|
400 |
+
'data' => [
|
401 |
+
'robots' => $ro_value,
|
402 |
+
],
|
403 |
] );
|
404 |
}
|
405 |
|
@@ -9,16 +9,14 @@
|
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
-
The_SEO_Framework\Interpreters\Form
|
|
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
switch ( $instance ) :
|
20 |
-
case 'the_seo_framework_schema_metabox_main':
|
21 |
-
Form::header_title( __( 'Schema.org Output Settings', 'autodescription' ) );
|
22 |
|
23 |
if ( $this->has_json_ld_plugin() )
|
24 |
HTML::attention_description( __( 'Another Schema.org plugin has been detected. These markup settings might conflict.', 'autodescription' ) );
|
@@ -27,38 +25,39 @@ switch ( $instance ) :
|
|
27 |
HTML::description( __( 'When your web pages include structured data markup, search engines can use that data to index your content better, present it more prominently in search results, and use it in several different applications.', 'autodescription' ) );
|
28 |
HTML::description( __( 'This is also known as the "Knowledge Graph" and "Structured Data", which is under heavy active development by several search engines. Therefore, the usage of the outputted markup is not guaranteed.', 'autodescription' ) );
|
29 |
|
30 |
-
$
|
|
|
|
|
31 |
'structure' => [
|
32 |
'name' => __( 'Structure', 'autodescription' ),
|
33 |
-
'callback' =>
|
34 |
'dashicon' => 'admin-multisite',
|
35 |
],
|
36 |
'presence' => [
|
37 |
'name' => __( 'Presence', 'autodescription' ),
|
38 |
-
'callback' =>
|
39 |
'dashicon' => 'networking',
|
40 |
],
|
41 |
];
|
42 |
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
SeoSettings::_nav_tab_wrapper( 'schema', $tabs );
|
53 |
break;
|
54 |
|
55 |
-
case '
|
56 |
-
|
57 |
HTML::description( __( 'The site structure Schema.org output allows search engines to gain knowledge on how your website is built.', 'autodescription' ) );
|
58 |
HTML::description( __( "For example, search engines display your pages' URLs when listed in the search results. These options allow you to enhance those URLs output.", 'autodescription' ) );
|
59 |
?>
|
60 |
-
<hr>
|
61 |
-
|
|
|
62 |
HTML::description( __( "Breadcrumb trails indicate page positions in the site's hierarchy. Using the following option will show the hierarchy within the search results when available.", 'autodescription' ) );
|
63 |
|
64 |
$info = HTML::make_info(
|
@@ -67,9 +66,9 @@ switch ( $instance ) :
|
|
67 |
false
|
68 |
);
|
69 |
HTML::wrap_fields(
|
70 |
-
|
71 |
'id' => 'ld_json_breadcrumbs',
|
72 |
-
'label' => esc_html__( 'Enable Breadcrumbs?', 'autodescription' ) .
|
73 |
'escape' => false,
|
74 |
] ),
|
75 |
true
|
@@ -87,17 +86,17 @@ switch ( $instance ) :
|
|
87 |
false
|
88 |
);
|
89 |
HTML::wrap_fields(
|
90 |
-
|
91 |
'id' => 'ld_json_searchbox',
|
92 |
-
'label' => esc_html_x( 'Enable Sitelinks Searchbox?', 'Sitelinks Searchbox is a Product name', 'autodescription' ) .
|
93 |
'escape' => false,
|
94 |
] ),
|
95 |
true
|
96 |
);
|
97 |
break;
|
98 |
|
99 |
-
case '
|
100 |
-
|
101 |
HTML::description( __( 'The authorized presence Schema.org output helps search engine users find ways to interact with this website.', 'autodescription' ) );
|
102 |
|
103 |
$info = HTML::make_info(
|
@@ -105,11 +104,10 @@ switch ( $instance ) :
|
|
105 |
'https://developers.google.com/search/docs/guides/enhance-site#add-your-sites-name-logo-and-social-links',
|
106 |
false
|
107 |
);
|
108 |
-
// Echo checkbox.
|
109 |
HTML::wrap_fields(
|
110 |
-
|
111 |
'id' => 'knowledge_output',
|
112 |
-
'label' => esc_html__( 'Output Authorized Presence?', 'autodescription' ) .
|
113 |
'escape' => false,
|
114 |
] ),
|
115 |
true
|
@@ -117,10 +115,10 @@ switch ( $instance ) :
|
|
117 |
?>
|
118 |
<hr>
|
119 |
|
120 |
-
<?php
|
121 |
<p>
|
122 |
-
<label for="<?php
|
123 |
-
<select name="<?php
|
124 |
<?php
|
125 |
$knowledge_type = (array) apply_filters(
|
126 |
'the_seo_framework_knowledge_types',
|
@@ -137,16 +135,16 @@ switch ( $instance ) :
|
|
137 |
</p>
|
138 |
|
139 |
<p>
|
140 |
-
<label for="<?php
|
141 |
<strong><?php esc_html_e( 'The organization or personal name', 'autodescription' ); ?></strong>
|
142 |
</label>
|
143 |
</p>
|
144 |
<p>
|
145 |
-
<input type="text" name="<?php
|
146 |
</p>
|
147 |
<hr>
|
148 |
<?php
|
149 |
-
|
150 |
HTML::description( esc_html__( 'These options are used when this site represents an organization. When no logo is outputted, search engine will look elsewhere.', 'autodescription' ) );
|
151 |
$info = HTML::make_info(
|
152 |
__( 'Learn how this data is used.', 'autodescription' ),
|
@@ -154,9 +152,9 @@ switch ( $instance ) :
|
|
154 |
false
|
155 |
);
|
156 |
HTML::wrap_fields(
|
157 |
-
|
158 |
'id' => 'knowledge_logo',
|
159 |
-
'label' => esc_html__( 'Enable logo?', 'autodescription' ) .
|
160 |
'escape' => false,
|
161 |
] ),
|
162 |
true );
|
@@ -168,16 +166,16 @@ switch ( $instance ) :
|
|
168 |
<strong><?php esc_html_e( 'Logo URL', 'autodescription' ); ?></strong>
|
169 |
</label>
|
170 |
</p>
|
|
|
171 |
<p>
|
172 |
-
<
|
173 |
-
<input
|
174 |
-
<input type="hidden" name="<?php Form::field_name( 'knowledge_logo_id' ); ?>" id="knowledge_logo-id" value="<?php echo absint( $this->get_option( 'knowledge_logo_id' ) ); ?>" />
|
175 |
</p>
|
176 |
<p class="hide-if-no-tsf-js">
|
177 |
<?php
|
178 |
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- already escaped.
|
179 |
echo Form::get_image_uploader_form( [
|
180 |
-
'id' => '
|
181 |
'data' => [
|
182 |
'inputType' => 'logo',
|
183 |
'width' => 512,
|
@@ -204,14 +202,14 @@ switch ( $instance ) :
|
|
204 |
'option' => 'knowledge_facebook',
|
205 |
'dashicon' => 'dashicons-facebook',
|
206 |
'desc' => __( 'Facebook Page', 'autodescription' ),
|
207 |
-
'placeholder' =>
|
208 |
'examplelink' => 'https://www.facebook.com/me',
|
209 |
],
|
210 |
'twitter' => [
|
211 |
'option' => 'knowledge_twitter',
|
212 |
'dashicon' => 'dashicons-twitter',
|
213 |
'desc' => __( 'Twitter Profile', 'autodescription' ),
|
214 |
-
'placeholder' =>
|
215 |
'examplelink' => 'https://twitter.com/home', // No example link available.
|
216 |
],
|
217 |
'gplus' => [
|
@@ -225,14 +223,14 @@ switch ( $instance ) :
|
|
225 |
'option' => 'knowledge_instagram',
|
226 |
'dashicon' => 'genericon-instagram',
|
227 |
'desc' => __( 'Instagram Profile', 'autodescription' ),
|
228 |
-
'placeholder' =>
|
229 |
'examplelink' => 'https://instagram.com/', // No example link available.
|
230 |
],
|
231 |
'youtube' => [
|
232 |
'option' => 'knowledge_youtube',
|
233 |
'dashicon' => 'genericon-youtube',
|
234 |
'desc' => __( 'Youtube Profile', 'autodescription' ),
|
235 |
-
'placeholder' =>
|
236 |
'examplelink' => 'https://www.youtube.com/user/%2f', // Yes a double slash.
|
237 |
],
|
238 |
'linkedin' => [
|
@@ -243,28 +241,28 @@ switch ( $instance ) :
|
|
243 |
* TODO switch to /in/ insteadof /company/ when knowledge-type is personal?
|
244 |
* Note that this feature is DEPRECATED. https://developers.google.com/search/docs/data-types/social-profile
|
245 |
*/
|
246 |
-
'placeholder' =>
|
247 |
'examplelink' => 'https://www.linkedin.com/profile/view',
|
248 |
],
|
249 |
'pinterest' => [
|
250 |
'option' => 'knowledge_pinterest',
|
251 |
'dashicon' => 'genericon-pinterest-alt',
|
252 |
'desc' => __( 'Pinterest Profile', 'autodescription' ),
|
253 |
-
'placeholder' =>
|
254 |
'examplelink' => 'https://www.pinterest.com/me/',
|
255 |
],
|
256 |
'soundcloud' => [
|
257 |
'option' => 'knowledge_soundcloud',
|
258 |
'dashicon' => 'genericon-cloud', // I know, it's not the real one. D:
|
259 |
'desc' => __( 'SoundCloud Profile', 'autodescription' ),
|
260 |
-
'placeholder' =>
|
261 |
'examplelink' => 'https://soundcloud.com/you',
|
262 |
],
|
263 |
'tumblr' => [
|
264 |
'option' => 'knowledge_tumblr',
|
265 |
'dashicon' => 'genericon-tumblr',
|
266 |
'desc' => __( 'Tumblr Blog', 'autodescription' ),
|
267 |
-
'placeholder' =>
|
268 |
'examplelink' => 'https://www.tumblr.com/dashboard', // No example link available.
|
269 |
],
|
270 |
];
|
@@ -282,7 +280,7 @@ switch ( $instance ) :
|
|
282 |
?>
|
283 |
<hr>
|
284 |
<?php
|
285 |
-
|
286 |
HTML::description( __( "Don't have a page at a site or is the profile only privately accessible? Leave that field empty. Unsure? Fill it in anyway.", 'autodescription' ) );
|
287 |
HTML::description( __( 'Add links that lead directly to the connected social pages of this website.', 'autodescription' ) );
|
288 |
HTML::description( __( 'These settings do not affect sharing behavior with the social networks.', 'autodescription' ) );
|
@@ -304,7 +302,7 @@ switch ( $instance ) :
|
|
304 |
|
305 |
?>
|
306 |
<p>
|
307 |
-
<label for="<?php
|
308 |
<strong><?php echo esc_html( $v['desc'] ); ?></strong>
|
309 |
<?php
|
310 |
if ( $v['examplelink'] ) {
|
@@ -317,7 +315,7 @@ switch ( $instance ) :
|
|
317 |
</label>
|
318 |
</p>
|
319 |
<p>
|
320 |
-
<input type="url" name="<?php
|
321 |
</p>
|
322 |
<?php
|
323 |
}
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
+
The_SEO_Framework\Interpreters\Form,
|
13 |
+
The_SEO_Framework\Interpreters\Settings_Input as Input;
|
14 |
|
15 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
16 |
|
17 |
+
switch ( $this->get_view_instance( 'schema', $instance ) ) :
|
18 |
+
case 'schema_main':
|
19 |
+
HTML::header_title( __( 'Schema.org Output Settings', 'autodescription' ) );
|
|
|
|
|
|
|
20 |
|
21 |
if ( $this->has_json_ld_plugin() )
|
22 |
HTML::attention_description( __( 'Another Schema.org plugin has been detected. These markup settings might conflict.', 'autodescription' ) );
|
25 |
HTML::description( __( 'When your web pages include structured data markup, search engines can use that data to index your content better, present it more prominently in search results, and use it in several different applications.', 'autodescription' ) );
|
26 |
HTML::description( __( 'This is also known as the "Knowledge Graph" and "Structured Data", which is under heavy active development by several search engines. Therefore, the usage of the outputted markup is not guaranteed.', 'autodescription' ) );
|
27 |
|
28 |
+
$_settings_class = SeoSettings::class;
|
29 |
+
|
30 |
+
$tabs = [
|
31 |
'structure' => [
|
32 |
'name' => __( 'Structure', 'autodescription' ),
|
33 |
+
'callback' => [ $_settings_class, '_schema_metabox_structure_tab' ],
|
34 |
'dashicon' => 'admin-multisite',
|
35 |
],
|
36 |
'presence' => [
|
37 |
'name' => __( 'Presence', 'autodescription' ),
|
38 |
+
'callback' => [ $_settings_class, '_schema_metabox_presence_tab' ],
|
39 |
'dashicon' => 'networking',
|
40 |
],
|
41 |
];
|
42 |
|
43 |
+
SeoSettings::_nav_tab_wrapper(
|
44 |
+
'schema',
|
45 |
+
/**
|
46 |
+
* @since 2.8.0
|
47 |
+
* @param array $defaults The default tabs.
|
48 |
+
*/
|
49 |
+
(array) apply_filters( 'the_seo_framework_schema_settings_tabs', $tabs )
|
50 |
+
);
|
|
|
|
|
51 |
break;
|
52 |
|
53 |
+
case 'schema_structure_tab':
|
54 |
+
HTML::header_title( __( 'Site Structure Options', 'autodescription' ) );
|
55 |
HTML::description( __( 'The site structure Schema.org output allows search engines to gain knowledge on how your website is built.', 'autodescription' ) );
|
56 |
HTML::description( __( "For example, search engines display your pages' URLs when listed in the search results. These options allow you to enhance those URLs output.", 'autodescription' ) );
|
57 |
?>
|
58 |
+
<hr>
|
59 |
+
<?php
|
60 |
+
HTML::header_title( __( 'Breadcrumbs', 'autodescription' ) );
|
61 |
HTML::description( __( "Breadcrumb trails indicate page positions in the site's hierarchy. Using the following option will show the hierarchy within the search results when available.", 'autodescription' ) );
|
62 |
|
63 |
$info = HTML::make_info(
|
66 |
false
|
67 |
);
|
68 |
HTML::wrap_fields(
|
69 |
+
Input::make_checkbox( [
|
70 |
'id' => 'ld_json_breadcrumbs',
|
71 |
+
'label' => esc_html__( 'Enable Breadcrumbs?', 'autodescription' ) . " $info",
|
72 |
'escape' => false,
|
73 |
] ),
|
74 |
true
|
86 |
false
|
87 |
);
|
88 |
HTML::wrap_fields(
|
89 |
+
Input::make_checkbox( [
|
90 |
'id' => 'ld_json_searchbox',
|
91 |
+
'label' => esc_html_x( 'Enable Sitelinks Searchbox?', 'Sitelinks Searchbox is a Product name', 'autodescription' ) . " $info",
|
92 |
'escape' => false,
|
93 |
] ),
|
94 |
true
|
95 |
);
|
96 |
break;
|
97 |
|
98 |
+
case 'schema_presence_tab':
|
99 |
+
HTML::header_title( __( 'Authorized Presence Options', 'autodescription' ) );
|
100 |
HTML::description( __( 'The authorized presence Schema.org output helps search engine users find ways to interact with this website.', 'autodescription' ) );
|
101 |
|
102 |
$info = HTML::make_info(
|
104 |
'https://developers.google.com/search/docs/guides/enhance-site#add-your-sites-name-logo-and-social-links',
|
105 |
false
|
106 |
);
|
|
|
107 |
HTML::wrap_fields(
|
108 |
+
Input::make_checkbox( [
|
109 |
'id' => 'knowledge_output',
|
110 |
+
'label' => esc_html__( 'Output Authorized Presence?', 'autodescription' ) . " $info",
|
111 |
'escape' => false,
|
112 |
] ),
|
113 |
true
|
115 |
?>
|
116 |
<hr>
|
117 |
|
118 |
+
<?php HTML::header_title( __( 'About this website', 'autodescription' ) ); ?>
|
119 |
<p>
|
120 |
+
<label for="<?php Input::field_id( 'knowledge_type' ); ?>"><?php echo esc_html_x( 'This website represents:', '...Organization or Person.', 'autodescription' ); ?></label>
|
121 |
+
<select name="<?php Input::field_name( 'knowledge_type' ); ?>" id="<?php Input::field_id( 'knowledge_type' ); ?>">
|
122 |
<?php
|
123 |
$knowledge_type = (array) apply_filters(
|
124 |
'the_seo_framework_knowledge_types',
|
135 |
</p>
|
136 |
|
137 |
<p>
|
138 |
+
<label for="<?php Input::field_id( 'knowledge_name' ); ?>">
|
139 |
<strong><?php esc_html_e( 'The organization or personal name', 'autodescription' ); ?></strong>
|
140 |
</label>
|
141 |
</p>
|
142 |
<p>
|
143 |
+
<input type="text" name="<?php Input::field_name( 'knowledge_name' ); ?>" class="large-text" id="<?php Input::field_id( 'knowledge_name' ); ?>" placeholder="<?php echo esc_attr( $this->get_blogname() ); ?>" value="<?php echo esc_attr( $this->get_option( 'knowledge_name' ) ); ?>" autocomplete=off />
|
144 |
</p>
|
145 |
<hr>
|
146 |
<?php
|
147 |
+
HTML::header_title( __( 'Website logo', 'autodescription' ) );
|
148 |
HTML::description( esc_html__( 'These options are used when this site represents an organization. When no logo is outputted, search engine will look elsewhere.', 'autodescription' ) );
|
149 |
$info = HTML::make_info(
|
150 |
__( 'Learn how this data is used.', 'autodescription' ),
|
152 |
false
|
153 |
);
|
154 |
HTML::wrap_fields(
|
155 |
+
Input::make_checkbox( [
|
156 |
'id' => 'knowledge_logo',
|
157 |
+
'label' => esc_html__( 'Enable logo?', 'autodescription' ) . " $info",
|
158 |
'escape' => false,
|
159 |
] ),
|
160 |
true );
|
166 |
<strong><?php esc_html_e( 'Logo URL', 'autodescription' ); ?></strong>
|
167 |
</label>
|
168 |
</p>
|
169 |
+
<p class="hide-if-tsf-js attention"><?php esc_html_e( 'Setting a logo requires JavaScript.', 'autodescription' ); ?></p>
|
170 |
<p>
|
171 |
+
<input class="large-text" type="url" readonly="readonly" data-readonly="1" name="<?php Input::field_name( 'knowledge_logo_url' ); ?>" id="knowledge_logo-url" placeholder="<?php echo esc_url( $logo_placeholder ); ?>" value="<?php echo esc_url( $this->get_option( 'knowledge_logo_url' ) ); ?>" />
|
172 |
+
<input type="hidden" name="<?php Input::field_name( 'knowledge_logo_id' ); ?>" id="knowledge_logo-id" value="<?php echo absint( $this->get_option( 'knowledge_logo_id' ) ); ?>" />
|
|
|
173 |
</p>
|
174 |
<p class="hide-if-no-tsf-js">
|
175 |
<?php
|
176 |
// phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- already escaped.
|
177 |
echo Form::get_image_uploader_form( [
|
178 |
+
'id' => 'knowledge_logo',
|
179 |
'data' => [
|
180 |
'inputType' => 'logo',
|
181 |
'width' => 512,
|
202 |
'option' => 'knowledge_facebook',
|
203 |
'dashicon' => 'dashicons-facebook',
|
204 |
'desc' => __( 'Facebook Page', 'autodescription' ),
|
205 |
+
'placeholder' => "https://www.facebook.com/$connectedi18n",
|
206 |
'examplelink' => 'https://www.facebook.com/me',
|
207 |
],
|
208 |
'twitter' => [
|
209 |
'option' => 'knowledge_twitter',
|
210 |
'dashicon' => 'dashicons-twitter',
|
211 |
'desc' => __( 'Twitter Profile', 'autodescription' ),
|
212 |
+
'placeholder' => "https://twitter.com/$connectedi18n",
|
213 |
'examplelink' => 'https://twitter.com/home', // No example link available.
|
214 |
],
|
215 |
'gplus' => [
|
223 |
'option' => 'knowledge_instagram',
|
224 |
'dashicon' => 'genericon-instagram',
|
225 |
'desc' => __( 'Instagram Profile', 'autodescription' ),
|
226 |
+
'placeholder' => "https://instagram.com/$connectedi18n",
|
227 |
'examplelink' => 'https://instagram.com/', // No example link available.
|
228 |
],
|
229 |
'youtube' => [
|
230 |
'option' => 'knowledge_youtube',
|
231 |
'dashicon' => 'genericon-youtube',
|
232 |
'desc' => __( 'Youtube Profile', 'autodescription' ),
|
233 |
+
'placeholder' => "https://www.youtube.com/channel/$connectedi18n",
|
234 |
'examplelink' => 'https://www.youtube.com/user/%2f', // Yes a double slash.
|
235 |
],
|
236 |
'linkedin' => [
|
241 |
* TODO switch to /in/ insteadof /company/ when knowledge-type is personal?
|
242 |
* Note that this feature is DEPRECATED. https://developers.google.com/search/docs/data-types/social-profile
|
243 |
*/
|
244 |
+
'placeholder' => "https://www.linkedin.com/company/$connectedi18n/",
|
245 |
'examplelink' => 'https://www.linkedin.com/profile/view',
|
246 |
],
|
247 |
'pinterest' => [
|
248 |
'option' => 'knowledge_pinterest',
|
249 |
'dashicon' => 'genericon-pinterest-alt',
|
250 |
'desc' => __( 'Pinterest Profile', 'autodescription' ),
|
251 |
+
'placeholder' => "https://www.pinterest.com/$connectedi18n/",
|
252 |
'examplelink' => 'https://www.pinterest.com/me/',
|
253 |
],
|
254 |
'soundcloud' => [
|
255 |
'option' => 'knowledge_soundcloud',
|
256 |
'dashicon' => 'genericon-cloud', // I know, it's not the real one. D:
|
257 |
'desc' => __( 'SoundCloud Profile', 'autodescription' ),
|
258 |
+
'placeholder' => "https://soundcloud.com/$connectedi18n",
|
259 |
'examplelink' => 'https://soundcloud.com/you',
|
260 |
],
|
261 |
'tumblr' => [
|
262 |
'option' => 'knowledge_tumblr',
|
263 |
'dashicon' => 'genericon-tumblr',
|
264 |
'desc' => __( 'Tumblr Blog', 'autodescription' ),
|
265 |
+
'placeholder' => "https://www.tumblr.com/blog/$connectedi18n",
|
266 |
'examplelink' => 'https://www.tumblr.com/dashboard', // No example link available.
|
267 |
],
|
268 |
];
|
280 |
?>
|
281 |
<hr>
|
282 |
<?php
|
283 |
+
HTML::header_title( __( 'Connected Social Pages', 'autodescription' ) );
|
284 |
HTML::description( __( "Don't have a page at a site or is the profile only privately accessible? Leave that field empty. Unsure? Fill it in anyway.", 'autodescription' ) );
|
285 |
HTML::description( __( 'Add links that lead directly to the connected social pages of this website.', 'autodescription' ) );
|
286 |
HTML::description( __( 'These settings do not affect sharing behavior with the social networks.', 'autodescription' ) );
|
302 |
|
303 |
?>
|
304 |
<p>
|
305 |
+
<label for="<?php Input::field_id( $v['option'] ); ?>">
|
306 |
<strong><?php echo esc_html( $v['desc'] ); ?></strong>
|
307 |
<?php
|
308 |
if ( $v['examplelink'] ) {
|
315 |
</label>
|
316 |
</p>
|
317 |
<p>
|
318 |
+
<input type="url" name="<?php Input::field_name( $v['option'] ); ?>" class="large-text" id="<?php Input::field_id( $v['option'] ); ?>" placeholder="<?php echo esc_attr( $v['placeholder'] ); ?>" value="<?php echo esc_attr( $this->get_option( $v['option'] ) ); ?>" autocomplete=off />
|
319 |
</p>
|
320 |
<?php
|
321 |
}
|
@@ -9,61 +9,60 @@
|
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
-
The_SEO_Framework\Interpreters\Form
|
|
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
|
16 |
-
|
17 |
-
|
|
|
18 |
|
19 |
-
|
20 |
-
case 'the_seo_framework_sitemaps_metabox_main':
|
21 |
-
$default_tabs = [
|
22 |
'general' => [
|
23 |
'name' => __( 'General', 'autodescription' ),
|
24 |
-
'callback' =>
|
25 |
'dashicon' => 'admin-generic',
|
26 |
],
|
27 |
'robots' => [
|
28 |
'name' => 'Robots.txt',
|
29 |
-
'callback' =>
|
30 |
'dashicon' => 'share-alt2',
|
31 |
],
|
32 |
'metadata' => [
|
33 |
'name' => __( 'Metadata', 'autodescription' ),
|
34 |
-
'callback' =>
|
35 |
'dashicon' => 'index-card',
|
36 |
],
|
37 |
'notify' => [
|
38 |
'name' => _x( 'Ping', 'Ping or notify search engine', 'autodescription' ),
|
39 |
-
'callback' =>
|
40 |
'dashicon' => 'megaphone',
|
41 |
],
|
42 |
'style' => [
|
43 |
'name' => __( 'Style', 'autodescription' ),
|
44 |
-
'callback' =>
|
45 |
'dashicon' => 'art',
|
46 |
],
|
47 |
];
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
SeoSettings::_nav_tab_wrapper( 'sitemaps', $tabs );
|
58 |
break;
|
59 |
|
60 |
-
case '
|
61 |
$sitemap_url = The_SEO_Framework\Bridges\Sitemap::get_instance()->get_expected_sitemap_endpoint_url();
|
62 |
$has_sitemap_plugin = $this->detect_sitemap_plugin();
|
63 |
$use_core_sitemaps = $this->use_core_sitemaps();
|
64 |
$sitemap_detected = $this->has_sitemap_xml();
|
65 |
|
66 |
-
|
67 |
HTML::description( __( 'The sitemap is an XML file that lists indexable pages of your website along with optional metadata. It helps search engines find new and updated content quickly.', 'autodescription' ) );
|
68 |
|
69 |
HTML::description_noesc(
|
@@ -88,11 +87,10 @@ switch ( $instance ) :
|
|
88 |
?>
|
89 |
<hr>
|
90 |
<?php
|
91 |
-
|
92 |
|
93 |
-
// Echo checkbox.
|
94 |
HTML::wrap_fields(
|
95 |
-
|
96 |
'id' => 'sitemaps_output',
|
97 |
'label' => esc_html__( 'Output optimized sitemap?', 'autodescription' )
|
98 |
. ' ' . HTML::make_info(
|
@@ -127,13 +125,31 @@ switch ( $instance ) :
|
|
127 |
)
|
128 |
);
|
129 |
}
|
130 |
-
}
|
131 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
?>
|
133 |
<hr>
|
134 |
|
135 |
<p>
|
136 |
-
<label for="<?php
|
137 |
<strong><?php esc_html_e( 'Sitemap Query Limit', 'autodescription' ); ?></strong>
|
138 |
</label>
|
139 |
</p>
|
@@ -142,26 +158,26 @@ switch ( $instance ) :
|
|
142 |
|
143 |
if ( has_filter( 'the_seo_framework_sitemap_post_limit' ) ) :
|
144 |
?>
|
145 |
-
<input type=hidden name="<?php
|
146 |
<p>
|
147 |
-
<input type="number" id="<?php
|
148 |
</p>
|
149 |
<?php
|
150 |
else :
|
151 |
?>
|
152 |
<p>
|
153 |
-
<input type="number" min=1 max=50000 name="<?php
|
154 |
</p>
|
155 |
<?php
|
156 |
endif;
|
157 |
HTML::description( __( 'Consider lowering this value when the sitemap shows a white screen or notifies you of memory exhaustion.', 'autodescription' ) );
|
158 |
break;
|
159 |
|
160 |
-
case '
|
161 |
$show_settings = true;
|
162 |
$robots_url = $this->get_robots_txt_url();
|
163 |
|
164 |
-
|
165 |
|
166 |
if ( $this->has_robots_txt() ) :
|
167 |
HTML::attention_description(
|
@@ -200,12 +216,9 @@ switch ( $instance ) :
|
|
200 |
echo '<hr>';
|
201 |
|
202 |
if ( $show_settings ) :
|
203 |
-
|
204 |
-
'<h4>%s</h4>',
|
205 |
-
esc_html__( 'Sitemap Hinting', 'autodescription' )
|
206 |
-
);
|
207 |
HTML::wrap_fields(
|
208 |
-
|
209 |
'id' => 'sitemaps_robots',
|
210 |
'label' => __( 'Add sitemap location to robots.txt?', 'autodescription' ),
|
211 |
] ),
|
@@ -226,13 +239,12 @@ switch ( $instance ) :
|
|
226 |
}
|
227 |
break;
|
228 |
|
229 |
-
case '
|
230 |
-
|
231 |
HTML::description( __( 'The modified time suggests to search engines where to look for content changes first.', 'autodescription' ) );
|
232 |
|
233 |
-
// Echo checkbox.
|
234 |
HTML::wrap_fields(
|
235 |
-
|
236 |
'id' => 'sitemaps_modified',
|
237 |
'label' => $this->convert_markdown(
|
238 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
@@ -243,38 +255,16 @@ switch ( $instance ) :
|
|
243 |
] ),
|
244 |
true
|
245 |
);
|
246 |
-
|
247 |
-
if ( $this->get_option( 'sitemaps_priority' ) ) :
|
248 |
-
?>
|
249 |
-
<hr>
|
250 |
-
<?php
|
251 |
-
Form::header_title( __( 'Priority Settings', 'autodescription' ) );
|
252 |
-
HTML::description( __( 'The priority index suggests to search engines which pages are deemed more important. It has no known impact on the SEO value and it is generally ignored.', 'autodescription' ) );
|
253 |
-
|
254 |
-
// Echo checkbox.
|
255 |
-
HTML::wrap_fields(
|
256 |
-
Form::make_checkbox( [
|
257 |
-
'id' => 'sitemaps_priority',
|
258 |
-
'label' => $this->convert_markdown(
|
259 |
-
/* translators: the backticks are Markdown! Preserve them as-is! */
|
260 |
-
esc_html__( 'Add `<priority>` to the optimized sitemap?', 'autodescription' ),
|
261 |
-
[ 'code' ]
|
262 |
-
),
|
263 |
-
'escape' => false,
|
264 |
-
] ),
|
265 |
-
true
|
266 |
-
);
|
267 |
-
endif;
|
268 |
break;
|
269 |
|
270 |
-
case '
|
271 |
-
|
272 |
HTML::description( __( 'Notifying search engines of a sitemap change is helpful to get your content indexed as soon as possible.', 'autodescription' ) );
|
273 |
HTML::description( __( 'By default this will happen at most once an hour.', 'autodescription' ) );
|
274 |
|
275 |
HTML::wrap_fields(
|
276 |
[
|
277 |
-
|
278 |
'id' => 'ping_use_cron',
|
279 |
'label' => esc_html__( 'Use cron for pinging?', 'autodescription' )
|
280 |
. ' ' . HTML::make_info(
|
@@ -284,7 +274,7 @@ switch ( $instance ) :
|
|
284 |
),
|
285 |
'escape' => false,
|
286 |
] ),
|
287 |
-
|
288 |
'id' => 'ping_use_cron_prerender',
|
289 |
'label' => esc_html__( 'Prerender optimized sitemap before pinging via cron?', 'autodescription' )
|
290 |
. ' ' . HTML::make_info(
|
@@ -302,7 +292,7 @@ switch ( $instance ) :
|
|
302 |
?>
|
303 |
<hr>
|
304 |
<?php
|
305 |
-
|
306 |
|
307 |
$engines = [
|
308 |
'ping_google' => 'Google',
|
@@ -314,27 +304,26 @@ switch ( $instance ) :
|
|
314 |
foreach ( $engines as $option => $engine ) {
|
315 |
/* translators: %s = Google */
|
316 |
$ping_label = sprintf( __( 'Notify %s about sitemap changes?', 'autodescription' ), $engine );
|
317 |
-
$ping_checkbox .=
|
318 |
'id' => $option,
|
319 |
'label' => $ping_label,
|
320 |
] );
|
321 |
}
|
322 |
|
323 |
-
// Echo checkbox.
|
324 |
HTML::wrap_fields( $ping_checkbox, true );
|
325 |
break;
|
326 |
|
327 |
-
case '
|
328 |
-
|
329 |
HTML::description( __( 'You can style the optimized sitemap to give it a more personal look for your visitors. Search engines do not use these styles.', 'autodescription' ) );
|
330 |
HTML::description( __( 'Note: Changes may not appear to have an effect directly because the stylesheet is cached in the browser for 30 minutes.', 'autodescription' ) );
|
331 |
?>
|
332 |
<hr>
|
333 |
<?php
|
334 |
-
|
335 |
|
336 |
HTML::wrap_fields(
|
337 |
-
|
338 |
'id' => 'sitemap_styles',
|
339 |
'label' => esc_html__( 'Style sitemap?', 'autodescription' ) . ' ' . HTML::make_info( __( 'This makes the sitemap more readable for humans.', 'autodescription' ), '', false ),
|
340 |
'escape' => false,
|
@@ -351,29 +340,29 @@ switch ( $instance ) :
|
|
351 |
|
352 |
?>
|
353 |
<p>
|
354 |
-
<label for="<?php
|
355 |
<strong><?php esc_html_e( 'Sitemap Header Background Color', 'autodescription' ); ?></strong>
|
356 |
</label>
|
357 |
</p>
|
358 |
<p>
|
359 |
-
<input type="text" name="<?php
|
360 |
</p>
|
361 |
|
362 |
<p>
|
363 |
-
<label for="<?php
|
364 |
<strong><?php esc_html_e( 'Sitemap Title and Lines Color', 'autodescription' ); ?></strong>
|
365 |
</label>
|
366 |
</p>
|
367 |
<p>
|
368 |
-
<input type="text" name="<?php
|
369 |
</p>
|
370 |
|
371 |
<hr>
|
372 |
<?php
|
373 |
-
|
374 |
|
375 |
HTML::wrap_fields(
|
376 |
-
|
377 |
'id' => 'sitemap_logo',
|
378 |
'label' => __( 'Show logo next to sitemap header title?', 'autodescription' ),
|
379 |
] ),
|
@@ -391,10 +380,10 @@ switch ( $instance ) :
|
|
391 |
<strong><?php esc_html_e( 'Logo URL', 'autodescription' ); ?></strong>
|
392 |
</label>
|
393 |
</p>
|
|
|
394 |
<p>
|
395 |
-
<
|
396 |
-
<input
|
397 |
-
<input type="hidden" name="<?php Form::field_name( 'sitemap_logo_id' ); ?>" id="sitemap_logo-id" value="<?php echo absint( $this->get_option( 'sitemap_logo_id' ) ); ?>" />
|
398 |
</p>
|
399 |
<p class="hide-if-no-tsf-js">
|
400 |
<?php
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
+
The_SEO_Framework\Interpreters\Form,
|
13 |
+
The_SEO_Framework\Interpreters\Settings_Input as Input;
|
14 |
|
15 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
16 |
|
17 |
+
switch ( $this->get_view_instance( 'sitemaps', $instance ) ) :
|
18 |
+
case 'sitemaps_main':
|
19 |
+
$_settings_class = SeoSettings::class;
|
20 |
|
21 |
+
$tabs = [
|
|
|
|
|
22 |
'general' => [
|
23 |
'name' => __( 'General', 'autodescription' ),
|
24 |
+
'callback' => [ $_settings_class, '_sitemaps_metabox_general_tab' ],
|
25 |
'dashicon' => 'admin-generic',
|
26 |
],
|
27 |
'robots' => [
|
28 |
'name' => 'Robots.txt',
|
29 |
+
'callback' => [ $_settings_class, '_sitemaps_metabox_robots_tab' ],
|
30 |
'dashicon' => 'share-alt2',
|
31 |
],
|
32 |
'metadata' => [
|
33 |
'name' => __( 'Metadata', 'autodescription' ),
|
34 |
+
'callback' => [ $_settings_class, '_sitemaps_metabox_metadata_tab' ],
|
35 |
'dashicon' => 'index-card',
|
36 |
],
|
37 |
'notify' => [
|
38 |
'name' => _x( 'Ping', 'Ping or notify search engine', 'autodescription' ),
|
39 |
+
'callback' => [ $_settings_class, '_sitemaps_metabox_notify_tab' ],
|
40 |
'dashicon' => 'megaphone',
|
41 |
],
|
42 |
'style' => [
|
43 |
'name' => __( 'Style', 'autodescription' ),
|
44 |
+
'callback' => [ $_settings_class, '_sitemaps_metabox_style_tab' ],
|
45 |
'dashicon' => 'art',
|
46 |
],
|
47 |
];
|
48 |
|
49 |
+
SeoSettings::_nav_tab_wrapper(
|
50 |
+
'sitemaps',
|
51 |
+
/**
|
52 |
+
* @since 2.6.0
|
53 |
+
* @param array $tabs The default tabs.
|
54 |
+
*/
|
55 |
+
(array) apply_filters( 'the_seo_framework_sitemaps_settings_tabs', $tabs )
|
56 |
+
);
|
|
|
57 |
break;
|
58 |
|
59 |
+
case 'sitemaps_general_tab':
|
60 |
$sitemap_url = The_SEO_Framework\Bridges\Sitemap::get_instance()->get_expected_sitemap_endpoint_url();
|
61 |
$has_sitemap_plugin = $this->detect_sitemap_plugin();
|
62 |
$use_core_sitemaps = $this->use_core_sitemaps();
|
63 |
$sitemap_detected = $this->has_sitemap_xml();
|
64 |
|
65 |
+
HTML::header_title( __( 'Sitemap Integration Settings', 'autodescription' ) );
|
66 |
HTML::description( __( 'The sitemap is an XML file that lists indexable pages of your website along with optional metadata. It helps search engines find new and updated content quickly.', 'autodescription' ) );
|
67 |
|
68 |
HTML::description_noesc(
|
87 |
?>
|
88 |
<hr>
|
89 |
<?php
|
90 |
+
HTML::header_title( __( 'Sitemap Output', 'autodescription' ) );
|
91 |
|
|
|
92 |
HTML::wrap_fields(
|
93 |
+
Input::make_checkbox( [
|
94 |
'id' => 'sitemaps_output',
|
95 |
'label' => esc_html__( 'Output optimized sitemap?', 'autodescription' )
|
96 |
. ' ' . HTML::make_info(
|
125 |
)
|
126 |
);
|
127 |
}
|
|
|
128 |
|
129 |
+
/**
|
130 |
+
* @since 4.2.0
|
131 |
+
* @param bool $tell Whether to tell that there's a plugin active that can use multiple sitemaps.
|
132 |
+
*/
|
133 |
+
if ( apply_filters( 'the_seo_framework_tell_multilingual_sitemap', false ) ) {
|
134 |
+
HTML::description_noesc(
|
135 |
+
// Markdown escapes.
|
136 |
+
$this->convert_markdown(
|
137 |
+
sprintf(
|
138 |
+
/* translators: %s = Documentation URL in markdown */
|
139 |
+
esc_html__( 'A multilingual plugin has been detected, so your site may have multiple sitemaps. [Learn more](%s).', 'autodescription' ),
|
140 |
+
'https://kb.theseoframework.com/?p=104#same-site-sitemaps'
|
141 |
+
),
|
142 |
+
[ 'a' ],
|
143 |
+
[ 'a_internal' => false ] // opens in new tab.
|
144 |
+
)
|
145 |
+
);
|
146 |
+
}
|
147 |
+
}
|
148 |
?>
|
149 |
<hr>
|
150 |
|
151 |
<p>
|
152 |
+
<label for="<?php Input::field_id( 'sitemap_query_limit' ); ?>">
|
153 |
<strong><?php esc_html_e( 'Sitemap Query Limit', 'autodescription' ); ?></strong>
|
154 |
</label>
|
155 |
</p>
|
158 |
|
159 |
if ( has_filter( 'the_seo_framework_sitemap_post_limit' ) ) :
|
160 |
?>
|
161 |
+
<input type=hidden name="<?php Input::field_name( 'sitemap_query_limit' ); ?>" value="<?php echo absint( $this->get_sitemap_post_limit() ); ?>">
|
162 |
<p>
|
163 |
+
<input type="number" id="<?php Input::field_id( 'sitemap_query_limit' ); ?>" value="<?php echo absint( $this->get_sitemap_post_limit() ); ?>" disabled />
|
164 |
</p>
|
165 |
<?php
|
166 |
else :
|
167 |
?>
|
168 |
<p>
|
169 |
+
<input type="number" min=1 max=50000 name="<?php Input::field_name( 'sitemap_query_limit' ); ?>" id="<?php Input::field_id( 'sitemap_query_limit' ); ?>" placeholder="<?php echo absint( $this->get_default_option( 'sitemap_query_limit' ) ); ?>" value="<?php echo absint( $this->get_option( 'sitemap_query_limit' ) ); ?>" />
|
170 |
</p>
|
171 |
<?php
|
172 |
endif;
|
173 |
HTML::description( __( 'Consider lowering this value when the sitemap shows a white screen or notifies you of memory exhaustion.', 'autodescription' ) );
|
174 |
break;
|
175 |
|
176 |
+
case 'sitemaps_robots_tab':
|
177 |
$show_settings = true;
|
178 |
$robots_url = $this->get_robots_txt_url();
|
179 |
|
180 |
+
HTML::header_title( __( 'Robots.txt Settings', 'autodescription' ) );
|
181 |
|
182 |
if ( $this->has_robots_txt() ) :
|
183 |
HTML::attention_description(
|
216 |
echo '<hr>';
|
217 |
|
218 |
if ( $show_settings ) :
|
219 |
+
HTML::header_title( __( 'Sitemap Hinting', 'autodescription' ) );
|
|
|
|
|
|
|
220 |
HTML::wrap_fields(
|
221 |
+
Input::make_checkbox( [
|
222 |
'id' => 'sitemaps_robots',
|
223 |
'label' => __( 'Add sitemap location to robots.txt?', 'autodescription' ),
|
224 |
] ),
|
239 |
}
|
240 |
break;
|
241 |
|
242 |
+
case 'sitemaps_metadata_tab':
|
243 |
+
HTML::header_title( __( 'Timestamps Settings', 'autodescription' ) );
|
244 |
HTML::description( __( 'The modified time suggests to search engines where to look for content changes first.', 'autodescription' ) );
|
245 |
|
|
|
246 |
HTML::wrap_fields(
|
247 |
+
Input::make_checkbox( [
|
248 |
'id' => 'sitemaps_modified',
|
249 |
'label' => $this->convert_markdown(
|
250 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
255 |
] ),
|
256 |
true
|
257 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
break;
|
259 |
|
260 |
+
case 'sitemaps_notify_tab':
|
261 |
+
HTML::header_title( __( 'Ping Settings', 'autodescription' ) );
|
262 |
HTML::description( __( 'Notifying search engines of a sitemap change is helpful to get your content indexed as soon as possible.', 'autodescription' ) );
|
263 |
HTML::description( __( 'By default this will happen at most once an hour.', 'autodescription' ) );
|
264 |
|
265 |
HTML::wrap_fields(
|
266 |
[
|
267 |
+
Input::make_checkbox( [
|
268 |
'id' => 'ping_use_cron',
|
269 |
'label' => esc_html__( 'Use cron for pinging?', 'autodescription' )
|
270 |
. ' ' . HTML::make_info(
|
274 |
),
|
275 |
'escape' => false,
|
276 |
] ),
|
277 |
+
Input::make_checkbox( [
|
278 |
'id' => 'ping_use_cron_prerender',
|
279 |
'label' => esc_html__( 'Prerender optimized sitemap before pinging via cron?', 'autodescription' )
|
280 |
. ' ' . HTML::make_info(
|
292 |
?>
|
293 |
<hr>
|
294 |
<?php
|
295 |
+
HTML::header_title( __( 'Notify Search Engines', 'autodescription' ) );
|
296 |
|
297 |
$engines = [
|
298 |
'ping_google' => 'Google',
|
304 |
foreach ( $engines as $option => $engine ) {
|
305 |
/* translators: %s = Google */
|
306 |
$ping_label = sprintf( __( 'Notify %s about sitemap changes?', 'autodescription' ), $engine );
|
307 |
+
$ping_checkbox .= Input::make_checkbox( [
|
308 |
'id' => $option,
|
309 |
'label' => $ping_label,
|
310 |
] );
|
311 |
}
|
312 |
|
|
|
313 |
HTML::wrap_fields( $ping_checkbox, true );
|
314 |
break;
|
315 |
|
316 |
+
case 'sitemaps_style_tab':
|
317 |
+
HTML::header_title( __( 'Optimized Sitemap Styling Settings', 'autodescription' ) );
|
318 |
HTML::description( __( 'You can style the optimized sitemap to give it a more personal look for your visitors. Search engines do not use these styles.', 'autodescription' ) );
|
319 |
HTML::description( __( 'Note: Changes may not appear to have an effect directly because the stylesheet is cached in the browser for 30 minutes.', 'autodescription' ) );
|
320 |
?>
|
321 |
<hr>
|
322 |
<?php
|
323 |
+
HTML::header_title( __( 'Enable Styling', 'autodescription' ) );
|
324 |
|
325 |
HTML::wrap_fields(
|
326 |
+
Input::make_checkbox( [
|
327 |
'id' => 'sitemap_styles',
|
328 |
'label' => esc_html__( 'Style sitemap?', 'autodescription' ) . ' ' . HTML::make_info( __( 'This makes the sitemap more readable for humans.', 'autodescription' ), '', false ),
|
329 |
'escape' => false,
|
340 |
|
341 |
?>
|
342 |
<p>
|
343 |
+
<label for="<?php Input::field_id( 'sitemap_color_main' ); ?>">
|
344 |
<strong><?php esc_html_e( 'Sitemap Header Background Color', 'autodescription' ); ?></strong>
|
345 |
</label>
|
346 |
</p>
|
347 |
<p>
|
348 |
+
<input type="text" name="<?php Input::field_name( 'sitemap_color_main' ); ?>" class="tsf-color-picker" id="<?php Input::field_id( 'sitemap_color_main' ); ?>" placeholder="<?php echo esc_attr( $default_colors['main'] ); ?>" value="<?php echo esc_attr( $current_colors['main'] ); ?>" data-tsf-default-color="<?php echo esc_attr( $default_colors['main'] ); ?>" />
|
349 |
</p>
|
350 |
|
351 |
<p>
|
352 |
+
<label for="<?php Input::field_id( 'sitemap_color_accent' ); ?>">
|
353 |
<strong><?php esc_html_e( 'Sitemap Title and Lines Color', 'autodescription' ); ?></strong>
|
354 |
</label>
|
355 |
</p>
|
356 |
<p>
|
357 |
+
<input type="text" name="<?php Input::field_name( 'sitemap_color_accent' ); ?>" class="tsf-color-picker" id="<?php Input::field_id( 'sitemap_color_accent' ); ?>" placeholder="<?php echo esc_attr( $default_colors['accent'] ); ?>" value="<?php echo esc_attr( $current_colors['accent'] ); ?>" data-tsf-default-color="<?php echo esc_attr( $default_colors['accent'] ); ?>" />
|
358 |
</p>
|
359 |
|
360 |
<hr>
|
361 |
<?php
|
362 |
+
HTML::header_title( __( 'Header Title Logo', 'autodescription' ) );
|
363 |
|
364 |
HTML::wrap_fields(
|
365 |
+
Input::make_checkbox( [
|
366 |
'id' => 'sitemap_logo',
|
367 |
'label' => __( 'Show logo next to sitemap header title?', 'autodescription' ),
|
368 |
] ),
|
380 |
<strong><?php esc_html_e( 'Logo URL', 'autodescription' ); ?></strong>
|
381 |
</label>
|
382 |
</p>
|
383 |
+
<p class="hide-if-tsf-js attention"><?php esc_html_e( 'Setting a logo requires JavaScript.', 'autodescription' ); ?></p>
|
384 |
<p>
|
385 |
+
<input class="large-text" type="url" readonly="readonly" data-readonly="1" name="<?php Input::field_name( 'sitemap_logo_url' ); ?>" id="sitemap_logo-url" placeholder="<?php echo esc_url( $logo_placeholder ); ?>" value="<?php echo esc_url( $this->get_option( 'sitemap_logo_url' ) ); ?>" />
|
386 |
+
<input type="hidden" name="<?php Input::field_name( 'sitemap_logo_id' ); ?>" id="sitemap_logo-id" value="<?php echo absint( $this->get_option( 'sitemap_logo_id' ) ); ?>" />
|
|
|
387 |
</p>
|
388 |
<p class="hide-if-no-tsf-js">
|
389 |
<?php
|
@@ -9,57 +9,55 @@
|
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
-
The_SEO_Framework\Interpreters\Form
|
|
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
|
16 |
-
|
17 |
-
|
|
|
18 |
|
19 |
-
|
20 |
-
case 'the_seo_framework_social_metabox_main':
|
21 |
-
$default_tabs = [
|
22 |
'general' => [
|
23 |
'name' => __( 'General', 'autodescription' ),
|
24 |
-
'callback' =>
|
25 |
'dashicon' => 'admin-generic',
|
26 |
],
|
27 |
'facebook' => [
|
28 |
'name' => 'Facebook',
|
29 |
-
'callback' =>
|
30 |
'dashicon' => 'facebook-alt',
|
31 |
],
|
32 |
'twitter' => [
|
33 |
'name' => 'Twitter',
|
34 |
-
'callback' =>
|
35 |
'dashicon' => 'twitter',
|
36 |
],
|
37 |
'oembed' => [
|
38 |
'name' => 'oEmbed',
|
39 |
-
'callback' =>
|
40 |
'dashicon' => 'share-alt2',
|
41 |
],
|
42 |
'postdates' => [
|
43 |
'name' => __( 'Post Dates', 'autodescription' ),
|
44 |
-
'callback' =>
|
45 |
'dashicon' => 'backup',
|
46 |
],
|
47 |
];
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
SeoSettings::_nav_tab_wrapper( 'social', $tabs );
|
59 |
break;
|
60 |
|
61 |
-
case '
|
62 |
-
|
63 |
HTML::description( __( 'Output various meta tags for social site integration, among other third-party services.', 'autodescription' ) );
|
64 |
|
65 |
?>
|
@@ -68,7 +66,7 @@ switch ( $instance ) :
|
|
68 |
|
69 |
// Echo Open Graph Tags checkboxes.
|
70 |
HTML::wrap_fields(
|
71 |
-
|
72 |
'id' => 'og_tags',
|
73 |
'label' => __( 'Output Open Graph meta tags?', 'autodescription' ),
|
74 |
'description' => __( 'Facebook, Twitter, Pinterest and many other social sites make use of these meta tags.', 'autodescription' ),
|
@@ -80,7 +78,7 @@ switch ( $instance ) :
|
|
80 |
|
81 |
// Echo Facebook Tags checkbox.
|
82 |
HTML::wrap_fields(
|
83 |
-
|
84 |
'id' => 'facebook_tags',
|
85 |
'label' => __( 'Output Facebook meta tags?', 'autodescription' ),
|
86 |
'description' => __( 'Output various meta tags targeted at Facebook.', 'autodescription' ),
|
@@ -90,7 +88,7 @@ switch ( $instance ) :
|
|
90 |
|
91 |
// Echo Twitter Tags checkboxes.
|
92 |
HTML::wrap_fields(
|
93 |
-
|
94 |
'id' => 'twitter_tags',
|
95 |
'label' => __( 'Output Twitter meta tags?', 'autodescription' ),
|
96 |
'description' => __( 'Output various meta tags targeted at Twitter.', 'autodescription' ),
|
@@ -102,7 +100,7 @@ switch ( $instance ) :
|
|
102 |
|
103 |
// Echo oEmbed scripts checkboxes.
|
104 |
HTML::wrap_fields(
|
105 |
-
|
106 |
'id' => 'oembed_scripts',
|
107 |
'label' => __( 'Output oEmbed scripts?', 'autodescription' ),
|
108 |
'description' => __( 'WordPress, Discord, Drupal, Squarespace, and many other clients can make use of these scripts.', 'autodescription' ),
|
@@ -112,7 +110,7 @@ switch ( $instance ) :
|
|
112 |
?>
|
113 |
<hr>
|
114 |
<?php
|
115 |
-
|
116 |
HTML::description( __( 'Most social sites and third-party services automatically include the website URL inside their embeds. When the site title is described well in the site URL, including it in the social title will be redundant.', 'autodescription' ) );
|
117 |
|
118 |
$info = HTML::make_info(
|
@@ -122,9 +120,9 @@ switch ( $instance ) :
|
|
122 |
);
|
123 |
|
124 |
HTML::wrap_fields(
|
125 |
-
|
126 |
'id' => 'social_title_rem_additions',
|
127 |
-
'label' => esc_html__( 'Remove site title from generated social titles?', 'autodescription' ) .
|
128 |
'escape' => false,
|
129 |
] ),
|
130 |
true
|
@@ -132,11 +130,11 @@ switch ( $instance ) :
|
|
132 |
?>
|
133 |
<hr>
|
134 |
<?php
|
135 |
-
|
136 |
HTML::description( __( 'A social image can be displayed when your website is shared. It is a great way to grab attention.', 'autodescription' ) );
|
137 |
|
138 |
HTML::wrap_fields(
|
139 |
-
|
140 |
'id' => 'multi_og_image',
|
141 |
'label' => __( 'Output multiple Open Graph image tags?', 'autodescription' ),
|
142 |
'description' => __( 'This enables users to select any image attached to the page shared on social networks, like Facebook.', 'autodescription' ),
|
@@ -151,8 +149,8 @@ switch ( $instance ) :
|
|
151 |
</label>
|
152 |
</p>
|
153 |
<p>
|
154 |
-
<input class="large-text" type="url" name="<?php
|
155 |
-
<input type="hidden" name="<?php
|
156 |
</p>
|
157 |
<p class="hide-if-no-tsf-js">
|
158 |
<?php
|
@@ -162,24 +160,24 @@ switch ( $instance ) :
|
|
162 |
</p>
|
163 |
<hr>
|
164 |
<?php
|
165 |
-
|
166 |
HTML::description( __( 'Discord styles embeds with the theme color. The theme color can also affect the tab-color in some browsers.', 'autodescription' ) );
|
167 |
?>
|
168 |
<p>
|
169 |
-
<label for="<?php
|
170 |
<strong><?php esc_html_e( 'Theme Color', 'autodescription' ); ?></strong>
|
171 |
</label>
|
172 |
</p>
|
173 |
<p>
|
174 |
-
<input type="text" name="<?php
|
175 |
</p>
|
176 |
<hr>
|
177 |
<?php
|
178 |
-
|
179 |
HTML::description( __( 'The shortlink tag can be manually used for microblogging services like Twitter, but it has no SEO value whatsoever.', 'autodescription' ) );
|
180 |
|
181 |
HTML::wrap_fields(
|
182 |
-
|
183 |
'id' => 'shortlink_tag',
|
184 |
'label' => __( 'Output shortlink tag?', 'autodescription' ),
|
185 |
] ),
|
@@ -187,7 +185,7 @@ switch ( $instance ) :
|
|
187 |
);
|
188 |
break;
|
189 |
|
190 |
-
case '
|
191 |
$fb_author = $this->get_option( 'facebook_author' );
|
192 |
$fb_author_placeholder = _x( 'https://www.facebook.com/YourPersonalProfile', 'Example Facebook Personal URL', 'autodescription' );
|
193 |
|
@@ -197,14 +195,14 @@ switch ( $instance ) :
|
|
197 |
$fb_appid = $this->get_option( 'facebook_appid' );
|
198 |
$fb_appid_placeholder = '123456789012345';
|
199 |
|
200 |
-
|
201 |
HTML::description( __( 'Facebook post sharing works mostly through Open Graph. However, you can also link your Business and Personal Facebook pages, among various other options.', 'autodescription' ) );
|
202 |
HTML::description( __( 'When these options are filled in, Facebook might link the Facebook profile to be followed and liked when your post or page is shared.', 'autodescription' ) );
|
203 |
?>
|
204 |
<hr>
|
205 |
|
206 |
<p>
|
207 |
-
<label for="<?php
|
208 |
<strong><?php esc_html_e( 'Facebook App ID', 'autodescription' ); ?></strong>
|
209 |
<?php
|
210 |
echo ' ';
|
@@ -216,11 +214,11 @@ switch ( $instance ) :
|
|
216 |
</label>
|
217 |
</p>
|
218 |
<p>
|
219 |
-
<input type="text" name="<?php
|
220 |
</p>
|
221 |
|
222 |
<p>
|
223 |
-
<label for="<?php
|
224 |
<strong><?php esc_html_e( 'Facebook Publisher page', 'autodescription' ); ?></strong>
|
225 |
<?php
|
226 |
echo ' ';
|
@@ -232,11 +230,11 @@ switch ( $instance ) :
|
|
232 |
</label>
|
233 |
</p>
|
234 |
<p>
|
235 |
-
<input type="url" name="<?php
|
236 |
</p>
|
237 |
|
238 |
<p>
|
239 |
-
<label for="<?php
|
240 |
<strong><?php esc_html_e( 'Facebook Author Fallback Page', 'autodescription' ); ?></strong>
|
241 |
<?php
|
242 |
echo ' ';
|
@@ -249,12 +247,12 @@ switch ( $instance ) :
|
|
249 |
</p>
|
250 |
<?php HTML::description( __( 'Authors can override this option on their profile page.', 'autodescription' ) ); ?>
|
251 |
<p>
|
252 |
-
<input type="url" name="<?php
|
253 |
</p>
|
254 |
<?php
|
255 |
break;
|
256 |
|
257 |
-
case '
|
258 |
$tw_site = $this->get_option( 'twitter_site' );
|
259 |
$tw_site_placeholder = _x( '@your-site-username', 'Twitter @username', 'autodescription' );
|
260 |
|
@@ -263,14 +261,14 @@ switch ( $instance ) :
|
|
263 |
|
264 |
$twitter_card = $this->get_twitter_card_types();
|
265 |
|
266 |
-
|
267 |
HTML::description( __( 'Twitter post sharing works mostly through Twitter Cards, and may fall back to use Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options.', 'autodescription' ) );
|
268 |
|
269 |
?>
|
270 |
<hr>
|
271 |
|
272 |
<fieldset id="tsf-twitter-cards">
|
273 |
-
<legend><?php
|
274 |
<?php
|
275 |
HTML::description(
|
276 |
__( 'The Twitter Card type may have the image highlighted, either small at the side or large above.', 'autodescription' )
|
@@ -282,15 +280,15 @@ switch ( $instance ) :
|
|
282 |
foreach ( $twitter_card as $type => $name ) {
|
283 |
?>
|
284 |
<span class="tsf-toblock">
|
285 |
-
<input type="radio" name="<?php
|
286 |
-
<label for="<?php
|
287 |
<span>
|
288 |
<?php
|
289 |
echo HTML::code_wrap( $name ); // phpcs:ignore, WordPress.Security.EscapeOutput
|
290 |
echo ' ';
|
291 |
HTML::make_info(
|
292 |
__( 'Learn more about this card.', 'autodescription' ),
|
293 |
-
|
294 |
);
|
295 |
?>
|
296 |
</span>
|
@@ -304,14 +302,14 @@ switch ( $instance ) :
|
|
304 |
|
305 |
<hr>
|
306 |
<?php
|
307 |
-
|
308 |
/* source: https://developer.twitter.com/en/docs/tweets/optimize-with-cards/guides/getting-started#attribution */
|
309 |
HTML::description( __( 'Twitter claims users will be able to follow and view the profiles of attributed accounts directly from the card when these fields are filled in.', 'autodescription' ) );
|
310 |
HTML::description( __( 'However, for now, these fields seem to have no discernible effect.', 'autodescription' ) );
|
311 |
?>
|
312 |
|
313 |
<p>
|
314 |
-
<label for="<?php
|
315 |
<strong><?php esc_html_e( 'Website Twitter Profile', 'autodescription' ); ?></strong>
|
316 |
<?php
|
317 |
echo ' ';
|
@@ -323,11 +321,11 @@ switch ( $instance ) :
|
|
323 |
</label>
|
324 |
</p>
|
325 |
<p>
|
326 |
-
<input type="text" name="<?php
|
327 |
</p>
|
328 |
|
329 |
<p>
|
330 |
-
<label for="<?php
|
331 |
<strong><?php esc_html_e( 'Twitter Author Fallback Profile', 'autodescription' ); ?></strong>
|
332 |
<?php
|
333 |
echo ' ';
|
@@ -340,13 +338,13 @@ switch ( $instance ) :
|
|
340 |
</p>
|
341 |
<?php HTML::description( __( 'Authors can override this option on their profile page.', 'autodescription' ) ); ?>
|
342 |
<p>
|
343 |
-
<input type="text" name="<?php
|
344 |
</p>
|
345 |
<?php
|
346 |
break;
|
347 |
|
348 |
-
case '
|
349 |
-
|
350 |
HTML::description( __( 'Some social sharing services and clients, like WordPress, LinkedIn, and Discord, obtain the linked page information via oEmbed.', 'autodescription' ) );
|
351 |
?>
|
352 |
<hr>
|
@@ -354,7 +352,7 @@ switch ( $instance ) :
|
|
354 |
|
355 |
// Split the wraps--the informational messages make for bad legibility otherwise.
|
356 |
HTML::wrap_fields(
|
357 |
-
|
358 |
'id' => 'oembed_use_og_title',
|
359 |
'label' => __( 'Use Open Graph title?', 'autodescription' ),
|
360 |
'description' => __( 'Check this option if you want to replace page titles with Open Graph titles in embeds.', 'autodescription' ),
|
@@ -367,16 +365,16 @@ switch ( $instance ) :
|
|
367 |
false
|
368 |
);
|
369 |
HTML::wrap_fields(
|
370 |
-
|
371 |
'id' => 'oembed_use_social_image',
|
372 |
-
'label' => esc_html__( 'Use social image?', 'autodescription' ) .
|
373 |
'description' => esc_html__( "LinkedIn displays the post's featured image in embeds. Check this option if you want to replace it with the social image.", 'autodescription' ),
|
374 |
'escape' => false,
|
375 |
] ),
|
376 |
true
|
377 |
);
|
378 |
HTML::wrap_fields(
|
379 |
-
|
380 |
'id' => 'oembed_remove_author',
|
381 |
'label' => __( 'Remove author name?', 'autodescription' ),
|
382 |
'description' => __( "Discord shows the page author's name above the sharing embed. Check this option if you find this undesirable.", 'autodescription' ),
|
@@ -385,10 +383,10 @@ switch ( $instance ) :
|
|
385 |
);
|
386 |
|
387 |
break;
|
388 |
-
case '
|
389 |
$posts_i18n = esc_html__( 'Posts', 'autodescription' );
|
390 |
|
391 |
-
|
392 |
HTML::description( __( "Some social sites output the shared post's publishing and modified data in the sharing snippet.", 'autodescription' ) );
|
393 |
?>
|
394 |
<hr>
|
@@ -396,7 +394,7 @@ switch ( $instance ) :
|
|
396 |
|
397 |
HTML::wrap_fields(
|
398 |
[
|
399 |
-
|
400 |
'id' => 'post_publish_time',
|
401 |
'label' => $this->convert_markdown(
|
402 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
@@ -405,7 +403,7 @@ switch ( $instance ) :
|
|
405 |
),
|
406 |
'escape' => false,
|
407 |
] ),
|
408 |
-
|
409 |
'id' => 'post_modify_time',
|
410 |
'label' => $this->convert_markdown(
|
411 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
+
The_SEO_Framework\Interpreters\Form,
|
13 |
+
The_SEO_Framework\Interpreters\Settings_Input as Input;
|
14 |
|
15 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
16 |
|
17 |
+
switch ( $this->get_view_instance( 'social', $instance ) ) :
|
18 |
+
case 'social_main':
|
19 |
+
$_settings_class = SeoSettings::class;
|
20 |
|
21 |
+
$tabs = [
|
|
|
|
|
22 |
'general' => [
|
23 |
'name' => __( 'General', 'autodescription' ),
|
24 |
+
'callback' => [ $_settings_class, '_social_metabox_general_tab' ],
|
25 |
'dashicon' => 'admin-generic',
|
26 |
],
|
27 |
'facebook' => [
|
28 |
'name' => 'Facebook',
|
29 |
+
'callback' => [ $_settings_class, '_social_metabox_facebook_tab' ],
|
30 |
'dashicon' => 'facebook-alt',
|
31 |
],
|
32 |
'twitter' => [
|
33 |
'name' => 'Twitter',
|
34 |
+
'callback' => [ $_settings_class, '_social_metabox_twitter_tab' ],
|
35 |
'dashicon' => 'twitter',
|
36 |
],
|
37 |
'oembed' => [
|
38 |
'name' => 'oEmbed',
|
39 |
+
'callback' => [ $_settings_class, '_social_metabox_oembed_tab' ],
|
40 |
'dashicon' => 'share-alt2',
|
41 |
],
|
42 |
'postdates' => [
|
43 |
'name' => __( 'Post Dates', 'autodescription' ),
|
44 |
+
'callback' => [ $_settings_class, '_social_metabox_postdates_tab' ],
|
45 |
'dashicon' => 'backup',
|
46 |
],
|
47 |
];
|
48 |
|
49 |
+
SeoSettings::_nav_tab_wrapper(
|
50 |
+
'social',
|
51 |
+
/**
|
52 |
+
* @since 2.2.2
|
53 |
+
* @param array $defaults The default tabs.
|
54 |
+
*/
|
55 |
+
(array) apply_filters( 'the_seo_framework_social_settings_tabs', $tabs )
|
56 |
+
);
|
|
|
|
|
57 |
break;
|
58 |
|
59 |
+
case 'social_general_tab':
|
60 |
+
HTML::header_title( __( 'Social Meta Tags Settings', 'autodescription' ) );
|
61 |
HTML::description( __( 'Output various meta tags for social site integration, among other third-party services.', 'autodescription' ) );
|
62 |
|
63 |
?>
|
66 |
|
67 |
// Echo Open Graph Tags checkboxes.
|
68 |
HTML::wrap_fields(
|
69 |
+
Input::make_checkbox( [
|
70 |
'id' => 'og_tags',
|
71 |
'label' => __( 'Output Open Graph meta tags?', 'autodescription' ),
|
72 |
'description' => __( 'Facebook, Twitter, Pinterest and many other social sites make use of these meta tags.', 'autodescription' ),
|
78 |
|
79 |
// Echo Facebook Tags checkbox.
|
80 |
HTML::wrap_fields(
|
81 |
+
Input::make_checkbox( [
|
82 |
'id' => 'facebook_tags',
|
83 |
'label' => __( 'Output Facebook meta tags?', 'autodescription' ),
|
84 |
'description' => __( 'Output various meta tags targeted at Facebook.', 'autodescription' ),
|
88 |
|
89 |
// Echo Twitter Tags checkboxes.
|
90 |
HTML::wrap_fields(
|
91 |
+
Input::make_checkbox( [
|
92 |
'id' => 'twitter_tags',
|
93 |
'label' => __( 'Output Twitter meta tags?', 'autodescription' ),
|
94 |
'description' => __( 'Output various meta tags targeted at Twitter.', 'autodescription' ),
|
100 |
|
101 |
// Echo oEmbed scripts checkboxes.
|
102 |
HTML::wrap_fields(
|
103 |
+
Input::make_checkbox( [
|
104 |
'id' => 'oembed_scripts',
|
105 |
'label' => __( 'Output oEmbed scripts?', 'autodescription' ),
|
106 |
'description' => __( 'WordPress, Discord, Drupal, Squarespace, and many other clients can make use of these scripts.', 'autodescription' ),
|
110 |
?>
|
111 |
<hr>
|
112 |
<?php
|
113 |
+
HTML::header_title( __( 'Social Title Settings', 'autodescription' ) );
|
114 |
HTML::description( __( 'Most social sites and third-party services automatically include the website URL inside their embeds. When the site title is described well in the site URL, including it in the social title will be redundant.', 'autodescription' ) );
|
115 |
|
116 |
$info = HTML::make_info(
|
120 |
);
|
121 |
|
122 |
HTML::wrap_fields(
|
123 |
+
Input::make_checkbox( [
|
124 |
'id' => 'social_title_rem_additions',
|
125 |
+
'label' => esc_html__( 'Remove site title from generated social titles?', 'autodescription' ) . " $info",
|
126 |
'escape' => false,
|
127 |
] ),
|
128 |
true
|
130 |
?>
|
131 |
<hr>
|
132 |
<?php
|
133 |
+
HTML::header_title( __( 'Social Image Settings', 'autodescription' ) );
|
134 |
HTML::description( __( 'A social image can be displayed when your website is shared. It is a great way to grab attention.', 'autodescription' ) );
|
135 |
|
136 |
HTML::wrap_fields(
|
137 |
+
Input::make_checkbox( [
|
138 |
'id' => 'multi_og_image',
|
139 |
'label' => __( 'Output multiple Open Graph image tags?', 'autodescription' ),
|
140 |
'description' => __( 'This enables users to select any image attached to the page shared on social networks, like Facebook.', 'autodescription' ),
|
149 |
</label>
|
150 |
</p>
|
151 |
<p>
|
152 |
+
<input class="large-text" type="url" name="<?php Input::field_name( 'social_image_fb_url' ); ?>" id="tsf_fb_socialimage-url" value="<?php echo esc_url( $this->get_option( 'social_image_fb_url' ) ); ?>" />
|
153 |
+
<input type="hidden" name="<?php Input::field_name( 'social_image_fb_id' ); ?>" id="tsf_fb_socialimage-id" value="<?php echo absint( $this->get_option( 'social_image_fb_id' ) ); ?>" disabled class="tsf-enable-media-if-js" />
|
154 |
</p>
|
155 |
<p class="hide-if-no-tsf-js">
|
156 |
<?php
|
160 |
</p>
|
161 |
<hr>
|
162 |
<?php
|
163 |
+
HTML::header_title( __( 'Theme Color Settings', 'autodescription' ) );
|
164 |
HTML::description( __( 'Discord styles embeds with the theme color. The theme color can also affect the tab-color in some browsers.', 'autodescription' ) );
|
165 |
?>
|
166 |
<p>
|
167 |
+
<label for="<?php Input::field_id( 'theme_color' ); ?>">
|
168 |
<strong><?php esc_html_e( 'Theme Color', 'autodescription' ); ?></strong>
|
169 |
</label>
|
170 |
</p>
|
171 |
<p>
|
172 |
+
<input type="text" name="<?php Input::field_name( 'theme_color' ); ?>" class="tsf-color-picker" id="<?php Input::field_id( 'theme_color' ); ?>" value="<?php echo esc_attr( $this->get_option( 'theme_color' ) ); ?>" data-tsf-default-color="" />
|
173 |
</p>
|
174 |
<hr>
|
175 |
<?php
|
176 |
+
HTML::header_title( __( 'Site Shortlink Settings', 'autodescription' ) );
|
177 |
HTML::description( __( 'The shortlink tag can be manually used for microblogging services like Twitter, but it has no SEO value whatsoever.', 'autodescription' ) );
|
178 |
|
179 |
HTML::wrap_fields(
|
180 |
+
Input::make_checkbox( [
|
181 |
'id' => 'shortlink_tag',
|
182 |
'label' => __( 'Output shortlink tag?', 'autodescription' ),
|
183 |
] ),
|
185 |
);
|
186 |
break;
|
187 |
|
188 |
+
case 'social_facebook_tab':
|
189 |
$fb_author = $this->get_option( 'facebook_author' );
|
190 |
$fb_author_placeholder = _x( 'https://www.facebook.com/YourPersonalProfile', 'Example Facebook Personal URL', 'autodescription' );
|
191 |
|
195 |
$fb_appid = $this->get_option( 'facebook_appid' );
|
196 |
$fb_appid_placeholder = '123456789012345';
|
197 |
|
198 |
+
HTML::header_title( __( 'Facebook Integration Settings', 'autodescription' ) );
|
199 |
HTML::description( __( 'Facebook post sharing works mostly through Open Graph. However, you can also link your Business and Personal Facebook pages, among various other options.', 'autodescription' ) );
|
200 |
HTML::description( __( 'When these options are filled in, Facebook might link the Facebook profile to be followed and liked when your post or page is shared.', 'autodescription' ) );
|
201 |
?>
|
202 |
<hr>
|
203 |
|
204 |
<p>
|
205 |
+
<label for="<?php Input::field_id( 'facebook_appid' ); ?>">
|
206 |
<strong><?php esc_html_e( 'Facebook App ID', 'autodescription' ); ?></strong>
|
207 |
<?php
|
208 |
echo ' ';
|
214 |
</label>
|
215 |
</p>
|
216 |
<p>
|
217 |
+
<input type="text" name="<?php Input::field_name( 'facebook_appid' ); ?>" class="large-text ltr" id="<?php Input::field_id( 'facebook_appid' ); ?>" placeholder="<?php echo esc_attr( $fb_appid_placeholder ); ?>" value="<?php echo esc_attr( $fb_appid ); ?>" />
|
218 |
</p>
|
219 |
|
220 |
<p>
|
221 |
+
<label for="<?php Input::field_id( 'facebook_publisher' ); ?>">
|
222 |
<strong><?php esc_html_e( 'Facebook Publisher page', 'autodescription' ); ?></strong>
|
223 |
<?php
|
224 |
echo ' ';
|
230 |
</label>
|
231 |
</p>
|
232 |
<p>
|
233 |
+
<input type="url" name="<?php Input::field_name( 'facebook_publisher' ); ?>" class="large-text" id="<?php Input::field_id( 'facebook_publisher' ); ?>" placeholder="<?php echo esc_attr( $fb_publisher_placeholder ); ?>" value="<?php echo esc_attr( $fb_publisher ); ?>" />
|
234 |
</p>
|
235 |
|
236 |
<p>
|
237 |
+
<label for="<?php Input::field_id( 'facebook_author' ); ?>">
|
238 |
<strong><?php esc_html_e( 'Facebook Author Fallback Page', 'autodescription' ); ?></strong>
|
239 |
<?php
|
240 |
echo ' ';
|
247 |
</p>
|
248 |
<?php HTML::description( __( 'Authors can override this option on their profile page.', 'autodescription' ) ); ?>
|
249 |
<p>
|
250 |
+
<input type="url" name="<?php Input::field_name( 'facebook_author' ); ?>" class="large-text" id="<?php Input::field_id( 'facebook_author' ); ?>" placeholder="<?php echo esc_attr( $fb_author_placeholder ); ?>" value="<?php echo esc_attr( $fb_author ); ?>" />
|
251 |
</p>
|
252 |
<?php
|
253 |
break;
|
254 |
|
255 |
+
case 'social_twitter_tab':
|
256 |
$tw_site = $this->get_option( 'twitter_site' );
|
257 |
$tw_site_placeholder = _x( '@your-site-username', 'Twitter @username', 'autodescription' );
|
258 |
|
261 |
|
262 |
$twitter_card = $this->get_twitter_card_types();
|
263 |
|
264 |
+
HTML::header_title( __( 'Twitter Integration Settings', 'autodescription' ) );
|
265 |
HTML::description( __( 'Twitter post sharing works mostly through Twitter Cards, and may fall back to use Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options.', 'autodescription' ) );
|
266 |
|
267 |
?>
|
268 |
<hr>
|
269 |
|
270 |
<fieldset id="tsf-twitter-cards">
|
271 |
+
<legend><?php HTML::header_title( __( 'Twitter Card Type', 'autodescription' ) ); ?></legend>
|
272 |
<?php
|
273 |
HTML::description(
|
274 |
__( 'The Twitter Card type may have the image highlighted, either small at the side or large above.', 'autodescription' )
|
280 |
foreach ( $twitter_card as $type => $name ) {
|
281 |
?>
|
282 |
<span class="tsf-toblock">
|
283 |
+
<input type="radio" name="<?php Input::field_name( 'twitter_card' ); ?>" id="<?php Input::field_id( "twitter_card_{$type}" ); ?>" value="<?php echo esc_attr( $type ); ?>" <?php checked( $this->get_option( 'twitter_card' ), $type ); ?> />
|
284 |
+
<label for="<?php Input::field_id( "twitter_card_{$type}" ); ?>">
|
285 |
<span>
|
286 |
<?php
|
287 |
echo HTML::code_wrap( $name ); // phpcs:ignore, WordPress.Security.EscapeOutput
|
288 |
echo ' ';
|
289 |
HTML::make_info(
|
290 |
__( 'Learn more about this card.', 'autodescription' ),
|
291 |
+
"https://dev.twitter.com/cards/types/$name"
|
292 |
);
|
293 |
?>
|
294 |
</span>
|
302 |
|
303 |
<hr>
|
304 |
<?php
|
305 |
+
HTML::header_title( __( 'Card and Content Attribution', 'autodescription' ) );
|
306 |
/* source: https://developer.twitter.com/en/docs/tweets/optimize-with-cards/guides/getting-started#attribution */
|
307 |
HTML::description( __( 'Twitter claims users will be able to follow and view the profiles of attributed accounts directly from the card when these fields are filled in.', 'autodescription' ) );
|
308 |
HTML::description( __( 'However, for now, these fields seem to have no discernible effect.', 'autodescription' ) );
|
309 |
?>
|
310 |
|
311 |
<p>
|
312 |
+
<label for="<?php Input::field_id( 'twitter_site' ); ?>" class="tsf-toblock">
|
313 |
<strong><?php esc_html_e( 'Website Twitter Profile', 'autodescription' ); ?></strong>
|
314 |
<?php
|
315 |
echo ' ';
|
321 |
</label>
|
322 |
</p>
|
323 |
<p>
|
324 |
+
<input type="text" name="<?php Input::field_name( 'twitter_site' ); ?>" class="large-text ltr" id="<?php Input::field_id( 'twitter_site' ); ?>" placeholder="<?php echo esc_attr( $tw_site_placeholder ); ?>" value="<?php echo esc_attr( $tw_site ); ?>" />
|
325 |
</p>
|
326 |
|
327 |
<p>
|
328 |
+
<label for="<?php Input::field_id( 'twitter_creator' ); ?>" class="tsf-toblock">
|
329 |
<strong><?php esc_html_e( 'Twitter Author Fallback Profile', 'autodescription' ); ?></strong>
|
330 |
<?php
|
331 |
echo ' ';
|
338 |
</p>
|
339 |
<?php HTML::description( __( 'Authors can override this option on their profile page.', 'autodescription' ) ); ?>
|
340 |
<p>
|
341 |
+
<input type="text" name="<?php Input::field_name( 'twitter_creator' ); ?>" class="large-text ltr" id="<?php Input::field_id( 'twitter_creator' ); ?>" placeholder="<?php echo esc_attr( $tw_creator_placeholder ); ?>" value="<?php echo esc_attr( $tw_creator ); ?>" />
|
342 |
</p>
|
343 |
<?php
|
344 |
break;
|
345 |
|
346 |
+
case 'social_oembed_tab':
|
347 |
+
HTML::header_title( __( 'oEmbed Settings', 'autodescription' ) );
|
348 |
HTML::description( __( 'Some social sharing services and clients, like WordPress, LinkedIn, and Discord, obtain the linked page information via oEmbed.', 'autodescription' ) );
|
349 |
?>
|
350 |
<hr>
|
352 |
|
353 |
// Split the wraps--the informational messages make for bad legibility otherwise.
|
354 |
HTML::wrap_fields(
|
355 |
+
Input::make_checkbox( [
|
356 |
'id' => 'oembed_use_og_title',
|
357 |
'label' => __( 'Use Open Graph title?', 'autodescription' ),
|
358 |
'description' => __( 'Check this option if you want to replace page titles with Open Graph titles in embeds.', 'autodescription' ),
|
365 |
false
|
366 |
);
|
367 |
HTML::wrap_fields(
|
368 |
+
Input::make_checkbox( [
|
369 |
'id' => 'oembed_use_social_image',
|
370 |
+
'label' => esc_html__( 'Use social image?', 'autodescription' ) . " $_info",
|
371 |
'description' => esc_html__( "LinkedIn displays the post's featured image in embeds. Check this option if you want to replace it with the social image.", 'autodescription' ),
|
372 |
'escape' => false,
|
373 |
] ),
|
374 |
true
|
375 |
);
|
376 |
HTML::wrap_fields(
|
377 |
+
Input::make_checkbox( [
|
378 |
'id' => 'oembed_remove_author',
|
379 |
'label' => __( 'Remove author name?', 'autodescription' ),
|
380 |
'description' => __( "Discord shows the page author's name above the sharing embed. Check this option if you find this undesirable.", 'autodescription' ),
|
383 |
);
|
384 |
|
385 |
break;
|
386 |
+
case 'social_postdates_tab':
|
387 |
$posts_i18n = esc_html__( 'Posts', 'autodescription' );
|
388 |
|
389 |
+
HTML::header_title( __( 'Post Date Settings', 'autodescription' ) );
|
390 |
HTML::description( __( "Some social sites output the shared post's publishing and modified data in the sharing snippet.", 'autodescription' ) );
|
391 |
?>
|
392 |
<hr>
|
394 |
|
395 |
HTML::wrap_fields(
|
396 |
[
|
397 |
+
Input::make_checkbox( [
|
398 |
'id' => 'post_publish_time',
|
399 |
'label' => $this->convert_markdown(
|
400 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
403 |
),
|
404 |
'escape' => false,
|
405 |
] ),
|
406 |
+
Input::make_checkbox( [
|
407 |
'id' => 'post_modify_time',
|
408 |
'label' => $this->convert_markdown(
|
409 |
/* translators: the backticks are Markdown! Preserve them as-is! */
|
@@ -9,21 +9,17 @@
|
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
-
The_SEO_Framework\Interpreters\
|
13 |
|
14 |
-
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and
|
15 |
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
switch ( $instance ) :
|
20 |
-
case 'the_seo_framework_title_metabox_main':
|
21 |
-
$blogname = $this->get_blogname();
|
22 |
$sep = esc_html( $this->get_separator( 'title' ) );
|
23 |
-
$showleft = 'left' === $this->get_option( 'title_location' );
|
24 |
|
25 |
-
$additions_left =
|
26 |
-
$additions_right =
|
27 |
|
28 |
$latest_post_id = $this->get_latest_post_id();
|
29 |
$latest_cat_id = $this->get_latest_category_id();
|
@@ -32,56 +28,78 @@ switch ( $instance ) :
|
|
32 |
$post_name = strip_tags( get_the_title( $latest_post_id ) ) ?: __( 'Example Post', 'autodescription' );
|
33 |
$post_title = $this->s_title( $this->hellip_if_over( $post_name, 60 ) );
|
34 |
|
35 |
-
|
36 |
-
$
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
|
|
|
|
|
|
41 |
$cat_prefix,
|
42 |
-
$
|
43 |
);
|
44 |
|
45 |
-
$example_post_left
|
46 |
-
$example_post_right
|
47 |
-
$
|
48 |
-
$
|
|
|
|
|
49 |
|
50 |
-
|
9 |
|
10 |
use The_SEO_Framework\Bridges\SeoSettings,
|
11 |
The_SEO_Framework\Interpreters\HTML,
|
12 |
+
The_SEO_Framework\Interpreters\Settings_Input as Input;
|
13 |
|
14 |
+
defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and tsf()->_verify_include_secret( $_secret ) or die;
|
15 |
|
16 |
+
switch ( $this->get_view_instance( 'title', $instance ) ) :
|
17 |
+
case 'title_main':
|
18 |
+
$blogname = esc_html( $this->get_blogname() );
|
|
|
|
|
|
|
19 |
$sep = esc_html( $this->get_separator( 'title' ) );
|
|
|
20 |
|
21 |
+
$additions_left = "<span class=tsf-title-additions-js><span class=tsf-site-title-js>$blogname</span><span class=tsf-sep-js> $sep </span></span>";
|
22 |
+
$additions_right = "<span class=tsf-title-additions-js><span class=tsf-sep-js> $sep </span><span class=tsf-site-title-js>$blogname</span></span>";
|
23 |
|
24 |
$latest_post_id = $this->get_latest_post_id();
|
25 |
$latest_cat_id = $this->get_latest_category_id();
|
28 |
$post_name = strip_tags( get_the_title( $latest_post_id ) ) ?: __( 'Example Post', 'autodescription' );
|
29 |
$post_title = $this->s_title( $this->hellip_if_over( $post_name, 60 ) );
|
30 |
|
31 |
+
$cat_prefix = $this->s_title( _x( 'Category:', 'category archive title prefix', 'default' ) );
|
32 |
+
$cat_title = $this->s_title( $this->hellip_if_over(
|
33 |
+
// phpcs:ignore, WordPress.WP.AlternativeFunctions.strip_tags_strip_tags -- We don't expect users to set scripts in titles.
|
34 |
+
strip_tags( get_cat_name( $latest_cat_id ) ?: __( 'Example Category', 'autodescription' ) ),
|
35 |
+
60 - strlen( $cat_prefix )
|
36 |
+
) );
|
37 |
+
$cat_title_full = sprintf(
|
38 |
+
/* translators: 1: Title prefix. 2: Title. */
|
39 |
+
_x( '%1$s %2$s', 'archive title', 'default' ),
|
40 |
$cat_prefix,
|
41 |
+
$cat_title
|
42 |
);
|
43 |
|
44 |
+
$example_post_left = "<em>{$additions_left}{$post_name}</em>";
|
45 |
+
$example_post_right = "<em>{$post_name}{$additions_right}</em>";
|
46 |
+
$example_tax_left_full = "<em>{$additions_left}{$cat_title_full}</em>";
|
47 |
+
$example_tax_right_full = "<em>{$cat_title_full}{$additions_right}</em>";
|
48 |
+
$example_tax_left = "<em>{$additions_left}{$cat_title}</em>";
|
49 |
+
$example_tax_right = "<em>{$cat_title}{$additions_right}</em>";
|
50 |
|
51 |
+
HTML::header_title( __( 'Automated Title Settings', 'autodescription' ) )
|