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

@@ -83,12 +83,15 @@ class WPSEO_Custom_Fields_Plugin implements WPSEO_WordPress_Integration {
* @return WP_Post|array|null Returns a post if found, otherwise returns an empty array.
*/
protected function get_post() {
$post = filter_input( INPUT_GET, 'post' );
if ( isset( $post ) && $post !== false ) {
$post_id = (int) WPSEO_Utils::validate_int( $post );
return get_post( $post_id );
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- Reason: We are not controlling the request.
if ( isset( $_GET['post'] ) && is_string( $_GET['post'] ) ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are casting the unsafe value to an integer.
$post_id = (int) wp_unslash( $_GET['post'] );
if ( $post_id > 0 ) {
return get_post( $post_id );
}
}
// phpcs:enable WordPress.Security.NonceVerification.Recommended
if ( isset( $GLOBALS['post'] ) ) {
return $GLOBALS['post'];

View File

@@ -82,9 +82,7 @@ class WPSEO_Export_Keywords_CSV {
}
}
$csv .= PHP_EOL;
return $csv;
return $csv . PHP_EOL;
}
/**

View File

@@ -66,23 +66,29 @@ class WPSEO_Export_Keywords_Term_Presenter implements WPSEO_Export_Keywords_Pres
*/
protected function prepare_column_result( array $result, $column ) {
switch ( $column ) {
case 'title':
$result['title'] = $result['name'];
unset( $result['name'] );
break;
case 'url':
$result['url'] = get_term_link( $result['ID'], $result['taxonomy'] );
break;
case 'readability_score':
$content_score = WPSEO_Taxonomy_Meta::get_term_meta( $result['ID'], $result['taxonomy'], 'content_score' );
$result['readability_score'] = WPSEO_Rank::from_numeric_score( (int) $content_score )->get_label();
break;
case 'keywords':
$result['keywords'] = $this->get_result_keywords( $result );
break;
case 'keywords_score':
$result['keywords_score'] = $this->get_result_keywords_score( $result );
break;
case 'url':
$result['url'] = get_term_link( $result['ID'], $result['taxonomy'] );
break;
case 'title':
$result['title'] = $result['name'];
unset( $result['name'] );
break;
case 'seo_title':
$result['seo_title'] = WPSEO_Taxonomy_Meta::get_term_meta( $result['ID'], $result['taxonomy'], 'title' );
break;
case 'meta_description':
$result['meta_description'] = WPSEO_Taxonomy_Meta::get_term_meta( $result['ID'], $result['taxonomy'], 'desc' );
break;
case 'readability_score':
$content_score = WPSEO_Taxonomy_Meta::get_term_meta( $result['ID'], $result['taxonomy'], 'content_score' );
$result['readability_score'] = WPSEO_Rank::from_numeric_score( (int) $content_score )->get_label();
break;
}
return $result;

View File

@@ -110,18 +110,4 @@ class WPSEO_Metabox_Link_Suggestions implements WPSEO_WordPress_Integration {
]
);
}
/**
* Returns whether or not we need to index more posts for correct link suggestion functionality
*
* @deprecated 14.7
* @codeCoverageIgnore
*
* @return bool Whether or not we need to index more posts.
*/
public function is_site_unindexed() {
_deprecated_function( __METHOD__, 'WPSEO Premium 14.7' );
return false;
}
}

View File

