Yoast SEO update
This commit is contained in:
parent
f2c2e26638
commit
d30e180e77
1569 changed files with 96960 additions and 36354 deletions
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* A WordPress integration that listens for whether the SEO changes have been saved successfully.
|
||||
*/
|
||||
class WPSEO_Admin_Settings_Changed_Listener implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* Have the Yoast SEO settings been saved.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private static $settings_saved = false;
|
||||
|
||||
/**
|
||||
* Registers all hooks to WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
add_action( 'admin_init', [ $this, 'intercept_save_update_notification' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks and overwrites the wp_settings_errors global to determine whether the Yoast SEO settings have been saved.
|
||||
*/
|
||||
public function intercept_save_update_notification() {
|
||||
global $pagenow;
|
||||
|
||||
if ( $pagenow !== 'admin.php' || ! YoastSEO()->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 '<p class="wpseo-message"><span class="dashicons dashicons-yes"></span>',
|
||||
esc_html__( 'Settings saved.', 'wordpress-seo' ),
|
||||
'</p>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,16 +12,13 @@ if ( ! defined( 'WPSEO_VERSION' ) ) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @todo this whole thing should probably be a proper class.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convenience function to JSON encode and echo results and then die
|
||||
* Convenience function to JSON encode and echo results and then die.
|
||||
*
|
||||
* @param array $results Results array for encoding.
|
||||
*/
|
||||
function wpseo_ajax_json_echo_die( $results ) {
|
||||
echo wp_json_encode( $results );
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
|
||||
echo WPSEO_Utils::format_json_encode( $results );
|
||||
die();
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +46,7 @@ add_action( 'wp_ajax_wpseo_set_option', 'wpseo_set_option' );
|
|||
/**
|
||||
* Since 3.2 Notifications are dismissed in the Notification Center.
|
||||
*/
|
||||
add_action( 'wp_ajax_yoast_dismiss_notification', array( 'Yoast_Notification_Center', 'ajax_dismiss_notification' ) );
|
||||
add_action( 'wp_ajax_yoast_dismiss_notification', [ 'Yoast_Notification_Center', 'ajax_dismiss_notification' ] );
|
||||
|
||||
/**
|
||||
* Function used to remove the admin notices for several purposes, dies on exit.
|
||||
|
|
@ -69,42 +66,6 @@ function wpseo_set_ignore() {
|
|||
|
||||
add_action( 'wp_ajax_wpseo_set_ignore', 'wpseo_set_ignore' );
|
||||
|
||||
/**
|
||||
* Hides the default tagline notice for a specific user.
|
||||
*/
|
||||
function wpseo_dismiss_tagline_notice() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
die( '-1' );
|
||||
}
|
||||
|
||||
check_ajax_referer( 'wpseo-dismiss-tagline-notice' );
|
||||
|
||||
update_user_meta( get_current_user_id(), 'wpseo_seen_tagline_notice', 'seen' );
|
||||
|
||||
die( '1' );
|
||||
}
|
||||
|
||||
add_action( 'wp_ajax_wpseo_dismiss_tagline_notice', 'wpseo_dismiss_tagline_notice' );
|
||||
|
||||
/**
|
||||
* Used in the editor to replace vars for the snippet preview
|
||||
*/
|
||||
function wpseo_ajax_replace_vars() {
|
||||
global $post;
|
||||
check_ajax_referer( 'wpseo-replace-vars' );
|
||||
|
||||
$post = get_post( intval( filter_input( INPUT_POST, 'post_id' ) ) );
|
||||
global $wp_query;
|
||||
$wp_query->queried_object = $post;
|
||||
$wp_query->queried_object_id = $post->ID;
|
||||
|
||||
$omit = array( 'excerpt', 'excerpt_only', 'title' );
|
||||
echo wpseo_replace_vars( stripslashes( filter_input( INPUT_POST, 'string' ) ), $post, $omit );
|
||||
die;
|
||||
}
|
||||
|
||||
add_action( 'wp_ajax_wpseo_replace_vars', 'wpseo_ajax_replace_vars' );
|
||||
|
||||
/**
|
||||
* Save an individual SEO title from the Bulk Editor.
|
||||
*/
|
||||
|
|
@ -124,7 +85,7 @@ function wpseo_save_description() {
|
|||
add_action( 'wp_ajax_wpseo_save_metadesc', 'wpseo_save_description' );
|
||||
|
||||
/**
|
||||
* Save titles & descriptions
|
||||
* Save titles & descriptions.
|
||||
*
|
||||
* @param string $what Type of item to save (title, description).
|
||||
*/
|
||||
|
|
@ -158,12 +119,12 @@ function wpseo_upsert_meta( $post_id, $new_meta_value, $orig_meta_value, $meta_k
|
|||
$sanitized_new_meta_value = wp_strip_all_tags( $new_meta_value );
|
||||
$orig_meta_value = wp_strip_all_tags( $orig_meta_value );
|
||||
|
||||
$upsert_results = array(
|
||||
$upsert_results = [
|
||||
'status' => 'success',
|
||||
'post_id' => $post_id,
|
||||
"new_{$return_key}" => $sanitized_new_meta_value,
|
||||
"original_{$return_key}" => $orig_meta_value,
|
||||
);
|
||||
];
|
||||
|
||||
$the_post = get_post( $post_id );
|
||||
if ( empty( $the_post ) ) {
|
||||
|
|
@ -209,7 +170,6 @@ function wpseo_upsert_meta( $post_id, $new_meta_value, $orig_meta_value, $meta_k
|
|||
);
|
||||
|
||||
return $upsert_results;
|
||||
|
||||
}
|
||||
|
||||
if ( $sanitized_new_meta_value === $orig_meta_value && $sanitized_new_meta_value !== $new_meta_value ) {
|
||||
|
|
@ -246,30 +206,31 @@ function wpseo_save_all_descriptions() {
|
|||
add_action( 'wp_ajax_wpseo_save_all_descriptions', 'wpseo_save_all_descriptions' );
|
||||
|
||||
/**
|
||||
* Utility function to save values
|
||||
* Utility function to save values.
|
||||
*
|
||||
* @param string $what Type of item so save.
|
||||
*/
|
||||
function wpseo_save_all( $what ) {
|
||||
check_ajax_referer( 'wpseo-bulk-editor' );
|
||||
|
||||
// @todo the WPSEO Utils class can't filter arrays in POST yet.
|
||||
$new_values = $_POST['items'];
|
||||
$original_values = $_POST['existing_items'];
|
||||
|
||||
$results = array();
|
||||
|
||||
if ( is_array( $new_values ) && $new_values !== array() ) {
|
||||
foreach ( $new_values as $post_id => $new_value ) {
|
||||
$original_value = $original_values[ $post_id ];
|
||||
$results[] = wpseo_upsert_new( $what, $post_id, $new_value, $original_value );
|
||||
}
|
||||
$results = [];
|
||||
if ( ! isset( $_POST['items'], $_POST['existingItems'] ) ) {
|
||||
wpseo_ajax_json_echo_die( $results );
|
||||
}
|
||||
|
||||
$new_values = array_map( [ 'WPSEO_Utils', 'sanitize_text_field' ], wp_unslash( (array) $_POST['items'] ) );
|
||||
$original_values = array_map( [ 'WPSEO_Utils', 'sanitize_text_field' ], wp_unslash( (array) $_POST['existingItems'] ) );
|
||||
|
||||
foreach ( $new_values as $post_id => $new_value ) {
|
||||
$original_value = $original_values[ $post_id ];
|
||||
$results[] = wpseo_upsert_new( $what, $post_id, $new_value, $original_value );
|
||||
}
|
||||
|
||||
wpseo_ajax_json_echo_die( $results );
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new value
|
||||
* Insert a new value.
|
||||
*
|
||||
* @param string $what Item type (such as title).
|
||||
* @param int $post_id Post ID.
|
||||
|
|
@ -296,7 +257,8 @@ function ajax_get_keyword_usage() {
|
|||
}
|
||||
|
||||
wp_die(
|
||||
wp_json_encode( WPSEO_Meta::keyword_usage( $keyword, $post_id ) )
|
||||
// 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 ) )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -326,64 +288,45 @@ function ajax_get_term_keyword_usage() {
|
|||
$usage = $usage[ $keyword ];
|
||||
|
||||
wp_die(
|
||||
wp_json_encode( $usage )
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
|
||||
WPSEO_Utils::format_json_encode( $usage )
|
||||
);
|
||||
}
|
||||
|
||||
add_action( 'wp_ajax_get_term_keyword_usage', 'ajax_get_term_keyword_usage' );
|
||||
|
||||
// Crawl Issue Manager AJAX hooks.
|
||||
new WPSEO_GSC_Ajax();
|
||||
/**
|
||||
* Registers hooks for all AJAX integrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function wpseo_register_ajax_integrations() {
|
||||
$integrations = [ new Yoast_Network_Admin() ];
|
||||
|
||||
// SEO Score Recalculations.
|
||||
new WPSEO_Recalculate_Scores_Ajax();
|
||||
foreach ( $integrations as $integration ) {
|
||||
$integration->register_ajax_hooks();
|
||||
}
|
||||
}
|
||||
|
||||
new Yoast_OnPage_Ajax();
|
||||
wpseo_register_ajax_integrations();
|
||||
|
||||
new WPSEO_Shortcode_Filter();
|
||||
|
||||
new WPSEO_Taxonomy_Columns();
|
||||
|
||||
// Setting the notice for the recalculate the posts.
|
||||
new Yoast_Dismissable_Notice_Ajax( 'recalculate', Yoast_Dismissable_Notice_Ajax::FOR_SITE );
|
||||
|
||||
/********************** DEPRECATED METHODS **********************/
|
||||
|
||||
/* ********************* DEPRECATED FUNCTIONS ********************* */
|
||||
|
||||
/**
|
||||
* Removes stopword from the sample permalink that is generated in an AJAX request
|
||||
* Hides the default tagline notice for a specific user.
|
||||
*
|
||||
* @deprecated 6.3
|
||||
* @deprecated 13.2
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
function wpseo_remove_stopwords_sample_permalink() {
|
||||
_deprecated_function( __FUNCTION__, 'WPSEO 6.3', 'This method is deprecated.' );
|
||||
|
||||
wpseo_ajax_json_echo_die( '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to delete blocking files, dies on exit.
|
||||
*
|
||||
* @deprecated 7.0
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
function wpseo_kill_blocking_files() {
|
||||
_deprecated_function( __FUNCTION__, 'WPSEO 7.0', 'This method is deprecated.' );
|
||||
|
||||
wpseo_ajax_json_echo_die( '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the posting of a new FB admin.
|
||||
*
|
||||
* @deprecated 7.1
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
function wpseo_add_fb_admin() {
|
||||
function wpseo_dismiss_tagline_notice() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
die( '-1' );
|
||||
}
|
||||
_deprecated_function( __FUNCTION__, 'WPSEO 7.0', 'This method is deprecated.' );
|
||||
|
||||
_deprecated_function( __FUNCTION__, 'WPSEO 13.2', 'This method is deprecated.' );
|
||||
wpseo_ajax_json_echo_die( '' );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,121 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Ajax
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Recalculate_Scores
|
||||
*
|
||||
* This class handles the SEO score recalculation for all posts with a filled focus keyword
|
||||
*/
|
||||
class WPSEO_Recalculate_Scores_Ajax {
|
||||
|
||||
/**
|
||||
* Initialize the AJAX hooks
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'wp_ajax_wpseo_recalculate_scores', array( $this, 'recalculate_scores' ) );
|
||||
add_action( 'wp_ajax_wpseo_update_score', array( $this, 'save_score' ) );
|
||||
add_action( 'wp_ajax_wpseo_recalculate_total', array( $this, 'get_total' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the totals for the posts and the terms.
|
||||
*/
|
||||
public function get_total() {
|
||||
check_ajax_referer( 'wpseo_recalculate', 'nonce' );
|
||||
|
||||
wp_die(
|
||||
wp_json_encode(
|
||||
array(
|
||||
'posts' => $this->calculate_posts(),
|
||||
'terms' => $this->calculate_terms(),
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start recalculation
|
||||
*/
|
||||
public function recalculate_scores() {
|
||||
check_ajax_referer( 'wpseo_recalculate', 'nonce' );
|
||||
|
||||
$fetch_object = $this->get_fetch_object();
|
||||
if ( ! empty( $fetch_object ) ) {
|
||||
$paged = filter_input( INPUT_POST, 'paged', FILTER_VALIDATE_INT );
|
||||
$response = $fetch_object->get_items_to_recalculate( $paged );
|
||||
|
||||
if ( ! empty( $response ) ) {
|
||||
wp_die( wp_json_encode( $response ) );
|
||||
}
|
||||
}
|
||||
|
||||
wp_die( '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the new linkdex score for given post
|
||||
*/
|
||||
public function save_score() {
|
||||
check_ajax_referer( 'wpseo_recalculate', 'nonce' );
|
||||
|
||||
$fetch_object = $this->get_fetch_object();
|
||||
if ( ! empty( $fetch_object ) ) {
|
||||
$scores = filter_input( INPUT_POST, 'scores', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
|
||||
$fetch_object->save_scores( $scores );
|
||||
}
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the needed object for recalculating scores.
|
||||
*
|
||||
* @return WPSEO_Recalculate_Posts|WPSEO_Recalculate_Terms
|
||||
*/
|
||||
private function get_fetch_object() {
|
||||
switch ( filter_input( INPUT_POST, 'type' ) ) {
|
||||
case 'post':
|
||||
return new WPSEO_Recalculate_Posts();
|
||||
case 'term':
|
||||
return new WPSEO_Recalculate_Terms();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total number of posts
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function calculate_posts() {
|
||||
$count_posts_query = new WP_Query(
|
||||
array(
|
||||
'post_type' => 'any',
|
||||
'meta_key' => '_yoast_wpseo_focuskw',
|
||||
'posts_per_page' => 1,
|
||||
'fields' => 'ids',
|
||||
)
|
||||
);
|
||||
|
||||
return $count_posts_query->found_posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of terms
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function calculate_terms() {
|
||||
$total = 0;
|
||||
foreach ( get_taxonomies( array(), 'objects' ) as $taxonomy ) {
|
||||
$total += wp_count_terms( $taxonomy->name, array( 'hide_empty' => false ) );
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
}
|
||||
|
|
@ -6,36 +6,37 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Shortcode_Filter
|
||||
* Class WPSEO_Shortcode_Filter.
|
||||
*
|
||||
* Used for parsing WP shortcodes with AJAX
|
||||
* Used for parsing WP shortcodes with AJAX.
|
||||
*/
|
||||
class WPSEO_Shortcode_Filter {
|
||||
|
||||
/**
|
||||
* Initialize the AJAX hooks
|
||||
* Initialize the AJAX hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'wp_ajax_wpseo_filter_shortcodes', array( $this, 'do_filter' ) );
|
||||
add_action( 'wp_ajax_wpseo_filter_shortcodes', [ $this, 'do_filter' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the shortcodes
|
||||
* Parse the shortcodes.
|
||||
*/
|
||||
public function do_filter() {
|
||||
check_ajax_referer( 'wpseo-filter-shortcodes', 'nonce' );
|
||||
|
||||
$shortcodes = filter_input( INPUT_POST, 'data', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY );
|
||||
|
||||
$parsed_shortcodes = array();
|
||||
$parsed_shortcodes = [];
|
||||
|
||||
foreach ( $shortcodes as $shortcode ) {
|
||||
$parsed_shortcodes[] = array(
|
||||
$parsed_shortcodes[] = [
|
||||
'shortcode' => $shortcode,
|
||||
'output' => do_shortcode( $shortcode ),
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
wp_die( wp_json_encode( $parsed_shortcodes ) );
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: WPSEO_Utils::format_json_encode is considered safe.
|
||||
wp_die( WPSEO_Utils::format_json_encode( $parsed_shortcodes ) );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,39 +6,48 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* This class will catch the request to dismiss the target notice (set by notice_name) and will store the dismiss status as an user meta
|
||||
* in the database
|
||||
* This class will catch the request to dismiss the target notice (set by notice_name)
|
||||
* and will store the dismiss status as an user meta in the database.
|
||||
*/
|
||||
class Yoast_Dismissable_Notice_Ajax {
|
||||
|
||||
/**
|
||||
* @var string Notice type toggle value for user notices.
|
||||
* Notice type toggle value for user notices.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FOR_USER = 'user_meta';
|
||||
|
||||
/**
|
||||
* @var string Notice type toggle value for network notices.
|
||||
* Notice type toggle value for network notices.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FOR_NETWORK = 'site_option';
|
||||
|
||||
/**
|
||||
* @var string Notice type toggle value for site notices.
|
||||
* Notice type toggle value for site notices.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const FOR_SITE = 'option';
|
||||
|
||||
|
||||
/**
|
||||
* @var string Name of the notice that will be dismissed.
|
||||
* Name of the notice that will be dismissed.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $notice_name;
|
||||
|
||||
/**
|
||||
* The type of the current notice.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $notice_type;
|
||||
|
||||
/**
|
||||
* Initialize the hooks for the AJAX request
|
||||
* Initialize the hooks for the AJAX request.
|
||||
*
|
||||
* @param string $notice_name The name for the hook to catch the notice.
|
||||
* @param string $notice_type The notice type.
|
||||
|
|
@ -47,11 +56,11 @@ class Yoast_Dismissable_Notice_Ajax {
|
|||
$this->notice_name = $notice_name;
|
||||
$this->notice_type = $notice_type;
|
||||
|
||||
add_action( 'wp_ajax_wpseo_dismiss_' . $notice_name, array( $this, 'dismiss_notice' ) );
|
||||
add_action( 'wp_ajax_wpseo_dismiss_' . $notice_name, [ $this, 'dismiss_notice' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the dismiss notice request
|
||||
* Handles the dismiss notice request.
|
||||
*/
|
||||
public function dismiss_notice() {
|
||||
check_ajax_referer( 'wpseo-dismiss-' . $this->notice_name );
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Ajax
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class Yoast_OnPage_Ajax
|
||||
*
|
||||
* This class will catch the request to dismiss the Ryte notice and will store
|
||||
* the dismiss status as an user meta in the database.
|
||||
*/
|
||||
class Yoast_OnPage_Ajax {
|
||||
|
||||
/**
|
||||
* Initialize the hooks for the AJAX request
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'wp_ajax_wpseo_dismiss_onpageorg', array( $this, 'dismiss_notice' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the dismiss notice request
|
||||
*/
|
||||
public function dismiss_notice() {
|
||||
check_ajax_referer( 'wpseo-dismiss-onpageorg' );
|
||||
|
||||
$this->save_dismissed();
|
||||
|
||||
wp_die( 'true' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Storing the dismissed value as an user option in the database
|
||||
*/
|
||||
private function save_dismissed() {
|
||||
update_user_meta( get_current_user_id(), WPSEO_OnPage::USER_META_KEY, 1 );
|
||||
}
|
||||
}
|
||||
|
|
@ -6,29 +6,33 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class Yoast_Plugin_Conflict_Ajax
|
||||
* Class Yoast_Plugin_Conflict_Ajax.
|
||||
*/
|
||||
class Yoast_Plugin_Conflict_Ajax {
|
||||
|
||||
/**
|
||||
* Option identifier where dismissed conflicts are stored.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $option_name = 'wpseo_dismissed_conflicts';
|
||||
|
||||
/**
|
||||
* List of notification identifiers that have been dismissed.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $dismissed_conflicts = array();
|
||||
private $dismissed_conflicts = [];
|
||||
|
||||
/**
|
||||
* Initialize the hooks for the AJAX request
|
||||
* Initialize the hooks for the AJAX request.
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'wp_ajax_wpseo_dismiss_plugin_conflict', array( $this, 'dismiss_notice' ) );
|
||||
add_action( 'wp_ajax_wpseo_dismiss_plugin_conflict', [ $this, 'dismiss_notice' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the dismiss notice request
|
||||
* Handles the dismiss notice request.
|
||||
*/
|
||||
public function dismiss_notice() {
|
||||
check_ajax_referer( 'dismiss-plugin-conflict' );
|
||||
|
|
@ -45,7 +49,7 @@ class Yoast_Plugin_Conflict_Ajax {
|
|||
}
|
||||
|
||||
/**
|
||||
* Getting the user option from the database
|
||||
* Getting the user option from the database.
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
|
|
@ -67,11 +71,11 @@ class Yoast_Plugin_Conflict_Ajax {
|
|||
return $dismissed_conflicts[ $plugin_section ];
|
||||
}
|
||||
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Storing the conflicting plugins as an user option in the database
|
||||
* Storing the conflicting plugins as an user option in the database.
|
||||
*
|
||||
* @param string $plugin_section Plugin conflict type (such as Open Graph or sitemap).
|
||||
*/
|
||||
|
|
@ -84,7 +88,7 @@ class Yoast_Plugin_Conflict_Ajax {
|
|||
}
|
||||
|
||||
/**
|
||||
* Loop through the plugins to compare them with the already stored dismissed plugin conflicts
|
||||
* Loop through the plugins to compare them with the already stored dismissed plugin conflicts.
|
||||
*
|
||||
* @param array $posted_plugins Plugin set to check.
|
||||
*/
|
||||
|
|
@ -95,7 +99,7 @@ class Yoast_Plugin_Conflict_Ajax {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if plugin is already dismissed, if not store it in the array that will be saved later
|
||||
* Check if plugin is already dismissed, if not store it in the array that will be saved later.
|
||||
*
|
||||
* @param string $posted_plugin Plugin to check against dismissed conflicts.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Banner
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the render object for generating the html for the given banner.
|
||||
*/
|
||||
class WPSEO_Admin_Banner_Renderer {
|
||||
|
||||
/** @var string */
|
||||
protected $base_path = '';
|
||||
|
||||
/**
|
||||
* Renders the admin banner.
|
||||
*
|
||||
* @param WPSEO_Admin_Banner $banner The banner to render.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render( WPSEO_Admin_Banner $banner ) {
|
||||
$output = '<a class="wpseo-banner__link" target="_blank" href="' . esc_url( $banner->get_url() ) . '">';
|
||||
$output .= '<img class="wpseo-banner__image" width="' . esc_attr( $banner->get_width() ) . '" height="' . esc_attr( $banner->get_height() ) . '" src="' . esc_attr( $this->get_image_path( $banner->get_image() ) ) . '" alt="' . esc_attr( $banner->get_alt() ) . '"/>';
|
||||
$output .= '</a>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the base path, where the images are located.
|
||||
*
|
||||
* @param string $base_path The image location.
|
||||
*/
|
||||
public function set_base_path( $base_path ) {
|
||||
$this->base_path = $base_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path for the image.
|
||||
*
|
||||
* @param string $image The image path.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_image_path( $image ) {
|
||||
return rtrim( $this->base_path, '/' ) . '/' . ltrim( $image, '/' );
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Banner
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the render object for generating the html for the banner sidebar
|
||||
*/
|
||||
class WPSEO_Admin_Banner_Sidebar_Renderer {
|
||||
|
||||
/** @var WPSEO_Admin_Banner_Spot_Renderer */
|
||||
protected $spot_renderer;
|
||||
|
||||
/**
|
||||
* Sets the spot renderer.
|
||||
*
|
||||
* @param WPSEO_Admin_Banner_Spot_Renderer $spot_renderer The spot renderer that has to be used.
|
||||
*/
|
||||
public function __construct( WPSEO_Admin_Banner_Spot_Renderer $spot_renderer ) {
|
||||
$this->spot_renderer = $spot_renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the admin banner sidebar.
|
||||
*
|
||||
* @param WPSEO_Admin_Banner_Sidebar $banner_sidebar The sidebar to render.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render( WPSEO_Admin_Banner_Sidebar $banner_sidebar ) {
|
||||
return sprintf( '
|
||||
<div class="wpseo_content_cell" id="sidebar-container">
|
||||
<div id="sidebar">
|
||||
<div class="wpseo_content_cell_title yoast-sidebar__title ">
|
||||
%1$s
|
||||
</div>
|
||||
%2$s
|
||||
</div>
|
||||
</div>',
|
||||
$banner_sidebar->get_title(),
|
||||
$this->render_banner_spots( $banner_sidebar->get_banner_spots() )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the admin banner spots.
|
||||
*
|
||||
* @param WPSEO_Admin_Banner_Spot[] $banner_spots The banner spots to render.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function render_banner_spots( array $banner_spots ) {
|
||||
$return = '';
|
||||
foreach ( $banner_spots as $banner_spot ) {
|
||||
$return .= $this->spot_renderer->render( $banner_spot );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,348 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Banner
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the render object for generating the html for the given banner.
|
||||
*/
|
||||
class WPSEO_Admin_Banner_Sidebar {
|
||||
|
||||
/** @var string */
|
||||
protected $title = '';
|
||||
|
||||
/** @var WPSEO_Admin_Banner_Spot[] */
|
||||
protected $banner_spots = array();
|
||||
|
||||
/** @var WPSEO_Admin_Banner_Renderer */
|
||||
protected $banner_renderer;
|
||||
|
||||
/**
|
||||
* WPSEO_Admin_Banner_Sidebar constructor.
|
||||
*
|
||||
* @param string $title The title for the sidebar.
|
||||
* @param WPSEO_Admin_Banner_Renderer $banner_renderer The render class for banners.
|
||||
*/
|
||||
public function __construct( $title, WPSEO_Admin_Banner_Renderer $banner_renderer ) {
|
||||
$this->title = $title;
|
||||
$this->banner_renderer = $banner_renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the banner sidebar by setting its banner spots.
|
||||
*
|
||||
* @param WPSEO_Features $features Class regarding WPSEO Features.
|
||||
*/
|
||||
public function initialize( WPSEO_Features $features ) {
|
||||
if ( $features->is_free() ) {
|
||||
$this->add_banner_spot( $this->get_premium_spot() );
|
||||
}
|
||||
|
||||
$this->add_banner_spot( $this->get_services_spot() );
|
||||
|
||||
$extensions_spot = $this->get_extensions_spot( $this->get_active_extensions() );
|
||||
if ( $extensions_spot->has_banners() ) {
|
||||
$this->add_banner_spot( $extensions_spot );
|
||||
}
|
||||
|
||||
$this->add_banner_spot( $this->get_courses_spot() );
|
||||
$this->add_banner_spot( $this->get_remove_banner_spot() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array with bannerspots.
|
||||
*
|
||||
* @return WPSEO_Admin_Banner_Spot[]
|
||||
*/
|
||||
public function get_banner_spots() {
|
||||
return $this->banner_spots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a banner spot.
|
||||
*
|
||||
* @param WPSEO_Admin_Banner_Spot $spot The spot to add.
|
||||
*/
|
||||
protected function add_banner_spot( WPSEO_Admin_Banner_Spot $spot ) {
|
||||
$this->banner_spots[] = $spot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the premium banner spot.
|
||||
*
|
||||
* @return WPSEO_Admin_Banner_Spot
|
||||
*/
|
||||
protected function get_premium_spot() {
|
||||
$premium_spot = new WPSEO_Admin_Banner_Spot( '', $this->banner_renderer );
|
||||
|
||||
$premium_uri = WPSEO_Shortlinker::get( 'https://yoa.st/jj' );
|
||||
|
||||
$premium_spot->set_extra(
|
||||
/* translators: %1$s expands to the plugin name */
|
||||
'<h2>' . sprintf( esc_html__( 'Upgrade to %1$s', 'wordpress-seo' ), 'Yoast SEO Premium' ) . '</h2>' .
|
||||
'<ul>' .
|
||||
'<li><strong>' . esc_html__( 'Rank for up to 5 focus keywords per page', 'wordpress-seo' ) . '</strong></li>' .
|
||||
'<li><strong>' . esc_html__( 'Preview your page in Facebook and Twitter', 'wordpress-seo' ) . '</strong></li>' .
|
||||
'<li><strong>' . esc_html__( 'Get real-time suggestions for internal links', 'wordpress-seo' ) . '</strong></li>' .
|
||||
'<li><strong>' . esc_html__( 'No more dead links a.k.a. 404 pages', 'wordpress-seo' ) . '</strong></li>' .
|
||||
'<li><strong>' . esc_html__( '24/7 email support', 'wordpress-seo' ) . '</strong></li>' .
|
||||
'<li><strong>' . esc_html__( 'No ads', 'wordpress-seo' ) . '</strong></li>' .
|
||||
'</ul>' .
|
||||
/* translators: %s expands to Yoast SEO Premium */
|
||||
'<a id="wpseo-premium-button" class="button button-primary" href="' . $premium_uri . '" target="_blank">' . sprintf( __( 'Get %s now', 'wordpress-seo' ), 'Yoast SEO Premium' ) . '</a><br/>'
|
||||
);
|
||||
|
||||
return $premium_spot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the services banner spot.
|
||||
*
|
||||
* @return WPSEO_Admin_Banner_Spot
|
||||
*/
|
||||
protected function get_services_spot() {
|
||||
$service_spot = new WPSEO_Admin_Banner_Spot( __( 'Services', 'wordpress-seo' ), $this->banner_renderer );
|
||||
|
||||
$service_spot->set_description(
|
||||
sprintf(
|
||||
/* translators: %1$s expands to a link start tag to the Yoast Services page, %2$s to Yoast, %3$s is the link closing tag. */
|
||||
__( 'Do you want to know how to improve your rankings? %1$sLet team %2$s help you!%3$s', 'wordpress-seo' ),
|
||||
'<a target="_blank" href="' . WPSEO_Shortlinker::get( 'https://yoa.st/jk' ) . '">',
|
||||
'Yoast',
|
||||
'</a>'
|
||||
)
|
||||
);
|
||||
|
||||
$service_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/jm' ),
|
||||
'configuration-service.png',
|
||||
261,
|
||||
152,
|
||||
sprintf(
|
||||
/* translators: %1$s expands to Yoast SEO Premium. */
|
||||
__( 'Let our experts set up your %1$s plugin!', 'wordpress-seo' ),
|
||||
'Yoast SEO Premium'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return $service_spot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with the Yoast SEO extensions with the value true when they are active.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_active_extensions() {
|
||||
return array(
|
||||
'video' => class_exists( 'wpseo_Video_Sitemap' ),
|
||||
'woocommerce' => class_exists( 'Woocommerce' ) && class_exists( 'Yoast_WooCommerce_SEO' ),
|
||||
'news' => class_exists( 'WPSEO_News' ),
|
||||
'local' => defined( 'WPSEO_LOCAL_VERSION' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extensions banner spot.
|
||||
*
|
||||
* @param array $active_extensions The active extensions.
|
||||
*
|
||||
* @return WPSEO_Admin_Banner_Spot
|
||||
*/
|
||||
protected function get_extensions_spot( array $active_extensions ) {
|
||||
$extension_spot = new WPSEO_Admin_Banner_Spot( __( 'Extensions', 'wordpress-seo' ), $this->banner_renderer );
|
||||
|
||||
$extension_spot->set_description(
|
||||
sprintf(
|
||||
/* translators: %1$s expands to a link start tag to the Yoast plugin page, %2$s is the link closing tag. */
|
||||
__( 'Take your SEO to the next level and outrank your competition with our %1$sSEO plugins%2$s.', 'wordpress-seo' ),
|
||||
'<a target="_blank" href="' . WPSEO_Shortlinker::get( 'https://yoa.st/jn' ) . '">',
|
||||
'</a>'
|
||||
)
|
||||
);
|
||||
|
||||
if ( empty( $active_extensions['video'] ) ) {
|
||||
$extension_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/jo' ),
|
||||
'video-seo.png',
|
||||
261,
|
||||
152,
|
||||
sprintf(
|
||||
/* translators: %1$s expands to Yoast Video SEO. */
|
||||
__( 'Buy the %1$s plugin now and optimize your videos for video search results and social media!', 'wordpress-seo' ),
|
||||
'Yoast Video SEO'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( empty( $active_extensions['woocommerce'] ) ) {
|
||||
$extension_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/jp' ),
|
||||
'woocommerce-seo.png',
|
||||
261,
|
||||
152,
|
||||
sprintf(
|
||||
/* translators: %1$s expands to Yoast WooCommerce SEO. */
|
||||
__( 'Buy the %1$s plugin now and optimize your shop today to improve your product promotion!', 'wordpress-seo' ),
|
||||
'Yoast WooCommerce SEO'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( empty( $active_extensions['local'] ) ) {
|
||||
$extension_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/jq' ),
|
||||
'local-seo.png', 261,
|
||||
152,
|
||||
sprintf(
|
||||
/* translators: %1$s expands to Yoast Local SEO. */
|
||||
__( 'Buy the %1$s plugin now to improve your site’s Local SEO and ranking in Google Maps!', 'wordpress-seo' ),
|
||||
'Yoast Local SEO'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( empty( $active_extensions['news'] ) ) {
|
||||
$extension_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/jr' ),
|
||||
'news-seo.png',
|
||||
261,
|
||||
152,
|
||||
sprintf(
|
||||
/* translators: %1$s expands to Yoast News SEO. */
|
||||
__( 'Buy the %1$s plugin now and start optimizing to get your site featured in Google News!', 'wordpress-seo' ),
|
||||
'Yoast News SEO'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $extension_spot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the courses banner spot.
|
||||
*
|
||||
* @return WPSEO_Admin_Banner_Spot
|
||||
*/
|
||||
protected function get_courses_spot() {
|
||||
$courses_spot = new WPSEO_Admin_Banner_Spot( __( 'Improve your SEO skills', 'wordpress-seo' ), $this->banner_renderer );
|
||||
|
||||
$courses_spot->set_description(
|
||||
sprintf(
|
||||
/* translators: %1$s expands to a link start tag to the Yoast Services page, %2$s is the link closing tag. */
|
||||
__( 'We believe SEO should be for everyone. That’s why we develop courses on any topic related to SEO. %1$sDiscover our online SEO courses »%2$s', 'wordpress-seo' ),
|
||||
'<a target="_blank" href="' . WPSEO_Shortlinker::get( 'https://yoa.st/jt' ) . '">',
|
||||
'</a>'
|
||||
)
|
||||
);
|
||||
|
||||
$courses_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/ju' ),
|
||||
'basic-seo-training.png',
|
||||
261,
|
||||
152,
|
||||
__( 'Take the online Basic SEO Training course and learn the fundamentals of SEO!', 'wordpress-seo' )
|
||||
)
|
||||
);
|
||||
|
||||
$courses_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/jv' ),
|
||||
'yoast-seo-for-wordpress-training.png',
|
||||
261,
|
||||
152,
|
||||
sprintf(
|
||||
/* translators: %1$s expands to Yoast SEO for WordPress Training, %2$s to Yoast SEO for WordPress. */
|
||||
__( 'Take the %1$s course and become a certified %2$s expert!', 'wordpress-seo' ),
|
||||
'Yoast SEO for WordPress Training',
|
||||
'Yoast SEO for WordPress'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$courses_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/jw' ),
|
||||
'seo-copywriting-training.png',
|
||||
261,
|
||||
152,
|
||||
__( 'Take the online SEO Copywriting Training course and learn how to write awesome copy that ranks!', 'wordpress-seo' )
|
||||
)
|
||||
);
|
||||
|
||||
$courses_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/qy' ),
|
||||
'site-structure-training.png',
|
||||
261,
|
||||
152,
|
||||
__( 'Take the online Site Structure Training course and learn how to structure your website!', 'wordpress-seo' )
|
||||
)
|
||||
);
|
||||
|
||||
$courses_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/jaa' ),
|
||||
'technical-seo-training.png',
|
||||
261,
|
||||
152,
|
||||
__( 'Take the online Technical SEO Training course and learn essential technical SEO-concepts!', 'wordpress-seo' )
|
||||
)
|
||||
);
|
||||
|
||||
$courses_spot->add_banner(
|
||||
new WPSEO_Admin_Banner(
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/15h' ),
|
||||
'structured-data-course.png',
|
||||
261,
|
||||
152,
|
||||
__( 'Take the online Structured Data Training course and learn how to create rich snippets!', 'wordpress-seo' )
|
||||
)
|
||||
);
|
||||
|
||||
return $courses_spot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remove banner spot.
|
||||
*
|
||||
* @return WPSEO_Admin_Banner_Spot
|
||||
*/
|
||||
protected function get_remove_banner_spot() {
|
||||
|
||||
$remove_banner_spot = new WPSEO_Admin_Banner_Spot(
|
||||
__( 'Remove these ads?', 'wordpress-seo' )
|
||||
);
|
||||
|
||||
$remove_banner_spot->set_description(
|
||||
'<a target="_blank" href="' . WPSEO_Shortlinker::get( 'https://yoa.st/jy' ) . '">' .
|
||||
/* translators: %1$s expands to Yoast SEO Premium */
|
||||
sprintf( __( 'Upgrade to %1$s »', 'wordpress-seo' ), 'Yoast SEO Premium' ) .
|
||||
'</a>'
|
||||
);
|
||||
|
||||
return $remove_banner_spot;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Banner
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the render object for generating the html for the given banner spot.
|
||||
*/
|
||||
class WPSEO_Admin_Banner_Spot_Renderer {
|
||||
|
||||
/**
|
||||
* Renders the admin banner spot.
|
||||
*
|
||||
* @param WPSEO_Admin_Banner_Spot $banner_spot The spot to render.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render( WPSEO_Admin_Banner_Spot $banner_spot ) {
|
||||
$output = '<div class="yoast-sidebar__spot">';
|
||||
if ( $banner_spot->get_title() !== '' ) {
|
||||
$output .= '<strong>' . $banner_spot->get_title() . '</strong>';
|
||||
}
|
||||
|
||||
if ( $banner_spot->get_extra() !== '' ) {
|
||||
$output .= $banner_spot->get_extra();
|
||||
}
|
||||
|
||||
if ( $banner_spot->get_description() !== '' ) {
|
||||
$output .= '<p>' . $banner_spot->get_description() . '</p>';
|
||||
}
|
||||
|
||||
$output .= $banner_spot->render_banner();
|
||||
$output .= '</div>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Banner
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the an admin banner spot.
|
||||
*/
|
||||
class WPSEO_Admin_Banner_Spot {
|
||||
|
||||
/** @var string */
|
||||
private $title;
|
||||
|
||||
/** @var string */
|
||||
private $description = '';
|
||||
|
||||
/** @var string */
|
||||
private $extra = '';
|
||||
|
||||
/** @var WPSEO_Admin_Banner[] */
|
||||
private $banners = array();
|
||||
|
||||
/**
|
||||
* WPSEO_Admin_Banner_Spot constructor.
|
||||
*
|
||||
* @param string $title The title for the spot.
|
||||
* @param WPSEO_Admin_Banner_Renderer $banner_renderer The renderer for the banner.
|
||||
*/
|
||||
public function __construct( $title, WPSEO_Admin_Banner_Renderer $banner_renderer = null ) {
|
||||
$this->title = $title;
|
||||
$this->banner_renderer = ( is_null( $banner_renderer ) ? new WPSEO_Admin_Banner_Renderer() : $banner_renderer );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_description() {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extra content.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_extra() {
|
||||
return $this->extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description
|
||||
*
|
||||
* @param string $description The description.
|
||||
*/
|
||||
public function set_description( $description ) {
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the "extra"
|
||||
*
|
||||
* @param string $extra The "extra".
|
||||
*/
|
||||
public function set_extra( $extra ) {
|
||||
$this->extra = $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an admin banner.
|
||||
*
|
||||
* @param WPSEO_Admin_Banner $banner The banner to add.
|
||||
*/
|
||||
public function add_banner( WPSEO_Admin_Banner $banner ) {
|
||||
$this->banners[] = $banner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the banner.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render_banner() {
|
||||
if ( ! $this->has_banners() ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->banner_renderer->render( $this->get_random_banner() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are any banners set.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_banners() {
|
||||
return ! empty( $this->banners );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random banner.
|
||||
*
|
||||
* @return null|WPSEO_Admin_Banner
|
||||
*/
|
||||
protected function get_random_banner() {
|
||||
return $this->banners[ array_rand( $this->banners, 1 ) ];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Banner
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents an admin banner.
|
||||
*/
|
||||
class WPSEO_Admin_Banner {
|
||||
|
||||
/** @var string */
|
||||
private $url;
|
||||
|
||||
/** @var string */
|
||||
private $image;
|
||||
|
||||
/** @var integer */
|
||||
private $width;
|
||||
|
||||
/** @var integer */
|
||||
private $height;
|
||||
|
||||
/** @var string */
|
||||
private $alt;
|
||||
|
||||
/**
|
||||
* Sets the attributes for this object.
|
||||
*
|
||||
* @param string $url The URL where the banner links to.
|
||||
* @param string $image The image filename.
|
||||
* @param integer $width The width of the image.
|
||||
* @param integer $height The height of the image.
|
||||
* @param string $alt The alt text for the image.
|
||||
*/
|
||||
public function __construct( $url, $image, $width, $height, $alt = '' ) {
|
||||
$this->url = $url;
|
||||
$this->image = $image;
|
||||
$this->alt = $alt;
|
||||
$this->width = $width;
|
||||
$this->height = $height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set url.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_url() {
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_image() {
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the alt-text.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_alt() {
|
||||
return $this->alt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_width() {
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_height() {
|
||||
return $this->height;
|
||||
}
|
||||
}
|
||||
|
|
@ -9,15 +9,20 @@
|
|||
* Abstract Capability Manager shared code.
|
||||
*/
|
||||
abstract class WPSEO_Abstract_Capability_Manager implements WPSEO_Capability_Manager {
|
||||
/** @var array Registered capabilities */
|
||||
protected $capabilities = array();
|
||||
|
||||
/**
|
||||
* Registered capabilities.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $capabilities = [];
|
||||
|
||||
/**
|
||||
* Registers a capability.
|
||||
*
|
||||
* @param string $capability Capability to register.
|
||||
* @param array $roles Roles to add the capability to.
|
||||
* @param bool $overwrite Optional. Use add or overwrite as registration method.
|
||||
* @param bool $overwrite Optional. Use add or overwrite as registration method.
|
||||
*/
|
||||
public function register( $capability, array $roles, $overwrite = false ) {
|
||||
if ( $overwrite || ! isset( $this->capabilities[ $capability ] ) ) {
|
||||
|
|
@ -76,7 +81,7 @@ abstract class WPSEO_Abstract_Capability_Manager implements WPSEO_Capability_Man
|
|||
|
||||
// Make sure we have the expected type.
|
||||
if ( ! is_array( $filtered ) ) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
|
|
|
|||
|
|
@ -9,24 +9,27 @@
|
|||
* Capability Manager Factory.
|
||||
*/
|
||||
class WPSEO_Capability_Manager_Factory {
|
||||
|
||||
/**
|
||||
* Returns the Manager to use.
|
||||
*
|
||||
* @param string $plugin_type Whether it's Free or Premium.
|
||||
*
|
||||
* @return WPSEO_Capability_Manager Manager to use.
|
||||
*/
|
||||
public static function get() {
|
||||
static $manager = null;
|
||||
public static function get( $plugin_type = 'free' ) {
|
||||
static $manager = [];
|
||||
|
||||
if ( $manager === null ) {
|
||||
if ( ! array_key_exists( $plugin_type, $manager ) ) {
|
||||
if ( function_exists( 'wpcom_vip_add_role_caps' ) ) {
|
||||
$manager = new WPSEO_Capability_Manager_VIP();
|
||||
$manager[ $plugin_type ] = new WPSEO_Capability_Manager_VIP();
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'wpcom_vip_add_role_caps' ) ) {
|
||||
$manager = new WPSEO_Capability_Manager_WP();
|
||||
$manager[ $plugin_type ] = new WPSEO_Capability_Manager_WP();
|
||||
}
|
||||
}
|
||||
|
||||
return $manager;
|
||||
return $manager[ $plugin_type ];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,11 @@
|
|||
*/
|
||||
class WPSEO_Capability_Manager_Integration implements WPSEO_WordPress_Integration {
|
||||
|
||||
/** @var WPSEO_Capability_Manager Capability manager to use. */
|
||||
/**
|
||||
* Capability manager to use.
|
||||
*
|
||||
* @var WPSEO_Capability_Manager
|
||||
*/
|
||||
public $manager;
|
||||
|
||||
/**
|
||||
|
|
@ -31,11 +35,11 @@ class WPSEO_Capability_Manager_Integration implements WPSEO_WordPress_Integratio
|
|||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
add_filter( 'members_get_capabilities', array( $this, 'get_capabilities' ) );
|
||||
add_action( 'members_register_cap_groups', array( $this, 'action_members_register_cap_group' ) );
|
||||
add_filter( 'members_get_capabilities', [ $this, 'get_capabilities' ] );
|
||||
add_action( 'members_register_cap_groups', [ $this, 'action_members_register_cap_group' ] );
|
||||
|
||||
add_filter( 'ure_capabilities_groups_tree', array( $this, 'filter_ure_capabilities_groups_tree' ) );
|
||||
add_filter( 'ure_custom_capability_groups', array( $this, 'filter_ure_custom_capability_groups' ), 10, 2 );
|
||||
add_filter( 'ure_capabilities_groups_tree', [ $this, 'filter_ure_capabilities_groups_tree' ] );
|
||||
add_filter( 'ure_custom_capability_groups', [ $this, 'filter_ure_custom_capability_groups' ], 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -45,7 +49,7 @@ class WPSEO_Capability_Manager_Integration implements WPSEO_WordPress_Integratio
|
|||
* @param array $caps Optional existing capability list.
|
||||
* @return array
|
||||
*/
|
||||
public function get_capabilities( array $caps = array() ) {
|
||||
public function get_capabilities( array $caps = [] ) {
|
||||
if ( ! did_action( 'wpseo_register_capabilities' ) ) {
|
||||
do_action( 'wpseo_register_capabilities' );
|
||||
}
|
||||
|
|
@ -56,40 +60,40 @@ class WPSEO_Capability_Manager_Integration implements WPSEO_WordPress_Integratio
|
|||
/**
|
||||
* Add capabilities to its own group in the Members plugin.
|
||||
*
|
||||
* @see members_register_cap_group()
|
||||
* @see members_register_cap_group()
|
||||
*/
|
||||
public function action_members_register_cap_group() {
|
||||
if ( ! function_exists( 'members_register_cap_group' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register the yoast group.
|
||||
members_register_cap_group( 'wordpress-seo',
|
||||
array(
|
||||
'label' => esc_html__( 'Yoast SEO', 'wordpress-seo' ),
|
||||
'caps' => $this->get_capabilities(),
|
||||
'icon' => 'dashicons-admin-plugins',
|
||||
'diff_added' => true,
|
||||
)
|
||||
);
|
||||
$args = [
|
||||
'label' => esc_html__( 'Yoast SEO', 'wordpress-seo' ),
|
||||
'caps' => $this->get_capabilities(),
|
||||
'icon' => 'dashicons-admin-plugins',
|
||||
'diff_added' => true,
|
||||
];
|
||||
members_register_cap_group( 'wordpress-seo', $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Yoast SEO capability group in the User Role Editor plugin.
|
||||
*
|
||||
* @see URE_Capabilities_Groups_Manager::get_groups_tree()
|
||||
* @see URE_Capabilities_Groups_Manager::get_groups_tree()
|
||||
*
|
||||
* @param array $groups Current groups.
|
||||
* @param array $groups Current groups.
|
||||
*
|
||||
* @return array Filtered list of capabilty groups.
|
||||
*/
|
||||
public function filter_ure_capabilities_groups_tree( $groups = array() ) {
|
||||
public function filter_ure_capabilities_groups_tree( $groups = [] ) {
|
||||
$groups = (array) $groups;
|
||||
|
||||
$groups['wordpress-seo'] = array(
|
||||
$groups['wordpress-seo'] = [
|
||||
'caption' => 'Yoast SEO',
|
||||
'parent' => 'custom',
|
||||
'level' => 3,
|
||||
);
|
||||
];
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
|
@ -97,14 +101,14 @@ class WPSEO_Capability_Manager_Integration implements WPSEO_WordPress_Integratio
|
|||
/**
|
||||
* Adds capabilities to the Yoast SEO group in the User Role Editor plugin.
|
||||
*
|
||||
* @see URE_Capabilities_Groups_Manager::get_cap_groups()
|
||||
* @see URE_Capabilities_Groups_Manager::get_cap_groups()
|
||||
*
|
||||
* @param array $groups Current capability groups.
|
||||
* @param string $cap_id Capability identifier.
|
||||
* @param array $groups Current capability groups.
|
||||
* @param string $cap_id Capability identifier.
|
||||
*
|
||||
* @return array List of filtered groups.
|
||||
*/
|
||||
public function filter_ure_custom_capability_groups( $groups = array(), $cap_id = '' ) {
|
||||
public function filter_ure_custom_capability_groups( $groups = [], $cap_id = '' ) {
|
||||
if ( in_array( $cap_id, $this->get_capabilities(), true ) ) {
|
||||
$groups = (array) $groups;
|
||||
$groups[] = 'wordpress-seo';
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@
|
|||
* VIP implementation of the Capability Manager.
|
||||
*/
|
||||
final class WPSEO_Capability_Manager_VIP extends WPSEO_Abstract_Capability_Manager {
|
||||
|
||||
/**
|
||||
* Adds the registered capabilities to the system.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add() {
|
||||
$role_capabilities = array();
|
||||
$role_capabilities = [];
|
||||
foreach ( $this->capabilities as $capability => $roles ) {
|
||||
$role_capabilities = $this->get_role_capabilities( $role_capabilities, $capability, $roles );
|
||||
}
|
||||
|
|
@ -35,7 +36,7 @@ final class WPSEO_Capability_Manager_VIP extends WPSEO_Abstract_Capability_Manag
|
|||
$roles = wp_roles()->get_names();
|
||||
$roles = array_keys( $roles );
|
||||
|
||||
$role_capabilities = array();
|
||||
$role_capabilities = [];
|
||||
foreach ( array_keys( $this->capabilities ) as $capability ) {
|
||||
// Allow filtering of roles.
|
||||
$role_capabilities = $this->get_role_capabilities( $role_capabilities, $capability, $roles );
|
||||
|
|
@ -61,7 +62,7 @@ final class WPSEO_Capability_Manager_VIP extends WPSEO_Abstract_Capability_Manag
|
|||
|
||||
foreach ( $filtered_roles as $role ) {
|
||||
if ( ! isset( $add_role_caps[ $role ] ) ) {
|
||||
$role_capabilities[ $role ] = array();
|
||||
$role_capabilities[ $role ] = [];
|
||||
}
|
||||
|
||||
$role_capabilities[ $role ][] = $capability;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
* Default WordPress capability manager implementation.
|
||||
*/
|
||||
final class WPSEO_Capability_Manager_WP extends WPSEO_Abstract_Capability_Manager {
|
||||
|
||||
/**
|
||||
* Adds the capabilities to the roles.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
* Capability Manager interface.
|
||||
*/
|
||||
interface WPSEO_Capability_Manager {
|
||||
|
||||
/**
|
||||
* Registers a capability.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
* Capability Utils collection.
|
||||
*/
|
||||
class WPSEO_Capability_Utils {
|
||||
|
||||
/**
|
||||
* Checks if the user has the proper capabilities.
|
||||
*
|
||||
|
|
@ -21,7 +22,52 @@ class WPSEO_Capability_Utils {
|
|||
return self::has( $capability );
|
||||
}
|
||||
|
||||
return self::has_any( array( 'wpseo_manage_options', $capability ) );
|
||||
return self::has_any( [ 'wpseo_manage_options', $capability ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the users that have the specified capability.
|
||||
*
|
||||
* @param string $capability The name of the capability.
|
||||
*
|
||||
* @return array The users that have the capability.
|
||||
*/
|
||||
public static function get_applicable_users( $capability ) {
|
||||
$applicable_roles = self::get_applicable_roles( $capability );
|
||||
|
||||
if ( $applicable_roles === [] ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return get_users( [ 'role__in' => $applicable_roles ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the roles that have the specified capability.
|
||||
*
|
||||
* @param string $capability The name of the capability.
|
||||
*
|
||||
* @return array The names of the roles that have the capability.
|
||||
*/
|
||||
public static function get_applicable_roles( $capability ) {
|
||||
$roles = wp_roles();
|
||||
$role_names = $roles->get_names();
|
||||
|
||||
$applicable_roles = [];
|
||||
foreach ( array_keys( $role_names ) as $role_name ) {
|
||||
$role = $roles->get_role( $role_name );
|
||||
|
||||
if ( ! $role ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add role if it has the capability.
|
||||
if ( array_key_exists( $capability, $role->capabilities ) && $role->capabilities[ $capability ] === true ) {
|
||||
$applicable_roles[] = $role_name;
|
||||
}
|
||||
}
|
||||
|
||||
return $applicable_roles;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -9,13 +9,18 @@
|
|||
* Capabilities registration class.
|
||||
*/
|
||||
class WPSEO_Register_Capabilities implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* Registers the hooks.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
add_action( 'wpseo_register_capabilities', array( $this, 'register' ) );
|
||||
add_action( 'wpseo_register_capabilities', [ $this, 'register' ] );
|
||||
|
||||
if ( is_multisite() ) {
|
||||
add_action( 'user_has_cap', [ $this, 'filter_user_has_wpseo_manage_options_cap' ], 10, 4 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -26,17 +31,47 @@ class WPSEO_Register_Capabilities implements WPSEO_WordPress_Integration {
|
|||
public function register() {
|
||||
$manager = WPSEO_Capability_Manager_Factory::get();
|
||||
|
||||
$manager->register( 'wpseo_bulk_edit', array( 'editor', 'wpseo_editor', 'wpseo_manager' ) );
|
||||
$manager->register( 'wpseo_edit_advanced_metadata', array( 'wpseo_editor', 'wpseo_manager' ) );
|
||||
$manager->register( 'wpseo_bulk_edit', [ 'editor', 'wpseo_editor', 'wpseo_manager' ] );
|
||||
$manager->register( 'wpseo_edit_advanced_metadata', [ 'editor', 'wpseo_editor', 'wpseo_manager' ] );
|
||||
|
||||
$manager->register( 'wpseo_manage_options', array( 'wpseo_manager' ) );
|
||||
$manager->register( 'wpseo_manage_options', [ 'administrator', 'wpseo_manager' ] );
|
||||
$manager->register( 'view_site_health_checks', [ 'wpseo_manager' ] );
|
||||
}
|
||||
|
||||
/*
|
||||
* Respect MultiSite 'access' setting if set to 'super admins only'.
|
||||
* This means that local admins do not get the `wpseo_manage_options` capability.
|
||||
*/
|
||||
if ( WPSEO_Options::get( 'access' ) !== 'superadmins' ) {
|
||||
$manager->register( 'wpseo_manage_options', array( 'administrator' ) );
|
||||
/**
|
||||
* Revokes the 'wpseo_manage_options' capability from administrator users if it should
|
||||
* only be granted to network administrators.
|
||||
*
|
||||
* @param array $allcaps An array of all the user's capabilities.
|
||||
* @param array $caps Actual capabilities being checked.
|
||||
* @param array $args Optional parameters passed to has_cap(), typically object ID.
|
||||
* @param WP_User $user The user object.
|
||||
*
|
||||
* @return array Possibly modified array of the user's capabilities.
|
||||
*/
|
||||
public function filter_user_has_wpseo_manage_options_cap( $allcaps, $caps, $args, $user ) {
|
||||
|
||||
// We only need to do something if 'wpseo_manage_options' is being checked.
|
||||
if ( ! in_array( 'wpseo_manage_options', $caps, true ) ) {
|
||||
return $allcaps;
|
||||
}
|
||||
|
||||
// If the user does not have 'wpseo_manage_options' anyway, we don't need to revoke access.
|
||||
if ( empty( $allcaps['wpseo_manage_options'] ) ) {
|
||||
return $allcaps;
|
||||
}
|
||||
|
||||
// If the user does not have 'delete_users', they are not an administrator.
|
||||
if ( empty( $allcaps['delete_users'] ) ) {
|
||||
return $allcaps;
|
||||
}
|
||||
|
||||
$options = WPSEO_Options::get_instance();
|
||||
|
||||
if ( $options->get( 'access' ) === 'superadmin' && ! is_super_admin( $user->ID ) ) {
|
||||
unset( $allcaps['wpseo_manage_options'] );
|
||||
}
|
||||
|
||||
return $allcaps;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a way to determine the analysis worker asset location.
|
||||
*/
|
||||
final class WPSEO_Admin_Asset_Analysis_Worker_Location implements WPSEO_Admin_Asset_Location {
|
||||
|
||||
/**
|
||||
* Holds the asset's location.
|
||||
*
|
||||
* @var WPSEO_Admin_Asset_Location
|
||||
*/
|
||||
private $asset_location;
|
||||
|
||||
/**
|
||||
* Holds the asset itself.
|
||||
*
|
||||
* @var WPSEO_Admin_Asset
|
||||
*/
|
||||
private $asset;
|
||||
|
||||
/**
|
||||
* Constructs the location of the analysis worker asset.
|
||||
*
|
||||
* @param string $flat_version The flat version of the asset.
|
||||
* @param string $name The name of the analysis worker asset.
|
||||
*/
|
||||
public function __construct( $flat_version = '', $name = 'analysis-worker' ) {
|
||||
if ( $flat_version === '' ) {
|
||||
$asset_manager = new WPSEO_Admin_Asset_Manager();
|
||||
$flat_version = $asset_manager->flatten_version( WPSEO_VERSION );
|
||||
}
|
||||
|
||||
$analysis_worker = $name . '-' . $flat_version . '.js';
|
||||
|
||||
$this->asset_location = WPSEO_Admin_Asset_Manager::create_default_location();
|
||||
$this->asset = new WPSEO_Admin_Asset(
|
||||
[
|
||||
'name' => $name,
|
||||
'src' => $analysis_worker,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the analysis worker asset.
|
||||
*
|
||||
* @return WPSEO_Admin_Asset The analysis worker asset.
|
||||
*/
|
||||
public function get_asset() {
|
||||
return $this->asset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the URL of the asset on the dev server.
|
||||
*
|
||||
* @param WPSEO_Admin_Asset $asset The asset to determine the URL for.
|
||||
* @param string $type The type of asset. Usually JS or CSS.
|
||||
*
|
||||
* @return string The URL of the asset.
|
||||
*/
|
||||
public function get_url( WPSEO_Admin_Asset $asset, $type ) {
|
||||
$scheme = wp_parse_url( $asset->get_src(), PHP_URL_SCHEME );
|
||||
if ( in_array( $scheme, [ 'http', 'https' ], true ) ) {
|
||||
return $asset->get_src();
|
||||
}
|
||||
|
||||
return $this->asset_location->get_url( $asset, $type );
|
||||
}
|
||||
}
|
||||
|
|
@ -9,28 +9,25 @@
|
|||
* Changes the asset paths to dev server paths.
|
||||
*/
|
||||
final class WPSEO_Admin_Asset_Dev_Server_Location implements WPSEO_Admin_Asset_Location {
|
||||
|
||||
/**
|
||||
* Holds the dev server's default URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const DEFAULT_URL = 'http://localhost:8080';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $dev_server_script = array(
|
||||
'commons',
|
||||
'configuration-wizard',
|
||||
'wp-seo-dashboard-widget',
|
||||
'wp-seo-help-center',
|
||||
'wp-seo-metabox',
|
||||
'wp-seo-post-scraper',
|
||||
'wp-seo-term-scraper',
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds the url where the server is located.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $url;
|
||||
|
||||
/**
|
||||
* @param string $url Where the dev server is located.
|
||||
* Class constructor.
|
||||
*
|
||||
* @param string|null $url Where the dev server is located.
|
||||
*/
|
||||
public function __construct( $url = null ) {
|
||||
if ( $url === null ) {
|
||||
|
|
@ -49,7 +46,7 @@ final class WPSEO_Admin_Asset_Dev_Server_Location implements WPSEO_Admin_Asset_L
|
|||
* @return string The URL of the asset.
|
||||
*/
|
||||
public function get_url( WPSEO_Admin_Asset $asset, $type ) {
|
||||
if ( WPSEO_Admin_Asset::TYPE_CSS === $type ) {
|
||||
if ( $type === WPSEO_Admin_Asset::TYPE_CSS ) {
|
||||
return $this->get_default_url( $asset, $type );
|
||||
}
|
||||
|
||||
|
|
@ -57,11 +54,11 @@ final class WPSEO_Admin_Asset_Dev_Server_Location implements WPSEO_Admin_Asset_L
|
|||
$flat_version = $asset_manager->flatten_version( WPSEO_VERSION );
|
||||
$version_less_source = str_replace( '-' . $flat_version, '', $asset->get_src() );
|
||||
|
||||
if ( ! in_array( $version_less_source, self::$dev_server_script, true ) ) {
|
||||
if ( strpos( $version_less_source, 'select2' ) !== false ) {
|
||||
return $this->get_default_url( $asset, $type );
|
||||
}
|
||||
|
||||
$path = sprintf( '%s%s.js', $asset->get_src(), $asset->get_suffix() );
|
||||
$path = sprintf( 'js/dist/%s%s.js', $asset->get_src(), $asset->get_suffix() );
|
||||
|
||||
return trailingslashit( $this->url ) . $path;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,31 +6,47 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* This class registers all the necessary styles and scripts. Also has methods for the enqueing of scripts and styles. It automatically adds a prefix to the handle.
|
||||
* This class registers all the necessary styles and scripts.
|
||||
*
|
||||
* Also has methods for the enqueing of scripts and styles.
|
||||
* It automatically adds a prefix to the handle.
|
||||
*/
|
||||
class WPSEO_Admin_Asset_Manager {
|
||||
|
||||
/**
|
||||
* Prefix for naming the assets.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PREFIX = 'yoast-seo-';
|
||||
|
||||
/**
|
||||
* Class that manages the assets' location.
|
||||
*
|
||||
* @var WPSEO_Admin_Asset_Location
|
||||
*/
|
||||
protected $asset_location;
|
||||
|
||||
/**
|
||||
* Prefix for naming the assets.
|
||||
* Prefix for naming the assets.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PREFIX = 'yoast-seo-';
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* Constructs a manager of assets. Needs a location to know where to register assets at.
|
||||
*
|
||||
* @param WPSEO_Admin_Asset_Location $asset_location The provider of the asset location.
|
||||
* @param WPSEO_Admin_Asset_Location|null $asset_location The provider of the asset location.
|
||||
* @param string $prefix The prefix for naming assets.
|
||||
*/
|
||||
public function __construct( WPSEO_Admin_Asset_Location $asset_location = null ) {
|
||||
public function __construct( WPSEO_Admin_Asset_Location $asset_location = null, $prefix = self::PREFIX ) {
|
||||
if ( $asset_location === null ) {
|
||||
$asset_location = self::create_default_location();
|
||||
}
|
||||
|
||||
$this->asset_location = $asset_location;
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -39,7 +55,7 @@ class WPSEO_Admin_Asset_Manager {
|
|||
* @param string $script The name of the script to enqueue.
|
||||
*/
|
||||
public function enqueue_script( $script ) {
|
||||
wp_enqueue_script( self::PREFIX . $script );
|
||||
wp_enqueue_script( $this->prefix . $script );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -48,7 +64,14 @@ class WPSEO_Admin_Asset_Manager {
|
|||
* @param string $style The name of the style to enqueue.
|
||||
*/
|
||||
public function enqueue_style( $style ) {
|
||||
wp_enqueue_style( self::PREFIX . $style );
|
||||
wp_enqueue_style( $this->prefix . $style );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues the appropriate language for the user.
|
||||
*/
|
||||
public function enqueue_user_language_script() {
|
||||
$this->enqueue_script( 'language-' . YoastSEO()->helpers->language->get_researcher_language() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -57,9 +80,11 @@ class WPSEO_Admin_Asset_Manager {
|
|||
* @param WPSEO_Admin_Asset $script The script to register.
|
||||
*/
|
||||
public function register_script( WPSEO_Admin_Asset $script ) {
|
||||
$url = $script->get_src() ? $this->get_url( $script, WPSEO_Admin_Asset::TYPE_JS ) : false;
|
||||
|
||||
wp_register_script(
|
||||
self::PREFIX . $script->get_name(),
|
||||
$this->asset_location->get_url( $script, WPSEO_Admin_Asset::TYPE_JS ),
|
||||
$this->prefix . $script->get_name(),
|
||||
$url,
|
||||
$script->get_deps(),
|
||||
$script->get_version(),
|
||||
$script->is_in_footer()
|
||||
|
|
@ -73,8 +98,8 @@ class WPSEO_Admin_Asset_Manager {
|
|||
*/
|
||||
public function register_style( WPSEO_Admin_Asset $style ) {
|
||||
wp_register_style(
|
||||
self::PREFIX . $style->get_name(),
|
||||
$this->asset_location->get_url( $style, WPSEO_Admin_Asset::TYPE_CSS ),
|
||||
$this->prefix . $style->get_name(),
|
||||
$this->get_url( $style, WPSEO_Admin_Asset::TYPE_CSS ),
|
||||
$style->get_deps(),
|
||||
$style->get_version(),
|
||||
$style->get_media()
|
||||
|
|
@ -85,17 +110,6 @@ class WPSEO_Admin_Asset_Manager {
|
|||
* Calls the functions that register scripts and styles with the scripts and styles to be registered as arguments.
|
||||
*/
|
||||
public function register_assets() {
|
||||
|
||||
$user_locale = WPSEO_Utils::get_user_locale();
|
||||
$language = WPSEO_Utils::get_language( $user_locale );
|
||||
|
||||
wp_register_script(
|
||||
self::PREFIX . 'intl-polyfill',
|
||||
sprintf( 'https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.%s', $language ),
|
||||
array(),
|
||||
WPSEO_VERSION
|
||||
);
|
||||
|
||||
$this->register_scripts( $this->scripts_to_be_registered() );
|
||||
$this->register_styles( $this->styles_to_be_registered() );
|
||||
}
|
||||
|
|
@ -113,9 +127,9 @@ class WPSEO_Admin_Asset_Manager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Registers all the styles it recieves.
|
||||
* Registers all the styles it receives.
|
||||
*
|
||||
* @param array $styles Styles that need to be registerd.
|
||||
* @param array $styles Styles that need to be registered.
|
||||
*/
|
||||
public function register_styles( $styles ) {
|
||||
foreach ( $styles as $style ) {
|
||||
|
|
@ -124,6 +138,17 @@ class WPSEO_Admin_Asset_Manager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Localizes the script.
|
||||
*
|
||||
* @param string $handle The script handle.
|
||||
* @param string $object_name The object name.
|
||||
* @param array $data The l10n data.
|
||||
*/
|
||||
public function localize_script( $handle, $object_name, $data ) {
|
||||
\wp_localize_script( $this->prefix . $handle, $object_name, $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of styles that shouldn't be registered but are needed in other locations in the plugin.
|
||||
*
|
||||
|
|
@ -131,19 +156,19 @@ class WPSEO_Admin_Asset_Manager {
|
|||
*/
|
||||
public function special_styles() {
|
||||
$flat_version = $this->flatten_version( WPSEO_VERSION );
|
||||
$asset_args = [
|
||||
'name' => 'inside-editor',
|
||||
'src' => 'inside-editor-' . $flat_version,
|
||||
];
|
||||
|
||||
return array(
|
||||
'inside-editor' => new WPSEO_Admin_Asset( array(
|
||||
'name' => 'inside-editor',
|
||||
'src' => 'inside-editor-' . $flat_version,
|
||||
) ),
|
||||
);
|
||||
return [ 'inside-editor' => new WPSEO_Admin_Asset( $asset_args ) ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens a version number for use in a filename
|
||||
* Flattens a version number for use in a filename.
|
||||
*
|
||||
* @param string $version The original version number.
|
||||
*
|
||||
* @return string The flattened version number.
|
||||
*/
|
||||
public function flatten_version( $version ) {
|
||||
|
|
@ -168,7 +193,18 @@ class WPSEO_Admin_Asset_Manager {
|
|||
return new WPSEO_Admin_Asset_Dev_Server_Location( $url );
|
||||
}
|
||||
|
||||
return new WPSEO_Admin_Asset_SEO_Location( WPSEO_FILE );
|
||||
return new WPSEO_Admin_Asset_SEO_Location( WPSEO_FILE, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given script is enqueued.
|
||||
*
|
||||
* @param string $script The script to check.
|
||||
*
|
||||
* @return bool True when the script is enqueued.
|
||||
*/
|
||||
public function is_script_enqueued( $script ) {
|
||||
return \wp_script_is( $this->prefix . $script );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -176,13 +212,190 @@ class WPSEO_Admin_Asset_Manager {
|
|||
*
|
||||
* @todo Data format is not self-documenting. Needs explanation inline. R.
|
||||
*
|
||||
* @return array scripts that need to be registered.
|
||||
* @return array The scripts that need to be registered.
|
||||
*/
|
||||
private function scripts_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',
|
||||
];
|
||||
$additional_dependencies = [
|
||||
'analysis-worker' => [ self::PREFIX . 'analysis-package' ],
|
||||
'api-client' => [ 'wp-api' ],
|
||||
'dashboard-widget' => [ self::PREFIX . 'api-client' ],
|
||||
'elementor' => [ self::PREFIX . 'api-client' ],
|
||||
'indexation' => [
|
||||
'jquery-ui-core',
|
||||
'jquery-ui-progressbar',
|
||||
],
|
||||
'post-edit' => [
|
||||
self::PREFIX . 'api-client',
|
||||
self::PREFIX . 'block-editor',
|
||||
self::PREFIX . 'select2',
|
||||
],
|
||||
'reindex-links' => [
|
||||
'jquery-ui-core',
|
||||
'jquery-ui-progressbar',
|
||||
],
|
||||
'settings' => [
|
||||
'jquery-ui-core',
|
||||
'jquery-ui-progressbar',
|
||||
self::PREFIX . 'api-client',
|
||||
self::PREFIX . 'select2',
|
||||
],
|
||||
'term-edit' => [
|
||||
self::PREFIX . 'api-client',
|
||||
self::PREFIX . 'classic-editor',
|
||||
self::PREFIX . 'select2',
|
||||
],
|
||||
];
|
||||
|
||||
$plugin_scripts = $this->load_generated_asset_file(
|
||||
[
|
||||
'asset_file' => __DIR__ . '/../src/generated/assets/plugin.php',
|
||||
'ext_length' => $ext_length,
|
||||
'additional_deps' => $additional_dependencies,
|
||||
'header_scripts' => $header_scripts,
|
||||
]
|
||||
);
|
||||
$external_scripts = $this->load_generated_asset_file(
|
||||
[
|
||||
'asset_file' => __DIR__ . '/../src/generated/assets/externals.php',
|
||||
'ext_length' => $ext_length,
|
||||
'suffix' => '-package',
|
||||
'base_dir' => 'externals/',
|
||||
'additional_deps' => $additional_dependencies,
|
||||
'header_scripts' => $header_scripts,
|
||||
]
|
||||
);
|
||||
$language_scripts = $this->load_generated_asset_file(
|
||||
[
|
||||
'asset_file' => __DIR__ . '/../src/generated/assets/languages.php',
|
||||
'ext_length' => $ext_length,
|
||||
'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['post-edit-classic'] = [
|
||||
'name' => 'post-edit-classic',
|
||||
'src' => $scripts['post-edit']['src'],
|
||||
'deps' => array_map(
|
||||
function( $dep ) {
|
||||
if ( $dep === self::PREFIX . 'block-editor' ) {
|
||||
return self::PREFIX . 'classic-editor';
|
||||
}
|
||||
return $dep;
|
||||
},
|
||||
$scripts['post-edit']['deps']
|
||||
),
|
||||
'in_footer' => ! in_array( 'post-edit-classic', $header_scripts, true ),
|
||||
];
|
||||
|
||||
// Add the current language to every script that requires the analysis package.
|
||||
foreach ( $scripts as $name => $script ) {
|
||||
if ( substr( $name, -8 ) === 'language' ) {
|
||||
continue;
|
||||
}
|
||||
if ( in_array( self::PREFIX . 'analysis-package', $script['deps'], true ) ) {
|
||||
$scripts[ $name ]['deps'][] = self::PREFIX . YoastSEO()->helpers->language->get_researcher_language() . '-language';
|
||||
}
|
||||
}
|
||||
|
||||
return $scripts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a generated asset file.
|
||||
*
|
||||
* @param array $args {
|
||||
* The arguments.
|
||||
*
|
||||
* @type string $asset_file The asset file to load.
|
||||
* @type int $ext_length The length of the extension, including suffix, of the filename.
|
||||
* @type string $suffix Optional. The suffix of the asset name.
|
||||
* @type array<string, string[]> $additional_deps Optional. The additional dependencies assets may have.
|
||||
* @type string $base_dir Optional. The base directory of the asset.
|
||||
* @type string[] $header_scripts Optional. The script names that should be in the header.
|
||||
* }
|
||||
*
|
||||
* @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_generated_asset_file( $args ) {
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
[
|
||||
'suffix' => '',
|
||||
'additional_deps' => [],
|
||||
'base_dir' => '',
|
||||
'header_scripts' => [],
|
||||
]
|
||||
);
|
||||
$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'];
|
||||
|
||||
$deps = $data['dependencies'];
|
||||
if ( isset( $args['additional_deps'][ $name ] ) ) {
|
||||
$deps = array_merge( $deps, $args['additional_deps'][ $name ] );
|
||||
}
|
||||
|
||||
$scripts[ $name ] = [
|
||||
'name' => $name,
|
||||
'src' => $args['base_dir'] . $file,
|
||||
'deps' => $deps,
|
||||
'in_footer' => ! in_array( $name, $args['header_scripts'], true ),
|
||||
];
|
||||
}
|
||||
|
||||
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 = WPSEO_Utils::get_user_locale();
|
||||
$language = WPSEO_Utils::get_language( $user_locale );
|
||||
$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.
|
||||
|
|
@ -191,217 +404,80 @@ class WPSEO_Admin_Asset_Manager {
|
|||
$select2_language = $language;
|
||||
}
|
||||
|
||||
$flat_version = $this->flatten_version( WPSEO_VERSION );
|
||||
$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 array(
|
||||
array(
|
||||
'name' => 'react-dependencies',
|
||||
// Load webpack-commons for bundle support.
|
||||
'src' => 'commons-' . $flat_version,
|
||||
'deps' => array(
|
||||
self::PREFIX . 'intl-polyfill',
|
||||
self::PREFIX . 'babel-polyfill',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'help-center',
|
||||
'src' => 'wp-seo-help-center-' . $flat_version,
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
self::PREFIX . 'react-dependencies',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'admin-script',
|
||||
'src' => 'wp-seo-admin-' . $flat_version,
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
'jquery-ui-core',
|
||||
'jquery-ui-progressbar',
|
||||
self::PREFIX . 'select2',
|
||||
self::PREFIX . 'select2-translations',
|
||||
self::PREFIX . 'babel-polyfill',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'admin-media',
|
||||
'src' => 'wp-seo-admin-media-' . $flat_version,
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
'jquery-ui-core',
|
||||
self::PREFIX . 'babel-polyfill',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'bulk-editor',
|
||||
'src' => 'wp-seo-bulk-editor-' . $flat_version,
|
||||
'deps' => array( 'jquery', self::PREFIX . 'babel-polyfill' ),
|
||||
),
|
||||
array(
|
||||
'name' => 'dismissible',
|
||||
'src' => 'wp-seo-dismissible-' . $flat_version,
|
||||
'deps' => array( 'jquery', self::PREFIX . 'babel-polyfill' ),
|
||||
),
|
||||
array(
|
||||
'name' => 'admin-global-script',
|
||||
'src' => 'wp-seo-admin-global-' . $flat_version,
|
||||
'deps' => array( 'jquery', self::PREFIX . 'babel-polyfill' ),
|
||||
),
|
||||
array(
|
||||
'name' => 'metabox',
|
||||
'src' => 'wp-seo-metabox-' . $flat_version,
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
self::PREFIX . 'select2',
|
||||
self::PREFIX . 'select2-translations',
|
||||
self::PREFIX . 'react-dependencies',
|
||||
),
|
||||
'in_footer' => false,
|
||||
),
|
||||
array(
|
||||
'name' => 'featured-image',
|
||||
'src' => 'wp-seo-featured-image-' . $flat_version,
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
self::PREFIX . 'babel-polyfill',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'admin-gsc',
|
||||
'src' => 'wp-seo-admin-gsc-' . $flat_version,
|
||||
'deps' => array( self::PREFIX . 'babel-polyfill' ),
|
||||
'in_footer' => false,
|
||||
),
|
||||
array(
|
||||
'name' => 'post-scraper',
|
||||
'src' => 'wp-seo-post-scraper-' . $flat_version,
|
||||
'deps' => array(
|
||||
self::PREFIX . 'replacevar-plugin',
|
||||
self::PREFIX . 'shortcode-plugin',
|
||||
'wp-util',
|
||||
self::PREFIX . 'react-dependencies',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'term-scraper',
|
||||
'src' => 'wp-seo-term-scraper-' . $flat_version,
|
||||
'deps' => array(
|
||||
self::PREFIX . 'replacevar-plugin',
|
||||
self::PREFIX . 'react-dependencies',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'replacevar-plugin',
|
||||
'src' => 'wp-seo-replacevar-plugin-' . $flat_version,
|
||||
'deps' => array(
|
||||
self::PREFIX . 'babel-polyfill',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'shortcode-plugin',
|
||||
'src' => 'wp-seo-shortcode-plugin-' . $flat_version,
|
||||
'deps' => array(
|
||||
self::PREFIX . 'babel-polyfill',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'recalculate',
|
||||
'src' => 'wp-seo-recalculate-' . $flat_version,
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
'jquery-ui-core',
|
||||
'jquery-ui-progressbar',
|
||||
self::PREFIX . 'babel-polyfill',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'primary-category',
|
||||
'src' => 'wp-seo-metabox-category-' . $flat_version,
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
'wp-util',
|
||||
self::PREFIX . 'babel-polyfill',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'select2',
|
||||
'src' => 'select2/select2.full',
|
||||
'suffix' => '.min',
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
),
|
||||
'version' => '4.0.3',
|
||||
),
|
||||
array(
|
||||
'name' => 'select2-translations',
|
||||
'src' => 'select2/i18n/' . $select2_language,
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
self::PREFIX . 'select2',
|
||||
),
|
||||
'version' => '4.0.3',
|
||||
'suffix' => '',
|
||||
),
|
||||
array(
|
||||
'name' => 'configuration-wizard',
|
||||
'src' => 'configuration-wizard-' . $flat_version,
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
self::PREFIX . 'react-dependencies',
|
||||
),
|
||||
),
|
||||
// Register for backwards-compatiblity.
|
||||
array(
|
||||
'name' => 'polyfill',
|
||||
'src' => 'wp-seo-babel-polyfill-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
'name' => 'babel-polyfill',
|
||||
'src' => 'wp-seo-babel-polyfill-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
'name' => 'reindex-links',
|
||||
'src' => 'wp-seo-reindex-links-' . $flat_version,
|
||||
'deps' => array(
|
||||
'jquery',
|
||||
'jquery-ui-core',
|
||||
'jquery-ui-progressbar',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'edit-page-script',
|
||||
'src' => 'wp-seo-edit-page-' . $flat_version,
|
||||
'deps' => array( 'jquery' ),
|
||||
),
|
||||
array(
|
||||
'name' => 'quick-edit-handler',
|
||||
'src' => 'wp-seo-quick-edit-handler-' . $flat_version,
|
||||
'deps' => array( 'jquery' ),
|
||||
'in_footer' => true,
|
||||
),
|
||||
array(
|
||||
'name' => 'api',
|
||||
'src' => 'wp-seo-api-' . $flat_version,
|
||||
'deps' => array(
|
||||
'wp-api',
|
||||
'jquery',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'dashboard-widget',
|
||||
'src' => 'wp-seo-dashboard-widget-' . $flat_version,
|
||||
'deps' => array(
|
||||
self::PREFIX . 'api',
|
||||
'jquery',
|
||||
self::PREFIX . 'react-dependencies',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => 'filter-explanation',
|
||||
'src' => 'wp-seo-filter-explanation-' . $flat_version,
|
||||
'deps' => array( 'jquery' ),
|
||||
),
|
||||
);
|
||||
return $scripts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the scripts that should be renamed for BC.
|
||||
*
|
||||
* @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_renamed_scripts() {
|
||||
$scripts = [];
|
||||
$renamed_scripts = [
|
||||
'admin-global-script' => 'admin-global',
|
||||
'analysis' => 'analysis-package',
|
||||
'analysis-report' => 'analysis-report-package',
|
||||
'api' => 'api-client',
|
||||
'commons' => 'commons-package',
|
||||
'edit-page' => 'edit-page-script',
|
||||
'draft-js' => 'draft-js-package',
|
||||
'feature-flag' => 'feature-flag-package',
|
||||
'helpers' => 'helpers-package',
|
||||
'jed' => 'jed-package',
|
||||
'legacy-components' => 'components-package',
|
||||
'network-admin-script' => 'network-admin',
|
||||
'redux' => 'redux-package',
|
||||
'replacement-variable-editor' => 'replacement-variable-editor-package',
|
||||
'search-metadata-previews' => 'search-metadata-previews-package',
|
||||
'social-metadata-forms' => 'social-metadata-forms-package',
|
||||
'styled-components' => 'styled-components-package',
|
||||
'style-guide' => 'style-guide-package',
|
||||
'yoast-components' => 'components-new-package',
|
||||
];
|
||||
|
||||
foreach ( $renamed_scripts as $original => $replacement ) {
|
||||
$scripts[] = [
|
||||
'name' => $original,
|
||||
'src' => false,
|
||||
'deps' => [ self::PREFIX . $replacement ],
|
||||
];
|
||||
}
|
||||
|
||||
return $scripts;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -409,87 +485,141 @@ class WPSEO_Admin_Asset_Manager {
|
|||
*
|
||||
* @todo Data format is not self-documenting. Needs explanation inline. R.
|
||||
*
|
||||
* @return array styles that need to be registered.
|
||||
* @return array Styles that need to be registered.
|
||||
*/
|
||||
private function styles_to_be_registered() {
|
||||
protected function styles_to_be_registered() {
|
||||
$flat_version = $this->flatten_version( WPSEO_VERSION );
|
||||
|
||||
return array(
|
||||
array(
|
||||
return [
|
||||
[
|
||||
'name' => 'admin-css',
|
||||
'src' => 'yst_plugin_tools-' . $flat_version,
|
||||
'deps' => array( self::PREFIX . 'toggle-switch' ),
|
||||
),
|
||||
array(
|
||||
'name' => 'toggle-switch',
|
||||
'src' => 'toggle-switch-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
'deps' => [ self::PREFIX . 'toggle-switch' ],
|
||||
],
|
||||
[
|
||||
'name' => 'toggle-switch',
|
||||
'src' => 'toggle-switch-' . $flat_version,
|
||||
],
|
||||
[
|
||||
'name' => 'dismissible',
|
||||
'src' => 'wpseo-dismissible-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
'name' => 'alerts',
|
||||
],
|
||||
[
|
||||
'name' => 'notifications',
|
||||
'src' => 'notifications-' . $flat_version,
|
||||
],
|
||||
[
|
||||
'name' => 'alert',
|
||||
'src' => 'alerts-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'name' => 'edit-page',
|
||||
'src' => 'edit-page-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'name' => 'featured-image',
|
||||
'src' => 'featured-image-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'name' => 'metabox-css',
|
||||
'src' => 'metabox-' . $flat_version,
|
||||
'deps' => array(
|
||||
'deps' => [
|
||||
self::PREFIX . 'select2',
|
||||
),
|
||||
),
|
||||
array(
|
||||
self::PREFIX . 'admin-css',
|
||||
'wp-components',
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'wp-dashboard',
|
||||
'src' => 'dashboard-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'name' => 'scoring',
|
||||
'src' => 'yst_seo_score-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
'name' => 'snippet',
|
||||
'src' => 'snippet-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'name' => 'adminbar',
|
||||
'src' => 'adminbar-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
'deps' => [
|
||||
'admin-bar',
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'primary-category',
|
||||
'src' => 'metabox-primary-category-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'name' => 'select2',
|
||||
'src' => 'select2/select2',
|
||||
'suffix' => '.min',
|
||||
'version' => '4.0.1',
|
||||
'rtl' => false,
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'name' => 'admin-global',
|
||||
'src' => 'admin-global-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'name' => 'yoast-components',
|
||||
'src' => 'yoast-components-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'name' => 'extensions',
|
||||
'src' => 'yoast-extensions-' . $flat_version,
|
||||
),
|
||||
array(
|
||||
'deps' => [
|
||||
'wp-components',
|
||||
],
|
||||
],
|
||||
[
|
||||
'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,
|
||||
],
|
||||
[
|
||||
'name' => 'structured-data-blocks',
|
||||
'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' => 'workouts',
|
||||
'src' => 'workouts-' . $flat_version,
|
||||
'deps' => [ self::PREFIX . 'monorepo' ],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the URL of the asset.
|
||||
*
|
||||
* @param WPSEO_Admin_Asset $asset The asset to determine the URL for.
|
||||
* @param string $type The type of asset. Usually JS or CSS.
|
||||
*
|
||||
* @return string The URL of the asset.
|
||||
*/
|
||||
protected function get_url( WPSEO_Admin_Asset $asset, $type ) {
|
||||
$scheme = wp_parse_url( $asset->get_src(), PHP_URL_SCHEME );
|
||||
if ( in_array( $scheme, [ 'http', 'https' ], true ) ) {
|
||||
return $asset->get_src();
|
||||
}
|
||||
|
||||
return $this->asset_location->get_url( $asset, $type );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,17 +11,28 @@
|
|||
final class WPSEO_Admin_Asset_SEO_Location implements WPSEO_Admin_Asset_Location {
|
||||
|
||||
/**
|
||||
* Path to the plugin file.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $plugin_file;
|
||||
|
||||
/**
|
||||
* Whether or not to add the file suffix to the asset.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $add_suffix = true;
|
||||
|
||||
/**
|
||||
* The plugin file to base the asset location upon.
|
||||
*
|
||||
* @param string $plugin_file The plugin file string.
|
||||
* @param string $plugin_file The plugin file string.
|
||||
* @param boolean $add_suffix Optional. Whether or not a file suffix should be added.
|
||||
*/
|
||||
public function __construct( $plugin_file ) {
|
||||
public function __construct( $plugin_file, $add_suffix = true ) {
|
||||
$this->plugin_file = $plugin_file;
|
||||
$this->add_suffix = $add_suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -38,57 +49,35 @@ final class WPSEO_Admin_Asset_SEO_Location implements WPSEO_Admin_Asset_Location
|
|||
return '';
|
||||
}
|
||||
|
||||
if ( YOAST_ENVIRONMENT !== 'development' && ! $asset->get_suffix() ) {
|
||||
$plugin_path = plugin_dir_path( $this->plugin_file );
|
||||
if ( ! file_exists( $plugin_path . $path ) ) {
|
||||
|
||||
// Give a notice to the user in the console (only once).
|
||||
WPSEO_Utils::javascript_console_notification(
|
||||
'Development Files',
|
||||
sprintf(
|
||||
/* translators: %1$s resolves to https://github.com/Yoast/wordpress-seo */
|
||||
__( 'You are trying to load non-minified files. These are only available in our development package. Check out %1$s to see all the source files.', 'wordpress-seo' ),
|
||||
'https://github.com/Yoast/wordpress-seo'
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
// Just load the .min file.
|
||||
$path = $this->get_path( $asset, $type, '.min' );
|
||||
}
|
||||
}
|
||||
|
||||
return plugins_url( $path, $this->plugin_file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the path relative to the plugin folder of an asset.
|
||||
*
|
||||
* @param WPSEO_Admin_Asset $asset The asset to determine the path
|
||||
* for.
|
||||
* @param string $type The type of asset.
|
||||
* @param string|null $force_suffix The suffix to force, or null when
|
||||
* to use the default suffix.
|
||||
* @param WPSEO_Admin_Asset $asset The asset to determine the path for.
|
||||
* @param string $type The type of asset.
|
||||
*
|
||||
* @return string The path to the asset file.
|
||||
*/
|
||||
protected function get_path( WPSEO_Admin_Asset $asset, $type, $force_suffix = null ) {
|
||||
protected function get_path( WPSEO_Admin_Asset $asset, $type ) {
|
||||
$relative_path = '';
|
||||
$rtl_suffix = '';
|
||||
|
||||
$suffix = ( $force_suffix === null ) ? $asset->get_suffix() : $force_suffix;
|
||||
|
||||
switch ( $type ) {
|
||||
case WPSEO_Admin_Asset::TYPE_JS:
|
||||
$relative_path = 'js/dist/' . $asset->get_src() . $suffix . '.js';
|
||||
$relative_path = 'js/dist/' . $asset->get_src();
|
||||
if ( $this->add_suffix ) {
|
||||
$relative_path = $relative_path . $asset->get_suffix() . '.js';
|
||||
}
|
||||
break;
|
||||
|
||||
case WPSEO_Admin_Asset::TYPE_CSS:
|
||||
// Path and suffix for RTL stylesheets.
|
||||
if ( function_exists( 'is_rtl' ) && is_rtl() && $asset->has_rtl() ) {
|
||||
if ( is_rtl() && $asset->has_rtl() ) {
|
||||
$rtl_suffix = '-rtl';
|
||||
}
|
||||
$relative_path = 'css/dist/' . $asset->get_src() . $rtl_suffix . $suffix . '.css';
|
||||
$relative_path = 'css/dist/' . $asset->get_src() . $rtl_suffix . $asset->get_suffix() . '.css';
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Localizes JavaScript files.
|
||||
*/
|
||||
final class WPSEO_Admin_Asset_Yoast_Components_L10n {
|
||||
|
||||
/**
|
||||
* Represents the asset manager.
|
||||
*
|
||||
* @var WPSEO_Admin_Asset_Manager
|
||||
*/
|
||||
protected $asset_manager;
|
||||
|
||||
/**
|
||||
* WPSEO_Admin_Asset_Yoast_Components_L10n constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->asset_manager = new WPSEO_Admin_Asset_Manager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Localizes the given script with the JavaScript translations.
|
||||
*
|
||||
* @param string $script_handle The script handle to localize for.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function localize_script( $script_handle ) {
|
||||
$translations = [
|
||||
'yoast-components' => $this->get_translations( 'yoast-components' ),
|
||||
'wordpress-seo' => $this->get_translations( 'wordpress-seojs' ),
|
||||
'yoast-schema-blocks' => $this->get_translations( 'yoast-schema-blocks' ),
|
||||
];
|
||||
$this->asset_manager->localize_script( $script_handle, 'wpseoYoastJSL10n', $translations );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns translations necessary for JS files.
|
||||
*
|
||||
* @param string $component The component to retrieve the translations for.
|
||||
* @return object|null The translations in a Jed format for JS files.
|
||||
*/
|
||||
protected function get_translations( $component ) {
|
||||
$locale = \get_user_locale();
|
||||
|
||||
$file = WPSEO_PATH . 'languages/' . $component . '-' . $locale . '.json';
|
||||
if ( file_exists( $file ) ) {
|
||||
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Retrieving a local file.
|
||||
$file = file_get_contents( $file );
|
||||
if ( is_string( $file ) && $file !== '' ) {
|
||||
return json_decode( $file, true );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determines the editor specific replacement variables.
|
||||
*/
|
||||
class WPSEO_Admin_Editor_Specific_Replace_Vars {
|
||||
|
||||
/**
|
||||
* Holds the editor specific replacements variables.
|
||||
*
|
||||
* @var array The editor specific replacement variables.
|
||||
*/
|
||||
protected $replacement_variables = [
|
||||
// Posts types.
|
||||
'page' => [ 'id', 'pt_single', 'pt_plural', 'parent_title' ],
|
||||
'post' => [ 'id', 'term404', 'pt_single', 'pt_plural' ],
|
||||
// Custom post type.
|
||||
'custom_post_type' => [ 'id', 'term404', 'pt_single', 'pt_plural', 'parent_title' ],
|
||||
// Settings - archive pages.
|
||||
'custom-post-type_archive' => [ 'pt_single', 'pt_plural' ],
|
||||
|
||||
// Taxonomies.
|
||||
'category' => [ 'term_title', 'term_description', 'category_description', 'parent_title', 'term_hierarchy' ],
|
||||
'post_tag' => [ 'term_title', 'term_description', 'tag_description' ],
|
||||
'post_format' => [ 'term_title' ],
|
||||
// Custom taxonomy.
|
||||
'term-in-custom-taxonomy' => [ 'term_title', 'term_description', 'category_description', 'parent_title', 'term_hierarchy' ],
|
||||
|
||||
// Settings - special pages.
|
||||
'search' => [ 'searchphrase' ],
|
||||
];
|
||||
|
||||
/**
|
||||
* WPSEO_Admin_Editor_Specific_Replace_Vars constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->add_for_page_types(
|
||||
[ 'page', 'post', 'custom_post_type' ],
|
||||
WPSEO_Custom_Fields::get_custom_fields()
|
||||
);
|
||||
|
||||
$this->add_for_page_types(
|
||||
[ 'post', 'term-in-custom-taxonomy' ],
|
||||
WPSEO_Custom_Taxonomies::get_custom_taxonomies()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the editor specific replacement variables.
|
||||
*
|
||||
* @return array The editor specific replacement variables.
|
||||
*/
|
||||
public function get() {
|
||||
/**
|
||||
* Filter: Adds the possibility to add extra editor specific replacement variables.
|
||||
*
|
||||
* @api array $replacement_variables Array of editor specific replace vars.
|
||||
*/
|
||||
$replacement_variables = apply_filters(
|
||||
'wpseo_editor_specific_replace_vars',
|
||||
$this->replacement_variables
|
||||
);
|
||||
|
||||
if ( ! is_array( $replacement_variables ) ) {
|
||||
$replacement_variables = $this->replacement_variables;
|
||||
}
|
||||
|
||||
return array_filter( $replacement_variables, 'is_array' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the generic replacement variable names.
|
||||
*
|
||||
* Which are the replacement variables without the editor specific ones.
|
||||
*
|
||||
* @param array $replacement_variables Possibly generic replacement variables.
|
||||
*
|
||||
* @return array The generic replacement variable names.
|
||||
*/
|
||||
public function get_generic( $replacement_variables ) {
|
||||
$shared_variables = array_diff(
|
||||
$this->extract_names( $replacement_variables ),
|
||||
$this->get_unique_replacement_variables()
|
||||
);
|
||||
|
||||
return array_values( $shared_variables );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the page type of the current term.
|
||||
*
|
||||
* @param string $taxonomy The taxonomy name.
|
||||
*
|
||||
* @return string The page type.
|
||||
*/
|
||||
public function determine_for_term( $taxonomy ) {
|
||||
$replacement_variables = $this->get();
|
||||
if ( array_key_exists( $taxonomy, $replacement_variables ) ) {
|
||||
return $taxonomy;
|
||||
}
|
||||
|
||||
return 'term-in-custom-taxonomy';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the page type of the current post.
|
||||
*
|
||||
* @param WP_Post $post A WordPress post instance.
|
||||
*
|
||||
* @return string The page type.
|
||||
*/
|
||||
public function determine_for_post( $post ) {
|
||||
if ( $post instanceof WP_Post === false ) {
|
||||
return 'post';
|
||||
}
|
||||
|
||||
$replacement_variables = $this->get();
|
||||
if ( array_key_exists( $post->post_type, $replacement_variables ) ) {
|
||||
return $post->post_type;
|
||||
}
|
||||
|
||||
return 'custom_post_type';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the page type for a post type.
|
||||
*
|
||||
* @param string $post_type The name of the post_type.
|
||||
* @param string $fallback The page type to fall back to.
|
||||
*
|
||||
* @return string The page type.
|
||||
*/
|
||||
public function determine_for_post_type( $post_type, $fallback = 'custom_post_type' ) {
|
||||
if ( ! $this->has_for_page_type( $post_type ) ) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
return $post_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the page type for an archive page.
|
||||
*
|
||||
* @param string $name The name of the archive.
|
||||
* @param string $fallback The page type to fall back to.
|
||||
*
|
||||
* @return string The page type.
|
||||
*/
|
||||
public function determine_for_archive( $name, $fallback = 'custom-post-type_archive' ) {
|
||||
$page_type = $name . '_archive';
|
||||
|
||||
if ( ! $this->has_for_page_type( $page_type ) ) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
return $page_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the replavement variables for the given page types.
|
||||
*
|
||||
* @param array $page_types Page types to add variables for.
|
||||
* @param array $replacement_variables_to_add The variables to add.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function add_for_page_types( array $page_types, array $replacement_variables_to_add ) {
|
||||
if ( empty( $replacement_variables_to_add ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$replacement_variables_to_add = array_fill_keys( $page_types, $replacement_variables_to_add );
|
||||
$replacement_variables = $this->replacement_variables;
|
||||
|
||||
$this->replacement_variables = array_merge_recursive( $replacement_variables, $replacement_variables_to_add );
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the names from the given replacements variables.
|
||||
*
|
||||
* @param array $replacement_variables Replacement variables to extract the name from.
|
||||
*
|
||||
* @return array Extracted names.
|
||||
*/
|
||||
protected function extract_names( $replacement_variables ) {
|
||||
$extracted_names = [];
|
||||
|
||||
foreach ( $replacement_variables as $replacement_variable ) {
|
||||
if ( empty( $replacement_variable['name'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extracted_names[] = $replacement_variable['name'];
|
||||
}
|
||||
|
||||
return $extracted_names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given page type has editor specific replace vars.
|
||||
*
|
||||
* @param string $page_type The page type to check.
|
||||
*
|
||||
* @return bool True if there are associated editor specific replace vars.
|
||||
*/
|
||||
protected function has_for_page_type( $page_type ) {
|
||||
$replacement_variables = $this->get();
|
||||
|
||||
return ( ! empty( $replacement_variables[ $page_type ] ) && is_array( $replacement_variables[ $page_type ] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges all editor specific replacement variables into one array and removes duplicates.
|
||||
*
|
||||
* @return array The list of unique editor specific replacement variables.
|
||||
*/
|
||||
protected function get_unique_replacement_variables() {
|
||||
$merged_replacement_variables = call_user_func_array( 'array_merge', array_values( $this->get() ) );
|
||||
|
||||
return array_unique( $merged_replacement_variables );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Handles the Gutenberg Compatibility notification showing and hiding.
|
||||
*/
|
||||
class WPSEO_Admin_Gutenberg_Compatibility_Notification implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* Notification ID to use.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $notification_id = 'wpseo-outdated-gutenberg-plugin';
|
||||
|
||||
/**
|
||||
* Instance of gutenberg compatibility checker.
|
||||
*
|
||||
* @var WPSEO_Gutenberg_Compatibility
|
||||
*/
|
||||
protected $compatibility_checker;
|
||||
|
||||
/**
|
||||
* Instance of Yoast Notification Center.
|
||||
*
|
||||
* @var Yoast_Notification_Center
|
||||
*/
|
||||
protected $notification_center;
|
||||
|
||||
/**
|
||||
* WPSEO_Admin_Gutenberg_Compatibility_Notification constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->compatibility_checker = new WPSEO_Gutenberg_Compatibility();
|
||||
$this->notification_center = Yoast_Notification_Center::get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all hooks to WordPress.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
add_action( 'admin_init', [ $this, 'manage_notification' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages if the notification should be shown or removed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function manage_notification() {
|
||||
/**
|
||||
* Filter: 'yoast_display_gutenberg_compat_notification' - Allows developer to disable the Gutenberg compatibility
|
||||
* notification.
|
||||
*
|
||||
* @api bool
|
||||
*/
|
||||
$display_notification = apply_filters( 'yoast_display_gutenberg_compat_notification', true );
|
||||
|
||||
if (
|
||||
! $this->compatibility_checker->is_installed()
|
||||
|| $this->compatibility_checker->is_fully_compatible()
|
||||
|| ! $display_notification
|
||||
) {
|
||||
$this->notification_center->remove_notification_by_id( $this->notification_id );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->add_notification();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the notification to the notificaton center.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function add_notification() {
|
||||
$level = $this->compatibility_checker->is_below_minimum() ? Yoast_Notification::ERROR : Yoast_Notification::WARNING;
|
||||
|
||||
$message = sprintf(
|
||||
/* translators: %1$s expands to Yoast SEO, %2$s expands to the installed version, %3$s expands to Gutenberg */
|
||||
__( '%1$s detected you are using version %2$s of %3$s, please update to the latest version to prevent compatibility issues.', 'wordpress-seo' ),
|
||||
'Yoast SEO',
|
||||
$this->compatibility_checker->get_installed_version(),
|
||||
'Gutenberg'
|
||||
);
|
||||
|
||||
$notification = new Yoast_Notification(
|
||||
$message,
|
||||
[
|
||||
'id' => $this->notification_id,
|
||||
'type' => $level,
|
||||
'priority' => 1,
|
||||
]
|
||||
);
|
||||
|
||||
$this->notification_center->add_notification( $notification );
|
||||
}
|
||||
}
|
||||
|
|
@ -11,21 +11,29 @@
|
|||
class WPSEO_Admin_Help_Panel {
|
||||
|
||||
/**
|
||||
* Unique identifier of the element the inline help refers to, used as an identifier in the html.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* The Help Button text. Needs a properly escaped string.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $help_button_text;
|
||||
|
||||
/**
|
||||
* The Help Panel content. Needs a properly escaped string (might contain HTML).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $help_content;
|
||||
|
||||
/**
|
||||
* Optional Whether to print out a container div element for the Help Panel, used for styling.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $wrapper;
|
||||
|
|
@ -33,11 +41,13 @@ class WPSEO_Admin_Help_Panel {
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $id Unique identifier of the element the inline help refers to, used as an identifier in the html.
|
||||
* @param string $help_button_text The Help Button text. Needs a properly escaped string.
|
||||
* @param string $help_content The Help Panel content. Needs a properly escaped string (might contain HTML).
|
||||
* @param string $wrapper Optional Whether to print out a container div element for the Help Panel, used for styling.
|
||||
* Pass a `has-wrapper` value to print out the container. Default: no container.
|
||||
* @param string $id Unique identifier of the element the inline help refers to, used as
|
||||
* an identifier in the html.
|
||||
* @param string $help_button_text The Help Button text. Needs a properly escaped string.
|
||||
* @param string $help_content The Help Panel content. Needs a properly escaped string (might contain HTML).
|
||||
* @param string $wrapper Optional Whether to print out a container div element for the Help Panel,
|
||||
* used for styling.
|
||||
* Pass a `has-wrapper` value to print out the container. Default: no container.
|
||||
*/
|
||||
public function __construct( $id, $help_button_text, $help_content, $wrapper = '' ) {
|
||||
$this->id = $id;
|
||||
|
|
@ -78,7 +88,7 @@ class WPSEO_Admin_Help_Panel {
|
|||
$wrapper_start = '';
|
||||
$wrapper_end = '';
|
||||
|
||||
if ( 'has-wrapper' === $this->wrapper ) {
|
||||
if ( $this->wrapper === 'has-wrapper' ) {
|
||||
$wrapper_start = '<div class="yoast-seo-help-container">';
|
||||
$wrapper_end = '</div>';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class WPSEO_Admin_Init {
|
|||
private $asset_manager;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* Class constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$GLOBALS['wpseo_admin'] = new WPSEO_Admin();
|
||||
|
|
@ -34,18 +34,33 @@ class WPSEO_Admin_Init {
|
|||
|
||||
$this->asset_manager = new WPSEO_Admin_Asset_Manager();
|
||||
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_dismissible' ) );
|
||||
add_action( 'admin_init', array( $this, 'tagline_notice' ), 15 );
|
||||
add_action( 'admin_init', array( $this, 'blog_public_notice' ), 15 );
|
||||
add_action( 'admin_init', array( $this, 'permalink_notice' ), 15 );
|
||||
add_action( 'admin_init', array( $this, 'page_comments_notice' ), 15 );
|
||||
add_action( 'admin_init', array( $this, 'ga_compatibility_notice' ), 15 );
|
||||
add_action( 'admin_init', array( $this, 'yoast_plugin_compatibility_notification' ), 15 );
|
||||
add_action( 'admin_init', array( $this, 'yoast_plugin_suggestions_notification' ), 15 );
|
||||
add_action( 'admin_init', array( $this, 'recalculate_notice' ), 15 );
|
||||
add_action( 'admin_init', array( $this->asset_manager, 'register_assets' ) );
|
||||
add_action( 'admin_init', array( $this, 'show_hook_deprecation_warnings' ) );
|
||||
add_action( 'admin_init', array( 'WPSEO_Plugin_Conflict', 'hook_check_for_plugin_conflicts' ) );
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_dismissible' ] );
|
||||
add_action( 'admin_init', [ $this, 'unsupported_php_notice' ], 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();
|
||||
|
|
@ -63,362 +78,36 @@ class WPSEO_Admin_Init {
|
|||
}
|
||||
|
||||
/**
|
||||
* Helper to verify if the current user has already seen the about page for the current version
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function seen_about() {
|
||||
$seen_about_version = substr( get_user_meta( get_current_user_id(), 'wpseo_seen_about_version', true ), 0, 3 );
|
||||
$last_minor_version = substr( WPSEO_VERSION, 0, 3 );
|
||||
|
||||
return version_compare( $seen_about_version, $last_minor_version, '>=' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify about the default tagline if the user hasn't changed it
|
||||
*/
|
||||
public function tagline_notice() {
|
||||
|
||||
$current_url = ( is_ssl() ? 'https://' : 'http://' );
|
||||
$current_url .= sanitize_text_field( $_SERVER['SERVER_NAME'] ) . sanitize_text_field( $_SERVER['REQUEST_URI'] );
|
||||
$customize_url = add_query_arg( array(
|
||||
'url' => urlencode( $current_url ),
|
||||
), wp_customize_url() );
|
||||
|
||||
$info_message = sprintf(
|
||||
/* translators: 1: link open tag; 2: link close tag. */
|
||||
__( 'You still have the default WordPress tagline, even an empty one is probably better. %1$sYou can fix this in the customizer%2$s.', 'wordpress-seo' ),
|
||||
'<a href="' . esc_attr( $customize_url ) . '">',
|
||||
'</a>'
|
||||
);
|
||||
|
||||
$notification_options = array(
|
||||
'type' => Yoast_Notification::ERROR,
|
||||
'id' => 'wpseo-dismiss-tagline-notice',
|
||||
'capabilities' => 'wpseo_manage_options',
|
||||
);
|
||||
|
||||
$tagline_notification = new Yoast_Notification( $info_message, $notification_options );
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
if ( $this->has_default_tagline() ) {
|
||||
$notification_center->add_notification( $tagline_notification );
|
||||
}
|
||||
else {
|
||||
$notification_center->remove_notification( $tagline_notification );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an alert if the blog is not publicly visible
|
||||
*/
|
||||
public function blog_public_notice() {
|
||||
|
||||
$info_message = '<strong>' . __( 'Huge SEO Issue: You\'re blocking access to robots.', 'wordpress-seo' ) . '</strong> ';
|
||||
$info_message .= sprintf(
|
||||
/* translators: %1$s resolves to the opening tag of the link to the reading settings, %1$s resolves to the closing tag for the link */
|
||||
__( '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>'
|
||||
);
|
||||
|
||||
$notification_options = array(
|
||||
'type' => Yoast_Notification::ERROR,
|
||||
'id' => 'wpseo-dismiss-blog-public-notice',
|
||||
'priority' => 1.0,
|
||||
'capabilities' => 'wpseo_manage_options',
|
||||
);
|
||||
|
||||
$notification = new Yoast_Notification( $info_message, $notification_options );
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
if ( ! $this->is_blog_public() ) {
|
||||
$notification_center->add_notification( $notification );
|
||||
}
|
||||
else {
|
||||
$notification_center->remove_notification( $notification );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display notice to disable comment pagination
|
||||
*/
|
||||
public function page_comments_notice() {
|
||||
|
||||
$info_message = __( 'Paging comments is enabled, this is not needed in 999 out of 1000 cases, we recommend to disable it.', 'wordpress-seo' );
|
||||
$info_message .= '<br/>';
|
||||
|
||||
$info_message .= sprintf(
|
||||
/* translators: %1$s resolves to the opening tag of the link to the comment setting page, %2$s resolves to the closing tag of the link */
|
||||
__( 'To fix this uncheck the box in front of the "Break comments into pages..." on the %1$sComment settings page%2$s.', 'wordpress-seo' ),
|
||||
'<a href="' . esc_url( admin_url( 'options-discussion.php' ) ) . '">',
|
||||
'</a>'
|
||||
);
|
||||
|
||||
$notification_options = array(
|
||||
'type' => Yoast_Notification::WARNING,
|
||||
'id' => 'wpseo-dismiss-page_comments-notice',
|
||||
'capabilities' => 'wpseo_manage_options',
|
||||
);
|
||||
|
||||
$tagline_notification = new Yoast_Notification( $info_message, $notification_options );
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
if ( $this->has_page_comments() ) {
|
||||
$notification_center->add_notification( $tagline_notification );
|
||||
}
|
||||
else {
|
||||
$notification_center->remove_notification( $tagline_notification );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the site has the default tagline
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_default_tagline() {
|
||||
$blog_description = get_bloginfo( 'description' );
|
||||
$default_blog_description = 'Just another WordPress site';
|
||||
|
||||
// We are checking against the WordPress internal translation.
|
||||
// @codingStandardsIgnoreLine
|
||||
$translated_blog_description = __( 'Just another WordPress site' );
|
||||
|
||||
return $translated_blog_description === $blog_description || $default_blog_description === $blog_description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show alert when the permalink doesn't contain %postname%
|
||||
*/
|
||||
public function permalink_notice() {
|
||||
|
||||
$info_message = __( 'You do not have your postname in the URL of your posts and pages, it is highly recommended that you do. Consider setting your permalink structure to <strong>/%postname%/</strong>.', 'wordpress-seo' );
|
||||
$info_message .= '<br/>';
|
||||
$info_message .= sprintf(
|
||||
/* translators: %1$s resolves to the starting tag of the link to the permalink settings page, %2$s resolves to the closing tag of the link */
|
||||
__( 'You can fix this on the %1$sPermalink settings page%2$s.', 'wordpress-seo' ),
|
||||
'<a href="' . admin_url( 'options-permalink.php' ) . '">',
|
||||
'</a>'
|
||||
);
|
||||
|
||||
$notification_options = array(
|
||||
'type' => Yoast_Notification::WARNING,
|
||||
'id' => 'wpseo-dismiss-permalink-notice',
|
||||
'capabilities' => 'wpseo_manage_options',
|
||||
'priority' => 0.8,
|
||||
);
|
||||
|
||||
$notification = new Yoast_Notification( $info_message, $notification_options );
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
if ( ! $this->has_postname_in_permalink() ) {
|
||||
$notification_center->add_notification( $notification );
|
||||
}
|
||||
else {
|
||||
$notification_center->remove_notification( $notification );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Are page comments enabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_page_comments() {
|
||||
return '1' === get_option( 'page_comments' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a notice to the user if they have Google Analytics for WordPress 5.4.3 installed because it causes an error
|
||||
* on the google search console page.
|
||||
*/
|
||||
public function ga_compatibility_notice() {
|
||||
|
||||
$notification = $this->get_compatibility_notification();
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
|
||||
if ( defined( 'GAWP_VERSION' ) && '5.4.3' === GAWP_VERSION ) {
|
||||
$notification_center->add_notification( $notification );
|
||||
}
|
||||
else {
|
||||
$notification_center->remove_notification( $notification );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build compatibility problem notification
|
||||
*
|
||||
* @return Yoast_Notification
|
||||
*/
|
||||
private function get_compatibility_notification() {
|
||||
$info_message = sprintf(
|
||||
/* translators: %1$s expands to Yoast SEO, %2$s expands to 5.4.3, %3$s expands to Google Analytics by Yoast */
|
||||
__( '%1$s detected you are using version %2$s of %3$s, please update to the latest version to prevent compatibility issues.', 'wordpress-seo' ),
|
||||
'Yoast SEO',
|
||||
'5.4.3',
|
||||
'Google Analytics by Yoast'
|
||||
);
|
||||
|
||||
return new Yoast_Notification(
|
||||
$info_message,
|
||||
array(
|
||||
'id' => 'gawp-compatibility-notice',
|
||||
'type' => Yoast_Notification::ERROR,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a suggested plugins notification needs to be displayed.
|
||||
* Creates an unsupported PHP version notification in the notification center.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function yoast_plugin_suggestions_notification() {
|
||||
$checker = new WPSEO_Plugin_Availability();
|
||||
public function unsupported_php_notice() {
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
$notification_center->remove_notification_by_id( 'wpseo-dismiss-unsupported-php' );
|
||||
}
|
||||
|
||||
// Get all Yoast plugins that have dependencies.
|
||||
$plugins = $checker->get_plugins_with_dependencies();
|
||||
/**
|
||||
* Gets the latest released major WordPress version from the WordPress stable-check api.
|
||||
*
|
||||
* @return float|int The latest released major WordPress version. 0 when the stable-check API doesn't respond.
|
||||
*/
|
||||
private function get_latest_major_wordpress_version() {
|
||||
$core_updates = get_core_updates( [ 'dismissed' => true ] );
|
||||
|
||||
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 ( $core_updates === false ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( $checker->dependencies_are_satisfied( $plugin ) && ! $checker->is_installed( $plugin ) ) {
|
||||
$notification_center->add_notification( $notification );
|
||||
|
||||
continue;
|
||||
$wp_version_latest = get_bloginfo( 'version' );
|
||||
foreach ( $core_updates as $update ) {
|
||||
if ( $update->response === 'upgrade' && version_compare( $update->version, $wp_version_latest, '>' ) ) {
|
||||
$wp_version_latest = $update->version;
|
||||
}
|
||||
|
||||
$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,
|
||||
array(
|
||||
'id' => 'wpseo-suggested-plugin-' . $name,
|
||||
'type' => Yoast_Notification::WARNING,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an alert if outdated versions of Yoast SEO plugins are running.
|
||||
*/
|
||||
public function yoast_plugin_compatibility_notification() {
|
||||
$compatibility_checker = new WPSEO_Plugin_Compatibility( WPSEO_VERSION );
|
||||
$plugins = $compatibility_checker->get_installed_plugins_compatibility();
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
|
||||
foreach ( $plugins as $name => $plugin ) {
|
||||
$type = ( $plugin['active'] ) ? Yoast_Notification::ERROR : Yoast_Notification::WARNING;
|
||||
$notification = $this->get_yoast_seo_compatibility_notification( $name, $plugin, $type );
|
||||
|
||||
if ( $plugin['compatible'] === false ) {
|
||||
$notification_center->add_notification( $notification );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$notification_center->remove_notification( $notification );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Yoast SEO compatibility problem 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 $level The severity level to use for the notification.
|
||||
*
|
||||
* @return Yoast_Notification
|
||||
*/
|
||||
private function get_yoast_seo_compatibility_notification( $name, $plugin, $level = Yoast_Notification::WARNING ) {
|
||||
$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 detected you are using version %2$s of %3$s, please update to the latest version to prevent compatibility issues.', 'wordpress-seo' ),
|
||||
'Yoast SEO',
|
||||
$plugin['version'],
|
||||
$plugin['title']
|
||||
);
|
||||
|
||||
return new Yoast_Notification(
|
||||
$info_message,
|
||||
array(
|
||||
'id' => 'wpseo-outdated-yoast-seo-plugin-' . $name,
|
||||
'type' => $level,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the notice for recalculating the post. the Notice will only be shown if the user hasn't dismissed it before.
|
||||
*/
|
||||
public function recalculate_notice() {
|
||||
// Just a return, because we want to temporary disable this notice (#3998 and #4532).
|
||||
return;
|
||||
|
||||
if ( filter_input( INPUT_GET, 'recalculate' ) === '1' ) {
|
||||
update_option( 'wpseo_dismiss_recalculate', '1' );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $this->is_site_notice_dismissed( 'wpseo_dismiss_recalculate' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Yoast_Notification_Center::get()->add_notification(
|
||||
new Yoast_Notification(
|
||||
sprintf(
|
||||
/* translators: 1: is a link to 'admin_url / admin.php?page=wpseo_tools&recalculate=1' 2: closing link tag */
|
||||
__( 'We\'ve updated our SEO score algorithm. %1$sRecalculate the SEO scores%2$s for all posts and pages.', 'wordpress-seo' ),
|
||||
'<a href="' . admin_url( 'admin.php?page=wpseo_tools&recalculate=1' ) . '">',
|
||||
'</a>'
|
||||
),
|
||||
array(
|
||||
'type' => 'updated yoast-dismissible',
|
||||
'id' => 'wpseo-dismiss-recalculate',
|
||||
'nonce' => wp_create_nonce( 'wpseo-dismiss-recalculate' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user has dismissed the given notice (by $notice_name)
|
||||
*
|
||||
* @param string $notice_name The name of the notice that might be dismissed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_site_notice_dismissed( $notice_name ) {
|
||||
return '1' === get_option( $notice_name, true );
|
||||
// Strip the patch version and convert to a float.
|
||||
return (float) $wp_version_latest;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -427,7 +116,7 @@ class WPSEO_Admin_Init {
|
|||
* @return bool
|
||||
*/
|
||||
private function on_wpseo_admin_page() {
|
||||
return 'admin.php' === $this->pagenow && strpos( filter_input( INPUT_GET, 'page' ), 'wpseo' ) === 0;
|
||||
return $this->pagenow === 'admin.php' && strpos( filter_input( INPUT_GET, 'page' ), 'wpseo' ) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -470,7 +159,7 @@ class WPSEO_Admin_Init {
|
|||
* Loads admin page class for all admin pages starting with `wpseo_`.
|
||||
*/
|
||||
private function load_admin_user_class() {
|
||||
if ( in_array( $this->pagenow, array( 'user-edit.php', 'profile.php' ), true )
|
||||
if ( in_array( $this->pagenow, [ 'user-edit.php', 'profile.php' ], true )
|
||||
&& current_user_can( 'edit_users' )
|
||||
) {
|
||||
new WPSEO_Admin_User_Profile();
|
||||
|
|
@ -488,10 +177,13 @@ class WPSEO_Admin_Init {
|
|||
// For backwards compatabilty, this still needs a global, for now...
|
||||
$GLOBALS['wpseo_admin_pages'] = new WPSEO_Admin_Pages();
|
||||
|
||||
$page = filter_input( INPUT_GET, 'page' );
|
||||
// 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' ) ) ) {
|
||||
if ( WPSEO_Utils::is_yoast_seo_free_page( $page ) ) {
|
||||
$this->register_i18n_promo_class();
|
||||
$this->register_premium_upsell_admin_block();
|
||||
if ( $page !== 'wpseo_titles' ) {
|
||||
$this->register_premium_upsell_admin_block();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -510,7 +202,7 @@ class WPSEO_Admin_Init {
|
|||
* @return void
|
||||
*/
|
||||
private function register_premium_upsell_admin_block() {
|
||||
if ( ! WPSEO_Utils::is_yoast_seo_premium() ) {
|
||||
if ( ! YoastSEO()->helpers->product->is_premium() ) {
|
||||
$upsell_block = new WPSEO_Premium_Upsell_Admin_Block( 'wpseo_admin_promo_footer' );
|
||||
$upsell_block->register_hooks();
|
||||
}
|
||||
|
|
@ -524,11 +216,12 @@ class WPSEO_Admin_Init {
|
|||
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(
|
||||
array(
|
||||
[
|
||||
'textdomain' => 'wordpress-seo',
|
||||
'plugin_name' => 'Yoast SEO',
|
||||
'hook' => 'wpseo_admin_promo_footer',
|
||||
), false
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$message = $i18n_module->get_promo_message();
|
||||
|
|
@ -541,10 +234,10 @@ class WPSEO_Admin_Init {
|
|||
|
||||
$notification = new Yoast_Notification(
|
||||
$message,
|
||||
array(
|
||||
[
|
||||
'type' => Yoast_Notification::WARNING,
|
||||
'id' => 'i18nModuleTranslationAssistance',
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
if ( $message ) {
|
||||
|
|
@ -557,7 +250,7 @@ class WPSEO_Admin_Init {
|
|||
}
|
||||
|
||||
/**
|
||||
* See if we should start our XML Sitemaps Admin class
|
||||
* See if we should start our XML Sitemaps Admin class.
|
||||
*/
|
||||
private function load_xml_sitemaps_admin() {
|
||||
if ( WPSEO_Options::get( 'enable_xml_sitemap', false ) ) {
|
||||
|
|
@ -566,12 +259,12 @@ class WPSEO_Admin_Init {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if the site is set to be publicly visible
|
||||
* Checks whether search engines are discouraged from indexing the site.
|
||||
*
|
||||
* @return bool
|
||||
* @return bool Whether search engines are discouraged from indexing the site.
|
||||
*/
|
||||
private function is_blog_public() {
|
||||
return '1' === (string) get_option( 'blog_public' );
|
||||
private function are_search_engines_discouraged() {
|
||||
return (string) get_option( 'blog_public' ) === '0';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -580,53 +273,45 @@ class WPSEO_Admin_Init {
|
|||
public function show_hook_deprecation_warnings() {
|
||||
global $wp_filter;
|
||||
|
||||
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
|
||||
return false;
|
||||
if ( wp_doing_ajax() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// WordPress hooks that have been deprecated since a Yoast SEO version.
|
||||
$deprecated_filters = array(
|
||||
'wpseo_metadesc_length' => array(
|
||||
'version' => '3.0',
|
||||
'alternative' => 'javascript',
|
||||
),
|
||||
'wpseo_metadesc_length_reason' => array(
|
||||
'version' => '3.0',
|
||||
'alternative' => 'javascript',
|
||||
),
|
||||
'wpseo_body_length_score' => array(
|
||||
'version' => '3.0',
|
||||
'alternative' => 'javascript',
|
||||
),
|
||||
'wpseo_linkdex_results' => array(
|
||||
'version' => '3.0',
|
||||
'alternative' => 'javascript',
|
||||
),
|
||||
'wpseo_snippet' => array(
|
||||
'version' => '3.0',
|
||||
'alternative' => 'javascript',
|
||||
),
|
||||
'wp_seo_get_bc_title' => array(
|
||||
'version' => '5.8',
|
||||
'alternative' => 'wpseo_breadcrumb_single_link_info',
|
||||
),
|
||||
'wpseo_metakey' => array(
|
||||
'version' => '6.3',
|
||||
$deprecated_filters = [
|
||||
'wpseo_genesis_force_adjacent_rel_home' => [
|
||||
'version' => '9.4',
|
||||
'alternative' => null,
|
||||
),
|
||||
'wpseo_metakeywords' => array(
|
||||
'version' => '6.3',
|
||||
],
|
||||
'wpseo_opengraph' => [
|
||||
'version' => '14.0',
|
||||
'alternative' => null,
|
||||
),
|
||||
'wpseo_stopwords' => array(
|
||||
'version' => '7.0',
|
||||
],
|
||||
'wpseo_twitter' => [
|
||||
'version' => '14.0',
|
||||
'alternative' => null,
|
||||
),
|
||||
'wpseo_redirect_orphan_attachment' => array(
|
||||
'version' => '7.0',
|
||||
],
|
||||
'wpseo_twitter_taxonomy_image' => [
|
||||
'version' => '14.0',
|
||||
'alternative' => null,
|
||||
),
|
||||
);
|
||||
],
|
||||
'wpseo_twitter_metatag_key' => [
|
||||
'version' => '14.0',
|
||||
'alternative' => null,
|
||||
],
|
||||
'wp_seo_get_bc_ancestors' => [
|
||||
'version' => '14.0',
|
||||
'alternative' => 'wpseo_breadcrumb_links',
|
||||
],
|
||||
'validate_facebook_app_id_api_response_code' => [
|
||||
'version' => '15.5',
|
||||
'alternative' => null,
|
||||
],
|
||||
'validate_facebook_app_id_api_response_body' => [
|
||||
'version' => '15.5',
|
||||
'alternative' => null,
|
||||
],
|
||||
];
|
||||
|
||||
// Determine which filters have been registered.
|
||||
$deprecated_notices = array_intersect(
|
||||
|
|
@ -637,31 +322,177 @@ class WPSEO_Admin_Init {
|
|||
// Show notice for each deprecated filter or action that has been registered.
|
||||
foreach ( $deprecated_notices as $deprecated_filter ) {
|
||||
$deprecation_info = $deprecated_filters[ $deprecated_filter ];
|
||||
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- Only uses the hardcoded values from above.
|
||||
_deprecated_hook(
|
||||
$deprecated_filter,
|
||||
'WPSEO ' . $deprecation_info['version'],
|
||||
$deprecation_info['alternative']
|
||||
);
|
||||
// phpcs:enable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is a dismiss notice action.
|
||||
*
|
||||
* @param string $notice_name The name of the notice to dismiss.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function dismiss_notice( $notice_name ) {
|
||||
return filter_input( INPUT_GET, $notice_name ) === '1' && wp_verify_nonce( filter_input( INPUT_GET, 'nonce' ), $notice_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the permalink uses %postname%
|
||||
* Check if the permalink uses %postname%.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function has_postname_in_permalink() {
|
||||
return ( false !== strpos( get_option( 'permalink_structure' ), '%postname%' ) );
|
||||
return ( strpos( get_option( 'permalink_structure' ), '%postname%' ) !== false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a notice on the permalink settings page.
|
||||
*/
|
||||
public function permalink_settings_notice() {
|
||||
global $pagenow;
|
||||
|
||||
if ( $pagenow === 'options-permalink.php' ) {
|
||||
printf(
|
||||
'<div class="notice notice-warning"><p><strong>%1$s</strong><br>%2$s<br><a href="%3$s" target="_blank">%4$s</a></p></div>',
|
||||
esc_html__( 'WARNING:', 'wordpress-seo' ),
|
||||
sprintf(
|
||||
/* translators: %1$s and %2$s expand to <em> items to emphasize the word in the middle. */
|
||||
esc_html__( 'Changing your permalinks settings can seriously impact your search engine visibility. It should almost %1$s never %2$s be done on a live website.', 'wordpress-seo' ),
|
||||
'<em>',
|
||||
'</em>'
|
||||
),
|
||||
esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/why-permalinks/' ) ),
|
||||
// The link's content.
|
||||
esc_html__( 'Learn about why permalinks are important for SEO.', 'wordpress-seo' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param \WP_Post $post The current post object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_publish_box_section( $post ) {
|
||||
if ( in_array( $this->pagenow, [ 'post.php', 'post-new.php' ], true ) ) {
|
||||
?>
|
||||
<div id="yoast-seo-publishbox-section"></div>
|
||||
<?php
|
||||
/**
|
||||
* Fires after the post time/date setting in the Publish meta box.
|
||||
*
|
||||
* @api \WP_Post The current post object.
|
||||
*/
|
||||
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' );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,205 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determines the recommended replacement variables based on the context.
|
||||
*/
|
||||
class WPSEO_Admin_Recommended_Replace_Vars {
|
||||
|
||||
/**
|
||||
* The recommended replacement variables.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $recommended_replace_vars = [
|
||||
// Posts types.
|
||||
'page' => [ 'sitename', 'title', 'sep', 'primary_category' ],
|
||||
'post' => [ 'sitename', 'title', 'sep', 'primary_category' ],
|
||||
// Homepage.
|
||||
'homepage' => [ 'sitename', 'sitedesc', 'sep' ],
|
||||
// Custom post type.
|
||||
'custom_post_type' => [ 'sitename', 'title', 'sep' ],
|
||||
|
||||
// Taxonomies.
|
||||
'category' => [ 'sitename', 'term_title', 'sep', 'term_hierarchy' ],
|
||||
'post_tag' => [ 'sitename', 'term_title', 'sep' ],
|
||||
'post_format' => [ 'sitename', 'term_title', 'sep', 'page' ],
|
||||
|
||||
// Custom taxonomy.
|
||||
'term-in-custom-taxomomy' => [ 'sitename', 'term_title', 'sep', 'term_hierarchy' ],
|
||||
|
||||
// Settings - archive pages.
|
||||
'author_archive' => [ 'sitename', 'title', 'sep', 'page' ],
|
||||
'date_archive' => [ 'sitename', 'sep', 'date', 'page' ],
|
||||
'custom-post-type_archive' => [ 'sitename', 'title', 'sep', 'page' ],
|
||||
|
||||
// Settings - special pages.
|
||||
'search' => [ 'sitename', 'searchphrase', 'sep', 'page' ],
|
||||
'404' => [ 'sitename', 'sep' ],
|
||||
];
|
||||
|
||||
/**
|
||||
* Determines the page type of the current term.
|
||||
*
|
||||
* @param string $taxonomy The taxonomy name.
|
||||
*
|
||||
* @return string The page type.
|
||||
*/
|
||||
public function determine_for_term( $taxonomy ) {
|
||||
$recommended_replace_vars = $this->get_recommended_replacevars();
|
||||
if ( array_key_exists( $taxonomy, $recommended_replace_vars ) ) {
|
||||
return $taxonomy;
|
||||
}
|
||||
|
||||
return 'term-in-custom-taxomomy';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the page type of the current post.
|
||||
*
|
||||
* @param WP_Post $post A WordPress post instance.
|
||||
*
|
||||
* @return string The page type.
|
||||
*/
|
||||
public function determine_for_post( $post ) {
|
||||
if ( $post instanceof WP_Post === false ) {
|
||||
return 'post';
|
||||
}
|
||||
|
||||
if ( $post->post_type === 'page' && $this->is_homepage( $post ) ) {
|
||||
return 'homepage';
|
||||
}
|
||||
|
||||
$recommended_replace_vars = $this->get_recommended_replacevars();
|
||||
if ( array_key_exists( $post->post_type, $recommended_replace_vars ) ) {
|
||||
return $post->post_type;
|
||||
}
|
||||
|
||||
return 'custom_post_type';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the page type for a post type.
|
||||
*
|
||||
* @param string $post_type The name of the post_type.
|
||||
* @param string $fallback The page type to fall back to.
|
||||
*
|
||||
* @return string The page type.
|
||||
*/
|
||||
public function determine_for_post_type( $post_type, $fallback = 'custom_post_type' ) {
|
||||
$page_type = $post_type;
|
||||
$recommended_replace_vars = $this->get_recommended_replacevars();
|
||||
$has_recommended_replacevars = $this->has_recommended_replace_vars( $recommended_replace_vars, $page_type );
|
||||
|
||||
if ( ! $has_recommended_replacevars ) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
return $page_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the page type for an archive page.
|
||||
*
|
||||
* @param string $name The name of the archive.
|
||||
* @param string $fallback The page type to fall back to.
|
||||
*
|
||||
* @return string The page type.
|
||||
*/
|
||||
public function determine_for_archive( $name, $fallback = 'custom-post-type_archive' ) {
|
||||
$page_type = $name . '_archive';
|
||||
$recommended_replace_vars = $this->get_recommended_replacevars();
|
||||
$has_recommended_replacevars = $this->has_recommended_replace_vars( $recommended_replace_vars, $page_type );
|
||||
|
||||
if ( ! $has_recommended_replacevars ) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
return $page_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the recommended replacement variables for the given page type.
|
||||
*
|
||||
* @param string $page_type The page type.
|
||||
*
|
||||
* @return array The recommended replacement variables.
|
||||
*/
|
||||
public function get_recommended_replacevars_for( $page_type ) {
|
||||
$recommended_replace_vars = $this->get_recommended_replacevars();
|
||||
$has_recommended_replace_vars = $this->has_recommended_replace_vars( $recommended_replace_vars, $page_type );
|
||||
|
||||
if ( ! $has_recommended_replace_vars ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $recommended_replace_vars[ $page_type ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the recommended replacement variables.
|
||||
*
|
||||
* @return array The recommended replacement variables.
|
||||
*/
|
||||
public function get_recommended_replacevars() {
|
||||
/**
|
||||
* Filter: Adds the possibility to add extra recommended replacement variables.
|
||||
*
|
||||
* @api array $additional_replace_vars Empty array to add the replacevars to.
|
||||
*/
|
||||
$recommended_replace_vars = apply_filters( 'wpseo_recommended_replace_vars', $this->recommended_replace_vars );
|
||||
|
||||
if ( ! is_array( $recommended_replace_vars ) ) {
|
||||
return $this->recommended_replace_vars;
|
||||
}
|
||||
|
||||
return $recommended_replace_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given page type has recommended replace vars.
|
||||
*
|
||||
* @param array $recommended_replace_vars The recommended replace vars
|
||||
* to check in.
|
||||
* @param string $page_type The page type to check.
|
||||
*
|
||||
* @return bool True if there are associated recommended replace vars.
|
||||
*/
|
||||
private function has_recommended_replace_vars( $recommended_replace_vars, $page_type ) {
|
||||
if ( ! isset( $recommended_replace_vars[ $page_type ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! is_array( $recommended_replace_vars[ $page_type ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not a post is the homepage.
|
||||
*
|
||||
* @param WP_Post $post The WordPress global post object.
|
||||
*
|
||||
* @return bool True if the given post is the homepage.
|
||||
*/
|
||||
private function is_homepage( $post ) {
|
||||
if ( $post instanceof WP_Post === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The page on front returns a string with normal WordPress interaction, while the post ID is an int.
|
||||
* This way we make sure we always compare strings.
|
||||
*/
|
||||
$post_id = (int) $post->ID;
|
||||
$page_on_front = (int) get_option( 'page_on_front' );
|
||||
|
||||
return get_option( 'show_on_front' ) === 'page' && $page_on_front === $post_id;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,16 +10,17 @@
|
|||
* Customizes user profile.
|
||||
*/
|
||||
class WPSEO_Admin_User_Profile {
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'show_user_profile', array( $this, 'user_profile' ) );
|
||||
add_action( 'edit_user_profile', array( $this, 'user_profile' ) );
|
||||
add_action( 'personal_options_update', array( $this, 'process_user_option_update' ) );
|
||||
add_action( 'edit_user_profile_update', array( $this, 'process_user_option_update' ) );
|
||||
add_action( 'show_user_profile', [ $this, 'user_profile' ] );
|
||||
add_action( 'edit_user_profile', [ $this, 'user_profile' ] );
|
||||
add_action( 'personal_options_update', [ $this, 'process_user_option_update' ] );
|
||||
add_action( 'edit_user_profile_update', [ $this, 'process_user_option_update' ] );
|
||||
|
||||
add_action( 'update_user_meta', array( $this, 'clear_author_sitemap_cache' ), 10, 3 );
|
||||
add_action( 'update_user_meta', [ $this, 'clear_author_sitemap_cache' ], 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -27,13 +28,13 @@ class WPSEO_Admin_User_Profile {
|
|||
*
|
||||
* @since 3.1
|
||||
*
|
||||
* @param int $meta_id The ID of the meta option changed.
|
||||
* @param int $meta_id The ID of the meta option changed.
|
||||
* @param int $object_id The ID of the user.
|
||||
* @param string $meta_key The key of the meta field changed.
|
||||
* @param string $meta_key The key of the meta field changed.
|
||||
*/
|
||||
public function clear_author_sitemap_cache( $meta_id, $object_id, $meta_key ) {
|
||||
if ( '_yoast_wpseo_profile_updated' === $meta_key ) {
|
||||
WPSEO_Sitemaps_Cache::clear( array( 'author' ) );
|
||||
if ( $meta_key === '_yoast_wpseo_profile_updated' ) {
|
||||
WPSEO_Sitemaps_Cache::clear( [ 'author' ] );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class WPSEO_Admin_Utils {
|
|||
* @return string The link to the plugin install. Returns the title if the plugin is deemed a Premium product.
|
||||
*/
|
||||
public static function get_install_link( $plugin ) {
|
||||
$install_url = WPSEO_Admin_Utils::get_install_url( $plugin['slug'] );
|
||||
$install_url = self::get_install_url( $plugin['slug'] );
|
||||
|
||||
if ( $install_url === '' || ( isset( $plugin['premium'] ) && $plugin['premium'] === true ) ) {
|
||||
return $plugin['title'];
|
||||
|
|
@ -65,6 +65,17 @@ class WPSEO_Admin_Utils {
|
|||
$install_url,
|
||||
$plugin['title']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a visually hidden accessible message for links that open in a new browser tab.
|
||||
*
|
||||
* @return string The visually hidden accessible message.
|
||||
*/
|
||||
public static function get_new_tab_message() {
|
||||
return sprintf(
|
||||
'<span class="screen-reader-text">%s</span>',
|
||||
esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,13 @@
|
|||
*/
|
||||
class WPSEO_Admin {
|
||||
|
||||
/** The page identifier used in WordPress to register the admin page !DO NOT CHANGE THIS! */
|
||||
/**
|
||||
* The page identifier used in WordPress to register the admin page.
|
||||
*
|
||||
* !DO NOT CHANGE THIS!
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PAGE_IDENTIFIER = 'wpseo_dashboard';
|
||||
|
||||
/**
|
||||
|
|
@ -24,7 +30,7 @@ class WPSEO_Admin {
|
|||
* Class constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$integrations = array();
|
||||
$integrations = [];
|
||||
|
||||
global $pagenow;
|
||||
|
||||
|
|
@ -36,46 +42,37 @@ class WPSEO_Admin {
|
|||
}
|
||||
|
||||
if ( WPSEO_Options::get( 'stripcategorybase' ) === true ) {
|
||||
add_action( 'created_category', array( $this, 'schedule_rewrite_flush' ) );
|
||||
add_action( 'edited_category', array( $this, 'schedule_rewrite_flush' ) );
|
||||
add_action( 'delete_category', array( $this, 'schedule_rewrite_flush' ) );
|
||||
add_action( 'created_category', [ $this, 'schedule_rewrite_flush' ] );
|
||||
add_action( 'edited_category', [ $this, 'schedule_rewrite_flush' ] );
|
||||
add_action( 'delete_category', [ $this, 'schedule_rewrite_flush' ] );
|
||||
}
|
||||
|
||||
$this->admin_features = array(
|
||||
// Google Search Console.
|
||||
'google_search_console' => new WPSEO_GSC(),
|
||||
'dashboard_widget' => new Yoast_Dashboard_Widget(),
|
||||
);
|
||||
|
||||
if ( WPSEO_Metabox::is_post_overview( $pagenow ) || WPSEO_Metabox::is_post_edit( $pagenow ) ) {
|
||||
$this->admin_features['primary_category'] = new WPSEO_Primary_Term_Admin();
|
||||
if ( WPSEO_Options::get( 'disable-attachment' ) === true ) {
|
||||
add_filter( 'wpseo_accessible_post_types', [ 'WPSEO_Post_Type', 'filter_attachment_post_type' ] );
|
||||
}
|
||||
|
||||
if ( filter_input( INPUT_GET, 'page' ) === 'wpseo_tools' && filter_input( INPUT_GET, 'tool' ) === null ) {
|
||||
new WPSEO_Recalculate_Scores();
|
||||
}
|
||||
add_filter( 'plugin_action_links_' . WPSEO_BASENAME, [ $this, 'add_action_link' ], 10, 2 );
|
||||
add_filter( 'network_admin_plugin_action_links_' . WPSEO_BASENAME, [ $this, 'add_action_link' ], 10, 2 );
|
||||
|
||||
add_filter( 'plugin_action_links_' . WPSEO_BASENAME, array( $this, 'add_action_link' ), 10, 2 );
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'config_page_scripts' ] );
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_global_style' ] );
|
||||
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'config_page_scripts' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_global_style' ) );
|
||||
add_filter( 'user_contactmethods', [ $this, 'update_contactmethods' ], 10, 1 );
|
||||
|
||||
add_filter( 'user_contactmethods', array( $this, 'update_contactmethods' ), 10, 1 );
|
||||
add_action( 'after_switch_theme', [ $this, 'switch_theme' ] );
|
||||
add_action( 'switch_theme', [ $this, 'switch_theme' ] );
|
||||
|
||||
add_action( 'after_switch_theme', array( $this, 'switch_theme' ) );
|
||||
add_action( 'switch_theme', array( $this, 'switch_theme' ) );
|
||||
add_filter( 'set-screen-option', [ $this, 'save_bulk_edit_options' ], 10, 3 );
|
||||
|
||||
add_filter( 'set-screen-option', array( $this, 'save_bulk_edit_options' ), 10, 3 );
|
||||
add_action( 'admin_init', [ 'WPSEO_Plugin_Conflict', 'hook_check_for_plugin_conflicts' ], 10, 1 );
|
||||
|
||||
add_action( 'admin_init', array( 'WPSEO_Plugin_Conflict', 'hook_check_for_plugin_conflicts' ), 10, 1 );
|
||||
|
||||
add_action( 'admin_init', array( $this, 'map_manage_options_cap' ) );
|
||||
add_action( 'admin_init', [ $this, 'map_manage_options_cap' ] );
|
||||
|
||||
WPSEO_Sitemaps_Cache::register_clear_on_option_update( 'wpseo' );
|
||||
WPSEO_Sitemaps_Cache::register_clear_on_option_update( 'home' );
|
||||
|
||||
if ( WPSEO_Utils::is_yoast_seo_page() ) {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
||||
if ( YoastSEO()->helpers->current_page->is_yoast_seo_page() ) {
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
||||
}
|
||||
|
||||
if ( WPSEO_Utils::is_api_available() ) {
|
||||
|
|
@ -86,27 +83,50 @@ class WPSEO_Admin {
|
|||
|
||||
$this->set_upsell_notice();
|
||||
|
||||
$this->check_php_version();
|
||||
$this->initialize_cornerstone_content();
|
||||
|
||||
$integrations[] = new WPSEO_Yoast_Columns();
|
||||
$integrations[] = new WPSEO_License_Page_Manager();
|
||||
$integrations[] = new WPSEO_Statistic_Integration();
|
||||
$integrations[] = new WPSEO_Slug_Change_Watcher();
|
||||
$integrations[] = new WPSEO_Capability_Manager_Integration( WPSEO_Capability_Manager_Factory::get() );
|
||||
$integrations = array_merge( $integrations, $this->initialize_seo_links() );
|
||||
if ( WPSEO_Utils::is_plugin_network_active() ) {
|
||||
$integrations[] = new Yoast_Network_Admin();
|
||||
}
|
||||
|
||||
$this->admin_features = [
|
||||
'dashboard_widget' => new Yoast_Dashboard_Widget(),
|
||||
];
|
||||
|
||||
if ( WPSEO_Metabox::is_post_overview( $pagenow ) || WPSEO_Metabox::is_post_edit( $pagenow ) ) {
|
||||
$this->admin_features['primary_category'] = new WPSEO_Primary_Term_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_Gutenberg_Compatibility_Notification();
|
||||
$integrations[] = new WPSEO_Expose_Shortlinks();
|
||||
$integrations[] = new WPSEO_MyYoast_Proxy();
|
||||
$integrations[] = new WPSEO_Schema_Person_Upgrade_Notification();
|
||||
$integrations[] = new WPSEO_Tracking( 'https://tracking.yoast.com/stats', ( WEEK_IN_SECONDS * 2 ) );
|
||||
$integrations[] = new WPSEO_Admin_Settings_Changed_Listener();
|
||||
|
||||
$integrations = array_merge(
|
||||
$integrations,
|
||||
$this->get_admin_features(),
|
||||
$this->initialize_cornerstone_content()
|
||||
);
|
||||
|
||||
/** @var WPSEO_WordPress_Integration $integration */
|
||||
foreach ( $integrations as $integration ) {
|
||||
$integration->register_hooks();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a rewrite flush to happen at shutdown.
|
||||
*/
|
||||
public function schedule_rewrite_flush() {
|
||||
// Bail if this is a multisite installation and the site has been switched.
|
||||
if ( is_multisite() && ms_is_switched() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action( 'shutdown', 'flush_rewrite_rules' );
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +143,7 @@ class WPSEO_Admin {
|
|||
* Register assets needed on admin pages.
|
||||
*/
|
||||
public function enqueue_assets() {
|
||||
if ( 'wpseo_licenses' === filter_input( INPUT_GET, 'page' ) ) {
|
||||
if ( filter_input( INPUT_GET, 'page' ) === 'wpseo_licenses' ) {
|
||||
$asset_manager = new WPSEO_Admin_Asset_Manager();
|
||||
$asset_manager->enqueue_style( 'extensions' );
|
||||
}
|
||||
|
|
@ -147,10 +167,11 @@ class WPSEO_Admin {
|
|||
* Maps the manage_options cap on saving an options page to wpseo_manage_options.
|
||||
*/
|
||||
public function map_manage_options_cap() {
|
||||
$option_page = ! empty( $_POST['option_page'] ) ? $_POST['option_page'] : ''; // WPCS: CSRF ok.
|
||||
// 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 ) {
|
||||
add_filter( 'option_page_capability_' . $option_page, array( $this, 'get_manage_options_cap' ) );
|
||||
add_filter( 'option_page_capability_' . $option_page, [ $this, 'get_manage_options_cap' ] );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,11 +181,11 @@ class WPSEO_Admin {
|
|||
*/
|
||||
public function bulk_edit_options() {
|
||||
$option = 'per_page';
|
||||
$args = array(
|
||||
$args = [
|
||||
'label' => __( 'Posts', 'wordpress-seo' ),
|
||||
'default' => 10,
|
||||
'option' => 'wpseo_posts_per_page',
|
||||
);
|
||||
];
|
||||
add_screen_option( $option, $args );
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +199,7 @@ class WPSEO_Admin {
|
|||
* @return int
|
||||
*/
|
||||
public function save_bulk_edit_options( $status, $option, $value ) {
|
||||
if ( 'wpseo_posts_per_page' === $option && ( $value > 0 && $value < 1000 ) ) {
|
||||
if ( $option && ( $value > 0 && $value < 1000 ) === 'wpseo_posts_per_page' ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
|
@ -188,36 +209,55 @@ class WPSEO_Admin {
|
|||
/**
|
||||
* Adds links to Premium Support and FAQ under the plugin in the plugin overview page.
|
||||
*
|
||||
* @staticvar string $this_plugin Holds the directory & filename for the plugin.
|
||||
*
|
||||
* @param array $links Array of links for the plugins, adapted when the current plugin is found.
|
||||
* @param string $file The filename for the current plugin, which the filter loops through.
|
||||
*
|
||||
* @return array $links
|
||||
* @return array
|
||||
*/
|
||||
public function add_action_link( $links, $file ) {
|
||||
if ( WPSEO_BASENAME === $file && WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) {
|
||||
$settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=' . self::PAGE_IDENTIFIER ) ) . '">' . __( 'Settings', 'wordpress-seo' ) . '</a>';
|
||||
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 );
|
||||
}
|
||||
else {
|
||||
$settings_url = admin_url( 'admin.php?page=' . self::PAGE_IDENTIFIER );
|
||||
}
|
||||
$settings_link = '<a href="' . esc_url( $settings_url ) . '">' . __( 'Settings', 'wordpress-seo' ) . '</a>';
|
||||
array_unshift( $links, $settings_link );
|
||||
}
|
||||
|
||||
if ( class_exists( 'WPSEO_Product_Premium' ) ) {
|
||||
$product_premium = new WPSEO_Product_Premium();
|
||||
$extension_manager = new WPSEO_Extension_Manager();
|
||||
// Add link to docs.
|
||||
$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 ( $extension_manager->is_activated( $product_premium->get_slug() ) ) {
|
||||
$addon_manager = new WPSEO_Addon_Manager();
|
||||
if ( YoastSEO()->helpers->product->is_premium() ) {
|
||||
|
||||
// Remove Free 'deactivate' link if Premium is active as well. We don't want users to deactivate Free when Premium is active.
|
||||
unset( $links['deactivate'] );
|
||||
$no_deactivation_explanation = '<span style="color: #32373c">' . sprintf(
|
||||
/* translators: %s expands to Yoast SEO Premium. */
|
||||
__( 'Required by %s', 'wordpress-seo' ),
|
||||
'Yoast SEO Premium'
|
||||
) . '</span>';
|
||||
|
||||
array_unshift( $links, $no_deactivation_explanation );
|
||||
|
||||
if ( $addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG ) ) {
|
||||
return $links;
|
||||
}
|
||||
|
||||
// Add link to where premium can be activated.
|
||||
$activation_link = '<a style="font-weight: bold;" href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/activate-my-yoast' ) ) . '" target="_blank">' . __( 'Activate your subscription', 'wordpress-seo' ) . '</a>';
|
||||
array_unshift( $links, $activation_link );
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
// Add link to premium support landing page.
|
||||
$premium_link = '<a href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yb' ) ) . '">' . __( 'Premium Support', 'wordpress-seo' ) . '</a>';
|
||||
// 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>';
|
||||
array_unshift( $links, $premium_link );
|
||||
|
||||
// Add link to docs.
|
||||
$faq_link = '<a href="' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yc' ) ) . '">' . __( 'FAQ', 'wordpress-seo' ) . '</a>';
|
||||
array_unshift( $links, $faq_link );
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
|
|
@ -226,9 +266,8 @@ class WPSEO_Admin {
|
|||
*/
|
||||
public function config_page_scripts() {
|
||||
$asset_manager = new WPSEO_Admin_Asset_Manager();
|
||||
$asset_manager->enqueue_script( 'admin-global-script' );
|
||||
|
||||
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'admin-global-script', 'wpseoAdminGlobalL10n', $this->localize_admin_global_script() );
|
||||
$asset_manager->enqueue_script( 'admin-global' );
|
||||
$asset_manager->localize_script( 'admin-global', 'wpseoAdminGlobalL10n', $this->localize_admin_global_script() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -240,21 +279,25 @@ class WPSEO_Admin {
|
|||
}
|
||||
|
||||
/**
|
||||
* Filter the $contactmethods array and add Facebook, Google+ and Twitter.
|
||||
* Filter the $contactmethods array and add a set of social profiles.
|
||||
*
|
||||
* These are used with the Facebook author, rel="author" and Twitter cards implementation.
|
||||
*
|
||||
* @param array $contactmethods Currently set contactmethods.
|
||||
*
|
||||
* @return array $contactmethods with added contactmethods.
|
||||
* @return array Contactmethods with added contactmethods.
|
||||
*/
|
||||
public function update_contactmethods( $contactmethods ) {
|
||||
// Add Google+.
|
||||
$contactmethods['googleplus'] = __( 'Google+', 'wordpress-seo' );
|
||||
// Add Twitter.
|
||||
$contactmethods['twitter'] = __( 'Twitter username (without @)', 'wordpress-seo' );
|
||||
// Add Facebook.
|
||||
$contactmethods['facebook'] = __( 'Facebook profile URL', 'wordpress-seo' );
|
||||
$contactmethods['facebook'] = __( 'Facebook profile URL', 'wordpress-seo' );
|
||||
$contactmethods['instagram'] = __( 'Instagram profile URL', 'wordpress-seo' );
|
||||
$contactmethods['linkedin'] = __( 'LinkedIn profile URL', 'wordpress-seo' );
|
||||
$contactmethods['myspace'] = __( 'MySpace profile URL', 'wordpress-seo' );
|
||||
$contactmethods['pinterest'] = __( 'Pinterest profile URL', 'wordpress-seo' );
|
||||
$contactmethods['soundcloud'] = __( 'SoundCloud profile URL', 'wordpress-seo' );
|
||||
$contactmethods['tumblr'] = __( 'Tumblr profile URL', 'wordpress-seo' );
|
||||
$contactmethods['twitter'] = __( 'Twitter username (without @)', 'wordpress-seo' );
|
||||
$contactmethods['youtube'] = __( 'YouTube profile URL', 'wordpress-seo' );
|
||||
$contactmethods['wikipedia'] = __( 'Wikipedia page about you', 'wordpress-seo' ) . '<br/><small>' . __( '(if one exists)', 'wordpress-seo' ) . '</small>';
|
||||
|
||||
return $contactmethods;
|
||||
}
|
||||
|
|
@ -263,8 +306,8 @@ class WPSEO_Admin {
|
|||
* Log the updated timestamp for user profiles when theme is changed.
|
||||
*/
|
||||
public function switch_theme() {
|
||||
$users = get_users( array( 'who' => 'authors' ) );
|
||||
if ( is_array( $users ) && $users !== array() ) {
|
||||
$users = get_users( [ 'who' => 'authors' ] );
|
||||
if ( is_array( $users ) && $users !== [] ) {
|
||||
foreach ( $users as $user ) {
|
||||
update_user_meta( $user->ID, '_yoast_wpseo_profile_updated', time() );
|
||||
}
|
||||
|
|
@ -277,28 +320,18 @@ class WPSEO_Admin {
|
|||
* @return array
|
||||
*/
|
||||
private function localize_admin_global_script() {
|
||||
return array(
|
||||
'dismiss_about_url' => $this->get_dismiss_url( 'wpseo-dismiss-about' ),
|
||||
'dismiss_tagline_url' => $this->get_dismiss_url( 'wpseo-dismiss-tagline-notice' ),
|
||||
'help_video_iframe_title' => __( 'Yoast SEO video tutorial', 'wordpress-seo' ),
|
||||
return [
|
||||
'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' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extending the current page URL with two params to be able to ignore the notice.
|
||||
*
|
||||
* @param string $dismiss_param The param used to dismiss the notification.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_dismiss_url( $dismiss_param ) {
|
||||
$arr_params = array(
|
||||
$dismiss_param => '1',
|
||||
'nonce' => wp_create_nonce( $dismiss_param ),
|
||||
);
|
||||
|
||||
return esc_url( add_query_arg( $arr_params ) );
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -310,219 +343,27 @@ class WPSEO_Admin {
|
|||
$upsell->initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes Whip to show a notice for outdated PHP versions.
|
||||
*/
|
||||
protected function check_php_version() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $this->on_dashboard_page() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
whip_wp_check_versions( array(
|
||||
'php' => '>=5.4',
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether we are on the admin dashboard page.
|
||||
*
|
||||
* @returns bool
|
||||
* @return bool
|
||||
*/
|
||||
protected function on_dashboard_page() {
|
||||
return 'index.php' === $GLOBALS['pagenow'];
|
||||
return $GLOBALS['pagenow'] === 'index.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the cornerstone filter.
|
||||
*
|
||||
* @return WPSEO_WordPress_Integration[] The integrations to initialize.
|
||||
*/
|
||||
protected function initialize_cornerstone_content() {
|
||||
if ( ! WPSEO_Options::get( 'enable_cornerstone_content' ) ) {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
$cornerstone = new WPSEO_Cornerstone();
|
||||
$cornerstone->register_hooks();
|
||||
|
||||
$cornerstone_filter = new WPSEO_Cornerstone_Filter();
|
||||
$cornerstone_filter->register_hooks();
|
||||
return [
|
||||
'cornerstone_filter' => new WPSEO_Cornerstone_Filter(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the seo link watcher.
|
||||
*
|
||||
* @returns WPSEO_WordPress_Integration[]
|
||||
*/
|
||||
protected function initialize_seo_links() {
|
||||
$integrations = array();
|
||||
|
||||
$link_table_compatibility_notifier = new WPSEO_Link_Compatibility_Notifier();
|
||||
$link_table_accessible_notifier = new WPSEO_Link_Table_Accessible_Notifier();
|
||||
|
||||
if ( ! WPSEO_Options::get( 'enable_text_link_counter' ) ) {
|
||||
$link_table_compatibility_notifier->remove_notification();
|
||||
|
||||
return $integrations;
|
||||
}
|
||||
|
||||
$integrations[] = new WPSEO_Link_Cleanup_Transient();
|
||||
|
||||
// Only use the link module for PHP 5.3 and higher and show a notice when version is wrong.
|
||||
if ( version_compare( phpversion(), '5.3', '<' ) ) {
|
||||
$link_table_compatibility_notifier->add_notification();
|
||||
|
||||
return $integrations;
|
||||
}
|
||||
|
||||
$link_table_compatibility_notifier->remove_notification();
|
||||
|
||||
// When the table doesn't exists, just add the notification and return early.
|
||||
if ( ! WPSEO_Link_Table_Accessible::is_accessible() ) {
|
||||
WPSEO_Link_Table_Accessible::cleanup();
|
||||
}
|
||||
|
||||
if ( ! WPSEO_Meta_Table_Accessible::is_accessible() ) {
|
||||
WPSEO_Meta_Table_Accessible::cleanup();
|
||||
}
|
||||
|
||||
if ( ! WPSEO_Link_Table_Accessible::is_accessible() || ! WPSEO_Meta_Table_Accessible::is_accessible() ) {
|
||||
$link_table_accessible_notifier->add_notification();
|
||||
|
||||
return $integrations;
|
||||
}
|
||||
|
||||
$link_table_accessible_notifier->remove_notification();
|
||||
|
||||
$integrations[] = new WPSEO_Link_Columns( new WPSEO_Meta_Storage() );
|
||||
$integrations[] = new WPSEO_Link_Reindex_Dashboard();
|
||||
$integrations[] = new WPSEO_Link_Notifier();
|
||||
|
||||
// Adds a filter to exclude the attachments from the link count.
|
||||
add_filter( 'wpseo_link_count_post_types', array( 'WPSEO_Post_Type', 'filter_attachment_post_type' ) );
|
||||
|
||||
return $integrations;
|
||||
}
|
||||
|
||||
/********************** DEPRECATED METHODS **********************/
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
/**
|
||||
* Register the menu item and its sub menu's.
|
||||
*
|
||||
* @deprecated 5.5
|
||||
*/
|
||||
public function register_settings_page() {
|
||||
_deprecated_function( __METHOD__, 'WPSEO 5.5.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the settings page for the Network settings.
|
||||
*
|
||||
* @deprecated 5.5
|
||||
*/
|
||||
public function register_network_settings_page() {
|
||||
_deprecated_function( __METHOD__, 'WPSEO 5.5.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the form for a WPSEO admin page.
|
||||
*
|
||||
* @deprecated 5.5
|
||||
*/
|
||||
public function load_page() {
|
||||
_deprecated_function( __METHOD__, 'WPSEO 5.5.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the form for the network configuration page.
|
||||
*
|
||||
* @deprecated 5.5
|
||||
*/
|
||||
public function network_config_page() {
|
||||
_deprecated_function( __METHOD__, 'WPSEO 5.5.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters all advanced settings pages from the given pages.
|
||||
*
|
||||
* @deprecated 5.5
|
||||
* @param array $pages The pages to filter.
|
||||
*/
|
||||
public function filter_settings_pages( array $pages ) {
|
||||
_deprecated_function( __METHOD__, 'WPSEO 5.5.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans stopwords out of the slug, if the slug hasn't been set yet.
|
||||
*
|
||||
* @deprecated 7.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function remove_stopwords_from_slug() {
|
||||
_deprecated_function( __METHOD__, 'WPSEO 7.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the stopwords from the slug.
|
||||
*
|
||||
* @deprecated 7.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function filter_stopwords_from_slug() {
|
||||
_deprecated_function( __METHOD__, 'WPSEO 7.0' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds contextual help to the titles & metas page.
|
||||
*
|
||||
* @deprecated 5.6.0
|
||||
*/
|
||||
public function title_metas_help_tab() {
|
||||
_deprecated_function( __METHOD__, '5.6.0' );
|
||||
|
||||
$screen = get_current_screen();
|
||||
|
||||
$screen->set_help_sidebar( '
|
||||
<p><strong>' . __( 'For more information:', 'wordpress-seo' ) . '</strong></p>
|
||||
<p><a target="_blank" href="https://yoast.com/wordpress-seo/#titles">' . __( 'Title optimization', 'wordpress-seo' ) . '</a></p>
|
||||
<p><a target="_blank" href="https://yoast.com/google-page-title/">' . __( 'Why Google won\'t display the right page title', 'wordpress-seo' ) . '</a></p>'
|
||||
);
|
||||
|
||||
$screen->add_help_tab(
|
||||
array(
|
||||
'id' => 'basic-help',
|
||||
'title' => __( 'Template explanation', 'wordpress-seo' ),
|
||||
'content' => "\n\t\t<h2>" . __( 'Template explanation', 'wordpress-seo' ) . "</h2>\n\t\t" . '<p>' .
|
||||
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'
|
||||
) .
|
||||
'</p><p>' . __( 'Note that not all variables can be used in every template.', 'wordpress-seo' ) . '</p>',
|
||||
)
|
||||
);
|
||||
|
||||
$screen->add_help_tab(
|
||||
array(
|
||||
'id' => 'title-vars',
|
||||
'title' => __( 'Basic Variables', 'wordpress-seo' ),
|
||||
'content' => "\n\t\t<h2>" . __( 'Basic Variables', 'wordpress-seo' ) . "</h2>\n\t\t" . WPSEO_Replace_Vars::get_basic_help_texts(),
|
||||
)
|
||||
);
|
||||
|
||||
$screen->add_help_tab(
|
||||
array(
|
||||
'id' => 'title-vars-advanced',
|
||||
'title' => __( 'Advanced Variables', 'wordpress-seo' ),
|
||||
'content' => "\n\t\t<h2>" . __( 'Advanced Variables', 'wordpress-seo' ) . "</h2>\n\t\t" . WPSEO_Replace_Vars::get_advanced_help_texts(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,62 +10,148 @@
|
|||
*/
|
||||
class WPSEO_Admin_Asset {
|
||||
|
||||
/**
|
||||
* Constant used to identify file type as a JS file.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TYPE_JS = 'js';
|
||||
|
||||
/**
|
||||
* Constant used to identify file type as a CSS file.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TYPE_CSS = 'css';
|
||||
|
||||
/**
|
||||
* The name option identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const NAME = 'name';
|
||||
|
||||
/**
|
||||
* The source option identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SRC = 'src';
|
||||
|
||||
/**
|
||||
* The dependencies option identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const DEPS = 'deps';
|
||||
|
||||
/**
|
||||
* The version option identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = 'version';
|
||||
|
||||
// Style specific.
|
||||
/* Style specific. */
|
||||
|
||||
/**
|
||||
* The media option identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const MEDIA = 'media';
|
||||
|
||||
/**
|
||||
* The rtl option identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const RTL = 'rtl';
|
||||
|
||||
// Script specific.
|
||||
/* Script specific. */
|
||||
|
||||
/**
|
||||
* The "in footer" option identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const IN_FOOTER = 'in_footer';
|
||||
|
||||
/**
|
||||
* Asset identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Path to the asset.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $src;
|
||||
|
||||
/**
|
||||
* Asset dependencies.
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
protected $deps;
|
||||
|
||||
/**
|
||||
* Asset version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $version;
|
||||
|
||||
/**
|
||||
* For CSS Assets. The type of media for which this stylesheet has been defined.
|
||||
*
|
||||
* See https://www.w3.org/TR/CSS2/media.html#media-types.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $media;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* For JS Assets. Whether or not the script should be loaded in the footer.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $in_footer;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* For CSS Assets. Whether this stylesheet is a right-to-left stylesheet.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $rtl;
|
||||
|
||||
/**
|
||||
* File suffix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $suffix;
|
||||
|
||||
/**
|
||||
* Default asset arguments.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $defaults = [
|
||||
'deps' => [],
|
||||
'in_footer' => true,
|
||||
'rtl' => true,
|
||||
'media' => 'all',
|
||||
'version' => '',
|
||||
'suffix' => '',
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructs an instance of the WPSEO_Admin_Asset class.
|
||||
*
|
||||
* @param array $args The arguments for this asset.
|
||||
*
|
||||
* @throws InvalidArgumentException Throws when no name or src has been provided.
|
||||
|
|
@ -79,14 +165,7 @@ class WPSEO_Admin_Asset {
|
|||
throw new InvalidArgumentException( 'src is a required argument' );
|
||||
}
|
||||
|
||||
$args = array_merge( array(
|
||||
'deps' => array(),
|
||||
'version' => WPSEO_VERSION,
|
||||
'in_footer' => true,
|
||||
'rtl' => true,
|
||||
'media' => 'all',
|
||||
'suffix' => WPSEO_CSSJS_SUFFIX,
|
||||
), $args );
|
||||
$args = array_merge( $this->defaults, $args );
|
||||
|
||||
$this->name = $args['name'];
|
||||
$this->src = $args['src'];
|
||||
|
|
@ -99,6 +178,8 @@ class WPSEO_Admin_Asset {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the asset identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
|
|
@ -106,6 +187,8 @@ class WPSEO_Admin_Asset {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the asset.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_src() {
|
||||
|
|
@ -113,6 +196,8 @@ class WPSEO_Admin_Asset {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the asset dependencies.
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public function get_deps() {
|
||||
|
|
@ -120,13 +205,21 @@ class WPSEO_Admin_Asset {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* Returns the asset version.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_version() {
|
||||
return $this->version;
|
||||
if ( ! empty( $this->version ) ) {
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the media type for CSS assets.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_media() {
|
||||
|
|
@ -134,39 +227,29 @@ class WPSEO_Admin_Asset {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
* Returns whether a script asset should be loaded in the footer of the page.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_in_footer() {
|
||||
return $this->in_footer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
* Returns whether this CSS has a RTL counterpart.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has_rtl() {
|
||||
return $this->rtl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file suffix.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_suffix() {
|
||||
return $this->suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full URL for this asset based on the path to the plugin file.
|
||||
*
|
||||
* @param string $type Type of asset.
|
||||
* @param string $plugin_file Absolute path to the plugin file.
|
||||
*
|
||||
* @return string The full URL to the asset.
|
||||
*/
|
||||
public function get_url( $type, $plugin_file ) {
|
||||
_deprecated_function( __CLASS__ . '::get_url', '6.2', 'WPSEO_Admin_Asset_SEO_Location::get_url' );
|
||||
|
||||
$asset_location = new WPSEO_Admin_Asset_SEO_Location( $plugin_file );
|
||||
|
||||
return $asset_location->get_url( $this, $type );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,15 @@ class WPSEO_Bulk_Description_List_Table extends WPSEO_Bulk_List_Table {
|
|||
protected $page_type = 'description';
|
||||
|
||||
/**
|
||||
* Settings with are used in __construct
|
||||
* Settings with are used in __construct.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $settings = array(
|
||||
protected $settings = [
|
||||
'singular' => 'wpseo_bulk_description',
|
||||
'plural' => 'wpseo_bulk_descriptions',
|
||||
'ajax' => true,
|
||||
);
|
||||
];
|
||||
|
||||
/**
|
||||
* The field in the database where meta field is saved.
|
||||
|
|
@ -37,21 +37,21 @@ class WPSEO_Bulk_Description_List_Table extends WPSEO_Bulk_List_Table {
|
|||
protected $target_db_field = 'metadesc';
|
||||
|
||||
/**
|
||||
* The columns shown on the table
|
||||
* The columns shown on the table.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_columns() {
|
||||
$columns = array(
|
||||
$columns = [
|
||||
'col_existing_yoast_seo_metadesc' => __( 'Existing Yoast Meta Description', 'wordpress-seo' ),
|
||||
'col_new_yoast_seo_metadesc' => __( 'New Yoast Meta Description', 'wordpress-seo' ),
|
||||
);
|
||||
];
|
||||
|
||||
return $this->merge_columns( $columns );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the metadescription
|
||||
* Parse the metadescription.
|
||||
*
|
||||
* @param string $column_name Column name.
|
||||
* @param object $record Data object.
|
||||
|
|
@ -70,8 +70,11 @@ class WPSEO_Bulk_Description_List_Table extends WPSEO_Bulk_List_Table {
|
|||
|
||||
case 'col_existing_yoast_seo_metadesc':
|
||||
// @todo Inconsistent return/echo behavior R.
|
||||
// I traced the escaping of the attributes to WPSEO_Bulk_List_Table::column_attributes. Alexander.
|
||||
// The output of WPSEO_Bulk_List_Table::parse_meta_data_field is properly escaped.
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo $this->parse_meta_data_field( $record->ID, $attributes );
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* End of class */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
class WPSEO_Bulk_List_Table extends WP_List_Table {
|
||||
|
||||
/**
|
||||
* The nonce that was passed with the request
|
||||
* The nonce that was passed with the request.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
|
@ -37,38 +37,38 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $meta_data = array();
|
||||
protected $meta_data = [];
|
||||
|
||||
/**
|
||||
* The current requested page_url
|
||||
* The current requested page_url.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $request_url;
|
||||
private $request_url = '';
|
||||
|
||||
/**
|
||||
* The current page (depending on $_GET['paged']) if current tab is for current page_type, else it will be 1
|
||||
* The current page (depending on $_GET['paged']) if current tab is for current page_type, else it will be 1.
|
||||
*
|
||||
* @var integer
|
||||
* @var int
|
||||
*/
|
||||
private $current_page;
|
||||
|
||||
/**
|
||||
* The current post filter, if is used (depending on $_GET['post_type_filter'])
|
||||
* The current post filter, if is used (depending on $_GET['post_type_filter']).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $current_filter;
|
||||
|
||||
/**
|
||||
* The current post status, if is used (depending on $_GET['post_status'])
|
||||
* The current post status, if is used (depending on $_GET['post_status']).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $current_status;
|
||||
|
||||
/**
|
||||
* The current sorting, if used (depending on $_GET['order'] and $_GET['orderby'])
|
||||
* The current sorting, if used (depending on $_GET['order'] and $_GET['orderby']).
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
|
@ -83,7 +83,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
|
||||
/**
|
||||
* Based on the page_type ($this->page_type) there will be constructed an url part, for subpages and
|
||||
* navigation
|
||||
* navigation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
|
@ -97,72 +97,52 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
protected $settings;
|
||||
|
||||
/**
|
||||
* Holds the pagination config.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pagination = array();
|
||||
protected $pagination = [];
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* Holds the sanitized data from the user input.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public function __construct() {
|
||||
protected $input_fields = [];
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @param array $args The arguments.
|
||||
*/
|
||||
public function __construct( $args = [] ) {
|
||||
parent::__construct( $this->settings );
|
||||
|
||||
$this->request_url = $_SERVER['REQUEST_URI'];
|
||||
$this->current_page = ( ! empty( $_GET['paged'] ) ) ? $_GET['paged'] : 1;
|
||||
$this->current_filter = ( ! empty( $_GET['post_type_filter'] ) ) ? $_GET['post_type_filter'] : 1;
|
||||
$this->current_status = ( ! empty( $_GET['post_status'] ) ) ? $_GET['post_status'] : 1;
|
||||
$this->current_order = array(
|
||||
'order' => ( ! empty( $_GET['order'] ) ) ? $_GET['order'] : 'asc',
|
||||
'orderby' => ( ! empty( $_GET['orderby'] ) ) ? $_GET['orderby'] : 'post_title',
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
[
|
||||
'nonce' => '',
|
||||
'input_fields' => [],
|
||||
]
|
||||
);
|
||||
|
||||
$this->verify_nonce();
|
||||
$this->input_fields = $args['input_fields'];
|
||||
if ( isset( $_SERVER['REQUEST_URI'] ) ) {
|
||||
$this->request_url = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
|
||||
}
|
||||
|
||||
$this->nonce = wp_create_nonce( 'bulk-editor-table' );
|
||||
$this->current_page = ( ! empty( $this->input_fields['paged'] ) ) ? $this->input_fields['paged'] : 1;
|
||||
$this->current_filter = ( ! empty( $this->input_fields['post_type_filter'] ) ) ? $this->input_fields['post_type_filter'] : 1;
|
||||
$this->current_status = ( ! empty( $this->input_fields['post_status'] ) ) ? $this->input_fields['post_status'] : 1;
|
||||
$this->current_order = [
|
||||
'order' => ( ! empty( $this->input_fields['order'] ) ) ? $this->input_fields['order'] : 'asc',
|
||||
'orderby' => ( ! empty( $this->input_fields['orderby'] ) ) ? $this->input_fields['orderby'] : 'post_title',
|
||||
];
|
||||
|
||||
$this->nonce = $args['nonce'];
|
||||
$this->page_url = "&nonce={$this->nonce}&type={$this->page_type}#top#{$this->page_type}";
|
||||
|
||||
$this->populate_editable_post_types();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies nonce if additional parameters have been sent.
|
||||
*
|
||||
* Shows an error notification if the nonce check fails.
|
||||
*/
|
||||
private function verify_nonce() {
|
||||
if ( $this->should_verify_nonce() && ! wp_verify_nonce( filter_input( INPUT_GET, 'nonce' ), 'bulk-editor-table' ) ) {
|
||||
Yoast_Notification_Center::get()->add_notification(
|
||||
new Yoast_Notification(
|
||||
__( 'You are not allowed to access this page.', 'wordpress-seo' ),
|
||||
array( 'type' => Yoast_Notification::ERROR )
|
||||
)
|
||||
);
|
||||
Yoast_Notification_Center::get()->display_notifications();
|
||||
die;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if additional parameters have been sent to determine if nonce should be checked or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function should_verify_nonce() {
|
||||
$possible_params = array(
|
||||
'type',
|
||||
'paged',
|
||||
'post_type_filter',
|
||||
'post_status',
|
||||
'order',
|
||||
'orderby',
|
||||
);
|
||||
|
||||
foreach ( $possible_params as $param_name ) {
|
||||
if ( filter_input( INPUT_GET, $param_name ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -181,17 +161,17 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
*/
|
||||
protected function populate_editable_post_types() {
|
||||
$post_types = get_post_types(
|
||||
array(
|
||||
[
|
||||
'public' => true,
|
||||
'exclude_from_search' => false,
|
||||
),
|
||||
],
|
||||
'object'
|
||||
);
|
||||
|
||||
$this->all_posts = array();
|
||||
$this->own_posts = array();
|
||||
$this->all_posts = [];
|
||||
$this->own_posts = [];
|
||||
|
||||
if ( is_array( $post_types ) && $post_types !== array() ) {
|
||||
if ( is_array( $post_types ) && $post_types !== [] ) {
|
||||
foreach ( $post_types as $post_type ) {
|
||||
if ( ! current_user_can( $post_type->cap->edit_posts ) ) {
|
||||
continue;
|
||||
|
|
@ -207,9 +187,8 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Will shown the navigation for the table like pagenavigation and pagefilter;
|
||||
* Will show the navigation for the table like pagenavigation and pagefilter.
|
||||
*
|
||||
* @param string $which Table nav location (such as top).
|
||||
*/
|
||||
|
|
@ -218,7 +197,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
?>
|
||||
<div class="tablenav <?php echo esc_attr( $which ); ?>">
|
||||
|
||||
<?php if ( 'top' === $which ) { ?>
|
||||
<?php if ( $which === 'top' ) { ?>
|
||||
<form id="posts-filter" action="" method="get">
|
||||
<input type="hidden" name="nonce" value="<?php echo esc_attr( $this->nonce ); ?>"/>
|
||||
<input type="hidden" name="page" value="wpseo_tools"/>
|
||||
|
|
@ -241,12 +220,12 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
?>
|
||||
|
||||
<br class="clear"/>
|
||||
<?php if ( 'top' === $which ) { ?>
|
||||
<?php if ( $which === 'top' ) { ?>
|
||||
</form>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -255,7 +234,8 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
* This function takes into account the post types in which the current user can
|
||||
* edit all posts, and the ones the current user can only edit his/her own.
|
||||
*
|
||||
* @return string $subquery The subquery, which should always be used in $wpdb->prepare(), passing the current user_id in as the first parameter.
|
||||
* @return string The subquery, which should always be used in $wpdb->prepare(),
|
||||
* passing the current user_id in as the first parameter.
|
||||
*/
|
||||
public function get_base_subquery() {
|
||||
global $wpdb;
|
||||
|
|
@ -278,41 +258,41 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
return $subquery;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* Gets the views.
|
||||
*
|
||||
* @return array The views.
|
||||
*/
|
||||
public function get_views() {
|
||||
global $wpdb;
|
||||
|
||||
$status_links = array();
|
||||
|
||||
$states = get_post_stati( array( 'show_in_admin_all_list' => true ) );
|
||||
$states = esc_sql( $states );
|
||||
$all_states = "'" . implode( "', '", $states ) . "'";
|
||||
$status_links = [];
|
||||
|
||||
$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' );
|
||||
$class = empty( $post_status ) ? ' class="current"' : '';
|
||||
$localized_text = sprintf(
|
||||
$post_status = filter_input( INPUT_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. */
|
||||
_nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_posts, 'posts', 'wordpress-seo' ),
|
||||
number_format_i18n( $total_posts )
|
||||
);
|
||||
|
||||
$status_links['all'] = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor' . $this->page_url ) ) . '"' . $class . '>' . $localized_text . '</a>';
|
||||
$status_links['all'] = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor' . $this->page_url ) ) . '"' . $current_link_attributes . '>' . $localized_text . '</a>';
|
||||
|
||||
$post_stati = get_post_stati( array( 'show_in_admin_all_list' => true ), 'objects' );
|
||||
if ( is_array( $post_stati ) && $post_stati !== array() ) {
|
||||
$post_stati = get_post_stati( [ 'show_in_admin_all_list' => true ], 'objects' );
|
||||
if ( is_array( $post_stati ) && $post_stati !== [] ) {
|
||||
foreach ( $post_stati as $status ) {
|
||||
|
||||
$status_name = esc_sql( $status->name );
|
||||
|
|
@ -331,26 +311,25 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
continue;
|
||||
}
|
||||
|
||||
$class = '';
|
||||
$current_link_attributes = '';
|
||||
if ( $status_name === $post_status ) {
|
||||
$class = ' class="current"';
|
||||
$current_link_attributes = ' class="current" aria-current="page"';
|
||||
}
|
||||
|
||||
$status_links[ $status_name ] = '<a href="' . esc_url( add_query_arg( array( 'post_status' => $status_name ), admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor' . $this->page_url ) ) ) . '"' . $class . '>' . sprintf( translate_nooped_plural( $status->label_count, $total ), number_format_i18n( $total ) ) . '</a>';
|
||||
$status_links[ $status_name ] = '<a href="' . esc_url( add_query_arg( [ 'post_status' => $status_name ], admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor' . $this->page_url ) ) ) . '"' . $current_link_attributes . '>' . sprintf( translate_nooped_plural( $status->label_count, $total ), number_format_i18n( $total ) ) . '</a>';
|
||||
}
|
||||
}
|
||||
unset( $post_stati, $status, $status_name, $total, $class );
|
||||
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')
|
||||
"
|
||||
);
|
||||
|
||||
$class = '';
|
||||
if ( 'trash' === $post_status ) {
|
||||
$class = 'class="current"';
|
||||
$current_link_attributes = '';
|
||||
if ( $post_status === 'trash' ) {
|
||||
$current_link_attributes = 'class="current" aria-current="page"';
|
||||
}
|
||||
|
||||
$localized_text = sprintf(
|
||||
|
|
@ -359,28 +338,29 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
number_format_i18n( $trashed_posts )
|
||||
);
|
||||
|
||||
$status_links['trash'] = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor&post_status=trash' . $this->page_url ) ) . '"' . $class . '>' . $localized_text . '</a>';
|
||||
$status_links['trash'] = '<a href="' . esc_url( admin_url( 'admin.php?page=wpseo_tools&tool=bulk-editor&post_status=trash' . $this->page_url ) ) . '"' . $current_link_attributes . '>' . $localized_text . '</a>';
|
||||
|
||||
return $status_links;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs extra table navigation.
|
||||
*
|
||||
* @param string $which Table nav location (such as top).
|
||||
*/
|
||||
public function extra_tablenav( $which ) {
|
||||
|
||||
if ( 'top' === $which ) {
|
||||
if ( $which === 'top' ) {
|
||||
$post_types = get_post_types(
|
||||
array(
|
||||
[
|
||||
'public' => true,
|
||||
'exclude_from_search' => false,
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
$instance_type = esc_attr( $this->page_type );
|
||||
|
||||
if ( is_array( $post_types ) && $post_types !== array() ) {
|
||||
if ( is_array( $post_types ) && $post_types !== [] ) {
|
||||
global $wpdb;
|
||||
|
||||
echo '<div class="alignleft actions">';
|
||||
|
|
@ -388,19 +368,19 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
$post_types = esc_sql( $post_types );
|
||||
$post_types = "'" . implode( "', '", $post_types ) . "'";
|
||||
|
||||
$states = get_post_stati( array( 'show_in_admin_all_list' => true ) );
|
||||
$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' );
|
||||
|
|
@ -408,7 +388,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
|
||||
$options = '<option value="-1">' . esc_html__( 'Show All Content Types', 'wordpress-seo' ) . '</option>';
|
||||
|
||||
if ( is_array( $post_types ) && $post_types !== array() ) {
|
||||
if ( is_array( $post_types ) && $post_types !== [] ) {
|
||||
foreach ( $post_types as $post_type ) {
|
||||
$obj = get_post_type_object( $post_type->post_type );
|
||||
$options .= sprintf(
|
||||
|
|
@ -427,30 +407,34 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
);
|
||||
printf(
|
||||
'<select name="post_type_filter" id="%2$s">%1$s</select>',
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $options is properly escaped above.
|
||||
$options,
|
||||
esc_attr( 'post-type-filter-' . $instance_type )
|
||||
);
|
||||
|
||||
submit_button( __( 'Filter', 'wordpress-seo' ), 'button', false, false, array( 'id' => 'post-query-submit' ) );
|
||||
submit_button( esc_html__( 'Filter', 'wordpress-seo' ), 'button', false, false, [ 'id' => 'post-query-submit' ] );
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of sortable columns.
|
||||
*
|
||||
* The format is: 'internal-name' => array( 'orderby', bool ).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sortable_columns() {
|
||||
return array(
|
||||
'col_page_title' => array( 'post_title', true ),
|
||||
'col_post_type' => array( 'post_type', false ),
|
||||
'col_post_date' => array( 'post_date', false ),
|
||||
);
|
||||
return [
|
||||
'col_page_title' => [ 'post_title', true ],
|
||||
'col_post_type' => [ 'post_type', false ],
|
||||
'col_post_date' => [ 'post_date', false ],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the correct pagenumber and pageurl for the navigation
|
||||
* Sets the correct pagenumber and pageurl for the navigation.
|
||||
*/
|
||||
public function prepare_page_navigation() {
|
||||
|
||||
|
|
@ -461,8 +445,11 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
$current_status = $this->current_status;
|
||||
$current_order = $this->current_order;
|
||||
|
||||
// If current type doesn't compare with objects page_type, than we have to unset some vars in the requested url (which will be use for internal table urls).
|
||||
if ( $_GET['type'] !== $this->page_type ) {
|
||||
/*
|
||||
* If current type doesn't compare with objects page_type, then we have to unset
|
||||
* some vars in the requested url (which will be used for internal table urls).
|
||||
*/
|
||||
if ( isset( $this->input_fields['type'] ) && $this->input_fields['type'] !== $this->page_type ) {
|
||||
$request_url = remove_query_arg( 'paged', $request_url ); // Page will be set with value 1 below.
|
||||
$request_url = remove_query_arg( 'post_type_filter', $request_url );
|
||||
$request_url = remove_query_arg( 'post_status', $request_url );
|
||||
|
|
@ -473,10 +460,10 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
$current_page = 1;
|
||||
$current_filter = '-1';
|
||||
$current_status = '';
|
||||
$current_order = array(
|
||||
$current_order = [
|
||||
'orderby' => 'post_title',
|
||||
'order' => 'asc',
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
$_SERVER['REQUEST_URI'] = $request_url;
|
||||
|
|
@ -488,11 +475,10 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
$_GET['post_status'] = $current_status;
|
||||
$_GET['orderby'] = $current_order['orderby'];
|
||||
$_GET['order'] = $current_order['order'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Preparing the requested pagerows and setting the needed variables
|
||||
* Preparing the requested pagerows and setting the needed variables.
|
||||
*/
|
||||
public function prepare_items() {
|
||||
|
||||
|
|
@ -513,11 +499,10 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
|
||||
// Get the metadata for the current items ($this->items).
|
||||
$this->get_meta_data();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Getting the columns for first row
|
||||
* Getting the columns for first row.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
|
@ -526,17 +511,17 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
}
|
||||
|
||||
/**
|
||||
* Setting the column headers
|
||||
* Setting the column headers.
|
||||
*/
|
||||
protected function set_column_headers() {
|
||||
$columns = $this->get_columns();
|
||||
$hidden = array();
|
||||
$hidden = [];
|
||||
$sortable = $this->get_sortable_columns();
|
||||
$this->_column_headers = array( $columns, $hidden, $sortable );
|
||||
$this->_column_headers = [ $columns, $hidden, $sortable ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Counting total items
|
||||
* Counting total items.
|
||||
*
|
||||
* @param string $subquery SQL FROM part.
|
||||
* @param string $all_states SQL IN part.
|
||||
|
|
@ -546,19 +531,17 @@ 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}
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getting the post_type_clause filter
|
||||
* Getting the post_type_clause filter.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
|
@ -594,18 +577,17 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
}
|
||||
|
||||
$this->set_pagination_args(
|
||||
array(
|
||||
[
|
||||
'total_items' => $total_items,
|
||||
'total_pages' => ceil( $total_items / $per_page ),
|
||||
'per_page' => $per_page,
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
$this->pagination = array(
|
||||
$this->pagination = [
|
||||
'per_page' => $per_page,
|
||||
'offset' => ( $paged - 1 ) * $per_page,
|
||||
);
|
||||
|
||||
'offset' => ( ( $paged - 1 ) * $per_page ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -634,7 +616,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
|
||||
// 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}
|
||||
|
|
@ -645,18 +627,19 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
}
|
||||
|
||||
/**
|
||||
* Heavily restricts the possible columns by which a user can order the table in the bulk editor, thereby preventing a possible CSRF vulnerability.
|
||||
* Heavily restricts the possible columns by which a user can order the table
|
||||
* in the bulk editor, thereby preventing a possible CSRF vulnerability.
|
||||
*
|
||||
* @param string $orderby The column by which we want to order.
|
||||
*
|
||||
* @return string $orderby
|
||||
* @return string
|
||||
*/
|
||||
protected function sanitize_orderby( $orderby ) {
|
||||
$valid_column_names = array(
|
||||
$valid_column_names = [
|
||||
'post_title',
|
||||
'post_type',
|
||||
'post_date',
|
||||
);
|
||||
];
|
||||
|
||||
if ( in_array( $orderby, $valid_column_names, true ) ) {
|
||||
return $orderby;
|
||||
|
|
@ -666,14 +649,15 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
}
|
||||
|
||||
/**
|
||||
* Makes sure the order clause is always ASC or DESC for the bulk editor table, thereby preventing a possible CSRF vulnerability.
|
||||
* Makes sure the order clause is always ASC or DESC for the bulk editor table,
|
||||
* thereby preventing a possible CSRF vulnerability.
|
||||
*
|
||||
* @param string $order Whether we want to sort ascending or descending.
|
||||
*
|
||||
* @return string $order SQL order string (ASC, DESC).
|
||||
* @return string SQL order string (ASC, DESC).
|
||||
*/
|
||||
protected function sanitize_order( $order ) {
|
||||
if ( in_array( strtoupper( $order ), array( 'ASC', 'DESC' ), true ) ) {
|
||||
if ( in_array( strtoupper( $order ), [ 'ASC', 'DESC' ], true ) ) {
|
||||
return $order;
|
||||
}
|
||||
|
||||
|
|
@ -703,13 +687,15 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
* @return string
|
||||
*/
|
||||
protected function get_all_states() {
|
||||
$states = get_post_stati( array( 'show_in_admin_all_list' => true ) );
|
||||
global $wpdb;
|
||||
|
||||
$states = get_post_stati( [ 'show_in_admin_all_list' => true ] );
|
||||
$states['trash'] = 'trash';
|
||||
|
||||
if ( ! empty( $_GET['post_status'] ) ) {
|
||||
$requested_state = sanitize_text_field( $_GET['post_status'] );
|
||||
if ( ! empty( $this->input_fields['post_status'] ) ) {
|
||||
$requested_state = $this->input_fields['post_status'];
|
||||
if ( in_array( $requested_state, $states, true ) ) {
|
||||
$states = array( $requested_state );
|
||||
$states = [ $requested_state ];
|
||||
}
|
||||
|
||||
if ( $requested_state !== 'trash' ) {
|
||||
|
|
@ -717,10 +703,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
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -732,7 +718,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
|
||||
list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
|
||||
|
||||
if ( ( is_array( $records ) && $records !== array() ) && ( is_array( $columns ) && $columns !== array() ) ) {
|
||||
if ( ( is_array( $records ) && $records !== [] ) && ( is_array( $columns ) && $columns !== [] ) ) {
|
||||
|
||||
foreach ( $records as $rec ) {
|
||||
|
||||
|
|
@ -776,14 +762,14 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
protected function column_attributes( $column_name, $hidden, $classes, $column_display_name ) {
|
||||
|
||||
$attributes = '';
|
||||
$class = array( $column_name, "column-$column_name$classes" );
|
||||
$class = [ $column_name, "column-$column_name$classes" ];
|
||||
|
||||
if ( in_array( $column_name, $hidden, true ) ) {
|
||||
$class[] = 'hidden';
|
||||
}
|
||||
|
||||
if ( ! empty( $class ) ) {
|
||||
$attributes = 'class="' . implode( ' ', $class ) . '"';
|
||||
$attributes = 'class="' . esc_attr( implode( ' ', $class ) ) . '"';
|
||||
}
|
||||
|
||||
$attributes .= ' data-colname="' . esc_attr( $column_display_name ) . '"';
|
||||
|
|
@ -807,9 +793,9 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
$post_type_object = get_post_type_object( $rec->post_type );
|
||||
$can_edit_post = current_user_can( $post_type_object->cap->edit_post, $rec->ID );
|
||||
|
||||
$actions = array();
|
||||
$actions = [];
|
||||
|
||||
if ( $can_edit_post && 'trash' !== $rec->post_status ) {
|
||||
if ( $can_edit_post && $rec->post_status !== 'trash' ) {
|
||||
$actions['edit'] = sprintf(
|
||||
'<a href="%s" aria-label="%s">%s</a>',
|
||||
esc_url( get_edit_post_link( $rec->ID, true ) ),
|
||||
|
|
@ -820,7 +806,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
}
|
||||
|
||||
if ( $post_type_object->public ) {
|
||||
if ( in_array( $rec->post_status, array( 'pending', 'draft', 'future' ), true ) ) {
|
||||
if ( in_array( $rec->post_status, [ 'pending', 'draft', 'future' ], true ) ) {
|
||||
if ( $can_edit_post ) {
|
||||
$actions['view'] = sprintf(
|
||||
'<a href="%s" aria-label="%s">%s</a>',
|
||||
|
|
@ -831,7 +817,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
);
|
||||
}
|
||||
}
|
||||
elseif ( 'trash' !== $rec->post_status ) {
|
||||
elseif ( $rec->post_status !== 'trash' ) {
|
||||
$actions['view'] = sprintf(
|
||||
'<a href="%s" aria-label="%s" rel="bookmark">%s</a>',
|
||||
esc_url( get_permalink( $rec->ID ) ),
|
||||
|
|
@ -845,7 +831,6 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
$return .= $this->row_actions( $actions );
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -907,7 +892,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
/**
|
||||
* Parse the field where the existing meta-data value is displayed.
|
||||
*
|
||||
* @param integer $record_id Record ID.
|
||||
* @param int $record_id Record ID.
|
||||
* @param string $attributes HTML attributes.
|
||||
* @param bool|array $values Optional values data array.
|
||||
*
|
||||
|
|
@ -916,7 +901,7 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
protected function parse_meta_data_field( $record_id, $attributes, $values = false ) {
|
||||
|
||||
// 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 ] : [];
|
||||
$meta_key = WPSEO_Meta::$meta_prefix . $this->target_db_field;
|
||||
$meta_value = ( ! empty( $meta_data[ $meta_key ] ) ) ? $meta_data[ $meta_key ] : '';
|
||||
|
||||
|
|
@ -924,7 +909,10 @@ class WPSEO_Bulk_List_Table extends WP_List_Table {
|
|||
$meta_value = $values[ $meta_value ];
|
||||
}
|
||||
|
||||
return sprintf( '<td %2$s id="wpseo-existing-%4$s-%3$s">%1$s</td>', $meta_value, $attributes, $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 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds a checkbox to the focus keyword section.
|
||||
*/
|
||||
class WPSEO_Cornerstone_Field {
|
||||
|
||||
/**
|
||||
* Returns a label with a checkbox in it. Make it possible to mark the page as cornerstone content.
|
||||
*
|
||||
* @param WP_POST $post The post object.
|
||||
*
|
||||
* @return string The HTML to show.
|
||||
*/
|
||||
public function get_html( $post ) {
|
||||
|
||||
$post_types = apply_filters( 'wpseo_cornerstone_post_types', WPSEO_Post_Type::get_accessible_post_types() );
|
||||
if ( ! is_array( $post_types ) || ! isset( $post_types[ get_post_type( $post ) ] ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$return = '';
|
||||
$return .= sprintf(
|
||||
'<input id="%1$s" class="wpseo-cornerstone-checkbox" type="checkbox" value="1" name="%1$s" %2$s/>',
|
||||
WPSEO_Cornerstone::META_NAME,
|
||||
checked( $this->get_meta_value( $post->ID ), '1', false )
|
||||
);
|
||||
|
||||
$return .= sprintf( '<label for="%1$s">', WPSEO_Cornerstone::META_NAME );
|
||||
|
||||
$return .= sprintf(
|
||||
/* translators: 1: link open tag; 2: link close tag. */
|
||||
__( 'This article is %1$scornerstone content%2$s', 'wordpress-seo' ),
|
||||
'<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/metabox-help-cornerstone' ) . '" target="_blank">',
|
||||
'</a>'
|
||||
);
|
||||
$return .= '</label>';
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the yoast cornerstone content.
|
||||
*/
|
||||
class WPSEO_Cornerstone {
|
||||
|
||||
const META_NAME = '_yst_is_cornerstone';
|
||||
|
||||
/**
|
||||
* Registers the hooks.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
global $pagenow;
|
||||
|
||||
if ( ! $this->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 );
|
||||
}
|
||||
}
|
||||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 '<p id="wpseo-settings-export-desc">';
|
||||
printf(
|
||||
'<div class="notice notice-error"><p>%1$s</p></div>',
|
||||
$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 '</p>';
|
||||
/* translators: %1$s expands to Yoast SEO */
|
||||
echo '<label for="wpseo-settings-export" class="yoast-inline-label">' . sprintf( __( 'Your %1$s settings:', 'wordpress-seo' ), 'Yoast SEO' ) . '</label><br />';
|
||||
echo '<textarea id="wpseo-settings-export" rows="20" cols="100" aria-describedby="wpseo-settings-export-desc">' . esc_textarea( $this->export ) . '</textarea>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exposes shortlinks in a global, so that we can pass them to our Javascript components.
|
||||
*/
|
||||
class WPSEO_Expose_Shortlinks implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* Array containing the keys and shortlinks.
|
||||
*
|
||||
* @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.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 );
|
||||
}
|
||||
}
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the class that contains the available extensions for Yoast SEO.
|
||||
*/
|
||||
class WPSEO_Extension_Manager {
|
||||
|
||||
/** The transient key to save the cache in */
|
||||
const TRANSIENT_CACHE_KEY = 'wpseo_license_active_extensions';
|
||||
|
||||
/** @var WPSEO_Extension[] */
|
||||
protected $extensions = array();
|
||||
|
||||
/** @var array List of active plugins */
|
||||
static protected $active_extensions;
|
||||
|
||||
/**
|
||||
* Adds an extension to the manager.
|
||||
*
|
||||
* @param string $extension_name The extension name.
|
||||
* @param WPSEO_Extension $extension The extension value object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add( $extension_name, WPSEO_Extension $extension = null ) {
|
||||
$this->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 );
|
||||
}
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the class that contains the list of possible extensions for Yoast SEO.
|
||||
*/
|
||||
class WPSEO_Extensions {
|
||||
|
||||
/** @var array Array with the Yoast extensions */
|
||||
protected $extensions = array(
|
||||
'Yoast SEO Premium' => 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';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Gutenberg_Compatibility
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Gutenberg_Compatibility
|
||||
*/
|
||||
class WPSEO_Gutenberg_Compatibility {
|
||||
|
||||
/**
|
||||
* The currently released version of Gutenberg.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CURRENT_RELEASE = '11.5.0';
|
||||
|
||||
/**
|
||||
* The minimally supported version of Gutenberg by the plugin.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const MINIMUM_SUPPORTED = '11.5.0';
|
||||
|
||||
/**
|
||||
* Holds the current version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $current_version;
|
||||
|
||||
/**
|
||||
* WPSEO_Gutenberg_Compatibility constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->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 '';
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Options\Tabs
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Help_Center_Item
|
||||
*/
|
||||
class WPSEO_Help_Center_Item {
|
||||
|
||||
/** @var string Identifier for this tab. */
|
||||
private $identifier;
|
||||
|
||||
/** @var string Label to display. */
|
||||
private $label;
|
||||
|
||||
/** @var string The dashicon classname to display in front of the label. */
|
||||
private $dashicon;
|
||||
|
||||
/** @var array Optional arguments. */
|
||||
private $args = array();
|
||||
|
||||
/**
|
||||
* WPSEO_Help_Center_Item constructor.
|
||||
*
|
||||
* @param string $identifier Unique identifier for this tab.
|
||||
* @param string $label Label to display.
|
||||
* @param array $args Optional. Settings for this tab.
|
||||
* @param string $dashicon Optional. The classname of the dahsicon to put in front of the label.
|
||||
*/
|
||||
public function __construct( $identifier, $label, $args = array(), $dashicon = '' ) {
|
||||
$this->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 '';
|
||||
}
|
||||
}
|
||||
|
|
@ -1,272 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Help_Center
|
||||
*/
|
||||
class WPSEO_Help_Center {
|
||||
/**
|
||||
* The tabs in the help center.
|
||||
*
|
||||
* @var WPSEO_Option_Tab[] $tab
|
||||
*/
|
||||
private $tabs;
|
||||
|
||||
/**
|
||||
* Mount point in the HTML.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $identifier = 'yoast-help-center-container';
|
||||
|
||||
/**
|
||||
* Additional help center items.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $help_center_items = array();
|
||||
|
||||
/**
|
||||
* Show premium support tab.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $premium_support;
|
||||
|
||||
/**
|
||||
* WPSEO_Help_Center constructor.
|
||||
*
|
||||
* @param string $unused Backwards compatible argument.
|
||||
* @param WPSEO_Option_Tabs|WPSEO_Option_Tab $option_tabs Currently displayed tabs.
|
||||
* @param boolean $premium_support Show premium support tab.
|
||||
*/
|
||||
public function __construct( $unused, $option_tabs, $premium_support = false ) {
|
||||
$this->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 '<div id="' . esc_attr( $this->identifier ) . '">' . esc_html__( 'Loading help center.', 'wordpress-seo' ) . '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 = '<p class="yoast-measure">' . __( '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' ) . '</p>';
|
||||
/* translators: %1$s: expands to 'Yoast SEO Premium'. */
|
||||
$popup_content .= '<p>' . sprintf( __( 'Other benefits of %1$s for you:', 'wordpress-seo' ), 'Yoast SEO Premium' ) . '</p>';
|
||||
$popup_content .= '<ul class="wpseo-premium-advantages-list">';
|
||||
$popup_content .= '<li>' . 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' ), '', ''
|
||||
) . '</li>';
|
||||
$popup_content .= '<li>' . __( 'Superfast internal links suggestions', 'wordpress-seo' ) . '</li>';
|
||||
$popup_content .= '<li>' . 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' ), '', ''
|
||||
) . '</li>';
|
||||
$popup_content .= '<li>' . __( '24/7 support', 'wordpress-seo' ) . '</li>';
|
||||
$popup_content .= '<li>' . __( 'No ads!', 'wordpress-seo' ) . '</li>';
|
||||
$popup_content .= '</ul>';
|
||||
|
||||
$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 <code>%s</code> 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();
|
||||
}
|
||||
}
|
||||
265
wp-content/plugins/wordpress-seo/admin/class-helpscout.php
Normal file
265
wp-content/plugins/wordpress-seo/admin/class-helpscout.php
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_HelpScout
|
||||
*/
|
||||
class WPSEO_HelpScout implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* The id for the beacon.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $beacon_id;
|
||||
|
||||
/**
|
||||
* The pages where the beacon is loaded.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pages;
|
||||
|
||||
/**
|
||||
* The products the beacon is loaded for.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $products;
|
||||
|
||||
/**
|
||||
* Whether to asks the user's consent before loading in HelpScout.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $ask_consent;
|
||||
|
||||
/**
|
||||
* WPSEO_HelpScout constructor.
|
||||
*
|
||||
* @param string $beacon_id The beacon id.
|
||||
* @param array $pages The pages where the beacon is loaded.
|
||||
* @param array $products The products the beacon is loaded for.
|
||||
* @param bool $ask_consent Optional. Whether to ask for consent before loading in HelpScout.
|
||||
*/
|
||||
public function __construct( $beacon_id, array $pages, array $products, $ask_consent = false ) {
|
||||
$this->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(
|
||||
'<script type="text/javascript">window.%1$s(\'%2$s\', %3$s)</script>',
|
||||
( $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(),
|
||||
'<a href="' . admin_url( 'themes.php' ) . '">Theme</a>' => $this->get_theme_info(),
|
||||
'<a href="' . admin_url( 'plugins.php' ) . '">Plugins</a>' => $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 = '<table>';
|
||||
|
||||
foreach ( $fields_to_use as $label => $field_to_use ) {
|
||||
if ( isset( $server_data[ $field_to_use ] ) ) {
|
||||
$server_info .= sprintf( '<tr><td>%1$s</td><td>%2$s</td></tr>', esc_html( $label ), esc_html( $server_data[ $field_to_use ] ) );
|
||||
}
|
||||
}
|
||||
|
||||
$server_info .= '</table>';
|
||||
|
||||
return $server_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns info about the Yoast SEO plugin version and license.
|
||||
*
|
||||
* @param object $plugin The plugin.
|
||||
*
|
||||
* @return string The product info.
|
||||
*/
|
||||
private function get_product_info( $plugin ) {
|
||||
if ( empty( $plugin ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$product_info = '<table>';
|
||||
$product_info .= '<tr><td>Version</td><td>' . $plugin->product->version . '</td></tr>';
|
||||
$product_info .= '<tr><td>Expiration date</td><td>' . $plugin->expiry_date . '</td></tr>';
|
||||
$product_info .= '</table>';
|
||||
|
||||
return $product_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the WordPress version + a suffix if current WP is multi site.
|
||||
*
|
||||
* @return string The WordPress version string.
|
||||
*/
|
||||
private function get_wordpress_version() {
|
||||
global $wp_version;
|
||||
|
||||
$wordpress_version = $wp_version;
|
||||
if ( is_multisite() ) {
|
||||
$wordpress_version .= ' MULTI-SITE';
|
||||
}
|
||||
|
||||
return $wordpress_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted HTML string for the current theme.
|
||||
*
|
||||
* @return string The theme info as string.
|
||||
*/
|
||||
private function get_theme_info() {
|
||||
$theme = wp_get_theme();
|
||||
|
||||
$theme_info = sprintf(
|
||||
'<a href="%1$s">%2$s</a> v%3$s by %4$s',
|
||||
esc_attr( $theme->display( 'ThemeURI' ) ),
|
||||
esc_html( $theme->display( 'Name' ) ),
|
||||
esc_html( $theme->display( 'Version' ) ),
|
||||
esc_html( $theme->display( 'Author' ) )
|
||||
);
|
||||
|
||||
if ( is_child_theme() ) {
|
||||
$theme_info .= sprintf( '<br />Child theme of: %1$s', esc_html( $theme->display( 'Template' ) ) );
|
||||
}
|
||||
|
||||
return $theme_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted HTML list of all active plugins.
|
||||
*
|
||||
* @return string The active plugins.
|
||||
*/
|
||||
private function get_active_plugins() {
|
||||
$updates_available = get_site_transient( 'update_plugins' );
|
||||
|
||||
$active_plugins = '';
|
||||
foreach ( wp_get_active_and_valid_plugins() as $plugin ) {
|
||||
$plugin_data = get_plugin_data( $plugin );
|
||||
$plugin_file = str_replace( trailingslashit( WP_PLUGIN_DIR ), '', $plugin );
|
||||
|
||||
if ( isset( $updates_available->response[ $plugin_file ] ) ) {
|
||||
$active_plugins .= '<i class="icon-close1"></i> ';
|
||||
}
|
||||
|
||||
$active_plugins .= sprintf(
|
||||
'<a href="%1$s">%2$s</a> v%3$s',
|
||||
esc_attr( $plugin_data['PluginURI'] ),
|
||||
esc_html( $plugin_data['Name'] ),
|
||||
esc_html( $plugin_data['Version'] )
|
||||
);
|
||||
}
|
||||
|
||||
return $active_plugins;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,211 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the values for a single Yoast Premium extension plugin.
|
||||
*/
|
||||
class WPSEO_License_Page_Manager implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* @var string Version number for License Page Manager.
|
||||
*/
|
||||
const VERSION_LEGACY = '1';
|
||||
|
||||
/**
|
||||
* @var string Version number for License Page Manager.
|
||||
*/
|
||||
const VERSION_BACKWARDS_COMPATIBILITY = '2';
|
||||
|
||||
/**
|
||||
* Registers all hooks to WordPress.
|
||||
*/
|
||||
public function register_hooks() {
|
||||
add_filter( 'http_response', array( $this, 'handle_response' ), 10, 3 );
|
||||
|
||||
if ( $this->get_version() === self::VERSION_BACKWARDS_COMPATIBILITY ) {
|
||||
add_filter( 'yoast-license-valid', '__return_true' );
|
||||
add_filter( 'yoast-show-license-notice', '__return_false' );
|
||||
add_action( 'admin_init', array( $this, 'validate_extensions' ), 15 );
|
||||
}
|
||||
else {
|
||||
add_action( 'admin_init', array( $this, 'remove_faulty_notifications' ), 15 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the extensions and show a notice for the invalid extensions.
|
||||
*/
|
||||
public function validate_extensions() {
|
||||
|
||||
if ( filter_input( INPUT_GET, 'page' ) === WPSEO_Admin::PAGE_IDENTIFIER ) {
|
||||
/**
|
||||
* Filter: 'yoast-active-extensions' - Collects all active extensions. This hook is implemented in the
|
||||
* license manager.
|
||||
*
|
||||
* @api array $extensions The array with extensions.
|
||||
*/
|
||||
apply_filters( 'yoast-active-extensions', array() );
|
||||
}
|
||||
|
||||
$extension_list = new WPSEO_Extensions();
|
||||
$extensions = $extension_list->get();
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
|
||||
foreach ( $extensions as $product_name ) {
|
||||
$notification = $this->create_notification( $product_name );
|
||||
|
||||
// Add a notification when the installed plugin isn't activated in My Yoast.
|
||||
if ( $extension_list->is_installed( $product_name ) && ! $extension_list->is_valid( $product_name ) ) {
|
||||
$notification_center->add_notification( $notification );
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$notification_center->remove_notification( $notification );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the faulty set notifications.
|
||||
*/
|
||||
public function remove_faulty_notifications() {
|
||||
$extension_list = new WPSEO_Extensions();
|
||||
$extensions = $extension_list->get();
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
|
||||
foreach ( $extensions as $product_name ) {
|
||||
$notification = $this->create_notification( $product_name );
|
||||
$notification_center->remove_notification( $notification );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the response.
|
||||
*
|
||||
* @param array $response HTTP response.
|
||||
* @param array $request_arguments HTTP request arguments. Unused.
|
||||
* @param string $url The request URL.
|
||||
*
|
||||
* @return array The response array.
|
||||
*/
|
||||
public function handle_response( array $response, $request_arguments, $url ) {
|
||||
$response_code = wp_remote_retrieve_response_code( $response );
|
||||
|
||||
if ( $response_code === 200 && $this->is_expected_endpoint( $url ) ) {
|
||||
$response_data = $this->parse_response( $response );
|
||||
$this->detect_version( $response_data );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the license page to use based on the version number.
|
||||
*
|
||||
* @return string The page to use.
|
||||
*/
|
||||
public function get_license_page() {
|
||||
return 'licenses';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version number of the license server.
|
||||
*
|
||||
* @return int The version number
|
||||
*/
|
||||
protected function get_version() {
|
||||
return get_option( $this->get_option_name(), self::VERSION_BACKWARDS_COMPATIBILITY );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the option name.
|
||||
*
|
||||
* @return string The option name.
|
||||
*/
|
||||
protected function get_option_name() {
|
||||
return 'wpseo_license_server_version';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version when there is a value in the response.
|
||||
*
|
||||
* @param array $response The response to extract the version from.
|
||||
*/
|
||||
protected function detect_version( $response ) {
|
||||
if ( ! empty( $response['serverVersion'] ) ) {
|
||||
$this->set_version( $response['serverVersion'] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version.
|
||||
*
|
||||
* @param string $server_version The version number to save.
|
||||
*/
|
||||
protected function set_version( $server_version ) {
|
||||
update_option( $this->get_option_name(), $server_version );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the response by getting its body and do a unserialize of it.
|
||||
*
|
||||
* @param array $response The response to parse.
|
||||
*
|
||||
* @return mixed|string|false The parsed response.
|
||||
*/
|
||||
protected function parse_response( $response ) {
|
||||
$response = json_decode( wp_remote_retrieve_body( $response ), true );
|
||||
$response = maybe_unserialize( $response );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given url matches the expected endpoint.
|
||||
*
|
||||
* @param string $url The url to check.
|
||||
*
|
||||
* @return bool True when url matches the endpoint.
|
||||
*/
|
||||
protected function is_expected_endpoint( $url ) {
|
||||
$url_parts = wp_parse_url( $url );
|
||||
|
||||
$is_yoast_com = ( in_array( $url_parts['host'], array( 'yoast.com', 'my.yoast.com' ), true ) );
|
||||
$is_edd_api = ( isset( $url_parts['path'] ) && $url_parts['path'] === '/edd-sl-api' );
|
||||
|
||||
return $is_yoast_com && $is_edd_api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of Yoast_Notification
|
||||
*
|
||||
* @param string $product_name The product to create the notification for.
|
||||
*
|
||||
* @return Yoast_Notification The created notification.
|
||||
*/
|
||||
protected function create_notification( $product_name ) {
|
||||
$notification_options = array(
|
||||
'type' => Yoast_Notification::ERROR,
|
||||
'id' => 'wpseo-dismiss-' . sanitize_title_with_dashes( $product_name, null, 'save' ),
|
||||
'capabilities' => 'wpseo_manage_options',
|
||||
);
|
||||
|
||||
$notification = new Yoast_Notification(
|
||||
sprintf(
|
||||
/* translators: %1$s expands to the product name. %2$s expands to a link to My Yoast */
|
||||
__( 'You are not receiving updates or support! Fix this problem by adding this site and enabling %1$s for it in %2$s.', 'wordpress-seo' ),
|
||||
$product_name,
|
||||
'<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/13j' ) . '" target="_blank">My Yoast</a>'
|
||||
),
|
||||
$notification_options
|
||||
);
|
||||
|
||||
return $notification;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,31 +5,54 @@
|
|||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
use Yoast\WP\SEO\Context\Meta_Tags_Context;
|
||||
use Yoast\WP\SEO\Integrations\Admin\Admin_Columns_Cache_Integration;
|
||||
use Yoast\WP\SEO\Surfaces\Values\Meta;
|
||||
|
||||
/**
|
||||
* Class WPSEO_Meta_Columns
|
||||
* Class WPSEO_Meta_Columns.
|
||||
*/
|
||||
class WPSEO_Meta_Columns {
|
||||
|
||||
/**
|
||||
* Holds the context objects for each indexable.
|
||||
*
|
||||
* @var Meta_Tags_Context[]
|
||||
*/
|
||||
protected $context = [];
|
||||
|
||||
/**
|
||||
* Holds the SEO analysis.
|
||||
*
|
||||
* @var WPSEO_Metabox_Analysis_SEO
|
||||
*/
|
||||
private $analysis_seo;
|
||||
|
||||
/**
|
||||
* Holds the readability analysis.
|
||||
*
|
||||
* @var WPSEO_Metabox_Analysis_Readability
|
||||
*/
|
||||
private $analysis_readability;
|
||||
|
||||
/**
|
||||
* Admin columns cache.
|
||||
*
|
||||
* @var Admin_Columns_Cache_Integration
|
||||
*/
|
||||
private $admin_columns_cache;
|
||||
|
||||
/**
|
||||
* When page analysis is enabled, just initialize the hooks.
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( apply_filters( 'wpseo_use_page_analysis', true ) === true ) {
|
||||
add_action( 'admin_init', array( $this, 'setup_hooks' ) );
|
||||
add_action( 'admin_init', [ $this, 'setup_hooks' ] );
|
||||
}
|
||||
|
||||
$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 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -39,14 +62,15 @@ class WPSEO_Meta_Columns {
|
|||
$this->set_post_type_hooks();
|
||||
|
||||
if ( $this->analysis_seo->is_enabled() ) {
|
||||
add_action( 'restrict_manage_posts', array( $this, 'posts_filter_dropdown' ) );
|
||||
add_action( 'restrict_manage_posts', [ $this, 'posts_filter_dropdown' ] );
|
||||
}
|
||||
|
||||
if ( $this->analysis_readability->is_enabled() ) {
|
||||
add_action( 'restrict_manage_posts', array( $this, 'posts_filter_dropdown_readability' ) );
|
||||
add_action( 'restrict_manage_posts', [ $this, 'posts_filter_dropdown_readability' ] );
|
||||
}
|
||||
|
||||
add_filter( 'request', array( $this, 'column_sort_orderby' ) );
|
||||
add_filter( 'request', [ $this, 'column_sort_orderby' ] );
|
||||
add_filter( 'default_hidden_columns', [ $this, 'column_hidden' ], 10, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -61,7 +85,7 @@ class WPSEO_Meta_Columns {
|
|||
return $columns;
|
||||
}
|
||||
|
||||
$added_columns = array();
|
||||
$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>';
|
||||
|
|
@ -75,7 +99,7 @@ class WPSEO_Meta_Columns {
|
|||
$added_columns['wpseo-metadesc'] = __( 'Meta Desc.', 'wordpress-seo' );
|
||||
|
||||
if ( $this->analysis_seo->is_enabled() ) {
|
||||
$added_columns['wpseo-focuskw'] = __( 'Focus KW', 'wordpress-seo' );
|
||||
$added_columns['wpseo-focuskw'] = __( 'Keyphrase', 'wordpress-seo' );
|
||||
}
|
||||
|
||||
return array_merge( $columns, $added_columns );
|
||||
|
|
@ -94,27 +118,23 @@ class WPSEO_Meta_Columns {
|
|||
|
||||
switch ( $column_name ) {
|
||||
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':
|
||||
$post = get_post( $post_id, ARRAY_A );
|
||||
$title = wpseo_replace_vars( $this->page_title( $post_id ), $post );
|
||||
$title = apply_filters( 'wpseo_title', $title );
|
||||
|
||||
echo esc_html( $title );
|
||||
echo esc_html( $this->get_meta( $post_id )->title );
|
||||
return;
|
||||
|
||||
case 'wpseo-metadesc':
|
||||
$post = get_post( $post_id, ARRAY_A );
|
||||
$metadesc_val = wpseo_replace_vars( WPSEO_Meta::get_value( 'metadesc', $post_id ), $post );
|
||||
$metadesc_val = apply_filters( 'wpseo_metadesc', $metadesc_val );
|
||||
$metadesc_val = $this->get_meta( $post_id )->meta_description;
|
||||
|
||||
if ( '' === $metadesc_val ) {
|
||||
if ( $metadesc_val === '' ) {
|
||||
echo '<span aria-hidden="true">—</span><span class="screen-reader-text">',
|
||||
esc_html__( 'Meta description not set.', 'wordpress-seo' ),
|
||||
'</span>';
|
||||
|
|
@ -127,9 +147,9 @@ class WPSEO_Meta_Columns {
|
|||
case 'wpseo-focuskw':
|
||||
$focuskw_val = WPSEO_Meta::get_value( 'focuskw', $post_id );
|
||||
|
||||
if ( '' === $focuskw_val ) {
|
||||
if ( $focuskw_val === '' ) {
|
||||
echo '<span aria-hidden="true">—</span><span class="screen-reader-text">',
|
||||
esc_html__( 'Focus keyword not set.', 'wordpress-seo' ),
|
||||
esc_html__( 'Focus keyphrase not set.', 'wordpress-seo' ),
|
||||
'</span>';
|
||||
return;
|
||||
}
|
||||
|
|
@ -163,30 +183,22 @@ class WPSEO_Meta_Columns {
|
|||
/**
|
||||
* Hides the SEO title, meta description and focus keyword columns if the user hasn't chosen which columns to hide.
|
||||
*
|
||||
* @param array|false $result The hidden columns.
|
||||
* @param string $option The option name used to set which columns should be hidden.
|
||||
* @param WP_User $user The User.
|
||||
* @param array $hidden The hidden columns.
|
||||
*
|
||||
* @return array $result Array containing the columns to hide.
|
||||
* @return array Array containing the columns to hide.
|
||||
*/
|
||||
public function column_hidden( $result, $option, $user ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( $user->has_prop( $wpdb->get_blog_prefix() . $option ) || $user->has_prop( $option ) ) {
|
||||
return $result;
|
||||
public function column_hidden( $hidden ) {
|
||||
if ( ! is_array( $hidden ) ) {
|
||||
$hidden = [];
|
||||
}
|
||||
|
||||
if ( ! is_array( $result ) ) {
|
||||
$result = array();
|
||||
}
|
||||
|
||||
array_push( $result, 'wpseo-title', 'wpseo-metadesc' );
|
||||
array_push( $hidden, 'wpseo-title', 'wpseo-metadesc' );
|
||||
|
||||
if ( $this->analysis_seo->is_enabled() ) {
|
||||
array_push( $result, 'wpseo-focuskw' );
|
||||
$hidden[] = 'wpseo-focuskw';
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -202,11 +214,13 @@ class WPSEO_Meta_Columns {
|
|||
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">';
|
||||
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput -- Output is correctly escaped in the generate_option() method.
|
||||
echo $this->generate_option( '', __( 'All SEO Scores', 'wordpress-seo' ) );
|
||||
|
||||
foreach ( $ranks as $rank ) {
|
||||
$selected = selected( $this->get_current_seo_filter(), $rank->get_rank(), false );
|
||||
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput -- Output is correctly escaped in the generate_option() method.
|
||||
echo $this->generate_option( $rank->get_rank(), $rank->get_drop_down_label(), $selected );
|
||||
}
|
||||
|
||||
|
|
@ -228,11 +242,13 @@ class WPSEO_Meta_Columns {
|
|||
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">';
|
||||
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput -- Output is correctly escaped in the generate_option() method.
|
||||
echo $this->generate_option( '', __( 'All Readability Scores', 'wordpress-seo' ) );
|
||||
|
||||
foreach ( $ranks as $rank ) {
|
||||
$selected = selected( $this->get_current_readability_filter(), $rank->get_rank(), false );
|
||||
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput -- Output is correctly escaped in the generate_option() method.
|
||||
echo $this->generate_option( $rank->get_rank(), $rank->get_drop_down_readability_labels(), $selected );
|
||||
}
|
||||
|
||||
|
|
@ -242,9 +258,9 @@ class WPSEO_Meta_Columns {
|
|||
/**
|
||||
* Generates an <option> element.
|
||||
*
|
||||
* @param string $value The option's value.
|
||||
* @param string $label The option's label.
|
||||
* @param string $selected HTML selected attribute for an option.
|
||||
* @param string $value The option's value.
|
||||
* @param string $label The option's label.
|
||||
* @param string $selected HTML selected attribute for an option.
|
||||
*
|
||||
* @return string The generated <option> element.
|
||||
*/
|
||||
|
|
@ -252,6 +268,19 @@ class WPSEO_Meta_Columns {
|
|||
return '<option ' . $selected . ' value="' . esc_attr( $value ) . '">' . esc_html( $label ) . '</option>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the meta object for a given post ID.
|
||||
*
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return Meta The meta object.
|
||||
*/
|
||||
protected function get_meta( $post_id ) {
|
||||
$indexable = $this->admin_columns_cache->get_indexable( $post_id );
|
||||
|
||||
return YoastSEO()->meta->for_indexable( $indexable, 'Post_Type' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the SEO score filter to be later used in the meta query, based on the passed SEO filter.
|
||||
*
|
||||
|
|
@ -294,11 +323,11 @@ class WPSEO_Meta_Columns {
|
|||
* @return array The keyword filter.
|
||||
*/
|
||||
protected function get_keyword_filter( $keyword_filter ) {
|
||||
return array(
|
||||
'post_type' => get_query_var( 'post_type', 'post' ),
|
||||
'meta_key' => WPSEO_Meta::$meta_prefix . 'focuskw',
|
||||
'meta_value' => sanitize_text_field( $keyword_filter ),
|
||||
);
|
||||
return [
|
||||
'post_type' => get_query_var( 'post_type', 'post' ),
|
||||
'key' => WPSEO_Meta::$meta_prefix . 'focuskw',
|
||||
'value' => sanitize_text_field( $keyword_filter ),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -318,7 +347,7 @@ class WPSEO_Meta_Columns {
|
|||
* @return array Array containing all the applicable filters.
|
||||
*/
|
||||
protected function collect_filters() {
|
||||
$active_filters = array();
|
||||
$active_filters = [];
|
||||
|
||||
$seo_filter = $this->get_current_seo_filter();
|
||||
$readability_filter = $this->get_current_readability_filter();
|
||||
|
|
@ -371,18 +400,18 @@ class WPSEO_Meta_Columns {
|
|||
* @return array Array containing the query parameters regarding meta robots.
|
||||
*/
|
||||
protected function get_meta_robots_query_values() {
|
||||
return array(
|
||||
return [
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
[
|
||||
'key' => WPSEO_Meta::$meta_prefix . 'meta-robots-noindex',
|
||||
'compare' => 'NOT EXISTS',
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'key' => WPSEO_Meta::$meta_prefix . 'meta-robots-noindex',
|
||||
'value' => '1',
|
||||
'compare' => '!=',
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -394,7 +423,7 @@ class WPSEO_Meta_Columns {
|
|||
*/
|
||||
protected function determine_score_filters( $score_filters ) {
|
||||
if ( count( $score_filters ) > 1 ) {
|
||||
return array_merge( array( 'relation' => 'AND' ), $score_filters );
|
||||
return array_merge( [ 'relation' => 'AND' ], $score_filters );
|
||||
}
|
||||
|
||||
return $score_filters;
|
||||
|
|
@ -439,7 +468,7 @@ class WPSEO_Meta_Columns {
|
|||
/**
|
||||
* Uses the vars to create a complete filter query that can later be executed to filter out posts.
|
||||
*
|
||||
* @param array $vars Array containing the variables that will be used in the meta query.
|
||||
* @param array $vars Array containing the variables that will be used in the meta query.
|
||||
* @param array $filters Array containing the filters that we need to apply in the meta query.
|
||||
*
|
||||
* @return array Array containing the complete filter query.
|
||||
|
|
@ -450,14 +479,14 @@ class WPSEO_Meta_Columns {
|
|||
return $vars;
|
||||
}
|
||||
|
||||
$result = array( 'meta_query' => array() );
|
||||
$result['meta_query'] = array_merge( $result['meta_query'], array( $this->determine_score_filters( $filters ) ) );
|
||||
$result = [ 'meta_query' => [] ];
|
||||
$result['meta_query'] = array_merge( $result['meta_query'], [ $this->determine_score_filters( $filters ) ] );
|
||||
|
||||
$current_seo_filter = $this->get_current_seo_filter();
|
||||
|
||||
// This only applies for the SEO score filter because it can because the SEO score can be altered by the no-index option.
|
||||
if ( $this->is_valid_filter( $current_seo_filter ) && ! in_array( $current_seo_filter, array( WPSEO_Rank::NO_INDEX, WPSEO_Rank::NO_FOCUS ), true ) ) {
|
||||
$result['meta_query'] = array_merge( $result['meta_query'], array( $this->get_meta_robots_query_values() ) );
|
||||
if ( $this->is_valid_filter( $current_seo_filter ) && ! in_array( $current_seo_filter, [ WPSEO_Rank::NO_INDEX, WPSEO_Rank::NO_FOCUS ], true ) ) {
|
||||
$result['meta_query'] = array_merge( $result['meta_query'], [ $this->get_meta_robots_query_values() ] );
|
||||
}
|
||||
|
||||
return array_merge( $vars, $result );
|
||||
|
|
@ -466,39 +495,39 @@ class WPSEO_Meta_Columns {
|
|||
/**
|
||||
* Creates a Readability score filter.
|
||||
*
|
||||
* @param number $low The lower boundary of the score.
|
||||
* @param number $low The lower boundary of the score.
|
||||
* @param number $high The higher boundary of the score.
|
||||
*
|
||||
* @return array The Readability Score filter.
|
||||
*/
|
||||
protected function create_readability_score_filter( $low, $high ) {
|
||||
return array(
|
||||
array(
|
||||
return [
|
||||
[
|
||||
'key' => WPSEO_Meta::$meta_prefix . 'content_score',
|
||||
'value' => array( $low, $high ),
|
||||
'value' => [ $low, $high ],
|
||||
'type' => 'numeric',
|
||||
'compare' => 'BETWEEN',
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SEO score filter.
|
||||
*
|
||||
* @param number $low The lower boundary of the score.
|
||||
* @param number $low The lower boundary of the score.
|
||||
* @param number $high The higher boundary of the score.
|
||||
*
|
||||
* @return array The SEO score filter.
|
||||
*/
|
||||
protected function create_seo_score_filter( $low, $high ) {
|
||||
return array(
|
||||
array(
|
||||
return [
|
||||
[
|
||||
'key' => WPSEO_Meta::$meta_prefix . 'linkdex',
|
||||
'value' => array( $low, $high ),
|
||||
'value' => [ $low, $high ],
|
||||
'type' => 'numeric',
|
||||
'compare' => 'BETWEEN',
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -507,13 +536,13 @@ class WPSEO_Meta_Columns {
|
|||
* @return array Array containin the no-index filter.
|
||||
*/
|
||||
protected function create_no_index_filter() {
|
||||
return array(
|
||||
array(
|
||||
return [
|
||||
[
|
||||
'key' => WPSEO_Meta::$meta_prefix . 'meta-robots-noindex',
|
||||
'value' => '1',
|
||||
'compare' => '=',
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -522,18 +551,18 @@ class WPSEO_Meta_Columns {
|
|||
* @return array Array containing the no focus keyword filter.
|
||||
*/
|
||||
protected function create_no_focus_keyword_filter() {
|
||||
return array(
|
||||
array(
|
||||
return [
|
||||
[
|
||||
'key' => WPSEO_Meta::$meta_prefix . 'meta-robots-noindex',
|
||||
'value' => 'needs-a-value-anyway',
|
||||
'compare' => 'NOT EXISTS',
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
'key' => WPSEO_Meta::$meta_prefix . 'linkdex',
|
||||
'value' => 'needs-a-value-anyway',
|
||||
'compare' => 'NOT EXISTS',
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -561,7 +590,7 @@ class WPSEO_Meta_Columns {
|
|||
/**
|
||||
* Determines whether the given post ID uses the default indexing settings.
|
||||
*
|
||||
* @param integer $post_id The post ID to check.
|
||||
* @param int $post_id The post ID to check.
|
||||
*
|
||||
* @return bool Whether or not the default indexing is being used for the post.
|
||||
*/
|
||||
|
|
@ -579,25 +608,25 @@ class WPSEO_Meta_Columns {
|
|||
private function filter_order_by( $order_by ) {
|
||||
switch ( $order_by ) {
|
||||
case 'wpseo-metadesc':
|
||||
return array(
|
||||
return [
|
||||
'meta_key' => WPSEO_Meta::$meta_prefix . 'metadesc',
|
||||
'orderby' => 'meta_value',
|
||||
);
|
||||
];
|
||||
|
||||
case 'wpseo-focuskw':
|
||||
return array(
|
||||
return [
|
||||
'meta_key' => WPSEO_Meta::$meta_prefix . 'focuskw',
|
||||
'orderby' => 'meta_value',
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the score column.
|
||||
*
|
||||
* @param integer $post_id The ID of the post for which to show the score.
|
||||
* @param int $post_id The ID of the post for which to show the score.
|
||||
*
|
||||
* @return string The HTML for the SEO score indicator.
|
||||
*/
|
||||
|
|
@ -613,7 +642,7 @@ class WPSEO_Meta_Columns {
|
|||
|
||||
if ( WPSEO_Meta::get_value( 'focuskw', $post_id ) === '' ) {
|
||||
$rank = new WPSEO_Rank( WPSEO_Rank::NO_FOCUS );
|
||||
$title = __( 'Focus keyword not set.', 'wordpress-seo' );
|
||||
$title = __( 'Focus keyphrase not set.', 'wordpress-seo' );
|
||||
|
||||
return $this->render_score_indicator( $rank, $title );
|
||||
}
|
||||
|
|
@ -645,7 +674,7 @@ class WPSEO_Meta_Columns {
|
|||
private function set_post_type_hooks() {
|
||||
$post_types = WPSEO_Post_Type::get_accessible_post_types();
|
||||
|
||||
if ( ! is_array( $post_types ) || $post_types === array() ) {
|
||||
if ( ! is_array( $post_types ) || $post_types === [] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -654,18 +683,9 @@ class WPSEO_Meta_Columns {
|
|||
continue;
|
||||
}
|
||||
|
||||
add_filter( 'manage_' . $post_type . '_posts_columns', array( $this, 'column_heading' ), 10, 1 );
|
||||
add_action( 'manage_' . $post_type . '_posts_custom_column', array( $this, 'column_content' ), 10, 2 );
|
||||
add_action( 'manage_edit-' . $post_type . '_sortable_columns', array( $this, 'column_sort' ), 10, 2 );
|
||||
|
||||
/*
|
||||
* Use the `get_user_option_{$option}` filter to change the output of the get_user_option
|
||||
* function for the `manage{$screen}columnshidden` option, which is based on the current
|
||||
* admin screen. The admin screen we want to target is the `edit-{$post_type}` screen.
|
||||
*/
|
||||
$filter = sprintf( 'get_user_option_%s', sprintf( 'manage%scolumnshidden', 'edit-' . $post_type ) );
|
||||
|
||||
add_filter( $filter, array( $this, 'column_hidden' ), 10, 3 );
|
||||
add_filter( 'manage_' . $post_type . '_posts_columns', [ $this, 'column_heading' ], 10, 1 );
|
||||
add_action( 'manage_' . $post_type . '_posts_custom_column', [ $this, 'column_content' ], 10, 2 );
|
||||
add_action( 'manage_edit-' . $post_type . '_sortable_columns', [ $this, 'column_sort' ], 10, 2 );
|
||||
}
|
||||
|
||||
unset( $post_type );
|
||||
|
|
@ -677,7 +697,7 @@ class WPSEO_Meta_Columns {
|
|||
*
|
||||
* @since 7.0
|
||||
*
|
||||
* @param string $post_type Optional. The post type to test, defaults to the current post post_type.
|
||||
* @param string|null $post_type Optional. The post type to test, defaults to the current post post_type.
|
||||
*
|
||||
* @return bool Whether or not the meta box (and associated columns etc) should be hidden.
|
||||
*/
|
||||
|
|
@ -692,31 +712,8 @@ class WPSEO_Meta_Columns {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieve the page title.
|
||||
* Renders the score indicator.
|
||||
*
|
||||
* @param int $post_id Post to retrieve the title for.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function page_title( $post_id ) {
|
||||
$fixed_title = WPSEO_Meta::get_value( 'title', $post_id );
|
||||
if ( $fixed_title !== '' ) {
|
||||
return $fixed_title;
|
||||
}
|
||||
|
||||
$post = get_post( $post_id );
|
||||
|
||||
if ( is_object( $post ) && WPSEO_Options::get( 'title-' . $post->post_type, '' ) !== '' ) {
|
||||
$title_template = WPSEO_Options::get( 'title-' . $post->post_type );
|
||||
$title_template = str_replace( ' %%page%% ', ' ', $title_template );
|
||||
|
||||
return wpseo_replace_vars( $title_template, $post );
|
||||
}
|
||||
|
||||
return wpseo_replace_vars( '%%title%%', $post );
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
|
|
@ -727,7 +724,7 @@ class WPSEO_Meta_Columns {
|
|||
$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">' . $title . '</span>';
|
||||
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>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -745,7 +742,7 @@ class WPSEO_Meta_Columns {
|
|||
}
|
||||
|
||||
$screen = get_current_screen();
|
||||
if ( null === $screen ) {
|
||||
if ( $screen === null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,111 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Links
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the link count storage.
|
||||
*/
|
||||
class WPSEO_Meta_Storage implements WPSEO_Installable {
|
||||
|
||||
const TABLE_NAME = 'yoast_seo_meta';
|
||||
|
||||
/** @var WPSEO_Database_Proxy */
|
||||
protected $database_proxy;
|
||||
|
||||
/** @var null|string */
|
||||
protected $table_prefix;
|
||||
|
||||
/**
|
||||
* Sets the table prefix.
|
||||
*
|
||||
* @param string $table_prefix Optional. The prefix to use for the table.
|
||||
*/
|
||||
public function __construct( $table_prefix = null ) {
|
||||
if ( null === $table_prefix ) {
|
||||
$table_prefix = $GLOBALS['wpdb']->get_blog_prefix();
|
||||
}
|
||||
|
||||
$this->table_prefix = $table_prefix;
|
||||
$this->database_proxy = new WPSEO_Database_Proxy( $GLOBALS['wpdb'], $this->get_table_name(), true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the table name to use.
|
||||
*
|
||||
* @return string The table name.
|
||||
*/
|
||||
public function get_table_name() {
|
||||
return $this->table_prefix . self::TABLE_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the database table.
|
||||
*
|
||||
* @return boolean True if the table was created, false if something went wrong.
|
||||
*/
|
||||
public function install() {
|
||||
return $this->database_proxy->create_table(
|
||||
array(
|
||||
'object_id bigint(20) UNSIGNED NOT NULL',
|
||||
'internal_link_count int(10) UNSIGNED NULL DEFAULT NULL',
|
||||
'incoming_link_count int(10) UNSIGNED NULL DEFAULT NULL',
|
||||
),
|
||||
array(
|
||||
'UNIQUE KEY object_id (object_id)',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the link count to the database.
|
||||
*
|
||||
* @param int $meta_id The id to save the link count for.
|
||||
* @param array $meta_data The total amount of links.
|
||||
*/
|
||||
public function save_meta_data( $meta_id, array $meta_data ) {
|
||||
$where = array( 'object_id' => $meta_id );
|
||||
|
||||
$saved = $this->database_proxy->upsert(
|
||||
array_merge( $where, $meta_data ),
|
||||
$where
|
||||
);
|
||||
|
||||
if ( $saved === false ) {
|
||||
WPSEO_Meta_Table_Accessible::set_inaccessible();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the incoming link count
|
||||
*
|
||||
* @param array $post_ids The posts to update the incoming link count for.
|
||||
* @param WPSEO_Link_Storage $storage The link storage object.
|
||||
*/
|
||||
public function update_incoming_link_count( array $post_ids, WPSEO_Link_Storage $storage ) {
|
||||
global $wpdb;
|
||||
|
||||
$query = $wpdb->prepare( '
|
||||
SELECT COUNT( id ) AS incoming, target_post_id AS post_id
|
||||
FROM ' . $storage->get_table_name() . '
|
||||
WHERE target_post_id IN(' . implode( ',', array_fill( 0, count( $post_ids ), '%d' ) ) . ')
|
||||
GROUP BY target_post_id',
|
||||
$post_ids
|
||||
);
|
||||
|
||||
$results = $wpdb->get_results( $query );
|
||||
|
||||
$post_ids_non_zero = array();
|
||||
foreach ( $results as $result ) {
|
||||
$this->save_meta_data( $result->post_id, array( 'incoming_link_count' => $result->incoming ) );
|
||||
$post_ids_non_zero[] = $result->post_id;
|
||||
}
|
||||
|
||||
$post_ids_zero = array_diff( $post_ids, $post_ids_non_zero );
|
||||
foreach ( $post_ids_zero as $post_id ) {
|
||||
$this->save_meta_data( $post_id, array( 'incoming_link_count' => 0 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Links
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the state of the table being accessible.
|
||||
*/
|
||||
class WPSEO_Meta_Table_Accessible {
|
||||
|
||||
const ACCESSIBLE = '0';
|
||||
const INACCESSBILE = '1';
|
||||
|
||||
/**
|
||||
* Checks if the given table name exists.
|
||||
*
|
||||
* @return bool True when table is accessible.
|
||||
*/
|
||||
public static function is_accessible() {
|
||||
$value = get_transient( self::transient_name() );
|
||||
|
||||
// If the value is not set, check the table.
|
||||
if ( false === $value ) {
|
||||
return self::check_table();
|
||||
}
|
||||
|
||||
return $value === self::ACCESSIBLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transient value to 1, to indicate the table is not accessible.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function set_inaccessible() {
|
||||
set_transient( self::transient_name(), self::INACCESSBILE, HOUR_IN_SECONDS );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the transient.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function cleanup() {
|
||||
delete_transient( self::transient_name() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transient value to 0, to indicate the table is accessible.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function set_accessible() {
|
||||
/*
|
||||
* Prefer to set a 0 timeout, but if the timeout was set before WordPress will not delete the transient
|
||||
* correctly when overridden with a zero value.
|
||||
*
|
||||
* Setting a YEAR_IN_SECONDS instead.
|
||||
*/
|
||||
set_transient( self::transient_name(), self::ACCESSIBLE, YEAR_IN_SECONDS );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the table exists if not, set the transient to indicate the inaccessible table.
|
||||
*
|
||||
* @return bool True if table is accessible.
|
||||
*/
|
||||
protected static function check_table() {
|
||||
global $wpdb;
|
||||
|
||||
$storage = new WPSEO_Meta_Storage();
|
||||
if ( $wpdb->get_var( 'SHOW TABLES LIKE "' . $storage->get_table_name() . '"' ) !== $storage->get_table_name() ) {
|
||||
self::set_inaccessible();
|
||||
return false;
|
||||
}
|
||||
|
||||
self::set_accessible();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the transient.
|
||||
*
|
||||
* @return string The name of the transient to use.
|
||||
*/
|
||||
protected static function transient_name() {
|
||||
return 'wpseo_meta_table_inaccessible';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the table exists if not, set the transient to indicate the inaccessible table.
|
||||
*
|
||||
* @deprecated 6.0
|
||||
*
|
||||
* @return bool True if table is accessible.
|
||||
*/
|
||||
public static function check_table_is_accessible() {
|
||||
_deprecated_function( __FUNCTION__, '6.0', __CLASS__ . '::is_accessible' );
|
||||
return self::is_accessible();
|
||||
}
|
||||
}
|
||||
209
wp-content/plugins/wordpress-seo/admin/class-my-yoast-proxy.php
Normal file
209
wp-content/plugins/wordpress-seo/admin/class-my-yoast-proxy.php
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Loads the MyYoast proxy.
|
||||
*
|
||||
* This class registers a proxy page on `admin.php`. Which is reached with the `page=PAGE_IDENTIFIER` parameter.
|
||||
* It will read external files and serves them like they are located locally.
|
||||
*/
|
||||
class WPSEO_MyYoast_Proxy implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* The page identifier used in WordPress to register the MyYoast proxy page.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PAGE_IDENTIFIER = 'wpseo_myyoast_proxy';
|
||||
|
||||
/**
|
||||
* The cache control's max age. Used in the header of a successful proxy response.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const CACHE_CONTROL_MAX_AGE = DAY_IN_SECONDS;
|
||||
|
||||
/**
|
||||
* Registers the hooks when the user is on the right page.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
if ( ! $this->is_proxy_page() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register the page for the proxy.
|
||||
add_action( 'admin_menu', [ $this, 'add_proxy_page' ] );
|
||||
add_action( 'admin_init', [ $this, 'handle_proxy_page' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the proxy page. It does not actually add a link to the dashboard.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_proxy_page() {
|
||||
add_dashboard_page( '', '', 'read', self::PAGE_IDENTIFIER, '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the requested proxy page and exits to prevent the WordPress UI from loading.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_proxy_page() {
|
||||
$this->render_proxy_page();
|
||||
|
||||
// Prevent the WordPress UI from loading.
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the requested proxy page.
|
||||
*
|
||||
* This is separated from the exits to be able to test it.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function render_proxy_page() {
|
||||
$proxy_options = $this->determine_proxy_options();
|
||||
if ( $proxy_options === [] ) {
|
||||
// Do not accept any other file than implemented.
|
||||
$this->set_header( 'HTTP/1.0 501 Requested file not implemented' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the headers before serving the remote file.
|
||||
$this->set_header( 'Content-Type: ' . $proxy_options['content_type'] );
|
||||
$this->set_header( 'Cache-Control: max-age=' . self::CACHE_CONTROL_MAX_AGE );
|
||||
|
||||
try {
|
||||
echo $this->get_remote_url_body( $proxy_options['url'] );
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
/*
|
||||
* Reset the file headers because the loading failed.
|
||||
*
|
||||
* Note: Due to supporting PHP 5.2 `header_remove` can not be used here.
|
||||
* Overwrite the headers instead.
|
||||
*/
|
||||
$this->set_header( 'Content-Type: text/plain' );
|
||||
$this->set_header( 'Cache-Control: max-age=0' );
|
||||
|
||||
$this->set_header( 'HTTP/1.0 500 ' . $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to load the given url via `wp_remote_get`.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param string $url The url to load.
|
||||
*
|
||||
* @return string The body of the response.
|
||||
*
|
||||
* @throws Exception When `wp_remote_get` returned an error.
|
||||
* @throws Exception When the response code is not 200.
|
||||
*/
|
||||
protected function get_remote_url_body( $url ) {
|
||||
$response = wp_remote_get( $url );
|
||||
|
||||
if ( $response instanceof WP_Error ) {
|
||||
throw new Exception( 'Unable to retrieve file from MyYoast' );
|
||||
}
|
||||
|
||||
if ( wp_remote_retrieve_response_code( $response ) !== 200 ) {
|
||||
throw new Exception( 'Received unexpected response from MyYoast' );
|
||||
}
|
||||
|
||||
return wp_remote_retrieve_body( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the proxy options based on the file and plugin version arguments.
|
||||
*
|
||||
* When the file is known it returns an array like this:
|
||||
* <code>
|
||||
* $array = array(
|
||||
* 'content_type' => 'the content type'
|
||||
* 'url' => 'the url, possibly with the plugin version'
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* @return array Empty for an unknown file. See format above for known files.
|
||||
*/
|
||||
protected function determine_proxy_options() {
|
||||
if ( $this->get_proxy_file() === 'research-webworker' ) {
|
||||
return [
|
||||
'content_type' => 'text/javascript; charset=UTF-8',
|
||||
'url' => 'https://my.yoast.com/api/downloads/file/analysis-worker?plugin_version=' . $this->get_plugin_version(),
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current page is the MyYoast proxy page.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the proxy file from the HTTP request parameters.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return string The sanitized file request parameter.
|
||||
*/
|
||||
protected function get_proxy_file() {
|
||||
return filter_input( INPUT_GET, 'file', FILTER_SANITIZE_STRING );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin version from the HTTP request parameters.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return string The sanitized plugin_version request parameter.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the HTTP header.
|
||||
*
|
||||
* This is a tiny helper function to enable better testing.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param string $header The header to set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function set_header( $header ) {
|
||||
header( $header );
|
||||
}
|
||||
}
|
||||
|
|
@ -6,17 +6,29 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Option_Tab
|
||||
* Class WPSEO_Option_Tab.
|
||||
*/
|
||||
class WPSEO_Option_Tab {
|
||||
|
||||
/** @var string Name of the tab */
|
||||
/**
|
||||
* Name of the tab.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/** @var string Label of the tab */
|
||||
/**
|
||||
* Label of the tab.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $label;
|
||||
|
||||
/** @var array Optional arguments */
|
||||
/**
|
||||
* Optional arguments.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $arguments;
|
||||
|
||||
/**
|
||||
|
|
@ -26,7 +38,7 @@ class WPSEO_Option_Tab {
|
|||
* @param string $label Localized label of the tab.
|
||||
* @param array $arguments Optional arguments.
|
||||
*/
|
||||
public function __construct( $name, $label, array $arguments = array() ) {
|
||||
public function __construct( $name, $label, array $arguments = [] ) {
|
||||
$this->name = sanitize_title( $name );
|
||||
$this->label = $label;
|
||||
$this->arguments = $arguments;
|
||||
|
|
@ -50,15 +62,6 @@ class WPSEO_Option_Tab {
|
|||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the video URL.
|
||||
*
|
||||
* @return string The video url.
|
||||
*/
|
||||
public function get_video_url() {
|
||||
return $this->get_argument( 'video_url' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves whether the tab needs a save button.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Option_Tabs_Formatter
|
||||
* Class WPSEO_Option_Tabs_Formatter.
|
||||
*/
|
||||
class WPSEO_Option_Tabs_Formatter {
|
||||
|
||||
/**
|
||||
* Retrieves the path to the view of the tab.
|
||||
*
|
||||
* @param WPSEO_Option_Tabs $option_tabs Option Tabs to get base from.
|
||||
* @param WPSEO_Option_Tab $tab Tab to get name from.
|
||||
*
|
||||
|
|
@ -21,6 +23,8 @@ class WPSEO_Option_Tabs_Formatter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Outputs the option tabs.
|
||||
*
|
||||
* @param WPSEO_Option_Tabs $option_tabs Option Tabs to get tabs from.
|
||||
*/
|
||||
public function run( WPSEO_Option_Tabs $option_tabs ) {
|
||||
|
|
@ -36,21 +40,37 @@ class WPSEO_Option_Tabs_Formatter {
|
|||
}
|
||||
echo '</h2>';
|
||||
|
||||
$help_center = new WPSEO_Help_Center( '', $option_tabs, WPSEO_Utils::is_yoast_seo_premium() );
|
||||
$help_center->localize_data();
|
||||
$help_center->mount();
|
||||
|
||||
foreach ( $option_tabs->get_tabs() as $tab ) {
|
||||
$identifier = $tab->get_name();
|
||||
|
||||
$class = 'wpseotab ' . ( $tab->has_save_button() ? 'save' : 'nosave' );
|
||||
printf( '<div id="%1$s" class="%2$s">', esc_attr( $identifier ), esc_attr( $class ) );
|
||||
|
||||
// Output the settings view for all tabs.
|
||||
$tab_view = $this->get_tab_view( $option_tabs, $tab );
|
||||
if ( is_file( $tab_view ) ) {
|
||||
$yform = Yoast_Form::get_instance();
|
||||
require_once $tab_view;
|
||||
$tab_filter_name = sprintf( '%s_%s', $option_tabs->get_base(), $tab->get_name() );
|
||||
|
||||
/**
|
||||
* Allows to override the content that is display on the specific option tab.
|
||||
*
|
||||
* @internal For internal Yoast SEO use only.
|
||||
*
|
||||
* @api string|null The content that should be displayed for this tab. Leave empty for default behaviour.
|
||||
*
|
||||
* @param WPSEO_Option_Tabs $option_tabs The registered option tabs.
|
||||
* @param WPSEO_Option_Tab $tab The tab that is being displayed.
|
||||
*/
|
||||
$option_tab_content = apply_filters( 'wpseo_option_tab-' . $tab_filter_name, null, $option_tabs, $tab );
|
||||
if ( ! empty( $option_tab_content ) ) {
|
||||
echo wp_kses_post( $option_tab_content );
|
||||
}
|
||||
|
||||
if ( empty( $option_tab_content ) ) {
|
||||
// Output the settings view for all tabs.
|
||||
$tab_view = $this->get_tab_view( $option_tabs, $tab );
|
||||
|
||||
if ( is_file( $tab_view ) ) {
|
||||
$yform = Yoast_Form::get_instance();
|
||||
require $tab_view;
|
||||
}
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
|
|
|
|||
|
|
@ -6,22 +6,36 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Option_Tabs
|
||||
* Class WPSEO_Option_Tabs.
|
||||
*/
|
||||
class WPSEO_Option_Tabs {
|
||||
|
||||
/** @var string Tabs base */
|
||||
/**
|
||||
* Tabs base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $base;
|
||||
|
||||
/** @var array The tabs in this group */
|
||||
private $tabs = array();
|
||||
/**
|
||||
* The tabs in this group.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $tabs = [];
|
||||
|
||||
/** @var string Name of the active tab */
|
||||
/**
|
||||
* Name of the active tab.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $active_tab = '';
|
||||
|
||||
/**
|
||||
* WPSEO_Option_Tabs constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param string $base Base of the tabs.
|
||||
* @param string $active_tab Currently active tab.
|
||||
*/
|
||||
|
|
@ -33,7 +47,7 @@ class WPSEO_Option_Tabs {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the base
|
||||
* Get the base.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
|
@ -42,7 +56,7 @@ class WPSEO_Option_Tabs {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a tab
|
||||
* Add a tab.
|
||||
*
|
||||
* @param WPSEO_Option_Tab $tab Tab to add.
|
||||
*
|
||||
|
|
@ -55,16 +69,16 @@ class WPSEO_Option_Tabs {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get active tab
|
||||
* Get active tab.
|
||||
*
|
||||
* @return null|WPSEO_Option_Tab Get the active tab.
|
||||
* @return WPSEO_Option_Tab|null Get the active tab.
|
||||
*/
|
||||
public function get_active_tab() {
|
||||
if ( empty( $this->active_tab ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$active_tabs = array_filter( $this->tabs, array( $this, 'is_active_tab' ) );
|
||||
$active_tabs = array_filter( $this->tabs, [ $this, 'is_active_tab' ] );
|
||||
if ( ! empty( $active_tabs ) ) {
|
||||
$active_tabs = array_values( $active_tabs );
|
||||
if ( count( $active_tabs ) === 1 ) {
|
||||
|
|
@ -76,7 +90,7 @@ class WPSEO_Option_Tabs {
|
|||
}
|
||||
|
||||
/**
|
||||
* Is the tab the active tab
|
||||
* Is the tab the active tab.
|
||||
*
|
||||
* @param WPSEO_Option_Tab $tab Tab to check for active tab.
|
||||
*
|
||||
|
|
@ -87,7 +101,7 @@ class WPSEO_Option_Tabs {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all tabs
|
||||
* Get all tabs.
|
||||
*
|
||||
* @return WPSEO_Option_Tab[]
|
||||
*/
|
||||
|
|
@ -96,9 +110,9 @@ class WPSEO_Option_Tabs {
|
|||
}
|
||||
|
||||
/**
|
||||
* Display the tabs
|
||||
* Display the tabs.
|
||||
*
|
||||
* @param Yoast_Form $yform Yoast Form needed in the views.
|
||||
* @param Yoast_Form $yform Yoast Form needed in the views.
|
||||
*/
|
||||
public function display( Yoast_Form $yform ) {
|
||||
$formatter = new WPSEO_Option_Tabs_Formatter();
|
||||
|
|
|
|||
141
wp-content/plugins/wordpress-seo/admin/class-paper-presenter.php
Normal file
141
wp-content/plugins/wordpress-seo/admin/class-paper-presenter.php
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_presenter_paper.
|
||||
*/
|
||||
class WPSEO_Paper_Presenter {
|
||||
|
||||
/**
|
||||
* Title of the paper.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* The view variables.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* The path to the view file.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $view_file;
|
||||
|
||||
/**
|
||||
* WPSEO_presenter_paper constructor.
|
||||
*
|
||||
* @param string $title The title of the paper.
|
||||
* @param string|null $view_file Optional. The path to the view file. Use the content setting
|
||||
* if do not wish to use a view file.
|
||||
* @param array $settings Optional. Settings for the paper.
|
||||
*/
|
||||
public function __construct( $title, $view_file = null, array $settings = [] ) {
|
||||
$defaults = [
|
||||
'paper_id' => null,
|
||||
'paper_id_prefix' => 'wpseo-',
|
||||
'collapsible' => false,
|
||||
'collapsible_header_class' => '',
|
||||
'expanded' => false,
|
||||
'help_text' => '',
|
||||
'title_after' => '',
|
||||
'class' => '',
|
||||
'content' => '',
|
||||
'view_data' => [],
|
||||
];
|
||||
|
||||
$this->settings = wp_parse_args( $settings, $defaults );
|
||||
$this->title = $title;
|
||||
$this->view_file = $view_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the collapsible paper and returns it as a string.
|
||||
*
|
||||
* @return string The rendered paper.
|
||||
*/
|
||||
public function get_output() {
|
||||
$view_variables = $this->get_view_variables();
|
||||
|
||||
extract( $view_variables, EXTR_SKIP );
|
||||
|
||||
$content = $this->settings['content'];
|
||||
|
||||
if ( $this->view_file !== null ) {
|
||||
ob_start();
|
||||
require $this->view_file;
|
||||
$content = ob_get_clean();
|
||||
}
|
||||
|
||||
ob_start();
|
||||
require WPSEO_PATH . 'admin/views/paper-collapsible.php';
|
||||
$rendered_output = ob_get_clean();
|
||||
|
||||
return $rendered_output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the view variables.
|
||||
*
|
||||
* @return array The view variables.
|
||||
*/
|
||||
private function get_view_variables() {
|
||||
if ( $this->settings['help_text'] instanceof WPSEO_Admin_Help_Panel === false ) {
|
||||
$this->settings['help_text'] = new WPSEO_Admin_Help_Panel( '', '', '' );
|
||||
}
|
||||
|
||||
$view_variables = [
|
||||
'class' => $this->settings['class'],
|
||||
'collapsible' => $this->settings['collapsible'],
|
||||
'collapsible_config' => $this->collapsible_config(),
|
||||
'collapsible_header_class' => $this->settings['collapsible_header_class'],
|
||||
'title_after' => $this->settings['title_after'],
|
||||
'help_text' => $this->settings['help_text'],
|
||||
'view_file' => $this->view_file,
|
||||
'title' => $this->title,
|
||||
'paper_id' => $this->settings['paper_id'],
|
||||
'paper_id_prefix' => $this->settings['paper_id_prefix'],
|
||||
'yform' => Yoast_Form::get_instance(),
|
||||
];
|
||||
|
||||
return array_merge( $this->settings['view_data'], $view_variables );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the collapsible config based on the settings.
|
||||
*
|
||||
* @return array The config.
|
||||
*/
|
||||
protected function collapsible_config() {
|
||||
if ( empty( $this->settings['collapsible'] ) ) {
|
||||
return [
|
||||
'toggle_icon' => '',
|
||||
'class' => '',
|
||||
'expanded' => '',
|
||||
];
|
||||
}
|
||||
|
||||
if ( ! empty( $this->settings['expanded'] ) ) {
|
||||
return [
|
||||
'toggle_icon' => 'dashicons-arrow-up-alt2',
|
||||
'class' => 'toggleable-container',
|
||||
'expanded' => 'true',
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'toggle_icon' => 'dashicons-arrow-down-alt2',
|
||||
'class' => 'toggleable-container toggleable-container-hidden',
|
||||
'expanded' => 'false',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -11,9 +11,11 @@
|
|||
class WPSEO_Plugin_Availability {
|
||||
|
||||
/**
|
||||
* Holds the plugins.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $plugins = array();
|
||||
protected $plugins = [];
|
||||
|
||||
/**
|
||||
* Registers the plugins so we can access them.
|
||||
|
|
@ -27,8 +29,8 @@ class WPSEO_Plugin_Availability {
|
|||
* Registers all the available Yoast SEO plugins.
|
||||
*/
|
||||
protected function register_yoast_plugins() {
|
||||
$this->plugins = array(
|
||||
'yoast-seo-premium' => array(
|
||||
$this->plugins = [
|
||||
'yoast-seo-premium' => [
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/1y7' ),
|
||||
'title' => 'Yoast SEO Premium',
|
||||
'description' => sprintf(
|
||||
|
|
@ -40,9 +42,9 @@ class WPSEO_Plugin_Availability {
|
|||
'slug' => 'wordpress-seo-premium/wp-seo-premium.php',
|
||||
'version_sync' => true,
|
||||
'premium' => true,
|
||||
),
|
||||
],
|
||||
|
||||
'video-seo-for-wordpress-seo-by-yoast' => array(
|
||||
'video-seo-for-wordpress-seo-by-yoast' => [
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/1y8' ),
|
||||
'title' => 'Video SEO',
|
||||
'description' => __( 'Optimize your videos to show them off in search results and get more clicks!', 'wordpress-seo' ),
|
||||
|
|
@ -50,9 +52,9 @@ class WPSEO_Plugin_Availability {
|
|||
'slug' => 'wpseo-video/video-seo.php',
|
||||
'version_sync' => true,
|
||||
'premium' => true,
|
||||
),
|
||||
],
|
||||
|
||||
'yoast-news-seo' => array(
|
||||
'yoast-news-seo' => [
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/1y9' ),
|
||||
'title' => 'News SEO',
|
||||
'description' => __( 'Are you in Google News? Increase your traffic from Google News by optimizing for it!', 'wordpress-seo' ),
|
||||
|
|
@ -60,9 +62,9 @@ class WPSEO_Plugin_Availability {
|
|||
'slug' => 'wpseo-news/wpseo-news.php',
|
||||
'version_sync' => true,
|
||||
'premium' => true,
|
||||
),
|
||||
],
|
||||
|
||||
'local-seo-for-yoast-seo' => array(
|
||||
'local-seo-for-yoast-seo' => [
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/1ya' ),
|
||||
'title' => 'Local SEO',
|
||||
'description' => __( 'Rank better locally and in Google Maps, without breaking a sweat!', 'wordpress-seo' ),
|
||||
|
|
@ -70,9 +72,9 @@ class WPSEO_Plugin_Availability {
|
|||
'slug' => 'wordpress-seo-local/local-seo.php',
|
||||
'version_sync' => true,
|
||||
'premium' => true,
|
||||
),
|
||||
],
|
||||
|
||||
'yoast-woocommerce-seo' => array(
|
||||
'yoast-woocommerce-seo' => [
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/1o0' ),
|
||||
'title' => 'Yoast WooCommerce SEO',
|
||||
'description' => sprintf(
|
||||
|
|
@ -80,53 +82,17 @@ class WPSEO_Plugin_Availability {
|
|||
__( 'Seamlessly integrate WooCommerce with %1$s and get extra features!', 'wordpress-seo' ),
|
||||
'Yoast SEO'
|
||||
),
|
||||
'_dependencies' => array(
|
||||
'WooCommerce' => array(
|
||||
'_dependencies' => [
|
||||
'WooCommerce' => [
|
||||
'slug' => 'woocommerce/woocommerce.php',
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
'installed' => false,
|
||||
'slug' => 'wpseo-woocommerce/wpseo-woocommerce.php',
|
||||
'version_sync' => true,
|
||||
'premium' => true,
|
||||
),
|
||||
|
||||
'yoast-acf-analysis' => array(
|
||||
'url' => 'https://wordpress.org/plugins/acf-content-analysis-for-yoast-seo/',
|
||||
'title' => 'ACF Content Analysis for Yoast SEO',
|
||||
'description' => sprintf(
|
||||
/* translators: %1$s expands to Yoast SEO, %2$s expands to Advanced Custom Fields */
|
||||
__( 'Seamlessly integrate %2$s with %1$s for the content analysis!', 'wordpress-seo' ),
|
||||
'Yoast SEO',
|
||||
'Advanced Custom Fields'
|
||||
),
|
||||
'installed' => false,
|
||||
'slug' => 'acf-content-analysis-for-yoast-seo/yoast-acf-analysis.php',
|
||||
'_dependencies' => array(
|
||||
'Advanced Custom Fields' => array(
|
||||
'slug' => 'advanced-custom-fields/acf.php',
|
||||
),
|
||||
),
|
||||
'version_sync' => false,
|
||||
),
|
||||
|
||||
'yoastseo-amp' => array(
|
||||
'url' => 'https://wordpress.org/plugins/glue-for-yoast-seo-amp/',
|
||||
'title' => 'Yoast SEO AMP Glue',
|
||||
'description' => sprintf(
|
||||
/* translators: %1$s expands to Yoast SEO */
|
||||
__( 'Seamlessly integrate %1$s into your AMP pages!', 'wordpress-seo' ), 'Yoast SEO'
|
||||
),
|
||||
'installed' => false,
|
||||
'slug' => 'glue-for-yoast-seo-amp/yoastseo-amp.php',
|
||||
'_dependencies' => array(
|
||||
'AMP' => array(
|
||||
'slug' => 'amp/amp.php',
|
||||
),
|
||||
),
|
||||
'version_sync' => false,
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -151,7 +117,7 @@ class WPSEO_Plugin_Availability {
|
|||
/**
|
||||
* Checks whether or not a plugin is known within the Yoast SEO collection.
|
||||
*
|
||||
* @param {string} $plugin The plugin to search for.
|
||||
* @param string $plugin The plugin to search for.
|
||||
*
|
||||
* @return bool Whether or not the plugin is exists.
|
||||
*/
|
||||
|
|
@ -171,13 +137,13 @@ class WPSEO_Plugin_Availability {
|
|||
/**
|
||||
* Gets a specific plugin. Returns an empty array if it cannot be found.
|
||||
*
|
||||
* @param {string} $plugin The plugin to search for.
|
||||
* @param string $plugin The plugin to search for.
|
||||
*
|
||||
* @return array The plugin properties.
|
||||
*/
|
||||
public function get_plugin( $plugin ) {
|
||||
if ( ! $this->plugin_exists( $plugin ) ) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->plugins[ $plugin ];
|
||||
|
|
@ -186,7 +152,7 @@ class WPSEO_Plugin_Availability {
|
|||
/**
|
||||
* Gets the version of the plugin.
|
||||
*
|
||||
* @param {string} $plugin The plugin to search for.
|
||||
* @param array $plugin The information available about the plugin.
|
||||
*
|
||||
* @return string The version associated with the plugin.
|
||||
*/
|
||||
|
|
@ -201,7 +167,7 @@ class WPSEO_Plugin_Availability {
|
|||
/**
|
||||
* Checks if there are dependencies available for the plugin.
|
||||
*
|
||||
* @param {string} $plugin The plugin to search for.
|
||||
* @param array $plugin The information available about the plugin.
|
||||
*
|
||||
* @return bool Whether or not there is a dependency present.
|
||||
*/
|
||||
|
|
@ -212,13 +178,13 @@ class WPSEO_Plugin_Availability {
|
|||
/**
|
||||
* Gets the dependencies for the plugin.
|
||||
*
|
||||
* @param {string} $plugin The plugin to search for.
|
||||
* @param array $plugin The information available about the plugin.
|
||||
*
|
||||
* @return array Array containing all the dependencies associated with the plugin.
|
||||
*/
|
||||
public function get_dependencies( $plugin ) {
|
||||
if ( ! $this->has_dependencies( $plugin ) ) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
return $plugin['_dependencies'];
|
||||
|
|
@ -227,7 +193,7 @@ class WPSEO_Plugin_Availability {
|
|||
/**
|
||||
* Checks if all dependencies are satisfied.
|
||||
*
|
||||
* @param {string} $plugin The plugin to search for.
|
||||
* @param array $plugin The information available about the plugin.
|
||||
*
|
||||
* @return bool Whether or not the dependencies are satisfied.
|
||||
*/
|
||||
|
|
@ -237,7 +203,7 @@ class WPSEO_Plugin_Availability {
|
|||
}
|
||||
|
||||
$dependencies = $this->get_dependencies( $plugin );
|
||||
$installed_dependencies = array_filter( $dependencies, array( $this, 'is_dependency_available' ) );
|
||||
$installed_dependencies = array_filter( $dependencies, [ $this, 'is_dependency_available' ] );
|
||||
|
||||
return count( $installed_dependencies ) === count( $dependencies );
|
||||
}
|
||||
|
|
@ -245,7 +211,7 @@ class WPSEO_Plugin_Availability {
|
|||
/**
|
||||
* Checks whether or not one of the plugins is properly installed and usable.
|
||||
*
|
||||
* @param {string} $plugin The plugin to search for.
|
||||
* @param array $plugin The information available about the plugin.
|
||||
*
|
||||
* @return bool Whether or not the plugin is properly installed.
|
||||
*/
|
||||
|
|
@ -263,7 +229,7 @@ class WPSEO_Plugin_Availability {
|
|||
* @return array The installed plugins.
|
||||
*/
|
||||
public function get_installed_plugins() {
|
||||
$installed = array();
|
||||
$installed = [];
|
||||
|
||||
foreach ( $this->plugins as $plugin_key => $plugin ) {
|
||||
if ( $this->is_installed( $plugin ) ) {
|
||||
|
|
@ -277,7 +243,7 @@ class WPSEO_Plugin_Availability {
|
|||
/**
|
||||
* Checks for the availability of the plugin.
|
||||
*
|
||||
* @param {string} $plugin The plugin to search for.
|
||||
* @param array $plugin The information available about the plugin.
|
||||
*
|
||||
* @return bool Whether or not the plugin is available.
|
||||
*/
|
||||
|
|
@ -288,12 +254,12 @@ class WPSEO_Plugin_Availability {
|
|||
/**
|
||||
* Checks whether a dependency is available.
|
||||
*
|
||||
* @param {string} $dependency The dependency to look for.
|
||||
* @param array $dependency The information about the dependency to look for.
|
||||
*
|
||||
* @return bool Whether or not the dependency is available.
|
||||
*/
|
||||
public function is_dependency_available( $dependency ) {
|
||||
return in_array( $dependency['slug'], array_keys( get_plugins() ), true );
|
||||
return isset( get_plugins()[ $dependency['slug'] ] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -305,7 +271,7 @@ class WPSEO_Plugin_Availability {
|
|||
*/
|
||||
public function get_dependency_names( $plugin ) {
|
||||
if ( ! $this->has_dependencies( $plugin ) ) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
return array_keys( $plugin['_dependencies'] );
|
||||
|
|
@ -317,7 +283,7 @@ class WPSEO_Plugin_Availability {
|
|||
* @return array Array of the plugins that have dependencies.
|
||||
*/
|
||||
public function get_plugins_with_dependencies() {
|
||||
return array_filter( $this->plugins, array( $this, 'has_dependencies' ) );
|
||||
return array_filter( $this->plugins, [ $this, 'has_dependencies' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,109 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Plugin_Compatibility
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Plugin_Compatibility
|
||||
*/
|
||||
class WPSEO_Plugin_Compatibility {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $current_wpseo_version;
|
||||
|
||||
/**
|
||||
* @var WPSEO_Plugin_Availability
|
||||
*/
|
||||
protected $availability_checker;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $installed_plugins;
|
||||
|
||||
/**
|
||||
* WPSEO_Plugin_Compatibility constructor.
|
||||
*
|
||||
* @param string $version The version to check against.
|
||||
* @param null|class $availability_checker The checker to use.
|
||||
*/
|
||||
public function __construct( $version, $availability_checker = null ) {
|
||||
// We trim off the patch version, as this shouldn't break the comparison.
|
||||
$this->current_wpseo_version = $this->get_major_minor_version( $version );
|
||||
$this->availability_checker = $this->retrieve_availability_checker( $availability_checker );
|
||||
$this->installed_plugins = $this->availability_checker->get_installed_plugins();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the availability checker.
|
||||
*
|
||||
* @param null|object $checker The checker to set.
|
||||
*
|
||||
* @return WPSEO_Plugin_Availability The checker to use.
|
||||
*/
|
||||
private function retrieve_availability_checker( $checker ) {
|
||||
if ( is_null( $checker ) || ! is_object( $checker ) ) {
|
||||
$checker = new WPSEO_Plugin_Availability();
|
||||
$checker->register();
|
||||
}
|
||||
|
||||
return $checker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the availability checker's get_installed_plugins method.
|
||||
*
|
||||
* @return array Array containing all the installed plugins.
|
||||
*/
|
||||
public function get_installed_plugins() {
|
||||
return $this->installed_plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of installed plugins and whether or not they are compatible.
|
||||
*
|
||||
* @return array Array containing the installed plugins and compatibility.
|
||||
*/
|
||||
public function get_installed_plugins_compatibility() {
|
||||
foreach ( $this->installed_plugins as $key => $plugin ) {
|
||||
|
||||
$this->installed_plugins[ $key ]['compatible'] = $this->is_compatible( $key );
|
||||
}
|
||||
|
||||
return $this->installed_plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not a plugin is compatible.
|
||||
*
|
||||
* @param string $plugin The plugin to look for and match.
|
||||
*
|
||||
* @return bool Whether or not the plugin is compatible.
|
||||
*/
|
||||
public function is_compatible( $plugin ) {
|
||||
$plugin = $this->availability_checker->get_plugin( $plugin );
|
||||
|
||||
// If we are not syncing versions, we are always compatible.
|
||||
if ( ! isset( $plugin['version_sync'] ) || $plugin['version_sync'] !== true ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$plugin_version = $this->availability_checker->get_version( $plugin );
|
||||
return $this->get_major_minor_version( $plugin_version ) === $this->current_wpseo_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the major/minor version of the plugin for easier comparing.
|
||||
*
|
||||
* @param string $version The version to trim.
|
||||
*
|
||||
* @return string The major/minor version of the plugin.
|
||||
*/
|
||||
protected function get_major_minor_version( $version ) {
|
||||
return substr( $version, 0, 3 );
|
||||
}
|
||||
}
|
||||
|
|
@ -18,9 +18,9 @@ class WPSEO_Plugin_Conflict extends Yoast_Plugin_Conflict {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $plugins = array(
|
||||
protected $plugins = [
|
||||
// The plugin which are writing OG metadata.
|
||||
'open_graph' => array(
|
||||
'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.
|
||||
|
|
@ -43,7 +43,6 @@ class WPSEO_Plugin_Conflict extends Yoast_Plugin_Conflict {
|
|||
'open-graph-protocol-framework/open-graph-protocol-framework.php',
|
||||
// Open Graph Protocol Framework.
|
||||
'seo-facebook-comments/seofacebook.php', // SEO Facebook Comments.
|
||||
'seo-ultimate/seo-ultimate.php', // SEO Ultimate.
|
||||
'sexybookmarks/sexy-bookmarks.php', // Shareaholic.
|
||||
'shareaholic/sexy-bookmarks.php', // Shareaholic.
|
||||
'sharepress/sharepress.php', // SharePress.
|
||||
|
|
@ -61,8 +60,8 @@ class WPSEO_Plugin_Conflict extends Yoast_Plugin_Conflict {
|
|||
'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' => array(
|
||||
],
|
||||
'xml_sitemaps' => [
|
||||
'google-sitemap-plugin/google-sitemap-plugin.php',
|
||||
// Google Sitemap (BestWebSoft).
|
||||
'xml-sitemaps/xml-sitemaps.php',
|
||||
|
|
@ -93,17 +92,22 @@ class WPSEO_Plugin_Conflict extends Yoast_Plugin_Conflict {
|
|||
// Sewn In XML Sitemap (jcow).
|
||||
'rps-sitemap-generator/rps-sitemap-generator.php',
|
||||
// RPS Sitemap Generator (redpixelstudios).
|
||||
),
|
||||
'cloaking' => array(
|
||||
],
|
||||
'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.
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Overrides instance to set with this class as class
|
||||
* Overrides instance to set with this class as class.
|
||||
*
|
||||
* @param string $class_name Optional class name.
|
||||
*
|
||||
|
|
@ -131,16 +135,16 @@ class WPSEO_Plugin_Conflict extends Yoast_Plugin_Conflict {
|
|||
$instance->add_active_plugin( $instance->find_plugin_category( $plugin ), $plugin );
|
||||
}
|
||||
|
||||
$plugin_sections = array();
|
||||
$plugin_sections = [];
|
||||
|
||||
// Only check for open graph problems when they are enabled.
|
||||
if ( WPSEO_Options::get( 'opengraph' ) ) {
|
||||
/* 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 OpenGraph 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' )
|
||||
/* 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' ) . '">'
|
||||
/* translators: %1$s expands to Yoast SEO. */
|
||||
. sprintf( __( 'Configure %1$s\'s OpenGraph settings', 'wordpress-seo' ), 'Yoast SEO' )
|
||||
. sprintf( __( 'Configure %1$s\'s Open Graph settings', 'wordpress-seo' ), 'Yoast SEO' )
|
||||
. '</a>';
|
||||
}
|
||||
|
||||
|
|
@ -158,6 +162,9 @@ class WPSEO_Plugin_Conflict extends Yoast_Plugin_Conflict {
|
|||
/* translators: %2$s expands to 'RS Head Cleaner' plugin name of possibly conflicting plugin with regard to differentiating output between search engines and normal users. */
|
||||
$plugin_sections['cloaking'] = __( 'The plugin %2$s changes your site\'s output and in doing that differentiates between search engines and normal users, a process that\'s called cloaking. We highly recommend that you disable it.', 'wordpress-seo' );
|
||||
|
||||
/* translators: %1$s expands to Yoast SEO, %2$s: 'SEO' plugin name of possibly conflicting plugin with regard to the creation of duplicate SEO meta. */
|
||||
$plugin_sections['seo'] = __( 'Both %1$s and %2$s manage the SEO of your site. Running two SEO plugins at the same time is detrimental.', 'wordpress-seo' );
|
||||
|
||||
$instance->check_plugin_conflicts( $plugin_sections );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Premium_popup
|
||||
* Class WPSEO_Premium_popup.
|
||||
*/
|
||||
class WPSEO_Premium_Popup {
|
||||
|
||||
/**
|
||||
* An unique identifier for the popup
|
||||
*
|
||||
|
|
@ -19,39 +20,39 @@ class WPSEO_Premium_Popup {
|
|||
/**
|
||||
* The heading level of the title of the popup.
|
||||
*
|
||||
* @var String
|
||||
* @var string
|
||||
*/
|
||||
private $heading_level = '';
|
||||
|
||||
/**
|
||||
* The title of the popup
|
||||
* The title of the popup.
|
||||
*
|
||||
* @var String
|
||||
* @var string
|
||||
*/
|
||||
private $title = '';
|
||||
|
||||
/**
|
||||
* The content of the popup
|
||||
* The content of the popup.
|
||||
*
|
||||
* @var String
|
||||
* @var string
|
||||
*/
|
||||
private $content = '';
|
||||
|
||||
/**
|
||||
* The URL for where the button should link to.
|
||||
*
|
||||
* @var String
|
||||
* @var string
|
||||
*/
|
||||
private $url = '';
|
||||
|
||||
/**
|
||||
* Wpseo_Premium_Popup constructor.
|
||||
*
|
||||
* @param String $identifier An unique identifier for the popup.
|
||||
* @param String $heading_level The heading level for the title of the popup.
|
||||
* @param String $title The title of the popup.
|
||||
* @param String $content The content of the popup.
|
||||
* @param String $url The URL for where the button should link to.
|
||||
* @param string $identifier An unique identifier for the popup.
|
||||
* @param string $heading_level The heading level for the title of the popup.
|
||||
* @param string $title The title of the popup.
|
||||
* @param string $content The content of the popup.
|
||||
* @param string $url The URL for where the button should link to.
|
||||
*/
|
||||
public function __construct( $identifier, $heading_level, $title, $content, $url ) {
|
||||
$this->identifier = $identifier;
|
||||
|
|
@ -77,19 +78,23 @@ class WPSEO_Premium_Popup {
|
|||
$assets_uri = trailingslashit( plugin_dir_url( WPSEO_FILE ) );
|
||||
|
||||
/* translators: %s expands to Yoast SEO Premium */
|
||||
$cta_text = sprintf( __( 'Get %s now!', 'wordpress-seo' ), 'Yoast SEO Premium' );
|
||||
$classes = '';
|
||||
$cta_text = esc_html( sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' ) );
|
||||
$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 = '';
|
||||
if ( $popup ) {
|
||||
$classes = ' hidden';
|
||||
}
|
||||
$micro_copy = __( '1 year free updates and upgrades included!', 'wordpress-seo' );
|
||||
$micro_copy = __( '1 year free support and updates included!', 'wordpress-seo' );
|
||||
|
||||
$popup = <<<EO_POPUP
|
||||
<div id="wpseo-{$this->identifier}-popup" class="wpseo-premium-popup wp-clearfix$classes">
|
||||
<img class="alignright wpseo-premium-popup-icon" src="{$assets_uri}images/Yoast_SEO_Icon.svg" width="150" height="150" alt="Yoast SEO"/>
|
||||
<img class="alignright wpseo-premium-popup-icon" src="{$assets_uri}packages/js/images/Yoast_SEO_Icon.svg" width="150" height="150" alt="Yoast SEO"/>
|
||||
<{$this->heading_level} id="wpseo-contact-support-popup-title" class="wpseo-premium-popup-title">{$this->title}</{$this->heading_level}>
|
||||
{$this->content}
|
||||
<a id="wpseo-{$this->identifier}-popup-button" class="button button-primary" href="{$this->url}" target="_blank" rel="noreferrer noopener">{$cta_text}</a><br/>
|
||||
<a id="wpseo-{$this->identifier}-popup-button" class="yoast-button-upsell" href="{$this->url}" target="_blank">
|
||||
{$cta_text} {$new_tab_message} {$caret_icon}
|
||||
</a><br/>
|
||||
<small>{$micro_copy}</small>
|
||||
</div>
|
||||
EO_POPUP;
|
||||
|
|
|
|||
|
|
@ -9,11 +9,20 @@
|
|||
* Class WPSEO_Premium_Upsell_Admin_Block
|
||||
*/
|
||||
class WPSEO_Premium_Upsell_Admin_Block {
|
||||
/** @var string Hook to display the block on. */
|
||||
|
||||
/**
|
||||
* Hook to display the block on.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $hook;
|
||||
|
||||
/** @var string Identifier to use in the dismissal functionality. */
|
||||
protected $identifier = 'premium_upsell_admin_block';
|
||||
/**
|
||||
* Identifier to use in the dismissal functionality.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier = 'premium_upsell';
|
||||
|
||||
/**
|
||||
* Registers which hook the block will be displayed on.
|
||||
|
|
@ -30,9 +39,7 @@ class WPSEO_Premium_Upsell_Admin_Block {
|
|||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
if ( ! $this->is_hidden() ) {
|
||||
add_action( $this->hook, array( $this, 'render' ) );
|
||||
}
|
||||
add_action( $this->hook, [ $this, 'render' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -43,37 +50,47 @@ class WPSEO_Premium_Upsell_Admin_Block {
|
|||
public function render() {
|
||||
$url = WPSEO_Shortlinker::get( 'https://yoa.st/17h' );
|
||||
|
||||
$arguments = array(
|
||||
'<strong>' . esc_html__( 'Multiple keywords', 'wordpress-seo' ) . '</strong>: ' . esc_html__( 'Increase your SEO reach', 'wordpress-seo' ),
|
||||
$arguments = [
|
||||
'<strong>' . esc_html__( 'Multiple keyphrases', 'wordpress-seo' ) . '</strong>: ' . esc_html__( 'Increase your SEO reach', '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__( '24/7 support', 'wordpress-seo' ) . '</strong>',
|
||||
'<strong>' . esc_html__( '24/7 email support', 'wordpress-seo' ) . '</strong>',
|
||||
'<strong>' . esc_html__( 'No ads!', 'wordpress-seo' ) . '</strong>',
|
||||
);
|
||||
];
|
||||
|
||||
$arguments_html = implode( '', array_map( array( $this, 'get_argument_html' ), $arguments ) );
|
||||
$arguments_html = implode( '', array_map( [ $this, 'get_argument_html' ], $arguments ) );
|
||||
|
||||
$class = $this->get_html_class();
|
||||
|
||||
/* translators: %s expands to "Yoast SEO Premium". */
|
||||
$dismiss_msg = sprintf( __( 'Dismiss %s upgrade motivation', 'wordpress-seo' ), 'Yoast SEO Premium' );
|
||||
/* translators: %s expands to "Yoast SEO Premium". */
|
||||
$upgrade_msg = sprintf( __( 'Find out why you should upgrade to %s »', 'wordpress-seo' ), 'Yoast SEO Premium' );
|
||||
/* translators: %s expands to Yoast SEO Premium */
|
||||
$button_text = sprintf( esc_html__( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' );
|
||||
$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>';
|
||||
|
||||
echo '<div class="' . esc_attr( $class ) . '">';
|
||||
printf(
|
||||
'<a href="%1$s" style="" class="alignright %2$s" aria-label="%3$s">X</a>',
|
||||
esc_url( add_query_arg( array( $this->get_query_variable_name() => 1 ) ) ),
|
||||
esc_attr( $class . '--close' ),
|
||||
esc_attr( $dismiss_msg )
|
||||
$upgrade_button = sprintf(
|
||||
'<a id="%1$s" class="yoast-button-upsell" href="%2$s" target="_blank">%3$s</a>',
|
||||
esc_attr( 'wpseo-' . $this->identifier . '-popup-button' ),
|
||||
esc_url( $url ),
|
||||
$button_text
|
||||
);
|
||||
|
||||
echo '<div class="' . esc_attr( $class ) . '">';
|
||||
|
||||
echo '<div>';
|
||||
echo '<h2 class="' . esc_attr( $class . '--header' ) . '">' . esc_html__( 'Go premium!', 'wordpress-seo' ) . '</h2>';
|
||||
echo '<h2 class="' . esc_attr( $class . '--header' ) . '">' .
|
||||
sprintf(
|
||||
/* translators: %s expands to Yoast SEO Premium */
|
||||
esc_html__( 'Upgrade to %s', 'wordpress-seo' ),
|
||||
'Yoast SEO Premium'
|
||||
) .
|
||||
'</h2>';
|
||||
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Correctly escaped in $this->get_argument_html() method.
|
||||
echo '<ul class="' . esc_attr( $class . '--motivation' ) . '">' . $arguments_html . '</ul>';
|
||||
|
||||
echo '<p><a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $upgrade_msg ) . '</a><br />';
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Correctly escaped in $upgrade_button and $button_text above.
|
||||
echo '<p>' . $upgrade_button . '</p>';
|
||||
echo '</div>';
|
||||
|
||||
echo '</div>';
|
||||
|
|
@ -96,45 +113,6 @@ class WPSEO_Premium_Upsell_Admin_Block {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the block is hidden by the user.
|
||||
*
|
||||
* @return bool False when it should be shown, True if it should be hidden.
|
||||
*/
|
||||
protected function is_hidden() {
|
||||
$transient_name = $this->get_option_name();
|
||||
|
||||
$hide = (bool) get_user_option( $transient_name );
|
||||
if ( ! $hide ) {
|
||||
$query_variable_name = $this->get_query_variable_name();
|
||||
if ( filter_input( INPUT_GET, $query_variable_name, FILTER_VALIDATE_INT ) === 1 ) {
|
||||
// No expiration time, so this would normally not expire, but it wouldn't be copied to other sites etc.
|
||||
update_user_option( get_current_user_id(), $transient_name, true );
|
||||
$hide = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $hide;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the option name to use.
|
||||
*
|
||||
* @return string The name of the option to save the data in.
|
||||
*/
|
||||
protected function get_option_name() {
|
||||
return 'yoast_promo_hide_' . $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the query variable to use for dismissing the block.
|
||||
*
|
||||
* @return string The name of the query variable to use.
|
||||
*/
|
||||
protected function get_query_variable_name() {
|
||||
return 'yoast_promo_hide_' . $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML base class to use.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -6,28 +6,25 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Adds the UI to change the primary term for a post
|
||||
* Adds the UI to change the primary term for a post.
|
||||
*/
|
||||
class WPSEO_Primary_Term_Admin {
|
||||
class WPSEO_Primary_Term_Admin implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'admin_footer', array( $this, 'wp_footer' ), 10 );
|
||||
public function register_hooks() {
|
||||
add_filter( 'wpseo_content_meta_section_content', [ $this, 'add_input_fields' ] );
|
||||
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
||||
add_action( 'admin_footer', [ $this, 'wp_footer' ], 10 );
|
||||
|
||||
add_action( 'save_post', array( $this, 'save_primary_terms' ) );
|
||||
|
||||
$primary_term = new WPSEO_Frontend_Primary_Category();
|
||||
$primary_term->register_hooks();
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current post ID.
|
||||
* Gets the current post ID.
|
||||
*
|
||||
* @return integer The post ID.
|
||||
* @return int The post ID.
|
||||
*/
|
||||
protected function get_current_id() {
|
||||
$post_id = filter_input( INPUT_GET, 'post', FILTER_SANITIZE_NUMBER_INT );
|
||||
|
|
@ -39,7 +36,62 @@ class WPSEO_Primary_Term_Admin {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add primary term templates
|
||||
* Adds hidden fields for primary taxonomies.
|
||||
*
|
||||
* @param string $content The metabox content.
|
||||
*
|
||||
* @return string The HTML content.
|
||||
*/
|
||||
public function add_input_fields( $content ) {
|
||||
$taxonomies = $this->get_primary_term_taxonomies();
|
||||
|
||||
foreach ( $taxonomies as $taxonomy ) {
|
||||
$content .= $this->primary_term_field( $taxonomy->name );
|
||||
$content .= wp_nonce_field( 'save-primary-term', WPSEO_Meta::$form_prefix . 'primary_' . $taxonomy->name . '_nonce', false, false );
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the HTML for a hidden field for a primary taxonomy.
|
||||
*
|
||||
* @param string $taxonomy_name The taxonomy's slug.
|
||||
*
|
||||
* @return string The HTML for a hidden primary taxonomy field.
|
||||
*/
|
||||
protected function primary_term_field( $taxonomy_name ) {
|
||||
return sprintf(
|
||||
'<input class="yoast-wpseo-primary-term" type="hidden" id="%1$s" name="%2$s" value="%3$s" />',
|
||||
esc_attr( $this->generate_field_id( $taxonomy_name ) ),
|
||||
esc_attr( $this->generate_field_name( $taxonomy_name ) ),
|
||||
esc_attr( $this->get_primary_term( $taxonomy_name ) )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an id for a primary taxonomy's hidden field.
|
||||
*
|
||||
* @param string $taxonomy_name The taxonomy's slug.
|
||||
*
|
||||
* @return string The field id.
|
||||
*/
|
||||
protected function generate_field_id( $taxonomy_name ) {
|
||||
return 'yoast-wpseo-primary-' . $taxonomy_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a name for a primary taxonomy's hidden field.
|
||||
*
|
||||
* @param string $taxonomy_name The taxonomy's slug.
|
||||
*
|
||||
* @return string The field id.
|
||||
*/
|
||||
protected function generate_field_name( $taxonomy_name ) {
|
||||
return WPSEO_Meta::$form_prefix . 'primary_' . $taxonomy_name . '_term';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds primary term templates.
|
||||
*/
|
||||
public function wp_footer() {
|
||||
$taxonomies = $this->get_primary_term_taxonomies();
|
||||
|
|
@ -50,7 +102,7 @@ class WPSEO_Primary_Term_Admin {
|
|||
}
|
||||
|
||||
/**
|
||||
* Enqueues all the assets needed for the primary term interface
|
||||
* Enqueues all the assets needed for the primary term interface.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
|
@ -70,37 +122,19 @@ class WPSEO_Primary_Term_Admin {
|
|||
|
||||
$asset_manager = new WPSEO_Admin_Asset_Manager();
|
||||
$asset_manager->enqueue_style( 'primary-category' );
|
||||
$asset_manager->enqueue_script( 'primary-category' );
|
||||
|
||||
$taxonomies = array_map( array( $this, 'map_taxonomies_for_js' ), $taxonomies );
|
||||
$mapped_taxonomies = $this->get_mapped_taxonomies_for_js( $taxonomies );
|
||||
|
||||
$data = array(
|
||||
'taxonomies' => $taxonomies,
|
||||
);
|
||||
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'primary-category', 'wpseoPrimaryCategoryL10n', $data );
|
||||
$data = [
|
||||
'taxonomies' => $mapped_taxonomies,
|
||||
];
|
||||
|
||||
$asset_manager->localize_script( 'post-edit', 'wpseoPrimaryCategoryL10n', $data );
|
||||
$asset_manager->localize_script( 'post-edit-classic', 'wpseoPrimaryCategoryL10n', $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves all selected primary terms
|
||||
*
|
||||
* @param int $post_id Post ID to save primary terms for.
|
||||
*/
|
||||
public function save_primary_terms( $post_id ) {
|
||||
// Bail if this is a multisite installation and the site has been switched.
|
||||
if ( is_multisite() && ms_is_switched() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$taxonomies = $this->get_primary_term_taxonomies( $post_id );
|
||||
|
||||
foreach ( $taxonomies as $taxonomy ) {
|
||||
$this->save_primary_term( $post_id, $taxonomy );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* /**
|
||||
* Get the id of the primary term
|
||||
* Gets the id of the primary term.
|
||||
*
|
||||
* @param string $taxonomy_name Taxonomy name for the term.
|
||||
*
|
||||
|
|
@ -113,19 +147,18 @@ class WPSEO_Primary_Term_Admin {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns all the taxonomies for which the primary term selection is enabled
|
||||
* Returns all the taxonomies for which the primary term selection is enabled.
|
||||
*
|
||||
* @param int $post_id Default current post ID.
|
||||
* @param int|null $post_id Default current post ID.
|
||||
* @return array
|
||||
*/
|
||||
protected function get_primary_term_taxonomies( $post_id = null ) {
|
||||
|
||||
if ( null === $post_id ) {
|
||||
if ( $post_id === null ) {
|
||||
$post_id = $this->get_current_id();
|
||||
}
|
||||
|
||||
$taxonomies = wp_cache_get( 'primary_term_taxonomies_' . $post_id, 'wpseo' );
|
||||
if ( false !== $taxonomies ) {
|
||||
if ( $taxonomies !== false ) {
|
||||
return $taxonomies;
|
||||
}
|
||||
|
||||
|
|
@ -137,30 +170,14 @@ class WPSEO_Primary_Term_Admin {
|
|||
}
|
||||
|
||||
/**
|
||||
* Include templates file
|
||||
* Includes templates file.
|
||||
*/
|
||||
protected function include_js_templates() {
|
||||
include_once WPSEO_PATH . 'admin/views/js-templates-primary-term.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the primary term for a specific taxonomy
|
||||
*
|
||||
* @param int $post_id Post ID to save primary term for.
|
||||
* @param WP_Term $taxonomy Taxonomy to save primary term for.
|
||||
*/
|
||||
protected function save_primary_term( $post_id, $taxonomy ) {
|
||||
$primary_term = filter_input( INPUT_POST, WPSEO_Meta::$form_prefix . 'primary_' . $taxonomy->name . '_term', FILTER_SANITIZE_NUMBER_INT );
|
||||
|
||||
// We accept an empty string here because we need to save that if no terms are selected.
|
||||
if ( null !== $primary_term && check_admin_referer( 'save-primary-term', WPSEO_Meta::$form_prefix . 'primary_' . $taxonomy->name . '_nonce' ) ) {
|
||||
$primary_term_object = new WPSEO_Primary_Term( $taxonomy->name, $post_id );
|
||||
$primary_term_object->set_primary_term( $primary_term );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the primary term taxonomies.
|
||||
* Generates the primary term taxonomies.
|
||||
*
|
||||
* @param int $post_id ID of the post.
|
||||
*
|
||||
|
|
@ -169,7 +186,7 @@ class WPSEO_Primary_Term_Admin {
|
|||
protected function generate_primary_term_taxonomies( $post_id ) {
|
||||
$post_type = get_post_type( $post_id );
|
||||
$all_taxonomies = get_object_taxonomies( $post_type, 'objects' );
|
||||
$all_taxonomies = array_filter( $all_taxonomies, array( $this, 'filter_hierarchical_taxonomies' ) );
|
||||
$all_taxonomies = array_filter( $all_taxonomies, [ $this, 'filter_hierarchical_taxonomies' ] );
|
||||
|
||||
/**
|
||||
* Filters which taxonomies for which the user can choose the primary term.
|
||||
|
|
@ -186,11 +203,22 @@ class WPSEO_Primary_Term_Admin {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns an array suitable for use in the javascript
|
||||
* Creates a map of taxonomies for localization.
|
||||
*
|
||||
* @param array $taxonomies The taxononmies that should be mapped.
|
||||
*
|
||||
* @return array The mapped taxonomies.
|
||||
*/
|
||||
protected function get_mapped_taxonomies_for_js( $taxonomies ) {
|
||||
return array_map( [ $this, 'map_taxonomies_for_js' ], $taxonomies );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array suitable for use in the javascript.
|
||||
*
|
||||
* @param stdClass $taxonomy The taxonomy to map.
|
||||
*
|
||||
* @return array
|
||||
* @return array The mapped taxonomy.
|
||||
*/
|
||||
private function map_taxonomies_for_js( $taxonomy ) {
|
||||
$primary_term = $this->get_primary_term( $taxonomy->name );
|
||||
|
|
@ -199,30 +227,35 @@ class WPSEO_Primary_Term_Admin {
|
|||
$primary_term = '';
|
||||
}
|
||||
|
||||
return array(
|
||||
'title' => $taxonomy->labels->singular_name,
|
||||
'name' => $taxonomy->name,
|
||||
'primary' => $primary_term,
|
||||
'terms' => array_map( array( $this, 'map_terms_for_js' ), get_terms( $taxonomy->name ) ),
|
||||
$terms = get_terms(
|
||||
[
|
||||
'taxonomy' => $taxonomy->name,
|
||||
'update_term_meta_cache' => false,
|
||||
'fields' => 'id=>name',
|
||||
]
|
||||
);
|
||||
|
||||
$mapped_terms_for_js = [];
|
||||
foreach ( $terms as $id => $name ) {
|
||||
$mapped_terms_for_js[] = [
|
||||
'id' => $id,
|
||||
'name' => $name,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => $taxonomy->labels->singular_name,
|
||||
'name' => $taxonomy->name,
|
||||
'primary' => $primary_term,
|
||||
'singularLabel' => $taxonomy->labels->singular_name,
|
||||
'fieldId' => $this->generate_field_id( $taxonomy->name ),
|
||||
'restBase' => ( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name,
|
||||
'terms' => $mapped_terms_for_js,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array suitable for use in the javascript
|
||||
*
|
||||
* @param stdClass $term The term to map.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function map_terms_for_js( $term ) {
|
||||
return array(
|
||||
'id' => $term->term_id,
|
||||
'name' => $term->name,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not a taxonomy is hierarchical
|
||||
* Returns whether or not a taxonomy is hierarchical.
|
||||
*
|
||||
* @param stdClass $taxonomy Taxonomy object.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -10,11 +10,27 @@
|
|||
*/
|
||||
class WPSEO_Product_Upsell_Notice {
|
||||
|
||||
/**
|
||||
* Holds the name of the user meta key.
|
||||
*
|
||||
* The value of this database field holds whether the user has dismissed this notice or not.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const USER_META_DISMISSED = 'wpseo-remove-upsell-notice';
|
||||
|
||||
/**
|
||||
* Holds the option name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const OPTION_NAME = 'wpseo';
|
||||
|
||||
/** @var array */
|
||||
/**
|
||||
* Holds the options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
|
|
@ -28,15 +44,7 @@ class WPSEO_Product_Upsell_Notice {
|
|||
* Checks if the notice should be added or removed.
|
||||
*/
|
||||
public function initialize() {
|
||||
if ( $this->is_notice_dismissed() ) {
|
||||
$this->remove_notification();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $this->should_add_notification() ) {
|
||||
$this->add_notification();
|
||||
}
|
||||
$this->remove_notification();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -62,7 +70,7 @@ class WPSEO_Product_Upsell_Notice {
|
|||
|
||||
$this->dismiss_notice();
|
||||
|
||||
wp_redirect( admin_url( 'admin.php?page=wpseo_dashboard' ) );
|
||||
wp_safe_redirect( admin_url( 'admin.php?page=wpseo_dashboard' ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +85,8 @@ class WPSEO_Product_Upsell_Notice {
|
|||
|
||||
/**
|
||||
* Checks if the options has a first activated on date value.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function has_first_activated_on() {
|
||||
return $this->options['first_activated_on'] !== false;
|
||||
|
|
@ -100,7 +110,7 @@ class WPSEO_Product_Upsell_Notice {
|
|||
}
|
||||
|
||||
/**
|
||||
* Adds a notification to the notification center.
|
||||
* Removes a notification to the notification center.
|
||||
*/
|
||||
protected function remove_notification() {
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
|
|
@ -113,11 +123,10 @@ class WPSEO_Product_Upsell_Notice {
|
|||
* @return string
|
||||
*/
|
||||
protected function get_premium_upsell_section() {
|
||||
$features = new WPSEO_Features();
|
||||
if ( $features->is_free() ) {
|
||||
if ( ! YoastSEO()->helpers->product->is_premium() ) {
|
||||
return sprintf(
|
||||
/* translators: %1$s expands anchor to premium plugin page, %2$s expands to </a> */
|
||||
__( 'By the way, did you know we also have a %1$sPremium plugin%2$s? It offers advanced features, like a redirect manager and support for multiple keywords. It also comes with 24/7 personal support.', 'wordpress-seo' ),
|
||||
__( 'By the way, did you know we also have a %1$sPremium plugin%2$s? It offers advanced features, like a redirect manager and support for multiple keyphrases. It also comes with 24/7 personal support.', 'wordpress-seo' ),
|
||||
"<a href='" . WPSEO_Shortlinker::get( 'https://yoa.st/premium-notification' ) . "'>",
|
||||
'</a>'
|
||||
);
|
||||
|
|
@ -141,7 +150,7 @@ class WPSEO_Product_Upsell_Notice {
|
|||
) . "\n\n";
|
||||
|
||||
$message .= sprintf(
|
||||
/* translators: %1$s is a link start tag to the bugreport guidelines on the Yoast knowledge base, %2$s is the link closing tag. */
|
||||
/* translators: %1$s is a link start tag to the bugreport guidelines on the Yoast help center, %2$s is the link closing tag. */
|
||||
__( 'If you are experiencing issues, %1$splease file a bug report%2$s and we\'ll do our best to help you out.', 'wordpress-seo' ),
|
||||
'<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/bugreport' ) . '">',
|
||||
'</a>'
|
||||
|
|
@ -149,21 +158,16 @@ class WPSEO_Product_Upsell_Notice {
|
|||
|
||||
$message .= $this->get_premium_upsell_section() . "\n\n";
|
||||
|
||||
$message .= sprintf(
|
||||
/* translators: %1$s is the notification dismissal link start tag, %2$s is the link closing tag. */
|
||||
__( '%1$sPlease don\'t show me this notification anymore%2$s', 'wordpress-seo' ),
|
||||
'<a class="button" href="' . admin_url( '?page=' . WPSEO_Admin::PAGE_IDENTIFIER . '&yoast_dismiss=upsell' ) . '">',
|
||||
'</a>'
|
||||
);
|
||||
$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>';
|
||||
|
||||
$notification = new Yoast_Notification(
|
||||
$message,
|
||||
array(
|
||||
[
|
||||
'type' => Yoast_Notification::WARNING,
|
||||
'id' => 'wpseo-upsell-notice',
|
||||
'capabilities' => 'wpseo_manage_options',
|
||||
'priority' => 0.8,
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
return $notification;
|
||||
|
|
@ -172,7 +176,7 @@ class WPSEO_Product_Upsell_Notice {
|
|||
/**
|
||||
* Dismisses the notice.
|
||||
*
|
||||
* @return string
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_notice_dismissed() {
|
||||
return get_user_meta( get_current_user_id(), self::USER_META_DISMISSED, true ) === '1';
|
||||
|
|
@ -186,9 +190,9 @@ class WPSEO_Product_Upsell_Notice {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the set options
|
||||
* Returns the set options.
|
||||
*
|
||||
* @return mixed|void
|
||||
* @return mixed
|
||||
*/
|
||||
protected function get_options() {
|
||||
return get_option( self::OPTION_NAME );
|
||||
|
|
|
|||
|
|
@ -1,54 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Recalculate_Scores
|
||||
*
|
||||
* This class handles the SEO score recalculation for all posts with a filled focus keyword
|
||||
*/
|
||||
class WPSEO_Recalculate_Scores {
|
||||
|
||||
/**
|
||||
* Constructing the object by modalbox, the localization and the totals.
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'recalculate_assets' ) );
|
||||
add_action( 'admin_footer', array( $this, 'modal_box' ), 20 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the localize script.
|
||||
*/
|
||||
public function recalculate_assets() {
|
||||
$asset_manager = new WPSEO_Admin_Asset_Manager();
|
||||
$asset_manager->enqueue_script( 'recalculate' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the modal box to be displayed when needed.
|
||||
*/
|
||||
public function modal_box() {
|
||||
// Adding the thickbox.
|
||||
add_thickbox();
|
||||
|
||||
$progress = sprintf(
|
||||
/* translators: 1: expands to a <span> containing the number of posts recalculated. 2: expands to a <strong> containing the total number of posts. */
|
||||
esc_html__( '%1$s of %2$s done.', 'wordpress-seo' ),
|
||||
'<span id="wpseo_count">0</span>',
|
||||
'<strong id="wpseo_count_total">0</strong>'
|
||||
);
|
||||
|
||||
?>
|
||||
<div id="wpseo_recalculate" class="hidden">
|
||||
<p><?php esc_html_e( 'Recalculating SEO scores for all pieces of content with a focus keyword.', 'wordpress-seo' ); ?></p>
|
||||
|
||||
<div id="wpseo_progressbar"></div>
|
||||
<p><?php echo $progress; ?></p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
|
@ -10,23 +10,49 @@
|
|||
*/
|
||||
class WPSEO_Remote_Request {
|
||||
|
||||
/**
|
||||
* Holds the post method.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const METHOD_POST = 'post';
|
||||
const METHOD_GET = 'get';
|
||||
|
||||
/** @var string */
|
||||
/**
|
||||
* Holds the get method.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const METHOD_GET = 'get';
|
||||
|
||||
/**
|
||||
* Holds the endpoint to send the request to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $endpoint = '';
|
||||
|
||||
/** @var array */
|
||||
protected $args = array(
|
||||
/**
|
||||
* Holds the arguments to use in this request.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $args = [
|
||||
'blocking' => false,
|
||||
'sslverify' => false,
|
||||
'timeout' => 2,
|
||||
);
|
||||
];
|
||||
|
||||
/** @var WP_Error|null */
|
||||
/**
|
||||
* Holds the response error.
|
||||
*
|
||||
* @var WP_Error|null
|
||||
*/
|
||||
protected $response_error;
|
||||
|
||||
/** @var mixed */
|
||||
/**
|
||||
* Holds the response body.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $response_body;
|
||||
|
||||
/**
|
||||
|
|
@ -35,7 +61,7 @@ class WPSEO_Remote_Request {
|
|||
* @param string $endpoint The endpoint to send the request to.
|
||||
* @param array $args The arguments to use in this request.
|
||||
*/
|
||||
public function __construct( $endpoint, array $args = array() ) {
|
||||
public function __construct( $endpoint, array $args = [] ) {
|
||||
$this->endpoint = $endpoint;
|
||||
$this->args = wp_parse_args( $this->args, $args );
|
||||
}
|
||||
|
|
@ -76,7 +102,7 @@ class WPSEO_Remote_Request {
|
|||
/**
|
||||
* Returns the value of the response error.
|
||||
*
|
||||
* @return null|WP_Error The response error.
|
||||
* @return WP_Error|null The response error.
|
||||
*/
|
||||
public function get_response_error() {
|
||||
return $this->response_error;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Notifies the user to update the Person on the publish entity in the Configuration Wizard.
|
||||
*/
|
||||
class WPSEO_Schema_Person_Upgrade_Notification implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* Registers all hooks to WordPress
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
add_action( 'admin_init', [ $this, 'handle_notification' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles if the notification should be added or removed.
|
||||
*/
|
||||
public function handle_notification() {
|
||||
$company_or_person_user_id = WPSEO_Options::get( 'company_or_person_user_id', false );
|
||||
if ( WPSEO_Options::get( 'company_or_person' ) === 'person' && empty( $company_or_person_user_id ) ) {
|
||||
$this->add_notification();
|
||||
return;
|
||||
}
|
||||
|
||||
$this->remove_notification();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a notification to the notification center.
|
||||
*/
|
||||
protected function add_notification() {
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
$notification_center->add_notification( $this->get_notification() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a notification to the notification center.
|
||||
*/
|
||||
protected function remove_notification() {
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
$notification_center->remove_notification( $this->get_notification() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the notification object.
|
||||
*
|
||||
* @return Yoast_Notification
|
||||
*/
|
||||
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. */
|
||||
__( '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>'
|
||||
);
|
||||
|
||||
$notification = new Yoast_Notification(
|
||||
$message,
|
||||
[
|
||||
'type' => Yoast_Notification::WARNING,
|
||||
'id' => 'wpseo-schema-person-upgrade',
|
||||
'capabilities' => 'wpseo_manage_options',
|
||||
'priority' => 0.8,
|
||||
]
|
||||
);
|
||||
|
||||
return $notification;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class adds the Social tab to the Yoast SEO metabox and makes sure the settings are saved.
|
||||
*/
|
||||
class WPSEO_Social_Admin extends WPSEO_Metabox {
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
self::translate_meta_boxes();
|
||||
add_filter( 'wpseo_save_metaboxes', array( $this, 'save_meta_boxes' ), 10, 1 );
|
||||
add_action( 'wpseo_save_compare_data', array( $this, 'og_data_compare' ), 10, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate text strings for use in the meta box.
|
||||
*
|
||||
* IMPORTANT: if you want to add a new string (option) somewhere, make sure you add that array key to
|
||||
* the main meta box definition array in the class WPSEO_Meta() as well!!!!
|
||||
*/
|
||||
public static function translate_meta_boxes() {
|
||||
/* translators: %s expands to the social network's name. */
|
||||
$title_text = __( 'If you don\'t want to use the post title for sharing the post on %s but instead want another title there, write it here.', 'wordpress-seo' );
|
||||
|
||||
/* translators: %s expands to the social network's name. */
|
||||
$description_text = __( 'If you don\'t want to use the meta description for sharing the post on %s but want another description there, write it here.', 'wordpress-seo' );
|
||||
|
||||
/* translators: %s expands to the social network's name. */
|
||||
$image_text = __( 'If you want to override the image used on %s for this post, upload / choose an image or add the URL here.', 'wordpress-seo' );
|
||||
|
||||
/* translators: %1$s expands to the social network, %2$s to the recommended image size. */
|
||||
$image_size_text = __( 'The recommended image size for %1$s is %2$s pixels.', 'wordpress-seo' );
|
||||
|
||||
$social_networks = array(
|
||||
'opengraph' => __( 'Facebook', 'wordpress-seo' ),
|
||||
'twitter' => __( 'Twitter', 'wordpress-seo' ),
|
||||
);
|
||||
|
||||
// Source: https://blog.bufferapp.com/ideal-image-sizes-social-media-posts.
|
||||
$recommended_image_sizes = array(
|
||||
/* translators: %1$s expands to the image recommended width, %2$s to its height. */
|
||||
'opengraph' => sprintf( __( '%1$s by %2$s', 'wordpress-seo' ), '1200', '630' ),
|
||||
// Source: https://developers.facebook.com/docs/sharing/best-practices#images.
|
||||
/* translators: %1$s expands to the image recommended width, %2$s to its height. */
|
||||
'twitter' => sprintf( __( '%1$s by %2$s', 'wordpress-seo' ), '1024', '512' ),
|
||||
);
|
||||
|
||||
foreach ( $social_networks as $network => $label ) {
|
||||
if ( true === WPSEO_Options::get( $network, false ) ) {
|
||||
/* translators: %s expands to the name of a social network. */
|
||||
self::$meta_fields['social'][ $network . '-title' ]['title'] = sprintf( __( '%s Title', 'wordpress-seo' ), $label );
|
||||
self::$meta_fields['social'][ $network . '-title' ]['description'] = sprintf( $title_text, $label );
|
||||
|
||||
/* translators: %s expands to the name of a social network. */
|
||||
self::$meta_fields['social'][ $network . '-description' ]['title'] = sprintf( __( '%s Description', 'wordpress-seo' ), $label );
|
||||
self::$meta_fields['social'][ $network . '-description' ]['description'] = sprintf( $description_text, $label );
|
||||
|
||||
/* translators: %s expands to the name of a social network. */
|
||||
self::$meta_fields['social'][ $network . '-image' ]['title'] = sprintf( __( '%s Image', 'wordpress-seo' ), $label );
|
||||
self::$meta_fields['social'][ $network . '-image' ]['description'] = sprintf( $image_text, $label ) . ' ' . sprintf( $image_size_text, $label, $recommended_image_sizes[ $network ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metabox section for the social settings.
|
||||
*
|
||||
* @return WPSEO_Metabox_Tab_Section
|
||||
*/
|
||||
public function get_meta_section() {
|
||||
$tabs = array();
|
||||
$social_meta_fields = $this->get_meta_field_defs( 'social' );
|
||||
$single = true;
|
||||
|
||||
$opengraph = WPSEO_Options::get( 'opengraph' );
|
||||
$twitter = WPSEO_Options::get( 'twitter' );
|
||||
|
||||
if ( $opengraph === true && $twitter === true ) {
|
||||
$single = null;
|
||||
}
|
||||
|
||||
if ( $opengraph === true ) {
|
||||
$tabs[] = new WPSEO_Metabox_Form_Tab(
|
||||
'facebook',
|
||||
$this->get_social_tab_content( 'opengraph', $social_meta_fields ),
|
||||
'<span class="screen-reader-text">' . __( 'Facebook / Open Graph metadata', 'wordpress-seo' ) . '</span><span class="dashicons dashicons-facebook-alt"></span>',
|
||||
array(
|
||||
'link_aria_label' => __( 'Facebook / Open Graph metadata', 'wordpress-seo' ),
|
||||
'link_class' => 'yoast-tooltip yoast-tooltip-se',
|
||||
'single' => $single,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( $twitter === true ) {
|
||||
$tabs[] = new WPSEO_Metabox_Form_Tab(
|
||||
'twitter',
|
||||
$this->get_social_tab_content( 'twitter', $social_meta_fields ),
|
||||
'<span class="screen-reader-text">' . __( 'Twitter metadata', 'wordpress-seo' ) . '</span><span class="dashicons dashicons-twitter"></span>',
|
||||
array(
|
||||
'link_aria_label' => __( 'Twitter metadata', 'wordpress-seo' ),
|
||||
'link_class' => 'yoast-tooltip yoast-tooltip-se',
|
||||
'single' => $single,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return new WPSEO_Metabox_Tab_Section(
|
||||
'social',
|
||||
'<span class="screen-reader-text">' . __( 'Social', 'wordpress-seo' ) . '</span><span class="dashicons dashicons-share"></span>',
|
||||
$tabs,
|
||||
array(
|
||||
'link_aria_label' => __( 'Social', 'wordpress-seo' ),
|
||||
'link_class' => 'yoast-tooltip yoast-tooltip-e',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the html for a social settings tab for one of the supported social media.
|
||||
*
|
||||
* @param string $medium Medium. Can be 'opengraph' or 'twitter'.
|
||||
* @param array $meta_field_defs The social meta field definitions.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_social_tab_content( $medium, $meta_field_defs ) {
|
||||
$field_names = array(
|
||||
$medium . '-title',
|
||||
$medium . '-description',
|
||||
$medium . '-image',
|
||||
);
|
||||
|
||||
$tab_content = $this->get_premium_notice( $medium );
|
||||
|
||||
foreach ( $field_names as $field_name ) {
|
||||
$tab_content .= $this->do_meta_box( $meta_field_defs[ $field_name ], $field_name );
|
||||
}
|
||||
|
||||
return $tab_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Upgrade to Premium notice.
|
||||
*
|
||||
* @param string $network The social network.
|
||||
*
|
||||
* @return string The notice HTML on the free version, empty string on premium.
|
||||
*/
|
||||
public function get_premium_notice( $network ) {
|
||||
$features = new WPSEO_Features();
|
||||
if ( $features->is_premium() ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$network_name = __( 'Facebook', 'wordpress-seo' );
|
||||
|
||||
if ( 'twitter' === $network ) {
|
||||
$network_name = __( 'Twitter', 'wordpress-seo' );
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'<div class="notice inline yoast-notice yoast-notice-go-premium">
|
||||
<p>%1$s</p>
|
||||
<p><a href="%2$s" target="_blank">%3$s</a></p>
|
||||
</div>',
|
||||
sprintf(
|
||||
/* translators: %1$s expands to the social network's name, %2$s to Yoast SEO Premium. */
|
||||
esc_html__( 'Do you want to preview what it will look like if people share this post on %1$s? You can, with %2$s.', 'wordpress-seo' ),
|
||||
esc_html( $network_name ),
|
||||
'<strong>Yoast SEO Premium</strong>'
|
||||
),
|
||||
esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/179' ) ),
|
||||
sprintf(
|
||||
/* translators: %s expands to Yoast SEO Premium. */
|
||||
esc_html__( 'Find out why you should upgrade to %s', 'wordpress-seo' ),
|
||||
'Yoast SEO Premium'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter over the meta boxes to save, this function adds the Social meta boxes.
|
||||
*
|
||||
* @param array $field_defs Array of metaboxes to save.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function save_meta_boxes( $field_defs ) {
|
||||
return array_merge( $field_defs, $this->get_meta_field_defs( 'social' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will compare opengraph fields with the posted values.
|
||||
*
|
||||
* When fields are changed, the facebook cache will be purge.
|
||||
*
|
||||
* @param WP_Post $post Post instance.
|
||||
*/
|
||||
public function og_data_compare( $post ) {
|
||||
|
||||
// Check if post data is available, if post_id is set and if original post_status is publish.
|
||||
// @codingStandardsIgnoreStart
|
||||
if (
|
||||
! empty( $_POST ) && ! empty( $post->ID ) && $post->post_status === 'publish' &&
|
||||
isset( $_POST['original_post_status'] ) && $_POST['original_post_status'] === 'publish'
|
||||
) {
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
$fields_to_compare = array(
|
||||
'opengraph-title',
|
||||
'opengraph-description',
|
||||
'opengraph-image',
|
||||
);
|
||||
|
||||
$reset_facebook_cache = false;
|
||||
|
||||
foreach ( $fields_to_compare as $field_to_compare ) {
|
||||
$old_value = self::get_value( $field_to_compare, $post->ID );
|
||||
$new_value = self::get_post_value( self::$form_prefix . $field_to_compare );
|
||||
|
||||
if ( $old_value !== $new_value ) {
|
||||
$reset_facebook_cache = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unset( $field_to_compare, $old_value, $new_value );
|
||||
|
||||
if ( $reset_facebook_cache ) {
|
||||
wp_remote_get(
|
||||
'https://graph.facebook.com/?id=' . get_permalink( $post->ID ) . '&scrape=true&method=post'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* End of class */
|
||||
|
|
@ -11,11 +11,15 @@
|
|||
class WPSEO_Suggested_Plugins implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* Holds the availability checker.
|
||||
*
|
||||
* @var WPSEO_Plugin_Availability
|
||||
*/
|
||||
protected $availability_checker;
|
||||
|
||||
/**
|
||||
* Holds the notification center.
|
||||
*
|
||||
* @var Yoast_Notification_Center
|
||||
*/
|
||||
protected $notification_center;
|
||||
|
|
@ -24,7 +28,7 @@ class WPSEO_Suggested_Plugins implements WPSEO_WordPress_Integration {
|
|||
* WPSEO_Suggested_Plugins constructor.
|
||||
*
|
||||
* @param WPSEO_Plugin_Availability $availability_checker The availability checker to use.
|
||||
* @param Yoast_Notification_Center $notification_center The notification center to add notifications to.
|
||||
* @param Yoast_Notification_Center $notification_center The notification center to add notifications to.
|
||||
*/
|
||||
public function __construct( WPSEO_Plugin_Availability $availability_checker, Yoast_Notification_Center $notification_center ) {
|
||||
$this->availability_checker = $availability_checker;
|
||||
|
|
@ -37,8 +41,8 @@ class WPSEO_Suggested_Plugins implements WPSEO_WordPress_Integration {
|
|||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
add_action( 'admin_init', array( $this->availability_checker, 'register' ) );
|
||||
add_action( 'admin_init', array( $this, 'add_notifications' ) );
|
||||
add_action( 'admin_init', [ $this->availability_checker, 'register' ] );
|
||||
add_action( 'admin_init', [ $this, 'add_notifications' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -57,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 ( ! WPSEO_Utils::is_yoast_seo_premium() && ( ! $checker->is_installed( $plugin ) || ! $checker->is_active( $plugin['slug'] ) ) ) {
|
||||
if ( ! $checker->is_installed( $plugin ) || ! $checker->is_active( $plugin['slug'] ) ) {
|
||||
$this->notification_center->add_notification( $notification );
|
||||
|
||||
continue;
|
||||
|
|
@ -73,87 +76,86 @@ 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 = $this->create_activate_suggested_plugin_message( $plugin );
|
||||
}
|
||||
|
||||
return new Yoast_Notification(
|
||||
$message,
|
||||
array(
|
||||
[
|
||||
'id' => 'wpseo-suggested-plugin-' . $name,
|
||||
'type' => Yoast_Notification::WARNING,
|
||||
'capabilities' => array( 'install_plugins' ),
|
||||
)
|
||||
'capabilities' => [ 'install_plugins' ],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a more information link that directs the user to WordPress.org Plugin repository.
|
||||
*
|
||||
* @param string $url The URL to the plugin's page.
|
||||
* @param string $url The URL to the plugin's page.
|
||||
* @param string $name The name of the plugin.
|
||||
*
|
||||
* @return string The more information link.
|
||||
*/
|
||||
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' )
|
||||
sprintf( __( 'More information about %1$s', 'wordpress-seo' ), $name )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param array $suggested_plugin The suggested plugin.
|
||||
*
|
||||
* @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' );
|
||||
protected function create_activate_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 and opening anchor tag, %5$s expands to a closing anchor tag. */
|
||||
$message = __( 'It looks like you\'ve installed our %1$s%2$s addon%3$s. %4$sActivate it now%5$s to unlock more tools and SEO features to make your products stand out in search results.', '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'] )
|
||||
'<strong>',
|
||||
$suggested_plugin['title'],
|
||||
'</strong>',
|
||||
'<a href="' . $activation_url . '">',
|
||||
'</a>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,260 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Notifications
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class Yoast_Alerts
|
||||
*/
|
||||
class Yoast_Alerts {
|
||||
|
||||
const ADMIN_PAGE = 'wpseo_dashboard';
|
||||
|
||||
/** @var int Total notifications count */
|
||||
private static $notification_count = 0;
|
||||
|
||||
/** @var array All error notifications */
|
||||
private static $errors = array();
|
||||
/** @var array Active errors */
|
||||
private static $active_errors = array();
|
||||
/** @var array Dismissed errors */
|
||||
private static $dismissed_errors = array();
|
||||
|
||||
/** @var array All warning notifications */
|
||||
private static $warnings = array();
|
||||
/** @var array Active warnings */
|
||||
private static $active_warnings = array();
|
||||
/** @var array Dismissed warnings */
|
||||
private static $dismissed_warnings = array();
|
||||
|
||||
/**
|
||||
* Yoast_Alerts constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
$this->add_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add hooks
|
||||
*/
|
||||
private function add_hooks() {
|
||||
|
||||
$page = filter_input( INPUT_GET, 'page' );
|
||||
if ( self::ADMIN_PAGE === $page ) {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
||||
}
|
||||
|
||||
// Needed for adminbar and Alerts page.
|
||||
add_action( 'admin_init', array( __CLASS__, 'collect_alerts' ), 99 );
|
||||
|
||||
// Add AJAX hooks.
|
||||
add_action( 'wp_ajax_yoast_dismiss_alert', array( $this, 'ajax_dismiss_alert' ) );
|
||||
add_action( 'wp_ajax_yoast_restore_alert', array( $this, 'ajax_restore_alert' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue assets
|
||||
*/
|
||||
public function enqueue_assets() {
|
||||
|
||||
$asset_manager = new WPSEO_Admin_Asset_Manager();
|
||||
$asset_manager->enqueue_style( 'alerts' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ajax request to dismiss an alert
|
||||
*/
|
||||
public function ajax_dismiss_alert() {
|
||||
|
||||
$notification = $this->get_notification_from_ajax_request();
|
||||
if ( $notification ) {
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
$notification_center->maybe_dismiss_notification( $notification );
|
||||
|
||||
$this->output_ajax_response( $notification->get_type() );
|
||||
}
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ajax request to restore an alert
|
||||
*/
|
||||
public function ajax_restore_alert() {
|
||||
|
||||
$notification = $this->get_notification_from_ajax_request();
|
||||
if ( $notification ) {
|
||||
delete_user_meta( get_current_user_id(), $notification->get_dismissal_key() );
|
||||
|
||||
$this->output_ajax_response( $notification->get_type() );
|
||||
}
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create AJAX response data
|
||||
*
|
||||
* @param string $type Alert type.
|
||||
*/
|
||||
private function output_ajax_response( $type ) {
|
||||
|
||||
$html = $this->get_view_html( $type );
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'html' => $html,
|
||||
'total' => self::get_active_alert_count(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML to return in the AJAX request
|
||||
*
|
||||
* @param string $type Alert type.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function get_view_html( $type ) {
|
||||
|
||||
switch ( $type ) {
|
||||
case 'error':
|
||||
$view = 'errors';
|
||||
break;
|
||||
|
||||
case 'warning':
|
||||
default:
|
||||
$view = 'warnings';
|
||||
break;
|
||||
}
|
||||
|
||||
// Re-collect alerts.
|
||||
self::collect_alerts();
|
||||
|
||||
/** @noinspection PhpUnusedLocalVariableInspection */
|
||||
$alerts_data = self::get_template_variables();
|
||||
|
||||
ob_start();
|
||||
include WPSEO_PATH . 'admin/views/partial-alerts-' . $view . '.php';
|
||||
$html = ob_get_clean();
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the Yoast Notification from the AJAX request
|
||||
*
|
||||
* @return null|Yoast_Notification
|
||||
*/
|
||||
private function get_notification_from_ajax_request() {
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
$notification_id = filter_input( INPUT_POST, 'notification' );
|
||||
|
||||
return $notification_center->get_notification_by_id( $notification_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the alerts overview page
|
||||
*/
|
||||
public static function show_overview_page() {
|
||||
|
||||
/** @noinspection PhpUnusedLocalVariableInspection */
|
||||
$alerts_data = self::get_template_variables();
|
||||
|
||||
include WPSEO_PATH . 'admin/views/alerts-dashboard.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the alerts and group them together
|
||||
*/
|
||||
public static function collect_alerts() {
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
|
||||
$notifications = $notification_center->get_sorted_notifications();
|
||||
self::$notification_count = count( $notifications );
|
||||
|
||||
self::$errors = array_filter( $notifications, array( __CLASS__, 'filter_error_alerts' ) );
|
||||
self::$dismissed_errors = array_filter( self::$errors, array( __CLASS__, 'filter_dismissed_alerts' ) );
|
||||
self::$active_errors = array_diff( self::$errors, self::$dismissed_errors );
|
||||
|
||||
self::$warnings = array_filter( $notifications, array( __CLASS__, 'filter_warning_alerts' ) );
|
||||
self::$dismissed_warnings = array_filter( self::$warnings, array( __CLASS__, 'filter_dismissed_alerts' ) );
|
||||
self::$active_warnings = array_diff( self::$warnings, self::$dismissed_warnings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the variables needed in the views
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_template_variables() {
|
||||
|
||||
return array(
|
||||
'metrics' => array(
|
||||
'total' => self::$notification_count,
|
||||
'active' => self::get_active_alert_count(),
|
||||
'errors' => count( self::$errors ),
|
||||
'warnings' => count( self::$warnings ),
|
||||
),
|
||||
'errors' => array(
|
||||
'dismissed' => self::$dismissed_errors,
|
||||
'active' => self::$active_errors,
|
||||
),
|
||||
'warnings' => array(
|
||||
'dismissed' => self::$dismissed_warnings,
|
||||
'active' => self::$active_warnings,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of active alerts
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function get_active_alert_count() {
|
||||
|
||||
return ( count( self::$active_errors ) + count( self::$active_warnings ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter out any non-errors
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to test.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function filter_error_alerts( Yoast_Notification $notification ) {
|
||||
|
||||
return $notification->get_type() === 'error';
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter out any non-warnings
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to test.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function filter_warning_alerts( Yoast_Notification $notification ) {
|
||||
|
||||
return $notification->get_type() !== 'error';
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter out any dismissed notifications
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to test.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function filter_dismissed_alerts( Yoast_Notification $notification ) {
|
||||
|
||||
return Yoast_Notification_Center::is_notification_dismissed( $notification );
|
||||
}
|
||||
}
|
||||
|
|
@ -11,34 +11,98 @@
|
|||
class WPSEO_Yoast_Columns implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* Registers all hooks to WordPress
|
||||
* Registers all hooks to WordPress.
|
||||
*/
|
||||
public function register_hooks() {
|
||||
add_action( 'load-edit.php', array( $this, 'add_help_tab' ) );
|
||||
add_action( 'load-edit.php', [ $this, 'add_help_tab' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the help tab to the help center for current screen.
|
||||
*/
|
||||
public function add_help_tab() {
|
||||
$link_columns_present = $this->display_links();
|
||||
$meta_columns_present = $this->display_meta_columns();
|
||||
if ( ! ( $link_columns_present || $meta_columns_present ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$help_tab_content = sprintf(
|
||||
/* translators: %1$s: Yoast SEO */
|
||||
__( '%1$s adds several columns to this page.', 'wordpress-seo' ),
|
||||
'Yoast SEO'
|
||||
);
|
||||
|
||||
if ( $meta_columns_present ) {
|
||||
$help_tab_content .= ' ' . sprintf(
|
||||
/* translators: %1$s: Link to article about content analysis, %2$s: Anchor closing */
|
||||
__( 'We\'ve written an article about %1$show to use the SEO score and Readability score%2$s.', 'wordpress-seo' ),
|
||||
'<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/16p' ) . '">',
|
||||
'</a>'
|
||||
);
|
||||
}
|
||||
|
||||
if ( $link_columns_present ) {
|
||||
$help_tab_content .= ' ' . sprintf(
|
||||
/* translators: %1$s: Link to article about text links, %2$s: Anchor closing tag, %3$s: Emphasis open tag, %4$s: Emphasis close tag */
|
||||
__( 'The links columns show the number of articles on this site linking %3$sto%4$s this article and the number of URLs linked %3$sfrom%4$s this article. Learn more about %1$show to use these features to improve your internal linking%2$s, which greatly enhances your SEO.', 'wordpress-seo' ),
|
||||
'<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/16p' ) . '">',
|
||||
'</a>',
|
||||
'<em>',
|
||||
'</em>'
|
||||
);
|
||||
}
|
||||
|
||||
$screen = get_current_screen();
|
||||
$screen->add_help_tab(
|
||||
array(
|
||||
[
|
||||
/* translators: %s expands to Yoast */
|
||||
'title' => sprintf( __( '%s Columns', 'wordpress-seo' ), 'Yoast' ),
|
||||
'id' => 'yst-columns',
|
||||
'content' => sprintf(
|
||||
/* translators: %1$s: Yoast SEO, %2$s: Link to article about content analysis, %3$s: Anchor closing, %4$s: Link to article about text links, %5$s: Emphasis open tag, %6$s: Emphasis close tag */
|
||||
'<p>' . __( '%1$s adds several columns to this page. We\'ve written an article about %2$show to use the SEO score and Readability score%3$s. The links columns show the number of articles on this site linking %5$sto%6$s this article and the number of URLs linked %5$sfrom%6$s this article. Learn more about %4$show to use these features to improve your internal linking%3$s, which greatly enhances your SEO.', 'wordpress-seo' ) . '</p>',
|
||||
'Yoast SEO',
|
||||
'<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/16p' ) . '">',
|
||||
'</a>',
|
||||
'<a href="' . WPSEO_Shortlinker::get( 'https://yoa.st/16q' ) . '">',
|
||||
'<em>',
|
||||
'</em>'
|
||||
),
|
||||
'content' => '<p>' . $help_tab_content . '</p>',
|
||||
'priority' => 15,
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the post type from the $_GET variable.
|
||||
*
|
||||
* @return string The current post type.
|
||||
*/
|
||||
private function get_current_post_type() {
|
||||
return filter_input( INPUT_GET, 'post_type' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not 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
|
||||
*/
|
||||
private function display_links() {
|
||||
$current_post_type = sanitize_text_field( $this->get_current_post_type() );
|
||||
|
||||
if ( empty( $current_post_type ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return WPSEO_Post_Type::is_post_type_accessible( $current_post_type );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private function display_meta_columns() {
|
||||
$current_post_type = sanitize_text_field( $this->get_current_post_type() );
|
||||
|
||||
if ( empty( $current_post_type ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return WPSEO_Utils::is_metabox_active( $current_post_type, 'post_type' );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,35 +6,51 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class to change or add WordPress dashboard widgets
|
||||
* Class to change or add WordPress dashboard widgets.
|
||||
*/
|
||||
class Yoast_Dashboard_Widget {
|
||||
class Yoast_Dashboard_Widget implements WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* Holds the cache transient key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CACHE_TRANSIENT_KEY = 'wpseo-dashboard-totals';
|
||||
|
||||
/**
|
||||
* Holds an instance of the admin asset manager.
|
||||
*
|
||||
* @var WPSEO_Admin_Asset_Manager
|
||||
*/
|
||||
protected $asset_manager;
|
||||
|
||||
/**
|
||||
* Holds the dashboard statistics.
|
||||
*
|
||||
* @var WPSEO_Statistics
|
||||
*/
|
||||
protected $statistics;
|
||||
|
||||
/**
|
||||
* @param WPSEO_Statistics $statistics The statistics class to retrieve statistics from.
|
||||
* Yoast_Dashboard_Widget constructor.
|
||||
*
|
||||
* @param WPSEO_Statistics|null $statistics WPSEO_Statistics instance.
|
||||
*/
|
||||
public function __construct( WPSEO_Statistics $statistics = null ) {
|
||||
if ( null === $statistics ) {
|
||||
if ( $statistics === null ) {
|
||||
$statistics = new WPSEO_Statistics();
|
||||
}
|
||||
|
||||
$this->statistics = $statistics;
|
||||
$this->asset_manager = new WPSEO_Admin_Asset_Manager();
|
||||
}
|
||||
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_dashboard_assets' ) );
|
||||
add_action( 'admin_init', array( $this, 'queue_dashboard_widget' ) );
|
||||
/**
|
||||
* Register WordPress hooks.
|
||||
*/
|
||||
public function register_hooks() {
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_dashboard_assets' ] );
|
||||
add_action( 'admin_init', [ $this, 'queue_dashboard_widget' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -44,20 +60,20 @@ class Yoast_Dashboard_Widget {
|
|||
*/
|
||||
public function queue_dashboard_widget() {
|
||||
if ( $this->show_widget() ) {
|
||||
add_action( 'wp_dashboard_setup', array( $this, 'add_dashboard_widget' ) );
|
||||
add_action( 'wp_dashboard_setup', [ $this, 'add_dashboard_widget' ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds dashboard widget to WordPress
|
||||
* Adds dashboard widget to WordPress.
|
||||
*/
|
||||
public function add_dashboard_widget() {
|
||||
add_filter( 'postbox_classes_dashboard_wpseo-dashboard-overview', array( $this, 'wpseo_dashboard_overview_class' ) );
|
||||
add_filter( 'postbox_classes_dashboard_wpseo-dashboard-overview', [ $this, 'wpseo_dashboard_overview_class' ] );
|
||||
wp_add_dashboard_widget(
|
||||
'wpseo-dashboard-overview',
|
||||
/* translators: %s is the plugin name */
|
||||
sprintf( __( '%s Posts Overview', 'wordpress-seo' ), 'Yoast SEO' ),
|
||||
array( $this, 'display_dashboard_widget' )
|
||||
[ $this, 'display_dashboard_widget' ]
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -80,19 +96,6 @@ class Yoast_Dashboard_Widget {
|
|||
echo '<div id="yoast-seo-dashboard-widget"></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues stylesheet for the dashboard if the current page is the dashboard.
|
||||
*/
|
||||
public function enqueue_dashboard_stylesheets() {
|
||||
_deprecated_function( __METHOD__, 'WPSEO 5.5', 'This method is deprecated, please use the <code>enqueue_dashboard_assets</code> method.' );
|
||||
|
||||
if ( ! $this->is_dashboard_screen() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->asset_manager->enqueue_style( 'wp-dashboard' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues assets for the dashboard if the current page is the dashboard.
|
||||
*/
|
||||
|
|
@ -101,7 +104,9 @@ class Yoast_Dashboard_Widget {
|
|||
return;
|
||||
}
|
||||
|
||||
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'dashboard-widget', 'wpseoDashboardWidgetL10n', $this->localize_dashboard_script() );
|
||||
$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' );
|
||||
}
|
||||
|
|
@ -112,23 +117,16 @@ class Yoast_Dashboard_Widget {
|
|||
* @return array The translated strings.
|
||||
*/
|
||||
public function localize_dashboard_script() {
|
||||
return array(
|
||||
return [
|
||||
'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' ),
|
||||
'ryte_header' => sprintf(
|
||||
/* translators: %1$s expands to Ryte. */
|
||||
__( 'Indexability check by %1$s', 'wordpress-seo' ),
|
||||
'Ryte'
|
||||
),
|
||||
'ryte_fetch' => __( 'Fetch the current status', 'wordpress-seo' ),
|
||||
'ryte_analyze' => __( 'Analyze entire site', 'wordpress-seo' ),
|
||||
'ryte_fetch_url' => esc_attr( add_query_arg( 'wpseo-redo-onpage', '1' ) ) . '#wpseo-dashboard-overview',
|
||||
'ryte_landing_url' => WPSEO_Shortlinker::get( 'https://yoa.st/rytelp' ),
|
||||
);
|
||||
'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,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,326 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements server-side user input validation.
|
||||
*
|
||||
* @since 12.0
|
||||
*/
|
||||
class Yoast_Input_Validation {
|
||||
|
||||
/**
|
||||
* The error descriptions.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $error_descriptions = [];
|
||||
|
||||
/**
|
||||
* Check whether an option group is a Yoast SEO setting.
|
||||
*
|
||||
* The normal pattern is 'yoast' . $option_name . 'options'.
|
||||
*
|
||||
* @since 12.0
|
||||
*
|
||||
* @param string $group_name The option group name.
|
||||
*
|
||||
* @return bool Whether or not it's an Yoast SEO option group.
|
||||
*/
|
||||
public static function is_yoast_option_group_name( $group_name ) {
|
||||
return ( strpos( $group_name, 'yoast' ) !== false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error message to the document title when submitting a settings
|
||||
* form and errors are returned.
|
||||
*
|
||||
* Uses the WordPress `admin_title` filter in the WPSEO_Option subclasses.
|
||||
*
|
||||
* @since 12.0
|
||||
*
|
||||
* @param string $admin_title The page title, with extra context added.
|
||||
*
|
||||
* @return string The modified or original admin title.
|
||||
*/
|
||||
public static function add_yoast_admin_document_title_errors( $admin_title ) {
|
||||
$errors = get_settings_errors();
|
||||
$error_count = 0;
|
||||
|
||||
foreach ( $errors as $error ) {
|
||||
// For now, filter the admin title only in the Yoast SEO settings pages.
|
||||
if ( self::is_yoast_option_group_name( $error['setting'] ) && $error['code'] !== 'settings_updated' ) {
|
||||
++$error_count;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $error_count > 0 ) {
|
||||
return sprintf(
|
||||
/* translators: %1$s: amount of errors, %2$s: the admin page title */
|
||||
_n( 'The form contains %1$s error. %2$s', 'The form contains %1$s errors. %2$s', $error_count, 'wordpress-seo' ),
|
||||
number_format_i18n( $error_count ),
|
||||
$admin_title
|
||||
);
|
||||
}
|
||||
|
||||
return $admin_title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a specific form input field was submitted with an invalid value.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @param string $error_code Must be the same slug-name used for the field variable and for `add_settings_error()`.
|
||||
*
|
||||
* @return bool Whether or not the submitted input field contained an invalid value.
|
||||
*/
|
||||
public static function yoast_form_control_has_error( $error_code ) {
|
||||
$errors = get_settings_errors();
|
||||
|
||||
foreach ( $errors as $error ) {
|
||||
if ( $error['code'] === $error_code ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the error descriptions.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @param array $descriptions An associative array of error descriptions.
|
||||
* For each entry, the key must be the setting variable.
|
||||
*/
|
||||
public static function set_error_descriptions( $descriptions = [] ) {
|
||||
$defaults = [
|
||||
'baiduverify' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Baidu verification codes can only contain letters, numbers, hyphens, and underscores. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'baiduverify' )
|
||||
),
|
||||
'facebook_site' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Please check the format of the Facebook Page URL you entered. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'facebook_site' )
|
||||
),
|
||||
'googleverify' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Google verification codes can only contain letters, numbers, hyphens, and underscores. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'googleverify' )
|
||||
),
|
||||
'instagram_url' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Please check the format of the Instagram URL you entered. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'instagram_url' )
|
||||
),
|
||||
'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' ),
|
||||
self::get_dirty_value_message( 'linkedin_url' )
|
||||
),
|
||||
'msverify' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Bing confirmation codes can only contain letters from A to F, numbers, hyphens, and underscores. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'msverify' )
|
||||
),
|
||||
'myspace_url' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Please check the format of the MySpace URL you entered. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'myspace_url' )
|
||||
),
|
||||
'pinterest_url' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Please check the format of the Pinterest URL you entered. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'pinterest_url' )
|
||||
),
|
||||
'pinterestverify' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Pinterest confirmation codes can only contain letters from A to F, numbers, hyphens, and underscores. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'pinterestverify' )
|
||||
),
|
||||
'twitter_site' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Twitter usernames can only contain letters, numbers, and underscores. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'twitter_site' )
|
||||
),
|
||||
'wikipedia_url' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Please check the format of the Wikipedia URL you entered. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'wikipedia_url' )
|
||||
),
|
||||
'yandexverify' => sprintf(
|
||||
/* translators: %s: additional message with the submitted invalid value */
|
||||
esc_html__( 'Yandex confirmation codes can only contain letters from A to F, numbers, hyphens, and underscores. %s', 'wordpress-seo' ),
|
||||
self::get_dirty_value_message( 'yandexverify' )
|
||||
),
|
||||
'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' ),
|
||||
self::get_dirty_value_message( 'youtube_url' )
|
||||
),
|
||||
];
|
||||
|
||||
$descriptions = wp_parse_args( $descriptions, $defaults );
|
||||
|
||||
self::$error_descriptions = $descriptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the error descriptions.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @return array An associative array of error descriptions.
|
||||
*/
|
||||
public static function get_error_descriptions() {
|
||||
return self::$error_descriptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a specific error description.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @param string $error_code Code of the error set via `add_settings_error()`, normally the variable name.
|
||||
*
|
||||
* @return string|null The error description.
|
||||
*/
|
||||
public static function get_error_description( $error_code ) {
|
||||
if ( ! isset( self::$error_descriptions[ $error_code ] ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$error_descriptions[ $error_code ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the aria-invalid HTML attribute based on the submitted invalid value.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @param string $error_code Code of the error set via `add_settings_error()`, normally the variable name.
|
||||
*
|
||||
* @return string The aria-invalid HTML attribute or empty string.
|
||||
*/
|
||||
public static function get_the_aria_invalid_attribute( $error_code ) {
|
||||
if ( self::yoast_form_control_has_error( $error_code ) ) {
|
||||
return ' aria-invalid="true"';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the aria-describedby HTML attribute based on the submitted invalid value.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @param string $error_code Code of the error set via `add_settings_error()`, normally the variable name.
|
||||
*
|
||||
* @return string The aria-describedby HTML attribute or empty string.
|
||||
*/
|
||||
public static function get_the_aria_describedby_attribute( $error_code ) {
|
||||
if ( self::yoast_form_control_has_error( $error_code ) && self::get_error_description( $error_code ) ) {
|
||||
return ' aria-describedby="' . esc_attr( $error_code ) . '-error-description"';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the error description wrapped in a HTML paragraph.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @param string $error_code Code of the error set via `add_settings_error()`, normally the variable name.
|
||||
*
|
||||
* @return string The error description HTML or empty string.
|
||||
*/
|
||||
public static function get_the_error_description( $error_code ) {
|
||||
$error_description = self::get_error_description( $error_code );
|
||||
|
||||
if ( self::yoast_form_control_has_error( $error_code ) && $error_description ) {
|
||||
return '<p id="' . esc_attr( $error_code ) . '-error-description" class="yoast-input-validation__error-description">' . $error_description . '</p>';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the submitted invalid value to the WordPress `$wp_settings_errors` global.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @param string $error_code Code of the error set via `add_settings_error()`, normally the variable name.
|
||||
* @param string $dirty_value The submitted invalid value.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function add_dirty_value_to_settings_errors( $error_code, $dirty_value ) {
|
||||
global $wp_settings_errors;
|
||||
|
||||
if ( ! is_array( $wp_settings_errors ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $wp_settings_errors as $index => $error ) {
|
||||
if ( $error['code'] === $error_code ) {
|
||||
// phpcs:ignore WordPress.WP.GlobalVariablesOverride -- This is a deliberate action.
|
||||
$wp_settings_errors[ $index ]['yoast_dirty_value'] = $dirty_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an invalid submitted value.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @param string $error_code Code of the error set via `add_settings_error()`, normally the variable name.
|
||||
*
|
||||
* @return string The submitted invalid input field value.
|
||||
*/
|
||||
public static function get_dirty_value( $error_code ) {
|
||||
$errors = get_settings_errors();
|
||||
|
||||
foreach ( $errors as $error ) {
|
||||
if ( $error['code'] === $error_code && isset( $error['yoast_dirty_value'] ) ) {
|
||||
return $error['yoast_dirty_value'];
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a specific invalid value message.
|
||||
*
|
||||
* @since 12.1
|
||||
*
|
||||
* @param string $error_code Code of the error set via `add_settings_error()`, normally the variable name.
|
||||
*
|
||||
* @return string The error invalid value message or empty string.
|
||||
*/
|
||||
public static function get_dirty_value_message( $error_code ) {
|
||||
$dirty_value = self::get_dirty_value( $error_code );
|
||||
|
||||
if ( $dirty_value ) {
|
||||
return sprintf(
|
||||
/* translators: %s: form value as submitted. */
|
||||
esc_html__( 'The submitted value was: %s', 'wordpress-seo' ),
|
||||
esc_html( $dirty_value )
|
||||
);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,324 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Internals
|
||||
*/
|
||||
|
||||
/**
|
||||
* Multisite utility class for network admin functionality.
|
||||
*/
|
||||
class Yoast_Network_Admin implements WPSEO_WordPress_AJAX_Integration, WPSEO_WordPress_Integration {
|
||||
|
||||
/**
|
||||
* Action identifier for updating plugin network options.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const UPDATE_OPTIONS_ACTION = 'yoast_handle_network_options';
|
||||
|
||||
/**
|
||||
* Action identifier for restoring a site.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const RESTORE_SITE_ACTION = 'yoast_restore_site';
|
||||
|
||||
/**
|
||||
* Gets the available sites as choices, e.g. for a dropdown.
|
||||
*
|
||||
* @param bool $include_empty Optional. Whether to include an initial placeholder choice.
|
||||
* Default false.
|
||||
* @param bool $show_title Optional. Whether to show the title for each site. This requires
|
||||
* switching through the sites, so has performance implications for
|
||||
* sites that do not use a persistent cache.
|
||||
* Default false.
|
||||
*
|
||||
* @return array Choices as $site_id => $site_label pairs.
|
||||
*/
|
||||
public function get_site_choices( $include_empty = false, $show_title = false ) {
|
||||
$choices = [];
|
||||
|
||||
if ( $include_empty ) {
|
||||
$choices['-'] = __( 'None', 'wordpress-seo' );
|
||||
}
|
||||
|
||||
$criteria = [
|
||||
'deleted' => 0,
|
||||
'network_id' => get_current_network_id(),
|
||||
];
|
||||
$sites = get_sites( $criteria );
|
||||
|
||||
foreach ( $sites as $site ) {
|
||||
$site_name = $site->domain . $site->path;
|
||||
if ( $show_title ) {
|
||||
$site_name = $site->blogname . ' (' . $site->domain . $site->path . ')';
|
||||
}
|
||||
$choices[ $site->blog_id ] = $site->blog_id . ': ' . $site_name;
|
||||
|
||||
$site_states = $this->get_site_states( $site );
|
||||
if ( ! empty( $site_states ) ) {
|
||||
$choices[ $site->blog_id ] .= ' [' . implode( ', ', $site_states ) . ']';
|
||||
}
|
||||
}
|
||||
|
||||
return $choices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the states of a site.
|
||||
*
|
||||
* @param WP_Site $site Site object.
|
||||
*
|
||||
* @return array Array of $state_slug => $state_label pairs.
|
||||
*/
|
||||
public function get_site_states( $site ) {
|
||||
$available_states = [
|
||||
'public' => __( 'public', 'wordpress-seo' ),
|
||||
'archived' => __( 'archived', 'wordpress-seo' ),
|
||||
'mature' => __( 'mature', 'wordpress-seo' ),
|
||||
'spam' => __( 'spam', 'wordpress-seo' ),
|
||||
'deleted' => __( 'deleted', 'wordpress-seo' ),
|
||||
];
|
||||
|
||||
$site_states = [];
|
||||
foreach ( $available_states as $state_slug => $state_label ) {
|
||||
if ( $site->$state_slug === '1' ) {
|
||||
$site_states[ $state_slug ] = $state_label;
|
||||
}
|
||||
}
|
||||
|
||||
return $site_states;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a request to update plugin network options.
|
||||
*
|
||||
* This method works similar to how option updates are handled in `wp-admin/options.php` and
|
||||
* `wp-admin/network/settings.php`.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_update_options_request() {
|
||||
$option_group = filter_input( INPUT_POST, 'network_option_group', FILTER_SANITIZE_STRING );
|
||||
|
||||
$this->verify_request( "{$option_group}-network-options" );
|
||||
|
||||
$whitelist_options = Yoast_Network_Settings_API::get()->get_whitelist_options( $option_group );
|
||||
|
||||
if ( empty( $whitelist_options ) ) {
|
||||
add_settings_error( $option_group, 'settings_updated', __( 'You are not allowed to modify unregistered network settings.', 'wordpress-seo' ), 'error' );
|
||||
|
||||
$this->terminate_request();
|
||||
return;
|
||||
}
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification -- Nonce verified via `verify_request()` above.
|
||||
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.
|
||||
$value = wp_unslash( $_POST[ $option_name ] );
|
||||
}
|
||||
|
||||
WPSEO_Options::update_site_option( $option_name, $value );
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification
|
||||
|
||||
$settings_errors = get_settings_errors();
|
||||
if ( empty( $settings_errors ) ) {
|
||||
add_settings_error( $option_group, 'settings_updated', __( 'Settings Updated.', 'wordpress-seo' ), 'updated' );
|
||||
}
|
||||
|
||||
$this->terminate_request();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a request to restore a site's default settings.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_restore_site_request() {
|
||||
$this->verify_request( 'wpseo-network-restore', 'restore_site_nonce' );
|
||||
|
||||
$option_group = 'wpseo_ms';
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification -- Nonce verified via `verify_request()` above.
|
||||
$site_id = ! empty( $_POST[ $option_group ]['site_id'] ) ? (int) $_POST[ $option_group ]['site_id'] : 0;
|
||||
if ( ! $site_id ) {
|
||||
add_settings_error( $option_group, 'settings_updated', __( 'No site has been selected to restore.', 'wordpress-seo' ), 'error' );
|
||||
|
||||
$this->terminate_request();
|
||||
return;
|
||||
}
|
||||
|
||||
$site = get_site( $site_id );
|
||||
if ( ! $site ) {
|
||||
/* translators: %s expands to the ID of a site within a multisite network. */
|
||||
add_settings_error( $option_group, 'settings_updated', sprintf( __( 'Site with ID %d not found.', 'wordpress-seo' ), $site_id ), 'error' );
|
||||
}
|
||||
else {
|
||||
WPSEO_Options::reset_ms_blog( $site_id );
|
||||
|
||||
/* translators: %s expands to the name of a site within a multisite network. */
|
||||
add_settings_error( $option_group, 'settings_updated', sprintf( __( '%s restored to default SEO settings.', 'wordpress-seo' ), esc_html( $site->blogname ) ), 'updated' );
|
||||
}
|
||||
|
||||
$this->terminate_request();
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs nonce, action and option group fields for a network settings page in the plugin.
|
||||
*
|
||||
* @param string $option_group Option group name for the current page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function settings_fields( $option_group ) {
|
||||
?>
|
||||
<input type="hidden" name="network_option_group" value="<?php echo esc_attr( $option_group ); ?>" />
|
||||
<input type="hidden" name="action" value="<?php echo esc_attr( self::UPDATE_OPTIONS_ACTION ); ?>" />
|
||||
<?php
|
||||
wp_nonce_field( "$option_group-network-options" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues network admin assets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_assets() {
|
||||
$asset_manager = new WPSEO_Admin_Asset_Manager();
|
||||
$asset_manager->enqueue_script( 'network-admin' );
|
||||
|
||||
$translations = [
|
||||
/* translators: %s: success message */
|
||||
'success_prefix' => __( 'Success: %s', 'wordpress-seo' ),
|
||||
/* translators: %s: error message */
|
||||
'error_prefix' => __( 'Error: %s', 'wordpress-seo' ),
|
||||
];
|
||||
$asset_manager->localize_script(
|
||||
'network-admin',
|
||||
'wpseoNetworkAdminGlobalL10n',
|
||||
$translations
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks in the necessary actions and filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks() {
|
||||
|
||||
if ( ! $this->meets_requirements() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
||||
|
||||
add_action( 'admin_action_' . self::UPDATE_OPTIONS_ACTION, [ $this, 'handle_update_options_request' ] );
|
||||
add_action( 'admin_action_' . self::RESTORE_SITE_ACTION, [ $this, 'handle_restore_site_request' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks in the necessary AJAX actions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_ajax_hooks() {
|
||||
add_action( 'wp_ajax_' . self::UPDATE_OPTIONS_ACTION, [ $this, 'handle_update_options_request' ] );
|
||||
add_action( 'wp_ajax_' . self::RESTORE_SITE_ACTION, [ $this, 'handle_restore_site_request' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the requirements to use this class are met.
|
||||
*
|
||||
* @return bool True if requirements are met, false otherwise.
|
||||
*/
|
||||
public function meets_requirements() {
|
||||
return is_multisite() && is_network_admin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the current request is valid.
|
||||
*
|
||||
* @param string $action Nonce action.
|
||||
* @param string $query_arg Optional. Nonce query argument. Default '_wpnonce'.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function verify_request( $action, $query_arg = '_wpnonce' ) {
|
||||
$has_access = current_user_can( 'wpseo_manage_network_options' );
|
||||
|
||||
if ( wp_doing_ajax() ) {
|
||||
check_ajax_referer( $action, $query_arg );
|
||||
|
||||
if ( ! $has_access ) {
|
||||
wp_die( -1, 403 );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
check_admin_referer( $action, $query_arg );
|
||||
|
||||
if ( ! $has_access ) {
|
||||
wp_die( esc_html__( 'You are not allowed to perform this action.', 'wordpress-seo' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates the current request by either redirecting back or sending an AJAX response.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function terminate_request() {
|
||||
if ( wp_doing_ajax() ) {
|
||||
$settings_errors = get_settings_errors();
|
||||
|
||||
if ( ! empty( $settings_errors ) && $settings_errors[0]['type'] === 'updated' ) {
|
||||
wp_send_json_success( $settings_errors, 200 );
|
||||
}
|
||||
|
||||
wp_send_json_error( $settings_errors, 400 );
|
||||
}
|
||||
|
||||
$this->persist_settings_errors();
|
||||
$this->redirect_back( [ 'settings-updated' => 'true' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists settings errors.
|
||||
*
|
||||
* Settings errors are stored in a transient for 30 seconds so that this transient
|
||||
* can be retrieved on the next page load.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function persist_settings_errors() {
|
||||
/*
|
||||
* A regular transient is used here, since it is automatically cleared right after the redirect.
|
||||
* A network transient would be cleaner, but would require a lot of copied code from core for
|
||||
* just a minor adjustment when displaying settings errors.
|
||||
*/
|
||||
set_transient( 'settings_errors', get_settings_errors(), 30 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirects back to the referer URL, with optional query arguments.
|
||||
*
|
||||
* @param array $query_args Optional. Query arguments to add to the redirect URL. Default none.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function redirect_back( $query_args = [] ) {
|
||||
$sendback = wp_get_referer();
|
||||
|
||||
if ( ! empty( $query_args ) ) {
|
||||
$sendback = add_query_arg( $query_args, $sendback );
|
||||
}
|
||||
|
||||
wp_safe_redirect( $sendback );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Network
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements a network settings API for the plugin's multisite settings.
|
||||
*/
|
||||
class Yoast_Network_Settings_API {
|
||||
|
||||
/**
|
||||
* Registered network settings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $registered_settings = [];
|
||||
|
||||
/**
|
||||
* Options whitelist, keyed by option group.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $whitelist_options = [];
|
||||
|
||||
/**
|
||||
* The singleton instance of this class.
|
||||
*
|
||||
* @var Yoast_Network_Settings_API
|
||||
*/
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* Registers a network setting and its data.
|
||||
*
|
||||
* @param string $option_group The group the network option is part of.
|
||||
* @param string $option_name The name of the network option to sanitize and save.
|
||||
* @param array $args {
|
||||
* Optional. Data used to describe the network setting when registered.
|
||||
*
|
||||
* @type callable $sanitize_callback A callback function that sanitizes the network option's value.
|
||||
* @type mixed $default Default value when calling `get_network_option()`.
|
||||
* }
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_setting( $option_group, $option_name, $args = [] ) {
|
||||
|
||||
$defaults = [
|
||||
'group' => $option_group,
|
||||
'sanitize_callback' => null,
|
||||
];
|
||||
$args = wp_parse_args( $args, $defaults );
|
||||
|
||||
if ( ! isset( $this->whitelist_options[ $option_group ] ) ) {
|
||||
$this->whitelist_options[ $option_group ] = [];
|
||||
}
|
||||
|
||||
$this->whitelist_options[ $option_group ][] = $option_name;
|
||||
|
||||
if ( ! empty( $args['sanitize_callback'] ) ) {
|
||||
add_filter( "sanitize_option_{$option_name}", [ $this, 'filter_sanitize_option' ], 10, 2 );
|
||||
}
|
||||
|
||||
if ( array_key_exists( 'default', $args ) ) {
|
||||
add_filter( "default_site_option_{$option_name}", [ $this, 'filter_default_option' ], 10, 2 );
|
||||
}
|
||||
|
||||
$this->registered_settings[ $option_name ] = $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered settings and their data.
|
||||
*
|
||||
* @return array Array of $option_name => $data pairs.
|
||||
*/
|
||||
public function get_registered_settings() {
|
||||
return $this->registered_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the whitelisted options for a given option group.
|
||||
*
|
||||
* @param string $option_group Option group.
|
||||
*
|
||||
* @return array List of option names, or empty array if unknown option group.
|
||||
*/
|
||||
public function get_whitelist_options( $option_group ) {
|
||||
if ( ! isset( $this->whitelist_options[ $option_group ] ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->whitelist_options[ $option_group ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters sanitization for a network option value.
|
||||
*
|
||||
* This method is added as a filter to `sanitize_option_{$option}` for network options that are
|
||||
* registered with a sanitize callback.
|
||||
*
|
||||
* @param string $value The sanitized option value.
|
||||
* @param string $option The option name.
|
||||
*
|
||||
* @return string The filtered sanitized option value.
|
||||
*/
|
||||
public function filter_sanitize_option( $value, $option ) {
|
||||
|
||||
if ( empty( $this->registered_settings[ $option ] ) ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return call_user_func( $this->registered_settings[ $option ]['sanitize_callback'], $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the default value for a network option.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @return mixed The filtered default value.
|
||||
*/
|
||||
public function filter_default_option( $default, $option ) {
|
||||
|
||||
// If a default value was manually passed to the function, allow it to override.
|
||||
if ( $default !== false ) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
if ( empty( $this->registered_settings[ $option ] ) ) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->registered_settings[ $option ]['default'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the requirements to use this class are met.
|
||||
*
|
||||
* @return bool True if requirements are met, false otherwise.
|
||||
*/
|
||||
public function meets_requirements() {
|
||||
return is_multisite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the singleton instance of this class.
|
||||
*
|
||||
* @return Yoast_Network_Settings_API The singleton instance.
|
||||
*/
|
||||
public static function get() {
|
||||
|
||||
if ( self::$instance === null ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,49 +5,92 @@
|
|||
* @package WPSEO\Admin\Notifications
|
||||
*/
|
||||
|
||||
use Yoast\WP\SEO\Presenters\Abstract_Presenter;
|
||||
|
||||
/**
|
||||
* Handles notifications storage and display.
|
||||
*/
|
||||
class Yoast_Notification_Center {
|
||||
|
||||
/** Option name to store notifications on */
|
||||
/**
|
||||
* Option name to store notifications on.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const STORAGE_KEY = 'yoast_notifications';
|
||||
|
||||
/** @var \Yoast_Notification_Center The singleton instance of this object */
|
||||
/**
|
||||
* The singleton instance of this object.
|
||||
*
|
||||
* @var \Yoast_Notification_Center
|
||||
*/
|
||||
private static $instance = null;
|
||||
|
||||
/** @var $notifications Yoast_Notification[] */
|
||||
private $notifications = array();
|
||||
/**
|
||||
* Holds the notifications.
|
||||
*
|
||||
* @var \Yoast_Notification[][]
|
||||
*/
|
||||
private $notifications = [];
|
||||
|
||||
/** @var array Notifications there are newly added */
|
||||
private $new = array();
|
||||
/**
|
||||
* Notifications there are newly added.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $new = [];
|
||||
|
||||
/** @var array Notifications that were resolved this execution */
|
||||
/**
|
||||
* Notifications that were resolved this execution.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $resolved = 0;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
* Internal storage for transaction before notifications have been retrieved from storage.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $queued_transactions = [];
|
||||
|
||||
/**
|
||||
* Internal flag for whether notifications have been retrieved from storage.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $notifications_retrieved = false;
|
||||
|
||||
/**
|
||||
* Internal flag for whether notifications need to be updated in storage.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $notifications_need_storage = false;
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*/
|
||||
private function __construct() {
|
||||
|
||||
$this->retrieve_notifications_from_storage();
|
||||
add_action( 'init', [ $this, 'setup_current_notifications' ], 1 );
|
||||
|
||||
add_action( 'all_admin_notices', array( $this, 'display_notifications' ) );
|
||||
add_action( 'all_admin_notices', [ $this, 'display_notifications' ] );
|
||||
|
||||
add_action( 'wp_ajax_yoast_get_notifications', array( $this, 'ajax_get_notifications' ) );
|
||||
add_action( 'wp_ajax_yoast_get_notifications', [ $this, 'ajax_get_notifications' ] );
|
||||
|
||||
add_action( 'wpseo_deactivate', array( $this, 'deactivate_hook' ) );
|
||||
add_action( 'shutdown', array( $this, 'update_storage' ) );
|
||||
add_action( 'wpseo_deactivate', [ $this, 'deactivate_hook' ] );
|
||||
add_action( 'shutdown', [ $this, 'update_storage' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton getter
|
||||
* Singleton getter.
|
||||
*
|
||||
* @return Yoast_Notification_Center
|
||||
*/
|
||||
public static function get() {
|
||||
|
||||
if ( null === self::$instance ) {
|
||||
if ( self::$instance === null ) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +98,7 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Dismiss a notification
|
||||
* Dismiss a notification.
|
||||
*/
|
||||
public static function ajax_dismiss_notification() {
|
||||
|
||||
|
|
@ -67,16 +110,17 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
$notification = $notification_center->get_notification_by_id( $notification_id );
|
||||
if ( false === ( $notification instanceof Yoast_Notification ) ) {
|
||||
if ( ( $notification instanceof Yoast_Notification ) === false ) {
|
||||
|
||||
// Permit legacy.
|
||||
$notification = new Yoast_Notification( '', array(
|
||||
$options = [
|
||||
'id' => $notification_id,
|
||||
'dismissal_key' => $notification_id,
|
||||
) );
|
||||
];
|
||||
$notification = new Yoast_Notification( '', $options );
|
||||
}
|
||||
|
||||
if ( $notification_center->maybe_dismiss_notification( $notification ) ) {
|
||||
if ( self::maybe_dismiss_notification( $notification ) ) {
|
||||
die( '1' );
|
||||
}
|
||||
|
||||
|
|
@ -84,28 +128,36 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if the user has dismissed a notification
|
||||
* Check if the user has dismissed a notification.
|
||||
*
|
||||
* @param Yoast_Notification $notification The notification to check for dismissal.
|
||||
* @param null|int $user_id User ID to check on.
|
||||
* @param int|null $user_id User ID to check on.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_notification_dismissed( Yoast_Notification $notification, $user_id = null ) {
|
||||
|
||||
$user_id = ( ! is_null( $user_id ) ? $user_id : get_current_user_id() );
|
||||
$user_id = self::get_user_id( $user_id );
|
||||
$dismissal_key = $notification->get_dismissal_key();
|
||||
|
||||
$current_value = get_user_meta( $user_id, $dismissal_key, true );
|
||||
// This checks both the site-specific user option and the meta value.
|
||||
$current_value = get_user_option( $dismissal_key, $user_id );
|
||||
|
||||
// Migrate old user meta to user option on-the-fly.
|
||||
if ( ! empty( $current_value )
|
||||
&& metadata_exists( 'user', $user_id, $dismissal_key )
|
||||
&& update_user_option( $user_id, $dismissal_key, $current_value ) ) {
|
||||
delete_user_meta( $user_id, $dismissal_key );
|
||||
}
|
||||
|
||||
return ! empty( $current_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the nofitication is being dismissed
|
||||
* Checks if the notification is being dismissed.
|
||||
*
|
||||
* @param string|Yoast_Notification $notification Notification to check dismissal of.
|
||||
* @param string $meta_value Value to set the meta value to if dismissed.
|
||||
* @param Yoast_Notification $notification Notification to check dismissal of.
|
||||
* @param string $meta_value Value to set the meta value to if dismissed.
|
||||
*
|
||||
* @return bool True if dismissed.
|
||||
*/
|
||||
|
|
@ -131,7 +183,7 @@ class Yoast_Notification_Center {
|
|||
|
||||
// Fallback to ?dismissal_key=1&nonce=bla when JavaScript fails.
|
||||
if ( ! $is_dismissing ) {
|
||||
$is_dismissing = ( '1' === self::get_user_input( $dismissal_key ) );
|
||||
$is_dismissing = ( self::get_user_input( $dismissal_key ) === '1' );
|
||||
}
|
||||
|
||||
if ( ! $is_dismissing ) {
|
||||
|
|
@ -139,7 +191,7 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
$user_nonce = self::get_user_input( 'nonce' );
|
||||
if ( false === wp_verify_nonce( $user_nonce, $notification_id ) ) {
|
||||
if ( wp_verify_nonce( $user_nonce, $notification_id ) === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -147,7 +199,43 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Clear dismissal information for the specified Notification
|
||||
* Dismisses a notification.
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to dismiss.
|
||||
* @param string $meta_value Value to save in the dismissal.
|
||||
*
|
||||
* @return bool True if dismissed, false otherwise.
|
||||
*/
|
||||
public static function dismiss_notification( Yoast_Notification $notification, $meta_value = 'seen' ) {
|
||||
// Dismiss notification.
|
||||
return update_user_option( get_current_user_id(), $notification->get_dismissal_key(), $meta_value ) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores a notification.
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to restore.
|
||||
*
|
||||
* @return bool True if restored, false otherwise.
|
||||
*/
|
||||
public static function restore_notification( Yoast_Notification $notification ) {
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$dismissal_key = $notification->get_dismissal_key();
|
||||
|
||||
// Restore notification.
|
||||
$restored = delete_user_option( $user_id, $dismissal_key );
|
||||
|
||||
// Delete unprefixed user meta too for backward-compatibility.
|
||||
if ( metadata_exists( 'user', $user_id, $dismissal_key ) ) {
|
||||
$restored = delete_user_meta( $user_id, $dismissal_key ) && $restored;
|
||||
}
|
||||
|
||||
return $restored;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear dismissal information for the specified Notification.
|
||||
*
|
||||
* When a cause is resolved, the next time it is present we want to show
|
||||
* the message again.
|
||||
|
|
@ -158,6 +246,8 @@ class Yoast_Notification_Center {
|
|||
*/
|
||||
public function clear_dismissal( $notification ) {
|
||||
|
||||
global $wpdb;
|
||||
|
||||
if ( $notification instanceof Yoast_Notification ) {
|
||||
$dismissal_key = $notification->get_dismissal_key();
|
||||
}
|
||||
|
|
@ -171,30 +261,62 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
// Remove notification dismissal for all users.
|
||||
$deleted = delete_metadata( 'user', 0, $dismissal_key, '', true );
|
||||
$deleted = delete_metadata( 'user', 0, $wpdb->get_blog_prefix() . $dismissal_key, '', true );
|
||||
|
||||
// Delete unprefixed user meta too for backward-compatibility.
|
||||
$deleted = delete_metadata( 'user', 0, $dismissal_key, '', true ) || $deleted;
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add notification to the cookie
|
||||
* Retrieves notifications from the storage and merges in previous notification changes.
|
||||
*
|
||||
* The current user in WordPress is not loaded shortly before the 'init' hook, but the plugin
|
||||
* sometimes needs to add or remove notifications before that. In such cases, the transactions
|
||||
* are not actually executed, but added to a queue. That queue is then handled in this method,
|
||||
* after notifications for the current user have been set up.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setup_current_notifications() {
|
||||
$this->retrieve_notifications_from_storage( get_current_user_id() );
|
||||
|
||||
foreach ( $this->queued_transactions as $transaction ) {
|
||||
list( $callback, $args ) = $transaction;
|
||||
|
||||
call_user_func_array( $callback, $args );
|
||||
}
|
||||
|
||||
$this->queued_transactions = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add notification to the cookie.
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification object instance.
|
||||
*/
|
||||
public function add_notification( Yoast_Notification $notification ) {
|
||||
|
||||
$callback = [ $this, __METHOD__ ];
|
||||
$args = func_get_args();
|
||||
if ( $this->queue_transaction( $callback, $args ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't add if the user can't see it.
|
||||
if ( ! $notification->display_for_current_user() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$notification_id = $notification->get_id();
|
||||
$user_id = $notification->get_user_id();
|
||||
|
||||
// Empty notifications are always added.
|
||||
if ( $notification_id !== '' ) {
|
||||
|
||||
// If notification ID exists in notifications, don't add again.
|
||||
$present_notification = $this->get_notification_by_id( $notification_id );
|
||||
$present_notification = $this->get_notification_by_id( $notification_id, $user_id );
|
||||
if ( ! is_null( $present_notification ) ) {
|
||||
$this->remove_notification( $present_notification, false );
|
||||
}
|
||||
|
|
@ -205,19 +327,25 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
// Add to list.
|
||||
$this->notifications[] = $notification;
|
||||
$this->notifications[ $user_id ][] = $notification;
|
||||
|
||||
$this->notifications_need_storage = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification by ID
|
||||
* Get the notification by ID and user ID.
|
||||
*
|
||||
* @param string $notification_id The ID of the notification to search for.
|
||||
* @param string $notification_id The ID of the notification to search for.
|
||||
* @param int|null $user_id The ID of the user.
|
||||
*
|
||||
* @return null|Yoast_Notification
|
||||
* @return Yoast_Notification|null
|
||||
*/
|
||||
public function get_notification_by_id( $notification_id ) {
|
||||
public function get_notification_by_id( $notification_id, $user_id = null ) {
|
||||
$user_id = self::get_user_id( $user_id );
|
||||
|
||||
foreach ( $this->notifications as & $notification ) {
|
||||
$notifications = $this->get_notifications_for_user( $user_id );
|
||||
|
||||
foreach ( $notifications as $notification ) {
|
||||
if ( $notification_id === $notification->get_id() ) {
|
||||
return $notification;
|
||||
}
|
||||
|
|
@ -227,7 +355,7 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Display the notifications
|
||||
* Display the notifications.
|
||||
*
|
||||
* @param bool $echo_as_json True when notifications should be printed directly.
|
||||
*
|
||||
|
|
@ -236,48 +364,62 @@ class Yoast_Notification_Center {
|
|||
public function display_notifications( $echo_as_json = false ) {
|
||||
|
||||
// Never display notifications for network admin.
|
||||
if ( function_exists( 'is_network_admin' ) && is_network_admin() ) {
|
||||
if ( is_network_admin() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sorted_notifications = $this->get_sorted_notifications();
|
||||
$notifications = array_filter( $sorted_notifications, array( $this, 'is_notification_persistent' ) );
|
||||
$notifications = array_filter( $sorted_notifications, [ $this, 'is_notification_persistent' ] );
|
||||
|
||||
if ( empty( $notifications ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
array_walk( $notifications, array( $this, 'remove_notification' ) );
|
||||
array_walk( $notifications, [ $this, 'remove_notification' ] );
|
||||
|
||||
$notifications = array_unique( $notifications );
|
||||
if ( $echo_as_json ) {
|
||||
$notification_json = array();
|
||||
$notification_json = [];
|
||||
|
||||
foreach ( $notifications as $notification ) {
|
||||
$notification_json[] = $notification->render();
|
||||
}
|
||||
|
||||
echo json_encode( $notification_json );
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
|
||||
echo WPSEO_Utils::format_json_encode( $notification_json );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $notifications as $notification ) {
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Temporarily disabled, see: https://github.com/Yoast/wordpress-seo-premium/issues/2510 and https://github.com/Yoast/wordpress-seo-premium/issues/2511.
|
||||
echo $notification;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove notification after it has been displayed
|
||||
* Remove notification after it has been displayed.
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to remove.
|
||||
* @param bool $resolve Resolve as fixed.
|
||||
* @param bool $resolve Resolve as fixed.
|
||||
*/
|
||||
public function remove_notification( Yoast_Notification $notification, $resolve = true ) {
|
||||
|
||||
$callback = [ $this, __METHOD__ ];
|
||||
$args = func_get_args();
|
||||
if ( $this->queue_transaction( $callback, $args ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$index = false;
|
||||
|
||||
// ID of the user to show the notification for, defaults to current user id.
|
||||
$user_id = $notification->get_user_id();
|
||||
$notifications = $this->get_notifications_for_user( $user_id );
|
||||
|
||||
// Match persistent Notifications by ID, non persistent by item in the array.
|
||||
if ( $notification->is_persistent() ) {
|
||||
foreach ( $this->notifications as $current_index => $present_notification ) {
|
||||
foreach ( $notifications as $current_index => $present_notification ) {
|
||||
if ( $present_notification->get_id() === $notification->get_id() ) {
|
||||
$index = $current_index;
|
||||
break;
|
||||
|
|
@ -285,24 +427,45 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
}
|
||||
else {
|
||||
$index = array_search( $notification, $this->notifications, true );
|
||||
$index = array_search( $notification, $notifications, true );
|
||||
}
|
||||
|
||||
if ( false === $index ) {
|
||||
if ( $index === false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $notification->is_persistent() && $resolve ) {
|
||||
$this->resolved++;
|
||||
++$this->resolved;
|
||||
$this->clear_dismissal( $notification );
|
||||
}
|
||||
|
||||
unset( $this->notifications[ $index ] );
|
||||
$this->notifications = array_values( $this->notifications );
|
||||
unset( $notifications[ $index ] );
|
||||
$this->notifications[ $user_id ] = array_values( $notifications );
|
||||
|
||||
$this->notifications_need_storage = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification count
|
||||
* Removes a notification by its ID.
|
||||
*
|
||||
* @param string $notification_id The notification id.
|
||||
* @param bool $resolve Resolve as fixed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function remove_notification_by_id( $notification_id, $resolve = true ) {
|
||||
$notification = $this->get_notification_by_id( $notification_id );
|
||||
|
||||
if ( $notification === null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->remove_notification( $notification, $resolve );
|
||||
$this->notifications_need_storage = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification count.
|
||||
*
|
||||
* @param bool $dismissed Count dismissed notifications.
|
||||
*
|
||||
|
|
@ -310,18 +473,18 @@ class Yoast_Notification_Center {
|
|||
*/
|
||||
public function get_notification_count( $dismissed = false ) {
|
||||
|
||||
$notifications = $this->get_notifications();
|
||||
$notifications = array_filter( $notifications, array( $this, 'filter_persistent_notifications' ) );
|
||||
$notifications = $this->get_notifications_for_user( get_current_user_id() );
|
||||
$notifications = array_filter( $notifications, [ $this, 'filter_persistent_notifications' ] );
|
||||
|
||||
if ( ! $dismissed ) {
|
||||
$notifications = array_filter( $notifications, array( $this, 'filter_dismissed_notifications' ) );
|
||||
$notifications = array_filter( $notifications, [ $this, 'filter_dismissed_notifications' ] );
|
||||
}
|
||||
|
||||
return count( $notifications );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of notifications resolved this execution
|
||||
* Get the number of notifications resolved this execution.
|
||||
*
|
||||
* These notifications have been resolved and should be counted when active again.
|
||||
*
|
||||
|
|
@ -333,25 +496,24 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the notifications sorted on type and priority
|
||||
* Return the notifications sorted on type and priority.
|
||||
*
|
||||
* @return array|Yoast_Notification[] Sorted Notifications
|
||||
*/
|
||||
public function get_sorted_notifications() {
|
||||
|
||||
$notifications = $this->get_notifications();
|
||||
$notifications = $this->get_notifications_for_user( get_current_user_id() );
|
||||
if ( empty( $notifications ) ) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
// Sort by severity, error first.
|
||||
usort( $notifications, array( $this, 'sort_notifications' ) );
|
||||
usort( $notifications, [ $this, 'sort_notifications' ] );
|
||||
|
||||
return $notifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX display notifications
|
||||
* AJAX display notifications.
|
||||
*/
|
||||
public function ajax_get_notifications() {
|
||||
$echo = filter_input( INPUT_POST, 'version' ) === '2';
|
||||
|
|
@ -364,7 +526,7 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Remove storage when the plugin is deactivated
|
||||
* Remove storage when the plugin is deactivated.
|
||||
*/
|
||||
public function deactivate_hook() {
|
||||
|
||||
|
|
@ -372,7 +534,40 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Save persistent notifications to storage
|
||||
* Returns the given user ID if it exists.
|
||||
* Otherwise, this function returns the ID of the current user.
|
||||
*
|
||||
* @param int $user_id The user ID to check.
|
||||
*
|
||||
* @return int The user ID to use.
|
||||
*/
|
||||
private static function get_user_id( $user_id ) {
|
||||
if ( $user_id ) {
|
||||
return $user_id;
|
||||
}
|
||||
return get_current_user_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the notifications on user ID.
|
||||
*
|
||||
* In other terms, it returns an associative array,
|
||||
* mapping user ID to a list of notifications for this user.
|
||||
*
|
||||
* @param array|Yoast_Notification[] $notifications The notifications to split.
|
||||
*
|
||||
* @return array The notifications, split on user ID.
|
||||
*/
|
||||
private function split_on_user_id( $notifications ) {
|
||||
$split_notifications = [];
|
||||
foreach ( $notifications as $notification ) {
|
||||
$split_notifications[ $notification->get_user_id() ][] = $notification;
|
||||
}
|
||||
return $split_notifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save persistent notifications to storage.
|
||||
*
|
||||
* We need to be able to retrieve these so they can be dismissed at any time during the execution.
|
||||
*
|
||||
|
|
@ -382,50 +577,97 @@ class Yoast_Notification_Center {
|
|||
*/
|
||||
public function update_storage() {
|
||||
|
||||
$notifications = $this->get_notifications();
|
||||
$notifications = $this->notifications;
|
||||
|
||||
/**
|
||||
* One array of Yoast_Notifications, merged from multiple arrays.
|
||||
*
|
||||
* @var Yoast_Notification[] $merged_notifications
|
||||
*/
|
||||
$merged_notifications = [];
|
||||
if ( ! empty( $notifications ) ) {
|
||||
$merged_notifications = array_merge( ...$notifications );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter: 'yoast_notifications_before_storage' - Allows developer to filter notifications before saving them.
|
||||
*
|
||||
* @api Yoast_Notification[] $notifications
|
||||
*/
|
||||
$notifications = apply_filters( 'yoast_notifications_before_storage', $notifications );
|
||||
$filtered_merged_notifications = apply_filters( 'yoast_notifications_before_storage', $merged_notifications );
|
||||
|
||||
// No notifications to store, clear storage.
|
||||
// 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 );
|
||||
|
||||
// No notifications to store, clear storage if it was previously present.
|
||||
if ( empty( $notifications ) ) {
|
||||
$this->remove_storage();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$notifications = array_map( array( $this, 'notification_to_array' ), $notifications );
|
||||
|
||||
// Save the notifications to the storage.
|
||||
update_user_option( get_current_user_id(), self::STORAGE_KEY, $notifications );
|
||||
// Only store notifications if changes are made.
|
||||
if ( $this->notifications_need_storage ) {
|
||||
array_walk( $notifications, [ $this, 'store_notifications_for_user' ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a way to verify present notifications
|
||||
* Stores the notifications to its respective user's storage.
|
||||
*
|
||||
* @param array|Yoast_Notification[] $notifications The notifications to store.
|
||||
* @param int $user_id The ID of the user for which to store the notifications.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function store_notifications_for_user( $notifications, $user_id ) {
|
||||
$notifications_as_arrays = array_map( [ $this, 'notification_to_array' ], $notifications );
|
||||
update_user_option( $user_id, self::STORAGE_KEY, $notifications_as_arrays );
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a way to verify present notifications.
|
||||
*
|
||||
* @return array|Yoast_Notification[] Registered notifications.
|
||||
*/
|
||||
public function get_notifications() {
|
||||
|
||||
return $this->notifications;
|
||||
if ( ! $this->notifications ) {
|
||||
return [];
|
||||
}
|
||||
return array_merge( ...$this->notifications );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get newly added notifications
|
||||
* Returns the notifications for the given user.
|
||||
*
|
||||
* @param int $user_id The id of the user to check.
|
||||
*
|
||||
* @return Yoast_Notification[] The notifications for the user with the given ID.
|
||||
*/
|
||||
public function get_notifications_for_user( $user_id ) {
|
||||
if ( array_key_exists( $user_id, $this->notifications ) ) {
|
||||
return $this->notifications[ $user_id ];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get newly added notifications.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_new_notifications() {
|
||||
|
||||
return array_map( array( $this, 'get_notification_by_id' ), $this->new );
|
||||
return array_map( [ $this, 'get_notification_by_id' ], $this->new );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information from the User input
|
||||
* Get information from the User input.
|
||||
*
|
||||
* @param string $key Key to retrieve.
|
||||
*
|
||||
|
|
@ -434,7 +676,9 @@ class Yoast_Notification_Center {
|
|||
private static function get_user_input( $key ) {
|
||||
|
||||
$filter_input_type = INPUT_GET;
|
||||
if ( 'POST' === strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
|
||||
$request_method = isset( $_SERVER['REQUEST_METHOD'] ) ? filter_var( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : '';
|
||||
|
||||
if ( strtoupper( $request_method ) === 'POST' ) {
|
||||
$filter_input_type = INPUT_POST;
|
||||
}
|
||||
|
||||
|
|
@ -442,13 +686,21 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieve the notifications from storage
|
||||
* Retrieve the notifications from storage and fill the relevant property.
|
||||
*
|
||||
* @return array Yoast_Notification[] Notifications
|
||||
* @param int $user_id The ID of the user to retrieve notifications for.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function retrieve_notifications_from_storage() {
|
||||
private function retrieve_notifications_from_storage( $user_id ) {
|
||||
|
||||
$stored_notifications = get_user_option( self::STORAGE_KEY, get_current_user_id() );
|
||||
if ( $this->notifications_retrieved ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->notifications_retrieved = true;
|
||||
|
||||
$stored_notifications = get_user_option( self::STORAGE_KEY, $user_id );
|
||||
|
||||
// Check if notifications are stored.
|
||||
if ( empty( $stored_notifications ) ) {
|
||||
|
|
@ -456,16 +708,16 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
if ( is_array( $stored_notifications ) ) {
|
||||
$notifications = array_map( array( $this, 'array_to_notification' ), $stored_notifications );
|
||||
$notifications = array_map( [ $this, 'array_to_notification' ], $stored_notifications );
|
||||
// Apply array_values to ensure we get a 0-indexed array.
|
||||
$notifications = array_values( array_filter( $notifications, array( $this, 'filter_notification_current_user' ) ) );
|
||||
$notifications = array_values( array_filter( $notifications, [ $this, 'filter_notification_current_user' ] ) );
|
||||
|
||||
$this->notifications = $notifications;
|
||||
$this->notifications[ $user_id ] = $notifications;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort on type then priority
|
||||
* Sort on type then priority.
|
||||
*
|
||||
* @param Yoast_Notification $a Compare with B.
|
||||
* @param Yoast_Notification $b Compare with A.
|
||||
|
|
@ -481,11 +733,11 @@ class Yoast_Notification_Center {
|
|||
return WPSEO_Utils::calc( $b->get_priority(), 'compare', $a->get_priority() );
|
||||
}
|
||||
|
||||
if ( 'error' === $a_type ) {
|
||||
if ( $a_type === 'error' ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( 'error' === $b_type ) {
|
||||
if ( $b_type === 'error' ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -493,41 +745,21 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Dismiss the notification
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to dismiss.
|
||||
* @param string $meta_value Value to save in the dismissal.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function dismiss_notification( Yoast_Notification $notification, $meta_value = 'seen' ) {
|
||||
// Dismiss notification.
|
||||
return ( false !== update_user_meta( get_current_user_id(), $notification->get_dismissal_key(), $meta_value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all notifications from storage
|
||||
*/
|
||||
private function remove_storage() {
|
||||
|
||||
delete_user_option( get_current_user_id(), self::STORAGE_KEY );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear local stored notifications
|
||||
* Clear local stored notifications.
|
||||
*/
|
||||
private function clear_notifications() {
|
||||
|
||||
$this->notifications = array();
|
||||
$this->notifications = [];
|
||||
$this->notifications_retrieved = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter out non-persistent notifications.
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to test for persistent.
|
||||
*
|
||||
* @since 3.2
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to test for persistent.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function filter_persistent_notifications( Yoast_Notification $notification ) {
|
||||
|
|
@ -536,7 +768,7 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Filter out dismissed notifications
|
||||
* Filter out dismissed notifications.
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to check.
|
||||
*
|
||||
|
|
@ -544,21 +776,27 @@ class Yoast_Notification_Center {
|
|||
*/
|
||||
private function filter_dismissed_notifications( Yoast_Notification $notification ) {
|
||||
|
||||
return ! $this->maybe_dismiss_notification( $notification );
|
||||
return ! self::maybe_dismiss_notification( $notification );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Notification to array representation
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to convert.
|
||||
* Convert Notification to array representation.
|
||||
*
|
||||
* @since 3.2
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to convert.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function notification_to_array( Yoast_Notification $notification ) {
|
||||
|
||||
return $notification->to_array();
|
||||
$notification_data = $notification->to_array();
|
||||
|
||||
if ( isset( $notification_data['nonce'] ) ) {
|
||||
unset( $notification_data['nonce'] );
|
||||
}
|
||||
|
||||
return $notification_data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -570,6 +808,17 @@ class Yoast_Notification_Center {
|
|||
*/
|
||||
private function array_to_notification( $notification_data ) {
|
||||
|
||||
if ( isset( $notification_data['options']['nonce'] ) ) {
|
||||
unset( $notification_data['options']['nonce'] );
|
||||
}
|
||||
|
||||
if (
|
||||
isset( $notification_data['message'] ) &&
|
||||
\is_subclass_of( $notification_data['message'], Abstract_Presenter::class, false )
|
||||
) {
|
||||
$notification_data['message'] = $notification_data['message']->present();
|
||||
}
|
||||
|
||||
return new Yoast_Notification(
|
||||
$notification_data['message'],
|
||||
$notification_data['options']
|
||||
|
|
@ -577,7 +826,7 @@ class Yoast_Notification_Center {
|
|||
}
|
||||
|
||||
/**
|
||||
* Filter notifications that should not be displayed for the current user
|
||||
* Filter notifications that should not be displayed for the current user.
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to test.
|
||||
*
|
||||
|
|
@ -597,4 +846,68 @@ class Yoast_Notification_Center {
|
|||
private function is_notification_persistent( Yoast_Notification $notification ) {
|
||||
return ! $notification->is_persistent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues a notification transaction for later execution if notifications are not yet set up.
|
||||
*
|
||||
* @param callable $callback Callback that performs the transaction.
|
||||
* @param array $args Arguments to pass to the callback.
|
||||
*
|
||||
* @return bool True if transaction was queued, false if it can be performed immediately.
|
||||
*/
|
||||
private function queue_transaction( $callback, $args ) {
|
||||
if ( $this->notifications_retrieved ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->add_transaction_to_queue( $callback, $args );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a notification transaction to the queue for later execution.
|
||||
*
|
||||
* @param callable $callback Callback that performs the transaction.
|
||||
* @param array $args Arguments to pass to the callback.
|
||||
*/
|
||||
private function add_transaction_to_queue( $callback, $args ) {
|
||||
$this->queued_transactions[] = [ $callback, $args ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all notifications from storage.
|
||||
*
|
||||
* @return bool True when notifications got removed.
|
||||
*/
|
||||
protected function remove_storage() {
|
||||
if ( ! $this->has_stored_notifications() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
delete_user_option( get_current_user_id(), self::STORAGE_KEY );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are stored notifications.
|
||||
*
|
||||
* @return bool True when there are stored notifications.
|
||||
*/
|
||||
protected function has_stored_notifications() {
|
||||
$stored_notifications = $this->get_stored_notifications();
|
||||
|
||||
return ! empty( $stored_notifications );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the stored notifications.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return array|false Array with notifications or false when not set.
|
||||
*/
|
||||
protected function get_stored_notifications() {
|
||||
return get_user_option( self::STORAGE_KEY, get_current_user_id() );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,31 +12,43 @@
|
|||
class Yoast_Notification {
|
||||
|
||||
/**
|
||||
* @var string Type of capability check.
|
||||
* Type of capability check.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const MATCH_ALL = 'all';
|
||||
|
||||
/**
|
||||
* @var string Type of capability check.
|
||||
* Type of capability check.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const MATCH_ANY = 'any';
|
||||
|
||||
/**
|
||||
* @var string Notification type.
|
||||
* Notification type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ERROR = 'error';
|
||||
|
||||
/**
|
||||
* @var string Notification type.
|
||||
* Notification type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WARNING = 'warning';
|
||||
|
||||
/**
|
||||
* @var string Notification type.
|
||||
* Notification type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const UPDATED = 'updated';
|
||||
|
||||
/**
|
||||
* Options of this Notification.
|
||||
*
|
||||
* Contains optional arguments:
|
||||
*
|
||||
* - type: The notification type, i.e. 'updated' or 'error'
|
||||
|
|
@ -48,21 +60,34 @@ class Yoast_Notification {
|
|||
* - capability_check: How to check capability pass: all or any.
|
||||
* - wpseo_page_only: Only display on wpseo page or on every page.
|
||||
*
|
||||
* @var array Options of this Notification.
|
||||
* @var array
|
||||
*/
|
||||
private $options = array();
|
||||
private $options = [];
|
||||
|
||||
/** @var array Contains default values for the optional arguments */
|
||||
private $defaults = array(
|
||||
/**
|
||||
* Contains default values for the optional arguments.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $defaults = [
|
||||
'type' => self::UPDATED,
|
||||
'id' => '',
|
||||
'user' => null,
|
||||
'nonce' => null,
|
||||
'priority' => 0.5,
|
||||
'data_json' => array(),
|
||||
'data_json' => [],
|
||||
'dismissal_key' => null,
|
||||
'capabilities' => array(),
|
||||
'capabilities' => [],
|
||||
'capability_check' => self::MATCH_ALL,
|
||||
);
|
||||
'yoast_branding' => false,
|
||||
];
|
||||
|
||||
/**
|
||||
* The message for the notification.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $message;
|
||||
|
||||
/**
|
||||
* Notification class constructor.
|
||||
|
|
@ -70,7 +95,7 @@ class Yoast_Notification {
|
|||
* @param string $message Message string.
|
||||
* @param array $options Set of options.
|
||||
*/
|
||||
public function __construct( $message, $options = array() ) {
|
||||
public function __construct( $message, $options = [] ) {
|
||||
$this->message = $message;
|
||||
$this->options = $this->normalize_options( $options );
|
||||
}
|
||||
|
|
@ -84,10 +109,33 @@ class Yoast_Notification {
|
|||
return $this->options['id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the user to show the notification for.
|
||||
*
|
||||
* @return WP_User The user to show this notification for.
|
||||
*/
|
||||
public function get_user() {
|
||||
return $this->options['user'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the is of the user to show the notification for.
|
||||
*
|
||||
* Returns the id of the current user if not user has been sent.
|
||||
*
|
||||
* @return int The user id
|
||||
*/
|
||||
public function get_user_id() {
|
||||
if ( $this->get_user() !== null ) {
|
||||
return $this->get_user()->ID;
|
||||
}
|
||||
return get_current_user_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve nonce identifier.
|
||||
*
|
||||
* @return null|string Nonce for this Notification.
|
||||
* @return string|null Nonce for this Notification.
|
||||
*/
|
||||
public function get_nonce() {
|
||||
if ( $this->options['id'] && empty( $this->options['nonce'] ) ) {
|
||||
|
|
@ -98,7 +146,7 @@ class Yoast_Notification {
|
|||
}
|
||||
|
||||
/**
|
||||
* Make sure the nonce is up to date
|
||||
* Make sure the nonce is up to date.
|
||||
*/
|
||||
public function refresh_nonce() {
|
||||
if ( $this->options['id'] ) {
|
||||
|
|
@ -107,7 +155,7 @@ class Yoast_Notification {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the type of the notification
|
||||
* Get the type of the notification.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
|
@ -116,7 +164,7 @@ class Yoast_Notification {
|
|||
}
|
||||
|
||||
/**
|
||||
* Priority of the notification
|
||||
* Priority of the notification.
|
||||
*
|
||||
* Relative to the type.
|
||||
*
|
||||
|
|
@ -127,7 +175,7 @@ class Yoast_Notification {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the User Meta key to check for dismissal of notification
|
||||
* Get the User Meta key to check for dismissal of notification.
|
||||
*
|
||||
* @return string User Meta Option key that registers dismissal.
|
||||
*/
|
||||
|
|
@ -140,7 +188,7 @@ class Yoast_Notification {
|
|||
}
|
||||
|
||||
/**
|
||||
* Is this Notification persistent
|
||||
* Is this Notification persistent.
|
||||
*
|
||||
* @return bool True if persistent, False if fire and forget.
|
||||
*/
|
||||
|
|
@ -151,9 +199,9 @@ class Yoast_Notification {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if the notification is relevant for the current user
|
||||
* Check if the notification is relevant for the current user.
|
||||
*
|
||||
* @return bool True if a user needs to see this Notification, False if not.
|
||||
* @return bool True if a user needs to see this notification, false if not.
|
||||
*/
|
||||
public function display_for_current_user() {
|
||||
// If the notification is for the current page only, always show.
|
||||
|
|
@ -166,25 +214,25 @@ class Yoast_Notification {
|
|||
}
|
||||
|
||||
/**
|
||||
* Does the current user match required capabilities
|
||||
* Does the current user match required capabilities.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function match_capabilities() {
|
||||
// Super Admin can do anything.
|
||||
if ( is_multisite() && is_super_admin() ) {
|
||||
if ( is_multisite() && is_super_admin( $this->options['user']->ID ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter capabilities that enable the displaying of this notification.
|
||||
*
|
||||
* @since 3.2
|
||||
*
|
||||
* @param array $capabilities The capabilities that must be present for this Notification.
|
||||
* @param array $capabilities The capabilities that must be present for this notification.
|
||||
* @param Yoast_Notification $notification The notification object.
|
||||
*
|
||||
* @return array of capabilities or empty for no restrictions.
|
||||
* @return array Array of capabilities or empty for no restrictions.
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
$capabilities = apply_filters( 'wpseo_notification_capabilities', $this->options['capabilities'], $this );
|
||||
|
||||
|
|
@ -196,22 +244,22 @@ class Yoast_Notification {
|
|||
/**
|
||||
* Filter capability check to enable all or any capabilities.
|
||||
*
|
||||
* @since 3.2
|
||||
*
|
||||
* @param string $capability_check The type of check that will be used to determine if an capability is present.
|
||||
* @param Yoast_Notification $notification The notification object.
|
||||
*
|
||||
* @return string self::MATCH_ALL or self::MATCH_ANY.
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
$capability_check = apply_filters( 'wpseo_notification_capability_check', $this->options['capability_check'], $this );
|
||||
|
||||
if ( ! in_array( $capability_check, array( self::MATCH_ALL, self::MATCH_ANY ), true ) ) {
|
||||
if ( ! in_array( $capability_check, [ self::MATCH_ALL, self::MATCH_ANY ], true ) ) {
|
||||
$capability_check = self::MATCH_ALL;
|
||||
}
|
||||
|
||||
if ( ! empty( $capabilities ) ) {
|
||||
|
||||
$has_capabilities = array_filter( $capabilities, array( $this, 'has_capability' ) );
|
||||
$has_capabilities = array_filter( $capabilities, [ $this, 'has_capability' ] );
|
||||
|
||||
switch ( $capability_check ) {
|
||||
case self::MATCH_ALL:
|
||||
|
|
@ -225,30 +273,31 @@ class Yoast_Notification {
|
|||
}
|
||||
|
||||
/**
|
||||
* Array filter function to find matched capabilities
|
||||
* Array filter function to find matched capabilities.
|
||||
*
|
||||
* @param string $capability Capability to test.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function has_capability( $capability ) {
|
||||
return current_user_can( $capability );
|
||||
$user = $this->options['user'];
|
||||
return $user->has_cap( $capability );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the object properties as an array
|
||||
* Return the object properties as an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function to_array() {
|
||||
return array(
|
||||
return [
|
||||
'message' => $this->message,
|
||||
'options' => $this->options,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds string (view) behaviour to the Notification
|
||||
* Adds string (view) behaviour to the notification.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
|
@ -262,14 +311,14 @@ class Yoast_Notification {
|
|||
* @return string The rendered notification.
|
||||
*/
|
||||
public function render() {
|
||||
$attributes = array();
|
||||
$attributes = [];
|
||||
|
||||
// Default notification classes.
|
||||
$classes = array(
|
||||
'yoast-alert',
|
||||
);
|
||||
$classes = [
|
||||
'yoast-notification',
|
||||
];
|
||||
|
||||
// Maintain WordPress visualisation of alerts when they are not persistent.
|
||||
// Maintain WordPress visualisation of notifications when they are not persistent.
|
||||
if ( ! $this->is_persistent() ) {
|
||||
$classes[] = 'notice';
|
||||
$classes[] = $this->get_type();
|
||||
|
|
@ -280,14 +329,44 @@ class Yoast_Notification {
|
|||
}
|
||||
|
||||
// Combined attribute key and value into a string.
|
||||
array_walk( $attributes, array( $this, 'parse_attributes' ) );
|
||||
array_walk( $attributes, [ $this, 'parse_attributes' ] );
|
||||
|
||||
$message = null;
|
||||
if ( $this->options['yoast_branding'] ) {
|
||||
$message = $this->wrap_yoast_seo_icon( $this->message );
|
||||
}
|
||||
|
||||
if ( $message === null ) {
|
||||
$message = wpautop( $this->message );
|
||||
}
|
||||
|
||||
// Build the output DIV.
|
||||
return '<div ' . implode( ' ', $attributes ) . '>' . wpautop( $this->message ) . '</div>' . PHP_EOL;
|
||||
return '<div ' . implode( ' ', $attributes ) . '>' . $message . '</div>' . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSON if provided
|
||||
* Wraps the message with a Yoast SEO icon.
|
||||
*
|
||||
* @param string $message The message to wrap.
|
||||
*
|
||||
* @return string The wrapped message.
|
||||
*/
|
||||
private function wrap_yoast_seo_icon( $message ) {
|
||||
$out = sprintf(
|
||||
'<img src="%1$s" height="%2$d" width="%3$d" class="yoast-seo-icon" />',
|
||||
esc_url( plugin_dir_url( WPSEO_FILE ) . 'packages/js/images/Yoast_SEO_Icon.svg' ),
|
||||
60,
|
||||
60
|
||||
);
|
||||
$out .= '<div class="yoast-seo-icon-wrap">';
|
||||
$out .= $message;
|
||||
$out .= '</div>';
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSON if provided.
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
|
|
@ -296,11 +375,11 @@ class Yoast_Notification {
|
|||
return '';
|
||||
}
|
||||
|
||||
return wp_json_encode( $this->options['data_json'] );
|
||||
return WPSEO_Utils::format_json_encode( $this->options['data_json'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we only have values that we can work with
|
||||
* Make sure we only have values that we can work with.
|
||||
*
|
||||
* @param array $options Options to normalize.
|
||||
*
|
||||
|
|
@ -313,20 +392,25 @@ class Yoast_Notification {
|
|||
$options['priority'] = min( 1, max( 0, $options['priority'] ) );
|
||||
|
||||
// Set default capabilities when not supplied.
|
||||
if ( empty( $options['capabilities'] ) || array() === $options['capabilities'] ) {
|
||||
$options['capabilities'] = array( 'wpseo_manage_options' );
|
||||
if ( empty( $options['capabilities'] ) || $options['capabilities'] === [] ) {
|
||||
$options['capabilities'] = [ 'wpseo_manage_options' ];
|
||||
}
|
||||
|
||||
// Set to the current user if not supplied.
|
||||
if ( $options['user'] === null ) {
|
||||
$options['user'] = wp_get_current_user();
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format HTML element attributes
|
||||
* Format HTML element attributes.
|
||||
*
|
||||
* @param string $value Attribute value.
|
||||
* @param string $key Attribute name.
|
||||
*/
|
||||
private function parse_attributes( & $value, $key ) {
|
||||
$value = sprintf( '%s="%s"', $key, esc_attr( $value ) );
|
||||
private function parse_attributes( &$value, $key ) {
|
||||
$value = sprintf( '%s="%s"', sanitize_key( $key ), esc_attr( $value ) );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,376 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\Notifications
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class Yoast_Notifications.
|
||||
*/
|
||||
class Yoast_Notifications {
|
||||
|
||||
/**
|
||||
* Holds the admin page's ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ADMIN_PAGE = 'wpseo_dashboard';
|
||||
|
||||
/**
|
||||
* Total notifications count.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private static $notification_count = 0;
|
||||
|
||||
/**
|
||||
* All error notifications.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $errors = [];
|
||||
|
||||
/**
|
||||
* Active errors.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $active_errors = [];
|
||||
|
||||
/**
|
||||
* Dismissed errors.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $dismissed_errors = [];
|
||||
|
||||
/**
|
||||
* All warning notifications.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $warnings = [];
|
||||
|
||||
/**
|
||||
* Active warnings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $active_warnings = [];
|
||||
|
||||
/**
|
||||
* Dismissed warnings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $dismissed_warnings = [];
|
||||
|
||||
/**
|
||||
* Yoast_Notifications constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
$this->add_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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' ] );
|
||||
}
|
||||
|
||||
// Needed for adminbar and Notifications page.
|
||||
add_action( 'admin_init', [ __CLASS__, 'collect_notifications' ], 99 );
|
||||
|
||||
// Add AJAX hooks.
|
||||
add_action( 'wp_ajax_yoast_dismiss_notification', [ $this, 'ajax_dismiss_notification' ] );
|
||||
add_action( 'wp_ajax_yoast_restore_notification', [ $this, 'ajax_restore_notification' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ajax request to dismiss a notification.
|
||||
*/
|
||||
public function ajax_dismiss_notification() {
|
||||
|
||||
$notification = $this->get_notification_from_ajax_request();
|
||||
if ( $notification ) {
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
$notification_center->maybe_dismiss_notification( $notification );
|
||||
|
||||
$this->output_ajax_response( $notification->get_type() );
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
public function ajax_restore_notification() {
|
||||
|
||||
$notification = $this->get_notification_from_ajax_request();
|
||||
if ( $notification ) {
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
$notification_center->restore_notification( $notification );
|
||||
|
||||
$this->output_ajax_response( $notification->get_type() );
|
||||
}
|
||||
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create AJAX response data.
|
||||
*
|
||||
* @param string $type Notification type.
|
||||
*/
|
||||
private function output_ajax_response( $type ) {
|
||||
|
||||
$html = $this->get_view_html( $type );
|
||||
// phpcs:disable WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe.
|
||||
echo WPSEO_Utils::format_json_encode(
|
||||
[
|
||||
'html' => $html,
|
||||
'total' => self::get_active_notification_count(),
|
||||
]
|
||||
);
|
||||
// phpcs:enable -- Reason: WPSEO_Utils::format_json_encode is safe.
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML to return in the AJAX request.
|
||||
*
|
||||
* @param string $type Notification type.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function get_view_html( $type ) {
|
||||
|
||||
switch ( $type ) {
|
||||
case 'error':
|
||||
$view = 'errors';
|
||||
break;
|
||||
|
||||
case 'warning':
|
||||
default:
|
||||
$view = 'warnings';
|
||||
break;
|
||||
}
|
||||
|
||||
// Re-collect notifications.
|
||||
self::collect_notifications();
|
||||
|
||||
/**
|
||||
* Stops PHPStorm from nagging about this variable being unused. The variable is used in the view.
|
||||
*
|
||||
* @noinspection PhpUnusedLocalVariableInspection
|
||||
*/
|
||||
$notifications_data = self::get_template_variables();
|
||||
|
||||
ob_start();
|
||||
include WPSEO_PATH . 'admin/views/partial-notifications-' . $view . '.php';
|
||||
$html = ob_get_clean();
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the Yoast Notification from the AJAX request.
|
||||
*
|
||||
* @return Yoast_Notification|null
|
||||
*/
|
||||
private function get_notification_from_ajax_request() {
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
$notification_id = filter_input( INPUT_POST, 'notification' );
|
||||
|
||||
return $notification_center->get_notification_by_id( $notification_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the notifications and group them together.
|
||||
*/
|
||||
public static function collect_notifications() {
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
|
||||
$notifications = $notification_center->get_sorted_notifications();
|
||||
self::$notification_count = count( $notifications );
|
||||
|
||||
self::$errors = array_filter( $notifications, [ __CLASS__, 'filter_error_notifications' ] );
|
||||
self::$dismissed_errors = array_filter( self::$errors, [ __CLASS__, 'filter_dismissed_notifications' ] );
|
||||
self::$active_errors = array_diff( self::$errors, self::$dismissed_errors );
|
||||
|
||||
self::$warnings = array_filter( $notifications, [ __CLASS__, 'filter_warning_notifications' ] );
|
||||
self::$dismissed_warnings = array_filter( self::$warnings, [ __CLASS__, 'filter_dismissed_notifications' ] );
|
||||
self::$active_warnings = array_diff( self::$warnings, self::$dismissed_warnings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the variables needed in the views.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_template_variables() {
|
||||
|
||||
return [
|
||||
'metrics' => [
|
||||
'total' => self::$notification_count,
|
||||
'active' => self::get_active_notification_count(),
|
||||
'errors' => count( self::$errors ),
|
||||
'warnings' => count( self::$warnings ),
|
||||
],
|
||||
'errors' => [
|
||||
'dismissed' => self::$dismissed_errors,
|
||||
'active' => self::$active_errors,
|
||||
],
|
||||
'warnings' => [
|
||||
'dismissed' => self::$dismissed_warnings,
|
||||
'active' => self::$active_warnings,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function get_active_notification_count() {
|
||||
|
||||
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.
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to test.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function filter_error_notifications( Yoast_Notification $notification ) {
|
||||
|
||||
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.
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to test.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function filter_warning_notifications( Yoast_Notification $notification ) {
|
||||
|
||||
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.
|
||||
*
|
||||
* @param Yoast_Notification $notification Notification to test.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function filter_dismissed_notifications( Yoast_Notification $notification ) {
|
||||
|
||||
return Yoast_Notification_Center::is_notification_dismissed( $notification );
|
||||
}
|
||||
}
|
||||
|
||||
class_alias( Yoast_Notifications::class, 'Yoast_Alerts' );
|
||||
|
|
@ -14,38 +14,39 @@ class 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 plugins.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $plugins = array();
|
||||
protected $plugins = [];
|
||||
|
||||
/**
|
||||
* All the current active plugins will be stored in this private var
|
||||
* All the current active plugins will be stored in this private var.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $all_active_plugins = array();
|
||||
protected $all_active_plugins = [];
|
||||
|
||||
/**
|
||||
* After searching for active plugins that are in $this->plugins the active plugins will be stored in this
|
||||
* property
|
||||
* property.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $active_plugins = array();
|
||||
protected $active_plugins = [];
|
||||
|
||||
/**
|
||||
* Property for holding instance of itself
|
||||
* Property for holding instance of itself.
|
||||
*
|
||||
* @var Yoast_Plugin_Conflict
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* For the use of singleton pattern. Create instance of itself and return his instance
|
||||
* For the use of singleton pattern. Create instance of itself and return this instance.
|
||||
*
|
||||
* @param string $class_name Give the classname to initialize. If classname is false (empty) it will use it's own __CLASS__.
|
||||
* @param string $class_name Give the classname to initialize. If classname is
|
||||
* false (empty) it will use it's own __CLASS__.
|
||||
*
|
||||
* @return Yoast_Plugin_Conflict
|
||||
*/
|
||||
|
|
@ -63,7 +64,7 @@ class Yoast_Plugin_Conflict {
|
|||
}
|
||||
|
||||
/**
|
||||
* Setting instance, all active plugins and search for active plugins
|
||||
* 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.
|
||||
|
|
@ -81,7 +82,7 @@ class Yoast_Plugin_Conflict {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if there are conflicting plugins for given $plugin_section
|
||||
* Check if there are conflicting plugins for given $plugin_section.
|
||||
*
|
||||
* @param string $plugin_section Type of plugin conflict (such as Open Graph or sitemap).
|
||||
*
|
||||
|
|
@ -92,7 +93,7 @@ class Yoast_Plugin_Conflict {
|
|||
static $sections_checked;
|
||||
|
||||
if ( $sections_checked === null ) {
|
||||
$sections_checked = array();
|
||||
$sections_checked = [];
|
||||
}
|
||||
|
||||
if ( ! in_array( $plugin_section, $sections_checked, true ) ) {
|
||||
|
|
@ -123,9 +124,9 @@ class Yoast_Plugin_Conflict {
|
|||
// Getting the active plugins by given section.
|
||||
$plugins = $this->active_plugins[ $plugin_section ];
|
||||
|
||||
$plugin_names = array();
|
||||
$plugin_names = [];
|
||||
foreach ( $plugins as $plugin ) {
|
||||
$name = WPSEO_Utils::get_plugin_name( $plugin );
|
||||
$name = $this->get_plugin_name( $plugin );
|
||||
if ( ! empty( $name ) ) {
|
||||
$plugin_names[] = '<em>' . $name . '</em>';
|
||||
}
|
||||
|
|
@ -138,7 +139,7 @@ class Yoast_Plugin_Conflict {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks for given $plugin_sections for conflicts
|
||||
* Checks for given $plugin_sections for conflicts.
|
||||
*
|
||||
* @param array $plugin_sections Set of sections.
|
||||
*/
|
||||
|
|
@ -164,7 +165,7 @@ class Yoast_Plugin_Conflict {
|
|||
$inactive_sections = array_diff( $all_plugin_sections, $sections );
|
||||
if ( ! empty( $inactive_sections ) ) {
|
||||
foreach ( $inactive_sections as $section ) {
|
||||
array_walk( $this->plugins[ $section ], array( $this, 'clear_error' ) );
|
||||
array_walk( $this->plugins[ $section ], [ $this, 'clear_error' ] );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,12 +179,12 @@ class Yoast_Plugin_Conflict {
|
|||
$inactive_plugins = array_diff( $this->plugins[ $section ], $this->active_plugins[ $section ] );
|
||||
}
|
||||
|
||||
array_walk( $inactive_plugins, array( $this, 'clear_error' ) );
|
||||
array_walk( $inactive_plugins, [ $this, 'clear_error' ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting an error on the screen
|
||||
* Setting an error on the screen.
|
||||
*
|
||||
* @param string $plugin_section Type of conflict group (such as Open Graph or sitemap).
|
||||
* @param string $readable_plugin_section This is the value for the translation.
|
||||
|
|
@ -194,7 +195,7 @@ class Yoast_Plugin_Conflict {
|
|||
|
||||
foreach ( $this->active_plugins[ $plugin_section ] as $plugin_file ) {
|
||||
|
||||
$plugin_name = WPSEO_Utils::get_plugin_name( $plugin_file );
|
||||
$plugin_name = $this->get_plugin_name( $plugin_file );
|
||||
|
||||
$error_message = '';
|
||||
/* translators: %1$s: 'Facebook & Open Graph' plugin name(s) of possibly conflicting plugin(s), %2$s to Yoast SEO */
|
||||
|
|
@ -202,7 +203,7 @@ class Yoast_Plugin_Conflict {
|
|||
$error_message .= '<p>' . sprintf( $readable_plugin_section, 'Yoast SEO', $plugin_name ) . '</p>';
|
||||
|
||||
/* translators: %s: 'Facebook' plugin name of possibly conflicting plugin */
|
||||
$error_message .= '<a class="button button-primary" href="' . wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $plugin_file . '&plugin_status=all', 'deactivate-plugin_' . $plugin_file ) . '">' . sprintf( __( 'Deactivate %s', 'wordpress-seo' ), WPSEO_Utils::get_plugin_name( $plugin_file ) ) . '</a> ';
|
||||
$error_message .= '<a class="button button-primary" href="' . wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . $plugin_file . '&plugin_status=all', 'deactivate-plugin_' . $plugin_file ) . '">' . sprintf( __( 'Deactivate %s', 'wordpress-seo' ), $this->get_plugin_name( $plugin_file ) ) . '</a> ';
|
||||
|
||||
$identifier = $this->get_notification_identifier( $plugin_file );
|
||||
|
||||
|
|
@ -210,17 +211,17 @@ class Yoast_Plugin_Conflict {
|
|||
$notification_center->add_notification(
|
||||
new Yoast_Notification(
|
||||
$error_message,
|
||||
array(
|
||||
[
|
||||
'type' => Yoast_Notification::ERROR,
|
||||
'id' => 'wpseo-conflict-' . $identifier,
|
||||
)
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the notification for a plugin
|
||||
* Clear the notification for a plugin.
|
||||
*
|
||||
* @param string $plugin_file Clear the optional notification for this plugin.
|
||||
*/
|
||||
|
|
@ -228,11 +229,7 @@ class Yoast_Plugin_Conflict {
|
|||
$identifier = $this->get_notification_identifier( $plugin_file );
|
||||
|
||||
$notification_center = Yoast_Notification_Center::get();
|
||||
$notification = $notification_center->get_notification_by_id( 'wpseo-conflict-' . $identifier );
|
||||
|
||||
if ( $notification ) {
|
||||
$notification_center->remove_notification( $notification );
|
||||
}
|
||||
$notification_center->remove_notification_by_id( 'wpseo-conflict-' . $identifier );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -247,7 +244,7 @@ class Yoast_Plugin_Conflict {
|
|||
}
|
||||
|
||||
/**
|
||||
* Loop through plugins and check if each plugin is active
|
||||
* Loop through plugins and check if each plugin is active.
|
||||
*
|
||||
* @param array $plugins Set of plugins.
|
||||
* @param string $plugin_section Type of conflict group (such as Open Graph or sitemap).
|
||||
|
|
@ -260,9 +257,8 @@ class Yoast_Plugin_Conflict {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if given plugin exists in array with all_active_plugins
|
||||
* Check if given plugin exists in array with all_active_plugins.
|
||||
*
|
||||
* @param string $plugin Plugin basename string.
|
||||
*
|
||||
|
|
@ -284,7 +280,7 @@ class Yoast_Plugin_Conflict {
|
|||
protected function add_active_plugin( $plugin_section, $plugin ) {
|
||||
|
||||
if ( ! array_key_exists( $plugin_section, $this->active_plugins ) ) {
|
||||
$this->active_plugins[ $plugin_section ] = array();
|
||||
$this->active_plugins[ $plugin_section ] = [];
|
||||
}
|
||||
|
||||
if ( ! in_array( $plugin, $this->active_plugins[ $plugin_section ], true ) ) {
|
||||
|
|
@ -293,9 +289,9 @@ class Yoast_Plugin_Conflict {
|
|||
}
|
||||
|
||||
/**
|
||||
* Search in $this->plugins for the given $plugin
|
||||
* Search in $this->plugins for the given $plugin.
|
||||
*
|
||||
* If there is a result it will return the plugin category
|
||||
* If there is a result it will return the plugin category.
|
||||
*
|
||||
* @param string $plugin Plugin basename string.
|
||||
*
|
||||
|
|
@ -308,7 +304,23 @@ class Yoast_Plugin_Conflict {
|
|||
return $plugin_section;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plugin name from file.
|
||||
*
|
||||
* @param string $plugin Plugin path relative to plugins directory.
|
||||
*
|
||||
* @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 );
|
||||
|
||||
if ( $plugin_details['Name'] !== '' ) {
|
||||
return $plugin_details['Name'];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -324,7 +336,7 @@ class Yoast_Plugin_Conflict {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the identifier from the plugin file
|
||||
* Get the identifier from the plugin file.
|
||||
*
|
||||
* @param string $plugin_file Plugin file to get Identifier from.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -6,28 +6,34 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Configuration_Components
|
||||
* Class WPSEO_Configuration_Components.
|
||||
*/
|
||||
class WPSEO_Configuration_Components {
|
||||
|
||||
/** @var WPSEO_Config_Component[] List of registered components */
|
||||
protected $components = array();
|
||||
/**
|
||||
* List of registered components.
|
||||
*
|
||||
* @var WPSEO_Config_Component[]
|
||||
*/
|
||||
protected $components = [];
|
||||
|
||||
/** @var WPSEO_Configuration_Options_Adapter Adapter */
|
||||
/**
|
||||
* Adapter.
|
||||
*
|
||||
* @var WPSEO_Configuration_Options_Adapter
|
||||
*/
|
||||
protected $adapter;
|
||||
|
||||
/**
|
||||
* Add default components.
|
||||
*/
|
||||
public function initialize() {
|
||||
$this->add_component( new WPSEO_Config_Component_Connect_Google_Search_Console() );
|
||||
$this->add_component( new WPSEO_Config_Component_Mailchimp_Signup() );
|
||||
$this->add_component( new WPSEO_Config_Component_Configuration_Choices() );
|
||||
$this->add_component( new WPSEO_Config_Component_Suggestions() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a component
|
||||
* Add a component.
|
||||
*
|
||||
* @param WPSEO_Config_Component $component Component to add.
|
||||
*/
|
||||
|
|
@ -59,14 +65,14 @@ class WPSEO_Configuration_Components {
|
|||
foreach ( $this->components as $component ) {
|
||||
$adapter->add_custom_lookup(
|
||||
$component->get_field()->get_identifier(),
|
||||
array(
|
||||
[
|
||||
$component,
|
||||
'get_data',
|
||||
),
|
||||
array(
|
||||
],
|
||||
[
|
||||
$component,
|
||||
'set_data',
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,18 +6,50 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Configuration_Endpoint
|
||||
* Class WPSEO_Configuration_Endpoint.
|
||||
*/
|
||||
class WPSEO_Configuration_Endpoint {
|
||||
|
||||
/**
|
||||
* Holds the REST namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const REST_NAMESPACE = 'yoast/v1';
|
||||
|
||||
/**
|
||||
* Holds the endpoint to retrieve from.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ENDPOINT_RETRIEVE = 'configurator';
|
||||
|
||||
/**
|
||||
* Holds the endpoint to store to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const ENDPOINT_STORE = 'configurator';
|
||||
|
||||
/**
|
||||
* Holds the capability that can retrieve from the endpoint.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CAPABILITY_RETRIEVE = 'wpseo_manage_options';
|
||||
|
||||
/**
|
||||
* Holds the capability that can store to the endpoint.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const CAPABILITY_STORE = 'wpseo_manage_options';
|
||||
|
||||
/** @var WPSEO_Configuration_Service Service to use */
|
||||
/**
|
||||
* Service to use.
|
||||
*
|
||||
* @var WPSEO_Configuration_Service
|
||||
*/
|
||||
protected $service;
|
||||
|
||||
/**
|
||||
|
|
@ -34,34 +66,24 @@ class WPSEO_Configuration_Endpoint {
|
|||
*/
|
||||
public function register() {
|
||||
// Register fetch config.
|
||||
register_rest_route( self::REST_NAMESPACE, self::ENDPOINT_RETRIEVE, array(
|
||||
$route_args = [
|
||||
'methods' => 'GET',
|
||||
'callback' => array(
|
||||
$this->service,
|
||||
'get_configuration',
|
||||
),
|
||||
'permission_callback' => array(
|
||||
$this,
|
||||
'can_retrieve_data',
|
||||
),
|
||||
) );
|
||||
'callback' => [ $this->service, 'get_configuration' ],
|
||||
'permission_callback' => [ $this, 'can_retrieve_data' ],
|
||||
];
|
||||
register_rest_route( self::REST_NAMESPACE, self::ENDPOINT_RETRIEVE, $route_args );
|
||||
|
||||
// Register save changes.
|
||||
register_rest_route( self::REST_NAMESPACE, self::ENDPOINT_STORE, array(
|
||||
$route_args = [
|
||||
'methods' => 'POST',
|
||||
'callback' => array(
|
||||
$this->service,
|
||||
'set_configuration',
|
||||
),
|
||||
'permission_callback' => array(
|
||||
$this,
|
||||
'can_save_data',
|
||||
),
|
||||
) );
|
||||
'callback' => [ $this->service, 'set_configuration' ],
|
||||
'permission_callback' => [ $this, 'can_save_data' ],
|
||||
];
|
||||
register_rest_route( self::REST_NAMESPACE, self::ENDPOINT_STORE, $route_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission callback implementation
|
||||
* Permission callback implementation.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
|
@ -70,7 +92,7 @@ class WPSEO_Configuration_Endpoint {
|
|||
}
|
||||
|
||||
/**
|
||||
* Permission callback implementation
|
||||
* Permission callback implementation.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,23 +6,44 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Configuration_Options_Adapter
|
||||
* Class WPSEO_Configuration_Options_Adapter.
|
||||
*
|
||||
* Convert Configuration settings to WPSEO Options
|
||||
* Convert Configuration settings to WPSEO Options.
|
||||
*
|
||||
* @since 3.6
|
||||
*/
|
||||
class WPSEO_Configuration_Options_Adapter {
|
||||
|
||||
/**
|
||||
* Holds the option type value that indicates: WordPress.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const OPTION_TYPE_WORDPRESS = 'wordpress';
|
||||
const OPTION_TYPE_YOAST = 'yoast';
|
||||
const OPTION_TYPE_CUSTOM = 'custom';
|
||||
|
||||
/** @var array List of registered lookups */
|
||||
protected $lookup = array();
|
||||
|
||||
/**
|
||||
* Add a lookup for a WordPress native option
|
||||
* Holds the option type value that indicates: Yoast.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const OPTION_TYPE_YOAST = 'yoast';
|
||||
|
||||
/**
|
||||
* Holds the option type value that indicates: Custom.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const OPTION_TYPE_CUSTOM = 'custom';
|
||||
|
||||
/**
|
||||
* List of registered lookups.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $lookup = [];
|
||||
|
||||
/**
|
||||
* Add a lookup for a WordPress native option.
|
||||
*
|
||||
* @param string $class_name Class to bind to an option.
|
||||
* @param string $option Option name to use.
|
||||
|
|
@ -39,7 +60,7 @@ class WPSEO_Configuration_Options_Adapter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a lookup for a Yoast option
|
||||
* Add a lookup for a Yoast option.
|
||||
*
|
||||
* @param string $class_name Class to bind to the lookup.
|
||||
* @param string $key Key in the option group to bind to.
|
||||
|
|
@ -58,23 +79,7 @@ class WPSEO_Configuration_Options_Adapter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add a lookup for a Yoast option
|
||||
*
|
||||
* @param string $class_name Class to bind to the lookup.
|
||||
* @param string $option Option group to use.
|
||||
* @param string $key Key in the option group to bind to.
|
||||
*
|
||||
* @deprecated 7.0
|
||||
*
|
||||
* @throws InvalidArgumentException Thrown when invalid input is provided.
|
||||
*/
|
||||
public function add_yoast_lookup( $class_name, $option, $key ) {
|
||||
_deprecated_function( __METHOD__, 'WPSEO 7.0', 'WPSEO_Configuration_Options_Adapter::add_option_lookup' );
|
||||
$this->add_option_lookup( $class_name, $key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a lookup for a custom implementation
|
||||
* Add a lookup for a custom implementation.
|
||||
*
|
||||
* @param string $class_name Class to bind to the lookup.
|
||||
* @param callable $callback_get Callback to retrieve data.
|
||||
|
|
@ -88,10 +93,11 @@ class WPSEO_Configuration_Options_Adapter {
|
|||
throw new InvalidArgumentException( 'Custom option must be callable.' );
|
||||
}
|
||||
|
||||
$this->add_lookup( $class_name, self::OPTION_TYPE_CUSTOM, array(
|
||||
$callback_get,
|
||||
$callback_set,
|
||||
) );
|
||||
$this->add_lookup(
|
||||
$class_name,
|
||||
self::OPTION_TYPE_CUSTOM,
|
||||
[ $callback_get, $callback_set ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -104,14 +110,14 @@ class WPSEO_Configuration_Options_Adapter {
|
|||
* @throws Exception Thrown when invalid input is provided.
|
||||
*/
|
||||
protected function add_lookup( $class_name, $type, $option ) {
|
||||
$this->lookup[ $class_name ] = array(
|
||||
$this->lookup[ $class_name ] = [
|
||||
'type' => $type,
|
||||
'option' => $option,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data for the provided field
|
||||
* Get the data for the provided field.
|
||||
*
|
||||
* @param WPSEO_Config_Field $field Field to get data for.
|
||||
*
|
||||
|
|
@ -139,7 +145,7 @@ class WPSEO_Configuration_Options_Adapter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Save data from a field
|
||||
* Save data from a field.
|
||||
*
|
||||
* @param WPSEO_Config_Field $field Field to use for lookup.
|
||||
* @param mixed $value Value to save to the lookup of the field.
|
||||
|
|
@ -168,11 +174,11 @@ class WPSEO_Configuration_Options_Adapter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the lookup type for a specific class
|
||||
* Get the lookup type for a specific class.
|
||||
*
|
||||
* @param string $class_name Class to get the type of.
|
||||
*
|
||||
* @return null|string
|
||||
* @return string|null
|
||||
*/
|
||||
protected function get_option_type( $class_name ) {
|
||||
if ( ! isset( $this->lookup[ $class_name ] ) ) {
|
||||
|
|
@ -183,11 +189,11 @@ class WPSEO_Configuration_Options_Adapter {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the option for a specific class
|
||||
* Get the option for a specific class.
|
||||
*
|
||||
* @param string $class_name Class to get the option of.
|
||||
*
|
||||
* @return null|string|array
|
||||
* @return string|array|null
|
||||
*/
|
||||
protected function get_option( $class_name ) {
|
||||
if ( ! isset( $this->lookup[ $class_name ] ) ) {
|
||||
|
|
|
|||
|
|
@ -6,14 +6,19 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @class WPSEO_Configuration_Wizard Loads the Yoast configuration wizard.
|
||||
* Loads the Yoast configuration wizard.
|
||||
*/
|
||||
class WPSEO_Configuration_Page {
|
||||
|
||||
/**
|
||||
* Admin page identifier.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PAGE_IDENTIFIER = 'wpseo_configurator';
|
||||
|
||||
/**
|
||||
* Sets the hooks when the user has enought rights and is on the right page.
|
||||
* Sets the hooks when the user has enough rights and is on the right page.
|
||||
*/
|
||||
public function set_hooks() {
|
||||
if ( ! ( $this->is_config_page() && current_user_can( WPSEO_Configuration_Endpoint::CAPABILITY_RETRIEVE ) ) ) {
|
||||
|
|
@ -25,9 +30,9 @@ class WPSEO_Configuration_Page {
|
|||
}
|
||||
|
||||
// Register the page for the wizard.
|
||||
add_action( 'admin_menu', array( $this, 'add_wizard_page' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
||||
add_action( 'admin_init', array( $this, 'render_wizard_page' ) );
|
||||
add_action( 'admin_menu', [ $this, 'add_wizard_page' ] );
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
|
||||
add_action( 'admin_init', [ $this, 'render_wizard_page' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -44,13 +49,12 @@ class WPSEO_Configuration_Page {
|
|||
$this->remove_notification();
|
||||
$this->remove_notification_option();
|
||||
|
||||
wp_redirect( admin_url( 'admin.php?page=' . WPSEO_Admin::PAGE_IDENTIFIER ) );
|
||||
wp_safe_redirect( admin_url( 'admin.php?page=' . WPSEO_Admin::PAGE_IDENTIFIER ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers the page for the wizard.
|
||||
* Registers the page for the wizard.
|
||||
*/
|
||||
public function add_wizard_page() {
|
||||
add_dashboard_page( '', '', 'wpseo_manage_options', self::PAGE_IDENTIFIER, '' );
|
||||
|
|
@ -70,6 +74,10 @@ class WPSEO_Configuration_Page {
|
|||
public function enqueue_assets() {
|
||||
wp_enqueue_media();
|
||||
|
||||
if ( ! wp_script_is( 'wp-element', 'registered' ) && function_exists( 'gutenberg_register_scripts_and_styles' ) ) {
|
||||
gutenberg_register_scripts_and_styles();
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the `forms.css` WP stylesheet before any Yoast style, this way
|
||||
* it's easier to override selectors with the same specificity later.
|
||||
|
|
@ -82,7 +90,10 @@ class WPSEO_Configuration_Page {
|
|||
|
||||
$config = $this->get_config();
|
||||
|
||||
wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'configuration-wizard', 'yoastWizardConfig', $config );
|
||||
$asset_manager->localize_script( 'configuration-wizard', 'yoastWizardConfig', $config );
|
||||
|
||||
$yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_L10n();
|
||||
$yoast_components_l10n->localize_script( 'configuration-wizard' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -91,6 +102,11 @@ class WPSEO_Configuration_Page {
|
|||
public function show_wizard() {
|
||||
$this->enqueue_assets();
|
||||
$dashboard_url = admin_url( '/admin.php?page=wpseo_dashboard' );
|
||||
$wizard_title = sprintf(
|
||||
/* translators: %s expands to Yoast SEO. */
|
||||
__( '%s › Configuration Wizard', 'wordpress-seo' ),
|
||||
'Yoast SEO'
|
||||
);
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<!--[if IE 9]>
|
||||
|
|
@ -100,14 +116,9 @@ class WPSEO_Configuration_Page {
|
|||
<html <?php language_attributes(); ?>>
|
||||
<!--<![endif]-->
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title><?php
|
||||
printf(
|
||||
/* translators: %s expands to Yoast SEO. */
|
||||
esc_html__( '%s › Configuration Wizard', 'wordpress-seo' ),
|
||||
'Yoast SEO' );
|
||||
?></title>
|
||||
<title><?php echo esc_html( $wizard_title ); ?></title>
|
||||
<?php
|
||||
wp_print_head_scripts();
|
||||
wp_print_styles( 'yoast-seo-yoast-components' );
|
||||
|
|
@ -128,7 +139,7 @@ class WPSEO_Configuration_Page {
|
|||
<a class="button yoast-wizard-return-link" href="<?php echo esc_url( $dashboard_url ); ?>">
|
||||
<span aria-hidden="true" class="dashicons dashicons-no"></span>
|
||||
<?php
|
||||
esc_html_e( 'Close wizard', 'wordpress-seo' );
|
||||
esc_html_e( 'Close the Wizard', 'wordpress-seo' );
|
||||
?>
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -150,7 +161,6 @@ class WPSEO_Configuration_Page {
|
|||
</body>
|
||||
</html>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -159,8 +169,7 @@ class WPSEO_Configuration_Page {
|
|||
* @return array The API endpoint config.
|
||||
*/
|
||||
public function get_config() {
|
||||
$service = new WPSEO_GSC_Service();
|
||||
$config = array(
|
||||
$config = [
|
||||
'namespace' => WPSEO_Configuration_Endpoint::REST_NAMESPACE,
|
||||
'endpoint_retrieve' => WPSEO_Configuration_Endpoint::ENDPOINT_RETRIEVE,
|
||||
'endpoint_store' => WPSEO_Configuration_Endpoint::ENDPOINT_STORE,
|
||||
|
|
@ -168,10 +177,7 @@ class WPSEO_Configuration_Page {
|
|||
'root' => esc_url_raw( rest_url() ),
|
||||
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
||||
'finishUrl' => admin_url( 'admin.php?page=wpseo_dashboard&configuration=finished' ),
|
||||
'gscAuthURL' => $service->get_client()->createAuthUrl(),
|
||||
'gscProfiles' => $service->get_sites(),
|
||||
'gscNonce' => wp_create_nonce( 'wpseo-gsc-ajax-security' ),
|
||||
);
|
||||
];
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
|
@ -185,21 +191,6 @@ class WPSEO_Configuration_Page {
|
|||
return ( filter_input( INPUT_GET, 'page' ) === self::PAGE_IDENTIFIER );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the translations necessary for the configuration wizard.
|
||||
*
|
||||
* @deprecated 4.9
|
||||
*
|
||||
* @returns array The translations for the configuration wizard.
|
||||
*/
|
||||
public function get_translations() {
|
||||
_deprecated_function( __METHOD__, 'WPSEO 4.9', 'WPSEO_' );
|
||||
|
||||
$translations = new WPSEO_Configuration_Translations( WPSEO_Utils::get_user_locale() );
|
||||
|
||||
return $translations->retrieve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a notification to the notification center.
|
||||
*/
|
||||
|
|
@ -234,12 +225,12 @@ class WPSEO_Configuration_Page {
|
|||
|
||||
$notification = new Yoast_Notification(
|
||||
$message,
|
||||
array(
|
||||
[
|
||||
'type' => Yoast_Notification::WARNING,
|
||||
'id' => 'wpseo-dismiss-onboarding-notice',
|
||||
'capabilities' => 'wpseo_manage_options',
|
||||
'priority' => 0.8,
|
||||
)
|
||||
]
|
||||
);
|
||||
|
||||
return $notification;
|
||||
|
|
@ -260,5 +251,4 @@ class WPSEO_Configuration_Page {
|
|||
private function remove_notification_option() {
|
||||
WPSEO_Options::set( 'show_onboarding_notice', false );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,26 +6,50 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Configuration_Service
|
||||
* Class WPSEO_Configuration_Service.
|
||||
*/
|
||||
class WPSEO_Configuration_Service {
|
||||
|
||||
/** @var WPSEO_Configuration_Structure */
|
||||
/**
|
||||
* Class holding the onboarding wizard configuration.
|
||||
*
|
||||
* @var WPSEO_Configuration_Structure
|
||||
*/
|
||||
protected $structure;
|
||||
|
||||
/** @var WPSEO_Configuration_Components */
|
||||
/**
|
||||
* Class holding the onboarding wizard components.
|
||||
*
|
||||
* @var WPSEO_Configuration_Components
|
||||
*/
|
||||
protected $components;
|
||||
|
||||
/** @var WPSEO_Configuration_Storage */
|
||||
/**
|
||||
* Class handling the onboarding wizard persistence.
|
||||
*
|
||||
* @var WPSEO_Configuration_Storage
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/** @var WPSEO_Configuration_Endpoint */
|
||||
/**
|
||||
* Class handling the onboarding wizard endpoint.
|
||||
*
|
||||
* @var WPSEO_Configuration_Endpoint
|
||||
*/
|
||||
protected $endpoint;
|
||||
|
||||
/** @var WPSEO_Configuration_Options_Adapter */
|
||||
/**
|
||||
* Adapter that converts onboarding wizard configuration to WordPress options.
|
||||
*
|
||||
* @var WPSEO_Configuration_Options_Adapter
|
||||
*/
|
||||
protected $adapter;
|
||||
|
||||
/** @var WPSEO_Configuration_Translations */
|
||||
/**
|
||||
* Class handling the onboarding wizard endpoint.
|
||||
*
|
||||
* @var WPSEO_Configuration_Translations
|
||||
*/
|
||||
protected $translations;
|
||||
|
||||
/**
|
||||
|
|
@ -37,7 +61,7 @@ class WPSEO_Configuration_Service {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set default handlers
|
||||
* Set default handlers.
|
||||
*/
|
||||
public function set_default_providers() {
|
||||
$this->set_storage( new WPSEO_Configuration_Storage() );
|
||||
|
|
@ -45,11 +69,11 @@ class WPSEO_Configuration_Service {
|
|||
$this->set_components( new WPSEO_Configuration_Components() );
|
||||
$this->set_endpoint( new WPSEO_Configuration_Endpoint() );
|
||||
$this->set_structure( new WPSEO_Configuration_Structure() );
|
||||
$this->set_translations( new WPSEO_Configuration_Translations( WPSEO_Utils::get_user_locale() ) );
|
||||
$this->set_translations( new WPSEO_Configuration_Translations( \get_user_locale() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set storage handler
|
||||
* Set storage handler.
|
||||
*
|
||||
* @param WPSEO_Configuration_Storage $storage Storage handler to use.
|
||||
*/
|
||||
|
|
@ -58,7 +82,7 @@ class WPSEO_Configuration_Service {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set endpoint handler
|
||||
* Set endpoint handler.
|
||||
*
|
||||
* @param WPSEO_Configuration_Endpoint $endpoint Endpoint implementation to use.
|
||||
*/
|
||||
|
|
@ -68,7 +92,7 @@ class WPSEO_Configuration_Service {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the options adapter
|
||||
* Set the options adapter.
|
||||
*
|
||||
* @param WPSEO_Configuration_Options_Adapter $adapter Adapter to use.
|
||||
*/
|
||||
|
|
@ -77,7 +101,7 @@ class WPSEO_Configuration_Service {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set components provider
|
||||
* Set components provider.
|
||||
*
|
||||
* @param WPSEO_Configuration_Components $components Component provider to use.
|
||||
*/
|
||||
|
|
@ -86,7 +110,7 @@ class WPSEO_Configuration_Service {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set structure provider
|
||||
* Set structure provider.
|
||||
*
|
||||
* @param WPSEO_Configuration_Structure $structure Structure provider to use.
|
||||
*/
|
||||
|
|
@ -104,13 +128,11 @@ class WPSEO_Configuration_Service {
|
|||
}
|
||||
|
||||
/**
|
||||
* Populate the configuration
|
||||
* Populate the configuration.
|
||||
*/
|
||||
protected function populate_configuration() {
|
||||
// Switch to the user locale with fallback to the site locale.
|
||||
if ( function_exists( 'switch_to_locale' ) ) {
|
||||
switch_to_locale( WPSEO_Utils::get_user_locale() );
|
||||
}
|
||||
switch_to_locale( \get_user_locale() );
|
||||
|
||||
// Make sure we have our translations available.
|
||||
wpseo_load_textdomain();
|
||||
|
|
@ -124,13 +146,11 @@ class WPSEO_Configuration_Service {
|
|||
$this->components->set_storage( $this->storage );
|
||||
|
||||
// @todo: check if this is really needed, since the switch happens only in the API.
|
||||
if ( function_exists( 'restore_current_locale' ) ) {
|
||||
restore_current_locale();
|
||||
}
|
||||
restore_current_locale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by endpoint to retrieve configuration
|
||||
* Used by endpoint to retrieve configuration.
|
||||
*
|
||||
* @return array List of settings.
|
||||
*/
|
||||
|
|
@ -140,15 +160,15 @@ class WPSEO_Configuration_Service {
|
|||
$steps = $this->structure->retrieve();
|
||||
$translations = $this->translations->retrieve();
|
||||
|
||||
return array(
|
||||
return [
|
||||
'fields' => $fields,
|
||||
'steps' => $steps,
|
||||
'translations' => $translations,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by endpoint to store changes
|
||||
* Used by endpoint to store changes.
|
||||
*
|
||||
* @param WP_REST_Request $request Request from the REST API.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -6,23 +6,29 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Configuration_Storage
|
||||
* Class WPSEO_Configuration_Storage.
|
||||
*/
|
||||
class WPSEO_Configuration_Storage {
|
||||
|
||||
/** @var WPSEO_Configuration_Options_Adapter */
|
||||
/**
|
||||
* Holds the configuration options adapter.
|
||||
*
|
||||
* @var \WPSEO_Configuration_Options_Adapter
|
||||
*/
|
||||
protected $adapter;
|
||||
|
||||
/** @var array WPSEO_Config_Field */
|
||||
protected $fields = array();
|
||||
/**
|
||||
* Holds the configuration fields.
|
||||
*
|
||||
* @var \WPSEO_Config_Field[]
|
||||
*/
|
||||
protected $fields = [];
|
||||
|
||||
/**
|
||||
* Add default fields
|
||||
* Add default fields.
|
||||
*/
|
||||
public function add_default_fields() {
|
||||
$fields = array(
|
||||
new WPSEO_Config_Field_Upsell_Configuration_Service(),
|
||||
new WPSEO_Config_Field_Upsell_Site_Review(),
|
||||
$fields = [
|
||||
new WPSEO_Config_Field_Success_Message(),
|
||||
new WPSEO_Config_Field_Mailchimp_Signup(),
|
||||
new WPSEO_Config_Field_Environment(),
|
||||
|
|
@ -31,8 +37,6 @@ class WPSEO_Configuration_Storage {
|
|||
new WPSEO_Config_Field_Title_Intro(),
|
||||
new WPSEO_Config_Field_Site_Name(),
|
||||
new WPSEO_Config_Field_Separator(),
|
||||
new WPSEO_Config_Field_Google_Search_Console_Intro(),
|
||||
new WPSEO_Config_Field_Social_Profiles_Intro(),
|
||||
new WPSEO_Config_Field_Profile_URL_Facebook(),
|
||||
new WPSEO_Config_Field_Profile_URL_Twitter(),
|
||||
new WPSEO_Config_Field_Profile_URL_Instagram(),
|
||||
|
|
@ -40,13 +44,16 @@ class WPSEO_Configuration_Storage {
|
|||
new WPSEO_Config_Field_Profile_URL_MySpace(),
|
||||
new WPSEO_Config_Field_Profile_URL_Pinterest(),
|
||||
new WPSEO_Config_Field_Profile_URL_YouTube(),
|
||||
new WPSEO_Config_Field_Profile_URL_GooglePlus(),
|
||||
new WPSEO_Config_Field_Profile_URL_Wikipedia(),
|
||||
new WPSEO_Config_Field_Company_Or_Person(),
|
||||
new WPSEO_Config_Field_Company_Info_Missing(),
|
||||
new WPSEO_Config_Field_Company_Name(),
|
||||
new WPSEO_Config_Field_Company_Logo(),
|
||||
new WPSEO_Config_Field_Person_Name(),
|
||||
new WPSEO_Config_Field_Person(),
|
||||
new WPSEO_Config_Field_Post_Type_Visibility(),
|
||||
);
|
||||
new WPSEO_Config_Field_Tracking_Intro(),
|
||||
new WPSEO_Config_Field_Tracking(),
|
||||
];
|
||||
|
||||
$post_type_factory = new WPSEO_Config_Factory_Post_Type();
|
||||
$fields = array_merge( $fields, $post_type_factory->get_fields() );
|
||||
|
|
@ -57,7 +64,7 @@ class WPSEO_Configuration_Storage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Allow for field injections
|
||||
* Allow for field injections.
|
||||
*
|
||||
* @param WPSEO_Config_Field $field Field to add to the stack.
|
||||
*/
|
||||
|
|
@ -70,7 +77,7 @@ class WPSEO_Configuration_Storage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the adapter to use
|
||||
* Set the adapter to use.
|
||||
*
|
||||
* @param WPSEO_Configuration_Options_Adapter $adapter Adapter to use.
|
||||
*/
|
||||
|
|
@ -83,7 +90,7 @@ class WPSEO_Configuration_Storage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current adapter
|
||||
* Retrieve the current adapter.
|
||||
*
|
||||
* @return WPSEO_Configuration_Options_Adapter
|
||||
*/
|
||||
|
|
@ -92,14 +99,13 @@ class WPSEO_Configuration_Storage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieve the registered fields
|
||||
* Retrieve the registered fields.
|
||||
*
|
||||
* @returns array List of settings.
|
||||
* @return array List of settings.
|
||||
*/
|
||||
public function retrieve() {
|
||||
$output = array();
|
||||
$output = [];
|
||||
|
||||
/** @var WPSEO_Config_Field $field */
|
||||
foreach ( $this->fields as $field ) {
|
||||
|
||||
$build = $field->to_array();
|
||||
|
|
@ -116,16 +122,15 @@ class WPSEO_Configuration_Storage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Save the data
|
||||
* Save the data.
|
||||
*
|
||||
* @param array $data_to_store Data provided by the API which needs to be processed for saving.
|
||||
*
|
||||
* @return string Results
|
||||
*/
|
||||
public function store( $data_to_store ) {
|
||||
$output = array();
|
||||
$output = [];
|
||||
|
||||
/** @var WPSEO_Config_Field $field */
|
||||
foreach ( $this->fields as $field ) {
|
||||
|
||||
$field_identifier = $field->get_identifier();
|
||||
|
|
@ -134,16 +139,16 @@ class WPSEO_Configuration_Storage {
|
|||
continue;
|
||||
}
|
||||
|
||||
$field_data = array();
|
||||
$field_data = [];
|
||||
if ( isset( $data_to_store[ $field_identifier ] ) ) {
|
||||
$field_data = $data_to_store[ $field_identifier ];
|
||||
}
|
||||
|
||||
$result = $this->adapter->set( $field, $field_data );
|
||||
|
||||
$build = array(
|
||||
$build = [
|
||||
'result' => $result,
|
||||
);
|
||||
];
|
||||
|
||||
// Set current data to object to be displayed.
|
||||
$data = $this->get_field_data( $field );
|
||||
|
|
@ -158,7 +163,7 @@ class WPSEO_Configuration_Storage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Filter out null input values
|
||||
* Filter out null input values.
|
||||
*
|
||||
* @param mixed $input Input to test against.
|
||||
*
|
||||
|
|
@ -169,7 +174,7 @@ class WPSEO_Configuration_Storage {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get data from a specific field
|
||||
* Get data from a specific field.
|
||||
*
|
||||
* @param WPSEO_Config_Field $field Field to get data for.
|
||||
*
|
||||
|
|
@ -182,7 +187,7 @@ class WPSEO_Configuration_Storage {
|
|||
$defaults = $field->get_data();
|
||||
|
||||
// Remove 'null' values from input.
|
||||
$data = array_filter( $data, array( $this, 'is_not_null' ) );
|
||||
$data = array_filter( $data, [ $this, 'is_not_null' ] );
|
||||
|
||||
// Merge defaults with data.
|
||||
$data = array_merge( $defaults, $data );
|
||||
|
|
|
|||
|
|
@ -10,28 +10,31 @@
|
|||
*/
|
||||
class WPSEO_Configuration_Structure {
|
||||
|
||||
/** @var array Registered steps */
|
||||
protected $steps = array();
|
||||
/**
|
||||
* Registered steps.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $steps = [];
|
||||
|
||||
/**
|
||||
* WPSEO_Configuration_Structure constructor.
|
||||
* List of fields for each configuration step.
|
||||
*
|
||||
* This list does not include the fields for the 'postTypeVisibility'
|
||||
* step as that list will be generated on the fly.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public function initialize() {
|
||||
$this->add_step( 'intro', __( 'Welcome!', 'wordpress-seo' ), array(
|
||||
'configurationChoices',
|
||||
), false, true );
|
||||
|
||||
$this->add_step( 'environment_type', __( 'Environment', 'wordpress-seo' ), array( 'environment_type' ) );
|
||||
$this->add_step( 'siteType', __( 'Site type', 'wordpress-seo' ), array( 'siteType' ) );
|
||||
$this->add_step( 'publishingEntity', __( 'Company or person', 'wordpress-seo' ), array(
|
||||
private $fields = [
|
||||
'environment_type' => [ 'environment_type' ],
|
||||
'siteType' => [ 'siteType' ],
|
||||
'publishingEntity' => [
|
||||
'publishingEntity',
|
||||
'publishingEntityType',
|
||||
'publishingEntityCompanyInfo',
|
||||
'publishingEntityCompanyName',
|
||||
'publishingEntityCompanyLogo',
|
||||
'publishingEntityPersonName',
|
||||
) );
|
||||
$this->add_step( 'profileUrls', __( 'Social profiles', 'wordpress-seo' ), array(
|
||||
'socialProfilesIntro',
|
||||
'publishingEntityPersonId',
|
||||
'profileUrlFacebook',
|
||||
'profileUrlTwitter',
|
||||
'profileUrlInstagram',
|
||||
|
|
@ -39,37 +42,56 @@ class WPSEO_Configuration_Structure {
|
|||
'profileUrlMySpace',
|
||||
'profileUrlPinterest',
|
||||
'profileUrlYouTube',
|
||||
'profileUrlGooglePlus',
|
||||
) );
|
||||
'profileUrlWikipedia',
|
||||
],
|
||||
'multipleAuthors' => [ 'multipleAuthors' ],
|
||||
'titleTemplate' => [
|
||||
'titleIntro',
|
||||
'siteName',
|
||||
'separator',
|
||||
],
|
||||
'tracking' => [
|
||||
'trackingIntro',
|
||||
'tracking',
|
||||
],
|
||||
'newsletter' => [
|
||||
'mailchimpSignup',
|
||||
'suggestions',
|
||||
],
|
||||
'success' => [ 'successMessage' ],
|
||||
];
|
||||
|
||||
$fields = array( 'postTypeVisibility' );
|
||||
/**
|
||||
* WPSEO_Configuration_Structure constructor.
|
||||
*/
|
||||
public function initialize() {
|
||||
$this->add_step( 'environment-type', __( 'Environment', 'wordpress-seo' ), $this->fields['environment_type'] );
|
||||
$this->add_step( 'site-type', __( 'Site type', 'wordpress-seo' ), $this->fields['siteType'] );
|
||||
$this->add_step(
|
||||
'publishing-entity',
|
||||
__( 'Organization or person', 'wordpress-seo' ),
|
||||
$this->fields['publishingEntity']
|
||||
);
|
||||
|
||||
$fields = [ 'postTypeVisibility' ];
|
||||
|
||||
$post_type_factory = new WPSEO_Config_Factory_Post_Type();
|
||||
foreach ( $post_type_factory->get_fields() as $post_type_field ) {
|
||||
$fields[] = $post_type_field->get_identifier();
|
||||
}
|
||||
$this->add_step( 'postTypeVisibility', __( 'Search engine visibility', 'wordpress-seo' ), $fields );
|
||||
$this->add_step( 'post-type-visibility', __( 'Search engine visibility', 'wordpress-seo' ), $fields );
|
||||
|
||||
$this->add_step( 'multipleAuthors', __( 'Multiple authors', 'wordpress-seo' ), array( 'multipleAuthors' ) );
|
||||
$this->add_step( 'connectGoogleSearchConsole', __( 'Google Search Console', 'wordpress-seo' ), array(
|
||||
'googleSearchConsoleIntro',
|
||||
'connectGoogleSearchConsole',
|
||||
) );
|
||||
$this->add_step( 'titleTemplate', __( 'Title settings', 'wordpress-seo' ), array(
|
||||
'titleIntro',
|
||||
'siteName',
|
||||
'separator',
|
||||
) );
|
||||
$this->add_step(
|
||||
'multiple-authors',
|
||||
__( 'Multiple authors', 'wordpress-seo' ),
|
||||
$this->fields['multipleAuthors']
|
||||
);
|
||||
|
||||
$this->add_step( 'newsletter', __( 'Newsletter', 'wordpress-seo' ), array(
|
||||
'mailchimpSignup',
|
||||
), true, true );
|
||||
$this->add_step( 'suggestions', __( 'You might like', 'wordpress-seo' ), array(
|
||||
'suggestions',
|
||||
), true, true );
|
||||
$this->add_step( 'success', __( 'Success!', 'wordpress-seo' ), array(
|
||||
'successMessage',
|
||||
), true, true );
|
||||
$this->add_step( 'title-template', __( 'Title settings', 'wordpress-seo' ), $this->fields['titleTemplate'] );
|
||||
/* translators: %s expands to Yoast SEO */
|
||||
$this->add_step( 'tracking', sprintf( __( 'Help us improve %s', 'wordpress-seo' ), 'Yoast SEO' ), $this->fields['tracking'] );
|
||||
$this->add_step( 'newsletter', __( 'Continue learning', 'wordpress-seo' ), $this->fields['newsletter'], true, true );
|
||||
$this->add_step( 'success', __( 'Success!', 'wordpress-seo' ), $this->fields['success'], true, true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -82,16 +104,16 @@ class WPSEO_Configuration_Structure {
|
|||
* @param bool $full_width Wheter the step content is full width or not.
|
||||
*/
|
||||
protected function add_step( $identifier, $title, $fields, $navigation = true, $full_width = false ) {
|
||||
$this->steps[ $identifier ] = array(
|
||||
$this->steps[ $identifier ] = [
|
||||
'title' => $title,
|
||||
'fields' => $fields,
|
||||
'hideNavigation' => ! (bool) $navigation,
|
||||
'fullWidth' => $full_width,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the registered steps
|
||||
* Retrieve the registered steps.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,20 +6,28 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Configuration_Structure
|
||||
* Class WPSEO_Configuration_Structure.
|
||||
*/
|
||||
class WPSEO_Configuration_Translations {
|
||||
|
||||
/** @var array Registered steps */
|
||||
protected $translations = array();
|
||||
/**
|
||||
* Registered steps.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $translations = [];
|
||||
|
||||
/** @var string The locale */
|
||||
/**
|
||||
* The locale.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $locale;
|
||||
|
||||
/**
|
||||
* Sets the translations based on the file.
|
||||
*
|
||||
* @param string $locale The locale to retreive the translations for.
|
||||
* @param string $locale The locale to retrieve the translations for.
|
||||
*/
|
||||
public function __construct( $locale ) {
|
||||
$this->locale = $locale;
|
||||
|
|
@ -27,7 +35,7 @@ class WPSEO_Configuration_Translations {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieve the translations
|
||||
* Retrieve the translations.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
|
@ -42,14 +50,15 @@ class WPSEO_Configuration_Translations {
|
|||
*/
|
||||
protected function get_translations_from_file() {
|
||||
|
||||
$file = plugin_dir_path( WPSEO_FILE ) . 'languages/yoast-components-' . $this->locale . '.json';
|
||||
$file = WPSEO_PATH . 'languages/yoast-components-' . $this->locale . '.json';
|
||||
if ( file_exists( $file ) ) {
|
||||
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- Retrieving a local file.
|
||||
$file = file_get_contents( $file );
|
||||
if ( is_string( $file ) && $file !== '' ) {
|
||||
return json_decode( $file, true );
|
||||
}
|
||||
}
|
||||
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,98 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\ConfigurationUI
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the configuration choices component.
|
||||
*/
|
||||
class WPSEO_Config_Component_Configuration_Choices implements WPSEO_Config_Component {
|
||||
|
||||
/**
|
||||
* Gets the component identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_identifier() {
|
||||
return 'ConfigurationChoices';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field.
|
||||
*
|
||||
* @return WPSEO_Config_Field
|
||||
*/
|
||||
public function get_field() {
|
||||
$field = new WPSEO_Config_Field_Configuration_Choices();
|
||||
|
||||
$field->set_property( 'label', sprintf(
|
||||
/* translators: %s expands to 'Yoast SEO'. */
|
||||
__( 'Please choose the %s configuration of your liking:', 'wordpress-seo' ), 'Yoast SEO' )
|
||||
);
|
||||
|
||||
$field->add_choice(
|
||||
sprintf(
|
||||
/* translators: %s expands to 'Yoast SEO'. */
|
||||
__( 'Configure %s in a few steps', 'wordpress-seo' ),
|
||||
'Yoast SEO'
|
||||
),
|
||||
sprintf(
|
||||
/* translators: %1$s expands to 'Yoast SEO'. */
|
||||
__( 'Welcome to the %1$s configuration wizard. In a few simple steps we\'ll help you configure your SEO settings to match your website\'s needs! %1$s will take care of all the technical optimizations your site needs.', 'wordpress-seo' ),
|
||||
'Yoast SEO'
|
||||
),
|
||||
array(
|
||||
'type' => 'primary',
|
||||
'label' => sprintf(
|
||||
/* translators: %s expands to 'Yoast SEO'. */
|
||||
__( 'Configure %s', 'wordpress-seo' ), 'Yoast SEO'
|
||||
),
|
||||
'action' => 'nextStep',
|
||||
),
|
||||
plugin_dir_url( WPSEO_FILE ) . '/images/Yoast_SEO_Icon.svg'
|
||||
);
|
||||
$field->add_choice(
|
||||
sprintf(
|
||||
/* translators: %s expands to 'Yoast SEO'. */
|
||||
__( 'Let us set up %s for you', 'wordpress-seo' ), 'Yoast SEO'
|
||||
),
|
||||
sprintf(
|
||||
/* translators: %1$s expands to 'Yoast SEO', %2$s expands to 'Yoast SEO Premium'. */
|
||||
__( 'While we strive to make setting up %1$s as easy as possible, we understand it can still be daunting. If you would rather have us set up %1$s for you (and get a copy of %2$s in the process), order a %1$s configuration service and sit back while we configure your site.', 'wordpress-seo' ),
|
||||
'Yoast SEO',
|
||||
'Yoast SEO Premium'
|
||||
),
|
||||
array(
|
||||
'type' => 'secondary',
|
||||
'label' => __( 'Configuration service', 'wordpress-seo' ),
|
||||
'action' => 'followURL',
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/wizard-configuration-upsell' ),
|
||||
),
|
||||
plugin_dir_url( WPSEO_FILE ) . 'images/yoast-configuration-icon.svg'
|
||||
);
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data for the field.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_data() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save data
|
||||
*
|
||||
* @param array $data Data containing changes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function set_data( $data ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package WPSEO\Admin\ConfigurationUI
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Config_Component_Connect_Google_Search_Console
|
||||
*/
|
||||
class WPSEO_Config_Component_Connect_Google_Search_Console implements WPSEO_Config_Component {
|
||||
|
||||
const OPTION_ACCESS_TOKEN = 'wpseo-gsc-access_token';
|
||||
const OPTION_REFRESH_TOKEN = 'wpseo-gsc-refresh_token';
|
||||
|
||||
|
||||
/** @var WPSEO_GSC_Service Service to use */
|
||||
protected $gsc_service;
|
||||
|
||||
/**
|
||||
* WPSEO_Config_Component_Connect_Google_Search_Console constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->gsc_service = new WPSEO_GSC_Service( $this->get_profile() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Google Search Console service.
|
||||
*
|
||||
* @param WPSEO_GSC_Service $service Set service to use.
|
||||
*/
|
||||
public function set_gsc_service( WPSEO_GSC_Service $service ) {
|
||||
$this->gsc_service = $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the component identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_identifier() {
|
||||
return 'ConnectGoogleSearchConsole';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field.
|
||||
*
|
||||
* @return WPSEO_Config_Field
|
||||
*/
|
||||
public function get_field() {
|
||||
return new WPSEO_Config_Field_Connect_Google_Search_Console();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data for the field.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_data() {
|
||||
|
||||
$data = array(
|
||||
'profileList' => $this->get_profilelist(),
|
||||
'profile' => $this->get_profile(),
|
||||
'hasAccessToken' => $this->hasAccessToken(),
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save data
|
||||
*
|
||||
* @param array $data Data containing changes.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function set_data( $data ) {
|
||||
|
||||
$current_data = $this->get_data();
|
||||
|
||||
$this->handle_profile_change( $current_data, $data );
|
||||
|
||||
// Save profile.
|
||||
$has_saved = update_option(
|
||||
WPSEO_GSC::OPTION_WPSEO_GSC,
|
||||
array( 'profile' => $data['profile'] )
|
||||
);
|
||||
|
||||
// Collect results to return to the configurator.
|
||||
$results = array(
|
||||
'profile' => $has_saved,
|
||||
);
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove issues when the profile has changed
|
||||
*
|
||||
* @param array $current_data Saved data before changes.
|
||||
* @param array $data Data after changes.
|
||||
*/
|
||||
protected function handle_profile_change( $current_data, $data ) {
|
||||
// If the profile has been changed, remove issues.
|
||||
if ( $current_data['profile'] === $data['profile'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->reload_issues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current GSC profile
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_profile() {
|
||||
return WPSEO_GSC_Settings::get_profile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload GSC issues
|
||||
*/
|
||||
protected function reload_issues() {
|
||||
WPSEO_GSC_Settings::reload_issues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list with the profiles.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_profilelist() {
|
||||
$profiles = array();
|
||||
$sites = $this->gsc_service->get_sites();
|
||||
foreach ( $sites as $site_key => $site_value ) {
|
||||
$profiles[ untrailingslashit( $site_key ) ] = untrailingslashit( $site_value );
|
||||
}
|
||||
|
||||
return $profiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is an access token. If so, there is a connection.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function hasAccessToken() {
|
||||
return ( null !== $this->gsc_service->get_client()->getAccessToken() );
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,11 @@
|
|||
*/
|
||||
class WPSEO_Config_Component_Mailchimp_Signup implements WPSEO_Config_Component {
|
||||
|
||||
/**
|
||||
* The name of the mailchimp signup meta key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const META_NAME = 'wpseo-has-mailchimp-signup';
|
||||
|
||||
/**
|
||||
|
|
@ -24,7 +29,7 @@ class WPSEO_Config_Component_Mailchimp_Signup implements WPSEO_Config_Component
|
|||
/**
|
||||
* Gets the field.
|
||||
*
|
||||
* @return WPSEO_Config_Field
|
||||
* @return WPSEO_Config_Field_Mailchimp_Signup
|
||||
*/
|
||||
public function get_field() {
|
||||
return new WPSEO_Config_Field_Mailchimp_Signup();
|
||||
|
|
@ -36,15 +41,15 @@ class WPSEO_Config_Component_Mailchimp_Signup implements WPSEO_Config_Component
|
|||
* @return mixed
|
||||
*/
|
||||
public function get_data() {
|
||||
$data = array(
|
||||
$data = [
|
||||
'hasSignup' => $this->has_mailchimp_signup(),
|
||||
);
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save data
|
||||
* Save data.
|
||||
*
|
||||
* @param array $data Data containing changes.
|
||||
*
|
||||
|
|
@ -61,15 +66,15 @@ class WPSEO_Config_Component_Mailchimp_Signup implements WPSEO_Config_Component
|
|||
}
|
||||
|
||||
// Collect results to return to the configurator.
|
||||
$results = array(
|
||||
$results = [
|
||||
'hasSignup' => $has_saved,
|
||||
);
|
||||
];
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user has entered his email for mailchimp already.
|
||||
* Checks if the user has entered their email for mailchimp already.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -28,58 +28,69 @@ class WPSEO_Config_Component_Suggestions implements WPSEO_Config_Component {
|
|||
$field = new WPSEO_Config_Field_Suggestions();
|
||||
|
||||
// Only show Premium upsell when we are not inside a Premium install.
|
||||
if ( ! WPSEO_Utils::is_yoast_seo_premium() ) {
|
||||
if ( ! YoastSEO()->helpers->product->is_premium() ) {
|
||||
$field->add_suggestion(
|
||||
/* translators: %s resolves to Yoast SEO Premium */
|
||||
sprintf( __( 'Outrank the competition with %s', 'wordpress-seo' ), 'Yoast SEO Premium' ),
|
||||
/* translators: %1$s resolves to Yoast SEO Premium */
|
||||
sprintf( __( 'Do you want to outrank your competition? %1$s gives you awesome additional features that\'ll help you to set up your SEO strategy like a professional. Use the multiple focus keywords functionality, the redirect manager and our internal linking tool. %1$s will also give you access to premium support.', 'wordpress-seo' ), 'Yoast SEO Premium' ),
|
||||
array(
|
||||
sprintf( __( 'Do you want to outrank your competition? %1$s gives you awesome additional features that\'ll help you to set up your SEO strategy like a professional. Add synonyms and related keywords, use our Premium SEO analysis, the redirect manager and our internal linking tool. %1$s will also give you access to premium support.', 'wordpress-seo' ), 'Yoast SEO Premium' ),
|
||||
[
|
||||
'label' => __( 'Upgrade to Premium', 'wordpress-seo' ),
|
||||
'type' => 'primary',
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/wizard-suggestion-premium' ),
|
||||
),
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/video-yoast-seo-premium' )
|
||||
'href' => WPSEO_Shortlinker::get( 'https://yoa.st/wizard-suggestion-premium' ),
|
||||
],
|
||||
[
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/video-yoast-seo-premium' ),
|
||||
'title' => sprintf(
|
||||
/* translators: %1$s expands to Yoast SEO Premium. */
|
||||
__( '%1$s video', 'wordpress-seo' ),
|
||||
'Yoast SEO Premium'
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$field->add_suggestion(
|
||||
__( 'Learn how to write copy that ranks', 'wordpress-seo' ),
|
||||
/* translators: %1$s resolves to SEO copywriting training */
|
||||
sprintf( __( 'Do you want to learn how to write content that generates traffic? Check out our %1$s. We will help you to write awesome copy that will rank in the search engines. The %1$s covers all the main steps in SEO copywriting: from keyword research to publishing.', 'wordpress-seo' ), 'SEO copywriting training' ),
|
||||
array(
|
||||
'label' => 'SEO copywriting training',
|
||||
'type' => 'link',
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/configuration-wizard-copywrite-course-link' ),
|
||||
__( 'Find out what words your audience uses to find you', 'wordpress-seo' ),
|
||||
sprintf(
|
||||
/* translators: %1$s resolves to Keyword research training */
|
||||
__( 'Keyword research is essential in any SEO strategy. You decide the search terms you want to be found for, and figure out what words your audience uses to find you. Great keyword research tells you what content you need to start ranking for the terms you want to rank for. Make sure your efforts go into the keywords you actually have a chance at ranking for! The %1$s walks you through this process, step by step.', 'wordpress-seo' ),
|
||||
'Keyword research training'
|
||||
),
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/video-course-copywriting' )
|
||||
);
|
||||
|
||||
$field->add_suggestion(
|
||||
/* translators: %1$s resolves to Yoast SEO, %2$s resolves to Yoast SEO plugin training */
|
||||
sprintf( __( 'Get the most out of %1$s with the %2$s', 'wordpress-seo' ), 'Yoast SEO', 'Yoast SEO plugin training' ),
|
||||
/* translators: %1$s resolves to Yoast SEO */
|
||||
sprintf( __( 'Do you want to know all the ins and outs of the %1$s plugin? Do you want to learn all about our advanced settings? Want to be able to really get the most out of the %1$s plugin? Check out our %1$s plugin training and start outranking the competition!', 'wordpress-seo' ), 'Yoast SEO' ),
|
||||
array(
|
||||
'label' => 'Yoast SEO plugin training',
|
||||
[
|
||||
'label' => 'Keyword research training',
|
||||
'type' => 'link',
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/wizard-suggestion-plugin-course' ),
|
||||
),
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/video-plugin-course' )
|
||||
'href' => WPSEO_Shortlinker::get( 'https://yoa.st/3lg' ),
|
||||
],
|
||||
[
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/3lf' ),
|
||||
'title' => sprintf(
|
||||
/* translators: %1$s expands to Keyword research training. */
|
||||
__( '%1$s video', 'wordpress-seo' ),
|
||||
'Keyword research training'
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
// When we are running in Yoast SEO Premium and don't have Local SEO installed, show Local SEO as suggestion.
|
||||
if ( WPSEO_Utils::is_yoast_seo_premium() && ! defined( 'WPSEO_LOCAL_FILE' ) ) {
|
||||
if ( YoastSEO()->helpers->product->is_premium() && ! defined( 'WPSEO_LOCAL_FILE' ) ) {
|
||||
$field->add_suggestion(
|
||||
sprintf( __( 'Attract more customers near you', 'wordpress-seo' ), 'Yoast SEO', 'Yoast SEO plugin training' ),
|
||||
__( 'Attract more customers near you', 'wordpress-seo' ),
|
||||
/* translators: %1$s resolves to Local SEO */
|
||||
sprintf( __( 'If you want to outrank the competition in a specific town or region, check out our %1$s plugin! You’ll be able to easily insert Google maps, opening hours, contact information and a store locator. Besides that %1$s helps you to improve the usability of your contact page.', 'wordpress-seo' ), 'Local SEO' ),
|
||||
array(
|
||||
[
|
||||
'label' => 'Local SEO',
|
||||
'type' => 'link',
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/wizard-suggestion-localseo' ),
|
||||
),
|
||||
WPSEO_Shortlinker::get( 'https://yoa.st/video-localseo' )
|
||||
'href' => WPSEO_Shortlinker::get( 'https://yoa.st/wizard-suggestion-local-seo' ),
|
||||
],
|
||||
[
|
||||
'url' => WPSEO_Shortlinker::get( 'https://yoa.st/video-localseo' ),
|
||||
'title' => sprintf(
|
||||
/* translators: %1$s expands to Local SEO. */
|
||||
__( '%1$s video', 'wordpress-seo' ),
|
||||
'Local SEO'
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -92,11 +103,11 @@ class WPSEO_Config_Component_Suggestions implements WPSEO_Config_Component {
|
|||
* @return array
|
||||
*/
|
||||
public function get_data() {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Save data
|
||||
* Save data.
|
||||
*
|
||||
* @param array $data Data containing changes.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -6,21 +6,26 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Config Component interface
|
||||
* Config Component interface.
|
||||
*/
|
||||
interface WPSEO_Config_Component {
|
||||
|
||||
/**
|
||||
* Get onboarding wizard component identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_identifier();
|
||||
|
||||
/**
|
||||
* Get onboarding wizard component data.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_data();
|
||||
|
||||
/**
|
||||
* Save changes
|
||||
* Save changes.
|
||||
*
|
||||
* @param array $data Data provided by the API.
|
||||
*
|
||||
|
|
@ -29,6 +34,8 @@ interface WPSEO_Config_Component {
|
|||
public function set_data( $data );
|
||||
|
||||
/**
|
||||
* Get onboarding wizard component field.
|
||||
*
|
||||
* @return WPSEO_Config_Field
|
||||
*/
|
||||
public function get_field();
|
||||
|
|
|
|||
|
|
@ -6,24 +6,30 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Config_Factory_Post_Type
|
||||
* Class WPSEO_Config_Factory_Post_Type.
|
||||
*/
|
||||
class WPSEO_Config_Factory_Post_Type {
|
||||
|
||||
/** @var WPSEO_Config_Field_Choice_Post_Type[] List of fields */
|
||||
protected static $fields = array();
|
||||
/**
|
||||
* List of fields.
|
||||
*
|
||||
* @var WPSEO_Config_Field_Choice_Post_Type[]
|
||||
*/
|
||||
protected static $fields = [];
|
||||
|
||||
/**
|
||||
* Retrieves a list of fields.
|
||||
*
|
||||
* @return WPSEO_Config_Field_Choice_Post_Type[] List of fields.
|
||||
*/
|
||||
public function get_fields() {
|
||||
|
||||
if ( empty( self::$fields ) ) {
|
||||
|
||||
$fields = array();
|
||||
$fields = [];
|
||||
|
||||
// WPSEO_Post_type::get_accessible_post_types() should *not* be used to get a similar experience from the settings.
|
||||
$post_types = get_post_types( array( 'public' => true ), 'objects' );
|
||||
$post_types = get_post_types( [ 'public' => true ], 'objects' );
|
||||
$post_types = WPSEO_Post_Type::filter_attachment_post_type( $post_types );
|
||||
if ( ! empty( $post_types ) ) {
|
||||
foreach ( $post_types as $post_type => $post_type_object ) {
|
||||
|
|
@ -43,13 +49,13 @@ class WPSEO_Config_Factory_Post_Type {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add custom properties for specific post types
|
||||
* Add custom properties for specific post types.
|
||||
*
|
||||
* @param string $post_type Post type of field that is being added.
|
||||
* @param WPSEO_Config_Field $field Field that corresponds to the post type.
|
||||
*/
|
||||
private function add_custom_properties( $post_type, $field ) {
|
||||
if ( 'attachment' === $post_type ) {
|
||||
if ( $post_type === 'attachment' ) {
|
||||
$field->set_property( 'explanation', __( 'WordPress automatically generates an URL for each media item in the library. Enabling this will allow for google to index the generated URL.', 'wordpress-seo' ) );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,15 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Config_Field_Choice_Post_Type
|
||||
* Class WPSEO_Config_Field_Choice_Post_Type.
|
||||
*/
|
||||
class WPSEO_Config_Field_Choice_Post_Type extends WPSEO_Config_Field_Choice {
|
||||
|
||||
/** @var string Post type */
|
||||
/**
|
||||
* Post type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $post_type;
|
||||
|
||||
/**
|
||||
|
|
@ -32,15 +36,15 @@ class WPSEO_Config_Field_Choice_Post_Type extends WPSEO_Config_Field_Choice {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set adapter
|
||||
* Set adapter.
|
||||
*
|
||||
* @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on.
|
||||
*/
|
||||
public function set_adapter( WPSEO_Configuration_Options_Adapter $adapter ) {
|
||||
$adapter->add_custom_lookup(
|
||||
$this->get_identifier(),
|
||||
array( $this, 'get_data' ),
|
||||
array( $this, 'set_data' )
|
||||
[ $this, 'get_data' ],
|
||||
[ $this, 'set_data' ]
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -54,6 +58,8 @@ class WPSEO_Config_Field_Choice_Post_Type extends WPSEO_Config_Field_Choice {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieves the data.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function get_data() {
|
||||
|
|
@ -67,7 +73,7 @@ class WPSEO_Config_Field_Choice_Post_Type extends WPSEO_Config_Field_Choice {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set new data
|
||||
* Set new data.
|
||||
*
|
||||
* @param string $visible Visible (true) or hidden (false).
|
||||
*
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Class WPSEO_Config_Field_Choice
|
||||
* Class WPSEO_Config_Field_Choice.
|
||||
*/
|
||||
class WPSEO_Config_Field_Choice extends WPSEO_Config_Field {
|
||||
|
||||
|
|
@ -18,23 +18,23 @@ class WPSEO_Config_Field_Choice extends WPSEO_Config_Field {
|
|||
public function __construct( $field ) {
|
||||
parent::__construct( $field, 'Choice' );
|
||||
|
||||
$this->properties['choices'] = array();
|
||||
$this->properties['choices'] = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a choice to the properties
|
||||
* Add a choice to the properties.
|
||||
*
|
||||
* @param string $value Value op the option.
|
||||
* @param string $label Label to display for the value.
|
||||
* @param string $screen_reader_text Optional. Screenreader text to use.
|
||||
* @param string $value Value op the option.
|
||||
* @param string $label Label to display for the value.
|
||||
* @param string $aria_label Optional. Aria label text to use.
|
||||
*/
|
||||
public function add_choice( $value, $label, $screen_reader_text = '' ) {
|
||||
$choice = array(
|
||||
public function add_choice( $value, $label, $aria_label = '' ) {
|
||||
$choice = [
|
||||
'label' => $label,
|
||||
);
|
||||
];
|
||||
|
||||
if ( $screen_reader_text ) {
|
||||
$choice['screenReaderText'] = $screen_reader_text;
|
||||
if ( $aria_label ) {
|
||||
$choice['screenReaderText'] = $aria_label;
|
||||
}
|
||||
|
||||
$this->properties['choices'][ $value ] = $choice;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue