diff --git a/wp-content/plugins/wordpress-seo/admin/admin-settings-changed-listener.php b/wp-content/plugins/wordpress-seo/admin/admin-settings-changed-listener.php
new file mode 100644
index 00000000..f3032b09
--- /dev/null
+++ b/wp-content/plugins/wordpress-seo/admin/admin-settings-changed-listener.php
@@ -0,0 +1,85 @@
+helpers->current_page->is_yoast_seo_page() ) {
+ return;
+ }
+
+ // Variable name is the same as the global that is set by get_settings_errors.
+ $wp_settings_errors = get_settings_errors();
+
+ foreach ( $wp_settings_errors as $key => $wp_settings_error ) {
+ if ( ! $this->is_settings_updated_notification( $wp_settings_error ) ) {
+ continue;
+ }
+
+ self::$settings_saved = true;
+ unset( $wp_settings_errors[ $key ] );
+ // phpcs:ignore WordPress.WP.GlobalVariablesOverride -- Overwrite the global with the list excluding the Changed saved message.
+ $GLOBALS['wp_settings_errors'] = $wp_settings_errors;
+ break;
+ }
+ }
+
+ /**
+ * Checks whether the settings notification is a settings_updated notification.
+ *
+ * @param array $wp_settings_error The settings object.
+ *
+ * @return bool Whether this is a settings updated settings notification.
+ */
+ public function is_settings_updated_notification( $wp_settings_error ) {
+ return ! empty( $wp_settings_error['code'] ) && $wp_settings_error['code'] === 'settings_updated';
+ }
+
+ /**
+ * Get whether the settings have successfully been saved
+ *
+ * @return bool Whether the settings have successfully been saved.
+ */
+ public function have_settings_been_saved() {
+ return self::$settings_saved;
+ }
+
+ /**
+ * Renders a success message if the Yoast SEO settings have been saved.
+ */
+ public function show_success_message() {
+ if ( $this->have_settings_been_saved() ) {
+ echo '
' .
- sprintf(
- /* translators: %1$s expands to Yoast SEO. */
- __( 'The title & metas settings for %1$s are made up of variables that are replaced by specific values from the page when the page is displayed. The tabs on the left explain the available variables.', 'wordpress-seo' ),
- 'Yoast SEO'
- ) .
- '
' . __( 'Note that not all variables can be used in every template.', 'wordpress-seo' ) . '
', esc_html( $meta_value ), $attributes, esc_attr( $id ) );
}
/**
@@ -942,44 +930,41 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
// Little housekeeping.
unset( $post_ids, $meta_data );
-
}
/**
* Getting all post_ids from to $this->items.
*
- * @return string
+ * @return array
*/
protected function get_post_ids() {
- $needed_ids = array();
+ $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}) && 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}" );
}
/**
@@ -992,7 +977,6 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
foreach ( $meta_data as $row ) {
$this->meta_data[ $row->post_id ][ $row->meta_key ] = $row->meta_value;
}
-
}
/**
@@ -1002,15 +986,15 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
*
* @return array
*/
- protected function merge_columns( $columns = array() ) {
+ protected function merge_columns( $columns = [] ) {
$columns = array_merge(
- array(
+ [
'col_page_title' => __( 'WP Page Title', 'wordpress-seo' ),
'col_post_type' => __( 'Content Type', 'wordpress-seo' ),
'col_post_status' => __( 'Post Status', 'wordpress-seo' ),
'col_post_date' => __( 'Publication date', 'wordpress-seo' ),
'col_page_slug' => __( 'Page URL/Slug', 'wordpress-seo' ),
- ),
+ ],
$columns
);
@@ -1018,4 +1002,4 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
return $columns;
}
-} /* End of class */
+}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-bulk-title-editor-list-table.php b/wp-content/plugins/wordpress-seo/admin/class-bulk-title-editor-list-table.php
index 6e47401b..5314fdb5 100644
--- a/wp-content/plugins/wordpress-seo/admin/class-bulk-title-editor-list-table.php
+++ b/wp-content/plugins/wordpress-seo/admin/class-bulk-title-editor-list-table.php
@@ -12,23 +12,22 @@
class WPSEO_Bulk_Title_Editor_List_Table extends WPSEO_Bulk_List_Table {
/**
- * Current type for this class will be title
+ * Current type for this class will be title.
*
* @var string
*/
protected $page_type = 'title';
-
/**
- * Settings with are used in __construct
+ * Settings with are used in __construct.
*
* @var array
*/
- protected $settings = array(
+ protected $settings = [
'singular' => 'wpseo_bulk_title',
'plural' => 'wpseo_bulk_titles',
'ajax' => true,
- );
+ ];
/**
* The field in the database where meta field is saved.
@@ -38,24 +37,24 @@ class WPSEO_Bulk_Title_Editor_List_Table extends WPSEO_Bulk_List_Table {
protected $target_db_field = 'title';
/**
- * The columns shown on the table
+ * The columns shown on the table.
*
* @return array
*/
public function get_columns() {
- $columns = array(
+ $columns = [
/* translators: %1$s expands to Yoast SEO */
'col_existing_yoast_seo_title' => sprintf( __( 'Existing %1$s Title', 'wordpress-seo' ), 'Yoast SEO' ),
/* translators: %1$s expands to Yoast SEO */
'col_new_yoast_seo_title' => sprintf( __( 'New %1$s Title', 'wordpress-seo' ), 'Yoast SEO' ),
- );
+ ];
return $this->merge_columns( $columns );
}
/**
- * Parse the title columns
+ * Parse the title columns.
*
* @param string $column_name Column name.
* @param object $record Data object.
@@ -66,11 +65,14 @@ class WPSEO_Bulk_Title_Editor_List_Table extends WPSEO_Bulk_List_Table {
protected function parse_page_specific_column( $column_name, $record, $attributes ) {
// Fill meta data if exists in $this->meta_data.
- $meta_data = ( ! empty( $this->meta_data[ $record->ID ] ) ) ? $this->meta_data[ $record->ID ] : array();
+ $meta_data = ( ! empty( $this->meta_data[ $record->ID ] ) ) ? $this->meta_data[ $record->ID ] : [];
switch ( $column_name ) {
case 'col_existing_yoast_seo_title':
- // @todo Inconsistent echo/return behavior R.
+ // @todo Inconsistent return/echo behavior R.
+ // I traced the escaping of the attributes to WPSEO_Bulk_List_Table::column_attributes.
+ // The output of WPSEO_Bulk_List_Table::parse_meta_data_field is properly escaped.
+ // phpcs:ignore WordPress.Security.EscapeOutput
echo $this->parse_meta_data_field( $record->ID, $attributes );
break;
@@ -84,4 +86,4 @@ class WPSEO_Bulk_Title_Editor_List_Table extends WPSEO_Bulk_List_Table {
unset( $meta_data );
}
-} /* End of class */
+}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-collector.php b/wp-content/plugins/wordpress-seo/admin/class-collector.php
index f1ae1e6b..f7687974 100644
--- a/wp-content/plugins/wordpress-seo/admin/class-collector.php
+++ b/wp-content/plugins/wordpress-seo/admin/class-collector.php
@@ -10,8 +10,12 @@
*/
class WPSEO_Collector {
- /** @var WPSEO_Collection[] */
- protected $collections = array();
+ /**
+ * Holds the collections.
+ *
+ * @var WPSEO_Collection[]
+ */
+ protected $collections = [];
/**
* Adds a collection object to the collections.
@@ -28,7 +32,7 @@ class WPSEO_Collector {
* @return array The collected data.
*/
public function collect() {
- $data = array();
+ $data = [];
foreach ( $this->collections as $collection ) {
$data = array_merge( $data, $collection->get() );
@@ -43,6 +47,6 @@ class WPSEO_Collector {
* @return false|string The encode string.
*/
public function get_as_json() {
- return wp_json_encode( $this->collect() );
+ return WPSEO_Utils::format_json_encode( $this->collect() );
}
}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-config.php b/wp-content/plugins/wordpress-seo/admin/class-config.php
index 294b89f8..444ee139 100644
--- a/wp-content/plugins/wordpress-seo/admin/class-config.php
+++ b/wp-content/plugins/wordpress-seo/admin/class-config.php
@@ -5,15 +5,19 @@
* @package WPSEO\Admin
*/
+use Yoast\WP\SEO\Config\Schema_Types;
+
/**
- * Class WPSEO_Admin_Pages
+ * Class WPSEO_Admin_Pages.
*
* Class with functionality for the Yoast SEO admin pages.
*/
class WPSEO_Admin_Pages {
/**
- * @var string $currentoption The option in use for the current admin page.
+ * The option in use for the current admin page.
+ *
+ * @var string
*/
public $currentoption = 'wpseo';
@@ -25,15 +29,15 @@ class WPSEO_Admin_Pages {
private $asset_manager;
/**
- * Class constructor, which basically only hooks the init function on the init hook
+ * Class constructor, which basically only hooks the init function on the init hook.
*/
public function __construct() {
- add_action( 'init', array( $this, 'init' ), 20 );
+ add_action( 'init', [ $this, 'init' ], 20 );
$this->asset_manager = new WPSEO_Admin_Asset_Manager();
}
/**
- * Make sure the needed scripts are loaded for 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' ) ) {
@@ -41,23 +45,8 @@ class WPSEO_Admin_Pages {
wp_redirect( admin_url( 'admin.php?page=' . WPSEO_Configuration_Page::PAGE_IDENTIFIER ) );
}
- add_action( 'admin_init', array( $this, 'admin_init' ) );
- add_action( 'admin_enqueue_scripts', array( $this, 'config_page_scripts' ) );
- add_action( 'admin_enqueue_scripts', array( $this, 'config_page_styles' ) );
- }
-
- /**
- * Run admin-specific actions.
- */
- public function admin_init() {
-
- $page = filter_input( INPUT_GET, 'page' );
- $tool = filter_input( INPUT_GET, 'tool' );
- $export_nonce = filter_input( INPUT_POST, WPSEO_Export::NONCE_NAME );
-
- if ( 'wpseo_tools' === $page && 'import-export' === $tool && $export_nonce !== null ) {
- $this->do_yoast_export();
- }
+ add_action( 'admin_enqueue_scripts', [ $this, 'config_page_scripts' ] );
+ add_action( 'admin_enqueue_scripts', [ $this, 'config_page_styles' ] );
}
/**
@@ -69,45 +58,118 @@ class WPSEO_Admin_Pages {
wp_enqueue_style( 'global' );
wp_enqueue_style( 'wp-admin' );
$this->asset_manager->enqueue_style( 'select2' );
-
$this->asset_manager->enqueue_style( 'admin-css' );
+
+ $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' );
+ }
}
/**
* Loads the required scripts for the config page.
*/
public function config_page_scripts() {
- $this->asset_manager->enqueue_script( 'admin-script' );
- $this->asset_manager->enqueue_script( 'help-center' );
-
+ $this->asset_manager->enqueue_script( 'settings' );
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();
+
+ $script_data = [
+ 'userLanguageCode' => WPSEO_Language_Utils::get_language( \get_user_locale() ),
+ 'dismissedAlerts' => $dismissed_alerts,
+ ];
+
$page = filter_input( INPUT_GET, 'page' );
- wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'admin-script', 'wpseoSelect2Locale', WPSEO_Utils::get_language( WPSEO_Utils::get_user_locale() ) );
+ if ( $page === 'wpseo_titles' ) {
+ $script_data['analysis'] = [
+ 'plugins' => [
+ 'replaceVars' => $this->get_replace_vars_script_data(),
+ ],
+ ];
- if ( in_array( $page, array( 'wpseo_social', WPSEO_Admin::PAGE_IDENTIFIER, 'wpseo_titles' ), true ) ) {
+ $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 ) ) {
wp_enqueue_media();
- $this->asset_manager->enqueue_script( 'admin-media' );
- wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'admin-media', 'wpseoMediaL10n', $this->localize_media_script() );
+ $script_data['media'] = [
+ 'choose_image' => __( 'Use Image', 'wordpress-seo' ),
+ ];
}
- if ( 'wpseo_tools' === $page ) {
+ 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();
}
/**
- * Pass some variables to js for upload module.
+ * Retrieves some variables that are needed for replacing variables in JS.
*
- * @return array
+ * @return array The replacement and recommended replacement variables.
*/
- public function localize_media_script() {
- return array(
- 'choose_image' => __( 'Use Image', 'wordpress-seo' ),
- );
+ public function get_replace_vars_script_data() {
+ $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();
+ $replace_vars_list = $replace_vars->get_replacement_variables_list();
+
+ return [
+ 'replace_vars' => $replace_vars_list,
+ '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 ),
+ ];
+ }
+
+ /**
+ * 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' ) );
}
/**
@@ -120,28 +182,8 @@ class WPSEO_Admin_Pages {
$this->asset_manager->enqueue_script( 'yoast-seo' );
}
- if ( 'bulk-editor' === $tool ) {
+ if ( $tool === 'bulk-editor' ) {
$this->asset_manager->enqueue_script( 'bulk-editor' );
}
}
-
- /**
- * Runs the yoast exporter class to possibly init the file download.
- */
- private function do_yoast_export() {
- check_admin_referer( WPSEO_Export::NONCE_ACTION, WPSEO_Export::NONCE_NAME );
-
- if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) {
- return;
- }
-
- $wpseo_post = filter_input( INPUT_POST, 'wpseo' );
- $include_taxonomy = ! empty( $wpseo_post['include_taxonomy'] );
- $export = new WPSEO_Export( $include_taxonomy );
-
- if ( $export->has_error() ) {
- add_action( 'admin_notices', array( $export, 'set_error_hook' ) );
-
- }
- }
-} /* End of class */
+}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-cornerstone-field.php b/wp-content/plugins/wordpress-seo/admin/class-cornerstone-field.php
deleted file mode 100644
index 094fbe93..00000000
--- a/wp-content/plugins/wordpress-seo/admin/class-cornerstone-field.php
+++ /dev/null
@@ -1,57 +0,0 @@
-',
- WPSEO_Cornerstone::META_NAME,
- checked( $this->get_meta_value( $post->ID ), '1', false )
- );
-
- $return .= sprintf( '';
-
- return $return;
- }
-
- /**
- * Gets the meta value from the database.
- *
- * @param int $post_id The post id to get the meta value for.
- *
- * @return null|string The meta value from the database.
- */
- protected function get_meta_value( $post_id ) {
- return get_post_meta( $post_id, WPSEO_Cornerstone::META_NAME, true );
- }
-}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-cornerstone.php b/wp-content/plugins/wordpress-seo/admin/class-cornerstone.php
deleted file mode 100644
index 167f7766..00000000
--- a/wp-content/plugins/wordpress-seo/admin/class-cornerstone.php
+++ /dev/null
@@ -1,92 +0,0 @@
-page_contains_cornerstone_content_field( $pagenow ) ) {
- return;
- }
-
- add_action( 'save_post', array( $this, 'save_meta_value' ) );
- add_filter( 'wpseo_cornerstone_post_types', array( 'WPSEO_Post_Type', 'filter_attachment_post_type' ) );
- }
-
- /**
- * Saves the meta value to the database.
- *
- * @param int $post_id The post id to save the meta value for.
- *
- * @return void
- */
- public function save_meta_value( $post_id ) {
- $is_cornerstone_content = $this->is_cornerstone_content();
-
- if ( $is_cornerstone_content ) {
- $this->update_meta( $post_id, $is_cornerstone_content );
-
- return;
- }
-
- $this->delete_meta( $post_id );
- }
-
- /**
- * Returns the result of the cornerstone content checkbox.
- *
- * @return bool True when checkbox is checked.
- */
- protected function is_cornerstone_content() {
- return filter_input( INPUT_POST, self::META_NAME ) === '1';
- }
-
- /**
- * Checks if the current page matches one of the pages that contains the cornerstone content field.
- *
- * @param string $page The page to check.
- *
- * @return bool True when the page contains the cornerstone content field.
- */
- protected function page_contains_cornerstone_content_field( $page ) {
- return WPSEO_Metabox::is_post_edit( $page );
- }
-
- /**
- * Updates the cornerstone content post meta with the given cornerstone content value.
- *
- * @param int $post_id The post id to save the meta value for.
- * @param bool $is_cornerstone_content Whether or not the post should be considered to be cornerstone content.
- *
- * @return void
- */
- protected function update_meta( $post_id, $is_cornerstone_content ) {
- update_post_meta( $post_id, self::META_NAME, $is_cornerstone_content );
- }
-
- /**
- * Deletes the cornerstone content post meta for the given post id.
- *
- * @param int $post_id The post id to delete the cornerstone content meta value for..
- *
- * @return void
- */
- protected function delete_meta( $post_id ) {
- delete_post_meta( $post_id, self::META_NAME );
- }
-}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-customizer.php b/wp-content/plugins/wordpress-seo/admin/class-customizer.php
index a22ae6ce..5771e466 100644
--- a/wp-content/plugins/wordpress-seo/admin/class-customizer.php
+++ b/wp-content/plugins/wordpress-seo/admin/class-customizer.php
@@ -11,19 +11,52 @@
class WPSEO_Customizer {
/**
+ * Holds the customize manager.
+ *
* @var WP_Customize_Manager
*/
protected $wp_customize;
+ /**
+ * Template for the setting IDs used for the customizer.
+ *
+ * @var string
+ */
+ private $setting_template = 'wpseo_titles[%s]';
+
+ /**
+ * Default arguments for the breadcrumbs customizer settings object.
+ *
+ * @var array
+ */
+ private $default_setting_args = [
+ 'default' => '',
+ 'type' => 'option',
+ 'transport' => 'refresh',
+ ];
+
+ /**
+ * Default arguments for the breadcrumbs customizer control object.
+ *
+ * @var array
+ */
+ private $default_control_args = [
+ 'label' => '',
+ 'type' => 'text',
+ 'section' => 'wpseo_breadcrumbs_customizer_section',
+ 'settings' => '',
+ 'context' => '',
+ ];
+
/**
* Construct Method.
*/
public function __construct() {
- add_action( 'customize_register', array( $this, 'wpseo_customize_register' ) );
+ add_action( 'customize_register', [ $this, 'wpseo_customize_register' ] );
}
/**
- * Function to support WordPress Customizer
+ * Function to support WordPress Customizer.
*
* @param WP_Customize_Manager $wp_customize Manager class instance.
*/
@@ -35,7 +68,7 @@ class WPSEO_Customizer {
$this->wp_customize = $wp_customize;
$this->breadcrumbs_section();
- $this->breadcrumbs_blog_remove_setting();
+ $this->breadcrumbs_blog_show_setting();
$this->breadcrumbs_separator_setting();
$this->breadcrumbs_home_setting();
$this->breadcrumbs_prefix_setting();
@@ -45,211 +78,152 @@ class WPSEO_Customizer {
}
/**
- * Add the breadcrumbs section to the customizer
+ * Add the breadcrumbs section to the customizer.
*/
private function breadcrumbs_section() {
- $this->wp_customize->add_section(
- 'wpseo_breadcrumbs_customizer_section', array(
- /* translators: %s is the name of the plugin */
- 'title' => sprintf( __( '%s Breadcrumbs', 'wordpress-seo' ), 'Yoast SEO' ),
- 'priority' => 999,
- 'active_callback' => array( $this, 'breadcrumbs_active_callback' ),
- )
- );
+ $section_args = [
+ /* translators: %s is the name of the plugin */
+ 'title' => sprintf( __( '%s Breadcrumbs', 'wordpress-seo' ), 'Yoast SEO' ),
+ 'priority' => 999,
+ 'active_callback' => [ $this, 'breadcrumbs_active_callback' ],
+ ];
+ $this->wp_customize->add_section( 'wpseo_breadcrumbs_customizer_section', $section_args );
}
/**
- * Returns whether or not the breadcrumbs are active
+ * Returns whether or not the breadcrumbs are active.
*
* @return bool
*/
public function breadcrumbs_active_callback() {
- return true === ( current_theme_supports( 'yoast-seo-breadcrumbs' ) || WPSEO_Options::get( 'breadcrumbs-enable' ) );
+ return current_theme_supports( 'yoast-seo-breadcrumbs' ) || WPSEO_Options::get( 'breadcrumbs-enable' );
}
/**
- * Adds the breadcrumbs remove blog checkbox
+ * Adds the breadcrumbs show blog checkbox.
*/
- private function breadcrumbs_blog_remove_setting() {
- $this->wp_customize->add_setting(
- 'wpseo_titles[breadcrumbs-display-blog-page]', array(
- 'default' => '',
- 'type' => 'option',
- 'transport' => 'refresh',
- )
- );
+ private function breadcrumbs_blog_show_setting() {
+ $index = 'breadcrumbs-display-blog-page';
+ $control_args = [
+ 'label' => __( 'Show blog page in breadcrumbs', 'wordpress-seo' ),
+ 'type' => 'checkbox',
+ 'active_callback' => [ $this, 'breadcrumbs_blog_show_active_cb' ],
+ ];
- $this->wp_customize->add_control(
- new WP_Customize_Control(
- $this->wp_customize, 'wpseo-breadcrumbs-display-blog-page', array(
- 'label' => __( 'Remove blog page from breadcrumbs', 'wordpress-seo' ),
- 'type' => 'checkbox',
- 'section' => 'wpseo_breadcrumbs_customizer_section',
- 'settings' => 'wpseo_titles[breadcrumbs-display-blog-page]',
- 'context' => '',
- 'active_callback' => array( $this, 'breadcrumbs_blog_remove_active_cb' ),
- )
- )
- );
+ $this->add_setting_and_control( $index, $control_args );
}
/**
- * Returns whether or not to show the breadcrumbs blog remove option
+ * Returns whether or not to show the breadcrumbs blog show option.
*
* @return bool
*/
- public function breadcrumbs_blog_remove_active_cb() {
- return 'page' === get_option( 'show_on_front' );
+ public function breadcrumbs_blog_show_active_cb() {
+ return get_option( 'show_on_front' ) === 'page';
}
/**
- * Adds the breadcrumbs separator text field
+ * Adds the breadcrumbs separator text field.
*/
private function breadcrumbs_separator_setting() {
- $this->wp_customize->add_setting(
- 'wpseo_titles[breadcrumbs-sep]', array(
- 'default' => '',
- 'type' => 'option',
- 'transport' => 'refresh',
- )
- );
+ $index = 'breadcrumbs-sep';
+ $control_args = [
+ 'label' => __( 'Breadcrumbs separator:', 'wordpress-seo' ),
+ ];
+ $id = 'wpseo-breadcrumbs-separator';
- $this->wp_customize->add_control(
- new WP_Customize_Control(
- $this->wp_customize, 'wpseo-breadcrumbs-separator', array(
- 'label' => __( 'Breadcrumbs separator:', 'wordpress-seo' ),
- 'type' => 'text',
- 'section' => 'wpseo_breadcrumbs_customizer_section',
- 'settings' => 'wpseo_titles[breadcrumbs-sep]',
- 'context' => '',
- )
- )
- );
+ $this->add_setting_and_control( $index, $control_args, $id );
}
/**
- * Adds the breadcrumbs home anchor text field
+ * Adds the breadcrumbs home anchor text field.
*/
private function breadcrumbs_home_setting() {
- $this->wp_customize->add_setting(
- 'wpseo_titles[breadcrumbs-home]', array(
- 'default' => '',
- 'type' => 'option',
- 'transport' => 'refresh',
- )
- );
+ $index = 'breadcrumbs-home';
+ $control_args = [
+ 'label' => __( 'Anchor text for the homepage:', 'wordpress-seo' ),
+ ];
- $this->wp_customize->add_control(
- new WP_Customize_Control(
- $this->wp_customize, 'wpseo-breadcrumbs-home', array(
- 'label' => __( 'Anchor text for the homepage:', 'wordpress-seo' ),
- 'type' => 'text',
- 'section' => 'wpseo_breadcrumbs_customizer_section',
- 'settings' => 'wpseo_titles[breadcrumbs-home]',
- 'context' => '',
- )
- )
- );
+ $this->add_setting_and_control( $index, $control_args );
}
/**
- * Adds the breadcrumbs prefix text field
+ * Adds the breadcrumbs prefix text field.
*/
private function breadcrumbs_prefix_setting() {
- $this->wp_customize->add_setting(
- 'wpseo_titles[breadcrumbs-prefix]', array(
- 'default' => '',
- 'type' => 'option',
- 'transport' => 'refresh',
- )
- );
+ $index = 'breadcrumbs-prefix';
+ $control_args = [
+ 'label' => __( 'Prefix for breadcrumbs:', 'wordpress-seo' ),
+ ];
- $this->wp_customize->add_control(
- new WP_Customize_Control(
- $this->wp_customize, 'wpseo-breadcrumbs-prefix', array(
- 'label' => __( 'Prefix for breadcrumbs:', 'wordpress-seo' ),
- 'type' => 'text',
- 'section' => 'wpseo_breadcrumbs_customizer_section',
- 'settings' => 'wpseo_titles[breadcrumbs-prefix]',
- 'context' => '',
- )
- )
- );
+ $this->add_setting_and_control( $index, $control_args );
}
/**
- * Adds the breadcrumbs archive prefix text field
+ * Adds the breadcrumbs archive prefix text field.
*/
private function breadcrumbs_archiveprefix_setting() {
- $this->wp_customize->add_setting(
- 'wpseo_titles[breadcrumbs-archiveprefix]', array(
- 'default' => '',
- 'type' => 'option',
- 'transport' => 'refresh',
- )
- );
+ $index = 'breadcrumbs-archiveprefix';
+ $control_args = [
+ 'label' => __( 'Prefix for archive pages:', 'wordpress-seo' ),
+ ];
- $this->wp_customize->add_control(
- new WP_Customize_Control(
- $this->wp_customize, 'wpseo-breadcrumbs-archiveprefix', array(
- 'label' => __( 'Prefix for archive pages:', 'wordpress-seo' ),
- 'type' => 'text',
- 'section' => 'wpseo_breadcrumbs_customizer_section',
- 'settings' => 'wpseo_titles[breadcrumbs-archiveprefix]',
- 'context' => '',
- )
- )
- );
+ $this->add_setting_and_control( $index, $control_args );
}
/**
- * Adds the breadcrumbs search prefix text field
+ * Adds the breadcrumbs search prefix text field.
*/
private function breadcrumbs_searchprefix_setting() {
- $this->wp_customize->add_setting(
- 'wpseo_titles[breadcrumbs-searchprefix]', array(
- 'default' => '',
- 'type' => 'option',
- 'transport' => 'refresh',
- )
- );
+ $index = 'breadcrumbs-searchprefix';
+ $control_args = [
+ 'label' => __( 'Prefix for search result pages:', 'wordpress-seo' ),
+ ];
- $this->wp_customize->add_control(
- new WP_Customize_Control(
- $this->wp_customize, 'wpseo-breadcrumbs-searchprefix', array(
- 'label' => __( 'Prefix for search result pages:', 'wordpress-seo' ),
- 'type' => 'text',
- 'section' => 'wpseo_breadcrumbs_customizer_section',
- 'settings' => 'wpseo_titles[breadcrumbs-searchprefix]',
- 'context' => '',
- )
- )
- );
+ $this->add_setting_and_control( $index, $control_args );
}
/**
- * Adds the breadcrumb 404 prefix text field
+ * Adds the breadcrumb 404 prefix text field.
*/
private function breadcrumbs_404_setting() {
- $this->wp_customize->add_setting(
- 'wpseo_titles[breadcrumbs-404crumb]', array(
- 'default' => '',
- 'type' => 'option',
- 'transport' => 'refresh',
- )
- );
+ $index = 'breadcrumbs-404crumb';
+ $control_args = [
+ 'label' => __( 'Breadcrumb for 404 pages:', 'wordpress-seo' ),
+ ];
- $this->wp_customize->add_control(
- new WP_Customize_Control(
- $this->wp_customize, 'wpseo-breadcrumbs-404crumb', array(
- 'label' => __( 'Breadcrumb for 404 pages:', 'wordpress-seo' ),
- 'type' => 'text',
- 'section' => 'wpseo_breadcrumbs_customizer_section',
- 'settings' => 'wpseo_titles[breadcrumbs-404crumb]',
- 'context' => '',
- )
- )
- );
+ $this->add_setting_and_control( $index, $control_args );
+ }
+
+ /**
+ * Adds the customizer setting and control.
+ *
+ * @param string $index Array key index to use for the customizer setting.
+ * @param array $control_args Customizer control object arguments.
+ * Only those different from the default need to be passed.
+ * @param string|null $id Optional. Customizer control object ID.
+ * Will default to 'wpseo-' . $index.
+ * @param array $custom_settings Optional. Customizer setting arguments.
+ * Only those different from the default need to be passed.
+ */
+ private function add_setting_and_control( $index, $control_args, $id = null, $custom_settings = [] ) {
+ $setting = sprintf( $this->setting_template, $index );
+ $control_args = array_merge( $this->default_control_args, $control_args );
+ $control_args['settings'] = $setting;
+
+ $settings_args = $this->default_setting_args;
+ if ( ! empty( $custom_settings ) ) {
+ $settings_args = array_merge( $settings_args, $custom_settings );
+ }
+
+ if ( ! isset( $id ) ) {
+ $id = 'wpseo-' . $index;
+ }
+
+ $this->wp_customize->add_setting( $setting, $settings_args );
+
+ $control = new WP_Customize_Control( $this->wp_customize, $id, $control_args );
+ $this->wp_customize->add_control( $control );
}
}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-database-proxy.php b/wp-content/plugins/wordpress-seo/admin/class-database-proxy.php
index f1b06dfd..c4ca791b 100644
--- a/wp-content/plugins/wordpress-seo/admin/class-database-proxy.php
+++ b/wp-content/plugins/wordpress-seo/admin/class-database-proxy.php
@@ -6,33 +6,68 @@
*/
/**
- * Represents the proxy for communicating with the database
+ * Represents the proxy for communicating with the database.
*/
class WPSEO_Database_Proxy {
- /** @var string */
+ /**
+ * Holds the table name.
+ *
+ * @var string
+ */
protected $table_name;
- /** @var bool */
+ /**
+ * Determines whether to suppress errors or not.
+ *
+ * @var bool
+ */
protected $suppress_errors = true;
- /** @var bool */
+ /**
+ * Determines if this table is multisite.
+ *
+ * @var bool
+ */
+ protected $is_multisite_table = false;
+
+ /**
+ * Holds the last suppressed state.
+ *
+ * @var bool
+ */
protected $last_suppressed_state;
- /** @var wpdb */
+ /**
+ * Holds the WordPress database object.
+ *
+ * @var wpdb
+ */
protected $database;
/**
- * Sets the class attributes.
+ * Sets the class attributes and registers the table.
*
- * @param wpdb $database The database object.
- * @param string $table_name The table name that is represented.
- * @param bool $suppress_errors Should the errors be suppressed.
+ * @param wpdb $database The database object.
+ * @param string $table_name The table name that is represented.
+ * @param bool $suppress_errors Should the errors be suppressed.
+ * @param bool $is_multisite_table Should the table be global in multisite.
*/
- public function __construct( $database, $table_name, $suppress_errors = true ) {
- $this->table_name = $table_name;
- $this->suppress_errors = (bool) $suppress_errors;
- $this->database = $database;
+ public function __construct( $database, $table_name, $suppress_errors = true, $is_multisite_table = false ) {
+ $this->table_name = $table_name;
+ $this->suppress_errors = (bool) $suppress_errors;
+ $this->is_multisite_table = (bool) $is_multisite_table;
+ $this->database = $database;
+
+ // If the table prefix was provided, strip it as it's handled automatically.
+ $table_prefix = $this->get_table_prefix();
+ if ( ! empty( $table_prefix ) && strpos( $this->table_name, $table_prefix ) === 0 ) {
+ $this->table_prefix = substr( $this->table_name, strlen( $table_prefix ) );
+ }
+
+ if ( ! $this->is_table_registered() ) {
+ $this->register_table();
+ }
}
/**
@@ -58,7 +93,7 @@ class WPSEO_Database_Proxy {
*
* @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 $format Optional. Data prepare format.
* @param null $where_format Optional. Where prepare format.
*
* @return false|int False when the update request is invalid, int on number of rows changed.
@@ -76,22 +111,47 @@ class WPSEO_Database_Proxy {
/**
* Upserts data in the database.
*
- * Tries to insert the data first, if this fails an update is attempted.
+ * 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 $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|null $where Unused. Where condition as key => value array.
+ * @param null $format Optional. Data prepare format.
+ * @param null $where_format Deprecated. Where prepare format.
*
* @return false|int False when the upsert request is invalid, int on number of rows changed.
*/
- public function upsert( array $data, array $where, $format = null, $where_format = null ) {
- $result = $this->insert( $data, $format );
-
- if ( false === $result ) {
- $result = $this->update( $data, $where, $format, $where_format );
+ public function upsert( array $data, array $where = null, $format = null, $where_format = null ) {
+ if ( $where_format !== null ) {
+ _deprecated_argument( __METHOD__, '7.7.0', 'The where_format argument is deprecated' );
}
+ $this->pre_execution();
+
+ $update = [];
+ $keys = [];
+ $columns = array_keys( $data );
+ foreach ( $columns as $column ) {
+ $keys[] = '`' . $column . '`';
+ $update[] = sprintf( '`%1$s` = VALUES(`%1$s`)', $column );
+ }
+
+ $query = sprintf(
+ 'INSERT INTO `%1$s` (%2$s) VALUES ( %3$s ) ON DUPLICATE KEY UPDATE %4$s',
+ $this->get_table_name(),
+ implode( ', ', $keys ),
+ implode( ', ', array_fill( 0, count( $data ), '%s' ) ),
+ implode( ', ', $update )
+ );
+
+ $result = $this->database->query(
+ $this->database->prepare(
+ $query,
+ array_values( $data )
+ )
+ );
+
+ $this->post_execution();
+
return $result;
}
@@ -99,7 +159,7 @@ class WPSEO_Database_Proxy {
* Deletes a record from the database.
*
* @param array $where Where clauses for the query.
- * @param null|array $format Formats for the data.
+ * @param array|null $format Formats for the data.
*
* @return false|int
*/
@@ -118,7 +178,7 @@ class WPSEO_Database_Proxy {
*
* @param string $query The query to execute.
*
- * @return array|null|object The resultset
+ * @return array|object|null The resultset
*/
public function get_results( $query ) {
$this->pre_execution();
@@ -138,9 +198,9 @@ class WPSEO_Database_Proxy {
*
* @return bool True when creation is successful.
*/
- public function create_table( array $columns, array $indexes = array() ) {
- $create_table = sprintf( '
- CREATE TABLE IF NOT EXISTS %1$s ( %2$s ) %3$s',
+ public function create_table( array $columns, array $indexes = [] ) {
+ $create_table = sprintf(
+ 'CREATE TABLE IF NOT EXISTS %1$s ( %2$s ) %3$s',
$this->get_table_name(),
implode( ',', array_merge( $columns, $indexes ) ),
$this->database->get_charset_collate()
@@ -183,11 +243,56 @@ class WPSEO_Database_Proxy {
}
/**
- * Returns the set table name.
+ * Returns the full table name.
*
- * @return string
+ * @return string Full table name including prefix.
*/
- protected function get_table_name() {
- return $this->table_name;
+ public function get_table_name() {
+ return $this->get_table_prefix() . $this->table_name;
+ }
+
+ /**
+ * Returns the prefix to use for the table.
+ *
+ * @return string The table prefix depending on the database context.
+ */
+ protected function get_table_prefix() {
+ if ( $this->is_multisite_table ) {
+ return $this->database->base_prefix;
+ }
+
+ return $this->database->get_blog_prefix();
+ }
+
+ /**
+ * Registers the table with WordPress.
+ *
+ * @return void
+ */
+ protected function register_table() {
+ $table_name = $this->table_name;
+ $full_table_name = $this->get_table_name();
+
+ $this->database->$table_name = $full_table_name;
+
+ if ( $this->is_multisite_table ) {
+ $this->database->ms_global_tables[] = $table_name;
+ return;
+ }
+
+ $this->database->tables[] = $table_name;
+ }
+
+ /**
+ * Checks if the table has been registered with WordPress.
+ *
+ * @return bool True if the table is registered, false otherwise.
+ */
+ protected function is_table_registered() {
+ if ( $this->is_multisite_table ) {
+ return in_array( $this->table_name, $this->database->ms_global_tables, true );
+ }
+
+ return in_array( $this->table_name, $this->database->tables, true );
}
}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-export.php b/wp-content/plugins/wordpress-seo/admin/class-export.php
index c1e4402d..a2e38a9d 100644
--- a/wp-content/plugins/wordpress-seo/admin/class-export.php
+++ b/wp-content/plugins/wordpress-seo/admin/class-export.php
@@ -6,131 +6,98 @@
*/
/**
- * Class WPSEO_Export
+ * Class WPSEO_Export.
*
- * Class with functionality to export the WP SEO settings
+ * Class with functionality to export the WP SEO settings.
*/
class WPSEO_Export {
- const ZIP_FILENAME = 'yoast-seo-settings-export.zip';
- const INI_FILENAME = 'settings.ini';
-
+ /**
+ * Holds the nonce action.
+ *
+ * @var string
+ */
const NONCE_ACTION = 'wpseo_export';
- const NONCE_NAME = 'wpseo_export_nonce';
/**
+ * Holds the export data.
+ *
* @var string
*/
private $export = '';
/**
- * @var string
- */
- private $error = '';
-
- /**
- * @var string
- */
- public $export_zip_url = '';
-
- /**
- * @var boolean
+ * Holds whether the export was a success.
+ *
+ * @var bool
*/
public $success;
/**
- * Whether or not the export will include taxonomy metadata
- *
- * @var boolean
+ * Handles the export request.
*/
- private $include_taxonomy;
-
- /**
- * @var array
- */
- private $dir = array();
-
-
- /**
- * Class constructor
- *
- * @param boolean $include_taxonomy Whether to include the taxonomy metadata the plugin creates.
- */
- public function __construct( $include_taxonomy = false ) {
- $this->include_taxonomy = $include_taxonomy;
- $this->dir = wp_upload_dir();
-
+ public function export() {
+ check_admin_referer( self::NONCE_ACTION );
$this->export_settings();
+ $this->output();
}
/**
- * Returns true when the property error has a value.
- *
- * @return bool
+ * Outputs the export.
*/
- public function has_error() {
- return ( $this->error !== '' );
- }
-
- /**
- * Sets the error hook, to display the error to the user.
- */
- public function set_error_hook() {
- /* translators: %1$s expands to Yoast SEO */
- $message = sprintf( __( 'Error creating %1$s export: ', 'wordpress-seo' ), 'Yoast SEO' ) . $this->error;
+ public function output() {
+ if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) {
+ esc_html_e( 'You do not have the required rights to export settings.', 'wordpress-seo' );
+ return;
+ }
+ echo '
';
printf(
- '
%1$s
',
- $message
+ /* translators: %1$s expands to Import settings */
+ esc_html__(
+ 'Copy all these settings to another site\'s %1$s tab and click "%1$s" there.',
+ 'wordpress-seo'
+ ),
+ esc_html__(
+ 'Import settings',
+ 'wordpress-seo'
+ )
);
+ echo '';
+ /* translators: %1$s expands to Yoast SEO */
+ echo ' ';
+ echo '';
}
/**
* Exports the current site's WP SEO settings.
*/
private function export_settings() {
-
$this->export_header();
foreach ( WPSEO_Options::get_option_names() as $opt_group ) {
$this->write_opt_group( $opt_group );
}
-
- $this->taxonomy_metadata();
-
- if ( ! $this->write_settings_file() ) {
- $this->error = __( 'Could not write settings to file.', 'wordpress-seo' );
-
- return;
- }
-
- if ( $this->zip_file() ) {
- // Just exit, because there is a download being served.
- exit;
- }
}
/**
- * Writes the header of the export file.
+ * Writes the header of the export.
*/
private function export_header() {
$header = sprintf(
/* translators: %1$s expands to Yoast SEO, %2$s expands to Yoast.com */
- esc_html__( 'This is a settings export file for the %1$s plugin by %2$s', 'wordpress-seo' ),
+ esc_html__( 'These are settings for the %1$s plugin by %2$s', 'wordpress-seo' ),
'Yoast SEO',
'Yoast.com'
);
- $this->write_line( '; ' . $header . ' - ' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yd' ) ) );
- if ( $this->include_taxonomy ) {
- $this->write_line( '; ' . __( 'This export includes taxonomy metadata', 'wordpress-seo' ) );
- }
+ $this->write_line( '; ' . $header );
}
/**
- * Writes a line to the export
+ * Writes a line to the export.
*
- * @param string $line Line string.
- * @param boolean $newline_first Boolean flag whether to prepend with new line.
+ * @param string $line Line string.
+ * @param bool $newline_first Boolean flag whether to prepend with new line.
*/
private function write_line( $line, $newline_first = false ) {
if ( $newline_first ) {
@@ -140,7 +107,7 @@ class WPSEO_Export {
}
/**
- * Writes an entire option group to the export
+ * Writes an entire option group to the export.
*
* @param string $opt_group Option group name.
*/
@@ -157,7 +124,7 @@ class WPSEO_Export {
foreach ( $options as $key => $elem ) {
if ( is_array( $elem ) ) {
$count = count( $elem );
- for ( $i = 0; $i < $count; $i ++ ) {
+ for ( $i = 0; $i < $count; $i++ ) {
$this->write_setting( $key . '[]', $elem[ $i ] );
}
}
@@ -168,7 +135,7 @@ class WPSEO_Export {
}
/**
- * Writes a settings line to the export
+ * Writes a settings line to the export.
*
* @param string $key Key string.
* @param string $val Value string.
@@ -179,109 +146,4 @@ class WPSEO_Export {
}
$this->write_line( $key . ' = ' . $val );
}
-
- /**
- * Adds the taxonomy meta data if there is any
- */
- private function taxonomy_metadata() {
- if ( $this->include_taxonomy ) {
- $taxonomy_meta = get_option( 'wpseo_taxonomy_meta' );
- if ( is_array( $taxonomy_meta ) ) {
- $this->write_line( '[wpseo_taxonomy_meta]', true );
- $this->write_setting( 'wpseo_taxonomy_meta', urlencode( wp_json_encode( $taxonomy_meta ) ) );
- }
- else {
- $this->write_line( '; ' . __( 'No taxonomy metadata found', 'wordpress-seo' ), true );
- }
- }
- }
-
- /**
- * Writes the settings to our temporary settings.ini file
- *
- * @return boolean unsigned
- */
- private function write_settings_file() {
- $handle = fopen( $this->dir['path'] . '/' . self::INI_FILENAME, 'w' );
- if ( ! $handle ) {
- return false;
- }
-
- $res = fwrite( $handle, $this->export );
- if ( ! $res ) {
- return false;
- }
-
- fclose( $handle );
-
- return true;
- }
-
- /**
- * Zips the settings ini file
- *
- * @return bool|null
- */
- private function zip_file() {
- $is_zip_created = $this->create_zip();
-
- // The settings.ini isn't needed, because it's in the zipfile.
- $this->remove_settings_ini();
-
- if ( ! $is_zip_created ) {
- $this->error = __( 'Could not zip settings-file.', 'wordpress-seo' );
-
- return false;
- }
-
- $this->serve_settings_export();
- $this->remove_zip();
-
- return true;
- }
-
- /**
- * Creates the zipfile and returns true if it created successful.
- *
- * @return bool
- */
- private function create_zip() {
- chdir( $this->dir['path'] );
- $zip = new PclZip( './' . self::ZIP_FILENAME );
- if ( 0 === $zip->create( './' . self::INI_FILENAME ) ) {
- return false;
- }
-
- return file_exists( self::ZIP_FILENAME );
- }
-
- /**
- * Downloads the zip file.
- */
- private function serve_settings_export() {
- // Clean any content that has been already output. For example by other plugins or faulty PHP files.
- if ( ob_get_contents() ) {
- ob_clean();
- }
- header( 'Content-Type: application/octet-stream; charset=utf-8' );
- header( 'Content-Transfer-Encoding: Binary' );
- header( 'Content-Disposition: attachment; filename=' . self::ZIP_FILENAME );
- header( 'Content-Length: ' . filesize( self::ZIP_FILENAME ) );
-
- readfile( self::ZIP_FILENAME );
- }
-
- /**
- * Removes the settings ini file.
- */
- private function remove_settings_ini() {
- unlink( './' . self::INI_FILENAME );
- }
-
- /**
- * Removes the files because they are already downloaded.
- */
- private function remove_zip() {
- unlink( './' . self::ZIP_FILENAME );
- }
}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-expose-shortlinks.php b/wp-content/plugins/wordpress-seo/admin/class-expose-shortlinks.php
new file mode 100644
index 00000000..3cacce17
--- /dev/null
+++ b/wp-content/plugins/wordpress-seo/admin/class-expose-shortlinks.php
@@ -0,0 +1,115 @@
+ '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.social_previews' => 'https://yoa.st/social-preview-cta',
+ 'shortlinks.upsell.sidebar.focus_keyword_synonyms_link' => 'https://yoa.st/textlink-synonyms-popup-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.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.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.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.gsc.create_redirect_button' => 'https://yoa.st/redirects',
+ 'shortlinks.readability_analysis_info' => 'https://yoa.st/readability-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',
+ 'shortlinks.semrush.volume_help' => 'https://yoa.st/3-v',
+ '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',
+ ];
+
+ /**
+ * Registers all hooks to WordPress.
+ *
+ * @return void
+ */
+ public function register_hooks() {
+ add_filter( 'wpseo_admin_l10n', [ $this, 'expose_shortlinks' ] );
+ }
+
+ /**
+ * Adds shortlinks to the passed array.
+ *
+ * @param array $input The array to add shortlinks to.
+ *
+ * @return array The passed array with the additional shortlinks.
+ */
+ public function expose_shortlinks( $input ) {
+ foreach ( $this->get_shortlinks() as $key => $shortlink ) {
+ $input[ $key ] = WPSEO_Shortlinker::get( $shortlink );
+ }
+
+ $input['default_query_params'] = WPSEO_Shortlinker::get_query_params();
+
+ return $input;
+ }
+
+ /**
+ * Retrieves the shortlinks.
+ *
+ * @return array The shortlinks.
+ */
+ private function get_shortlinks() {
+ if ( ! $this->is_term_edit() ) {
+ return $this->shortlinks;
+ }
+
+ $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';
+
+ return $shortlinks;
+ }
+
+ /**
+ * Checks if the current page is a term edit page.
+ *
+ * @return bool True when page is term edit.
+ */
+ private function is_term_edit() {
+ global $pagenow;
+
+ return WPSEO_Taxonomy::is_term_edit( $pagenow );
+ }
+}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-extension-manager.php b/wp-content/plugins/wordpress-seo/admin/class-extension-manager.php
deleted file mode 100644
index 835cb586..00000000
--- a/wp-content/plugins/wordpress-seo/admin/class-extension-manager.php
+++ /dev/null
@@ -1,140 +0,0 @@
-extensions[ $extension_name ] = $extension;
- }
-
- /**
- * Removes an extension from the manager.
- *
- * @param string $extension_name The name of the extension to remove.
- *
- * @return void
- */
- public function remove( $extension_name ) {
- if ( array_key_exists( $extension_name, $this->extensions ) ) {
- unset( $this->extensions[ $extension_name ] );
- }
- }
-
- /**
- * Returns the extension for the given extension name.
- *
- * @param string $extension_name The name of the extension to get.
- *
- * @return null|WPSEO_Extension The extension object or null when it doesn't exist.
- */
- public function get( $extension_name ) {
- if ( array_key_exists( $extension_name, $this->extensions ) ) {
- return $this->extensions[ $extension_name ];
- }
-
- return null;
- }
-
- /**
- * Returns all set extension.
- *
- * @return WPSEO_Extension[] Array with the extensions.
- */
- public function get_all() {
- return $this->extensions;
- }
-
- /**
- * Checks if the plugin is activated within My Yoast.
- *
- * @param string $extension_name The extension name to check.
- *
- * @return bool True when the plugin is activated.
- */
- public function is_activated( $extension_name ) {
- if ( self::$active_extensions === null ) {
- // Force re-check on license & dashboard pages.
- $current_page = $this->get_current_page();
-
- // Check whether the licenses are valid or whether we need to show notifications.
- $exclude_cache = ( $current_page === 'wpseo_licenses' || $current_page === 'wpseo_dashboard' );
-
- // Fetch transient data on any other page.
- if ( ! $exclude_cache ) {
- self::$active_extensions = $this->get_cached_extensions();
- }
-
- // If the active extensions is still NULL, we need to set it.
- if ( ! is_array( self::$active_extensions ) ) {
- self::$active_extensions = $this->retrieve_active_extensions();
-
- $this->set_cached_extensions( self::$active_extensions );
- }
- }
-
- return in_array( $extension_name, self::$active_extensions, true );
- }
-
- /**
- * Retrieves the active extensions via an external request.
- *
- * @return array Array containing the active extensions.
- */
- protected function retrieve_active_extensions() {
- return (array) apply_filters( 'yoast-active-extensions', array() );
- }
-
- /**
- * Returns the current page.
- *
- * @return string The current page.
- */
- protected function get_current_page() {
- return filter_input( INPUT_GET, 'page' );
- }
-
- /**
- * Gets a cached list of active extensions.
- *
- * @return boolean|array The cached extensions.
- */
- protected function get_cached_extensions() {
- return get_transient( self::TRANSIENT_CACHE_KEY );
- }
-
- /**
- * Sets the active extensions transient for the set duration.
- *
- * @param array $extensions The extensions to add.
- * @param int $duration The duration that the list of extensions needs to remain cached.
- *
- * @return void
- */
- protected function set_cached_extensions( $extensions, $duration = DAY_IN_SECONDS ) {
- set_transient( self::TRANSIENT_CACHE_KEY, $extensions, $duration );
- }
-}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-extensions.php b/wp-content/plugins/wordpress-seo/admin/class-extensions.php
deleted file mode 100644
index 96969ca2..00000000
--- a/wp-content/plugins/wordpress-seo/admin/class-extensions.php
+++ /dev/null
@@ -1,108 +0,0 @@
- array(
- 'slug' => 'yoast-seo-premium',
- 'identifier' => 'wordpress-seo-premium',
- 'classname' => 'WPSEO_Premium',
- ),
- 'News SEO' => array(
- 'slug' => 'news-seo',
- 'identifier' => 'wpseo-news',
- 'classname' => 'WPSEO_News',
- ),
- 'Yoast WooCommerce SEO' => array(
- 'slug' => 'woocommerce-yoast-seo',
- 'identifier' => 'wpseo-woocommerce',
- 'classname' => 'Yoast_WooCommerce_SEO',
- ),
- 'Video SEO' => array(
- 'slug' => 'video-seo-for-wordpress',
- 'identifier' => 'wpseo-video',
- 'classname' => 'WPSEO_Video_Sitemap',
- ),
- 'Local SEO' => array(
- 'slug' => 'local-seo-for-wordpress',
- 'identifier' => 'wpseo-local',
- 'classname' => 'WPSEO_Local_Core',
- ),
- 'Local SEO for WooCommerce' => array(
- 'slug' => 'local-seo-for-woocommerce',
- 'identifier' => 'wpseo-local-woocommerce',
- 'classname' => 'WPSEO_Local_WooCommerce',
- ),
- );
-
- /**
- * Returns the set extensions.
- *
- * @return array All the extension names.
- */
- public function get() {
- return array_keys( $this->extensions );
- }
-
- /**
- * Checks if the extension is valid.
- *
- * @param string $extension The extension to get the name for.
- *
- * @return bool Returns true when valid.
- */
- public function is_valid( $extension ) {
- $extensions = new WPSEO_Extension_Manager();
- return $extensions->is_activated( $this->extensions[ $extension ]['identifier'] );
- }
-
- /**
- * Invalidates the extension by removing its option.
- *
- * @param string $extension The extension to invalidate.
- */
- public function invalidate( $extension ) {
- /*
- * Make sure we clear the current site and multisite options.
- *
- * Because plugins can be site-activated or multi-site activated we need to clear
- * all possible options.
- *
- * If we knew here that the extension in question was network activated
- * we could do this a lot more easily.
- */
- delete_option( $this->get_option_name( $extension ) );
- delete_site_option( $this->get_option_name( $extension ) );
- }
-
- /**
- * Checks if the plugin has been installed.
- *
- * @param string $extension The name of the plugin to check.
- *
- * @return bool Returns true when installed.
- */
- public function is_installed( $extension ) {
- return class_exists( $this->extensions[ $extension ]['classname'] );
- }
-
- /**
- * Converts the extension to the required option name.
- *
- * @param string $extension The extension name to convert.
- *
- * @return string Returns the option name.
- */
- protected function get_option_name( $extension ) {
- return sanitize_title_with_dashes( $this->extensions[ $extension ]['slug'] . '_', null, 'save' ) . 'license';
- }
-}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-gutenberg-compatibility.php b/wp-content/plugins/wordpress-seo/admin/class-gutenberg-compatibility.php
new file mode 100644
index 00000000..9a2991e8
--- /dev/null
+++ b/wp-content/plugins/wordpress-seo/admin/class-gutenberg-compatibility.php
@@ -0,0 +1,107 @@
+current_version = $this->detect_installed_gutenberg_version();
+ }
+
+ /**
+ * Determines whether or not Gutenberg is installed.
+ *
+ * @return bool Whether or not Gutenberg is installed.
+ */
+ public function is_installed() {
+ return $this->current_version !== '';
+ }
+
+ /**
+ * Determines whether or not the currently installed version of Gutenberg is below the minimum supported version.
+ *
+ * @return bool True if the currently installed version is below the minimum supported version. False otherwise.
+ */
+ public function is_below_minimum() {
+ return version_compare( $this->current_version, $this->get_minimum_supported_version(), '<' );
+ }
+
+ /**
+ * Gets the currently installed version.
+ *
+ * @return string The currently installed version.
+ */
+ public function get_installed_version() {
+ return $this->current_version;
+ }
+
+ /**
+ * Determines whether or not the currently installed version of Gutenberg is the latest, fully compatible version.
+ *
+ * @return bool Whether or not the currently installed version is fully compatible.
+ */
+ public function is_fully_compatible() {
+ return version_compare( $this->current_version, $this->get_latest_release(), '>=' );
+ }
+
+ /**
+ * Gets the latest released version of Gutenberg.
+ *
+ * @return string The latest release.
+ */
+ protected function get_latest_release() {
+ return self::CURRENT_RELEASE;
+ }
+
+ /**
+ * Gets the minimum supported version of Gutenberg.
+ *
+ * @return string The minumum supported release.
+ */
+ protected function get_minimum_supported_version() {
+ return self::MINIMUM_SUPPORTED;
+ }
+
+ /**
+ * Detects the currently installed Gutenberg version.
+ *
+ * @return string The currently installed Gutenberg version. Empty if the version couldn't be detected.
+ */
+ protected function detect_installed_gutenberg_version() {
+ if ( defined( 'GUTENBERG_VERSION' ) ) {
+ return GUTENBERG_VERSION;
+ }
+
+ return '';
+ }
+}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-help-center-item.php b/wp-content/plugins/wordpress-seo/admin/class-help-center-item.php
deleted file mode 100644
index 7816a542..00000000
--- a/wp-content/plugins/wordpress-seo/admin/class-help-center-item.php
+++ /dev/null
@@ -1,96 +0,0 @@
-identifier = $identifier;
- $this->label = $label;
- $this->dashicon = $dashicon;
- $this->args = $args;
- }
-
- /**
- * Get the label.
- *
- * @return string
- */
- public function get_label() {
- return $this->label;
- }
-
- /**
- * Get the identifier.
- *
- * @return string
- */
- public function get_identifier() {
- return $this->identifier;
- }
-
- /**
- * Get the dashicon.
- *
- * @return string
- */
- public function get_dashicon() {
- return $this->dashicon;
- }
-
- /**
- * Get the content of this tab.
- *
- * @return mixed|string
- */
- public function get_content() {
- if ( ! empty( $this->args['content'] ) ) {
- return $this->args['content'];
- }
-
- if ( ! empty( $this->args['callback'] ) ) {
- return call_user_func_array( $this->args['callback'], array( $this ) );
- }
-
- if ( ! empty( $this->args['view'] ) ) {
- $view = $this->args['view'];
- if ( substr( $view, - 4 ) === '.php' ) {
- $view = substr( $view, 0, - 4 );
- }
-
- if ( ! empty( $this->args['view_arguments'] ) ) {
- extract( $this->args['view_arguments'] );
- }
-
- include WPSEO_PATH . 'admin/views/' . $view . '.php';
- }
-
- return '';
- }
-}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-help-center.php b/wp-content/plugins/wordpress-seo/admin/class-help-center.php
deleted file mode 100644
index 79006b19..00000000
--- a/wp-content/plugins/wordpress-seo/admin/class-help-center.php
+++ /dev/null
@@ -1,272 +0,0 @@
-premium_support = $premium_support;
-
- $tabs = new WPSEO_Option_Tabs( '' );
-
- if ( $option_tabs instanceof WPSEO_Option_Tabs ) {
- $tabs = $option_tabs;
- }
-
- if ( $option_tabs instanceof WPSEO_Option_Tab ) {
- $tabs = new WPSEO_Option_Tabs( '', $option_tabs->get_name() );
- $tabs->add_tab( $option_tabs );
- }
-
- $this->tabs = $tabs;
- }
-
- /**
- * Localize data required by the help center component.
- */
- public function localize_data() {
- $this->add_contact_support_item();
- $this->enqueue_localized_data( $this->format_data( $this->tabs->get_tabs() ) );
- }
-
- /**
- * Format the required data for localized script.
- *
- * @param WPSEO_Option_Tab[] $tabs Yoast admin pages navigational tabs.
- *
- * @return array Associative array containing data for help center component.
- */
- protected function format_data( array $tabs ) {
- $formatted_data = array( 'tabs' => array() );
-
- foreach ( $tabs as $tab ) {
- $formatted_data['tabs'][ $tab->get_name() ] = array(
- 'label' => $tab->get_label(),
- 'videoUrl' => $tab->get_video_url(),
- 'id' => $tab->get_name(),
- );
- }
-
- $active_tab = $this->tabs->get_active_tab();
- $active_tab = ( null === $active_tab ) ? $tabs[0] : $active_tab;
-
- $formatted_data['mountId'] = $this->identifier;
- $formatted_data['initialTab'] = $active_tab->get_name();
-
- $is_premium = WPSEO_Utils::is_yoast_seo_premium();
-
- // Will translate to either empty string or "1" in localised script.
- $formatted_data['isPremium'] = $is_premium;
- $formatted_data['pluginVersion'] = WPSEO_VERSION;
-
- // Open HelpScout on activating this tab ID.
- $formatted_data['shouldDisplayContactForm'] = $this->premium_support;
-
- $formatted_data['translations'] = self::get_translated_texts();
-
- $formatted_data['videoDescriptions'] = array(
- array(
- 'title' => __( 'Need some help?', 'wordpress-seo' ),
- 'description' => __( 'Go Premium and our experts will be there for you to answer any questions you might have about the setup and use of the plugin.', 'wordpress-seo' ),
- 'link' => WPSEO_Shortlinker::get( 'https://yoa.st/seo-premium-vt' ),
- 'linkText' => __( 'Get Yoast SEO Premium now »', 'wordpress-seo' ),
- ),
- array(
- 'title' => __( 'Want to be a Yoast SEO Expert?', 'wordpress-seo' ),
- 'description' => __( 'Follow our Yoast SEO for WordPress training and become a certified Yoast SEO Expert!', 'wordpress-seo' ),
- 'link' => WPSEO_Shortlinker::get( 'https://yoa.st/wordpress-training-vt' ),
- 'linkText' => __( 'Enroll in the Yoast SEO for WordPress training »', 'wordpress-seo' ),
- ),
- );
-
- $formatted_data['contactSupportParagraphs'] = array(
- array(
- 'image' => array(
- 'src' => esc_url( plugin_dir_url( WPSEO_FILE ) . 'images/support-team.svg' ),
- 'width' => 100,
- 'height' => 100,
- 'alt' => '',
- ),
- 'content' => null,
- ),
- array(
- 'image' => null,
- 'content' => __( 'If you have a problem that you can\'t solve with our video tutorials or knowledge base, you can send a message to our support team. They can be reached 24/7.', 'wordpress-seo' ),
- ),
- array(
- 'image' => null,
- 'content' => __( 'Support requests you create here are sent directly into our support system, which is secured with 256 bit SSL, so communication is 100% secure.', 'wordpress-seo' ),
- ),
- );
-
- $formatted_data['extraTabs'] = $this->get_extra_tabs();
-
- return $formatted_data;
- }
-
- /**
- * Get additional tabs for the help center component.
- *
- * @return array Additional help center tabs.
- */
- protected function get_extra_tabs() {
- $help_center_items = apply_filters( 'wpseo_help_center_items', $this->help_center_items );
-
- return array_map( array( $this, 'format_helpcenter_tab' ), $help_center_items );
- }
-
- /**
- * Convert WPSEO_Help_Center_Item into help center format.
- *
- * @param WPSEO_Help_Center_Item $item The item to convert.
- *
- * @return array Formatted item.
- */
- protected function format_helpcenter_tab( WPSEO_Help_Center_Item $item ) {
- return array(
- 'identifier' => $item->get_identifier(),
- 'label' => $item->get_label(),
- 'content' => $item->get_content(),
- );
- }
-
- /**
- * Enqueue localized script for help center component.
- *
- * @param array $data Data to localize.
- */
- protected function enqueue_localized_data( $data ) {
- wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'help-center', 'wpseoHelpCenterData', $data );
- }
-
- /**
- * Outputs the help center div.
- */
- public function mount() {
- echo '
' . esc_html__( 'Loading help center.', 'wordpress-seo' ) . '
';
- }
-
- /**
- * Add the contact support help center item to the help center.
- */
- private function add_contact_support_item() {
- /* translators: %s: expands to 'Yoast SEO Premium'. */
- $popup_title = sprintf( __( 'Email support is a %s feature', 'wordpress-seo' ), 'Yoast SEO Premium' );
- $popup_content = '
' . __( 'Go Premium and our experts will be there for you to answer any questions you might have about the set-up and use of the plug-in!', 'wordpress-seo' ) . '
';
- /* translators: %1$s: expands to 'Yoast SEO Premium'. */
- $popup_content .= '
' . sprintf( __( 'Other benefits of %1$s for you:', 'wordpress-seo' ), 'Yoast SEO Premium' ) . '
';
- $popup_content .= '
';
- $popup_content .= '
' . sprintf(
- // We don't use strong text here, but we do use it in the "Add keyword" popup, this is just to have the same translatable strings.
- /* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */
- __( '%1$sNo more dead links%2$s: easy redirect manager', 'wordpress-seo' ), '', ''
- ) . '
' . sprintf(
- // We don't use strong text here, but we do use it in the "Add keyword" popup, this is just to have the same translatable strings.
- /* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */
- __( '%1$sSocial media preview%2$s: Facebook & Twitter', 'wordpress-seo' ), '', ''
- ) . '
';
- $popup_content .= '
' . __( '24/7 support', 'wordpress-seo' ) . '
';
- $popup_content .= '
' . __( 'No ads!', 'wordpress-seo' ) . '
';
- $popup_content .= '
';
-
- $premium_popup = new WPSEO_Premium_Popup( 'contact-support', 'h2', $popup_title, $popup_content, WPSEO_Shortlinker::get( 'https://yoa.st/contact-support' ) );
- $contact_support_help_center_item = new WPSEO_Help_Center_Item(
- 'contact-support',
- __( 'Get support', 'wordpress-seo' ),
- array( 'content' => $premium_popup->get_premium_message( false ) ),
- 'dashicons-email-alt'
- );
-
- $this->help_center_items[] = $contact_support_help_center_item;
- }
-
- /**
- * Pass text variables to js for the help center JS module.
- *
- * %s is replaced with %s and replaced again in the javascript with the actual variable.
- *
- * @return array Translated text strings for the help center.
- */
- public static function get_translated_texts() {
- // Esc_html is not needed because React already handles HTML in the (translations of) these strings.
- return array(
- 'locale' => WPSEO_Utils::get_user_locale(),
- 'videoTutorial' => __( 'Video tutorial', 'wordpress-seo' ),
- 'knowledgeBase' => __( 'Knowledge base', 'wordpress-seo' ),
- 'getSupport' => __( 'Get support', 'wordpress-seo' ),
- 'algoliaSearcher.loadingPlaceholder' => __( 'Loading...', 'wordpress-seo' ),
- 'algoliaSearcher.errorMessage' => __( 'Something went wrong. Please try again later.', 'wordpress-seo' ),
- 'searchBar.headingText' => __( 'Search the Yoast Knowledge Base for answers to your questions:', 'wordpress-seo' ),
- 'searchBar.placeholderText' => __( 'Type here to search...', 'wordpress-seo' ),
- 'searchBar.buttonText' => __( 'Search', 'wordpress-seo' ),
- 'searchResultDetail.openButton' => __( 'View in KB', 'wordpress-seo' ),
- 'searchResultDetail.openButtonLabel' => __( 'Open the knowledge base article in a new window or read it in the iframe below', 'wordpress-seo' ),
- 'searchResultDetail.backButton' => __( 'Go back', 'wordpress-seo' ),
- 'searchResultDetail.backButtonLabel' => __( 'Go back to the search results', 'wordpress-seo' ),
- 'searchResultDetail.iframeTitle' => __( 'Knowledge base article', 'wordpress-seo' ),
- 'searchResultDetail.searchResult' => __( 'Search result', 'wordpress-seo' ),
- 'searchResult.noResultsText' => __( 'No results found.', 'wordpress-seo' ),
- 'searchResult.foundResultsText' => sprintf(
- /* translators: %s expands to the number of results found . */
- __( 'Number of results found: %s', 'wordpress-seo' ),
- '{ resultsCount }'
- ),
- 'searchResult.searchResultsHeading' => __( 'Search results', 'wordpress-seo' ),
- 'a11yNotice.opensInNewTab' => __( '(Opens in a new browser tab)', 'wordpress-seo' ),
- 'contactSupport.button' => __( 'New support request', 'wordpress-seo' ),
- 'helpCenter.buttonText' => __( 'Need help?', 'wordpress-seo' ),
- );
- }
-
- /**
- * Outputs the help center.
- *
- * @deprecated 5.6
- */
- public function output_help_center() {
- _deprecated_function( 'WPSEO_Help_Center::output_help_center', 'WPSEO 5.6.0', 'WPSEO_Help_Center::mount()' );
- $this->mount();
- }
-}
diff --git a/wp-content/plugins/wordpress-seo/admin/class-helpscout.php b/wp-content/plugins/wordpress-seo/admin/class-helpscout.php
new file mode 100644
index 00000000..aef7057e
--- /dev/null
+++ b/wp-content/plugins/wordpress-seo/admin/class-helpscout.php
@@ -0,0 +1,265 @@
+beacon_id = $beacon_id;
+ $this->pages = $pages;
+ $this->products = $products;
+ $this->ask_consent = $ask_consent;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function register_hooks() {
+ if ( ! $this->is_beacon_page() ) {
+ return;
+ }
+
+ add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_help_scout_script' ] );
+ add_action( 'admin_footer', [ $this, 'output_beacon_js' ] );
+ }
+
+ /**
+ * Enqueues the HelpScout script.
+ */
+ public function enqueue_help_scout_script() {
+ $asset_manager = new WPSEO_Admin_Asset_Manager();
+ $asset_manager->enqueue_script( 'help-scout-beacon' );
+ }
+
+ /**
+ * Outputs a small piece of javascript for the beacon.
+ */
+ public function output_beacon_js() {
+ printf(
+ '',
+ ( $this->ask_consent ) ? 'wpseoHelpScoutBeaconConsent' : 'wpseoHelpScoutBeacon',
+ esc_html( $this->beacon_id ),
+ WPSEO_Utils::format_json_encode( $this->get_session_data() )
+ );
+ }
+
+ /**
+ * Checks if the current page is a page containing the beacon.
+ *
+ * @return bool
+ */
+ private function is_beacon_page() {
+ return in_array( $this->get_current_page(), $this->pages, true );
+ }
+
+ /**
+ * Retrieves the value of the current page.
+ *
+ * @return string The current page.
+ */
+ private function get_current_page() {
+ $page = filter_input( INPUT_GET, 'page' );
+ if ( isset( $page ) && $page !== false ) {
+ return $page;
+ }
+
+ return '';
+ }
+
+ /**
+ * Retrieves the identifying data.
+ *
+ * @return string The data to pass as identifying data.
+ */
+ protected function get_session_data() {
+ /** @noinspection PhpUnusedLocalVariableInspection */
+ // Do not make these strings translatable! They are for our support agents, the user won't see them!
+ $current_user = wp_get_current_user();
+
+ $data = [
+ 'name' => trim( $current_user->user_firstname . ' ' . $current_user->user_lastname ),
+ 'email' => $current_user->user_email,
+ 'WordPress Version' => $this->get_wordpress_version(),
+ 'Server' => $this->get_server_info(),
+ 'Theme' => $this->get_theme_info(),
+ 'Plugins' => $this->get_active_plugins(),
+ ];
+
+ if ( ! empty( $this->products ) ) {
+ $addon_manager = new WPSEO_Addon_Manager();
+ foreach ( $this->products as $product ) {
+ $subscription = $addon_manager->get_subscription( $product );
+
+ if ( ! $subscription ) {
+ continue;
+ }
+
+ $data[ $subscription->product->name ] = $this->get_product_info( $subscription );
+ }
+ }
+
+ return WPSEO_Utils::format_json_encode( $data );
+ }
+
+ /**
+ * Returns basic info about the server software.
+ *
+ * @return string
+ */
+ private function get_server_info() {
+ $server_tracking_data = new WPSEO_Tracking_Server_Data();
+ $server_data = $server_tracking_data->get();
+ $server_data = $server_data['server'];
+
+ $fields_to_use = [
+ 'IP' => 'ip',
+ 'Hostname' => 'Hostname',
+ 'OS' => 'os',
+ 'PHP' => 'PhpVersion',
+ 'CURL' => 'CurlVersion',
+ ];
+
+ $server_data['CurlVersion'] = $server_data['CurlVersion']['version'] . '(SSL Support' . $server_data['CurlVersion']['sslSupport'] . ')';
+
+ $server_info = '