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:
@@ -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 ) )
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 ),
|
||||
|
||||
@@ -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'] );
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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' ],
|
||||
|
||||
|
||||
@@ -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' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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' )
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 “%s”', '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 “%s”', '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 “%s”', '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}" );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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">—</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">—</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.
|
||||
*
|
||||
|
||||
@@ -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 '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>';
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>';
|
||||
|
||||
@@ -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 = '';
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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. We’ve 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>'
|
||||
);
|
||||
|
||||
|
||||
@@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
|
||||
@@ -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' )
|
||||
),
|
||||
];
|
||||
|
||||
@@ -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 ] );
|
||||
}
|
||||
|
||||
|
||||
@@ -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'];
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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( ' & ', $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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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' ],
|
||||
|
||||
@@ -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'] )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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', '==' );
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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>';
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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' );
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
15
wp/wp-content/plugins/wordpress-seo-premium/vendor/yoast/wordpress-seo/admin/pages/redirects.php
vendored
Normal file
15
wp/wp-content/plugins/wordpress-seo-premium/vendor/yoast/wordpress-seo/admin/pages/redirects.php
vendored
Normal 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';
|
||||
@@ -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>';
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -72,6 +72,13 @@ class WPSEO_Taxonomy_Fields {
|
||||
'options' => '',
|
||||
'hide' => false,
|
||||
],
|
||||
'inclusive_language_score' => [
|
||||
'label' => '',
|
||||
'description' => '',
|
||||
'type' => 'hidden',
|
||||
'options' => '',
|
||||
'hide' => false,
|
||||
],
|
||||
'focuskw' => [
|
||||
'label' => '',
|
||||
'description' => '',
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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 ),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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. You’ll see what words you use most often and if they’re 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 you’re 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,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 site’s 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,
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>',
|
||||
|
||||
@@ -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;
|
||||
|
||||
237
wp/wp-content/plugins/wordpress-seo-premium/vendor/yoast/wordpress-seo/admin/views/redirects.php
vendored
Normal file
237
wp/wp-content/plugins/wordpress-seo-premium/vendor/yoast/wordpress-seo/admin/views/redirects.php
vendored
Normal 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"> </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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>';
|
||||
@@ -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.'
|
||||
);
|
||||
|
||||
@@ -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' );
|
||||
@@ -7,6 +7,9 @@
|
||||
* @uses Yoast_Form $yform Form object.
|
||||
*/
|
||||
|
||||
use Yoast\WP\SEO\Presenters\Admin\Beta_Badge_Presenter;
|
||||
use Yoast\WP\SEO\Presenters\Admin\Premium_Badge_Presenter;
|
||||
|
||||
if ( ! defined( 'WPSEO_VERSION' ) ) {
|
||||
header( 'Status: 403 Forbidden' );
|
||||
header( 'HTTP/1.1 403 Forbidden' );
|
||||
@@ -26,34 +29,80 @@ $feature_toggles = Yoast_Feature_Toggles::instance()->get_all();
|
||||
);
|
||||
|
||||
foreach ( $feature_toggles as $feature ) {
|
||||
$is_premium = YoastSEO()->helpers->product->is_premium();
|
||||
$premium_version = YoastSEO()->helpers->product->get_premium_version();
|
||||
|
||||
if ( $feature->premium && $feature->premium_version ) {
|
||||
$not_supported_in_current_premium_version = $is_premium && \version_compare( $premium_version, $feature->premium_version, '<' );
|
||||
|
||||
if ( $not_supported_in_current_premium_version ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$help_text = esc_html( $feature->label );
|
||||
if ( ! empty( $feature->extra ) ) {
|
||||
$help_text .= ' ' . $feature->extra;
|
||||
}
|
||||
if ( ! empty( $feature->read_more_label ) ) {
|
||||
$help_text .= ' ';
|
||||
$url = $feature->read_more_url;
|
||||
if ( ! empty( $feature->premium ) && $feature->premium === true ) {
|
||||
$url = $feature->premium_url;
|
||||
}
|
||||
$help_text .= sprintf(
|
||||
'<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s</a>',
|
||||
esc_url( WPSEO_Shortlinker::get( $feature->read_more_url ) ),
|
||||
esc_url( WPSEO_Shortlinker::get( $url ) ),
|
||||
esc_html( $feature->read_more_label )
|
||||
);
|
||||
}
|
||||
|
||||
$feature_help = new WPSEO_Admin_Help_Panel(
|
||||
WPSEO_Option::ALLOW_KEY_PREFIX . $feature->setting,
|
||||
/* translators: %s expands to a feature's name */
|
||||
/* translators: Hidden accessibility text; %s expands to a feature's name. */
|
||||
sprintf( esc_html__( 'Help on: %s', 'wordpress-seo' ), esc_html( $feature->name ) ),
|
||||
$help_text
|
||||
);
|
||||
|
||||
$name = $feature->name;
|
||||
if ( ! empty( $feature->premium ) && $feature->premium === true ) {
|
||||
$name .= ' ' . new Premium_Badge_Presenter( $feature->name );
|
||||
}
|
||||
|
||||
if ( ! empty( $feature->in_beta ) && $feature->in_beta === true ) {
|
||||
$name .= ' ' . new Beta_Badge_Presenter( $feature->name );
|
||||
}
|
||||
|
||||
$disabled = false;
|
||||
$show_premium_upsell = false;
|
||||
$premium_upsell_url = '';
|
||||
$note_when_disabled = '';
|
||||
|
||||
if ( $feature->premium === true && YoastSEO()->helpers->product->is_premium() === false ) {
|
||||
$disabled = true;
|
||||
$show_premium_upsell = true;
|
||||
$premium_upsell_url = WPSEO_Shortlinker::get( $feature->premium_upsell_url );
|
||||
}
|
||||
|
||||
$preserve_disabled_value = false;
|
||||
if ( $disabled ) {
|
||||
$preserve_disabled_value = true;
|
||||
}
|
||||
|
||||
$yform->toggle_switch(
|
||||
WPSEO_Option::ALLOW_KEY_PREFIX . $feature->setting,
|
||||
[
|
||||
'on' => __( 'Allow Control', 'wordpress-seo' ),
|
||||
'off' => __( 'Disable', 'wordpress-seo' ),
|
||||
],
|
||||
'<strong>' . $feature->name . '</strong>',
|
||||
$feature_help->get_button_html() . $feature_help->get_panel_html()
|
||||
$name,
|
||||
$feature_help->get_button_html() . $feature_help->get_panel_html(),
|
||||
[
|
||||
'disabled' => $disabled,
|
||||
'preserve_disabled_value' => $preserve_disabled_value,
|
||||
'show_premium_upsell' => $show_premium_upsell,
|
||||
'premium_upsell_url' => $premium_upsell_url,
|
||||
'note_when_disabled' => $note_when_disabled,
|
||||
]
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
* @uses Yoast_Form $yform Form object.
|
||||
*/
|
||||
|
||||
use Yoast\WP\SEO\Presenters\Admin\Badge_Presenter;
|
||||
use Yoast\WP\SEO\Presenters\Admin\Premium_Badge_Presenter;
|
||||
|
||||
if ( ! defined( 'WPSEO_VERSION' ) ) {
|
||||
header( 'Status: 403 Forbidden' );
|
||||
header( 'HTTP/1.1 403 Forbidden' );
|
||||
@@ -43,20 +46,52 @@ $integration_toggles = Yoast_Integration_Toggles::instance()->get_all();
|
||||
|
||||
$feature_help = new WPSEO_Admin_Help_Panel(
|
||||
WPSEO_Option::ALLOW_KEY_PREFIX . $integration->setting,
|
||||
/* translators: %s expands to an integration's name */
|
||||
/* translators: Hidden accessibility text; %s expands to an integration's name. */
|
||||
sprintf( esc_html__( 'Help on: %s', 'wordpress-seo' ), esc_html( $integration->name ) ),
|
||||
$help_text
|
||||
);
|
||||
|
||||
$name = $integration->name;
|
||||
if ( ! empty( $integration->premium ) && $integration->premium === true ) {
|
||||
$name .= ' ' . new Premium_Badge_Presenter( $integration->name );
|
||||
}
|
||||
|
||||
if ( ! empty( $integration->new ) && $integration->new === true ) {
|
||||
$name .= ' ' . new Badge_Presenter( $integration->name );
|
||||
}
|
||||
|
||||
$disabled = $integration->disabled;
|
||||
$show_premium_upsell = false;
|
||||
$premium_upsell_url = '';
|
||||
|
||||
if ( $integration->premium === true && YoastSEO()->helpers->product->is_premium() === false ) {
|
||||
$disabled = true;
|
||||
$show_premium_upsell = true;
|
||||
$premium_upsell_url = WPSEO_Shortlinker::get( $integration->premium_upsell_url );
|
||||
}
|
||||
|
||||
$preserve_disabled_value = false;
|
||||
if ( $disabled ) {
|
||||
$preserve_disabled_value = true;
|
||||
}
|
||||
|
||||
$yform->toggle_switch(
|
||||
WPSEO_Option::ALLOW_KEY_PREFIX . $integration->setting,
|
||||
[
|
||||
'on' => __( 'Allow Control', 'wordpress-seo' ),
|
||||
'off' => __( 'Disable', 'wordpress-seo' ),
|
||||
],
|
||||
'<strong>' . $integration->name . '</strong>',
|
||||
$feature_help->get_button_html() . $feature_help->get_panel_html()
|
||||
$name,
|
||||
$feature_help->get_button_html() . $feature_help->get_panel_html(),
|
||||
[
|
||||
'disabled' => $disabled,
|
||||
'preserve_disabled_value' => $preserve_disabled_value,
|
||||
'show_premium_upsell' => $show_premium_upsell,
|
||||
'premium_upsell_url' => $premium_upsell_url,
|
||||
]
|
||||
);
|
||||
|
||||
do_action( 'Yoast\WP\SEO\admin_network_integration_after', $integration );
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
@@ -60,7 +60,7 @@ function wpseo_import_external_select( $name, $plugins ) {
|
||||
|
||||
<div class="tab-block">
|
||||
<h3><?php esc_html_e( 'Step 2: Import', 'wordpress-seo' ); ?></h3>
|
||||
<p>
|
||||
<p class="yoast-import-explanation">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: 1: expands to Yoast SEO */
|
||||
@@ -76,7 +76,25 @@ function wpseo_import_external_select( $name, $plugins ) {
|
||||
wpseo_import_external_select( 'import_external_plugin', $import_check->needs_import );
|
||||
?>
|
||||
<?php
|
||||
do_action( 'wpseo_import_other_plugins' );
|
||||
|
||||
/**
|
||||
* 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_import_other_plugins_internal' );
|
||||
|
||||
/**
|
||||
* Hook used to import other plugins.
|
||||
*
|
||||
* @deprecated 19.10 No replacement available.
|
||||
*/
|
||||
do_action_deprecated(
|
||||
'wpseo_import_other_plugins',
|
||||
[],
|
||||
'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.'
|
||||
);
|
||||
?>
|
||||
<input type="submit" class="button button-primary" name="import_external"
|
||||
value="<?php esc_attr_e( 'Import', 'wordpress-seo' ); ?>"/>
|
||||
@@ -91,12 +109,13 @@ function wpseo_import_external_select( $name, $plugins ) {
|
||||
</div>
|
||||
|
||||
<div class="tab-block">
|
||||
<h3><?php esc_html_e( 'Step 4: Run the configuration wizard', 'wordpress-seo' ); ?></h3>
|
||||
<h3><?php esc_html_e( 'Step 4: Go through the first time configuration', 'wordpress-seo' ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
esc_html__( 'You should run the configuration wizard, from the SEO → General → Dashboard page, to make sure all the settings for your site are correct.', 'wordpress-seo' ),
|
||||
'<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_dashboard' ) ) . '">',
|
||||
/* translators: 1: Link start tag to the First time configuration tab in the General page, 2: Link closing tag. */
|
||||
esc_html__( 'You should finish the %1$sfirst time configuration%2$s to make sure your SEO data has been optimized and you’ve set the essential Yoast SEO settings for your site.', 'wordpress-seo' ),
|
||||
'<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_dashboard#top#first-time-configuration' ) ) . '">',
|
||||
'</a>'
|
||||
);
|
||||
?>
|
||||
@@ -105,7 +124,7 @@ function wpseo_import_external_select( $name, $plugins ) {
|
||||
|
||||
<div class="tab-block">
|
||||
<h3><?php esc_html_e( 'Step 5: Clean up', 'wordpress-seo' ); ?></h3>
|
||||
<p>
|
||||
<p class="yoast-cleanup-explanation">
|
||||
<?php esc_html_e( 'Once you\'re certain your site is OK, you can clean up. This will remove all the original data.', 'wordpress-seo' ); ?>
|
||||
</p>
|
||||
<form action="<?php echo esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=import-export#top#import-seo' ) ); ?>"
|
||||
|
||||
@@ -14,7 +14,8 @@ if ( ! defined( 'WPSEO_VERSION' ) ) {
|
||||
/* translators: %1$s expands to Yoast SEO */
|
||||
$submit_button_value = sprintf( __( 'Export your %1$s settings', 'wordpress-seo' ), 'Yoast SEO' );
|
||||
|
||||
if ( filter_input( INPUT_POST, 'do_export' ) ) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: The nonce will be verified in WPSEO_Export below, We are only strictly comparing with '1'.
|
||||
if ( isset( $_POST['do_export'] ) && wp_unslash( $_POST['do_export'] ) === '1' ) {
|
||||
$export = new WPSEO_Export();
|
||||
$export->export();
|
||||
return;
|
||||
|
||||
@@ -20,29 +20,30 @@ $yoast_seo_import = false;
|
||||
* In case of POST the user is on the Yoast SEO import page and in case of the GET the user sees a notice from
|
||||
* Yoast SEO that we can import stuff for that plugin.
|
||||
*/
|
||||
if ( filter_input( INPUT_POST, 'import' ) || filter_input( INPUT_GET, 'import' ) ) {
|
||||
check_admin_referer( 'wpseo-import' );
|
||||
|
||||
$yoast_seo_post_wpseo = filter_input( INPUT_POST, 'wpseo', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
|
||||
$yoast_seo_action = 'import';
|
||||
}
|
||||
elseif ( filter_input( INPUT_POST, 'import_external' ) ) {
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are only comparing the variable so no need to sanitize.
|
||||
if ( isset( $_POST['import_external'] ) && wp_unslash( $_POST['import_external'] ) === 'Import' ) {
|
||||
check_admin_referer( 'wpseo-import-plugins' );
|
||||
|
||||
$yoast_seo_class = filter_input( INPUT_POST, 'import_external_plugin' );
|
||||
if ( class_exists( $yoast_seo_class ) ) {
|
||||
$yoast_seo_import = new WPSEO_Import_Plugin( new $yoast_seo_class(), 'import' );
|
||||
if ( isset( $_POST['import_external_plugin'] ) && is_string( $_POST['import_external_plugin'] ) ) {
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are using the variable as a class name.
|
||||
$yoast_seo_class = wp_unslash( $_POST['import_external_plugin'] );
|
||||
if ( class_exists( $yoast_seo_class ) ) {
|
||||
$yoast_seo_import = new WPSEO_Import_Plugin( new $yoast_seo_class(), 'import' );
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ( filter_input( INPUT_POST, 'clean_external' ) ) {
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are only comparing the variable so no need to sanitize.
|
||||
elseif ( isset( $_POST['clean_external'] ) && wp_unslash( $_POST['clean_external'] ) === 'Clean up' ) {
|
||||
check_admin_referer( 'wpseo-clean-plugins' );
|
||||
|
||||
$yoast_seo_class = filter_input( INPUT_POST, 'clean_external_plugin' );
|
||||
if ( class_exists( $yoast_seo_class ) ) {
|
||||
$yoast_seo_import = new WPSEO_Import_Plugin( new $yoast_seo_class(), 'cleanup' );
|
||||
if ( isset( $_POST['clean_external_plugin'] ) && is_string( $_POST['clean_external_plugin'] ) ) {
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are using the variable as a class name.
|
||||
$yoast_seo_class = wp_unslash( $_POST['clean_external_plugin'] );
|
||||
if ( class_exists( $yoast_seo_class ) ) {
|
||||
$yoast_seo_import = new WPSEO_Import_Plugin( new $yoast_seo_class(), 'cleanup' );
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ( filter_input( INPUT_POST, 'settings_import' ) ) {
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: We are only comparing to an empty string.
|
||||
elseif ( isset( $_POST['settings_import'] ) && wp_unslash( $_POST['settings_import'] ) !== '' ) {
|
||||
$yoast_seo_import = new WPSEO_Import_Settings();
|
||||
$yoast_seo_import->import();
|
||||
}
|
||||
|
||||
@@ -60,4 +60,18 @@ $wpseo_no_index_author_label = sprintf(
|
||||
<?php esc_html_e( 'Removes the readability analysis section from the metabox and disables all readability-related suggestions.', 'wordpress-seo' ); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( WPSEO_Options::get( 'inclusive_language_analysis_active', false ) ) : ?>
|
||||
<input class="yoast-settings__checkbox double" type="checkbox" id="wpseo_inclusive_language_analysis_disable"
|
||||
name="wpseo_inclusive_language_analysis_disable" aria-describedby="wpseo_inclusive_language_analysis_disable_desc"
|
||||
value="on" <?php echo ( get_the_author_meta( 'wpseo_inclusive_language_analysis_disable', $user->ID ) === 'on' ) ? 'checked' : ''; ?> />
|
||||
<label class="yoast-label-strong"
|
||||
for="wpseo_inclusive_language_analysis_disable"><?php esc_html_e( 'Disable inclusive language analysis', 'wordpress-seo' ); ?></label>
|
||||
<br>
|
||||
<p class="description" id="wpseo_inclusive_language_analysis_disable_desc">
|
||||
<?php esc_html_e( 'Removes the inclusive language analysis section from the metabox and disables all inclusive language-related suggestions.', 'wordpress-seo' ); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php do_action( 'wpseo_render_user_profile', $user ); ?>
|
||||
</div>
|
||||
|
||||
@@ -50,7 +50,7 @@ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an message when a post is about to get trashed.
|
||||
* Shows a message when a post is about to get trashed.
|
||||
*
|
||||
* @param int $post_id The current post ID.
|
||||
*
|
||||
@@ -61,15 +61,17 @@ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration {
|
||||
return;
|
||||
}
|
||||
|
||||
$post_label = $this->get_post_type_label( get_post_type( $post_id ) );
|
||||
|
||||
/* translators: %1$s expands to the translated name of the post type. */
|
||||
$first_sentence = sprintf( __( 'You just trashed a %1$s.', 'wordpress-seo' ), $this->get_post_type_label( get_post_type( $post_id ) ) );
|
||||
$message = $this->get_message( $first_sentence );
|
||||
$first_sentence = sprintf( __( 'You just trashed a %1$s.', 'wordpress-seo' ), $post_label );
|
||||
$message = $this->get_message( $first_sentence, 'trashed', $post_label );
|
||||
|
||||
$this->add_notification( $message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an message when a post is about to get trashed.
|
||||
* Shows a message when a post is about to get trashed.
|
||||
*
|
||||
* @param int $post_id The current post ID.
|
||||
*
|
||||
@@ -80,9 +82,11 @@ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration {
|
||||
return;
|
||||
}
|
||||
|
||||
$post_label = $this->get_post_type_label( get_post_type( $post_id ) );
|
||||
|
||||
/* translators: %1$s expands to the translated name of the post type. */
|
||||
$first_sentence = sprintf( __( 'You just deleted a %1$s.', 'wordpress-seo' ), $this->get_post_type_label( get_post_type( $post_id ) ) );
|
||||
$message = $this->get_message( $first_sentence );
|
||||
$first_sentence = sprintf( __( 'You just deleted a %1$s.', 'wordpress-seo' ), $post_label );
|
||||
$message = $this->get_message( $first_sentence, 'deleted', $post_label );
|
||||
|
||||
$this->add_notification( $message );
|
||||
}
|
||||
@@ -90,22 +94,21 @@ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration {
|
||||
/**
|
||||
* Shows a message when a term 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.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function detect_term_delete( $term_id ) {
|
||||
if ( ! $this->is_term_viewable( $term_id ) ) {
|
||||
public function detect_term_delete( $term_taxonomy_id ) {
|
||||
if ( ! $this->is_term_viewable( $term_taxonomy_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$first_sentence = sprintf(
|
||||
/* translators: 1: term label */
|
||||
__( 'You just deleted a %1$s.', 'wordpress-seo' ),
|
||||
$this->get_taxonomy_label_for_term( $term_id )
|
||||
);
|
||||
$term = \get_term_by( 'term_taxonomy_id', (int) $term_taxonomy_id );
|
||||
$term_label = $this->get_taxonomy_label_for_term( $term->term_id );
|
||||
|
||||
$message = $this->get_message( $first_sentence );
|
||||
/* translators: %1$s expands to the translated name of the term. */
|
||||
$first_sentence = sprintf( __( 'You just deleted a %1$s.', 'wordpress-seo' ), $term_label );
|
||||
$message = $this->get_message( $first_sentence, 'deleted', $term_label );
|
||||
|
||||
$this->add_notification( $message );
|
||||
}
|
||||
@@ -134,12 +137,12 @@ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration {
|
||||
/**
|
||||
* Checks if the term is viewable.
|
||||
*
|
||||
* @param string $term_id The term ID to check.
|
||||
* @param int $term_taxonomy_id The term taxonomy ID to check.
|
||||
*
|
||||
* @return bool Whether the term is viewable or not.
|
||||
*/
|
||||
protected function is_term_viewable( $term_id ) {
|
||||
$term = get_term( $term_id );
|
||||
protected function is_term_viewable( $term_taxonomy_id ) {
|
||||
$term = \get_term_by( 'term_taxonomy_id', (int) $term_taxonomy_id );
|
||||
|
||||
if ( ! $term || is_wp_error( $term ) ) {
|
||||
return false;
|
||||
@@ -206,14 +209,17 @@ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration {
|
||||
* Returns the message around changed URLs.
|
||||
*
|
||||
* @param string $first_sentence The first sentence of the notification.
|
||||
* @param string $action The action performed, either "deleted" or "trashed".
|
||||
* @param string $object_label The label of the object that was deleted or trashed.
|
||||
*
|
||||
* @return string The full notification.
|
||||
*/
|
||||
protected function get_message( $first_sentence ) {
|
||||
protected function get_message( $first_sentence, $action, $object_label ) {
|
||||
return '<h2>' . __( 'Make sure you don\'t miss out on traffic!', 'wordpress-seo' ) . '</h2>'
|
||||
. '<p>'
|
||||
. $first_sentence
|
||||
. ' ' . __( 'Search engines and other websites can still send traffic to your deleted post.', 'wordpress-seo' )
|
||||
/* translators: %1$s expands to either "deleted" or "trashed". %2$s expands to the name of the post or term. */
|
||||
. ' ' . sprintf( __( 'Search engines and other websites can still send traffic to your %1$s %2$s.', 'wordpress-seo' ), $action, $object_label )
|
||||
. ' ' . __( 'You should create a redirect to ensure your visitors do not get a 404 error when they click on the no longer working URL.', 'wordpress-seo' )
|
||||
/* translators: %s expands to Yoast SEO Premium */
|
||||
. ' ' . sprintf( __( 'With %s, you can easily create such redirects.', 'wordpress-seo' ), 'Yoast SEO Premium' )
|
||||
@@ -221,6 +227,7 @@ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration {
|
||||
. '<p><a class="yoast-button-upsell" href="' . WPSEO_Shortlinker::get( 'https://yoa.st/1d0' ) . '" target="_blank">'
|
||||
/* translators: %s expands to Yoast SEO Premium */
|
||||
. sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' )
|
||||
/* translators: Hidden accessibility text. */
|
||||
. '<span class="screen-reader-text">' . __( '(Opens in a new browser tab)', 'wordpress-seo' ) . '</span>'
|
||||
. '<span aria-hidden="true" class="yoast-button-upsell__caret"></span>'
|
||||
. '</a></p>';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.seo_page_wpseo_page_academy{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity));z-index:-1}.seo_page_wpseo_page_academy #wpcontent{padding-right:0!important}.seo_page_wpseo_page_academy #wpfooter{padding-left:1rem}@media (min-width:768px){.seo_page_wpseo_page_academy #wpfooter{padding-right:17rem;padding-left:2rem}}@media screen and (max-width:782px){.seo_page_wpseo_page_academy .wp-responsive-open #wpbody{left:-190px}}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user