@@ -6,7 +6,7 @@
*/
/**
* Implements multi keyword int he admin.
* Implements multi keyword in the admin.
*/
class WPSEO_Multi_Keyword implements WPSEO_WordPress_Integration {

View File

@@ -103,24 +103,6 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
$this->remove_colliding_redirect( $post, $post_before );
/**
* Filter: 'wpseo_premium_post_redirect_slug_change' - Check if a redirect should be created
* on post slug change.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\post_redirect_slug_change'} filter instead.
*
* @api bool Determines if a redirect should be created for this post slug change.
* @api int The ID of the post.
* @api WP_Post The current post object.
* @api WP_Post The previous post object.
*/
$create_redirect = apply_filters_deprecated(
'wpseo_premium_post_redirect_slug_change',
[ false, $post_id, $post, $post_before ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\post_redirect_slug_change'
);
/**
* Filter: 'Yoast\WP\SEO\post_redirect_slug_change' - Check if a redirect should be created
* on post slug change.
@@ -134,7 +116,7 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* @api WP_Post The current post object.
* @api WP_Post The previous post object.
*/
$create_redirect = apply_filters( 'Yoast\WP\SEO\post_redirect_slug_change', $create_redirect, $post_id, $post, $post_before );
$create_redirect = apply_filters( 'Yoast\WP\SEO\post_redirect_slug_change', false, $post_id, $post, $post_before );
if ( $create_redirect === true ) {
return true;
@@ -146,7 +128,7 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
}
// If the post URL wasn't public before, or isn't public now, don't even check if we have to redirect.
if ( ! $this->check_public_post_status( $post_before->ID ) || ! $this->check_public_post_status( $post->ID ) ) {
if ( ! $this->check_public_post_status( $post_before ) || ! $this->check_public_post_status( $post ) ) {
return false;
}
@@ -200,22 +182,6 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
// Check if the post type is enabled for redirects.
$post_type = get_post_type( $post );
/**
* Filter: 'wpseo_premium_redirect_post_type' - Check if a redirect should be created
* on post slug change for specified post type.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\redirect_post_type'} filter instead.
*
* @api bool Determines if a redirect should be created for this post type.
* @api string The post type that is being checked for.
*/
$post_type_accessible = apply_filters_deprecated(
'wpseo_premium_redirect_post_type',
[ WPSEO_Post_Type::is_post_type_accessible( $post_type ), $post_type ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\redirect_post_type'
);
/**
* Filter: 'Yoast\WP\SEO\redirect_post_type' - Check if a redirect should be created
* on post slug change for specified post type.
@@ -227,7 +193,7 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* @api bool Determines if a redirect should be created for this post type.
* @api string The post type that is being checked for.
*/
$post_type_accessible = apply_filters( 'Yoast\WP\SEO\redirect_post_type', $post_type_accessible, $post_type );
$post_type_accessible = apply_filters( 'Yoast\WP\SEO\redirect_post_type', WPSEO_Post_Type::is_post_type_accessible( $post_type ), $post_type );
if ( ! $post_type_accessible ) {
return false;
@@ -249,32 +215,24 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
/**
* Checks whether the given post is public or not.
*
* @param int $post_id The current post ID.
* @param int|WP_Post $post Post ID or post object.
*
* @return bool
*/
private function check_public_post_status( $post_id ) {
private function check_public_post_status( $post ) {
$public_post_statuses = [
'publish',
'static',
'private',
];
/**
* Filter: 'wpseo_public_post_statuses' - Allow changing the statuses that are expected
* to have caused a URL to be public.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\public_post_statuses'} filter instead.
*
* @api array $published_post_statuses The statuses that'll be treated as published.
* @param object $post The post object we're doing the published check for.
*/
$public_post_statuses = apply_filters_deprecated(
'wpseo_public_post_statuses',
[ $public_post_statuses, $post_id ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\public_post_statuses'
);
// Need to set $post_id for backward compatibility with the filter, as $post can also be an object now.
if ( is_int( $post ) ) {
$post_id = $post;
}
else {
$post_id = $post->ID;
}
/**
* Filter: 'Yoast\WP\SEO\public_post_statuses' - Allow changing the statuses that are expected
@@ -289,7 +247,7 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
*/
$public_post_statuses = apply_filters( 'Yoast\WP\SEO\public_post_statuses', $public_post_statuses, $post_id );
return ( in_array( get_post_status( $post_id ), $public_post_statuses, true ) );
return ( in_array( get_post_status( $post ), $public_post_statuses, true ) );
}
/**
@@ -413,13 +371,12 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
// Message should only be shown if there isn't already a redirect.
$redirect = $this->get_redirect( $url );
if ( is_a( $redirect, 'WPSEO_Redirect' ) === $should_exist ) {
if ( $should_exist === false ) {
return $url;
}
if ( is_a( $redirect, 'WPSEO_Redirect' ) && $should_exist ) {
return $redirect;
}
if ( ! is_a( $redirect, 'WPSEO_Redirect' ) && ! $should_exist ) {
return $url;
}
}
}
return false;
@@ -433,21 +390,6 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
protected function get_included_automatic_redirection_post_types() {
$post_types = WPSEO_Post_Type::get_accessible_post_types();
/**
* Filter: 'wpseo_premium_include_automatic_redirection_post_types' - Post types to create
* automatic redirects for.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\automatic_redirection_post_types'} filter instead.
*
* @api array $included_post_types Array with the post type names to include to automatic redirection.
*/
$included_post_types = apply_filters_deprecated(
'wpseo_premium_include_automatic_redirection_post_types',
[ $post_types ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\automatic_redirection_post_types'
);
/**
* Filter: 'Yoast\WP\SEO\automatic_redirection_post_types' - Post types to create
* automatic redirects for.
@@ -458,7 +400,7 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
*
* @api array $included_post_types Array with the post type names to include to automatic redirection.
*/
$included_post_types = apply_filters( 'Yoast\WP\SEO\automatic_redirection_post_types', $included_post_types );
$included_post_types = apply_filters( 'Yoast\WP\SEO\automatic_redirection_post_types', $post_types );
if ( ! is_array( $included_post_types ) ) {
$included_post_types = [];
@@ -584,25 +526,38 @@ class WPSEO_Post_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* @return bool True when the current page is nested pages.
*/
protected function is_nested_pages( $current_page ) {
return ( $current_page === 'admin.php' && filter_input( INPUT_GET, 'page' ) === 'nestedpages' );
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- Reason: We are not controlling the request.
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are strictly comparing only.
return ( $current_page === 'admin.php' && isset( $_GET['page'] ) && is_string( $_GET['page'] ) && wp_unslash( $_GET['page'] ) === 'nestedpages' );
// phpcs:enable WordPress.Security.NonceVerification.Recommended.
}
/**
* Retrieves wpseo_old_post_url field from the post.
*
* @return mixed.
* @return mixed
*/
protected function get_post_old_post_url() {
return filter_input( INPUT_POST, 'wpseo_old_post_url' );
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Reason: Seems to be only used in tests.
if ( isset( $_POST['wpseo_old_post_url'] ) && is_string( $_POST['wpseo_old_post_url'] ) ) {
return sanitize_text_field( wp_unslash( $_POST['wpseo_old_post_url'] ) );
}
// phpcs:enable WordPress.Security.NonceVerification.Missing.
return false;
}
/**
* Retrieves action field from the post.
*
* @return mixed.
* @return mixed
*/
protected function get_post_action() {
return filter_input( INPUT_POST, 'action' );
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- Reason: We are not controlling the request.
if ( isset( $_POST['action'] ) && is_string( $_POST['action'] ) ) {
return sanitize_text_field( wp_unslash( $_POST['action'] ) );
}
// phpcs:enable WordPress.Security.NonceVerification.Recommended.
return false;
}
/**

View File

@@ -19,6 +19,7 @@ class WPSEO_Premium_Assets implements WPSEO_WordPress_Integration {
*/
public function register_hooks() {
add_action( 'admin_init', [ $this, 'register_assets' ] );
add_action( 'init', [ $this, 'register_frontend_assets' ], 11 );
}
/**
@@ -35,6 +36,18 @@ class WPSEO_Premium_Assets implements WPSEO_WordPress_Integration {
array_walk( $styles, [ $this, 'register_style' ] );
}
/**
* Registers the assets for premium.
*
* @return void
*/
public function register_frontend_assets() {
$version = $this->get_version();
$scripts = $this->get_frontend_scripts( $version );
array_walk( $scripts, [ $this, 'register_script' ] );
}
/**
* Retrieves a flatten version.
*
@@ -48,6 +61,46 @@ class WPSEO_Premium_Assets implements WPSEO_WordPress_Integration {
return $asset_manager->flatten_version( WPSEO_PREMIUM_VERSION );
}
/**
* Retrieves an array of script to register.
*
* @codeCoverageIgnore Returns a simple dataset.
*
* @param string $version Current version number.
*
* @return array The scripts.
*/
protected function get_frontend_scripts( $version ) {
return [
[
'name' => 'yoast-seo-premium-commons',
'path' => 'assets/js/dist/',
'filename' => 'commons-premium-' . $version . WPSEO_CSSJS_SUFFIX . '.js',
'dependencies' => [],
],
[
'name' => 'yoast-seo-premium-frontend-inspector',
'path' => 'assets/js/dist/',
'filename' => 'frontend-inspector-' . $version . WPSEO_CSSJS_SUFFIX . '.js',
'dependencies' => [
'lodash',
'react',
'react-dom',
'wp-data',
'wp-dom-ready',
'wp-element',
'wp-i18n',
'yoast-seo-premium-commons',
WPSEO_Admin_Asset_Manager::PREFIX . 'frontend-inspector-resources',
WPSEO_Admin_Asset_Manager::PREFIX . 'prop-types-package',
WPSEO_Admin_Asset_Manager::PREFIX . 'style-guide',
WPSEO_Admin_Asset_Manager::PREFIX . 'yoast-components',
],
'in_footer' => true,
],
];
}
/**
* Retrieves an array of script to register.
*
@@ -90,6 +143,38 @@ class WPSEO_Premium_Assets implements WPSEO_WordPress_Integration {
WPSEO_Admin_Asset_Manager::PREFIX . 'yoast-components',
],
],
[
'name' => 'yoast-seo-premium-draft-js-plugins',
'path' => 'assets/js/dist/',
'filename' => 'wp-seo-premium-draft-js-plugins-' . $version . WPSEO_CSSJS_SUFFIX . '.js',
'in_footer' => true,
'dependencies' => [
'yoast-seo-premium-commons',
WPSEO_Admin_Asset_Manager::PREFIX . 'search-metadata-previews',
],
],
[
'name' => 'yoast-seo-premium-workouts',
'path' => 'assets/js/dist/',
'filename' => 'workouts-' . $version . WPSEO_CSSJS_SUFFIX . '.js',
'dependencies' => [
'clipboard',
'lodash',
'wp-api-fetch',
'wp-a11y',
'wp-components',
'wp-compose',
'wp-data',
'wp-dom-ready',
'wp-element',
'wp-i18n',
'yoast-seo-premium-commons',
WPSEO_Admin_Asset_Manager::PREFIX . 'analysis',
WPSEO_Admin_Asset_Manager::PREFIX . 'admin-modules',
WPSEO_Admin_Asset_Manager::PREFIX . 'react-select',
WPSEO_Admin_Asset_Manager::PREFIX . 'yoast-components',
],
],
[
'name' => 'yoast-seo-social-metadata-previews-package',
'path' => 'assets/js/dist/yoast/',
@@ -240,11 +325,60 @@ class WPSEO_Premium_Assets implements WPSEO_WordPress_Integration {
'footer' => true,
],
[
'name' => 'wp-seo-premium-schema-blocks',
'name' => 'wp-seo-premium-ai-generator',
'path' => 'assets/js/dist/',
'filename' => 'wp-seo-premium-schema-blocks-' . $version . WPSEO_CSSJS_SUFFIX . '.js',
'filename' => 'ai-generator-' . $version . WPSEO_CSSJS_SUFFIX . '.js',
'dependencies' => [
WPSEO_Admin_Asset_Manager::PREFIX . 'schema-blocks-package',
'lodash',
'wp-api-fetch',
'wp-components',
'wp-data',
'wp-dom-ready',
'wp-element',
'wp-hooks',
'wp-i18n',
'yoast-seo-premium-commons',
WPSEO_Admin_Asset_Manager::PREFIX . 'analysis',
WPSEO_Admin_Asset_Manager::PREFIX . 'editor-modules',
WPSEO_Admin_Asset_Manager::PREFIX . 'ui-library-package',
WPSEO_Admin_Asset_Manager::PREFIX . 'react-helmet-package',
],
],
[
'name' => 'wp-seo-premium-manage-ai-consent-button',
'path' => 'assets/js/dist/',
'filename' => 'manage-ai-consent-button-' . $version . WPSEO_CSSJS_SUFFIX . '.js',
'dependencies' => [
'lodash',
'wp-api-fetch',
'wp-components',
'wp-data',
'wp-dom-ready',
'wp-element',
'wp-hooks',
'wp-i18n',
'yoast-seo-premium-commons',
WPSEO_Admin_Asset_Manager::PREFIX . 'ui-library-package',
WPSEO_Admin_Asset_Manager::PREFIX . 'react-helmet-package',
],
],
[
'name' => 'wp-seo-premium-introductions',
'path' => 'assets/js/dist/',
'filename' => 'introductions-' . $version . WPSEO_CSSJS_SUFFIX . '.js',
'dependencies' => [
'lodash',
'wp-api-fetch',
'wp-components',
'wp-data',
'wp-dom-ready',
'wp-element',
'wp-hooks',
'wp-i18n',
'yoast-seo-premium-commons',
WPSEO_Admin_Asset_Manager::PREFIX . 'introductions',
WPSEO_Admin_Asset_Manager::PREFIX . 'ui-library-package',
WPSEO_Admin_Asset_Manager::PREFIX . 'react-helmet-package',
],
],
];
@@ -260,12 +394,21 @@ class WPSEO_Premium_Assets implements WPSEO_WordPress_Integration {
* @return array The styles.
*/
protected function get_styles( $version ) {
$rtl_suffix = ( is_rtl() ) ? '-rtl' : '';
return [
[
'name' => WPSEO_Admin_Asset_Manager::PREFIX . 'premium-metabox',
'source' => 'assets/css/dist/premium-metabox-' . $version . '.css',
'dependencies' => [],
],
[
'name' => WPSEO_Admin_Asset_Manager::PREFIX . 'premium-workouts',
'source' => 'assets/css/dist/premium-workouts-' . $version . '.css',
'dependencies' => [
'wp-components',
],
],
[
'name' => 'elementor-premium',
'source' => 'assets/css/dist/premium-elementor-' . $version . '.css',
@@ -274,10 +417,36 @@ class WPSEO_Premium_Assets implements WPSEO_WordPress_Integration {
],
],
[
'name' => WPSEO_Admin_Asset_Manager::PREFIX . 'premium-schema-blocks',
'source' => 'assets/css/dist/premium-schema-blocks-' . $version . '.css',
'name' => WPSEO_Admin_Asset_Manager::PREFIX . 'premium-draft-js-plugins',
'source' => 'assets/css/dist/premium-draft-js-plugins-' . $version . '.css',
'dependencies' => [],
],
[
'name' => WPSEO_Admin_Asset_Manager::PREFIX . 'premium-thank-you',
'source' => 'assets/css/dist/premium-thank-you-' . $version . '.css',
'dependencies' => [],
],
[
'name' => WPSEO_Admin_Asset_Manager::PREFIX . 'premium-settings',
'source' => 'assets/css/dist/premium-settings-' . $version . '.css',
'dependencies' => [],
],
[
'name' => WPSEO_Admin_Asset_Manager::PREFIX . 'premium-post-overview',
'source' => 'assets/css/dist/premium-post-overview-' . $version . '.css',
'dependencies' => [],
],
[
'name' => WPSEO_Admin_Asset_Manager::PREFIX . 'premium-tailwind',
'source' => 'assets/css/dist/premium-tailwind-' . $version . $rtl_suffix . '.css',
'dependencies' => [],
],
[
'name' => WPSEO_Admin_Asset_Manager::PREFIX . 'premium-ai-generator',
'source' => 'assets/css/dist/premium-ai-generator-' . $version . $rtl_suffix . '.css',
'dependencies' => [
WPSEO_Admin_Asset_Manager::PREFIX . 'schema-blocks',
WPSEO_Admin_Asset_Manager::PREFIX . 'premium-tailwind',
WPSEO_Admin_Asset_Manager::PREFIX . 'monorepo',
],
],
];

View File

@@ -25,7 +25,9 @@ class WPSEO_Premium_Expose_Shortlinks implements WPSEO_WordPress_Integration {
* @return array Admin localization object.
*/
public function expose_shortlinks( $input ) {
$input['shortlinks.keyword_synonyms_info'] = WPSEO_Shortlinker::get( 'https://yoa.st/kd1' );
$input['shortlinks.keyword_synonyms_info'] = WPSEO_Shortlinker::get( 'https://yoa.st/kd1' );
$input['shortlinks.site_structure_metabox'] = WPSEO_Shortlinker::get( 'https://yoa.st/site-structure-metabox' );
$input['shortlinks.notification_internal_link'] = WPSEO_Shortlinker::get( 'https://yoa.st/notification-internal-link' );
return $input;
}

View File

@@ -167,7 +167,7 @@ class WPSEO_Premium_Import_Manager implements WPSEO_WordPress_Integration {
*
* @param array $result The import result.
*
* @return void.
* @return void
*/
protected function set_import_success( array $result ) {
$this->import->success = true;
@@ -330,7 +330,13 @@ class WPSEO_Premium_Import_Manager implements WPSEO_WordPress_Integration {
* @return string The posted htaccess.
*/
protected function get_posted_htaccess() {
return stripcslashes( filter_input( INPUT_POST, 'htaccess' ) );
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are validating a nonce here.
if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'wpseo-import' )
&& isset( $_POST['htaccess'] ) && is_string( $_POST['htaccess'] ) ) {
return sanitize_text_field( wp_unslash( $_POST['htaccess'] ) );
}
return '';
}
/**
@@ -341,13 +347,14 @@ class WPSEO_Premium_Import_Manager implements WPSEO_WordPress_Integration {
* @return string|null The posted import plugin.
*/
protected function get_posted_import_plugin() {
$wpseo_post = filter_input( INPUT_POST, 'wpseo', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
if ( ! isset( $wpseo_post['import_plugin'] ) ) {
return null;
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are validating a nonce here.
if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'wpseo-import' )
&& isset( $_POST['wpseo'] ) && is_array( $_POST['wpseo'] )
&& isset( $_POST['wpseo']['import_plugin'] ) && is_string( $_POST['wpseo']['import_plugin'] ) ) {
return sanitize_text_field( wp_unslash( $_POST['wpseo']['import_plugin'] ) );
}
return $wpseo_post['import_plugin'];
return null;
}
/**

View File

@@ -91,9 +91,12 @@ class WPSEO_Premium_Keyword_Export_Manager implements WPSEO_WordPress_Integratio
* @return bool True if this is a valid CSV export request.
*/
protected function is_valid_csv_export_request() {
return filter_input( INPUT_GET, 'page' ) === 'wpseo_tools'
&& filter_input( INPUT_GET, 'tool' ) === 'import-export'
&& filter_input( INPUT_POST, 'export-posts' );
// phpcs:disable WordPress.Security.NonceVerification -- Reason: Nonce is checked in export.
// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are strictly comparing only or ignoring the value.
return ( isset( $_GET['page'] ) && is_string( $_GET['page'] ) && wp_unslash( $_GET['page'] ) === 'wpseo_tools' )
&& ( isset( $_GET['tool'] ) && is_string( $_GET['tool'] ) && wp_unslash( $_GET['tool'] ) === 'import-export' )
&& ( isset( $_POST['export-posts'] ) && ! empty( $_POST['export-posts'] ) );
// phpcs:enable
}
/**

View File

@@ -5,8 +5,9 @@
* @package WPSEO\Premium|Classes
*/
use Yoast\WP\SEO\Helpers\Prominent_Words_Helper;
use Yoast\WP\SEO\Integrations\Admin\Prominent_Words\Indexing_Integration;
use Yoast\WP\SEO\Premium\Helpers\Current_Page_Helper;
use Yoast\WP\SEO\Premium\Helpers\Prominent_Words_Helper;
use Yoast\WP\SEO\Premium\Integrations\Admin\Prominent_Words\Indexing_Integration;
/**
* The metabox for premium.
@@ -27,14 +28,23 @@ class WPSEO_Premium_Metabox implements WPSEO_WordPress_Integration {
*/
protected $prominent_words_helper;
/**
* Holds the Current_Page_Helper instance.
*
* @var Current_Page_Helper
*/
private $current_page_helper;
/**
* Creates the meta box class.
*
* @param Prominent_Words_Helper $prominent_words_helper The prominent words helper.
* @param Current_Page_Helper $current_page_helper The Current_Page_Helper.
* @param WPSEO_Metabox_Link_Suggestions|null $link_suggestions The link suggestions meta box.
*/
public function __construct(
Prominent_Words_Helper $prominent_words_helper,
Current_Page_Helper $current_page_helper,
WPSEO_Metabox_Link_Suggestions $link_suggestions = null
) {
if ( $link_suggestions === null ) {
@@ -42,6 +52,7 @@ class WPSEO_Premium_Metabox implements WPSEO_WordPress_Integration {
}
$this->prominent_words_helper = $prominent_words_helper;
$this->current_page_helper = $current_page_helper;
$this->link_suggestions = $link_suggestions;
}
@@ -67,8 +78,10 @@ class WPSEO_Premium_Metabox implements WPSEO_WordPress_Integration {
public static function are_content_endpoints_available() {
if ( function_exists( 'rest_get_server' ) ) {
$namespaces = rest_get_server()->get_namespaces();
return in_array( 'wp/v2', $namespaces, true );
}
return false;
}
@@ -102,9 +115,6 @@ class WPSEO_Premium_Metabox implements WPSEO_WordPress_Integration {
wp_enqueue_script( WPSEO_Admin_Asset_Manager::PREFIX . 'premium-metabox' );
wp_enqueue_style( WPSEO_Admin_Asset_Manager::PREFIX . 'premium-metabox' );
$localization = new WPSEO_Admin_Asset_Yoast_Components_L10n();
$localization->localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'premium-metabox' );
$premium_localization = new WPSEO_Premium_Asset_JS_L10n();
$premium_localization->localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'premium-metabox' );
@@ -113,20 +123,53 @@ class WPSEO_Premium_Metabox implements WPSEO_WordPress_Integration {
/**
* Send data to assets by using wp_localize_script.
* Also localizes the Table of Contents heading title to the wp-seo-premium-blocks asset.
*
* @return void
*/
public function send_data_to_assets() {
$analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$analysis_seo = new WPSEO_Metabox_Analysis_SEO();
$content_analysis = new WPSEO_Metabox_Analysis_Readability();
$assets_manager = new WPSEO_Admin_Asset_Manager();
/**
* Filters the parameter to disable Table of Content block.
*
* Note: Used to prevent auto-generation of HTML anchors for headings when TOC block is registered.
*
* @since 21.5
*
* @param bool $disable_table_of_content The value of the `autoload` parameter. Default: false.
*
* @return bool The filtered value of the `disable_table_of_content` parameter.
*/
$disable_table_of_content = apply_filters( 'Yoast\WP\SEO\disable_table_of_content_block', false );
$data = [
'restApi' => $this->get_rest_api_config(),
'seoAnalysisEnabled' => $analysis_seo->is_enabled(),
'licensedURL' => WPSEO_Utils::get_home_url(),
'settingsPageUrl' => admin_url( 'admin.php?page=wpseo_dashboard#top#features' ),
'integrationsTabURL' => admin_url( 'admin.php?page=wpseo_dashboard#top#integrations' ),
'restApi' => $this->get_rest_api_config(),
'seoAnalysisEnabled' => $analysis_seo->is_enabled(),
'contentAnalysisEnabled' => $content_analysis->is_enabled(),
'licensedURL' => WPSEO_Utils::get_home_url(),
'settingsPageUrl' => admin_url( 'admin.php?page=wpseo_page_settings#/site-features#card-wpseo-enable_link_suggestions' ),
'integrationsTabURL' => admin_url( 'admin.php?page=wpseo_integrations' ),
'commonsScriptUrl' => \plugins_url(
'assets/js/dist/commons-premium-' . $assets_manager->flatten_version( WPSEO_PREMIUM_VERSION ) . WPSEO_CSSJS_SUFFIX . '.js',
WPSEO_PREMIUM_FILE
),
'premiumAssessmentsScriptUrl' => \plugins_url(
'assets/js/dist/register-premium-assessments-' . $assets_manager->flatten_version( WPSEO_PREMIUM_VERSION ) . WPSEO_CSSJS_SUFFIX . '.js',
WPSEO_PREMIUM_FILE
),
'pluginUrl' => \plugins_url( '', \WPSEO_PREMIUM_FILE ),
];
if ( \defined( 'YOAST_SEO_TEXT_FORMALITY' ) && YOAST_SEO_TEXT_FORMALITY === true ) {
$data['textFormalityScriptUrl'] = \plugins_url(
'assets/js/dist/register-text-formality-' . $assets_manager->flatten_version( WPSEO_PREMIUM_VERSION ) . WPSEO_CSSJS_SUFFIX . '.js',
WPSEO_PREMIUM_FILE
);
}
if ( WPSEO_Metabox::is_post_edit( $this->get_current_page() ) ) {
$data = array_merge( $data, $this->get_post_metabox_config() );
}
@@ -134,8 +177,24 @@ class WPSEO_Premium_Metabox implements WPSEO_WordPress_Integration {
$data = array_merge( $data, $this->get_term_metabox_config() );
}
if ( current_user_can( 'edit_others_posts' ) ) {
$data['workoutsUrl'] = admin_url( 'admin.php?page=wpseo_workouts' );
}
// Use an extra level in the array to preserve booleans. WordPress sanitizes scalar values in the first level of the array.
wp_localize_script( 'yoast-seo-premium-metabox', 'wpseoPremiumMetaboxData', [ 'data' => $data ] );
// Localize the title of the Table of Contents block: the translation needs to be based on the site language instead of the user language.
wp_localize_script(
'wp-seo-premium-blocks',
'wpseoTOCData',
[
'data' => [
'TOCTitle' => \__( 'Table of contents', 'wordpress-seo-premium' ),
'disableTableOfContents' => $disable_table_of_content,
],
]
);
}
/**
@@ -144,27 +203,26 @@ class WPSEO_Premium_Metabox implements WPSEO_WordPress_Integration {
* @return array The config.
*/
protected function get_post_metabox_config() {
$insights_enabled = WPSEO_Options::get( 'enable_metabox_insights', false );
$link_suggestions_enabled = WPSEO_Options::get( 'enable_link_suggestions', false );
$post = $this->get_post();
$prominent_words_support = new WPSEO_Premium_Prominent_Words_Support();
if ( ! $prominent_words_support->is_post_type_supported( $post->post_type ) ) {
$insights_enabled = false;
}
$prominent_words_support = new WPSEO_Premium_Prominent_Words_Support();
$is_prominent_words_available = $prominent_words_support->is_post_type_supported( $post->post_type );
$site_locale = \get_locale();
$language = WPSEO_Language_Utils::get_language( $site_locale );
return [
'insightsEnabled' => ( $insights_enabled ) ? 'enabled' : 'disabled',
'currentObjectId' => $this->get_post_ID(),
'currentObjectType' => 'post',
'linkSuggestionsEnabled' => ( $link_suggestions_enabled ) ? 'enabled' : 'disabled',
'linkSuggestionsAvailable' => $prominent_words_support->is_post_type_supported( $post->post_type ),
'linkSuggestionsUnindexed' => ! $this->is_prominent_words_indexing_completed() && WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ),
'perIndexableLimit' => $this->per_indexable_limit( $language ),
'currentObjectId' => $this->get_post_ID(),
'currentObjectType' => 'post',
'linkSuggestionsEnabled' => ( $link_suggestions_enabled ) ? 'enabled' : 'disabled',
'linkSuggestionsAvailable' => $is_prominent_words_available,
'linkSuggestionsUnindexed' => ! $this->is_prominent_words_indexing_completed() && WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ),
'perIndexableLimit' => $this->per_indexable_limit( $language ),
'isProminentWordsAvailable' => $is_prominent_words_available,
'isTitleAssessmentAvailable' => true,
];
}
@@ -189,24 +247,22 @@ class WPSEO_Premium_Metabox implements WPSEO_WordPress_Integration {
}
$link_suggestions_enabled = WPSEO_Options::get( 'enable_link_suggestions', false );
$insights_enabled = WPSEO_Options::get( 'enable_metabox_insights', false );
$prominent_words_support = new WPSEO_Premium_Prominent_Words_Support();
if ( ! $prominent_words_support->is_taxonomy_supported( $term->taxonomy ) ) {
$insights_enabled = false;
}
$prominent_words_support = new WPSEO_Premium_Prominent_Words_Support();
$is_prominent_words_available = $prominent_words_support->is_taxonomy_supported( $term->taxonomy );
$site_locale = \get_locale();
$language = WPSEO_Language_Utils::get_language( $site_locale );
return [
'insightsEnabled' => ( $insights_enabled ) ? 'enabled' : 'disabled',
'currentObjectId' => $term->term_id,
'currentObjectType' => 'term',
'linkSuggestionsEnabled' => ( $link_suggestions_enabled ) ? 'enabled' : 'disabled',
'linkSuggestionsAvailable' => $prominent_words_support->is_taxonomy_supported( $term->taxonomy ),
'linkSuggestionsUnindexed' => ! $this->is_prominent_words_indexing_completed() && WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ),
'perIndexableLimit' => $this->per_indexable_limit( $language ),
'currentObjectId' => $term->term_id,
'currentObjectType' => 'term',
'linkSuggestionsEnabled' => ( $link_suggestions_enabled ) ? 'enabled' : 'disabled',
'linkSuggestionsAvailable' => $is_prominent_words_available,
'linkSuggestionsUnindexed' => ! $this->is_prominent_words_indexing_completed() && WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ),
'perIndexableLimit' => $this->per_indexable_limit( $language ),
'isProminentWordsAvailable' => $is_prominent_words_available,
'isTitleAssessmentAvailable' => false,
];
}
@@ -278,72 +334,18 @@ class WPSEO_Premium_Metabox implements WPSEO_WordPress_Integration {
protected function load_metabox( $current_page ) {
// When the current page is a term related one.
if ( WPSEO_Taxonomy::is_term_edit( $current_page ) || WPSEO_Taxonomy::is_term_overview( $current_page ) ) {
return WPSEO_Options::get( 'display-metabox-tax-' . $this->get_current_taxonomy() );
return WPSEO_Options::get( 'display-metabox-tax-' . $this->current_page_helper->get_current_taxonomy() );
}
// When the current page isn't a post related one.
if ( WPSEO_Metabox::is_post_edit( $current_page ) || WPSEO_Metabox::is_post_overview( $current_page ) ) {
return WPSEO_Post_Type::has_metabox_enabled( $this->get_current_post_type() );
return WPSEO_Post_Type::has_metabox_enabled( $this->current_page_helper->get_current_post_type() );
}
// Make sure ajax integrations are loaded.
return wp_doing_ajax();
}
/**
* Retrieves the current post type.
*
* @codeCoverageIgnore It depends on external request input.
*
* @return string The post type.
*/
protected function get_current_post_type() {
$post = filter_input( INPUT_GET, 'post', FILTER_SANITIZE_STRING );
if ( $post ) {
return get_post_type( get_post( $post ) );
}
return filter_input(
INPUT_GET,
'post_type',
FILTER_SANITIZE_STRING,
[
'options' => [
'default' => 'post',
],
]
);
}
/**
* Retrieves the current taxonomy.
*
* @codeCoverageIgnore This function depends on external request input.
*
* @return string The taxonomy.
*/
protected function get_current_taxonomy() {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- doing a strict in_array check should be sufficient.
if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || ! in_array( $_SERVER['REQUEST_METHOD'], [ 'GET', 'POST' ], true ) ) {
return '';
}
if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
return (string) filter_input(
INPUT_POST,
'taxonomy',
FILTER_SANITIZE_STRING
);
}
return (string) filter_input(
INPUT_GET,
'taxonomy',
FILTER_SANITIZE_STRING
);
}
/**
* Retrieves the value of the pagenow variable.
*

View File

@@ -26,7 +26,11 @@ class WPSEO_Premium_Option extends WPSEO_Option {
*/
protected $defaults = [
// Form fields.
'prominent_words_indexing_completed' => null,
'prominent_words_indexing_completed' => null,
'workouts' => [ 'cornerstone' => [ 'finishedSteps' => [] ] ],
'should_redirect_after_install' => false,
'activation_redirect_timestamp' => 0,
'dismiss_update_premium_notification' => '0',
];
/**
@@ -67,6 +71,26 @@ class WPSEO_Premium_Option extends WPSEO_Option {
$clean[ $key ] = WPSEO_Utils::validate_bool( $dirty[ $key ] );
}
break;
case 'workouts':
if ( isset( $dirty[ $key ] ) && is_array( $dirty[ $key ] ) ) {
$clean[ $key ] = $dirty[ $key ];
}
break;
case 'should_redirect_after_install':
if ( isset( $dirty[ $key ] ) && is_bool( $dirty[ $key ] ) ) {
$clean[ $key ] = $dirty[ $key ];
}
break;
case 'activation_redirect_timestamp':
if ( isset( $dirty[ $key ] ) && is_int( $dirty[ $key ] ) ) {
$clean[ $key ] = $dirty[ $key ];
}
break;
case 'dismiss_update_premium_notification':
if ( isset( $dirty[ $key ] ) && is_string( $dirty[ $key ] ) ) {
$clean[ $key ] = $dirty[ $key ];
}
break;
}
}

View File

@@ -16,20 +16,6 @@ class WPSEO_Premium_Orphaned_Content_Support {
* @return array The supported post types.
*/
public function get_supported_post_types() {
/**
* Filter: 'wpseo_orphaned_post_types' - Allows changes for the accessible post types.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\orphaned_post_types'} filter instead.
*
* @api array The accessible post types.
*/
$orphaned_post_types = apply_filters_deprecated(
'wpseo_orphaned_post_types',
[ WPSEO_Post_Type::get_accessible_post_types() ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\orphaned_post_types'
);
/**
* Filter: 'Yoast\WP\SEO\orphaned_post_types' - Allows changes for the accessible post types.
*
@@ -39,7 +25,7 @@ class WPSEO_Premium_Orphaned_Content_Support {
*
* @api array The accessible post types.
*/
$orphaned_post_types = apply_filters( 'Yoast\WP\SEO\orphaned_post_types', $orphaned_post_types );
$orphaned_post_types = apply_filters( 'Yoast\WP\SEO\orphaned_post_types', WPSEO_Post_Type::get_accessible_post_types() );
if ( ! is_array( $orphaned_post_types ) || empty( $orphaned_post_types ) ) {
$orphaned_post_types = [];

View File

@@ -16,20 +16,6 @@ class WPSEO_Premium_Prominent_Words_Support {
* @return array The supported post types.
*/
public function get_supported_post_types() {
/**
* Filter: 'wpseo_prominent_words_post_types' - Allows changes for the accessible post types.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\prominent_words_post_types'} filter instead.
*
* @api array The accessible post types.
*/
$prominent_words_post_types = apply_filters_deprecated(
'wpseo_prominent_words_post_types',
[ WPSEO_Post_Type::get_accessible_post_types() ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\prominent_words_post_types'
);
/**
* Filter: 'Yoast\WP\SEO\prominent_words_post_types' - Allows changes for the accessible post types.
*
@@ -41,7 +27,7 @@ class WPSEO_Premium_Prominent_Words_Support {
*/
$prominent_words_post_types = apply_filters(
'Yoast\WP\SEO\prominent_words_post_types',
$prominent_words_post_types
WPSEO_Post_Type::get_accessible_post_types()
);
if ( ! is_array( $prominent_words_post_types ) || empty( $prominent_words_post_types ) ) {

View File

@@ -72,9 +72,12 @@ class WPSEO_Premium_Redirect_Export_Manager implements WPSEO_WordPress_Integrati
* @return bool
*/
protected function is_valid_csv_export_request() {
return filter_input( INPUT_GET, 'page' ) === 'wpseo_tools'
&& filter_input( INPUT_GET, 'tool' ) === 'import-export'
&& filter_input( INPUT_POST, 'export' );
// phpcs:disable WordPress.Security.NonceVerification -- Reason: Nonce is checked in export.
// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are strictly comparing only or ignoring the value.
return ( isset( $_GET['page'] ) && is_string( $_GET['page'] ) && wp_unslash( $_GET['page'] ) === 'wpseo_tools' )
&& ( isset( $_GET['tool'] ) && is_string( $_GET['tool'] ) && wp_unslash( $_GET['tool'] ) === 'import-export' )
&& ( isset( $_POST['export'] ) && ! empty( $_POST['export'] ) );
// phpcs:enable
}
/**

View File

@@ -64,7 +64,7 @@ class WPSEO_Premium_Stale_Cornerstone_Content_Filter extends WPSEO_Abstract_Post
}
return sprintf(
/* translators: %s expands to the posttype label, %2$s expands anchor to blog post about cornerstone content, %3$s expands to </a> */
/* translators: %1$s expands to dynamic post type label, %2$s expands anchor to blog post about cornerstone content, %3$s expands to </a> */
__( 'Stale cornerstone content refers to cornerstone content that hasnt been updated in the last 6 months. Make sure to keep these %1$s up-to-date. %2$sLearn more about cornerstone content%3$s.', 'wordpress-seo-premium' ),
strtolower( $post_type_object->labels->name ),
'<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/1i9' ) . '" target="_blank">',

View File

@@ -59,16 +59,18 @@ class WPSEO_Redirect_Apache_Exporter extends WPSEO_Redirect_File_Exporter {
return $this->format_non_target( $redirect );
}
$origin = $redirect->get_origin();
if ( $redirect->get_format() === WPSEO_Redirect_Formats::PLAIN ) {
return sprintf(
$this->get_format( $redirect->get_format() ),
$this->format_url( $redirect->get_origin() ),
$this->format_url( $redirect->get_target() ),
$redirect->get_type()
);
$origin = $this->format_url( $redirect->get_origin() );
}
return parent::format( $redirect );
return sprintf(
$this->get_format( $redirect->get_format() ),
$origin,
$this->format_url( $redirect->get_target() ),
$redirect->get_type()
);
}
/**

View File

@@ -53,21 +53,6 @@ class WPSEO_Redirect_Nginx_Exporter extends WPSEO_Redirect_File_Exporter {
* @return string
*/
private function add_x_redirect_header() {
/**
* Filter: 'wpseo_add_x_redirect' - can be used to remove the X-Redirect-By header
* Yoast SEO Premium creates (defaults to true, which is adding it)
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\add_x_redirect'} filter instead.
*
* @api bool
*/
$add_x_redirect = apply_filters_deprecated(
'wpseo_add_x_redirect',
[ true ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\add_x_redirect'
);
/**
* Filter: 'Yoast\WP\SEO\add_x_redirect' - can be used to remove the X-Redirect-By header
* Yoast SEO Premium creates (defaults to true, which is adding it)
@@ -78,7 +63,7 @@ class WPSEO_Redirect_Nginx_Exporter extends WPSEO_Redirect_File_Exporter {
*
* @api bool
*/
if ( apply_filters( 'Yoast\WP\SEO\add_x_redirect', $add_x_redirect ) === true ) {
if ( apply_filters( 'Yoast\WP\SEO\add_x_redirect', true ) === true ) {
return 'add_header X-Redirect-By "Yoast SEO Premium";';
}

View File

@@ -27,11 +27,25 @@ class WPSEO_Redirect_Option_Exporter implements WPSEO_Redirect_Exporter {
$formatted_redirects[ $redirect->get_format() ][ $redirect->get_origin() ] = $this->format( $redirect );
}
// Save the plain redirects. No need to autoload, since the option is fetched straight from the DB.
update_option( WPSEO_Redirect_Option::OPTION_PLAIN, $formatted_redirects[ WPSEO_Redirect_Formats::PLAIN ], 'no' );
/**
* Filters the parameter to save the redirect options as autoloaded.
*
* Note that the `autoload` value in the database will change only if the option value changes (i.e. a redirect is added, edited or deleted).
* Otherwise you will need to change the `autoload` value directly in the DB.
*
* @since 20.13
*
* @param bool $autoload The value of the `autoload` parameter. Default: true.
* @param string $type The type of redirects, either `plain` or `regex`.
* @param array $formatted_redirects The redirects to be written in the options, already formatted.
*
* @return bool The filtered value of the `autoload` parameter.
*/
$autoload_options_plain = apply_filters( 'Yoast\WP\SEO\redirects_options_autoload', true, 'plain', $formatted_redirects );
$autoload_options_regex = apply_filters( 'Yoast\WP\SEO\redirects_options_autoload', true, 'regex', $formatted_redirects );
// Save the regex redirects. No need to autoload, since the option is fetched straight from the DB.
update_option( WPSEO_Redirect_Option::OPTION_REGEX, $formatted_redirects[ WPSEO_Redirect_Formats::REGEX ], 'no' );
update_option( WPSEO_Redirect_Option::OPTION_PLAIN, $formatted_redirects[ WPSEO_Redirect_Formats::PLAIN ], $autoload_options_plain );
update_option( WPSEO_Redirect_Option::OPTION_REGEX, $formatted_redirects[ WPSEO_Redirect_Formats::REGEX ], $autoload_options_regex );
return true;
}

View File

@@ -45,14 +45,17 @@ class WPSEO_Redirect_Table_Presenter extends WPSEO_Redirect_Tab_Presenter {
* @return string The old URL.
*/
private function get_old_url() {
// Check if there's an old URL set.
$old_url = filter_input( INPUT_GET, 'old_url', FILTER_DEFAULT, [ 'default' => '' ] );
if ( isset( $_GET['old_url'] ) && is_string( $_GET['old_url'] ) ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We decode it before sanitization to keep encoded characters.
$old_url = sanitize_text_field( rawurldecode( wp_unslash( $_GET['old_url'] ) ) );
if ( ! empty( $old_url ) ) {
check_admin_referer( 'wpseo_redirects-old-url', 'wpseo_premium_redirects_nonce' );
if ( $old_url !== '' ) {
return esc_attr( rawurldecode( $old_url ) );
return esc_attr( $old_url );
}
}
return $old_url;
return '';
}
/**

View File

@@ -177,14 +177,20 @@ class WPSEO_Redirect_Ajax {
* @return WPSEO_Redirect
*/
private function get_redirect_from_post( $post_value ) {
$post_values = filter_input( INPUT_POST, $post_value, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
// phpcs:ignore WordPress.Security.NonceVerification -- Reason: nonce is verified in ajax_update_redirect and ajax_add_redirect.
if ( isset( $_POST[ $post_value ] ) && is_array( $_POST[ $post_value ] ) ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification -- Reason: we want to stick to sanitize_url function, while the nonce has been already checked.
$post_values = wp_unslash( $_POST[ $post_value ] );
return new WPSEO_Redirect(
$this->sanitize_url( $post_values['origin'] ),
$this->sanitize_url( $post_values['target'] ),
urldecode( $post_values['type'] ),
$this->redirect_format
);
return new WPSEO_Redirect(
$this->sanitize_url( $post_values['origin'] ),
$this->sanitize_url( $post_values['target'] ),
urldecode( $post_values['type'] ),
$this->redirect_format
);
}
return new WPSEO_Redirect( '', '', '', '' );
}
/**

View File

@@ -182,20 +182,6 @@ class WPSEO_Redirect_Option {
array_walk( $redirects, [ $this, 'map_object_to_option' ] );
/**
* Filter: 'wpseo_premium_save_redirects' - can be used to filter the redirects before saving.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\save_redirects'} filter instead.
*
* @api array $redirects
*/
$redirects = apply_filters_deprecated(
'wpseo_premium_save_redirects',
[ $redirects ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\save_redirects'
);
/**
* Filter: 'Yoast\WP\SEO\save_redirects' - can be used to filter the redirects before saving.
*
@@ -219,19 +205,7 @@ class WPSEO_Redirect_Option {
* @return array
*/
public function get_from_option( $option_name = self::OPTION ) {
/**
* Filter: 'wpseo_premium_get_redirects' - can be used to filter the redirects on option retrieval.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\get_redirects'} filter instead.
*
* @api array $redirects
*/
$redirects = apply_filters_deprecated(
'wpseo_premium_get_redirects',
[ get_option( $option_name ) ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\get_redirects'
);
$redirects = get_option( $option_name );
/**
* Filter: 'Yoast\WP\SEO\get_redirects' - can be used to filter the redirects on option retrieval.
@@ -259,22 +233,6 @@ class WPSEO_Redirect_Option {
* @return void
*/
protected function run_redirects_modified_action( WPSEO_Redirect $redirect ) {
/**
* Filter: wpseo_premium_redirects_modified - Allow developers to run actions when the redirects are modified.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\redirects_modified'} action instead.
*
* @api string $origin The redirect origin.
* @param string $target The redirect target.
* @param int $type The redirect type (301, 404, 410, etc).
*/
do_action_deprecated(
'wpseo_premium_redirects_modified',
[ $redirect->get_origin(), $redirect->get_target(), $redirect->get_type() ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\redirects_modified'
);
/**
* Filter: Yoast\WP\SEO\redirects_modified - Allow developers to run actions when the redirects are modified.
*

View File

@@ -42,13 +42,11 @@ class WPSEO_Redirect_Page {
* A redirect-type filter.
*/
public function list_table_search() {
$options = [ 'options' => [ 'default' => '' ] ];
$url = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL, $options );
if ( empty( $url ) && isset( $_SERVER['REQUEST_URI'] ) ) {
$url = filter_var( $_SERVER['REQUEST_URI'], FILTER_SANITIZE_URL, $options );
if ( ! isset( $_SERVER['REQUEST_URI'] ) ) {
return;
}
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Variable is used in a strict comparison and sanitized by wp_safe_redirect anyway.
$url = wp_unslash( $_SERVER['REQUEST_URI'] );
$new_url = $this->extract_redirect_type_from_url( $url );
$new_url = $this->extract_search_string_from_url( $new_url );
@@ -67,12 +65,14 @@ class WPSEO_Redirect_Page {
* @return string The newly formatted URL. Returns original URL if filter is null.
*/
protected function extract_redirect_type_from_url( $url ) {
$filter = filter_input( INPUT_POST, 'redirect-type' );
if ( $filter === null ) {
if ( ( ! isset( $_POST['redirect-type'] ) ) || ( ! is_string( $_POST['redirect-type'] ) )
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized in wp_verify_none.
|| ! isset( $_POST['wpseo_redirects_ajax_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['wpseo_redirects_ajax_nonce'] ), 'wpseo-redirects-ajax-security' ) ) {
return $url;
}
$filter = sanitize_text_field( wp_unslash( $_POST['redirect-type'] ) );
$new_url = remove_query_arg( 'redirect-type', $url );
if ( $filter !== '0' ) {
@@ -90,12 +90,14 @@ class WPSEO_Redirect_Page {
* @return string The newly formatted URL. Returns original URL if search string is null.
*/
protected function extract_search_string_from_url( $url ) {
$search_string = filter_input( INPUT_POST, 's' );
if ( $search_string === null ) {
if ( ( ! isset( $_POST['s'] ) ) || ( ! is_string( $_POST['s'] ) )
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized in wp_verify_none.
|| ! isset( $_POST['wpseo_redirects_ajax_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['wpseo_redirects_ajax_nonce'] ), 'wpseo-redirects-ajax-security' ) ) {
return $url;
}
$search_string = sanitize_text_field( wp_unslash( $_POST['s'] ) );
$new_url = remove_query_arg( 's', $url );
if ( $search_string !== '' ) {
@@ -127,11 +129,12 @@ class WPSEO_Redirect_Page {
plugin_dir_url( WPSEO_PREMIUM_FILE )
. 'assets/js/dist/wp-seo-premium-admin-redirects-' . $version . WPSEO_CSSJS_SUFFIX . '.js',
$dependencies,
WPSEO_PREMIUM_VERSION
WPSEO_PREMIUM_VERSION,
true
);
wp_localize_script( 'wp-seo-premium-admin-redirects', 'wpseoPremiumStrings', WPSEO_Premium_Javascript_Strings::strings() );
wp_localize_script( 'wp-seo-premium-admin-redirects', 'wpseoUserLocale', [ 'code' => substr( \get_user_locale(), 0, 2 ) ] );
wp_localize_script( 'wp-seo-premium-admin-redirects', 'wpseoAdminRedirect', [ 'homeUrl' => home_url( '/' ) ] );
wp_enqueue_style( 'wpseo-premium-redirects', plugin_dir_url( WPSEO_PREMIUM_FILE ) . 'assets/css/dist/premium-redirects-' . $version . '.css', [], WPSEO_PREMIUM_VERSION );
wp_enqueue_style( 'wp-jquery-ui-dialog' );
@@ -147,16 +150,19 @@ class WPSEO_Redirect_Page {
/**
* Catch redirects_per_page.
*
* @param string $status Unused.
* @param string $option The option name where the value is set for.
* @param string $value The new value for the screen option.
* @param string|false $status The value to save instead of the option value.
* Default false (to skip saving the current option).
* @param string $option The option name where the value is set for.
* @param string $value The new value for the screen option.
*
* @return string|void
* @return string|false
*/
public function set_screen_option( $status, $option, $value ) {
if ( $option === 'redirects_per_page' ) {
return $value;
}
return $status;
}
/**
@@ -232,7 +238,8 @@ class WPSEO_Redirect_Page {
add_action( 'update_option_wpseo_redirect', [ $this, 'save_redirect_files' ], 10, 2 );
// Convert post into get on search and loading the page scripts.
if ( filter_input( INPUT_GET, 'page' ) === 'wpseo_redirects' ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Recommended -- We're not manipulating the value.
if ( isset( $_GET['page'] ) && is_string( $_GET['page'] ) && wp_unslash( $_GET['page'] ) === 'wpseo_redirects' ) {
$upgrade_manager = new WPSEO_Upgrade_Manager();
$upgrade_manager->retry_upgrade_31();
@@ -263,17 +270,16 @@ class WPSEO_Redirect_Page {
static $current_tab;
if ( $current_tab === null ) {
$current_tab = filter_input(
INPUT_GET,
'tab',
FILTER_VALIDATE_REGEXP,
[
'options' => [
'default' => WPSEO_Redirect_Formats::PLAIN,
'regexp' => '/^(' . WPSEO_Redirect_Formats::PLAIN . '|' . WPSEO_Redirect_Formats::REGEX . '|settings)$/',
],
]
);
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We're not manipulating the value.
if ( isset( $_GET['tab'] ) && is_string( $_GET['tab'] )
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Recommended -- value sanitized in the if body, regex filters unwanted values.
&& in_array( wp_unslash( $_GET['tab'] ), [ WPSEO_Redirect_Formats::PLAIN, WPSEO_Redirect_Formats::REGEX, 'settings' ], true ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- the regex takes care of filtering out unwanted values.
$current_tab = sanitize_text_field( wp_unslash( $_GET['tab'] ) );
}
else {
$current_tab = WPSEO_Redirect_Formats::PLAIN;
}
}
return $current_tab;
@@ -305,35 +311,31 @@ class WPSEO_Redirect_Page {
* @return void
*/
private function fetch_bulk_action() {
if ( wp_verify_nonce( filter_input( INPUT_POST, 'wpseo_redirects_ajax_nonce' ), 'wpseo-redirects-ajax-security' ) ) {
if ( filter_input( INPUT_POST, 'action' ) === 'delete' || filter_input( INPUT_POST, 'action2' ) === 'delete' ) {
$bulk_delete = filter_input( INPUT_POST, 'wpseo_redirects_bulk_delete', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
$redirects = [];
foreach ( $bulk_delete as $origin ) {
$redirect = $this->get_redirect_manager()->get_redirect( $origin );
if ( $redirect !== false ) {
$redirects[] = $redirect;
}
}
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized in wp_verify_none.
if ( ! isset( $_POST['wpseo_redirects_ajax_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['wpseo_redirects_ajax_nonce'] ), 'wpseo-redirects-ajax-security' ) ) {
return;
}
$this->get_redirect_manager()->delete_redirects( $redirects );
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We're just strictly comparing the value.
if ( ( ! isset( $_POST['action'] ) || ! is_string( $_POST['action'] ) || ! wp_unslash( $_POST['action'] ) === 'delete' )
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We're just strictly comparing the value.
&& ( ! isset( $_POST['action2'] ) || ! is_string( $_POST['action2'] ) || ! wp_unslash( $_POST['action2'] ) === 'delete' ) ) {
return;
}
if ( ! isset( $_POST['wpseo_redirects_bulk_delete'] ) || ! is_array( $_POST['wpseo_redirects_bulk_delete'] ) ) {
return;
}
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Array elements are sanitized one by one in the foreach loop.
$bulk_delete = wp_unslash( $_POST['wpseo_redirects_bulk_delete'] );
$redirects = [];
foreach ( $bulk_delete as $origin ) {
$redirect = $this->get_redirect_manager()->get_redirect( $origin );
if ( $redirect !== false ) {
$redirects[] = $redirect;
}
}
}
/* ********************* DEPRECATED METHODS ********************* */
/**
* Get the Yoast SEO options.
*
* @deprecated 12.9
* @codeCoverageIgnore
*
* @return array
*/
public static function get_options() {
_deprecated_function( __METHOD__, 'WPSEO 12.9' );
return [];
$this->get_redirect_manager()->delete_redirects( $redirects );
}
}

View File

@@ -45,6 +45,27 @@ class WPSEO_Redirect_Table extends WP_List_Table {
*/
private $primary_column = 'type';
/**
* Caches the WPSEO_Redirect_Types::get() result.
*
* @var string[]
*/
private $redirect_types;
/**
* Holds the orderby.
*
* @var string
*/
private $orderby = 'old';
/**
* Holds the order.
*
* @var string
*/
private $order = 'asc';
/**
* WPSEO_Redirect_Table constructor.
*
@@ -57,6 +78,10 @@ class WPSEO_Redirect_Table extends WP_List_Table {
$this->current_column = $current_column;
// Cache used in filter_items and extra_tablenav.
$wpseo_redirect_types = new WPSEO_Redirect_Types();
$this->redirect_types = $wpseo_redirect_types->get();
$this->set_items( $redirects );
add_filter( 'list_table_primary_column', [ $this, 'redirect_list_table_primary_column' ], 10, 2 );
@@ -74,20 +99,22 @@ class WPSEO_Redirect_Table extends WP_List_Table {
return;
}
$selected = filter_input( INPUT_GET, 'redirect-type' );
if ( ! $selected ) {
$selected = $this->filter['redirect_type'];
if ( $selected === null ) {
$selected = 0;
}
?>
<div class="alignleft actions">
<label for="filter-by-redirect" class="screen-reader-text"><?php esc_html_e( 'Filter by redirect type', 'wordpress-seo-premium' ); ?></label>
<label for="filter-by-redirect" class="screen-reader-text">
<?php
/* translators: Hidden accessibility text. */
esc_html_e( 'Filter by redirect type', 'wordpress-seo-premium' );
?>
</label>
<select name="redirect-type" id="filter-by-redirect">
<option<?php selected( $selected, 0 ); ?> value="0"><?php esc_html_e( 'All redirect types', 'wordpress-seo-premium' ); ?></option>
<?php
$redirect_types = new WPSEO_Redirect_Types();
foreach ( $redirect_types->get() as $http_code => $redirect_type ) {
foreach ( $this->redirect_types as $http_code => $redirect_type ) {
printf(
"<option %s value='%s'>%s</option>\n",
selected( $selected, $http_code, false ),
@@ -163,8 +190,7 @@ class WPSEO_Redirect_Table extends WP_List_Table {
// Set pagination.
$this->set_pagination_args( $pagination_args );
$paged = filter_input( INPUT_GET, 'paged' );
$current_page = (int) ( ( isset( $paged ) && $paged !== false ) ? $paged : 0 );
$current_page = $this->get_pagenum();
// Setting the starting point. If starting point is below 1, overwrite it with value 0, otherwise it will be sliced of at the back.
$slice_start = ( $current_page - 1 );
@@ -201,37 +227,11 @@ class WPSEO_Redirect_Table extends WP_List_Table {
* @return int The order that should be used.
*/
public function do_reorder( $a, $b ) {
// If no sort, default to title.
$orderby = filter_input(
INPUT_GET,
'orderby',
FILTER_VALIDATE_REGEXP,
[
'options' => [
'default' => 'old',
'regexp' => '/^(old|new|type)$/',
],
]
);
// If no order, default to asc.
$order = filter_input(
INPUT_GET,
'order',
FILTER_VALIDATE_REGEXP,
[
'options' => [
'default' => 'asc',
'regexp' => '/^(asc|desc)$/',
],
]
);
// Determine sort order.
$result = strcmp( $a[ $orderby ], $b[ $orderby ] );
$result = strcmp( $a[ $this->orderby ], $b[ $this->orderby ] );
// Send final sort direction to usort.
return ( $order === 'asc' ) ? $result : ( -$result );
return ( $this->order === 'asc' ) ? $result : ( -$result );
}
/**
@@ -246,6 +246,7 @@ class WPSEO_Redirect_Table extends WP_List_Table {
'<label class="screen-reader-text" for="wpseo-redirects-bulk-cb-%2$s">%3$s</label> <input type="checkbox" name="wpseo_redirects_bulk_delete[]" id="wpseo-redirects-bulk-cb-%2$s" value="%1$s" />',
esc_attr( $item['old'] ),
$item['row_number'],
/* translators: Hidden accessibility text. */
esc_html( __( 'Select this redirect', 'wordpress-seo-premium' ) )
);
}
@@ -260,14 +261,15 @@ class WPSEO_Redirect_Table extends WP_List_Table {
*/
public function column_default( $item, $column_name ) {
$is_regex = ( filter_input( INPUT_GET, 'tab' ) === 'regex' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We are not processing form information.
$is_regex = isset( $_GET['tab'] ) && is_string( $_GET['tab'] ) && sanitize_text_field( wp_unslash( $_GET['tab'] ) ) === 'regex';
$row_actions = $this->get_row_actions( $column_name );
switch ( $column_name ) {
case 'new':
$classes = [ 'val' ];
$new_url = $item['new'];
$classes = [ 'val' ];
$new_url = $item['new'];
$new_full_url = home_url( $new_url );
if ( ! $is_regex && WPSEO_Redirect_Util::requires_trailing_slash( $new_url ) ) {
$classes[] = 'has-trailing-slash';
}
@@ -280,15 +282,19 @@ class WPSEO_Redirect_Table extends WP_List_Table {
$classes[] = 'remove-slashes';
}
return "<div class='" . esc_attr( implode( ' ', $classes ) ) . "'>" . esc_html( $new_url ) . '</div>' . $row_actions;
if ( $new_url ) {
return '<a class="' . esc_attr( implode( ' ', $classes ) ) . '" href="' . esc_url( $new_full_url ) . '" target="_blank">' . esc_html( $new_url ) . '</a>' . $row_actions;
}
return '<div class="val remove-slashes"></div>' . $row_actions;
case 'old':
$classes = '';
$classes = '';
$old_full_url = home_url( $item['old'] );
if ( $is_regex === true ) {
$classes = ' remove-slashes';
return '<div class="val remove-slashes">' . esc_html( $item['old'] ) . '</div>' . $row_actions;
}
return "<div class='val" . $classes . "'>" . esc_html( $item['old'] ) . '</div>' . $row_actions;
return '<a class="val' . $classes . '" href="' . esc_url( $old_full_url ) . '" target="_blank">' . esc_html( $item['old'] ) . '</a>' . $row_actions;
case 'type':
return '<div class="val type">' . esc_html( $item['type'] ) . '</div>' . $row_actions;
@@ -324,6 +330,8 @@ class WPSEO_Redirect_Table extends WP_List_Table {
// Sort the results.
if ( count( $this->items ) > 0 ) {
$this->orderby = $this->get_orderby();
$this->order = $this->get_order();
usort( $this->items, [ $this, 'do_reorder' ] );
}
}
@@ -336,15 +344,26 @@ class WPSEO_Redirect_Table extends WP_List_Table {
* @return array The filtered items.
*/
private function filter_items( array $items ) {
$search_string = filter_input( INPUT_GET, 's', FILTER_DEFAULT, [ 'options' => [ 'default' => '' ] ] );
$search_string = '';
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We come from our own redirect in a simple search form, let's not overcomplicate.
if ( isset( $_GET['s'] ) && is_string( $_GET['s'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: Same as above.
$search_string = trim( sanitize_text_field( wp_unslash( $_GET['s'] ) ), '/' );
}
if ( $search_string !== '' ) {
$this->filter['search_string'] = trim( $search_string, '/' );
$this->filter['search_string'] = $search_string;
$items = array_filter( $items, [ $this, 'filter_by_search_string' ] );
}
$redirect_type = (int) filter_input( INPUT_GET, 'redirect-type' );
if ( ! empty( $redirect_type ) ) {
$redirect_type = 0;
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: We come from our own redirect in a simple filter form, let's not overcomplicate.
if ( isset( $_GET['redirect-type'] ) && is_string( $_GET['redirect-type'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: Cast to an integer and strictly compared against known keys.
$redirect_type = (int) wp_unslash( $_GET['redirect-type'] );
$redirect_type = array_key_exists( $redirect_type, $this->redirect_types ) ? $redirect_type : 0;
}
if ( $redirect_type !== 0 ) {
$this->filter['redirect_type'] = $redirect_type;
$items = array_filter( $items, [ $this, 'filter_by_type' ] );
@@ -426,9 +445,46 @@ class WPSEO_Redirect_Table extends WP_List_Table {
* @param object $item The item being acted upon.
* @param string $column_name Current column name.
* @param string $primary Primary column name.
*
* @return string Empty string.
*/
protected function handle_row_actions( $item, $column_name, $primary ) {
return '';
}
/**
* Retrieves the orderby from the request.
*
* @return string The orderby value.
*/
private function get_orderby() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: WP list table is not using a nonce.
if ( isset( $_GET['orderby'] ) && is_string( $_GET['orderby'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: same as above and we are strictly comparing the values.
$orderby = wp_unslash( $_GET['orderby'] );
if ( array_key_exists( $orderby, $this->get_sortable_columns() ) ) {
return $orderby;
}
}
return 'old';
}
/**
* Retrieves the order from the request.
*
* @return string The order value.
*/
private function get_order() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reason: WP list table is not using a nonce.
if ( isset( $_GET['order'] ) && is_string( $_GET['order'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: same as above and we are strictly comparing the values.
$order = wp_unslash( $_GET['order'] );
if ( in_array( $order, [ 'asc', 'desc' ], true ) ) {
return $order;
}
}
return 'asc';
}
}

View File

@@ -30,20 +30,6 @@ class WPSEO_Redirect_Types {
'451' => __( '451 Unavailable For Legal Reasons', 'wordpress-seo-premium' ),
];
/**
* Filter: 'wpseo_premium_redirect_types' - can be used to filter the redirect types.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\redirect_types'} filter instead.
*
* @api array $redirect_types
*/
$redirect_types = apply_filters_deprecated(
'wpseo_premium_redirect_types',
[ $redirect_types ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\redirect_types'
);
/**
* Filter: 'Yoast\WP\SEO\redirect_types' - can be used to filter the redirect types.
*

View File

@@ -66,6 +66,11 @@ class WPSEO_Redirect_Url_Formatter {
* @return string
*/
protected function get_subdirectory( $url ) {
return $this->sanitize_url( wp_parse_url( $url, PHP_URL_PATH ) );
$path = wp_parse_url( $url, PHP_URL_PATH );
if ( is_string( $path ) ) {
return $this->sanitize_url( $path );
}
return '';
}
}

View File

@@ -82,7 +82,7 @@ class WPSEO_Redirect_Util {
public static function has_extension( $url ) {
$parsed = wp_parse_url( $url, PHP_URL_PATH );
return strpos( $parsed, '.' ) !== false;
return ( is_string( $parsed ) && strpos( $parsed, '.' ) !== false );
}
/**
@@ -111,7 +111,9 @@ class WPSEO_Redirect_Util {
*/
public static function strip_base_url_path_from_url( $base_url, $url ) {
$base_url_path = wp_parse_url( $base_url, PHP_URL_PATH );
$base_url_path = ltrim( $base_url_path, '/' );
if ( ! empty( $base_url_path ) ) {
$base_url_path = ltrim( $base_url_path, '/' );
}
if ( empty( $base_url_path ) ) {
return $url;

View File

@@ -119,6 +119,7 @@ class WPSEO_Redirect implements ArrayAccess {
* @return bool True on success or false on failure.
* The return value will be cast to boolean if non-boolean was returned.
*/
#[ReturnTypeWillChange]
public function offsetExists( $offset ) {
return in_array( $offset, [ 'url', 'type' ], true );
}
@@ -132,6 +133,7 @@ class WPSEO_Redirect implements ArrayAccess {
*
* @return mixed Can return all value types.
*/
#[ReturnTypeWillChange]
public function offsetGet( $offset ) {
switch ( $offset ) {
case 'old':
@@ -157,6 +159,7 @@ class WPSEO_Redirect implements ArrayAccess {
*
* @return void
*/
#[ReturnTypeWillChange]
public function offsetSet( $offset, $value ) {
switch ( $offset ) {
case 'url':
@@ -179,6 +182,7 @@ class WPSEO_Redirect implements ArrayAccess {
*
* @return void
*/
#[ReturnTypeWillChange]
public function offsetUnset( $offset ) {
}

View File

@@ -28,7 +28,7 @@ $yoast_seo_quick_edit_table = $view_vars['quick_edit_table'];
printf(
/* translators: 1: opens a link to a related help center article. 2: closes the link. */
esc_html__( 'Regular Expression (regex) Redirects are extremely powerful redirects. You should only use them if you know what you are doing. %1$sRead more about regex redirects on our help center%2$s.', 'wordpress-seo-premium' ),
'<a href="https://yoa.st/3lo" target="_blank">',
'<a href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/3lo' ) ) . '" target="_blank">',
'</a>'
);
?>

View File

@@ -10,6 +10,8 @@
* }
*/
use Yoast\WP\SEO\Presenters\Admin\Alert_Presenter;
$yoast_seo_file_path = $view_vars['file_path'];
$yoast_seo_redirect_file = $view_vars['redirect_file'];
@@ -72,6 +74,20 @@ if ( ! empty( $yoast_seo_redirect_file ) ) {
<div id="table-settings" class="tab-url redirect-table-tab">
<?php echo '<h2>' . esc_html__( 'Redirects settings', 'wordpress-seo-premium' ) . '</h2>'; ?>
<?php
$yoast_seo_disable_toggles = ( ( WPSEO_Options::get( 'disable_php_redirect' ) === 'off' ) && \is_multisite() );
if ( $yoast_seo_disable_toggles ) {
$yoast_seo_disable_htaccess_message = esc_html__( 'Since this site is a multisite, web server redirect methods have been disabled to prevent issues.', 'wordpress-seo-premium' )
. '&nbsp;<a href="https://yoa.st/4k9 ">'
. esc_html__( 'Read more about why web server redirect methods have been disabled on a multisite.', 'wordpress-seo-premium' )
. '</a>';
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in Alert_Presenter.
echo new Alert_Presenter( $yoast_seo_disable_htaccess_message, 'info' );
}
?>
<form action="<?php echo esc_url( admin_url( 'options.php' ) ); ?>" method="post">
<?php
settings_fields( 'yoast_wpseo_redirect_options' );
@@ -84,24 +100,26 @@ if ( ! empty( $yoast_seo_redirect_file ) ) {
'off' => 'PHP',
'on' => ( WPSEO_Utils::is_apache() ) ? '.htaccess' : __( 'Web server', 'wordpress-seo-premium' ),
];
$yoast_seo_form->toggle_switch( 'disable_php_redirect', $yoast_seo_toggle_values, __( 'Redirect method', 'wordpress-seo-premium' ) );
$yoast_seo_form->toggle_switch( 'disable_php_redirect', $yoast_seo_toggle_values, __( 'Redirect method', 'wordpress-seo-premium' ), '', [ 'disabled' => $yoast_seo_disable_toggles ] );
$yoast_seo_opening_p = ( $yoast_seo_disable_toggles ) ? '<p class="redirect_htaccess_disabled">' : '<p>';
if ( WPSEO_Utils::is_apache() ) {
/* translators: 1: '.htaccess' file name */
echo '<p>' . sprintf( esc_html__( 'Write redirects to the %1$s file. Make sure the %1$s file is writable.', 'wordpress-seo-premium' ), '<code>.htaccess</code>' ) . '</p>';
echo $yoast_seo_opening_p . sprintf( esc_html__( 'Write redirects to the %1$s file. Make sure the %1$s file is writable.', 'wordpress-seo-premium' ), '<code>.htaccess</code>' ) . '</p>';
$yoast_seo_form->light_switch( 'separate_file', __( 'Generate a separate redirect file', 'wordpress-seo-premium' ) );
$yoast_seo_form->light_switch( 'separate_file', __( 'Generate a separate redirect file', 'wordpress-seo-premium' ), [], true, '', false, [ 'disabled' => $yoast_seo_disable_toggles ] );
/* translators: %s: '.htaccess' file name */
echo '<p>' . sprintf( esc_html__( 'By default we write the redirects to your %s file, check this if you want the redirects written to a separate file. Only check this option if you know what you are doing!', 'wordpress-seo-premium' ), '<code>.htaccess</code>' ) . '</p>';
echo $yoast_seo_opening_p . sprintf( esc_html__( 'By default we write the redirects to your %s file, check this if you want the redirects written to a separate file. Only check this option if you know what you are doing!', 'wordpress-seo-premium' ), '<code>.htaccess</code>' ) . '</p>';
}
else {
/* translators: %s: 'Yoast SEO Premium' */
echo '<p>' . sprintf( esc_html__( '%s can generate redirect files that can be included in your website web server configuration. If you choose this option the PHP redirects will be disabled. Only check this option if you know what you are doing!', 'wordpress-seo-premium' ), 'Yoast SEO Premium' ) . '</p>';
echo $yoast_seo_opening_p . sprintf( esc_html__( '%s can generate redirect files that can be included in your website web server configuration. If you choose this option the PHP redirects will be disabled. Only check this option if you know what you are doing!', 'wordpress-seo-premium' ), 'Yoast SEO Premium' ) . '</p>';
}
?>
<p class="submit">
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php esc_html_e( 'Save Changes', 'wordpress-seo-premium' ); ?>" />
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php esc_attr_e( 'Save Changes', 'wordpress-seo-premium' ); ?>" />
</p>
</form>
</div>

View File

@@ -10,24 +10,24 @@
?>
<h2 class="nav-tab-wrapper" id="wpseo-tabs">
<?php
foreach ( $redirect_tabs['tabs'] as $yoast_seo_tab_url => $yoast_seo_tab_value ) :
foreach ( $redirect_tabs['tabs'] as $yoast_seo_tab_url => $yoast_seo_tab_value ) {
$yoast_seo_active = '';
if ( $redirect_tabs['current_tab'] === $yoast_seo_tab_url ) {
$yoast_seo_active = ' nav-tab-active';
}
echo '<a class="nav-tab' . esc_attr( $yoast_seo_active ) . '" id="tab-url-tab" href="' . esc_url( $redirect_tabs['page_url'] . $yoast_seo_tab_url ) . '">' . esc_html( $yoast_seo_tab_value ) . '</a>';
endforeach;
}
?>
</h2>
<?php
if ( ! empty( $tab_presenter ) ) :
if ( ! empty( $tab_presenter ) ) {
$tab_presenter->display(
[
'nonce' => wp_create_nonce( 'wpseo-redirects-ajax-security' ),
]
);
endif;
}
?>
<br class="clear">

View File

@@ -31,35 +31,4 @@ class WPSEO_Social_Previews implements WPSEO_WordPress_Integration {
public function enqueue_assets() {
wp_enqueue_script( 'yoast-social-metadata-previews' );
}
/* ********************* DEPRECATED FUNCTIONS ********************* */
/**
* Retrieves image data from an image URL.
*
* @deprecated 14.4
*
* @codeCoverageIgnore
*/
public function ajax_retrieve_image_data_from_url() {
_deprecated_function( __METHOD__, '14.5' );
}
/**
* Determines an attachment ID from a URL which might be an attachment URL.
*
* @deprecated 14.4
*
* @codeCoverageIgnore
*
* @link https://philipnewcomer.net/2012/11/get-the-attachment-id-from-an-image-url-in-wordpress/
*
* @param string $url The URL to retrieve the attachment ID for.
*
* @return bool|int The attachment ID or false.
*/
public function retrieve_image_id_from_url( $url ) {
_deprecated_function( __METHOD__, '14.5' );
return false;
}
}

View File

@@ -102,6 +102,8 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* Set old URL when the quick edit is used for taxonomies.
*/
public function set_old_url_quick_edit() {
check_ajax_referer( 'taxinlineeditnonce', '_inline_edit' );
$permalink = $this->get_taxonomy_permalink();
if ( ! is_wp_error( $permalink ) ) {
@@ -119,21 +121,6 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* @return bool
*/
public function detect_slug_change( $term_id, $tt_id, $taxonomy ) {
/**
* Filter: 'wpseo_premium_term_redirect_slug_change' - Check if a redirect should be created
* on term slug change.
*
* @deprecated 12.9.0. Use the {@see 'Yoast\WP\SEO\term_redirect_slug_change'} filter instead.
*
* @api bool unsigned
*/
$create_redirect = apply_filters_deprecated(
'wpseo_premium_term_redirect_slug_change',
[ false ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\term_redirect_slug_change'
);
/**
* Filter: 'Yoast\WP\SEO\term_redirect_slug_change' - Check if a redirect should be created
* on term slug change.
@@ -144,7 +131,7 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
*
* @api bool unsigned
*/
if ( apply_filters( 'Yoast\WP\SEO\term_redirect_slug_change', $create_redirect ) === true ) {
if ( apply_filters( 'Yoast\WP\SEO\term_redirect_slug_change', false ) === true ) {
return true;
}
@@ -184,18 +171,17 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
/**
* Offer to create a redirect from the term that is about to get deleted.
*
* @param int $term_id The term id that will be deleted.
* @param int $term_taxonomy_id The term taxonomy id that will be deleted.
*/
public function detect_term_delete( $term_id ) {
$term = \get_term( $term_id );
public function detect_term_delete( $term_taxonomy_id ) {
$term = \get_term_by( 'term_taxonomy_id', (int) $term_taxonomy_id );
if ( ! $term || is_wp_error( $term ) ) {
return;
}
if ( $this->is_redirect_needed( $term ) ) {
$url = $this->get_target_url( $term, $term->taxonomy );
$url = $this->get_target_url( $term, $term->taxonomy );
if ( $this->is_redirect_needed( $term, $url ) ) {
$this->set_delete_notification( $url );
}
}
@@ -204,11 +190,14 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* Checks if a redirect is needed for the term with the given ID.
*
* @param WP_Term $term The term to check.
* @param string $url The target url.
*
* @return bool If a redirect is needed.
*/
protected function is_redirect_needed( $term ) {
return ! \is_nav_menu( $term->term_id ) && \is_taxonomy_viewable( $term->taxonomy );
protected function is_redirect_needed( $term, $url ) {
$redirect_manager = new WPSEO_Redirect_Manager( 'plain' );
$redirect = $redirect_manager->get_redirect( $url );
return ! $redirect || ( ! \is_nav_menu( $term->term_id ) && \is_taxonomy_viewable( $term->taxonomy ) );
}
/**
@@ -226,7 +215,7 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
}
/**
* Get the URL to the term and returns it's path.
* Gets the URL to the term and returns its path.
*
* @param string $tag The current tag name.
* @param string $taxonomy The name of the current taxonomy.
@@ -234,8 +223,16 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* @return string
*/
protected function get_target_url( $tag, $taxonomy ) {
// Get the term link.
$term_link = get_term_link( $tag, $taxonomy );
// Return early if the term link is not a string, i.e. a WP_Error Object.
if ( ! is_string( $term_link ) ) {
return '';
}
// Use the correct URL path.
$url = wp_parse_url( get_term_link( $tag, $taxonomy ) );
$url = wp_parse_url( $term_link );
if ( is_array( $url ) && isset( $url['path'] ) ) {
return $url['path'];
}
@@ -249,7 +246,13 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* @return string|WP_Error
*/
protected function get_taxonomy_permalink() {
return get_term_link( get_term( filter_input( INPUT_POST, 'tax_ID' ), filter_input( INPUT_POST, 'taxonomy' ) ), filter_input( INPUT_POST, 'taxonomy' ) );
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Reason: We verify the nonce before coming here.
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We do sanitize by casting to int.
$term_id = isset( $_POST['tax_ID'] ) ? (int) wp_unslash( $_POST['tax_ID'] ) : 0;
$taxonomy = isset( $_POST['taxonomy'] ) ? sanitize_text_field( wp_unslash( $_POST['taxonomy'] ) ) : null;
// phpcs:enable
return get_term_link( get_term( $term_id, $taxonomy ), $taxonomy );
}
/**
@@ -258,7 +261,10 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* @return bool|string
*/
protected function get_old_url() {
$wpseo_old_term_url = filter_input( INPUT_POST, 'wpseo_old_term_url' );
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Reason: This is used while hooked in an action thus we don't control the nonce creation.
// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: This data looks like it's being used only with WP functions later on.
$wpseo_old_term_url = isset( $_POST['wpseo_old_term_url'] ) ? wp_unslash( $_POST['wpseo_old_term_url'] ) : null;
// phpcs:enable
if ( empty( $wpseo_old_term_url ) ) {
if ( ! empty( $this->old_url ) ) {
@@ -324,7 +330,13 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* @return bool True when in an AJAX-request and the action is inline-save.
*/
protected function is_action_inline_save_tax() {
return ( wp_doing_ajax() && filter_input( INPUT_POST, 'action' ) === 'inline-save-tax' );
if ( ! wp_doing_ajax() ) {
return false;
}
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: We don't control the nonce creation.
$action = isset( $_POST['action'] ) ? sanitize_text_field( wp_unslash( $_POST['action'] ) ) : null;
return $action === 'inline-save-tax';
}
/**
@@ -333,6 +345,12 @@ class WPSEO_Term_Watcher extends WPSEO_Watcher implements WPSEO_WordPress_Integr
* @return bool True when in an AJAX-request and the action is delete-tag.
*/
protected function is_action_delete_tag() {
return ( wp_doing_ajax() && filter_input( INPUT_POST, 'action' ) === 'delete-tag' );
if ( ! wp_doing_ajax() ) {
return false;
}
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Reason: We don't control the nonce creation.
$action = isset( $_POST['action'] ) ? sanitize_text_field( wp_unslash( $_POST['action'] ) ) : null;
return $action === 'delete-tag';
}
}

View File

@@ -98,6 +98,103 @@ class WPSEO_Upgrade_Manager {
if ( version_compare( $version_number, '16.3-beta2', '<' ) ) {
add_action( 'init', [ $this, 'upgrade_16_3' ], 12 );
}
if ( version_compare( $version_number, '17.2-RC0', '<' ) ) {
add_action( 'init', [ $this, 'upgrade_17_2' ], 12 );
}
if ( version_compare( $version_number, '17.3-RC4', '<' ) ) {
add_action( 'init', [ $this, 'upgrade_17_3' ], 12 );
}
if ( version_compare( $version_number, '17.4-RC0', '<' ) ) {
add_action( 'init', [ $this, 'upgrade_17_4' ], 12 );
}
if ( version_compare( $version_number, '17.7-RC0', '<' ) ) {
add_action( 'init', [ $this, 'upgrade_17_7' ], 12 );
}
if ( version_compare( $version_number, '19.3-RC0', '<' ) ) {
add_action( 'init', [ $this, 'upgrade_19_3' ], 12 );
}
}
/**
* Removes the inclusive language feature notification from the Notification center.
*
* @return void
*/
public function upgrade_19_3() {
Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-inclusive-language-notice' );
}
/**
* Make sure our options autoload.
*
* @return void
*/
public function upgrade_17_7() {
global $wpdb;
foreach ( [ WPSEO_Redirect_Option::OPTION_PLAIN, WPSEO_Redirect_Option::OPTION_REGEX ] as $option ) {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery -- Normal methods only work if the option value has changed.
$wpdb->update( $wpdb->options, [ 'autoload' => 'yes' ], [ 'option_name' => $option ] );
}
// Make sure we don't autoload the non-exported option.
$wpdb->update( $wpdb->options, [ 'autoload' => 'no' ], [ 'option_name' => WPSEO_Redirect_Option::OPTION ] );
}
/**
* Schedules the cleanup integration if it's no already scheduled.
*
* @return void
*/
public function upgrade_17_4() {
$this->retrigger_cleanup();
}
/**
* Clears the first step of the orphaned workout.
*
* @return void
*/
public function upgrade_17_3() {
$workouts_option = WPSEO_Options::get( 'workouts' );
if ( isset( $workouts_option['orphaned'] )
&& isset( $workouts_option['orphaned']['indexablesByStep'] )
&& is_array( $workouts_option['orphaned']['indexablesByStep'] )
) {
$workouts_option['orphaned']['indexablesByStep']['improveRemove'] = [];
WPSEO_Options::set( 'workouts', $workouts_option );
}
}
/**
* Schedules the cleanup integration if it's no already scheduled.
*
* @return void
*/
public function upgrade_17_2() {
$this->retrigger_cleanup();
}
/**
* Re-triggers the cleanup of old things from the database.
*
* @return void
*/
protected function retrigger_cleanup() {
// If Yoast SEO hasn't been upgraded to 17.2 the cleanup integration has not been implemented in the current way.
if ( ! \defined( '\Yoast\WP\SEO\Integrations\Cleanup_Integration::START_HOOK' ) ) {
return;
}
// If Yoast SEO premium was upgraded after Yoast SEO, reschedule the task to clean out orphaned prominent words.
if ( ! \wp_next_scheduled( \Yoast\WP\SEO\Integrations\Cleanup_Integration::START_HOOK ) ) {
\wp_schedule_single_event( ( time() + ( MINUTE_IN_SECONDS * 5 ) ), \Yoast\WP\SEO\Integrations\Cleanup_Integration::START_HOOK );
}
}
/**
@@ -200,6 +297,7 @@ class WPSEO_Upgrade_Manager {
if ( $this->should_retry_upgrade_31() ) {
if ( $immediately ) {
WPSEO_Redirect_Upgrade::upgrade_3_1();
return;
}
add_action( 'wp', [ 'WPSEO_Redirect_Upgrade', 'upgrade_3_1' ], 12 );

View File

@@ -69,7 +69,12 @@ $yoast_seo_plugins = [
</p>
<form action="" method="post" accept-charset="<?php echo esc_attr( get_bloginfo( 'charset' ) ); ?>">
<?php wp_nonce_field( 'wpseo-import', '_wpnonce', true ); ?>
<label for="htaccess" class="screen-reader-text"><?php esc_html_e( 'Enter redirects to import', 'wordpress-seo-premium' ); ?></label>
<label for="htaccess" class="screen-reader-text">
<?php
/* translators: Hidden accessibility text. */
esc_html_e( 'Enter redirects to import', 'wordpress-seo-premium' );
?>
</label>
<textarea name="htaccess" id="htaccess" rows="15" class="large-text code"></textarea><br/>
<input type="submit" class="button button-primary" name="import" value="<?php esc_attr_e( 'Import .htaccess', 'wordpress-seo-premium' ); ?>"/>
</form>

View File

@@ -0,0 +1,107 @@
<?php
/**
* WPSEO Premium plugin file.
*
* @package WPSEO\Premium\Views
*/
?>
<img class="yoast-image" src="https://yoast.com/app/uploads/2021/06/premium_assistant_bubble.png" />
<h1><?php esc_html_e( 'Installation successful!', 'wordpress-seo-premium' ); ?></h1>
<p class="yoast-whats-next">
<?php esc_html_e( 'So, what\'s next?', 'wordpress-seo-premium' ); ?>
</p>
<div class="yoast-grid yoast">
<div>
<h3>
<?php esc_html_e( 'Rank with articles you want to rank with', 'wordpress-seo-premium' ); ?>
</h3>
<img width="256px" height="196px" src="https://yoast.com/shared-assets/images/wpseo_installation_successful/16-6/cornerstone.png" alt="Cornerstone" />
<p>
<?php
echo sprintf(
/* translators: %1$s: <strong>, %2$s: </strong> */
esc_html__(
'%1$sCornerstone content%2$s is the content on your site thats most important. You want to rank highest in Google with these articles. Make sure your internal linking structure reflects what pages are most important. Want to know how?',
'wordpress-seo-premium'
),
'<strong>',
'</strong>'
);
?>
</p>
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wpseo_workouts' ) ); ?>" class="yoast-button yoast-button--secondary" target="_blank">
<?php esc_html_e( 'Do the cornerstone workout!', 'wordpress-seo-premium' ); ?>
</a>
</div>
<div>
<h3>
<?php esc_html_e( 'Optimize your content further with our smart analysis', 'wordpress-seo-premium' ); ?>
</h3>
<img width="256px" height="196px" src="https://yoast.com/shared-assets/images/wpseo_installation_successful/16-6/analysis.png" alt="Analysis" />
<p>
<?php
echo sprintf(
/* translators: %1$s: <strong>, %2$s: </strong> */
esc_html__(
'Different people search with different search terms. With our %1$spremium analysis%2$s, you are free to use variations and synonyms of your keywords in your content, which will make your writing style far more natural.',
'wordpress-seo-premium'
),
'<strong>',
'</strong>'
);
?>
</p>
<a href="<?php echo esc_url( admin_url( 'edit.php?post_status=publish&post_type=post&seo_filter=na' ) ); ?>" class="yoast-button yoast-button--secondary" target="_blank">
<?php esc_html_e( 'Score some more green bullets', 'wordpress-seo-premium' ); ?>
</a>
</div>
<div>
<h3>
<?php esc_html_e( 'Keep your site well-organised so people won\'t get lost', 'wordpress-seo-premium' ); ?>
</h3>
<img width="256px" height="196px" src="https://yoast.com/shared-assets/images/wpseo_installation_successful/16-6/redirect-manager.png" alt="redirect-manager" />
<p>
<?php
echo sprintf(
/* translators: %1$s: Yoast SEO, %2$s: <strong>, %3$s: </strong> */
esc_html__(
'The %1$s %2$sRedirect Manager%3$s automatically prevents visitors from reaching a dead end whenever you move or delete content. It also makes managing your existing redirects easy.',
'wordpress-seo-premium'
),
'Yoast SEO',
'<strong>',
'</strong>'
);
?>
</p>
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wpseo_redirects' ) ); ?>" class="yoast-button yoast-button--secondary" target="_blank">
<?php esc_html_e( 'Check out the Redirect Manager', 'wordpress-seo-premium' ); ?>
</a>
</div>
<div>
<h3>
<?php esc_html_e( 'Master vital SEO skills with our online courses', 'wordpress-seo-premium' ); ?>
</h3>
<img width="256px" height="196px" src="https://yoast.com/shared-assets/images/wpseo_installation_successful/16-6/academy.png" alt="Academy" />
<p>
<?php
echo sprintf(
/* translators: %1$s: Yoast SEO Premium, %2$s: <strong>, %3$s: Yoast SEO, %4$s: </strong> */
esc_html__(
'%1$s grants you direct access to %2$sall premium %3$s academy courses%4$s. Learn all the ins and outs of holistic SEO from industry experts.',
'wordpress-seo-premium'
),
'Yoast SEO Premium',
'<strong>',
'Yoast SEO',
'</strong>'
);
?>
</p>
<a href="<?php echo esc_url( add_query_arg( [ 'screen' => 'wpseo_installation_successful' ], esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/4em' ) ) ) ); ?>" class="yoast-button yoast-button--secondary" target="_blank">
<?php esc_html_e( 'Browse our courses', 'wordpress-seo-premium' ); ?>
</a>
</div>
</div>

View File

@@ -78,32 +78,19 @@ abstract class WPSEO_Watcher {
$show_notification = true;
/**
* Filter: "wpseo_enable_notification_{$watch_type}_{$notification_type}" - Filter whether or not the
* notification for a given watch type and notification type should be shown.
*
* @deprecated 12.9.0. Use the {@see "Yoast\WP\SEO\enable_notification_{$watch_type}_{$notification_type}"} filter instead.
*
* @api bool $show_notification Defaults to true.
*/
$show_notification = apply_filters_deprecated(
'wpseo_enable_notification_' . $this->watch_type . '_' . $notification_type,
[ $show_notification ],
'YoastSEO Premium 12.9.0',
'Yoast\WP\SEO\enable_notification_{$watch_type}_{$notification_type}'
);
/**
* Filter: "Yoast\WP\SEO\enable_notification_{$watch_type}_{$notification_type}" - Filter whether or
* Filter: 'Yoast\WP\SEO\enable_notification_{$watch_type}_{$notification_type}' - Filter whether or
* not the notification for a given watch type and notification type should be shown.
*
* Note: This is a Premium plugin-only hook.
*
* @since 12.9.0
* @since 16.5
*
* @see https://developer.yoast.com/customization/yoast-seo-premium/disabling-automatic-redirects-notifications
*
* @api bool $show_notification Defaults to true.
*/
$show_notification = apply_filters(
"Yoast\WP\SEO\enable_notification_{$this->watch_type}_{$notification_type}",
'Yoast\WP\SEO\enable_notification_' . $this->watch_type . '_' . $notification_type,
$show_notification
);
@@ -270,7 +257,7 @@ abstract class WPSEO_Watcher {
* @param string $url The URL that will be redirected.
* @param string $id The ID of the element.
*
* @return string.
* @return string
*/
protected function get_delete_action_list( $url, $id ) {
return sprintf(