Merged in feature/MAW-855-import-code-into-aws (pull request #2)

code import from pantheon

* code import from pantheon
This commit is contained in:
Tony Volpe
2023-12-04 23:08:14 +00:00
parent 8c9b1312bc
commit 8f4b5efda6
4766 changed files with 185592 additions and 239967 deletions

View File

@@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit85714e6ef573a9700a89c1b37454f5f2::getLoader();
return ComposerAutoloaderInit0c422f20871bcbf1c73c1006dcf06201::getLoader();

View File

@@ -42,30 +42,75 @@ namespace Composer\Autoload;
*/
class ClassLoader
{
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
}
/**
* @return string[]
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
@@ -75,28 +120,47 @@ class ClassLoader
return array();
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
public function addClassMap(array $classMap)
{
@@ -111,9 +175,11 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
@@ -156,11 +222,13 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
@@ -204,8 +272,10 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
@@ -220,10 +290,12 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
@@ -243,6 +315,8 @@ class ClassLoader
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
@@ -265,6 +339,8 @@ class ClassLoader
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
@@ -285,6 +361,8 @@ class ClassLoader
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
@@ -305,6 +383,8 @@ class ClassLoader
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
@@ -324,6 +404,8 @@ class ClassLoader
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
@@ -338,7 +420,7 @@ class ClassLoader
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
@@ -347,6 +429,8 @@ class ClassLoader
return true;
}
return null;
}
/**
@@ -401,6 +485,11 @@ class ClassLoader
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
@@ -472,6 +561,10 @@ class ClassLoader
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
* @private
*/
function includeFile($file)
{

View File

@@ -25,7 +25,7 @@ return array(
'WPSEO_Export_Keywords_Query' => $baseDir . '/classes/export/export-keywords-query-interface.php',
'WPSEO_Export_Keywords_Term_Presenter' => $baseDir . '/classes/export/export-keywords-term-presenter.php',
'WPSEO_Export_Keywords_Term_Query' => $baseDir . '/classes/export/export-keywords-term-query.php',
'WPSEO_Facebook_Profile' => $baseDir . '/classes/facebook-profile.php',
'WPSEO_Facebook_Profile' => $baseDir . '/src/deprecated/classes/facebook-profile.php',
'WPSEO_Metabox_Link_Suggestions' => $baseDir . '/classes/metabox-link-suggestions.php',
'WPSEO_Multi_Keyword' => $baseDir . '/classes/multi-keyword.php',
'WPSEO_Post_Watcher' => $baseDir . '/classes/post-watcher.php',
@@ -33,9 +33,6 @@ return array(
'WPSEO_Premium_Asset_JS_L10n' => $baseDir . '/classes/premium-asset-js-l10n.php',
'WPSEO_Premium_Assets' => $baseDir . '/classes/premium-assets.php',
'WPSEO_Premium_Expose_Shortlinks' => $baseDir . '/classes/premium-expose-shortlinks.php',
'WPSEO_Premium_Free_Translations' => $baseDir . '/classes/premium-free-translations.php',
'WPSEO_Premium_GSC' => $baseDir . '/classes/premium-gsc.php',
'WPSEO_Premium_GSC_Modal' => $baseDir . '/classes/premium-gsc-modal.php',
'WPSEO_Premium_Import_Manager' => $baseDir . '/classes/premium-import-manager.php',
'WPSEO_Premium_Javascript_Strings' => $baseDir . '/classes/premium-javascript-strings.php',
'WPSEO_Premium_Keyword_Export_Manager' => $baseDir . '/classes/premium-keyword-export-manager.php',
@@ -44,13 +41,7 @@ return array(
'WPSEO_Premium_Orphaned_Content_Support' => $baseDir . '/classes/premium-orphaned-content-support.php',
'WPSEO_Premium_Orphaned_Content_Utils' => $baseDir . '/classes/premium-orphaned-content-utils.php',
'WPSEO_Premium_Orphaned_Post_Filter' => $baseDir . '/classes/premium-orphaned-post-filter.php',
'WPSEO_Premium_Orphaned_Post_Notifier' => $baseDir . '/classes/premium-orphaned-post-notifier.php',
'WPSEO_Premium_Orphaned_Post_Query' => $baseDir . '/classes/premium-orphaned-post-query.php',
'WPSEO_Premium_Prominent_Words_Language_Support' => $baseDir . '/classes/deprecated/premium-prominent-words-language-support.php',
'WPSEO_Premium_Prominent_Words_Recalculation' => $baseDir . '/classes/premium-prominent-words-recalculation.php',
'WPSEO_Premium_Prominent_Words_Recalculation_Endpoint' => $baseDir . '/classes/deprecated/premium-prominent-words-recalculation-endpoint.php',
'WPSEO_Premium_Prominent_Words_Recalculation_Notifier' => $baseDir . '/classes/deprecated/premium-prominent-words-recalculation-notifier.php',
'WPSEO_Premium_Prominent_Words_Recalculation_Service' => $baseDir . '/classes/deprecated/premium-prominent-words-recalculation-service.php',
'WPSEO_Premium_Prominent_Words_Support' => $baseDir . '/classes/premium-prominent-words-support.php',
'WPSEO_Premium_Prominent_Words_Unindexed_Post_Query' => $baseDir . '/classes/premium-prominent-words-unindexed-post-query.php',
'WPSEO_Premium_Prominent_Words_Versioning' => $baseDir . '/classes/premium-prominent-words-versioning.php',
@@ -78,7 +69,6 @@ return array(
'WPSEO_Redirect_Formats' => $baseDir . '/classes/redirect/redirect-formats.php',
'WPSEO_Redirect_Formatter' => $baseDir . '/classes/redirect/redirect-formatter.php',
'WPSEO_Redirect_HTAccess_Loader' => $baseDir . '/classes/redirect/loaders/redirect-htaccess-loader.php',
'WPSEO_Redirect_Handler' => $baseDir . '/src/deprecated/redirect-handler.php',
'WPSEO_Redirect_Htaccess_Exporter' => $baseDir . '/classes/redirect/exporters/redirect-htaccess-exporter.php',
'WPSEO_Redirect_Htaccess_Util' => $baseDir . '/classes/redirect/redirect-htaccess-util.php',
'WPSEO_Redirect_Import_Exception' => $baseDir . '/classes/redirect/redirect-import-exception.php',
@@ -118,75 +108,126 @@ return array(
'WPSEO_Validation_Result' => $baseDir . '/classes/validation-result.php',
'WPSEO_Validation_Warning' => $baseDir . '/classes/validation-warning.php',
'WPSEO_Watcher' => $baseDir . '/classes/watcher.php',
'Yoast\\WP\\SEO\\Actions\\Link_Suggestions_Action' => $baseDir . '/src/deprecated/actions/renamed-classes.php',
'Yoast\\WP\\SEO\\Actions\\Prominent_Words\\Complete_Action' => $baseDir . '/src/deprecated/actions/prominent-words/renamed-classes.php',
'Yoast\\WP\\SEO\\Actions\\Prominent_Words\\Content_Action' => $baseDir . '/src/deprecated/actions/prominent-words/renamed-classes.php',
'Yoast\\WP\\SEO\\Actions\\Prominent_Words\\Save_Action' => $baseDir . '/src/deprecated/actions/prominent-words/renamed-classes.php',
'Yoast\\WP\\SEO\\Actions\\Zapier_Action' => $baseDir . '/src/deprecated/actions/renamed-classes.php',
'Yoast\\WP\\SEO\\Conditionals\\Zapier_Enabled_Conditional' => $baseDir . '/src/conditionals/zapier-enabled-conditional.php',
'Yoast\\WP\\SEO\\Config\\Migrations\\WpYoastPremiumImprovedInternalLinking' => $baseDir . '/src/config/migrations/20190715101200_WpYoastPremiumImprovedInternalLinking.php',
'Yoast\\WP\\SEO\\Database\\Migration_Runner_Premium' => $baseDir . '/src/deprecated/database/renamed-classes.php',
'Yoast\\WP\\SEO\\Helpers\\Prominent_Words_Helper' => $baseDir . '/src/helpers/prominent-words-helper.php',
'Yoast\\WP\\SEO\\Helpers\\Zapier_Helper' => $baseDir . '/src/helpers/zapier-helper.php',
'Yoast\\WP\\SEO\\Initializers\\Redirect_Handler' => $baseDir . '/src/initializers/redirect-handler.php',
'Yoast\\WP\\SEO\\Integrations\\Admin\\Prominent_Words\\Indexation_Integration' => $baseDir . '/src/deprecated/integrations/admin/prominent-words/indexation-integration.php',
'Yoast\\WP\\SEO\\Integrations\\Admin\\Prominent_Words\\Indexing_Integration' => $baseDir . '/src/integrations/admin/prominent-words/indexing-integration.php',
'Yoast\\WP\\SEO\\Integrations\\Admin\\Prominent_Words\\Metabox_Integration' => $baseDir . '/src/integrations/admin/prominent-words/metabox-integration.php',
'Yoast\\WP\\SEO\\Integrations\\Admin\\Prominent_Words\\Notification_Event_Integration' => $baseDir . '/src/deprecated/integrations/admin/prominent-words/notification-event-integration.php',
'Yoast\\WP\\SEO\\Integrations\\Admin\\Prominent_Words_Notification' => $baseDir . '/src/deprecated/integrations/admin/prominent-words-notification.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Block_Patterns' => $baseDir . '/src/integrations/blocks/block-patterns.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Estimated_Reading_Time_Block' => $baseDir . '/src/integrations/blocks/estimated-reading-time-block.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Job_Posting_Block' => $baseDir . '/src/integrations/blocks/job-posting-block.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Related_Links_Block' => $baseDir . '/src/integrations/blocks/related-links-block.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Schema_Blocks' => $baseDir . '/src/integrations/blocks/schema-blocks.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Block_Patterns' => $baseDir . '/src/deprecated/integrations/blocks/block-patterns.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Job_Posting_Block' => $baseDir . '/src/deprecated/integrations/blocks/job-posting-block.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Siblings_Block' => $baseDir . '/classes/blocks/siblings-block.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Subpages_Block' => $baseDir . '/classes/blocks/subpages-block.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Elementor_Premium' => $baseDir . '/src/integrations/third-party/elementor-premium.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\TranslationsPress' => $baseDir . '/src/integrations/third-party/translationspress.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Zapier' => $baseDir . '/src/integrations/third-party/zapier.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Zapier_Classic_Editor' => $baseDir . '/src/integrations/third-party/zapier-classic-editor.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Zapier_Trigger' => $baseDir . '/src/integrations/third-party/zapier-trigger.php',
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Premium_Option_Wpseo_Watcher' => $baseDir . '/src/integrations/watchers/premium-option-wpseo-watcher.php',
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Zapier_APIKey_Reset_Watcher' => $baseDir . '/src/integrations/watchers/zapier-apikey-reset-watcher.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Wincher_Keyphrases' => $baseDir . '/src/integrations/third-party/wincher-keyphrases.php',
'Yoast\\WP\\SEO\\Models\\Prominent_Words' => $baseDir . '/src/models/prominent-words.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\AI_Generator_Action' => $baseDir . '/src/actions/ai-generator-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Link_Suggestions_Action' => $baseDir . '/src/actions/link-suggestions-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Prominent_Words\\Complete_Action' => $baseDir . '/src/actions/prominent-words/complete-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Prominent_Words\\Content_Action' => $baseDir . '/src/actions/prominent-words/content-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Prominent_Words\\Save_Action' => $baseDir . '/src/actions/prominent-words/save-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Zapier_Action' => $baseDir . '/src/actions/zapier-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Zapier_Action' => $baseDir . '/src/deprecated/actions/zapier-action.php',
'Yoast\\WP\\SEO\\Premium\\Addon_Installer' => $baseDir . '/src/addon-installer.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Social_Templates_Conditional' => $baseDir . '/src/conditionals/social-templates-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Ai_Editor_Conditional' => $baseDir . '/src/conditionals/ai-editor-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Algolia_Enabled_Conditional' => $baseDir . '/src/conditionals/algolia-enabled-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Cornerstone_Enabled_Conditional' => $baseDir . '/src/conditionals/cornerstone-enabled-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\EDD_Conditional' => $baseDir . '/src/conditionals/edd-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Inclusive_Language_Enabled_Conditional' => $baseDir . '/src/conditionals/inclusive-language-enabled-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Term_Overview_Or_Ajax_Conditional' => $baseDir . '/src/conditionals/term-overview-or-ajax-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Zapier_Enabled_Conditional' => $baseDir . '/src/deprecated/conditionals/zapier-enabled-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Config\\Badge_Group_Names' => $baseDir . '/src/config/badge-group-names.php',
'Yoast\\WP\\SEO\\Premium\\Config\\Migrations\\AddIndexOnIndexableIdAndStem' => $baseDir . '/src/config/migrations/20210827093024_AddIndexOnIndexableIdAndStem.php',
'Yoast\\WP\\SEO\\Premium\\Database\\Migration_Runner_Premium' => $baseDir . '/src/database/migration-runner-premium.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Forbidden_Property_Mutation_Exception' => $baseDir . '/src/exceptions/forbidden-property-mutation-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Bad_Request_Exception' => $baseDir . '/src/exceptions/remote-request/bad-request-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Forbidden_Exception' => $baseDir . '/src/exceptions/remote-request/forbidden-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Internal_Server_Error_Exception' => $baseDir . '/src/exceptions/remote-request/internal-server-error-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Not_Found_Exception' => $baseDir . '/src/exceptions/remote-request/not-found-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Payment_Required_Exception' => $baseDir . '/src/exceptions/remote-request/payment-required-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Remote_Request_Exception' => $baseDir . '/src/exceptions/remote-request/remote-request-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Request_Timeout_Exception' => $baseDir . '/src/exceptions/remote-request/request-timeout-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Service_Unavailable_Exception' => $baseDir . '/src/exceptions/remote-request/service-unavailable-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Too_Many_Requests_Exception' => $baseDir . '/src/exceptions/remote-request/too-many-requests-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Unauthorized_Exception' => $baseDir . '/src/exceptions/remote-request/unauthorized-exception.php',
'Yoast\\WP\\SEO\\Premium\\Generated\\Cached_Container' => $baseDir . '/src/generated/container.php',
'Yoast\\WP\\SEO\\Premium\\Helpers\\AI_Generator_Helper' => $baseDir . '/src/helpers/ai-generator-helper.php',
'Yoast\\WP\\SEO\\Premium\\Helpers\\Current_Page_Helper' => $baseDir . '/src/helpers/current-page-helper.php',
'Yoast\\WP\\SEO\\Premium\\Helpers\\Prominent_Words_Helper' => $baseDir . '/src/helpers/prominent-words-helper.php',
'Yoast\\WP\\SEO\\Premium\\Helpers\\Version_Helper' => $baseDir . '/src/helpers/version-helper.php',
'Yoast\\WP\\SEO\\Premium\\Helpers\\Zapier_Helper' => $baseDir . '/src/deprecated/helpers/zapier-helper.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Crawl_Cleanup_Permalinks' => $baseDir . '/src/deprecated/initializers/crawl-cleanup-permalinks.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Index_Now_Key' => $baseDir . '/src/initializers/index-now-key.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Introductions_Initializer' => $baseDir . '/src/initializers/introductions-initializer.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Plugin' => $baseDir . '/src/initializers/plugin.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Redirect_Handler' => $baseDir . '/src/initializers/redirect-handler.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Woocommerce' => $baseDir . '/src/initializers/woocommerce.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Wp_Cli_Initializer' => $baseDir . '/src/initializers/wp-cli-initializer.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Abstract_OpenGraph_Integration' => $baseDir . '/src/integrations/abstract-opengraph-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Ai_Consent_Integration' => $baseDir . '/src/integrations/admin/ai-consent-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Ai_Generator_Integration' => $baseDir . '/src/integrations/admin/ai-generator-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Cornerstone_Column_Integration' => $baseDir . '/src/integrations/admin/cornerstone-column-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Cornerstone_Taxonomy_Column_Integration' => $baseDir . '/src/integrations/admin/cornerstone-taxonomy-column-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Crawl_Settings_Integration' => $baseDir . '/src/deprecated/integrations/admin/crawl-settings-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Inclusive_Language_Column_Integration' => $baseDir . '/src/integrations/admin/inclusive-language-column-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Inclusive_Language_Filter_Integration' => $baseDir . '/src/integrations/admin/inclusive-language-filter-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Inclusive_Language_Taxonomy_Column_Integration' => $baseDir . '/src/integrations/admin/inclusive-language-taxonomy-column-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Integrations_Page' => $baseDir . '/src/deprecated/integrations/admin/integrations-page.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Keyword_Integration' => $baseDir . '/src/integrations/admin/keyword-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Metabox_Formatter_Integration' => $baseDir . '/src/integrations/admin/metabox-formatter-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Plugin_Links_Integration' => $baseDir . '/src/integrations/admin/plugin-links-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Social_Templates\\Social_Templates_Integration' => $baseDir . '/src/integrations/admin/social-templates/social-templates-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Prominent_Words\\Indexing_Integration' => $baseDir . '/src/integrations/admin/prominent-words/indexing-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Prominent_Words\\Metabox_Integration' => $baseDir . '/src/integrations/admin/prominent-words/metabox-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Related_Keyphrase_Filter_Integration' => $baseDir . '/src/integrations/admin/related-keyphrase-filter-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Replacement_Variables_Integration' => $baseDir . '/src/integrations/admin/replacement-variables-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Settings_Integration' => $baseDir . '/src/integrations/admin/settings-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Thank_You_Page_Integration' => $baseDir . '/src/integrations/admin/thank-you-page-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Update_Premium_Notification' => $baseDir . '/src/integrations/admin/update-premium-notification.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\User_Profile_Integration' => $baseDir . '/src/integrations/admin/user-profile-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Workouts_Integration' => $baseDir . '/src/integrations/admin/workouts-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Zapier_Notification_Integration' => $baseDir . '/src/deprecated/integrations/admin/zapier-notification-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Alerts\\Ai_Generator_Tip_Notification' => $baseDir . '/src/integrations/alerts/ai-generator-tip-notification.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Blocks\\Estimated_Reading_Time_Block' => $baseDir . '/src/integrations/blocks/estimated-reading-time-block.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Blocks\\Related_Links_Block' => $baseDir . '/src/integrations/blocks/related-links-block.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Blocks\\Schema_Blocks' => $baseDir . '/src/deprecated/integrations/blocks/schema-blocks.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Cleanup_Integration' => $baseDir . '/src/integrations/cleanup-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Front_End\\Crawl_Cleanup_Basic' => $baseDir . '/src/deprecated/integrations/front-end/crawl-cleanup-basic.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Front_End\\Crawl_Cleanup_Rss' => $baseDir . '/src/deprecated/integrations/front-end/crawl-cleanup-rss.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Front_End\\Crawl_Cleanup_Searches' => $baseDir . '/src/deprecated/integrations/front-end/crawl-cleanup-searches.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Front_End\\Robots_Txt_Integration' => $baseDir . '/src/integrations/front-end/robots-txt-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Frontend_Inspector' => $baseDir . '/src/integrations/frontend-inspector.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Index_Now_Ping' => $baseDir . '/src/integrations/index-now-ping.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Missing_Indexables_Count_Integration' => $baseDir . '/src/integrations/missing-indexables-count-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\OpenGraph_Author_Archive' => $baseDir . '/src/integrations/opengraph-author-archive.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\OpenGraph_Date_Archive' => $baseDir . '/src/integrations/opengraph-date-archive.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\OpenGraph_PostType_Archive' => $baseDir . '/src/integrations/opengraph-posttype-archive.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\OpenGraph_Post_Type' => $baseDir . '/src/integrations/opengraph-post-type.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\OpenGraph_Term_Archive' => $baseDir . '/src/integrations/opengraph-term-archive.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Publishing_Principles_Schema_Integration' => $baseDir . '/src/integrations/publishing-principles-schema-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Routes\\AI_Generator_Route' => $baseDir . '/src/integrations/routes/ai-generator-route.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Routes\\Workouts_Routes_Integration' => $baseDir . '/src/integrations/routes/workouts-routes-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Algolia' => $baseDir . '/src/integrations/third-party/algolia.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\EDD' => $baseDir . '/src/integrations/third-party/edd.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Elementor_Premium' => $baseDir . '/src/integrations/third-party/elementor-premium.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Mastodon' => $baseDir . '/src/integrations/third-party/mastodon.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Zapier' => $baseDir . '/src/deprecated/integrations/third-party/zapier.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Zapier_Classic_Editor' => $baseDir . '/src/deprecated/integrations/third-party/zapier-classic-editor.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Zapier_Trigger' => $baseDir . '/src/deprecated/integrations/third-party/zapier-trigger.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Upgrade_Integration' => $baseDir . '/src/integrations/upgrade-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\User_Profile_Integration' => $baseDir . '/src/integrations/user-profile-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Watchers\\Premium_Option_Wpseo_Watcher' => $baseDir . '/src/deprecated/integrations/watchers/premium-option-wpseo-watcher.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Watchers\\Prominent_Words_Watcher' => $baseDir . '/src/integrations/watchers/prominent-words-watcher.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Watchers\\Zapier_APIKey_Reset_Watcher' => $baseDir . '/src/deprecated/integrations/watchers/zapier-apikey-reset-watcher.php',
'Yoast\\WP\\SEO\\Premium\\Main' => $baseDir . '/src/main.php',
'Yoast\\WP\\SEO\\Premium\\Presenters\\Icons\\Checkmark_Icon_Presenter' => $baseDir . '/src/presenters/icons/checkmark-icon-presenter.php',
'Yoast\\WP\\SEO\\Premium\\Presenters\\Icons\\Cross_Icon_Presenter' => $baseDir . '/src/presenters/icons/cross-icon-presenter.php',
'Yoast\\WP\\SEO\\Premium\\Presenters\\Icons\\Icon_Presenter' => $baseDir . '/src/presenters/icons/icon-presenter.php',
'Yoast\\WP\\SEO\\Premium\\Presenters\\Mastodon_Link_Presenter' => $baseDir . '/src/presenters/mastodon-link-presenter.php',
'Yoast\\WP\\SEO\\Premium\\Repositories\\Prominent_Words_Repository' => $baseDir . '/src/repositories/prominent-words-repository.php',
'Yoast\\WP\\SEO\\Premium\\Routes\\Link_Suggestions_Route' => $baseDir . '/src/routes/link-suggestions-route.php',
'Yoast\\WP\\SEO\\Premium\\Routes\\Prominent_Words_Route' => $baseDir . '/src/routes/prominent-words-route.php',
'Yoast\\WP\\SEO\\Premium\\Routes\\Workouts_Route' => $baseDir . '/src/routes/workouts-route.php',
'Yoast\\WP\\SEO\\Premium\\Routes\\Zapier_Route' => $baseDir . '/src/deprecated/routes/zapier-route.php',
'Yoast\\WP\\SEO\\Premium\\Surfaces\\Helpers_Surface' => $baseDir . '/src/surfaces/helpers-surface.php',
'Yoast\\WP\\SEO\\Premium\\WordPress\\Wrapper' => $baseDir . '/src/wordpress/wrapper.php',
'Yoast\\WP\\SEO\\Presenters\\Admin\\Prominent_Words\\Indexation_List_Item_Presenter' => $baseDir . '/src/deprecated/presenters/indexation-list-item-presenter.php',
'Yoast\\WP\\SEO\\Presenters\\Admin\\Prominent_Words\\Indexation_Modal_Presenter' => $baseDir . '/src/deprecated/presenters/indexation-modal-presenter.php',
'Yoast\\WP\\SEO\\Presenters\\Prominent_Words_Notification' => $baseDir . '/src/deprecated/presenters/prominent-words-notification.php',
'Yoast\\WP\\SEO\\Repositories\\Prominent_Words_Repository' => $baseDir . '/src/repositories/prominent-words-repository.php',
'Yoast\\WP\\SEO\\Routes\\Link_Suggestions_Route' => $baseDir . '/src/routes/link-suggestions-route.php',
'Yoast\\WP\\SEO\\Routes\\Prominent_Words_Route' => $baseDir . '/src/routes/prominent-words-route.php',
'Yoast\\WP\\SEO\\Routes\\Zapier_Route' => $baseDir . '/src/routes/zapier-route.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Assets\\Icons' => $baseDir . '/src/schema-templates/assets/icons.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern' => $baseDir . '/src/schema-templates/block-patterns/block-pattern.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern_Categories' => $baseDir . '/src/schema-templates/block-patterns/block-pattern-categories.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern_Keywords' => $baseDir . '/src/schema-templates/block-patterns/block-pattern-keywords.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Base_Pattern' => $baseDir . '/src/schema-templates/block-patterns/job-posting-base-pattern.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Default' => $baseDir . '/src/schema-templates/block-patterns/job-posting-default.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Minimal' => $baseDir . '/src/schema-templates/block-patterns/job-posting-minimal.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Yoast_Com' => $baseDir . '/src/schema-templates/block-patterns/job-posting-yoast-com.php',
'Yoast\\WP\\SEO\\WordPress\\Premium_Wrapper' => $baseDir . '/src/deprecated/wordpress/renamed-classes.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern' => $baseDir . '/src/deprecated/schema-templates/block-patterns/block-pattern.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern_Categories' => $baseDir . '/src/deprecated/schema-templates/block-patterns/block-pattern-categories.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern_Keywords' => $baseDir . '/src/deprecated/schema-templates/block-patterns/block-pattern-keywords.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Base_Pattern' => $baseDir . '/src/deprecated/schema-templates/block-patterns/job-posting-base-pattern.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_One_Column' => $baseDir . '/src/deprecated/schema-templates/block-patterns/job-posting-one-column.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Two_Columns' => $baseDir . '/src/deprecated/schema-templates/block-patterns/job-posting-two-columns.php',
);

View File

@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit85714e6ef573a9700a89c1b37454f5f2
class ComposerAutoloaderInit0c422f20871bcbf1c73c1006dcf06201
{
private static $loader;
@@ -24,15 +24,15 @@ class ComposerAutoloaderInit85714e6ef573a9700a89c1b37454f5f2
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit85714e6ef573a9700a89c1b37454f5f2', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit0c422f20871bcbf1c73c1006dcf06201', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit85714e6ef573a9700a89c1b37454f5f2', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit0c422f20871bcbf1c73c1006dcf06201', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit85714e6ef573a9700a89c1b37454f5f2::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit0c422f20871bcbf1c73c1006dcf06201::getInitializer($loader));
} else {
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {

View File

@@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInit85714e6ef573a9700a89c1b37454f5f2
class ComposerStaticInit0c422f20871bcbf1c73c1006dcf06201
{
public static $prefixLengthsPsr4 = array (
'C' =>
@@ -40,7 +40,7 @@ class ComposerStaticInit85714e6ef573a9700a89c1b37454f5f2
'WPSEO_Export_Keywords_Query' => __DIR__ . '/../..' . '/classes/export/export-keywords-query-interface.php',
'WPSEO_Export_Keywords_Term_Presenter' => __DIR__ . '/../..' . '/classes/export/export-keywords-term-presenter.php',
'WPSEO_Export_Keywords_Term_Query' => __DIR__ . '/../..' . '/classes/export/export-keywords-term-query.php',
'WPSEO_Facebook_Profile' => __DIR__ . '/../..' . '/classes/facebook-profile.php',
'WPSEO_Facebook_Profile' => __DIR__ . '/../..' . '/src/deprecated/classes/facebook-profile.php',
'WPSEO_Metabox_Link_Suggestions' => __DIR__ . '/../..' . '/classes/metabox-link-suggestions.php',
'WPSEO_Multi_Keyword' => __DIR__ . '/../..' . '/classes/multi-keyword.php',
'WPSEO_Post_Watcher' => __DIR__ . '/../..' . '/classes/post-watcher.php',
@@ -48,9 +48,6 @@ class ComposerStaticInit85714e6ef573a9700a89c1b37454f5f2
'WPSEO_Premium_Asset_JS_L10n' => __DIR__ . '/../..' . '/classes/premium-asset-js-l10n.php',
'WPSEO_Premium_Assets' => __DIR__ . '/../..' . '/classes/premium-assets.php',
'WPSEO_Premium_Expose_Shortlinks' => __DIR__ . '/../..' . '/classes/premium-expose-shortlinks.php',
'WPSEO_Premium_Free_Translations' => __DIR__ . '/../..' . '/classes/premium-free-translations.php',
'WPSEO_Premium_GSC' => __DIR__ . '/../..' . '/classes/premium-gsc.php',
'WPSEO_Premium_GSC_Modal' => __DIR__ . '/../..' . '/classes/premium-gsc-modal.php',
'WPSEO_Premium_Import_Manager' => __DIR__ . '/../..' . '/classes/premium-import-manager.php',
'WPSEO_Premium_Javascript_Strings' => __DIR__ . '/../..' . '/classes/premium-javascript-strings.php',
'WPSEO_Premium_Keyword_Export_Manager' => __DIR__ . '/../..' . '/classes/premium-keyword-export-manager.php',
@@ -59,13 +56,7 @@ class ComposerStaticInit85714e6ef573a9700a89c1b37454f5f2
'WPSEO_Premium_Orphaned_Content_Support' => __DIR__ . '/../..' . '/classes/premium-orphaned-content-support.php',
'WPSEO_Premium_Orphaned_Content_Utils' => __DIR__ . '/../..' . '/classes/premium-orphaned-content-utils.php',
'WPSEO_Premium_Orphaned_Post_Filter' => __DIR__ . '/../..' . '/classes/premium-orphaned-post-filter.php',
'WPSEO_Premium_Orphaned_Post_Notifier' => __DIR__ . '/../..' . '/classes/premium-orphaned-post-notifier.php',
'WPSEO_Premium_Orphaned_Post_Query' => __DIR__ . '/../..' . '/classes/premium-orphaned-post-query.php',
'WPSEO_Premium_Prominent_Words_Language_Support' => __DIR__ . '/../..' . '/classes/deprecated/premium-prominent-words-language-support.php',
'WPSEO_Premium_Prominent_Words_Recalculation' => __DIR__ . '/../..' . '/classes/premium-prominent-words-recalculation.php',
'WPSEO_Premium_Prominent_Words_Recalculation_Endpoint' => __DIR__ . '/../..' . '/classes/deprecated/premium-prominent-words-recalculation-endpoint.php',
'WPSEO_Premium_Prominent_Words_Recalculation_Notifier' => __DIR__ . '/../..' . '/classes/deprecated/premium-prominent-words-recalculation-notifier.php',
'WPSEO_Premium_Prominent_Words_Recalculation_Service' => __DIR__ . '/../..' . '/classes/deprecated/premium-prominent-words-recalculation-service.php',
'WPSEO_Premium_Prominent_Words_Support' => __DIR__ . '/../..' . '/classes/premium-prominent-words-support.php',
'WPSEO_Premium_Prominent_Words_Unindexed_Post_Query' => __DIR__ . '/../..' . '/classes/premium-prominent-words-unindexed-post-query.php',
'WPSEO_Premium_Prominent_Words_Versioning' => __DIR__ . '/../..' . '/classes/premium-prominent-words-versioning.php',
@@ -93,7 +84,6 @@ class ComposerStaticInit85714e6ef573a9700a89c1b37454f5f2
'WPSEO_Redirect_Formats' => __DIR__ . '/../..' . '/classes/redirect/redirect-formats.php',
'WPSEO_Redirect_Formatter' => __DIR__ . '/../..' . '/classes/redirect/redirect-formatter.php',
'WPSEO_Redirect_HTAccess_Loader' => __DIR__ . '/../..' . '/classes/redirect/loaders/redirect-htaccess-loader.php',
'WPSEO_Redirect_Handler' => __DIR__ . '/../..' . '/src/deprecated/redirect-handler.php',
'WPSEO_Redirect_Htaccess_Exporter' => __DIR__ . '/../..' . '/classes/redirect/exporters/redirect-htaccess-exporter.php',
'WPSEO_Redirect_Htaccess_Util' => __DIR__ . '/../..' . '/classes/redirect/redirect-htaccess-util.php',
'WPSEO_Redirect_Import_Exception' => __DIR__ . '/../..' . '/classes/redirect/redirect-import-exception.php',
@@ -133,85 +123,136 @@ class ComposerStaticInit85714e6ef573a9700a89c1b37454f5f2
'WPSEO_Validation_Result' => __DIR__ . '/../..' . '/classes/validation-result.php',
'WPSEO_Validation_Warning' => __DIR__ . '/../..' . '/classes/validation-warning.php',
'WPSEO_Watcher' => __DIR__ . '/../..' . '/classes/watcher.php',
'Yoast\\WP\\SEO\\Actions\\Link_Suggestions_Action' => __DIR__ . '/../..' . '/src/deprecated/actions/renamed-classes.php',
'Yoast\\WP\\SEO\\Actions\\Prominent_Words\\Complete_Action' => __DIR__ . '/../..' . '/src/deprecated/actions/prominent-words/renamed-classes.php',
'Yoast\\WP\\SEO\\Actions\\Prominent_Words\\Content_Action' => __DIR__ . '/../..' . '/src/deprecated/actions/prominent-words/renamed-classes.php',
'Yoast\\WP\\SEO\\Actions\\Prominent_Words\\Save_Action' => __DIR__ . '/../..' . '/src/deprecated/actions/prominent-words/renamed-classes.php',
'Yoast\\WP\\SEO\\Actions\\Zapier_Action' => __DIR__ . '/../..' . '/src/deprecated/actions/renamed-classes.php',
'Yoast\\WP\\SEO\\Conditionals\\Zapier_Enabled_Conditional' => __DIR__ . '/../..' . '/src/conditionals/zapier-enabled-conditional.php',
'Yoast\\WP\\SEO\\Config\\Migrations\\WpYoastPremiumImprovedInternalLinking' => __DIR__ . '/../..' . '/src/config/migrations/20190715101200_WpYoastPremiumImprovedInternalLinking.php',
'Yoast\\WP\\SEO\\Database\\Migration_Runner_Premium' => __DIR__ . '/../..' . '/src/deprecated/database/renamed-classes.php',
'Yoast\\WP\\SEO\\Helpers\\Prominent_Words_Helper' => __DIR__ . '/../..' . '/src/helpers/prominent-words-helper.php',
'Yoast\\WP\\SEO\\Helpers\\Zapier_Helper' => __DIR__ . '/../..' . '/src/helpers/zapier-helper.php',
'Yoast\\WP\\SEO\\Initializers\\Redirect_Handler' => __DIR__ . '/../..' . '/src/initializers/redirect-handler.php',
'Yoast\\WP\\SEO\\Integrations\\Admin\\Prominent_Words\\Indexation_Integration' => __DIR__ . '/../..' . '/src/deprecated/integrations/admin/prominent-words/indexation-integration.php',
'Yoast\\WP\\SEO\\Integrations\\Admin\\Prominent_Words\\Indexing_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/prominent-words/indexing-integration.php',
'Yoast\\WP\\SEO\\Integrations\\Admin\\Prominent_Words\\Metabox_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/prominent-words/metabox-integration.php',
'Yoast\\WP\\SEO\\Integrations\\Admin\\Prominent_Words\\Notification_Event_Integration' => __DIR__ . '/../..' . '/src/deprecated/integrations/admin/prominent-words/notification-event-integration.php',
'Yoast\\WP\\SEO\\Integrations\\Admin\\Prominent_Words_Notification' => __DIR__ . '/../..' . '/src/deprecated/integrations/admin/prominent-words-notification.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Block_Patterns' => __DIR__ . '/../..' . '/src/integrations/blocks/block-patterns.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Estimated_Reading_Time_Block' => __DIR__ . '/../..' . '/src/integrations/blocks/estimated-reading-time-block.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Job_Posting_Block' => __DIR__ . '/../..' . '/src/integrations/blocks/job-posting-block.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Related_Links_Block' => __DIR__ . '/../..' . '/src/integrations/blocks/related-links-block.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Schema_Blocks' => __DIR__ . '/../..' . '/src/integrations/blocks/schema-blocks.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Block_Patterns' => __DIR__ . '/../..' . '/src/deprecated/integrations/blocks/block-patterns.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Job_Posting_Block' => __DIR__ . '/../..' . '/src/deprecated/integrations/blocks/job-posting-block.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Siblings_Block' => __DIR__ . '/../..' . '/classes/blocks/siblings-block.php',
'Yoast\\WP\\SEO\\Integrations\\Blocks\\Subpages_Block' => __DIR__ . '/../..' . '/classes/blocks/subpages-block.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Elementor_Premium' => __DIR__ . '/../..' . '/src/integrations/third-party/elementor-premium.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\TranslationsPress' => __DIR__ . '/../..' . '/src/integrations/third-party/translationspress.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Zapier' => __DIR__ . '/../..' . '/src/integrations/third-party/zapier.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Zapier_Classic_Editor' => __DIR__ . '/../..' . '/src/integrations/third-party/zapier-classic-editor.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Zapier_Trigger' => __DIR__ . '/../..' . '/src/integrations/third-party/zapier-trigger.php',
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Premium_Option_Wpseo_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/premium-option-wpseo-watcher.php',
'Yoast\\WP\\SEO\\Integrations\\Watchers\\Zapier_APIKey_Reset_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/zapier-apikey-reset-watcher.php',
'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Wincher_Keyphrases' => __DIR__ . '/../..' . '/src/integrations/third-party/wincher-keyphrases.php',
'Yoast\\WP\\SEO\\Models\\Prominent_Words' => __DIR__ . '/../..' . '/src/models/prominent-words.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\AI_Generator_Action' => __DIR__ . '/../..' . '/src/actions/ai-generator-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Link_Suggestions_Action' => __DIR__ . '/../..' . '/src/actions/link-suggestions-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Prominent_Words\\Complete_Action' => __DIR__ . '/../..' . '/src/actions/prominent-words/complete-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Prominent_Words\\Content_Action' => __DIR__ . '/../..' . '/src/actions/prominent-words/content-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Prominent_Words\\Save_Action' => __DIR__ . '/../..' . '/src/actions/prominent-words/save-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Zapier_Action' => __DIR__ . '/../..' . '/src/actions/zapier-action.php',
'Yoast\\WP\\SEO\\Premium\\Actions\\Zapier_Action' => __DIR__ . '/../..' . '/src/deprecated/actions/zapier-action.php',
'Yoast\\WP\\SEO\\Premium\\Addon_Installer' => __DIR__ . '/../..' . '/src/addon-installer.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Social_Templates_Conditional' => __DIR__ . '/../..' . '/src/conditionals/social-templates-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Ai_Editor_Conditional' => __DIR__ . '/../..' . '/src/conditionals/ai-editor-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Algolia_Enabled_Conditional' => __DIR__ . '/../..' . '/src/conditionals/algolia-enabled-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Cornerstone_Enabled_Conditional' => __DIR__ . '/../..' . '/src/conditionals/cornerstone-enabled-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\EDD_Conditional' => __DIR__ . '/../..' . '/src/conditionals/edd-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Inclusive_Language_Enabled_Conditional' => __DIR__ . '/../..' . '/src/conditionals/inclusive-language-enabled-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Term_Overview_Or_Ajax_Conditional' => __DIR__ . '/../..' . '/src/conditionals/term-overview-or-ajax-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Conditionals\\Zapier_Enabled_Conditional' => __DIR__ . '/../..' . '/src/deprecated/conditionals/zapier-enabled-conditional.php',
'Yoast\\WP\\SEO\\Premium\\Config\\Badge_Group_Names' => __DIR__ . '/../..' . '/src/config/badge-group-names.php',
'Yoast\\WP\\SEO\\Premium\\Config\\Migrations\\AddIndexOnIndexableIdAndStem' => __DIR__ . '/../..' . '/src/config/migrations/20210827093024_AddIndexOnIndexableIdAndStem.php',
'Yoast\\WP\\SEO\\Premium\\Database\\Migration_Runner_Premium' => __DIR__ . '/../..' . '/src/database/migration-runner-premium.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Forbidden_Property_Mutation_Exception' => __DIR__ . '/../..' . '/src/exceptions/forbidden-property-mutation-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Bad_Request_Exception' => __DIR__ . '/../..' . '/src/exceptions/remote-request/bad-request-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Forbidden_Exception' => __DIR__ . '/../..' . '/src/exceptions/remote-request/forbidden-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Internal_Server_Error_Exception' => __DIR__ . '/../..' . '/src/exceptions/remote-request/internal-server-error-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Not_Found_Exception' => __DIR__ . '/../..' . '/src/exceptions/remote-request/not-found-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Payment_Required_Exception' => __DIR__ . '/../..' . '/src/exceptions/remote-request/payment-required-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Remote_Request_Exception' => __DIR__ . '/../..' . '/src/exceptions/remote-request/remote-request-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Request_Timeout_Exception' => __DIR__ . '/../..' . '/src/exceptions/remote-request/request-timeout-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Service_Unavailable_Exception' => __DIR__ . '/../..' . '/src/exceptions/remote-request/service-unavailable-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Too_Many_Requests_Exception' => __DIR__ . '/../..' . '/src/exceptions/remote-request/too-many-requests-exception.php',
'Yoast\\WP\\SEO\\Premium\\Exceptions\\Remote_Request\\Unauthorized_Exception' => __DIR__ . '/../..' . '/src/exceptions/remote-request/unauthorized-exception.php',
'Yoast\\WP\\SEO\\Premium\\Generated\\Cached_Container' => __DIR__ . '/../..' . '/src/generated/container.php',
'Yoast\\WP\\SEO\\Premium\\Helpers\\AI_Generator_Helper' => __DIR__ . '/../..' . '/src/helpers/ai-generator-helper.php',
'Yoast\\WP\\SEO\\Premium\\Helpers\\Current_Page_Helper' => __DIR__ . '/../..' . '/src/helpers/current-page-helper.php',
'Yoast\\WP\\SEO\\Premium\\Helpers\\Prominent_Words_Helper' => __DIR__ . '/../..' . '/src/helpers/prominent-words-helper.php',
'Yoast\\WP\\SEO\\Premium\\Helpers\\Version_Helper' => __DIR__ . '/../..' . '/src/helpers/version-helper.php',
'Yoast\\WP\\SEO\\Premium\\Helpers\\Zapier_Helper' => __DIR__ . '/../..' . '/src/deprecated/helpers/zapier-helper.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Crawl_Cleanup_Permalinks' => __DIR__ . '/../..' . '/src/deprecated/initializers/crawl-cleanup-permalinks.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Index_Now_Key' => __DIR__ . '/../..' . '/src/initializers/index-now-key.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Introductions_Initializer' => __DIR__ . '/../..' . '/src/initializers/introductions-initializer.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Plugin' => __DIR__ . '/../..' . '/src/initializers/plugin.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Redirect_Handler' => __DIR__ . '/../..' . '/src/initializers/redirect-handler.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Woocommerce' => __DIR__ . '/../..' . '/src/initializers/woocommerce.php',
'Yoast\\WP\\SEO\\Premium\\Initializers\\Wp_Cli_Initializer' => __DIR__ . '/../..' . '/src/initializers/wp-cli-initializer.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Abstract_OpenGraph_Integration' => __DIR__ . '/../..' . '/src/integrations/abstract-opengraph-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Ai_Consent_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/ai-consent-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Ai_Generator_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/ai-generator-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Cornerstone_Column_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/cornerstone-column-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Cornerstone_Taxonomy_Column_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/cornerstone-taxonomy-column-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Crawl_Settings_Integration' => __DIR__ . '/../..' . '/src/deprecated/integrations/admin/crawl-settings-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Inclusive_Language_Column_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/inclusive-language-column-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Inclusive_Language_Filter_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/inclusive-language-filter-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Inclusive_Language_Taxonomy_Column_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/inclusive-language-taxonomy-column-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Integrations_Page' => __DIR__ . '/../..' . '/src/deprecated/integrations/admin/integrations-page.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Keyword_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/keyword-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Metabox_Formatter_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/metabox-formatter-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Plugin_Links_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/plugin-links-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Social_Templates\\Social_Templates_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/social-templates/social-templates-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Prominent_Words\\Indexing_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/prominent-words/indexing-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Prominent_Words\\Metabox_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/prominent-words/metabox-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Related_Keyphrase_Filter_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/related-keyphrase-filter-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Replacement_Variables_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/replacement-variables-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Settings_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/settings-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Thank_You_Page_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/thank-you-page-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Update_Premium_Notification' => __DIR__ . '/../..' . '/src/integrations/admin/update-premium-notification.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\User_Profile_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/user-profile-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Workouts_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/workouts-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Admin\\Zapier_Notification_Integration' => __DIR__ . '/../..' . '/src/deprecated/integrations/admin/zapier-notification-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Alerts\\Ai_Generator_Tip_Notification' => __DIR__ . '/../..' . '/src/integrations/alerts/ai-generator-tip-notification.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Blocks\\Estimated_Reading_Time_Block' => __DIR__ . '/../..' . '/src/integrations/blocks/estimated-reading-time-block.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Blocks\\Related_Links_Block' => __DIR__ . '/../..' . '/src/integrations/blocks/related-links-block.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Blocks\\Schema_Blocks' => __DIR__ . '/../..' . '/src/deprecated/integrations/blocks/schema-blocks.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Cleanup_Integration' => __DIR__ . '/../..' . '/src/integrations/cleanup-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Front_End\\Crawl_Cleanup_Basic' => __DIR__ . '/../..' . '/src/deprecated/integrations/front-end/crawl-cleanup-basic.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Front_End\\Crawl_Cleanup_Rss' => __DIR__ . '/../..' . '/src/deprecated/integrations/front-end/crawl-cleanup-rss.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Front_End\\Crawl_Cleanup_Searches' => __DIR__ . '/../..' . '/src/deprecated/integrations/front-end/crawl-cleanup-searches.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Front_End\\Robots_Txt_Integration' => __DIR__ . '/../..' . '/src/integrations/front-end/robots-txt-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Frontend_Inspector' => __DIR__ . '/../..' . '/src/integrations/frontend-inspector.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Index_Now_Ping' => __DIR__ . '/../..' . '/src/integrations/index-now-ping.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Missing_Indexables_Count_Integration' => __DIR__ . '/../..' . '/src/integrations/missing-indexables-count-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\OpenGraph_Author_Archive' => __DIR__ . '/../..' . '/src/integrations/opengraph-author-archive.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\OpenGraph_Date_Archive' => __DIR__ . '/../..' . '/src/integrations/opengraph-date-archive.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\OpenGraph_PostType_Archive' => __DIR__ . '/../..' . '/src/integrations/opengraph-posttype-archive.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\OpenGraph_Post_Type' => __DIR__ . '/../..' . '/src/integrations/opengraph-post-type.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\OpenGraph_Term_Archive' => __DIR__ . '/../..' . '/src/integrations/opengraph-term-archive.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Publishing_Principles_Schema_Integration' => __DIR__ . '/../..' . '/src/integrations/publishing-principles-schema-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Routes\\AI_Generator_Route' => __DIR__ . '/../..' . '/src/integrations/routes/ai-generator-route.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Routes\\Workouts_Routes_Integration' => __DIR__ . '/../..' . '/src/integrations/routes/workouts-routes-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Algolia' => __DIR__ . '/../..' . '/src/integrations/third-party/algolia.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\EDD' => __DIR__ . '/../..' . '/src/integrations/third-party/edd.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Elementor_Premium' => __DIR__ . '/../..' . '/src/integrations/third-party/elementor-premium.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Mastodon' => __DIR__ . '/../..' . '/src/integrations/third-party/mastodon.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Zapier' => __DIR__ . '/../..' . '/src/deprecated/integrations/third-party/zapier.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Zapier_Classic_Editor' => __DIR__ . '/../..' . '/src/deprecated/integrations/third-party/zapier-classic-editor.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Third_Party\\Zapier_Trigger' => __DIR__ . '/../..' . '/src/deprecated/integrations/third-party/zapier-trigger.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Upgrade_Integration' => __DIR__ . '/../..' . '/src/integrations/upgrade-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\User_Profile_Integration' => __DIR__ . '/../..' . '/src/integrations/user-profile-integration.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Watchers\\Premium_Option_Wpseo_Watcher' => __DIR__ . '/../..' . '/src/deprecated/integrations/watchers/premium-option-wpseo-watcher.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Watchers\\Prominent_Words_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/prominent-words-watcher.php',
'Yoast\\WP\\SEO\\Premium\\Integrations\\Watchers\\Zapier_APIKey_Reset_Watcher' => __DIR__ . '/../..' . '/src/deprecated/integrations/watchers/zapier-apikey-reset-watcher.php',
'Yoast\\WP\\SEO\\Premium\\Main' => __DIR__ . '/../..' . '/src/main.php',
'Yoast\\WP\\SEO\\Premium\\Presenters\\Icons\\Checkmark_Icon_Presenter' => __DIR__ . '/../..' . '/src/presenters/icons/checkmark-icon-presenter.php',
'Yoast\\WP\\SEO\\Premium\\Presenters\\Icons\\Cross_Icon_Presenter' => __DIR__ . '/../..' . '/src/presenters/icons/cross-icon-presenter.php',
'Yoast\\WP\\SEO\\Premium\\Presenters\\Icons\\Icon_Presenter' => __DIR__ . '/../..' . '/src/presenters/icons/icon-presenter.php',
'Yoast\\WP\\SEO\\Premium\\Presenters\\Mastodon_Link_Presenter' => __DIR__ . '/../..' . '/src/presenters/mastodon-link-presenter.php',
'Yoast\\WP\\SEO\\Premium\\Repositories\\Prominent_Words_Repository' => __DIR__ . '/../..' . '/src/repositories/prominent-words-repository.php',
'Yoast\\WP\\SEO\\Premium\\Routes\\Link_Suggestions_Route' => __DIR__ . '/../..' . '/src/routes/link-suggestions-route.php',
'Yoast\\WP\\SEO\\Premium\\Routes\\Prominent_Words_Route' => __DIR__ . '/../..' . '/src/routes/prominent-words-route.php',
'Yoast\\WP\\SEO\\Premium\\Routes\\Workouts_Route' => __DIR__ . '/../..' . '/src/routes/workouts-route.php',
'Yoast\\WP\\SEO\\Premium\\Routes\\Zapier_Route' => __DIR__ . '/../..' . '/src/deprecated/routes/zapier-route.php',
'Yoast\\WP\\SEO\\Premium\\Surfaces\\Helpers_Surface' => __DIR__ . '/../..' . '/src/surfaces/helpers-surface.php',
'Yoast\\WP\\SEO\\Premium\\WordPress\\Wrapper' => __DIR__ . '/../..' . '/src/wordpress/wrapper.php',
'Yoast\\WP\\SEO\\Presenters\\Admin\\Prominent_Words\\Indexation_List_Item_Presenter' => __DIR__ . '/../..' . '/src/deprecated/presenters/indexation-list-item-presenter.php',
'Yoast\\WP\\SEO\\Presenters\\Admin\\Prominent_Words\\Indexation_Modal_Presenter' => __DIR__ . '/../..' . '/src/deprecated/presenters/indexation-modal-presenter.php',
'Yoast\\WP\\SEO\\Presenters\\Prominent_Words_Notification' => __DIR__ . '/../..' . '/src/deprecated/presenters/prominent-words-notification.php',
'Yoast\\WP\\SEO\\Repositories\\Prominent_Words_Repository' => __DIR__ . '/../..' . '/src/repositories/prominent-words-repository.php',
'Yoast\\WP\\SEO\\Routes\\Link_Suggestions_Route' => __DIR__ . '/../..' . '/src/routes/link-suggestions-route.php',
'Yoast\\WP\\SEO\\Routes\\Prominent_Words_Route' => __DIR__ . '/../..' . '/src/routes/prominent-words-route.php',
'Yoast\\WP\\SEO\\Routes\\Zapier_Route' => __DIR__ . '/../..' . '/src/routes/zapier-route.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Assets\\Icons' => __DIR__ . '/../..' . '/src/schema-templates/assets/icons.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern' => __DIR__ . '/../..' . '/src/schema-templates/block-patterns/block-pattern.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern_Categories' => __DIR__ . '/../..' . '/src/schema-templates/block-patterns/block-pattern-categories.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern_Keywords' => __DIR__ . '/../..' . '/src/schema-templates/block-patterns/block-pattern-keywords.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Base_Pattern' => __DIR__ . '/../..' . '/src/schema-templates/block-patterns/job-posting-base-pattern.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Default' => __DIR__ . '/../..' . '/src/schema-templates/block-patterns/job-posting-default.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Minimal' => __DIR__ . '/../..' . '/src/schema-templates/block-patterns/job-posting-minimal.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Yoast_Com' => __DIR__ . '/../..' . '/src/schema-templates/block-patterns/job-posting-yoast-com.php',
'Yoast\\WP\\SEO\\WordPress\\Premium_Wrapper' => __DIR__ . '/../..' . '/src/deprecated/wordpress/renamed-classes.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern' => __DIR__ . '/../..' . '/src/deprecated/schema-templates/block-patterns/block-pattern.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern_Categories' => __DIR__ . '/../..' . '/src/deprecated/schema-templates/block-patterns/block-pattern-categories.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Block_Pattern_Keywords' => __DIR__ . '/../..' . '/src/deprecated/schema-templates/block-patterns/block-pattern-keywords.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Base_Pattern' => __DIR__ . '/../..' . '/src/deprecated/schema-templates/block-patterns/job-posting-base-pattern.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_One_Column' => __DIR__ . '/../..' . '/src/deprecated/schema-templates/block-patterns/job-posting-one-column.php',
'Yoast\\WP\\SEO\\Schema_Templates\\Block_Patterns\\Job_Posting_Two_Columns' => __DIR__ . '/../..' . '/src/deprecated/schema-templates/block-patterns/job-posting-two-columns.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit85714e6ef573a9700a89c1b37454f5f2::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit85714e6ef573a9700a89c1b37454f5f2::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit85714e6ef573a9700a89c1b37454f5f2::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit0c422f20871bcbf1c73c1006dcf06201::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit0c422f20871bcbf1c73c1006dcf06201::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit0c422f20871bcbf1c73c1006dcf06201::$classMap;
}, null, ClassLoader::class);
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,8 +4,8 @@
$issues = array();
if (!(PHP_VERSION_ID >= 50620)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 5.6.20". You are running ' . PHP_VERSION . '.';
if (!(PHP_VERSION_ID >= 70205)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.';
}
if ($issues) {

View File

@@ -32,7 +32,11 @@ function wpseo_set_option() {
check_ajax_referer( 'wpseo-setoption' );
$option = sanitize_text_field( filter_input( INPUT_POST, 'option' ) );
if ( ! isset( $_POST['option'] ) || ! is_string( $_POST['option'] ) ) {
die( '-1' );
}
$option = sanitize_text_field( wp_unslash( $_POST['option'] ) );
if ( $option !== 'page_comments' ) {
die( '-1' );
}
@@ -58,7 +62,11 @@ function wpseo_set_ignore() {
check_ajax_referer( 'wpseo-ignore' );
$ignore_key = sanitize_text_field( filter_input( INPUT_POST, 'option' ) );
if ( ! isset( $_POST['option'] ) || ! is_string( $_POST['option'] ) ) {
die( '-1' );
}
$ignore_key = sanitize_text_field( wp_unslash( $_POST['option'] ) );
WPSEO_Options::set( 'ignore_' . $ignore_key, true );
die( '1' );
@@ -92,9 +100,18 @@ add_action( 'wp_ajax_wpseo_save_metadesc', 'wpseo_save_description' );
function wpseo_save_what( $what ) {
check_ajax_referer( 'wpseo-bulk-editor' );
$new = filter_input( INPUT_POST, 'new_value' );
$post_id = intval( filter_input( INPUT_POST, 'wpseo_post_id' ) );
$original = filter_input( INPUT_POST, 'existing_value' );
if ( ! isset( $_POST['new_value'], $_POST['wpseo_post_id'], $_POST['existing_value'] ) || ! is_string( $_POST['new_value'] ) || ! is_string( $_POST['existing_value'] ) ) {
die( '-1' );
}
$new = sanitize_text_field( wp_unslash( $_POST['new_value'] ) );
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are casting the unsafe value to an integer.
$post_id = (int) wp_unslash( $_POST['wpseo_post_id'] );
$original = sanitize_text_field( wp_unslash( $_POST['existing_value'] ) );
if ( $post_id === 0 ) {
die( '-1' );
}
$results = wpseo_upsert_new( $what, $post_id, $new, $original );
@@ -111,7 +128,7 @@ function wpseo_save_what( $what ) {
* @param string $meta_key Meta key string.
* @param string $return_key Return key string to use in results.
*
* @return string
* @return array
*/
function wpseo_upsert_meta( $post_id, $new_meta_value, $orig_meta_value, $meta_key, $return_key ) {
@@ -232,45 +249,80 @@ function wpseo_save_all( $what ) {
/**
* Insert a new value.
*
* @param string $what Item type (such as title).
* @param int $post_id Post ID.
* @param string $new New value to record.
* @param string $original Original value.
* @param string $what Item type (such as title).
* @param int $post_id Post ID.
* @param string $new_value New value to record.
* @param string $original Original value.
*
* @return string
*/
function wpseo_upsert_new( $what, $post_id, $new, $original ) {
function wpseo_upsert_new( $what, $post_id, $new_value, $original ) {
$meta_key = WPSEO_Meta::$meta_prefix . $what;
return wpseo_upsert_meta( $post_id, $new, $original, $meta_key, $what );
return wpseo_upsert_meta( $post_id, $new_value, $original, $meta_key, $what );
}
/**
* Retrieves the keyword for the keyword doubles.
* Retrieves the post ids where the keyword is used before as well as the types of those posts.
*/
function ajax_get_keyword_usage() {
$post_id = filter_input( INPUT_POST, 'post_id' );
$keyword = filter_input( INPUT_POST, 'keyword' );
function ajax_get_keyword_usage_and_post_types() {
check_ajax_referer( 'wpseo-keyword-usage-and-post-types', 'nonce' );
if ( ! current_user_can( 'edit_post', $post_id ) ) {
if ( ! isset( $_POST['post_id'], $_POST['keyword'] ) || ! is_string( $_POST['keyword'] ) ) {
die( '-1' );
}
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We are casting to an integer.
$post_id = (int) wp_unslash( $_POST['post_id'] );
if ( $post_id === 0 || ! current_user_can( 'edit_post', $post_id ) ) {
die( '-1' );
}
$keyword = sanitize_text_field( wp_unslash( $_POST['keyword'] ) );
$post_ids = WPSEO_Meta::keyword_usage( $keyword, $post_id );
if ( ! empty( $post_ids ) ) {
$post_types = WPSEO_Meta::post_types_for_ids( $post_ids );
}
else {
$post_types = [];
}
$return_object = [
'keyword_usage' => $post_ids,
'post_types' => $post_types,
];
wp_die(
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
WPSEO_Utils::format_json_encode( WPSEO_Meta::keyword_usage( $keyword, $post_id ) )
WPSEO_Utils::format_json_encode( $return_object )
);
}
add_action( 'wp_ajax_get_focus_keyword_usage', 'ajax_get_keyword_usage' );
add_action( 'wp_ajax_get_focus_keyword_usage_and_post_types', 'ajax_get_keyword_usage_and_post_types' );
/**
* Retrieves the keyword for the keyword doubles of the termpages.
*/
function ajax_get_term_keyword_usage() {
$post_id = filter_input( INPUT_POST, 'post_id' );
$keyword = filter_input( INPUT_POST, 'keyword' );
$taxonomy_name = filter_input( INPUT_POST, 'taxonomy' );
check_ajax_referer( 'wpseo-keyword-usage', 'nonce' );
if ( ! isset( $_POST['post_id'], $_POST['keyword'], $_POST['taxonomy'] ) || ! is_string( $_POST['keyword'] ) || ! is_string( $_POST['taxonomy'] ) ) {
wp_die( -1 );
}
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are casting the unsafe input to an integer.
$post_id = (int) wp_unslash( $_POST['post_id'] );
if ( $post_id === 0 ) {
wp_die( -1 );
}
$keyword = sanitize_text_field( wp_unslash( $_POST['keyword'] ) );
$taxonomy_name = sanitize_text_field( wp_unslash( $_POST['taxonomy'] ) );
$taxonomy = get_taxonomy( $taxonomy_name );
@@ -284,7 +336,7 @@ function ajax_get_term_keyword_usage() {
$usage = WPSEO_Taxonomy_Meta::get_keyword_usage( $keyword, $post_id, $taxonomy_name );
// Normalize the result so it it the same as the post keyword usage AJAX request.
// Normalize the result so it is the same as the post keyword usage AJAX request.
$usage = $usage[ $keyword ];
wp_die(
@@ -317,16 +369,27 @@ new WPSEO_Taxonomy_Columns();
/* ********************* DEPRECATED FUNCTIONS ********************* */
/**
* Hides the default tagline notice for a specific user.
*
* @deprecated 13.2
* @codeCoverageIgnore
* Retrieves the keyword for the keyword doubles.
*/
function wpseo_dismiss_tagline_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
function ajax_get_keyword_usage() {
_deprecated_function( __METHOD__, 'WPSEO 20.4' );
check_ajax_referer( 'wpseo-keyword-usage', 'nonce' );
if ( ! isset( $_POST['post_id'], $_POST['keyword'] ) || ! is_string( $_POST['keyword'] ) ) {
die( '-1' );
}
_deprecated_function( __FUNCTION__, 'WPSEO 13.2', 'This method is deprecated.' );
wpseo_ajax_json_echo_die( '' );
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We are casting to an integer.
$post_id = (int) wp_unslash( $_POST['post_id'] );
if ( $post_id === 0 || ! current_user_can( 'edit_post', $post_id ) ) {
die( '-1' );
}
$keyword = sanitize_text_field( wp_unslash( $_POST['keyword'] ) );
wp_die(
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
WPSEO_Utils::format_json_encode( WPSEO_Meta::keyword_usage( $keyword, $post_id ) )
);
}

View File

@@ -25,11 +25,21 @@ class WPSEO_Shortcode_Filter {
public function do_filter() {
check_ajax_referer( 'wpseo-filter-shortcodes', 'nonce' );
$shortcodes = filter_input( INPUT_POST, 'data', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
if ( ! isset( $_POST['data'] ) || ! is_array( $_POST['data'] ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: WPSEO_Utils::format_json_encode is considered safe.
wp_die( WPSEO_Utils::format_json_encode( [] ) );
}
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: $shortcodes is getting sanitized later, before it's used.
$shortcodes = wp_unslash( $_POST['data'] );
$parsed_shortcodes = [];
foreach ( $shortcodes as $shortcode ) {
if ( $shortcode !== sanitize_text_field( $shortcode ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: WPSEO_Utils::format_json_encode is considered safe.
wp_die( WPSEO_Utils::format_json_encode( [] ) );
}
$parsed_shortcodes[] = [
'shortcode' => $shortcode,
'output' => do_shortcode( $shortcode ),

View File

@@ -37,7 +37,18 @@ class Yoast_Plugin_Conflict_Ajax {
public function dismiss_notice() {
check_ajax_referer( 'dismiss-plugin-conflict' );
$conflict_data = filter_input( INPUT_POST, 'data', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
if ( ! isset( $_POST['data'] ) || ! is_array( $_POST['data'] ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: WPSEO_Utils::format_json_encode is considered safe.
wp_die( WPSEO_Utils::format_json_encode( [] ) );
}
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: $conflict_data is getting sanitized later.
$conflict_data = wp_unslash( $_POST['data'] );
$conflict_data = [
'section' => sanitize_text_field( $conflict_data['section'] ),
'plugins' => sanitize_text_field( $conflict_data['plugins'] ),
];
$this->dismissed_conflicts = $this->get_dismissed_conflicts( $conflict_data['section'] );

View File

@@ -21,6 +21,11 @@ class WPSEO_Register_Capabilities implements WPSEO_WordPress_Integration {
if ( is_multisite() ) {
add_action( 'user_has_cap', [ $this, 'filter_user_has_wpseo_manage_options_cap' ], 10, 4 );
}
/**
* Maybe add manage_privacy_options capability for wpseo_manager user role.
*/
add_filter( 'map_meta_cap', [ $this, 'map_meta_cap_for_seo_manager' ], 10, 2 );
}
/**
@@ -32,7 +37,7 @@ class WPSEO_Register_Capabilities implements WPSEO_WordPress_Integration {
$manager = WPSEO_Capability_Manager_Factory::get();
$manager->register( 'wpseo_bulk_edit', [ 'editor', 'wpseo_editor', 'wpseo_manager' ] );
$manager->register( 'wpseo_edit_advanced_metadata', [ 'wpseo_editor', 'wpseo_manager' ] );
$manager->register( 'wpseo_edit_advanced_metadata', [ 'editor', 'wpseo_editor', 'wpseo_manager' ] );
$manager->register( 'wpseo_manage_options', [ 'administrator', 'wpseo_manager' ] );
$manager->register( 'view_site_health_checks', [ 'wpseo_manager' ] );
@@ -74,4 +79,33 @@ class WPSEO_Register_Capabilities implements WPSEO_WordPress_Integration {
return $allcaps;
}
/**
* Maybe add manage_privacy_options capability for wpseo_manager user role.
*
* @param string[] $caps Primitive capabilities required of the user.
* @param string[] $cap Capability being checked.
*
* @return string[] Filtered primitive capabilities required of the user.
*/
public function map_meta_cap_for_seo_manager( $caps, $cap ) {
$user = wp_get_current_user();
// No multisite support.
if ( is_multisite() ) {
return $caps;
}
// User must be of role wpseo_manager.
if ( ! in_array( 'wpseo_manager', $user->roles, true ) ) {
return $caps;
}
// Remove manage_options cap requirement if requested cap is manage_privacy_options.
if ( $cap === 'manage_privacy_options' ) {
return array_diff( $caps, [ 'manage_options' ] );
}
return $caps;
}
}

View File

@@ -50,14 +50,6 @@ final class WPSEO_Admin_Asset_Dev_Server_Location implements WPSEO_Admin_Asset_L
return $this->get_default_url( $asset, $type );
}
$asset_manager = new WPSEO_Admin_Asset_Manager();
$flat_version = $asset_manager->flatten_version( WPSEO_VERSION );
$version_less_source = str_replace( '-' . $flat_version, '', $asset->get_src() );
if ( strpos( $version_less_source, 'select2' ) !== false ) {
return $this->get_default_url( $asset, $type );
}
$path = sprintf( 'js/dist/%s%s.js', $asset->get_src(), $asset->get_suffix() );
return trailingslashit( $this->url ) . $path;

View File

@@ -89,6 +89,10 @@ class WPSEO_Admin_Asset_Manager {
$script->get_version(),
$script->is_in_footer()
);
if ( in_array( 'wp-i18n', $script->get_deps(), true ) ) {
wp_set_script_translations( $this->prefix . $script->get_name(), 'wordpress-seo' );
}
}
/**
@@ -149,6 +153,17 @@ class WPSEO_Admin_Asset_Manager {
\wp_localize_script( $this->prefix . $handle, $object_name, $data );
}
/**
* Adds an inline script.
*
* @param string $handle The script handle.
* @param string $data The l10n data.
* @param string $position Optional. Whether to add the inline script before the handle or after.
*/
public function add_inline_script( $handle, $data, $position = 'after' ) {
\wp_add_inline_script( $this->prefix . $handle, $data, $position );
}
/**
* A list of styles that shouldn't be registered but are needed in other locations in the plugin.
*
@@ -215,51 +230,75 @@ class WPSEO_Admin_Asset_Manager {
* @return array The scripts that need to be registered.
*/
protected function scripts_to_be_registered() {
$flat_version = $this->flatten_version( WPSEO_VERSION );
$ext_length = ( strlen( $flat_version ) + 4 );
$header_scripts = [
'admin-global',
'block-editor',
'classic-editor',
'post-edit',
'help-scout-beacon',
'redirect-old-features-tab',
];
$additional_dependencies = [
'analysis-worker' => [ self::PREFIX . 'analysis-package' ],
'api-client' => [ 'wp-api' ],
'dashboard-widget' => [ self::PREFIX . 'api-client' ],
'elementor' => [ self::PREFIX . 'api-client' ],
'indexation' => [
'analysis-worker' => [ self::PREFIX . 'analysis-package' ],
'api-client' => [ 'wp-api' ],
'crawl-settings' => [ 'jquery' ],
'dashboard-widget' => [ self::PREFIX . 'api-client' ],
'wincher-dashboard-widget' => [ self::PREFIX . 'api-client' ],
'editor-modules' => [ 'jquery' ],
'elementor' => [
self::PREFIX . 'api-client',
self::PREFIX . 'externals-components',
self::PREFIX . 'externals-contexts',
self::PREFIX . 'externals-redux',
],
'indexation' => [
'jquery-ui-core',
'jquery-ui-progressbar',
],
'post-edit' => [
'first-time-configuration' => [
self::PREFIX . 'api-client',
self::PREFIX . 'externals-components',
self::PREFIX . 'externals-contexts',
self::PREFIX . 'externals-redux',
],
'integrations-page' => [
self::PREFIX . 'api-client',
self::PREFIX . 'externals-components',
self::PREFIX . 'externals-contexts',
self::PREFIX . 'externals-redux',
],
'post-edit' => [
self::PREFIX . 'api-client',
self::PREFIX . 'block-editor',
self::PREFIX . 'select2',
self::PREFIX . 'externals-components',
self::PREFIX . 'externals-contexts',
self::PREFIX . 'externals-redux',
],
'reindex-links' => [
'reindex-links' => [
'jquery-ui-core',
'jquery-ui-progressbar',
],
'settings' => [
'settings' => [
'jquery-ui-core',
'jquery-ui-progressbar',
self::PREFIX . 'api-client',
self::PREFIX . 'select2',
self::PREFIX . 'externals-components',
self::PREFIX . 'externals-contexts',
self::PREFIX . 'externals-redux',
],
'term-edit' => [
'term-edit' => [
self::PREFIX . 'api-client',
self::PREFIX . 'classic-editor',
self::PREFIX . 'select2',
self::PREFIX . 'externals-components',
self::PREFIX . 'externals-contexts',
self::PREFIX . 'externals-redux',
],
];
$plugin_scripts = $this->load_generated_asset_file(
[
'asset_file' => __DIR__ . '/../src/generated/assets/plugin.php',
'ext_length' => $ext_length,
'ext_length' => 3,
'additional_deps' => $additional_dependencies,
'header_scripts' => $header_scripts,
]
@@ -267,7 +306,7 @@ class WPSEO_Admin_Asset_Manager {
$external_scripts = $this->load_generated_asset_file(
[
'asset_file' => __DIR__ . '/../src/generated/assets/externals.php',
'ext_length' => $ext_length,
'ext_length' => 3,
'suffix' => '-package',
'base_dir' => 'externals/',
'additional_deps' => $additional_dependencies,
@@ -277,29 +316,42 @@ class WPSEO_Admin_Asset_Manager {
$language_scripts = $this->load_generated_asset_file(
[
'asset_file' => __DIR__ . '/../src/generated/assets/languages.php',
'ext_length' => $ext_length,
'ext_length' => 3,
'suffix' => '-language',
'base_dir' => 'languages/',
'additional_deps' => $additional_dependencies,
'header_scripts' => $header_scripts,
]
);
$select2_scripts = $this->load_select2_scripts();
$renamed_scripts = $this->load_renamed_scripts();
$scripts = array_merge(
$plugin_scripts,
$external_scripts,
$language_scripts,
$select2_scripts,
$renamed_scripts
);
$scripts['installation-success'] = [
'name' => 'installation-success',
'src' => 'installation-success.js',
'deps' => [
'wp-a11y',
'wp-dom-ready',
'wp-components',
'wp-element',
'wp-i18n',
self::PREFIX . 'yoast-components',
self::PREFIX . 'externals-components',
],
'version' => $scripts['installation-success']['version'],
];
$scripts['post-edit-classic'] = [
'name' => 'post-edit-classic',
'src' => $scripts['post-edit']['src'],
'deps' => array_map(
function( $dep ) {
static function( $dep ) {
if ( $dep === self::PREFIX . 'block-editor' ) {
return self::PREFIX . 'classic-editor';
}
@@ -308,6 +360,31 @@ class WPSEO_Admin_Asset_Manager {
$scripts['post-edit']['deps']
),
'in_footer' => ! in_array( 'post-edit-classic', $header_scripts, true ),
'version' => $scripts['post-edit']['version'],
];
$scripts['workouts'] = [
'name' => 'workouts',
'src' => 'workouts.js',
'deps' => [
'clipboard',
'lodash',
'wp-api-fetch',
'wp-a11y',
'wp-components',
'wp-compose',
'wp-data',
'wp-dom-ready',
'wp-element',
'wp-i18n',
self::PREFIX . 'externals-components',
self::PREFIX . 'externals-contexts',
self::PREFIX . 'externals-redux',
self::PREFIX . 'analysis',
self::PREFIX . 'react-select',
self::PREFIX . 'yoast-components',
],
'version' => $scripts['workouts']['version'],
];
// Add the current language to every script that requires the analysis package.
@@ -359,9 +436,9 @@ class WPSEO_Admin_Asset_Manager {
$scripts = [];
$assets = require $args['asset_file'];
foreach ( $assets as $file => $data ) {
$name = substr( $file, 0, -$args['ext_length'] );
$name = strtolower( preg_replace( '/([A-Z])/', '-$1', $name ) );
$name = $name . $args['suffix'];
$name = substr( $file, 0, -$args['ext_length'] );
$name = strtolower( preg_replace( '/([A-Z])/', '-$1', $name ) );
$name .= $args['suffix'];
$deps = $data['dependencies'];
if ( isset( $args['additional_deps'][ $name ] ) ) {
@@ -373,66 +450,13 @@ class WPSEO_Admin_Asset_Manager {
'src' => $args['base_dir'] . $file,
'deps' => $deps,
'in_footer' => ! in_array( $name, $args['header_scripts'], true ),
'version' => $data['version'],
];
}
return $scripts;
}
/**
* Loads the select2 scripts.
*
* @return array {
* The scripts to be registered.
*
* @type string $name The name of the asset.
* @type string $src The src of the asset.
* @type string[] $deps The dependenies of the asset.
* @type bool $in_footer Whether or not the asset should be in the footer.
* }
*/
protected function load_select2_scripts() {
$scripts = [];
$select2_language = 'en';
$user_locale = \get_user_locale();
$language = WPSEO_Language_Utils::get_language( $user_locale );
if ( file_exists( WPSEO_PATH . "js/dist/select2/i18n/{$user_locale}.js" ) ) {
$select2_language = $user_locale; // Chinese and some others use full locale.
}
elseif ( file_exists( WPSEO_PATH . "js/dist/select2/i18n/{$language}.js" ) ) {
$select2_language = $language;
}
$scripts['select2'] = [
'name' => 'select2',
'src' => false,
'deps' => [
self::PREFIX . 'select2-translations',
self::PREFIX . 'select2-core',
],
];
$scripts['select2-core'] = [
'name' => 'select2-core',
'src' => 'select2/select2.full.min.js',
'deps' => [
'jquery',
],
'version' => '4.0.3',
];
$scripts['select2-translations'] = [
'name' => 'select2-translations',
'src' => 'select2/i18n/' . $select2_language . '.js',
'deps' => [
'jquery',
self::PREFIX . 'select2-core',
],
'version' => '4.0.3',
];
return $scripts;
}
/**
* Loads the scripts that should be renamed for BC.
*
@@ -512,10 +536,6 @@ class WPSEO_Admin_Asset_Manager {
'name' => 'alert',
'src' => 'alerts-' . $flat_version,
],
[
'name' => 'badge',
'src' => 'badge-' . $flat_version,
],
[
'name' => 'edit-page',
'src' => 'edit-page-' . $flat_version,
@@ -528,11 +548,24 @@ class WPSEO_Admin_Asset_Manager {
'name' => 'metabox-css',
'src' => 'metabox-' . $flat_version,
'deps' => [
self::PREFIX . 'select2',
self::PREFIX . 'admin-css',
self::PREFIX . 'tailwind',
'wp-components',
],
],
[
'name' => 'ai-generator',
'src' => 'ai-generator-' . $flat_version,
'deps' => [
self::PREFIX . 'tailwind',
self::PREFIX . 'introductions',
],
],
[
'name' => 'introductions',
'src' => 'introductions-' . $flat_version,
'deps' => [ self::PREFIX . 'tailwind' ],
],
[
'name' => 'wp-dashboard',
'src' => 'dashboard-' . $flat_version,
@@ -552,21 +585,10 @@ class WPSEO_Admin_Asset_Manager {
'name' => 'primary-category',
'src' => 'metabox-primary-category-' . $flat_version,
],
[
'name' => 'select2',
'src' => 'select2/select2',
'suffix' => '.min',
'version' => '4.0.1',
'rtl' => false,
],
[
'name' => 'admin-global',
'src' => 'admin-global-' . $flat_version,
],
[
'name' => 'yoast-components',
'src' => 'yoast-components-' . $flat_version,
],
[
'name' => 'extensions',
'src' => 'yoast-extensions-' . $flat_version,
@@ -578,13 +600,6 @@ class WPSEO_Admin_Asset_Manager {
'name' => 'filter-explanation',
'src' => 'filter-explanation-' . $flat_version,
],
[
'name' => 'search-appearance',
'src' => 'search-appearance-' . $flat_version,
'deps' => [
self::PREFIX . 'monorepo',
],
],
[
'name' => 'monorepo',
'src' => 'monorepo-' . $flat_version,
@@ -594,14 +609,50 @@ class WPSEO_Admin_Asset_Manager {
'src' => 'structured-data-blocks-' . $flat_version,
'deps' => [ 'wp-edit-blocks' ],
],
[
'name' => 'schema-blocks',
'src' => 'schema-blocks-' . $flat_version,
],
[
'name' => 'elementor',
'src' => 'elementor-' . $flat_version,
],
[
'name' => 'tailwind',
'src' => 'tailwind-' . $flat_version,
],
[
'name' => 'new-settings',
'src' => 'new-settings-' . $flat_version,
'deps' => [ self::PREFIX . 'tailwind' ],
],
[
'name' => 'black-friday-banner',
'src' => 'black-friday-banner-' . $flat_version,
'deps' => [ self::PREFIX . 'tailwind' ],
],
[
'name' => 'academy',
'src' => 'academy-' . $flat_version,
'deps' => [ self::PREFIX . 'tailwind' ],
],
[
'name' => 'support',
'src' => 'support-' . $flat_version,
'deps' => [ self::PREFIX . 'tailwind' ],
],
[
'name' => 'workouts',
'src' => 'workouts-' . $flat_version,
'deps' => [
self::PREFIX . 'monorepo',
],
],
[
'name' => 'first-time-configuration',
'src' => 'first-time-configuration-' . $flat_version,
'deps' => [ self::PREFIX . 'tailwind' ],
],
[
'name' => 'inside-editor',
'src' => 'inside-editor-' . $flat_version,
],
];
}

View File

@@ -20,15 +20,15 @@ final class WPSEO_Admin_Asset_SEO_Location implements WPSEO_Admin_Asset_Location
/**
* Whether or not to add the file suffix to the asset.
*
* @var boolean
* @var bool
*/
protected $add_suffix = true;
/**
* The plugin file to base the asset location upon.
*
* @param string $plugin_file The plugin file string.
* @param boolean $add_suffix Optional. Whether or not a file suffix should be added.
* @param string $plugin_file The plugin file string.
* @param bool $add_suffix Optional. Whether or not a file suffix should be added.
*/
public function __construct( $plugin_file, $add_suffix = true ) {
$this->plugin_file = $plugin_file;
@@ -68,7 +68,7 @@ final class WPSEO_Admin_Asset_SEO_Location implements WPSEO_Admin_Asset_Location
case WPSEO_Admin_Asset::TYPE_JS:
$relative_path = 'js/dist/' . $asset->get_src();
if ( $this->add_suffix ) {
$relative_path = $relative_path . $asset->get_suffix() . '.js';
$relative_path .= $asset->get_suffix() . '.js';
}
break;

View File

@@ -27,7 +27,7 @@ class WPSEO_Admin_Editor_Specific_Replace_Vars {
// Taxonomies.
'category' => [ 'term_title', 'term_description', 'category_description', 'parent_title', 'term_hierarchy' ],
'post_tag' => [ 'term_title', 'term_description', 'tag_description' ],
'post_format' => [],
'post_format' => [ 'term_title' ],
// Custom taxonomy.
'term-in-custom-taxonomy' => [ 'term_title', 'term_description', 'category_description', 'parent_title', 'term_hierarchy' ],

View File

@@ -35,34 +35,14 @@ class WPSEO_Admin_Init {
$this->asset_manager = new WPSEO_Admin_Asset_Manager();
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_dismissible' ] );
add_action( 'admin_init', [ $this, 'yoast_plugin_suggestions_notification' ], 15 );
add_action( 'admin_init', [ $this, 'unsupported_php_notice' ], 15 );
add_action( 'admin_init', [ $this, 'remove_translations_notification' ], 15 );
add_action( 'admin_init', [ $this->asset_manager, 'register_assets' ] );
add_action( 'admin_init', [ $this, 'show_hook_deprecation_warnings' ] );
add_action( 'admin_init', [ 'WPSEO_Plugin_Conflict', 'hook_check_for_plugin_conflicts' ] );
add_action( 'admin_notices', [ $this, 'permalink_settings_notice' ] );
add_action( 'post_submitbox_misc_actions', [ $this, 'add_publish_box_section' ] );
/*
* The `admin_notices` hook fires on single site admin pages vs.
* `network_admin_notices` which fires on multisite admin pages and
* `user_admin_notices` which fires on multisite user admin pagss.
*/
add_action( 'admin_notices', [ $this, 'search_engines_discouraged_notice' ] );
$health_checks = [
new WPSEO_Health_Check_Page_Comments(),
new WPSEO_Health_Check_Ryte(),
new WPSEO_Health_Check_Default_Tagline(),
new WPSEO_Health_Check_Postname_Permalink(),
new WPSEO_Health_Check_Curl_Version(),
new WPSEO_Health_Check_Link_Table_Not_Accessible(),
];
foreach ( $health_checks as $health_check ) {
$health_check->register_test();
}
$this->load_meta_boxes();
$this->load_taxonomy_class();
$this->load_admin_page_class();
@@ -79,56 +59,13 @@ class WPSEO_Admin_Init {
}
/**
* Determines whether a suggested plugins notification needs to be displayed.
* Removes any notification for incomplete translations.
*
* @return void
*/
public function yoast_plugin_suggestions_notification() {
$checker = new WPSEO_Plugin_Availability();
public function remove_translations_notification() {
$notification_center = Yoast_Notification_Center::get();
// Get all Yoast plugins that have dependencies.
$plugins = $checker->get_plugins_with_dependencies();
foreach ( $plugins as $plugin_name => $plugin ) {
$dependency_names = $checker->get_dependency_names( $plugin );
$notification = $this->get_yoast_seo_suggested_plugins_notification( $plugin_name, $plugin, $dependency_names[0] );
if ( $checker->dependencies_are_satisfied( $plugin ) && ! $checker->is_installed( $plugin ) ) {
$notification_center->add_notification( $notification );
continue;
}
$notification_center->remove_notification( $notification );
}
}
/**
* Build Yoast SEO suggested plugins notification.
*
* @param string $name The plugin name to use for the unique ID.
* @param array $plugin The plugin to retrieve the data from.
* @param string $dependency_name The name of the dependency.
*
* @return Yoast_Notification The notification containing the suggested plugin.
*/
private function get_yoast_seo_suggested_plugins_notification( $name, $plugin, $dependency_name ) {
$info_message = sprintf(
/* translators: %1$s expands to Yoast SEO, %2$s expands to the plugin version, %3$s expands to the plugin name */
__( '%1$s and %2$s can work together a lot better by adding a helper plugin. Please install %3$s to make your life better.', 'wordpress-seo' ),
'Yoast SEO',
$dependency_name,
sprintf( '<a href="%s">%s</a>', $plugin['url'], $plugin['title'] )
);
return new Yoast_Notification(
$info_message,
[
'id' => 'wpseo-suggested-plugin-' . $name,
'type' => Yoast_Notification::WARNING,
]
);
$notification_center->remove_notification_by_id( 'i18nModuleTranslationAssistance' );
}
/**
@@ -170,17 +107,26 @@ class WPSEO_Admin_Init {
* @return bool
*/
private function on_wpseo_admin_page() {
return $this->pagenow === 'admin.php' && strpos( filter_input( INPUT_GET, 'page' ), 'wpseo' ) === 0;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( ! isset( $_GET['page'] ) || ! is_string( $_GET['page'] ) ) {
return false;
}
if ( $this->pagenow !== 'admin.php' ) {
return false;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$current_page = sanitize_text_field( wp_unslash( $_GET['page'] ) );
return strpos( $current_page, 'wpseo' ) === 0;
}
/**
* Determine whether we should load the meta box class and if so, load it.
* Whether we should load the meta box classes.
*
* @return bool true if we should load the meta box classes, false otherwise.
*/
private function load_meta_boxes() {
$is_editor = WPSEO_Metabox::is_post_overview( $this->pagenow ) || WPSEO_Metabox::is_post_edit( $this->pagenow );
$is_inline_save = filter_input( INPUT_POST, 'action' ) === 'inline-save';
private function should_load_meta_boxes() {
/**
* Filter: 'wpseo_always_register_metaboxes_on_admin' - Allow developers to change whether
* the WPSEO metaboxes are only registered on the typical pages (lean loading) or always
@@ -188,8 +134,28 @@ class WPSEO_Admin_Init {
*
* @api bool Whether to always register the metaboxes or not. Defaults to false.
*/
if ( $is_editor || $is_inline_save || apply_filters( 'wpseo_always_register_metaboxes_on_admin', false )
) {
if ( apply_filters( 'wpseo_always_register_metaboxes_on_admin', false ) ) {
return true;
}
// If we are in a post editor.
if ( WPSEO_Metabox::is_post_overview( $this->pagenow ) || WPSEO_Metabox::is_post_edit( $this->pagenow ) ) {
return true;
}
// If we are doing an inline save.
if ( check_ajax_referer( 'inlineeditnonce', '_inline_edit', false ) && isset( $_POST['action'] ) && sanitize_text_field( wp_unslash( $_POST['action'] ) ) === 'inline-save' ) {
return true;
}
return false;
}
/**
* Determine whether we should load the meta box class and if so, load it.
*/
private function load_meta_boxes() {
if ( $this->should_load_meta_boxes() ) {
$GLOBALS['wpseo_metabox'] = new WPSEO_Metabox();
$GLOBALS['wpseo_meta_columns'] = new WPSEO_Meta_Columns();
}
@@ -231,9 +197,16 @@ class WPSEO_Admin_Init {
// For backwards compatabilty, this still needs a global, for now...
$GLOBALS['wpseo_admin_pages'] = new WPSEO_Admin_Pages();
// Only register the yoast i18n when the page is a Yoast SEO page.
if ( WPSEO_Utils::is_yoast_seo_free_page( filter_input( INPUT_GET, 'page' ) ) ) {
$this->register_i18n_promo_class();
$page = null;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['page'] ) && is_string( $_GET['page'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$page = sanitize_text_field( wp_unslash( $_GET['page'] ) );
}
// Only renders Yoast SEO Premium upsells when the page is a Yoast SEO page.
if ( $page !== null && WPSEO_Utils::is_yoast_seo_free_page( $page ) ) {
$this->register_premium_upsell_admin_block();
}
}
@@ -259,47 +232,6 @@ class WPSEO_Admin_Init {
}
}
/**
* Registers the promotion class for our GlotPress instance, then creates a notification with the i18n promo.
*
* @link https://github.com/Yoast/i18n-module
*/
private function register_i18n_promo_class() {
// BC, because an older version of the i18n-module didn't have this class.
$i18n_module = new Yoast_I18n_WordPressOrg_v3(
[
'textdomain' => 'wordpress-seo',
'plugin_name' => 'Yoast SEO',
'hook' => 'wpseo_admin_promo_footer',
],
false
);
$message = $i18n_module->get_promo_message();
if ( $message !== '' ) {
$message .= $i18n_module->get_dismiss_i18n_message_button();
}
$notification_center = Yoast_Notification_Center::get();
$notification = new Yoast_Notification(
$message,
[
'type' => Yoast_Notification::WARNING,
'id' => 'i18nModuleTranslationAssistance',
]
);
if ( $message ) {
$notification_center->add_notification( $notification );
return;
}
$notification_center->remove_notification( $notification );
}
/**
* See if we should start our XML Sitemaps Admin class.
*/
@@ -309,15 +241,6 @@ class WPSEO_Admin_Init {
}
}
/**
* Checks whether search engines are discouraged from indexing the site.
*
* @return bool Whether search engines are discouraged from indexing the site.
*/
private function are_search_engines_discouraged() {
return (string) get_option( 'blog_public' ) === '0';
}
/**
* Shows deprecation warnings to the user if a plugin has registered a filter we have deprecated.
*/
@@ -415,53 +338,6 @@ class WPSEO_Admin_Init {
}
}
/**
* Determines whether and where the "search engines discouraged" admin notice should be displayed.
*
* @return bool Whether the "search engines discouraged" admin notice should be displayed.
*/
private function should_display_search_engines_discouraged_notice() {
$discouraged_pages = [
'index.php',
'plugins.php',
'update-core.php',
];
return (
$this->are_search_engines_discouraged()
&& WPSEO_Capability_Utils::current_user_can( 'manage_options' )
&& WPSEO_Options::get( 'ignore_search_engines_discouraged_notice', false ) === false
&& (
$this->on_wpseo_admin_page()
|| in_array( $this->pagenow, $discouraged_pages, true )
)
);
}
/**
* Displays an admin notice when WordPress is set to discourage search engines from indexing the site.
*
* @return void
*/
public function search_engines_discouraged_notice() {
if ( ! $this->should_display_search_engines_discouraged_notice() ) {
return;
}
printf(
'<div id="robotsmessage" class="notice notice-error"><p><strong>%1$s</strong> %2$s <button type="button" id="robotsmessage-dismiss-button" class="button-link hide-if-no-js" data-nonce="%3$s">%4$s</button></p></div>',
esc_html__( 'Huge SEO Issue: You\'re blocking access to robots.', 'wordpress-seo' ),
sprintf(
/* translators: 1: Link start tag to the WordPress Reading Settings page, 2: Link closing tag. */
esc_html__( 'If you want search engines to show this site in their results, you must %1$sgo to your Reading Settings%2$s and uncheck the box for Search Engine Visibility.', 'wordpress-seo' ),
'<a href="' . esc_url( admin_url( 'options-reading.php' ) ) . '">',
'</a>'
),
esc_js( wp_create_nonce( 'wpseo-ignore' ) ),
esc_html__( 'I don\'t want this site to show in the search results.', 'wordpress-seo' )
);
}
/**
* Adds a custom Yoast section within the Classic Editor publish box.
*
@@ -482,68 +358,4 @@ class WPSEO_Admin_Init {
do_action( 'wpseo_publishbox_misc_actions', $post );
}
}
/* ********************* DEPRECATED METHODS ********************* */
/**
* Notify about the default tagline if the user hasn't changed it.
*
* @deprecated 13.2
* @codeCoverageIgnore
*/
public function tagline_notice() {
_deprecated_function( __METHOD__, 'WPSEO 13.2' );
}
/**
* Returns whether or not the site has the default tagline.
*
* @deprecated 13.2
* @codeCoverageIgnore
*
* @return bool
*/
public function has_default_tagline() {
_deprecated_function( __METHOD__, 'WPSEO 13.2' );
$blog_description = get_bloginfo( 'description' );
$default_blog_description = 'Just another WordPress site';
// We are using the WordPress internal translation.
$translated_blog_description = __( 'Just another WordPress site', 'default' );
return $translated_blog_description === $blog_description || $default_blog_description === $blog_description;
}
/**
* Shows an alert when the permalink doesn't contain %postname%.
*
* @deprecated 13.2
* @codeCoverageIgnore
*/
public function permalink_notice() {
_deprecated_function( __METHOD__, 'WPSEO 13.2' );
}
/**
* Add an alert if the blog is not publicly visible.
*
* @deprecated 14.1
* @codeCoverageIgnore
*/
public function blog_public_notice() {
_deprecated_function( __METHOD__, 'WPSEO 14.1' );
}
/**
* Handles the notifiers for the dashboard page.
*
* @deprecated 14.1
* @codeCoverageIgnore
*
* @return void
*/
public function handle_notifications() {
_deprecated_function( __METHOD__, 'WPSEO 14.1' );
}
}

View File

@@ -30,7 +30,7 @@ class WPSEO_Admin_Recommended_Replace_Vars {
'post_format' => [ 'sitename', 'term_title', 'sep', 'page' ],
// Custom taxonomy.
'term-in-custom-taxomomy' => [ 'sitename', 'term_title', 'sep', 'term_hierarchy' ],
'term-in-custom-taxonomy' => [ 'sitename', 'term_title', 'sep', 'term_hierarchy' ],
// Settings - archive pages.
'author_archive' => [ 'sitename', 'title', 'sep', 'page' ],
@@ -55,7 +55,7 @@ class WPSEO_Admin_Recommended_Replace_Vars {
return $taxonomy;
}
return 'term-in-custom-taxomomy';
return 'term-in-custom-taxonomy';
}
/**

View File

@@ -38,21 +38,6 @@ class WPSEO_Admin_User_Profile {
}
}
/**
* Filter POST variables.
*
* @param string $var_name Name of the variable to filter.
*
* @return mixed
*/
private function filter_input_post( $var_name ) {
$val = filter_input( INPUT_POST, $var_name );
if ( $val ) {
return WPSEO_Utils::sanitize_text_field( $val );
}
return '';
}
/**
* Updates the user metas that (might) have been set on the user profile page.
*
@@ -61,19 +46,23 @@ class WPSEO_Admin_User_Profile {
public function process_user_option_update( $user_id ) {
update_user_meta( $user_id, '_yoast_wpseo_profile_updated', time() );
$nonce_value = $this->filter_input_post( 'wpseo_nonce' );
if ( empty( $nonce_value ) ) { // Submit from alternate forms.
if ( ! check_admin_referer( 'wpseo_user_profile_update', 'wpseo_nonce' ) ) {
return;
}
check_admin_referer( 'wpseo_user_profile_update', 'wpseo_nonce' );
$wpseo_author_title = isset( $_POST['wpseo_author_title'] ) ? sanitize_text_field( wp_unslash( $_POST['wpseo_author_title'] ) ) : '';
$wpseo_author_metadesc = isset( $_POST['wpseo_author_metadesc'] ) ? sanitize_text_field( wp_unslash( $_POST['wpseo_author_metadesc'] ) ) : '';
$wpseo_noindex_author = isset( $_POST['wpseo_noindex_author'] ) ? sanitize_text_field( wp_unslash( $_POST['wpseo_noindex_author'] ) ) : '';
$wpseo_content_analysis_disable = isset( $_POST['wpseo_content_analysis_disable'] ) ? sanitize_text_field( wp_unslash( $_POST['wpseo_content_analysis_disable'] ) ) : '';
$wpseo_keyword_analysis_disable = isset( $_POST['wpseo_keyword_analysis_disable'] ) ? sanitize_text_field( wp_unslash( $_POST['wpseo_keyword_analysis_disable'] ) ) : '';
$wpseo_inclusive_language_analysis_disable = isset( $_POST['wpseo_inclusive_language_analysis_disable'] ) ? sanitize_text_field( wp_unslash( $_POST['wpseo_inclusive_language_analysis_disable'] ) ) : '';
update_user_meta( $user_id, 'wpseo_title', $this->filter_input_post( 'wpseo_author_title' ) );
update_user_meta( $user_id, 'wpseo_metadesc', $this->filter_input_post( 'wpseo_author_metadesc' ) );
update_user_meta( $user_id, 'wpseo_noindex_author', $this->filter_input_post( 'wpseo_noindex_author' ) );
update_user_meta( $user_id, 'wpseo_content_analysis_disable', $this->filter_input_post( 'wpseo_content_analysis_disable' ) );
update_user_meta( $user_id, 'wpseo_keyword_analysis_disable', $this->filter_input_post( 'wpseo_keyword_analysis_disable' ) );
update_user_meta( $user_id, 'wpseo_title', $wpseo_author_title );
update_user_meta( $user_id, 'wpseo_metadesc', $wpseo_author_metadesc );
update_user_meta( $user_id, 'wpseo_noindex_author', $wpseo_noindex_author );
update_user_meta( $user_id, 'wpseo_content_analysis_disable', $wpseo_content_analysis_disable );
update_user_meta( $user_id, 'wpseo_keyword_analysis_disable', $wpseo_keyword_analysis_disable );
update_user_meta( $user_id, 'wpseo_inclusive_language_analysis_disable', $wpseo_inclusive_language_analysis_disable );
}
/**

View File

@@ -75,6 +75,7 @@ class WPSEO_Admin_Utils {
public static function get_new_tab_message() {
return sprintf(
'<span class="screen-reader-text">%s</span>',
/* translators: Hidden accessibility text. */
esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' )
);
}

View File

@@ -5,6 +5,8 @@
* @package WPSEO\Admin
*/
use Yoast\WP\SEO\Integrations\Settings_Integration;
/**
* Class that holds most of the admin functionality for Yoast SEO.
*/
@@ -75,12 +77,6 @@ class WPSEO_Admin {
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
}
if ( WPSEO_Utils::is_api_available() ) {
$configuration = new WPSEO_Configuration_Page();
$configuration->set_hooks();
$configuration->catch_configuration_request();
}
$this->set_upsell_notice();
$this->initialize_cornerstone_content();
@@ -90,7 +86,8 @@ class WPSEO_Admin {
}
$this->admin_features = [
'dashboard_widget' => new Yoast_Dashboard_Widget(),
'dashboard_widget' => new Yoast_Dashboard_Widget(),
'wincher_dashboard_widget' => new Wincher_Dashboard_Widget(),
];
if ( WPSEO_Metabox::is_post_overview( $pagenow ) || WPSEO_Metabox::is_post_edit( $pagenow ) ) {
@@ -100,7 +97,6 @@ class WPSEO_Admin {
$integrations[] = new WPSEO_Yoast_Columns();
$integrations[] = new WPSEO_Statistic_Integration();
$integrations[] = new WPSEO_Capability_Manager_Integration( WPSEO_Capability_Manager_Factory::get() );
$integrations[] = new WPSEO_Admin_Media_Purge_Notification();
$integrations[] = new WPSEO_Admin_Gutenberg_Compatibility_Notification();
$integrations[] = new WPSEO_Expose_Shortlinks();
$integrations[] = new WPSEO_MyYoast_Proxy();
@@ -144,7 +140,9 @@ class WPSEO_Admin {
* Register assets needed on admin pages.
*/
public function enqueue_assets() {
if ( filter_input( INPUT_GET, 'page' ) === 'wpseo_licenses' ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form data.
$page = isset( $_GET['page'] ) && is_string( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
if ( $page === 'wpseo_licenses' ) {
$asset_manager = new WPSEO_Admin_Asset_Manager();
$asset_manager->enqueue_style( 'extensions' );
}
@@ -171,7 +169,7 @@ class WPSEO_Admin {
// phpcs:ignore WordPress.Security -- The variable is only used in strpos and thus safe to not unslash or sanitize.
$option_page = ! empty( $_POST['option_page'] ) ? $_POST['option_page'] : '';
if ( strpos( $option_page, 'yoast_wpseo' ) === 0 ) {
if ( strpos( $option_page, 'yoast_wpseo' ) === 0 || strpos( $option_page, Settings_Integration::PAGE ) === 0 ) {
add_filter( 'option_page_capability_' . $option_page, [ $this, 'get_manage_options_cap' ] );
}
}
@@ -216,6 +214,8 @@ class WPSEO_Admin {
* @return array
*/
public function add_action_link( $links, $file ) {
$first_time_configuration_notice_helper = \YoastSEO()->helpers->first_time_configuration_notice;
if ( $file === WPSEO_BASENAME && WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) {
if ( is_network_admin() ) {
$settings_url = network_admin_url( 'admin.php?page=' . self::PAGE_IDENTIFIER );
@@ -231,6 +231,14 @@ class WPSEO_Admin {
$faq_link = '<a href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yc' ) ) . '" target="_blank">' . __( 'FAQ', 'wordpress-seo' ) . '</a>';
array_unshift( $links, $faq_link );
if ( $first_time_configuration_notice_helper->first_time_configuration_not_finished() && ! is_network_admin() ) {
$configuration_title = ( ! $first_time_configuration_notice_helper->should_show_alternate_message() ) ? 'first-time configuration' : 'SEO configuration';
/* translators: CTA to finish the first time configuration. %s: Either first-time SEO configuration or SEO configuration. */
$message = sprintf( __( 'Finish your %s', 'wordpress-seo' ), $configuration_title );
$ftc_link = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_dashboard#top#first-time-configuration' ) ) . '" target="_blank">' . $message . '</a>';
array_unshift( $links, $ftc_link );
}
$addon_manager = new WPSEO_Addon_Manager();
if ( YoastSEO()->helpers->product->is_premium() ) {
@@ -256,7 +264,7 @@ class WPSEO_Admin {
}
// Add link to premium landing page.
$premium_link = '<a style="font-weight: bold;" href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yb' ) ) . '" target="_blank">' . __( 'Get Premium', 'wordpress-seo' ) . '</a>';
$premium_link = '<a style="font-weight: bold;" href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yb' ) ) . '" target="_blank" data-action="load-nfd-ctb" data-ctb-id="f6a84663-465f-4cb5-8ba5-f7a6d72224b2">' . __( 'Get Premium', 'wordpress-seo' ) . '</a>';
array_unshift( $links, $premium_link );
return $links;
@@ -307,7 +315,9 @@ class WPSEO_Admin {
* Log the updated timestamp for user profiles when theme is changed.
*/
public function switch_theme() {
$users = get_users( [ 'who' => 'authors' ] );
$users = get_users( [ 'capability' => [ 'edit_posts' ] ] );
if ( is_array( $users ) && $users !== [] ) {
foreach ( $users as $user ) {
update_user_meta( $user->ID, '_yoast_wpseo_profile_updated', time() );
@@ -321,18 +331,22 @@ class WPSEO_Admin {
* @return array
*/
private function localize_admin_global_script() {
return [
'isRtl' => is_rtl(),
'variable_warning' => sprintf(
return array_merge(
[
'isRtl' => is_rtl(),
'variable_warning' => sprintf(
/* translators: %1$s: '%%term_title%%' variable used in titles and meta's template that's not compatible with the given template, %2$s: expands to 'HelpScout beacon' */
__( 'Warning: the variable %1$s cannot be used in this template. See the %2$s for more info.', 'wordpress-seo' ),
'<code>%s</code>',
'HelpScout beacon'
),
/* translators: %s: expends to Yoast SEO */
'help_video_iframe_title' => sprintf( __( '%s video tutorial', 'wordpress-seo' ), 'Yoast SEO' ),
'scrollable_table_hint' => __( 'Scroll to see the table content.', 'wordpress-seo' ),
];
__( 'Warning: the variable %1$s cannot be used in this template. See the %2$s for more info.', 'wordpress-seo' ),
'<code>%s</code>',
'HelpScout beacon'
),
/* translators: %s: expends to Yoast SEO */
'help_video_iframe_title' => sprintf( __( '%s video tutorial', 'wordpress-seo' ), 'Yoast SEO' ),
'scrollable_table_hint' => __( 'Scroll to see the table content.', 'wordpress-seo' ),
'wincher_is_logged_in' => WPSEO_Options::get( 'wincher_integration_active', true ) ? YoastSEO()->helpers->wincher->login_status() : false,
],
YoastSEO()->helpers->wincher->get_admin_global_links()
);
}
/**

View File

@@ -188,12 +188,17 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
}
/**
* Will show the navigation for the table like pagenavigation and pagefilter.
* Will show the navigation for the table like page navigation and page filter.
*
* @param string $which Table nav location (such as top).
*/
public function display_tablenav( $which ) {
$post_status = sanitize_text_field( filter_input( INPUT_GET, 'post_status' ) );
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$post_status = isset( $_GET['post_status'] ) && is_string( $_GET['post_status'] ) ? sanitize_text_field( wp_unslash( $_GET['post_status'] ) ) : '';
$order_by = isset( $_GET['orderby'] ) && is_string( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : '';
$order = isset( $_GET['order'] ) && is_string( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : '';
$post_type_filter = isset( $_GET['post_type_filter'] ) && is_string( $_GET['post_type_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type_filter'] ) ) : '';
// phpcs:enable WordPress.Security.NonceVerification.Recommended;
?>
<div class="tablenav <?php echo esc_attr( $which ); ?>">
@@ -204,11 +209,11 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
<input type="hidden" name="tool" value="bulk-editor"/>
<input type="hidden" name="type" value="<?php echo esc_attr( $this->page_type ); ?>"/>
<input type="hidden" name="orderby"
value="<?php echo esc_attr( filter_input( INPUT_GET, 'orderby' ) ); ?>"/>
value="<?php echo esc_attr( $order_by ); ?>"/>
<input type="hidden" name="order"
value="<?php echo esc_attr( filter_input( INPUT_GET, 'order' ) ); ?>"/>
value="<?php echo esc_attr( $order ); ?>"/>
<input type="hidden" name="post_type_filter"
value="<?php echo esc_attr( filter_input( INPUT_GET, 'post_type_filter' ) ); ?>"/>
value="<?php echo esc_attr( $post_type_filter ); ?>"/>
<?php if ( ! empty( $post_status ) ) { ?>
<input type="hidden" name="post_status" value="<?php echo esc_attr( $post_status ); ?>"/>
<?php } ?>
@@ -268,21 +273,20 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
$status_links = [];
$states = get_post_stati( [ 'show_in_admin_all_list' => true ] );
$states = esc_sql( $states );
$all_states = "'" . implode( "', '", $states ) . "'";
$states = get_post_stati( [ 'show_in_admin_all_list' => true ] );
$subquery = $this->get_base_subquery();
$total_posts = $wpdb->get_var(
"
SELECT COUNT(ID) FROM {$subquery}
WHERE post_status IN ({$all_states})
"
$wpdb->prepare(
"SELECT COUNT(ID) FROM {$subquery}
WHERE post_status IN (" .
implode( ', ', array_fill( 0, count( $states ), '%s' ) ) .
')',
$states
)
);
$post_status = filter_input( INPUT_GET, 'post_status' );
$post_status = isset( $_GET['post_status'] ) && is_string( $_GET['post_status'] ) ? sanitize_text_field( wp_unslash( $_GET['post_status'] ) ) : '';
$current_link_attributes = empty( $post_status ) ? ' class="current" aria-current="page"' : '';
$localized_text = sprintf(
/* translators: %s expands to the number of posts in localized format. */
@@ -323,10 +327,9 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
unset( $post_stati, $status, $status_name, $total, $current_link_attributes );
$trashed_posts = $wpdb->get_var(
"SELECT COUNT(ID) FROM {$subquery}
WHERE post_status IN ('trash')
"
SELECT COUNT(ID) FROM {$subquery}
WHERE post_status IN ('trash')
"
);
$current_link_attributes = '';
@@ -372,21 +375,21 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
$states = get_post_stati( [ 'show_in_admin_all_list' => true ] );
$states['trash'] = 'trash';
$states = esc_sql( $states );
$all_states = "'" . implode( "', '", $states ) . "'";
$subquery = $this->get_base_subquery();
$post_types = $wpdb->get_results(
"
SELECT DISTINCT post_type FROM {$subquery}
WHERE post_status IN ({$all_states})
ORDER BY 'post_type' ASC
"
$wpdb->prepare(
"SELECT DISTINCT post_type FROM {$subquery}
WHERE post_status IN (" .
implode( ', ', array_fill( 0, count( $states ), '%s' ) ) .
') ORDER BY post_type ASC',
$states
)
);
$post_type_filter = filter_input( INPUT_GET, 'post_type_filter' );
$selected = ( ! empty( $post_type_filter ) ) ? sanitize_text_field( $post_type_filter ) : '-1';
$post_type_filter = isset( $_GET['post_type_filter'] ) && is_string( $_GET['post_type_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type_filter'] ) ) : '';
$selected = ( ! empty( $post_type_filter ) ) ? $post_type_filter : '-1';
$options = '<option value="-1">' . esc_html__( 'Show All Content Types', 'wordpress-seo' ) . '</option>';
@@ -405,6 +408,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
printf(
'<label for="%1$s" class="screen-reader-text">%2$s</label>',
esc_attr( 'post-type-filter-' . $instance_type ),
/* translators: Hidden accessibility text. */
esc_html__( 'Filter by content type', 'wordpress-seo' )
);
printf(
@@ -533,15 +537,13 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
*/
protected function count_items( $subquery, $all_states, $post_type_clause ) {
global $wpdb;
$total_items = $wpdb->get_var(
"
SELECT COUNT(ID)
FROM {$subquery}
WHERE post_status IN ({$all_states}) $post_type_clause
"
);
return $total_items;
return (int) $wpdb->get_var(
"SELECT COUNT(ID) FROM {$subquery}
WHERE post_status IN ({$all_states})
{$post_type_clause}
"
);
}
/**
@@ -551,12 +553,11 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
*/
protected function get_post_type_clause() {
// Filter Block.
$post_types = null;
$post_type_clause = '';
$post_type_filter = filter_input( INPUT_GET, 'post_type_filter' );
$post_type_filter = isset( $_GET['post_type_filter'] ) && is_string( $_GET['post_type_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type_filter'] ) ) : '';
if ( ! empty( $post_type_filter ) && get_post_type_object( sanitize_text_field( $post_type_filter ) ) ) {
$post_types = esc_sql( sanitize_text_field( $post_type_filter ) );
if ( ! empty( $post_type_filter ) && get_post_type_object( $post_type_filter ) ) {
$post_types = esc_sql( $post_type_filter );
$post_type_clause = "AND post_type IN ('{$post_types}')";
}
@@ -571,12 +572,18 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
* @param int $total_items Total items counts.
*/
protected function set_pagination( $total_items ) {
// Calculate items per page.
$per_page = $this->get_items_per_page( 'wpseo_posts_per_page', 10 );
$paged = esc_sql( sanitize_text_field( filter_input( INPUT_GET, 'paged' ) ) );
$paged = isset( $_GET['paged'] ) && is_string( $_GET['paged'] ) ? esc_sql( sanitize_text_field( wp_unslash( $_GET['paged'] ) ) ) : '';
if ( empty( $paged ) || ! is_numeric( $paged ) || $paged <= 0 ) {
if ( empty( $paged ) || ! is_numeric( $paged ) ) {
$paged = 1;
}
else {
$paged = (int) $paged;
}
if ( $paged <= 0 ) {
$paged = 1;
}
@@ -608,19 +615,19 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
*/
protected function parse_item_query( $subquery, $all_states, $post_type_clause ) {
// Order By block.
$orderby = filter_input( INPUT_GET, 'orderby' );
$orderby = isset( $_GET['orderby'] ) && is_string( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : '';
$orderby = ! empty( $orderby ) ? esc_sql( sanitize_text_field( $orderby ) ) : 'post_title';
$orderby = ! empty( $orderby ) ? esc_sql( $orderby ) : 'post_title';
$orderby = $this->sanitize_orderby( $orderby );
// Order clause.
$order = filter_input( INPUT_GET, 'order' );
$order = ! empty( $order ) ? esc_sql( strtoupper( sanitize_text_field( $order ) ) ) : 'ASC';
$order = isset( $_GET['order'] ) && is_string( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : '';
$order = ! empty( $order ) ? esc_sql( strtoupper( $order ) ) : 'ASC';
$order = $this->sanitize_order( $order );
// Get all needed results.
$query = "
SELECT ID, post_title, post_type, post_status, post_modified, post_date
SELECT ID, post_title, post_type, post_status, post_modified, post_date
FROM {$subquery}
WHERE post_status IN ({$all_states}) $post_type_clause
ORDER BY {$orderby} {$order}
@@ -691,6 +698,8 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
* @return string
*/
protected function get_all_states() {
global $wpdb;
$states = get_post_stati( [ 'show_in_admin_all_list' => true ] );
$states['trash'] = 'trash';
@@ -705,10 +714,10 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
}
}
$states = esc_sql( $states );
$all_states = "'" . implode( "', '", $states ) . "'";
return $all_states;
return $wpdb->prepare(
implode( ', ', array_fill( 0, count( $states ), '%s' ) ),
$states
);
}
/**
@@ -722,9 +731,9 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
if ( ( is_array( $records ) && $records !== [] ) && ( is_array( $columns ) && $columns !== [] ) ) {
foreach ( $records as $rec ) {
foreach ( $records as $record ) {
echo '<tr id="', esc_attr( 'record_' . $rec->ID ), '">';
echo '<tr id="', esc_attr( 'record_' . $record->ID ), '">';
foreach ( $columns as $column_name => $column_display_name ) {
@@ -735,10 +744,10 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
$attributes = $this->column_attributes( $column_name, $hidden, $classes, $column_display_name );
$column_value = $this->parse_column( $column_name, $rec );
$column_value = $this->parse_column( $column_name, $record );
if ( method_exists( $this, 'parse_page_specific_column' ) && empty( $column_value ) ) {
$column_value = $this->parse_page_specific_column( $column_name, $rec, $attributes );
$column_value = $this->parse_page_specific_column( $column_name, $record, $attributes );
}
if ( ! empty( $column_value ) ) {
@@ -801,7 +810,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
$actions['edit'] = sprintf(
'<a href="%s" aria-label="%s">%s</a>',
esc_url( get_edit_post_link( $rec->ID, true ) ),
/* translators: %s: post title */
/* translators: Hidden accessibility text; %s: post title. */
esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;', 'wordpress-seo' ), $title ) ),
__( 'Edit', 'wordpress-seo' )
);
@@ -813,7 +822,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
$actions['view'] = sprintf(
'<a href="%s" aria-label="%s">%s</a>',
esc_url( add_query_arg( 'preview', 'true', get_permalink( $rec->ID ) ) ),
/* translators: %s: post title */
/* translators: Hidden accessibility text; %s: post title. */
esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;', 'wordpress-seo' ), $title ) ),
__( 'Preview', 'wordpress-seo' )
);
@@ -823,7 +832,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
$actions['view'] = sprintf(
'<a href="%s" aria-label="%s" rel="bookmark">%s</a>',
esc_url( get_permalink( $rec->ID ) ),
/* translators: %s: post title */
/* translators: Hidden accessibility text; %s: post title. */
esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'wordpress-seo' ), $title ) ),
__( 'View', 'wordpress-seo' )
);
@@ -911,7 +920,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
$meta_value = $values[ $meta_value ];
}
$id = "wpseo-existing-$record_id-$this->target_db_field";
$id = "wpseo-existing-$this->target_db_field-$record_id";
// $attributes correctly escaped, verified by Alexander. See WPSEO_Bulk_Description_List_Table::parse_page_specific_column.
return sprintf( '<td %2$s id="%3$s">%1$s</td>', esc_html( $meta_value ), $attributes, esc_attr( $id ) );
@@ -937,38 +946,36 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
/**
* Getting all post_ids from to $this->items.
*
* @return string
* @return array
*/
protected function get_post_ids() {
$needed_ids = [];
$post_ids = [];
foreach ( $this->items as $item ) {
$needed_ids[] = $item->ID;
$post_ids[] = $item->ID;
}
$post_ids = "'" . implode( "', '", $needed_ids ) . "'";
return $post_ids;
}
/**
* Getting the meta_data from database.
*
* @param string $post_ids Post IDs string for SQL IN part.
* @param array $post_ids Post IDs for SQL IN part.
*
* @return mixed
*/
protected function get_meta_data_result( $post_ids ) {
protected function get_meta_data_result( array $post_ids ) {
global $wpdb;
$meta_data = $wpdb->get_results(
"
SELECT *
FROM {$wpdb->postmeta}
WHERE post_id IN({$post_ids}) AND meta_key = '" . WPSEO_Meta::$meta_prefix . $this->target_db_field . "'
"
$where = $wpdb->prepare(
'post_id IN (' . implode( ', ', array_fill( 0, count( $post_ids ), '%d' ) ) . ')',
$post_ids
);
return $meta_data;
$where .= $wpdb->prepare( ' AND meta_key = %s', WPSEO_Meta::$meta_prefix . $this->target_db_field );
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- They are prepared on the lines above.
return $wpdb->get_results( "SELECT * FROM {$wpdb->postmeta} WHERE {$where}" );
}
/**

View File

@@ -5,7 +5,10 @@
* @package WPSEO\Admin
*/
use Yoast\WP\SEO\Config\Schema_Types;
use Yoast\WP\SEO\Integrations\Academy_Integration;
use Yoast\WP\SEO\Integrations\Settings_Integration;
use Yoast\WP\SEO\Integrations\Support_Integration;
use Yoast\WP\SEO\Conditionals\WooCommerce_Conditional;
/**
* Class WPSEO_Admin_Pages.
@@ -33,6 +36,7 @@ class WPSEO_Admin_Pages {
*/
public function __construct() {
add_action( 'init', [ $this, 'init' ], 20 );
$this->asset_manager = new WPSEO_Admin_Asset_Manager();
}
@@ -40,9 +44,11 @@ class WPSEO_Admin_Pages {
* Make sure the needed scripts are loaded for admin pages.
*/
public function init() {
if ( filter_input( INPUT_GET, 'wpseo_reset_defaults' ) && wp_verify_nonce( filter_input( INPUT_GET, 'nonce' ), 'wpseo_reset_defaults' ) && current_user_can( 'manage_options' ) ) {
WPSEO_Options::reset();
wp_redirect( admin_url( 'admin.php?page=' . WPSEO_Configuration_Page::PAGE_IDENTIFIER ) );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$page = isset( $_GET['page'] ) && is_string( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
if ( \in_array( $page, [ Settings_Integration::PAGE, Academy_Integration::PAGE, Support_Integration::PAGE ], true ) ) {
// Bail, this is managed in the applicable integration.
return;
}
add_action( 'admin_enqueue_scripts', [ $this, 'config_page_scripts' ] );
@@ -57,16 +63,13 @@ class WPSEO_Admin_Pages {
wp_enqueue_style( 'thickbox' );
wp_enqueue_style( 'global' );
wp_enqueue_style( 'wp-admin' );
$this->asset_manager->enqueue_style( 'select2' );
$this->asset_manager->enqueue_style( 'admin-css' );
$this->asset_manager->enqueue_style( 'monorepo' );
$page = filter_input( INPUT_GET, 'page' );
if ( $page === 'wpseo_titles' ) {
$this->asset_manager->enqueue_style( 'search-appearance' );
}
if ( $page === 'wpseo_social' || $page === 'wpseo_licenses' ) {
$this->asset_manager->enqueue_style( 'monorepo' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$page = isset( $_GET['page'] ) && is_string( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
if ( $page === 'wpseo_licenses' ) {
$this->asset_manager->enqueue_style( 'tailwind' );
}
}
@@ -78,63 +81,40 @@ class WPSEO_Admin_Pages {
wp_enqueue_script( 'dashboard' );
wp_enqueue_script( 'thickbox' );
$alert_dismissal_action = YoastSEO()->classes->get( \Yoast\WP\SEO\Actions\Alert_Dismissal_Action::class );
$dismissed_alerts = $alert_dismissal_action->all_dismissed();
$alert_dismissal_action = YoastSEO()->classes->get( \Yoast\WP\SEO\Actions\Alert_Dismissal_Action::class );
$dismissed_alerts = $alert_dismissal_action->all_dismissed();
$woocommerce_conditional = new WooCommerce_Conditional();
$script_data = [
'userLanguageCode' => WPSEO_Language_Utils::get_language( \get_user_locale() ),
'dismissedAlerts' => $dismissed_alerts,
'userLanguageCode' => WPSEO_Language_Utils::get_language( \get_user_locale() ),
'dismissedAlerts' => $dismissed_alerts,
'isRtl' => is_rtl(),
'isPremium' => YoastSEO()->helpers->product->is_premium(),
'isWooCommerceActive' => $woocommerce_conditional->is_met(),
'currentPromotions' => YoastSEO()->classes->get( Yoast\WP\SEO\Promotions\Application\Promotion_Manager::class )->get_current_promotions(),
'webinarIntroSettingsUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/webinar-intro-settings' ),
'webinarIntroFirstTimeConfigUrl' => $this->get_webinar_shortlink(),
'linkParams' => WPSEO_Shortlinker::get_query_params(),
'pluginUrl' => \plugins_url( '', \WPSEO_FILE ),
];
$page = filter_input( INPUT_GET, 'page' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$page = isset( $_GET['page'] ) && is_string( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
if ( $page === 'wpseo_titles' ) {
$script_data['analysis'] = [
'plugins' => [
'replaceVars' => $this->get_replace_vars_script_data(),
],
];
$schema_types = new Schema_Types();
$script_data['searchAppearance'] = [
'isRtl' => is_rtl(),
'userEditUrl' => add_query_arg( 'user_id', '{user_id}', admin_url( 'user-edit.php' ) ),
'brushstrokeBackgroundURL' => plugins_url( 'images/brushstroke_background.svg', WPSEO_FILE ),
'showLocalSEOUpsell' => $this->should_show_local_seo_upsell(),
'localSEOUpsellURL' => WPSEO_Shortlinker::get( 'https://yoa.st/3mp' ),
'knowledgeGraphCompanyInfoMissing' => WPSEO_Language_Utils::get_knowledge_graph_company_info_missing_l10n(),
'schema' => [
'pageTypeOptions' => $schema_types->get_page_type_options(),
'articleTypeOptions' => $schema_types->get_article_type_options(),
],
];
/**
* Remove the emoji script as it is incompatible with both React and any
* contenteditable fields.
*/
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
$yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_L10n();
$yoast_components_l10n->localize_script( 'settings' );
}
if ( in_array( $page, [ 'wpseo_social', WPSEO_Admin::PAGE_IDENTIFIER, 'wpseo_titles' ], true ) ) {
if ( in_array( $page, [ WPSEO_Admin::PAGE_IDENTIFIER, 'wpseo_workouts' ], true ) ) {
wp_enqueue_media();
$script_data['media'] = [
'choose_image' => __( 'Use Image', 'wordpress-seo' ),
];
$script_data['userEditUrl'] = add_query_arg( 'user_id', '{user_id}', admin_url( 'user-edit.php' ) );
}
if ( $page === 'wpseo_tools' ) {
$this->enqueue_tools_scripts();
}
if ( $page === 'wpseo_social' ) {
$script_data['social'] = true;
}
$this->asset_manager->localize_script( 'settings', 'wpseoScriptData', $script_data );
$this->asset_manager->enqueue_user_language_script();
}
@@ -142,9 +122,13 @@ class WPSEO_Admin_Pages {
/**
* Retrieves some variables that are needed for replacing variables in JS.
*
* @deprecated 20.3
* @codeCoverageIgnore
*
* @return array The replacement and recommended replacement variables.
*/
public function get_replace_vars_script_data() {
_deprecated_function( __METHOD__, 'Yoast SEO 20.3' );
$replace_vars = new WPSEO_Replace_Vars();
$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars();
$editor_specific_replace_vars = new WPSEO_Admin_Editor_Specific_Replace_Vars();
@@ -155,28 +139,16 @@ class WPSEO_Admin_Pages {
'recommended_replace_vars' => $recommended_replace_vars->get_recommended_replacevars(),
'editor_specific_replace_vars' => $editor_specific_replace_vars->get(),
'shared_replace_vars' => $editor_specific_replace_vars->get_generic( $replace_vars_list ),
'hidden_replace_vars' => $replace_vars->get_hidden_replace_vars(),
];
}
/**
* Determines whether the Local SEO upsell should be shown.
*
* The Local SEO upsell should:
* - Only be shown in Free, not when Premium is active.
* - Not be shown when Local SEO is active.
*
* @return bool Whether the Local SEO upsell should be shown.
*/
private function should_show_local_seo_upsell() {
return ! YoastSEO()->helpers->product->is_premium()
&& ! ( defined( 'WPSEO_LOCAL_FILE' ) );
}
/**
* Enqueues and handles all the tool dependencies.
*/
private function enqueue_tools_scripts() {
$tool = filter_input( INPUT_GET, 'tool' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$tool = isset( $_GET['tool'] ) && is_string( $_GET['tool'] ) ? sanitize_text_field( wp_unslash( $_GET['tool'] ) ) : '';
if ( empty( $tool ) ) {
$this->asset_manager->enqueue_script( 'yoast-seo' );
@@ -186,4 +158,17 @@ class WPSEO_Admin_Pages {
$this->asset_manager->enqueue_script( 'bulk-editor' );
}
}
/**
* Returns the appropriate shortlink for the Webinar.
*
* @return string The shortlink for the Webinar.
*/
private function get_webinar_shortlink() {
if ( YoastSEO()->helpers->product->is_premium() ) {
return WPSEO_Shortlinker::get( 'https://yoa.st/webinar-intro-first-time-config-premium' );
}
return WPSEO_Shortlinker::get( 'https://yoa.st/webinar-intro-first-time-config' );
}
}

View File

@@ -73,8 +73,8 @@ class WPSEO_Database_Proxy {
/**
* Inserts data into the database.
*
* @param array $data Data to insert.
* @param null $format Formats for the data.
* @param array $data Data to insert.
* @param array|string|null $format Formats for the data.
*
* @return false|int Total amount of inserted rows or false on error.
*/
@@ -91,10 +91,10 @@ class WPSEO_Database_Proxy {
/**
* Updates data in the database.
*
* @param array $data Data to update on the table.
* @param array $where Where condition as key => value array.
* @param null $format Optional. Data prepare format.
* @param null $where_format Optional. Where prepare format.
* @param array $data Data to update on the table.
* @param array $where Where condition as key => value array.
* @param array|string|null $format Optional. Data prepare format.
* @param array|string|null $where_format Optional. Where prepare format.
*
* @return false|int False when the update request is invalid, int on number of rows changed.
*/
@@ -113,10 +113,10 @@ class WPSEO_Database_Proxy {
*
* Performs an insert into and if key is duplicate it will update the existing record.
*
* @param array $data Data to update on the table.
* @param array|null $where Unused. Where condition as key => value array.
* @param null $format Optional. Data prepare format.
* @param null $where_format Deprecated. Where prepare format.
* @param array $data Data to update on the table.
* @param array|null $where Unused. Where condition as key => value array.
* @param array|string|null $format Optional. Data prepare format.
* @param array|string|null $where_format Optional. Where prepare format.
*
* @return false|int False when the upsert request is invalid, int on number of rows changed.
*/
@@ -158,8 +158,8 @@ class WPSEO_Database_Proxy {
/**
* Deletes a record from the database.
*
* @param array $where Where clauses for the query.
* @param array|null $format Formats for the data.
* @param array $where Where clauses for the query.
* @param array|string|null $format Formats for the data.
*
* @return false|int
*/

View File

@@ -125,7 +125,8 @@ class WPSEO_Export {
if ( is_array( $elem ) ) {
$count = count( $elem );
for ( $i = 0; $i < $count; $i++ ) {
$this->write_setting( $key . '[]', $elem[ $i ] );
$elem_check = isset( $elem[ $i ] ) ? $elem[ $i ] : null;
$this->write_setting( $key . '[]', $elem_check );
}
}
else {

View File

@@ -16,25 +16,42 @@ class WPSEO_Expose_Shortlinks implements WPSEO_WordPress_Integration {
* @var array
*/
private $shortlinks = [
'shortlinks.advanced.allow_search_engines' => 'https://yoa.st/allow-search-engines',
'shortlinks.advanced.follow_links' => 'https://yoa.st/follow-links',
'shortlinks.advanced.meta_robots' => 'https://yoa.st/meta-robots-advanced',
'shortlinks.advanced.breadcrumbs_title' => 'https://yoa.st/breadcrumbs-title',
'shortlinks.metabox.schema.explanation' => 'https://yoa.st/400',
'shortlinks.metabox.schema.page_type' => 'https://yoa.st/402',
'shortlinks.sidebar.schema.explanation' => 'https://yoa.st/401',
'shortlinks.sidebar.schema.page_type' => 'https://yoa.st/403',
'shortlinks.focus_keyword_info' => 'https://yoa.st/focus-keyword',
'shortlinks.nofollow_sponsored' => 'https://yoa.st/nofollow-sponsored',
'shortlinks.snippet_preview_info' => 'https://yoa.st/snippet-preview',
'shortlinks.cornerstone_content_info' => 'https://yoa.st/1i9',
'shortlinks.upsell.sidebar.focus_keyword_synonyms_link' => 'https://yoa.st/textlink-synonyms-popup-sidebar',
'shortlinks.upsell.social_preview.social' => 'https://yoa.st/social-preview-facebook',
'shortlinks.upsell.social_preview.twitter' => 'https://yoa.st/social-preview-twitter',
'shortlinks.upsell.sidebar.news' => 'https://yoa.st/get-news-sidebar',
'shortlinks.upsell.sidebar.focus_keyword_synonyms_button' => 'https://yoa.st/keyword-synonyms-popup-sidebar',
'shortlinks.upsell.sidebar.focus_keyword_additional_link' => 'https://yoa.st/textlink-keywords-popup-sidebar',
'shortlinks.upsell.sidebar.premium_seo_analysis_button' => 'https://yoa.st/premium-seo-analysis-sidebar',
'shortlinks.upsell.sidebar.focus_keyword_additional_button' => 'https://yoa.st/add-keywords-popup-sidebar',
'shortlinks.upsell.sidebar.additional_link' => 'https://yoa.st/textlink-keywords-sidebar',
'shortlinks.upsell.sidebar.additional_button' => 'https://yoa.st/add-keywords-sidebar',
'shortlinks.upsell.sidebar.keyphrase_distribution' => 'https://yoa.st/keyphrase-distribution-sidebar',
'shortlinks.upsell.sidebar.word_complexity' => 'https://yoa.st/word-complexity-sidebar',
'shortlinks.upsell.sidebar.internal_linking_suggestions' => 'https://yoa.st/internal-linking-suggestions-sidebar',
'shortlinks.upsell.metabox.news' => 'https://yoa.st/get-news-metabox',
'shortlinks.upsell.metabox.go_premium' => 'https://yoa.st/pe-premium-page',
'shortlinks.upsell.metabox.focus_keyword_synonyms_link' => 'https://yoa.st/textlink-synonyms-popup-metabox',
'shortlinks.upsell.metabox.focus_keyword_synonyms_button' => 'https://yoa.st/keyword-synonyms-popup',
'shortlinks.upsell.metabox.focus_keyword_additional_link' => 'https://yoa.st/textlink-keywords-popup-metabox',
'shortlinks.upsell.metabox.premium_seo_analysis_button' => 'https://yoa.st/premium-seo-analysis-metabox',
'shortlinks.upsell.metabox.focus_keyword_additional_button' => 'https://yoa.st/add-keywords-popup',
'shortlinks.upsell.metabox.additional_link' => 'https://yoa.st/textlink-keywords-metabox',
'shortlinks.upsell.metabox.additional_button' => 'https://yoa.st/add-keywords-metabox',
'shortlinks.upsell.metabox.keyphrase_distribution' => 'https://yoa.st/keyphrase-distribution-metabox',
'shortlinks.upsell.metabox.word_complexity' => 'https://yoa.st/word-complexity-metabox',
'shortlinks.upsell.metabox.internal_linking_suggestions' => 'https://yoa.st/internal-linking-suggestions-metabox',
'shortlinks.upsell.gsc.create_redirect_button' => 'https://yoa.st/redirects',
'shortlinks.readability_analysis_info' => 'https://yoa.st/readability-analysis',
'shortlinks.inclusive_language_analysis_info' => 'https://yoa.st/inclusive-language-analysis',
'shortlinks.activate_premium_info' => 'https://yoa.st/activate-subscription',
'shortlinks.upsell.sidebar.morphology_upsell_metabox' => 'https://yoa.st/morphology-upsell-metabox',
'shortlinks.upsell.sidebar.morphology_upsell_sidebar' => 'https://yoa.st/morphology-upsell-sidebar',
@@ -42,6 +59,22 @@ class WPSEO_Expose_Shortlinks implements WPSEO_WordPress_Integration {
'shortlinks.semrush.trend_help' => 'https://yoa.st/3-v',
'shortlinks.semrush.prices' => 'https://yoa.st/semrush-prices',
'shortlinks.semrush.premium_landing_page' => 'https://yoa.st/413',
'shortlinks.wincher.seo_performance' => 'https://yoa.st/wincher-integration',
'shortlinks-insights-estimated_reading_time' => 'https://yoa.st/4fd',
'shortlinks-insights-flesch_reading_ease' => 'https://yoa.st/34r',
'shortlinks-insights-flesch_reading_ease_sidebar' => 'https://yoa.st/4mf',
'shortlinks-insights-flesch_reading_ease_metabox' => 'https://yoa.st/4mg',
'shortlinks-insights-flesch_reading_ease_article' => 'https://yoa.st/34s',
'shortlinks-insights-keyword_research_link' => 'https://yoa.st/keyword-research-metabox',
'shortlinks-insights-upsell-sidebar-prominent_words' => 'https://yoa.st/prominent-words-upsell-sidebar',
'shortlinks-insights-upsell-metabox-prominent_words' => 'https://yoa.st/prominent-words-upsell-metabox',
'shortlinks-insights-upsell-elementor-prominent_words' => 'https://yoa.st/prominent-words-upsell-elementor',
'shortlinks-insights-word_count' => 'https://yoa.st/word-count',
'shortlinks-insights-upsell-sidebar-text_formality' => 'https://yoa.st/formality-upsell-sidebar',
'shortlinks-insights-upsell-metabox-text_formality' => 'https://yoa.st/formality-upsell-metabox',
'shortlinks-insights-upsell-elementor-text_formality' => 'https://yoa.st/formality-upsell-elementor',
'shortlinks-insights-text_formality_info_free' => 'https://yoa.st/formality-free',
'shortlinks-insights-text_formality_info_premium' => 'https://yoa.st/formality',
];
/**
@@ -82,13 +115,14 @@ class WPSEO_Expose_Shortlinks implements WPSEO_WordPress_Integration {
$shortlinks = $this->shortlinks;
$shortlinks['shortlinks.upsell.metabox.focus_keyword_synonyms_link'] = 'https://yoa.st/textlink-synonyms-popup-metabox-term';
$shortlinks['shortlinks.upsell.metabox.focus_keyword_synonyms_button'] = 'https://yoa.st/keyword-synonyms-popup-term';
$shortlinks['shortlinks.upsell.metabox.focus_keyword_additional_link'] = 'https://yoa.st/textlink-keywords-popup-metabox-term';
$shortlinks['shortlinks.upsell.metabox.focus_keyword_additional_button'] = 'https://yoa.st/add-keywords-popup-term';
$shortlinks['shortlinks.upsell.metabox.additional_link'] = 'https://yoa.st/textlink-keywords-metabox-term';
$shortlinks['shortlinks.upsell.metabox.additional_button'] = 'https://yoa.st/add-keywords-metabox-term';
$shortlinks['shortlinks.upsell.sidebar.morphology_upsell_metabox'] = 'https://yoa.st/morphology-upsell-metabox-term';
$shortlinks['shortlinks.upsell.metabox.keyphrase_distribution'] = 'https://yoa.st/keyphrase-distribution-metabox-term';
$shortlinks['shortlinks.upsell.metabox.word_complexity'] = 'https://yoa.st/word-complexity-metabox-term';
$shortlinks['shortlinks.upsell.metabox.internal_linking_suggestions'] = 'https://yoa.st/internal-linking-suggestions-metabox-term';
return $shortlinks;
}

View File

@@ -15,21 +15,21 @@ class WPSEO_Gutenberg_Compatibility {
*
* @var string
*/
const CURRENT_RELEASE = '10.7.1';
const CURRENT_RELEASE = '16.8.1';
/**
* The minimally supported version of Gutenberg by the plugin.
*
* @var string
*/
const MINIMUM_SUPPORTED = '10.7.1';
const MINIMUM_SUPPORTED = '16.8.1';
/**
* Holds the current version.
*
* @var string
*/
protected $current_version;
protected $current_version = '';
/**
* WPSEO_Gutenberg_Compatibility constructor.

View File

@@ -6,6 +6,7 @@
*/
use Yoast\WP\SEO\Context\Meta_Tags_Context;
use Yoast\WP\SEO\Helpers\Score_Icon_Helper;
use Yoast\WP\SEO\Integrations\Admin\Admin_Columns_Cache_Integration;
use Yoast\WP\SEO\Surfaces\Values\Meta;
@@ -42,6 +43,13 @@ class WPSEO_Meta_Columns {
*/
private $admin_columns_cache;
/**
* Holds the Score_Icon_Helper.
*
* @var Score_Icon_Helper
*/
private $score_icon_helper;
/**
* When page analysis is enabled, just initialize the hooks.
*/
@@ -53,6 +61,7 @@ class WPSEO_Meta_Columns {
$this->analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$this->analysis_readability = new WPSEO_Metabox_Analysis_Readability();
$this->admin_columns_cache = YoastSEO()->classes->get( Admin_Columns_Cache_Integration::class );
$this->score_icon_helper = YoastSEO()->helpers->score_icon;
}
/**
@@ -88,11 +97,19 @@ class WPSEO_Meta_Columns {
$added_columns = [];
if ( $this->analysis_seo->is_enabled() ) {
$added_columns['wpseo-score'] = '<span class="yoast-tooltip yoast-tooltip-n yoast-tooltip-alt" data-label="' . esc_attr__( 'SEO score', 'wordpress-seo' ) . '"><span class="yoast-column-seo-score yoast-column-header-has-tooltip"><span class="screen-reader-text">' . __( 'SEO score', 'wordpress-seo' ) . '</span></span></span>';
$added_columns['wpseo-score'] = '<span class="yoast-column-seo-score yoast-column-header-has-tooltip" data-tooltip-text="' .
esc_attr__( 'SEO score', 'wordpress-seo' ) .
'"><span class="screen-reader-text">' .
__( 'SEO score', 'wordpress-seo' ) .
'</span></span></span>';
}
if ( $this->analysis_readability->is_enabled() ) {
$added_columns['wpseo-score-readability'] = '<span class="yoast-tooltip yoast-tooltip-n yoast-tooltip-alt" data-label="' . esc_attr__( 'Readability score', 'wordpress-seo' ) . '"><span class="yoast-column-readability yoast-column-header-has-tooltip"><span class="screen-reader-text">' . __( 'Readability score', 'wordpress-seo' ) . '</span></span></span>';
$added_columns['wpseo-score-readability'] = '<span class="yoast-column-readability yoast-column-header-has-tooltip" data-tooltip-text="' .
esc_attr__( 'Readability score', 'wordpress-seo' ) .
'"><span class="screen-reader-text">' .
__( 'Readability score', 'wordpress-seo' ) .
'</span></span></span>';
}
$added_columns['wpseo-title'] = __( 'SEO Title', 'wordpress-seo' );
@@ -120,28 +137,40 @@ class WPSEO_Meta_Columns {
case 'wpseo-score':
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Correctly escaped in render_score_indicator() method.
echo $this->parse_column_score( $post_id );
return;
case 'wpseo-score-readability':
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Correctly escaped in render_score_indicator() method.
echo $this->parse_column_score_readability( $post_id );
return;
case 'wpseo-title':
echo esc_html( $this->get_meta( $post_id )->title );
$meta = $this->get_meta( $post_id );
if ( $meta ) {
echo esc_html( $meta->title );
}
return;
case 'wpseo-metadesc':
$metadesc_val = $this->get_meta( $post_id )->meta_description;
$metadesc_val = '';
$meta = $this->get_meta( $post_id );
if ( $meta ) {
$metadesc_val = $meta->meta_description;
}
if ( $metadesc_val === '' ) {
echo '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">',
esc_html__( 'Meta description not set.', 'wordpress-seo' ),
'</span>';
/* translators: Hidden accessibility text. */
esc_html__( 'Meta description not set.', 'wordpress-seo' ),
'</span>';
return;
}
echo esc_html( $metadesc_val );
return;
case 'wpseo-focuskw':
@@ -149,12 +178,15 @@ class WPSEO_Meta_Columns {
if ( $focuskw_val === '' ) {
echo '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">',
esc_html__( 'Focus keyphrase not set.', 'wordpress-seo' ),
'</span>';
/* translators: Hidden accessibility text. */
esc_html__( 'Focus keyphrase not set.', 'wordpress-seo' ),
'</span>';
return;
}
echo esc_html( $focuskw_val );
return;
}
}
@@ -175,6 +207,11 @@ class WPSEO_Meta_Columns {
if ( $this->analysis_seo->is_enabled() ) {
$columns['wpseo-focuskw'] = 'wpseo-focuskw';
$columns['wpseo-score'] = 'wpseo-score';
}
if ( $this->analysis_readability->is_enabled() ) {
$columns['wpseo-score-readability'] = 'wpseo-score-readability';
}
return $columns;
@@ -211,6 +248,7 @@ class WPSEO_Meta_Columns {
$ranks = WPSEO_Rank::get_all_ranks();
/* translators: Hidden accessibility text. */
echo '<label class="screen-reader-text" for="wpseo-filter">' . esc_html__( 'Filter by SEO Score', 'wordpress-seo' ) . '</label>';
echo '<select name="seo_filter" id="wpseo-filter">';
@@ -239,6 +277,7 @@ class WPSEO_Meta_Columns {
$ranks = WPSEO_Rank::get_all_readability_ranks();
/* translators: Hidden accessibility text. */
echo '<label class="screen-reader-text" for="wpseo-readability-filter">' . esc_html__( 'Filter by Readability Score', 'wordpress-seo' ) . '</label>';
echo '<select name="readability_filter" id="wpseo-readability-filter">';
@@ -335,7 +374,7 @@ class WPSEO_Meta_Columns {
*
* @param mixed $filter The filter to check against.
*
* @return bool Whether or not the filter is considered valid.
* @return bool Whether the filter is considered valid.
*/
protected function is_valid_filter( $filter ) {
return ! empty( $filter ) && is_string( $filter );
@@ -368,13 +407,37 @@ class WPSEO_Meta_Columns {
}
if ( $this->is_valid_filter( $current_keyword_filter ) ) {
$active_filters = array_merge(
$active_filters,
$this->get_keyword_filter( $current_keyword_filter )
/**
* Adapt the meta query used to filter the post overview on keyphrase.
*
* @internal
*
* @api array $keyword_filter The current keyword filter.
*
* @param array $keyphrase The keyphrase used in the filter.
*/
$keyphrase_filter = \apply_filters(
'wpseo_change_keyphrase_filter_in_request',
$this->get_keyword_filter( $current_keyword_filter ),
$current_keyword_filter
);
if ( \is_array( $keyphrase_filter ) ) {
$active_filters = array_merge(
$active_filters,
[ $keyphrase_filter ]
);
}
}
return $active_filters;
/**
* Adapt the active applicable filters on the posts overview.
*
* @internal
*
* @param array $active_filters The current applicable filters.
*/
return \apply_filters( 'wpseo_change_applicable_filters', $active_filters );
}
/**
@@ -387,8 +450,22 @@ class WPSEO_Meta_Columns {
public function column_sort_orderby( $vars ) {
$collected_filters = $this->collect_filters();
if ( isset( $vars['orderby'] ) ) {
$vars = array_merge( $vars, $this->filter_order_by( $vars['orderby'] ) );
$order_by_column = $vars['orderby'];
if ( isset( $order_by_column ) ) {
// Based on the selected column, create a meta query.
$order_by = $this->filter_order_by( $order_by_column );
/**
* Adapt the order by part of the query on the posts overview.
*
* @internal
*
* @param array $order_by The current order by.
* @param string $order_by_column The current order by column.
*/
$order_by = \apply_filters( 'wpseo_change_order_by', $order_by, $order_by_column );
$vars = array_merge( $vars, $order_by );
}
return $this->build_filter_query( $vars, $collected_filters );
@@ -432,37 +509,57 @@ class WPSEO_Meta_Columns {
/**
* Retrieves the post type from the $_GET variable.
*
* @return string The current post type.
* @return string|null The sanitized current post type or null when the variable is not set in $_GET.
*/
public function get_current_post_type() {
return filter_input( INPUT_GET, 'post_type' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['post_type'] ) && is_string( $_GET['post_type'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
return sanitize_text_field( wp_unslash( $_GET['post_type'] ) );
}
return null;
}
/**
* Retrieves the SEO filter from the $_GET variable.
*
* @return string The current post type.
* @return string|null The sanitized seo filter or null when the variable is not set in $_GET.
*/
public function get_current_seo_filter() {
return filter_input( INPUT_GET, 'seo_filter' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['seo_filter'] ) && is_string( $_GET['seo_filter'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
return sanitize_text_field( wp_unslash( $_GET['seo_filter'] ) );
}
return null;
}
/**
* Retrieves the Readability filter from the $_GET variable.
*
* @return string The current post type.
* @return string|null The sanitized readability filter or null when the variable is not set in $_GET.
*/
public function get_current_readability_filter() {
return filter_input( INPUT_GET, 'readability_filter' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['readability_filter'] ) && is_string( $_GET['readability_filter'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
return sanitize_text_field( wp_unslash( $_GET['readability_filter'] ) );
}
return null;
}
/**
* Retrieves the keyword filter from the $_GET variable.
*
* @return string The current post type.
* @return string|null The sanitized seo keyword filter or null when the variable is not set in $_GET.
*/
public function get_current_keyword_filter() {
return filter_input( INPUT_GET, 'seo_kw_filter' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['seo_kw_filter'] ) && is_string( $_GET['seo_kw_filter'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
return sanitize_text_field( wp_unslash( $_GET['seo_kw_filter'] ) );
}
return null;
}
/**
@@ -609,15 +706,31 @@ class WPSEO_Meta_Columns {
switch ( $order_by ) {
case 'wpseo-metadesc':
return [
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Reason: Only used when user requests sorting.
'meta_key' => WPSEO_Meta::$meta_prefix . 'metadesc',
'orderby' => 'meta_value',
];
case 'wpseo-focuskw':
return [
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Reason: Only used when user requests sorting.
'meta_key' => WPSEO_Meta::$meta_prefix . 'focuskw',
'orderby' => 'meta_value',
];
case 'wpseo-score':
return [
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Reason: Only used when user requests sorting.
'meta_key' => WPSEO_Meta::$meta_prefix . 'linkdex',
'orderby' => 'meta_value_num',
];
case 'wpseo-score-readability':
return [
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Reason: Only used when user requests sorting.
'meta_key' => WPSEO_Meta::$meta_prefix . 'content_score',
'orderby' => 'meta_value_num',
];
}
return [];
@@ -631,27 +744,11 @@ class WPSEO_Meta_Columns {
* @return string The HTML for the SEO score indicator.
*/
private function parse_column_score( $post_id ) {
if ( ! $this->is_indexable( $post_id ) ) {
$rank = new WPSEO_Rank( WPSEO_Rank::NO_INDEX );
$title = __( 'Post is set to noindex.', 'wordpress-seo' );
$meta = $this->get_meta( $post_id );
WPSEO_Meta::set_value( 'linkdex', 0, $post_id );
return $this->render_score_indicator( $rank, $title );
if ( $meta ) {
return $this->score_icon_helper->for_seo( $meta->indexable, '', __( 'Post is set to noindex.', 'wordpress-seo' ) );
}
if ( WPSEO_Meta::get_value( 'focuskw', $post_id ) === '' ) {
$rank = new WPSEO_Rank( WPSEO_Rank::NO_FOCUS );
$title = __( 'Focus keyphrase not set.', 'wordpress-seo' );
return $this->render_score_indicator( $rank, $title );
}
$score = (int) WPSEO_Meta::get_value( 'linkdex', $post_id );
$rank = WPSEO_Rank::from_numeric_score( $score );
$title = $rank->get_label();
return $this->render_score_indicator( $rank, $title );
}
/**
@@ -662,10 +759,10 @@ class WPSEO_Meta_Columns {
* @return string The HTML for the readability score indicator.
*/
private function parse_column_score_readability( $post_id ) {
$score = (int) WPSEO_Meta::get_value( 'content_score', $post_id );
$rank = WPSEO_Rank::from_numeric_score( $score );
return $this->render_score_indicator( $rank );
$meta = $this->get_meta( $post_id );
if ( $meta ) {
return $this->score_icon_helper->for_readability( $meta->indexable->readability_score );
}
}
/**
@@ -702,7 +799,7 @@ class WPSEO_Meta_Columns {
* @return bool Whether or not the meta box (and associated columns etc) should be hidden.
*/
private function display_metabox( $post_type = null ) {
$current_post_type = sanitize_text_field( $this->get_current_post_type() );
$current_post_type = $this->get_current_post_type();
if ( ! isset( $post_type ) && ! empty( $current_post_type ) ) {
$post_type = $current_post_type;
@@ -711,22 +808,6 @@ class WPSEO_Meta_Columns {
return WPSEO_Utils::is_metabox_active( $post_type, 'post_type' );
}
/**
* Renders the score indicator.
*
* @param WPSEO_Rank $rank The rank this indicator should have.
* @param string $title Optional. The title for this rank, defaults to the title of the rank.
*
* @return string The HTML for a score indicator.
*/
private function render_score_indicator( $rank, $title = '' ) {
if ( empty( $title ) ) {
$title = $rank->get_label();
}
return '<div aria-hidden="true" title="' . esc_attr( $title ) . '" class="' . esc_attr( 'wpseo-score-icon ' . $rank->get_css_class() ) . '"></div><span class="screen-reader-text wpseo-score-text">' . esc_html( $title ) . '</span>';
}
/**
* Determines whether or not filter dropdowns should be displayed.
*

View File

@@ -163,7 +163,9 @@ class WPSEO_MyYoast_Proxy implements WPSEO_WordPress_Integration {
* @return bool True when the page request parameter equals the proxy page.
*/
protected function is_proxy_page() {
return filter_input( INPUT_GET, 'page' ) === self::PAGE_IDENTIFIER;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$page = isset( $_GET['page'] ) && is_string( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
return $page === self::PAGE_IDENTIFIER;
}
/**
@@ -171,10 +173,15 @@ class WPSEO_MyYoast_Proxy implements WPSEO_WordPress_Integration {
*
* @codeCoverageIgnore
*
* @return string The sanitized file request parameter.
* @return string The sanitized file request parameter or an empty string if it does not exist.
*/
protected function get_proxy_file() {
return filter_input( INPUT_GET, 'file', FILTER_SANITIZE_STRING );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['file'] ) && is_string( $_GET['file'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
return sanitize_text_field( wp_unslash( $_GET['file'] ) );
}
return '';
}
/**
@@ -182,14 +189,17 @@ class WPSEO_MyYoast_Proxy implements WPSEO_WordPress_Integration {
*
* @codeCoverageIgnore
*
* @return string The sanitized plugin_version request parameter.
* @return string The sanitized plugin_version request parameter or an empty string if it does not exist.
*/
protected function get_plugin_version() {
$plugin_version = filter_input( INPUT_GET, 'plugin_version', FILTER_SANITIZE_STRING );
// Replace slashes to secure against requiring a file from another path.
$plugin_version = str_replace( [ '/', '\\' ], '_', $plugin_version );
return $plugin_version;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['plugin_version'] ) && is_string( $_GET['plugin_version'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$plugin_version = sanitize_text_field( wp_unslash( $_GET['plugin_version'] ) );
// Replace slashes to secure against requiring a file from another path.
return str_replace( [ '/', '\\' ], '_', $plugin_version );
}
return '';
}
/**

View File

@@ -71,6 +71,24 @@ class WPSEO_Option_Tab {
return (bool) $this->get_argument( 'save_button', true );
}
/**
* Retrieves whether the tab hosts beta functionalities.
*
* @return bool True whether the tab hosts beta functionalities.
*/
public function is_beta() {
return (bool) $this->get_argument( 'beta', false );
}
/**
* Retrieves whether the tab hosts premium functionalities.
*
* @return bool True whether the tab hosts premium functionalities.
*/
public function is_premium() {
return (bool) $this->get_argument( 'premium', false );
}
/**
* Gets the option group.
*
@@ -83,12 +101,12 @@ class WPSEO_Option_Tab {
/**
* Retrieves the variable from the supplied arguments.
*
* @param string $variable Variable to retrieve.
* @param string|mixed $default Default to use when variable not found.
* @param string $variable Variable to retrieve.
* @param string|mixed $default_value Default to use when variable not found.
*
* @return mixed|string The retrieved variable.
*/
protected function get_argument( $variable, $default = '' ) {
return array_key_exists( $variable, $this->arguments ) ? $this->arguments[ $variable ] : $default;
protected function get_argument( $variable, $default_value = '' ) {
return array_key_exists( $variable, $this->arguments ) ? $this->arguments[ $variable ] : $default_value;
}
}

View File

@@ -5,6 +5,9 @@
* @package WPSEO\Admin\Options\Tabs
*/
use Yoast\WP\SEO\Presenters\Admin\Beta_Badge_Presenter;
use Yoast\WP\SEO\Presenters\Admin\Premium_Badge_Presenter;
/**
* Class WPSEO_Option_Tabs_Formatter.
*/
@@ -31,11 +34,21 @@ class WPSEO_Option_Tabs_Formatter {
echo '<h2 class="nav-tab-wrapper" id="wpseo-tabs">';
foreach ( $option_tabs->get_tabs() as $tab ) {
$label = esc_html( $tab->get_label() );
if ( $tab->is_beta() ) {
$label = '<span style="margin-right:4px;">' . $label . '</span>' . new Beta_Badge_Presenter( $tab->get_name() );
}
elseif ( $tab->is_premium() ) {
$label = '<span style="margin-right:4px;">' . $label . '</span>' . new Premium_Badge_Presenter( $tab->get_name() );
}
printf(
'<a class="nav-tab" id="%1$s" href="%2$s">%3$s</a>',
esc_attr( $tab->get_name() . '-tab' ),
esc_url( '#top#' . $tab->get_name() ),
esc_html( $tab->get_label() )
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: we do this on purpose
$label
);
}
echo '</h2>';

View File

@@ -42,7 +42,8 @@ class WPSEO_Option_Tabs {
public function __construct( $base, $active_tab = '' ) {
$this->base = sanitize_title( $base );
$tab = filter_input( INPUT_GET, 'tab' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$tab = isset( $_GET['tab'] ) && is_string( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : '';
$this->active_tab = empty( $tab ) ? $active_tab : $tab;
}

View File

@@ -6,6 +6,8 @@
* @since 1.7.0
*/
use Yoast\WP\SEO\Config\Conflicting_Plugins;
/**
* Contains list of conflicting plugins.
*/
@@ -14,96 +16,18 @@ class WPSEO_Plugin_Conflict extends Yoast_Plugin_Conflict {
/**
* The plugins must be grouped per section.
*
* It's possible to check for each section if there are conflicting plugin
* It's possible to check for each section if there are conflicting plugin.
*
* NOTE: when changing this array, be sure to update the array in Conflicting_Plugins_Service too.
*
* @var array
*/
protected $plugins = [
// The plugin which are writing OG metadata.
'open_graph' => [
'2-click-socialmedia-buttons/2-click-socialmedia-buttons.php',
// 2 Click Social Media Buttons.
'add-link-to-facebook/add-link-to-facebook.php', // Add Link to Facebook.
'add-meta-tags/add-meta-tags.php', // Add Meta Tags.
'easy-facebook-share-thumbnails/esft.php', // Easy Facebook Share Thumbnail.
'facebook/facebook.php', // Facebook (official plugin).
'facebook-awd/AWD_facebook.php', // Facebook AWD All in one.
'facebook-featured-image-and-open-graph-meta-tags/fb-featured-image.php',
// Facebook Featured Image & OG Meta Tags.
'facebook-meta-tags/facebook-metatags.php', // Facebook Meta Tags.
'wonderm00ns-simple-facebook-open-graph-tags/wonderm00n-open-graph.php',
// Facebook Open Graph Meta Tags for WordPress.
'facebook-revised-open-graph-meta-tag/index.php', // Facebook Revised Open Graph Meta Tag.
'facebook-thumb-fixer/_facebook-thumb-fixer.php', // Facebook Thumb Fixer.
'facebook-and-digg-thumbnail-generator/facebook-and-digg-thumbnail-generator.php',
// Fedmich's Facebook Open Graph Meta.
'network-publisher/networkpub.php', // Network Publisher.
'nextgen-facebook/nextgen-facebook.php', // NextGEN Facebook OG.
'opengraph/opengraph.php', // Open Graph.
'open-graph-protocol-framework/open-graph-protocol-framework.php',
// Open Graph Protocol Framework.
'seo-facebook-comments/seofacebook.php', // SEO Facebook Comments.
'sexybookmarks/sexy-bookmarks.php', // Shareaholic.
'shareaholic/sexy-bookmarks.php', // Shareaholic.
'sharepress/sharepress.php', // SharePress.
'simple-facebook-connect/sfc.php', // Simple Facebook Connect.
'social-discussions/social-discussions.php', // Social Discussions.
'social-sharing-toolkit/social_sharing_toolkit.php', // Social Sharing Toolkit.
'socialize/socialize.php', // Socialize.
'only-tweet-like-share-and-google-1/tweet-like-plusone.php',
// Tweet, Like, Google +1 and Share.
'wordbooker/wordbooker.php', // Wordbooker.
'wpsso/wpsso.php', // WordPress Social Sharing Optimization.
'wp-caregiver/wp-caregiver.php', // WP Caregiver.
'wp-facebook-like-send-open-graph-meta/wp-facebook-like-send-open-graph-meta.php',
// WP Facebook Like Send & Open Graph Meta.
'wp-facebook-open-graph-protocol/wp-facebook-ogp.php', // WP Facebook Open Graph protocol.
'wp-ogp/wp-ogp.php', // WP-OGP.
'zoltonorg-social-plugin/zosp.php', // Zolton.org Social Plugin.
],
'xml_sitemaps' => [
'google-sitemap-plugin/google-sitemap-plugin.php',
// Google Sitemap (BestWebSoft).
'xml-sitemaps/xml-sitemaps.php',
// XML Sitemaps (Denis de Bernardy and Mike Koepke).
'bwp-google-xml-sitemaps/bwp-simple-gxs.php',
// Better WordPress Google XML Sitemaps (Khang Minh).
'google-sitemap-generator/sitemap.php',
// Google XML Sitemaps (Arne Brachhold).
'xml-sitemap-feed/xml-sitemap.php',
// XML Sitemap & Google News feeds (RavanH).
'google-monthly-xml-sitemap/monthly-xml-sitemap.php',
// Google Monthly XML Sitemap (Andrea Pernici).
'simple-google-sitemap-xml/simple-google-sitemap-xml.php',
// Simple Google Sitemap XML (iTx Technologies).
'another-simple-xml-sitemap/another-simple-xml-sitemap.php',
// Another Simple XML Sitemap.
'xml-maps/google-sitemap.php',
// Xml Sitemap (Jason Martens).
'google-xml-sitemap-generator-by-anton-dachauer/adachauer-google-xml-sitemap.php',
// Google XML Sitemap Generator by Anton Dachauer (Anton Dachauer).
'wp-xml-sitemap/wp-xml-sitemap.php',
// WP XML Sitemap (Team Vivacity).
'sitemap-generator-for-webmasters/sitemap.php',
// Sitemap Generator for Webmasters (iwebslogtech).
'xml-sitemap-xml-sitemapcouk/xmls.php',
// XML Sitemap - XML-Sitemap.co.uk (Simon Hancox).
'sewn-in-xml-sitemap/sewn-xml-sitemap.php',
// Sewn In XML Sitemap (jcow).
'rps-sitemap-generator/rps-sitemap-generator.php',
// RPS Sitemap Generator (redpixelstudios).
],
'cloaking' => [
'rs-head-cleaner/rs-head-cleaner.php',
// RS Head Cleaner Plus https://wordpress.org/plugins/rs-head-cleaner/.
'rs-head-cleaner-lite/rs-head-cleaner-lite.php',
// RS Head Cleaner Lite https://wordpress.org/plugins/rs-head-cleaner-lite/.
],
'seo' => [
'all-in-one-seo-pack/all_in_one_seo_pack.php', // All in One SEO Pack.
'seo-ultimate/seo-ultimate.php', // SEO Ultimate.
'seo-by-rank-math/rank-math.php', // Rank Math.
],
'open_graph' => Conflicting_Plugins::OPEN_GRAPH_PLUGINS,
'xml_sitemaps' => Conflicting_Plugins::XML_SITEMAPS_PLUGINS,
'cloaking' => Conflicting_Plugins::CLOAKING_PLUGINS,
'seo' => Conflicting_Plugins::SEO_PLUGINS,
];
/**
@@ -125,13 +49,11 @@ class WPSEO_Plugin_Conflict extends Yoast_Plugin_Conflict {
* @param string|bool $plugin Optional plugin basename to check.
*/
public static function hook_check_for_plugin_conflicts( $plugin = false ) {
// The instance of itself.
// The instance of the plugin.
$instance = self::get_instance();
// Only add plugin as active plugin if $plugin isn't false.
// Only add the plugin as an active plugin if $plugin isn't false.
if ( $plugin && is_string( $plugin ) ) {
// Because it's just activated.
$instance->add_active_plugin( $instance->find_plugin_category( $plugin ), $plugin );
}
@@ -142,7 +64,7 @@ class WPSEO_Plugin_Conflict extends Yoast_Plugin_Conflict {
/* translators: %1$s expands to Yoast SEO, %2$s: 'Facebook' plugin name of possibly conflicting plugin with regard to creating OpenGraph output. */
$plugin_sections['open_graph'] = __( 'Both %1$s and %2$s create Open Graph output, which might make Facebook, Twitter, LinkedIn and other social networks use the wrong texts and images when your pages are being shared.', 'wordpress-seo' )
. '<br/><br/>'
. '<a class="button" href="' . admin_url( 'admin.php?page=wpseo_social#top#facebook' ) . '">'
. '<a class="button" href="' . admin_url( 'admin.php?page=wpseo_page_settings#/site-features#card-wpseo_social-opengraph' ) . '">'
/* translators: %1$s expands to Yoast SEO. */
. sprintf( __( 'Configure %1$s\'s Open Graph settings', 'wordpress-seo' ), 'Yoast SEO' )
. '</a>';
@@ -153,7 +75,7 @@ class WPSEO_Plugin_Conflict extends Yoast_Plugin_Conflict {
/* translators: %1$s expands to Yoast SEO, %2$s: 'Google XML Sitemaps' plugin name of possibly conflicting plugin with regard to the creation of sitemaps. */
$plugin_sections['xml_sitemaps'] = __( 'Both %1$s and %2$s can create XML sitemaps. Having two XML sitemaps is not beneficial for search engines and might slow down your site.', 'wordpress-seo' )
. '<br/><br/>'
. '<a class="button" href="' . admin_url( 'admin.php?page=wpseo_dashboard#top#features' ) . '">'
. '<a class="button" href="' . admin_url( 'admin.php?page=wpseo_page_settings#/site-features#card-wpseo-enable_xml_sitemap' ) . '">'
/* translators: %1$s expands to Yoast SEO. */
. sprintf( __( 'Toggle %1$s\'s XML Sitemap', 'wordpress-seo' ), 'Yoast SEO' )
. '</a>';

View File

@@ -78,7 +78,8 @@ class WPSEO_Premium_Popup {
$assets_uri = trailingslashit( plugin_dir_url( WPSEO_FILE ) );
/* translators: %s expands to Yoast SEO Premium */
$cta_text = esc_html( sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' ) );
$cta_text = esc_html( sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' ) );
/* translators: Hidden accessibility text. */
$new_tab_message = '<span class="screen-reader-text">' . esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ) . '</span>';
$caret_icon = '<span aria-hidden="true" class="yoast-button-upsell__caret"></span>';
$classes = '';

View File

@@ -5,6 +5,8 @@
* @package WPSEO\Admin
*/
use Yoast\WP\SEO\Promotions\Application\Promotion_Manager;
/**
* Class WPSEO_Premium_Upsell_Admin_Block
*/
@@ -51,10 +53,12 @@ class WPSEO_Premium_Upsell_Admin_Block {
$url = WPSEO_Shortlinker::get( 'https://yoa.st/17h' );
$arguments = [
'<strong>' . esc_html__( 'Multiple keyphrases', 'wordpress-seo' ) . '</strong>: ' . esc_html__( 'Increase your SEO reach', 'wordpress-seo' ),
'<strong>' . esc_html__( 'Use AI', 'wordpress-seo' ) . '</strong>: ' . esc_html__( 'Quickly create titles & meta descriptions', 'wordpress-seo' ),
'<strong>' . esc_html__( 'No more dead links', 'wordpress-seo' ) . '</strong>: ' . esc_html__( 'Easy redirect manager', 'wordpress-seo' ),
'<strong>' . esc_html__( 'Superfast internal linking suggestions', 'wordpress-seo' ) . '</strong>',
'<strong>' . esc_html__( 'Social media preview', 'wordpress-seo' ) . '</strong>: ' . esc_html__( 'Facebook & Twitter', 'wordpress-seo' ),
'<strong>' . esc_html__( 'Multiple keyphrases', 'wordpress-seo' ) . '</strong>: ' . esc_html__( 'Increase your SEO reach', 'wordpress-seo' ),
'<strong>' . esc_html__( 'SEO Workouts', 'wordpress-seo' ) . '</strong>: ' . esc_html__( 'Get guided in routine SEO tasks', 'wordpress-seo' ),
'<strong>' . esc_html__( '24/7 email support', 'wordpress-seo' ) . '</strong>',
'<strong>' . esc_html__( 'No ads!', 'wordpress-seo' ) . '</strong>',
];
@@ -64,12 +68,13 @@ class WPSEO_Premium_Upsell_Admin_Block {
$class = $this->get_html_class();
/* translators: %s expands to Yoast SEO Premium */
$button_text = sprintf( esc_html__( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' );
$button_text = YoastSEO()->classes->get( Promotion_Manager::class )->is( 'black-friday-2023-promotion' ) ? \esc_html__( 'Claim your 30% off now!', 'wordpress-seo' ) : sprintf( esc_html__( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' );
/* translators: Hidden accessibility text. */
$button_text .= '<span class="screen-reader-text">' . esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ) . '</span>' .
'<span aria-hidden="true" class="yoast-button-upsell__caret"></span>';
$upgrade_button = sprintf(
'<a id="%1$s" class="yoast-button-upsell" href="%2$s" target="_blank">%3$s</a>',
'<a id="%1$s" class="yoast-button-upsell" data-action="load-nfd-ctb" data-ctb-id="f6a84663-465f-4cb5-8ba5-f7a6d72224b2" href="%2$s" target="_blank">%3$s</a>',
esc_attr( 'wpseo-' . $this->identifier . '-popup-button' ),
esc_url( $url ),
$button_text
@@ -77,7 +82,14 @@ class WPSEO_Premium_Upsell_Admin_Block {
echo '<div class="' . esc_attr( $class ) . '">';
echo '<div>';
if ( YoastSEO()->classes->get( Promotion_Manager::class )->is( 'black-friday-2023-promotion' ) ) {
$bf_label = \esc_html__( 'BLACK FRIDAY', 'wordpress-seo' );
$sale_label = \esc_html__( '30% OFF', 'wordpress-seo' );
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Already escaped above.
echo "<div class='black-friday-container'><span>$bf_label</span> <span style='margin-left: auto;'>$sale_label</span> </div>";
}
echo '<div class="' . esc_attr( $class . '--container' ) . '">';
echo '<h2 class="' . esc_attr( $class . '--header' ) . '">' .
sprintf(
/* translators: %s expands to Yoast SEO Premium */

View File

@@ -27,9 +27,11 @@ class WPSEO_Primary_Term_Admin implements WPSEO_WordPress_Integration {
* @return int The post ID.
*/
protected function get_current_id() {
$post_id = filter_input( INPUT_GET, 'post', FILTER_SANITIZE_NUMBER_INT );
if ( empty( $post_id ) && isset( $GLOBALS['post_ID'] ) ) {
$post_id = filter_var( $GLOBALS['post_ID'], FILTER_SANITIZE_NUMBER_INT );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information, We are casting to an integer.
$post_id = isset( $_GET['post'] ) && is_string( $_GET['post'] ) ? (int) wp_unslash( $_GET['post'] ) : 0;
if ( $post_id === 0 && isset( $GLOBALS['post_ID'] ) ) {
$post_id = (int) $GLOBALS['post_ID'];
}
return $post_id;

View File

@@ -64,14 +64,22 @@ class WPSEO_Product_Upsell_Notice {
* Listener for the upsell notice.
*/
public function dismiss_notice_listener() {
if ( filter_input( INPUT_GET, 'yoast_dismiss' ) !== 'upsell' ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are validating a nonce here.
if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'dismiss-5star-upsell' ) ) {
return;
}
$dismiss_upsell = isset( $_GET['yoast_dismiss'] ) && is_string( $_GET['yoast_dismiss'] ) ? sanitize_text_field( wp_unslash( $_GET['yoast_dismiss'] ) ) : '';
if ( $dismiss_upsell !== 'upsell' ) {
return;
}
$this->dismiss_notice();
wp_safe_redirect( admin_url( 'admin.php?page=wpseo_dashboard' ) );
exit;
if ( wp_safe_redirect( admin_url( 'admin.php?page=wpseo_dashboard' ) ) ) {
exit;
}
}
/**
@@ -158,7 +166,7 @@ class WPSEO_Product_Upsell_Notice {
$message .= $this->get_premium_upsell_section() . "\n\n";
$message .= '<a class="button" href="' . admin_url( '?page=' . WPSEO_Admin::PAGE_IDENTIFIER . '&yoast_dismiss=upsell' ) . '">' . __( 'Please don\'t show me this notification anymore', 'wordpress-seo' ) . '</a>';
$message .= '<a class="button" href="' . wp_nonce_url( admin_url( '?page=' . WPSEO_Admin::PAGE_IDENTIFIER . '&yoast_dismiss=upsell' ), 'dismiss-5star-upsell' ) . '">' . __( 'Please don\'t show me this notification anymore', 'wordpress-seo' ) . '</a>';
$notification = new Yoast_Notification(
$message,

View File

@@ -6,7 +6,8 @@
*/
/**
* Notifies the user to update the Person on the publish entity in the Configuration Wizard.
* Notifies the user to update the Search Appearance settings when the site is set to represent a Person,
* but no person (name) has been chosen.
*/
class WPSEO_Schema_Person_Upgrade_Notification implements WPSEO_WordPress_Integration {
@@ -55,9 +56,9 @@ class WPSEO_Schema_Person_Upgrade_Notification implements WPSEO_WordPress_Integr
*/
protected function get_notification() {
$message = sprintf(
/* translators: %1$s is a link start tag to the Configuration Wizard, %2$s is the link closing tag. */
/* translators: %1$s is a link start tag to the Search Appearance settings, %2$s is the link closing tag. */
__( 'You have previously set your site to represent a person. Weve improved our functionality around Schema and the Knowledge Graph, so you should go in and %1$scomplete those settings%2$s.', 'wordpress-seo' ),
'<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_titles' ) ) . '">',
'<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_page_settings#/site-representation' ) ) . '">',
'</a>'
);

View File

@@ -61,10 +61,9 @@ class WPSEO_Suggested_Plugins implements WPSEO_WordPress_Integration {
continue;
}
$dependency_names = $checker->get_dependency_names( $plugin );
$notification = $this->get_yoast_seo_suggested_plugins_notification( $plugin_name, $plugin, $dependency_names[0] );
$notification = $this->get_yoast_seo_suggested_plugins_notification( $plugin_name, $plugin );
if ( ! $checker->is_installed( $plugin ) || ! $checker->is_active( $plugin['slug'] ) ) {
if ( ! $checker->is_installed( $plugin ) ) {
$this->notification_center->add_notification( $notification );
continue;
@@ -77,17 +76,16 @@ class WPSEO_Suggested_Plugins implements WPSEO_WordPress_Integration {
/**
* Build Yoast SEO suggested plugins notification.
*
* @param string $name The plugin name to use for the unique ID.
* @param array $plugin The plugin to retrieve the data from.
* @param string $dependency_name The name of the dependency.
* @param string $name The plugin name to use for the unique ID.
* @param array $plugin The plugin to retrieve the data from.
*
* @return Yoast_Notification The notification containing the suggested plugin.
*/
protected function get_yoast_seo_suggested_plugins_notification( $name, $plugin, $dependency_name ) {
$message = $this->create_install_suggested_plugin_message( $plugin, $dependency_name );
protected function get_yoast_seo_suggested_plugins_notification( $name, $plugin ) {
$message = $this->create_install_suggested_plugin_message( $plugin );
if ( $this->availability_checker->is_installed( $plugin ) && ! $this->availability_checker->is_active( $plugin['slug'] ) ) {
$message = $this->create_activate_suggested_plugin_message( $plugin, $dependency_name );
$message = '';
}
return new Yoast_Notification(
@@ -103,22 +101,22 @@ class WPSEO_Suggested_Plugins implements WPSEO_WordPress_Integration {
/**
* Creates a message to suggest the installation of a particular plugin.
*
* @param array $suggested_plugin The suggested plugin.
* @param array $third_party_plugin The third party plugin that we have a suggested plugin for.
* @param array $suggested_plugin The suggested plugin.
*
* @return string The install suggested plugin message.
*/
protected function create_install_suggested_plugin_message( $suggested_plugin, $third_party_plugin ) {
/* translators: %1$s expands to Yoast SEO, %2$s expands to the dependency name, %3$s expands to the install link, %4$s expands to the more info link. */
$message = __( '%1$s and %2$s can work together a lot better by adding a helper plugin. Please install %3$s to make your life better. %4$s.', 'wordpress-seo' );
protected function create_install_suggested_plugin_message( $suggested_plugin ) {
/* translators: %1$s expands to an opening strong tag, %2$s expands to the dependency name, %3$s expands to a closing strong tag, %4$s expands to an opening anchor tag, %5$s expands to a closing anchor tag. */
$message = __( 'It looks like you aren\'t using our %1$s%2$s addon%3$s. %4$sUpgrade today%5$s to unlock more tools and SEO features to make your products stand out in search results.', 'wordpress-seo' );
$install_link = WPSEO_Admin_Utils::get_install_link( $suggested_plugin );
return sprintf(
$message,
'Yoast SEO',
$third_party_plugin,
'<strong>',
$install_link,
$this->create_more_information_link( $suggested_plugin['url'], $suggested_plugin['title'] )
'</strong>',
$this->create_more_information_link( $suggested_plugin['url'], $suggested_plugin['title'] ),
'</a>'
);
}
@@ -132,32 +130,10 @@ class WPSEO_Suggested_Plugins implements WPSEO_WordPress_Integration {
*/
protected function create_more_information_link( $url, $name ) {
return sprintf(
'<a href="%s" aria-label="%s" target="_blank" rel="noopener noreferrer">%s</a>',
'<a href="%s" aria-label="%s" target="_blank" rel="noopener noreferrer">',
$url,
/* translators: %1$s expands to the dependency name. */
sprintf( __( 'More information about %1$s', 'wordpress-seo' ), $name ),
__( 'More information', 'wordpress-seo' )
);
}
/**
* Creates a message to suggest the activation of a particular plugin.
*
* @param array $suggested_plugin The suggested plugin.
* @param array $third_party_plugin The third party plugin that we have a suggested plugin for.
*
* @return string The activate suggested plugin message.
*/
protected function create_activate_suggested_plugin_message( $suggested_plugin, $third_party_plugin ) {
/* translators: %1$s expands to Yoast SEO, %2$s expands to the dependency name, %3$s expands to activation link. */
$message = __( '%1$s and %2$s can work together a lot better by adding a helper plugin. Please activate %3$s to make your life better.', 'wordpress-seo' );
$activation_url = WPSEO_Admin_Utils::get_activation_url( $suggested_plugin['slug'] );
return sprintf(
$message,
'Yoast SEO',
$third_party_plugin,
sprintf( '<a href="%s">%s</a>', $activation_url, $suggested_plugin['title'] )
/* translators: Hidden accessibility text; %1$s expands to the dependency name */
sprintf( __( 'More information about %1$s', 'wordpress-seo' ), $name )
);
}
}

View File

@@ -0,0 +1,128 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
*/
/**
* Wincher dashboard widget.
*/
class Wincher_Dashboard_Widget implements WPSEO_WordPress_Integration {
/**
* Holds an instance of the admin asset manager.
*
* @var WPSEO_Admin_Asset_Manager
*/
protected $asset_manager;
/**
* Wincher_Dashboard_Widget constructor.
*/
public function __construct() {
$this->asset_manager = new WPSEO_Admin_Asset_Manager();
}
/**
* Register WordPress hooks.
*/
public function register_hooks() {
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_wincher_dashboard_assets' ] );
add_action( 'admin_init', [ $this, 'queue_wincher_dashboard_widget' ] );
}
/**
* Adds the Wincher dashboard widget if it should be shown.
*
* @return void
*/
public function queue_wincher_dashboard_widget() {
if ( $this->show_widget() ) {
add_action( 'wp_dashboard_setup', [ $this, 'add_wincher_dashboard_widget' ] );
}
}
/**
* Adds the Wincher dashboard widget to WordPress.
*/
public function add_wincher_dashboard_widget() {
add_filter( 'postbox_classes_dashboard_wpseo-wincher-dashboard-overview', [ $this, 'wpseo_wincher_dashboard_overview_class' ] );
wp_add_dashboard_widget(
'wpseo-wincher-dashboard-overview',
/* translators: %1$s expands to Yoast SEO, %2$s to Wincher */
sprintf( __( '%1$s / %2$s: Top Keyphrases', 'wordpress-seo' ), 'Yoast SEO', 'Wincher' ),
[ $this, 'display_wincher_dashboard_widget' ]
);
}
/**
* Adds CSS classes to the dashboard widget.
*
* @param array $classes An array of postbox CSS classes.
*
* @return array
*/
public function wpseo_wincher_dashboard_overview_class( $classes ) {
$classes[] = 'yoast wpseo-wincherdashboard-overview';
return $classes;
}
/**
* Displays the Wincher dashboard widget.
*/
public function display_wincher_dashboard_widget() {
echo '<div id="yoast-seo-wincher-dashboard-widget"></div>';
}
/**
* Enqueues assets for the dashboard if the current page is the dashboard.
*/
public function enqueue_wincher_dashboard_assets() {
if ( ! $this->is_dashboard_screen() ) {
return;
}
$this->asset_manager->localize_script( 'wincher-dashboard-widget', 'wpseoWincherDashboardWidgetL10n', $this->localize_wincher_dashboard_script() );
$this->asset_manager->enqueue_script( 'wincher-dashboard-widget' );
$this->asset_manager->enqueue_style( 'wp-dashboard' );
$this->asset_manager->enqueue_style( 'monorepo' );
}
/**
* Translates strings used in the Wincher dashboard widget.
*
* @return array The translated strings.
*/
public function localize_wincher_dashboard_script() {
return [
'wincher_is_logged_in' => YoastSEO()->helpers->wincher->login_status(),
'wincher_website_id' => WPSEO_Options::get( 'wincher_website_id', '' ),
];
}
/**
* Checks if the current screen is the dashboard screen.
*
* @return bool Whether or not this is the dashboard screen.
*/
private function is_dashboard_screen() {
$current_screen = get_current_screen();
return ( $current_screen instanceof WP_Screen && $current_screen->id === 'dashboard' );
}
/**
* Returns true when the Wincher dashboard widget should be shown.
*
* @return bool
*/
private function show_widget() {
$analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$user_can_edit = $analysis_seo->is_enabled() && current_user_can( 'edit_posts' );
$is_wincher_active = YoastSEO()->helpers->wincher->is_active();
return $user_can_edit && $is_wincher_active;
}
}

View File

@@ -71,17 +71,22 @@ class WPSEO_Yoast_Columns implements WPSEO_WordPress_Integration {
* @return string The current post type.
*/
private function get_current_post_type() {
return filter_input( INPUT_GET, 'post_type' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['post_type'] ) && is_string( $_GET['post_type'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
return sanitize_text_field( wp_unslash( $_GET['post_type'] ) );
}
return '';
}
/**
* Whether or not we are showing link columns on this overview page.
* Whether we are showing link columns on this overview page.
* This depends on the post being accessible or not.
*
* @return bool Whether or not the linking columns are shown
* @return bool Whether the linking columns are shown
*/
private function display_links() {
$current_post_type = sanitize_text_field( $this->get_current_post_type() );
$current_post_type = $this->get_current_post_type();
if ( empty( $current_post_type ) ) {
return false;
@@ -94,10 +99,10 @@ class WPSEO_Yoast_Columns implements WPSEO_WordPress_Integration {
* Wraps the WPSEO_Metabox check to determine whether the metabox should be displayed either by
* choice of the admin or because the post type is not a public post type.
*
* @return bool Whether or not the meta box (and associated columns etc) should be hidden.
* @return bool Whether the meta box (and associated columns etc) should be hidden.
*/
private function display_meta_columns() {
$current_post_type = sanitize_text_field( $this->get_current_post_type() );
$current_post_type = $this->get_current_post_type();
if ( empty( $current_post_type ) ) {
return false;

View File

@@ -105,10 +105,9 @@ class Yoast_Dashboard_Widget implements WPSEO_WordPress_Integration {
}
$this->asset_manager->localize_script( 'dashboard-widget', 'wpseoDashboardWidgetL10n', $this->localize_dashboard_script() );
$yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_L10n();
$yoast_components_l10n->localize_script( 'dashboard-widget' );
$this->asset_manager->enqueue_script( 'dashboard-widget' );
$this->asset_manager->enqueue_style( 'wp-dashboard' );
$this->asset_manager->enqueue_style( 'monorepo' );
}
/**
@@ -118,14 +117,14 @@ class Yoast_Dashboard_Widget implements WPSEO_WordPress_Integration {
*/
public function localize_dashboard_script() {
return [
'feed_header' => sprintf(
'feed_header' => sprintf(
/* translators: %1$s resolves to Yoast.com */
__( 'Latest blog posts on %1$s', 'wordpress-seo' ),
'Yoast.com'
),
'feed_footer' => __( 'Read more like this on our SEO blog', 'wordpress-seo' ),
'wp_version' => substr( $GLOBALS['wp_version'], 0, 3 ) . '-' . ( is_plugin_active( 'classic-editor/classic-editor.php' ) ? '1' : '0' ),
'php_version' => PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION,
'feed_footer' => __( 'Read more like this on our SEO blog', 'wordpress-seo' ),
'wp_version' => substr( $GLOBALS['wp_version'], 0, 3 ) . '-' . ( is_plugin_active( 'classic-editor/classic-editor.php' ) ? '1' : '0' ),
'php_version' => PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION,
];
}

View File

@@ -6,6 +6,7 @@
*/
use Yoast\WP\SEO\Presenters\Admin\Light_Switch_Presenter;
use Yoast\WP\SEO\Presenters\Admin\Sidebar_Presenter;
/**
* Admin form class.
@@ -79,6 +80,7 @@ class Yoast_Form {
require_once ABSPATH . 'wp-admin/options-head.php';
?>
<h1 id="wpseo-title"><?php echo esc_html( get_admin_page_title() ); ?></h1>
<div id="yst-settings-header-root"></div>
<div class="wpseo_content_wrapper">
<div class="wpseo_content_cell" id="wpseo_content_top">
<?php
@@ -98,7 +100,7 @@ class Yoast_Form {
echo '<form action="' .
esc_url( $action_url ) .
'" method="post" id="wpseo-conf"' .
$enctype . ' accept-charset="' .
$enctype . ' accept-charset="' . // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- nothing to escape.
esc_attr( get_bloginfo( 'charset' ) ) .
'" novalidate="novalidate">';
call_user_func( $hidden_fields_cb, $option_long_name );
@@ -188,7 +190,9 @@ class Yoast_Form {
return;
}
require_once 'views/sidebar.php';
$sidebar_presenter = new Sidebar_Presenter();
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in presenter.
echo $sidebar_presenter->present();
}
/**
@@ -196,7 +200,7 @@ class Yoast_Form {
*
* @since 2.0
*
* @param string $text Label text string.
* @param string $text Label text string, which can contain escaped html.
* @param array $attr HTML attributes set.
*/
public function label( $text, $attr ) {
@@ -213,6 +217,7 @@ class Yoast_Form {
$aria_label = ' aria-label="' . esc_attr( $attr['aria_label'] ) . '"';
}
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before. Specifically, the $text variable can contain escaped html.
echo "<label class='" . esc_attr( $attr['class'] ) . "' for='" . esc_attr( $attr['for'] ) . "'$aria_label>$text";
if ( $attr['close'] ) {
echo '</label>';
@@ -235,7 +240,8 @@ class Yoast_Form {
$attr = wp_parse_args( $attr, $defaults );
$id = ( $attr['id'] === '' ) ? '' : ' id="' . esc_attr( $attr['id'] ) . '"';
echo '<legend class="yoast-form-legend ' . esc_attr( $attr['class'] ) . '"' . $id . '>' . $text . '</legend>';
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
echo '<legend class="' . esc_attr( 'yoast-form-legend ' . $attr['class'] ) . '"' . $id . '>' . $text . '</legend>';
}
/**
@@ -243,13 +249,13 @@ class Yoast_Form {
*
* @since 2.0
*
* @param string $var The variable within the option to create the checkbox for.
* @param string $variable The variable within the option to create the checkbox for.
* @param string $label The label to show for the variable.
* @param bool $label_left Whether the label should be left (true) or right (false).
* @param array $attr Extra attributes to add to the checkbox.
*/
public function checkbox( $var, $label, $label_left = false, $attr = [] ) {
$val = $this->get_field_value( $var, false );
public function checkbox( $variable, $label, $label_left = false, $attr = [] ) {
$val = $this->get_field_value( $variable, false );
$defaults = [
'disabled' => false,
@@ -262,19 +268,19 @@ class Yoast_Form {
$class = '';
if ( $label_left !== false ) {
$this->label( $label_left, [ 'for' => $var ] );
$this->label( $label_left, [ 'for' => $variable ] );
}
else {
$class = 'double';
}
$disabled_attribute = $this->get_disabled_attribute( $var, $attr );
$disabled_attribute = $this->get_disabled_attribute( $variable, $attr );
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped.
echo '<input class="checkbox ', esc_attr( $class ), '" type="checkbox" id="', esc_attr( $var ), '" name="', esc_attr( $this->option_name ), '[', esc_attr( $var ), ']" value="on"', checked( $val, 'on', false ), $disabled_attribute, '/>';
echo '<input class="', esc_attr( 'checkbox ' . $class ), '" type="checkbox" id="', esc_attr( $variable ), '" name="', esc_attr( $this->option_name . '[' . $variable . ']' ), '" value="on"', checked( $val, 'on', false ), $disabled_attribute, '/>';
if ( ! empty( $label ) ) {
$this->label( $label, [ 'for' => $var ] );
$this->label( $label, [ 'for' => $variable ] );
}
echo '<br class="clear" />';
@@ -301,7 +307,7 @@ class Yoast_Form {
printf(
'<input class="checkbox double" id="%1$s" type="checkbox" name="%2$s" %3$s %5$s value="%4$s"/>',
esc_attr( $variable . '-' . $name ),
esc_attr( $this->option_name ) . '[' . esc_attr( $variable ) . '][' . $name . ']',
esc_attr( $this->option_name . '[' . $variable . '][' . $name . ']' ),
checked( ! empty( $values[ $name ] ), true, false ),
esc_attr( $name ),
disabled( ( isset( $attr['disabled'] ) && $attr['disabled'] ), true, false )
@@ -321,16 +327,17 @@ class Yoast_Form {
*
* @since 3.1
*
* @param string $var The variable within the option to create the checkbox for.
* @param string $label The visual label text for the toggle.
* @param array $buttons Array of two visual labels for the buttons (defaults Disabled/Enabled).
* @param bool $reverse Reverse order of buttons (default true).
* @param string $help Inline Help that will be printed out before the toggle.
* @param bool $strong Whether the visual label is displayed in strong text. Default is false.
* @param array $attr Extra attributes to add to the light switch.
* @param string $variable The variable within the option to create the checkbox for.
* @param string $label The visual label text for the toggle.
* @param array $buttons Array of two visual labels for the buttons (defaults Disabled/Enabled).
* @param bool $reverse Reverse order of buttons (default true).
* @param string $help Inline Help that will be printed out before the toggle.
* @param bool $strong Whether the visual label is displayed in strong text. Default is false.
* Starting from Yoast SEO 16.5, the visual label is forced to bold via CSS.
* @param array $attr Extra attributes to add to the light switch.
*/
public function light_switch( $var, $label, $buttons = [], $reverse = true, $help = '', $strong = false, $attr = [] ) {
$val = $this->get_field_value( $var, false );
public function light_switch( $variable, $label, $buttons = [], $reverse = true, $help = '', $strong = false, $attr = [] ) {
$val = $this->get_field_value( $variable, false );
$defaults = [
'disabled' => false,
@@ -341,13 +348,13 @@ class Yoast_Form {
$val = 'on';
}
$disabled_attribute = $this->get_disabled_attribute( $var, $attr );
$disabled_attribute = $this->get_disabled_attribute( $variable, $attr );
$output = new Light_Switch_Presenter(
$var,
$variable,
$label,
$buttons,
$this->option_name . '[' . $var . ']',
$this->option_name . '[' . $variable . ']',
$val,
$reverse,
$help,
@@ -365,11 +372,11 @@ class Yoast_Form {
* @since 2.0
* @since 2.1 Introduced the `$attr` parameter.
*
* @param string $var The variable within the option to create the text input field for.
* @param string $label The label to show for the variable.
* @param array|string $attr Extra attributes to add to the input field. Can be class, disabled, autocomplete.
* @param string $variable The variable within the option to create the text input field for.
* @param string $label The label to show for the variable.
* @param array|string $attr Extra attributes to add to the input field. Can be class, disabled, autocomplete.
*/
public function textinput( $var, $label, $attr = [] ) {
public function textinput( $variable, $label, $attr = [] ) {
$type = 'text';
if ( ! is_array( $attr ) ) {
$attr = [
@@ -383,7 +390,7 @@ class Yoast_Form {
'class' => '',
];
$attr = wp_parse_args( $attr, $defaults );
$val = $this->get_field_value( $var, '' );
$val = $this->get_field_value( $variable, '' );
if ( isset( $attr['type'] ) && $attr['type'] === 'url' ) {
$val = urldecode( $val );
$type = 'url';
@@ -393,34 +400,74 @@ class Yoast_Form {
$this->label(
$label,
[
'for' => $var,
'for' => $variable,
'class' => 'textinput',
]
);
$has_input_error = Yoast_Input_Validation::yoast_form_control_has_error( $var );
$aria_attributes = Yoast_Input_Validation::get_the_aria_invalid_attribute( $var );
$aria_attributes = Yoast_Input_Validation::get_the_aria_invalid_attribute( $variable );
Yoast_Input_Validation::set_error_descriptions();
$aria_attributes .= Yoast_Input_Validation::get_the_aria_describedby_attribute( $var );
$aria_attributes .= Yoast_Input_Validation::get_the_aria_describedby_attribute( $variable );
$disabled_attribute = $this->get_disabled_attribute( $var, $attr );
$disabled_attribute = $this->get_disabled_attribute( $variable, $attr );
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped.
echo '<input' . $attributes . $aria_attributes . ' class="textinput ' . esc_attr( $attr['class'] ) . '" placeholder="' . esc_attr( $attr['placeholder'] ) . '" type="' . $type . '" id="', esc_attr( $var ), '" name="', esc_attr( $this->option_name ), '[', esc_attr( $var ), ']" value="', esc_attr( $val ), '"', $disabled_attribute, '/>', '<br class="clear" />';
echo Yoast_Input_Validation::get_the_error_description( $var );
echo '<input', $attributes, $aria_attributes, ' class="', esc_attr( 'textinput ' . $attr['class'] ), '" placeholder="', esc_attr( $attr['placeholder'] ), '" type="', $type, '" id="', esc_attr( $variable ), '" name="', esc_attr( $this->option_name . '[' . $variable . ']' ), '" value="', esc_attr( $val ), '"', $disabled_attribute, '/>', '<br class="clear" />';
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in getter.
echo Yoast_Input_Validation::get_the_error_description( $variable );
}
/**
* Create a Number input field.
*
* @param string $variable The variable within the option to create the text input field for.
* @param string $label The label to show for the variable.
* @param array|string $attr Extra attributes to add to the input field. Can be class, disabled, autocomplete.
*/
public function number( $variable, $label, $attr = [] ) {
$type = 'number';
$defaults = [
'placeholder' => '',
'class' => 'number',
'disabled' => false,
'min' => 0,
'max' => 100,
];
$attr = wp_parse_args( $attr, $defaults );
$val = $this->get_field_value( $variable, 0 );
$this->label(
$label,
[
'for' => $variable,
'class' => 'textinput ' . $attr['class'],
]
);
$aria_attributes = Yoast_Input_Validation::get_the_aria_invalid_attribute( $variable );
Yoast_Input_Validation::set_error_descriptions();
$aria_attributes .= Yoast_Input_Validation::get_the_aria_describedby_attribute( $variable );
$disabled_attribute = $this->get_disabled_attribute( $variable, $attr );
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped.
echo '<input' . $aria_attributes . ' class="' . esc_attr( $attr['class'] ) . '" type="' . $type . '" id="', esc_attr( $variable ), '" min="', esc_attr( $attr['min'] ), '" max="', esc_attr( $attr['max'] ), '" name="', esc_attr( $this->option_name . '[' . $variable . ']' ), '" value="', esc_attr( $val ), '"', $disabled_attribute, '/>', '<br class="clear" />';
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in getter.
echo Yoast_Input_Validation::get_the_error_description( $variable );
}
/**
* Creates a text input field with with the ability to add content after the label.
*
* @param string $var The variable within the option to create the text input field for.
* @param string $label The label to show for the variable.
* @param array $attr Extra attributes to add to the input field.
* @param string $variable The variable within the option to create the text input field for.
* @param string $label The label to show for the variable.
* @param array $attr Extra attributes to add to the input field.
*
* @return void
*/
public function textinput_extra_content( $var, $label, $attr = [] ) {
public function textinput_extra_content( $variable, $label, $attr = [] ) {
$type = 'text';
$defaults = [
@@ -429,7 +476,7 @@ class Yoast_Form {
];
$attr = \wp_parse_args( $attr, $defaults );
$val = $this->get_field_value( $var, '' );
$val = $this->get_field_value( $variable, '' );
if ( isset( $attr['type'] ) && $attr['type'] === 'url' ) {
$val = urldecode( $val );
@@ -440,7 +487,7 @@ class Yoast_Form {
$this->label(
$label,
[
'for' => $var,
'for' => $variable,
'class' => $attr['class'] . '--label',
]
);
@@ -451,28 +498,28 @@ class Yoast_Form {
}
echo '</div>';
$has_input_error = Yoast_Input_Validation::yoast_form_control_has_error( $var );
$aria_attributes = Yoast_Input_Validation::get_the_aria_invalid_attribute( $var );
$has_input_error = Yoast_Input_Validation::yoast_form_control_has_error( $variable );
$aria_attributes = Yoast_Input_Validation::get_the_aria_invalid_attribute( $variable );
Yoast_Input_Validation::set_error_descriptions();
$aria_attributes .= Yoast_Input_Validation::get_the_aria_describedby_attribute( $var );
$aria_attributes .= Yoast_Input_Validation::get_the_aria_describedby_attribute( $variable );
// phpcs:disable WordPress.Security.EscapeOutput -- Reason: output is properly escaped or hardcoded.
printf(
'<input type="%1$s" name="%2$s" id="%3$s" class="%4$s"%5$s%6$s%7$s value="%8$s"%9$s>',
$type,
\esc_attr( $this->option_name ) . '[' . \esc_attr( $var ) . ']',
\esc_attr( $var ),
\esc_attr( $this->option_name . '[' . $variable . ']' ),
\esc_attr( $variable ),
\esc_attr( $attr['class'] ),
isset( $attr['placeholder'] ) ? ' placeholder="' . \esc_attr( $attr['placeholder'] ) . '"' : '',
isset( $attr['autocomplete'] ) ? ' autocomplete="' . \esc_attr( $attr['autocomplete'] ) . '"' : '',
$aria_attributes,
\esc_attr( $val ),
$this->get_disabled_attribute( $var, $attr )
$this->get_disabled_attribute( $variable, $attr )
);
// phpcs:enable
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: output is properly escaped.
echo Yoast_Input_Validation::get_the_error_description( $var );
echo Yoast_Input_Validation::get_the_error_description( $variable );
}
/**
@@ -480,11 +527,11 @@ class Yoast_Form {
*
* @since 2.0
*
* @param string $var The variable within the option to create the textarea for.
* @param string $label The label to show for the variable.
* @param string|array $attr The CSS class or an array of attributes to assign to the textarea.
* @param string $variable The variable within the option to create the textarea for.
* @param string $label The label to show for the variable.
* @param string|array $attr The CSS class or an array of attributes to assign to the textarea.
*/
public function textarea( $var, $label, $attr = [] ) {
public function textarea( $variable, $label, $attr = [] ) {
if ( ! is_array( $attr ) ) {
$attr = [
'class' => $attr,
@@ -498,20 +545,20 @@ class Yoast_Form {
'disabled' => false,
];
$attr = wp_parse_args( $attr, $defaults );
$val = $this->get_field_value( $var, '' );
$val = $this->get_field_value( $variable, '' );
$this->label(
$label,
[
'for' => $var,
'for' => $variable,
'class' => 'textinput',
]
);
$disabled_attribute = $this->get_disabled_attribute( $var, $attr );
$disabled_attribute = $this->get_disabled_attribute( $variable, $attr );
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped.
echo '<textarea cols="' . esc_attr( $attr['cols'] ) . '" rows="' . esc_attr( $attr['rows'] ) . '" class="textinput ' . esc_attr( $attr['class'] ) . '" id="' . esc_attr( $var ) . '" name="' . esc_attr( $this->option_name ) . '[' . esc_attr( $var ) . ']"', $disabled_attribute, '>' . esc_textarea( $val ) . '</textarea><br class="clear" />';
echo '<textarea cols="' . esc_attr( $attr['cols'] ) . '" rows="' . esc_attr( $attr['rows'] ) . '" class="' . esc_attr( 'textinput ' . $attr['class'] ) . '" id="' . esc_attr( $variable ) . '" name="' . esc_attr( $this->option_name . '[' . $variable . ']' ), '"', $disabled_attribute, '>' . esc_textarea( $val ) . '</textarea><br class="clear" />';
}
/**
@@ -519,20 +566,24 @@ class Yoast_Form {
*
* @since 2.0
*
* @param string $var The variable within the option to create the hidden input for.
* @param string $id The ID of the element.
* @param string $variable The variable within the option to create the hidden input for.
* @param string $id The ID of the element.
* @param mixed $val Optional. The value to set in the input field. Otherwise the value from the options will be used.
*/
public function hidden( $var, $id = '' ) {
$val = $this->get_field_value( $var, '' );
public function hidden( $variable, $id = '', $val = null ) {
if ( is_null( $val ) ) {
$val = $this->get_field_value( $variable, '' );
}
if ( is_bool( $val ) ) {
$val = ( $val === true ) ? 'true' : 'false';
}
if ( $id === '' ) {
$id = 'hidden_' . $var;
$id = 'hidden_' . $variable;
}
echo '<input type="hidden" id="' . esc_attr( $id ) . '" name="' . esc_attr( $this->option_name ) . '[' . esc_attr( $var ) . ']" value="' . esc_attr( $val ) . '"/>';
echo '<input type="hidden" id="' . esc_attr( $id ) . '" name="' . esc_attr( $this->option_name . '[' . $variable . ']' ), '" value="' . esc_attr( $val ) . '"/>';
}
/**
@@ -540,7 +591,7 @@ class Yoast_Form {
*
* @since 2.0
*
* @param string $var The variable within the option to create the select for.
* @param string $variable The variable within the option to create the select for.
* @param string $label The label to show for the variable.
* @param array $select_options The select options to choose from.
* @param string $styled The select style. Use 'styled' to get a styled select. Default 'unstyled'.
@@ -548,7 +599,7 @@ class Yoast_Form {
* @param array $attr Extra attributes to add to the select.
* @param string $help Optional. Inline Help HTML that will be printed after the label. Default is empty.
*/
public function select( $var, $label, array $select_options, $styled = 'unstyled', $show_label = true, $attr = [], $help = '' ) {
public function select( $variable, $label, array $select_options, $styled = 'unstyled', $show_label = true, $attr = [], $help = '' ) {
if ( empty( $select_options ) ) {
return;
}
@@ -562,22 +613,22 @@ class Yoast_Form {
$this->label(
$label,
[
'for' => $var,
'for' => $variable,
'class' => 'select',
]
);
echo $help; // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: The help contains HTML.
}
$select_name = esc_attr( $this->option_name ) . '[' . esc_attr( $var ) . ']';
$active_option = $this->get_field_value( $var, '' );
$select_name = esc_attr( $this->option_name ) . '[' . esc_attr( $variable ) . ']';
$active_option = $this->get_field_value( $variable, '' );
$wrapper_start_tag = '';
$wrapper_end_tag = '';
$select = new Yoast_Input_Select( $var, $select_name, $select_options, $active_option );
$select = new Yoast_Input_Select( $variable, $select_name, $select_options, $active_option );
$select->add_attribute( 'class', 'select' );
if ( $this->is_control_disabled( $var )
if ( $this->is_control_disabled( $variable )
|| ( isset( $attr['disabled'] ) && $attr['disabled'] ) ) {
$select->add_attribute( 'disabled', 'disabled' );
}
@@ -591,8 +642,10 @@ class Yoast_Form {
$wrapper_end_tag = '</span>';
}
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
echo $wrapper_start_tag;
$select->output_html();
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
echo $wrapper_end_tag;
echo '<br class="clear"/>';
}
@@ -602,12 +655,12 @@ class Yoast_Form {
*
* @since 2.0
*
* @param string $var The variable within the option to create the file upload field for.
* @param string $label The label to show for the variable.
* @param array $attr Extra attributes to add to the file upload input.
* @param string $variable The variable within the option to create the file upload field for.
* @param string $label The label to show for the variable.
* @param array $attr Extra attributes to add to the file upload input.
*/
public function file_upload( $var, $label, $attr = [] ) {
$val = $this->get_field_value( $var, '' );
public function file_upload( $variable, $label, $attr = [] ) {
$val = $this->get_field_value( $variable, '' );
if ( is_array( $val ) ) {
$val = $val['url'];
}
@@ -617,16 +670,16 @@ class Yoast_Form {
];
$attr = wp_parse_args( $attr, $defaults );
$var_esc = esc_attr( $var );
$var_esc = esc_attr( $variable );
$this->label(
$label,
[
'for' => $var,
'for' => $variable,
'class' => 'select',
]
);
$disabled_attribute = $this->get_disabled_attribute( $var, $attr );
$disabled_attribute = $this->get_disabled_attribute( $variable, $attr );
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped.
echo '<input type="file" value="' . esc_attr( $val ) . '" class="textinput" name="' . esc_attr( $this->option_name ) . '[' . $var_esc . ']" id="' . $var_esc . '"', $disabled_attribute, '/>';
@@ -645,15 +698,15 @@ class Yoast_Form {
*
* @since 2.0
*
* @param string $var Option name.
* @param string $label Label message.
* @param array $attr Extra attributes to add to the media input and buttons.
* @param string $variable Option name.
* @param string $label Label message.
* @param array $attr Extra attributes to add to the media input and buttons.
*/
public function media_input( $var, $label, $attr = [] ) {
$val = $this->get_field_value( $var, '' );
$id_value = $this->get_field_value( $var . '_id', '' );
public function media_input( $variable, $label, $attr = [] ) {
$val = $this->get_field_value( $variable, '' );
$id_value = $this->get_field_value( $variable . '_id', '' );
$var_esc = esc_attr( $var );
$var_esc = esc_attr( $variable );
$defaults = [
'disabled' => false,
@@ -663,26 +716,26 @@ class Yoast_Form {
$this->label(
$label,
[
'for' => 'wpseo_' . $var,
'for' => 'wpseo_' . $variable,
'class' => 'select',
]
);
$id_field_id = 'wpseo_' . $var_esc . '_id';
$disabled_attribute = $this->get_disabled_attribute( $var, $attr );
$disabled_attribute = $this->get_disabled_attribute( $variable, $attr );
echo '<span>';
echo '<input',
' class="textinput"',
' id="wpseo_', $var_esc, '"',
' id="wpseo_', $var_esc, '"', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
' type="text" size="36"',
' name="', esc_attr( $this->option_name ), '[', $var_esc, ']"',
' name="', esc_attr( $this->option_name ), '[', $var_esc, ']"', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
' value="', esc_attr( $val ), '"',
' readonly="readonly"',
' /> ';
echo '<input',
' id="wpseo_', $var_esc, '_button"',
' id="wpseo_', $var_esc, '_button"', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
' class="wpseo_image_upload_button button"',
' type="button"',
' value="', esc_attr__( 'Upload Image', 'wordpress-seo' ), '"',
@@ -700,6 +753,7 @@ class Yoast_Form {
echo '<input',
' type="hidden"',
' id="', esc_attr( $id_field_id ), '"',
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
' name="', esc_attr( $this->option_name ), '[', $var_esc, '_id]"',
' value="', esc_attr( $id_value ), '"',
' />';
@@ -712,25 +766,26 @@ class Yoast_Form {
*
* @since 2.0
*
* @param string $var The variable within the option to create the radio button for.
* @param string $variable The variable within the option to create the radio button for.
* @param array $values The radio options to choose from.
* @param string $legend Optional. The legend to show for the field set, if any.
* @param array $legend_attr Optional. The attributes for the legend, if any.
* @param array $attr Extra attributes to add to the radio button.
*/
public function radio( $var, $values, $legend = '', $legend_attr = [], $attr = [] ) {
public function radio( $variable, $values, $legend = '', $legend_attr = [], $attr = [] ) {
if ( ! is_array( $values ) || $values === [] ) {
return;
}
$val = $this->get_field_value( $var, false );
$val = $this->get_field_value( $variable, false );
$var_esc = esc_attr( $var );
$var_esc = esc_attr( $variable );
$defaults = [
'disabled' => false,
];
$attr = wp_parse_args( $attr, $defaults );
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
echo '<fieldset class="yoast-form-fieldset wpseo_radio_block" id="' . $var_esc . '">';
if ( is_string( $legend ) && $legend !== '' ) {
@@ -756,7 +811,7 @@ class Yoast_Form {
$key_esc = esc_attr( $key );
$disabled_attribute = $this->get_disabled_attribute( $var, $attr );
$disabled_attribute = $this->get_disabled_attribute( $variable, $attr );
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped.
echo '<input type="radio" class="radio" id="' . $var_esc . '-' . $key_esc . '" name="' . esc_attr( $this->option_name ) . '[' . $var_esc . ']" value="' . $key_esc . '" ' . checked( $val, $key_esc, false ) . $disabled_attribute . ' />';
@@ -777,15 +832,15 @@ class Yoast_Form {
*
* @since 3.1
*
* @param string $var The variable within the option to create the radio buttons for.
* @param array $values Associative array of on/off keys and their values to be used as
* the label elements text for the radio buttons. Optionally, each
* value can be an array of visible label text and screen reader text.
* @param string $label The visual label for the radio buttons group, used as the fieldset legend.
* @param string $help Inline Help that will be printed out before the visible toggles text.
* @param array $attr Extra attributes to add to the toggle switch.
* @param string $variable The variable within the option to create the radio buttons for.
* @param array $values Associative array of on/off keys and their values to be used as
* the label elements text for the radio buttons. Optionally, each
* value can be an array of visible label text and screen reader text.
* @param string $label The visual label for the radio buttons group, used as the fieldset legend.
* @param string $help Inline Help that will be printed out before the visible toggles text.
* @param array $attr Extra attributes to add to the toggle switch.
*/
public function toggle_switch( $var, $values, $label, $help = '', $attr = [] ) {
public function toggle_switch( $variable, $values, $label, $help = '', $attr = [] ) {
if ( ! is_array( $values ) || $values === [] ) {
return;
}
@@ -795,7 +850,12 @@ class Yoast_Form {
];
$attr = wp_parse_args( $attr, $defaults );
$val = $this->get_field_value( $var, false );
if ( isset( $attr['preserve_disabled_value'] ) && $attr['preserve_disabled_value'] ) {
$this->hidden( $variable );
$variable .= '_disabled';
}
$val = $this->get_field_value( $variable, false );
if ( $val === true ) {
$val = 'on';
}
@@ -805,12 +865,27 @@ class Yoast_Form {
$help_class = ! empty( $help ) ? ' switch-container__has-help' : '';
$var_esc = esc_attr( $var );
$has_premium_upsell = ( isset( $attr['show_premium_upsell'] ) && $attr['show_premium_upsell'] && isset( $attr['premium_upsell_url'] ) && ! empty( $attr['premium_upsell_url'] ) );
$upsell_class = ( $has_premium_upsell ) ? ' premium-upsell' : '';
printf( '<div class="%s">', esc_attr( 'switch-container' . $help_class ) );
$var_esc = esc_attr( $variable );
printf( '<div class="%s">', esc_attr( 'switch-container' . $help_class . $upsell_class ) );
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
echo '<fieldset id="', $var_esc, '" class="fieldset-switch-toggle"><legend>', $label, '</legend>', $help;
echo $this->get_disabled_note( $var );
// Show disabled note if attribute does not exists or does exist and is set to true.
if ( ! isset( $attr['show_disabled_note'] ) || ( $attr['show_disabled_note'] === true ) ) {
if ( isset( $attr['note_when_disabled'] ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
echo $this->get_disabled_note( $variable, $attr['note_when_disabled'] );
}
else {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
echo $this->get_disabled_note( $variable );
}
}
echo '<div class="switch-toggle switch-candy switch-yoast-seo">';
foreach ( $values as $key => $value ) {
@@ -824,46 +899,58 @@ class Yoast_Form {
$key_esc = esc_attr( $key );
$for = $var_esc . '-' . $key_esc;
$disabled_attribute = $this->get_disabled_attribute( $var, $attr );
$disabled_attribute = $this->get_disabled_attribute( $variable, $attr );
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped.
echo '<input type="radio" id="' . $for . '" name="' . esc_attr( $this->option_name ) . '[' . $var_esc . ']" value="' . $key_esc . '" ' . checked( $val, $key_esc, false ) . $disabled_attribute . ' />',
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output escaped before.
'<label for="', $for, '">', esc_html( $value ), $screen_reader_text_html, '</label>';
}
echo '<a></a></div></fieldset><div class="clear"></div></div>' . PHP_EOL . PHP_EOL;
$upsell_button = '';
if ( $has_premium_upsell ) {
$upsell_button = '<a class="yoast-button yoast-button--buy yoast-button--small" data-action="load-nfd-ctb" data-ctb-id="f6a84663-465f-4cb5-8ba5-f7a6d72224b2" href=' .
esc_url( $attr['premium_upsell_url'] ) . ' target="_blank">' .
esc_html__( 'Unlock with Premium!', 'wordpress-seo' ) .
/* translators: Hidden accessibility text. */
'<span class="screen-reader-text">' . esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ) . '</span>' .
'<span aria-hidden="true" class="yoast-button--buy__caret"></span></a>';
}
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- All variable output is escaped above.
echo '<a></a></div></fieldset><div class="clear"></div>' . $upsell_button . '</div>' . PHP_EOL . PHP_EOL;
}
/**
* Creates a toggle switch to define whether an indexable should be indexed or not.
*
* @param string $var The variable within the option to create the radio buttons for.
* @param string $label The visual label for the radio buttons group, used as the fieldset legend.
* @param string $help Inline Help that will be printed out before the visible toggles text.
* @param array $attr Extra attributes to add to the index switch.
* @param string $variable The variable within the option to create the radio buttons for.
* @param string $label The visual label for the radio buttons group, used as the fieldset legend.
* @param string $help Inline Help that will be printed out before the visible toggles text.
* @param array $attr Extra attributes to add to the index switch.
*
* @return void
*/
public function index_switch( $var, $label, $help = '', $attr = [] ) {
public function index_switch( $variable, $label, $help = '', $attr = [] ) {
$defaults = [
'disabled' => false,
];
$attr = wp_parse_args( $attr, $defaults );
$index_switch_values = [
'off' => __( 'Yes', 'wordpress-seo' ),
'on' => __( 'No', 'wordpress-seo' ),
'off' => __( 'On', 'wordpress-seo' ),
'on' => __( 'Off', 'wordpress-seo' ),
];
$is_disabled = ( isset( $attr['disabled'] ) && $attr['disabled'] );
$this->toggle_switch(
$var,
$variable,
$index_switch_values,
sprintf(
/* translators: %s expands to an indexable object's name, like a post type or taxonomy */
esc_html__( 'Show %s in search results?', 'wordpress-seo' ),
'<strong>' . esc_html( $label ) . '</strong>'
$label
),
$help,
[ 'disabled' => $is_disabled ]
@@ -873,7 +960,7 @@ class Yoast_Form {
/**
* Creates a toggle switch to show hide certain options.
*
* @param string $var The variable within the option to create the radio buttons for.
* @param string $variable The variable within the option to create the radio buttons for.
* @param string $label The visual label for the radio buttons group, used as the fieldset legend.
* @param bool $inverse_keys Whether or not the option keys need to be inverted to support older functions.
* @param string $help Inline Help that will be printed out before the visible toggles text.
@@ -881,7 +968,7 @@ class Yoast_Form {
*
* @return void
*/
public function show_hide_switch( $var, $label, $inverse_keys = false, $help = '', $attr = [] ) {
public function show_hide_switch( $variable, $label, $inverse_keys = false, $help = '', $attr = [] ) {
$defaults = [
'disabled' => false,
];
@@ -891,14 +978,14 @@ class Yoast_Form {
$off_key = ( $inverse_keys ) ? 'on' : 'off';
$show_hide_switch = [
$on_key => __( 'Show', 'wordpress-seo' ),
$off_key => __( 'Hide', 'wordpress-seo' ),
$on_key => __( 'On', 'wordpress-seo' ),
$off_key => __( 'Off', 'wordpress-seo' ),
];
$is_disabled = ( isset( $attr['disabled'] ) && $attr['disabled'] );
$this->toggle_switch(
$var,
$variable,
$show_hide_switch,
$label,
$help,
@@ -926,41 +1013,46 @@ class Yoast_Form {
/**
* Checks whether a given control should be disabled.
*
* @param string $var The variable within the option to check whether its control should be disabled.
* @param string $variable The variable within the option to check whether its control should be disabled.
*
* @return bool True if control should be disabled, false otherwise.
*/
protected function is_control_disabled( $var ) {
protected function is_control_disabled( $variable ) {
if ( $this->option_instance === null ) {
return false;
}
// Disable the Usage tracking feature for multisite subsites.
if ( $this->is_tracking_on_subsite( $var ) ) {
if ( $this->is_tracking_on_subsite( $variable ) ) {
return true;
}
return $this->option_instance->is_disabled( $var );
return $this->option_instance->is_disabled( $variable );
}
/**
* Gets the explanation note to print if a given control is disabled.
*
* @param string $var The variable within the option to print a disabled note for.
* @param string $variable The variable within the option to print a disabled note for.
* @param string $custom_note An optional custom note to print instead.
*
* @return string Explanation note HTML string, or empty string if no note necessary.
*/
protected function get_disabled_note( $var ) {
if ( ! $this->is_control_disabled( $var ) ) {
protected function get_disabled_note( $variable, $custom_note = '' ) {
if ( $custom_note === '' && ! $this->is_control_disabled( $variable ) ) {
return '';
}
$disabled_message = esc_html__( 'This feature has been disabled by the network admin.', 'wordpress-seo' );
// The explanation to show when disabling the Usage tracking feature for multisite subsites.
if ( $this->is_tracking_on_subsite( $var ) ) {
if ( $this->is_tracking_on_subsite( $variable ) ) {
$disabled_message = esc_html__( 'This feature has been disabled since subsites never send tracking data.', 'wordpress-seo' );
}
if ( $custom_note ) {
$disabled_message = esc_html( $custom_note );
}
return '<p class="disabled-note">' . $disabled_message . '</p>';
}
@@ -979,13 +1071,13 @@ class Yoast_Form {
/**
* Returns the disabled attribute HTML.
*
* @param string $var The variable within the option of the related form element.
* @param array $attr Extra attributes added to the form element.
* @param string $variable The variable within the option of the related form element.
* @param array $attr Extra attributes added to the form element.
*
* @return string The disabled attribute HTML.
*/
protected function get_disabled_attribute( $var, $attr ) {
if ( $this->is_control_disabled( $var ) || ( isset( $attr['disabled'] ) && $attr['disabled'] ) ) {
protected function get_disabled_attribute( $variable, $attr ) {
if ( $this->is_control_disabled( $variable ) || ( isset( $attr['disabled'] ) && $attr['disabled'] ) ) {
return ' disabled';
}

View File

@@ -124,7 +124,7 @@ class Yoast_Input_Validation {
),
'linkedin_url' => sprintf(
/* translators: %s: additional message with the submitted invalid value */
esc_html__( 'Please check the format of the Linkedin URL you entered. %s', 'wordpress-seo' ),
esc_html__( 'Please check the format of the LinkedIn URL you entered. %s', 'wordpress-seo' ),
self::get_dirty_value_message( 'linkedin_url' )
),
'msverify' => sprintf(
@@ -164,7 +164,7 @@ class Yoast_Input_Validation {
),
'youtube_url' => sprintf(
/* translators: %s: additional message with the submitted invalid value */
esc_html__( 'Please check the format of the Youtube URL you entered. %s', 'wordpress-seo' ),
esc_html__( 'Please check the format of the YouTube URL you entered. %s', 'wordpress-seo' ),
self::get_dirty_value_message( 'youtube_url' )
),
];

View File

@@ -100,7 +100,17 @@ class Yoast_Network_Admin implements WPSEO_WordPress_AJAX_Integration, WPSEO_Wor
* @return void
*/
public function handle_update_options_request() {
$option_group = filter_input( INPUT_POST, 'network_option_group', FILTER_SANITIZE_STRING );
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: Nonce verification will happen in verify_request below.
if ( ! isset( $_POST['network_option_group'] ) || ! is_string( $_POST['network_option_group'] ) ) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: Nonce verification will happen in verify_request below.
$option_group = sanitize_text_field( wp_unslash( $_POST['network_option_group'] ) );
if ( empty( $option_group ) ) {
return;
}
$this->verify_request( "{$option_group}-network-options" );
@@ -117,7 +127,7 @@ class Yoast_Network_Admin implements WPSEO_WordPress_AJAX_Integration, WPSEO_Wor
foreach ( $whitelist_options as $option_name ) {
$value = null;
if ( isset( $_POST[ $option_name ] ) ) {
// Adding sanitize_text_field around this will break the saving of settings because it expects a string: https://github.com/Yoast/wordpress-seo/issues/12440.
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: Adding sanitize_text_field around this will break the saving of settings because it expects a string: https://github.com/Yoast/wordpress-seo/issues/12440.
$value = wp_unslash( $_POST[ $option_name ] );
}

View File

@@ -120,20 +120,20 @@ class Yoast_Network_Settings_API {
* This function is added as a filter to `default_site_option_{$option}` for network options that
* are registered with a default.
*
* @param mixed $default Existing default value to return.
* @param string $option The option name.
* @param mixed $default_value Existing default value to return.
* @param string $option The option name.
*
* @return mixed The filtered default value.
*/
public function filter_default_option( $default, $option ) {
public function filter_default_option( $default_value, $option ) {
// If a default value was manually passed to the function, allow it to override.
if ( $default !== false ) {
return $default;
if ( $default_value !== false ) {
return $default_value;
}
if ( empty( $this->registered_settings[ $option ] ) ) {
return $default;
return $default_value;
}
return $this->registered_settings[ $option ]['default'];

View File

@@ -61,6 +61,13 @@ class Yoast_Notification_Center {
*/
private $notifications_retrieved = false;
/**
* Internal flag for whether notifications need to be updated in storage.
*
* @var bool
*/
private $notifications_need_storage = false;
/**
* Construct.
*/
@@ -94,14 +101,23 @@ class Yoast_Notification_Center {
* Dismiss a notification.
*/
public static function ajax_dismiss_notification() {
$notification_center = self::get();
$notification_id = filter_input( INPUT_POST, 'notification' );
if ( ! isset( $_POST['notification'] ) || ! is_string( $_POST['notification'] ) ) {
die( '-1' );
}
$notification_id = sanitize_text_field( wp_unslash( $_POST['notification'] ) );
if ( empty( $notification_id ) ) {
die( '-1' );
}
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are using the variable as a nonce.
if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['nonce'] ), $notification_id ) ) {
die( '-1' );
}
$notification = $notification_center->get_notification_by_id( $notification_id );
if ( ( $notification instanceof Yoast_Notification ) === false ) {
@@ -291,7 +307,7 @@ class Yoast_Notification_Center {
*/
public function add_notification( Yoast_Notification $notification ) {
$callback = [ $this, __METHOD__ ];
$callback = [ $this, __FUNCTION__ ];
$args = func_get_args();
if ( $this->queue_transaction( $callback, $args ) ) {
return;
@@ -321,6 +337,8 @@ class Yoast_Notification_Center {
// Add to list.
$this->notifications[ $user_id ][] = $notification;
$this->notifications_need_storage = true;
}
/**
@@ -396,7 +414,7 @@ class Yoast_Notification_Center {
*/
public function remove_notification( Yoast_Notification $notification, $resolve = true ) {
$callback = [ $this, __METHOD__ ];
$callback = [ $this, __FUNCTION__ ];
$args = func_get_args();
if ( $this->queue_transaction( $callback, $args ) ) {
return;
@@ -432,6 +450,8 @@ class Yoast_Notification_Center {
unset( $notifications[ $index ] );
$this->notifications[ $user_id ] = array_values( $notifications );
$this->notifications_need_storage = true;
}
/**
@@ -450,6 +470,7 @@ class Yoast_Notification_Center {
}
$this->remove_notification( $notification, $resolve );
$this->notifications_need_storage = true;
}
/**
@@ -504,7 +525,12 @@ class Yoast_Notification_Center {
* AJAX display notifications.
*/
public function ajax_get_notifications() {
$echo = filter_input( INPUT_POST, 'version' ) === '2';
$echo = false;
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form data.
if ( isset( $_POST['version'] ) && is_string( $_POST['version'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are only comparing the variable in a condition.
$echo = wp_unslash( $_POST['version'] ) === '2';
}
// Display the notices.
$this->display_notifications( $echo );
@@ -582,7 +608,13 @@ class Yoast_Notification_Center {
*
* @api Yoast_Notification[] $notifications
*/
$merged_notifications = apply_filters( 'yoast_notifications_before_storage', $merged_notifications );
$filtered_merged_notifications = apply_filters( 'yoast_notifications_before_storage', $merged_notifications );
// The notifications were filtered and therefore need to be stored.
if ( $merged_notifications !== $filtered_merged_notifications ) {
$merged_notifications = $filtered_merged_notifications;
$this->notifications_need_storage = true;
}
$notifications = $this->split_on_user_id( $merged_notifications );
@@ -593,7 +625,10 @@ class Yoast_Notification_Center {
return;
}
array_walk( $notifications, [ $this, 'store_notifications_for_user' ] );
// Only store notifications if changes are made.
if ( $this->notifications_need_storage ) {
array_walk( $notifications, [ $this, 'store_notifications_for_user' ] );
}
}
/**
@@ -648,20 +683,29 @@ class Yoast_Notification_Center {
/**
* Get information from the User input.
*
* Note that this function does not handle nonce verification.
*
* @param string $key Key to retrieve.
*
* @return mixed value of key if set.
* @return string non-sanitized value of key if set, an empty string otherwise.
*/
private static function get_user_input( $key ) {
$filter_input_type = INPUT_GET;
$request_method = isset( $_SERVER['REQUEST_METHOD'] ) ? filter_var( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : '';
if ( strtoupper( $request_method ) === 'POST' ) {
$filter_input_type = INPUT_POST;
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.NonceVerification.Missing -- Reason: We are not processing form information and only using this variable in a comparison.
$request_method = isset( $_SERVER['REQUEST_METHOD'] ) && is_string( $_SERVER['REQUEST_METHOD'] ) ? strtoupper( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : '';
// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: This function does not sanitize variables.
// phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- Reason: This function does not verify a nonce.
if ( $request_method === 'POST' ) {
if ( isset( $_POST[ $key ] ) && is_string( $_POST[ $key ] ) ) {
return wp_unslash( $_POST[ $key ] );
}
}
return filter_input( $filter_input_type, $key );
else {
if ( isset( $_GET[ $key ] ) && is_string( $_GET[ $key ] ) ) {
return wp_unslash( $_GET[ $key ] );
}
}
// phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
return '';
}
/**
@@ -791,9 +835,8 @@ class Yoast_Notification_Center {
unset( $notification_data['options']['nonce'] );
}
if (
isset( $notification_data['message'] ) &&
\is_subclass_of( $notification_data['message'], Abstract_Presenter::class, false )
if ( isset( $notification_data['message'] )
&& \is_subclass_of( $notification_data['message'], Abstract_Presenter::class, false )
) {
$notification_data['message'] = $notification_data['message']->present();
}

View File

@@ -119,7 +119,7 @@ class Yoast_Notification {
}
/**
* Retrieve the is of the user to show the notification for.
* Retrieve the id of the user to show the notification for.
*
* Returns the id of the current user if not user has been sent.
*

View File

@@ -78,10 +78,13 @@ class Yoast_Notifications {
* Add hooks
*/
private function add_hooks() {
$page = filter_input( INPUT_GET, 'page' );
if ( $page === self::ADMIN_PAGE ) {
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['page'] ) && is_string( $_GET['page'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$page = sanitize_text_field( wp_unslash( $_GET['page'] ) );
if ( $page === self::ADMIN_PAGE ) {
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
}
}
// Needed for adminbar and Notifications page.
@@ -96,21 +99,9 @@ class Yoast_Notifications {
* Enqueue assets.
*/
public function enqueue_assets() {
$asset_manager = new WPSEO_Admin_Asset_Manager();
$asset_manager->enqueue_style( 'notifications' );
}
/**
* Deprecated: Handle ajax request to dismiss a alert.
* Renamed to ajax_dismiss_notification
*
* @deprecated 14.0
*
* @codeCoverageIgnore
*/
public function ajax_dismiss_alert() {
_deprecated_function( __METHOD__, 'WPSEO 14.0' );
$asset_manager->enqueue_style( 'notifications' );
}
/**
@@ -129,19 +120,6 @@ class Yoast_Notifications {
wp_die();
}
/**
* Deprecated: Handle ajax request to restore a notification.
* Renamed to ajax_restore_notification
*
* @deprecated 14.0
* @codeCoverageIgnore
*
* @return void
*/
public function ajax_restore_alert() {
_deprecated_function( __METHOD__, 'WPSEO 14.0' );
}
/**
* Handle ajax request to restore a notification.
*/
@@ -216,13 +194,22 @@ class Yoast_Notifications {
/**
* Extract the Yoast Notification from the AJAX request.
*
* @return Yoast_Notification|null
* This function does not handle nonce verification.
*
* @return Yoast_Notification|null A Yoast_Notification on success, null on failure.
*/
private function get_notification_from_ajax_request() {
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: This function does not handle nonce verification.
if ( ! isset( $_POST['notification'] ) || ! is_string( $_POST['notification'] ) ) {
return null;
}
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: This function does not handle nonce verification.
$notification_id = sanitize_text_field( wp_unslash( $_POST['notification'] ) );
if ( empty( $notification_id ) ) {
return null;
}
$notification_center = Yoast_Notification_Center::get();
$notification_id = filter_input( INPUT_POST, 'notification' );
return $notification_center->get_notification_by_id( $notification_id );
}
@@ -270,20 +257,6 @@ class Yoast_Notifications {
];
}
/**
* Deprecated: Get the number of active notifications.
* Renamed to get_active_notification_count
*
* @deprecated 14.0
* @codeCoverageIgnore
*
* @return int
*/
public function get_active_alert_count() {
_deprecated_function( __METHOD__, 'WPSEO 14.0' );
return 0;
}
/**
* Get the number of active notifications.
*
@@ -294,20 +267,6 @@ class Yoast_Notifications {
return ( count( self::$active_errors ) + count( self::$active_warnings ) );
}
/**
* Deprecated: Filter out any non-errors. Renamed to filter_error_notifications
*
* @deprecated 14.0
* @codeCoverageIgnore
*
* @param Yoast_Notification $notification Notification to test.
* @return bool
*/
public function filter_error_alerts( Yoast_Notification $notification ) {
_deprecated_function( __METHOD__, 'WPSEO 14.0' );
return false;
}
/**
* Filter out any non-errors.
*
@@ -320,20 +279,6 @@ class Yoast_Notifications {
return $notification->get_type() === 'error';
}
/**
* Deprecated: Filter out any non-warnings. Renamed to filter_warning_notifications
*
* @deprecated 14.0
* @codeCoverageIgnore
*
* @param Yoast_Notification $notification Notification to test.
* @return bool
*/
public function filter_warning_alerts( Yoast_Notification $notification ) {
_deprecated_function( __METHOD__, 'WPSEO 14.0' );
return false;
}
/**
* Filter out any non-warnings.
*
@@ -346,20 +291,6 @@ class Yoast_Notifications {
return $notification->get_type() !== 'error';
}
/**
* Deprecated: Filter out any dismissed notifications. Renamed to filter_dismissed_alerts.
*
* @deprecated 14.0
* @codeCoverageIgnore
*
* @param Yoast_Notification $notification Notification to test.
* @return bool
*/
public function filter_dismissed_alerts( Yoast_Notification $notification ) {
_deprecated_function( __METHOD__, 'WPSEO 14.0' );
return false;
}
/**
* Filter out any dismissed notifications.
*

View File

@@ -33,7 +33,7 @@ class Yoast_Plugin_Conflict {
*
* @var array
*/
protected $active_plugins = [];
protected $active_conflicting_plugins = [];
/**
* Property for holding instance of itself.
@@ -67,14 +67,19 @@ class Yoast_Plugin_Conflict {
* Setting instance, all active plugins and search for active plugins.
*
* Protected constructor to prevent creating a new instance of the
* *Singleton* via the `new` operator from outside of this class.
* *Singleton* via the `new` operator from outside this class.
*/
protected function __construct() {
// Set active plugins.
$this->all_active_plugins = get_option( 'active_plugins' );
if ( filter_input( INPUT_GET, 'action' ) === 'deactivate' ) {
$this->remove_deactivated_plugin();
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['action'] ) && is_string( $_GET['action'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information and only comparing the variable in a condition.
$action = wp_unslash( $_GET['action'] );
if ( $action === 'deactivate' ) {
$this->remove_deactivated_plugin();
}
}
// Search for active plugins.
@@ -92,52 +97,23 @@ class Yoast_Plugin_Conflict {
static $sections_checked;
// Return early if there are no active conflicting plugins at all.
if ( empty( $this->active_conflicting_plugins ) ) {
return false;
}
if ( $sections_checked === null ) {
$sections_checked = [];
}
if ( ! in_array( $plugin_section, $sections_checked, true ) ) {
if ( ! \in_array( $plugin_section, $sections_checked, true ) ) {
$sections_checked[] = $plugin_section;
$has_conflicts = ( ! empty( $this->active_plugins[ $plugin_section ] ) );
return $has_conflicts;
return ( ! empty( $this->active_conflicting_plugins[ $plugin_section ] ) );
}
return false;
}
/**
* Getting all the conflicting plugins and return them as a string.
*
* This method will loop through all conflicting plugins to get the details of each plugin. The plugin name
* will be taken from the details to parse a comma separated string, which can be use for by example a notice
*
* @param string $plugin_section Plugin conflict type (such as Open Graph or sitemap).
*
* @return string
*/
public function get_conflicting_plugins_as_string( $plugin_section ) {
if ( ! function_exists( 'get_plugin_data' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
// Getting the active plugins by given section.
$plugins = $this->active_plugins[ $plugin_section ];
$plugin_names = [];
foreach ( $plugins as $plugin ) {
$name = $this->get_plugin_name( $plugin );
if ( ! empty( $name ) ) {
$plugin_names[] = '<em>' . $name . '</em>';
}
}
unset( $plugins, $plugin );
if ( ! empty( $plugin_names ) ) {
return implode( ' &amp; ', $plugin_names );
}
}
/**
* Checks for given $plugin_sections for conflicts.
*
@@ -152,9 +128,9 @@ class Yoast_Plugin_Conflict {
}
// List of all active sections.
$sections = array_keys( $plugin_sections );
$sections = \array_keys( $plugin_sections );
// List of all sections.
$all_plugin_sections = array_keys( $this->plugins );
$all_plugin_sections = \array_keys( $this->plugins );
/*
* Get all sections that are inactive.
@@ -162,24 +138,24 @@ class Yoast_Plugin_Conflict {
*
* This happens when Sitemaps or OpenGraph implementations toggle active/disabled.
*/
$inactive_sections = array_diff( $all_plugin_sections, $sections );
$inactive_sections = \array_diff( $all_plugin_sections, $sections );
if ( ! empty( $inactive_sections ) ) {
foreach ( $inactive_sections as $section ) {
array_walk( $this->plugins[ $section ], [ $this, 'clear_error' ] );
\array_walk( $this->plugins[ $section ], [ $this, 'clear_error' ] );
}
}
// For active sections clear errors for inactive plugins.
foreach ( $sections as $section ) {
// By default clear errors for all plugins of the section.
// By default, clear errors for all plugins of the section.
$inactive_plugins = $this->plugins[ $section ];
// If there are active plugins, filter them from being cleared.
if ( isset( $this->active_plugins[ $section ] ) ) {
$inactive_plugins = array_diff( $this->plugins[ $section ], $this->active_plugins[ $section ] );
if ( isset( $this->active_conflicting_plugins[ $section ] ) ) {
$inactive_plugins = \array_diff( $this->plugins[ $section ], $this->active_conflicting_plugins[ $section ] );
}
array_walk( $inactive_plugins, [ $this, 'clear_error' ] );
\array_walk( $inactive_plugins, [ $this, 'clear_error' ] );
}
}
@@ -193,7 +169,7 @@ class Yoast_Plugin_Conflict {
$notification_center = Yoast_Notification_Center::get();
foreach ( $this->active_plugins[ $plugin_section ] as $plugin_file ) {
foreach ( $this->active_conflicting_plugins[ $plugin_section ] as $plugin_file ) {
$plugin_name = $this->get_plugin_name( $plugin_file );
@@ -265,7 +241,7 @@ class Yoast_Plugin_Conflict {
* @return bool
*/
protected function check_plugin_is_active( $plugin ) {
return in_array( $plugin, $this->all_active_plugins, true );
return \in_array( $plugin, $this->all_active_plugins, true );
}
/**
@@ -278,13 +254,12 @@ class Yoast_Plugin_Conflict {
* @param string $plugin Plugin basename string.
*/
protected function add_active_plugin( $plugin_section, $plugin ) {
if ( ! array_key_exists( $plugin_section, $this->active_plugins ) ) {
$this->active_plugins[ $plugin_section ] = [];
if ( ! \array_key_exists( $plugin_section, $this->active_conflicting_plugins ) ) {
$this->active_conflicting_plugins[ $plugin_section ] = [];
}
if ( ! in_array( $plugin, $this->active_plugins[ $plugin_section ], true ) ) {
$this->active_plugins[ $plugin_section ][] = $plugin;
if ( ! \in_array( $plugin, $this->active_conflicting_plugins[ $plugin_section ], true ) ) {
$this->active_conflicting_plugins[ $plugin_section ][] = $plugin;
}
}
@@ -298,9 +273,8 @@ class Yoast_Plugin_Conflict {
* @return int|string
*/
protected function find_plugin_category( $plugin ) {
foreach ( $this->plugins as $plugin_section => $plugins ) {
if ( in_array( $plugin, $plugins, true ) ) {
if ( \in_array( $plugin, $plugins, true ) ) {
return $plugin_section;
}
}
@@ -314,7 +288,7 @@ class Yoast_Plugin_Conflict {
* @return string|bool Plugin name or false when no name is set.
*/
protected function get_plugin_name( $plugin ) {
$plugin_details = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
$plugin_details = \get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
if ( $plugin_details['Name'] !== '' ) {
return $plugin_details['Name'];
@@ -327,8 +301,14 @@ class Yoast_Plugin_Conflict {
* When being in the deactivation process the currently deactivated plugin has to be removed.
*/
private function remove_deactivated_plugin() {
$deactivated_plugin = filter_input( INPUT_GET, 'plugin' );
$key_to_remove = array_search( $deactivated_plugin, $this->all_active_plugins, true );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: On the deactivation screen the nonce is already checked by WordPress itself.
if ( ! isset( $_GET['plugin'] ) || ! is_string( $_GET['plugin'] ) ) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: On the deactivation screen the nonce is already checked by WordPress itself.
$deactivated_plugin = sanitize_text_field( wp_unslash( $_GET['plugin'] ) );
$key_to_remove = \array_search( $deactivated_plugin, $this->all_active_plugins, true );
if ( $key_to_remove !== false ) {
unset( $this->all_active_plugins[ $key_to_remove ] );
@@ -343,6 +323,6 @@ class Yoast_Plugin_Conflict {
* @return string
*/
private function get_notification_identifier( $plugin_file ) {
return md5( $plugin_file );
return \md5( $plugin_file );
}
}

View File

@@ -145,11 +145,15 @@ abstract class WPSEO_Abstract_Post_Filter implements WPSEO_WordPress_Integration
/**
* Returns true when the filter is active.
*
* @return bool Whether or not the filter is active.
* @return bool Whether the filter is active.
*/
protected function is_filter_active() {
return ( $this->is_supported_post_type( $this->get_current_post_type() )
&& filter_input( INPUT_GET, self::FILTER_QUERY_ARG ) === $this->get_query_val() );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET[ self::FILTER_QUERY_ARG ] ) && is_string( $_GET[ self::FILTER_QUERY_ARG ] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
return sanitize_text_field( wp_unslash( $_GET[ self::FILTER_QUERY_ARG ] ) ) === $this->get_query_val();
}
return false;
}
/**
@@ -158,11 +162,15 @@ abstract class WPSEO_Abstract_Post_Filter implements WPSEO_WordPress_Integration
* @return string The current post type.
*/
protected function get_current_post_type() {
$filter_options = [
'options' => [ 'default' => 'post' ],
];
return filter_input( INPUT_GET, 'post_type', FILTER_DEFAULT, $filter_options );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['post_type'] ) && is_string( $_GET['post_type'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$post_type = sanitize_text_field( wp_unslash( $_GET['post_type'] ) );
if ( ! empty( $post_type ) ) {
return $post_type;
}
}
return 'post';
}
/**

View File

@@ -49,8 +49,8 @@ class WPSEO_Cornerstone_Filter extends WPSEO_Abstract_Post_Filter {
if ( $this->is_filter_active() ) {
global $wpdb;
$where .= sprintf(
' AND ' . $wpdb->posts . '.ID IN( SELECT post_id FROM ' . $wpdb->postmeta . ' WHERE meta_key = "%s" AND meta_value = "1" ) ',
$where .= $wpdb->prepare(
" AND {$wpdb->posts}.ID IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = '1' ) ",
WPSEO_Meta::$meta_prefix . self::META_NAME
);
}
@@ -118,12 +118,11 @@ class WPSEO_Cornerstone_Filter extends WPSEO_Abstract_Post_Filter {
return (int) $wpdb->get_var(
$wpdb->prepare(
'
SELECT COUNT( 1 )
FROM ' . $wpdb->postmeta . '
WHERE post_id IN( SELECT ID FROM ' . $wpdb->posts . ' WHERE post_type = %s ) AND
meta_value = "1" AND meta_key = %s
',
"SELECT COUNT( 1 )
FROM {$wpdb->postmeta}
WHERE post_id IN( SELECT ID FROM {$wpdb->posts} WHERE post_type = %s ) AND
meta_key = %s AND meta_value = '1'
",
$this->get_current_post_type(),
WPSEO_Meta::$meta_prefix . self::META_NAME
)

View File

@@ -5,11 +5,14 @@
* @package WPSEO\Admin\Formatter
*/
use Yoast\WP\SEO\Conditionals\Third_Party\Polylang_Conditional;
use Yoast\WP\SEO\Conditionals\Third_Party\TranslatePress_Conditional;
use Yoast\WP\SEO\Conditionals\Third_Party\WPML_Conditional;
use Yoast\WP\SEO\Config\Schema_Types;
use Yoast\WP\SEO\Config\SEMrush_Client;
use Yoast\WP\SEO\Exceptions\OAuth\Authentication_Failed_Exception;
use Yoast\WP\SEO\Exceptions\SEMrush\Tokens\Empty_Property_Exception;
use Yoast\WP\SEO\Exceptions\SEMrush\Tokens\Empty_Token_Exception;
use Yoast\WP\SEO\Exceptions\OAuth\Tokens\Empty_Property_Exception;
use Yoast\WP\SEO\Exceptions\OAuth\Tokens\Empty_Token_Exception;
/**
* This class forces needed methods for the metabox localization.
@@ -50,129 +53,173 @@ class WPSEO_Metabox_Formatter {
* @return array Default settings for the metabox.
*/
private function get_defaults() {
$analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$analysis_readability = new WPSEO_Metabox_Analysis_Readability();
$schema_types = new Schema_Types();
$analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$analysis_readability = new WPSEO_Metabox_Analysis_Readability();
$analysis_inclusive_language = new WPSEO_Metabox_Analysis_Inclusive_Language();
$schema_types = new Schema_Types();
$is_wincher_active = YoastSEO()->helpers->wincher->is_active();
$host = YoastSEO()->helpers->url->get_url_host( get_site_url() );
return [
'author_name' => get_the_author_meta( 'display_name' ),
'site_name' => get_bloginfo( 'name' ),
'sitewide_social_image' => WPSEO_Options::get( 'og_default_image' ),
'search_url' => '',
'post_edit_url' => '',
'base_url' => '',
'contentTab' => __( 'Readability', 'wordpress-seo' ),
'keywordTab' => __( 'Keyphrase:', 'wordpress-seo' ),
'removeKeyword' => __( 'Remove keyphrase', 'wordpress-seo' ),
'contentLocale' => get_locale(),
'userLocale' => \get_user_locale(),
'translations' => $this->get_translations(),
'keyword_usage' => [],
'title_template' => '',
'metadesc_template' => '',
'contentAnalysisActive' => $analysis_readability->is_enabled() ? 1 : 0,
'keywordAnalysisActive' => $analysis_seo->is_enabled() ? 1 : 0,
'cornerstoneActive' => WPSEO_Options::get( 'enable_cornerstone_content', false ) ? 1 : 0,
'semrushIntegrationActive' => WPSEO_Options::get( 'semrush_integration_active', true ) ? 1 : 0,
'intl' => $this->get_content_analysis_component_translations(),
'isRtl' => is_rtl(),
'isPremium' => YoastSEO()->helpers->product->is_premium(),
'wordFormRecognitionActive' => YoastSEO()->helpers->language->is_word_form_recognition_active( WPSEO_Language_Utils::get_language( get_locale() ) ),
'siteIconUrl' => get_site_icon_url(),
'countryCode' => WPSEO_Options::get( 'semrush_country_code', false ),
'SEMrushLoginStatus' => WPSEO_Options::get( 'semrush_integration_active', true ) ? $this->get_semrush_login_status() : false,
'showSocial' => [
'author_name' => get_the_author_meta( 'display_name' ),
'site_name' => YoastSEO()->meta->for_current_page()->site_name,
'sitewide_social_image' => WPSEO_Options::get( 'og_default_image' ),
'search_url' => '',
'post_edit_url' => '',
'base_url' => '',
'contentTab' => __( 'Readability', 'wordpress-seo' ),
'keywordTab' => __( 'Keyphrase:', 'wordpress-seo' ),
'removeKeyword' => __( 'Remove keyphrase', 'wordpress-seo' ),
'contentLocale' => get_locale(),
'userLocale' => \get_user_locale(),
'translations' => $this->get_translations(),
'keyword_usage' => [],
'title_template' => '',
'metadesc_template' => '',
'contentAnalysisActive' => $analysis_readability->is_enabled() ? 1 : 0,
'keywordAnalysisActive' => $analysis_seo->is_enabled() ? 1 : 0,
'inclusiveLanguageAnalysisActive' => $analysis_inclusive_language->is_enabled() ? 1 : 0,
'cornerstoneActive' => WPSEO_Options::get( 'enable_cornerstone_content', false ) ? 1 : 0,
'semrushIntegrationActive' => WPSEO_Options::get( 'semrush_integration_active', true ) ? 1 : 0,
'intl' => $this->get_content_analysis_component_translations(),
'isRtl' => is_rtl(),
'isPremium' => YoastSEO()->helpers->product->is_premium(),
'wordFormRecognitionActive' => YoastSEO()->helpers->language->is_word_form_recognition_active( WPSEO_Language_Utils::get_language( get_locale() ) ),
'siteIconUrl' => get_site_icon_url(),
'countryCode' => WPSEO_Options::get( 'semrush_country_code', false ),
'SEMrushLoginStatus' => WPSEO_Options::get( 'semrush_integration_active', true ) ? $this->get_semrush_login_status() : false,
'showSocial' => [
'facebook' => WPSEO_Options::get( 'opengraph', false ),
'twitter' => WPSEO_Options::get( 'twitter', false ),
],
'schema' => [
'schema' => [
'displayFooter' => WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ),
'pageTypeOptions' => $schema_types->get_page_type_options(),
'articleTypeOptions' => $schema_types->get_article_type_options(),
],
'twitterCardType' => YoastSEO()->helpers->options->get( 'twitter_card_type' ),
'twitterCardType' => 'summary_large_image',
/**
* Filter to determine if the markers should be enabled or not.
*
* @param bool $showMarkers Should the markers being enabled. Default = true.
*/
'show_markers' => apply_filters( 'wpseo_enable_assessment_markers', true ),
'publish_box' => [
'show_markers' => apply_filters( 'wpseo_enable_assessment_markers', true ),
'publish_box' => [
'labels' => [
'content' => [
'keyword' => [
'na' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */
__( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-seo-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'Not available', 'wordpress-seo' ) . '</strong>'
),
'bad' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */
__( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-seo-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'Needs improvement', 'wordpress-seo' ) . '</strong>'
),
'ok' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */
__( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-seo-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'OK', 'wordpress-seo' ) . '</strong>'
),
'good' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */
__( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-seo-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'Good', 'wordpress-seo' ) . '</strong>'
),
],
'content' => [
'na' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */
__( '%1$sReadability%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-readability-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'Not available', 'wordpress-seo' ) . '</strong>'
),
'bad' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */
__( '%1$sReadability%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-readability-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'Needs improvement', 'wordpress-seo' ) . '</strong>'
),
'ok' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */
__( '%1$sReadability%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-readability-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'OK', 'wordpress-seo' ) . '</strong>'
),
'good' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */
__( '%1$sReadability%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-readability-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'Good', 'wordpress-seo' ) . '</strong>'
),
],
'keyword' => [
'inclusive-language' => [
'na' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */
__( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-seo-analysis-collapsible-metabox">',
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the inclusive language score. */
__( '%1$sInclusive language%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-inclusive-language-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'Not available', 'wordpress-seo' ) . '</strong>'
),
'bad' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */
__( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-seo-analysis-collapsible-metabox">',
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the inclusive language score. */
__( '%1$sInclusive language%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-inclusive-language-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'Needs improvement', 'wordpress-seo' ) . '</strong>'
),
'ok' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */
__( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-seo-analysis-collapsible-metabox">',
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the inclusive language score. */
__( '%1$sInclusive language%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-inclusive-language-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'OK', 'wordpress-seo' ) . '</strong>'
'<strong>' . __( 'Potentially non-inclusive', 'wordpress-seo' ) . '</strong>'
),
'good' => sprintf(
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */
__( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-seo-analysis-collapsible-metabox">',
/* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the inclusive language score. */
__( '%1$sInclusive language%2$s: %3$s', 'wordpress-seo' ),
'<a href="#yoast-inclusive-language-analysis-collapsible-metabox">',
'</a>',
'<strong>' . __( 'Good', 'wordpress-seo' ) . '</strong>'
),
],
],
],
'markdownEnabled' => $this->is_markdown_enabled(),
'analysisHeadingTitle' => __( 'Analysis', 'wordpress-seo' ),
'zapierIntegrationActive' => WPSEO_Options::get( 'zapier_integration_active', false ) ? 1 : 0,
'zapierConnectedStatus' => ! empty( WPSEO_Options::get( 'zapier_subscription', [] ) ) ? 1 : 0,
'markdownEnabled' => $this->is_markdown_enabled(),
'analysisHeadingTitle' => __( 'Analysis', 'wordpress-seo' ),
'zapierIntegrationActive' => WPSEO_Options::get( 'zapier_integration_active', false ) ? 1 : 0,
'zapierConnectedStatus' => ! empty( WPSEO_Options::get( 'zapier_subscription', [] ) ) ? 1 : 0,
'wincherIntegrationActive' => ( $is_wincher_active ) ? 1 : 0,
'wincherLoginStatus' => ( $is_wincher_active ) ? YoastSEO()->helpers->wincher->login_status() : false,
'wincherWebsiteId' => WPSEO_Options::get( 'wincher_website_id', '' ),
'wincherAutoAddKeyphrases' => WPSEO_Options::get( 'wincher_automatically_add_keyphrases', false ),
'wordproofIntegrationActive' => YoastSEO()->helpers->wordproof->is_active() ? 1 : 0,
'multilingualPluginActive' => $this->multilingual_plugin_active(),
/**
* Filter to determine whether the PreviouslyUsedKeyword assessment should run.
*
* @param bool $previouslyUsedKeywordActive Whether the PreviouslyUsedKeyword assessment should run.
*/
'previouslyUsedKeywordActive' => apply_filters( 'wpseo_previously_used_keyword_active', true ),
'previouslyUsedKeywordActive' => apply_filters( 'wpseo_previously_used_keyword_active', true ),
'getJetpackBoostPrePublishLink' => WPSEO_Shortlinker::get( 'https://yoa.st/jetpack-boost-get-prepublish?domain=' . $host ),
'upgradeJetpackBoostPrePublishLink' => WPSEO_Shortlinker::get( 'https://yoa.st/jetpack-boost-upgrade-prepublish?domain=' . $host ),
'woocommerceUpsellSchemaLink' => WPSEO_Shortlinker::get( 'https://yoa.st/product-schema-metabox' ),
'woocommerceUpsellGooglePreviewLink' => WPSEO_Shortlinker::get( 'https://yoa.st/product-google-preview-metabox' ),
];
}
@@ -193,6 +240,7 @@ class WPSEO_Metabox_Formatter {
'content-analysis.highlight' => __( 'Highlight this result in the text', 'wordpress-seo' ),
'content-analysis.nohighlight' => __( 'Remove highlight from the text', 'wordpress-seo' ),
'content-analysis.disabledButton' => __( 'Marks are disabled in current view', 'wordpress-seo' ),
/* translators: Hidden accessibility text. */
'a11yNotice.opensInNewTab' => __( '(Opens in a new browser tab)', 'wordpress-seo' ),
];
}
@@ -268,43 +316,16 @@ class WPSEO_Metabox_Formatter {
return $semrush_client->has_valid_tokens();
}
/* ********************* DEPRECATED METHODS ********************* */
/**
* Returns the translations for the Add Keyword modal.
* Checks whether a multilingual plugin is currently active. Currently, we only check the following plugins: WPML, Polylang, and TranslatePress.
*
* These strings are not escaped because they're meant to be used with React
* which already takes care of that. If used in PHP, they should be escaped.
*
* @deprecated 15.5
* @codeCoverageIgnore
*
* @return array Translated text strings for the Add Keyword modal.
* @return bool Whether a multilingual plugin is currently active.
*/
public function get_add_keyword_upsell_translations() {
_deprecated_function( __METHOD__, 'WPSEO 15.5' );
private function multilingual_plugin_active() {
$wpml_active = YoastSEO()->classes->get( WPML_Conditional::class )->is_met();
$polylang_active = YoastSEO()->classes->get( Polylang_Conditional::class )->is_met();
$translatepress_active = YoastSEO()->classes->get( TranslatePress_Conditional::class )->is_met();
return [
'title' => __( 'Would you like to add more than one keyphrase?', 'wordpress-seo' ),
'intro' => sprintf(
/* translators: %s expands to a 'Yoast SEO Premium' text linked to the yoast.com website. */
__( 'Great news: you can, with %s!', 'wordpress-seo' ),
'{{link}}Yoast SEO Premium{{/link}}'
),
'link' => WPSEO_Shortlinker::get( 'https://yoa.st/pe-premium-page' ),
'other' => sprintf(
/* translators: %s expands to 'Yoast SEO Premium'. */
__( 'Other benefits of %s for you:', 'wordpress-seo' ),
'Yoast SEO Premium'
),
'buylink' => WPSEO_Shortlinker::get( 'https://yoa.st/add-keywords-popup' ),
'buy' => sprintf(
/* translators: %s expands to 'Yoast SEO Premium'. */
__( 'Get %s', 'wordpress-seo' ),
'Yoast SEO Premium'
),
'small' => __( '1 year free support and updates included!', 'wordpress-seo' ),
'a11yNotice.opensInNewTab' => __( '(Opens in a new browser tab)', 'wordpress-seo' ),
];
return ( $wpml_active || $polylang_active || $translatepress_active );
}
}

View File

@@ -24,6 +24,13 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
*/
private $permalink;
/**
* Whether we must return social templates values.
*
* @var bool
*/
private $use_social_templates = false;
/**
* Constructor.
*
@@ -34,6 +41,17 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
public function __construct( $post, array $options, $structure ) {
$this->post = $post;
$this->permalink = $structure;
$this->use_social_templates = $this->use_social_templates();
}
/**
* Determines whether the social templates should be used.
*
* @return bool Whether the social templates should be used.
*/
public function use_social_templates() {
return WPSEO_Options::get( 'opengraph', false ) === true;
}
/**
@@ -42,27 +60,42 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
* @return array
*/
public function get_values() {
$values = [
'search_url' => $this->search_url(),
'post_edit_url' => $this->edit_url(),
'base_url' => $this->base_url_for_js(),
'metaDescriptionDate' => '',
];
if ( $this->post instanceof WP_Post ) {
$keyword_usage = $this->get_focus_keyword_usage();
$values_to_set = [
'keyword_usage' => $this->get_focus_keyword_usage(),
'title_template' => $this->get_title_template(),
'metadesc_template' => $this->get_metadesc_template(),
'metaDescriptionDate' => $this->get_metadesc_date(),
'first_content_image' => $this->get_image_url(),
'keyword_usage' => $keyword_usage,
'keyword_usage_post_types' => $this->get_post_types_for_all_ids( $keyword_usage ),
'title_template' => $this->get_title_template(),
'title_template_no_fallback' => $this->get_title_template( false ),
'metadesc_template' => $this->get_metadesc_template(),
'metaDescriptionDate' => $this->get_metadesc_date(),
'first_content_image' => $this->get_image_url(),
'social_title_template' => $this->get_social_title_template(),
'social_description_template' => $this->get_social_description_template(),
'social_image_template' => $this->get_social_image_template(),
'isInsightsEnabled' => $this->is_insights_enabled(),
];
$values = ( $values_to_set + $values );
}
return $values;
/**
* Filter: 'wpseo_post_edit_values' - Allows changing the values Yoast SEO uses inside the post editor.
*
* @api array $values The key-value map Yoast SEO uses inside the post editor.
*
* @param WP_Post $post The post opened in the editor.
*/
return \apply_filters( 'wpseo_post_edit_values', $values, $this->post );
}
/**
@@ -71,14 +104,7 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
* @return string|null The image URL for the social preview.
*/
protected function get_image_url() {
$post_id = $this->post->ID;
if ( has_post_thumbnail( $post_id ) ) {
$featured_image_info = wp_get_attachment_image_src( get_post_thumbnail_id( $post_id ), 'thumbnail' );
return isset( $featured_image_info[0] ) ? $featured_image_info[0] : null;
}
return WPSEO_Image_Utils::get_first_usable_content_image_for_post( $post_id );
return WPSEO_Image_Utils::get_first_usable_content_image_for_post( $this->post->ID );
}
/**
@@ -119,6 +145,11 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
$base_url = preg_replace( '#%postname%/?$#', '', $this->permalink );
}
// If %pagename% is the last tag, just strip it and use that as a base.
if ( preg_match( '#%pagename%/?$#', $this->permalink ) === 1 ) {
$base_url = preg_replace( '#%pagename%/?$#', '', $this->permalink );
}
return $base_url;
}
@@ -131,34 +162,29 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
$keyword = WPSEO_Meta::get_value( 'focuskw', $this->post->ID );
$usage = [ $keyword => $this->get_keyword_usage_for_current_post( $keyword ) ];
if ( YoastSEO()->helpers->product->is_premium() ) {
return $this->get_premium_keywords( $usage );
}
return $usage;
/**
* Allows enhancing the array of posts' that share their focus keywords with the post's related keywords.
*
* @param array $usage The array of posts' ids that share their focus keywords with the post.
* @param int $post_id The id of the post we're finding the usage of related keywords for.
*/
return apply_filters( 'wpseo_posts_for_related_keywords', $usage, $this->post->ID );
}
/**
* Retrieves the additional keywords from Premium, that are associated with the post.
* Retrieves the post types for the given post IDs.
*
* @param array $usage The original keyword usage for the main keyword.
*
* @return array The keyword usage, including the additional keywords.
* @param array $post_ids_per_keyword An associative array with keywords as keys and an array of post ids where those keywords are used.
* @return array The post types for the given post IDs.
*/
protected function get_premium_keywords( $usage ) {
$additional_keywords = json_decode( WPSEO_Meta::get_value( 'focuskeywords', $this->post->ID ), true );
private function get_post_types_for_all_ids( $post_ids_per_keyword ) {
if ( empty( $additional_keywords ) ) {
return $usage;
$post_type_per_keyword_result = [];
foreach ( $post_ids_per_keyword as $keyword => $post_ids ) {
$post_type_per_keyword_result[ $keyword ] = WPSEO_Meta::post_types_for_ids( $post_ids );
}
foreach ( $additional_keywords as $additional_keyword ) {
$keyword = $additional_keyword['keyword'];
$usage[ $keyword ] = $this->get_keyword_usage_for_current_post( $keyword );
}
return $usage;
return $post_type_per_keyword_result;
}
/**
@@ -175,13 +201,15 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
/**
* Retrieves the title template.
*
* @param bool $fallback Whether to return the hardcoded fallback if the template value is empty.
*
* @return string The title template.
*/
private function get_title_template() {
private function get_title_template( $fallback = true ) {
$title = $this->get_template( 'title' );
if ( $title === '' ) {
return '%%title%% %%sep%% %%sitename%%';
if ( $title === '' && $fallback === true ) {
return '%%title%% %%page%% %%sep%% %%sitename%%';
}
return $title;
@@ -190,12 +218,51 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
/**
* Retrieves the metadesc template.
*
* @return string
* @return string The metadesc template.
*/
private function get_metadesc_template() {
return $this->get_template( 'metadesc' );
}
/**
* Retrieves the social title template.
*
* @return string The social title template.
*/
private function get_social_title_template() {
if ( $this->use_social_templates ) {
return $this->get_social_template( 'title' );
}
return '';
}
/**
* Retrieves the social description template.
*
* @return string The social description template.
*/
private function get_social_description_template() {
if ( $this->use_social_templates ) {
return $this->get_social_template( 'description' );
}
return '';
}
/**
* Retrieves the social image template.
*
* @return string The social description template.
*/
private function get_social_image_template() {
if ( $this->use_social_templates ) {
return $this->get_social_template( 'image-url' );
}
return '';
}
/**
* Retrieves a template.
*
@@ -213,6 +280,24 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
return '';
}
/**
* Retrieves a social template.
*
* @param string $template_option_name The name of the option in which the template you want to get is saved.
*
* @return string
*/
private function get_social_template( $template_option_name ) {
/**
* Filters the social template value for a given post type.
*
* @param string $template The social template value, defaults to empty string.
* @param string $template_option_name The subname of the option in which the template you want to get is saved.
* @param string $post_type The name of the post type.
*/
return \apply_filters( 'wpseo_social_template_post_type', '', $template_option_name, $this->post->post_type );
}
/**
* Determines the date to be displayed in the snippet preview.
*
@@ -221,4 +306,13 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
private function get_metadesc_date() {
return YoastSEO()->helpers->date->format_translated( $this->post->post_date, 'M j, Y' );
}
/**
* Determines whether the insights feature is enabled for this post.
*
* @return bool
*/
protected function is_insights_enabled() {
return WPSEO_Options::get( 'enable_metabox_insights', false );
}
}

View File

@@ -24,6 +24,13 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
*/
private $taxonomy;
/**
* Whether we must return social templates values.
*
* @var bool
*/
private $use_social_templates = false;
/**
* Array with the WPSEO_Titles options.
*
@@ -40,6 +47,17 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
public function __construct( $taxonomy, $term ) {
$this->taxonomy = $taxonomy;
$this->term = $term;
$this->use_social_templates = $this->use_social_templates();
}
/**
* Determines whether the social templates should be used.
*
* @return bool Whether the social templates should be used.
*/
public function use_social_templates() {
return WPSEO_Options::get( 'opengraph', false ) === true;
}
/**
@@ -53,15 +71,21 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
// Todo: a column needs to be added on the termpages to add a filter for the keyword, so this can be used in the focus keyphrase doubles.
if ( is_object( $this->term ) && property_exists( $this->term, 'taxonomy' ) ) {
$values = [
'search_url' => $this->search_url(),
'post_edit_url' => $this->edit_url(),
'base_url' => $this->base_url_for_js(),
'taxonomy' => $this->term->taxonomy,
'keyword_usage' => $this->get_focus_keyword_usage(),
'title_template' => $this->get_title_template(),
'metadesc_template' => $this->get_metadesc_template(),
'first_content_image' => $this->get_image_url(),
'semrushIntegrationActive' => 0,
'search_url' => $this->search_url(),
'post_edit_url' => $this->edit_url(),
'base_url' => $this->base_url_for_js(),
'taxonomy' => $this->term->taxonomy,
'keyword_usage' => $this->get_focus_keyword_usage(),
'title_template' => $this->get_title_template(),
'title_template_no_fallback' => $this->get_title_template( false ),
'metadesc_template' => $this->get_metadesc_template(),
'first_content_image' => $this->get_image_url(),
'semrushIntegrationActive' => 0,
'social_title_template' => $this->get_social_title_template(),
'social_description_template' => $this->get_social_description_template(),
'social_image_template' => $this->get_social_image_template(),
'wincherIntegrationActive' => 0,
'isInsightsEnabled' => $this->is_insights_enabled(),
];
}
@@ -92,9 +116,7 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
* @return string
*/
private function edit_url() {
global $wp_version;
$script_filename = version_compare( $wp_version, '4.5', '<' ) ? 'edit-tags' : 'term';
return admin_url( $script_filename . '.php?action=edit&taxonomy=' . $this->term->taxonomy . '&tag_ID={id}' );
return admin_url( 'term.php?action=edit&taxonomy=' . $this->term->taxonomy . '&tag_ID={id}' );
}
/**
@@ -106,7 +128,9 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
$base_url = home_url( '/', null );
if ( ! WPSEO_Options::get( 'stripcategorybase', false ) ) {
$base_url = trailingslashit( $base_url . $this->taxonomy->rewrite['slug'] );
if ( $this->taxonomy->rewrite ) {
$base_url = trailingslashit( $base_url . $this->taxonomy->rewrite['slug'] );
}
}
return $base_url;
@@ -126,13 +150,17 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
/**
* Retrieves the title template.
*
* @param bool $fallback Whether to return the hardcoded fallback if the template value is empty.
*
* @return string The title template.
*/
private function get_title_template() {
private function get_title_template( $fallback = true ) {
$title = $this->get_template( 'title' );
if ( $title === '' ) {
return '%%title%% %%sep%% %%sitename%%';
if ( $title === '' && $fallback === true ) {
/* translators: %s expands to the variable used for term title. */
$archives = sprintf( __( '%s Archives', 'wordpress-seo' ), '%%term_title%%' );
return $archives . ' %%page%% %%sep%% %%sitename%%';
}
return $title;
@@ -141,12 +169,51 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
/**
* Retrieves the metadesc template.
*
* @return string
* @return string The metadesc template.
*/
private function get_metadesc_template() {
return $this->get_template( 'metadesc' );
}
/**
* Retrieves the social title template.
*
* @return string The social title template.
*/
private function get_social_title_template() {
if ( $this->use_social_templates ) {
return $this->get_social_template( 'title' );
}
return '';
}
/**
* Retrieves the social description template.
*
* @return string The social description template.
*/
private function get_social_description_template() {
if ( $this->use_social_templates ) {
return $this->get_social_template( 'description' );
}
return '';
}
/**
* Retrieves the social image template.
*
* @return string The social description template.
*/
private function get_social_image_template() {
if ( $this->use_social_templates ) {
return $this->get_social_template( 'image-url' );
}
return '';
}
/**
* Retrieves a template.
*
@@ -158,4 +225,31 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface
$needed_option = $template_option_name . '-tax-' . $this->term->taxonomy;
return WPSEO_Options::get( $needed_option, '' );
}
/**
* Retrieves a social template.
*
* @param string $template_option_name The name of the option in which the template you want to get is saved.
*
* @return string
*/
private function get_social_template( $template_option_name ) {
/**
* Filters the social template value for a given taxonomy.
*
* @param string $template The social template value, defaults to empty string.
* @param string $template_option_name The subname of the option in which the template you want to get is saved.
* @param string $taxonomy The name of the taxonomy.
*/
return \apply_filters( 'wpseo_social_template_taxonomy', '', $template_option_name, $this->term->taxonomy );
}
/**
* Determines whether the insights feature is enabled for this taxonomy.
*
* @return bool
*/
protected function is_insights_enabled() {
return WPSEO_Options::get( 'enable_metabox_insights', false );
}
}

View File

@@ -7,7 +7,7 @@
* @package WPSEO\Admin\Google_Search_Console
*/
_deprecated_file( __FILE__, 'WPSEO 9.5' );
_deprecated_file( __FILE__, 'Yoast SEO 9.5' );
echo '<h1 class="wpseo-redirect-url-title">';
printf(

View File

@@ -52,7 +52,13 @@ class WPSEO_Import_Settings {
return;
}
$content = filter_input( INPUT_POST, 'settings_import' );
if ( ! isset( $_POST['settings_import'] ) || ! is_string( $_POST['settings_import'] ) ) {
return;
}
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: The raw content will be parsed afterwards.
$content = wp_unslash( $_POST['settings_import'] );
if ( empty( $content ) ) {
return;
}

View File

@@ -0,0 +1,239 @@
<?php
/**
* File with the class to handle data from All in One SEO Pack, versions 4 and up.
*
* @package WPSEO\Admin\Import\Plugins
*/
use Yoast\WP\SEO\Actions\Importing\Aioseo\Aioseo_Cleanup_Action;
use Yoast\WP\SEO\Actions\Importing\Aioseo\Aioseo_Posts_Importing_Action;
/**
* Class with functionality to import & clean All in One SEO Pack post metadata, versions 4 and up.
*/
class WPSEO_Import_AIOSEO_V4 extends WPSEO_Plugin_Importer {
/**
* The plugin name.
*
* @var string
*/
protected $plugin_name = 'All In One SEO Pack';
/**
* Meta key, used in SQL LIKE clause for delete query.
*
* @var string
*/
protected $meta_key = '_aioseo_%';
/**
* Array of meta keys to detect and import.
*
* @var array
*/
protected $clone_keys = [
[
'old_key' => '_aioseo_title',
'new_key' => 'title',
],
[
'old_key' => '_aioseo_description',
'new_key' => 'metadesc',
],
[
'old_key' => '_aioseo_og_title',
'new_key' => 'opengraph-title',
],
[
'old_key' => '_aioseo_og_description',
'new_key' => 'opengraph-description',
],
[
'old_key' => '_aioseo_twitter_title',
'new_key' => 'twitter-title',
],
[
'old_key' => '_aioseo_twitter_description',
'new_key' => 'twitter-description',
],
];
/**
* Mapping between the AiOSEO replace vars and the Yoast replace vars.
*
* @var array
*
* @see https://yoast.com/help/list-available-snippet-variables-yoast-seo/
*/
protected $replace_vars = [
// They key is the AiOSEO replace var, the value is the Yoast replace var (see class-wpseo-replace-vars).
'#author_first_name' => '%%author_first_name%%',
'#author_last_name' => '%%author_last_name%%',
'#author_name' => '%%name%%',
'#categories' => '%%category%%',
'#current_date' => '%%currentdate%%',
'#current_day' => '%%currentday%%',
'#current_month' => '%%currentmonth%%',
'#current_year' => '%%currentyear%%',
'#permalink' => '%%permalink%%',
'#post_content' => '%%post_content%%',
'#post_date' => '%%date%%',
'#post_day' => '%%post_day%%',
'#post_month' => '%%post_month%%',
'#post_title' => '%%title%%',
'#post_year' => '%%post_year%%',
'#post_excerpt_only' => '%%excerpt_only%%',
'#post_excerpt' => '%%excerpt%%',
'#separator_sa' => '%%sep%%',
'#site_title' => '%%sitename%%',
'#tagline' => '%%sitedesc%%',
'#taxonomy_title' => '%%category_title%%',
];
/**
* Replaces the AiOSEO variables in our temporary table with Yoast variables (replace vars).
*
* @param array $replace_values Key value pair of values to replace with other values. This is only used in the base class but not here.
* That is because this class doesn't have any `convert` keys in `$clone_keys`.
* For that reason, we're overwriting the base class' `meta_key_clone_replace()` function without executing that base functionality.
*
* @return void
*/
protected function meta_key_clone_replace( $replace_values ) {
global $wpdb;
// At this point we're already looping through all the $clone_keys (this happens in meta_keys_clone() in the abstract class).
// Now, we'll also loop through the replace_vars array, which holds the mappings between the AiOSEO variables and the Yoast variables.
// We'll replace all the AiOSEO variables in the temporary table with their Yoast equivalents.
foreach ( $this->replace_vars as $aioseo_variable => $yoast_variable ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: We need this query and this is done at many other places as well, for example class-import-rankmath.
$wpdb->query(
$wpdb->prepare(
'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )',
$aioseo_variable,
$yoast_variable
)
);
}
// The AiOSEO custom fields take the form of `#custom_field-myfield`.
// These should be mapped to %%cf_myfield%%.
$meta_values_with_custom_fields = $this->get_meta_values_with_custom_field_or_taxonomy( $wpdb, 'custom_field' );
$unique_custom_fields = $this->get_unique_custom_fields_or_taxonomies( $meta_values_with_custom_fields, 'custom_field' );
$this->replace_custom_field_or_taxonomy_replace_vars( $unique_custom_fields, $wpdb, 'custom_field', 'cf' );
// Map `#tax_name-{tax-slug}` to `%%ct_{tax-slug}%%``.
$meta_values_with_custom_taxonomies = $this->get_meta_values_with_custom_field_or_taxonomy( $wpdb, 'tax_name' );
$unique_custom_taxonomies = $this->get_unique_custom_fields_or_taxonomies( $meta_values_with_custom_taxonomies, 'tax_name' );
$this->replace_custom_field_or_taxonomy_replace_vars( $unique_custom_taxonomies, $wpdb, 'tax_name', 'ct' );
}
/**
* Filters out all unique custom fields/taxonomies/etc. used in an AiOSEO replace var.
*
* @param string[] $meta_values An array of all the meta values that
* contain one or more AIOSEO custom field replace vars
* (in the form `#custom_field-xyz`).
* @param string $aioseo_prefix The AiOSEO prefix to use
* (e.g. `custom-field` for custom fields or `tax_name` for custom taxonomies).
*
* @return string[] An array of all the unique custom fields/taxonomies/etc. used in the replace vars.
* E.g. `xyz` in the above example.
*/
protected function get_unique_custom_fields_or_taxonomies( $meta_values, $aioseo_prefix ) {
$unique_custom_fields_or_taxonomies = [];
foreach ( $meta_values as $meta_value ) {
// Find all custom field replace vars, store them in `$matches`.
\preg_match_all(
"/#$aioseo_prefix-([\w-]+)/",
$meta_value,
$matches
);
/*
* `$matches[1]` contain the captured matches of the
* first capturing group (the `([\w-]+)` in the regex above).
*/
$custom_fields_or_taxonomies = $matches[1];
foreach ( $custom_fields_or_taxonomies as $custom_field_or_taxonomy ) {
$unique_custom_fields_or_taxonomies[ \trim( $custom_field_or_taxonomy ) ] = 1;
}
}
return \array_keys( $unique_custom_fields_or_taxonomies );
}
/**
* Replaces every AIOSEO custom field/taxonomy/etc. replace var with the Yoast version.
*
* E.g. `#custom_field-xyz` becomes `%%cf_xyz%%`.
*
* @param string[] $unique_custom_fields_or_taxonomies An array of unique custom fields to replace the replace vars of.
* @param wpdb $wpdb The WordPress database object.
* @param string $aioseo_prefix The AiOSEO prefix to use
* (e.g. `custom-field` for custom fields or `tax_name` for custom taxonomies).
* @param string $yoast_prefix The Yoast prefix to use (e.g. `cf` for custom fields).
*/
protected function replace_custom_field_or_taxonomy_replace_vars( $unique_custom_fields_or_taxonomies, $wpdb, $aioseo_prefix, $yoast_prefix ) {
foreach ( $unique_custom_fields_or_taxonomies as $unique_custom_field_or_taxonomy ) {
$aioseo_variable = "#{$aioseo_prefix}-{$unique_custom_field_or_taxonomy}";
$yoast_variable = "%%{$yoast_prefix}_{$unique_custom_field_or_taxonomy}%%";
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query(
$wpdb->prepare(
'UPDATE tmp_meta_table SET meta_value = REPLACE( meta_value, %s, %s )',
$aioseo_variable,
$yoast_variable
)
);
}
}
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
/**
* Retrieve all the meta values from the temporary meta table that contain
* at least one AiOSEO custom field replace var.
*
* @param wpdb $wpdb The WordPress database object.
* @param string $aioseo_prefix The AiOSEO prefix to use
* (e.g. `custom-field` for custom fields or `tax_name` for custom taxonomies).
*
* @return string[] All meta values that contain at least one AioSEO custom field replace var.
*/
protected function get_meta_values_with_custom_field_or_taxonomy( $wpdb, $aioseo_prefix ) {
return $wpdb->get_col(
$wpdb->prepare(
'SELECT meta_value FROM tmp_meta_table WHERE meta_value LIKE %s',
"%#$aioseo_prefix-%"
)
);
}
// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
/**
* Detects whether there is AIOSEO data to import by looking whether the AIOSEO data have been cleaned up.
*
* @return bool Boolean indicating whether there is something to import.
*/
protected function detect() {
$aioseo_cleanup_action = YoastSEO()->classes->get( Aioseo_Cleanup_Action::class );
return ( $aioseo_cleanup_action->get_total_unindexed() > 0 );
}
/**
* Import AIOSEO post data from their custom indexable table. Not currently used.
*
* @return void
*/
protected function import() {
// This is overriden from the import.js and never run.
$aioseo_posts_import_action = YoastSEO()->classes->get( Aioseo_Posts_Importing_Action::class );
$aioseo_posts_import_action->index();
}
}

View File

@@ -1,12 +1,12 @@
<?php
/**
* File with the class to handle data from All in One SEO Pack.
* File with the class to handle data from All in One SEO Pack, versions 3 and under.
*
* @package WPSEO\Admin\Import\Plugins
*/
/**
* Class with functionality to import & clean All in One SEO Pack post metadata.
* Class with functionality to import & clean All in One SEO Pack post metadata, versions 3 and under.
*/
class WPSEO_Import_AIOSEO extends WPSEO_Plugin_Importer {

View File

@@ -15,7 +15,7 @@ class WPSEO_Import_SEO_Framework extends WPSEO_Plugin_Importer {
*
* @var string
*/
protected $plugin_name = 'SEO Framework';
protected $plugin_name = 'The SEO Framework';
/**
* Meta key, used in SQL LIKE clause for delete query.

View File

@@ -45,7 +45,7 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer {
protected function import() {
// Query for all the posts that have an _seop_settings meta set.
$query_posts = new WP_Query( 'post_type=any&meta_key=_seop_settings&order=ASC&fields=ids&nopaging=true' );
foreach ( $query_posts->posts as $key => $post_id ) {
foreach ( $query_posts->posts as $post_id ) {
$this->import_post_focus_keywords( $post_id );
$this->import_seopressor_post_settings( $post_id );
}

View File

@@ -19,6 +19,7 @@ class WPSEO_Plugin_Importers {
*/
private static $importers = [
'WPSEO_Import_AIOSEO',
'WPSEO_Import_AIOSEO_V4',
'WPSEO_Import_Greg_SEO',
'WPSEO_Import_HeadSpace',
'WPSEO_Import_Jetpack_SEO',

View File

@@ -24,45 +24,48 @@ class WPSEO_Admin_Menu extends WPSEO_Base_Menu {
* Registers the menu item submenus.
*/
public function register_settings_page() {
$can_manage_options = $this->check_manage_capability();
if ( $can_manage_options ) {
/*
* The current user has the capability to control anything.
* This means that all submenus and dashboard can be shown.
*/
global $admin_page_hooks;
add_menu_page(
'Yoast SEO: ' . __( 'Dashboard', 'wordpress-seo' ),
__( 'SEO', 'wordpress-seo' ) . ' ' . $this->get_notification_counter(),
$this->get_manage_capability(),
$this->get_page_identifier(),
$this->get_admin_page_callback(),
$this->get_icon_svg(),
'99.31337'
);
// Wipe notification bits from hooks.
// phpcs:ignore WordPress.WP.GlobalVariablesOverride -- This is a deliberate action.
$admin_page_hooks[ $this->get_page_identifier() ] = 'seo';
}
$manage_capability = $this->get_manage_capability();
$page_identifier = $this->get_page_identifier();
$admin_page_callback = $this->get_admin_page_callback();
// Get all submenu pages.
$submenu_pages = $this->get_submenu_pages();
// Add submenu items to the main menu if possible.
if ( $can_manage_options ) {
$this->register_submenu_pages( $submenu_pages );
foreach ( $submenu_pages as $submenu_page ) {
if ( WPSEO_Capability_Utils::current_user_can( $submenu_page[3] ) ) {
$manage_capability = $submenu_page[3];
$page_identifier = $submenu_page[4];
$admin_page_callback = $submenu_page[5];
break;
}
}
foreach ( $submenu_pages as $index => $submenu_page ) {
$submenu_pages[ $index ][0] = $page_identifier;
}
/*
* If the user does not have the general manage options capability,
* we need to make sure the desired sub-item can be reached.
* The current user has the capability to control anything.
* This means that all submenus and dashboard can be shown.
*/
if ( ! $can_manage_options ) {
$this->register_menu_pages( $submenu_pages );
}
global $admin_page_hooks;
add_menu_page(
'Yoast SEO: ' . __( 'Dashboard', 'wordpress-seo' ),
'Yoast SEO ' . $this->get_notification_counter(),
$manage_capability,
$page_identifier,
$admin_page_callback,
$this->get_icon_svg(),
99
);
// Wipe notification bits from hooks.
// phpcs:ignore WordPress.WP.GlobalVariablesOverride -- This is a deliberate action.
$admin_page_hooks[ $page_identifier ] = 'seo';
// Add submenu items to the main menu if possible.
$this->register_submenu_pages( $submenu_pages );
}
/**
@@ -84,13 +87,11 @@ class WPSEO_Admin_Menu extends WPSEO_Base_Menu {
// Submenu pages.
$submenu_pages = [
$this->get_submenu_page( __( 'General', 'wordpress-seo' ), $this->get_page_identifier() ),
$this->get_submenu_page( __( 'Search Appearance', 'wordpress-seo' ), 'wpseo_titles' ),
$this->get_submenu_page(
__( 'Search Console', 'wordpress-seo' ),
'wpseo_search_console',
$search_console_callback
),
$this->get_submenu_page( __( 'Social', 'wordpress-seo' ), 'wpseo_social' ),
$this->get_submenu_page( __( 'Tools', 'wordpress-seo' ), 'wpseo_tools' ),
$this->get_submenu_page( $this->get_license_page_title(), 'wpseo_licenses' ),
];
@@ -113,12 +114,10 @@ class WPSEO_Admin_Menu extends WPSEO_Base_Menu {
$notification_count = $notification_center->get_notification_count();
// Add main page.
/* translators: %s: number of notifications */
/* translators: Hidden accessibility text; %s: number of notifications. */
$notifications = sprintf( _n( '%s notification', '%s notifications', $notification_count, 'wordpress-seo' ), number_format_i18n( $notification_count ) );
$counter = sprintf( '<span class="update-plugins count-%1$d"><span class="plugin-count" aria-hidden="true">%1$d</span><span class="screen-reader-text">%2$s</span></span>', $notification_count, $notifications );
return $counter;
return sprintf( '<span class="update-plugins count-%1$d"><span class="plugin-count" aria-hidden="true">%1$d</span><span class="screen-reader-text">%2$s</span></span>', $notification_count, $notifications );
}
/**

View File

@@ -5,6 +5,8 @@
* @package WPSEO\Admin\Menu
*/
use Yoast\WP\SEO\Promotions\Application\Promotion_Manager;
/**
* Admin menu base class.
*/
@@ -92,13 +94,6 @@ abstract class WPSEO_Base_Menu implements WPSEO_WordPress_Integration {
// Loop through submenu pages and add them.
array_walk( $submenu_pages, [ $this, 'register_submenu_page' ] );
// Set the first submenu title to the title of the first submenu page.
global $submenu;
if ( isset( $submenu[ $this->get_page_identifier() ] ) && $this->check_manage_capability() ) {
// phpcs:ignore WordPress.WP.GlobalVariablesOverride -- This is a deliberate action.
$submenu[ $this->get_page_identifier() ][0][0] = $submenu_pages[0][2];
}
}
/**
@@ -138,7 +133,7 @@ abstract class WPSEO_Base_Menu implements WPSEO_WordPress_Integration {
$submenu_page[4],
$submenu_page[5],
$this->get_icon_svg(),
'99.31337'
99
);
// If necessary, add hooks for the submenu page.
@@ -188,9 +183,6 @@ abstract class WPSEO_Base_Menu implements WPSEO_WordPress_Integration {
$page_title .= ' - Yoast SEO';
// Force the general manage capability to be used.
$submenu_page[3] = $this->get_manage_capability();
// Register submenu page.
$hook_suffix = add_submenu_page(
$submenu_page[0],
@@ -268,6 +260,10 @@ abstract class WPSEO_Base_Menu implements WPSEO_WordPress_Integration {
$title = __( 'Premium', 'wordpress-seo' );
}
if ( YoastSEO()->classes->get( Promotion_Manager::class )->is( 'black-friday-2023-promotion' ) && ! YoastSEO()->helpers->product->is_premium() ) {
$title = __( 'Premium', 'wordpress-seo' ) . '<span class="yoast-menu-bf-sale-badge">' . __( '30% OFF', 'wordpress-seo' ) . '</span>';
}
return $title;
}

View File

@@ -59,8 +59,12 @@ class WPSEO_Menu implements WPSEO_WordPress_Integration {
* @return void
*/
public function load_page() {
$page = filter_input( INPUT_GET, 'page' );
$this->show_page( $page );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['page'] ) && is_string( $_GET['page'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$page = sanitize_text_field( wp_unslash( $_GET['page'] ) );
$this->show_page( $page );
}
}
/**
@@ -76,14 +80,6 @@ class WPSEO_Menu implements WPSEO_WordPress_Integration {
require_once WPSEO_PATH . 'admin/pages/tools.php';
break;
case 'wpseo_titles':
require_once WPSEO_PATH . 'admin/pages/metas.php';
break;
case 'wpseo_social':
require_once WPSEO_PATH . 'admin/pages/social.php';
break;
case 'wpseo_licenses':
require_once WPSEO_PATH . 'admin/pages/licenses.php';
break;
@@ -92,10 +88,6 @@ class WPSEO_Menu implements WPSEO_WordPress_Integration {
require_once WPSEO_PATH . 'admin/views/tool-file-editor.php';
break;
case 'wpseo_configurator':
require_once WPSEO_PATH . 'admin/config-ui/class-configuration-page.php';
break;
default:
require_once WPSEO_PATH . 'admin/pages/dashboard.php';
break;

View File

@@ -32,7 +32,7 @@ class WPSEO_Network_Admin_Menu extends WPSEO_Base_Menu {
add_menu_page(
__( 'Network Settings', 'wordpress-seo' ) . ' - Yoast SEO',
__( 'SEO', 'wordpress-seo' ),
'Yoast SEO',
$this->get_manage_capability(),
$this->get_page_identifier(),
[ $this, 'network_config_page' ],

View File

@@ -30,6 +30,7 @@ class WPSEO_Replacevar_Editor {
* @type string $label_description Optional. The label to use for the description field.
* @type string $description_placeholder Optional. The placeholder text to use for the description field.
* @type bool $has_new_badge Optional. Whether to show the "New" badge.
* @type bool $has_premium_badge Optional. Whether to show the "Premium" badge.
* }
*/
private $arguments;
@@ -50,6 +51,7 @@ class WPSEO_Replacevar_Editor {
* @type string $label_description Optional. The label to use for the description field.
* @type string $description_placeholder Optional. The placeholder text to use for the description field.
* @type bool $has_new_badge Optional. Whether to show the "New" badge.
* @type bool $has_premium_badge Optional. Whether to show the "Premium" badge.
* }
*/
public function __construct( Yoast_Form $yform, $arguments ) {
@@ -61,6 +63,8 @@ class WPSEO_Replacevar_Editor {
'label_description' => '',
'description_placeholder' => '',
'has_new_badge' => false,
'is_disabled' => false,
'has_premium_badge' => false,
]
);
@@ -77,6 +81,8 @@ class WPSEO_Replacevar_Editor {
'label_description' => (string) $arguments['label_description'],
'description_placeholder' => (string) $arguments['description_placeholder'],
'has_new_badge' => (bool) $arguments['has_new_badge'],
'is_disabled' => (bool) $arguments['is_disabled'],
'has_premium_badge' => (bool) $arguments['has_premium_badge'],
];
}
@@ -102,7 +108,10 @@ class WPSEO_Replacevar_Editor {
data-react-replacevar-label-title="%6$s"
data-react-replacevar-label-description="%7$s"
data-react-replacevar-description-placeholder="%8$s"
data-react-replacevar-has-new-badge="%9$s"></div>',
data-react-replacevar-has-new-badge="%9$s"
data-react-replacevar-is-disabled="%10$s"
data-react-replacevar-has-premium-badge="%11$s"
></div>',
esc_attr( $this->arguments['title'] ),
esc_attr( $this->arguments['description'] ),
esc_attr( $this->arguments['page_type_recommended'] ),
@@ -111,7 +120,9 @@ class WPSEO_Replacevar_Editor {
esc_attr( $this->arguments['label_title'] ),
esc_attr( $this->arguments['label_description'] ),
esc_attr( $this->arguments['description_placeholder'] ),
esc_attr( $this->arguments['has_new_badge'] )
esc_attr( $this->arguments['has_new_badge'] ),
esc_attr( $this->arguments['is_disabled'] ),
esc_attr( $this->arguments['has_premium_badge'] )
);
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin\Metabox
*/
/**
* Represents the inclusive language analysis.
*/
class WPSEO_Metabox_Analysis_Inclusive_Language implements WPSEO_Metabox_Analysis {
/**
* Whether this analysis is enabled.
*
* @return bool Whether or not this analysis is enabled.
*/
public function is_enabled() {
return $this->is_globally_enabled() && $this->is_user_enabled() && $this->is_current_version_supported()
&& YoastSEO()->helpers->language->has_inclusive_language_support( \WPSEO_Language_Utils::get_language( \get_locale() ) );
}
/**
* Whether or not this analysis is enabled by the user.
*
* @return bool Whether or not this analysis is enabled by the user.
*/
public function is_user_enabled() {
return ! get_the_author_meta( 'wpseo_inclusive_language_analysis_disable', get_current_user_id() );
}
/**
* Whether or not this analysis is enabled globally.
*
* @return bool Whether or not this analysis is enabled globally.
*/
public function is_globally_enabled() {
return WPSEO_Options::get( 'inclusive_language_analysis_active', false );
}
/**
* Whether the inclusive language analysis should be loaded in Free.
*
* It should always be loaded when Premium is not active. If Premium is active, it depends on the version. Some Premium
* versions also have inclusive language code (when it was still a Premium only feature) which would result in rendering
* the analysis twice. In those cases, the analysis should be only loaded from the Premium side.
*
* @return bool Whether or not the inclusive language analysis should be loaded.
*/
private function is_current_version_supported() {
$is_premium = YoastSEO()->helpers->product->is_premium();
$premium_version = YoastSEO()->helpers->product->get_premium_version();
return ! $is_premium
|| \version_compare( $premium_version, '19.6-RC0', '>=' )
|| \version_compare( $premium_version, '19.2', '==' );
}
}

View File

@@ -16,7 +16,12 @@ class WPSEO_Metabox_Editor {
* @codeCoverageIgnore
*/
public function register_hooks() {
// For the Classic editor.
add_filter( 'mce_css', [ $this, 'add_css_inside_editor' ] );
// For the Block/Gutenberg editor.
// See https://github.com/danielbachhuber/gutenberg-migration-guide/blob/master/filter-mce-css.md.
add_action( 'enqueue_block_editor_assets', [ $this, 'add_editor_styles' ] );
add_filter( 'tiny_mce_before_init', [ $this, 'add_custom_element' ] );
}
@@ -44,6 +49,14 @@ class WPSEO_Metabox_Editor {
return $css_files;
}
/**
* Enqueues the CSS to use in the TinyMCE editor.
*/
public function add_editor_styles() {
$asset_manager = new WPSEO_Admin_Asset_Manager();
$asset_manager->enqueue_style( 'inside-editor' );
}
/**
* Adds a custom element to the tinyMCE editor that we need for marking the content.
*

View File

@@ -0,0 +1,42 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
*/
/**
* Generates and displays the React root element for a metabox section.
*/
class WPSEO_Metabox_Section_Inclusive_Language implements WPSEO_Metabox_Section {
/**
* Name of the section, used as an identifier in the HTML.
*
* @var string
*/
public $name = 'inclusive-language';
/**
* Outputs the section link.
*/
public function display_link() {
printf(
'<li role="presentation"><a role="tab" href="#wpseo-meta-section-%1$s" id="wpseo-meta-tab-%1$s" aria-controls="wpseo-meta-section-%1$s" class="wpseo-meta-section-link">
<div class="wpseo-score-icon-container" id="wpseo-inclusive-language-score-icon"></div><span>%2$s</span></a></li>',
esc_attr( $this->name ),
esc_html__( 'Inclusive language', 'wordpress-seo' )
);
}
/**
* Outputs the section content.
*/
public function display_content() {
printf(
'<div role="tabpanel" id="wpseo-meta-section-%1$s" aria-labelledby="wpseo-meta-tab-%1$s" tabindex="0" class="wpseo-meta-section">',
esc_attr( $this->name )
);
echo '<div id="wpseo-metabox-inclusive-language-root" class="wpseo-metabox-root"></div>', '</div>';
}
}

View File

@@ -5,9 +5,11 @@
* @package WPSEO\Admin
*/
use Yoast\WP\SEO\Conditionals\Admin\Estimated_Reading_Time_Conditional;
use Yoast\WP\SEO\Conditionals\Admin\Post_Conditional;
use Yoast\WP\SEO\Helpers\Input_Helper;
use Yoast\WP\SEO\Actions\Alert_Dismissal_Action;
use Yoast\WP\SEO\Conditionals\Third_Party\Jetpack_Boost_Active_Conditional;
use Yoast\WP\SEO\Conditionals\Third_Party\Jetpack_Boost_Not_Premium_Conditional;
use Yoast\WP\SEO\Conditionals\WooCommerce_Conditional;
use Yoast\WP\SEO\Introductions\Infrastructure\Wistia_Embed_Permission_Repository;
use Yoast\WP\SEO\Presenters\Admin\Alert_Presenter;
use Yoast\WP\SEO\Presenters\Admin\Meta_Fields_Presenter;
@@ -17,26 +19,33 @@ use Yoast\WP\SEO\Presenters\Admin\Meta_Fields_Presenter;
class WPSEO_Metabox extends WPSEO_Meta {
/**
* Whether or not the social tab is enabled.
* Whether the social tab is enabled.
*
* @var bool
*/
private $social_is_enabled;
/**
* Helper to determine whether or not the SEO analysis is enabled.
* Helper to determine whether the SEO analysis is enabled.
*
* @var WPSEO_Metabox_Analysis_SEO
*/
protected $seo_analysis;
/**
* Helper to determine whether or not the readability analysis is enabled.
* Helper to determine whether the readability analysis is enabled.
*
* @var WPSEO_Metabox_Analysis_Readability
*/
protected $readability_analysis;
/**
* Helper to determine whether the inclusive language analysis is enabled.
*
* @var WPSEO_Metabox_Analysis_Inclusive_Language
*/
protected $inclusive_language_analysis;
/**
* The metabox editor object.
*
@@ -52,25 +61,19 @@ class WPSEO_Metabox extends WPSEO_Meta {
protected $post = null;
/**
* Whether or not the advanced metadata is enabled.
* Whether the advanced metadata is enabled.
*
* @var bool
*/
protected $is_advanced_metadata_enabled;
/**
* Represents the estimated_reading_time_conditional.
*
* @var Estimated_Reading_Time_Conditional
*/
protected $estimated_reading_time_conditional;
/**
* Class constructor.
*/
public function __construct() {
if ( $this->is_internet_explorer() ) {
add_action( 'add_meta_boxes', [ $this, 'internet_explorer_metabox' ] );
return;
}
@@ -87,13 +90,9 @@ class WPSEO_Metabox extends WPSEO_Meta {
$this->social_is_enabled = WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false );
$this->is_advanced_metadata_enabled = WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false;
$this->estimated_reading_time_conditional = new Estimated_Reading_Time_Conditional(
new Post_Conditional(),
new Input_Helper()
);
$this->seo_analysis = new WPSEO_Metabox_Analysis_SEO();
$this->readability_analysis = new WPSEO_Metabox_Analysis_Readability();
$this->seo_analysis = new WPSEO_Metabox_Analysis_SEO();
$this->readability_analysis = new WPSEO_Metabox_Analysis_Readability();
$this->inclusive_language_analysis = new WPSEO_Metabox_Analysis_Inclusive_Language();
}
/**
@@ -204,6 +203,12 @@ class WPSEO_Metabox extends WPSEO_Meta {
'<a href="https://googlewebmastercentral.blogspot.com/2009/12/handling-legitimate-cross-domain.html" target="_blank" rel="noopener">',
WPSEO_Admin_Utils::get_new_tab_message() . '</a>'
);
/* translators: %s expands to the post type name. */
WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['title'] = __( 'Timestamp this %s', 'wordpress-seo' );
WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['description'] = __( 'Use WordProof to timestamp this page to comply with legal regulations and join the fight for a more transparant and accountable internet.', 'wordpress-seo' );
WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['options']['0'] = __( 'Off', 'wordpress-seo' );
WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['options']['1'] = __( 'On', 'wordpress-seo' );
WPSEO_Meta::$meta_fields['advanced']['wordproof_timestamp']['type'] = 'hidden';
WPSEO_Meta::$meta_fields['advanced']['redirect']['title'] = __( '301 Redirect', 'wordpress-seo' );
WPSEO_Meta::$meta_fields['advanced']['redirect']['description'] = __( 'The URL that this page should redirect to.', 'wordpress-seo' );
@@ -298,6 +303,10 @@ class WPSEO_Metabox extends WPSEO_Meta {
$values['semrushIntegrationActive'] = 0;
}
if ( $values['wincherIntegrationActive'] && $this->post->post_type === 'attachment' ) {
$values['wincherIntegrationActive'] = 0;
}
return $values;
}
@@ -414,6 +423,10 @@ class WPSEO_Metabox extends WPSEO_Meta {
$tabs[] = new WPSEO_Metabox_Section_Readability();
}
if ( $this->inclusive_language_analysis->is_enabled() ) {
$tabs[] = new WPSEO_Metabox_Section_Inclusive_Language();
}
if ( $this->is_advanced_metadata_enabled ) {
$tabs[] = new WPSEO_Metabox_Section_React(
'schema',
@@ -588,7 +601,6 @@ class WPSEO_Metabox extends WPSEO_Meta {
$options_count = count( $meta_field_def['options'] );
// This select now uses Select2.
$content .= '<select multiple="multiple" size="' . esc_attr( $options_count ) . '" name="' . $esc_form_key . '[]" id="' . $esc_form_key . '" class="yoast' . $class . '"' . $aria_describedby . '>';
foreach ( $meta_field_def['options'] as $val => $option ) {
$selected = '';
@@ -707,7 +719,8 @@ class WPSEO_Metabox extends WPSEO_Meta {
return false;
}
if ( ! isset( $_POST['yoast_free_metabox_nonce'] ) || ! wp_verify_nonce( $_POST['yoast_free_metabox_nonce'], 'yoast_free_metabox' ) ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized in wp_verify_none.
if ( ! isset( $_POST['yoast_free_metabox_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['yoast_free_metabox_nonce'] ), 'yoast_free_metabox' ) ) {
return false;
}
@@ -806,6 +819,10 @@ class WPSEO_Metabox extends WPSEO_Meta {
return true;
}
if ( $key === 'inclusive_language_score' && ! $this->inclusive_language_analysis->is_enabled() ) {
return true;
}
return false;
}
@@ -834,8 +851,10 @@ class WPSEO_Metabox extends WPSEO_Meta {
}
$post_id = get_queried_object_id();
if ( empty( $post_id ) && isset( $_GET['post'] ) ) {
$post_id = sanitize_text_field( filter_input( INPUT_GET, 'post' ) );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( empty( $post_id ) && isset( $_GET['post'] ) && is_string( $_GET['post'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$post_id = sanitize_text_field( wp_unslash( $_GET['post'] ) );
}
if ( $post_id !== 0 ) {
@@ -845,8 +864,8 @@ class WPSEO_Metabox extends WPSEO_Meta {
$asset_manager->enqueue_style( 'metabox-css' );
$asset_manager->enqueue_style( 'scoring' );
$asset_manager->enqueue_style( 'select2' );
$asset_manager->enqueue_style( 'monorepo' );
$asset_manager->enqueue_style( 'ai-generator' );
$is_block_editor = WP_Screen::get()->is_block_editor();
$post_edit_handle = 'post-edit';
@@ -856,9 +875,6 @@ class WPSEO_Metabox extends WPSEO_Meta {
$asset_manager->enqueue_script( $post_edit_handle );
$asset_manager->enqueue_style( 'admin-css' );
$yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_L10n();
$yoast_components_l10n->localize_script( $post_edit_handle );
/**
* Removes the emoji script as it is incompatible with both React and any
* contenteditable fields.
@@ -866,19 +882,18 @@ class WPSEO_Metabox extends WPSEO_Meta {
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
$asset_manager->localize_script( $post_edit_handle, 'wpseoAdminL10n', WPSEO_Utils::get_admin_l10n() );
$asset_manager->localize_script( $post_edit_handle, 'wpseoFeaturesL10n', WPSEO_Utils::retrieve_enabled_features() );
$plugins_script_data = [
'replaceVars' => [
'no_parent_text' => __( '(no parent)', 'wordpress-seo' ),
'replace_vars' => $this->get_replace_vars(),
'hidden_replace_vars' => $this->get_hidden_replace_vars(),
'recommended_replace_vars' => $this->get_recommended_replace_vars(),
'scope' => $this->determine_scope(),
'has_taxonomies' => $this->current_post_type_has_taxonomies(),
],
'shortcodes' => [
'wpseo_filter_shortcodes_nonce' => wp_create_nonce( 'wpseo-filter-shortcodes' ),
'wpseo_shortcode_tags' => $this->get_valid_shortcode_tags(),
'wpseo_shortcode_tags' => $this->get_valid_shortcode_tags(),
],
];
@@ -887,26 +902,43 @@ class WPSEO_Metabox extends WPSEO_Meta {
'dependencies' => YoastSEO()->helpers->asset->get_dependency_urls_by_handle( 'yoast-seo-analysis-worker' ),
'keywords_assessment_url' => YoastSEO()->helpers->asset->get_asset_url( 'yoast-seo-used-keywords-assessment' ),
'log_level' => WPSEO_Utils::get_analysis_worker_log_level(),
// We need to make the feature flags separately available inside of the analysis web worker.
'enabled_features' => WPSEO_Utils::retrieve_enabled_features(),
];
$alert_dismissal_action = YoastSEO()->classes->get( \Yoast\WP\SEO\Actions\Alert_Dismissal_Action::class );
$dismissed_alerts = $alert_dismissal_action->all_dismissed();
$alert_dismissal_action = YoastSEO()->classes->get( Alert_Dismissal_Action::class );
$dismissed_alerts = $alert_dismissal_action->all_dismissed();
$woocommerce_conditional = new WooCommerce_Conditional();
$woocommerce_active = $woocommerce_conditional->is_met();
$wpseo_plugin_availability_checker = new WPSEO_Plugin_Availability();
$woocommerce_seo_file = 'wpseo-woocommerce/wpseo-woocommerce.php';
$woocommerce_seo_active = $wpseo_plugin_availability_checker->is_active( $woocommerce_seo_file );
$script_data = [
// @todo replace this translation with JavaScript translations.
'media' => [ 'choose_image' => __( 'Use Image', 'wordpress-seo' ) ],
'metabox' => $this->get_metabox_script_data(),
'userLanguageCode' => WPSEO_Language_Utils::get_language( \get_user_locale() ),
'isPost' => true,
'isBlockEditor' => $is_block_editor,
'analysis' => [
'plugins' => $plugins_script_data,
'worker' => $worker_script_data,
'estimatedReadingTimeEnabled' => $this->estimated_reading_time_conditional->is_met(),
'media' => [ 'choose_image' => __( 'Use Image', 'wordpress-seo' ) ],
'metabox' => $this->get_metabox_script_data(),
'userLanguageCode' => WPSEO_Language_Utils::get_language( \get_user_locale() ),
'isPost' => true,
'isBlockEditor' => $is_block_editor,
'postId' => $post_id,
'postStatus' => get_post_status( $post_id ),
'postType' => get_post_type( $post_id ),
'usedKeywordsNonce' => \wp_create_nonce( 'wpseo-keyword-usage-and-post-types' ),
'analysis' => [
'plugins' => $plugins_script_data,
'worker' => $worker_script_data,
],
'dismissedAlerts' => $dismissed_alerts,
'dismissedAlerts' => $dismissed_alerts,
'currentPromotions' => YoastSEO()->classes->get( Yoast\WP\SEO\Promotions\Application\Promotion_Manager::class )->get_current_promotions(),
'webinarIntroBlockEditorUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/webinar-intro-block-editor' ),
'blackFridayBlockEditorUrl' => ( YoastSEO()->classes->get( Yoast\WP\SEO\Promotions\Application\Promotion_Manager::class )->is( 'black-friday-2023-checklist' ) ) ? WPSEO_Shortlinker::get( 'https://yoa.st/black-friday-checklist' ) : '',
'isJetpackBoostActive' => ( $is_block_editor ) ? YoastSEO()->classes->get( Jetpack_Boost_Active_Conditional::class )->is_met() : false,
'isJetpackBoostNotPremium' => ( $is_block_editor ) ? YoastSEO()->classes->get( Jetpack_Boost_Not_Premium_Conditional::class )->is_met() : false,
'isWooCommerceActive' => $woocommerce_active,
'woocommerceUpsell' => get_post_type( $post_id ) === 'product' && ! $woocommerce_seo_active && $woocommerce_active,
'isWooCommerceActive' => $woocommerce_active,
'linkParams' => WPSEO_Shortlinker::get_query_params(),
'pluginUrl' => \plugins_url( '', \WPSEO_FILE ),
'wistiaEmbedPermission' => YoastSEO()->classes->get( Wistia_Embed_Permission_Repository::class )->get_value_for_user( \get_current_user_id() ),
];
if ( post_type_supports( get_post_type(), 'thumbnail' ) ) {
@@ -932,9 +964,10 @@ class WPSEO_Metabox extends WPSEO_Meta {
return $this->post;
}
$post = filter_input( INPUT_GET, 'post' );
if ( ! empty( $post ) ) {
$post_id = (int) WPSEO_Utils::validate_int( $post );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['post'] ) && is_string( $_GET['post'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information, Sanitization happens in the validate_int function.
$post_id = (int) WPSEO_Utils::validate_int( wp_unslash( $_GET['post'] ) );
$this->post = get_post( $post_id );
@@ -980,7 +1013,21 @@ class WPSEO_Metabox extends WPSEO_Meta {
'sitedesc',
'sep',
'page',
'currentdate',
'currentyear',
'currentmonth',
'currentday',
'post_year',
'post_month',
'post_day',
'name',
'author_first_name',
'author_last_name',
'permalink',
'post_content',
'category_title',
'tag',
'category',
];
foreach ( $vars_to_cache as $var ) {
@@ -991,6 +1038,15 @@ class WPSEO_Metabox extends WPSEO_Meta {
return array_merge( $cached_replacement_vars, $this->get_custom_replace_vars( $this->get_metabox_post() ) );
}
/**
* Returns the list of replace vars that should be hidden inside the editor.
*
* @return string[] The hidden replace vars.
*/
protected function get_hidden_replace_vars() {
return ( new WPSEO_Replace_Vars() )->get_hidden_replace_vars();
}
/**
* Prepares the recommended replace vars for localization.
*
@@ -1067,12 +1123,39 @@ class WPSEO_Metabox extends WPSEO_Meta {
$custom_fields = get_post_custom( $post->ID );
// If $custom_fields is an empty string or generally not an array, return early.
if ( ! is_array( $custom_fields ) ) {
return $custom_replace_vars;
}
$meta = YoastSEO()->meta->for_post( $post->ID );
if ( ! $meta ) {
return $custom_replace_vars;
}
// Simply concatenate all fields containing replace vars so we can handle them all with a single regex find.
$replace_vars_fields = implode(
' ',
[
$meta->presentation->title,
$meta->presentation->meta_description,
]
);
preg_match_all( '/%%cf_([A-Za-z0-9_]+)%%/', $replace_vars_fields, $matches );
$fields_to_include = $matches[1];
foreach ( $custom_fields as $custom_field_name => $custom_field ) {
// Skip private custom fields.
if ( substr( $custom_field_name, 0, 1 ) === '_' ) {
continue;
}
// Skip custom fields that are not used, new ones will be fetched dynamically.
if ( ! in_array( $custom_field_name, $fields_to_include, true ) ) {
continue;
}
// Skip custom field values that are serialized.
if ( is_serialized( $custom_field[0] ) ) {
continue;

View File

@@ -90,10 +90,15 @@ abstract class WPSEO_Dismissible_Notification implements WPSEO_Listener, WPSEO_N
*
* @codeCoverageIgnore
*
* @return string The listener value.
* @return string|null The listener value or null if not set.
*/
protected function get_listener_value() {
return filter_input( INPUT_GET, 'yoast_dismiss' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: Normally we would need to check for a nonce here but this class is not used anymore.
if ( isset( $_GET['yoast_dismiss'] ) && is_string( $_GET['yoast_dismiss'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: Normally we would need to check for a nonce here but this class is not used anymore.
return sanitize_text_field( wp_unslash( $_GET['yoast_dismiss'] ) );
}
return null;
}
/**

View File

@@ -25,8 +25,8 @@ $yform->admin_header( true, 'wpseo' );
do_action( 'wpseo_all_admin_notices' );
$tabs = new WPSEO_Option_Tabs( 'dashboard' );
$tabs->add_tab(
$dashboard_tabs = new WPSEO_Option_Tabs( 'dashboard' );
$dashboard_tabs->add_tab(
new WPSEO_Option_Tab(
'dashboard',
__( 'Dashboard', 'wordpress-seo' ),
@@ -35,28 +35,13 @@ $tabs->add_tab(
]
)
);
$tabs->add_tab(
new WPSEO_Option_Tab(
'features',
__( 'Features', 'wordpress-seo' )
)
);
$tabs->add_tab(
new WPSEO_Option_Tab(
'integrations',
__( 'Integrations', 'wordpress-seo' )
)
);
$tabs->add_tab(
new WPSEO_Option_Tab(
'webmaster-tools',
__( 'Webmaster Tools', 'wordpress-seo' )
)
);
do_action( 'wpseo_settings_tabs_dashboard', $tabs );
/**
* Allows the addition of tabs to the dashboard by calling $dashboard_tabs->add_tab().
*/
do_action( 'wpseo_settings_tabs_dashboard', $dashboard_tabs );
$tabs->display( $yform );
$dashboard_tabs->display( $yform );
do_action( 'wpseo_dashboard' );

View File

@@ -14,11 +14,21 @@ if ( ! defined( 'WPSEO_VERSION' ) ) {
$yform = Yoast_Form::get_instance();
$yform->admin_header( true, 'wpseo_ms' );
$tabs = new WPSEO_Option_Tabs( 'network' );
$tabs->add_tab( new WPSEO_Option_Tab( 'general', __( 'General', 'wordpress-seo' ) ) );
$tabs->add_tab( new WPSEO_Option_Tab( 'features', __( 'Features', 'wordpress-seo' ) ) );
$tabs->add_tab( new WPSEO_Option_Tab( 'integrations', __( 'Integrations', 'wordpress-seo' ) ) );
$tabs->add_tab( new WPSEO_Option_Tab( 'restore-site', __( 'Restore Site', 'wordpress-seo' ), [ 'save_button' => false ] ) );
$tabs->display( $yform );
$network_tabs = new WPSEO_Option_Tabs( 'network' );
$network_tabs->add_tab( new WPSEO_Option_Tab( 'general', __( 'General', 'wordpress-seo' ) ) );
$network_tabs->add_tab( new WPSEO_Option_Tab( 'features', __( 'Features', 'wordpress-seo' ) ) );
$network_tabs->add_tab( new WPSEO_Option_Tab( 'integrations', __( 'Integrations', 'wordpress-seo' ) ) );
$network_tabs->add_tab(
new WPSEO_Option_Tab(
'crawl-settings',
__( 'Crawl settings', 'wordpress-seo' ),
[
'save_button' => true,
]
)
);
$network_tabs->add_tab( new WPSEO_Option_Tab( 'restore-site', __( 'Restore Site', 'wordpress-seo' ), [ 'save_button' => false ] ) );
$network_tabs->display( $yform );
$yform->admin_footer();

View File

@@ -0,0 +1,15 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
* @since 19.0
*/
if ( ! defined( 'WPSEO_VERSION' ) ) {
header( 'Status: 403 Forbidden' );
header( 'HTTP/1.1 403 Forbidden' );
exit();
}
require WPSEO_PATH . 'admin/views/redirects.php';

View File

@@ -11,7 +11,13 @@ if ( ! defined( 'WPSEO_VERSION' ) ) {
exit();
}
$tool_page = (string) filter_input( INPUT_GET, 'tool' );
$tool_page = '';
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['tool'] ) && is_string( $_GET['tool'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$tool_page = sanitize_text_field( wp_unslash( $_GET['tool'] ) );
}
$yform = Yoast_Form::get_instance();
$yform->admin_header( false );
@@ -22,7 +28,7 @@ if ( $tool_page === '' ) {
$tools['import-export'] = [
'title' => __( 'Import and Export', 'wordpress-seo' ),
'desc' => __( 'Import settings from other SEO plugins and export your settings for re-use on (another) blog.', 'wordpress-seo' ),
'desc' => __( 'Import settings from other SEO plugins and export your settings for re-use on (another) site.', 'wordpress-seo' ),
];
if ( WPSEO_Utils::allow_system_file_edit() === true && ! is_multisite() ) {
@@ -60,9 +66,23 @@ if ( $tool_page === '' ) {
}
/**
* Action: 'wpseo_tools_overview_list_items' - Hook to add additional tools to the overview.
* WARNING: This hook is intended for internal use only.
* Don't use it in your code as it will be removed shortly.
*/
do_action( 'wpseo_tools_overview_list_items' );
do_action( 'wpseo_tools_overview_list_items_internal' );
/**
* Action: 'wpseo_tools_overview_list_items' - Hook to add additional tools to the overview.
*
* @deprecated 19.10 No replacement available.
*/
do_action_deprecated(
'wpseo_tools_overview_list_items',
[],
'19.10',
'',
'This action is going away with no replacement. If you want to add settings that interact with Yoast SEO, please create your own settings page.'
);
echo '</ul>';
}

View File

@@ -19,13 +19,7 @@ class WPSEO_Role_Manager_Factory {
static $manager = null;
if ( $manager === null ) {
if ( function_exists( 'wpcom_vip_add_role' ) ) {
$manager = new WPSEO_Role_Manager_VIP();
}
if ( ! function_exists( 'wpcom_vip_add_role' ) ) {
$manager = new WPSEO_Role_Manager_WP();
}
$manager = new WPSEO_Role_Manager_WP();
}
return $manager;

View File

@@ -7,12 +7,18 @@
/**
* VIP implementation of the Role Manager.
*
* @deprecated 19.9
* @codeCoverageIgnore
*/
final class WPSEO_Role_Manager_VIP extends WPSEO_Abstract_Role_Manager {
/**
* Adds a role to the system.
*
* @deprecated 19.9
* @codeCoverageIgnore
*
* @param string $role Role to add.
* @param string $display_name Name to display for the role.
* @param array $capabilities Capabilities to add to the role.
@@ -20,6 +26,8 @@ final class WPSEO_Role_Manager_VIP extends WPSEO_Abstract_Role_Manager {
* @return void
*/
protected function add_role( $role, $display_name, array $capabilities = [] ) {
_deprecated_function( __METHOD__, 'Yoast SEO 19.9' );
$enabled_capabilities = [];
$disabled_capabilities = [];
@@ -43,11 +51,16 @@ final class WPSEO_Role_Manager_VIP extends WPSEO_Abstract_Role_Manager {
/**
* Removes a role from the system.
*
* @deprecated 19.9
* @codeCoverageIgnore
*
* @param string $role Role to remove.
*
* @return void
*/
protected function remove_role( $role ) {
_deprecated_function( __METHOD__, 'Yoast SEO 19.9' );
remove_role( $role );
}
}

View File

@@ -5,6 +5,9 @@
* @package WPSEO\Admin
*/
use Yoast\WP\SEO\Helpers\Score_Icon_Helper;
use Yoast\WP\SEO\Repositories\Indexable_Repository;
/**
* This class adds columns to the taxonomy table.
*/
@@ -31,6 +34,20 @@ class WPSEO_Taxonomy_Columns {
*/
private $taxonomy;
/**
* Holds the Indexable_Repository.
*
* @var Indexable_Repository
*/
protected $indexable_repository;
/**
* Holds the Score_Icon_Helper.
*
* @var Score_Icon_Helper
*/
protected $score_icon_helper;
/**
* WPSEO_Taxonomy_Columns constructor.
*/
@@ -45,6 +62,8 @@ class WPSEO_Taxonomy_Columns {
$this->analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$this->analysis_readability = new WPSEO_Metabox_Analysis_Readability();
$this->indexable_repository = YoastSEO()->classes->get( Indexable_Repository::class );
$this->score_icon_helper = YoastSEO()->helpers->score_icon;
}
/**
@@ -65,11 +84,13 @@ class WPSEO_Taxonomy_Columns {
$new_columns[ $column_name ] = $column_value;
if ( $column_name === 'description' && $this->analysis_seo->is_enabled() ) {
$new_columns['wpseo-score'] = '<span class="yoast-tooltip yoast-tooltip-n yoast-tooltip-alt" data-label="' . esc_attr__( 'SEO score', 'wordpress-seo' ) . '"><span class="yoast-column-seo-score yoast-column-header-has-tooltip"><span class="screen-reader-text">' . __( 'SEO score', 'wordpress-seo' ) . '</span></span></span>';
$new_columns['wpseo-score'] = '<span class="yoast-tooltip yoast-tooltip-n yoast-tooltip-alt" data-label="' . esc_attr__( 'SEO score', 'wordpress-seo' ) . '"><span class="yoast-column-seo-score yoast-column-header-has-tooltip"><span class="screen-reader-text">' .
__( 'SEO score', 'wordpress-seo' ) . '</span></span></span>';
}
if ( $column_name === 'description' && $this->analysis_readability->is_enabled() ) {
$new_columns['wpseo-score-readability'] = '<span class="yoast-tooltip yoast-tooltip-n yoast-tooltip-alt" data-label="' . esc_attr__( 'Readability score', 'wordpress-seo' ) . '"><span class="yoast-column-readability yoast-column-header-has-tooltip"><span class="screen-reader-text">' . __( 'Readability score', 'wordpress-seo' ) . '</span></span></span>';
$new_columns['wpseo-score-readability'] = '<span class="yoast-tooltip yoast-tooltip-n yoast-tooltip-alt" data-label="' . esc_attr__( 'Readability score', 'wordpress-seo' ) . '"><span class="yoast-column-readability yoast-column-header-has-tooltip"><span class="screen-reader-text">' .
__( 'Readability score', 'wordpress-seo' ) . '</span></span></span>';
}
}
@@ -99,12 +120,24 @@ class WPSEO_Taxonomy_Columns {
}
/**
* Retrieves the taxonomy from the $_GET variable.
* Retrieves the taxonomy from the $_GET or $_POST variable.
*
* @return string The current taxonomy.
* @return string|null The current taxonomy or null when it is not set.
*/
public function get_current_taxonomy() {
return filter_input( $this->get_taxonomy_input_type(), 'taxonomy' );
// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( ! empty( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] === 'POST' ) {
if ( isset( $_POST['taxonomy'] ) && is_string( $_POST['taxonomy'] ) ) {
return sanitize_text_field( wp_unslash( $_POST['taxonomy'] ) );
}
}
else {
if ( isset( $_GET['taxonomy'] ) && is_string( $_GET['taxonomy'] ) ) {
return sanitize_text_field( wp_unslash( $_GET['taxonomy'] ) );
}
}
// phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
return null;
}
/**
@@ -113,11 +146,19 @@ class WPSEO_Taxonomy_Columns {
* @return string|null
*/
private function get_taxonomy() {
// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( wp_doing_ajax() ) {
return FILTER_INPUT( INPUT_POST, 'taxonomy' );
if ( isset( $_POST['taxonomy'] ) && is_string( $_POST['taxonomy'] ) ) {
return sanitize_text_field( wp_unslash( $_POST['taxonomy'] ) );
}
}
return FILTER_INPUT( INPUT_GET, 'taxonomy' );
else {
if ( isset( $_GET['taxonomy'] ) && is_string( $_GET['taxonomy'] ) ) {
return sanitize_text_field( wp_unslash( $_GET['taxonomy'] ) );
}
}
// phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
return null;
}
/**
@@ -128,22 +169,9 @@ class WPSEO_Taxonomy_Columns {
* @return string
*/
private function get_score_value( $term_id ) {
$term = get_term( $term_id, $this->taxonomy );
$indexable = $this->indexable_repository->find_by_id_and_type( (int) $term_id, 'term' );
// When the term isn't indexable.
if ( ! $this->is_indexable( $term ) ) {
return $this->create_score_icon(
new WPSEO_Rank( WPSEO_Rank::NO_INDEX ),
__( 'Term is set to noindex.', 'wordpress-seo' )
);
}
// When there is a focus key word.
$focus_keyword = $this->get_focus_keyword( $term );
$score = (int) WPSEO_Taxonomy_Meta::get_term_meta( $term_id, $this->taxonomy, 'linkdex' );
$rank = WPSEO_Rank::from_numeric_score( $score );
return $this->create_score_icon( $rank, $rank->get_label() );
return $this->score_icon_helper->for_seo( $indexable, '', __( 'Term is set to noindex.', 'wordpress-seo' ) );
}
/**
@@ -155,25 +183,8 @@ class WPSEO_Taxonomy_Columns {
*/
private function get_score_readability_value( $term_id ) {
$score = (int) WPSEO_Taxonomy_Meta::get_term_meta( $term_id, $this->taxonomy, 'content_score' );
$rank = WPSEO_Rank::from_numeric_score( $score );
return $this->create_score_icon( $rank );
}
/**
* Creates an icon by the given values.
*
* @param WPSEO_Rank $rank The ranking object.
* @param string $title Optional. The title to show. Defaults to the rank label.
*
* @return string The HTML for a score icon.
*/
private function create_score_icon( WPSEO_Rank $rank, $title = '' ) {
if ( empty( $title ) ) {
$title = $rank->get_label();
}
return '<div aria-hidden="true" title="' . esc_attr( $title ) . '" class="wpseo-score-icon ' . esc_attr( $rank->get_css_class() ) . '"></div><span class="screen-reader-text wpseo-score-text">' . $title . '</span>';
return $this->score_icon_helper->for_readability( $score );
}
/**
@@ -181,7 +192,7 @@ class WPSEO_Taxonomy_Columns {
*
* @param mixed $term The current term.
*
* @return bool Whether or not the term is indexable.
* @return bool Whether the term is indexable.
*/
private function is_indexable( $term ) {
// When the no_index value is not empty and not default, check if its value is index.
@@ -202,35 +213,6 @@ class WPSEO_Taxonomy_Columns {
return true;
}
/**
* Returns the focus keyword if this is set, otherwise it will give the term name.
*
* @param stdClass|WP_Term $term The current term.
*
* @return string
*/
private function get_focus_keyword( $term ) {
$focus_keyword = WPSEO_Taxonomy_Meta::get_term_meta( 'focuskw', $term->term_id, $term->taxonomy );
if ( $focus_keyword !== false ) {
return $focus_keyword;
}
return $term->name;
}
/**
* Checks if a taxonomy is being added via a POST method. If not, it defaults to a GET request.
*
* @return int
*/
private function get_taxonomy_input_type() {
if ( ! empty( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] === 'POST' ) {
return INPUT_POST;
}
return INPUT_GET;
}
/**
* Wraps the WPSEO_Metabox check to determine whether the metabox should be displayed either by
* choice of the admin or because the taxonomy is not public.
@@ -239,10 +221,10 @@ class WPSEO_Taxonomy_Columns {
*
* @param string|null $taxonomy Optional. The taxonomy to test, defaults to the current taxonomy.
*
* @return bool Whether or not the meta box (and associated columns etc) should be hidden.
* @return bool Whether the meta box (and associated columns etc) should be hidden.
*/
private function display_metabox( $taxonomy = null ) {
$current_taxonomy = sanitize_text_field( $this->get_current_taxonomy() );
$current_taxonomy = $this->get_current_taxonomy();
if ( ! isset( $taxonomy ) && ! empty( $current_taxonomy ) ) {
$taxonomy = $current_taxonomy;

View File

@@ -72,6 +72,13 @@ class WPSEO_Taxonomy_Fields {
'options' => '',
'hide' => false,
],
'inclusive_language_score' => [
'label' => '',
'description' => '',
'type' => 'hidden',
'options' => '',
'hide' => false,
],
'focuskw' => [
'label' => '',
'description' => '',

View File

@@ -45,6 +45,13 @@ class WPSEO_Taxonomy_Metabox {
*/
protected $readability_analysis;
/**
* Helper to determine whether or not the inclusive language analysis is enabled.
*
* @var WPSEO_Metabox_Analysis_Inclusive_Language
*/
protected $inclusive_language_analysis;
/**
* The constructor.
*
@@ -56,8 +63,9 @@ class WPSEO_Taxonomy_Metabox {
$this->taxonomy = $taxonomy;
$this->is_social_enabled = WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false );
$this->seo_analysis = new WPSEO_Metabox_Analysis_SEO();
$this->readability_analysis = new WPSEO_Metabox_Analysis_Readability();
$this->seo_analysis = new WPSEO_Metabox_Analysis_SEO();
$this->readability_analysis = new WPSEO_Metabox_Analysis_Readability();
$this->inclusive_language_analysis = new WPSEO_Metabox_Analysis_Inclusive_Language();
}
/**
@@ -140,6 +148,10 @@ class WPSEO_Taxonomy_Metabox {
$tabs[] = new WPSEO_Metabox_Section_Readability();
}
if ( $this->inclusive_language_analysis->is_enabled() ) {
$tabs[] = new WPSEO_Metabox_Section_Inclusive_Language();
}
if ( $this->is_social_enabled ) {
$tabs[] = new WPSEO_Metabox_Section_React(
'social',
@@ -151,6 +163,56 @@ class WPSEO_Taxonomy_Metabox {
);
}
$tabs = array_merge( $tabs, $this->get_additional_tabs() );
return $tabs;
}
/**
* Returns the metabox tabs that have been added by other plugins.
*
* @return WPSEO_Metabox_Section_Additional[]
*/
protected function get_additional_tabs() {
$tabs = [];
/**
* Private filter: 'yoast_free_additional_taxonomy_metabox_sections'.
*
* Meant for internal use only. Allows adding additional tabs to the Yoast SEO metabox for taxonomies.
*
* @param array[] $tabs {
* An array of arrays with tab specifications.
*
* @type array $tab {
* A tab specification.
*
* @type string $name The name of the tab. Used in the HTML IDs, href and aria properties.
* @type string $link_content The content of the tab link.
* @type string $content The content of the tab.
* @type array $options {
* Optional. Extra options.
*
* @type string $link_class Optional. The class for the tab link.
* @type string $link_aria_label Optional. The aria label of the tab link.
* }
* }
* }
*/
$requested_tabs = apply_filters( 'yoast_free_additional_taxonomy_metabox_sections', [] );
foreach ( $requested_tabs as $tab ) {
if ( is_array( $tab ) && array_key_exists( 'name', $tab ) && array_key_exists( 'link_content', $tab ) && array_key_exists( 'content', $tab ) ) {
$options = array_key_exists( 'options', $tab ) ? $tab['options'] : [];
$tabs[] = new WPSEO_Metabox_Section_Additional(
$tab['name'],
$tab['link_content'],
$tab['content'],
$options
);
}
}
return $tabs;
}

View File

@@ -33,11 +33,18 @@ class WPSEO_Taxonomy {
*/
private $analysis_readability;
/**
* Holds the metabox inclusive language analysis instance.
*
* @var WPSEO_Metabox_Analysis_Inclusive_Language
*/
private $analysis_inclusive_language;
/**
* Class constructor.
*/
public function __construct() {
$this->taxonomy = $this->get_taxonomy();
$this->taxonomy = $this::get_taxonomy();
add_action( 'edit_term', [ $this, 'update_term' ], 99, 3 );
add_action( 'init', [ $this, 'custom_category_descriptions_allow_html' ] );
@@ -46,8 +53,9 @@ class WPSEO_Taxonomy {
if ( self::is_term_overview( $GLOBALS['pagenow'] ) ) {
new WPSEO_Taxonomy_Columns();
}
$this->analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$this->analysis_readability = new WPSEO_Metabox_Analysis_Readability();
$this->analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$this->analysis_readability = new WPSEO_Metabox_Analysis_Readability();
$this->analysis_inclusive_language = new WPSEO_Metabox_Analysis_Inclusive_Language();
}
/**
@@ -61,7 +69,8 @@ class WPSEO_Taxonomy {
return;
}
$this->insert_description_field_editor();
// Adds custom category description editor. Needs a hook that runs before the description field.
add_action( "{$this->taxonomy}_term_edit_form_top", [ $this, 'custom_category_description_editor' ] );
add_action( sanitize_text_field( $this->taxonomy ) . '_edit_form', [ $this, 'term_metabox' ], 90, 1 );
add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
@@ -125,10 +134,11 @@ class WPSEO_Taxonomy {
$asset_manager->enqueue_style( 'scoring' );
$asset_manager->enqueue_style( 'monorepo' );
$tag_id = filter_input( INPUT_GET, 'tag_ID' );
$tag_id = $this::get_tag_id();
if (
self::is_term_edit( $pagenow )
&& ! empty( $tag_id ) // After we drop support for <4.5 this can be removed.
&& ! is_null( $tag_id )
) {
wp_enqueue_media(); // Enqueue files needed for upload functionality.
@@ -136,9 +146,6 @@ class WPSEO_Taxonomy {
$asset_manager->enqueue_style( 'scoring' );
$asset_manager->enqueue_script( 'term-edit' );
$yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_L10n();
$yoast_components_l10n->localize_script( 'term-edit' );
/**
* Remove the emoji script as it is incompatible with both React and any
* contenteditable fields.
@@ -146,10 +153,9 @@ class WPSEO_Taxonomy {
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
$asset_manager->localize_script( 'term-edit', 'wpseoAdminL10n', WPSEO_Utils::get_admin_l10n() );
$asset_manager->localize_script( 'term-edit', 'wpseoFeaturesL10n', WPSEO_Utils::retrieve_enabled_features() );
$script_data = [
'analysis' => [
'analysis' => [
'plugins' => [
'replaceVars' => [
'no_parent_text' => __( '(no parent)', 'wordpress-seo' ),
@@ -157,6 +163,9 @@ class WPSEO_Taxonomy {
'recommended_replace_vars' => $this->get_recommended_replace_vars(),
'scope' => $this->determine_scope(),
],
'shortcodes' => [
'wpseo_shortcode_tags' => $this->get_valid_shortcode_tags(),
],
],
'worker' => [
'url' => YoastSEO()->helpers->asset->get_asset_url( 'yoast-seo-analysis-worker' ),
@@ -165,13 +174,16 @@ class WPSEO_Taxonomy {
'log_level' => WPSEO_Utils::get_analysis_worker_log_level(),
],
],
'media' => [
'media' => [
// @todo replace this translation with JavaScript translations.
'choose_image' => __( 'Use Image', 'wordpress-seo' ),
],
'metabox' => $this->localize_term_scraper_script(),
'userLanguageCode' => WPSEO_Language_Utils::get_language( \get_user_locale() ),
'isTerm' => true,
'metabox' => $this->localize_term_scraper_script( $tag_id ),
'userLanguageCode' => WPSEO_Language_Utils::get_language( \get_user_locale() ),
'isTerm' => true,
'postId' => $tag_id,
'usedKeywordsNonce' => \wp_create_nonce( 'wpseo-keyword-usage' ),
'linkParams' => WPSEO_Shortlinker::get_query_params(),
];
$asset_manager->localize_script( 'term-edit', 'wpseoScriptData', $script_data );
$asset_manager->enqueue_user_language_script();
@@ -198,9 +210,10 @@ class WPSEO_Taxonomy {
/* Create post array with only our values. */
$new_meta_data = [];
foreach ( WPSEO_Taxonomy_Meta::$defaults_per_term as $key => $default ) {
$posted_value = filter_input( INPUT_POST, $key );
if ( isset( $posted_value ) && $posted_value !== false ) {
$new_meta_data[ $key ] = $posted_value;
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: Nonce is already checked by WordPress before executing this action.
if ( isset( $_POST[ $key ] ) && is_string( $_POST[ $key ] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: Nonce is already checked by WordPress before executing this action.
$new_meta_data[ $key ] = sanitize_text_field( wp_unslash( $_POST[ $key ] ) );
}
// If analysis is disabled remove that analysis score value from the DB.
@@ -229,6 +242,10 @@ class WPSEO_Taxonomy {
return true;
}
if ( $key === 'wpseo_inclusive_language_score' && ! $this->analysis_inclusive_language->is_enabled() ) {
return true;
}
return false;
}
@@ -252,11 +269,12 @@ class WPSEO_Taxonomy {
/**
* Pass variables to js for use with the term-scraper.
*
* @param int $term_id The ID of the term to localize the script for.
*
* @return array
*/
public function localize_term_scraper_script() {
$term_id = filter_input( INPUT_GET, 'tag_ID' );
$term = get_term_by( 'id', $term_id, $this->get_taxonomy() );
public function localize_term_scraper_script( $term_id ) {
$term = get_term_by( 'id', $term_id, $this::get_taxonomy() );
$taxonomy = get_taxonomy( $term->taxonomy );
$term_formatter = new WPSEO_Metabox_Formatter(
@@ -287,7 +305,7 @@ class WPSEO_Taxonomy {
* @return string String decribing the current scope.
*/
private function determine_scope() {
$taxonomy = $this->get_taxonomy();
$taxonomy = $this::get_taxonomy();
if ( $taxonomy === 'category' ) {
return 'category';
@@ -325,13 +343,15 @@ class WPSEO_Taxonomy {
/**
* Function to get the labels for the current taxonomy.
*
* @return object Labels for the current taxonomy.
* @return object|null Labels for the current taxonomy or null if the taxonomy is not set.
*/
public static function get_labels() {
$term = filter_input( INPUT_GET, 'taxonomy', FILTER_DEFAULT, [ 'options' => [ 'default' => '' ] ] );
$taxonomy = get_taxonomy( $term );
return $taxonomy->labels;
$term = self::get_taxonomy();
if ( $term !== '' ) {
$taxonomy = get_taxonomy( $term );
return $taxonomy->labels;
}
return null;
}
/**
@@ -351,8 +371,30 @@ class WPSEO_Taxonomy {
*
* @return string
*/
private function get_taxonomy() {
return filter_input( INPUT_GET, 'taxonomy', FILTER_DEFAULT, [ 'options' => [ 'default' => '' ] ] );
private static function get_taxonomy() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['taxonomy'] ) && is_string( $_GET['taxonomy'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
return sanitize_text_field( wp_unslash( $_GET['taxonomy'] ) );
}
return '';
}
/**
* Get the current tag ID from the GET parameters.
*
* @return int|null the tag ID if it exists, null otherwise.
*/
private static function get_tag_id() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
if ( isset( $_GET['tag_ID'] ) && is_string( $_GET['tag_ID'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are not processing form information, We are casting to an integer.
$tag_id = (int) wp_unslash( $_GET['tag_ID'] );
if ( $tag_id > 0 ) {
return $tag_id;
}
}
return null;
}
/**
@@ -361,8 +403,8 @@ class WPSEO_Taxonomy {
* @return array The replacement variables.
*/
private function get_replace_vars() {
$term_id = filter_input( INPUT_GET, 'tag_ID' );
$term = get_term_by( 'id', $term_id, $this->get_taxonomy() );
$term_id = $this::get_tag_id();
$term = get_term_by( 'id', $term_id, $this::get_taxonomy() );
$cached_replacement_vars = [];
@@ -396,7 +438,11 @@ class WPSEO_Taxonomy {
*/
private function get_recommended_replace_vars() {
$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars();
$taxonomy = filter_input( INPUT_GET, 'taxonomy' );
$taxonomy = $this::get_taxonomy();
if ( $taxonomy === '' ) {
return [];
}
// What is recommended depends on the current context.
$page_type = $recommended_replace_vars->determine_for_term( $taxonomy );
@@ -405,18 +451,17 @@ class WPSEO_Taxonomy {
}
/**
* Adds custom category description editor.
* Needs a hook that runs before the description field. Prior to WP version 4.5 we need to use edit_form as
* term_edit_form_top was introduced in WP 4.5. This can be removed after <4.5 is no longer supported.
* Returns an array with shortcode tags for all registered shortcodes.
*
* @return void
* @return array
*/
private function insert_description_field_editor() {
if ( version_compare( $GLOBALS['wp_version'], '4.5', '<' ) ) {
add_action( "{$this->taxonomy}_edit_form", [ $this, 'custom_category_description_editor' ] );
return;
private function get_valid_shortcode_tags() {
$shortcode_tags = [];
foreach ( $GLOBALS['shortcode_tags'] as $tag => $description ) {
$shortcode_tags[] = $tag;
}
add_action( "{$this->taxonomy}_term_edit_form_top", [ $this, 'custom_category_description_editor' ] );
return $shortcode_tags;
}
}

View File

@@ -0,0 +1,126 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin\Tracking
*/
use Yoast\WP\SEO\Conditionals\WooCommerce_Conditional;
/**
* Represents the addon option data.
*/
class WPSEO_Tracking_Addon_Data implements WPSEO_Collection {
/**
* The local options we want to track.
*
* @var string[] The option_names for the options we want to track.
*/
private $local_include_list = [
'use_multiple_locations',
'multiple_locations_same_organization',
'business_type',
'woocommerce_local_pickup_setting',
];
/**
* The woo options we want to track.
*
* @var string[] The option_names for the options we want to track.
*/
private $woo_include_list = [];
/**
* The news options we want to track.
*
* @var string[] The option_names for the options we want to track.
*/
private $news_include_list = [];
/**
* The video options we want to track.
*
* @var string[] The option_names for the options we want to track.
*/
private $video_include_list = [];
/**
* Returns the collection data.
*
* @return array The collection data.
*/
public function get() {
$addon_settings = [];
$addon_manager = new WPSEO_Addon_Manager();
if ( $addon_manager->is_installed( WPSEO_Addon_Manager::LOCAL_SLUG ) ) {
$addon_settings = $this->get_local_addon_settings( $addon_settings, 'wpseo_local', WPSEO_Addon_Manager::LOCAL_SLUG, $this->local_include_list );
}
if ( $addon_manager->is_installed( WPSEO_Addon_Manager::WOOCOMMERCE_SLUG ) ) {
$addon_settings = $this->get_addon_settings( $addon_settings, 'wpseo_woo', WPSEO_Addon_Manager::WOOCOMMERCE_SLUG, $this->woo_include_list );
}
if ( $addon_manager->is_installed( WPSEO_Addon_Manager::NEWS_SLUG ) ) {
$addon_settings = $this->get_addon_settings( $addon_settings, 'wpseo_news', WPSEO_Addon_Manager::NEWS_SLUG, $this->news_include_list );
}
if ( $addon_manager->is_installed( WPSEO_Addon_Manager::VIDEO_SLUG ) ) {
$addon_settings = $this->get_addon_settings( $addon_settings, 'wpseo_video', WPSEO_Addon_Manager::VIDEO_SLUG, $this->video_include_list );
}
return $addon_settings;
}
/**
* Gets the tracked options from the addon
*
* @param array $addon_settings The current list of addon settings.
* @param string $source_name The option key of the addon.
* @param string $slug The addon slug.
* @param array $option_include_list All the options to be included in tracking.
*
* @return array
*/
public function get_addon_settings( array $addon_settings, $source_name, $slug, $option_include_list ) {
$source_options = \get_option( $source_name, [] );
if ( ! \is_array( $source_options ) || empty( $source_options ) ) {
return $addon_settings;
}
$addon_settings[ $slug ] = \array_intersect_key( $source_options, \array_flip( $option_include_list ) );
return $addon_settings;
}
/**
* Filter business_type in local addon settings.
*
* Remove the business_type setting when 'multiple_locations_shared_business_info' setting is turned off.
*
* @param array $addon_settings The current list of addon settings.
* @param string $source_name The option key of the addon.
* @param string $slug The addon slug.
* @param array $option_include_list All the options to be included in tracking.
*
* @return array
*/
public function get_local_addon_settings( array $addon_settings, $source_name, $slug, $option_include_list ) {
$source_options = \get_option( $source_name, [] );
if ( ! \is_array( $source_options ) || empty( $source_options ) ) {
return $addon_settings;
}
$addon_settings[ $slug ] = \array_intersect_key( $source_options, \array_flip( $option_include_list ) );
if ( \array_key_exists( 'use_multiple_locations', $source_options ) && \array_key_exists( 'business_type', $addon_settings[ $slug ] ) && $source_options['use_multiple_locations'] === 'on' && $source_options['multiple_locations_shared_business_info'] === 'off' ) {
$addon_settings[ $slug ]['business_type'] = 'multiple_locations';
}
if ( ! ( new WooCommerce_Conditional() )->is_met() ) {
unset( $addon_settings[ $slug ]['woocommerce_local_pickup_setting'] );
}
return $addon_settings;
}
}

View File

@@ -17,18 +17,36 @@ class WPSEO_Tracking_Default_Data implements WPSEO_Collection {
*/
public function get() {
return [
'siteTitle' => get_option( 'blogname' ),
'@timestamp' => (int) date( 'Uv' ),
'wpVersion' => $this->get_wordpress_version(),
'homeURL' => home_url(),
'adminURL' => admin_url(),
'isMultisite' => is_multisite(),
'siteLanguage' => get_bloginfo( 'language' ),
'gmt_offset' => get_option( 'gmt_offset' ),
'timezoneString' => get_option( 'timezone_string' ),
'siteTitle' => get_option( 'blogname' ),
'@timestamp' => (int) gmdate( 'Uv' ),
'wpVersion' => $this->get_wordpress_version(),
'homeURL' => home_url(),
'adminURL' => admin_url(),
'isMultisite' => is_multisite(),
'siteLanguage' => get_bloginfo( 'language' ),
'gmt_offset' => get_option( 'gmt_offset' ),
'timezoneString' => get_option( 'timezone_string' ),
'migrationStatus' => get_option( 'yoast_migrations_free' ),
'countPosts' => $this->get_post_count( 'post' ),
'countPages' => $this->get_post_count( 'page' ),
];
}
/**
* Returns the number of posts of a certain type.
*
* @param string $post_type The post type return the count for.
*
* @return int The count for this post type.
*/
protected function get_post_count( $post_type ) {
$count = wp_count_posts( $post_type );
if ( isset( $count->publish ) ) {
return $count->publish;
}
return 0;
}
/**
* Returns the WordPress version.
*

View File

@@ -10,6 +10,13 @@
*/
class WPSEO_Tracking_Plugin_Data implements WPSEO_Collection {
/**
* Plugins with auto updating enabled.
*
* @var array
*/
private $auto_update_plugin_list;
/**
* Returns the collection data.
*
@@ -31,9 +38,10 @@ class WPSEO_Tracking_Plugin_Data implements WPSEO_Collection {
if ( ! function_exists( 'get_plugin_data' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$plugins = wp_get_active_and_valid_plugins();
$plugins = array_map( 'get_plugin_data', $plugins );
$this->set_auto_update_plugin_list();
$plugins = array_map( [ $this, 'format_plugin' ], $plugins );
$plugin_data = [];
@@ -45,6 +53,25 @@ class WPSEO_Tracking_Plugin_Data implements WPSEO_Collection {
return $plugin_data;
}
/**
* Sets all auto updating plugin data so it can be used in the tracking list.
*
* @return void
*/
public function set_auto_update_plugin_list() {
$auto_update_plugins = [];
$auto_update_plugin_files = \get_option( 'auto_update_plugins' );
if ( $auto_update_plugin_files ) {
foreach ( $auto_update_plugin_files as $auto_update_plugin ) {
$data = get_plugin_data( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $auto_update_plugin );
$auto_update_plugins[ $data['Name'] ] = $data;
}
}
$this->auto_update_plugin_list = $auto_update_plugins;
}
/**
* Formats the plugin array.
*
@@ -53,9 +80,11 @@ class WPSEO_Tracking_Plugin_Data implements WPSEO_Collection {
* @return array The formatted array.
*/
protected function format_plugin( array $plugin ) {
return [
'name' => $plugin['Name'],
'version' => $plugin['Version'],
'name' => $plugin['Name'],
'version' => $plugin['Version'],
'auto_updating' => \array_key_exists( $plugin['Name'], $this->auto_update_plugin_list ),
];
}
}

View File

@@ -36,7 +36,7 @@ class WPSEO_Tracking_Server_Data implements WPSEO_Collection {
$server_data['Hostname'] = gethostbyaddr( $ipaddress );
}
$server_data['os'] = php_uname();
$server_data['os'] = function_exists( 'php_uname' ) ? php_uname() : PHP_OS;
$server_data['PhpVersion'] = PHP_VERSION;
$server_data['CurlVersion'] = $this->get_curl_info();
$server_data['PhpExtensions'] = $this->get_php_extensions();

View File

@@ -26,6 +26,7 @@ class WPSEO_Tracking_Settings_Data implements WPSEO_Collection {
'alternate_website_name',
'company_logo',
'company_name',
'company_alternate_name',
'person_name',
'person_logo',
'person_logo_id',
@@ -44,6 +45,8 @@ class WPSEO_Tracking_Settings_Data implements WPSEO_Collection {
'open_graph_frontpage_desc',
'open_graph_frontpage_image',
'open_graph_frontpage_image_id',
'other_social_urls',
'mastodon_url',
'pinterest_url',
'pinterestverify',
'twitter_site',
@@ -51,6 +54,20 @@ class WPSEO_Tracking_Settings_Data implements WPSEO_Collection {
'wikipedia_url',
'semrush_tokens',
'zapier_api_key',
'wincher_tokens',
'wincher_website_id',
'least_readability_ignore_list',
'least_seo_score_ignore_list',
'most_linked_ignore_list',
'least_linked_ignore_list',
'indexables_page_reading_list',
'publishing_principles_id',
'ownership_funding_info_id',
'actionable_feedback_policy_id',
'corrections_policy_id',
'ethics_policy_id',
'diversity_policy_id',
'diversity_staffing_report_id',
];
/**
@@ -72,6 +89,7 @@ class WPSEO_Tracking_Settings_Data implements WPSEO_Collection {
'environment_type',
'content_analysis_active',
'keyword_analysis_active',
'inclusive_language_analysis_active',
'enable_admin_bar_menu',
'enable_cornerstone_content',
'enable_xml_sitemap',
@@ -105,7 +123,6 @@ class WPSEO_Tracking_Settings_Data implements WPSEO_Collection {
'disable-date',
'disable-post_format',
'disable-attachment',
'is-media-purge-relevant',
'breadcrumbs-404crumb',
'breadcrumbs-display-blog-page',
'breadcrumbs-boldlast',
@@ -164,6 +181,7 @@ class WPSEO_Tracking_Settings_Data implements WPSEO_Collection {
'twitter_card_type',
'youtube_url',
'wikipedia_url',
'mastodon_url',
'indexables_indexing_completed',
'semrush_integration_active',
'semrush_tokens',
@@ -173,6 +191,50 @@ class WPSEO_Tracking_Settings_Data implements WPSEO_Collection {
'zapier_api_key',
'enable_metabox_insights',
'enable_link_suggestions',
'enable_index_now',
'enable_ai_generator',
'workouts',
'wincher_integration_active',
'wincher_tokens',
'wincher_website_id',
'wincher_automatically_add_keyphrases',
'first_time_install',
'other_social_urls',
'remove_feed_global',
'remove_feed_global_comments',
'remove_feed_post_comments',
'remove_feed_authors',
'remove_feed_categories',
'remove_feed_tags',
'remove_feed_custom_taxonomies',
'remove_feed_post_types',
'remove_feed_search',
'remove_atom_rdf_feeds',
'remove_shortlinks',
'remove_rest_api_links',
'remove_rsd_wlw_links',
'remove_oembed_links',
'remove_generator',
'remove_emoji_scripts',
'remove_powered_by_header',
'remove_pingback_header',
'clean_campaign_tracking_urls',
'clean_permalinks',
'clean_permalinks_extra_variables',
'search_cleanup',
'search_cleanup_emoji',
'search_cleanup_patterns',
'search_character_limit',
'redirect_search_pretty_urls',
'wordproof_integration_active',
'indexables_overview_state',
'deny_search_crawling',
'deny_wp_json_crawling',
'deny_adsbot_crawling',
'deny_ccbot_crawling',
'deny_google_extended_crawling',
'deny_gptbot_crawling',
'last_known_no_unindexed',
];
/**

View File

@@ -20,14 +20,16 @@ class WPSEO_Tracking_Theme_Data implements WPSEO_Collection {
return [
'theme' => [
'name' => $theme->get( 'Name' ),
'url' => $theme->get( 'ThemeURI' ),
'version' => $theme->get( 'Version' ),
'author' => [
'name' => $theme->get( 'Name' ),
'url' => $theme->get( 'ThemeURI' ),
'version' => $theme->get( 'Version' ),
'author' => [
'name' => $theme->get( 'Author' ),
'url' => $theme->get( 'AuthorURI' ),
],
'parentTheme' => $this->get_parent_theme( $theme ),
'parentTheme' => $this->get_parent_theme( $theme ),
'blockTemplateSupport' => current_theme_supports( 'block-templates' ),
'isBlockTheme' => function_exists( 'wp_is_block_theme' ) && wp_is_block_theme(),
],
];
}

View File

@@ -5,6 +5,9 @@
* @package WPSEO\Admin\Tracking
*/
use Yoast\WP\SEO\Analytics\Application\Missing_Indexables_Collector;
use Yoast\WP\SEO\Analytics\Application\To_Be_Cleaned_Indexables_Collector;
/**
* This class handles the tracking routine.
*/
@@ -93,12 +96,12 @@ class WPSEO_Tracking implements WPSEO_WordPress_Integration {
* needs to receive the same arguments as those used when originally
* scheduling the event otherwise it will always return false.
*/
if ( ! wp_next_scheduled( 'wpseo_send_tracking_data_after_core_update', true ) ) {
if ( ! wp_next_scheduled( 'wpseo_send_tracking_data_after_core_update', [ true ] ) ) {
/*
* Schedule sending of data tracking 6 hours after a WordPress core
* update. Pass a `true` parameter for the callback `$force` argument.
*/
wp_schedule_single_event( ( time() + ( HOUR_IN_SECONDS * 6 ) ), 'wpseo_send_tracking_data_after_core_update', true );
wp_schedule_single_event( ( time() + ( HOUR_IN_SECONDS * 6 ) ), 'wpseo_send_tracking_data_after_core_update', [ true ] );
}
}
@@ -106,7 +109,7 @@ class WPSEO_Tracking implements WPSEO_WordPress_Integration {
* Sends the tracking data.
*
* @param bool $force Whether to send the tracking data ignoring the two
* weeks time treshhold. Default false.
* weeks time threshold. Default false.
*/
public function send( $force = false ) {
if ( ! $this->should_send_tracking( $force ) ) {
@@ -188,6 +191,9 @@ class WPSEO_Tracking implements WPSEO_WordPress_Integration {
$collector->add_collection( new WPSEO_Tracking_Theme_Data() );
$collector->add_collection( new WPSEO_Tracking_Plugin_Data() );
$collector->add_collection( new WPSEO_Tracking_Settings_Data() );
$collector->add_collection( new WPSEO_Tracking_Addon_Data() );
$collector->add_collection( YoastSEO()->classes->get( Missing_Indexables_Collector::class ) );
$collector->add_collection( YoastSEO()->classes->get( To_Be_Cleaned_Indexables_Collector::class ) );
return $collector;
}
@@ -221,7 +227,7 @@ class WPSEO_Tracking implements WPSEO_WordPress_Integration {
return false;
}
if ( wp_get_environment_type() !== 'production' ) {
if ( ! YoastSEO()->helpers->environment->is_production_mode() ) {
return false;
}

View File

@@ -24,6 +24,37 @@ class Yoast_Feature_Toggle {
*/
protected $setting = '';
/**
* Whether the feature is premium or not.
*
* @var bool
*/
protected $premium = false;
/**
* Whether the feature is in beta or not.
*
* @var bool
*/
protected $in_beta = false;
/**
* The Premium version in which this feature has been added.
*
* @var string
*/
protected $premium_version = '';
/**
* The languages in which this feature is supported.
* E.g. for language specific analysis support.
*
* If empty, the feature is considered to have support in all languages.
*
* @var string[]
*/
protected $supported_languages = [];
/**
* Feature toggle label.
*
@@ -38,6 +69,20 @@ class Yoast_Feature_Toggle {
*/
protected $read_more_url = '';
/**
* URL to learn more about the premium feature.
*
* @var string
*/
protected $premium_url = '';
/**
* URL to buy premium.
*
* @var string
*/
protected $premium_upsell_url = '';
/**
* Label for the learn more link.
*
@@ -66,6 +111,20 @@ class Yoast_Feature_Toggle {
*/
protected $order = 100;
/**
* Disable the integration toggle.
*
* @var bool
*/
protected $disabled = false;
/**
* Whether the feature is new or not.
*
* @var bool
*/
protected $new = false;
/**
* Constructor.
*
@@ -74,14 +133,21 @@ class Yoast_Feature_Toggle {
* @param array $args {
* Feature toggle arguments.
*
* @type string $name Required. Feature toggle identifier.
* @type string $setting Required. Name of the setting the feature toggle is associated with.
* @type string $label Feature toggle label.
* @type string $read_more_url URL to learn more about the feature. Default empty string.
* @type string $read_more_label Label for the learn more link. Default empty string.
* @type string $extra Additional help content for the feature. Default empty string.
* @type int $order Value to specify the feature toggle order. A lower value indicates
* a higher priority. Default 100.
* @type string $name Required. Feature toggle identifier.
* @type string $setting Required. Name of the setting the feature toggle is associated with.
* @type string $disabled Whether the feature is premium or not.
* @type string $label Feature toggle label.
* @type string $read_more_url URL to learn more about the feature. Default empty string.
* @type string $premium_upsell_url URL to buy premium. Default empty string.
* @type string $read_more_label Label for the learn more link. Default empty string.
* @type string $extra Additional help content for the feature. Default empty string.
* @type int $order Value to specify the feature toggle order. A lower value indicates
* a higher priority. Default 100.
* @type bool $disabled Disable the integration toggle. Default false.
* @type string $new Whether the feature is new or not.
* @type bool $in_beta Whether the feature is in beta or not.
* @type array $supported_languages The languages that this feature supports.
* @type string $premium_version The Premium version in which this feature was added.
* }
*
* @throws InvalidArgumentException Thrown when a required argument is missing.

View File

@@ -5,6 +5,7 @@
* @package WPSEO\Admin
*/
use Yoast\WP\SEO\Helpers\Language_Helper;
use Yoast\WP\SEO\Presenters\Admin\Alert_Presenter;
/**
@@ -86,6 +87,15 @@ class Yoast_Feature_Toggles {
'read_more_url' => 'https://yoa.st/2ao',
'order' => 20,
],
(object) [
'name' => __( 'Inclusive language analysis', 'wordpress-seo' ),
'supported_languages' => Language_Helper::$languages_with_inclusive_language_support,
'setting' => 'inclusive_language_analysis_active',
'label' => __( 'The inclusive language analysis offers suggestions to write more inclusive copy.', 'wordpress-seo' ),
'read_more_label' => __( 'Discover why inclusive language is important for SEO.', 'wordpress-seo' ),
'read_more_url' => 'https://yoa.st/inclusive-language-features-free',
'order' => 25,
],
(object) [
'name' => __( 'Cornerstone content', 'wordpress-seo' ),
'setting' => 'enable_cornerstone_content',
@@ -102,6 +112,26 @@ class Yoast_Feature_Toggles {
'read_more_url' => 'https://yoa.st/2aj',
'order' => 40,
],
(object) [
'name' => __( 'Insights', 'wordpress-seo' ),
'setting' => 'enable_metabox_insights',
'label' => __( 'Find relevant data about your content right in the Insights section in the Yoast SEO metabox. Youll see what words you use most often and if theyre a match with your keywords! ', 'wordpress-seo' ),
'read_more_label' => __( 'Find out how Insights can help you improve your content.', 'wordpress-seo' ),
'read_more_url' => 'https://yoa.st/4ew',
'premium_url' => 'https://yoa.st/2ai',
'order' => 41,
],
(object) [
'name' => __( 'Link suggestions', 'wordpress-seo' ),
'premium' => true,
'setting' => 'enable_link_suggestions',
'label' => __( 'Get relevant internal linking suggestions — while youre writing! The link suggestions metabox shows a list of posts on your blog with similar content that might be interesting to link to. ', 'wordpress-seo' ),
'read_more_label' => __( 'Read more about how internal linking can improve your site structure.', 'wordpress-seo' ),
'read_more_url' => 'https://yoa.st/4ev',
'premium_url' => 'https://yoa.st/17g',
'premium_upsell_url' => 'https://yoa.st/get-link-suggestions',
'order' => 42,
],
(object) [
'name' => __( 'XML sitemaps', 'wordpress-seo' ),
'setting' => 'enable_xml_sitemap',
@@ -140,7 +170,7 @@ class Yoast_Feature_Toggles {
__( 'Allow us to track some data about your site to improve our plugin.', 'wordpress-seo' ),
'Yoast SEO'
),
'read_more_url' => 'https://yoa.st/usage-tracking',
'read_more_url' => 'https://yoa.st/usage-tracking-2',
'order' => 95,
],
(object) [
@@ -161,6 +191,28 @@ class Yoast_Feature_Toggles {
'read_more_url' => 'https://yoa.st/help-slack-share',
'order' => 105,
],
(object) [
'name' => __( 'IndexNow', 'wordpress-seo' ),
'premium' => true,
'setting' => 'enable_index_now',
'label' => __( 'Automatically ping search engines like Bing and Yandex whenever you publish, update or delete a post.', 'wordpress-seo' ),
'read_more_label' => __( 'Find out how IndexNow can help your site.', 'wordpress-seo' ),
'read_more_url' => 'https://yoa.st/index-now-read-more',
'premium_url' => 'https://yoa.st/index-now-feature',
'premium_upsell_url' => 'https://yoa.st/get-indexnow',
'order' => 110,
],
(object) [
'name' => __( 'AI title & description generator', 'wordpress-seo' ),
'premium' => true,
'setting' => 'enable_ai_generator',
'label' => __( 'Use the power of Yoast AI to automatically generate compelling titles and descriptions for your posts and pages.', 'wordpress-seo' ),
'read_more_label' => __( 'Learn more', 'wordpress-seo' ),
'read_more_url' => 'https://yoa.st/ai-generator-read-more',
'premium_url' => 'https://yoa.st/ai-generator-feature',
'premium_upsell_url' => 'https://yoa.st/get-ai-generator',
'order' => 115,
],
];
/**

View File

@@ -74,19 +74,17 @@ class Yoast_Integration_Toggles {
'order' => 10,
],
(object) [
/* translators: %s: Ryte */
'name' => sprintf( __( '%s integration', 'wordpress-seo' ), 'Ryte' ),
'setting' => 'ryte_indexability',
'label' => sprintf(
/* translators: 1: Ryte, 2: Yoast SEO */
__( '%1$s will check weekly if your site is still indexable by search engines and %2$s will notify you when this is not the case.', 'wordpress-seo' ),
'Ryte',
'Yoast SEO'
),
/* translators: %s: Ryte */
'read_more_label' => sprintf( __( 'Read more about how %s works.', 'wordpress-seo' ), 'Ryte ' ),
'read_more_url' => 'https://yoa.st/2an',
'order' => 20,
/* translators: %s: Algolia. */
'name' => \sprintf( \esc_html__( '%s integration', 'wordpress-seo' ), 'Algolia' ),
'premium' => true,
'setting' => 'algolia_integration_active',
'label' => __( 'Improve the quality of your site search! Automatically helps your users find your cornerstone and most important content in your internal search results. It also removes noindexed posts & pages from your sites search results.', 'wordpress-seo' ),
/* translators: %s: Algolia. */
'read_more_label' => \sprintf( \__( 'Find out more about our %s integration.', 'wordpress-seo' ), 'Algolia' ),
'read_more_url' => 'https://yoa.st/4eu',
'premium_url' => 'https://yoa.st/4ex',
'premium_upsell_url' => 'https://yoa.st/get-algolia-integration',
'order' => 25,
],
];

View File

@@ -14,7 +14,7 @@ if ( ! defined( 'WPSEO_VERSION' ) ) {
<script type="text/html" id="tmpl-primary-term-ui">
<?php
/* translators: accessibility text. %1$s expands to the term title, %2$s to the taxonomy title. */
/* translators: Hidden accessibility text; %1$s expands to the term title, %2$s to the taxonomy title. */
$yoast_free_js_button_label = __( 'Make %1$s primary %2$s', 'wordpress-seo' );
$yoast_free_js_button_label = sprintf(
$yoast_free_js_button_label,

View File

@@ -6,6 +6,8 @@
* @since 5.1
*/
use Yoast\WP\SEO\Promotions\Application\Promotion_Manager;
if ( ! defined( 'WPSEO_VERSION' ) ) {
header( 'Status: 403 Forbidden' );
header( 'HTTP/1.1 403 Forbidden' );
@@ -20,6 +22,7 @@ $premium_extension = [
'title' => 'Yoast SEO Premium',
/* translators: %1$s expands to Yoast SEO */
'desc' => sprintf( __( 'The premium version of %1$s with more features & support.', 'wordpress-seo' ), 'Yoast SEO' ),
'image' => plugin_dir_url( WPSEO_FILE ) . 'packages/js/images/Yoast_SEO_Icon.svg',
'benefits' => [],
];
@@ -28,40 +31,42 @@ $extensions = [
'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zt' ),
'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zs' ),
'title' => 'Local SEO',
'display_title' => __( 'Stop losing customers to other local businesses', 'wordpress-seo' ),
'display_title' => __( 'Maximize your visibility for local searches', 'wordpress-seo' ),
'desc' => __( 'Rank better locally and in Google Maps, without breaking a sweat!', 'wordpress-seo' ),
'image' => plugins_url( 'images/local_plugin_assistant.svg?v=' . WPSEO_VERSION, WPSEO_FILE ),
'benefits' => [
__( 'Get better search results in local search', 'wordpress-seo' ),
__( 'Easily insert Google Maps, a store locator, opening hours and more', 'wordpress-seo' ),
/* translators: %1$s expands to WooCommerce */
sprintf( __( 'Allow customers to pick up their %s order locally', 'wordpress-seo' ), 'WooCommerce' ),
__( 'Attract more local customers to your website and physical store', 'wordpress-seo' ),
__( 'Automatically get technical SEO best practices for local businesses', 'wordpress-seo' ),
__( 'Easily add maps, address finders, and opening hours to your content', 'wordpress-seo' ),
__( 'Optimize your business for multiple locations', 'wordpress-seo' ),
],
],
WPSEO_Addon_Manager::VIDEO_SLUG => [
'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zx/' ),
'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zw/' ),
'title' => 'Video SEO',
'display_title' => __( 'Start ranking better for your videos', 'wordpress-seo' ),
'display_title' => __( 'Drive more traffic to your videos', 'wordpress-seo' ),
'desc' => __( 'Optimize your videos to show them off in search results and get more clicks!', 'wordpress-seo' ),
'image' => plugins_url( 'images/video_plugin_assistant.svg?v=' . WPSEO_VERSION, WPSEO_FILE ),
'benefits' => [
__( 'Show your videos in Google Videos', 'wordpress-seo' ),
__( 'Enhance the experience of sharing posts with videos', 'wordpress-seo' ),
__( 'Make videos responsive through enabling fitvids.js', 'wordpress-seo' ),
__( 'Know that Google discovers your videos', 'wordpress-seo' ),
__( 'Load pages faster that include videos', 'wordpress-seo' ),
__( 'Make your videos responsive for all screen sizes', 'wordpress-seo' ),
__( 'Get XML video sitemaps', 'wordpress-seo' ),
],
],
WPSEO_Addon_Manager::NEWS_SLUG => [
'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zv/' ),
'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zu/' ),
'title' => 'News SEO',
'display_title' => __( 'Everything you need for Google News', 'wordpress-seo' ),
'display_title' => __( 'Rank higher in Google\'s news carousel', 'wordpress-seo' ),
'desc' => __( 'Are you in Google News? Increase your traffic from Google News by optimizing for it!', 'wordpress-seo' ),
'image' => plugins_url( 'images/news_plugin_assistant.svg?v=' . WPSEO_VERSION, WPSEO_FILE ),
'benefits' => [
__( 'Optimize your site for Google News', 'wordpress-seo' ),
__( 'Immediately pings Google on the publication of a new post', 'wordpress-seo' ),
__( 'Creates XML News Sitemaps', 'wordpress-seo' ),
__( 'Ping Google on the publication of a new post', 'wordpress-seo' ),
__( 'Add all necessary schema.org markup', 'wordpress-seo' ),
__( 'Get XML news sitemaps', 'wordpress-seo' ),
],
],
];
@@ -72,21 +77,47 @@ if ( YoastSEO()->helpers->woocommerce->is_active() ) {
'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zr' ),
'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zq' ),
'title' => 'Yoast WooCommerce SEO',
'display_title' => __( 'Make your products stand out in Google', 'wordpress-seo' ),
'display_title' => __( 'Drive more traffic to your online store', 'wordpress-seo' ),
/* translators: %1$s expands to Yoast SEO */
'desc' => sprintf( __( 'Seamlessly integrate WooCommerce with %1$s and get extra features!', 'wordpress-seo' ), 'Yoast SEO' ),
'image' => plugins_url( 'images/woo_plugin_assistant.svg?v=' . WPSEO_VERSION, WPSEO_FILE ),
'benefits' => [
sprintf( __( 'Improve sharing on Facebook and Pinterest', 'wordpress-seo' ) ),
/* translators: %1$s expands to Yoast, %2$s expands to WooCommerce */
sprintf( __( 'Use %1$s breadcrumbs instead of %2$s ones', 'wordpress-seo' ), 'Yoast', 'WooCommerce' ),
__( 'Write product pages that rank with the enhanced SEO analysis', 'wordpress-seo' ),
__( 'Increase clicks of Google search with rich results', 'wordpress-seo' ),
__( 'Add global identifiers for variable products', 'wordpress-seo' ),
/* translators: %1$s expands to Yoast SEO, %2$s expands to WooCommerce */
sprintf( __( 'A seamless integration between %1$s and %2$s', 'wordpress-seo' ), 'Yoast SEO', 'WooCommerce' ),
sprintf( __( 'Seamless integration between %1$s and %2$s', 'wordpress-seo' ), 'Yoast SEO', 'WooCommerce' ),
],
'buy_button' => 'WooCommerce SEO',
];
}
// The total number of plugins to consider is the length of the array + 1 for Premium.
// @phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
$number_plugins_total = ( count( $extensions ) + 1 );
// @phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
$number_plugins_active = 0;
$extensions['yoast-seo-plugin-subscription'] = [
'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/premium-page-bundle-buy' ),
'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/premium-page-bundle-info' ),
/* translators: used in phrases such as "More information about all the Yoast plugins" */
'title' => __( 'all the Yoast plugins', 'wordpress-seo' ),
'display_title' => __( 'Cover all your SEO bases', 'wordpress-seo' ),
'desc' => '',
'image' => plugins_url( 'images/plugin_subscription.svg?v=' . WPSEO_VERSION, WPSEO_FILE ),
'benefits' => [
__( 'Get all 5 Yoast plugins for WordPress with a big discount', 'wordpress-seo' ),
__( 'Reach new customers that live near your business', 'wordpress-seo' ),
__( 'Drive more traffic with your videos', 'wordpress-seo' ),
__( 'Rank higher in Google\'s news carousel', 'wordpress-seo' ),
__( 'Drive more traffic to your online store', 'wordpress-seo' ),
],
/* translators: used in phrases such as "Buy all the Yoast plugins" */
'buy_button' => __( 'all the Yoast plugins', 'wordpress-seo' ),
];
$addon_manager = new WPSEO_Addon_Manager();
$has_valid_premium_subscription = YoastSEO()->helpers->product->is_premium() && $addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG );
@@ -94,9 +125,23 @@ $has_valid_premium_subscription = YoastSEO()->helpers->product->is_premium() &&
$wpseo_extensions_header = sprintf( __( '%1$s Extensions', 'wordpress-seo' ), 'Yoast SEO' );
$new_tab_message = sprintf(
'<span class="screen-reader-text">%1$s</span>',
/* translators: Hidden accessibility text. */
esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' )
);
$sale_badge = '';
$premium_sale_badge = '';
if ( YoastSEO()->classes->get( Promotion_Manager::class )->is( 'black-friday-2023-promotion' ) ) {
/* translators: %1$s expands to opening span, %2$s expands to closing span */
$sale_badge_span = sprintf( esc_html__( '%1$sSALE 30%% OFF!%2$s', 'wordpress-seo' ), '<span>', '</span>' );
$sale_badge = '<div class="yoast-seo-premium-extension-sale-badge">' . $sale_badge_span . '</div>';
$premium_sale_badge = ( $has_valid_premium_subscription ) ? '' : $sale_badge;
}
?>
<div class="wrap yoast wpseo_table_page">
@@ -105,46 +150,65 @@ $new_tab_message = sprintf(
<div id="extensions">
<section class="yoast-seo-premium-extension">
<?php echo $premium_sale_badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Output is already escaped ?>
<h2>
<?php
printf(
/* translators: 1: expands to Yoast SEO Premium */
esc_html__( '%1$s, take your optimization to the next level!', 'wordpress-seo' ),
esc_html__( 'Drive more traffic to your site with %1$s', 'wordpress-seo' ),
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: The `get_title` value is hardcoded; only passed through the WPSEO_Extensions class.
'<span class="yoast-heading-highlight">' . $premium_extension['title'] . '</span>'
$premium_extension['title']
);
?>
<img alt="" width="100" height="100" src="<?php echo esc_url( $premium_extension['image'] ); ?>"/>
</h2>
<?php
if ( ! $has_valid_premium_subscription ) :
?>
<ul class="yoast-seo-premium-benefits yoast-list--usp">
<li class="yoast-seo-premium-benefits__item">
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Redirect manager', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'create and manage redirects from within your WordPress install.', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Be more efficient in creating content', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'Use AI to create high-quality titles and meta descriptions for posts and pages', 'wordpress-seo' ); ?></span>
</li>
<li class="yoast-seo-premium-benefits__item">
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Synonyms & related keyphrases', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'optimize a single post for synonyms and related keyphrases.', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Reach bigger audiences', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'Optimize a single post for synonyms and related keyphrases and get extra checks with the Premium SEO analysis', 'wordpress-seo' ); ?></span>
</li>
<li class="yoast-seo-premium-benefits__item">
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Social previews', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'check what your Facebook or Twitter post will look like.', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Save time on doing SEO', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'The Yoast SEO workouts guide you through important routine SEO tasks', 'wordpress-seo' ); ?></span>
</li>
<li class="yoast-seo-premium-benefits__item">
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Improve your internal linking structure', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'Get tools that tell you where and how to improve internal linking', 'wordpress-seo' ); ?></span>
</li>
<li class="yoast-seo-premium-benefits__item">
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Reduce your site\'s carbon footprint', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'Save energy by reducing the crawlability of your site without hurting your rankings!', 'wordpress-seo' ); ?></span>
</li>
<li class="yoast-seo-premium-benefits__item">
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Prevents 404s', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'Easily create and manage redirects when you move or delete content', 'wordpress-seo' ); ?></span>
</li>
<li class="yoast-seo-premium-benefits__item">
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Stand out on social media', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'Check what your Facebook or Twitter post will look like before posting them', 'wordpress-seo' ); ?></span>
</li>
<li class="yoast-seo-premium-benefits__item">
<span class="yoast-seo-premium-benefits__title"><?php esc_html_e( 'Premium support', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'gain access to our 24/7 support team.', 'wordpress-seo' ); ?></span>
<span class="yoast-seo-premium-benefits__description"><?php esc_html_e( 'Gain access to our 24/7 support team', 'wordpress-seo' ); ?></span>
</li>
</ul>
<?php endif; ?>
<?php if ( $addon_manager->is_installed( WPSEO_Addon_Manager::PREMIUM_SLUG ) ) : ?>
<div class="yoast-button yoast-button--noarrow yoast-button--extension yoast-button--extension-installed"><?php esc_html_e( 'Installed', 'wordpress-seo' ); ?></div>
<?php if ( $has_valid_premium_subscription ) : ?>
<?php
if ( $has_valid_premium_subscription ) :
++$number_plugins_active;
?>
<div class="yoast-button yoast-button--noarrow yoast-button--extension yoast-button--extension-activated"><?php esc_html_e( 'Activated', 'wordpress-seo' ); ?></div>
<a target="_blank" href="<?php WPSEO_Shortlinker::show( 'https://yoa.st/13k' ); ?>"
class="yoast-link--license">
<a target="_blank" href="<?php WPSEO_Shortlinker::show( 'https://yoa.st/13k' ); ?>" class="yoast-link--license">
<?php
printf(
/* translators: %s expands to the extension title */
@@ -157,8 +221,7 @@ $new_tab_message = sprintf(
</a>
<?php else : ?>
<div class="yoast-button yoast-button--noarrow yoast-button--extension yoast-button--extension-not-activated"><?php esc_html_e( 'Not activated', 'wordpress-seo' ); ?></div>
<a target="_blank" href="<?php WPSEO_Shortlinker::show( 'https://yoa.st/13i' ); ?>"
class="yoast-link--license">
<a target="_blank" href="<?php WPSEO_Shortlinker::show( 'https://yoa.st/13i' ); ?>" class="yoast-link--license">
<?php
printf(
/* translators: %s expands to the extension title */
@@ -174,8 +237,7 @@ $new_tab_message = sprintf(
<?php else : ?>
<a target="_blank" href="<?php echo esc_url( $premium_extension['buyUrl'] ); ?>"
class="yoast-button-upsell">
<a target="_blank" data-action="load-nfd-ctb" data-ctb-id="f6a84663-465f-4cb5-8ba5-f7a6d72224b2" href="<?php echo esc_url( $premium_extension['buyUrl'] ); ?>" class="yoast-button-upsell">
<?php
printf(
/* translators: $s expands to Yoast SEO Premium */
@@ -188,8 +250,7 @@ $new_tab_message = sprintf(
?>
</a>
<a target="_blank" href="<?php echo esc_url( $premium_extension['infoUrl'] ); ?>"
class="yoast-link--more-info">
<a target="_blank" href="<?php echo esc_url( $premium_extension['infoUrl'] ); ?>" class="yoast-link--more-info">
<?php
printf(
/* translators: Text between 1: and 2: will only be shown to screen readers. 3: expands to the product name. */
@@ -206,7 +267,7 @@ $new_tab_message = sprintf(
<?php endif; ?>
<?php if ( ! $has_valid_premium_subscription ) { ?>
<p>
<small class="yoast-money-back-guarantee"><?php esc_html_e( 'Comes with our 30-day no questions asked money back guarantee', 'wordpress-seo' ); ?></small>
<small class="yoast-money-back-guarantee"><?php esc_html_e( 'With 30-day money-back guarantee. No questions asked.', 'wordpress-seo' ); ?></small>
</p>
<?php } ?>
</section>
@@ -216,21 +277,31 @@ $new_tab_message = sprintf(
<section class="yoast-promo-extensions">
<h2>
<?php
/* translators: 1: expands to Yoast SEO */
$yoast_seo_extensions = sprintf( esc_html__( '%1$s extensions', 'wordpress-seo' ), 'Yoast SEO' );
$yoast_seo_extensions = '<span class="yoast-heading-highlight">' . $yoast_seo_extensions . '</span>';
$yoast_outrank_copy = sprintf( esc_html__( 'Outrank your competitors even further', 'wordpress-seo' ) );
$yoast_outrank_copy = '<span class="yoast-heading-highlight">' . $yoast_outrank_copy . '</span>';
printf(
/* translators: 1: expands to Yoast SEO extensions */
esc_html__( '%1$s to optimize your site even further', 'wordpress-seo' ),
/* translators: 1: expands to Outrank your competitors even further, 2: expands to Yoast SEO */
esc_html__( '%1$s with %2$s extensions', 'wordpress-seo' ),
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: $yoast_seo_extensions is properly escaped.
$yoast_seo_extensions
$yoast_outrank_copy,
'Yoast SEO'
);
?>
</h2>
<?php foreach ( $extensions as $slug => $extension ) : ?>
<?php
foreach ( $extensions as $slug => $extension ) :
// Skip the "All the plugins" card if the user has already all the plugins active.
if ( $slug === 'yoast-seo-plugin-subscription' && $number_plugins_active === $number_plugins_total ) {
continue;
}
?>
<section class="yoast-promoblock secondary yoast-promo-extension">
<?php if ( ! $addon_manager->has_valid_subscription( $slug ) || ! $addon_manager->is_installed( $slug ) ) : ?>
<?php echo $sale_badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Output already escaped ?>
<?php endif; ?>
<h3>
<img alt="" width="100" height="100" src="<?php echo esc_url( $extension['image'] ); ?>"/>
<?php echo esc_html( $extension['display_title'] ); ?>
@@ -243,12 +314,14 @@ $new_tab_message = sprintf(
<div class="yoast-button-container">
<?php if ( $addon_manager->is_installed( $slug ) ) : ?>
<div class="yoast-button yoast-button--noarrow yoast-button--extension yoast-button--extension-installed"><?php esc_html_e( 'Installed', 'wordpress-seo' ); ?></div>
<div class="yoast-button yoast-button--noarrow yoast-button--extension yoast-button--extension-installed"><?php esc_html_e( 'Installed', 'wordpress-seo' ); ?></div>
<?php if ( $addon_manager->has_valid_subscription( $slug ) ) : ?>
<?php
if ( $addon_manager->has_valid_subscription( $slug ) ) :
++$number_plugins_active;
?>
<div class="yoast-button yoast-button--noarrow yoast-button--extension yoast-button--extension-activated"><?php esc_html_e( 'Activated', 'wordpress-seo' ); ?></div>
<a target="_blank" href="<?php WPSEO_Shortlinker::show( 'https://yoa.st/13k' ); ?>"
class="yoast-link--license">
<a target="_blank" href="<?php WPSEO_Shortlinker::show( 'https://yoa.st/13k' ); ?>" class="yoast-link--license">
<?php
printf(
/* translators: %s expands to the extension title */
@@ -261,9 +334,8 @@ $new_tab_message = sprintf(
?>
</a>
<?php else : ?>
<div class="yoast-button yoast-button--noarrow yoast-button--extension yoast-button--extension-not-activated"><?php esc_html_e( 'Not activated', 'wordpress-seo' ); ?></div>
<a target="_blank" href="<?php WPSEO_Shortlinker::show( 'https://yoa.st/13i' ); ?>"
class="yoast-link--license">
<div class="yoast-button yoast-button--noarrow yoast-button--extension yoast-button--extension-not-activated"><?php esc_html_e( 'Not activated', 'wordpress-seo' ); ?></div>
<a target="_blank" href="<?php WPSEO_Shortlinker::show( 'https://yoa.st/13i' ); ?>" class="yoast-link--license">
<?php
printf(
/* translators: %s expands to the extension title */
@@ -277,11 +349,10 @@ $new_tab_message = sprintf(
</a>
<?php endif; ?>
<?php else : ?>
<a target="_blank" class="yoast-button-upsell"
href="<?php echo esc_url( $extension['buyUrl'] ); ?>">
<a target="_blank" class="yoast-button-upsell" href="<?php echo esc_url( $extension['buyUrl'] ); ?>">
<?php
printf(
/* translators: %s expands to the product name */
/* translators: %s expands to the product name, e.g. "News SEO" or "all the Yoast Plugins" */
esc_html__( 'Buy %s', 'wordpress-seo' ),
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: The possible `get_buy_button` values are hardcoded (buy_button or title); only passed through the WPSEO_Extensions class.
( isset( $extension['buy_button'] ) ) ? $extension['buy_button'] : $extension['title']
@@ -292,11 +363,10 @@ $new_tab_message = sprintf(
?>
</a>
<a target="_blank" class="yoast-link--more-info"
href="<?php echo esc_url( $extension['infoUrl'] ); ?>">
<a target="_blank" class="yoast-link--more-info" href="<?php echo esc_url( $extension['infoUrl'] ); ?>">
<?php
printf(
/* translators: Text between 1: and 2: will only be shown to screen readers. 3: expands to the product name. */
/* translators: Text between 1: and 2: will only be shown to screen readers. 3: expands to the product name, e.g. "News SEO" or "all the Yoast Plugins" */
esc_html__( 'More information %1$sabout %3$s%2$s', 'wordpress-seo' ),
'<span class="screen-reader-text">',
'</span>',

View File

@@ -21,20 +21,21 @@ if ( ! function_exists( '_yoast_display_notifications' ) ) {
/**
* Create the notifications HTML with restore/dismiss button.
*
* @param array $list List of notifications.
* @param string $status Status of the notifications (active/dismissed).
* @param array $notifications_list List of notifications.
* @param string $status Status of the notifications (active/dismissed).
*
* @return string The output to render.
*/
function _yoast_display_notifications( $list, $status ) {
function _yoast_display_notifications( $notifications_list, $status ) {
$notifications = '';
foreach ( $list as $notification ) {
foreach ( $notifications_list as $notification ) {
switch ( $status ) {
case 'active':
$button = sprintf(
'<button type="button" class="button dismiss"><span class="screen-reader-text">%1$s</span><span class="dashicons dashicons-hidden"></span></button>',
/* translators: Hidden accessibility text. */
esc_html__( 'Hide this item.', 'wordpress-seo' )
);
break;
@@ -42,6 +43,7 @@ if ( ! function_exists( '_yoast_display_notifications' ) ) {
case 'dismissed':
$button = sprintf(
'<button type="button" class="button restore"><span class="screen-reader-text">%1$s</span><span class="dashicons yoast-svg-icon-eye"></span></button>',
/* translators: Hidden accessibility text. */
esc_html__( 'Show this item.', 'wordpress-seo' )
);
break;

View File

@@ -0,0 +1,237 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin
* @since 19.0
*/
if ( ! defined( 'WPSEO_VERSION' ) ) {
header( 'Status: 403 Forbidden' );
header( 'HTTP/1.1 403 Forbidden' );
exit();
}
?>
<div class="wrap yoast wpseo-admin-page page-wpseo_redirects">
<h1 id="wpseo-title"><?php echo \esc_html( \get_admin_page_title() ); ?></h1>
<div class="wpseo_content_wrapper" style="position: relative;">
<div style="position: absolute;top: 0;bottom: 0;left: 0;right: 0;z-index: 100; display: flex;justify-content: center;align-items: center;background: radial-gradient(#ffffffcf 20%, #ffffff00 50%);">
<a class="yoast-button-upsell" data-action="load-nfd-ctb" data-ctb-id="f6a84663-465f-4cb5-8ba5-f7a6d72224b2" href="<?php echo \esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/4e0/' ) ); ?>" target="_blank">
<?php
echo \esc_html__( 'Unlock with Premium', 'wordpress-seo' )
// phpcs:ignore WordPress.Security.EscapeOutput -- Already escapes correctly.
. WPSEO_Admin_Utils::get_new_tab_message();
?>
<span aria-hidden="true" class="yoast-button-upsell__caret"></span></a>
</div>
<div class="wpseo_content_cell" id="wpseo_content_top" style="opacity: 0.5;">
<h2 class="nav-tab-wrapper" id="wpseo-tabs">
<a class="nav-tab nav-tab-active" id="tab-url-tab" href="#" tabindex="-1">
<?php
\esc_html_e( 'Redirects', 'wordpress-seo' )
?>
</a>
<a class="nav-tab" id="tab-url-tab" href="" tabindex="-1">
<?php
\esc_html_e( 'Regex Redirects', 'wordpress-seo' )
?>
</a>
<a class="nav-tab" id="tab-url-tab" href="#" tabindex="-1">
<?php
\esc_html_e( 'Settings', 'wordpress-seo' )
?>
</a>
</h2>
<div id="table-plain" class="tab-url redirect-table-tab">
<h2>
<?php
\esc_html_e( 'Plain redirects', 'wordpress-seo' )
?>
</h2>
<form class="wpseo-new-redirect-form" method="post">
<div class="wpseo_redirect_form">
<div class="redirect_form_row" id="row-wpseo_redirects_type">
<label class="textinput" for="wpseo_redirects_type">
<span class="title">
<?php
\esc_html_e( 'Type', 'wordpress-seo' )
?>
</span>
</label>
<select name="wpseo_redirects_type" id="wpseo_redirects_type" class="select select2-hidden-accessible" data-select2-id="wpseo_redirects_type" tabindex="-1" aria-hidden="true">
<option value="301" data-select2-id="2">
<?php
\esc_html_e( '301 Moved Permanently', 'wordpress-seo' )
?>
</option>
</select>
<span class="select2 select2-container select2-container--default" dir="ltr" data-select2-id="1" style="width: 400px;">
<span class="selection">
<span class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="-1" aria-disabled="false" aria-labelledby="select2-wpseo_redirects_type-container">
<span class="select2-selection__rendered" id="select2-wpseo_redirects_type-container" role="textbox" aria-readonly="true" title="301 Moved Permanently">
<?php
\esc_html_e( '301 Moved Permanently', 'wordpress-seo' )
?>
</span>
<span class="select2-selection__arrow" role="presentation">
<b role="presentation"></b>
</span>
</span>
</span>
<span class="dropdown-wrapper" aria-hidden="true"></span>
</span>
</div>
<p class="label desc description wpseo-redirect-clear">
<?php
printf(
/* translators: 1: opens a link. 2: closes the link. */
esc_html__( 'The redirect type is the HTTP response code sent to the browser telling the browser what type of redirect is served. %1$sLearn more about redirect types%2$s.', 'wordpress-seo' ),
'<a href="#" target="_blank">',
'</a>'
);
?>
<div class="redirect_form_row" id="row-wpseo_redirects_origin">
<label class="textinput" for="wpseo_redirects_origin">
<span class="title">
<?php
\esc_html_e( 'Old URL', 'wordpress-seo' )
?>
</span>
</label>
<input type="text" class="textinput" name="wpseo_redirects_origin" id="wpseo_redirects_origin" value="" tabindex="-1">
</div>
<br class="clear">
<div class="redirect_form_row wpseo_redirect_target_holder" id="row-wpseo_redirects_target">
<label class="textinput" for="wpseo_redirects_target">
<span class="title">
<?php
\esc_html_e( 'URL', 'wordpress-seo' )
?>
</span>
</label>
<input type="text" class="textinput" name="wpseo_redirects_target" id="wpseo_redirects_target" value="" tabindex="-1">
</div>
<br class="clear">
<button type="button" class="button button-primary" tabindex="-1">
<?php
\esc_html_e( 'Add Redirect', 'wordpress-seo' )
?>
</button>
</div>
</form>
<p class="desc">&nbsp;</p>
<form id="plain" class="wpseo-redirects-table-form" method="post" action="">
<input type="hidden" class="wpseo_redirects_ajax_nonce" name="wpseo_redirects_ajax_nonce" value="6ccb86df42">
<input type="hidden" id="_wpnonce" name="_wpnonce" value="4b02cca185">
<input type="hidden" name="_wp_http_referer" value="/wp-admin/admin.php?page=wpseo_redirects"> <div class="tablenav top">
<div class="alignleft actions">
<select name="redirect-type" id="filter-by-redirect" tabindex="-1">
<option selected="selected" value="0">
<?php
\esc_html_e( 'All redirect types', 'wordpress-seo' )
?>
</option>
</select>
<input type="button" name="filter_action" id="post-query-submit" class="button" value="<?php \esc_attr_e( 'Filter', 'wordpress-seo' ); ?>" tabindex="-1">
</div>
<br class="clear">
</div>
<table class="wp-list-table widefat fixed striped table-view-list plain">
<thead>
<tr>
<td id="cb" class="manage-column column-cb check-column">
<input id="cb-select-all-1" type="checkbox" tabindex="-1">
</td>
<th scope="col" id="type" class="manage-column column-type column-primary sortable desc">
<a href="#" tabindex="-1">
<span>
<?php
\esc_html_e( 'Type', 'wordpress-seo' )
?>
</span>
<span class="sorting-indicator"></span>
</a>
</th>
<th scope="col" id="old" class="manage-column column-old sortable desc">
<a href="#" tabindex="-1">
<span>
<?php
\esc_html_e( 'Old URL', 'wordpress-seo' )
?>
</span>
<span class="sorting-indicator"></span>
</a>
</th>
<th scope="col" id="new" class="manage-column column-new sortable desc">
<a href="#" tabindex="-1">
<span>
<?php
\esc_html_e( 'New URL', 'wordpress-seo' )
?>
</span>
<span class="sorting-indicator"></span>
</a>
</th>
</tr>
</thead>
<tbody id="the-list">
<tr class="no-items">
<td class="colspanchange" colspan="4">
<?php
\esc_html_e( 'No items found.', 'wordpress-seo' )
?>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="manage-column column-cb check-column">
<input id="cb-select-all-2" type="checkbox" tabindex="-1">
</td>
<th scope="col" class="manage-column column-type column-primary sortable desc">
<a href="#" tabindex="-1">
<span>
<?php
\esc_html_e( 'Type', 'wordpress-seo' )
?>
</span>
<span class="sorting-indicator"></span></a>
</th>
<th scope="col" class="manage-column column-old sortable desc">
<a href="#" tabindex="-1">
<span>
<?php
\esc_html_e( 'Old URL', 'wordpress-seo' )
?>
</span>
<span class="sorting-indicator"></span>
</a>
</th>
<th scope="col" class="manage-column column-new sortable desc">
<a href="#" tabindex="-1">
<span>
<?php
\esc_html_e( 'New URL', 'wordpress-seo' )
?>
</span>
<span class="sorting-indicator"></span></a>
</th>
</tr>
</tfoot>
</table>
</form>
</div>
<br class="clear">
</div><!-- end of div wpseo_content_top --></div><!-- end of div wpseo_content_wrapper -->
</div>

View File

@@ -14,9 +14,6 @@
*/
$notifications_data = Yoast_Notifications::get_template_variables();
$notifier = new WPSEO_Configuration_Notifier();
$notifier->listen();
$wpseo_contributors_phrase = sprintf(
/* translators: %1$s expands to Yoast SEO */
__( 'See who contributed to %1$s.', 'wordpress-seo' ),
@@ -28,11 +25,6 @@ $wpseo_contributors_phrase = sprintf(
<div class="tab-block">
<div class="yoast-notifications">
<?php
// phpcs:ignore WordPress.Security.EscapeOutput -- WPSEO_Configuration_Notifier::notify() escapes correctly.
echo $notifier->notify();
?>
<div class="yoast-container yoast-container__error">
<?php require WPSEO_PATH . 'admin/views/partial-notifications-errors.php'; ?>
</div>
@@ -47,6 +39,6 @@ $wpseo_contributors_phrase = sprintf(
<div class="tab-block">
<h2><?php esc_html_e( 'Credits', 'wordpress-seo' ); ?></h2>
<p>
<a href="<?php WPSEO_Shortlinker::show( 'https://yoa.st/yoast-seo-credits' ); ?>"><?php echo esc_html( $wpseo_contributors_phrase ); ?></a>
<a href="<?php WPSEO_Shortlinker::show( 'https://yoa.st/yoast-seo-credits' ); ?>" target="_blank"><?php echo esc_html( $wpseo_contributors_phrase ); ?></a>
</p>
</div>

View File

@@ -0,0 +1,14 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin\Views
*/
if ( ! defined( 'WPSEO_VERSION' ) ) {
header( 'Status: 403 Forbidden' );
header( 'HTTP/1.1 403 Forbidden' );
exit();
}
echo '<div id="wpseo-first-time-configuration"></div>';

View File

@@ -13,9 +13,23 @@ if ( ! defined( 'WPSEO_VERSION' ) ) {
exit();
}
/**
* WARNING: This hook is intended for internal use only.
* Don't use it in your code as it will be removed shortly.
*/
do_action( 'wpseo_settings_tab_site_analysis_internal', $yform );
/**
* Fires when displaying the site wide analysis tab.
*
* @deprecated 19.10 No replacement available.
*
* @param Yoast_Form $yform The yoast form object.
*/
do_action( 'wpseo_settings_tab_site_analysis', $yform );
do_action_deprecated(
'wpseo_settings_tab_site_analysis',
[ $yform ],
'19.10',
'',
'This action is going away with no replacement. If you want to add settings that interact with Yoast SEO, please create your own settings page.'
);

View File

@@ -0,0 +1,50 @@
<?php
/**
* WPSEO plugin file.
*
* @package WPSEO\Admin\Views
*
* @uses Yoast_Form $yform Form object.
*/
if ( ! defined( 'WPSEO_VERSION' ) ) {
header( 'Status: 403 Forbidden' );
header( 'HTTP/1.1 403 Forbidden' );
exit();
}
$feature_toggles = Yoast_Feature_Toggles::instance()->get_all();
?>
<h2><?php esc_html_e( 'Crawl settings', 'wordpress-seo' ); ?></h2>
<div class="yoast-measure">
<?php
echo sprintf(
/* translators: %s expands to Yoast SEO */
esc_html__( 'This tab allows you to selectively disable %s features for all sites in the network. By default all features are enabled, which allows site admins to choose for themselves if they want to toggle a feature on or off for their site. When you disable a feature here, site admins will not be able to use that feature at all.', 'wordpress-seo' ),
'Yoast SEO'
);
echo '<p style="margin: 0.5em 0 1em;">';
echo sprintf(
/* translators: %1$s opens the link to the Yoast.com article about Crawl settings, %2$s closes the link, */
esc_html__( '%1$sLearn more about crawl settings.%2$s', 'wordpress-seo' ),
'<a href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/crawl-settings' ) ) . '" target="_blank" rel="noopener noreferrer">',
'</a>'
);
echo '</p>';
/**
* Fires when displaying the crawl cleanup network tab.
*
* @param Yoast_Form $yform The yoast form object.
*/
do_action( 'wpseo_settings_tab_crawl_cleanup_network', $yform );
?>
</div>
<?php
/*
* Required to prevent our settings framework from saving the default because the field
* isn't explicitly set when saving the Dashboard page.
*/
$yform->hidden( 'show_onboarding_notice', 'wpseo_show_onboarding_notice' );

Some files were not shown because too many files have changed in this diff Show More