diff --git a/wp-content/plugins/wordpress-seo/admin/admin-settings-changed-listener.php b/wp-content/plugins/wordpress-seo/admin/admin-settings-changed-listener.php new file mode 100644 index 00000000..f3032b09 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/admin-settings-changed-listener.php @@ -0,0 +1,85 @@ +helpers->current_page->is_yoast_seo_page() ) { + return; + } + + // Variable name is the same as the global that is set by get_settings_errors. + $wp_settings_errors = get_settings_errors(); + + foreach ( $wp_settings_errors as $key => $wp_settings_error ) { + if ( ! $this->is_settings_updated_notification( $wp_settings_error ) ) { + continue; + } + + self::$settings_saved = true; + unset( $wp_settings_errors[ $key ] ); + // phpcs:ignore WordPress.WP.GlobalVariablesOverride -- Overwrite the global with the list excluding the Changed saved message. + $GLOBALS['wp_settings_errors'] = $wp_settings_errors; + break; + } + } + + /** + * Checks whether the settings notification is a settings_updated notification. + * + * @param array $wp_settings_error The settings object. + * + * @return bool Whether this is a settings updated settings notification. + */ + public function is_settings_updated_notification( $wp_settings_error ) { + return ! empty( $wp_settings_error['code'] ) && $wp_settings_error['code'] === 'settings_updated'; + } + + /** + * Get whether the settings have successfully been saved + * + * @return bool Whether the settings have successfully been saved. + */ + public function have_settings_been_saved() { + return self::$settings_saved; + } + + /** + * Renders a success message if the Yoast SEO settings have been saved. + */ + public function show_success_message() { + if ( $this->have_settings_been_saved() ) { + echo '

', + esc_html__( 'Settings saved.', 'wordpress-seo' ), + '

'; + } + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/ajax.php b/wp-content/plugins/wordpress-seo/admin/ajax.php index 0df8d933..37d36344 100644 --- a/wp-content/plugins/wordpress-seo/admin/ajax.php +++ b/wp-content/plugins/wordpress-seo/admin/ajax.php @@ -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( '' ); } diff --git a/wp-content/plugins/wordpress-seo/admin/ajax/class-recalculate-scores-ajax.php b/wp-content/plugins/wordpress-seo/admin/ajax/class-recalculate-scores-ajax.php deleted file mode 100644 index 8ab77a7b..00000000 --- a/wp-content/plugins/wordpress-seo/admin/ajax/class-recalculate-scores-ajax.php +++ /dev/null @@ -1,121 +0,0 @@ - $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; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/ajax/class-shortcode-filter.php b/wp-content/plugins/wordpress-seo/admin/ajax/class-shortcode-filter.php index 26e6b071..833b1bfc 100644 --- a/wp-content/plugins/wordpress-seo/admin/ajax/class-shortcode-filter.php +++ b/wp-content/plugins/wordpress-seo/admin/ajax/class-shortcode-filter.php @@ -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 ) ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-dismissable-notice.php b/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-dismissable-notice.php index 46cb14c9..e6a30c73 100644 --- a/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-dismissable-notice.php +++ b/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-dismissable-notice.php @@ -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 ); diff --git a/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-onpage-ajax.php b/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-onpage-ajax.php deleted file mode 100644 index 0e8f22d1..00000000 --- a/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-onpage-ajax.php +++ /dev/null @@ -1,40 +0,0 @@ -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 ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-plugin-conflict-ajax.php b/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-plugin-conflict-ajax.php index e4f80895..5567909d 100644 --- a/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-plugin-conflict-ajax.php +++ b/wp-content/plugins/wordpress-seo/admin/ajax/class-yoast-plugin-conflict-ajax.php @@ -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. */ diff --git a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-renderer.php b/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-renderer.php deleted file mode 100644 index 2fbb6dc2..00000000 --- a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-renderer.php +++ /dev/null @@ -1,50 +0,0 @@ -get_url() ) . '">'; - $output .= '' . esc_attr( $banner->get_alt() ) . ''; - $output .= ''; - - 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, '/' ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-sidebar-renderer.php b/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-sidebar-renderer.php deleted file mode 100644 index 785b804f..00000000 --- a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-sidebar-renderer.php +++ /dev/null @@ -1,62 +0,0 @@ -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( ' - ', - $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; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-sidebar.php b/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-sidebar.php deleted file mode 100644 index 8f4399f8..00000000 --- a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-sidebar.php +++ /dev/null @@ -1,348 +0,0 @@ -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 */ - '

' . sprintf( esc_html__( 'Upgrade to %1$s', 'wordpress-seo' ), 'Yoast SEO Premium' ) . '

' . - '' . - /* translators: %s expands to Yoast SEO Premium */ - '' . sprintf( __( 'Get %s now', 'wordpress-seo' ), 'Yoast SEO Premium' ) . '
' - ); - - 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' ), - '', - 'Yoast', - '' - ) - ); - - $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' ), - '', - '' - ) - ); - - 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' ), - '', - '' - ) - ); - - $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( - '' . - /* translators: %1$s expands to Yoast SEO Premium */ - sprintf( __( 'Upgrade to %1$s »', 'wordpress-seo' ), 'Yoast SEO Premium' ) . - '' - ); - - return $remove_banner_spot; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-spot-renderer.php b/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-spot-renderer.php deleted file mode 100644 index 25c52a64..00000000 --- a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-spot-renderer.php +++ /dev/null @@ -1,39 +0,0 @@ -'; - if ( $banner_spot->get_title() !== '' ) { - $output .= '' . $banner_spot->get_title() . ''; - } - - if ( $banner_spot->get_extra() !== '' ) { - $output .= $banner_spot->get_extra(); - } - - if ( $banner_spot->get_description() !== '' ) { - $output .= '

' . $banner_spot->get_description() . '

'; - } - - $output .= $banner_spot->render_banner(); - $output .= ''; - - return $output; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-spot.php b/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-spot.php deleted file mode 100644 index 648fd6d6..00000000 --- a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner-spot.php +++ /dev/null @@ -1,120 +0,0 @@ -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 ) ]; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner.php b/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner.php deleted file mode 100644 index 55d0b358..00000000 --- a/wp-content/plugins/wordpress-seo/admin/banner/class-admin-banner.php +++ /dev/null @@ -1,89 +0,0 @@ -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; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/capabilities/class-abstract-capability-manager.php b/wp-content/plugins/wordpress-seo/admin/capabilities/class-abstract-capability-manager.php index 00e7417b..29e81605 100644 --- a/wp-content/plugins/wordpress-seo/admin/capabilities/class-abstract-capability-manager.php +++ b/wp-content/plugins/wordpress-seo/admin/capabilities/class-abstract-capability-manager.php @@ -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; diff --git a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-factory.php b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-factory.php index 0e1c56a1..e265bee1 100644 --- a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-factory.php +++ b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-factory.php @@ -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 ]; } } diff --git a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-integration.php b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-integration.php index b08416c6..ec8df74a 100644 --- a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-integration.php +++ b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-integration.php @@ -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'; diff --git a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-vip.php b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-vip.php index b621ddeb..4f56e8e4 100644 --- a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-vip.php +++ b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-vip.php @@ -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; diff --git a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-wp.php b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-wp.php index 63ba3134..18309567 100644 --- a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-wp.php +++ b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager-wp.php @@ -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. * diff --git a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager.php b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager.php index 1f8ec264..63f6962d 100644 --- a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager.php +++ b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-manager.php @@ -9,6 +9,7 @@ * Capability Manager interface. */ interface WPSEO_Capability_Manager { + /** * Registers a capability. * diff --git a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-utils.php b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-utils.php index 7124a337..0134f3c4 100644 --- a/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-utils.php +++ b/wp-content/plugins/wordpress-seo/admin/capabilities/class-capability-utils.php @@ -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; } /** diff --git a/wp-content/plugins/wordpress-seo/admin/capabilities/class-register-capabilities.php b/wp-content/plugins/wordpress-seo/admin/capabilities/class-register-capabilities.php index 762cf7c4..cd3d3646 100644 --- a/wp-content/plugins/wordpress-seo/admin/capabilities/class-register-capabilities.php +++ b/wp-content/plugins/wordpress-seo/admin/capabilities/class-register-capabilities.php @@ -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; } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-asset-analysis-worker-location.php b/wp-content/plugins/wordpress-seo/admin/class-admin-asset-analysis-worker-location.php new file mode 100644 index 00000000..cb980ad1 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-asset-analysis-worker-location.php @@ -0,0 +1,75 @@ +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 ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-asset-dev-server-location.php b/wp-content/plugins/wordpress-seo/admin/class-admin-asset-dev-server-location.php index d8c19fa2..5765bdc2 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-admin-asset-dev-server-location.php +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-asset-dev-server-location.php @@ -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; } diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-asset-manager.php b/wp-content/plugins/wordpress-seo/admin/class-admin-asset-manager.php index 4a469306..f0929b92 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-admin-asset-manager.php +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-asset-manager.php @@ -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 $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 ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-asset-seo-location.php b/wp-content/plugins/wordpress-seo/admin/class-admin-asset-seo-location.php index 8719cd08..82ff1b68 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-admin-asset-seo-location.php +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-asset-seo-location.php @@ -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; } diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-asset-yoast-components-l10n.php b/wp-content/plugins/wordpress-seo/admin/class-admin-asset-yoast-components-l10n.php new file mode 100644 index 00000000..04f290a7 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-asset-yoast-components-l10n.php @@ -0,0 +1,63 @@ +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; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-editor-specific-replace-vars.php b/wp-content/plugins/wordpress-seo/admin/class-admin-editor-specific-replace-vars.php new file mode 100644 index 00000000..4bcd1684 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-editor-specific-replace-vars.php @@ -0,0 +1,227 @@ + [ '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 ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-gutenberg-compatibility-notification.php b/wp-content/plugins/wordpress-seo/admin/class-admin-gutenberg-compatibility-notification.php new file mode 100644 index 00000000..44d1957d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-gutenberg-compatibility-notification.php @@ -0,0 +1,105 @@ +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 ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-help-panel.php b/wp-content/plugins/wordpress-seo/admin/class-admin-help-panel.php index 152598e5..6fdb6c2f 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-admin-help-panel.php +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-help-panel.php @@ -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 = '
'; $wrapper_end = '
'; } diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-init.php b/wp-content/plugins/wordpress-seo/admin/class-admin-init.php index 1c32b97f..8735d413 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-admin-init.php +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-init.php @@ -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' ), - '', - '' - ); - - $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 = '' . __( 'Huge SEO Issue: You\'re blocking access to robots.', 'wordpress-seo' ) . ' '; - $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' ), - '', - '' - ); - - $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 .= '
'; - - $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' ), - '', - '' - ); - - $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 /%postname%/.', 'wordpress-seo' ); - $info_message .= '
'; - $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' ), - '', - '' - ); - - $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( '%s', $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' ), - '', - '' - ), - 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( + '

%1$s
%2$s
%4$s

', + esc_html__( 'WARNING:', 'wordpress-seo' ), + sprintf( + /* translators: %1$s and %2$s expand to 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' ), + '', + '' + ), + 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( + '

%1$s %2$s

', + 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' ), + '', + '' + ), + 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 ) ) { + ?> +
+ [ '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; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-user-profile.php b/wp-content/plugins/wordpress-seo/admin/class-admin-user-profile.php index 76e6c61d..4579e462 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-admin-user-profile.php +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-user-profile.php @@ -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' ] ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin-utils.php b/wp-content/plugins/wordpress-seo/admin/class-admin-utils.php index d1a0aab4..b907214f 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-admin-utils.php +++ b/wp-content/plugins/wordpress-seo/admin/class-admin-utils.php @@ -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( + '%s', + esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ) + ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-admin.php b/wp-content/plugins/wordpress-seo/admin/class-admin.php index 22b26966..6f9ca269 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-admin.php +++ b/wp-content/plugins/wordpress-seo/admin/class-admin.php @@ -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 = '' . __( 'Settings', 'wordpress-seo' ) . ''; + 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 = '' . __( 'Settings', 'wordpress-seo' ) . ''; 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 = '' . __( 'FAQ', 'wordpress-seo' ) . ''; + 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 = '' . sprintf( + /* translators: %s expands to Yoast SEO Premium. */ + __( 'Required by %s', 'wordpress-seo' ), + 'Yoast SEO Premium' + ) . ''; + + 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 = '' . __( 'Activate your subscription', 'wordpress-seo' ) . ''; + array_unshift( $links, $activation_link ); + + return $links; } - // Add link to premium support landing page. - $premium_link = '' . __( 'Premium Support', 'wordpress-seo' ) . ''; + // Add link to premium landing page. + $premium_link = '' . __( 'Get Premium', 'wordpress-seo' ) . ''; array_unshift( $links, $premium_link ); - // Add link to docs. - $faq_link = '' . __( 'FAQ', 'wordpress-seo' ) . ''; - 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' ) . '
' . __( '(if one exists)', 'wordpress-seo' ) . ''; 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' ), + '%s', + '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( ' -

' . __( 'For more information:', 'wordpress-seo' ) . '

-

' . __( 'Title optimization', 'wordpress-seo' ) . '

-

' . __( 'Why Google won\'t display the right page title', 'wordpress-seo' ) . '

' - ); - - $screen->add_help_tab( - array( - 'id' => 'basic-help', - 'title' => __( 'Template explanation', 'wordpress-seo' ), - 'content' => "\n\t\t

" . __( 'Template explanation', 'wordpress-seo' ) . "

\n\t\t" . '

' . - sprintf( - /* translators: %1$s expands to Yoast SEO. */ - __( 'The title & metas settings for %1$s are made up of variables that are replaced by specific values from the page when the page is displayed. The tabs on the left explain the available variables.', 'wordpress-seo' ), - 'Yoast SEO' - ) . - '

' . __( 'Note that not all variables can be used in every template.', 'wordpress-seo' ) . '

', - ) - ); - - $screen->add_help_tab( - array( - 'id' => 'title-vars', - 'title' => __( 'Basic Variables', 'wordpress-seo' ), - 'content' => "\n\t\t

" . __( 'Basic Variables', 'wordpress-seo' ) . "

\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

" . __( 'Advanced Variables', 'wordpress-seo' ) . "

\n\t\t" . WPSEO_Replace_Vars::get_advanced_help_texts(), - ) - ); - } - - // @codeCoverageIgnoreEnd } diff --git a/wp-content/plugins/wordpress-seo/admin/class-asset.php b/wp-content/plugins/wordpress-seo/admin/class-asset.php index f593648d..70e22346 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-asset.php +++ b/wp-content/plugins/wordpress-seo/admin/class-asset.php @@ -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 ); - } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-bulk-description-editor-list-table.php b/wp-content/plugins/wordpress-seo/admin/class-bulk-description-editor-list-table.php index 667ba199..3b65304b 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-bulk-description-editor-list-table.php +++ b/wp-content/plugins/wordpress-seo/admin/class-bulk-description-editor-list-table.php @@ -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 */ +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-bulk-editor-list-table.php b/wp-content/plugins/wordpress-seo/admin/class-bulk-editor-list-table.php index 009660d4..5be8f439 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-bulk-editor-list-table.php +++ b/wp-content/plugins/wordpress-seo/admin/class-bulk-editor-list-table.php @@ -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 { ?>
- +
@@ -241,12 +220,12 @@ class WPSEO_Bulk_List_Table extends WP_List_Table { ?>
- +
- 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 (%s)', 'All (%s)', $total_posts, 'posts', 'wordpress-seo' ), number_format_i18n( $total_posts ) ); - $status_links['all'] = '' . $localized_text . ''; + $status_links['all'] = '' . $localized_text . ''; - $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 ] = '' . sprintf( translate_nooped_plural( $status->label_count, $total ), number_format_i18n( $total ) ) . ''; + $status_links[ $status_name ] = '' . sprintf( translate_nooped_plural( $status->label_count, $total ), number_format_i18n( $total ) ) . ''; } } - 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'] = '' . $localized_text . ''; + $status_links['trash'] = '' . $localized_text . ''; 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 '
'; @@ -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 = ''; - 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( '', + // 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 '
'; } } } /** + * 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( '%s', 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( '%s', @@ -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( '%s', 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( '%1$s', $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( '%1$s', esc_html( $meta_value ), $attributes, esc_attr( $id ) ); } /** @@ -942,44 +930,41 @@ class WPSEO_Bulk_List_Table extends WP_List_Table { // Little housekeeping. unset( $post_ids, $meta_data ); - } /** * Getting all post_ids from to $this->items. * - * @return string + * @return array */ protected function get_post_ids() { - $needed_ids = array(); + $post_ids = []; foreach ( $this->items as $item ) { - $needed_ids[] = $item->ID; + $post_ids[] = $item->ID; } - $post_ids = "'" . implode( "', '", $needed_ids ) . "'"; - return $post_ids; } /** * Getting the meta_data from database. * - * @param string $post_ids Post IDs string for SQL IN part. + * @param array $post_ids Post IDs for SQL IN part. * * @return mixed */ - protected function get_meta_data_result( $post_ids ) { + protected function get_meta_data_result( array $post_ids ) { global $wpdb; - $meta_data = $wpdb->get_results( - " - SELECT * - FROM {$wpdb->postmeta} - WHERE post_id IN({$post_ids}) && meta_key = '" . WPSEO_Meta::$meta_prefix . $this->target_db_field . "' - " + $where = $wpdb->prepare( + 'post_id IN (' . implode( ', ', array_fill( 0, count( $post_ids ), '%d' ) ) . ')', + $post_ids ); - return $meta_data; + $where .= $wpdb->prepare( ' AND meta_key = %s', WPSEO_Meta::$meta_prefix . $this->target_db_field ); + + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- They are prepared on the lines above. + return $wpdb->get_results( "SELECT * FROM {$wpdb->postmeta} WHERE {$where}" ); } /** @@ -992,7 +977,6 @@ class WPSEO_Bulk_List_Table extends WP_List_Table { foreach ( $meta_data as $row ) { $this->meta_data[ $row->post_id ][ $row->meta_key ] = $row->meta_value; } - } /** @@ -1002,15 +986,15 @@ class WPSEO_Bulk_List_Table extends WP_List_Table { * * @return array */ - protected function merge_columns( $columns = array() ) { + protected function merge_columns( $columns = [] ) { $columns = array_merge( - array( + [ 'col_page_title' => __( 'WP Page Title', 'wordpress-seo' ), 'col_post_type' => __( 'Content Type', 'wordpress-seo' ), 'col_post_status' => __( 'Post Status', 'wordpress-seo' ), 'col_post_date' => __( 'Publication date', 'wordpress-seo' ), 'col_page_slug' => __( 'Page URL/Slug', 'wordpress-seo' ), - ), + ], $columns ); @@ -1018,4 +1002,4 @@ class WPSEO_Bulk_List_Table extends WP_List_Table { return $columns; } -} /* End of class */ +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-bulk-title-editor-list-table.php b/wp-content/plugins/wordpress-seo/admin/class-bulk-title-editor-list-table.php index 6e47401b..5314fdb5 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-bulk-title-editor-list-table.php +++ b/wp-content/plugins/wordpress-seo/admin/class-bulk-title-editor-list-table.php @@ -12,23 +12,22 @@ class WPSEO_Bulk_Title_Editor_List_Table extends WPSEO_Bulk_List_Table { /** - * Current type for this class will be title + * Current type for this class will be title. * * @var string */ protected $page_type = 'title'; - /** - * Settings with are used in __construct + * Settings with are used in __construct. * * @var array */ - protected $settings = array( + protected $settings = [ 'singular' => 'wpseo_bulk_title', 'plural' => 'wpseo_bulk_titles', 'ajax' => true, - ); + ]; /** * The field in the database where meta field is saved. @@ -38,24 +37,24 @@ class WPSEO_Bulk_Title_Editor_List_Table extends WPSEO_Bulk_List_Table { protected $target_db_field = 'title'; /** - * The columns shown on the table + * The columns shown on the table. * * @return array */ public function get_columns() { - $columns = array( + $columns = [ /* translators: %1$s expands to Yoast SEO */ 'col_existing_yoast_seo_title' => sprintf( __( 'Existing %1$s Title', 'wordpress-seo' ), 'Yoast SEO' ), /* translators: %1$s expands to Yoast SEO */ 'col_new_yoast_seo_title' => sprintf( __( 'New %1$s Title', 'wordpress-seo' ), 'Yoast SEO' ), - ); + ]; return $this->merge_columns( $columns ); } /** - * Parse the title columns + * Parse the title columns. * * @param string $column_name Column name. * @param object $record Data object. @@ -66,11 +65,14 @@ class WPSEO_Bulk_Title_Editor_List_Table extends WPSEO_Bulk_List_Table { protected function parse_page_specific_column( $column_name, $record, $attributes ) { // Fill meta data if exists in $this->meta_data. - $meta_data = ( ! empty( $this->meta_data[ $record->ID ] ) ) ? $this->meta_data[ $record->ID ] : array(); + $meta_data = ( ! empty( $this->meta_data[ $record->ID ] ) ) ? $this->meta_data[ $record->ID ] : []; switch ( $column_name ) { case 'col_existing_yoast_seo_title': - // @todo Inconsistent echo/return behavior R. + // @todo Inconsistent return/echo behavior R. + // I traced the escaping of the attributes to WPSEO_Bulk_List_Table::column_attributes. + // The output of WPSEO_Bulk_List_Table::parse_meta_data_field is properly escaped. + // phpcs:ignore WordPress.Security.EscapeOutput echo $this->parse_meta_data_field( $record->ID, $attributes ); break; @@ -84,4 +86,4 @@ class WPSEO_Bulk_Title_Editor_List_Table extends WPSEO_Bulk_List_Table { unset( $meta_data ); } -} /* End of class */ +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-collector.php b/wp-content/plugins/wordpress-seo/admin/class-collector.php index f1ae1e6b..f7687974 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-collector.php +++ b/wp-content/plugins/wordpress-seo/admin/class-collector.php @@ -10,8 +10,12 @@ */ class WPSEO_Collector { - /** @var WPSEO_Collection[] */ - protected $collections = array(); + /** + * Holds the collections. + * + * @var WPSEO_Collection[] + */ + protected $collections = []; /** * Adds a collection object to the collections. @@ -28,7 +32,7 @@ class WPSEO_Collector { * @return array The collected data. */ public function collect() { - $data = array(); + $data = []; foreach ( $this->collections as $collection ) { $data = array_merge( $data, $collection->get() ); @@ -43,6 +47,6 @@ class WPSEO_Collector { * @return false|string The encode string. */ public function get_as_json() { - return wp_json_encode( $this->collect() ); + return WPSEO_Utils::format_json_encode( $this->collect() ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-config.php b/wp-content/plugins/wordpress-seo/admin/class-config.php index 294b89f8..444ee139 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-config.php +++ b/wp-content/plugins/wordpress-seo/admin/class-config.php @@ -5,15 +5,19 @@ * @package WPSEO\Admin */ +use Yoast\WP\SEO\Config\Schema_Types; + /** - * Class WPSEO_Admin_Pages + * Class WPSEO_Admin_Pages. * * Class with functionality for the Yoast SEO admin pages. */ class WPSEO_Admin_Pages { /** - * @var string $currentoption The option in use for the current admin page. + * The option in use for the current admin page. + * + * @var string */ public $currentoption = 'wpseo'; @@ -25,15 +29,15 @@ class WPSEO_Admin_Pages { private $asset_manager; /** - * Class constructor, which basically only hooks the init function on the init hook + * Class constructor, which basically only hooks the init function on the init hook. */ public function __construct() { - add_action( 'init', array( $this, 'init' ), 20 ); + add_action( 'init', [ $this, 'init' ], 20 ); $this->asset_manager = new WPSEO_Admin_Asset_Manager(); } /** - * Make sure the needed scripts are loaded for admin pages + * Make sure the needed scripts are loaded for admin pages. */ public function init() { if ( filter_input( INPUT_GET, 'wpseo_reset_defaults' ) && wp_verify_nonce( filter_input( INPUT_GET, 'nonce' ), 'wpseo_reset_defaults' ) && current_user_can( 'manage_options' ) ) { @@ -41,23 +45,8 @@ class WPSEO_Admin_Pages { wp_redirect( admin_url( 'admin.php?page=' . WPSEO_Configuration_Page::PAGE_IDENTIFIER ) ); } - add_action( 'admin_init', array( $this, 'admin_init' ) ); - add_action( 'admin_enqueue_scripts', array( $this, 'config_page_scripts' ) ); - add_action( 'admin_enqueue_scripts', array( $this, 'config_page_styles' ) ); - } - - /** - * Run admin-specific actions. - */ - public function admin_init() { - - $page = filter_input( INPUT_GET, 'page' ); - $tool = filter_input( INPUT_GET, 'tool' ); - $export_nonce = filter_input( INPUT_POST, WPSEO_Export::NONCE_NAME ); - - if ( 'wpseo_tools' === $page && 'import-export' === $tool && $export_nonce !== null ) { - $this->do_yoast_export(); - } + add_action( 'admin_enqueue_scripts', [ $this, 'config_page_scripts' ] ); + add_action( 'admin_enqueue_scripts', [ $this, 'config_page_styles' ] ); } /** @@ -69,45 +58,118 @@ class WPSEO_Admin_Pages { wp_enqueue_style( 'global' ); wp_enqueue_style( 'wp-admin' ); $this->asset_manager->enqueue_style( 'select2' ); - $this->asset_manager->enqueue_style( 'admin-css' ); + + $page = filter_input( INPUT_GET, 'page' ); + if ( $page === 'wpseo_titles' ) { + $this->asset_manager->enqueue_style( 'search-appearance' ); + } + + if ( $page === 'wpseo_social' || $page === 'wpseo_licenses' ) { + $this->asset_manager->enqueue_style( 'monorepo' ); + } } /** * Loads the required scripts for the config page. */ public function config_page_scripts() { - $this->asset_manager->enqueue_script( 'admin-script' ); - $this->asset_manager->enqueue_script( 'help-center' ); - + $this->asset_manager->enqueue_script( 'settings' ); wp_enqueue_script( 'dashboard' ); wp_enqueue_script( 'thickbox' ); + $alert_dismissal_action = YoastSEO()->classes->get( \Yoast\WP\SEO\Actions\Alert_Dismissal_Action::class ); + $dismissed_alerts = $alert_dismissal_action->all_dismissed(); + + $script_data = [ + 'userLanguageCode' => WPSEO_Language_Utils::get_language( \get_user_locale() ), + 'dismissedAlerts' => $dismissed_alerts, + ]; + $page = filter_input( INPUT_GET, 'page' ); - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'admin-script', 'wpseoSelect2Locale', WPSEO_Utils::get_language( WPSEO_Utils::get_user_locale() ) ); + if ( $page === 'wpseo_titles' ) { + $script_data['analysis'] = [ + 'plugins' => [ + 'replaceVars' => $this->get_replace_vars_script_data(), + ], + ]; - if ( in_array( $page, array( 'wpseo_social', WPSEO_Admin::PAGE_IDENTIFIER, 'wpseo_titles' ), true ) ) { + $schema_types = new Schema_Types(); + $script_data['searchAppearance'] = [ + 'isRtl' => is_rtl(), + 'userEditUrl' => add_query_arg( 'user_id', '{user_id}', admin_url( 'user-edit.php' ) ), + 'brushstrokeBackgroundURL' => plugins_url( 'images/brushstroke_background.svg', WPSEO_FILE ), + 'showLocalSEOUpsell' => $this->should_show_local_seo_upsell(), + 'localSEOUpsellURL' => WPSEO_Shortlinker::get( 'https://yoa.st/3mp' ), + 'knowledgeGraphCompanyInfoMissing' => WPSEO_Language_Utils::get_knowledge_graph_company_info_missing_l10n(), + 'schema' => [ + 'pageTypeOptions' => $schema_types->get_page_type_options(), + 'articleTypeOptions' => $schema_types->get_article_type_options(), + ], + ]; + + /** + * Remove the emoji script as it is incompatible with both React and any + * contenteditable fields. + */ + remove_action( 'admin_print_scripts', 'print_emoji_detection_script' ); + + $yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_L10n(); + $yoast_components_l10n->localize_script( 'settings' ); + } + + if ( in_array( $page, [ 'wpseo_social', WPSEO_Admin::PAGE_IDENTIFIER, 'wpseo_titles' ], true ) ) { wp_enqueue_media(); - $this->asset_manager->enqueue_script( 'admin-media' ); - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'admin-media', 'wpseoMediaL10n', $this->localize_media_script() ); + $script_data['media'] = [ + 'choose_image' => __( 'Use Image', 'wordpress-seo' ), + ]; } - if ( 'wpseo_tools' === $page ) { + if ( $page === 'wpseo_tools' ) { $this->enqueue_tools_scripts(); } + + if ( $page === 'wpseo_social' ) { + $script_data['social'] = true; + } + + $this->asset_manager->localize_script( 'settings', 'wpseoScriptData', $script_data ); + $this->asset_manager->enqueue_user_language_script(); } /** - * Pass some variables to js for upload module. + * Retrieves some variables that are needed for replacing variables in JS. * - * @return array + * @return array The replacement and recommended replacement variables. */ - public function localize_media_script() { - return array( - 'choose_image' => __( 'Use Image', 'wordpress-seo' ), - ); + public function get_replace_vars_script_data() { + $replace_vars = new WPSEO_Replace_Vars(); + $recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars(); + $editor_specific_replace_vars = new WPSEO_Admin_Editor_Specific_Replace_Vars(); + $replace_vars_list = $replace_vars->get_replacement_variables_list(); + + return [ + 'replace_vars' => $replace_vars_list, + 'recommended_replace_vars' => $recommended_replace_vars->get_recommended_replacevars(), + 'editor_specific_replace_vars' => $editor_specific_replace_vars->get(), + 'shared_replace_vars' => $editor_specific_replace_vars->get_generic( $replace_vars_list ), + ]; + } + + /** + * Determines whether the Local SEO upsell should be shown. + * + * The Local SEO upsell should: + * - Only be shown in Free, not when Premium is active. + * - Not be shown when Local SEO is active. + * + * @return bool Whether the Local SEO upsell should be shown. + */ + private function should_show_local_seo_upsell() { + return ! YoastSEO()->helpers->product->is_premium() + && ! ( defined( 'WPSEO_LOCAL_FILE' ) ); } /** @@ -120,28 +182,8 @@ class WPSEO_Admin_Pages { $this->asset_manager->enqueue_script( 'yoast-seo' ); } - if ( 'bulk-editor' === $tool ) { + if ( $tool === 'bulk-editor' ) { $this->asset_manager->enqueue_script( 'bulk-editor' ); } } - - /** - * Runs the yoast exporter class to possibly init the file download. - */ - private function do_yoast_export() { - check_admin_referer( WPSEO_Export::NONCE_ACTION, WPSEO_Export::NONCE_NAME ); - - if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) { - return; - } - - $wpseo_post = filter_input( INPUT_POST, 'wpseo' ); - $include_taxonomy = ! empty( $wpseo_post['include_taxonomy'] ); - $export = new WPSEO_Export( $include_taxonomy ); - - if ( $export->has_error() ) { - add_action( 'admin_notices', array( $export, 'set_error_hook' ) ); - - } - } -} /* End of class */ +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-cornerstone-field.php b/wp-content/plugins/wordpress-seo/admin/class-cornerstone-field.php deleted file mode 100644 index 094fbe93..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-cornerstone-field.php +++ /dev/null @@ -1,57 +0,0 @@ -', - WPSEO_Cornerstone::META_NAME, - checked( $this->get_meta_value( $post->ID ), '1', false ) - ); - - $return .= sprintf( ''; - - return $return; - } - - /** - * Gets the meta value from the database. - * - * @param int $post_id The post id to get the meta value for. - * - * @return null|string The meta value from the database. - */ - protected function get_meta_value( $post_id ) { - return get_post_meta( $post_id, WPSEO_Cornerstone::META_NAME, true ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-cornerstone.php b/wp-content/plugins/wordpress-seo/admin/class-cornerstone.php deleted file mode 100644 index 167f7766..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-cornerstone.php +++ /dev/null @@ -1,92 +0,0 @@ -page_contains_cornerstone_content_field( $pagenow ) ) { - return; - } - - add_action( 'save_post', array( $this, 'save_meta_value' ) ); - add_filter( 'wpseo_cornerstone_post_types', array( 'WPSEO_Post_Type', 'filter_attachment_post_type' ) ); - } - - /** - * Saves the meta value to the database. - * - * @param int $post_id The post id to save the meta value for. - * - * @return void - */ - public function save_meta_value( $post_id ) { - $is_cornerstone_content = $this->is_cornerstone_content(); - - if ( $is_cornerstone_content ) { - $this->update_meta( $post_id, $is_cornerstone_content ); - - return; - } - - $this->delete_meta( $post_id ); - } - - /** - * Returns the result of the cornerstone content checkbox. - * - * @return bool True when checkbox is checked. - */ - protected function is_cornerstone_content() { - return filter_input( INPUT_POST, self::META_NAME ) === '1'; - } - - /** - * Checks if the current page matches one of the pages that contains the cornerstone content field. - * - * @param string $page The page to check. - * - * @return bool True when the page contains the cornerstone content field. - */ - protected function page_contains_cornerstone_content_field( $page ) { - return WPSEO_Metabox::is_post_edit( $page ); - } - - /** - * Updates the cornerstone content post meta with the given cornerstone content value. - * - * @param int $post_id The post id to save the meta value for. - * @param bool $is_cornerstone_content Whether or not the post should be considered to be cornerstone content. - * - * @return void - */ - protected function update_meta( $post_id, $is_cornerstone_content ) { - update_post_meta( $post_id, self::META_NAME, $is_cornerstone_content ); - } - - /** - * Deletes the cornerstone content post meta for the given post id. - * - * @param int $post_id The post id to delete the cornerstone content meta value for.. - * - * @return void - */ - protected function delete_meta( $post_id ) { - delete_post_meta( $post_id, self::META_NAME ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-customizer.php b/wp-content/plugins/wordpress-seo/admin/class-customizer.php index a22ae6ce..5771e466 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-customizer.php +++ b/wp-content/plugins/wordpress-seo/admin/class-customizer.php @@ -11,19 +11,52 @@ class WPSEO_Customizer { /** + * Holds the customize manager. + * * @var WP_Customize_Manager */ protected $wp_customize; + /** + * Template for the setting IDs used for the customizer. + * + * @var string + */ + private $setting_template = 'wpseo_titles[%s]'; + + /** + * Default arguments for the breadcrumbs customizer settings object. + * + * @var array + */ + private $default_setting_args = [ + 'default' => '', + 'type' => 'option', + 'transport' => 'refresh', + ]; + + /** + * Default arguments for the breadcrumbs customizer control object. + * + * @var array + */ + private $default_control_args = [ + 'label' => '', + 'type' => 'text', + 'section' => 'wpseo_breadcrumbs_customizer_section', + 'settings' => '', + 'context' => '', + ]; + /** * Construct Method. */ public function __construct() { - add_action( 'customize_register', array( $this, 'wpseo_customize_register' ) ); + add_action( 'customize_register', [ $this, 'wpseo_customize_register' ] ); } /** - * Function to support WordPress Customizer + * Function to support WordPress Customizer. * * @param WP_Customize_Manager $wp_customize Manager class instance. */ @@ -35,7 +68,7 @@ class WPSEO_Customizer { $this->wp_customize = $wp_customize; $this->breadcrumbs_section(); - $this->breadcrumbs_blog_remove_setting(); + $this->breadcrumbs_blog_show_setting(); $this->breadcrumbs_separator_setting(); $this->breadcrumbs_home_setting(); $this->breadcrumbs_prefix_setting(); @@ -45,211 +78,152 @@ class WPSEO_Customizer { } /** - * Add the breadcrumbs section to the customizer + * Add the breadcrumbs section to the customizer. */ private function breadcrumbs_section() { - $this->wp_customize->add_section( - 'wpseo_breadcrumbs_customizer_section', array( - /* translators: %s is the name of the plugin */ - 'title' => sprintf( __( '%s Breadcrumbs', 'wordpress-seo' ), 'Yoast SEO' ), - 'priority' => 999, - 'active_callback' => array( $this, 'breadcrumbs_active_callback' ), - ) - ); + $section_args = [ + /* translators: %s is the name of the plugin */ + 'title' => sprintf( __( '%s Breadcrumbs', 'wordpress-seo' ), 'Yoast SEO' ), + 'priority' => 999, + 'active_callback' => [ $this, 'breadcrumbs_active_callback' ], + ]; + $this->wp_customize->add_section( 'wpseo_breadcrumbs_customizer_section', $section_args ); } /** - * Returns whether or not the breadcrumbs are active + * Returns whether or not the breadcrumbs are active. * * @return bool */ public function breadcrumbs_active_callback() { - return true === ( current_theme_supports( 'yoast-seo-breadcrumbs' ) || WPSEO_Options::get( 'breadcrumbs-enable' ) ); + return current_theme_supports( 'yoast-seo-breadcrumbs' ) || WPSEO_Options::get( 'breadcrumbs-enable' ); } /** - * Adds the breadcrumbs remove blog checkbox + * Adds the breadcrumbs show blog checkbox. */ - private function breadcrumbs_blog_remove_setting() { - $this->wp_customize->add_setting( - 'wpseo_titles[breadcrumbs-display-blog-page]', array( - 'default' => '', - 'type' => 'option', - 'transport' => 'refresh', - ) - ); + private function breadcrumbs_blog_show_setting() { + $index = 'breadcrumbs-display-blog-page'; + $control_args = [ + 'label' => __( 'Show blog page in breadcrumbs', 'wordpress-seo' ), + 'type' => 'checkbox', + 'active_callback' => [ $this, 'breadcrumbs_blog_show_active_cb' ], + ]; - $this->wp_customize->add_control( - new WP_Customize_Control( - $this->wp_customize, 'wpseo-breadcrumbs-display-blog-page', array( - 'label' => __( 'Remove blog page from breadcrumbs', 'wordpress-seo' ), - 'type' => 'checkbox', - 'section' => 'wpseo_breadcrumbs_customizer_section', - 'settings' => 'wpseo_titles[breadcrumbs-display-blog-page]', - 'context' => '', - 'active_callback' => array( $this, 'breadcrumbs_blog_remove_active_cb' ), - ) - ) - ); + $this->add_setting_and_control( $index, $control_args ); } /** - * Returns whether or not to show the breadcrumbs blog remove option + * Returns whether or not to show the breadcrumbs blog show option. * * @return bool */ - public function breadcrumbs_blog_remove_active_cb() { - return 'page' === get_option( 'show_on_front' ); + public function breadcrumbs_blog_show_active_cb() { + return get_option( 'show_on_front' ) === 'page'; } /** - * Adds the breadcrumbs separator text field + * Adds the breadcrumbs separator text field. */ private function breadcrumbs_separator_setting() { - $this->wp_customize->add_setting( - 'wpseo_titles[breadcrumbs-sep]', array( - 'default' => '', - 'type' => 'option', - 'transport' => 'refresh', - ) - ); + $index = 'breadcrumbs-sep'; + $control_args = [ + 'label' => __( 'Breadcrumbs separator:', 'wordpress-seo' ), + ]; + $id = 'wpseo-breadcrumbs-separator'; - $this->wp_customize->add_control( - new WP_Customize_Control( - $this->wp_customize, 'wpseo-breadcrumbs-separator', array( - 'label' => __( 'Breadcrumbs separator:', 'wordpress-seo' ), - 'type' => 'text', - 'section' => 'wpseo_breadcrumbs_customizer_section', - 'settings' => 'wpseo_titles[breadcrumbs-sep]', - 'context' => '', - ) - ) - ); + $this->add_setting_and_control( $index, $control_args, $id ); } /** - * Adds the breadcrumbs home anchor text field + * Adds the breadcrumbs home anchor text field. */ private function breadcrumbs_home_setting() { - $this->wp_customize->add_setting( - 'wpseo_titles[breadcrumbs-home]', array( - 'default' => '', - 'type' => 'option', - 'transport' => 'refresh', - ) - ); + $index = 'breadcrumbs-home'; + $control_args = [ + 'label' => __( 'Anchor text for the homepage:', 'wordpress-seo' ), + ]; - $this->wp_customize->add_control( - new WP_Customize_Control( - $this->wp_customize, 'wpseo-breadcrumbs-home', array( - 'label' => __( 'Anchor text for the homepage:', 'wordpress-seo' ), - 'type' => 'text', - 'section' => 'wpseo_breadcrumbs_customizer_section', - 'settings' => 'wpseo_titles[breadcrumbs-home]', - 'context' => '', - ) - ) - ); + $this->add_setting_and_control( $index, $control_args ); } /** - * Adds the breadcrumbs prefix text field + * Adds the breadcrumbs prefix text field. */ private function breadcrumbs_prefix_setting() { - $this->wp_customize->add_setting( - 'wpseo_titles[breadcrumbs-prefix]', array( - 'default' => '', - 'type' => 'option', - 'transport' => 'refresh', - ) - ); + $index = 'breadcrumbs-prefix'; + $control_args = [ + 'label' => __( 'Prefix for breadcrumbs:', 'wordpress-seo' ), + ]; - $this->wp_customize->add_control( - new WP_Customize_Control( - $this->wp_customize, 'wpseo-breadcrumbs-prefix', array( - 'label' => __( 'Prefix for breadcrumbs:', 'wordpress-seo' ), - 'type' => 'text', - 'section' => 'wpseo_breadcrumbs_customizer_section', - 'settings' => 'wpseo_titles[breadcrumbs-prefix]', - 'context' => '', - ) - ) - ); + $this->add_setting_and_control( $index, $control_args ); } /** - * Adds the breadcrumbs archive prefix text field + * Adds the breadcrumbs archive prefix text field. */ private function breadcrumbs_archiveprefix_setting() { - $this->wp_customize->add_setting( - 'wpseo_titles[breadcrumbs-archiveprefix]', array( - 'default' => '', - 'type' => 'option', - 'transport' => 'refresh', - ) - ); + $index = 'breadcrumbs-archiveprefix'; + $control_args = [ + 'label' => __( 'Prefix for archive pages:', 'wordpress-seo' ), + ]; - $this->wp_customize->add_control( - new WP_Customize_Control( - $this->wp_customize, 'wpseo-breadcrumbs-archiveprefix', array( - 'label' => __( 'Prefix for archive pages:', 'wordpress-seo' ), - 'type' => 'text', - 'section' => 'wpseo_breadcrumbs_customizer_section', - 'settings' => 'wpseo_titles[breadcrumbs-archiveprefix]', - 'context' => '', - ) - ) - ); + $this->add_setting_and_control( $index, $control_args ); } /** - * Adds the breadcrumbs search prefix text field + * Adds the breadcrumbs search prefix text field. */ private function breadcrumbs_searchprefix_setting() { - $this->wp_customize->add_setting( - 'wpseo_titles[breadcrumbs-searchprefix]', array( - 'default' => '', - 'type' => 'option', - 'transport' => 'refresh', - ) - ); + $index = 'breadcrumbs-searchprefix'; + $control_args = [ + 'label' => __( 'Prefix for search result pages:', 'wordpress-seo' ), + ]; - $this->wp_customize->add_control( - new WP_Customize_Control( - $this->wp_customize, 'wpseo-breadcrumbs-searchprefix', array( - 'label' => __( 'Prefix for search result pages:', 'wordpress-seo' ), - 'type' => 'text', - 'section' => 'wpseo_breadcrumbs_customizer_section', - 'settings' => 'wpseo_titles[breadcrumbs-searchprefix]', - 'context' => '', - ) - ) - ); + $this->add_setting_and_control( $index, $control_args ); } /** - * Adds the breadcrumb 404 prefix text field + * Adds the breadcrumb 404 prefix text field. */ private function breadcrumbs_404_setting() { - $this->wp_customize->add_setting( - 'wpseo_titles[breadcrumbs-404crumb]', array( - 'default' => '', - 'type' => 'option', - 'transport' => 'refresh', - ) - ); + $index = 'breadcrumbs-404crumb'; + $control_args = [ + 'label' => __( 'Breadcrumb for 404 pages:', 'wordpress-seo' ), + ]; - $this->wp_customize->add_control( - new WP_Customize_Control( - $this->wp_customize, 'wpseo-breadcrumbs-404crumb', array( - 'label' => __( 'Breadcrumb for 404 pages:', 'wordpress-seo' ), - 'type' => 'text', - 'section' => 'wpseo_breadcrumbs_customizer_section', - 'settings' => 'wpseo_titles[breadcrumbs-404crumb]', - 'context' => '', - ) - ) - ); + $this->add_setting_and_control( $index, $control_args ); + } + + /** + * Adds the customizer setting and control. + * + * @param string $index Array key index to use for the customizer setting. + * @param array $control_args Customizer control object arguments. + * Only those different from the default need to be passed. + * @param string|null $id Optional. Customizer control object ID. + * Will default to 'wpseo-' . $index. + * @param array $custom_settings Optional. Customizer setting arguments. + * Only those different from the default need to be passed. + */ + private function add_setting_and_control( $index, $control_args, $id = null, $custom_settings = [] ) { + $setting = sprintf( $this->setting_template, $index ); + $control_args = array_merge( $this->default_control_args, $control_args ); + $control_args['settings'] = $setting; + + $settings_args = $this->default_setting_args; + if ( ! empty( $custom_settings ) ) { + $settings_args = array_merge( $settings_args, $custom_settings ); + } + + if ( ! isset( $id ) ) { + $id = 'wpseo-' . $index; + } + + $this->wp_customize->add_setting( $setting, $settings_args ); + + $control = new WP_Customize_Control( $this->wp_customize, $id, $control_args ); + $this->wp_customize->add_control( $control ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-database-proxy.php b/wp-content/plugins/wordpress-seo/admin/class-database-proxy.php index f1b06dfd..c4ca791b 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-database-proxy.php +++ b/wp-content/plugins/wordpress-seo/admin/class-database-proxy.php @@ -6,33 +6,68 @@ */ /** - * Represents the proxy for communicating with the database + * Represents the proxy for communicating with the database. */ class WPSEO_Database_Proxy { - /** @var string */ + /** + * Holds the table name. + * + * @var string + */ protected $table_name; - /** @var bool */ + /** + * Determines whether to suppress errors or not. + * + * @var bool + */ protected $suppress_errors = true; - /** @var bool */ + /** + * Determines if this table is multisite. + * + * @var bool + */ + protected $is_multisite_table = false; + + /** + * Holds the last suppressed state. + * + * @var bool + */ protected $last_suppressed_state; - /** @var wpdb */ + /** + * Holds the WordPress database object. + * + * @var wpdb + */ protected $database; /** - * Sets the class attributes. + * Sets the class attributes and registers the table. * - * @param wpdb $database The database object. - * @param string $table_name The table name that is represented. - * @param bool $suppress_errors Should the errors be suppressed. + * @param wpdb $database The database object. + * @param string $table_name The table name that is represented. + * @param bool $suppress_errors Should the errors be suppressed. + * @param bool $is_multisite_table Should the table be global in multisite. */ - public function __construct( $database, $table_name, $suppress_errors = true ) { - $this->table_name = $table_name; - $this->suppress_errors = (bool) $suppress_errors; - $this->database = $database; + public function __construct( $database, $table_name, $suppress_errors = true, $is_multisite_table = false ) { + $this->table_name = $table_name; + $this->suppress_errors = (bool) $suppress_errors; + $this->is_multisite_table = (bool) $is_multisite_table; + $this->database = $database; + + // If the table prefix was provided, strip it as it's handled automatically. + $table_prefix = $this->get_table_prefix(); + if ( ! empty( $table_prefix ) && strpos( $this->table_name, $table_prefix ) === 0 ) { + $this->table_prefix = substr( $this->table_name, strlen( $table_prefix ) ); + } + + if ( ! $this->is_table_registered() ) { + $this->register_table(); + } } /** @@ -58,7 +93,7 @@ class WPSEO_Database_Proxy { * * @param array $data Data to update on the table. * @param array $where Where condition as key => value array. - * @param null $format Optional. data prepare format. + * @param null $format Optional. Data prepare format. * @param null $where_format Optional. Where prepare format. * * @return false|int False when the update request is invalid, int on number of rows changed. @@ -76,22 +111,47 @@ class WPSEO_Database_Proxy { /** * Upserts data in the database. * - * Tries to insert the data first, if this fails an update is attempted. + * Performs an insert into and if key is duplicate it will update the existing record. * - * @param array $data Data to update on the table. - * @param array $where Where condition as key => value array. - * @param null $format Optional. data prepare format. - * @param null $where_format Optional. Where prepare format. + * @param array $data Data to update on the table. + * @param array|null $where Unused. Where condition as key => value array. + * @param null $format Optional. Data prepare format. + * @param null $where_format Deprecated. Where prepare format. * * @return false|int False when the upsert request is invalid, int on number of rows changed. */ - public function upsert( array $data, array $where, $format = null, $where_format = null ) { - $result = $this->insert( $data, $format ); - - if ( false === $result ) { - $result = $this->update( $data, $where, $format, $where_format ); + public function upsert( array $data, array $where = null, $format = null, $where_format = null ) { + if ( $where_format !== null ) { + _deprecated_argument( __METHOD__, '7.7.0', 'The where_format argument is deprecated' ); } + $this->pre_execution(); + + $update = []; + $keys = []; + $columns = array_keys( $data ); + foreach ( $columns as $column ) { + $keys[] = '`' . $column . '`'; + $update[] = sprintf( '`%1$s` = VALUES(`%1$s`)', $column ); + } + + $query = sprintf( + 'INSERT INTO `%1$s` (%2$s) VALUES ( %3$s ) ON DUPLICATE KEY UPDATE %4$s', + $this->get_table_name(), + implode( ', ', $keys ), + implode( ', ', array_fill( 0, count( $data ), '%s' ) ), + implode( ', ', $update ) + ); + + $result = $this->database->query( + $this->database->prepare( + $query, + array_values( $data ) + ) + ); + + $this->post_execution(); + return $result; } @@ -99,7 +159,7 @@ class WPSEO_Database_Proxy { * Deletes a record from the database. * * @param array $where Where clauses for the query. - * @param null|array $format Formats for the data. + * @param array|null $format Formats for the data. * * @return false|int */ @@ -118,7 +178,7 @@ class WPSEO_Database_Proxy { * * @param string $query The query to execute. * - * @return array|null|object The resultset + * @return array|object|null The resultset */ public function get_results( $query ) { $this->pre_execution(); @@ -138,9 +198,9 @@ class WPSEO_Database_Proxy { * * @return bool True when creation is successful. */ - public function create_table( array $columns, array $indexes = array() ) { - $create_table = sprintf( ' - CREATE TABLE IF NOT EXISTS %1$s ( %2$s ) %3$s', + public function create_table( array $columns, array $indexes = [] ) { + $create_table = sprintf( + 'CREATE TABLE IF NOT EXISTS %1$s ( %2$s ) %3$s', $this->get_table_name(), implode( ',', array_merge( $columns, $indexes ) ), $this->database->get_charset_collate() @@ -183,11 +243,56 @@ class WPSEO_Database_Proxy { } /** - * Returns the set table name. + * Returns the full table name. * - * @return string + * @return string Full table name including prefix. */ - protected function get_table_name() { - return $this->table_name; + public function get_table_name() { + return $this->get_table_prefix() . $this->table_name; + } + + /** + * Returns the prefix to use for the table. + * + * @return string The table prefix depending on the database context. + */ + protected function get_table_prefix() { + if ( $this->is_multisite_table ) { + return $this->database->base_prefix; + } + + return $this->database->get_blog_prefix(); + } + + /** + * Registers the table with WordPress. + * + * @return void + */ + protected function register_table() { + $table_name = $this->table_name; + $full_table_name = $this->get_table_name(); + + $this->database->$table_name = $full_table_name; + + if ( $this->is_multisite_table ) { + $this->database->ms_global_tables[] = $table_name; + return; + } + + $this->database->tables[] = $table_name; + } + + /** + * Checks if the table has been registered with WordPress. + * + * @return bool True if the table is registered, false otherwise. + */ + protected function is_table_registered() { + if ( $this->is_multisite_table ) { + return in_array( $this->table_name, $this->database->ms_global_tables, true ); + } + + return in_array( $this->table_name, $this->database->tables, true ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-export.php b/wp-content/plugins/wordpress-seo/admin/class-export.php index c1e4402d..a2e38a9d 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-export.php +++ b/wp-content/plugins/wordpress-seo/admin/class-export.php @@ -6,131 +6,98 @@ */ /** - * Class WPSEO_Export + * Class WPSEO_Export. * - * Class with functionality to export the WP SEO settings + * Class with functionality to export the WP SEO settings. */ class WPSEO_Export { - const ZIP_FILENAME = 'yoast-seo-settings-export.zip'; - const INI_FILENAME = 'settings.ini'; - + /** + * Holds the nonce action. + * + * @var string + */ const NONCE_ACTION = 'wpseo_export'; - const NONCE_NAME = 'wpseo_export_nonce'; /** + * Holds the export data. + * * @var string */ private $export = ''; /** - * @var string - */ - private $error = ''; - - /** - * @var string - */ - public $export_zip_url = ''; - - /** - * @var boolean + * Holds whether the export was a success. + * + * @var bool */ public $success; /** - * Whether or not the export will include taxonomy metadata - * - * @var boolean + * Handles the export request. */ - private $include_taxonomy; - - /** - * @var array - */ - private $dir = array(); - - - /** - * Class constructor - * - * @param boolean $include_taxonomy Whether to include the taxonomy metadata the plugin creates. - */ - public function __construct( $include_taxonomy = false ) { - $this->include_taxonomy = $include_taxonomy; - $this->dir = wp_upload_dir(); - + public function export() { + check_admin_referer( self::NONCE_ACTION ); $this->export_settings(); + $this->output(); } /** - * Returns true when the property error has a value. - * - * @return bool + * Outputs the export. */ - public function has_error() { - return ( $this->error !== '' ); - } - - /** - * Sets the error hook, to display the error to the user. - */ - public function set_error_hook() { - /* translators: %1$s expands to Yoast SEO */ - $message = sprintf( __( 'Error creating %1$s export: ', 'wordpress-seo' ), 'Yoast SEO' ) . $this->error; + public function output() { + if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) { + esc_html_e( 'You do not have the required rights to export settings.', 'wordpress-seo' ); + return; + } + echo '

'; printf( - '

%1$s

', - $message + /* translators: %1$s expands to Import settings */ + esc_html__( + 'Copy all these settings to another site\'s %1$s tab and click "%1$s" there.', + 'wordpress-seo' + ), + esc_html__( + 'Import settings', + 'wordpress-seo' + ) ); + echo '

'; + /* translators: %1$s expands to Yoast SEO */ + echo '
'; + echo ''; } /** * Exports the current site's WP SEO settings. */ private function export_settings() { - $this->export_header(); foreach ( WPSEO_Options::get_option_names() as $opt_group ) { $this->write_opt_group( $opt_group ); } - - $this->taxonomy_metadata(); - - if ( ! $this->write_settings_file() ) { - $this->error = __( 'Could not write settings to file.', 'wordpress-seo' ); - - return; - } - - if ( $this->zip_file() ) { - // Just exit, because there is a download being served. - exit; - } } /** - * Writes the header of the export file. + * Writes the header of the export. */ private function export_header() { $header = sprintf( /* translators: %1$s expands to Yoast SEO, %2$s expands to Yoast.com */ - esc_html__( 'This is a settings export file for the %1$s plugin by %2$s', 'wordpress-seo' ), + esc_html__( 'These are settings for the %1$s plugin by %2$s', 'wordpress-seo' ), 'Yoast SEO', 'Yoast.com' ); - $this->write_line( '; ' . $header . ' - ' . esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/1yd' ) ) ); - if ( $this->include_taxonomy ) { - $this->write_line( '; ' . __( 'This export includes taxonomy metadata', 'wordpress-seo' ) ); - } + $this->write_line( '; ' . $header ); } /** - * Writes a line to the export + * Writes a line to the export. * - * @param string $line Line string. - * @param boolean $newline_first Boolean flag whether to prepend with new line. + * @param string $line Line string. + * @param bool $newline_first Boolean flag whether to prepend with new line. */ private function write_line( $line, $newline_first = false ) { if ( $newline_first ) { @@ -140,7 +107,7 @@ class WPSEO_Export { } /** - * Writes an entire option group to the export + * Writes an entire option group to the export. * * @param string $opt_group Option group name. */ @@ -157,7 +124,7 @@ class WPSEO_Export { foreach ( $options as $key => $elem ) { if ( is_array( $elem ) ) { $count = count( $elem ); - for ( $i = 0; $i < $count; $i ++ ) { + for ( $i = 0; $i < $count; $i++ ) { $this->write_setting( $key . '[]', $elem[ $i ] ); } } @@ -168,7 +135,7 @@ class WPSEO_Export { } /** - * Writes a settings line to the export + * Writes a settings line to the export. * * @param string $key Key string. * @param string $val Value string. @@ -179,109 +146,4 @@ class WPSEO_Export { } $this->write_line( $key . ' = ' . $val ); } - - /** - * Adds the taxonomy meta data if there is any - */ - private function taxonomy_metadata() { - if ( $this->include_taxonomy ) { - $taxonomy_meta = get_option( 'wpseo_taxonomy_meta' ); - if ( is_array( $taxonomy_meta ) ) { - $this->write_line( '[wpseo_taxonomy_meta]', true ); - $this->write_setting( 'wpseo_taxonomy_meta', urlencode( wp_json_encode( $taxonomy_meta ) ) ); - } - else { - $this->write_line( '; ' . __( 'No taxonomy metadata found', 'wordpress-seo' ), true ); - } - } - } - - /** - * Writes the settings to our temporary settings.ini file - * - * @return boolean unsigned - */ - private function write_settings_file() { - $handle = fopen( $this->dir['path'] . '/' . self::INI_FILENAME, 'w' ); - if ( ! $handle ) { - return false; - } - - $res = fwrite( $handle, $this->export ); - if ( ! $res ) { - return false; - } - - fclose( $handle ); - - return true; - } - - /** - * Zips the settings ini file - * - * @return bool|null - */ - private function zip_file() { - $is_zip_created = $this->create_zip(); - - // The settings.ini isn't needed, because it's in the zipfile. - $this->remove_settings_ini(); - - if ( ! $is_zip_created ) { - $this->error = __( 'Could not zip settings-file.', 'wordpress-seo' ); - - return false; - } - - $this->serve_settings_export(); - $this->remove_zip(); - - return true; - } - - /** - * Creates the zipfile and returns true if it created successful. - * - * @return bool - */ - private function create_zip() { - chdir( $this->dir['path'] ); - $zip = new PclZip( './' . self::ZIP_FILENAME ); - if ( 0 === $zip->create( './' . self::INI_FILENAME ) ) { - return false; - } - - return file_exists( self::ZIP_FILENAME ); - } - - /** - * Downloads the zip file. - */ - private function serve_settings_export() { - // Clean any content that has been already output. For example by other plugins or faulty PHP files. - if ( ob_get_contents() ) { - ob_clean(); - } - header( 'Content-Type: application/octet-stream; charset=utf-8' ); - header( 'Content-Transfer-Encoding: Binary' ); - header( 'Content-Disposition: attachment; filename=' . self::ZIP_FILENAME ); - header( 'Content-Length: ' . filesize( self::ZIP_FILENAME ) ); - - readfile( self::ZIP_FILENAME ); - } - - /** - * Removes the settings ini file. - */ - private function remove_settings_ini() { - unlink( './' . self::INI_FILENAME ); - } - - /** - * Removes the files because they are already downloaded. - */ - private function remove_zip() { - unlink( './' . self::ZIP_FILENAME ); - } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-expose-shortlinks.php b/wp-content/plugins/wordpress-seo/admin/class-expose-shortlinks.php new file mode 100644 index 00000000..3cacce17 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-expose-shortlinks.php @@ -0,0 +1,115 @@ + 'https://yoa.st/allow-search-engines', + 'shortlinks.advanced.follow_links' => 'https://yoa.st/follow-links', + 'shortlinks.advanced.meta_robots' => 'https://yoa.st/meta-robots-advanced', + 'shortlinks.advanced.breadcrumbs_title' => 'https://yoa.st/breadcrumbs-title', + 'shortlinks.metabox.schema.explanation' => 'https://yoa.st/400', + 'shortlinks.metabox.schema.page_type' => 'https://yoa.st/402', + 'shortlinks.sidebar.schema.explanation' => 'https://yoa.st/401', + 'shortlinks.sidebar.schema.page_type' => 'https://yoa.st/403', + 'shortlinks.focus_keyword_info' => 'https://yoa.st/focus-keyword', + 'shortlinks.nofollow_sponsored' => 'https://yoa.st/nofollow-sponsored', + 'shortlinks.snippet_preview_info' => 'https://yoa.st/snippet-preview', + 'shortlinks.cornerstone_content_info' => 'https://yoa.st/1i9', + 'shortlinks.upsell.social_previews' => 'https://yoa.st/social-preview-cta', + 'shortlinks.upsell.sidebar.focus_keyword_synonyms_link' => 'https://yoa.st/textlink-synonyms-popup-sidebar', + 'shortlinks.upsell.sidebar.focus_keyword_synonyms_button' => 'https://yoa.st/keyword-synonyms-popup-sidebar', + 'shortlinks.upsell.sidebar.focus_keyword_additional_link' => 'https://yoa.st/textlink-keywords-popup-sidebar', + 'shortlinks.upsell.sidebar.focus_keyword_additional_button' => 'https://yoa.st/add-keywords-popup-sidebar', + 'shortlinks.upsell.sidebar.additional_link' => 'https://yoa.st/textlink-keywords-sidebar', + 'shortlinks.upsell.sidebar.additional_button' => 'https://yoa.st/add-keywords-sidebar', + 'shortlinks.upsell.metabox.go_premium' => 'https://yoa.st/pe-premium-page', + 'shortlinks.upsell.metabox.focus_keyword_synonyms_link' => 'https://yoa.st/textlink-synonyms-popup-metabox', + 'shortlinks.upsell.metabox.focus_keyword_synonyms_button' => 'https://yoa.st/keyword-synonyms-popup', + 'shortlinks.upsell.metabox.focus_keyword_additional_link' => 'https://yoa.st/textlink-keywords-popup-metabox', + 'shortlinks.upsell.metabox.focus_keyword_additional_button' => 'https://yoa.st/add-keywords-popup', + 'shortlinks.upsell.metabox.additional_link' => 'https://yoa.st/textlink-keywords-metabox', + 'shortlinks.upsell.metabox.additional_button' => 'https://yoa.st/add-keywords-metabox', + 'shortlinks.upsell.gsc.create_redirect_button' => 'https://yoa.st/redirects', + 'shortlinks.readability_analysis_info' => 'https://yoa.st/readability-analysis', + 'shortlinks.activate_premium_info' => 'https://yoa.st/activate-subscription', + 'shortlinks.upsell.sidebar.morphology_upsell_metabox' => 'https://yoa.st/morphology-upsell-metabox', + 'shortlinks.upsell.sidebar.morphology_upsell_sidebar' => 'https://yoa.st/morphology-upsell-sidebar', + 'shortlinks.semrush.volume_help' => 'https://yoa.st/3-v', + 'shortlinks.semrush.trend_help' => 'https://yoa.st/3-v', + 'shortlinks.semrush.prices' => 'https://yoa.st/semrush-prices', + 'shortlinks.semrush.premium_landing_page' => 'https://yoa.st/413', + ]; + + /** + * Registers all hooks to WordPress. + * + * @return void + */ + public function register_hooks() { + add_filter( 'wpseo_admin_l10n', [ $this, 'expose_shortlinks' ] ); + } + + /** + * Adds shortlinks to the passed array. + * + * @param array $input The array to add shortlinks to. + * + * @return array The passed array with the additional shortlinks. + */ + public function expose_shortlinks( $input ) { + foreach ( $this->get_shortlinks() as $key => $shortlink ) { + $input[ $key ] = WPSEO_Shortlinker::get( $shortlink ); + } + + $input['default_query_params'] = WPSEO_Shortlinker::get_query_params(); + + return $input; + } + + /** + * Retrieves the shortlinks. + * + * @return array The shortlinks. + */ + private function get_shortlinks() { + if ( ! $this->is_term_edit() ) { + return $this->shortlinks; + } + + $shortlinks = $this->shortlinks; + + $shortlinks['shortlinks.upsell.metabox.focus_keyword_synonyms_link'] = 'https://yoa.st/textlink-synonyms-popup-metabox-term'; + $shortlinks['shortlinks.upsell.metabox.focus_keyword_synonyms_button'] = 'https://yoa.st/keyword-synonyms-popup-term'; + $shortlinks['shortlinks.upsell.metabox.focus_keyword_additional_link'] = 'https://yoa.st/textlink-keywords-popup-metabox-term'; + $shortlinks['shortlinks.upsell.metabox.focus_keyword_additional_button'] = 'https://yoa.st/add-keywords-popup-term'; + $shortlinks['shortlinks.upsell.metabox.additional_link'] = 'https://yoa.st/textlink-keywords-metabox-term'; + $shortlinks['shortlinks.upsell.metabox.additional_button'] = 'https://yoa.st/add-keywords-metabox-term'; + $shortlinks['shortlinks.upsell.sidebar.morphology_upsell_metabox'] = 'https://yoa.st/morphology-upsell-metabox-term'; + + return $shortlinks; + } + + /** + * Checks if the current page is a term edit page. + * + * @return bool True when page is term edit. + */ + private function is_term_edit() { + global $pagenow; + + return WPSEO_Taxonomy::is_term_edit( $pagenow ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-extension-manager.php b/wp-content/plugins/wordpress-seo/admin/class-extension-manager.php deleted file mode 100644 index 835cb586..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-extension-manager.php +++ /dev/null @@ -1,140 +0,0 @@ -extensions[ $extension_name ] = $extension; - } - - /** - * Removes an extension from the manager. - * - * @param string $extension_name The name of the extension to remove. - * - * @return void - */ - public function remove( $extension_name ) { - if ( array_key_exists( $extension_name, $this->extensions ) ) { - unset( $this->extensions[ $extension_name ] ); - } - } - - /** - * Returns the extension for the given extension name. - * - * @param string $extension_name The name of the extension to get. - * - * @return null|WPSEO_Extension The extension object or null when it doesn't exist. - */ - public function get( $extension_name ) { - if ( array_key_exists( $extension_name, $this->extensions ) ) { - return $this->extensions[ $extension_name ]; - } - - return null; - } - - /** - * Returns all set extension. - * - * @return WPSEO_Extension[] Array with the extensions. - */ - public function get_all() { - return $this->extensions; - } - - /** - * Checks if the plugin is activated within My Yoast. - * - * @param string $extension_name The extension name to check. - * - * @return bool True when the plugin is activated. - */ - public function is_activated( $extension_name ) { - if ( self::$active_extensions === null ) { - // Force re-check on license & dashboard pages. - $current_page = $this->get_current_page(); - - // Check whether the licenses are valid or whether we need to show notifications. - $exclude_cache = ( $current_page === 'wpseo_licenses' || $current_page === 'wpseo_dashboard' ); - - // Fetch transient data on any other page. - if ( ! $exclude_cache ) { - self::$active_extensions = $this->get_cached_extensions(); - } - - // If the active extensions is still NULL, we need to set it. - if ( ! is_array( self::$active_extensions ) ) { - self::$active_extensions = $this->retrieve_active_extensions(); - - $this->set_cached_extensions( self::$active_extensions ); - } - } - - return in_array( $extension_name, self::$active_extensions, true ); - } - - /** - * Retrieves the active extensions via an external request. - * - * @return array Array containing the active extensions. - */ - protected function retrieve_active_extensions() { - return (array) apply_filters( 'yoast-active-extensions', array() ); - } - - /** - * Returns the current page. - * - * @return string The current page. - */ - protected function get_current_page() { - return filter_input( INPUT_GET, 'page' ); - } - - /** - * Gets a cached list of active extensions. - * - * @return boolean|array The cached extensions. - */ - protected function get_cached_extensions() { - return get_transient( self::TRANSIENT_CACHE_KEY ); - } - - /** - * Sets the active extensions transient for the set duration. - * - * @param array $extensions The extensions to add. - * @param int $duration The duration that the list of extensions needs to remain cached. - * - * @return void - */ - protected function set_cached_extensions( $extensions, $duration = DAY_IN_SECONDS ) { - set_transient( self::TRANSIENT_CACHE_KEY, $extensions, $duration ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-extensions.php b/wp-content/plugins/wordpress-seo/admin/class-extensions.php deleted file mode 100644 index 96969ca2..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-extensions.php +++ /dev/null @@ -1,108 +0,0 @@ - array( - 'slug' => 'yoast-seo-premium', - 'identifier' => 'wordpress-seo-premium', - 'classname' => 'WPSEO_Premium', - ), - 'News SEO' => array( - 'slug' => 'news-seo', - 'identifier' => 'wpseo-news', - 'classname' => 'WPSEO_News', - ), - 'Yoast WooCommerce SEO' => array( - 'slug' => 'woocommerce-yoast-seo', - 'identifier' => 'wpseo-woocommerce', - 'classname' => 'Yoast_WooCommerce_SEO', - ), - 'Video SEO' => array( - 'slug' => 'video-seo-for-wordpress', - 'identifier' => 'wpseo-video', - 'classname' => 'WPSEO_Video_Sitemap', - ), - 'Local SEO' => array( - 'slug' => 'local-seo-for-wordpress', - 'identifier' => 'wpseo-local', - 'classname' => 'WPSEO_Local_Core', - ), - 'Local SEO for WooCommerce' => array( - 'slug' => 'local-seo-for-woocommerce', - 'identifier' => 'wpseo-local-woocommerce', - 'classname' => 'WPSEO_Local_WooCommerce', - ), - ); - - /** - * Returns the set extensions. - * - * @return array All the extension names. - */ - public function get() { - return array_keys( $this->extensions ); - } - - /** - * Checks if the extension is valid. - * - * @param string $extension The extension to get the name for. - * - * @return bool Returns true when valid. - */ - public function is_valid( $extension ) { - $extensions = new WPSEO_Extension_Manager(); - return $extensions->is_activated( $this->extensions[ $extension ]['identifier'] ); - } - - /** - * Invalidates the extension by removing its option. - * - * @param string $extension The extension to invalidate. - */ - public function invalidate( $extension ) { - /* - * Make sure we clear the current site and multisite options. - * - * Because plugins can be site-activated or multi-site activated we need to clear - * all possible options. - * - * If we knew here that the extension in question was network activated - * we could do this a lot more easily. - */ - delete_option( $this->get_option_name( $extension ) ); - delete_site_option( $this->get_option_name( $extension ) ); - } - - /** - * Checks if the plugin has been installed. - * - * @param string $extension The name of the plugin to check. - * - * @return bool Returns true when installed. - */ - public function is_installed( $extension ) { - return class_exists( $this->extensions[ $extension ]['classname'] ); - } - - /** - * Converts the extension to the required option name. - * - * @param string $extension The extension name to convert. - * - * @return string Returns the option name. - */ - protected function get_option_name( $extension ) { - return sanitize_title_with_dashes( $this->extensions[ $extension ]['slug'] . '_', null, 'save' ) . 'license'; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-gutenberg-compatibility.php b/wp-content/plugins/wordpress-seo/admin/class-gutenberg-compatibility.php new file mode 100644 index 00000000..9a2991e8 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-gutenberg-compatibility.php @@ -0,0 +1,107 @@ +current_version = $this->detect_installed_gutenberg_version(); + } + + /** + * Determines whether or not Gutenberg is installed. + * + * @return bool Whether or not Gutenberg is installed. + */ + public function is_installed() { + return $this->current_version !== ''; + } + + /** + * Determines whether or not the currently installed version of Gutenberg is below the minimum supported version. + * + * @return bool True if the currently installed version is below the minimum supported version. False otherwise. + */ + public function is_below_minimum() { + return version_compare( $this->current_version, $this->get_minimum_supported_version(), '<' ); + } + + /** + * Gets the currently installed version. + * + * @return string The currently installed version. + */ + public function get_installed_version() { + return $this->current_version; + } + + /** + * Determines whether or not the currently installed version of Gutenberg is the latest, fully compatible version. + * + * @return bool Whether or not the currently installed version is fully compatible. + */ + public function is_fully_compatible() { + return version_compare( $this->current_version, $this->get_latest_release(), '>=' ); + } + + /** + * Gets the latest released version of Gutenberg. + * + * @return string The latest release. + */ + protected function get_latest_release() { + return self::CURRENT_RELEASE; + } + + /** + * Gets the minimum supported version of Gutenberg. + * + * @return string The minumum supported release. + */ + protected function get_minimum_supported_version() { + return self::MINIMUM_SUPPORTED; + } + + /** + * Detects the currently installed Gutenberg version. + * + * @return string The currently installed Gutenberg version. Empty if the version couldn't be detected. + */ + protected function detect_installed_gutenberg_version() { + if ( defined( 'GUTENBERG_VERSION' ) ) { + return GUTENBERG_VERSION; + } + + return ''; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-help-center-item.php b/wp-content/plugins/wordpress-seo/admin/class-help-center-item.php deleted file mode 100644 index 7816a542..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-help-center-item.php +++ /dev/null @@ -1,96 +0,0 @@ -identifier = $identifier; - $this->label = $label; - $this->dashicon = $dashicon; - $this->args = $args; - } - - /** - * Get the label. - * - * @return string - */ - public function get_label() { - return $this->label; - } - - /** - * Get the identifier. - * - * @return string - */ - public function get_identifier() { - return $this->identifier; - } - - /** - * Get the dashicon. - * - * @return string - */ - public function get_dashicon() { - return $this->dashicon; - } - - /** - * Get the content of this tab. - * - * @return mixed|string - */ - public function get_content() { - if ( ! empty( $this->args['content'] ) ) { - return $this->args['content']; - } - - if ( ! empty( $this->args['callback'] ) ) { - return call_user_func_array( $this->args['callback'], array( $this ) ); - } - - if ( ! empty( $this->args['view'] ) ) { - $view = $this->args['view']; - if ( substr( $view, - 4 ) === '.php' ) { - $view = substr( $view, 0, - 4 ); - } - - if ( ! empty( $this->args['view_arguments'] ) ) { - extract( $this->args['view_arguments'] ); - } - - include WPSEO_PATH . 'admin/views/' . $view . '.php'; - } - - return ''; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-help-center.php b/wp-content/plugins/wordpress-seo/admin/class-help-center.php deleted file mode 100644 index 79006b19..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-help-center.php +++ /dev/null @@ -1,272 +0,0 @@ -premium_support = $premium_support; - - $tabs = new WPSEO_Option_Tabs( '' ); - - if ( $option_tabs instanceof WPSEO_Option_Tabs ) { - $tabs = $option_tabs; - } - - if ( $option_tabs instanceof WPSEO_Option_Tab ) { - $tabs = new WPSEO_Option_Tabs( '', $option_tabs->get_name() ); - $tabs->add_tab( $option_tabs ); - } - - $this->tabs = $tabs; - } - - /** - * Localize data required by the help center component. - */ - public function localize_data() { - $this->add_contact_support_item(); - $this->enqueue_localized_data( $this->format_data( $this->tabs->get_tabs() ) ); - } - - /** - * Format the required data for localized script. - * - * @param WPSEO_Option_Tab[] $tabs Yoast admin pages navigational tabs. - * - * @return array Associative array containing data for help center component. - */ - protected function format_data( array $tabs ) { - $formatted_data = array( 'tabs' => array() ); - - foreach ( $tabs as $tab ) { - $formatted_data['tabs'][ $tab->get_name() ] = array( - 'label' => $tab->get_label(), - 'videoUrl' => $tab->get_video_url(), - 'id' => $tab->get_name(), - ); - } - - $active_tab = $this->tabs->get_active_tab(); - $active_tab = ( null === $active_tab ) ? $tabs[0] : $active_tab; - - $formatted_data['mountId'] = $this->identifier; - $formatted_data['initialTab'] = $active_tab->get_name(); - - $is_premium = WPSEO_Utils::is_yoast_seo_premium(); - - // Will translate to either empty string or "1" in localised script. - $formatted_data['isPremium'] = $is_premium; - $formatted_data['pluginVersion'] = WPSEO_VERSION; - - // Open HelpScout on activating this tab ID. - $formatted_data['shouldDisplayContactForm'] = $this->premium_support; - - $formatted_data['translations'] = self::get_translated_texts(); - - $formatted_data['videoDescriptions'] = array( - array( - 'title' => __( 'Need some help?', 'wordpress-seo' ), - 'description' => __( 'Go Premium and our experts will be there for you to answer any questions you might have about the setup and use of the plugin.', 'wordpress-seo' ), - 'link' => WPSEO_Shortlinker::get( 'https://yoa.st/seo-premium-vt' ), - 'linkText' => __( 'Get Yoast SEO Premium now »', 'wordpress-seo' ), - ), - array( - 'title' => __( 'Want to be a Yoast SEO Expert?', 'wordpress-seo' ), - 'description' => __( 'Follow our Yoast SEO for WordPress training and become a certified Yoast SEO Expert!', 'wordpress-seo' ), - 'link' => WPSEO_Shortlinker::get( 'https://yoa.st/wordpress-training-vt' ), - 'linkText' => __( 'Enroll in the Yoast SEO for WordPress training »', 'wordpress-seo' ), - ), - ); - - $formatted_data['contactSupportParagraphs'] = array( - array( - 'image' => array( - 'src' => esc_url( plugin_dir_url( WPSEO_FILE ) . 'images/support-team.svg' ), - 'width' => 100, - 'height' => 100, - 'alt' => '', - ), - 'content' => null, - ), - array( - 'image' => null, - 'content' => __( 'If you have a problem that you can\'t solve with our video tutorials or knowledge base, you can send a message to our support team. They can be reached 24/7.', 'wordpress-seo' ), - ), - array( - 'image' => null, - 'content' => __( 'Support requests you create here are sent directly into our support system, which is secured with 256 bit SSL, so communication is 100% secure.', 'wordpress-seo' ), - ), - ); - - $formatted_data['extraTabs'] = $this->get_extra_tabs(); - - return $formatted_data; - } - - /** - * Get additional tabs for the help center component. - * - * @return array Additional help center tabs. - */ - protected function get_extra_tabs() { - $help_center_items = apply_filters( 'wpseo_help_center_items', $this->help_center_items ); - - return array_map( array( $this, 'format_helpcenter_tab' ), $help_center_items ); - } - - /** - * Convert WPSEO_Help_Center_Item into help center format. - * - * @param WPSEO_Help_Center_Item $item The item to convert. - * - * @return array Formatted item. - */ - protected function format_helpcenter_tab( WPSEO_Help_Center_Item $item ) { - return array( - 'identifier' => $item->get_identifier(), - 'label' => $item->get_label(), - 'content' => $item->get_content(), - ); - } - - /** - * Enqueue localized script for help center component. - * - * @param array $data Data to localize. - */ - protected function enqueue_localized_data( $data ) { - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'help-center', 'wpseoHelpCenterData', $data ); - } - - /** - * Outputs the help center div. - */ - public function mount() { - echo '
' . esc_html__( 'Loading help center.', 'wordpress-seo' ) . '
'; - } - - /** - * Add the contact support help center item to the help center. - */ - private function add_contact_support_item() { - /* translators: %s: expands to 'Yoast SEO Premium'. */ - $popup_title = sprintf( __( 'Email support is a %s feature', 'wordpress-seo' ), 'Yoast SEO Premium' ); - $popup_content = '

' . __( 'Go Premium and our experts will be there for you to answer any questions you might have about the set-up and use of the plug-in!', 'wordpress-seo' ) . '

'; - /* translators: %1$s: expands to 'Yoast SEO Premium'. */ - $popup_content .= '

' . sprintf( __( 'Other benefits of %1$s for you:', 'wordpress-seo' ), 'Yoast SEO Premium' ) . '

'; - $popup_content .= ''; - - $premium_popup = new WPSEO_Premium_Popup( 'contact-support', 'h2', $popup_title, $popup_content, WPSEO_Shortlinker::get( 'https://yoa.st/contact-support' ) ); - $contact_support_help_center_item = new WPSEO_Help_Center_Item( - 'contact-support', - __( 'Get support', 'wordpress-seo' ), - array( 'content' => $premium_popup->get_premium_message( false ) ), - 'dashicons-email-alt' - ); - - $this->help_center_items[] = $contact_support_help_center_item; - } - - /** - * Pass text variables to js for the help center JS module. - * - * %s is replaced with %s and replaced again in the javascript with the actual variable. - * - * @return array Translated text strings for the help center. - */ - public static function get_translated_texts() { - // Esc_html is not needed because React already handles HTML in the (translations of) these strings. - return array( - 'locale' => WPSEO_Utils::get_user_locale(), - 'videoTutorial' => __( 'Video tutorial', 'wordpress-seo' ), - 'knowledgeBase' => __( 'Knowledge base', 'wordpress-seo' ), - 'getSupport' => __( 'Get support', 'wordpress-seo' ), - 'algoliaSearcher.loadingPlaceholder' => __( 'Loading...', 'wordpress-seo' ), - 'algoliaSearcher.errorMessage' => __( 'Something went wrong. Please try again later.', 'wordpress-seo' ), - 'searchBar.headingText' => __( 'Search the Yoast Knowledge Base for answers to your questions:', 'wordpress-seo' ), - 'searchBar.placeholderText' => __( 'Type here to search...', 'wordpress-seo' ), - 'searchBar.buttonText' => __( 'Search', 'wordpress-seo' ), - 'searchResultDetail.openButton' => __( 'View in KB', 'wordpress-seo' ), - 'searchResultDetail.openButtonLabel' => __( 'Open the knowledge base article in a new window or read it in the iframe below', 'wordpress-seo' ), - 'searchResultDetail.backButton' => __( 'Go back', 'wordpress-seo' ), - 'searchResultDetail.backButtonLabel' => __( 'Go back to the search results', 'wordpress-seo' ), - 'searchResultDetail.iframeTitle' => __( 'Knowledge base article', 'wordpress-seo' ), - 'searchResultDetail.searchResult' => __( 'Search result', 'wordpress-seo' ), - 'searchResult.noResultsText' => __( 'No results found.', 'wordpress-seo' ), - 'searchResult.foundResultsText' => sprintf( - /* translators: %s expands to the number of results found . */ - __( 'Number of results found: %s', 'wordpress-seo' ), - '{ resultsCount }' - ), - 'searchResult.searchResultsHeading' => __( 'Search results', 'wordpress-seo' ), - 'a11yNotice.opensInNewTab' => __( '(Opens in a new browser tab)', 'wordpress-seo' ), - 'contactSupport.button' => __( 'New support request', 'wordpress-seo' ), - 'helpCenter.buttonText' => __( 'Need help?', 'wordpress-seo' ), - ); - } - - /** - * Outputs the help center. - * - * @deprecated 5.6 - */ - public function output_help_center() { - _deprecated_function( 'WPSEO_Help_Center::output_help_center', 'WPSEO 5.6.0', 'WPSEO_Help_Center::mount()' ); - $this->mount(); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-helpscout.php b/wp-content/plugins/wordpress-seo/admin/class-helpscout.php new file mode 100644 index 00000000..aef7057e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-helpscout.php @@ -0,0 +1,265 @@ +beacon_id = $beacon_id; + $this->pages = $pages; + $this->products = $products; + $this->ask_consent = $ask_consent; + } + + /** + * {@inheritDoc} + */ + public function register_hooks() { + if ( ! $this->is_beacon_page() ) { + return; + } + + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_help_scout_script' ] ); + add_action( 'admin_footer', [ $this, 'output_beacon_js' ] ); + } + + /** + * Enqueues the HelpScout script. + */ + public function enqueue_help_scout_script() { + $asset_manager = new WPSEO_Admin_Asset_Manager(); + $asset_manager->enqueue_script( 'help-scout-beacon' ); + } + + /** + * Outputs a small piece of javascript for the beacon. + */ + public function output_beacon_js() { + printf( + '', + ( $this->ask_consent ) ? 'wpseoHelpScoutBeaconConsent' : 'wpseoHelpScoutBeacon', + esc_html( $this->beacon_id ), + WPSEO_Utils::format_json_encode( $this->get_session_data() ) + ); + } + + /** + * Checks if the current page is a page containing the beacon. + * + * @return bool + */ + private function is_beacon_page() { + return in_array( $this->get_current_page(), $this->pages, true ); + } + + /** + * Retrieves the value of the current page. + * + * @return string The current page. + */ + private function get_current_page() { + $page = filter_input( INPUT_GET, 'page' ); + if ( isset( $page ) && $page !== false ) { + return $page; + } + + return ''; + } + + /** + * Retrieves the identifying data. + * + * @return string The data to pass as identifying data. + */ + protected function get_session_data() { + /** @noinspection PhpUnusedLocalVariableInspection */ + // Do not make these strings translatable! They are for our support agents, the user won't see them! + $current_user = wp_get_current_user(); + + $data = [ + 'name' => trim( $current_user->user_firstname . ' ' . $current_user->user_lastname ), + 'email' => $current_user->user_email, + 'WordPress Version' => $this->get_wordpress_version(), + 'Server' => $this->get_server_info(), + 'Theme' => $this->get_theme_info(), + 'Plugins' => $this->get_active_plugins(), + ]; + + if ( ! empty( $this->products ) ) { + $addon_manager = new WPSEO_Addon_Manager(); + foreach ( $this->products as $product ) { + $subscription = $addon_manager->get_subscription( $product ); + + if ( ! $subscription ) { + continue; + } + + $data[ $subscription->product->name ] = $this->get_product_info( $subscription ); + } + } + + return WPSEO_Utils::format_json_encode( $data ); + } + + /** + * Returns basic info about the server software. + * + * @return string + */ + private function get_server_info() { + $server_tracking_data = new WPSEO_Tracking_Server_Data(); + $server_data = $server_tracking_data->get(); + $server_data = $server_data['server']; + + $fields_to_use = [ + 'IP' => 'ip', + 'Hostname' => 'Hostname', + 'OS' => 'os', + 'PHP' => 'PhpVersion', + 'CURL' => 'CurlVersion', + ]; + + $server_data['CurlVersion'] = $server_data['CurlVersion']['version'] . '(SSL Support' . $server_data['CurlVersion']['sslSupport'] . ')'; + + $server_info = ''; + + foreach ( $fields_to_use as $label => $field_to_use ) { + if ( isset( $server_data[ $field_to_use ] ) ) { + $server_info .= sprintf( '', esc_html( $label ), esc_html( $server_data[ $field_to_use ] ) ); + } + } + + $server_info .= '
%1$s%2$s
'; + + 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 = ''; + $product_info .= ''; + $product_info .= ''; + $product_info .= '
Version' . $plugin->product->version . '
Expiration date' . $plugin->expiry_date . '
'; + + 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( + '%2$s 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( '
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 .= ' '; + } + + $active_plugins .= sprintf( + '%2$s v%3$s', + esc_attr( $plugin_data['PluginURI'] ), + esc_html( $plugin_data['Name'] ), + esc_html( $plugin_data['Version'] ) + ); + } + + return $active_plugins; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-license-page-manager.php b/wp-content/plugins/wordpress-seo/admin/class-license-page-manager.php deleted file mode 100644 index 05f2cabf..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-license-page-manager.php +++ /dev/null @@ -1,211 +0,0 @@ -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, - 'My Yoast' - ), - $notification_options - ); - - return $notification; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-meta-columns.php b/wp-content/plugins/wordpress-seo/admin/class-meta-columns.php index dc37a32e..dbfd3106 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-meta-columns.php +++ b/wp-content/plugins/wordpress-seo/admin/class-meta-columns.php @@ -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'] = '' . __( 'SEO score', 'wordpress-seo' ) . ''; @@ -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 '', esc_html__( 'Meta description not set.', 'wordpress-seo' ), ''; @@ -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 '', - esc_html__( 'Focus keyword not set.', 'wordpress-seo' ), + esc_html__( 'Focus keyphrase not set.', 'wordpress-seo' ), ''; 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 ''; echo ''; + // 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 '; } + /** + * 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 '' . $title . ''; + return '' . esc_html( $title ) . ''; } /** @@ -745,7 +742,7 @@ class WPSEO_Meta_Columns { } $screen = get_current_screen(); - if ( null === $screen ) { + if ( $screen === null ) { return false; } diff --git a/wp-content/plugins/wordpress-seo/admin/class-meta-storage.php b/wp-content/plugins/wordpress-seo/admin/class-meta-storage.php deleted file mode 100644 index a9bc5f27..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-meta-storage.php +++ /dev/null @@ -1,111 +0,0 @@ -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 ) ); - } - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-meta-table-accessible.php b/wp-content/plugins/wordpress-seo/admin/class-meta-table-accessible.php deleted file mode 100644 index 67a8f8c5..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-meta-table-accessible.php +++ /dev/null @@ -1,103 +0,0 @@ -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(); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-my-yoast-proxy.php b/wp-content/plugins/wordpress-seo/admin/class-my-yoast-proxy.php new file mode 100644 index 00000000..5b7366a7 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-my-yoast-proxy.php @@ -0,0 +1,209 @@ +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: + * + * $array = array( + * 'content_type' => 'the content type' + * 'url' => 'the url, possibly with the plugin version' + * ) + * + * + * @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 ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-option-tab.php b/wp-content/plugins/wordpress-seo/admin/class-option-tab.php index 332ee344..cc842325 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-option-tab.php +++ b/wp-content/plugins/wordpress-seo/admin/class-option-tab.php @@ -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. * diff --git a/wp-content/plugins/wordpress-seo/admin/class-option-tabs-formatter.php b/wp-content/plugins/wordpress-seo/admin/class-option-tabs-formatter.php index b2e38833..3425758b 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-option-tabs-formatter.php +++ b/wp-content/plugins/wordpress-seo/admin/class-option-tabs-formatter.php @@ -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 ''; - $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( '
', 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 '
'; diff --git a/wp-content/plugins/wordpress-seo/admin/class-option-tabs.php b/wp-content/plugins/wordpress-seo/admin/class-option-tabs.php index 706309b1..523943ca 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-option-tabs.php +++ b/wp-content/plugins/wordpress-seo/admin/class-option-tabs.php @@ -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(); diff --git a/wp-content/plugins/wordpress-seo/admin/class-paper-presenter.php b/wp-content/plugins/wordpress-seo/admin/class-paper-presenter.php new file mode 100644 index 00000000..99550e4a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-paper-presenter.php @@ -0,0 +1,141 @@ + 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', + ]; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-plugin-availability.php b/wp-content/plugins/wordpress-seo/admin/class-plugin-availability.php index bc225e6b..9e70dfe7 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-plugin-availability.php +++ b/wp-content/plugins/wordpress-seo/admin/class-plugin-availability.php @@ -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' ] ); } /** diff --git a/wp-content/plugins/wordpress-seo/admin/class-plugin-compatibility.php b/wp-content/plugins/wordpress-seo/admin/class-plugin-compatibility.php deleted file mode 100644 index 3fe3ca42..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-plugin-compatibility.php +++ /dev/null @@ -1,109 +0,0 @@ -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 ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-plugin-conflict.php b/wp-content/plugins/wordpress-seo/admin/class-plugin-conflict.php index 7a90b8e1..571a6d02 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-plugin-conflict.php +++ b/wp-content/plugins/wordpress-seo/admin/class-plugin-conflict.php @@ -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' ) . '

' . '' /* 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' ) . ''; } @@ -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 ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-premium-popup.php b/wp-content/plugins/wordpress-seo/admin/class-premium-popup.php index 6ad0ad5a..372f1179 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-premium-popup.php +++ b/wp-content/plugins/wordpress-seo/admin/class-premium-popup.php @@ -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 = '' . esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ) . ''; + $caret_icon = ''; + $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 = << - Yoast SEO + Yoast SEO <{$this->heading_level} id="wpseo-contact-support-popup-title" class="wpseo-premium-popup-title">{$this->title}heading_level}> {$this->content} - {$cta_text}
+ + {$cta_text} {$new_tab_message} {$caret_icon} +
{$micro_copy} EO_POPUP; diff --git a/wp-content/plugins/wordpress-seo/admin/class-premium-upsell-admin-block.php b/wp-content/plugins/wordpress-seo/admin/class-premium-upsell-admin-block.php index 76e0badd..e46088f0 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-premium-upsell-admin-block.php +++ b/wp-content/plugins/wordpress-seo/admin/class-premium-upsell-admin-block.php @@ -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( - '' . esc_html__( 'Multiple keywords', 'wordpress-seo' ) . ': ' . esc_html__( 'Increase your SEO reach', 'wordpress-seo' ), + $arguments = [ + '' . esc_html__( 'Multiple keyphrases', 'wordpress-seo' ) . ': ' . esc_html__( 'Increase your SEO reach', 'wordpress-seo' ), '' . esc_html__( 'No more dead links', 'wordpress-seo' ) . ': ' . esc_html__( 'Easy redirect manager', 'wordpress-seo' ), '' . esc_html__( 'Superfast internal linking suggestions', 'wordpress-seo' ) . '', '' . esc_html__( 'Social media preview', 'wordpress-seo' ) . ': ' . esc_html__( 'Facebook & Twitter', 'wordpress-seo' ), - '' . esc_html__( '24/7 support', 'wordpress-seo' ) . '', + '' . esc_html__( '24/7 email support', 'wordpress-seo' ) . '', '' . esc_html__( 'No ads!', 'wordpress-seo' ) . '', - ); + ]; - $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 .= '' . esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ) . '' . + ''; - echo '
'; - printf( - 'X', - esc_url( add_query_arg( array( $this->get_query_variable_name() => 1 ) ) ), - esc_attr( $class . '--close' ), - esc_attr( $dismiss_msg ) + $upgrade_button = sprintf( + '%3$s', + esc_attr( 'wpseo-' . $this->identifier . '-popup-button' ), + esc_url( $url ), + $button_text ); + echo '
'; + echo '
'; - echo '

' . esc_html__( 'Go premium!', 'wordpress-seo' ) . '

'; + echo '

' . + sprintf( + /* translators: %s expands to Yoast SEO Premium */ + esc_html__( 'Upgrade to %s', 'wordpress-seo' ), + 'Yoast SEO Premium' + ) . + '

'; + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Correctly escaped in $this->get_argument_html() method. echo '
    ' . $arguments_html . '
'; - echo '

' . esc_html( $upgrade_msg ) . '
'; + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Correctly escaped in $upgrade_button and $button_text above. + echo '

' . $upgrade_button . '

'; echo '
'; echo '
'; @@ -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. * diff --git a/wp-content/plugins/wordpress-seo/admin/class-primary-term-admin.php b/wp-content/plugins/wordpress-seo/admin/class-primary-term-admin.php index eefb5a16..99b4798c 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-primary-term-admin.php +++ b/wp-content/plugins/wordpress-seo/admin/class-primary-term-admin.php @@ -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( + '', + 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. * diff --git a/wp-content/plugins/wordpress-seo/admin/class-product-upsell-notice.php b/wp-content/plugins/wordpress-seo/admin/class-product-upsell-notice.php index 357c94c3..6938ae6f 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-product-upsell-notice.php +++ b/wp-content/plugins/wordpress-seo/admin/class-product-upsell-notice.php @@ -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 */ - __( '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' ), "", '' ); @@ -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' ), '', '' @@ -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' ), - '', - '' - ); + $message .= '' . __( 'Please don\'t show me this notification anymore', 'wordpress-seo' ) . ''; $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 ); diff --git a/wp-content/plugins/wordpress-seo/admin/class-recalculate-scores.php b/wp-content/plugins/wordpress-seo/admin/class-recalculate-scores.php deleted file mode 100644 index 926850af..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-recalculate-scores.php +++ /dev/null @@ -1,54 +0,0 @@ -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 containing the number of posts recalculated. 2: expands to a containing the total number of posts. */ - esc_html__( '%1$s of %2$s done.', 'wordpress-seo' ), - '0', - '0' - ); - - ?> - - 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; diff --git a/wp-content/plugins/wordpress-seo/admin/class-schema-person-upgrade-notification.php b/wp-content/plugins/wordpress-seo/admin/class-schema-person-upgrade-notification.php new file mode 100644 index 00000000..7f42cf45 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-schema-person-upgrade-notification.php @@ -0,0 +1,76 @@ +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' ), + '', + '' + ); + + $notification = new Yoast_Notification( + $message, + [ + 'type' => Yoast_Notification::WARNING, + 'id' => 'wpseo-schema-person-upgrade', + 'capabilities' => 'wpseo_manage_options', + 'priority' => 0.8, + ] + ); + + return $notification; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-social-admin.php b/wp-content/plugins/wordpress-seo/admin/class-social-admin.php deleted file mode 100644 index a2545a05..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-social-admin.php +++ /dev/null @@ -1,243 +0,0 @@ - __( '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 ), - '' . __( 'Facebook / Open Graph metadata', 'wordpress-seo' ) . '', - 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 ), - '' . __( 'Twitter metadata', 'wordpress-seo' ) . '', - array( - 'link_aria_label' => __( 'Twitter metadata', 'wordpress-seo' ), - 'link_class' => 'yoast-tooltip yoast-tooltip-se', - 'single' => $single, - ) - ); - } - - return new WPSEO_Metabox_Tab_Section( - 'social', - '' . __( 'Social', 'wordpress-seo' ) . '', - $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( - '
-

%1$s

-

%3$s

-
', - 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 ), - 'Yoast SEO Premium' - ), - 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 */ diff --git a/wp-content/plugins/wordpress-seo/admin/class-suggested-plugins.php b/wp-content/plugins/wordpress-seo/admin/class-suggested-plugins.php index f4d0ea34..ebabc63f 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-suggested-plugins.php +++ b/wp-content/plugins/wordpress-seo/admin/class-suggested-plugins.php @@ -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, + '', $install_link, - $this->create_more_information_link( $suggested_plugin['url'], $suggested_plugin['title'] ) + '', + $this->create_more_information_link( $suggested_plugin['url'], $suggested_plugin['title'] ), + '' ); } /** * 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( - '%s', + '', $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( '%s', $activation_url, $suggested_plugin['title'] ) + '', + $suggested_plugin['title'], + '', + '', + '' ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-alerts.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-alerts.php deleted file mode 100644 index 1f588fd0..00000000 --- a/wp-content/plugins/wordpress-seo/admin/class-yoast-alerts.php +++ /dev/null @@ -1,260 +0,0 @@ -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 ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-columns.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-columns.php index 20715d33..5e9d040a 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-yoast-columns.php +++ b/wp-content/plugins/wordpress-seo/admin/class-yoast-columns.php @@ -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' ), + '', + '' + ); + } + + 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' ), + '', + '', + '', + '' + ); + } + $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 */ - '

' . __( '%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' ) . '

', - 'Yoast SEO', - '', - '', - '', - '', - '' - ), + 'content' => '

' . $help_tab_content . '

', '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' ); + } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-dashboard-widget.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-dashboard-widget.php index 36b3ea21..89c8007b 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-yoast-dashboard-widget.php +++ b/wp-content/plugins/wordpress-seo/admin/class-yoast-dashboard-widget.php @@ -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 '
'; } - /** - * 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 enqueue_dashboard_assets 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, + ]; } /** diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-form.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-form.php index 3ada034e..f5ba1518 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-yoast-form.php +++ b/wp-content/plugins/wordpress-seo/admin/class-yoast-form.php @@ -5,6 +5,8 @@ * @package WPSEO\Admin */ +use Yoast\WP\SEO\Presenters\Admin\Light_Switch_Presenter; + /** * Admin form class. * @@ -13,25 +15,31 @@ class Yoast_Form { /** - * @var object Instance of this class + * Instance of this class + * + * @var Yoast_Form * @since 2.0 */ public static $instance; /** + * The short name of the option to use for the current page. + * * @var string * @since 2.0 */ public $option_name; /** - * @var array - * @since 2.0 + * Option instance. + * + * @since 8.4 + * @var WPSEO_Option|null */ - public $options; + protected $option_instance = null; /** - * Get the singleton instance of this class + * Get the singleton instance of this class. * * @since 2.0 * @@ -46,7 +54,7 @@ class Yoast_Form { } /** - * Generates the header for admin pages + * Generates the header for admin pages. * * @since 2.0 * @@ -63,8 +71,8 @@ class Yoast_Form {
'; - settings_fields( $option_long_name ); + + $network_admin = new Yoast_Network_Admin(); + if ( $network_admin->meets_requirements() ) { + $action_url = network_admin_url( 'settings.php' ); + $hidden_fields_cb = [ $network_admin, 'settings_fields' ]; + } + else { + $action_url = admin_url( 'options.php' ); + $hidden_fields_cb = 'settings_fields'; + } + + echo '
'; + call_user_func( $hidden_fields_cb, $option_long_name ); } $this->set_option( $option ); } /** - * Set the option used in output for form elements + * Set the option used in output for form elements. * * @since 2.0 * @@ -91,42 +115,15 @@ class Yoast_Form { */ public function set_option( $option_name ) { $this->option_name = $option_name; - $this->options = $this->get_option(); - } - /** - * Sets a value in the options. - * - * @since 5.4 - * - * @param string $key The key of the option to set. - * @param mixed $value The value to set the option to. - * @param bool $overwrite Whether to overwrite existing options. Default is false. - */ - public function set_options_value( $key, $value, $overwrite = false ) { - if ( $overwrite || ! array_key_exists( $key, $this->options ) ) { - $this->options[ $key ] = $value; + $this->option_instance = WPSEO_Options::get_option_instance( $option_name ); + if ( ! $this->option_instance ) { + $this->option_instance = null; } } /** - * Retrieve options based on whether we're on multisite or not. - * - * @since 1.2.4 - * @since 2.0 Moved to this class. - * - * @return array - */ - private function get_option() { - if ( is_network_admin() ) { - return get_site_option( $this->option_name ); - } - - return get_option( $this->option_name ); - } - - /** - * Generates the footer for admin pages + * Generates the footer for admin pages. * * @since 2.0 * @@ -135,19 +132,32 @@ class Yoast_Form { */ public function admin_footer( $submit = true, $show_sidebar = true ) { if ( $submit ) { + $settings_changed_listener = new WPSEO_Admin_Settings_Changed_Listener(); + echo '
'; + + echo '
'; submit_button( __( 'Save changes', 'wordpress-seo' ) ); + $settings_changed_listener->show_success_message(); + echo '
'; + + echo ''; + + echo '
'; echo '
'; } /** - * Apply general admin_footer hooks + * Apply general admin_footer hooks. */ - do_action( 'wpseo_admin_footer' ); + do_action( 'wpseo_admin_footer', $this ); /** - * Run possibly set actions to add for example an i18n box + * Run possibly set actions to add for example an i18n box. */ do_action( 'wpseo_admin_promo_footer' ); @@ -160,22 +170,7 @@ class Yoast_Form { echo '
'; - - if ( ( defined( 'WP_DEBUG' ) && WP_DEBUG === true ) ) { - $xdebug = ( extension_loaded( 'xdebug' ) ? true : false ); - echo ' -
- -

' . esc_html__( 'Debug Information', 'wordpress-seo' ) . '

-
-

' . esc_html__( 'Current option:', 'wordpress-seo' ) . ' ' . esc_html( $this->option_name ) . '

- ' . ( ( $xdebug ) ? '' : '
' );
-			var_dump( $this->get_option() );
-			echo '
-					' . ( ( $xdebug ) ? '' : '
' ) . ' -
-
'; - } + do_action( 'wpseo_admin_below_content', $this ); echo '
'; @@ -187,32 +182,17 @@ class Yoast_Form { * @since 2.0 */ public function admin_sidebar() { - // No banners in Premium. - if ( class_exists( 'WPSEO_Product_Premium' ) ) { - $product_premium = new WPSEO_Product_Premium(); - $extension_manager = new WPSEO_Extension_Manager(); - - if ( $extension_manager->is_activated( $product_premium->get_slug() ) ) { - return; - } + $addon_manager = new WPSEO_Addon_Manager(); + if ( YoastSEO()->helpers->product->is_premium() && $addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG ) ) { + return; } - $sidebar_renderer = new WPSEO_Admin_Banner_Sidebar_Renderer( new WPSEO_Admin_Banner_Spot_Renderer() ); - - $banner_renderer = new WPSEO_Admin_Banner_Renderer(); - $banner_renderer->set_base_path( plugins_url( 'images/banner/', WPSEO_FILE ) ); - - /* translators: %1$s expands to "Yoast". */ - $sidebar = new WPSEO_Admin_Banner_Sidebar( sprintf( __( '%1s recommendations for you', 'wordpress-seo' ), 'Yoast' ), $banner_renderer ); - $sidebar->initialize( new WPSEO_Features() ); - - echo $sidebar_renderer->render( $sidebar ); - + require_once 'views/sidebar.php'; } /** - * Output a label element + * Output a label element. * * @since 2.0 * @@ -220,13 +200,20 @@ class Yoast_Form { * @param array $attr HTML attributes set. */ public function label( $text, $attr ) { - $attr = wp_parse_args( $attr, array( - 'class' => 'checkbox', - 'close' => true, - 'for' => '', - ) - ); - echo "'; + // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: All output is properly escaped or hardcoded in the presenter. + echo $output; } /** @@ -349,28 +368,112 @@ class Yoast_Form { * * @param string $var The variable within the option to create the text input field for. * @param string $label The label to show for the variable. - * @param array|string $attr Extra class to add to the input field. + * @param array|string $attr Extra attributes to add to the input field. Can be class, disabled, autocomplete. */ - public function textinput( $var, $label, $attr = array() ) { + public function textinput( $var, $label, $attr = [] ) { + $type = 'text'; if ( ! is_array( $attr ) ) { - $attr = array( - 'class' => $attr, - ); + $attr = [ + 'class' => $attr, + 'disabled' => false, + ]; } - $attr = wp_parse_args( $attr, array( + + $defaults = [ 'placeholder' => '', 'class' => '', - ) ); - $val = ( isset( $this->options[ $var ] ) ) ? $this->options[ $var ] : ''; + ]; + $attr = wp_parse_args( $attr, $defaults ); + $val = $this->get_field_value( $var, '' ); + if ( isset( $attr['type'] ) && $attr['type'] === 'url' ) { + $val = urldecode( $val ); + $type = 'url'; + } + $attributes = isset( $attr['autocomplete'] ) ? ' autocomplete="' . esc_attr( $attr['autocomplete'] ) . '"' : ''; $this->label( - $label . ':', - array( + $label, + [ 'for' => $var, 'class' => 'textinput', - ) + ] ); - echo '', '
'; + + $has_input_error = Yoast_Input_Validation::yoast_form_control_has_error( $var ); + $aria_attributes = Yoast_Input_Validation::get_the_aria_invalid_attribute( $var ); + + Yoast_Input_Validation::set_error_descriptions(); + $aria_attributes .= Yoast_Input_Validation::get_the_aria_describedby_attribute( $var ); + + $disabled_attribute = $this->get_disabled_attribute( $var, $attr ); + + // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped. + echo '', '
'; + echo Yoast_Input_Validation::get_the_error_description( $var ); + } + + /** + * Creates a text input field with with the ability to add content after the label. + * + * @param string $var The variable within the option to create the text input field for. + * @param string $label The label to show for the variable. + * @param array $attr Extra attributes to add to the input field. + * + * @return void + */ + public function textinput_extra_content( $var, $label, $attr = [] ) { + $type = 'text'; + + $defaults = [ + 'class' => 'yoast-field-group__inputfield', + 'disabled' => false, + ]; + + $attr = \wp_parse_args( $attr, $defaults ); + $val = $this->get_field_value( $var, '' ); + + if ( isset( $attr['type'] ) && $attr['type'] === 'url' ) { + $val = urldecode( $val ); + $type = 'url'; + } + + echo '
'; + $this->label( + $label, + [ + 'for' => $var, + 'class' => $attr['class'] . '--label', + ] + ); + + if ( isset( $attr['extra_content'] ) ) { + // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: may contain HTML that should not be escaped. + echo $attr['extra_content']; + } + echo '
'; + + $has_input_error = Yoast_Input_Validation::yoast_form_control_has_error( $var ); + $aria_attributes = Yoast_Input_Validation::get_the_aria_invalid_attribute( $var ); + + Yoast_Input_Validation::set_error_descriptions(); + $aria_attributes .= Yoast_Input_Validation::get_the_aria_describedby_attribute( $var ); + + // phpcs:disable WordPress.Security.EscapeOutput -- Reason: output is properly escaped or hardcoded. + printf( + '', + $type, + \esc_attr( $this->option_name ) . '[' . \esc_attr( $var ) . ']', + \esc_attr( $var ), + \esc_attr( $attr['class'] ), + isset( $attr['placeholder'] ) ? ' placeholder="' . \esc_attr( $attr['placeholder'] ) . '"' : '', + isset( $attr['autocomplete'] ) ? ' autocomplete="' . \esc_attr( $attr['autocomplete'] ) . '"' : '', + $aria_attributes, + \esc_attr( $val ), + $this->get_disabled_attribute( $var, $attr ) + ); + // phpcs:enable + // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: output is properly escaped. + echo Yoast_Input_Validation::get_the_error_description( $var ); } /** @@ -378,31 +481,38 @@ class Yoast_Form { * * @since 2.0 * - * @param string $var The variable within the option to create the textarea for. - * @param string $label The label to show for the variable. - * @param array $attr The CSS class to assign to the textarea. + * @param string $var The variable within the option to create the textarea for. + * @param string $label The label to show for the variable. + * @param string|array $attr The CSS class or an array of attributes to assign to the textarea. */ - public function textarea( $var, $label, $attr = array() ) { + public function textarea( $var, $label, $attr = [] ) { if ( ! is_array( $attr ) ) { - $attr = array( + $attr = [ 'class' => $attr, - ); + ]; } - $attr = wp_parse_args( $attr, array( - 'cols' => '', - 'rows' => '', - 'class' => '', - ) ); - $val = ( isset( $this->options[ $var ] ) ) ? $this->options[ $var ] : ''; + + $defaults = [ + 'cols' => '', + 'rows' => '', + 'class' => '', + 'disabled' => false, + ]; + $attr = wp_parse_args( $attr, $defaults ); + $val = $this->get_field_value( $var, '' ); $this->label( - $label . ':', - array( + $label, + [ 'for' => $var, 'class' => 'textinput', - ) + ] ); - echo '
'; + + $disabled_attribute = $this->get_disabled_attribute( $var, $attr ); + + // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped. + echo '
'; } /** @@ -414,12 +524,12 @@ class Yoast_Form { * @param string $id The ID of the element. */ public function hidden( $var, $id = '' ) { - $val = ( isset( $this->options[ $var ] ) ) ? $this->options[ $var ] : ''; + $val = $this->get_field_value( $var, '' ); if ( is_bool( $val ) ) { $val = ( $val === true ) ? 'true' : 'false'; } - if ( '' === $id ) { + if ( $id === '' ) { $id = 'hidden_' . $var; } @@ -431,31 +541,60 @@ class Yoast_Form { * * @since 2.0 * - * @param string $field_name The variable within the option to create the select for. + * @param string $var The variable within the option to create the select for. * @param string $label The label to show for the variable. * @param array $select_options The select options to choose from. + * @param string $styled The select style. Use 'styled' to get a styled select. Default 'unstyled'. + * @param bool $show_label Whether or not to show the label, if not, it will be applied as an aria-label. + * @param array $attr Extra attributes to add to the select. + * @param string $help Optional. Inline Help HTML that will be printed after the label. Default is empty. */ - public function select( $field_name, $label, array $select_options ) { - + public function select( $var, $label, array $select_options, $styled = 'unstyled', $show_label = true, $attr = [], $help = '' ) { if ( empty( $select_options ) ) { return; } - $this->label( - $label . ':', - array( - 'for' => $field_name, - 'class' => 'select', - ) - ); + $defaults = [ + 'disabled' => false, + ]; + $attr = wp_parse_args( $attr, $defaults ); - $select_name = esc_attr( $this->option_name ) . '[' . esc_attr( $field_name ) . ']'; - $active_option = ( isset( $this->options[ $field_name ] ) ) ? $this->options[ $field_name ] : ''; + if ( $show_label ) { + $this->label( + $label, + [ + 'for' => $var, + 'class' => 'select', + ] + ); + echo $help; // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: The help contains HTML. + } - $select = new Yoast_Input_Select( $field_name, $select_name, $select_options, $active_option ); + $select_name = esc_attr( $this->option_name ) . '[' . esc_attr( $var ) . ']'; + $active_option = $this->get_field_value( $var, '' ); + $wrapper_start_tag = ''; + $wrapper_end_tag = ''; + + $select = new Yoast_Input_Select( $var, $select_name, $select_options, $active_option ); $select->add_attribute( 'class', 'select' ); - $select->output_html(); + if ( $this->is_control_disabled( $var ) + || ( isset( $attr['disabled'] ) && $attr['disabled'] ) ) { + $select->add_attribute( 'disabled', 'disabled' ); + } + + if ( ! $show_label ) { + $select->add_attribute( 'aria-label', $label ); + } + + if ( $styled === 'styled' ) { + $wrapper_start_tag = ''; + $wrapper_end_tag = ''; + } + + echo $wrapper_start_tag; + $select->output_html(); + echo $wrapper_end_tag; echo '
'; } @@ -466,25 +605,35 @@ class Yoast_Form { * * @param string $var The variable within the option to create the file upload field for. * @param string $label The label to show for the variable. + * @param array $attr Extra attributes to add to the file upload input. */ - public function file_upload( $var, $label ) { - $val = ''; - if ( isset( $this->options[ $var ] ) && is_array( $this->options[ $var ] ) ) { - $val = $this->options[ $var ]['url']; + public function file_upload( $var, $label, $attr = [] ) { + $val = $this->get_field_value( $var, '' ); + if ( is_array( $val ) ) { + $val = $val['url']; } + $defaults = [ + 'disabled' => false, + ]; + $attr = wp_parse_args( $attr, $defaults ); + $var_esc = esc_attr( $var ); $this->label( - $label . ':', - array( + $label, + [ 'for' => $var, 'class' => 'select', - ) + ] ); - echo ''; + + $disabled_attribute = $this->get_disabled_attribute( $var, $attr ); + + // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped. + echo ''; // Need to save separate array items in hidden inputs, because empty file inputs type will be deleted by settings API. - if ( ! empty( $this->options[ $var ] ) ) { + if ( ! empty( $val ) ) { $this->hidden( 'file', $this->option_name . '_file' ); $this->hidden( 'url', $this->option_name . '_url' ); $this->hidden( 'type', $this->option_name . '_type' ); @@ -493,30 +642,69 @@ class Yoast_Form { } /** - * Media input + * Media input. * * @since 2.0 * * @param string $var Option name. * @param string $label Label message. + * @param array $attr Extra attributes to add to the media input and buttons. */ - public function media_input( $var, $label ) { - $val = ''; - if ( isset( $this->options[ $var ] ) ) { - $val = $this->options[ $var ]; - } + public function media_input( $var, $label, $attr = [] ) { + $val = $this->get_field_value( $var, '' ); + $id_value = $this->get_field_value( $var . '_id', '' ); $var_esc = esc_attr( $var ); + $defaults = [ + 'disabled' => false, + ]; + $attr = wp_parse_args( $attr, $defaults ); + $this->label( - $label . ':', - array( + $label, + [ 'for' => 'wpseo_' . $var, 'class' => 'select', - ) + ] ); - echo ''; - echo ''; + + $id_field_id = 'wpseo_' . $var_esc . '_id'; + + $disabled_attribute = $this->get_disabled_attribute( $var, $attr ); + + echo ''; + echo ' '; + echo ' '; + echo ''; + echo ''; + echo ''; echo '
'; } @@ -529,44 +717,62 @@ class Yoast_Form { * @param array $values The radio options to choose from. * @param string $legend Optional. The legend to show for the field set, if any. * @param array $legend_attr Optional. The attributes for the legend, if any. + * @param array $attr Extra attributes to add to the radio button. */ - public function radio( $var, $values, $legend = '', $legend_attr = array() ) { - if ( ! is_array( $values ) || $values === array() ) { + public function radio( $var, $values, $legend = '', $legend_attr = [], $attr = [] ) { + if ( ! is_array( $values ) || $values === [] ) { return; } - if ( ! isset( $this->options[ $var ] ) ) { - $this->options[ $var ] = false; - } + $val = $this->get_field_value( $var, false ); $var_esc = esc_attr( $var ); + $defaults = [ + 'disabled' => false, + ]; + $attr = wp_parse_args( $attr, $defaults ); + echo '
'; - if ( is_string( $legend ) && '' !== $legend ) { + if ( is_string( $legend ) && $legend !== '' ) { - $legend_attr = wp_parse_args( $legend_attr, array( + $legend_defaults = [ 'id' => '', 'class' => 'radiogroup', - ) ); + ]; + + $legend_attr = wp_parse_args( $legend_attr, $legend_defaults ); $this->legend( $legend, $legend_attr ); } foreach ( $values as $key => $value ) { + $label = $value; + $aria_label = ''; + + if ( is_array( $value ) ) { + $label = isset( $value['label'] ) ? $value['label'] : ''; + $aria_label = isset( $value['aria_label'] ) ? $value['aria_label'] : ''; + } + $key_esc = esc_attr( $key ); - echo 'options[ $var ], $key_esc, false ) . ' />'; + + $disabled_attribute = $this->get_disabled_attribute( $var, $attr ); + + // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped. + echo ''; $this->label( - $value, - array( - 'for' => $var_esc . '-' . $key_esc, - 'class' => 'radio', - ) + $label, + [ + 'for' => $var_esc . '-' . $key_esc, + 'class' => 'radio', + 'aria_label' => $aria_label, + ] ); } echo '
'; } - /** * Create a toggle switch input field using two radio buttons. * @@ -578,19 +784,24 @@ class Yoast_Form { * value can be an array of visible label text and screen reader text. * @param string $label The visual label for the radio buttons group, used as the fieldset legend. * @param string $help Inline Help that will be printed out before the visible toggles text. + * @param array $attr Extra attributes to add to the toggle switch. */ - public function toggle_switch( $var, $values, $label, $help = '' ) { - if ( ! is_array( $values ) || $values === array() ) { + public function toggle_switch( $var, $values, $label, $help = '', $attr = [] ) { + if ( ! is_array( $values ) || $values === [] ) { return; } - if ( ! isset( $this->options[ $var ] ) ) { - $this->options[ $var ] = false; + + $defaults = [ + 'disabled' => false, + ]; + $attr = wp_parse_args( $attr, $defaults ); + + $val = $this->get_field_value( $var, false ); + if ( $val === true ) { + $val = 'on'; } - if ( $this->options[ $var ] === true ) { - $this->options[ $var ] = 'on'; - } - if ( $this->options[ $var ] === false ) { - $this->options[ $var ] = 'off'; + if ( $val === false ) { + $val = 'off'; } $help_class = ! empty( $help ) ? ' switch-container__has-help' : ''; @@ -598,11 +809,12 @@ class Yoast_Form { $var_esc = esc_attr( $var ); printf( '
', esc_attr( 'switch-container' . $help_class ) ); - echo '
', $label, '', $help, - '
'; + echo '
', $label, '', $help; + + echo $this->get_disabled_note( $var ); + echo '
'; foreach ( $values as $key => $value ) { - $screen_reader_text = ''; $screen_reader_text_html = ''; if ( is_array( $value ) ) { @@ -611,29 +823,40 @@ class Yoast_Form { $value = $value['text']; } - $key_esc = esc_attr( $key ); - $for = $var_esc . '-' . $key_esc; - echo 'options[ $var ], $key_esc, false ) . ' />', - ''; + $key_esc = esc_attr( $key ); + $for = $var_esc . '-' . $key_esc; + $disabled_attribute = $this->get_disabled_attribute( $var, $attr ); + + // phpcs:ignore WordPress.Security.EscapeOutput -- Reason: $disabled_attribute output is hardcoded and all other output is properly escaped. + echo '', + ''; } - echo '
' . "\n\n"; + echo '
' . PHP_EOL . PHP_EOL; } /** * Creates a toggle switch to define whether an indexable should be indexed or not. * - * @param string $var The variable within the option to create the radio buttons for. - * @param string $label The visual label for the radio buttons group, used as the fieldset legend. - * @param string $help Inline Help that will be printed out before the visible toggles text. + * @param string $var The variable within the option to create the radio buttons for. + * @param string $label The visual label for the radio buttons group, used as the fieldset legend. + * @param string $help Inline Help that will be printed out before the visible toggles text. + * @param array $attr Extra attributes to add to the index switch. * * @return void */ - public function index_switch( $var, $label, $help = '' ) { - $index_switch_values = array( - 'off' => __( 'Yes', 'wordpress-seo' ), - 'on' => __( 'No', 'wordpress-seo' ), - ); + public function index_switch( $var, $label, $help = '', $attr = [] ) { + $defaults = [ + 'disabled' => false, + ]; + $attr = wp_parse_args( $attr, $defaults ); + + $index_switch_values = [ + 'off' => __( 'On', 'wordpress-seo' ), + 'on' => __( 'Off', 'wordpress-seo' ), + ]; + + $is_disabled = ( isset( $attr['disabled'] ) && $attr['disabled'] ); $this->toggle_switch( $var, @@ -641,31 +864,132 @@ class Yoast_Form { sprintf( /* translators: %s expands to an indexable object's name, like a post type or taxonomy */ esc_html__( 'Show %s in search results?', 'wordpress-seo' ), - '' . esc_html( $label ) . '' + esc_html( $label ) ), - $help + $help, + [ 'disabled' => $is_disabled ] ); } /** * Creates a toggle switch to show hide certain options. * - * @param string $var The variable within the option to create the radio buttons for. - * @param string $label The visual label for the radio buttons group, used as the fieldset legend. - * @param bool $inverse_keys Whether or not the option keys need to be inverted to support older functions. - * @param string $help Inline Help that will be printed out before the visible toggles text. + * @param string $var The variable within the option to create the radio buttons for. + * @param string $label The visual label for the radio buttons group, used as the fieldset legend. + * @param bool $inverse_keys Whether or not the option keys need to be inverted to support older functions. + * @param string $help Inline Help that will be printed out before the visible toggles text. + * @param array $attr Extra attributes to add to the show-hide switch. * * @return void */ - public function show_hide_switch( $var, $label, $inverse_keys = false, $help = '' ) { + public function show_hide_switch( $var, $label, $inverse_keys = false, $help = '', $attr = [] ) { + $defaults = [ + 'disabled' => false, + ]; + $attr = wp_parse_args( $attr, $defaults ); + $on_key = ( $inverse_keys ) ? 'off' : 'on'; $off_key = ( $inverse_keys ) ? 'on' : 'off'; - $show_hide_switch = array( - $on_key => __( 'Show', 'wordpress-seo' ), - $off_key => __( 'Hide', 'wordpress-seo' ), - ); + $show_hide_switch = [ + $on_key => __( 'On', 'wordpress-seo' ), + $off_key => __( 'Off', 'wordpress-seo' ), + ]; - $this->toggle_switch( $var, $show_hide_switch, $label, $help ); + $is_disabled = ( isset( $attr['disabled'] ) && $attr['disabled'] ); + + $this->toggle_switch( + $var, + $show_hide_switch, + $label, + $help, + [ 'disabled' => $is_disabled ] + ); + } + + /** + * Retrieves the value for the form field. + * + * @param string $field_name The field name to retrieve the value for. + * @param string|null $default_value The default value, when field has no value. + * + * @return mixed|null The retrieved value. + */ + protected function get_field_value( $field_name, $default_value = null ) { + // On multisite subsites, the Usage tracking feature should always be set to Off. + if ( $this->is_tracking_on_subsite( $field_name ) ) { + return false; + } + + return WPSEO_Options::get( $field_name, $default_value ); + } + + /** + * Checks whether a given control should be disabled. + * + * @param string $var The variable within the option to check whether its control should be disabled. + * + * @return bool True if control should be disabled, false otherwise. + */ + protected function is_control_disabled( $var ) { + if ( $this->option_instance === null ) { + return false; + } + + // Disable the Usage tracking feature for multisite subsites. + if ( $this->is_tracking_on_subsite( $var ) ) { + return true; + } + + return $this->option_instance->is_disabled( $var ); + } + + /** + * Gets the explanation note to print if a given control is disabled. + * + * @param string $var The variable within the option to print a disabled note for. + * + * @return string Explanation note HTML string, or empty string if no note necessary. + */ + protected function get_disabled_note( $var ) { + if ( ! $this->is_control_disabled( $var ) ) { + return ''; + } + + $disabled_message = esc_html__( 'This feature has been disabled by the network admin.', 'wordpress-seo' ); + + // The explanation to show when disabling the Usage tracking feature for multisite subsites. + if ( $this->is_tracking_on_subsite( $var ) ) { + $disabled_message = esc_html__( 'This feature has been disabled since subsites never send tracking data.', 'wordpress-seo' ); + } + return '

' . $disabled_message . '

'; + } + + /** + * Determines whether we are dealing with the Usage tracking feature on a multisite subsite. + * This feature requires specific behavior for the toggle switch. + * + * @param string $feature_setting The feature setting. + * + * @return bool True if we are dealing with the Usage tracking feature on a multisite subsite. + */ + protected function is_tracking_on_subsite( $feature_setting ) { + return ( $feature_setting === 'tracking' && ! is_network_admin() && ! is_main_site() ); + } + + /** + * Returns the disabled attribute HTML. + * + * @param string $var The variable within the option of the related form element. + * @param array $attr Extra attributes added to the form element. + * + * @return string The disabled attribute HTML. + */ + protected function get_disabled_attribute( $var, $attr ) { + if ( $this->is_control_disabled( $var ) || ( isset( $attr['disabled'] ) && $attr['disabled'] ) ) { + return ' disabled'; + } + + return ''; } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-input-validation.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-input-validation.php new file mode 100644 index 00000000..a98dc36b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-yoast-input-validation.php @@ -0,0 +1,326 @@ + 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 '

' . $error_description . '

'; + } + + 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 ''; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-network-admin.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-network-admin.php new file mode 100644 index 00000000..02eea736 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-yoast-network-admin.php @@ -0,0 +1,324 @@ + $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 ) { + ?> + + + 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; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-network-settings-api.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-network-settings-api.php new file mode 100644 index 00000000..13253541 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-yoast-network-settings-api.php @@ -0,0 +1,164 @@ + $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; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-notification-center.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-notification-center.php index 1f92b8e7..03fcec17 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-yoast-notification-center.php +++ b/wp-content/plugins/wordpress-seo/admin/class-yoast-notification-center.php @@ -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() ); + } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-notification.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-notification.php index 70c64f41..28b378b1 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-yoast-notification.php +++ b/wp-content/plugins/wordpress-seo/admin/class-yoast-notification.php @@ -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 '
' . wpautop( $this->message ) . '
' . PHP_EOL; + return '
' . $message . '
' . 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( + '', + esc_url( plugin_dir_url( WPSEO_FILE ) . 'packages/js/images/Yoast_SEO_Icon.svg' ), + 60, + 60 + ); + $out .= '
'; + $out .= $message; + $out .= '
'; + + 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 ) ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-notifications.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-notifications.php new file mode 100644 index 00000000..34a1fb2c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/class-yoast-notifications.php @@ -0,0 +1,376 @@ +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' ); diff --git a/wp-content/plugins/wordpress-seo/admin/class-yoast-plugin-conflict.php b/wp-content/plugins/wordpress-seo/admin/class-yoast-plugin-conflict.php index 192f5d5d..e2e5e13b 100644 --- a/wp-content/plugins/wordpress-seo/admin/class-yoast-plugin-conflict.php +++ b/wp-content/plugins/wordpress-seo/admin/class-yoast-plugin-conflict.php @@ -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[] = '' . $name . ''; } @@ -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 .= '

' . sprintf( $readable_plugin_section, 'Yoast SEO', $plugin_name ) . '

'; /* translators: %s: 'Facebook' plugin name of possibly conflicting plugin */ - $error_message .= '' . sprintf( __( 'Deactivate %s', 'wordpress-seo' ), WPSEO_Utils::get_plugin_name( $plugin_file ) ) . ' '; + $error_message .= '' . sprintf( __( 'Deactivate %s', 'wordpress-seo' ), $this->get_plugin_name( $plugin_file ) ) . ' '; $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. * diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-components.php b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-components.php index 7576f188..3d28eb9c 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-components.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-components.php @@ -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', - ) + ] ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-endpoint.php b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-endpoint.php index 2a11758e..8fc39940 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-endpoint.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-endpoint.php @@ -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 */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-options-adapter.php b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-options-adapter.php index d99ebef0..22ff92e4 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-options-adapter.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-options-adapter.php @@ -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 ] ) ) { diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-page.php b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-page.php index 4f2afd63..0fd96f4d 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-page.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-page.php @@ -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' + ); ?> - + - <?php - printf( - /* translators: %s expands to Yoast SEO. */ - esc_html__( '%s › Configuration Wizard', 'wordpress-seo' ), - 'Yoast SEO' ); - ?> + <?php echo esc_html( $wizard_title ); ?> "> @@ -150,7 +161,6 @@ class WPSEO_Configuration_Page { 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 ); } - } diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-service.php b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-service.php index 49a67be3..55fa21b4 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-service.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-service.php @@ -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. * diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-storage.php b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-storage.php index 404b5cc1..9d748358 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-storage.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-storage.php @@ -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 ); diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-structure.php b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-structure.php index 223491dc..c58a098e 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-structure.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-structure.php @@ -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 */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-translations.php b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-translations.php index 615a39a7..429cf514 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-translations.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/class-configuration-translations.php @@ -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 []; } } diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-configuration-choices.php b/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-configuration-choices.php deleted file mode 100644 index 4e166bcf..00000000 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-configuration-choices.php +++ /dev/null @@ -1,98 +0,0 @@ -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; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-connect-google-search-console.php b/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-connect-google-search-console.php deleted file mode 100644 index 728b52b2..00000000 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-connect-google-search-console.php +++ /dev/null @@ -1,151 +0,0 @@ -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() ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-mailchimp-signup.php b/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-mailchimp-signup.php index 7dcf7e6b..02917a17 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-mailchimp-signup.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-mailchimp-signup.php @@ -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 */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-suggestions.php b/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-suggestions.php index 0c358cf8..226ffb36 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-suggestions.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/components/class-component-suggestions.php @@ -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. * diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/components/interface-component.php b/wp-content/plugins/wordpress-seo/admin/config-ui/components/interface-component.php index f1030d6d..3b9fa48c 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/components/interface-component.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/components/interface-component.php @@ -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(); diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/factories/class-factory-post-type.php b/wp-content/plugins/wordpress-seo/admin/config-ui/factories/class-factory-post-type.php index d9317871..2bfdd5f9 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/factories/class-factory-post-type.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/factories/class-factory-post-type.php @@ -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' ) ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-choice-post-type.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-choice-post-type.php index 6a63e971..96a489ed 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-choice-post-type.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-choice-post-type.php @@ -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). * diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-choice.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-choice.php index e7cd90f5..f698f706 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-choice.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-choice.php @@ -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; diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-info-missing.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-info-missing.php new file mode 100644 index 00000000..a1387571 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-info-missing.php @@ -0,0 +1,28 @@ +set_property( 'message', $l10n_data['message'] ); + $this->set_property( 'link', $l10n_data['URL'] ); + + $this->set_requires( 'publishingEntityType', 'company' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-logo.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-logo.php index c6c7d1df..42bb4fd3 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-logo.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-logo.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Company_Logo + * Class WPSEO_Config_Field_Company_Logo. */ class WPSEO_Config_Field_Company_Logo extends WPSEO_Config_Field { @@ -16,12 +16,14 @@ class WPSEO_Config_Field_Company_Logo extends WPSEO_Config_Field { public function __construct() { parent::__construct( 'publishingEntityCompanyLogo', 'MediaUpload' ); - $this->set_property( 'label', __( 'Provide an image of the company logo', 'wordpress-seo' ) ); + $this->set_property( 'label', __( 'Provide an image of the organization logo', 'wordpress-seo' ) ); $this->set_requires( 'publishingEntityType', 'company' ); } /** + * Sets the adapter. + * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ public function set_adapter( WPSEO_Configuration_Options_Adapter $adapter ) { diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-name.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-name.php index af079863..f8a3206d 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-name.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-name.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Company_Name + * Class WPSEO_Config_Field_Company_Name. */ class WPSEO_Config_Field_Company_Name extends WPSEO_Config_Field { @@ -16,12 +16,15 @@ class WPSEO_Config_Field_Company_Name extends WPSEO_Config_Field { public function __construct() { parent::__construct( 'publishingEntityCompanyName', 'Input' ); - $this->set_property( 'label', __( 'The name of the company', 'wordpress-seo' ) ); + $this->set_property( 'label', __( 'The name of the organization', 'wordpress-seo' ) ); + $this->set_property( 'autoComplete', 'organization' ); $this->set_requires( 'publishingEntityType', 'company' ); } /** + * Sets the adapter. + * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ public function set_adapter( WPSEO_Configuration_Options_Adapter $adapter ) { diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-or-person.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-or-person.php index 894a7084..22f884c8 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-or-person.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-company-or-person.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Company_Or_Person + * Class WPSEO_Config_Field_Company_Or_Person. */ class WPSEO_Config_Field_Company_Or_Person extends WPSEO_Config_Field_Choice { @@ -16,16 +16,17 @@ class WPSEO_Config_Field_Company_Or_Person extends WPSEO_Config_Field_Choice { public function __construct() { parent::__construct( 'publishingEntityType' ); - $this->set_property( 'label', __( 'Does your site represent a person or company?', 'wordpress-seo' ) ); + $this->set_property( 'label', __( 'Does your site represent a person or an organization?', 'wordpress-seo' ) ); - $this->set_property( 'description', __( 'This information will be used in Google\'s Knowledge Graph Card, the big - block of information you see on the right side of the search results.', 'wordpress-seo' ) ); + $this->set_property( 'description', __( 'This information will be used in Google\'s Knowledge Graph Card, the big block of information you see on the right side of the search results.', 'wordpress-seo' ) ); - $this->add_choice( 'company', __( 'Company', 'wordpress-seo' ) ); + $this->add_choice( 'company', __( 'Organization', 'wordpress-seo' ) ); $this->add_choice( 'person', __( 'Person', 'wordpress-seo' ) ); } /** + * Sets the adapter. + * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ public function set_adapter( WPSEO_Configuration_Options_Adapter $adapter ) { diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-configuration-choices.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-configuration-choices.php deleted file mode 100644 index 2dc213e6..00000000 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-configuration-choices.php +++ /dev/null @@ -1,43 +0,0 @@ -properties['choices'] = array(); - } - - /** - * Adds a choice to the properties - * - * @param string $title The title of the choice. - * @param string $copy The text explaining the choice. - * @param array $button The button details. - * @param null|string $image The image accompanying the choice. - */ - public function add_choice( $title, $copy, $button, $image = null ) { - $choice = array( - 'title' => $title, - 'copy' => $copy, - 'button' => $button, - ); - - if ( ! empty( $image ) ) { - $choice['image'] = $image; - } - - $this->properties['choices'][] = $choice; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-connect-google-search-console.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-connect-google-search-console.php deleted file mode 100644 index 7ab980d7..00000000 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-connect-google-search-console.php +++ /dev/null @@ -1,30 +0,0 @@ - '', - 'profileList' => '', - ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-environment.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-environment.php index 7201f939..7656bf93 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-environment.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-environment.php @@ -6,9 +6,10 @@ */ /** - * Class WPSEO_Config_Field_Environment + * Class WPSEO_Config_Field_Environment. */ class WPSEO_Config_Field_Environment extends WPSEO_Config_Field_Choice { + /** * WPSEO_Config_Field_Environment constructor. */ @@ -17,24 +18,22 @@ class WPSEO_Config_Field_Environment extends WPSEO_Config_Field_Choice { $this->set_property( 'label', __( 'Please specify if your site is under construction or already active.', 'wordpress-seo' ) ); - $this->set_property( 'description', __( 'Choose under construction if you want to keep the site out of the index - of search engines. Don\'t forget to activate it once you\'re ready to - publish your site.', 'wordpress-seo' ) ); + $this->set_property( 'description', __( 'Choose under construction if you want to keep the site out of the index of search engines. Don\'t forget to activate it once you\'re ready to publish your site.', 'wordpress-seo' ) ); $this->add_choice( 'production', __( 'Option A: My site is live and ready to be indexed', 'wordpress-seo' ) ); $this->add_choice( 'staging', __( 'Option B: My site is under construction and should not be indexed', 'wordpress-seo' ) ); } /** - * 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' ] ); } diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-google-search-console-intro.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-google-search-console-intro.php deleted file mode 100644 index a04826ff..00000000 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-google-search-console-intro.php +++ /dev/null @@ -1,37 +0,0 @@ -', - '' ); - - $disclaimer = __( 'Note: we don\'t store your data in any way and don\'t have full access to your account. -Your privacy is safe with us.', 'wordpress-seo' ); - - $html = '

' . $html . '

' . esc_html( $disclaimer ) . ''; - - $this->set_property( 'html', $html ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-mailchimp-signup.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-mailchimp-signup.php index 5c6bfb27..cf35b60e 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-mailchimp-signup.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-mailchimp-signup.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Mailchimp_Signup + * Class WPSEO_Config_Field_Mailchimp_Signup. */ class WPSEO_Config_Field_Mailchimp_Signup extends WPSEO_Config_Field { @@ -19,37 +19,42 @@ class WPSEO_Config_Field_Mailchimp_Signup extends WPSEO_Config_Field { $current_user = wp_get_current_user(); $user_email = ( $current_user->ID > 0 ) ? $current_user->user_email : ''; - $this->set_property( 'title', __( 'Stay up-to-date', 'wordpress-seo' ) ); - $this->set_property( - 'label', - sprintf( - /* translators: %s expands to Yoast SEO. */ - __( 'Your %1$s plugin is now set up. SEO, however, is subject to constant change. Sign up for our newsletter if you would like to keep up-to-date regarding %1$s, other plugins by Yoast and important news in the world of SEO.', 'wordpress-seo' ), - 'Yoast SEO' - ) + $signup_text = sprintf( + /* translators: %1$s expands to Yoast SEO for WordPress, %2$s expands to Yoast */ + __( 'Sign up for our newsletter if you would like to keep up-to-date about %1$s, other cool plugins by %2$s, and interesting news and tips from the world of SEO.', 'wordpress-seo' ), + 'Yoast SEO for WordPress', + 'Yoast' ); - $this->set_property( 'decoration', plugin_dir_url( WPSEO_FILE ) . 'images/newsletter-collage.png' ); + $gdpr_notice = sprintf( + /* translators: %1$s expands Yoast, %2$s expands to an opening anchor tag, %3$s expands to a closing anchor tag. */ + __( '%1$s respects your privacy. Read our %2$sprivacy policy%3$s on how we handle your personal information.', 'wordpress-seo' ), + 'Yoast', + '', + '' + ); + $this->set_property( 'label', $signup_text ); + $this->set_property( 'decoration', plugin_dir_url( WPSEO_FILE ) . 'images/newsletter-collage.png' ); $this->set_property( 'mailchimpActionUrl', 'https://yoast.us1.list-manage.com/subscribe/post-json?u=ffa93edfe21752c921f860358&id=972f1c9122' ); $this->set_property( 'currentUserEmail', $user_email ); - $this->set_property( 'userName', trim( $current_user->user_firstname . ' ' . $current_user->user_lastname ) ); + $this->set_property( 'freeAccountNotice', __( 'Includes a free MyYoast account which gives you access to our free SEO for Beginners course!', 'wordpress-seo' ) ); + $this->set_property( 'GDPRNotice', sprintf( '%s', $gdpr_notice ) ); } /** - * Get the data + * Get the data. * * @return array */ public function get_data() { - return array( + return [ 'hasSignup' => $this->has_mailchimp_signup(), - ); - + ]; } /** - * Checks if the user has entered his email for mailchimp already. + * Checks if the user has entered their email for mailchimp already. * * @return bool */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-multiple-authors.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-multiple-authors.php index ace9d5aa..633d20df 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-multiple-authors.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-multiple-authors.php @@ -6,9 +6,10 @@ */ /** - * Class WPSEO_Config_Field_Multiple_Authors + * Class WPSEO_Config_Field_Multiple_Authors. */ class WPSEO_Config_Field_Multiple_Authors extends WPSEO_Config_Field_Choice { + /** * WPSEO_Config_Field_Multiple_Authors constructor. */ @@ -17,8 +18,7 @@ class WPSEO_Config_Field_Multiple_Authors extends WPSEO_Config_Field_Choice { $this->set_property( 'label', __( 'Does, or will, your site have multiple authors?', 'wordpress-seo' ) ); - $this->set_property( 'description', __( 'If you choose no, your author archives will be deactivated to prevent - duplicate content issues.', 'wordpress-seo' ) ); + $this->set_property( 'description', __( 'If you choose no, your author archives will be deactivated to prevent duplicate content issues.', 'wordpress-seo' ) ); $this->add_choice( 'yes', __( 'Yes', 'wordpress-seo' ) ); $this->add_choice( 'no', __( 'No', 'wordpress-seo' ) ); @@ -32,15 +32,15 @@ class WPSEO_Config_Field_Multiple_Authors extends WPSEO_Config_Field_Choice { 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' ] ); } /** * Get the data from the stored options. * - * @return null|string + * @return string|null */ public function get_data() { @@ -50,10 +50,11 @@ class WPSEO_Config_Field_Multiple_Authors extends WPSEO_Config_Field_Choice { if ( ! isset( $value ) || is_null( $value ) ) { // If there are more than one users with level > 1 default to multiple authors. - $users = get_users( array( + $user_criteria = [ 'fields' => 'IDs', 'who' => 'authors', - ) ); + ]; + $users = get_users( $user_criteria ); $value = count( $users ) > 1; } @@ -64,7 +65,7 @@ class WPSEO_Config_Field_Multiple_Authors extends WPSEO_Config_Field_Choice { /** * Set the data in the options. * - * @param {string} $data The data to set for the field. + * @param string $data The data to set for the field. * * @return bool Returns true or false for successful storing the data. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-person-name.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-person.php similarity index 54% rename from wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-person-name.php rename to wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-person.php index 095f41f9..99f3e6ba 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-person-name.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-person.php @@ -6,25 +6,27 @@ */ /** - * Class WPSEO_Config_Field_Person_Name + * Class WPSEO_Config_Field_Person_Name. */ -class WPSEO_Config_Field_Person_Name extends WPSEO_Config_Field { +class WPSEO_Config_Field_Person extends WPSEO_Config_Field { /** * WPSEO_Config_Field_Company_Or_Person constructor. */ public function __construct() { - parent::__construct( 'publishingEntityPersonName', 'Input' ); + parent::__construct( 'publishingEntityPersonId', 'WordPressUserSelector' ); - $this->set_property( 'label', __( 'The name of the person', 'wordpress-seo' ) ); + $this->set_property( 'label', __( 'The person', 'wordpress-seo' ) ); $this->set_requires( 'publishingEntityType', 'person' ); } /** + * Sets the adapter. + * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ public function set_adapter( WPSEO_Configuration_Options_Adapter $adapter ) { - $adapter->add_option_lookup( $this->get_identifier(), 'person_name' ); + $adapter->add_option_lookup( $this->get_identifier(), 'company_or_person_user_id' ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-post-type-visibility.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-post-type-visibility.php index 000ba80a..b4f51e04 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-post-type-visibility.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-post-type-visibility.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Post_Type_Visibility + * Class WPSEO_Config_Field_Post_Type_Visibility. */ class WPSEO_Config_Field_Post_Type_Visibility extends WPSEO_Config_Field { @@ -16,9 +16,7 @@ class WPSEO_Config_Field_Post_Type_Visibility extends WPSEO_Config_Field { public function __construct() { parent::__construct( 'postTypeVisibility', 'HTML' ); - $copy = __( 'Please specify what content types you would like to appear in search engines. - If you do not know the differences between these, it\'s best to choose the - default settings.', 'wordpress-seo' ); + $copy = __( 'Please specify what content types you would like to appear in search engines. If you do not know the differences between these, it\'s best to choose the default settings.', 'wordpress-seo' ); $html = '

' . esc_html( $copy ) . '


'; diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-facebook.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-facebook.php index 019d3543..8a76eb1d 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-facebook.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-facebook.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Profile_URL_Facebook + * Class WPSEO_Config_Field_Profile_URL_Facebook. */ class WPSEO_Config_Field_Profile_URL_Facebook extends WPSEO_Config_Field { @@ -18,10 +18,12 @@ class WPSEO_Config_Field_Profile_URL_Facebook extends WPSEO_Config_Field { $this->set_property( 'label', __( 'Facebook Page URL', 'wordpress-seo' ) ); $this->set_property( 'pattern', '^https:\/\/www\.facebook\.com\/([^/]+)\/$' ); + + $this->set_requires( 'publishingEntityType', 'company' ); } /** - * Set adapter + * Set adapter. * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-googleplus.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-googleplus.php deleted file mode 100644 index e29f6a81..00000000 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-googleplus.php +++ /dev/null @@ -1,31 +0,0 @@ -set_property( 'label', __( 'Google+ URL', 'wordpress-seo' ) ); - $this->set_property( 'pattern', '^https:\/\/plus\.google\.com\/([^/]+)$' ); - } - - /** - * Set adapter - * - * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. - */ - public function set_adapter( WPSEO_Configuration_Options_Adapter $adapter ) { - $adapter->add_option_lookup( $this->get_identifier(), 'google_plus_url' ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-instagram.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-instagram.php index 0b4620c0..bcbb9f02 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-instagram.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-instagram.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Profile_URL_Instagram + * Class WPSEO_Config_Field_Profile_URL_Instagram. */ class WPSEO_Config_Field_Profile_URL_Instagram extends WPSEO_Config_Field { @@ -18,10 +18,12 @@ class WPSEO_Config_Field_Profile_URL_Instagram extends WPSEO_Config_Field { $this->set_property( 'label', __( 'Instagram URL', 'wordpress-seo' ) ); $this->set_property( 'pattern', '^https:\/\/www\.instagram\.com\/([^/]+)\/$' ); + + $this->set_requires( 'publishingEntityType', 'company' ); } /** - * Set adapter + * Set adapter. * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-linkedin.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-linkedin.php index a53b6c73..4ed5162e 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-linkedin.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-linkedin.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Profile_URL_LinkedIn + * Class WPSEO_Config_Field_Profile_URL_LinkedIn. */ class WPSEO_Config_Field_Profile_URL_LinkedIn extends WPSEO_Config_Field { @@ -18,10 +18,12 @@ class WPSEO_Config_Field_Profile_URL_LinkedIn extends WPSEO_Config_Field { $this->set_property( 'label', __( 'LinkedIn URL', 'wordpress-seo' ) ); $this->set_property( 'pattern', '^https:\/\/www\.linkedin\.com\/in\/([^/]+)$' ); + + $this->set_requires( 'publishingEntityType', 'company' ); } /** - * Set adapter + * Set adapter. * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-myspace.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-myspace.php index 9bfc03e8..c7ffe42b 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-myspace.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-myspace.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Profile_URL_MySpace + * Class WPSEO_Config_Field_Profile_URL_MySpace. */ class WPSEO_Config_Field_Profile_URL_MySpace extends WPSEO_Config_Field { @@ -18,10 +18,12 @@ class WPSEO_Config_Field_Profile_URL_MySpace extends WPSEO_Config_Field { $this->set_property( 'label', __( 'MySpace URL', 'wordpress-seo' ) ); $this->set_property( 'pattern', '^https:\/\/myspace\.com\/([^/]+)\/$' ); + + $this->set_requires( 'publishingEntityType', 'company' ); } /** - * Set adapter + * Set adapter. * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-pinterest.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-pinterest.php index ce1fb735..7182fea2 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-pinterest.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-pinterest.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Profile_URL_Pinterest + * Class WPSEO_Config_Field_Profile_URL_Pinterest. */ class WPSEO_Config_Field_Profile_URL_Pinterest extends WPSEO_Config_Field { @@ -18,10 +18,12 @@ class WPSEO_Config_Field_Profile_URL_Pinterest extends WPSEO_Config_Field { $this->set_property( 'label', __( 'Pinterest URL', 'wordpress-seo' ) ); $this->set_property( 'pattern', '^https:\/\/www\.pinterest\.com\/([^/]+)\/$' ); + + $this->set_requires( 'publishingEntityType', 'company' ); } /** - * Set adapter + * Set adapter. * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-twitter.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-twitter.php index 4c481038..2b45700e 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-twitter.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-twitter.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Profile_URL_Twitter + * Class WPSEO_Config_Field_Profile_URL_Twitter. */ class WPSEO_Config_Field_Profile_URL_Twitter extends WPSEO_Config_Field { @@ -17,10 +17,12 @@ class WPSEO_Config_Field_Profile_URL_Twitter extends WPSEO_Config_Field { parent::__construct( 'profileUrlTwitter', 'Input' ); $this->set_property( 'label', __( 'Twitter Username', 'wordpress-seo' ) ); + + $this->set_requires( 'publishingEntityType', 'company' ); } /** - * Set adapter + * Set adapter. * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-wikipedia.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-wikipedia.php new file mode 100644 index 00000000..9b364a9d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-wikipedia.php @@ -0,0 +1,35 @@ +set_property( 'label', __( 'Wikipedia URL', 'wordpress-seo' ) ); + $this->set_property( 'pattern', '^https:\/\/([a-z\-]+)\.wikipedia\.org\/([^/]+)$' ); + + $this->set_requires( 'publishingEntityType', 'company' ); + } + + /** + * Sets the adapter. + * + * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. + * + * @return void + */ + public function set_adapter( WPSEO_Configuration_Options_Adapter $adapter ) { + $adapter->add_option_lookup( $this->get_identifier(), 'wikipedia_url' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-youtube.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-youtube.php index ae093b19..8143400a 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-youtube.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-profile-url-youtube.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Profile_URL_YouTube + * Class WPSEO_Config_Field_Profile_URL_YouTube. */ class WPSEO_Config_Field_Profile_URL_YouTube extends WPSEO_Config_Field { @@ -18,10 +18,12 @@ class WPSEO_Config_Field_Profile_URL_YouTube extends WPSEO_Config_Field { $this->set_property( 'label', __( 'YouTube URL', 'wordpress-seo' ) ); $this->set_property( 'pattern', '^https:\/\/www\.youtube\.com\/([^/]+)$' ); + + $this->set_requires( 'publishingEntityType', 'company' ); } /** - * Set adapter + * Set adapter. * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-separator.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-separator.php index dddb4a39..8178f6fd 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-separator.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-separator.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Separator + * Class WPSEO_Config_Field_Separator. */ class WPSEO_Config_Field_Separator extends WPSEO_Config_Field_Choice { @@ -19,23 +19,21 @@ class WPSEO_Config_Field_Separator extends WPSEO_Config_Field_Choice { $this->set_property( 'label', __( 'Title Separator', 'wordpress-seo' ) ); $this->set_property( 'explanation', __( 'Choose the symbol to use as your title separator. This will display, for instance, between your post title and site name. Symbols are shown in the size they\'ll appear in the search results.', 'wordpress-seo' ) ); - $this->add_choice( 'sc-dash', '-', __( 'Dash', 'wordpress-seo' ) ); - $this->add_choice( 'sc-ndash', '–', __( 'En dash', 'wordpress-seo' ) ); - $this->add_choice( 'sc-mdash', '—', __( 'Em dash', 'wordpress-seo' ) ); - $this->add_choice( 'sc-middot', '·', __( 'Middle dot', 'wordpress-seo' ) ); - $this->add_choice( 'sc-bull', '•', __( 'Bullet', 'wordpress-seo' ) ); - $this->add_choice( 'sc-star', '*', __( 'Asterisk', 'wordpress-seo' ) ); - $this->add_choice( 'sc-smstar', '⋆', __( 'Low asterisk', 'wordpress-seo' ) ); - $this->add_choice( 'sc-pipe', '|', __( 'Vertical bar', 'wordpress-seo' ) ); - $this->add_choice( 'sc-tilde', '~', __( 'Small tilde', 'wordpress-seo' ) ); - $this->add_choice( 'sc-laquo', '«', __( 'Left angle quotation mark', 'wordpress-seo' ) ); - $this->add_choice( 'sc-raquo', '»', __( 'Right angle quotation mark', 'wordpress-seo' ) ); - $this->add_choice( 'sc-lt', '<', __( 'Less than sign', 'wordpress-seo' ) ); - $this->add_choice( 'sc-gt', '>', __( 'Greater than sign', 'wordpress-seo' ) ); + $this->add_choices(); } /** - * Set adapter + * Adds the title separator choices. + */ + protected function add_choices() { + $choices = WPSEO_Option_Titles::get_instance()->get_separator_options_for_display(); + foreach ( $choices as $key => $value ) { + $this->add_choice( $key, $value['label'], $value['aria_label'] ); + } + } + + /** + * Set adapter. * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-site-name.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-site-name.php index 8d8e2d57..21e4a5e7 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-site-name.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-site-name.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Site_Name + * Class WPSEO_Config_Field_Site_Name. */ class WPSEO_Config_Field_Site_Name extends WPSEO_Config_Field { @@ -22,22 +22,22 @@ class WPSEO_Config_Field_Site_Name extends WPSEO_Config_Field { } /** - * 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' ] ); } /** * Get the data from the stored options. * - * @return null|string + * @return string|null */ public function get_data() { if ( WPSEO_Options::get( 'website_name', false ) ) { @@ -50,7 +50,7 @@ class WPSEO_Config_Field_Site_Name extends WPSEO_Config_Field { /** * Set the data in the options. * - * @param {string} $data The data to set for the field. + * @param string $data The data to set for the field. * * @return bool Returns true or false for successful storing the data. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-site-type.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-site-type.php index a62b911f..348d0ae3 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-site-type.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-site-type.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Site_Type + * Class WPSEO_Config_Field_Site_Type. */ class WPSEO_Config_Field_Site_Type extends WPSEO_Config_Field_Choice { @@ -29,7 +29,7 @@ class WPSEO_Config_Field_Site_Type extends WPSEO_Config_Field_Choice { } /** - * Set adapter + * Set adapter. * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-social-profiles-intro.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-social-profiles-intro.php deleted file mode 100644 index 5c577609..00000000 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-social-profiles-intro.php +++ /dev/null @@ -1,33 +0,0 @@ -', - '' - ); - - $html = '

' . $intro_text . '

'; - - $this->set_property( 'html', $html ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-success-message.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-success-message.php index 091815c2..b565d6df 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-success-message.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-success-message.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Success_Message + * Class WPSEO_Config_Field_Success_Message. */ class WPSEO_Config_Field_Success_Message extends WPSEO_Config_Field { @@ -18,20 +18,21 @@ class WPSEO_Config_Field_Success_Message extends WPSEO_Config_Field { $success_message = sprintf( /* translators: %1$s expands to Yoast SEO. */ - __( '%1$s will now take care of all the needed technical optimization of your site. To really improve your site\'s performance in the search results, it\'s important to start creating content that ranks well for keywords you care about. Check out this video in which we explain how to use the %1$s metabox when you edit posts or pages.', 'wordpress-seo' ), + __( '%1$s will now take care of all the needed technical optimization of your site. To really improve your site\'s performance in the search results, it\'s important to know everything our plugin has to offer. Sign up for our free %1$s plugin training, in which you\'ll learn how to use %1$s and how it can help you make the best of your website!', 'wordpress-seo' ), 'Yoast SEO' ); $this->set_property( 'title', __( 'You\'ve done it!', 'wordpress-seo' ) ); $this->set_property( 'message', $success_message ); - $this->set_property( 'video', array( - 'url' => WPSEO_Shortlinker::get( 'https://yoa.st/metabox-screencast' ), - 'title' => sprintf( - /* translators: %1$s expands to Yoast SEO. */ - __( '%1$s video tutorial', 'wordpress-seo' ), - 'Yoast SEO' - ), - ) - ); + $this->set_property( 'href', WPSEO_Shortlinker::get( 'https://yoa.st/3rp' ) ); + + /* translators: %1$s expands to Yoast SEO. */ + $img_alt = __( '%1$s video tutorial', 'wordpress-seo' ); + $img_args = [ + 'src' => plugin_dir_url( WPSEO_FILE ) . ( 'images/Yoast_Academy_video.png' ), + 'alt' => sprintf( $img_alt, 'Yoast SEO' ), + ]; + + $this->set_property( 'image', $img_args ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-suggestions.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-suggestions.php index 61a75ec8..0725a004 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-suggestions.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-suggestions.php @@ -6,7 +6,7 @@ */ /** - * Holds the suggestions for the 'You might also like' page in the wizard + * Holds the suggestions for the 'You might also like' page in the wizard. */ class WPSEO_Config_Field_Suggestions extends WPSEO_Config_Field { @@ -16,23 +16,23 @@ class WPSEO_Config_Field_Suggestions extends WPSEO_Config_Field { public function __construct() { parent::__construct( 'suggestions', 'Suggestions' ); - $this->properties['suggestions'] = array(); + $this->properties['suggestions'] = []; } /** - * Adds a suggestion to the properties + * Adds a suggestion to the properties. * - * @param string $title The title of the choice. - * @param string $copy The text explaining the choice. - * @param array $button The button details. - * @param null|string $video The video accompanying the choice. + * @param string $title The title of the choice. + * @param string $copy The text explaining the choice. + * @param array $button The button details. + * @param array $video URL and title of the video accompanying the choice. */ - public function add_suggestion( $title, $copy, $button, $video = null ) { - $suggestion = array( + public function add_suggestion( $title, $copy, $button, array $video = [] ) { + $suggestion = [ 'title' => $title, 'copy' => $copy, 'button' => $button, - ); + ]; if ( ! empty( $video ) ) { $suggestion['video'] = $video; @@ -41,4 +41,3 @@ class WPSEO_Config_Field_Suggestions extends WPSEO_Config_Field { $this->properties['suggestions'][] = $suggestion; } } - diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-title-intro.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-title-intro.php index 2f380edf..599d2f01 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-title-intro.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-title-intro.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Config_Field_Title_Intro + * Class WPSEO_Config_Field_Title_Intro. */ class WPSEO_Config_Field_Title_Intro extends WPSEO_Config_Field { @@ -16,11 +16,7 @@ class WPSEO_Config_Field_Title_Intro extends WPSEO_Config_Field { public function __construct() { parent::__construct( 'titleIntro', 'HTML' ); - $html = __( 'On this page, you can change the name of your site and choose which - separator to use. The separator will display, for instance, between your - post title and site name. Symbols are shown in the size they\'ll appear in - the search results. Choose the one that fits your brand best or takes up - the least space in the snippets.', 'wordpress-seo' ); + $html = __( 'On this page, you can change the name of your site and choose which separator to use. The separator will display, for instance, between your post title and site name. Symbols are shown in the size they\'ll appear in the search results. Choose the one that fits your brand best or takes up the least space in the snippets.', 'wordpress-seo' ); $html = '

' . esc_html( $html ) . '

'; diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-tracking-intro.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-tracking-intro.php new file mode 100644 index 00000000..741bc4a2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-tracking-intro.php @@ -0,0 +1,25 @@ +' . esc_html__( 'At Yoast, we are always keen on providing the very best experience for you. To do so, we\'d like to collect some data about which other plugins and themes you have installed, and which features you use and don\'t use. Be assured that we\'ll never resell that data. And of course, as always, we won\'t collect any personal data about you or your visitors!', 'wordpress-seo' ) . '

'; + + $html .= '

' . esc_html__( 'Read more about our usage tracking.', 'wordpress-seo' ) . '

'; + + $this->set_property( 'html', $html ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-tracking.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-tracking.php new file mode 100644 index 00000000..7056c5cd --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-tracking.php @@ -0,0 +1,66 @@ +set_property( 'label', __( 'Can we collect anonymous information about your website and its usage?', 'wordpress-seo' ) ); + + $this->add_choice( 'no', __( 'No, I don\'t want to allow you to track my site data.', 'wordpress-seo' ) ); + $this->add_choice( 'yes', __( 'Yes, you can track my site\'s data!', 'wordpress-seo' ) ); + } + + /** + * 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(), + [ $this, 'get_data' ], + [ $this, 'set_data' ] + ); + } + + /** + * Gets the option that is set for this field. + * + * @return string The value for the environment_type wpseo option. + */ + public function get_data() { + $tracking = WPSEO_Options::get( 'tracking' ); + if ( $tracking ) { + return 'yes'; + } + return 'no'; + } + + /** + * Set new data. + * + * @param string $tracking The site's environment type. + * + * @return bool Returns whether the value is successfully set. + */ + public function set_data( $tracking ) { + $return = true; + if ( $this->get_data() !== $tracking ) { + $return = WPSEO_Options::set( 'tracking', $tracking ); + } + + return $return; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-upsell-configuration-service.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-upsell-configuration-service.php deleted file mode 100644 index ad2f8d78..00000000 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-upsell-configuration-service.php +++ /dev/null @@ -1,45 +0,0 @@ -', - '' - ); - - $html = '

' . esc_html( $intro_text ) . '

'; - $html .= '

' . wp_kses( $upsell_text, array( - 'a' => array( - 'target' => array( '_blank' ), - 'href' => array(), - ), - ) ) . '

'; - - - $this->set_property( 'html', $html ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-upsell-site-review.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-upsell-site-review.php deleted file mode 100644 index b62edef4..00000000 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field-upsell-site-review.php +++ /dev/null @@ -1,38 +0,0 @@ -Yoast SEO for WordPress training', - '', - '' - ); - - $html = '

' . - wp_kses( $upsell_text, array( - 'a' => array( - 'href' => array(), - 'target' => array( '_blank' ), - ), - ) ) . - '

'; - - $this->set_property( 'html', $html ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field.php b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field.php index 6e0cdcd0..27023a63 100644 --- a/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field.php +++ b/wp-content/plugins/wordpress-seo/admin/config-ui/fields/class-field.php @@ -6,23 +6,44 @@ */ /** - * Class WPSEO_Config_Field + * Class WPSEO_Config_Field. */ class WPSEO_Config_Field { - /** @var string Field name */ + + /** + * Field name. + * + * @var string + */ protected $field; - /** @var string Component to use */ + /** + * Component to use. + * + * @var string + */ protected $component; - /** @var array Properties of this field */ - protected $properties = array(); + /** + * Properties of this field. + * + * @var array + */ + protected $properties = []; - /** @var array Field requirements */ - protected $requires = array(); + /** + * Field requirements. + * + * @var array + */ + protected $requires = []; - /** @var array|mixed Value of this field */ - protected $data = array(); + /** + * Value of this field. + * + * @var array|mixed + */ + protected $data = []; /** * WPSEO_Config_Field constructor. @@ -36,7 +57,7 @@ class WPSEO_Config_Field { } /** - * Get the identifier + * Get the identifier. * * @return string */ @@ -45,7 +66,7 @@ class WPSEO_Config_Field { } /** - * Get the component + * Get the component. * * @return string */ @@ -54,7 +75,7 @@ class WPSEO_Config_Field { } /** - * Set a property value + * Set a property value. * * @param string $name Property to set. * @param mixed $value Value to apply. @@ -64,7 +85,7 @@ class WPSEO_Config_Field { } /** - * Get all the properties + * Get all the properties. * * @return array */ @@ -73,7 +94,7 @@ class WPSEO_Config_Field { } /** - * Get the data + * Get the data. * * @return mixed */ @@ -87,9 +108,9 @@ class WPSEO_Config_Field { * @return array */ public function to_array() { - $output = array( + $output = [ 'componentName' => $this->get_component(), - ); + ]; $properties = $this->get_properties(); if ( $properties ) { @@ -105,7 +126,7 @@ class WPSEO_Config_Field { } /** - * Set the adapter to use + * Set the adapter to use. * * @param WPSEO_Configuration_Options_Adapter $adapter Adapter to register lookup on. */ @@ -119,14 +140,14 @@ class WPSEO_Config_Field { * @param mixed $value Value of the field. */ public function set_requires( $field, $value ) { - $this->requires = array( + $this->requires = [ 'field' => $field, 'value' => $value, - ); + ]; } /** - * Get the required field settings (if present) + * Get the required field settings (if present). * * @return array */ diff --git a/wp-content/plugins/wordpress-seo/admin/endpoints/class-endpoint-file-size.php b/wp-content/plugins/wordpress-seo/admin/endpoints/class-endpoint-file-size.php new file mode 100644 index 00000000..03977762 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/endpoints/class-endpoint-file-size.php @@ -0,0 +1,85 @@ +service = $service; + } + + /** + * Registers the routes for the endpoints. + * + * @return void + */ + public function register() { + $route_args = [ + 'methods' => 'GET', + 'args' => [ + 'url' => [ + 'required' => true, + 'type' => 'string', + 'description' => 'The url to retrieve', + ], + ], + 'callback' => [ + $this->service, + 'get', + ], + 'permission_callback' => [ + $this, + 'can_retrieve_data', + ], + ]; + register_rest_route( self::REST_NAMESPACE, self::ENDPOINT_SINGULAR, $route_args ); + } + + /** + * Determines whether or not data can be retrieved for the registered endpoints. + * + * @return bool Whether or not data can be retrieved. + */ + public function can_retrieve_data() { + return current_user_can( self::CAPABILITY_RETRIEVE ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/endpoints/class-endpoint-statistics.php b/wp-content/plugins/wordpress-seo/admin/endpoints/class-endpoint-statistics.php index 2c254fd3..c744377a 100644 --- a/wp-content/plugins/wordpress-seo/admin/endpoints/class-endpoint-statistics.php +++ b/wp-content/plugins/wordpress-seo/admin/endpoints/class-endpoint-statistics.php @@ -10,12 +10,32 @@ */ class WPSEO_Endpoint_Statistics implements WPSEO_Endpoint { + /** + * The namespace of the REST route. + * + * @var string + */ const REST_NAMESPACE = 'yoast/v1'; + + /** + * The route of the statistics endpoint. + * + * @var string + */ const ENDPOINT_RETRIEVE = 'statistics'; + /** + * The name of the capability needed to retrieve data using the endpoints. + * + * @var string + */ const CAPABILITY_RETRIEVE = 'read'; - /** @var WPSEO_Statistics_Service Service to use */ + /** + * Service to use. + * + * @var WPSEO_Statistics_Service + */ protected $service; /** @@ -32,17 +52,12 @@ class WPSEO_Endpoint_Statistics implements WPSEO_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_statistics', - ), - 'permission_callback' => array( - $this, - 'can_retrieve_data', - ), - ) ); + 'callback' => [ $this->service, 'get_statistics' ], + 'permission_callback' => [ $this, 'can_retrieve_data' ], + ]; + register_rest_route( self::REST_NAMESPACE, self::ENDPOINT_RETRIEVE, $route_args ); } /** diff --git a/wp-content/plugins/wordpress-seo/admin/exceptions/class-file-size-exception.php b/wp-content/plugins/wordpress-seo/admin/exceptions/class-file-size-exception.php new file mode 100644 index 00000000..3deddbe2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/exceptions/class-file-size-exception.php @@ -0,0 +1,46 @@ +is_filter_active() ) { - add_action( 'restrict_manage_posts', array( $this, 'render_hidden_input' ) ); + add_action( 'restrict_manage_posts', [ $this, 'render_hidden_input' ] ); } if ( $this->is_filter_active() && $this->get_explanation() !== null ) { - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_explanation_assets' ) ); + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_explanation_assets' ] ); } } @@ -66,7 +71,7 @@ abstract class WPSEO_Abstract_Post_Filter implements WPSEO_WordPress_Integration */ public function add_filter_links() { foreach ( $this->get_post_types() as $post_type ) { - add_filter( 'views_edit-' . $post_type, array( $this, 'add_filter_link' ) ); + add_filter( 'views_edit-' . $post_type, [ $this, 'add_filter_link' ] ); } } @@ -79,10 +84,10 @@ abstract class WPSEO_Abstract_Post_Filter implements WPSEO_WordPress_Integration $asset_manager = new WPSEO_Admin_Asset_Manager(); $asset_manager->enqueue_script( 'filter-explanation' ); $asset_manager->enqueue_style( 'filter-explanation' ); - wp_localize_script( - WPSEO_Admin_Asset_Manager::PREFIX . 'filter-explanation', + $asset_manager->localize_script( + 'filter-explanation', 'yoastFilterExplanation', - array( 'text' => $this->get_explanation() ) + [ 'text' => $this->get_explanation() ] ); } @@ -129,10 +134,12 @@ abstract class WPSEO_Abstract_Post_Filter implements WPSEO_WordPress_Integration * @return string The url to activate this filter. */ protected function get_filter_url() { - return add_query_arg( array( + $query_args = [ self::FILTER_QUERY_ARG => $this->get_query_val(), 'post_type' => $this->get_current_post_type(), - ), 'edit.php' ); + ]; + + return add_query_arg( $query_args, 'edit.php' ); } /** @@ -151,11 +158,11 @@ abstract class WPSEO_Abstract_Post_Filter implements WPSEO_WordPress_Integration * @return string The current post type. */ protected function get_current_post_type() { - return filter_input( - INPUT_GET, 'post_type', FILTER_DEFAULT, array( - 'options' => array( 'default' => 'post' ), - ) - ); + $filter_options = [ + 'options' => [ 'default' => 'post' ], + ]; + + return filter_input( INPUT_GET, 'post_type', FILTER_DEFAULT, $filter_options ); } /** diff --git a/wp-content/plugins/wordpress-seo/admin/filters/class-cornerstone-filter.php b/wp-content/plugins/wordpress-seo/admin/filters/class-cornerstone-filter.php index 26102339..69e6cda4 100644 --- a/wp-content/plugins/wordpress-seo/admin/filters/class-cornerstone-filter.php +++ b/wp-content/plugins/wordpress-seo/admin/filters/class-cornerstone-filter.php @@ -10,17 +10,36 @@ */ class WPSEO_Cornerstone_Filter extends WPSEO_Abstract_Post_Filter { + /** + * Name of the meta value. + * + * @var string + */ + const META_NAME = 'is_cornerstone'; + + /** + * Registers the hooks. + * + * @return void + */ + public function register_hooks() { + parent::register_hooks(); + + add_filter( 'wpseo_cornerstone_post_types', [ 'WPSEO_Post_Type', 'filter_attachment_post_type' ] ); + add_filter( 'wpseo_cornerstone_post_types', [ $this, 'filter_metabox_disabled' ] ); + } + /** * Returns the query value this filter uses. * - * @return {string} The query value this filter uses. + * @return string The query value this filter uses. */ public function get_query_val() { return 'cornerstone'; } /** - * Modify the query based on the seo_filter variable in $_GET + * Modify the query based on the seo_filter variable in $_GET. * * @param string $where Query variables. * @@ -30,15 +49,35 @@ class WPSEO_Cornerstone_Filter extends WPSEO_Abstract_Post_Filter { if ( $this->is_filter_active() ) { global $wpdb; - $where .= sprintf( - ' AND ' . $wpdb->posts . '.ID IN( SELECT post_id FROM ' . $wpdb->postmeta . ' WHERE meta_key = "%s" AND meta_value = "1" ) ', - WPSEO_Cornerstone::META_NAME + $where .= $wpdb->prepare( + " AND {$wpdb->posts}.ID IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = '1' ) ", + WPSEO_Meta::$meta_prefix . self::META_NAME ); } return $where; } + /** + * Filters the post types that have the metabox disabled. + * + * @param array $post_types The post types to filter. + * + * @return array The filtered post types. + */ + public function filter_metabox_disabled( $post_types ) { + $filtered_post_types = []; + foreach ( $post_types as $post_type_key => $post_type ) { + if ( ! WPSEO_Post_Type::has_metabox_enabled( $post_type_key ) ) { + continue; + } + + $filtered_post_types[ $post_type_key ] = $post_type; + } + + return $filtered_post_types; + } + /** * Returns the label for this filter. * @@ -51,7 +90,7 @@ class WPSEO_Cornerstone_Filter extends WPSEO_Abstract_Post_Filter { /** * Returns a text explaining this filter. * - * @return string The explanation. + * @return string|null The explanation. */ protected function get_explanation() { $post_type_object = get_post_type_object( $this->get_current_post_type() ); @@ -72,20 +111,20 @@ class WPSEO_Cornerstone_Filter extends WPSEO_Abstract_Post_Filter { /** * Returns the total amount of articles marked as cornerstone content. * - * @return integer + * @return int */ protected function get_post_total() { global $wpdb; return (int) $wpdb->get_var( - $wpdb->prepare( ' - SELECT COUNT( 1 ) - FROM ' . $wpdb->postmeta . ' - WHERE post_id IN( SELECT ID FROM ' . $wpdb->posts . ' WHERE post_type = %s ) && - meta_value = "1" AND meta_key = %s - ', + $wpdb->prepare( + "SELECT COUNT( 1 ) + FROM {$wpdb->postmeta} + WHERE post_id IN( SELECT ID FROM {$wpdb->posts} WHERE post_type = %s ) AND + meta_key = %s AND meta_value = '1' + ", $this->get_current_post_type(), - WPSEO_Cornerstone::META_NAME + WPSEO_Meta::$meta_prefix . self::META_NAME ) ); } @@ -96,9 +135,14 @@ class WPSEO_Cornerstone_Filter extends WPSEO_Abstract_Post_Filter { * @return array The post types to which this filter should be added. */ protected function get_post_types() { + /** + * Filter: 'wpseo_cornerstone_post_types' - Filters post types to exclude the cornerstone feature for. + * + * @api array - The accessible post types to filter. + */ $post_types = apply_filters( 'wpseo_cornerstone_post_types', parent::get_post_types() ); if ( ! is_array( $post_types ) ) { - return array(); + return []; } return $post_types; diff --git a/wp-content/plugins/wordpress-seo/admin/formatter/class-metabox-formatter.php b/wp-content/plugins/wordpress-seo/admin/formatter/class-metabox-formatter.php index de43d690..8b50275d 100644 --- a/wp-content/plugins/wordpress-seo/admin/formatter/class-metabox-formatter.php +++ b/wp-content/plugins/wordpress-seo/admin/formatter/class-metabox-formatter.php @@ -5,13 +5,21 @@ * @package WPSEO\Admin\Formatter */ +use Yoast\WP\SEO\Config\Schema_Types; +use Yoast\WP\SEO\Config\SEMrush_Client; +use Yoast\WP\SEO\Exceptions\OAuth\Authentication_Failed_Exception; +use Yoast\WP\SEO\Exceptions\SEMrush\Tokens\Empty_Property_Exception; +use Yoast\WP\SEO\Exceptions\SEMrush\Tokens\Empty_Token_Exception; + /** - * This class forces needed methods for the metabox localization + * This class forces needed methods for the metabox localization. */ class WPSEO_Metabox_Formatter { /** - * @var WPSEO_Metabox_Formatter_Interface Object that provides formatted values. + * Object that provides formatted values. + * + * @var WPSEO_Metabox_Formatter_Interface */ private $formatter; @@ -25,7 +33,7 @@ class WPSEO_Metabox_Formatter { } /** - * Returns the values + * Returns the values. * * @return array */ @@ -37,113 +45,135 @@ class WPSEO_Metabox_Formatter { } /** - * Returns array with all the values always needed by a scraper object + * Returns array with all the values always needed by a scraper object. * * @return array Default settings for the metabox. */ private function get_defaults() { $analysis_seo = new WPSEO_Metabox_Analysis_SEO(); $analysis_readability = new WPSEO_Metabox_Analysis_Readability(); + $schema_types = new Schema_Types(); - return array( - 'language' => WPSEO_Language_Utils::get_site_language_name(), - 'settings_link' => $this->get_settings_link(), - 'search_url' => '', - 'post_edit_url' => '', - 'base_url' => '', - 'contentTab' => __( 'Readability', 'wordpress-seo' ), - 'keywordTab' => __( 'Keyword:', 'wordpress-seo' ), - 'enterFocusKeyword' => __( 'Enter your focus keyword', 'wordpress-seo' ), - 'removeKeyword' => __( 'Remove keyword', 'wordpress-seo' ), - 'contentLocale' => get_locale(), - 'userLocale' => WPSEO_Utils::get_user_locale(), - 'translations' => $this->get_translations(), - 'keyword_usage' => array(), - 'title_template' => '', - 'metadesc_template' => '', - 'contentAnalysisActive' => $analysis_readability->is_enabled() ? 1 : 0, - 'keywordAnalysisActive' => $analysis_seo->is_enabled() ? 1 : 0, - 'intl' => $this->get_content_analysis_component_translations(), - 'reactSnippetPreview' => defined( 'YOAST_FEATURE_SNIPPET_PREVIEW' ) && YOAST_FEATURE_SNIPPET_PREVIEW, + return [ + 'author_name' => get_the_author_meta( 'display_name' ), + 'site_name' => get_bloginfo( 'name' ), + 'sitewide_social_image' => WPSEO_Options::get( 'og_default_image' ), + 'search_url' => '', + 'post_edit_url' => '', + 'base_url' => '', + 'contentTab' => __( 'Readability', 'wordpress-seo' ), + 'keywordTab' => __( 'Keyphrase:', 'wordpress-seo' ), + 'removeKeyword' => __( 'Remove keyphrase', 'wordpress-seo' ), + 'contentLocale' => get_locale(), + 'userLocale' => \get_user_locale(), + 'translations' => $this->get_translations(), + 'keyword_usage' => [], + 'title_template' => '', + 'metadesc_template' => '', + 'contentAnalysisActive' => $analysis_readability->is_enabled() ? 1 : 0, + 'keywordAnalysisActive' => $analysis_seo->is_enabled() ? 1 : 0, + 'cornerstoneActive' => WPSEO_Options::get( 'enable_cornerstone_content', false ) ? 1 : 0, + 'semrushIntegrationActive' => WPSEO_Options::get( 'semrush_integration_active', true ) ? 1 : 0, + 'intl' => $this->get_content_analysis_component_translations(), + 'isRtl' => is_rtl(), + 'isPremium' => YoastSEO()->helpers->product->is_premium(), + 'wordFormRecognitionActive' => YoastSEO()->helpers->language->is_word_form_recognition_active( WPSEO_Language_Utils::get_language( get_locale() ) ), + 'siteIconUrl' => get_site_icon_url(), + 'countryCode' => WPSEO_Options::get( 'semrush_country_code', false ), + 'SEMrushLoginStatus' => WPSEO_Options::get( 'semrush_integration_active', true ) ? $this->get_semrush_login_status() : false, + 'showSocial' => [ + 'facebook' => WPSEO_Options::get( 'opengraph', false ), + 'twitter' => WPSEO_Options::get( 'twitter', false ), + ], + 'schema' => [ + 'displayFooter' => WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ), + 'pageTypeOptions' => $schema_types->get_page_type_options(), + 'articleTypeOptions' => $schema_types->get_article_type_options(), + ], + 'twitterCardType' => YoastSEO()->helpers->options->get( 'twitter_card_type' ), /** * Filter to determine if the markers should be enabled or not. * * @param bool $showMarkers Should the markers being enabled. Default = true. */ - 'show_markers' => apply_filters( 'wpseo_enable_assessment_markers', true ), - 'publish_box' => array( - 'labels' => array( - 'content' => array( + 'show_markers' => apply_filters( 'wpseo_enable_assessment_markers', true ), + 'publish_box' => [ + 'labels' => [ + 'content' => [ 'na' => sprintf( - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag. */ - __( 'Readability: %1$sNot available%2$s', 'wordpress-seo' ), - '', - '' + /* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */ + __( '%1$sReadability%2$s: %3$s', 'wordpress-seo' ), + '', + '', + '' . __( 'Not available', 'wordpress-seo' ) . '' ), 'bad' => sprintf( - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag. */ - __( 'Readability: %1$sNeeds improvement%2$s', 'wordpress-seo' ), - '', - '' + /* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */ + __( '%1$sReadability%2$s: %3$s', 'wordpress-seo' ), + '', + '', + '' . __( 'Needs improvement', 'wordpress-seo' ) . '' ), 'ok' => sprintf( - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag. */ - __( 'Readability: %1$sOK%2$s', 'wordpress-seo' ), - '', - '' + /* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */ + __( '%1$sReadability%2$s: %3$s', 'wordpress-seo' ), + '', + '', + '' . __( 'OK', 'wordpress-seo' ) . '' ), 'good' => sprintf( - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag. */ - __( 'Readability: %1$sGood%2$s', 'wordpress-seo' ), - '', - '' + /* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the readability score. */ + __( '%1$sReadability%2$s: %3$s', 'wordpress-seo' ), + '', + '', + '' . __( 'Good', 'wordpress-seo' ) . '' ), - ), - 'keyword' => array( + ], + 'keyword' => [ 'na' => sprintf( - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag. */ - __( 'SEO: %1$sNot available%2$s', 'wordpress-seo' ), - '', - '' + /* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */ + __( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ), + '', + '', + '' . __( 'Not available', 'wordpress-seo' ) . '' ), 'bad' => sprintf( - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag. */ - __( 'SEO: %1$sNeeds improvement%2$s', 'wordpress-seo' ), - '', - '' + /* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */ + __( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ), + '', + '', + '' . __( 'Needs improvement', 'wordpress-seo' ) . '' ), 'ok' => sprintf( - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag. */ - __( 'SEO: %1$sOK%2$s', 'wordpress-seo' ), - '', - '' + /* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */ + __( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ), + '', + '', + '' . __( 'OK', 'wordpress-seo' ) . '' ), 'good' => sprintf( - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag. */ - __( 'SEO: %1$sGood%2$s', 'wordpress-seo' ), - '', - '' + /* translators: %1$s expands to the opening anchor tag, %2$s to the closing anchor tag, %3$s to the SEO score. */ + __( '%1$sSEO%2$s: %3$s', 'wordpress-seo' ), + '', + '', + '' . __( 'Good', 'wordpress-seo' ) . '' ), - ), - ), - ), - 'markdownEnabled' => $this->is_markdown_enabled(), - ); - } + ], + ], + ], + 'markdownEnabled' => $this->is_markdown_enabled(), + 'analysisHeadingTitle' => __( 'Analysis', 'wordpress-seo' ), + 'zapierIntegrationActive' => WPSEO_Options::get( 'zapier_integration_active', false ) ? 1 : 0, + 'zapierConnectedStatus' => ! empty( WPSEO_Options::get( 'zapier_subscription', [] ) ) ? 1 : 0, - /** - * Returns a link to the settings page, if the user has the right capabilities. - * Returns an empty string otherwise. - * - * @return string The settings link. - */ - private function get_settings_link() { - if ( current_user_can( 'manage_options' ) ) { - return admin_url( 'options-general.php' ); - } - - return ''; + /** + * Filter to determine whether the PreviouslyUsedKeyword assessment should run. + * + * @param bool $previouslyUsedKeywordActive Whether the PreviouslyUsedKeyword assessment should run. + */ + 'previouslyUsedKeywordActive' => apply_filters( 'wpseo_previously_used_keyword_active', true ), + ]; } /** @@ -153,21 +183,18 @@ class WPSEO_Metabox_Formatter { */ private function get_content_analysis_component_translations() { // Esc_html is not needed because React already handles HTML in the (translations of) these strings. - return array( - 'locale' => WPSEO_Utils::get_user_locale(), - 'content-analysis.language-notice-link' => __( 'Change language', 'wordpress-seo' ), - 'content-analysis.errors' => __( 'Errors', 'wordpress-seo' ), - 'content-analysis.problems' => __( 'Problems', 'wordpress-seo' ), - 'content-analysis.improvements' => __( 'Improvements', 'wordpress-seo' ), - 'content-analysis.considerations' => __( 'Considerations', 'wordpress-seo' ), - 'content-analysis.good' => __( 'Good results', 'wordpress-seo' ), - 'content-analysis.language-notice' => __( 'Your site language is set to {language}.', 'wordpress-seo' ), - 'content-analysis.language-notice-contact-admin' => __( 'Your site language is set to {language}. If this is not correct, contact your site administrator.', 'wordpress-seo' ), - 'content-analysis.highlight' => __( 'Highlight this result in the text', 'wordpress-seo' ), - 'content-analysis.nohighlight' => __( 'Remove highlight from the text', 'wordpress-seo' ), - 'content-analysis.disabledButton' => __( 'Marks are disabled in current view', 'wordpress-seo' ), - 'a11yNotice.opensInNewTab' => __( '(Opens in a new browser tab)', 'wordpress-seo' ), - ); + return [ + 'locale' => \get_user_locale(), + 'content-analysis.errors' => __( 'Errors', 'wordpress-seo' ), + 'content-analysis.problems' => __( 'Problems', 'wordpress-seo' ), + 'content-analysis.improvements' => __( 'Improvements', 'wordpress-seo' ), + 'content-analysis.considerations' => __( 'Considerations', 'wordpress-seo' ), + 'content-analysis.good' => __( 'Good results', 'wordpress-seo' ), + 'content-analysis.highlight' => __( 'Highlight this result in the text', 'wordpress-seo' ), + 'content-analysis.nohighlight' => __( 'Remove highlight from the text', 'wordpress-seo' ), + 'content-analysis.disabledButton' => __( 'Marks are disabled in current view', 'wordpress-seo' ), + 'a11yNotice.opensInNewTab' => __( '(Opens in a new browser tab)', 'wordpress-seo' ), + ]; } /** @@ -176,32 +203,108 @@ class WPSEO_Metabox_Formatter { * @return array */ private function get_translations() { - $locale = WPSEO_Utils::get_user_locale(); + $locale = \get_user_locale(); - $file = plugin_dir_path( WPSEO_FILE ) . 'languages/wordpress-seo-' . $locale . '.json'; + $file = WPSEO_PATH . 'languages/wordpress-seo-' . $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 []; } /** * Checks if Jetpack's markdown module is enabled. * Can be extended to work with other plugins that parse markdown in the content. * - * @return boolean + * @return bool */ private function is_markdown_enabled() { + $is_markdown = false; + if ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'get_active_modules' ) ) { $active_modules = Jetpack::get_active_modules(); - return in_array( 'markdown', $active_modules, true ); + // First at all, check if Jetpack's markdown module is active. + $is_markdown = in_array( 'markdown', $active_modules, true ); } - return false; + /** + * Filters whether markdown support is active in the readability- and seo-analysis. + * + * @since 11.3 + * + * @param array $is_markdown Is markdown support for Yoast SEO active. + */ + return apply_filters( 'wpseo_is_markdown_enabled', $is_markdown ); + } + + /** + * Checks if the user is logged in to SEMrush. + * + * @return bool The SEMrush login status. + */ + private function get_semrush_login_status() { + try { + $semrush_client = YoastSEO()->classes->get( SEMrush_Client::class ); + } catch ( Empty_Property_Exception $e ) { + // Return false if token is malformed (empty property). + return false; + } + + // Get token (and refresh it if it's expired). + try { + $semrush_client->get_tokens(); + } catch ( Authentication_Failed_Exception $e ) { + return false; + } catch ( Empty_Token_Exception $e ) { + return false; + } + + return $semrush_client->has_valid_tokens(); + } + + /* ********************* DEPRECATED METHODS ********************* */ + + /** + * Returns the translations for the Add Keyword modal. + * + * These strings are not escaped because they're meant to be used with React + * which already takes care of that. If used in PHP, they should be escaped. + * + * @deprecated 15.5 + * @codeCoverageIgnore + * + * @return array Translated text strings for the Add Keyword modal. + */ + public function get_add_keyword_upsell_translations() { + _deprecated_function( __METHOD__, 'WPSEO 15.5' ); + + return [ + 'title' => __( 'Would you like to add more than one keyphrase?', 'wordpress-seo' ), + 'intro' => sprintf( + /* translators: %s expands to a 'Yoast SEO Premium' text linked to the yoast.com website. */ + __( 'Great news: you can, with %s!', 'wordpress-seo' ), + '{{link}}Yoast SEO Premium{{/link}}' + ), + 'link' => WPSEO_Shortlinker::get( 'https://yoa.st/pe-premium-page' ), + 'other' => sprintf( + /* translators: %s expands to 'Yoast SEO Premium'. */ + __( 'Other benefits of %s for you:', 'wordpress-seo' ), + 'Yoast SEO Premium' + ), + 'buylink' => WPSEO_Shortlinker::get( 'https://yoa.st/add-keywords-popup' ), + 'buy' => sprintf( + /* translators: %s expands to 'Yoast SEO Premium'. */ + __( 'Get %s', 'wordpress-seo' ), + 'Yoast SEO Premium' + ), + 'small' => __( '1 year free support and updates included!', 'wordpress-seo' ), + 'a11yNotice.opensInNewTab' => __( '(Opens in a new browser tab)', 'wordpress-seo' ), + ]; } } diff --git a/wp-content/plugins/wordpress-seo/admin/formatter/class-post-metabox-formatter.php b/wp-content/plugins/wordpress-seo/admin/formatter/class-post-metabox-formatter.php index e373be87..ddaf0c02 100644 --- a/wp-content/plugins/wordpress-seo/admin/formatter/class-post-metabox-formatter.php +++ b/wp-content/plugins/wordpress-seo/admin/formatter/class-post-metabox-formatter.php @@ -6,20 +6,31 @@ */ /** - * This class provides data for the post metabox by return its values for localization + * This class provides data for the post metabox by return its values for localization. */ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface { /** + * Holds the WordPress Post. + * * @var WP_Post */ private $post; /** - * @var string The permalink to follow. + * The permalink to follow. + * + * @var string */ private $permalink; + /** + * Whether we must return social templates values. + * + * @var bool + */ + private $use_social_templates = false; + /** * Constructor. * @@ -30,6 +41,20 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface public function __construct( $post, array $options, $structure ) { $this->post = $post; $this->permalink = $structure; + + $this->use_social_templates = $this->use_social_templates(); + } + + /** + * Determines whether the social templates should be used. + * + * @return bool Whether the social templates should be used. + */ + public function use_social_templates() { + return YoastSEO()->helpers->product->is_premium() + && defined( 'WPSEO_PREMIUM_VERSION' ) + && version_compare( WPSEO_PREMIUM_VERSION, '16.5-RC0', '>=' ) + && WPSEO_Options::get( 'opengraph', false ) === true; } /** @@ -38,20 +63,26 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface * @return array */ public function get_values() { - $values = array( + $values = [ 'search_url' => $this->search_url(), 'post_edit_url' => $this->edit_url(), 'base_url' => $this->base_url_for_js(), 'metaDescriptionDate' => '', - ); + + ]; if ( $this->post instanceof WP_Post ) { - $values_to_set = array( - 'keyword_usage' => $this->get_focus_keyword_usage(), - 'title_template' => $this->get_title_template(), - 'metadesc_template' => $this->get_metadesc_template(), - 'metaDescriptionDate' => $this->get_metadesc_date(), - ); + $values_to_set = [ + 'keyword_usage' => $this->get_focus_keyword_usage(), + 'title_template' => $this->get_title_template(), + 'title_template_no_fallback' => $this->get_title_template( false ), + 'metadesc_template' => $this->get_metadesc_template(), + 'metaDescriptionDate' => $this->get_metadesc_date(), + 'first_content_image' => $this->get_image_url(), + 'social_title_template' => $this->get_social_title_template(), + 'social_description_template' => $this->get_social_description_template(), + 'social_image_template' => $this->get_social_image_template(), + ]; $values = ( $values_to_set + $values ); } @@ -60,7 +91,16 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface } /** - * Returns the url to search for keyword for the post + * Gets the image URL for the post's social preview. + * + * @return string|null The image URL for the social preview. + */ + protected function get_image_url() { + return WPSEO_Image_Utils::get_first_usable_content_image_for_post( $this->post->ID ); + } + + /** + * Returns the url to search for keyword for the post. * * @return string */ @@ -69,7 +109,7 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface } /** - * Returns the url to edit the taxonomy + * Returns the url to edit the taxonomy. * * @return string */ @@ -78,7 +118,7 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface } /** - * Returns a base URL for use in the JS, takes permalink structure into account + * Returns a base URL for use in the JS, takes permalink structure into account. * * @return string */ @@ -88,12 +128,12 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface // The default base is the home_url. $base_url = home_url( '/', null ); - if ( 'post-new.php' === $pagenow ) { + if ( $pagenow === 'post-new.php' ) { return $base_url; } // If %postname% is the last tag, just strip it and use that as a base. - if ( 1 === preg_match( '#%postname%/?$#', $this->permalink ) ) { + if ( preg_match( '#%postname%/?$#', $this->permalink ) === 1 ) { $base_url = preg_replace( '#%postname%/?$#', '', $this->permalink ); } @@ -107,9 +147,9 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface */ private function get_focus_keyword_usage() { $keyword = WPSEO_Meta::get_value( 'focuskw', $this->post->ID ); - $usage = array( $keyword => $this->get_keyword_usage_for_current_post( $keyword ) ); + $usage = [ $keyword => $this->get_keyword_usage_for_current_post( $keyword ) ]; - if ( WPSEO_Utils::is_yoast_seo_premium() ) { + if ( YoastSEO()->helpers->product->is_premium() ) { return $this->get_premium_keywords( $usage ); } @@ -153,25 +193,72 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface /** * Retrieves the title template. * - * @return string + * @param bool $fallback Whether to return the hardcoded fallback if the template value is empty. + * + * @return string The title template. */ - private function get_title_template() { - return $this->get_template( 'title' ); + private function get_title_template( $fallback = true ) { + $title = $this->get_template( 'title' ); + + if ( $title === '' && $fallback === true ) { + return '%%title%% %%page%% %%sep%% %%sitename%%'; + } + + return $title; } /** * Retrieves the metadesc template. * - * @return string + * @return string The metadesc template. */ private function get_metadesc_template() { return $this->get_template( 'metadesc' ); } + /** + * Retrieves the social title template. + * + * @return string The social title template. + */ + private function get_social_title_template() { + if ( $this->use_social_templates ) { + return $this->get_template( 'social-title' ); + } + + return ''; + } + + /** + * Retrieves the social description template. + * + * @return string The social description template. + */ + private function get_social_description_template() { + if ( $this->use_social_templates ) { + return $this->get_template( 'social-description' ); + } + + return ''; + } + + /** + * Retrieves the social image template. + * + * @return string The social description template. + */ + private function get_social_image_template() { + if ( $this->use_social_templates ) { + return $this->get_template( 'social-image-url' ); + } + + return ''; + } + /** * Retrieves a template. * - * @param String $template_option_name The name of the option in which the template you want to get is saved. + * @param string $template_option_name The name of the option in which the template you want to get is saved. * * @return string */ @@ -186,28 +273,11 @@ class WPSEO_Post_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface } /** - * Determines the date to be displayed in the snippet preview + * Determines the date to be displayed in the snippet preview. * * @return string */ private function get_metadesc_date() { - $date = ''; - - if ( $this->is_show_date_enabled() ) { - $date = date_i18n( 'M j, Y', mysql2date( 'U', $this->post->post_date ) ); - } - - return $date; - } - - /** - * Returns whether or not showing the date in the snippet preview is enabled. - * - * @return bool - */ - private function is_show_date_enabled() { - $key = sprintf( 'showdate-%s', $this->post->post_type ); - - return WPSEO_Options::get( $key, true ); + return YoastSEO()->helpers->date->format_translated( $this->post->post_date, 'M j, Y' ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/formatter/class-term-metabox-formatter.php b/wp-content/plugins/wordpress-seo/admin/formatter/class-term-metabox-formatter.php index 704aab37..7f95519b 100644 --- a/wp-content/plugins/wordpress-seo/admin/formatter/class-term-metabox-formatter.php +++ b/wp-content/plugins/wordpress-seo/admin/formatter/class-term-metabox-formatter.php @@ -6,22 +6,35 @@ */ /** - * This class provides data for the term metabox by return its values for localization + * This class provides data for the term metabox by return its values for localization. */ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface { /** + * The term the metabox formatter is for. + * * @var WP_Term|stdClass */ private $term; /** + * The term's taxonomy. + * * @var stdClass */ private $taxonomy; /** - * @var array Array with the WPSEO_Titles options. + * Whether we must return social templates values. + * + * @var bool + */ + private $use_social_templates = false; + + /** + * Array with the WPSEO_Titles options. + * + * @var array */ protected $options; @@ -32,8 +45,22 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface * @param WP_Term|stdClass $term Term. */ public function __construct( $taxonomy, $term ) { - $this->term = $term; $this->taxonomy = $taxonomy; + $this->term = $term; + + $this->use_social_templates = $this->use_social_templates(); + } + + /** + * Determines whether the social templates should be used. + * + * @return bool Whether the social templates should be used. + */ + public function use_social_templates() { + return YoastSEO()->helpers->product->is_premium() + && defined( 'WPSEO_PREMIUM_VERSION' ) + && version_compare( WPSEO_PREMIUM_VERSION, '16.5-RC0', '>=' ) + && WPSEO_Options::get( 'opengraph', false ) === true; } /** @@ -42,26 +69,41 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface * @return array */ public function get_values() { - $values = array(); + $values = []; - // Todo: a column needs to be added on the termpages to add a filter for the keyword, so this can be used in the focus kw doubles. + // Todo: a column needs to be added on the termpages to add a filter for the keyword, so this can be used in the focus keyphrase doubles. if ( is_object( $this->term ) && property_exists( $this->term, 'taxonomy' ) ) { - $values = array( - 'search_url' => $this->search_url(), - 'post_edit_url' => $this->edit_url(), - 'base_url' => $this->base_url_for_js(), - 'taxonomy' => $this->term->taxonomy, - 'keyword_usage' => $this->get_focus_keyword_usage(), - 'title_template' => $this->get_title_template(), - 'metadesc_template' => $this->get_metadesc_template(), - ); + $values = [ + 'search_url' => $this->search_url(), + 'post_edit_url' => $this->edit_url(), + 'base_url' => $this->base_url_for_js(), + 'taxonomy' => $this->term->taxonomy, + 'keyword_usage' => $this->get_focus_keyword_usage(), + 'title_template' => $this->get_title_template(), + 'title_template_no_fallback' => $this->get_title_template( false ), + 'metadesc_template' => $this->get_metadesc_template(), + 'first_content_image' => $this->get_image_url(), + 'semrushIntegrationActive' => 0, + 'social_title_template' => $this->get_social_title_template(), + 'social_description_template' => $this->get_social_description_template(), + 'social_image_template' => $this->get_social_image_template(), + ]; } return $values; } /** - * Returns the url to search for keyword for the taxonomy + * Gets the image URL for the term's social preview. + * + * @return string|null The image URL for the social preview. + */ + protected function get_image_url() { + return WPSEO_Image_Utils::get_first_content_image_for_term( $this->term->term_id ); + } + + /** + * Returns the url to search for keyword for the taxonomy. * * @return string */ @@ -70,7 +112,7 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface } /** - * Returns the url to edit the taxonomy + * Returns the url to edit the taxonomy. * * @return string */ @@ -81,7 +123,7 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface } /** - * Returns a base URL for use in the JS, takes permalink structure into account + * Returns a base URL for use in the JS, takes permalink structure into account. * * @return string */ @@ -96,7 +138,7 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface } /** - * Counting the number of given keyword used for other term than given term_id + * Counting the number of given keyword used for other term than given term_id. * * @return array */ @@ -109,25 +151,74 @@ class WPSEO_Term_Metabox_Formatter implements WPSEO_Metabox_Formatter_Interface /** * Retrieves the title template. * - * @return string + * @param bool $fallback Whether to return the hardcoded fallback if the template value is empty. + * + * @return string The title template. */ - private function get_title_template() { - return $this->get_template( 'title' ); + private function get_title_template( $fallback = true ) { + $title = $this->get_template( 'title' ); + + if ( $title === '' && $fallback === true ) { + /* translators: %s expands to the variable used for term title. */ + $archives = sprintf( __( '%s Archives', 'wordpress-seo' ), '%%term_title%%' ); + return $archives . ' %%page%% %%sep%% %%sitename%%'; + } + + return $title; } /** * Retrieves the metadesc template. * - * @return string + * @return string The metadesc template. */ private function get_metadesc_template() { return $this->get_template( 'metadesc' ); } + /** + * Retrieves the social title template. + * + * @return string The social title template. + */ + private function get_social_title_template() { + if ( $this->use_social_templates ) { + return $this->get_template( 'social-title' ); + } + + return ''; + } + + /** + * Retrieves the social description template. + * + * @return string The social description template. + */ + private function get_social_description_template() { + if ( $this->use_social_templates ) { + return $this->get_template( 'social-description' ); + } + + return ''; + } + + /** + * Retrieves the social image template. + * + * @return string The social description template. + */ + private function get_social_image_template() { + if ( $this->use_social_templates ) { + return $this->get_template( 'social-image-url' ); + } + + return ''; + } + /** * Retrieves a template. * - * @param String $template_option_name The name of the option in which the template you want to get is saved. + * @param string $template_option_name The name of the option in which the template you want to get is saved. * * @return string */ diff --git a/wp-content/plugins/wordpress-seo/admin/formatter/interface-metabox-formatter.php b/wp-content/plugins/wordpress-seo/admin/formatter/interface-metabox-formatter.php index 12d89d18..8c220480 100644 --- a/wp-content/plugins/wordpress-seo/admin/formatter/interface-metabox-formatter.php +++ b/wp-content/plugins/wordpress-seo/admin/formatter/interface-metabox-formatter.php @@ -6,7 +6,7 @@ */ /** - * Interface to force get_values + * Interface to force get_values. */ interface WPSEO_Metabox_Formatter_Interface { @@ -16,5 +16,4 @@ interface WPSEO_Metabox_Formatter_Interface { * @return array */ public function get_values(); - } diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-ajax.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-ajax.php deleted file mode 100644 index 86037ab6..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-ajax.php +++ /dev/null @@ -1,110 +0,0 @@ -valid_nonce() ) { - $marker = new WPSEO_GSC_Marker( filter_input( INPUT_POST, 'url' ) ); - - wp_die( $marker->get_response() ); - } - - wp_die( 'false' ); - } - - /** - * Handle the AJAX request and dismiss the GSC notice - */ - public function dismiss_notice() { - check_ajax_referer( 'dismiss-gsc-notice' ); - - update_user_meta( get_current_user_id(), 'wpseo_dismissed_gsc_notice', true ); - - wp_die( 'true' ); - } - - /** - * Saves the authorization code. - */ - public function save_auth_code() { - if ( ! $this->valid_nonce() ) { - wp_die( '0' ); - } - - // Validate the authorization. - $service = $this->get_service(); - $authorization_code = filter_input( INPUT_POST, 'authorization' ); - $is_authorization_valid = WPSEO_GSC_Settings::validate_authorization( $authorization_code, $service->get_client() ); - if ( ! $is_authorization_valid ) { - wp_die( '0' ); - } - - $this->get_profiles(); - } - - /** - * Clears all authorization data. - */ - public function clear_auth_code() { - if ( ! $this->valid_nonce() ) { - wp_die( '0' ); - } - - $service = $this->get_service(); - - WPSEO_GSC_Settings::clear_data( $service ); - - $this->get_profiles(); - } - - /** - * Check if posted nonce is valid and return true if it is - * - * @return mixed - */ - private function valid_nonce() { - return wp_verify_nonce( filter_input( INPUT_POST, 'ajax_nonce' ), 'wpseo-gsc-ajax-security' ); - } - - /** - * Returns an instance of the Google Search Console service. - * - * @return WPSEO_GSC_Service - */ - private function get_service() { - return new WPSEO_GSC_Service(); - } - - /** - * Prints a JSON encoded string with the current profile config. - */ - private function get_profiles() { - $component = new WPSEO_Config_Component_Connect_Google_Search_Console(); - - wp_die( wp_json_encode( $component->get_data() ) ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-bulk-action.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-bulk-action.php deleted file mode 100644 index 2962537d..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-bulk-action.php +++ /dev/null @@ -1,98 +0,0 @@ -handle_bulk_action(); - } - } - - /** - * Handles the bulk action when there is an action posted - */ - private function handle_bulk_action() { - $bulk_action = $this->determine_bulk_action(); - if ( $bulk_action !== false ) { - $this->run_bulk_action( $bulk_action, $this->posted_issues() ); - - wp_redirect( filter_input( INPUT_POST, '_wp_http_referer' ) ); - exit; - } - } - - /** - * Determine which bulk action is selected and return that value - * - * @return string|bool - */ - private function determine_bulk_action() { - $action_inputs = array( - 'action', // Bulk action select above the table. - 'action2', // Bulk action select below the table. - ); - - foreach ( $action_inputs as $action_name ) { - $action = filter_input( INPUT_POST, $action_name ); - if ( ! empty( $action ) && $action !== '-1' ) { - return $action; - } - } - - return false; - } - - /** - * Get the posted issues and return them - * - * @return array - */ - private function posted_issues() { - $issues = filter_input( INPUT_POST, 'wpseo_crawl_issues', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ); - if ( ! empty( $issues ) ) { - return $issues; - } - - // Fallback if issues are empty. - return array(); - } - - /** - * Runs the bulk action - * - * @param string $bulk_action Action type. - * @param array $issues Set of issues to apply to. - */ - private function run_bulk_action( $bulk_action, $issues ) { - switch ( $bulk_action ) { - case 'mark_as_fixed': - array_map( array( $this, 'action_mark_as_fixed' ), $issues ); - - break; - } - } - - /** - * Marks the issue as fixed - * - * @param string $issue Issue URL. - * - * @return string - */ - private function action_mark_as_fixed( $issue ) { - new WPSEO_GSC_Marker( $issue ); - - return $issue; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-category-filters.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-category-filters.php deleted file mode 100644 index 178556d8..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-category-filters.php +++ /dev/null @@ -1,201 +0,0 @@ -set_counts( $platform_counts ); - } - - // Setting the filter values. - $this->set_filter_values(); - - $this->category = $this->get_current_category(); - } - - /** - * Returns the value of the current category - * - * @return mixed|string - */ - public function get_category() { - return $this->category; - } - - /** - * Returns the current filters as an array - * - * Only return categories with more than 0 issues - * - * @return array - */ - public function as_array() { - $new_views = array(); - - foreach ( $this->category_counts as $category_name => $category ) { - $new_views[] = $this->create_view_link( $category_name, $category['count'] ); - } - - return $new_views; - } - - /** - * Getting the current view - */ - private function get_current_category() { - $current_category = filter_input( INPUT_GET, 'category' ); - if ( ! empty( $current_category ) ) { - return $current_category; - } - - // Just prevent redirect loops. - if ( ! empty( $this->category_counts ) ) { - $current_category = 'not_found'; - if ( empty( $this->category_counts[ $current_category ] ) ) { - $current_category = key( $this->category_counts ); - } - - // Just redirect to set the category. - wp_redirect( add_query_arg( 'category', $current_category ) ); - exit; - } - } - - /** - * Setting the view counts based on the saved data. The info will be used to display the category filters - * - * @param array $platform_counts Set of counts by platform. - */ - private function set_counts( array $platform_counts ) { - $this->category_counts = $this->parse_counts( $platform_counts ); - } - - /** - * Setting the values for the filter - */ - private function set_filter_values() { - $this->set_filter_value( 'access_denied', __( 'Access denied', 'wordpress-seo' ), __( 'Server requires authentication or is blocking Googlebot from accessing the site.', 'wordpress-seo' ), __( 'Show information about errors in category \'Access Denied\'', 'wordpress-seo' ) ); - $this->set_filter_value( 'faulty_redirects', __( 'Faulty redirects', 'wordpress-seo' ) ); - $this->set_filter_value( 'not_followed', __( 'Not followed', 'wordpress-seo' ) ); - $this->set_filter_value( 'not_found', __( 'Not found', 'wordpress-seo' ), __( 'URL points to a non-existent page.', 'wordpress-seo' ), __( 'Show information about errors in category \'Not Found\'', 'wordpress-seo' ) ); - $this->set_filter_value( 'other', __( 'Other', 'wordpress-seo' ), __( 'Google was unable to crawl this URL due to an undetermined issue.', 'wordpress-seo' ), __( 'Show information about errors in category \'Other\'', 'wordpress-seo' ) ); - /* Translators: %1$s: expands to 'robots.txt'. */ - $this->set_filter_value( 'roboted', __( 'Blocked', 'wordpress-seo' ), sprintf( __( 'Googlebot could access your site, but certain URLs are blocked for Googlebot in your %1$s file. This block could either be for all Googlebots or even specifically for Googlebot-mobile.', 'wordpress-seo' ), 'robots.txt' ), __( 'Show information about errors in category \'Blocked\'', 'wordpress-seo' ) ); - $this->set_filter_value( 'server_error', __( 'Server Error', 'wordpress-seo' ), __( 'Request timed out or site is blocking Google.', 'wordpress-seo' ), __( 'Show information about errors in category \'Server\'', 'wordpress-seo' ) ); - $this->set_filter_value( 'soft_404', __( 'Soft 404', 'wordpress-seo' ), __( "The target URL doesn't exist, but your server is not returning a 404 (file not found) error.", 'wordpress-seo' ), __( 'Show information about errors in category \'Soft 404\'', 'wordpress-seo' ) ); - } - - /** - * Add new filter value to the filter_values - * - * @param string $key Filter key. - * @param string $value Filter value. - * @param string $description Optional description string. - * @param string $help_button_text Optional help button text. - */ - private function set_filter_value( $key, $value, $description = '', $help_button_text = '' ) { - $this->filter_values[ $key ] = array( - 'value' => $value, - 'description' => $description, - 'help-button' => $help_button_text, - ); - } - - /** - * Creates a filter link - * - * @param string $category Issue type. - * @param integer $count Count for the type. - * - * @return string - */ - private function create_view_link( $category, $count ) { - $href = add_query_arg( - array( - 'category' => $category, - 'paged' => 1, - ) - ); - - $class = 'gsc_category'; - - if ( $this->category === $category ) { - $class .= ' current'; - } - - $help_button = ''; - $help_panel = ''; - if ( $this->filter_values[ $category ]['description'] !== '' ) { - $help = new WPSEO_Admin_Help_Panel( $category, $this->filter_values[ $category ]['help-button'], $this->filter_values[ $category ]['description'], 'has-wrapper' ); - $help_button = $help->get_button_html(); - $help_panel = $help->get_panel_html(); - } - - return sprintf( - '%3$s (%5$s) %6$s %7$s', - esc_attr( $href ), - $class, - $this->filter_values[ $category ]['value'], - $category, - $count, - $help_button, - $help_panel - ); - } - - /** - * Parsing the category counts. When there are 0 issues for a specific category, just remove that one from the array - * - * @param array $category_counts Set of counts for categories. - * - * @return mixed - */ - private function parse_counts( $category_counts ) { - foreach ( $category_counts as $category_name => $category ) { - if ( $category['count'] === '0' ) { - unset( $category_counts[ $category_name ] ); - } - } - - return $category_counts; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-config.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-config.php deleted file mode 100644 index 78844c1b..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-config.php +++ /dev/null @@ -1,24 +0,0 @@ - 'Yoast SEO', - 'client_id' => '395430892738-ushj8aced0cji2j4bkq6bda6felaigb9.apps.googleusercontent.com', - 'client_secret' => 'c2kYgOwMhk1emWxQ3NaA8wOi', - 'redirect_uri' => 'urn:ietf:wg:oauth:2.0:oob', - 'scopes' => array( 'https://www.googleapis.com/auth/webmasters' ), - ); - -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-count.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-count.php deleted file mode 100644 index 7c8747c7..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-count.php +++ /dev/null @@ -1,229 +0,0 @@ -service = $service; - } - - /** - * Getting the counts for given platform and return them as an array - * - * @param string $platform Platform (desktop, mobile, feature phone). - * - * @return array - */ - public function get_platform_counts( $platform ) { - $counts = $this->get_counts(); - if ( array_key_exists( $platform, $counts ) ) { - return $counts[ $platform ]; - } - - return array(); - } - - /** - * Return the fetched issues - * - * @return array - */ - public function get_issues() { - return $this->issues; - } - - /** - * Listing the issues an gives them back as fetched issues - * - * @param string $platform Platform (desktop, mobile, feature phone). - * @param string $category Issue category. - */ - public function list_issues( $platform, $category ) { - $counts = $this->get_counts(); - - if ( array_key_exists( $platform, $counts ) ) { - $counts[ $platform ] = $this->list_category_issues( $counts[ $platform ], $platform, $category ); - - // Write the new counts value. - $this->set_counts( $counts ); - } - } - - /** - * Getting the counts for given platform and category. - * - * @param string $platform Platform (desktop, mobile, feature phone). - * @param string $category Issue type. - * - * @return integer - */ - public function get_issue_count( $platform, $category ) { - $counts = $this->get_counts(); - - if ( ! empty( $counts[ $platform ][ $category ]['count'] ) ) { - return $counts[ $platform ][ $category ]['count']; - } - - return 0; - } - - /** - * Update the count of the issues - * - * @param string $platform Platform (desktop, mobile, feature phone). - * @param string $category Issue type. - * @param integer $new_count Updated count. - */ - public function update_issue_count( $platform, $category, $new_count ) { - $counts = $this->get_counts(); - - if ( ! empty( $counts[ $platform ][ $category ] ) && is_array( $counts[ $platform ][ $category ] ) ) { - $counts[ $platform ][ $category ]['count'] = $new_count; - } - - $this->set_counts( $counts ); - } - - /** - * Fetching the counts from the GSC API - */ - public function fetch_counts() { - if ( WPSEO_GSC_Settings::get_profile() && $this->get_last_fetch() <= strtotime( '-12 hours' ) ) { - // Remove the timestamp. - $this->remove_last_fetch(); - - // Getting the counts and parse them. - $counts = $this->parse_counts( $this->service->get_crawl_issue_counts() ); - - // Fetching the counts by setting an option. - $this->set_counts( $counts ); - - // Saving the current timestamp. - $this->save_last_fetch(); - } - } - - /** - * Parsing the received counts from the API and map the keys to plugin friendly values - * - * @param array $fetched_counts Set of retrieved counts. - * - * @return array - */ - private function parse_counts( array $fetched_counts ) { - $counts = array(); - foreach ( $fetched_counts as $platform_name => $categories ) { - $new_platform = WPSEO_GSC_Mapper::platform_from_api( $platform_name ); - - foreach ( $categories as $category_name => $category ) { - $new_category = WPSEO_GSC_Mapper::category_from_api( $category_name ); - - $counts[ $new_platform ][ $new_category ] = $category; - } - } - - return $counts; - } - - /** - * Listing the issues for current category. - * - * @param array $counts Set of counts. - * @param string $platform Platform (desktop, mobile, feature phone). - * @param string $category Issue type. - * - * @return array - */ - private function list_category_issues( array $counts, $platform, $category ) { - // When the issues have to be fetched. - if ( array_key_exists( $category, $counts ) && $counts[ $category ]['count'] > 0 && $counts[ $category ]['last_fetch'] <= strtotime( '-12 hours' ) ) { - $issues = $this->service->fetch_category_issues( WPSEO_GSC_Mapper::platform_to_api( $platform ), WPSEO_GSC_Mapper::category_to_api( $category ) ); - if ( ! empty( $issues ) ) { - $this->issues = $issues; - } - - // Be sure the total count is correct. - $counts[ $category ]['count'] = count( $this->issues ); - - // Set last fetch. - $counts[ $category ]['last_fetch'] = time(); - } - - return $counts; - } - - /** - * Getting the counts from the options - * - * @return array - */ - private function get_counts() { - return get_option( self::OPTION_CI_COUNTS, array() ); - } - - /** - * Fetching the counts from the service and store them in an option - * - * @param array $counts Set of counts. - */ - private function set_counts( array $counts ) { - update_option( self::OPTION_CI_COUNTS, $counts ); - } - - /** - * Store the timestamp of when crawl errors were saved the last time. - */ - private function save_last_fetch() { - add_option( self::OPTION_CI_LAST_FETCH, time(), '', 'no' ); - } - - /** - * Remove the last checked option - */ - private function remove_last_fetch() { - delete_option( self::OPTION_CI_LAST_FETCH ); - } - - /** - * Get the timestamp of when the crawl errors were last saved - * - * @return int - */ - private function get_last_fetch() { - return get_option( self::OPTION_CI_LAST_FETCH, 0 ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-issue.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-issue.php deleted file mode 100644 index 0295959b..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-issue.php +++ /dev/null @@ -1,91 +0,0 @@ -url = $url; - $this->first_detected = $first_detected; - $this->last_crawled = $last_crawled; - $this->response_code = $response_code; - } - - /** - * Put the class properties in array - * - * @return array - */ - public function to_array() { - return array( - 'url' => $this->url, - 'first_detected' => $this->to_date_format( $this->first_detected ), - 'first_detected_raw' => $this->to_timestamp( $this->first_detected ), - 'last_crawled' => $this->to_date_format( $this->last_crawled ), - 'last_crawled_raw' => $this->to_timestamp( $this->last_crawled ), - 'response_code' => $this->response_code, - ); - } - - /** - * Converting the date to a date format - * - * @param DateTime $date_to_convert Date instance. - * @param string $format Format string. - * - * @return string - */ - private function to_date_format( DateTime $date_to_convert, $format = '' ) { - - if ( empty( $format ) ) { - $format = get_option( 'date_format' ); - } - - return date_i18n( $format, $date_to_convert->format( 'U' ) ); - } - - /** - * Converting the date to a timestamp - * - * @param DateTime $date_to_convert Date object instance. - * - * @return string - */ - private function to_timestamp( DateTime $date_to_convert ) { - return $date_to_convert->format( 'U' ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-issues.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-issues.php deleted file mode 100644 index efa461bb..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-issues.php +++ /dev/null @@ -1,177 +0,0 @@ -option_name = strtolower( 'wpseo-gsc-issues-' . $platform . '-' . $category ); - $this->issues = $this->get_issues(); - - if ( ! empty( $fetched_issues ) && is_array( $fetched_issues ) ) { - $this->save_fetched_issues( $fetched_issues ); - } - } - /** - * Getting the issues from the options. - * - * @return array - */ - public function get_issues() { - return get_option( $this->option_name, array() ); - } - - /** - * Deleting the issue from the issues - * - * @param string $url URL to delete issues for. - * - * @return bool - */ - public function delete_issue( $url ) { - $target_issue = $this->get_issue_by_url( $url ); - if ( $target_issue !== false ) { - unset( $this->issues[ $target_issue ] ); - - $this->save_issues( $this->issues ); - - return true; - } - - return false; - } - - /** - * Fetching the issues for current category and compare them with the already existing issues. - * - * @param array $fetched_issues Set of retrieved issues. - */ - private function save_fetched_issues( array $fetched_issues ) { - $this->set_current_issues(); - - $crawl_issues = $this->get_issues(); - - // Walk through the issues to do the comparison. - foreach ( $fetched_issues as $issue ) { - $this->issue_compare( $crawl_issues, $issue ); - } - - $this->save_issues( $crawl_issues ); - - // Refresh the value of $this->issues. - $this->issues = $this->get_issues(); - } - - /** - * Comparing the issue with the list of current existing issues - * - * @param array $crawl_issues Set of issues by reference. - * @param stdClass $issue Issue object to check against the list. - */ - private function issue_compare( &$crawl_issues, $issue ) { - $issue->pageUrl = WPSEO_Utils::format_url( (string) $issue->pageUrl ); - - if ( ! in_array( $issue->pageUrl, $this->current_issues, true ) ) { - array_push( - $crawl_issues, - $this->get_issue( $this->create_issue( $issue ) ) - ); - } - } - - /** - * The fetched issue from the API will be parsed as an WPSEO_Crawl_Issue object. After initializing the issue as an - * object, the object will be returned - * - * @param stdClass $issue Issue data object. - * - * @return WPSEO_GSC_Issue - */ - private function create_issue( $issue ) { - return new WPSEO_GSC_Issue( - $issue->pageUrl, - new DateTime( (string) $issue->first_detected ), - new DateTime( (string) $issue->last_crawled ), - (string) ( ! empty( $issue->responseCode ) ) ? $issue->responseCode : null - ); - } - - /** - * Returns the crawl issue as an array. - * - * @param WPSEO_GSC_Issue $crawl_issue Issue object instance. - * - * @return array() - */ - private function get_issue( WPSEO_GSC_Issue $crawl_issue ) { - return $crawl_issue->to_array(); - } - - /** - * Saving the issues to the options. The target option is base on current platform and category. - * - * @param array $issues Set of issues. - */ - private function save_issues( array $issues ) { - update_option( $this->option_name, $issues, false ); - } - - /** - * Getting the issues from the options and get only the URL out of it. This is because there will be a comparison - * with the issues from the API. - */ - private function set_current_issues() { - if ( ! empty( $this->issues ) ) { - $this->current_issues = wp_list_pluck( $this->issues, 'url' ); - } - } - - /** - * Search in the issues for the given $url - * - * @param string $url Issue URL to search for. - * - * @return int|string - */ - private function get_issue_by_url( $url ) { - foreach ( $this->issues as $key => $issue ) { - if ( $url === $issue['url'] ) { - return $key; - } - } - - return false; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-mapper.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-mapper.php deleted file mode 100644 index b62122c1..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-mapper.php +++ /dev/null @@ -1,121 +0,0 @@ - 'web', - 'mobile' => 'mobile', - 'smartphone_only' => 'smartphoneOnly', - 'settings' => 'settings', // This one is basicly not a platform, but a tab. - ); - - /** - * The categories which can be mapped - * - * @var array - */ - private static $categories = array( - 'access_denied' => 'authPermissions', - 'faulty_redirects' => 'manyToOneRedirect', - 'not_followed' => 'notFollowed', - 'not_found' => 'notFound', - 'other' => 'other', - 'roboted' => 'roboted', - 'server_error' => 'serverError', - 'soft_404' => 'soft404', - ); - - /** - * If there is no platform, just get the first key out of the array and redirect to it. - * - * @param string $platform Platform (desktop, mobile, feature phone). - * - * @return mixed - */ - public static function get_current_platform( $platform ) { - $current_platform = filter_input( INPUT_GET, $platform ); - if ( ! empty( $current_platform ) ) { - return $current_platform; - } - - wp_redirect( add_query_arg( $platform, key( self::$platforms ) ) ); - exit; - } - - /** - * Mapping the platform - * - * @param string $platform Platform (desktop, mobile, feature phone). - * - * @return mixed - */ - public static function platform_to_api( $platform ) { - if ( ! empty( $platform ) && array_key_exists( $platform, self::$platforms ) ) { - return self::$platforms[ $platform ]; - } - } - - /** - * Mapping the given platform by value and return its key - * - * @param string $platform Platform (desktop, mobile, feature phone). - * - * @return string - */ - public static function platform_from_api( $platform ) { - if ( ! empty( $platform ) ) { - $platform = array_search( $platform, self::$platforms, true ); - if ( $platform !== false ) { - return $platform; - } - } - - return $platform; - } - - /** - * Mapping the given category by searching for its key. - * - * @param string $category Issue type. - * - * @return mixed - */ - public static function category_to_api( $category ) { - if ( ! empty( $category ) && array_key_exists( $category, self::$categories ) ) { - return self::$categories[ $category ]; - } - - return $category; - } - - /** - * Mapping the given category by value and return its key - * - * @param string $category Issue type. - * - * @return string - */ - public static function category_from_api( $category ) { - if ( ! empty( $category ) ) { - $category = array_search( $category, self::$categories, true ); - if ( $category !== false ) { - return $category; - } - } - - return $category; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-marker.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-marker.php deleted file mode 100644 index d2f9996c..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-marker.php +++ /dev/null @@ -1,145 +0,0 @@ -url = $url; - $this->result = $this->get_result(); - } - - /** - * Getting the response for the AJAX request - * - * @return string - */ - public function get_response() { - return $this->result; - } - - /** - * Setting the result, this method will check if current - * - * @return string - */ - private function get_result() { - if ( $this->can_be_marked_as_fixed() ) { - $service = new WPSEO_GSC_Service( WPSEO_GSC_Settings::get_profile() ); - - if ( $this->set_crawl_issues() && $this->send_mark_as_fixed( $service ) && $this->delete_crawl_issue() ) { - $this->update_issue_count( $service ); - - return 'true'; - } - } - - return 'false'; - } - - /** - * Check if request is valid by verifying the posted nonce and return the URL if this one is set - * - * @return bool|string - */ - private function can_be_marked_as_fixed() { - if ( $this->url !== '' ) { - return $this->url; - } - - return false; - } - - /** - * Storing the data belonging to the current issue, this data is needed in the 'mark as fixed' flow - * - * @return bool - */ - private function set_crawl_issues() { - $this->platform = filter_input( INPUT_POST, 'platform' ); - $this->category = filter_input( INPUT_POST, 'category' ); - if ( $this->platform && $this->category ) { - $this->crawl_issues = new WPSEO_GSC_Issues( $this->platform, $this->category ); - - return true; - } - - return false; - } - - /** - * Sending a request to the Google Search Console API to let them know we marked an issue as fixed. - * - * @param WPSEO_GSC_Service $service Service object instance. - * - * @return bool - */ - private function send_mark_as_fixed( WPSEO_GSC_Service $service ) { - return $service->mark_as_fixed( $this->url, $this->platform, $this->category ); - } - - /** - * Delete the crawl issue from the database - * - * @return bool - */ - private function delete_crawl_issue() { - return $this->crawl_issues->delete_issue( $this->url ); - } - - /** - * Getting the counts for current platform - category combination and update the score of it. - * - * @param WPSEO_GSC_Service $service Service object instance. - */ - private function update_issue_count( WPSEO_GSC_Service $service ) { - $counts = new WPSEO_GSC_Count( $service ); - - // Get the issues. - $total_issues = $counts->get_issue_count( $this->platform, $this->category ); - - // Lower the current count with 1. - $total_issues = ( $total_issues - 1 ); - - // And update the count. - $counts->update_issue_count( $this->platform, $this->category, $total_issues ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-modal.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-modal.php deleted file mode 100644 index 713b856b..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-modal.php +++ /dev/null @@ -1,58 +0,0 @@ -view = $view; - $this->height = $height; - $this->view_vars = $view_vars; - } - - /** - * Returns the height of the modal. - * - * @return int The set height. - */ - public function get_height() { - return $this->height; - } - - /** - * Loads the view of the modal. - * - * @param string $unique_id An unique identifier for the modal. - */ - public function load_view( $unique_id ) { - extract( $this->view_vars ); - - echo ''; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-platform-tabs.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-platform-tabs.php deleted file mode 100644 index 5a6e8e28..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-platform-tabs.php +++ /dev/null @@ -1,97 +0,0 @@ -platform_tabs(); - } - - /** - * Getting the current_tab - * - * @return string - */ - public function current_tab() { - return $this->current_tab; - } - - /** - * Loops through the array with all the platforms and convert it into an array - * - * @return string - */ - private function platform_tabs() { - $tabs = array( 'settings' => __( 'Settings', 'wordpress-seo' ) ); - - $platforms = array( - 'web' => __( 'Desktop', 'wordpress-seo' ), - 'smartphone_only' => __( 'Smartphone', 'wordpress-seo' ), - 'mobile' => __( 'Feature phone', 'wordpress-seo' ), - ); - - if ( WPSEO_GSC_Settings::get_profile() !== '' ) { - $tabs = array_merge( $platforms, $tabs ); - } - - $admin_link = admin_url( 'admin.php?page=wpseo_search_console&tab=' ); - - $this->set_current_tab( $tabs ); - - $return = ''; - - foreach ( $tabs as $platform_target => $platform_value ) { - $return .= $this->platform_tab( $platform_target, $platform_value, $admin_link ); - } - - return $return; - } - - /** - * Setting the current tab - * - * @param array $platforms Set of platforms (desktop, mobile, feature phone). - */ - private function set_current_tab( array $platforms ) { - $this->current_tab = key( $platforms ); - $current_platform = filter_input( INPUT_GET, 'tab' ); - if ( ! empty( $current_platform ) && isset( $platforms[ $current_platform ] ) ) { - $this->current_tab = $current_platform; - } - } - - /** - * Parses the tab - * - * @param string $platform_target Platform (desktop, mobile, feature phone). - * @param string $platform_value Link anchor. - * @param string $admin_link Link URL admin base. - * - * @return string - */ - private function platform_tab( $platform_target, $platform_value, $admin_link ) { - $active = ''; - if ( $this->current_tab === $platform_target ) { - $active = ' nav-tab-active'; - } - - return '' . esc_html( $platform_value ) . ''; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-service.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-service.php deleted file mode 100644 index c4fdaaf2..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-service.php +++ /dev/null @@ -1,195 +0,0 @@ -profile = $profile; - - $this->set_client(); - } - - /** - * Returns the client - * - * @return Yoast_Api_Google_Client - */ - public function get_client() { - return $this->client; - } - - /** - * Removes the option and calls the clients clear_data method to clear that one as well - */ - public function clear_data() { - // Clear client data. - $this->client->clear_data(); - } - - /** - * Get all sites that are registered in the GSC panel - * - * @return array - */ - public function get_sites() { - $sites = array(); - - $response_json = $this->client->do_request( 'sites', true ); - - // Do list sites request. - if ( ! empty( $response_json->siteEntry ) ) { - foreach ( $response_json->siteEntry as $entry ) { - $sites[ str_ireplace( 'sites/', '', (string) $entry->siteUrl ) ] = (string) $entry->siteUrl; - } - - // Sorting the retrieved sites. - asort( $sites ); - } - - return $sites; - } - - /** - * Get crawl issues - * - * @return array - */ - public function get_crawl_issue_counts() { - // Setup crawl error list. - $crawl_error_counts = $this->get_crawl_error_counts( $this->profile ); - - $return = array(); - // Ignore coding standards for object properties. - if ( ! empty( $crawl_error_counts->countPerTypes ) ) { - foreach ( $crawl_error_counts->countPerTypes as $category ) { - $return[ $category->platform ][ $category->category ] = array( - 'count' => $category->entries[0]->count, - 'last_fetch' => null, - ); - } - } - - return $return; - } - - /** - * Sending request to mark issue as fixed - * - * @param string $url Issue URL. - * @param string $platform Platform (desktop, mobile, feature phone). - * @param string $category Issue type. - * - * @return bool - */ - public function mark_as_fixed( $url, $platform, $category ) { - $response = $this->client->do_request( 'sites/' . urlencode( $this->profile ) . '/urlCrawlErrorsSamples/' . urlencode( ltrim( $url, '/' ) ) . '?category=' . WPSEO_GSC_Mapper::category_to_api( $category ) . '&platform=' . WPSEO_GSC_Mapper::platform_to_api( $platform ) . '', false, 'DELETE' ); - return ( $response->getResponseHttpCode() === 204 ); - } - - /** - * Fetching the issues from the GSC API - * - * @param string $platform Platform (desktop, mobile, feature phone). - * @param string $category Issue type. - * - * @return mixed - */ - public function fetch_category_issues( $platform, $category ) { - $issues = $this->client->do_request( - 'sites/' . urlencode( $this->profile ) . '/urlCrawlErrorsSamples?category=' . $category . '&platform=' . $platform, - true - ); - - if ( ! empty( $issues->urlCrawlErrorSample ) ) { - return $issues->urlCrawlErrorSample; - } - } - - /** - * Setting the GSC client - */ - private function set_client() { - try { - new Yoast_Api_Libs( '2.0' ); - } - catch ( Exception $exception ) { - if ( $exception->getMessage() === 'required_version' ) { - $this->incompatible_api_libs( - __( 'Yoast plugins share some code between them to make your site faster. As a result of that, we need all Yoast plugins to be up to date. We\'ve detected this isn\'t the case, so please update the Yoast plugins that aren\'t up to date yet.', 'wordpress-seo' ) - ); - } - } - - if ( class_exists( 'Yoast_Api_Google_Client' ) === false ) { - $this->incompatible_api_libs( - sprintf( - /* translators: %1$s expands to Yoast SEO, %2$s expands to Google Analytics by Yoast */ - __( - '%1$s detected you’re using a version of %2$s which is not compatible with %1$s. Please update %2$s to the latest version to use this feature.', - 'wordpress-seo' - ), - 'Yoast SEO', - 'Google Analytics by Yoast' - ) - ); - - wp_redirect( admin_url( 'admin.php?page=' . WPSEO_Admin::PAGE_IDENTIFIER ) ); - exit; - } - - $this->client = new Yoast_Api_Google_Client( WPSEO_GSC_Config::$gsc, 'wpseo-gsc', 'https://www.googleapis.com/webmasters/v3/' ); - } - - /** - * Adding notice that the api libs has the wrong version - * - * @param string $notice Message string. - */ - private function incompatible_api_libs( $notice ) { - Yoast_Notification_Center::get()->add_notification( - new Yoast_Notification( $notice, array( 'type' => Yoast_Notification::ERROR ) ) - ); - } - - /** - * Getting the crawl error counts - * - * @param string $profile Profile name string. - * - * @return object|bool - */ - private function get_crawl_error_counts( $profile ) { - $crawl_error_counts = $this->client->do_request( - 'sites/' . urlencode( $profile ) . '/urlCrawlErrorsCounts/query', - true - ); - - if ( ! empty( $crawl_error_counts ) ) { - return $crawl_error_counts; - } - - return false; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-settings.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-settings.php deleted file mode 100644 index eb86928d..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-settings.php +++ /dev/null @@ -1,104 +0,0 @@ -clear_data(); - } - - /** - * Reloading all the issues - */ - public static function reload_issues() { - // Remove issue and issue counts. - self::remove(); - } - - /** - * When authorization is successful return true, otherwise false - * - * @param string $authorization_code Code to validate. - * @param Yoast_Api_Google_Client $client Client object instance. - * - * @return bool - */ - public static function validate_authorization( $authorization_code, Yoast_Api_Google_Client $client ) { - return ( $authorization_code !== '' && $client->authenticate_client( $authorization_code ) ); - } - - /** - * Get the GSC profile - * - * @return string - */ - public static function get_profile() { - // Get option. - $option = get_option( WPSEO_GSC::OPTION_WPSEO_GSC, array( 'profile' => '' ) ); - - // Set the profile. - $profile = ''; - if ( ! empty( $option['profile'] ) ) { - $profile = $option['profile']; - } - - // Return the profile. - return trim( $profile, '/' ); - } - - /** - * Removes the issue counts and all the issues from the options - */ - private static function remove() { - // Remove the issue counts from the options. - self::remove_issue_counts(); - - // Removing all issues from the database. - self::remove_issues(); - } - - /** - * Remove the issue counts - */ - private static function remove_issue_counts() { - // Remove the options which are holding the counts. - delete_option( WPSEO_GSC_Count::OPTION_CI_COUNTS ); - delete_option( WPSEO_GSC_Count::OPTION_CI_LAST_FETCH ); - } - - /** - * Delete the issues and their meta data from the database - */ - private static function remove_issues() { - global $wpdb; - - // Remove local crawl issues by running a delete query. - $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'wpseo-gsc-issues-%'" ); - } - - /** - * Removes the options for GSC - */ - private static function remove_gsc_option() { - delete_option( WPSEO_GSC::OPTION_WPSEO_GSC ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-table.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-table.php deleted file mode 100644 index a611d2e3..00000000 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc-table.php +++ /dev/null @@ -1,370 +0,0 @@ -search_string = $search_string; - } - - $this->current_view = $category; - - // Set the crawl issue source. - $this->show_fields( $platform ); - - $this->items = $items; - } - - /** - * Getting the screen id from this table - * - * @return string - */ - public function get_screen_id() { - return $this->screen->id; - } - - /** - * Setup the table variables, fetch the items from the database, search, sort and format the items. - */ - public function prepare_items() { - // Get variables needed for pagination. - $this->per_page = $this->get_items_per_page( 'errors_per_page', $this->per_page ); - $paged = filter_input( INPUT_GET, 'paged' ); - $this->current_page = intval( ( ! empty( $paged ) ) ? $paged : 1 ); - - $this->setup_columns(); - $this->views(); - $this->parse_items(); - } - - /** - * Set the table columns - * - * @return array - */ - public function get_columns() { - $columns = array( - 'cb' => '', - 'url' => __( 'URL', 'wordpress-seo' ), - 'last_crawled' => __( 'Last crawled', 'wordpress-seo' ), - 'first_detected' => __( 'First detected', 'wordpress-seo' ), - 'response_code' => __( 'Response code', 'wordpress-seo' ), - ); - - return $columns; - } - - /** - * Return the columns that are sortable - * - * @return array - */ - protected function get_sortable_columns() { - $sortable_columns = array( - 'url' => array( 'url', false ), - 'last_crawled' => array( 'last_crawled', false ), - 'first_detected' => array( 'first_detected', false ), - 'response_code' => array( 'response_code', false ), - ); - - return $sortable_columns; - } - - /** - * Return available bulk actions - * - * @return array - */ - protected function get_bulk_actions() { - return array( - 'mark_as_fixed' => __( 'Mark as fixed', 'wordpress-seo' ), - ); - } - - /** - * Default method to display a column - * - * @param array $item Data array. - * @param string $column_name Column name key. - * - * @return mixed - */ - protected function column_default( $item, $column_name ) { - return $item[ $column_name ]; - } - - /** - * Checkbox column - * - * @param array $item Item data array. - * - * @return string - */ - protected function column_cb( $item ) { - return sprintf( - '', - md5( $item['url'] ), - $item['url'], - __( 'Select redirect', 'wordpress-seo' ) - ); - } - - /** - * Formatting the output of the column last crawled into a dateformat - * - * @param array $item Item data array. - * - * @return string - */ - protected function column_last_crawled( $item ) { - return date_i18n( get_option( 'date_format' ), strtotime( $item['last_crawled'] ) ); - } - - /** - * Formatting the output of the column first detected into a dateformat - * - * @param array $item Item data array. - * - * @return string - */ - protected function column_first_detected( $item ) { - return date_i18n( get_option( 'date_format' ), strtotime( $item['first_detected'] ) ); - } - - /** - * URL column - * - * @param array $item Item data array. - * - * @return string - */ - protected function column_url( $item ) { - $actions = array(); - - if ( $this->can_create_redirect() ) { - /** Gets the modal box */ - $modal = $this->get_modal_box( $item['url'] ); - $modal->load_view( md5( $item['url'] ) ); - - $actions['create_redirect'] = '' . __( 'Create redirect', 'wordpress-seo' ) . ''; - } - - $actions['view'] = '' . __( 'View', 'wordpress-seo' ) . ''; - $actions['markasfixed'] = '' . __( 'Mark as fixed', 'wordpress-seo' ) . ''; - - return sprintf( - '%1$s %2$s', - $item['url'], - $this->row_actions( $actions ) - ); - } - - /** - * Running the setup of the columns - */ - private function setup_columns() { - $this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() ); - } - - /** - * Check if the current category allow creating redirects - * - * @return bool - */ - private function can_create_redirect() { - return in_array( $this->current_view, array( 'soft_404', 'not_found', 'access_denied' ), true ); - } - - /** - * Setting the table navigation - * - * @param int $total_items Total number of items. - * @param int $posts_per_page Number of items per page. - */ - private function set_pagination( $total_items, $posts_per_page ) { - $this->set_pagination_args( array( - 'total_items' => $total_items, - 'total_pages' => ceil( ( $total_items / $posts_per_page ) ), - 'per_page' => $posts_per_page, - ) ); - } - - /** - * Setting the items - */ - private function parse_items() { - if ( is_array( $this->items ) && count( $this->items ) > 0 ) { - if ( ! empty( $this->search_string ) ) { - $this->do_search(); - } - - $this->set_pagination( count( $this->items ), $this->per_page ); - - $this->sort_items(); - $this->paginate_items(); - } - } - - /** - * Search through the items - */ - private function do_search() { - $results = array(); - - foreach ( $this->items as $item ) { - foreach ( $item as $value ) { - if ( stristr( $value, $this->search_string ) !== false ) { - $results[] = $item; - continue; - } - } - } - - $this->items = $results; - } - - /** - * Running the pagination - */ - private function paginate_items() { - // Setting the starting point. If starting point is below 1, overwrite it with value 0, otherwise it will be sliced of at the back. - $slice_start = ( $this->current_page - 1 ); - if ( $slice_start < 0 ) { - $slice_start = 0; - } - - // Apply 'pagination'. - $this->items = array_slice( $this->items, ( $slice_start * $this->per_page ), $this->per_page ); - } - - /** - * Sort the items by callback - */ - private function sort_items() { - // Sort the results. - usort( $this->items, array( $this, 'do_reorder' ) ); - } - - /** - * Doing the sorting of the issues - * - * @param array $a First data set for comparison. - * @param array $b Second data set for comparison. - * - * @return int - */ - private function do_reorder( $a, $b ) { - $orderby = filter_input( INPUT_GET, 'orderby' ); - $order = filter_input( INPUT_GET, 'order' ); - - // If no sort, default to title. - $orderby = ( ! empty( $orderby ) ) ? $orderby : 'url'; - - // If no order, default to asc. - $order = ( ! empty( $order ) ) ? $order : 'asc'; - - // When there is a raw field of it, sort by this field. - if ( array_key_exists( $orderby . '_raw', $a ) && array_key_exists( $orderby . '_raw', $b ) ) { - $orderby = $orderby . '_raw'; - } - - // Determine sort order. - $result = strcmp( $a[ $orderby ], $b[ $orderby ] ); - - // Send final sort direction to usort. - return ( $order === 'asc' ) ? $result : ( - $result ); - } - - /** - * Checks if premium is loaded, if not the nopremium modal will be shown. Otherwise it will load the premium one. - * - * @param string $url URL string. - * - * @return WPSEO_GSC_Modal Instance of the GSC modal. - */ - private function get_modal_box( $url ) { - if ( defined( 'WPSEO_PREMIUM_FILE' ) && class_exists( 'WPSEO_Premium_GSC_Modal' ) ) { - static $premium_modal; - - if ( ! $premium_modal ) { - $premium_modal = new WPSEO_Premium_GSC_Modal(); - } - - return $premium_modal->show( $url ); - } - - return new WPSEO_GSC_Modal( - dirname( __FILE__ ) . '/views/gsc-redirect-nopremium.php', - self::FREE_MODAL_HEIGHT, - array( 'url' => $url ) - ); - } - - /** - * Showing the hidden fields used by the AJAX requests - * - * @param string $platform Platform (desktop, mobile, feature phone). - */ - private function show_fields( $platform ) { - echo ''; - echo ''; - echo ''; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc.php index 8dda1f47..3e3369b3 100644 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc.php +++ b/wp-content/plugins/wordpress-seo/admin/google_search_console/class-gsc.php @@ -6,308 +6,23 @@ */ /** - * Class WPSEO_GSC + * Class WPSEO_GSC. */ class WPSEO_GSC { /** - * The option where data will be stored + * The option where data will be stored. + * + * @var string */ const OPTION_WPSEO_GSC = 'wpseo-gsc'; /** - * @var WPSEO_GSC_Service - */ - private $service; - - /** - * @var WPSEO_GSC_Category_Filters - */ - protected $category_filter; - - /** - * @var WPSEO_GSC_Issues - */ - protected $issue_fetch; - - /** - * @var string current platform - */ - private $platform; - - /** - * @var string current category - */ - private $category; - - /** - * Constructor for the page class. This will initialize all GSC related stuff - */ - public function __construct() { - add_action( 'init', array( $this, 'init' ) ); - } - - /** - * Run init logic. - */ - public function init() { - - // Setting the screen option. - if ( filter_input( INPUT_GET, 'page' ) === 'wpseo_search_console' ) { - - if ( filter_input( INPUT_GET, 'tab' ) !== 'settings' && WPSEO_GSC_Settings::get_profile() === '' ) { - wp_redirect( add_query_arg( 'tab', 'settings' ) ); - exit; - } - - $this->set_hooks(); - $this->set_dependencies(); - $this->request_handler(); - } - - add_action( 'admin_init', array( $this, 'register_gsc_notification' ) ); - add_action( 'admin_init', array( $this, 'register_settings' ) ); - } - - /** - * If the Google Search Console has no credentials, add a notification for the user to give him a heads up. This message is dismissable. - */ - public function register_gsc_notification() { - - $notification = $this->get_profile_notification(); - $notification_center = Yoast_Notification_Center::get(); - - if ( WPSEO_GSC_Settings::get_profile() === '' ) { - $notification_center->add_notification( $notification ); - } - else { - $notification_center->remove_notification( $notification ); - } - } - - /** - * Builds the notification used when GSC is not connected to a profile + * Outputs the HTML for the redirect page. * - * @return Yoast_Notification - */ - private function get_profile_notification() { - return new Yoast_Notification( - sprintf( - /* translators: 1: link open tag; 2: link close tag. */ - __( 'Don\'t miss your crawl errors: %1$sconnect with Google Search Console here%2$s.', 'wordpress-seo' ), - '', - '' - ), - array( - 'type' => Yoast_Notification::WARNING, - 'id' => 'wpseo-dismiss-gsc', - 'capabilities' => 'wpseo_manage_options', - ) - ); - } - - /** - * Be sure the settings will be registered, so data can be stored - */ - public function register_settings() { - register_setting( 'yoast_wpseo_gsc_options', self::OPTION_WPSEO_GSC ); - } - - /** - * Function that outputs the redirect page + * @return void */ public function display() { require_once WPSEO_PATH . 'admin/google_search_console/views/gsc-display.php'; } - - /** - * Display the table - */ - public function display_table() { - // The list table. - $list_table = new WPSEO_GSC_Table( $this->platform, $this->category, $this->issue_fetch->get_issues() ); - - // Adding filter to display the category filters. - add_filter( 'views_' . $list_table->get_screen_id(), array( $this->category_filter, 'as_array' ) ); - - // Preparing and displaying the table. - $list_table->prepare_items(); - $list_table->search_box( __( 'Search', 'wordpress-seo' ), 'wpseo-crawl-issues-search' ); - $list_table->display(); - } - - /** - * Load the admin redirects scripts - */ - public function page_scripts() { - - $asset_manager = new WPSEO_Admin_Asset_Manager(); - $asset_manager->enqueue_script( 'admin-gsc' ); - $asset_manager->enqueue_style( 'metabox-css' ); - add_screen_option( 'per_page', array( - 'label' => __( 'Crawl errors per page', 'wordpress-seo' ), - 'default' => 50, - 'option' => 'errors_per_page', - ) ); - } - - /** - * Set the screen options - * - * @param string $status Status string. - * @param string $option Option key. - * @param string $value Value to return. - * - * @return mixed - */ - public function set_screen_option( $status, $option, $value ) { - if ( 'errors_per_page' === $option ) { - return $value; - } - } - - /** - * Setting the hooks to be load on page request - */ - private function set_hooks() { - add_action( 'admin_enqueue_scripts', array( $this, 'page_scripts' ) ); - add_filter( 'set-screen-option', array( $this, 'set_screen_option' ), 11, 3 ); - } - - /** - * Handles the POST and GET requests - */ - private function request_handler() { - - // List the table search post to a get. - $this->list_table_search_post_to_get(); - - // Catch the authorization code POST. - $this->catch_authentication_post(); - - // Is there a reset post than we will remove the posts and data. - if ( filter_input( INPUT_GET, 'gsc_reset' ) ) { - // Clear the google data. - WPSEO_GSC_Settings::clear_data( $this->service ); - - // Adding notification to the notification center. - /* Translators: %1$s: expands to Google Search Console. */ - $this->add_notification( sprintf( __( 'The %1$s data has been removed. You will have to reauthenticate if you want to retrieve the data again.', 'wordpress-seo' ), 'Google Search Console' ), Yoast_Notification::UPDATED ); - - // Directly output the notifications. - wp_redirect( remove_query_arg( 'gsc_reset' ) ); - exit; - } - - // Reloads al the issues. - if ( wp_verify_nonce( filter_input( INPUT_POST, 'reload-crawl-issues-nonce' ), 'reload-crawl-issues' ) && filter_input( INPUT_POST, 'reload-crawl-issues' ) ) { - // Reloading all the issues. - WPSEO_GSC_Settings::reload_issues(); - - // Adding the notification. - $this->add_notification( __( 'The issues have been successfully reloaded!', 'wordpress-seo' ), Yoast_Notification::UPDATED ); - - // Directly output the notifications. - Yoast_Notification_Center::get()->display_notifications(); - } - - // Catch bulk action request. - new WPSEO_GSC_Bulk_Action(); - } - - /** - * Catch the redirects search post and redirect it to a search get - */ - private function list_table_search_post_to_get() { - $search_string = filter_input( INPUT_POST, 's' ); - - if ( $search_string === null ) { - return; - } - - // When there is nothing being search and there is no search param in the url, break this method. - if ( $search_string === '' && filter_input( INPUT_GET, 's' ) === null ) { - return; - } - - $url = ( $search_string !== '' ) ? add_query_arg( 's', $search_string ) : remove_query_arg( 's' ); - - // Do the redirect. - wp_redirect( $url ); - exit; - - } - - /** - * Catch the authentication post - */ - private function catch_authentication_post() { - $gsc_values = filter_input( INPUT_POST, 'gsc', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY ); - // Catch the authorization code POST. - if ( ! empty( $gsc_values['authorization_code'] ) && wp_verify_nonce( $gsc_values['gsc_nonce'], 'wpseo-gsc_nonce' ) ) { - if ( ! WPSEO_GSC_Settings::validate_authorization( trim( $gsc_values['authorization_code'] ), $this->service->get_client() ) ) { - $this->add_notification( __( 'Incorrect Google Authorization Code.', 'wordpress-seo' ), Yoast_Notification::ERROR ); - } - - // Redirect user to prevent a post resubmission which causes an oauth error. - wp_redirect( admin_url( 'admin.php' ) . '?page=' . esc_attr( filter_input( INPUT_GET, 'page' ) ) . '&tab=settings' ); - exit; - } - } - - /** - * Adding notification to the yoast notification center - * - * @param string $message Message string. - * @param string $type Message type. - */ - private function add_notification( $message, $type ) { - Yoast_Notification_Center::get()->add_notification( - new Yoast_Notification( $message, array( 'type' => $type ) ) - ); - } - - /** - * Setting dependencies which will be used one this page - */ - private function set_dependencies() { - // Setting the service object. - $this->service = new WPSEO_GSC_Service( WPSEO_GSC_Settings::get_profile() ); - - // Setting the platform. - $this->platform = WPSEO_GSC_Mapper::get_current_platform( 'tab' ); - - // Loading the issue counter. - $issue_count = new WPSEO_GSC_Count( $this->service ); - $issue_count->fetch_counts(); - - // Loading the category filters. - $this->category_filter = new WPSEO_GSC_Category_Filters( $issue_count->get_platform_counts( $this->platform ) ); - - // Setting the current category. - $this->category = $this->category_filter->get_category(); - - // Listing the issues. - $issue_count->list_issues( $this->platform, $this->category ); - - // Fetching the issues. - $this->issue_fetch = new WPSEO_GSC_Issues( $this->platform, $this->category, $issue_count->get_issues() ); - } - - /** - * Setting the tab help on top of the screen - */ - public function set_help() { - $screen = get_current_screen(); - - $screen->add_help_tab( - array( - 'id' => 'basic-help', - 'title' => __( 'Issue categories', 'wordpress-seo' ), - 'content' => '

' . __( 'Desktop', 'wordpress-seo' ) . '
' . __( 'Errors that occurred when your site was crawled by Googlebot.', 'wordpress-seo' ) . '

' - . '

' . __( 'Smartphone', 'wordpress-seo' ) . '
' . __( 'Errors that occurred only when your site was crawled by Googlebot-Mobile (errors didn\'t appear for desktop).', 'wordpress-seo' ) . '

' - . '

' . __( 'Feature phone', 'wordpress-seo' ) . '
' . __( 'Errors that only occurred when your site was crawled by Googlebot for feature phones (errors didn\'t appear for desktop).', 'wordpress-seo' ) . '

', - ) - ); - } } diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/views/gsc-display.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/views/gsc-display.php index 3dacb390..510831c2 100644 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/views/gsc-display.php +++ b/wp-content/plugins/wordpress-seo/admin/google_search_console/views/gsc-display.php @@ -8,142 +8,47 @@ // Admin header. Yoast_Form::get_instance()->admin_header( false, 'wpseo-gsc', false, 'yoast_wpseo_gsc_options' ); -$platform_tabs = new WPSEO_GSC_Platform_Tabs(); - -if ( defined( 'WP_DEBUG' ) && WP_DEBUG && WPSEO_GSC_Settings::get_profile() !== '' ) { ?> -
- ' /> - -
- - - - -service->get_client()->getAccessToken() ) { - $video_url = WPSEO_Shortlinker::get( 'https://yoa.st/screencast-search-console' ); -} -else { - $video_url = WPSEO_Shortlinker::get( 'https://yoa.st/screencast-connect-search-console' ); -} - -$tab = new WPSEO_Option_Tab( 'GSC', __( 'Google Search Console', 'wordpress-seo' ), array( 'video_url' => $video_url ) ); -$gsc_help_center = new WPSEO_Help_Center( 'google-search-console', $tab, WPSEO_Utils::is_yoast_seo_premium() ); -$gsc_help_center->localize_data(); -$gsc_help_center->mount(); - -switch ( $platform_tabs->current_tab() ) { - case 'settings': - // Check if there is an access token. - if ( null === $this->service->get_client()->getAccessToken() ) { - // Print auth screen. - echo '

'; - printf( - /* Translators: %1$s: expands to Yoast SEO, %2$s expands to Google Search Console. */ - esc_html__( 'To allow %1$s to fetch your %2$s information, please enter your Google Authorization Code. Clicking the button below will open a new window.', 'wordpress-seo' ), - 'Yoast SEO', - 'Google Search Console' - ); - echo "

\n"; - echo ''; - echo "\n"; - - echo '

' . esc_html__( 'Enter your Google Authorization Code and press the Authenticate button.', 'wordpress-seo' ) . "

\n"; - echo "
\n"; - echo ""; - echo ""; - echo ""; - echo "
\n"; - } - else { - $reset_button = '' . esc_html__( 'Reauthenticate with Google ', 'wordpress-seo' ) . ''; - echo '

', esc_html__( 'Current profile', 'wordpress-seo' ), '

'; - $profile = WPSEO_GSC_Settings::get_profile(); - if ( $profile !== '' ) { - echo '

'; - echo $profile; - echo '

'; - - echo '

'; - echo $reset_button; - echo '

'; - - } - else { - echo "
"; - - settings_fields( 'yoast_wpseo_gsc_options' ); - Yoast_Form::get_instance()->set_option( 'wpseo-gsc' ); - - echo '

'; - $profiles = $this->service->get_sites(); - if ( ! empty( $profiles ) ) { - $show_save = true; - echo Yoast_Form::get_instance()->select( 'profile', __( 'Profile', 'wordpress-seo' ), $profiles ); - } - else { - $show_save = false; - esc_html_e( 'There were no profiles found', 'wordpress-seo' ); - } - echo '

'; - - echo '

'; - - if ( $show_save ) { - echo ' ' . __( 'or', 'wordpress-seo' ) , ' '; - } - echo $reset_button; - echo '

'; - echo '
'; - } - } - break; - - default: - $form_action_url = add_query_arg( 'page', esc_attr( filter_input( INPUT_GET, 'page' ) ) ); - - get_current_screen()->set_screen_reader_content( array( - // There are no views links in this screen, so no need for the views heading. - 'heading_views' => null, - 'heading_pagination' => __( 'Crawl issues list navigation', 'wordpress-seo' ), - 'heading_list' => __( 'Crawl issues list', 'wordpress-seo' ), - ) ); - - // Open
. - echo "\n"; - - // AJAX nonce. - echo "\n"; - - $this->display_table(); - - // Close . - echo "
\n"; - - break; -} +// GSC Error notification. +$gsc_url = 'https://search.google.com/search-console/index'; +$gsc_post_url = 'https://yoa.st/google-search-console-deprecated'; +$gsc_style_alert = ' + display: flex; + align-items: baseline; + position: relative; + padding: 16px; + border: 1px solid rgba(0, 0, 0, 0.2); + font-size: 14px; + font-weight: 400; + line-height: 1.5; + margin: 16px 0; + color: #450c11; + background: #f8d7da; +'; +$gsc_style_alert_icon = 'display: block; margin-right: 8px;'; +$gsc_style_alert_content = 'max-width: 600px;'; +$gsc_style_alert_link = 'color: #004973;'; +$gsc_notification = sprintf( + /* Translators: %1$s: expands to opening anchor tag, %2$s expands to closing anchor tag. */ + __( 'Google has discontinued its Crawl Errors API. Therefore, any possible crawl errors you might have cannot be displayed here anymore. %1$sRead our statement on this for further information%2$s.', 'wordpress-seo' ), + '', + WPSEO_Admin_Utils::get_new_tab_message() . '' +); +$gsc_notification .= '

'; +$gsc_notification .= sprintf( + /* Translators: %1$s: expands to opening anchor tag, %2$s expands to closing anchor tag. */ + __( 'To view your current crawl errors, %1$splease visit Google Search Console%2$s.', 'wordpress-seo' ), + '', + WPSEO_Admin_Utils::get_new_tab_message() . '' +); ?> +
+ + + + +
'; - - printf( - /* translators: %1$s expands anchor to knowledge base article, %2$s expands to */ - esc_html__( 'Please refer to %1$sour article about how to connect your website to Google Search Console%2$s if you need assistance.', 'wordpress-seo' ), - '', - '' - ); - - echo '

'; -?> - -
-admin_footer( false ); diff --git a/wp-content/plugins/wordpress-seo/admin/google_search_console/views/gsc-redirect-nopremium.php b/wp-content/plugins/wordpress-seo/admin/google_search_console/views/gsc-redirect-nopremium.php index 6907ef6b..140a4670 100644 --- a/wp-content/plugins/wordpress-seo/admin/google_search_console/views/gsc-redirect-nopremium.php +++ b/wp-content/plugins/wordpress-seo/admin/google_search_console/views/gsc-redirect-nopremium.php @@ -7,6 +7,8 @@ * @package WPSEO\Admin\Google_Search_Console */ +_deprecated_file( __FILE__, 'WPSEO 9.5' ); + echo '

'; printf( /* Translators: %s: expands to Yoast SEO Premium */ diff --git a/wp-content/plugins/wordpress-seo/admin/import/class-import-detector.php b/wp-content/plugins/wordpress-seo/admin/import/class-import-detector.php index b9b89cf7..89fc80cf 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/class-import-detector.php +++ b/wp-content/plugins/wordpress-seo/admin/import/class-import-detector.php @@ -6,17 +6,18 @@ */ /** - * Class WPSEO_Import_Plugins_Detector + * Class WPSEO_Import_Plugins_Detector. * * Class with functionality to detect whether we should import from another SEO plugin. */ class WPSEO_Import_Plugins_Detector { + /** * Plugins we need to import from. * * @var array */ - public $needs_import = array(); + public $needs_import = []; /** * Detects whether we need to import anything. diff --git a/wp-content/plugins/wordpress-seo/admin/import/class-import-plugin.php b/wp-content/plugins/wordpress-seo/admin/import/class-import-plugin.php index 7c8eb09e..d71fff83 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/class-import-plugin.php +++ b/wp-content/plugins/wordpress-seo/admin/import/class-import-plugin.php @@ -6,17 +6,22 @@ */ /** - * Class WPSEO_Import_Plugin + * Class WPSEO_Import_Plugin. * * Class with functionality to import Yoast SEO settings from other plugins. */ class WPSEO_Import_Plugin { + /** + * Holds the status of and message about imports. + * * @var WPSEO_Import_Status */ public $status; /** + * Class with functionality to import meta data from other plugins. + * * @var WPSEO_Plugin_Importer */ protected $importer; diff --git a/wp-content/plugins/wordpress-seo/admin/import/class-import-settings.php b/wp-content/plugins/wordpress-seo/admin/import/class-import-settings.php index 1c59a3d7..87cb193d 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/class-import-settings.php +++ b/wp-content/plugins/wordpress-seo/admin/import/class-import-settings.php @@ -6,167 +6,87 @@ */ /** - * Class WPSEO_Import_Settings + * Class WPSEO_Import_Settings. * * Class with functionality to import the Yoast SEO settings. */ class WPSEO_Import_Settings { + /** + * Nonce action key. + * + * @var string + */ + const NONCE_ACTION = 'wpseo-import-settings'; + + /** + * Holds the import status instance. + * * @var WPSEO_Import_Status */ public $status; /** - * @var array - */ - private $file; - - /** + * Holds the old WPSEO version. + * * @var string */ - private $filename; + private $old_wpseo_version; /** - * @var string - */ - private $old_wpseo_version = null; - - /** - * @var string - */ - private $path; - - /** - * @var array - */ - private $upload_dir; - - /** - * Class constructor + * Class constructor. */ public function __construct() { $this->status = new WPSEO_Import_Status( 'import', false ); - if ( ! $this->handle_upload() ) { - return $this->status; - } - - $this->determine_path(); - - if ( ! $this->unzip_file() ) { - $this->clean_up(); - - return $this->status; - } - - $this->parse_options(); - - $this->clean_up(); } /** - * Handle the file upload + * Imports the data submitted by the user. * - * @return boolean Import status. + * @return void */ - private function handle_upload() { - $overrides = array( 'mimes' => array( 'zip' => 'application/zip' ) ); // Explicitly allow zip in multisite. - $this->file = wp_handle_upload( $_FILES['settings_import_file'], $overrides ); + public function import() { + check_admin_referer( self::NONCE_ACTION ); - if ( is_wp_error( $this->file ) ) { - $this->status->set_msg( __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ' . $this->file->get_error_message() ); - - return false; - } - - if ( is_array( $this->file ) && isset( $this->file['error'] ) ) { - $this->status->set_msg( __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ' . $this->file['error'] ); - - return false; - } - - if ( ! isset( $this->file['file'] ) ) { - $this->status->set_msg( __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ' . __( 'Upload failed.', 'wordpress-seo' ) ); - - return false; - } - - return true; - } - - /** - * Determine the path to the import file - */ - private function determine_path() { - $this->upload_dir = wp_upload_dir(); - - if ( ! defined( 'DIRECTORY_SEPARATOR' ) ) { - define( 'DIRECTORY_SEPARATOR', '/' ); - } - $this->path = $this->upload_dir['basedir'] . DIRECTORY_SEPARATOR . 'wpseo-import' . DIRECTORY_SEPARATOR; - - if ( ! isset( $GLOBALS['wp_filesystem'] ) || ! is_object( $GLOBALS['wp_filesystem'] ) ) { - WP_Filesystem(); - } - } - - /** - * Unzip the file - * - * @return boolean - */ - private function unzip_file() { - $unzipped = unzip_file( $this->file['file'], $this->path ); - $msg_base = __( 'Settings could not be imported:', 'wordpress-seo' ) . ' '; - - if ( is_wp_error( $unzipped ) ) { - /* translators: %s expands to an error message. */ - $this->status->set_msg( $msg_base . sprintf( __( 'Unzipping failed with error "%s".', 'wordpress-seo' ), $unzipped->get_error_message() ) ); - - return false; - } - - $this->filename = $this->path . 'settings.ini'; - if ( ! is_file( $this->filename ) || ! is_readable( $this->filename ) ) { - $this->status->set_msg( $msg_base . __( 'Unzipping failed - file settings.ini not found.', 'wordpress-seo' ) ); - - return false; - } - - return true; - } - - /** - * Parse the option file - */ - private function parse_options() { - if ( defined( 'INI_SCANNER_RAW' ) ) { - /* - * Implemented INI_SCANNER_RAW to make sure variables aren't parsed. - * - * http://php.net/manual/en/function.parse-ini-file.php#99943 - */ - $options = parse_ini_file( $this->filename, true, INI_SCANNER_RAW ); - } - else { - // PHP 5.2 does not implement the 3rd argument, this is a fallback. - $options = parse_ini_file( $this->filename, true ); - } - - if ( is_array( $options ) && $options !== array() ) { - $this->import_options( $options ); + if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) { return; } - $this->status->set_msg( __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ' . __( 'No settings found in file.', 'wordpress-seo' ) ); + + $content = filter_input( INPUT_POST, 'settings_import' ); + if ( empty( $content ) ) { + return; + } + + $this->parse_options( $content ); } /** - * Parse the option group and import it + * Parse the options. + * + * @param string $raw_options The content to parse. + * + * @return void + */ + protected function parse_options( $raw_options ) { + $options = parse_ini_string( $raw_options, true, INI_SCANNER_RAW ); + + if ( is_array( $options ) && $options !== [] ) { + $this->import_options( $options ); + + return; + } + + $this->status->set_msg( __( 'Settings could not be imported:', 'wordpress-seo' ) . ' ' . __( 'No settings found.', 'wordpress-seo' ) ); + } + + /** + * Parse the option group and import it. * * @param string $name Name string. * @param array $option_group Option group data. * @param array $options Options data. */ - private function parse_option_group( $name, $option_group, $options ) { + protected function parse_option_group( $name, $option_group, $options ) { // Make sure that the imported options are cleaned/converted on import. $option_instance = WPSEO_Options::get_option_instance( $name ); if ( is_object( $option_instance ) && method_exists( $option_instance, 'import' ) ) { @@ -174,28 +94,12 @@ class WPSEO_Import_Settings { } } - /** - * Remove the files - */ - private function clean_up() { - if ( file_exists( $this->filename ) && is_writable( $this->filename ) ) { - unlink( $this->filename ); - } - if ( ! empty( $this->file['file'] ) && file_exists( $this->file['file'] ) && is_writable( $this->file['file'] ) ) { - unlink( $this->file['file'] ); - } - if ( file_exists( $this->path ) && is_writable( $this->path ) ) { - $wp_file = new WP_Filesystem_Direct( $this->path ); - $wp_file->rmdir( $this->path, true ); - } - } - /** * Imports the options if found. * - * @param array $options The options parsed from the ini file. + * @param array $options The options parsed from the provided settings. */ - private function import_options( $options ) { + protected function import_options( $options ) { if ( isset( $options['wpseo']['version'] ) && $options['wpseo']['version'] !== '' ) { $this->old_wpseo_version = $options['wpseo']['version']; } @@ -203,7 +107,11 @@ class WPSEO_Import_Settings { foreach ( $options as $name => $option_group ) { $this->parse_option_group( $name, $option_group, $options ); } + $this->status->set_msg( __( 'Settings successfully imported.', 'wordpress-seo' ) ); $this->status->set_status( true ); + + // Reset the cached option values. + WPSEO_Options::clear_cache(); } } diff --git a/wp-content/plugins/wordpress-seo/admin/import/class-import-status.php b/wp-content/plugins/wordpress-seo/admin/import/class-import-status.php index b5a36607..c105d4a7 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/class-import-status.php +++ b/wp-content/plugins/wordpress-seo/admin/import/class-import-status.php @@ -6,11 +6,12 @@ */ /** - * Class WPSEO_ImportStatus + * Class WPSEO_ImportStatus. * * Holds the status of and message about imports. */ class WPSEO_Import_Status { + /** * The import status. * diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-abstract-plugin-importer.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-abstract-plugin-importer.php index 5520db84..94741778 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-abstract-plugin-importer.php +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-abstract-plugin-importer.php @@ -6,11 +6,12 @@ */ /** - * Class WPSEO_Plugin_Importer + * Class WPSEO_Plugin_Importer. * * Class with functionality to import meta data from other plugins. */ abstract class WPSEO_Plugin_Importer { + /** * Holds the import status object. * @@ -26,17 +27,23 @@ abstract class WPSEO_Plugin_Importer { protected $plugin_name; /** - * Meta key, used in SQL LIKE clause for detect query. + * Meta key, used in SQL LIKE clause for delete query. * * @var string */ protected $meta_key; + /** + * Array of meta keys to detect and import. + * + * @var array + */ + protected $clone_keys; + /** * Class constructor. */ - public function __construct() { - } + public function __construct() {} /** * Returns the string for the plugin we're importing from. @@ -98,6 +105,9 @@ abstract class WPSEO_Plugin_Importer { */ protected function cleanup() { global $wpdb; + if ( empty( $this->meta_key ) ) { + return true; + } $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE %s", @@ -106,13 +116,22 @@ abstract class WPSEO_Plugin_Importer { ); $result = $wpdb->__get( 'result' ); if ( ! $result ) { - /* translators: %s is replaced with the plugin's name. */ - $this->status->set_msg( sprintf( __( 'Cleanup of %s data failed.', 'wordpress-seo' ), $this->plugin_name ) ); + $this->cleanup_error_msg(); } return $result; } + /** + * Sets the status message for when a cleanup has gone bad. + * + * @return void + */ + protected function cleanup_error_msg() { + /* translators: %s is replaced with the plugin's name. */ + $this->status->set_msg( sprintf( __( 'Cleanup of %s data failed.', 'wordpress-seo' ), $this->plugin_name ) ); + } + /** * Detects whether an import for this plugin is needed. * @@ -135,12 +154,17 @@ abstract class WPSEO_Plugin_Importer { */ protected function detect() { global $wpdb; - $result = $wpdb->get_var( + + $meta_keys = wp_list_pluck( $this->clone_keys, 'old_key' ); + $result = $wpdb->get_var( $wpdb->prepare( - "SELECT COUNT(*) AS `count` FROM {$wpdb->postmeta} WHERE meta_key LIKE %s", - $this->meta_key + "SELECT COUNT(*) AS `count` + FROM {$wpdb->postmeta} + WHERE meta_key IN ( " . implode( ', ', array_fill( 0, count( $meta_keys ), '%s' ) ) . ' )', + $meta_keys ) ); + if ( $result === '0' ) { return false; } @@ -157,12 +181,13 @@ abstract class WPSEO_Plugin_Importer { * * @return bool Clone status. */ - protected function meta_key_clone( $old_key, $new_key, $replace_values = array() ) { + protected function meta_key_clone( $old_key, $new_key, $replace_values = [] ) { global $wpdb; // First we create a temp table with all the values for meta_key. $result = $wpdb->query( $wpdb->prepare( + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange -- This is intentional + temporary. "CREATE TEMPORARY TABLE tmp_meta_table SELECT * FROM {$wpdb->postmeta} WHERE meta_key = %s", $old_key ) @@ -171,6 +196,7 @@ abstract class WPSEO_Plugin_Importer { $this->set_missing_db_rights_status(); return false; } + // Delete all the values in our temp table for posts that already have data for $new_key. $wpdb->query( $wpdb->prepare( @@ -179,7 +205,10 @@ abstract class WPSEO_Plugin_Importer { ) ); - // We set meta_id to NULL so on re-insert into the postmeta table, MYSQL can set new meta_id's and we don't get duplicates. + /* + * We set meta_id to NULL so on re-insert into the postmeta table, MYSQL can set + * new meta_id's and we don't get duplicates. + */ $wpdb->query( 'UPDATE tmp_meta_table SET meta_id = NULL' ); // Now we rename the meta_key. @@ -196,6 +225,7 @@ abstract class WPSEO_Plugin_Importer { $wpdb->query( "INSERT INTO {$wpdb->postmeta} SELECT * FROM tmp_meta_table" ); // Now we drop our temporary table. + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange -- This is intentional + a temporary table. $wpdb->query( 'DROP TEMPORARY TABLE IF EXISTS tmp_meta_table' ); return true; @@ -210,7 +240,7 @@ abstract class WPSEO_Plugin_Importer { */ protected function meta_keys_clone( $clone_keys ) { foreach ( $clone_keys as $clone_key ) { - $result = $this->meta_key_clone( $clone_key['old_key'], $clone_key['new_key'], isset( $clone_key['convert'] ) ? $clone_key['convert'] : array() ); + $result = $this->meta_key_clone( $clone_key['old_key'], $clone_key['new_key'], isset( $clone_key['convert'] ) ? $clone_key['convert'] : [] ); if ( ! $result ) { return false; } @@ -227,6 +257,22 @@ abstract class WPSEO_Plugin_Importer { $this->status->set_msg( sprintf( __( 'The %s importer functionality uses temporary database tables. It seems your WordPress install does not have the capability to do this, please consult your hosting provider.', 'wordpress-seo' ), 'Yoast SEO' ) ); } + /** + * Helper function to search for a key in an array and maybe save it as a meta field. + * + * @param string $plugin_key The key in the $data array to check. + * @param string $yoast_key The identifier we use in our meta settings. + * @param array $data The array of data for this post to sift through. + * @param int $post_id The post ID. + * + * @return void + */ + protected function import_meta_helper( $plugin_key, $yoast_key, $data, $post_id ) { + if ( ! empty( $data[ $plugin_key ] ) ) { + $this->maybe_save_post_meta( $yoast_key, $data[ $plugin_key ], $post_id ); + } + } + /** * Saves a post meta value if it doesn't already exist. * @@ -235,9 +281,21 @@ abstract class WPSEO_Plugin_Importer { * @param int $post_id The Post to save the meta for. */ protected function maybe_save_post_meta( $new_key, $value, $post_id ) { - $existing_value = get_post_meta( $post_id, WPSEO_Meta::$meta_prefix . $new_key, true ); + // Big. Fat. Sigh. Mostly used for _yst_is_cornerstone, but might be useful for other hidden meta's. + $key = WPSEO_Meta::$meta_prefix . $new_key; + $wpseo_meta = true; + if ( substr( $new_key, 0, 1 ) === '_' ) { + $key = $new_key; + $wpseo_meta = false; + } + + $existing_value = get_post_meta( $post_id, $key, true ); if ( empty( $existing_value ) ) { - WPSEO_Meta::set_value( $new_key, $value, $post_id ); + if ( $wpseo_meta ) { + WPSEO_Meta::set_value( $new_key, $value, $post_id ); + return; + } + update_post_meta( $post_id, $new_key, $value ); } } @@ -252,7 +310,7 @@ abstract class WPSEO_Plugin_Importer { global $wpdb; // Now we replace values if needed. - if ( is_array( $replace_values ) && $replace_values !== array() ) { + if ( is_array( $replace_values ) && $replace_values !== [] ) { foreach ( $replace_values as $old_value => $new_value ) { $wpdb->query( $wpdb->prepare( diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-aioseo.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-aioseo.php index 478b7af1..4680bedb 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-aioseo.php +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-aioseo.php @@ -9,6 +9,7 @@ * Class with functionality to import & clean All in One SEO Pack post metadata. */ class WPSEO_Import_AIOSEO extends WPSEO_Plugin_Importer { + /** * The plugin name. * @@ -17,37 +18,49 @@ class WPSEO_Import_AIOSEO extends WPSEO_Plugin_Importer { protected $plugin_name = 'All In One SEO Pack'; /** - * Meta key, used in SQL LIKE clause for detect query. + * Meta key, used in SQL LIKE clause for delete query. * * @var string */ protected $meta_key = '_aioseop_%'; /** - * Array of keys to clone. + * OpenGraph keys to import. * * @var array */ - protected $clone_keys = array( - array( + protected $import_keys = [ + 'aioseop_opengraph_settings_title' => 'opengraph-title', + 'aioseop_opengraph_settings_desc' => 'opengraph-description', + 'aioseop_opengraph_settings_customimg' => 'opengraph-image', + 'aioseop_opengraph_settings_customimg_twitter' => 'twitter-image', + ]; + + /** + * Array of meta keys to detect and import. + * + * @var array + */ + protected $clone_keys = [ + [ 'old_key' => '_aioseop_title', 'new_key' => 'title', - ), - array( + ], + [ 'old_key' => '_aioseop_description', 'new_key' => 'metadesc', - ), - array( + ], + [ 'old_key' => '_aioseop_noindex', 'new_key' => 'meta-robots-noindex', - 'convert' => array( 'on' => 1 ), - ), - array( + 'convert' => [ 'on' => 1 ], + ], + [ 'old_key' => '_aioseop_nofollow', 'new_key' => 'meta-robots-nofollow', - 'convert' => array( 'on' => 1 ), - ), - ); + 'convert' => [ 'on' => 1 ], + ], + ]; /** * Import All In One SEO meta values. @@ -58,9 +71,8 @@ class WPSEO_Import_AIOSEO extends WPSEO_Plugin_Importer { $status = parent::import(); if ( $status ) { $this->import_opengraph(); - return true; } - return false; + return $status; } /** @@ -89,14 +101,7 @@ class WPSEO_Import_AIOSEO extends WPSEO_Plugin_Importer { $meta = get_post_meta( $post_id, '_aioseop_opengraph_settings', true ); $meta = maybe_unserialize( $meta ); - $import_keys = array( - 'aioseop_opengraph_settings_title' => 'opengraph-title', - 'aioseop_opengraph_settings_desc' => 'opengraph-description', - 'aioseop_opengraph_settings_customimg' => 'opengraph-image', - 'aioseop_opengraph_settings_customimg_twitter' => 'twitter-image', - ); - - foreach ( $import_keys as $old_key => $new_key ) { + foreach ( $this->import_keys as $old_key => $new_key ) { $this->maybe_save_post_meta( $new_key, $meta[ $old_key ], $post_id ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-greg-high-performance-seo.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-greg-high-performance-seo.php new file mode 100644 index 00000000..8925421f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-greg-high-performance-seo.php @@ -0,0 +1,42 @@ + '_ghpseo_alternative_description', + 'new_key' => 'metadesc', + ], + [ + 'old_key' => '_ghpseo_secondary_title', + 'new_key' => 'title', + ], + ]; +} diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-headspace.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-headspace.php index 87f3f038..3a43d169 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-headspace.php +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-headspace.php @@ -6,11 +6,12 @@ */ /** - * Class WPSEO_Import_HeadSpace + * Class WPSEO_Import_HeadSpace. * * Class with functionality to import & clean HeadSpace SEO post metadata. */ class WPSEO_Import_HeadSpace extends WPSEO_Plugin_Importer { + /** * The plugin name. * @@ -19,35 +20,35 @@ class WPSEO_Import_HeadSpace extends WPSEO_Plugin_Importer { protected $plugin_name = 'HeadSpace SEO'; /** - * Meta key, used in SQL LIKE clause for detect query. + * Meta key, used in SQL LIKE clause for delete query. * * @var string */ protected $meta_key = '_headspace_%'; /** - * The arrays of keys to clone into Yoast SEO. + * Array of meta keys to detect and import. * * @var array */ - protected $clone_keys = array( - array( + protected $clone_keys = [ + [ 'old_key' => '_headspace_description', 'new_key' => 'metadesc', - ), - array( + ], + [ 'old_key' => '_headspace_page_title', 'new_key' => 'title', - ), - array( + ], + [ 'old_key' => '_headspace_noindex', 'new_key' => 'meta-robots-noindex', - 'convert' => array( 'on' => 1 ), - ), - array( + 'convert' => [ 'on' => 1 ], + ], + [ 'old_key' => '_headspace_nofollow', 'new_key' => 'meta-robots-nofollow', - 'convert' => array( 'on' => 1 ), - ), - ); + 'convert' => [ 'on' => 1 ], + ], + ]; } diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-jetpack.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-jetpack.php index 58c8bad8..5f57d816 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-jetpack.php +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-jetpack.php @@ -6,11 +6,12 @@ */ /** - * Class WPSEO_Import_Jetpack_SEO + * Class WPSEO_Import_Jetpack_SEO. * * Class with functionality to import & clean Jetpack SEO post metadata. */ class WPSEO_Import_Jetpack_SEO extends WPSEO_Plugin_Importer { + /** * The plugin name. * @@ -19,22 +20,21 @@ class WPSEO_Import_Jetpack_SEO extends WPSEO_Plugin_Importer { protected $plugin_name = 'Jetpack'; /** - * Meta key, used in SQL LIKE clause for detect query. + * Meta key, used in SQL LIKE clause for delete query. * * @var string */ protected $meta_key = 'advanced_seo_description'; /** - * The arrays of keys to clone into Yoast SEO. + * Array of meta keys to detect and import. * * @var array */ - protected $clone_keys = array( - array( + protected $clone_keys = [ + [ 'old_key' => 'advanced_seo_description', 'new_key' => 'metadesc', - ), - ); - + ], + ]; } diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-platinum-seo-pack.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-platinum-seo-pack.php new file mode 100644 index 00000000..16a5ce9e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-platinum-seo-pack.php @@ -0,0 +1,138 @@ + 'description', + 'new_key' => 'metadesc', + ], + [ + 'old_key' => 'title', + 'new_key' => 'title', + ], + ]; + + /** + * Runs the import of post meta keys stored by Platinum SEO Pack. + * + * @return bool + */ + protected function import() { + $return = parent::import(); + if ( $return ) { + $this->import_robots_meta(); + } + + return $return; + } + + /** + * Cleans up all the meta values Platinum SEO pack creates. + * + * @return bool + */ + protected function cleanup() { + $this->meta_key = 'title'; + parent::cleanup(); + + $this->meta_key = 'description'; + parent::cleanup(); + + $this->meta_key = 'metarobots'; + parent::cleanup(); + + return true; + } + + /** + * Finds all the robotsmeta fields to import and deals with them. + * + * There are four potential values that Platinum SEO stores: + * - index,folllow + * - index,nofollow + * - noindex,follow + * - noindex,nofollow + * + * We only have to deal with the latter 3, the first is our default. + * + * @return void + */ + protected function import_robots_meta() { + $this->import_by_meta_robots( 'index,nofollow', [ 'nofollow' ] ); + $this->import_by_meta_robots( 'noindex,follow', [ 'noindex' ] ); + $this->import_by_meta_robots( 'noindex,nofollow', [ 'noindex', 'nofollow' ] ); + } + + /** + * Imports the values for all index, nofollow posts. + * + * @param string $value The meta robots value to find posts for. + * @param array $metas The meta field(s) to save. + * + * @return void + */ + protected function import_by_meta_robots( $value, $metas ) { + $posts = $this->find_posts_by_robots_meta( $value ); + if ( ! $posts ) { + return; + } + + foreach ( $posts as $post_id ) { + foreach ( $metas as $meta ) { + $this->maybe_save_post_meta( 'meta-robots-' . $meta, 1, $post_id ); + } + } + } + + /** + * Finds posts by a given meta robots value. + * + * @param string $meta_value Robots meta value. + * + * @return array|bool Array of Post IDs on success, false on failure. + */ + protected function find_posts_by_robots_meta( $meta_value ) { + $posts = get_posts( + [ + 'post_type' => 'any', + 'meta_key' => 'robotsmeta', + 'meta_value' => $meta_value, + 'order' => 'ASC', + 'fields' => 'ids', + 'nopaging' => true, + ] + ); + if ( empty( $posts ) ) { + return false; + } + return $posts; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-premium-seo-pack.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-premium-seo-pack.php new file mode 100644 index 00000000..bd93b91e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-premium-seo-pack.php @@ -0,0 +1,39 @@ +table_name = $wpdb->prefix . 'psp'; + $this->meta_key = ''; + } + + /** + * Returns the query to return an identifier for the posts to import. + * + * @return string + */ + protected function retrieve_posts_query() { + return "SELECT URL AS identifier FROM {$this->table_name} WHERE blog_id = %d"; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-rankmath.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-rankmath.php new file mode 100644 index 00000000..9007f0fc --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-rankmath.php @@ -0,0 +1,175 @@ + 'rank_math_description', + 'new_key' => 'metadesc', + ], + [ + 'old_key' => 'rank_math_title', + 'new_key' => 'title', + ], + [ + 'old_key' => 'rank_math_canonical_url', + 'new_key' => 'canonical', + ], + [ + 'old_key' => 'rank_math_primary_category', + 'new_key' => 'primary_category', + ], + [ + 'old_key' => 'rank_math_facebook_title', + 'new_key' => 'opengraph-title', + ], + [ + 'old_key' => 'rank_math_facebook_description', + 'new_key' => 'opengraph-description', + ], + [ + 'old_key' => 'rank_math_facebook_image', + 'new_key' => 'opengraph-image', + ], + [ + 'old_key' => 'rank_math_facebook_image_id', + 'new_key' => 'opengraph-image-id', + ], + [ + 'old_key' => 'rank_math_twitter_title', + 'new_key' => 'twitter-title', + ], + [ + 'old_key' => 'rank_math_twitter_description', + 'new_key' => 'twitter-description', + ], + [ + 'old_key' => 'rank_math_twitter_image', + 'new_key' => 'twitter-image', + ], + [ + 'old_key' => 'rank_math_twitter_image_id', + 'new_key' => 'twitter-image-id', + ], + [ + 'old_key' => 'rank_math_focus_keyword', + 'new_key' => 'focuskw', + ], + ]; + + /** + * Handles post meta data to import. + * + * @return bool Import success status. + */ + protected function import() { + global $wpdb; + // Replace % with %% as their variables are the same except for that. + $wpdb->query( "UPDATE $wpdb->postmeta SET meta_value = REPLACE( meta_value, '%', '%%' ) WHERE meta_key IN ( 'rank_math_description', 'rank_math_title' )" ); + + $this->import_meta_robots(); + $return = $this->meta_keys_clone( $this->clone_keys ); + + // Return %% to % so our import is non-destructive. + $wpdb->query( "UPDATE $wpdb->postmeta SET meta_value = REPLACE( meta_value, '%%', '%' ) WHERE meta_key IN ( 'rank_math_description', 'rank_math_title' )" ); + + if ( $return ) { + $this->import_settings(); + } + + return $return; + } + + /** + * RankMath stores robots meta quite differently, so we have to parse it out. + */ + private function import_meta_robots() { + global $wpdb; + $post_metas = $wpdb->get_results( "SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = 'rank_math_robots'" ); + foreach ( $post_metas as $post_meta ) { + // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- Reason: We can't control the form in which Rankmath sends the data. + $robots_values = unserialize( $post_meta->meta_value ); + foreach ( [ 'noindex', 'nofollow' ] as $directive ) { + $directive_key = array_search( $directive, $robots_values, true ); + if ( $directive_key !== false ) { + update_post_meta( $post_meta->post_id, '_yoast_wpseo_meta-robots-' . $directive, 1 ); + unset( $robots_values[ $directive_key ] ); + } + } + if ( count( $robots_values ) > 0 ) { + $value = implode( ',', $robots_values ); + update_post_meta( $post_meta->post_id, '_yoast_wpseo_meta-robots-adv', $value ); + } + } + } + + /** + * Imports some of the RankMath settings. + */ + private function import_settings() { + $settings = [ + 'title_separator' => 'separator', + 'homepage_title' => 'title-home-wpseo', + 'homepage_description' => 'metadesc-home-wpseo', + 'author_archive_title' => 'title-author-wpseo', + 'date_archive_title' => 'title-archive-wpseo', + 'search_title' => 'title-search-wpseo', + '404_title' => 'title-404-wpseo', + 'pt_post_title' => 'title-post', + 'pt_page_title' => 'title-page', + ]; + $options = get_option( 'rank-math-options-titles' ); + + foreach ( $settings as $import_setting_key => $setting_key ) { + if ( ! empty( $options[ $import_setting_key ] ) ) { + $value = $options[ $import_setting_key ]; + // Make sure replace vars work. + $value = str_replace( '%', '%%', $value ); + WPSEO_Options::set( $setting_key, $value ); + } + } + } + + /** + * Removes the plugin data from the database. + * + * @return bool Cleanup status. + */ + protected function cleanup() { + $return = parent::cleanup(); + if ( $return ) { + global $wpdb; + $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'rank-math-%'" ); + $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '%rank_math%'" ); + } + + return $return; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-seo-framework.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-seo-framework.php new file mode 100644 index 00000000..8bdfa060 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-seo-framework.php @@ -0,0 +1,94 @@ + '_genesis_description', + 'new_key' => 'metadesc', + ], + [ + 'old_key' => '_genesis_title', + 'new_key' => 'title', + ], + [ + 'old_key' => '_genesis_noindex', + 'new_key' => 'meta-robots-noindex', + ], + [ + 'old_key' => '_genesis_nofollow', + 'new_key' => 'meta-robots-nofollow', + ], + [ + 'old_key' => '_genesis_canonical_uri', + 'new_key' => 'canonical', + ], + [ + 'old_key' => '_open_graph_title', + 'new_key' => 'opengraph-title', + ], + [ + 'old_key' => '_open_graph_description', + 'new_key' => 'opengraph-description', + ], + [ + 'old_key' => '_social_image_url', + 'new_key' => 'opengraph-image', + ], + [ + 'old_key' => '_twitter_title', + 'new_key' => 'twitter-title', + ], + [ + 'old_key' => '_twitter_description', + 'new_key' => 'twitter-description', + ], + ]; + + /** + * Removes all the metadata set by the SEO Framework plugin. + * + * @return bool + */ + protected function cleanup() { + $set1 = parent::cleanup(); + + $this->meta_key = '_social_image_%'; + $set2 = parent::cleanup(); + + $this->meta_key = '_twitter_%'; + $set3 = parent::cleanup(); + + $this->meta_key = '_open_graph_%'; + $set4 = parent::cleanup(); + + return ( $set1 || $set2 || $set3 || $set4 ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-seopressor.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-seopressor.php index 829549ae..d62aadc2 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-seopressor.php +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-seopressor.php @@ -6,11 +6,12 @@ */ /** - * Class WPSEO_Import_SEOPressor + * Class WPSEO_Import_SEOPressor. * * Class with functionality to import & clean SEOPressor post metadata. */ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer { + /** * The plugin name. * @@ -19,12 +20,23 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer { protected $plugin_name = 'SEOpressor'; /** - * Meta key, used in SQL LIKE clause for detect query. + * Meta key, used in SQL LIKE clause for delete query. * * @var string */ protected $meta_key = '_seop_settings'; + /** + * Array of meta keys to detect and import. + * + * @var array + */ + protected $clone_keys = [ + [ + 'old_key' => '_seop_settings', + ], + ]; + /** * Imports the post meta values to Yoast SEO. * @@ -64,7 +76,7 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer { $settings = get_post_meta( $post_id, '_seop_settings', true ); foreach ( - array( + [ 'fb_description' => 'opengraph-description', 'fb_title' => 'opengraph-title', 'fb_type' => 'og_type', @@ -75,7 +87,7 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer { 'tw_description' => 'twitter-description', 'tw_title' => 'twitter-title', 'tw_image' => 'twitter-image', - ) as $seopressor_key => $yoast_key ) { + ] as $seopressor_key => $yoast_key ) { $this->import_meta_helper( $seopressor_key, $yoast_key, $settings, $post_id ); } @@ -84,26 +96,10 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer { } } - /** - * Represents the Helper function to store the meta value should it be set in SEOPressor's settings. - * - * @param string $seo_pressor_key The key in the SEOPressor array. - * @param string $yoast_key The identifier we use in our meta settings. - * @param array $seopressor_settings The array of settings for this post in SEOpressor. - * @param int $post_id The post ID. - * - * @return void - */ - private function import_meta_helper( $seo_pressor_key, $yoast_key, $seopressor_settings, $post_id ) { - if ( ! empty( $seopressor_settings[ $seo_pressor_key ] ) ) { - $this->maybe_save_post_meta( $yoast_key, $seopressor_settings[ $seo_pressor_key ], $post_id ); - } - } - /** * Imports the focus keywords, and stores them for later use. * - * @param integer $post_id Post ID. + * @param int $post_id Post ID. * * @return void */ @@ -116,7 +112,7 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer { $focuskw2 = trim( get_post_meta( $post_id, '_seop_kw_2', true ) ); $focuskw3 = trim( get_post_meta( $post_id, '_seop_kw_3', true ) ); - $focus_keywords = array(); + $focus_keywords = []; if ( ! empty( $focuskw2 ) ) { $focus_keywords[] = $focuskw2; } @@ -124,16 +120,16 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer { $focus_keywords[] = $focuskw3; } - if ( $focus_keywords !== array() ) { - $this->maybe_save_post_meta( 'focuskeywords', wp_json_encode( $focus_keywords ), $post_id ); + if ( $focus_keywords !== [] ) { + $this->maybe_save_post_meta( 'focuskeywords', WPSEO_Utils::format_json_encode( $focus_keywords ), $post_id ); } } /** * Retrieves the SEOpressor robot value and map this to Yoast SEO values. * - * @param string $meta_rules The meta rules taken from the SEOpressor settings array. - * @param integer $post_id The post id of the current post. + * @param string $meta_rules The meta rules taken from the SEOpressor settings array. + * @param int $post_id The post id of the current post. * * @return void */ @@ -155,11 +151,11 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer { * @return array The robots values in Yoast format. */ private function get_robot_value( $seopressor_robots ) { - $return = array( + $return = [ 'index' => 2, 'follow' => 0, 'advanced' => '', - ); + ]; if ( in_array( 'noindex', $seopressor_robots, true ) ) { $return['index'] = 1; @@ -167,7 +163,7 @@ class WPSEO_Import_SEOPressor extends WPSEO_Plugin_Importer { if ( in_array( 'nofollow', $seopressor_robots, true ) ) { $return['follow'] = 1; } - foreach ( array( 'noarchive', 'nosnippet', 'noimageindex' ) as $needle ) { + foreach ( [ 'noarchive', 'nosnippet', 'noimageindex' ] as $needle ) { if ( in_array( $needle, $seopressor_robots, true ) ) { $return['advanced'] .= $needle . ','; } diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-smartcrawl.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-smartcrawl.php new file mode 100644 index 00000000..507120c6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-smartcrawl.php @@ -0,0 +1,151 @@ + '_wds_metadesc', + 'new_key' => 'metadesc', + ], + [ + 'old_key' => '_wds_title', + 'new_key' => 'title', + ], + [ + 'old_key' => '_wds_canonical', + 'new_key' => 'canonical', + ], + [ + 'old_key' => '_wds_focus-keywords', + 'new_key' => 'focuskw', + ], + [ + 'old_key' => '_wds_meta-robots-noindex', + 'new_key' => 'meta-robots-noindex', + ], + [ + 'old_key' => '_wds_meta-robots-nofollow', + 'new_key' => 'meta-robots-nofollow', + ], + ]; + + /** + * Used for importing Twitter and Facebook meta's. + * + * @var array + */ + protected $social_keys = []; + + /** + * Handles post meta data to import. + * + * @return bool Import success status. + */ + protected function import() { + $return = parent::import(); + if ( $return ) { + $this->import_opengraph(); + $this->import_twitter(); + } + + return $return; + } + + /** + * Imports the OpenGraph meta keys saved by Smartcrawl. + * + * @return bool Import status. + */ + protected function import_opengraph() { + $this->social_keys = [ + 'title' => 'opengraph-title', + 'description' => 'opengraph-description', + 'images' => 'opengraph-image', + ]; + return $this->post_find_import( '_wds_opengraph' ); + } + + /** + * Imports the Twitter meta keys saved by Smartcrawl. + * + * @return bool Import status. + */ + protected function import_twitter() { + $this->social_keys = [ + 'title' => 'twitter-title', + 'description' => 'twitter-description', + ]; + return $this->post_find_import( '_wds_twitter' ); + } + + /** + * Imports a post's serialized post meta values. + * + * @param int $post_id Post ID. + * @param string $key The meta key to import. + * + * @return void + */ + protected function import_serialized_post_meta( $post_id, $key ) { + $data = get_post_meta( $post_id, $key, true ); + $data = maybe_unserialize( $data ); + foreach ( $this->social_keys as $key => $meta_key ) { + if ( ! isset( $data[ $key ] ) ) { + return; + } + $value = $data[ $key ]; + if ( is_array( $value ) ) { + $value = $value[0]; + } + $this->maybe_save_post_meta( $meta_key, $value, $post_id ); + } + } + + /** + * Finds all the posts with a certain meta key and imports its values. + * + * @param string $key The meta key to search for. + * + * @return bool Import status. + */ + protected function post_find_import( $key ) { + $query_posts = new WP_Query( 'post_type=any&meta_key=' . $key . '&order=ASC&fields=ids&nopaging=true' ); + + if ( empty( $query_posts->posts ) ) { + return false; + } + + foreach ( array_values( $query_posts->posts ) as $post_id ) { + $this->import_serialized_post_meta( $post_id, $key ); + } + + return true; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-squirrly.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-squirrly.php new file mode 100644 index 00000000..2c088e26 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-squirrly.php @@ -0,0 +1,224 @@ + 'meta-robots-noindex', + 'nofollow' => 'meta-robots-nofollow', + 'title' => 'title', + 'description' => 'metadesc', + 'canonical' => 'canonical', + 'cornerstone' => '_yst_is_cornerstone', + 'tw_media' => 'twitter-image', + 'tw_title' => 'twitter-title', + 'tw_description' => 'twitter-description', + 'og_title' => 'opengraph-title', + 'og_description' => 'opengraph-description', + 'og_media' => 'opengraph-image', + 'focuskw' => 'focuskw', + ]; + + /** + * WPSEO_Import_Squirrly constructor. + */ + public function __construct() { + parent::__construct(); + + global $wpdb; + $this->table_name = $wpdb->prefix . 'qss'; + } + + /** + * Imports the post meta values to Yoast SEO. + * + * @return bool Import success status. + */ + protected function import() { + $results = $this->retrieve_posts(); + foreach ( $results as $post ) { + $return = $this->import_post_values( $post->identifier ); + if ( ! $return ) { + return false; + } + } + + return true; + } + + /** + * Retrieve the posts from the Squirrly Database. + * + * @return array Array of post IDs from the DB. + */ + protected function retrieve_posts() { + global $wpdb; + return $wpdb->get_results( + $wpdb->prepare( + $this->retrieve_posts_query(), + get_current_blog_id() + ) + ); + } + + /** + * Returns the query to return an identifier for the posts to import. + * + * @return string Query to get post ID's from the DB. + */ + protected function retrieve_posts_query() { + return "SELECT post_id AS identifier FROM {$this->table_name} WHERE blog_id = %d"; + } + + /** + * Removes the DB table and the post meta field Squirrly creates. + * + * @return bool Cleanup status. + */ + protected function cleanup() { + global $wpdb; + + // If we can clean, let's clean. + $wpdb->query( "DROP TABLE {$this->table_name}" ); + + // This removes the post meta field for the focus keyword from the DB. + parent::cleanup(); + + // If we can still see the table, something went wrong. + if ( $this->detect() ) { + $this->cleanup_error_msg(); + return false; + } + + return true; + } + + /** + * Detects whether there is post meta data to import. + * + * @return bool Boolean indicating whether there is something to import. + */ + protected function detect() { + global $wpdb; + + $result = $wpdb->get_var( "SHOW TABLES LIKE '{$this->table_name}'" ); + if ( is_wp_error( $result ) || is_null( $result ) ) { + return false; + } + + return true; + } + + /** + * Imports the data of a post out of Squirrly's DB table. + * + * @param mixed $post_identifier Post identifier, can be ID or string. + * + * @return bool Import status. + */ + private function import_post_values( $post_identifier ) { + $data = $this->retrieve_post_data( $post_identifier ); + if ( ! $data ) { + return false; + } + + if ( ! is_numeric( $post_identifier ) ) { + $post_id = url_to_postid( $post_identifier ); + } + + if ( is_numeric( $post_identifier ) ) { + $post_id = (int) $post_identifier; + $data['focuskw'] = $this->maybe_add_focus_kw( $post_identifier ); + } + + foreach ( $this->seo_field_keys as $squirrly_key => $yoast_key ) { + $this->import_meta_helper( $squirrly_key, $yoast_key, $data, $post_id ); + } + return true; + } + + /** + * Retrieves the Squirrly SEO data for a post from the DB. + * + * @param int $post_identifier Post ID. + * + * @return array|bool Array of data or false. + */ + private function retrieve_post_data( $post_identifier ) { + global $wpdb; + + if ( is_numeric( $post_identifier ) ) { + $post_identifier = (int) $post_identifier; + $query_where = 'post_id = %d'; + } + if ( ! is_numeric( $post_identifier ) ) { + $query_where = 'URL = %s'; + } + + $replacements = [ + get_current_blog_id(), + $post_identifier, + ]; + + $data = $wpdb->get_var( + $wpdb->prepare( + "SELECT seo FROM {$this->table_name} WHERE blog_id = %d AND " . $query_where, + $replacements + ) + ); + if ( ! $data || is_wp_error( $data ) ) { + return false; + } + $data = maybe_unserialize( $data ); + return $data; + } + + /** + * Squirrly stores the focus keyword in post meta. + * + * @param int $post_id Post ID. + * + * @return string The focus keyword. + */ + private function maybe_add_focus_kw( $post_id ) { + $focuskw = get_post_meta( $post_id, '_sq_post_keyword', true ); + if ( $focuskw ) { + $focuskw = json_decode( $focuskw ); + return $focuskw->keyword; + } + return ''; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-ultimate-seo.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-ultimate-seo.php index 7c3e9b5d..a5113650 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-ultimate-seo.php +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-ultimate-seo.php @@ -9,6 +9,7 @@ * Class with functionality to import & clean Ultimate SEO post metadata. */ class WPSEO_Import_Ultimate_SEO extends WPSEO_Plugin_Importer { + /** * The plugin name. * @@ -17,48 +18,47 @@ class WPSEO_Import_Ultimate_SEO extends WPSEO_Plugin_Importer { protected $plugin_name = 'Ultimate SEO'; /** - * Meta key, used in SQL LIKE clause for detect query. + * Meta key, used in SQL LIKE clause for delete query. * * @var string */ protected $meta_key = '_su_%'; /** - * The arrays of keys to clone into Yoast SEO. + * Array of meta keys to detect and import. * * @var array */ - protected $clone_keys = array( - array( + protected $clone_keys = [ + [ 'old_key' => '_su_description', 'new_key' => 'metadesc', - ), - array( + ], + [ 'old_key' => '_su_title', 'new_key' => 'title', - ), - array( + ], + [ 'old_key' => '_su_og_title', 'new_key' => 'opengraph-title', - ), - array( + ], + [ 'old_key' => '_su_og_description', 'new_key' => 'opengraph-description', - ), - array( + ], + [ 'old_key' => '_su_og_image', 'new_key' => 'opengraph-image', - ), - array( + ], + [ 'old_key' => '_su_meta_robots_noindex', 'new_key' => 'meta-robots-noindex', - 'convert' => array( 'on' => 1 ), - ), - array( + 'convert' => [ 'on' => 1 ], + ], + [ 'old_key' => '_su_meta_robots_nofollow', 'new_key' => 'meta-robots-nofollow', - 'convert' => array( 'on' => 1 ), - ), - ); - + 'convert' => [ 'on' => 1 ], + ], + ]; } diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-woothemes-seo.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-woothemes-seo.php index d514bc16..5ee943c3 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-woothemes-seo.php +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-woothemes-seo.php @@ -11,6 +11,7 @@ * Class with functionality to import & clean WooThemes SEO post metadata. */ class WPSEO_Import_WooThemes_SEO extends WPSEO_Plugin_Importer { + /** * The plugin name. * @@ -19,55 +20,55 @@ class WPSEO_Import_WooThemes_SEO extends WPSEO_Plugin_Importer { protected $plugin_name = 'WooThemes SEO'; /** - * Meta key, used in SQL LIKE clause for detect query. + * Meta key, used in SQL LIKE clause for delete query. * * @var string */ protected $meta_key = 'seo_title'; /** - * The arrays of keys to clone into Yoast SEO. + * Array of meta keys to detect and import. * * @var array */ - protected $clone_keys = array( - array( + protected $clone_keys = [ + [ 'old_key' => 'seo_description', 'new_key' => 'metadesc', - ), - array( + ], + [ 'old_key' => 'seo_title', 'new_key' => 'title', - ), - array( + ], + [ 'old_key' => 'seo_noindex', 'new_key' => 'meta-robots-noindex', - ), - array( + ], + [ 'old_key' => 'seo_follow', 'new_key' => 'meta-robots-nofollow', - ), - ); + ], + ]; /** * Holds the meta fields we can delete after import. * * @var array */ - protected $cleanup_metas = array( + protected $cleanup_metas = [ 'seo_follow', 'seo_noindex', 'seo_title', 'seo_description', 'seo_keywords', - ); + ]; /** * Holds the options we can delete after import. * * @var array */ - protected $cleanup_options = array( + protected $cleanup_options = [ 'seo_woo_archive_layout', 'seo_woo_single_layout', 'seo_woo_page_layout', @@ -75,7 +76,7 @@ class WPSEO_Import_WooThemes_SEO extends WPSEO_Plugin_Importer { 'seo_woo_meta_single_desc', 'seo_woo_meta_single_key', 'seo_woo_home_layout', - ); + ]; /** * Cleans up the WooThemes SEO settings. @@ -134,5 +135,4 @@ class WPSEO_Import_WooThemes_SEO extends WPSEO_Plugin_Importer { ); return $wpdb->__get( 'result' ); } - } diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-wp-meta-seo.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-wp-meta-seo.php new file mode 100644 index 00000000..e6a55efb --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-wp-meta-seo.php @@ -0,0 +1,82 @@ + '_metaseo_metadesc', + 'new_key' => 'metadesc', + ], + [ + 'old_key' => '_metaseo_metatitle', + 'new_key' => 'title', + ], + [ + 'old_key' => '_metaseo_metaopengraph-title', + 'new_key' => 'opengraph-title', + ], + [ + 'old_key' => '_metaseo_metaopengraph-desc', + 'new_key' => 'opengraph-description', + ], + [ + 'old_key' => '_metaseo_metaopengraph-image', + 'new_key' => 'opengraph-image', + ], + [ + 'old_key' => '_metaseo_metatwitter-title', + 'new_key' => 'twitter-title', + ], + [ + 'old_key' => '_metaseo_metatwitter-desc', + 'new_key' => 'twitter-description', + ], + [ + 'old_key' => '_metaseo_metatwitter-image', + 'new_key' => 'twitter-image', + ], + [ + 'old_key' => '_metaseo_metaindex', + 'new_key' => 'meta-robots-noindex', + 'convert' => [ + 'index' => 0, + 'noindex' => 1, + ], + ], + [ + 'old_key' => '_metaseo_metafollow', + 'new_key' => 'meta-robots-nofollow', + 'convert' => [ + 'follow' => 0, + 'nofollow' => 1, + ], + ], + ]; +} diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-wpseo.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-wpseo.php index 8ae0ac10..f8dfe347 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-wpseo.php +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-import-wpseo.php @@ -6,11 +6,12 @@ */ /** - * Class WPSEO_Import_WPSEO + * Class WPSEO_Import_WPSEO. * * Class with functionality to import & clean wpSEO.de post metadata. */ class WPSEO_Import_WPSEO extends WPSEO_Plugin_Importer { + /** * The plugin name. * @@ -19,31 +20,55 @@ class WPSEO_Import_WPSEO extends WPSEO_Plugin_Importer { protected $plugin_name = 'wpSEO.de'; /** - * Meta key, used in SQL LIKE clause for detect query. + * Meta key, used in SQL LIKE clause for delete query. * * @var string */ protected $meta_key = '_wpseo_edit_%'; /** - * The arrays of keys to clone into Yoast SEO. + * Array of meta keys to detect and import. * * @var array */ - protected $clone_keys = array( - array( + protected $clone_keys = [ + [ 'old_key' => '_wpseo_edit_description', 'new_key' => 'metadesc', - ), - array( + ], + [ 'old_key' => '_wpseo_edit_title', 'new_key' => 'title', - ), - array( + ], + [ 'old_key' => '_wpseo_edit_canonical', 'new_key' => 'canonical', - ), - ); + ], + [ + 'old_key' => '_wpseo_edit_og_title', + 'new_key' => 'opengraph-title', + ], + [ + 'old_key' => '_wpseo_edit_og_description', + 'new_key' => 'opengraph-description', + ], + [ + 'old_key' => '_wpseo_edit_og_image', + 'new_key' => 'opengraph-image', + ], + [ + 'old_key' => '_wpseo_edit_twittercard_title', + 'new_key' => 'twitter-title', + ], + [ + 'old_key' => '_wpseo_edit_twittercard_description', + 'new_key' => 'twitter-description', + ], + [ + 'old_key' => '_wpseo_edit_twittercard_image', + 'new_key' => 'twitter-image', + ], + ]; /** * The values 1 - 6 are the configured values from wpSEO. This array will map the values of wpSEO to our values. @@ -53,38 +78,38 @@ class WPSEO_Import_WPSEO extends WPSEO_Plugin_Importer { * * @var array */ - private $robot_values = array( + private $robot_values = [ // In wpSEO: index, follow. - 1 => array( + 1 => [ 'index' => 2, 'follow' => 0, - ), + ], // In wpSEO: index, nofollow. - 2 => array( + 2 => [ 'index' => 2, 'follow' => 1, - ), + ], // In wpSEO: noindex. - 3 => array( + 3 => [ 'index' => 1, 'follow' => 0, - ), + ], // In wpSEO: noindex, follow. - 4 => array( + 4 => [ 'index' => 1, 'follow' => 0, - ), + ], // In wpSEO: noindex, nofollow. - 5 => array( + 5 => [ 'index' => 1, 'follow' => 1, - ), + ], // In wpSEO: index. - 6 => array( + 6 => [ 'index' => 2, 'follow' => 0, - ), - ); + ], + ]; /** * Imports wpSEO settings. @@ -149,7 +174,7 @@ class WPSEO_Import_WPSEO extends WPSEO_Plugin_Importer { /** * Gets the wpSEO robot value and map this to Yoast SEO values. * - * @param integer $post_id The post id of the current post. + * @param int $post_id The post id of the current post. * * @return void */ @@ -168,7 +193,7 @@ class WPSEO_Import_WPSEO extends WPSEO_Plugin_Importer { * @return void */ private function import_taxonomy_metas() { - $terms = get_terms( get_taxonomies(), array( 'hide_empty' => false ) ); + $terms = get_terms( get_taxonomies(), [ 'hide_empty' => false ] ); $tax_meta = get_option( 'wpseo_taxonomy_meta' ); foreach ( $terms as $term ) { @@ -188,7 +213,7 @@ class WPSEO_Import_WPSEO extends WPSEO_Plugin_Importer { * * @return void */ - private function import_taxonomy_description( & $tax_meta, $taxonomy, $term_id ) { + private function import_taxonomy_description( &$tax_meta, $taxonomy, $term_id ) { $description = get_option( 'wpseo_' . $taxonomy . '_' . $term_id, false ); if ( $description !== false ) { // Import description. @@ -205,7 +230,7 @@ class WPSEO_Import_WPSEO extends WPSEO_Plugin_Importer { * * @return void */ - private function import_taxonomy_robots( & $tax_meta, $taxonomy, $term_id ) { + private function import_taxonomy_robots( &$tax_meta, $taxonomy, $term_id ) { $wpseo_robots = get_option( 'wpseo_' . $taxonomy . '_' . $term_id . '_robots', false ); if ( $wpseo_robots === false ) { return; @@ -213,7 +238,7 @@ class WPSEO_Import_WPSEO extends WPSEO_Plugin_Importer { // The value 1, 2 and 6 are the index values in wpSEO. $new_robot_value = 'noindex'; - if ( in_array( (int) $wpseo_robots, array( 1, 2, 6 ), true ) ) { + if ( in_array( (int) $wpseo_robots, [ 1, 2, 6 ], true ) ) { $new_robot_value = 'index'; } @@ -266,7 +291,7 @@ class WPSEO_Import_WPSEO extends WPSEO_Plugin_Importer { * @return void */ private function cleanup_term_meta() { - $terms = get_terms( get_taxonomies(), array( 'hide_empty' => false ) ); + $terms = get_terms( get_taxonomies(), [ 'hide_empty' => false ] ); foreach ( $terms as $term ) { $this->delete_taxonomy_metas( $term->taxonomy, $term->term_id ); } diff --git a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-importers.php b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-importers.php index ff76c5b1..a3a66301 100644 --- a/wp-content/plugins/wordpress-seo/admin/import/plugins/class-importers.php +++ b/wp-content/plugins/wordpress-seo/admin/import/plugins/class-importers.php @@ -6,23 +6,34 @@ */ /** - * Class WPSEO_Plugin_Importers + * Class WPSEO_Plugin_Importers. * * Object which contains all importers. */ class WPSEO_Plugin_Importers { + /** + * List of supported importers. + * * @var array */ - private static $importers = array( + private static $importers = [ 'WPSEO_Import_AIOSEO', + 'WPSEO_Import_Greg_SEO', 'WPSEO_Import_HeadSpace', 'WPSEO_Import_Jetpack_SEO', + 'WPSEO_Import_WP_Meta_SEO', + 'WPSEO_Import_Platinum_SEO', + 'WPSEO_Import_Premium_SEO_Pack', + 'WPSEO_Import_RankMath', 'WPSEO_Import_SEOPressor', + 'WPSEO_Import_SEO_Framework', + 'WPSEO_Import_Smartcrawl_SEO', + 'WPSEO_Import_Squirrly', 'WPSEO_Import_Ultimate_SEO', 'WPSEO_Import_WooThemes_SEO', 'WPSEO_Import_WPSEO', - ); + ]; /** * Returns an array of importers available. diff --git a/wp-content/plugins/wordpress-seo/admin/interface-collection.php b/wp-content/plugins/wordpress-seo/admin/interface-collection.php index 00aeba27..7cb236a3 100644 --- a/wp-content/plugins/wordpress-seo/admin/interface-collection.php +++ b/wp-content/plugins/wordpress-seo/admin/interface-collection.php @@ -16,5 +16,4 @@ interface WPSEO_Collection { * @return array The collection data. */ public function get(); - } diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-cleanup-transient.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-cleanup-transient.php deleted file mode 100644 index 12bd86cc..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-cleanup-transient.php +++ /dev/null @@ -1,35 +0,0 @@ -count = $this->get_results( $post_ids ); - } - - /** - * Gets the link count for given post id. - * - * @param int $post_id The post id. - * @param string $target_field The field to show. - * - * @return int|null The total amount of links or null if the target field - * does not exist for the given post id. - */ - public function get( $post_id, $target_field = 'internal_link_count' ) { - if ( array_key_exists( $post_id, $this->count ) && array_key_exists( $target_field, $this->count[ $post_id ] ) ) { - return $this->count[ $post_id ][ $target_field ]; - } - - return null; - } - - /** - * Gets the link count for the given post ids. - * - * @param array $post_ids Array with post_ids. - * - * @return array - */ - protected function get_results( $post_ids ) { - global $wpdb; - - $storage = new WPSEO_Meta_Storage(); - - $results = $wpdb->get_results( - $wpdb->prepare( ' - SELECT internal_link_count, incoming_link_count, object_id - FROM ' . $storage->get_table_name() . ' - WHERE object_id IN (' . implode( ',', array_fill( 0, count( $post_ids ), '%d' ) ) . ')', - $post_ids - ), - ARRAY_A - ); - - $output = array(); - foreach ( $results as $result ) { - $output[ (int) $result['object_id'] ] = array( - 'internal_link_count' => $result['internal_link_count'], - 'incoming_link_count' => (int) $result['incoming_link_count'], - ); - } - - // Set unfound items to zero. - foreach ( $post_ids as $post_id ) { - if ( ! array_key_exists( $post_id, $output ) ) { - $output[ $post_id ] = array( - 'internal_link_count' => null, - 'incoming_link_count' => 0, - ); - } - } - - return $output; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-columns.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-columns.php deleted file mode 100644 index 49e91eaa..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-columns.php +++ /dev/null @@ -1,255 +0,0 @@ -storage = $storage; - } - - /** - * Registers the hooks. - */ - public function register_hooks() { - global $pagenow; - $is_ajax_request = defined( 'DOING_AJAX' ) && DOING_AJAX; - - if ( ! WPSEO_Metabox::is_post_overview( $pagenow ) && ! $is_ajax_request ) { - return; - } - - // Exit when either table is not present or accessible. - if ( ! WPSEO_Link_Table_Accessible::is_accessible() || ! WPSEO_Meta_Table_Accessible::is_accessible() ) { - return; - } - - if ( $is_ajax_request ) { - add_action( 'admin_init', array( $this, 'set_count_objects' ) ); - } - - // Hook into tablenav to calculate links and linked. - add_action( 'manage_posts_extra_tablenav', array( $this, 'count_objects' ) ); - - add_filter( 'posts_clauses', array( $this, 'order_by_links' ), 1, 2 ); - add_filter( 'posts_clauses', array( $this, 'order_by_linked' ), 1, 2 ); - - add_filter( 'admin_init', array( $this, 'register_init_hooks' ) ); - } - - /** - * Register hooks that require to be registered after `init`. - */ - public function register_init_hooks() { - $this->public_post_types = apply_filters( 'wpseo_link_count_post_types', WPSEO_Post_Type::get_accessible_post_types() ); - - if ( is_array( $this->public_post_types ) && $this->public_post_types !== array() ) { - array_walk( $this->public_post_types, array( $this, 'set_post_type_hooks' ) ); - } - } - - /** - * Modifies the query pieces to allow ordering column by links to post. - * - * @param array $pieces Array of Query pieces. - * @param \WP_Query $query The Query on which to apply. - * - * @return array - */ - public function order_by_links( $pieces, $query ) { - if ( 'wpseo-' . self::COLUMN_LINKS !== $query->get( 'orderby' ) ) { - return $pieces; - } - - return $this->build_sort_query_pieces( $pieces, $query, 'internal_link_count' ); - } - - /** - * Modifies the query pieces to allow ordering column by links to post. - * - * @param array $pieces Array of Query pieces. - * @param \WP_Query $query The Query on which to apply. - * - * @return array - */ - public function order_by_linked( $pieces, $query ) { - if ( 'wpseo-' . self::COLUMN_LINKED !== $query->get( 'orderby' ) ) { - return $pieces; - } - - return $this->build_sort_query_pieces( $pieces, $query, 'incoming_link_count' ); - } - - /** - * Builds the pieces for a sorting query. - * - * @param array $pieces Array of Query pieces. - * @param \WP_Query $query The Query on which to apply. - * @param string $field The field in the table to JOIN on. - * - * @return array Modified Query pieces. - */ - protected function build_sort_query_pieces( $pieces, $query, $field ) { - global $wpdb; - - // We only want our code to run in the main WP query. - if ( ! $query->is_main_query() ) { - return $pieces; - } - - // Get the order query variable - ASC or DESC. - $order = strtoupper( $query->get( 'order' ) ); - - // Make sure the order setting qualifies. If not, set default as ASC. - if ( ! in_array( $order, array( 'ASC', 'DESC' ), true ) ) { - $order = 'ASC'; - } - - $table = $this->storage->get_table_name(); - - $pieces['join'] .= " LEFT JOIN $table AS yst_links ON yst_links.object_id = {$wpdb->posts}.ID "; - $pieces['orderby'] = "{$field} $order, FIELD( {$wpdb->posts}.post_status, 'publish' ) $order, {$pieces['orderby']}"; - - return $pieces; - } - - /** - * Sets the hooks for each post type. - * - * @param string $post_type The post type. - */ - public function set_post_type_hooks( $post_type ) { - add_filter( 'manage_' . $post_type . '_posts_columns', array( $this, 'add_post_columns' ) ); - add_action( 'manage_' . $post_type . '_posts_custom_column', array( $this, 'column_content' ), 10, 2 ); - add_filter( 'manage_edit-' . $post_type . '_sortable_columns', array( $this, 'column_sort' ) ); - } - - /** - * Adds the columns for the post overview. - * - * @param array $columns Array with columns. - * - * @return array The extended array with columns. - */ - public function add_post_columns( array $columns ) { - $columns[ 'wpseo-' . self::COLUMN_LINKS ] = '' . __( '# links in post', 'wordpress-seo' ) . ''; - - if ( ! WPSEO_Link_Query::has_unprocessed_posts( $this->public_post_types ) ) { - $columns[ 'wpseo-' . self::COLUMN_LINKED ] = '' . __( '# internal links to', 'wordpress-seo' ) . ''; - } - - return $columns; - } - - /** - * Makes sure we calculate all values in one query. - * - * @param string $target Extra table navigation location which is triggered. - */ - public function count_objects( $target ) { - if ( 'top' === $target ) { - $this->set_count_objects(); - } - } - - /** - * Sets the objects to use for the count. - */ - public function set_count_objects() { - global $wp_query; - - $posts = $wp_query->get_posts(); - $post_ids = array(); - - // Post lists return a list of objects. - if ( isset( $posts[0] ) && is_object( $posts[0] ) ) { - $post_ids = wp_list_pluck( $posts, 'ID' ); - } - elseif ( ! empty( $posts ) ) { - // Page list returns an array of post IDs. - $post_ids = array_keys( $posts ); - } - - $post_ids = WPSEO_Link_Query::filter_unprocessed_posts( $post_ids ); - - $links = new WPSEO_Link_Column_Count(); - $links->set( $post_ids ); - - $this->link_count = $links; - } - - /** - * Displays the column content for the given column - * - * @param string $column_name Column to display the content for. - * @param int $post_id Post to display the column content for. - */ - public function column_content( $column_name, $post_id ) { - $link_count = null; - - switch ( $column_name ) { - case 'wpseo-' . self::COLUMN_LINKS: - $link_count = $this->link_count->get( $post_id, 'internal_link_count' ); - break; - case 'wpseo-' . self::COLUMN_LINKED: - if ( get_post_status( $post_id ) === 'publish' ) { - $link_count = $this->link_count->get( $post_id, 'incoming_link_count' ); - } - break; - } - - if ( isset( $link_count ) ) { - echo (int) $link_count; - } - } - - /** - * Sets the sortable columns. - * - * @param array $columns Array with sortable columns. - * - * @return array The extended array with sortable columns. - */ - public function column_sort( array $columns ) { - $columns[ 'wpseo-' . self::COLUMN_LINKS ] = 'wpseo-' . self::COLUMN_LINKS; - $columns[ 'wpseo-' . self::COLUMN_LINKED ] = 'wpseo-' . self::COLUMN_LINKED; - - return $columns; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-compatibility-notifier.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-compatibility-notifier.php deleted file mode 100644 index 48c32abf..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-compatibility-notifier.php +++ /dev/null @@ -1,58 +0,0 @@ -add_notification( $this->get_notification() ); - } - - /** - * Removes the notification from the notification center. - */ - public function remove_notification() { - Yoast_Notification_Center::get()->remove_notification( $this->get_notification() ); - } - - /** - * Returns the notification when the version is incompatible - * - * @return Yoast_Notification The notification. - */ - protected function get_notification() { - return new Yoast_Notification( - sprintf( - /* translators: %1$s: Yoast SEO. %2$s: Version number of Yoast SEO. %3$s: PHP version %4$s: The current PHP versione. %5$s link to knowledge base article about solving PHP issue. %6$s: is anchor closing. */ - __( - 'The Text link counter feature (introduced in %1$s %2$s) is currently disabled. For this feature to work %1$s requires at least PHP version %3$s. We have detected PHP version %4$s on this website. - Please read the following %5$sknowledge base article%6$s to find out how to resolve this problem.', - 'wordpress-seo' - ), - 'Yoast SEO', - '5.0', - '5.3', - phpversion(), - '', - '' - ), - array( - 'type' => Yoast_Notification::WARNING, - 'id' => self::NOTIFICATION_ID, - 'capabilities' => 'wpseo_manage_options', - 'priority' => 0.8, - ) - ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-content-processor.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-content-processor.php deleted file mode 100644 index ed1b5a4b..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-content-processor.php +++ /dev/null @@ -1,135 +0,0 @@ -storage = $storage; - $this->count_storage = $count_storage; - } - - /** - * Process the content for the given post id. - * - * @param int $post_id The post id. - * @param string $content The content to process. - */ - public function process( $post_id, $content ) { - $link_extractor = new WPSEO_Link_Extractor( $content ); - $link_processor = new WPSEO_Link_Factory( - new WPSEO_Link_Type_Classifier( home_url() ), - new WPSEO_Link_Internal_Lookup(), - new WPSEO_Link_Filter( get_permalink( $post_id ) ) - ); - - $extracted_links = $link_extractor->extract(); - $links = $link_processor->build( $extracted_links ); - - $internal_links = array_filter( $links, array( $this, 'filter_internal_link' ) ); - - $stored_links = $this->get_stored_internal_links( $post_id ); - - $this->storage->cleanup( $post_id ); - $this->storage->save_links( $post_id, $links ); - - $this->update_link_counts( $post_id, count( $internal_links ), array_merge( $stored_links, $internal_links ) ); - } - - /** - * Updates the link counts for the post and referenced posts. - * - * @param int $post_id Post to update link counts for. - * @param int|null $count Number of internal links. - * @param array $links Links to process for incoming link count update. - */ - public function update_link_counts( $post_id, $count, array $links ) { - $this->store_internal_link_count( $post_id, $count ); - $this->update_incoming_links( $post_id, $links ); - } - - /** - * Retrieves the stored internal links for the supplied post. - * - * @param int $post_id The post to fetch links for. - * - * @return WPSEO_Link[] List of internal links connected to the post. - */ - public function get_stored_internal_links( $post_id ) { - $links = $this->storage->get_links( $post_id ); - return array_filter( $links, array( $this, 'filter_internal_link' ) ); - } - - /** - * Filters on INTERNAL links. - * - * @param WPSEO_Link $link Link to test type of. - * - * @return bool True for internal link, false for external link. - */ - protected function filter_internal_link( WPSEO_Link $link ) { - return $link->get_type() === WPSEO_Link::TYPE_INTERNAL; - } - - /** - * Stores the total links for the post. - * - * @param int $post_id The post id. - * @param int $internal_link_count Total amount of links in the post. - * - * @return void - */ - protected function store_internal_link_count( $post_id, $internal_link_count ) { - $this->count_storage->save_meta_data( $post_id, array( 'internal_link_count' => $internal_link_count ) ); - } - - /** - * Updates the incoming link count. - * - * @param int $post_id Post which is processed, this needs to be recalculated too. - * @param WPSEO_Link[] $links Links to update the incoming link count of. - * - * @return void - */ - protected function update_incoming_links( $post_id, $links ) { - $post_ids = $this->get_internal_post_ids( $links ); - $post_ids = array_merge( array( $post_id ), $post_ids ); - $this->count_storage->update_incoming_link_count( $post_ids, $this->storage ); - } - - /** - * Extract the post IDs from the links. - * - * @param WPSEO_Link[] $links Links to update the incoming link count of. - * - * @return int[] List of post IDs. - */ - protected function get_internal_post_ids( $links ) { - $post_ids = array(); - foreach ( $links as $link ) { - $post_ids[] = $link->get_target_post_id(); - } - - return array_filter( $post_ids ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-extractor.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-extractor.php deleted file mode 100644 index 84fab21c..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-extractor.php +++ /dev/null @@ -1,48 +0,0 @@ -content = $content; - } - - /** - * Extracts the hrefs from the content and returns them as an array. - * - * @return array All the extracted links - */ - public function extract() { - $links = array(); - - if ( strpos( $this->content, 'href' ) === false ) { - return $links; - } - - $regexp = ']*href=("??)([^" >]*?)\\1[^>]*>'; - - // Used modifiers iU to match case insensitive and make greedy quantifiers lazy. - if ( preg_match_all( "/$regexp/iU", $this->content, $matches, PREG_SET_ORDER ) ) { - foreach ( $matches as $match ) { - $links[] = trim( $match[2], "'" ); - } - } - - return $links; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-factory.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-factory.php deleted file mode 100644 index d0e10523..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-factory.php +++ /dev/null @@ -1,83 +0,0 @@ -classifier = $classifier; - $this->internal_lookup = $internal_lookup; - $this->filter = $filter; - } - - /** - * Formats an array of links to WPSEO_Link object. - * - * @param array $extracted_links The links for format. - * - * @return WPSEO_Link[] The formatted links. - */ - public function build( array $extracted_links ) { - $extracted_links = array_map( array( $this, 'build_link' ), $extracted_links ); - $filtered_links = array_filter( $extracted_links, array( - $this->filter, - 'internal_link_with_fragment_filter', - ) ); - - return $filtered_links; - } - - /** - * Builds the link. - * - * @param string $link The link to build. - * - * @return WPSEO_Link The built link. - */ - public function build_link( $link ) { - $link_type = $this->classifier->classify( $link ); - - $target_post_id = 0; - if ( $link_type === WPSEO_Link::TYPE_INTERNAL ) { - $target_post_id = $this->internal_lookup->lookup( $link ); - } - - return self::get_link( $link, $target_post_id, $link_type ); - } - - /** - * Returns the link object. - * - * @param string $url The URL of the link. - * @param int $target_post_id The target post ID. - * @param string $type The link type. - * - * @return WPSEO_Link Generated link object. - */ - public static function get_link( $url, $target_post_id, $type ) { - return new WPSEO_Link( $url, $target_post_id, $type ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-filter.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-filter.php deleted file mode 100644 index b08c4ba4..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-filter.php +++ /dev/null @@ -1,57 +0,0 @@ -current_page_path = untrailingslashit( WPSEO_Link_Utils::get_url_part( $current_page, 'path' ) ); - } - - /** - * Filters all internal links that contains an fragment in the URL. - * - * @param WPSEO_Link $link The link that might be filtered. - * - * @return bool False when url contains a fragment. - */ - public function internal_link_with_fragment_filter( WPSEO_Link $link ) { - // When the type is external. - if ( $link->get_type() === WPSEO_Link::TYPE_EXTERNAL ) { - return true; - } - - $url_parts = wp_parse_url( $link->get_url() ); - - if ( isset( $url_parts['path'] ) ) { - return ! $this->is_current_page( untrailingslashit( $url_parts['path'] ) ); - } - - return ( ! isset( $url_parts['fragment'] ) && ! isset( $url_parts['query'] ) ); - } - - /** - * Is the url path the same as the current page path. - * - * @param string $url_path The url path. - * - * @return bool True when path is equal to the current page path. - */ - protected function is_current_page( $url_path ) { - return ( ! empty( $url_path ) && $url_path === $this->current_page_path ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-installer.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-installer.php deleted file mode 100644 index 283c18d1..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-installer.php +++ /dev/null @@ -1,52 +0,0 @@ -installables = array( - new WPSEO_Link_Storage(), - new WPSEO_Meta_Storage(), - ); - } - - /** - * Runs the installation of the link module. - */ - public function install() { - foreach ( $this->get_installables() as $installable ) { - $installable->install(); - } - } - - /** - * Adds a installable object to the installer. - * - * @param WPSEO_Installable $installable The installable object. - */ - public function add_installable( WPSEO_Installable $installable ) { - $this->installables[] = $installable; - } - - /** - * Returns the installable objects. - * - * @return WPSEO_Installable[] The installables to use. - */ - protected function get_installables() { - return $this->installables; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-internal-lookup.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-internal-lookup.php deleted file mode 100644 index 4b2ef1ee..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-internal-lookup.php +++ /dev/null @@ -1,25 +0,0 @@ -has_notification() || $this->requires_notification() ) { - return; - } - - $this->remove_notification( $this->get_notification() ); - } - - /** - * Adds the notification when it isn't set already and the amount of unindexed items is greater than the set. - * threshold. - */ - public function manage_notification() { - if ( $this->has_notification() || ! $this->requires_notification() ) { - return; - } - - $this->add_notification( $this->get_notification() ); - } - - /** - * Checks if the notification has been set already. - * - * @return bool True when there is a notification. - */ - public function has_notification() { - $notification = Yoast_Notification_Center::get()->get_notification_by_id( self::NOTIFICATION_ID ); - - return $notification instanceof Yoast_Notification; - } - - /** - * Adds a notification to the notification center. - * - * @param Yoast_Notification $notification The notification to add. - */ - protected function add_notification( Yoast_Notification $notification ) { - Yoast_Notification_Center::get()->add_notification( $notification ); - } - - /** - * Removes the notification from the notification center. - * - * @param Yoast_Notification $notification The notification to remove. - */ - protected function remove_notification( Yoast_Notification $notification ) { - Yoast_Notification_Center::get()->remove_notification( $notification ); - } - - /** - * Returns an instance of the notification. - * - * @return Yoast_Notification The notification to show. - */ - protected function get_notification() { - return new Yoast_Notification( - sprintf( - /* translators: 1: link to yoast.com post about internal linking suggestion. 2: is anchor closing. 3: button to the recalculation option. 4: closing button */ - __( - 'To make sure all the links in your texts are counted, we need to analyze all your texts. - All you have to do is press the following button and we\'ll go through all your texts for you. - - %3$sCount links%4$s - - The Text link counter feature provides insights in how many links are found in your text and how many links are referring to your text. This is very helpful when you are improving your %1$sinternal linking%2$s.', - 'wordpress-seo' - ), - '', - '', - '' - ), - array( - 'type' => Yoast_Notification::WARNING, - 'id' => self::NOTIFICATION_ID, - 'capabilities' => 'wpseo_manage_options', - 'priority' => 0.8, - ) - ); - } - - /** - * Checks if the unindexed threshold is exceeded. - * - * @return bool True when the threshold is exceeded. - */ - protected function requires_notification() { - $post_types = apply_filters( 'wpseo_link_count_post_types', WPSEO_Post_Type::get_accessible_post_types() ); - if ( ! is_array( $post_types ) ) { - return false; - } - - return WPSEO_Link_Query::has_unprocessed_posts( $post_types ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-query.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-query.php deleted file mode 100644 index 001e2599..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-query.php +++ /dev/null @@ -1,160 +0,0 @@ -posts . ' AS posts - LEFT JOIN ' . $count_table . ' AS yoast_meta - ON yoast_meta.object_id = posts.ID - WHERE posts.post_status = "publish" - AND posts.post_type IN ( ' . $post_types . ' ) - AND yoast_meta.internal_link_count IS NULL - LIMIT 1'; - - // If anything is found, we have unprocessed posts. - $results = $wpdb->get_var( $query ); - - return ! empty( $results ); - } - - /** - * Filter out posts that have not been processed yet. - * - * @param array $post_ids Post IDs to filter. - * - * @return array - */ - public static function filter_unprocessed_posts( array $post_ids ) { - global $wpdb; - - $post_ids = array_filter( $post_ids ); - if ( empty( $post_ids ) || array() === $post_ids ) { - return $post_ids; - } - - $count_table = self::get_count_table_name(); - - $query = ' - SELECT object_id - FROM ' . $count_table . ' - WHERE object_id IN ( ' . implode( ',', $post_ids ) . ' ) - '; - - $results = $wpdb->get_results( $query, ARRAY_A ); - - return array_map( 'intval', wp_list_pluck( $results, 'object_id' ) ); - } - - /** - * Returns a limited set of unindexed posts. - * - * @param array $post_types The post type. - * @param int $limit The limit for the resultset. - * - * @return array|null|object The set of unindexed posts. - */ - public static function get_unprocessed_posts( array $post_types, $limit = 5 ) { - global $wpdb; - - $count_table = self::get_count_table_name(); - $post_types = self::format_post_types( $post_types ); - - // @codingStandardsIgnoreStart - $query = 'SELECT posts.ID, posts.post_content - FROM ' . $wpdb->posts . ' AS posts - LEFT JOIN ' . $count_table . ' AS yoast_meta - ON yoast_meta.object_id = posts.ID - WHERE posts.post_status = "publish" - AND posts.post_type IN ( ' . $post_types . ' ) - AND yoast_meta.internal_link_count IS NULL - LIMIT %d - '; - // @codingStandardsIgnoreEnd - - return $wpdb->get_results( - $wpdb->prepare( $query, $limit ) - ); - } - - /** - * Returns the total amount of unindexed posts for given post type. - * - * @param array $post_types The post types. - * - * @return int The total of unindexed posts. - */ - public static function get_unprocessed_count( array $post_types ) { - global $wpdb; - - if ( empty( $post_types ) ) { - return 0; - } - - $count_table = self::get_count_table_name(); - $post_types = self::format_post_types( $post_types ); - - // @codingStandardsIgnoreStart - $query = ' - SELECT COUNT( posts.ID ) - FROM ' . $wpdb->posts . ' AS posts - LEFT JOIN ' . $count_table . ' AS yoast_meta - ON yoast_meta.object_id = posts.ID - WHERE posts.post_status = "publish" - AND posts.post_type IN ( ' . $post_types . ' ) - AND yoast_meta.internal_link_count IS NULL'; - // @codingStandardsIgnoreEnd - - return (int) $wpdb->get_var( $query ); - } - - /** - * Returns the table name where the counts are stored. - * - * @return string - */ - protected static function get_count_table_name() { - $storage = new WPSEO_Meta_Storage(); - return $storage->get_table_name(); - } - - /** - * Formats an array with post types as an SQL string. - * - * @param array $post_types The post types to format. - * - * @return string Post types formatted for use in SQL statement. - */ - protected static function format_post_types( array $post_types ) { - $sanitized_post_types = array_map( 'esc_sql', $post_types ); - $post_types = sprintf( '"%s"', implode( '", "', $sanitized_post_types ) ); - - return $post_types; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-reindex-dashboard.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-reindex-dashboard.php deleted file mode 100644 index 613d845a..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-reindex-dashboard.php +++ /dev/null @@ -1,224 +0,0 @@ -is_dashboard_page() ) { - return; - } - - add_action( 'admin_enqueue_scripts', array( $this, 'calculate_unprocessed' ), 9 ); - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ), 10 ); - - add_action( 'admin_footer', array( $this, 'modal_box' ), 20 ); - - add_action( 'wpseo_tools_overview_list_items', array( $this, 'show_tools_overview_item' ), 10 ); - } - - /** - * Calculates the number of unprocessed items per post type. - * - * @return void - */ - public function calculate_unprocessed() { - $this->public_post_types = apply_filters( 'wpseo_link_count_post_types', WPSEO_Post_Type::get_accessible_post_types() ); - - if ( is_array( $this->public_post_types ) && $this->public_post_types !== array() ) { - $this->unprocessed = WPSEO_Link_Query::get_unprocessed_count( $this->public_post_types ); - } - } - - /** - * Adds an item to the tools page overview list. - * - * @return void - */ - public function show_tools_overview_item() { - echo '
  • '; - echo '' . esc_html__( 'Text link counter', 'wordpress-seo' ) . '
    '; - - if ( ! $this->has_unprocessed() ) { - echo $this->message_already_indexed(); - } - - if ( $this->has_unprocessed() ) { - printf( '%s', $this->message_start_indexing() ); - } - - echo '
  • '; - } - - /** - * Add the indexing interface for links to the dashboard. - * - * @deprecated 7.0 - * - * @return void - */ - public function add_link_index_interface() { - _deprecated_function( __METHOD__, 'WPSEO 7.0' ); - - $html = ''; - $html .= '

    ' . esc_html__( 'Text link counter', 'wordpress-seo' ) . '

    '; - $html .= '

    ' . sprintf( - /* translators: 1: link to yoast.com post about internal linking suggestion. 4: is Yoast.com 3: is anchor closing. */ - __( 'The links in all your public texts need to be counted. This will provide insights of which texts need more links to them. If you want to know more about the why and how of internal linking, check out %1$sthe article about internal linking on %2$s%3$s.', 'wordpress-seo' ), - '', - 'Yoast.com', - '' - ) . '

    '; - - if ( ! $this->has_unprocessed() ) { - $html .= '

    ' . $this->message_already_indexed() . '

    '; - } - - if ( $this->has_unprocessed() ) { - $html .= ''; - } - - $html .= '
    '; - - echo $html; - } - - /** - * Generates the model box. - * - * @return void - */ - public function modal_box() { - if ( ! $this->is_dashboard_page() ) { - return; - } - - // Adding the thickbox. - add_thickbox(); - - $blocks = array(); - - if ( ! $this->has_unprocessed() ) { - $inner_text = sprintf( '

    %s

    ', - esc_html__( 'All your texts are already counted, there is no need to count them again.', 'wordpress-seo' ) - ); - } - - if ( $this->has_unprocessed() ) { - $progress = sprintf( - /* translators: 1: expands to a containing the number of items recalculated. 2: expands to a containing the total number of items. */ - __( 'Text %1$s of %2$s processed.', 'wordpress-seo' ), - '0', - sprintf( '%d', $this->get_unprocessed_count() ) - ); - - $inner_text = ''; - $inner_text .= sprintf( '

    %s

    ', $progress ); - } - - $blocks[] = sprintf( '

    %s

    %s
    ', - esc_html__( 'Counting links in your texts', 'wordpress-seo' ), - $inner_text - ); - ?> - - enqueue_script( 'reindex-links' ); - - $data = array( - 'amount' => $this->get_unprocessed_count(), - 'restApi' => array( - 'root' => esc_url_raw( rest_url() ), - 'endpoint' => WPSEO_Link_Reindex_Post_Endpoint::REST_NAMESPACE . '/' . WPSEO_Link_Reindex_Post_Endpoint::ENDPOINT_QUERY, - 'nonce' => wp_create_nonce( 'wp_rest' ), - ), - 'message' => array( - 'indexingCompleted' => $this->message_already_indexed(), - ), - 'l10n' => array( - 'calculationInProgress' => __( 'Calculation in progress...', 'wordpress-seo' ), - 'calculationCompleted' => __( 'Calculation completed.', 'wordpress-seo' ), - ), - ); - - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'reindex-links', 'yoastReindexLinksData', array( 'data' => $data ) ); - } - - /** - * Checks if the current page is the dashboard page. - * - * @return bool True when current page is the dashboard page. - */ - protected function is_dashboard_page() { - return ( filter_input( INPUT_GET, 'page' ) === 'wpseo_tools' ); - } - - /** - * Retrieves the string to display when everything has been indexed. - * - * @return string The message to show when everything has been indexed. - */ - public function message_already_indexed() { - return '' . esc_html__( 'Good job! All the links in your texts have been counted.', 'wordpress-seo' ); - } - - /** - * Returns if there are unprocessed items - * - * @return bool True if there are unprocessed items. - */ - public function has_unprocessed() { - return $this->unprocessed > 0; - } - - /** - * Returns the number of unprocessed items. - * - * @return int Number of unprocessed items. - */ - public function get_unprocessed_count() { - return $this->unprocessed; - } - - /** - * Retrieves the message to show starting indexation. - * - * @return string The message. - */ - public function message_start_indexing() { - return sprintf( - '%2$s', - 175, - esc_attr__( 'Count links in your texts', 'wordpress-seo' ) - ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-reindex-post-endpoint.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-reindex-post-endpoint.php deleted file mode 100644 index 9c6d443c..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-reindex-post-endpoint.php +++ /dev/null @@ -1,56 +0,0 @@ -service = $service; - } - - /** - * Register the REST endpoint to WordPress. - */ - public function register() { - register_rest_route( self::REST_NAMESPACE, self::ENDPOINT_QUERY, array( - 'methods' => 'GET', - 'callback' => array( - $this->service, - 'reindex', - ), - 'permission_callback' => array( - $this, - 'can_retrieve_data', - ), - ) ); - } - - /** - * Determines if the current user is allowed to use this endpoint. - * - * @return bool - */ - public function can_retrieve_data() { - return current_user_can( self::CAPABILITY_RETRIEVE ); - } -} - diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-reindex-post-service.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-reindex-post-service.php deleted file mode 100644 index 9920e092..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-reindex-post-service.php +++ /dev/null @@ -1,95 +0,0 @@ -process_posts() ); - } - - /** - * Returns the posts. - * - * @return int The total amount of unprocessed posts. - */ - protected function process_posts() { - if ( ! $this->is_processable() ) { - return 0; - } - - $posts = $this->get_unprocessed_posts(); - array_walk( $posts, array( $this, 'process_post' ) ); - - return count( $posts ); - } - - /** - * Returns all unprocessed posts. - * - * @return array The unprocessed posts. - */ - protected function get_unprocessed_posts() { - $post_types = apply_filters( 'wpseo_link_count_post_types', WPSEO_Post_Type::get_accessible_post_types() ); - if ( ! is_array( $post_types ) ) { - return array(); - } - return WPSEO_Link_Query::get_unprocessed_posts( $post_types ); - } - - /** - * Checks if the required tables are accessible. - * - * @return bool True when the tables are accessible. - */ - protected function is_processable() { - return WPSEO_Link_Table_Accessible::is_accessible() && WPSEO_Meta_Table_Accessible::is_accessible(); - } - - /** - * Processes the post. - * - * @param stdObject $post The post to process. - * - * @return void - */ - protected function process_post( $post ) { - // Some plugins might output data, so let's buffer this to prevent wrong responses. - ob_start(); - - // Apply the filters to have the same content as shown on the frontend. - $content = apply_filters( 'the_content', $post->post_content ); - $content = str_replace( ']]>', ']]>', $content ); - - ob_end_clean(); - - $content_processor = $this->get_content_processor(); - $content_processor->process( $post->ID, $content ); - } - - /** - * Returns an instance of the content processor. - * - * @return WPSEO_Link_Content_Processor The instance of the link content processor. - */ - protected function get_content_processor() { - static $content_processor; - - if ( $content_processor === null ) { - $content_processor = new WPSEO_Link_Content_Processor( new WPSEO_Link_Storage(), new WPSEO_Meta_Storage() ); - } - - return $content_processor; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-storage.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-storage.php deleted file mode 100644 index c63772e4..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-storage.php +++ /dev/null @@ -1,152 +0,0 @@ -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( - 'id bigint(20) unsigned NOT NULL AUTO_INCREMENT', - 'url varchar(255) NOT NULL', - 'post_id bigint(20) unsigned NOT NULL', - 'target_post_id bigint(20) unsigned NOT NULL', - 'type VARCHAR(8) NOT NULL', - ), - array( - 'PRIMARY KEY (id)', - 'KEY link_direction (post_id, type)', - ) - ); - } - - /** - * Returns an array of links from the database. - * - * @param int $post_id The post to get the links for. - * - * @return WPSEO_Link[] The links connected to the post. - */ - public function get_links( $post_id ) { - global $wpdb; - - $results = $this->database_proxy->get_results( - $wpdb->prepare( ' - SELECT url, post_id, target_post_id, type - FROM ' . $this->get_table_name() . ' - WHERE post_id = %d', - $post_id - ) - ); - - if ( $this->database_proxy->has_error() ) { - WPSEO_Link_Table_Accessible::set_inaccessible(); - } - - $links = array(); - foreach ( $results as $link ) { - $links[] = WPSEO_Link_Factory::get_link( $link->url, $link->target_post_id, $link->type ); - } - - return $links; - } - - /** - * Walks the given links to save them. - * - * @param integer $post_id The post id to save. - * @param WPSEO_Link[] $links The link to save. - * - * @return void - */ - public function save_links( $post_id, array $links ) { - array_walk( $links, array( $this, 'save_link' ), $post_id ); - } - - /** - * Removes all records for given post_id. - * - * @param int $post_id The post_id to remove the records for. - * - * @return int|false The number of rows updated, or false on error. - */ - public function cleanup( $post_id ) { - $is_deleted = $this->database_proxy->delete( - array( 'post_id' => $post_id ), - array( '%d' ) - ); - - if ( $is_deleted === false ) { - WPSEO_Link_Table_Accessible::set_inaccessible(); - } - - return $is_deleted; - } - - /** - * Inserts the link into the database. - * - * @param WPSEO_Link $link The link to save. - * @param int $link_key The link key. Unused. - * @param int $post_id The post id to save the link for. - * - * @return void - */ - protected function save_link( WPSEO_Link $link, $link_key, $post_id ) { - $inserted = $this->database_proxy->insert( - array( - 'url' => $link->get_url(), - 'post_id' => $post_id, - 'target_post_id' => $link->get_target_post_id(), - 'type' => $link->get_type(), - ), - array( '%s', '%d', '%d', '%s' ) - ); - - if ( $inserted === false ) { - WPSEO_Link_Table_Accessible::set_inaccessible(); - } - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-table-accessible-notifier.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-table-accessible-notifier.php deleted file mode 100644 index 7f4f3d2c..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-table-accessible-notifier.php +++ /dev/null @@ -1,56 +0,0 @@ -add_notification( $this->get_notification() ); - } - - /** - * Removes the notification from the notification center. - */ - public function remove_notification() { - Yoast_Notification_Center::get()->remove_notification( $this->get_notification() ); - } - - /** - * Returns the notification when the table is not accessible. - * - * @return Yoast_Notification The notification. - */ - protected function get_notification() { - return new Yoast_Notification( - sprintf( - /* translators: %1$s: Yoast SEO. %2$s: Version number of Yoast SEO. %3$s: link to knowledge base article about solving table issue. %4$s: is anchor closing. */ - __( - 'The Text link counter feature (introduced in %1$s %2$s) is currently disabled. For this feature to work %1$s needs to create a table in your database. We were unable to create this table automatically. - Please read the following %3$sknowledge base article%4$s to find out how to resolve this problem.', - 'wordpress-seo' - ), - 'Yoast SEO', - '5.0', - '', - '' - ), - array( - 'type' => Yoast_Notification::WARNING, - 'id' => self::NOTIFICATION_ID, - 'capabilities' => 'wpseo_manage_options', - 'priority' => 0.8, - ) - ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-table-accessible.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-table-accessible.php deleted file mode 100644 index 3009c718..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-table-accessible.php +++ /dev/null @@ -1,103 +0,0 @@ -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_link_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(); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-type-classifier.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-type-classifier.php deleted file mode 100644 index 47d48d2d..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-type-classifier.php +++ /dev/null @@ -1,95 +0,0 @@ -base_host = WPSEO_Link_Utils::get_url_part( $base_url, 'host' ); - - $base_path = WPSEO_Link_Utils::get_url_part( $base_url, 'path' ); - if ( $base_path ) { - $this->base_path = trailingslashit( $base_path ); - } - } - - /** - * Determines if the given link is an outbound or an internal link. - * - * @param string $link The link to classify. - * - * @return string Returns outbound or internal. - */ - public function classify( $link ) { - $url_parts = wp_parse_url( $link ); - - // Because parse_url may return false. - if ( ! is_array( $url_parts ) ) { - $url_parts = array(); - } - - if ( $this->contains_protocol( $url_parts ) && $this->is_external_link( $url_parts ) ) { - return WPSEO_Link::TYPE_EXTERNAL; - } - - return WPSEO_Link::TYPE_INTERNAL; - } - - /** - * Returns true when the link starts with https:// or http:// - * - * @param array $url_parts The url parts to use. - * - * @return bool True if the url starts with a protocol. - */ - protected function contains_protocol( array $url_parts ) { - return isset( $url_parts['scheme'] ) && $url_parts['scheme'] !== null; - } - - /** - * Checks if the link contains the home_url. Returns true if this isn't the case. - * - * @param array $url_parts The url parts to use. - * - * @return bool True when the link doesn't contain the home url. - */ - protected function is_external_link( array $url_parts ) { - if ( isset( $url_parts['scheme'] ) && ! in_array( $url_parts['scheme'], array( 'http', 'https' ), true ) ) { - return true; - } - // When the base host is equal to the host. - if ( isset( $url_parts['host'] ) && $url_parts['host'] !== $this->base_host ) { - return true; - } - - // There is no base path. - if ( empty( $this->base_path ) ) { - return false; - } - - // When there is a path. - if ( isset( $url_parts['path'] ) ) { - return ( strpos( $url_parts['path'], $this->base_path ) === false ); - } - - return true; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-utils.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-utils.php deleted file mode 100644 index 7a6c9ee6..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-utils.php +++ /dev/null @@ -1,41 +0,0 @@ -register_hooks(); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link-watcher.php b/wp-content/plugins/wordpress-seo/admin/links/class-link-watcher.php deleted file mode 100644 index 94f23fea..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link-watcher.php +++ /dev/null @@ -1,121 +0,0 @@ -content_processor = $content_processor; - } - - /** - * Registers the hooks. - * - * @returns void - */ - public function register_hooks() { - add_action( 'save_post', array( $this, 'save_post' ), 10, 2 ); - add_action( 'delete_post', array( $this, 'delete_post' ) ); - } - - /** - * Saves the links that are used in the post. - * - * @param int $post_id The post id to. - * @param WP_Post $post The post object. - * - * @return void - */ - public function save_post( $post_id, WP_Post $post ) { - if ( ! WPSEO_Link_Table_Accessible::is_accessible() || ! WPSEO_Meta_Table_Accessible::is_accessible() ) { - return; - } - - // When the post is a revision. - if ( wp_is_post_revision( $post->ID ) ) { - return; - } - - // When the post status is auto-draft. - if ( $post->post_status === 'auto-draft' ) { - return; - } - - // When the post isn't processable, just remove the saved links. - if ( ! $this->is_processable( $post_id ) ) { - return; - } - - $this->process( $post_id, $post->post_content ); - } - - /** - * Removes the seo links when the post is deleted. - * - * @param int $post_id The post id. - * - * @return void - */ - public function delete_post( $post_id ) { - if ( ! WPSEO_Link_Table_Accessible::is_accessible() || ! WPSEO_Meta_Table_Accessible::is_accessible() ) { - return; - } - - // Fetch links to update related linked objects. - $links = $this->content_processor->get_stored_internal_links( $post_id ); - - // Update the storage, remove all links for this post. - $storage = new WPSEO_Link_Storage(); - $storage->cleanup( $post_id ); - - // Update link counts for object and referenced links. - $this->content_processor->update_link_counts( $post_id, 0, $links ); - } - - /** - * Checks if the post is processable. - * - * @param int $post_id The post id. - * - * @return bool True when the post is processable. - */ - protected function is_processable( $post_id ) { - /* - * Do not use the `wpseo_link_count_post_types` because we want to always count the links, - * even if we don't show them. - */ - $post_types = WPSEO_Post_Type::get_accessible_post_types(); - - return isset( $post_types[ get_post_type( $post_id ) ] ); - } - - /** - * Processes the content for the given post id. - * - * @param int $post_id The post id to process. - * @param string $content The content to process. - * - * @return void - */ - private function process( $post_id, $content ) { - // Apply the filters to have the same content as shown on the frontend. - $content = apply_filters( 'the_content', $content ); - $content = str_replace( ']]>', ']]>', $content ); - - $this->content_processor->process( $post_id, $content ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/links/class-link.php b/wp-content/plugins/wordpress-seo/admin/links/class-link.php deleted file mode 100644 index 3a3db549..00000000 --- a/wp-content/plugins/wordpress-seo/admin/links/class-link.php +++ /dev/null @@ -1,64 +0,0 @@ -url = $url; - $this->target_post_id = $target_post_id; - $this->type = $type; - } - - /** - * Returns the set URL. - * - * @return string The set url. - */ - public function get_url() { - return $this->url; - } - - /** - * Returns the set target post id. - * - * @return int The set target post id. - */ - public function get_target_post_id() { - return (int) $this->target_post_id; - } - - /** - * Return the set link type. - * - * @return string The set link type. - */ - public function get_type() { - return $this->type; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/menu/class-admin-menu.php b/wp-content/plugins/wordpress-seo/admin/menu/class-admin-menu.php index f6f5e5f9..99636897 100644 --- a/wp-content/plugins/wordpress-seo/admin/menu/class-admin-menu.php +++ b/wp-content/plugins/wordpress-seo/admin/menu/class-admin-menu.php @@ -8,18 +8,7 @@ /** * Registers the admin menu on the left of the admin area. */ -class WPSEO_Admin_Menu implements WPSEO_WordPress_Integration { - /** @var WPSEO_Menu Menu */ - protected $menu; - - /** - * Constructs the Admin Menu. - * - * @param WPSEO_Menu $menu Menu to use. - */ - public function __construct( WPSEO_Menu $menu ) { - $this->menu = $menu; - } +class WPSEO_Admin_Menu extends WPSEO_Base_Menu { /** * Registers all hooks to WordPress. @@ -28,79 +17,55 @@ class WPSEO_Admin_Menu implements WPSEO_WordPress_Integration { */ public function register_hooks() { // Needs the lower than default priority so other plugins can hook underneath it without issue. - add_action( 'admin_menu', array( $this, 'register_settings_page' ), 5 ); + add_action( 'admin_menu', [ $this, 'register_settings_page' ], 5 ); } /** * Registers the menu item submenus. */ public function register_settings_page() { - $can_manage_options = WPSEO_Capability_Utils::current_user_can( $this->get_manage_capability() ); - - if ( $can_manage_options ) { - /* - * The current user has the capability to control anything. - * This means that all submenus and dashboard can be shown. - */ - global $admin_page_hooks; - - add_menu_page( - 'Yoast SEO: ' . __( 'Dashboard', 'wordpress-seo' ), - __( 'SEO', 'wordpress-seo' ) . ' ' . $this->get_notification_counter(), - $this->get_manage_capability(), - $this->menu->get_page_identifier(), - $this->get_admin_page_callback(), - WPSEO_Utils::get_icon_svg(), - '99.31337' - ); - - $admin_page_hooks[ $this->menu->get_page_identifier() ] = 'seo'; // Wipe notification bits from hooks. R. - } + $manage_capability = $this->get_manage_capability(); + $page_identifier = $this->get_page_identifier(); + $admin_page_callback = $this->get_admin_page_callback(); // Get all submenu pages. $submenu_pages = $this->get_submenu_pages(); - // Add submenu items to the main menu if possible. - if ( $can_manage_options ) { - $this->register_submenu_pages( $submenu_pages ); + foreach ( $submenu_pages as $submenu_page ) { + if ( WPSEO_Capability_Utils::current_user_can( $submenu_page[3] ) ) { + $manage_capability = $submenu_page[3]; + $page_identifier = $submenu_page[4]; + $admin_page_callback = $submenu_page[5]; + break; + } + } + + foreach ( $submenu_pages as $index => $submenu_page ) { + $submenu_pages[ $index ][0] = $page_identifier; } /* - * If the user does not have the general manage options capability, - * we need to make sure the desired sub-item can be reached. + * The current user has the capability to control anything. + * This means that all submenus and dashboard can be shown. */ - if ( ! $can_manage_options ) { - $this->register_menu_pages( $submenu_pages ); - } - } + global $admin_page_hooks; - /** - * Registers submenu pages as menu pages. - * - * @param array $submenu_pages List of submenu pages. - */ - protected function register_menu_pages( $submenu_pages ) { - if ( ! is_array( $submenu_pages ) || $submenu_pages === array() ) { - return; - } + add_menu_page( + 'Yoast SEO: ' . __( 'Dashboard', 'wordpress-seo' ), + __( 'SEO', 'wordpress-seo' ) . ' ' . $this->get_notification_counter(), + $manage_capability, + $page_identifier, + $admin_page_callback, + $this->get_icon_svg(), + '99.31337' + ); - // Loop through submenu pages and add them. - foreach ( $submenu_pages as $submenu_page ) { - if ( $submenu_page[3] === $this->get_manage_capability() ) { - continue; - } + // Wipe notification bits from hooks. + // phpcs:ignore WordPress.WP.GlobalVariablesOverride -- This is a deliberate action. + $admin_page_hooks[ $page_identifier ] = 'seo'; - // Register submenu as menu page. - add_menu_page( - 'Yoast SEO: ' . $submenu_page[2], - $submenu_page[2], - $submenu_page[3], - $submenu_page[4], - $submenu_page[5], - WPSEO_Utils::get_icon_svg(), - '99.31337' - ); - } + // Add submenu items to the main menu if possible. + $this->register_submenu_pages( $submenu_pages ); } /** @@ -108,26 +73,30 @@ class WPSEO_Admin_Menu implements WPSEO_WordPress_Integration { * * @return array List of registered submenu pages. */ - protected function get_submenu_pages() { + public function get_submenu_pages() { global $wpseo_admin; - /** WPSEO_Admin $wpseo_admin */ - $admin_features = $wpseo_admin->get_admin_features(); + $search_console_callback = null; + + // Account for when the available submenu pages are requested from outside the admin. + if ( isset( $wpseo_admin ) ) { + $google_search_console = new WPSEO_GSC(); + $search_console_callback = [ $google_search_console, 'display' ]; + } // Submenu pages. - $submenu_pages = array( - $this->get_submenu_page( __( 'General', 'wordpress-seo' ), $this->menu->get_page_identifier() ), + $submenu_pages = [ + $this->get_submenu_page( __( 'General', 'wordpress-seo' ), $this->get_page_identifier() ), $this->get_submenu_page( __( 'Search Appearance', 'wordpress-seo' ), 'wpseo_titles' ), $this->get_submenu_page( __( 'Search Console', 'wordpress-seo' ), 'wpseo_search_console', - array( $admin_features['google_search_console'], 'display' ), - array( array( $admin_features['google_search_console'], 'set_help' ) ) + $search_console_callback ), $this->get_submenu_page( __( 'Social', 'wordpress-seo' ), 'wpseo_social' ), $this->get_submenu_page( __( 'Tools', 'wordpress-seo' ), 'wpseo_tools' ), $this->get_submenu_page( $this->get_license_page_title(), 'wpseo_licenses' ), - ); + ]; /** * Filter: 'wpseo_submenu_pages' - Collects all submenus that need to be shown. @@ -137,82 +106,6 @@ class WPSEO_Admin_Menu implements WPSEO_WordPress_Integration { return (array) apply_filters( 'wpseo_submenu_pages', $submenu_pages ); } - /** - * Creates a submenu formatted array. - * - * @param string $page_title Page title to use. - * @param string $page_slug Page slug to use. - * @param callable $callback Optional. Callback which handles the page request. - * @param callable[] $hook Optional. Hook to trigger when the page is registered. - * - * @return array Formatted submenu. - */ - protected function get_submenu_page( $page_title, $page_slug, $callback = null, $hook = null ) { - if ( $callback === null ) { - $callback = $this->get_admin_page_callback(); - } - - return array( - $this->menu->get_page_identifier(), - '', - $page_title, - $this->get_manage_capability(), - $page_slug, - $callback, - $hook, - ); - } - - /** - * Registers the submenu pages. - * - * This is only done when the user has the `wpseo_manage_options` capability, - * thus all capabilities can be set to this capability. - * - * @param array $submenu_pages List of submenu pages to register. - * - * @return void - */ - protected function register_submenu_pages( $submenu_pages ) { - if ( ! is_array( $submenu_pages ) || $submenu_pages === array() ) { - return; - } - - // Loop through submenu pages and add them. - foreach ( $submenu_pages as $submenu_page ) { - $page_title = $submenu_page[2]; - - // We cannot use $submenu_page[1] because add-ons define that, so hard-code this value. - if ( $submenu_page[4] === 'wpseo_licenses' ) { - $page_title = $this->get_license_page_title(); - } - - $page_title .= ' - Yoast SEO'; - - /* - * Add submenu page. - * - * If we don't register this on `wpseo_manage_options`, admin users with only this capability - * will not be able to see the submenus which are configured with something else, - * thus all submenu pages are registered with the `wpseo_manage_options` capability here. - */ - $admin_page = add_submenu_page( $submenu_page[0], $page_title, $submenu_page[2], $this->get_manage_capability(), $submenu_page[4], $submenu_page[5] ); - - // Check if we need to hook. - if ( isset( $submenu_page[6] ) && ( is_array( $submenu_page[6] ) && $submenu_page[6] !== array() ) ) { - foreach ( $submenu_page[6] as $submenu_page_action ) { - add_action( 'load-' . $admin_page, $submenu_page_action ); - } - } - } - - // Use WordPress global $submenu to directly access it's properties. - global $submenu; - if ( isset( $submenu[ $this->menu->get_page_identifier() ] ) && WPSEO_Capability_Utils::current_user_can( $this->get_manage_capability() ) ) { - $submenu[ $this->menu->get_page_identifier() ][0][0] = __( 'General', 'wordpress-seo' ); - } - } - /** * Returns the notification count in HTML format. * @@ -237,36 +130,6 @@ class WPSEO_Admin_Menu implements WPSEO_WordPress_Integration { * @return string Capability to check against. */ protected function get_manage_capability() { - /** - * Filter: 'wpseo_manage_options_capability' - Allow changing the capability users need to view the settings pages - * - * @deprecated 5.5 - * @api string unsigned The capability - */ - return apply_filters_deprecated( 'wpseo_manage_options_capability', array( 'wpseo_manage_options' ), 'WPSEO 5.5.0', false, 'Use the introduced wpseo_manage_options capability instead.' ); - } - - /** - * Returns the page handler callback. - * - * @return array Callback page handler. - */ - protected function get_admin_page_callback() { - return array( $this->menu, 'load_page' ); - } - - /** - * Returns the page title to use for the licenses page. - * - * @return string The title for the license page. - */ - protected function get_license_page_title() { - static $title = null; - - if ( $title === null ) { - $title = __( 'Premium', 'wordpress-seo' ); - } - - return $title; + return 'wpseo_manage_options'; } } diff --git a/wp-content/plugins/wordpress-seo/admin/menu/class-base-menu.php b/wp-content/plugins/wordpress-seo/admin/menu/class-base-menu.php new file mode 100644 index 00000000..c682e5ad --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/menu/class-base-menu.php @@ -0,0 +1,281 @@ +menu = $menu; + } + + /** + * Returns the list of registered submenu pages. + * + * @return array List of registered submenu pages. + */ + abstract public function get_submenu_pages(); + + /** + * Creates a submenu formatted array. + * + * @param string $page_title Page title to use. + * @param string $page_slug Page slug to use. + * @param callable|null $callback Optional. Callback which handles the page request. + * @param callable[]|null $hook Optional. Hook to trigger when the page is registered. + * + * @return array Formatted submenu. + */ + protected function get_submenu_page( $page_title, $page_slug, $callback = null, $hook = null ) { + if ( $callback === null ) { + $callback = $this->get_admin_page_callback(); + } + + return [ + $this->get_page_identifier(), + '', + $page_title, + $this->get_manage_capability(), + $page_slug, + $callback, + $hook, + ]; + } + + /** + * Registers submenu pages as menu pages. + * + * This method should only be used if the user does not have the required capabilities + * to access the parent menu page. + * + * @param array $submenu_pages List of submenu pages to register. + * + * @return void + */ + protected function register_menu_pages( $submenu_pages ) { + if ( ! is_array( $submenu_pages ) || empty( $submenu_pages ) ) { + return; + } + + // Loop through submenu pages and add them. + array_walk( $submenu_pages, [ $this, 'register_menu_page' ] ); + } + + /** + * Registers submenu pages. + * + * @param array $submenu_pages List of submenu pages to register. + * + * @return void + */ + protected function register_submenu_pages( $submenu_pages ) { + if ( ! is_array( $submenu_pages ) || empty( $submenu_pages ) ) { + return; + } + + // Loop through submenu pages and add them. + array_walk( $submenu_pages, [ $this, 'register_submenu_page' ] ); + } + + /** + * Registers a submenu page as a menu page. + * + * This method should only be used if the user does not have the required capabilities + * to access the parent menu page. + * + * @param array $submenu_page { + * Submenu page definition. + * + * @type string $0 Parent menu page slug. + * @type string $1 Page title, currently unused. + * @type string $2 Title to display in the menu. + * @type string $3 Required capability to access the page. + * @type string $4 Page slug. + * @type callable $5 Callback to run when the page is rendered. + * @type array $6 Optional. List of callbacks to run when the page is loaded. + * } + * + * @return void + */ + protected function register_menu_page( $submenu_page ) { + + // If the submenu page requires the general manage capability, it must be added as an actual submenu page. + if ( $submenu_page[3] === $this->get_manage_capability() ) { + return; + } + + $page_title = 'Yoast SEO: ' . $submenu_page[2]; + + // Register submenu page as menu page. + $hook_suffix = add_menu_page( + $page_title, + $submenu_page[2], + $submenu_page[3], + $submenu_page[4], + $submenu_page[5], + $this->get_icon_svg(), + '99.31337' + ); + + // If necessary, add hooks for the submenu page. + if ( isset( $submenu_page[6] ) && ( is_array( $submenu_page[6] ) ) ) { + $this->add_page_hooks( $hook_suffix, $submenu_page[6] ); + } + } + + /** + * Registers a submenu page. + * + * This method will override the capability of the page to automatically use the + * general manage capability. Use the `register_menu_page()` method if the submenu + * page should actually use a different capability. + * + * @param array $submenu_page { + * Submenu page definition. + * + * @type string $0 Parent menu page slug. + * @type string $1 Page title, currently unused. + * @type string $2 Title to display in the menu. + * @type string $3 Required capability to access the page. + * @type string $4 Page slug. + * @type callable $5 Callback to run when the page is rendered. + * @type array $6 Optional. List of callbacks to run when the page is loaded. + * } + * + * @return void + */ + protected function register_submenu_page( $submenu_page ) { + $page_title = $submenu_page[2]; + + // We cannot use $submenu_page[1] because add-ons define that, so hard-code this value. + if ( $submenu_page[4] === 'wpseo_licenses' ) { + $page_title = $this->get_license_page_title(); + } + + /* + * Handle the Google Search Console special case by passing a fake parent + * page slug. This way, the sub-page is stil registered and can be accessed + * directly. Its menu item won't be displayed. + */ + if ( $submenu_page[4] === 'wpseo_search_console' ) { + // Set the parent page slug to a non-existing one. + $submenu_page[0] = 'wpseo_fake_menu_parent_page_slug'; + } + + $page_title .= ' - Yoast SEO'; + + // Register submenu page. + $hook_suffix = add_submenu_page( + $submenu_page[0], + $page_title, + $submenu_page[2], + $submenu_page[3], + $submenu_page[4], + $submenu_page[5] + ); + + // If necessary, add hooks for the submenu page. + if ( isset( $submenu_page[6] ) && ( is_array( $submenu_page[6] ) ) ) { + $this->add_page_hooks( $hook_suffix, $submenu_page[6] ); + } + } + + /** + * Adds hook callbacks for a given admin page hook suffix. + * + * @param string $hook_suffix Admin page hook suffix, as returned by `add_menu_page()` + * or `add_submenu_page()`. + * @param array $callbacks Callbacks to add. + * + * @return void + */ + protected function add_page_hooks( $hook_suffix, array $callbacks ) { + foreach ( $callbacks as $callback ) { + add_action( 'load-' . $hook_suffix, $callback ); + } + } + + /** + * Gets the main admin page identifier. + * + * @return string Admin page identifier. + */ + protected function get_page_identifier() { + return $this->menu->get_page_identifier(); + } + + /** + * Checks whether the current user has capabilities to manage all options. + * + * @return bool True if capabilities are sufficient, false otherwise. + */ + protected function check_manage_capability() { + return WPSEO_Capability_Utils::current_user_can( $this->get_manage_capability() ); + } + + /** + * Returns the capability that is required to manage all options. + * + * @return string Capability to check against. + */ + abstract protected function get_manage_capability(); + + /** + * Returns the page handler callback. + * + * @return array Callback page handler. + */ + protected function get_admin_page_callback() { + return [ $this->menu, 'load_page' ]; + } + + /** + * Returns the page title to use for the licenses page. + * + * @return string The title for the license page. + */ + protected function get_license_page_title() { + static $title = null; + + if ( $title === null ) { + $title = __( 'Premium', 'wordpress-seo' ); + } + + return $title; + } + + /** + * Returns a base64 URL for the svg for use in the menu. + * + * @param bool $base64 Whether or not to return base64'd output. + * + * @return string SVG icon. + */ + public function get_icon_svg( $base64 = true ) { + $svg = ''; + + if ( $base64 ) { + //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- This encoding is intended. + return 'data:image/svg+xml;base64,' . base64_encode( $svg ); + } + + return $svg; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/menu/class-menu.php b/wp-content/plugins/wordpress-seo/admin/menu/class-menu.php index 2d647198..95391b43 100644 --- a/wp-content/plugins/wordpress-seo/admin/menu/class-menu.php +++ b/wp-content/plugins/wordpress-seo/admin/menu/class-menu.php @@ -9,10 +9,21 @@ * Registers the regular admin menu and network admin menu implementations. */ class WPSEO_Menu implements WPSEO_WordPress_Integration { - /** 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'; - /** @var array List of classes that add admin functionality. */ + /** + * List of classes that add admin functionality. + * + * @var array + */ protected $admin_features; /** @@ -24,8 +35,10 @@ class WPSEO_Menu implements WPSEO_WordPress_Integration { $admin_menu = new WPSEO_Admin_Menu( $this ); $admin_menu->register_hooks(); - $network_admin_menu = new WPSEO_Network_Admin_Menu( $this ); - $network_admin_menu->register_hooks(); + if ( WPSEO_Utils::is_plugin_network_active() ) { + $network_admin_menu = new WPSEO_Network_Admin_Menu( $this ); + $network_admin_menu->register_hooks(); + } $capability_normalizer = new WPSEO_Submenu_Capability_Normalize(); $capability_normalizer->register_hooks(); diff --git a/wp-content/plugins/wordpress-seo/admin/menu/class-network-admin-menu.php b/wp-content/plugins/wordpress-seo/admin/menu/class-network-admin-menu.php index 96875ab9..4538a779 100644 --- a/wp-content/plugins/wordpress-seo/admin/menu/class-network-admin-menu.php +++ b/wp-content/plugins/wordpress-seo/admin/menu/class-network-admin-menu.php @@ -8,18 +8,7 @@ /** * Network Admin Menu handler. */ -class WPSEO_Network_Admin_Menu implements WPSEO_WordPress_Integration { - /** @var WPSEO_Menu Menu */ - protected $menu; - - /** - * WPSEO_Network_Admin_Menu constructor. - * - * @param WPSEO_Menu $menu Menu to use. - */ - public function __construct( WPSEO_Menu $menu ) { - $this->menu = $menu; - } +class WPSEO_Network_Admin_Menu extends WPSEO_Base_Menu { /** * Registers all hooks to WordPress. @@ -28,7 +17,7 @@ class WPSEO_Network_Admin_Menu implements WPSEO_WordPress_Integration { */ public function register_hooks() { // Needs the lower than default priority so other plugins can hook underneath it without issue. - add_action( 'network_admin_menu', array( $this, 'register_settings_page' ), 5 ); + add_action( 'network_admin_menu', [ $this, 'register_settings_page' ], 5 ); } /** @@ -37,40 +26,46 @@ class WPSEO_Network_Admin_Menu implements WPSEO_WordPress_Integration { * @return void */ public function register_settings_page() { - if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) { + if ( ! $this->check_manage_capability() ) { return; } - $page_callback = array( $this->menu, 'load_page' ); - add_menu_page( - 'Yoast SEO: ' . __( 'MultiSite Settings', 'wordpress-seo' ), + __( 'Network Settings', 'wordpress-seo' ) . ' - Yoast SEO', __( 'SEO', 'wordpress-seo' ), - 'delete_users', - $this->menu->get_page_identifier(), - array( $this, 'network_config_page' ), - WPSEO_Utils::get_icon_svg() + $this->get_manage_capability(), + $this->get_page_identifier(), + [ $this, 'network_config_page' ], + $this->get_icon_svg() ); + $submenu_pages = $this->get_submenu_pages(); + $this->register_submenu_pages( $submenu_pages ); + } + + /** + * Returns the list of registered submenu pages. + * + * @return array List of registered submenu pages. + */ + public function get_submenu_pages() { + + // Submenu pages. + $submenu_pages = [ + $this->get_submenu_page( + __( 'General', 'wordpress-seo' ), + $this->get_page_identifier(), + [ $this, 'network_config_page' ] + ), + ]; + if ( WPSEO_Utils::allow_system_file_edit() === true ) { - add_submenu_page( - $this->menu->get_page_identifier(), - 'Yoast SEO: ' . __( 'Edit Files', 'wordpress-seo' ), - __( 'Edit Files', 'wordpress-seo' ), - 'delete_users', 'wpseo_files', - $page_callback - ); + $submenu_pages[] = $this->get_submenu_page( __( 'Edit Files', 'wordpress-seo' ), 'wpseo_files' ); } - // Add Extension submenu page. - add_submenu_page( - $this->menu->get_page_identifier(), - 'Yoast SEO: ' . __( 'Extensions', 'wordpress-seo' ), - __( 'Extensions', 'wordpress-seo' ), - 'delete_users', - 'wpseo_licenses', - $page_callback - ); + $submenu_pages[] = $this->get_submenu_page( __( 'Extensions', 'wordpress-seo' ), 'wpseo_licenses' ); + + return $submenu_pages; } /** @@ -81,4 +76,22 @@ class WPSEO_Network_Admin_Menu implements WPSEO_WordPress_Integration { public function network_config_page() { require_once WPSEO_PATH . 'admin/pages/network.php'; } + + /** + * Checks whether the current user has capabilities to manage all options. + * + * @return bool True if capabilities are sufficient, false otherwise. + */ + protected function check_manage_capability() { + return current_user_can( $this->get_manage_capability() ); + } + + /** + * Returns the capability that is required to manage all options. + * + * @return string Capability to check against. + */ + protected function get_manage_capability() { + return 'wpseo_manage_network_options'; + } } diff --git a/wp-content/plugins/wordpress-seo/admin/menu/class-replacevar-editor.php b/wp-content/plugins/wordpress-seo/admin/menu/class-replacevar-editor.php new file mode 100644 index 00000000..9924ee36 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/menu/class-replacevar-editor.php @@ -0,0 +1,157 @@ + true, + 'label_title' => '', + 'label_description' => '', + 'description_placeholder' => '', + 'has_new_badge' => false, + 'is_disabled' => false, + 'has_premium_badge' => false, + ] + ); + + $this->validate_arguments( $arguments ); + + $this->yform = $yform; + $this->arguments = [ + 'title' => (string) $arguments['title'], + 'description' => (string) $arguments['description'], + 'page_type_recommended' => (string) $arguments['page_type_recommended'], + 'page_type_specific' => (string) $arguments['page_type_specific'], + 'paper_style' => (bool) $arguments['paper_style'], + 'label_title' => (string) $arguments['label_title'], + 'label_description' => (string) $arguments['label_description'], + 'description_placeholder' => (string) $arguments['description_placeholder'], + 'has_new_badge' => (bool) $arguments['has_new_badge'], + 'is_disabled' => (bool) $arguments['is_disabled'], + 'has_premium_badge' => (bool) $arguments['has_premium_badge'], + ]; + } + + /** + * Renders a div for the react application to mount to, and hidden inputs where + * the app should store it's value so they will be properly saved when the form + * is submitted. + * + * @return void + */ + public function render() { + $this->yform->hidden( $this->arguments['title'], $this->arguments['title'] ); + $this->yform->hidden( $this->arguments['description'], $this->arguments['description'] ); + + printf( + '
    ', + esc_attr( $this->arguments['title'] ), + esc_attr( $this->arguments['description'] ), + esc_attr( $this->arguments['page_type_recommended'] ), + esc_attr( $this->arguments['page_type_specific'] ), + esc_attr( $this->arguments['paper_style'] ), + esc_attr( $this->arguments['label_title'] ), + esc_attr( $this->arguments['label_description'] ), + esc_attr( $this->arguments['description_placeholder'] ), + esc_attr( $this->arguments['has_new_badge'] ), + esc_attr( $this->arguments['is_disabled'] ), + esc_attr( $this->arguments['has_premium_badge'] ) + ); + } + + /** + * Validates the replacement variable editor arguments. + * + * @param array $arguments The arguments to validate. + * + * @throws InvalidArgumentException Thrown when not all required arguments are present. + */ + protected function validate_arguments( array $arguments ) { + $required_arguments = [ + 'title', + 'description', + 'page_type_recommended', + 'page_type_specific', + 'paper_style', + ]; + + foreach ( $required_arguments as $field_name ) { + if ( ! array_key_exists( $field_name, $arguments ) ) { + throw new InvalidArgumentException( + sprintf( + /* translators: %1$s expands to the missing field name. */ + __( 'Not all required fields are given. Missing field %1$s', 'wordpress-seo' ), + $field_name + ) + ); + } + } + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/menu/class-replacevar-field.php b/wp-content/plugins/wordpress-seo/admin/menu/class-replacevar-field.php new file mode 100644 index 00000000..e94d2c73 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/menu/class-replacevar-field.php @@ -0,0 +1,88 @@ +yform = $yform; + $this->field_id = $field_id; + $this->label = $label; + $this->page_type_recommended = $page_type_recommended; + $this->page_type_specific = $page_type_specific; + } + + /** + * Renders a div for the react application to mount to, and hidden inputs where + * the app should store it's value so they will be properly saved when the form + * is submitted. + * + * @return void + */ + public function render() { + $this->yform->hidden( $this->field_id, $this->field_id ); + + printf( + '
    ', + esc_attr( $this->field_id ), + esc_attr( $this->label ), + esc_attr( $this->page_type_recommended ), + esc_attr( $this->page_type_specific ) + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/menu/class-submenu-capability-normalize.php b/wp-content/plugins/wordpress-seo/admin/menu/class-submenu-capability-normalize.php index 0ffda00b..6e35718f 100644 --- a/wp-content/plugins/wordpress-seo/admin/menu/class-submenu-capability-normalize.php +++ b/wp-content/plugins/wordpress-seo/admin/menu/class-submenu-capability-normalize.php @@ -16,7 +16,7 @@ class WPSEO_Submenu_Capability_Normalize implements WPSEO_WordPress_Integration * @return void */ public function register_hooks() { - add_filter( 'wpseo_submenu_pages', array( $this, 'normalize_submenus_capability' ) ); + add_filter( 'wpseo_submenu_pages', [ $this, 'normalize_submenus_capability' ] ); } /** diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-abstract-sectioned-metabox-tab.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-abstract-sectioned-metabox-tab.php new file mode 100644 index 00000000..be32c1f6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/metabox/class-abstract-sectioned-metabox-tab.php @@ -0,0 +1,95 @@ + '', + 'link_class' => '', + 'link_aria_label' => '', + ]; + + $options = array_merge( $default_options, $options ); + + $this->name = $name; + + $this->link_content = $link_content; + $this->link_title = $options['link_title']; + $this->link_class = $options['link_class']; + $this->link_aria_label = $options['link_aria_label']; + } + + /** + * Outputs the section link if any section has been added. + */ + public function display_link() { + if ( $this->has_sections() ) { + printf( + '
  • %5$s
  • ', + esc_attr( $this->name ), + esc_attr( $this->link_class ), + ( $this->link_title !== '' ) ? ' title="' . esc_attr( $this->link_title ) . '"' : '', + ( $this->link_aria_label !== '' ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '', + $this->link_content + ); + } + } + + /** + * Checks whether the tab has any sections. + * + * @return bool Whether the tab has any sections + */ + abstract protected function has_sections(); +} diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-add-keyword-tab.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-add-keyword-tab.php deleted file mode 100644 index d04e7c58..00000000 --- a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-add-keyword-tab.php +++ /dev/null @@ -1,69 +0,0 @@ - -
  • - -
  • - - ' . sprintf( __( 'Great news: you can, with %1$s!', 'wordpress-seo' ), - 'Yoast SEO Premium' - ) . '

    '; - $popup_content .= '

    ' . sprintf( - /* translators: %s expands to 'Yoast SEO Premium'. */ - __( 'Other benefits of %s for you:', 'wordpress-seo' ), 'Yoast SEO Premium' - ) . '

    '; - $popup_content .= '
      '; - $popup_content .= '
    • ' . sprintf( - /* 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' ), '', '' - ) . '
    • '; - $popup_content .= '
    • ' . __( 'Superfast internal links suggestions', 'wordpress-seo' ) . '
    • '; - $popup_content .= '
    • ' . sprintf( - /* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */ - __( '%1$sSocial media preview%2$s: Facebook & Twitter', 'wordpress-seo' ), '', '' - ) . '
    • '; - $popup_content .= '
    • ' . __( '24/7 support', 'wordpress-seo' ) . '
    • '; - $popup_content .= '
    • ' . __( 'No ads!', 'wordpress-seo' ) . '
    • '; - $popup_content .= '
    '; - $premium_popup = new WPSEO_Premium_Popup( 'add-keyword', 'h1', $popup_title, $popup_content, WPSEO_Shortlinker::get( 'https://yoa.st/add-keywords-popup' ) ); - echo $premium_popup->get_premium_message(); - - return ob_get_clean(); - } - - /** - * Returns an empty string because this tab has no content - * - * @return string - */ - public function content() { - return ''; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-addon-section.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-addon-section.php deleted file mode 100644 index ea9dbdd4..00000000 --- a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-addon-section.php +++ /dev/null @@ -1,39 +0,0 @@ - -
    -
    -
      - -
    -
    - -
    - name = $name; + $this->content = $content; + $this->link_content = $link_content; + } + + /** + * Returns the html for the tab link. + * + * @return string + */ + public function link() { + return $this->link_content; + } + + /** + * Returns the html for the tab content. + * + * @return string + */ + public function content() { + $collapsible_paper = new WPSEO_Paper_Presenter( + $this->link(), + null, + [ + 'content' => $this->content, + 'collapsible' => true, + 'class' => 'metabox wpseo-form wpseo-collapsible-container', + 'paper_id' => 'collapsible-' . $this->name, + ] + ); + + return $collapsible_paper->get_output(); + } + + /** + * Returns the collapsible's unique identifier. + * + * @return string + */ + public function get_name() { + return $this->name; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-collapsibles-section.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-collapsibles-section.php new file mode 100644 index 00000000..3fde30a4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-collapsibles-section.php @@ -0,0 +1,63 @@ +collapsibles = $collapsibles; + } + + /** + * Outputs the section content if any tab has been added. + */ + public function display_content() { + if ( $this->has_sections() ) { + printf( '
    ', esc_attr( 'wpseo-meta-section-' . $this->name ) ); + echo '
    '; + + add_filter( 'wp_kses_allowed_html', [ 'WPSEO_Utils', 'extend_kses_post_with_forms' ] ); + add_filter( 'wp_kses_allowed_html', [ 'WPSEO_Utils', 'extend_kses_post_with_a11y' ] ); + foreach ( $this->collapsibles as $collapsible ) { + echo wp_kses_post( $collapsible->content() ); + } + remove_filter( 'wp_kses_allowed_html', [ 'WPSEO_Utils', 'extend_kses_post_with_forms' ] ); + remove_filter( 'wp_kses_allowed_html', [ 'WPSEO_Utils', 'extend_kses_post_with_a11y' ] ); + + echo '
    '; + } + } + + /** + * Checks whether the tab has any sections. + * + * @return bool Whether the tab has any sections + */ + protected function has_sections() { + return ! empty( $this->collapsibles ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-editor.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-editor.php index 951d644a..aa38321d 100644 --- a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-editor.php +++ b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-editor.php @@ -11,11 +11,13 @@ class WPSEO_Metabox_Editor { /** - * Registers hooks to WordPress + * Registers hooks to WordPress. + * + * @codeCoverageIgnore */ public function register_hooks() { - add_filter( 'mce_css', array( $this, 'add_css_inside_editor' ) ); - add_filter( 'tiny_mce_before_init', array( $this, 'add_custom_element' ) ); + add_filter( 'mce_css', [ $this, 'add_css_inside_editor' ] ); + add_filter( 'tiny_mce_before_init', [ $this, 'add_custom_element' ] ); } /** @@ -27,13 +29,12 @@ class WPSEO_Metabox_Editor { public function add_css_inside_editor( $css_files ) { $asset_manager = new WPSEO_Admin_Asset_Manager(); $styles = $asset_manager->special_styles(); - /** @var WPSEO_Admin_Asset $inside_editor */ $inside_editor = $styles['inside-editor']; $asset_location = new WPSEO_Admin_Asset_SEO_Location( WPSEO_FILE ); $url = $asset_location->get_url( $inside_editor, WPSEO_Admin_Asset::TYPE_CSS ); - if ( '' === $css_files ) { + if ( $css_files === '' ) { $css_files = $url; } else { diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-form-tab.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-form-tab.php index 2df47e8c..df39f8b0 100644 --- a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-form-tab.php +++ b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-form-tab.php @@ -11,42 +11,58 @@ class WPSEO_Metabox_Form_Tab implements WPSEO_Metabox_Tab { /** + * The tab identifier. + * * @var string */ private $name; /** + * The tab content. + * * @var string */ private $content; /** + * The tab link content. + * * @var string */ private $link_content; /** + * Additional tab content class. + * * @var string */ private $tab_class; /** + * Additional tab link class. + * * @var string */ private $link_class; /** + * Title attribute on the link span. + * * @var string */ private $link_title; /** + * Arial label attribute on the link span. + * * @var string */ private $link_aria_label; /** - * @var boolean + * Does it contain a single tab. + * + * @var bool */ private $single; @@ -58,14 +74,14 @@ class WPSEO_Metabox_Form_Tab implements WPSEO_Metabox_Tab { * @param string $link_content The text content of the tab link. * @param array $options Optional link attributes. */ - public function __construct( $name, $content, $link_content, array $options = array() ) { - $default_options = array( + public function __construct( $name, $content, $link_content, array $options = [] ) { + $default_options = [ 'tab_class' => '', 'link_class' => '', 'link_title' => '', 'link_aria_label' => '', 'single' => false, - ); + ]; $options = array_merge( $default_options, $options ); @@ -95,10 +111,10 @@ class WPSEO_Metabox_Form_Tab implements WPSEO_Metabox_Tab { return sprintf( $html, esc_attr( $this->name ), - ( '' !== $this->tab_class ) ? ' ' . esc_attr( $this->tab_class ) : '', - ( '' !== $this->link_class ) ? ' ' . esc_attr( $this->link_class ) : '', - ( '' !== $this->link_title ) ? ' title="' . esc_attr( $this->link_title ) . '"' : '', - ( '' !== $this->link_aria_label ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '', + ( $this->tab_class !== '' ) ? ' ' . esc_attr( $this->tab_class ) : '', + ( $this->link_class !== '' ) ? ' ' . esc_attr( $this->link_class ) : '', + ( $this->link_title !== '' ) ? ' title="' . esc_attr( $this->link_title ) . '"' : '', + ( $this->link_aria_label !== '' ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '', $this->link_content ); } diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-null-tab.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-null-tab.php index 548e924c..1e31fd2b 100644 --- a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-null-tab.php +++ b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-null-tab.php @@ -9,10 +9,11 @@ * Generates the HTML for a metabox tab. */ class WPSEO_Metabox_Null_Tab implements WPSEO_Metabox_Tab { + /** * Returns the html for the tab link. * - * @return string + * @return string|null */ public function link() { return null; @@ -21,7 +22,7 @@ class WPSEO_Metabox_Null_Tab implements WPSEO_Metabox_Tab { /** * Returns the html for the tab content. * - * @return string + * @return string|null */ public function content() { return null; diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-section-additional.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-section-additional.php new file mode 100644 index 00000000..7ec559dd --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-section-additional.php @@ -0,0 +1,109 @@ +name = $name; + $this->content = $content; + $default_options = [ + 'link_class' => '', + 'link_aria_label' => '', + 'content_class' => 'wpseo-form', + ]; + $options = wp_parse_args( $options, $default_options ); + $this->link_content = $link_content; + $this->link_class = $options['link_class']; + $this->link_aria_label = $options['link_aria_label']; + $this->content_class = $options['content_class']; + } + + /** + * Outputs the section link. + * + * @return void + */ + public function display_link() { + printf( + '
  • %4$s
  • ', + esc_attr( $this->name ), + esc_attr( $this->link_class ), + ( $this->link_aria_label !== '' ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '', + $this->link_content + ); + } + + /** + * Outputs the section content. + * + * @return void + */ + public function display_content() { + $html = sprintf( + '
    ', + esc_attr( $this->name ), + esc_attr( $this->content_class ) + ); + $html .= $this->content; + $html .= '
    '; + echo $html; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-section-react.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-section-react.php new file mode 100644 index 00000000..70906599 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-section-react.php @@ -0,0 +1,118 @@ +name = $name; + $this->content = $content; + + $default_options = [ + 'link_class' => '', + 'link_aria_label' => '', + 'html_after' => '', + ]; + + $options = wp_parse_args( $options, $default_options ); + + $this->link_content = $link_content; + $this->link_class = $options['link_class']; + $this->link_aria_label = $options['link_aria_label']; + $this->html_after = $options['html_after']; + } + + /** + * Outputs the section link. + * + * @return void + */ + public function display_link() { + printf( + '
  • %4$s
  • ', + esc_attr( $this->name ), + esc_attr( $this->link_class ), + ( $this->link_aria_label !== '' ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '', + wp_kses_post( $this->link_content ) + ); + } + + /** + * Outputs the section content. + * + * @return void + */ + public function display_content() { + add_filter( 'wp_kses_allowed_html', [ 'WPSEO_Utils', 'extend_kses_post_with_forms' ] ); + add_filter( 'wp_kses_allowed_html', [ 'WPSEO_Utils', 'extend_kses_post_with_a11y' ] ); + + printf( + '
    ', + esc_attr( $this->name ) + ); + echo wp_kses_post( $this->content ); + echo '
    '; + echo wp_kses_post( $this->html_after ); + echo '
    '; + + remove_filter( 'wp_kses_allowed_html', [ 'WPSEO_Utils', 'extend_kses_post_with_forms' ] ); + remove_filter( 'wp_kses_allowed_html', [ 'WPSEO_Utils', 'extend_kses_post_with_a11y' ] ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-section-readability.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-section-readability.php new file mode 100644 index 00000000..9ee8f3ff --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-section-readability.php @@ -0,0 +1,42 @@ + +
    %2$s
    ', + esc_attr( $this->name ), + esc_html__( 'Readability', 'wordpress-seo' ) + ); + } + + /** + * Outputs the section content. + */ + public function display_content() { + printf( + '
    ', + esc_attr( $this->name ) + ); + echo '
    ', '
    '; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-tab-section.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-tab-section.php deleted file mode 100644 index 187a1816..00000000 --- a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox-tab-section.php +++ /dev/null @@ -1,168 +0,0 @@ - '', - 'link_class' => '', - 'link_aria_label' => '', - ); - - $options = array_merge( $default_options, $options ); - - $this->name = $name; - - // Filter out invalid tab instances. - $valid_tabs = array_filter( $tabs, array( $this, 'is_valid_tab' ) ); - - foreach ( $valid_tabs as $tab ) { - $this->add_tab( $tab ); - } - $this->link_content = $link_content; - $this->link_title = $options['link_title']; - $this->link_class = $options['link_class']; - $this->link_aria_label = $options['link_aria_label']; - } - - /** - * Determines whether the passed tab is considered valid. - * - * @param mixed $tab The potential tab that needs to be validated. - * - * @return bool Whether or not the tab is valid. - */ - protected function is_valid_tab( $tab ) { - if ( $tab instanceof WPSEO_Metabox_Tab && ! $tab instanceof WPSEO_Metabox_Null_Tab ) { - return true; - } - - return false; - } - - /** - * Outputs the section link if any tab has been added. - */ - public function display_link() { - if ( $this->has_tabs() ) { - printf( - '
  • %5$s
  • ', - esc_attr( $this->name ), - esc_attr( $this->link_class ), - ( '' !== $this->link_title ) ? ' title="' . esc_attr( $this->link_title ) . '"' : '', - ( '' !== $this->link_aria_label ) ? ' aria-label="' . esc_attr( $this->link_aria_label ) . '"' : '', - $this->link_content - ); - } - } - - /** - * Outputs the section content if any tab has been added. - */ - public function display_content() { - if ( $this->has_tabs() ) { - $html = '
    '; - $html .= '
    '; - $html .= '
      %3$s
    %4$s'; - $html .= '
    '; - - printf( - $html, - esc_attr( 'wpseo-meta-section-' . $this->name ), - esc_attr( 'wpseo-metabox-tab-' . $this->name ), - $this->tab_links(), - $this->tab_content() - ); - } - } - - /** - * Add a `WPSEO_Metabox_Tab` object to the tabs. - * - * @param WPSEO_Metabox_Tab $tab Tab to add. - */ - public function add_tab( WPSEO_Metabox_Tab $tab ) { - $this->tabs[] = $tab; - } - - /** - * Checks if any tabs have been added to the section. - * - * @return bool - */ - protected function has_tabs() { - return ! empty( $this->tabs ); - } - - /** - * Concatenates all tabs' links into one html string. - * - * @return string - */ - private function tab_links() { - $links = ''; - foreach ( $this->tabs as $tab ) { - $links .= $tab->link(); - } - return $links; - } - - /** - * Concatenates all tabs' content into one html string. - * - * @return string - */ - private function tab_content() { - $content = ''; - foreach ( $this->tabs as $tab ) { - $content .= $tab->content(); - } - return $content; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox.php b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox.php index 21fa89de..fc32305b 100644 --- a/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox.php +++ b/wp-content/plugins/wordpress-seo/admin/metabox/class-metabox.php @@ -5,113 +5,208 @@ * @package WPSEO\Admin */ +use Yoast\WP\SEO\Conditionals\Admin\Estimated_Reading_Time_Conditional; +use Yoast\WP\SEO\Conditionals\Admin\Post_Conditional; +use Yoast\WP\SEO\Helpers\Input_Helper; +use Yoast\WP\SEO\Presenters\Admin\Alert_Presenter; +use Yoast\WP\SEO\Presenters\Admin\Meta_Fields_Presenter; + /** * This class generates the metabox on the edit post / page as well as contains all page analysis functionality. */ class WPSEO_Metabox extends WPSEO_Meta { /** - * @var WPSEO_Social_Admin + * Whether or not the social tab is enabled. + * + * @var bool */ - protected $social_admin; + private $social_is_enabled; /** + * Helper to determine whether or not the SEO analysis is enabled. + * * @var WPSEO_Metabox_Analysis_SEO */ - protected $analysis_seo; + protected $seo_analysis; /** + * Helper to determine whether or not the readability analysis is enabled. + * * @var WPSEO_Metabox_Analysis_Readability */ - protected $analysis_readability; + protected $readability_analysis; + + /** + * The metabox editor object. + * + * @var WPSEO_Metabox_Editor + */ + protected $editor; + + /** + * The Metabox post. + * + * @var WP_Post + */ + protected $post = null; + + /** + * Whether or not the advanced metadata is enabled. + * + * @var bool + */ + protected $is_advanced_metadata_enabled; + + /** + * Represents the estimated_reading_time_conditional. + * + * @var Estimated_Reading_Time_Conditional + */ + protected $estimated_reading_time_conditional; /** * Class constructor. */ public function __construct() { - add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) ); - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) ); - add_action( 'wp_insert_post', array( $this, 'save_postdata' ) ); - add_action( 'edit_attachment', array( $this, 'save_postdata' ) ); - add_action( 'add_attachment', array( $this, 'save_postdata' ) ); - add_action( 'post_submitbox_start', array( $this, 'publish_box' ) ); - add_action( 'admin_init', array( $this, 'setup_page_analysis' ) ); - add_action( 'admin_init', array( $this, 'translate_meta_boxes' ) ); - add_action( 'admin_footer', array( $this, 'template_keyword_tab' ) ); - add_action( 'admin_footer', array( $this, 'template_generic_tab' ) ); - - // Check if one of the social settings is checked in the options, if so, initialize the social_admin object. - if ( WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false ) ) { - $this->social_admin = new WPSEO_Social_Admin(); + if ( $this->is_internet_explorer() ) { + add_action( 'add_meta_boxes', [ $this, 'internet_explorer_metabox' ] ); + return; } + add_action( 'add_meta_boxes', [ $this, 'add_meta_box' ] ); + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] ); + add_action( 'wp_insert_post', [ $this, 'save_postdata' ] ); + add_action( 'edit_attachment', [ $this, 'save_postdata' ] ); + add_action( 'add_attachment', [ $this, 'save_postdata' ] ); + add_action( 'admin_init', [ $this, 'translate_meta_boxes' ] ); + $this->editor = new WPSEO_Metabox_Editor(); $this->editor->register_hooks(); - $this->analysis_seo = new WPSEO_Metabox_Analysis_SEO(); - $this->analysis_readability = new WPSEO_Metabox_Analysis_Readability(); + $this->social_is_enabled = WPSEO_Options::get( 'opengraph', false ) || WPSEO_Options::get( 'twitter', false ); + $this->is_advanced_metadata_enabled = WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false; + + $this->estimated_reading_time_conditional = new Estimated_Reading_Time_Conditional( + new Post_Conditional(), + new Input_Helper() + ); + + $this->seo_analysis = new WPSEO_Metabox_Analysis_SEO(); + $this->readability_analysis = new WPSEO_Metabox_Analysis_Readability(); } /** - * Translate text strings for use in the meta box. + * Checks whether the request comes from an IE 11 browser. + * + * @return bool Whether the request comes from an IE 11 browser. + */ + public static function is_internet_explorer() { + if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) { + return false; + } + + $user_agent = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ); + + if ( stripos( $user_agent, 'Trident/7.0' ) === false ) { + return false; + } + + return true; + } + + /** + * Adds an alternative metabox for internet explorer users. + */ + public function internet_explorer_metabox() { + $post_types = WPSEO_Post_Type::get_accessible_post_types(); + $post_types = array_filter( $post_types, [ $this, 'display_metabox' ] ); + + if ( ! is_array( $post_types ) || $post_types === [] ) { + return; + } + + $product_title = $this->get_product_title(); + + foreach ( $post_types as $post_type ) { + add_filter( "postbox_classes_{$post_type}_wpseo_meta", [ $this, 'wpseo_metabox_class' ] ); + + add_meta_box( + 'wpseo_meta', + $product_title, + [ $this, 'render_internet_explorer_notice' ], + $post_type, + 'normal', + apply_filters( 'wpseo_metabox_prio', 'high' ), + [ '__block_editor_compatible_meta_box' => true ] + ); + } + } + + /** + * Renders the content for the internet explorer metabox. + * + * @return void + */ + public function render_internet_explorer_notice() { + $content = sprintf( + /* translators: 1: Link start tag to the Firefox website, 2: Link start tag to the Chrome website, 3: Link start tag to the Edge website, 4: Link closing tag. */ + esc_html__( 'The browser you are currently using is unfortunately rather dated. Since we strive to give you the best experience possible, we no longer support this browser. Instead, please use %1$sFirefox%4$s, %2$sChrome%4$s or %3$sMicrosoft Edge%4$s.', 'wordpress-seo' ), + '', + '', + '', + '' + ); + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped above. + echo new Alert_Presenter( $content ); + } + + /** + * Translates 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() { - self::$meta_fields['general']['snippetpreview']['title'] = __( 'Snippet editor', 'wordpress-seo' ); - /* translators: 1: link open tag; 2: link close tag. */ - self::$meta_fields['general']['snippetpreview']['help'] = sprintf( __( 'This is a rendering of what this post might look like in Google\'s search results. %1$sLearn more about the Snippet Preview%2$s.', 'wordpress-seo' ), '', '' ); - self::$meta_fields['general']['snippetpreview']['help-button'] = __( 'Show information about the snippet editor', 'wordpress-seo' ); - - self::$meta_fields['general']['pageanalysis']['title'] = __( 'Analysis', 'wordpress-seo' ); - /* translators: 1: link open tag; 2: link close tag. */ - self::$meta_fields['general']['pageanalysis']['help'] = sprintf( __( 'This is the content analysis, a collection of content checks that analyze the content of your page. %1$sLearn more about the Content Analysis Tool%2$s.', 'wordpress-seo' ), '', '' ); - self::$meta_fields['general']['pageanalysis']['help-button'] = __( 'Show information about the content analysis', 'wordpress-seo' ); - - self::$meta_fields['general']['focuskw_text_input']['title'] = __( 'Focus keyword', 'wordpress-seo' ); - self::$meta_fields['general']['focuskw_text_input']['label'] = __( 'Enter a focus keyword', 'wordpress-seo' ); - /* translators: 1: link open tag; 2: link close tag. */ - self::$meta_fields['general']['focuskw_text_input']['help'] = sprintf( __( 'Pick the main keyword or keyphrase that this post/page is about. %1$sLearn more about the Focus Keyword%2$s.', 'wordpress-seo' ), '', '' ); - self::$meta_fields['general']['focuskw_text_input']['help-button'] = __( 'Show information about the focus keyword', 'wordpress-seo' ); - - self::$meta_fields['general']['title']['title'] = __( 'SEO title', 'wordpress-seo' ); - - self::$meta_fields['general']['metadesc']['title'] = __( 'Meta description', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['general']['title']['title'] = __( 'SEO title', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['general']['metadesc']['title'] = __( 'Meta description', 'wordpress-seo' ); /* translators: %s expands to the post type name. */ - self::$meta_fields['advanced']['meta-robots-noindex']['title'] = __( 'Allow search engines to show this %s in search results?', 'wordpress-seo' ); - if ( '0' === (string) get_option( 'blog_public' ) ) { - self::$meta_fields['advanced']['meta-robots-noindex']['description'] = '

    ' . __( 'Warning: even though you can set the meta robots setting here, the entire site is set to noindex in the sitewide privacy settings, so these settings won\'t have an effect.', 'wordpress-seo' ) . '

    '; + WPSEO_Meta::$meta_fields['advanced']['meta-robots-noindex']['title'] = __( 'Allow search engines to show this %s in search results?', 'wordpress-seo' ); + if ( (string) get_option( 'blog_public' ) === '0' ) { + WPSEO_Meta::$meta_fields['advanced']['meta-robots-noindex']['description'] = '' . __( 'Warning: even though you can set the meta robots setting here, the entire site is set to noindex in the sitewide privacy settings, so these settings won\'t have an effect.', 'wordpress-seo' ) . ''; } /* translators: %1$s expands to Yes or No, %2$s expands to the post type name.*/ - self::$meta_fields['advanced']['meta-robots-noindex']['options']['0'] = __( 'Default for %2$s, currently: %1$s', 'wordpress-seo' ); - self::$meta_fields['advanced']['meta-robots-noindex']['options']['2'] = __( 'Yes', 'wordpress-seo' ); - self::$meta_fields['advanced']['meta-robots-noindex']['options']['1'] = __( 'No', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-noindex']['options']['0'] = __( 'Default for %2$s, currently: %1$s', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-noindex']['options']['2'] = __( 'Yes', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-noindex']['options']['1'] = __( 'No', 'wordpress-seo' ); /* translators: %1$s expands to the post type name.*/ - self::$meta_fields['advanced']['meta-robots-nofollow']['title'] = __( 'Should search engines follow links on this %1$s?', 'wordpress-seo' ); - self::$meta_fields['advanced']['meta-robots-nofollow']['options']['0'] = __( 'Yes', 'wordpress-seo' ); - self::$meta_fields['advanced']['meta-robots-nofollow']['options']['1'] = __( 'No', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-nofollow']['title'] = __( 'Should search engines follow links on this %1$s?', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-nofollow']['options']['0'] = __( 'Yes', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-nofollow']['options']['1'] = __( 'No', 'wordpress-seo' ); - self::$meta_fields['advanced']['meta-robots-adv']['title'] = __( 'Meta robots advanced', 'wordpress-seo' ); - self::$meta_fields['advanced']['meta-robots-adv']['description'] = __( 'Advanced meta robots settings for this page.', 'wordpress-seo' ); - /* translators: %s expands to the advanced robots settings default as set in the site-wide settings.*/ - self::$meta_fields['advanced']['meta-robots-adv']['options']['-'] = __( 'Site-wide default: %s', 'wordpress-seo' ); - self::$meta_fields['advanced']['meta-robots-adv']['options']['none'] = __( 'None', 'wordpress-seo' ); - self::$meta_fields['advanced']['meta-robots-adv']['options']['noimageindex'] = __( 'No Image Index', 'wordpress-seo' ); - self::$meta_fields['advanced']['meta-robots-adv']['options']['noarchive'] = __( 'No Archive', 'wordpress-seo' ); - self::$meta_fields['advanced']['meta-robots-adv']['options']['nosnippet'] = __( 'No Snippet', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-adv']['title'] = __( 'Meta robots advanced', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-adv']['description'] = __( 'If you want to apply advanced meta robots settings for this page, please define them in the following field.', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-adv']['options']['noimageindex'] = __( 'No Image Index', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-adv']['options']['noarchive'] = __( 'No Archive', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['meta-robots-adv']['options']['nosnippet'] = __( 'No Snippet', 'wordpress-seo' ); - self::$meta_fields['advanced']['bctitle']['title'] = __( 'Breadcrumbs Title', 'wordpress-seo' ); - self::$meta_fields['advanced']['bctitle']['description'] = __( 'Title to use for this page in breadcrumb paths', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['bctitle']['title'] = __( 'Breadcrumbs Title', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['bctitle']['description'] = __( 'Title to use for this page in breadcrumb paths', 'wordpress-seo' ); - self::$meta_fields['advanced']['canonical']['title'] = __( 'Canonical URL', 'wordpress-seo' ); - /* translators: 1: link open tag; 2: link close tag. */ - self::$meta_fields['advanced']['canonical']['description'] = sprintf( __( 'The canonical URL that this page should point to, leave empty to default to permalink. %1$sCross domain canonical%2$s supported too.', 'wordpress-seo' ), '', '' ); + WPSEO_Meta::$meta_fields['advanced']['canonical']['title'] = __( 'Canonical URL', 'wordpress-seo' ); - self::$meta_fields['advanced']['redirect']['title'] = __( '301 Redirect', 'wordpress-seo' ); - self::$meta_fields['advanced']['redirect']['description'] = __( 'The URL that this page should redirect to.', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['canonical']['description'] = sprintf( + /* translators: 1: link open tag; 2: link close tag. */ + __( 'The canonical URL that this page should point to. Leave empty to default to permalink. %1$sCross domain canonical%2$s supported too.', 'wordpress-seo' ), + '', + WPSEO_Admin_Utils::get_new_tab_message() . '' + ); + + WPSEO_Meta::$meta_fields['advanced']['redirect']['title'] = __( '301 Redirect', 'wordpress-seo' ); + WPSEO_Meta::$meta_fields['advanced']['redirect']['description'] = __( 'The URL that this page should redirect to.', 'wordpress-seo' ); do_action( 'wpseo_tab_translate' ); } @@ -130,48 +225,6 @@ class WPSEO_Metabox extends WPSEO_Meta { return WPSEO_Utils::is_metabox_active( $identifier, $type ); } - /** - * Sets up all the functionality related to the prominence of the page analysis functionality. - */ - public function setup_page_analysis() { - if ( apply_filters( 'wpseo_use_page_analysis', true ) === true ) { - add_action( 'post_submitbox_start', array( $this, 'publish_box' ) ); - } - } - - /** - * Outputs the page analysis score in the Publish Box. - */ - public function publish_box() { - if ( $this->display_metabox() === false ) { - return; - } - - $post = $this->get_metabox_post(); - - if ( self::get_value( 'meta-robots-noindex', $post->ID ) === '1' ) { - $score_label = 'noindex'; - $title = __( 'Post is set to noindex.', 'wordpress-seo' ); - $score_title = $title; - } - else { - $score = self::get_value( 'linkdex', $post->ID ); - if ( $score === '' ) { - $score_label = 'na'; - $title = __( 'No focus keyword set.', 'wordpress-seo' ); - } - else { - $score_label = WPSEO_Utils::translate_score( $score ); - } - - $score_title = WPSEO_Utils::translate_score( $score, false ); - - if ( ! isset( $title ) ) { - $title = $score_title; - } - } - } - /** * Adds the Yoast SEO meta box to the edit boxes in the edit post, page, * attachment, and custom post types pages. @@ -180,31 +233,26 @@ class WPSEO_Metabox extends WPSEO_Meta { */ public function add_meta_box() { $post_types = WPSEO_Post_Type::get_accessible_post_types(); + $post_types = array_filter( $post_types, [ $this, 'display_metabox' ] ); - if ( ! is_array( $post_types ) || $post_types === array() ) { + if ( ! is_array( $post_types ) || $post_types === [] ) { return; } + $product_title = $this->get_product_title(); + foreach ( $post_types as $post_type ) { - if ( $this->display_metabox( $post_type ) === false ) { - continue; - } + add_filter( "postbox_classes_{$post_type}_wpseo_meta", [ $this, 'wpseo_metabox_class' ] ); - $product_title = 'Yoast SEO'; - - if ( file_exists( WPSEO_PATH . 'premium/' ) ) { - $product_title .= ' Premium'; - } - - if ( get_current_screen() !== null ) { - $screen_id = get_current_screen()->id; - add_filter( "postbox_classes_{$screen_id}_wpseo_meta", array( $this, 'wpseo_metabox_class' ) ); - } - - add_meta_box( 'wpseo_meta', $product_title, array( - $this, - 'meta_box', - ), $post_type, 'normal', apply_filters( 'wpseo_metabox_prio', 'high' ) ); + add_meta_box( + 'wpseo_meta', + $product_title, + [ $this, 'meta_box' ], + $post_type, + 'normal', + apply_filters( 'wpseo_metabox_prio', 'high' ), + [ '__block_editor_compatible_meta_box' => true ] + ); } } @@ -222,47 +270,56 @@ class WPSEO_Metabox extends WPSEO_Meta { } /** - * Pass variables to js for use with the post-scraper. + * Passes variables to js for use with the post-scraper. * * @return array */ - public function localize_post_scraper_script() { - $post = $this->get_metabox_post(); + public function get_metabox_script_data() { $permalink = ''; - if ( is_object( $post ) ) { - $permalink = get_sample_permalink( $post->ID ); + if ( is_object( $this->get_metabox_post() ) ) { + $permalink = get_sample_permalink( $this->get_metabox_post()->ID ); $permalink = $permalink[0]; } $post_formatter = new WPSEO_Metabox_Formatter( - new WPSEO_Post_Metabox_Formatter( $post, array(), $permalink ) + new WPSEO_Post_Metabox_Formatter( $this->get_metabox_post(), [], $permalink ) ); - return $post_formatter->get_values(); + $values = $post_formatter->get_values(); + + /** This filter is documented in admin/filters/class-cornerstone-filter.php. */ + $post_types = apply_filters( 'wpseo_cornerstone_post_types', WPSEO_Post_Type::get_accessible_post_types() ); + if ( $values['cornerstoneActive'] && ! in_array( $this->get_metabox_post()->post_type, $post_types, true ) ) { + $values['cornerstoneActive'] = false; + } + + if ( $values['semrushIntegrationActive'] && $this->post->post_type === 'attachment' ) { + $values['semrushIntegrationActive'] = 0; + } + + return $values; } /** - * Pass some variables to js for replacing variables. + * Determines whether or not the current post type has registered taxonomies. + * + * @return bool Whether the current post type has taxonomies. */ - public function localize_replace_vars_script() { - return array( - 'no_parent_text' => __( '(no parent)', 'wordpress-seo' ), - 'replace_vars' => $this->get_replace_vars(), - 'scope' => $this->determine_scope(), - ); + private function current_post_type_has_taxonomies() { + $post_taxonomies = get_object_taxonomies( get_post_type() ); + + return ! empty( $post_taxonomies ); } /** * Determines the scope based on the post type. * This can be used by the replacevar plugin to determine if a replacement needs to be executed. * - * @return string String decribing the current scope. + * @return string String describing the current scope. */ private function determine_scope() { - $post_type = get_post_type( $this->get_metabox_post() ); - - if ( $post_type === 'page' ) { + if ( $this->get_metabox_post()->post_type === 'page' ) { return 'page'; } @@ -270,268 +327,165 @@ class WPSEO_Metabox extends WPSEO_Meta { } /** - * Pass some variables to js for the edit / post page overview, snippet preview, etc. - * - * @return array - */ - public function localize_shortcode_plugin_script() { - return array( - 'wpseo_filter_shortcodes_nonce' => wp_create_nonce( 'wpseo-filter-shortcodes' ), - 'wpseo_shortcode_tags' => $this->get_valid_shortcode_tags(), - ); - } - - /** - * Output a tab in the Yoast SEO Metabox. - * - * @param string $id CSS ID of the tab. - * @param string $heading Heading for the tab. - * @param string $content Content of the tab. This content should be escaped. - */ - public function do_tab( $id, $heading, $content ) { - ?> -
    - -
    - get_content_sections(); + $this->render_hidden_fields(); + $this->render_tabs(); + } - $helpcenter_tab = new WPSEO_Option_Tab( 'metabox', __( 'Meta box', 'wordpress-seo' ), - array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/metabox-screencast' ) ) ); + /** + * Renders the metabox hidden fields. + * + * @return void + */ + protected function render_hidden_fields() { + wp_nonce_field( 'yoast_free_metabox', 'yoast_free_metabox_nonce' ); - $help_center = new WPSEO_Help_Center( '', $helpcenter_tab, WPSEO_Utils::is_yoast_seo_premium() ); - $help_center->localize_data(); - $help_center->mount(); + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in class. + echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'general' ); - if ( ! defined( 'WPSEO_PREMIUM_FILE' ) ) { - echo $this->get_buy_premium_link(); + if ( $this->is_advanced_metadata_enabled ) { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in class. + echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'advanced' ); } - echo '
    '; - echo '
      '; + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in class. + echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'schema', $this->get_metabox_post()->post_type ); - foreach ( $content_sections as $content_section ) { - if ( $content_section->name === 'premium' ) { + if ( $this->social_is_enabled ) { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped in class. + echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'social' ); + } + + /** + * Filter: 'wpseo_content_meta_section_content' - Allow filtering the metabox content before outputting. + * + * @api string $post_content The metabox content string. + */ + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output should be escaped in the filter. + echo apply_filters( 'wpseo_content_meta_section_content', '' ); + } + + /** + * Renders the metabox tabs. + * + * @return void + */ + protected function render_tabs() { + echo '
      '; + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: $this->get_product_title() returns a hard-coded string. + printf( '
        ', $this->get_product_title() ); + + $tabs = $this->get_tabs(); + + foreach ( $tabs as $tab ) { + if ( $tab->name === 'premium' ) { continue; } - $content_section->display_link(); + $tab->display_link(); } echo '
      '; - foreach ( $content_sections as $content_section ) { - $content_section->display_content(); + foreach ( $tabs as $tab ) { + $tab->display_content(); } echo '
      '; } /** - * Returns the relevant metabox sections for the current view. + * Returns the relevant metabox tabs for the current view. * * @return WPSEO_Metabox_Section[] */ - private function get_content_sections() { - $content_sections = array( $this->get_content_meta_section() ); + private function get_tabs() { + $tabs = []; - // Check if social_admin is an instance of WPSEO_Social_Admin. - if ( $this->social_admin instanceof WPSEO_Social_Admin ) { - $content_sections[] = $this->social_admin->get_meta_section(); + $label = __( 'SEO', 'wordpress-seo' ); + if ( $this->seo_analysis->is_enabled() ) { + $label = '' . $label; + } + $tabs[] = new WPSEO_Metabox_Section_React( 'content', $label ); + + if ( $this->readability_analysis->is_enabled() ) { + $tabs[] = new WPSEO_Metabox_Section_Readability(); } - if ( WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || WPSEO_Options::get( 'disableadvanced_meta' ) === false ) { - $content_sections[] = $this->get_advanced_meta_section(); + if ( $this->is_advanced_metadata_enabled ) { + $tabs[] = new WPSEO_Metabox_Section_React( + 'schema', + '' . __( 'Schema', 'wordpress-seo' ), + '' + ); } - if ( ! defined( 'WPSEO_PREMIUM_FILE' ) ) { - $content_sections[] = $this->get_buy_premium_section(); + if ( $this->social_is_enabled ) { + $tabs[] = new WPSEO_Metabox_Section_React( + 'social', + '' . __( 'Social', 'wordpress-seo' ), + '', + [ + 'html_after' => '
      ', + ] + ); } - if ( has_action( 'wpseo_tab_header' ) || has_action( 'wpseo_tab_content' ) ) { - $content_sections[] = $this->get_addons_meta_section(); + $tabs = array_merge( $tabs, $this->get_additional_tabs() ); + + return $tabs; + } + + /** + * Returns the metabox tabs that have been added by other plugins. + * + * @return WPSEO_Metabox_Section_Additional[] + */ + protected function get_additional_tabs() { + $tabs = []; + + /** + * Private filter: 'yoast_free_additional_metabox_sections'. + * + * Meant for internal use only. Allows adding additional tabs to the Yoast SEO metabox. + * + * @since 11.9 + * + * @param array[] $tabs { + * An array of arrays with tab specifications. + * + * @type array $tab { + * A tab specification. + * + * @type string $name The name of the tab. Used in the HTML IDs, href and aria properties. + * @type string $link_content The content of the tab link. + * @type string $content The content of the tab. + * @type array $options { + * Optional. Extra options. + * + * @type string $link_class Optional. The class for the tab link. + * @type string $link_aria_label Optional. The aria label of the tab link. + * } + * } + * } + */ + $requested_tabs = apply_filters( 'yoast_free_additional_metabox_sections', [] ); + + foreach ( $requested_tabs as $tab ) { + if ( is_array( $tab ) && array_key_exists( 'name', $tab ) && array_key_exists( 'link_content', $tab ) && array_key_exists( 'content', $tab ) ) { + $options = array_key_exists( 'options', $tab ) ? $tab['options'] : []; + $tabs[] = new WPSEO_Metabox_Section_Additional( + $tab['name'], + $tab['link_content'], + $tab['content'], + $options + ); + } } - return $content_sections; - } - - /** - * Returns the metabox section for the content analysis. - * - * @return WPSEO_Metabox_Section - */ - private function get_content_meta_section() { - $content = $this->get_tab_content( 'general' ); - - $tabs = array(); - - $tabs[] = new WPSEO_Metabox_Form_Tab( - 'content', - $content, - '', - array( - 'tab_class' => 'yoast-seo__remove-tab', - ) - ); - - $tabs[] = new WPSEO_Metabox_Add_Keyword_Tab(); - - return new WPSEO_Metabox_Tab_Section( - 'content', - '' . __( 'Content optimization', 'wordpress-seo' ) . '' . WPSEO_Utils::traffic_light_svg() . '', - $tabs, - array( - 'link_aria_label' => __( 'Content optimization', 'wordpress-seo' ), - 'link_class' => 'yoast-tooltip yoast-tooltip-e', - ) - ); - } - - /** - * Returns the metabox section for the advanced settings. - * - * @return WPSEO_Metabox_Section - */ - private function get_advanced_meta_section() { - $content = $this->get_tab_content( 'advanced' ); - - $tab = new WPSEO_Metabox_Form_Tab( - 'advanced', - $content, - __( 'Advanced', 'wordpress-seo' ), - array( - 'single' => true, - ) - ); - - return new WPSEO_Metabox_Tab_Section( - 'advanced', - '' . __( 'Advanced', 'wordpress-seo' ) . '', - array( $tab ), - array( - 'link_aria_label' => __( 'Advanced', 'wordpress-seo' ), - 'link_class' => 'yoast-tooltip yoast-tooltip-e', - ) - ); - } - - /** - * Returns a link to activate the Buy Premium tab. - * - * @return string - */ - private function get_buy_premium_link() { - return sprintf( "", - 'wpseo-metabox-buy-premium', - __( 'Go Premium', 'wordpress-seo' ) - ); - } - - /** - * Returns the metabox section for the Premium section. - * - * @return WPSEO_Metabox_Section - */ - private function get_buy_premium_section() { - $content = sprintf( "
      - %s -
        -
      • - %s - %s -
      • -
      • - %s - %s -
      • -
      • - %s - %s -
      • -
      • - %s - %s -
      • -
      - - - %s - - -

      %s

      -
      ", - /* translators: %1$s expands to Yoast SEO Premium. */ - sprintf( __( 'You\'re not getting the benefits of %1$s yet. If you had %1$s, you could use its awesome features:', 'wordpress-seo' ), 'Yoast SEO Premium' ), - __( 'Redirect manager', 'wordpress-seo' ), - __( 'Create and manage redirects within your WordPress install.', 'wordpress-seo' ), - __( 'Multiple focus keywords', 'wordpress-seo' ), - __( 'Optimize a single post for up to 5 keywords.', 'wordpress-seo' ), - __( 'Social Previews', 'wordpress-seo' ), - __( 'Check what your Facebook or Twitter post will look like.', 'wordpress-seo' ), - __( 'Premium support', 'wordpress-seo' ), - __( 'Gain access to our 24/7 support team.', 'wordpress-seo' ), - WPSEO_Shortlinker::get( 'https://yoa.st/pe-buy-premium' ), - /* translators: %s expands to Yoast SEO Premium. */ - sprintf( __( 'Get %s now!', 'wordpress-seo' ), 'Yoast SEO Premium' ), - WPSEO_Shortlinker::get( 'https://yoa.st/pe-premium-page' ), - __( 'More info', 'wordpress-seo' ) - ); - - $tab = new WPSEO_Metabox_Form_Tab( - 'premium', - $content, - 'Yoast SEO Premium', - array( - 'single' => true, - ) - ); - - return new WPSEO_Metabox_Tab_Section( - 'premium', - '', - array( $tab ), - array( - 'link_aria_label' => 'Yoast SEO Premium', - 'link_class' => 'yoast-tooltip yoast-tooltip-e', - ) - ); - } - - /** - * Returns a metabox section dedicated to hosting metabox tabs that have been added by other plugins through the - * `wpseo_tab_header` and `wpseo_tab_content` actions. - * - * @return WPSEO_Metabox_Section - */ - private function get_addons_meta_section() { - return new WPSEO_Metabox_Addon_Tab_Section( - 'addons', - '' . __( 'Add-ons', 'wordpress-seo' ) . '', - array(), - array( - 'link_aria_label' => __( 'Add-ons', 'wordpress-seo' ), - 'link_class' => 'yoast-tooltip yoast-tooltip-e', - ) - ); - } - - /** - * Gets the contents for the metabox tab. - * - * @param string $tab_name Tab for which to retrieve the field definitions. - * - * @return string - */ - private function get_tab_content( $tab_name ) { - $content = ''; - foreach ( $this->get_meta_field_defs( $tab_name ) as $key => $meta_field ) { - $content .= $this->do_meta_box( $meta_field, $key ); - } - unset( $key, $meta_field ); - - return $content; + return $tabs; } /** @@ -539,15 +493,15 @@ class WPSEO_Metabox extends WPSEO_Meta { * * @todo [JRF] Check if $class is added appropriately everywhere. * - * @param array $meta_field_def Contains the vars based on which output is generated. - * @param string $key Internal key (without prefix). + * @param array $meta_field_def Contains the vars based on which output is generated. + * @param string $key Internal key (without prefix). * - * @return string + * @return string */ public function do_meta_box( $meta_field_def, $key = '' ) { $content = ''; - $esc_form_key = esc_attr( self::$form_prefix . $key ); - $meta_value = self::get_value( $key, $this->get_metabox_post()->ID ); + $esc_form_key = esc_attr( WPSEO_Meta::$form_prefix . $key ); + $meta_value = WPSEO_Meta::get_value( $key, $this->get_metabox_post()->ID ); $class = ''; if ( isset( $meta_field_def['class'] ) && $meta_field_def['class'] !== '' ) { @@ -566,42 +520,12 @@ class WPSEO_Metabox extends WPSEO_Meta { $description = '

      ' . $meta_field_def['description'] . '

      '; } + // Add a hide_on_pages option that returns nothing when the field is rendered on a page. + if ( isset( $meta_field_def['hide_on_pages'] ) && $meta_field_def['hide_on_pages'] && get_post_type() === 'page' ) { + return ''; + } + switch ( $meta_field_def['type'] ) { - case 'pageanalysis': - if ( WPSEO_Options::get( 'content_analysis_active' ) === false && WPSEO_Options::get( 'keyword_analysis_active' ) === false ) { - break; - } - - $content .= '
      '; - $content .= '
      '; - $content .= '

      ' . __( 'Analysis', 'wordpress-seo' ) . '

      '; - $content .= '
      '; - $content .= '
      '; - $content .= '
      '; - $content .= '
      '; - break; - case 'snippetpreview': - $content .= '
      '; - break; - case 'focuskeyword': - if ( $placeholder !== '' ) { - $placeholder = ' placeholder="' . esc_attr( $placeholder ) . '"'; - } - - $content .= '
      '; - $content .= '
      '; - $content .= '

      ' . esc_html( $meta_field_def['title'] ) . '

      '; - $content .= ''; - $content .= ''; - - if ( WPSEO_Options::get( 'enable_cornerstone_content', false ) ) { - $cornerstone_field = new WPSEO_Cornerstone_Field(); - - $content .= $cornerstone_field->get_html( $this->get_metabox_post() ); - } - $content .= '
      '; - $content .= '
      '; - break; case 'text': $ac = ''; if ( isset( $meta_field_def['autocomplete'] ) && $meta_field_def['autocomplete'] === false ) { @@ -613,6 +537,13 @@ class WPSEO_Metabox extends WPSEO_Meta { $content .= ''; break; + case 'url': + if ( $placeholder !== '' ) { + $placeholder = ' placeholder="' . esc_attr( $placeholder ) . '"'; + } + $content .= ''; + break; + case 'textarea': $rows = 3; if ( isset( $meta_field_def['rows'] ) && $meta_field_def['rows'] > 0 ) { @@ -622,14 +553,18 @@ class WPSEO_Metabox extends WPSEO_Meta { break; case 'hidden': - $content .= '' . "\n"; + $default = ''; + if ( isset( $meta_field_def['default'] ) ) { + $default = sprintf( ' data-default="%s"', esc_attr( $meta_field_def['default'] ) ); + } + $content .= '' . "\n"; break; case 'select': - if ( isset( $meta_field_def['options'] ) && is_array( $meta_field_def['options'] ) && $meta_field_def['options'] !== array() ) { + if ( isset( $meta_field_def['options'] ) && is_array( $meta_field_def['options'] ) && $meta_field_def['options'] !== [] ) { $content .= ''; @@ -637,13 +572,13 @@ class WPSEO_Metabox extends WPSEO_Meta { break; case 'multiselect': - if ( isset( $meta_field_def['options'] ) && is_array( $meta_field_def['options'] ) && $meta_field_def['options'] !== array() ) { + if ( isset( $meta_field_def['options'] ) && is_array( $meta_field_def['options'] ) && $meta_field_def['options'] !== [] ) { // Set $meta_value as $selected_arr. $selected_arr = $meta_value; // If the multiselect field is 'meta-robots-adv' we should explode on ,. - if ( 'meta-robots-adv' === $key ) { + if ( $key === 'meta-robots-adv' ) { $selected_arr = explode( ',', $meta_value ); } @@ -657,7 +592,7 @@ class WPSEO_Metabox extends WPSEO_Meta { $content .= ' '; unset( $checked, $expl ); break; case 'radio': - if ( isset( $meta_field_def['options'] ) && is_array( $meta_field_def['options'] ) && $meta_field_def['options'] !== array() ) { + if ( isset( $meta_field_def['options'] ) && is_array( $meta_field_def['options'] ) && $meta_field_def['options'] !== [] ) { foreach ( $meta_field_def['options'] as $val => $option ) { - $checked = checked( $meta_value, $val, false ); + $checked = checked( $meta_value, $val, false ); $content .= ' '; } unset( $val, $option, $checked ); @@ -685,8 +620,28 @@ class WPSEO_Metabox extends WPSEO_Meta { break; case 'upload': - $content .= ''; - $content .= ''; + $content .= ' '; + $content .= ' '; + $content .= ''; break; } @@ -712,31 +667,21 @@ class WPSEO_Metabox extends WPSEO_Meta { } // If it's a set of radio buttons, output proper fieldset and legend. - if ( 'radio' === $meta_field_def['type'] ) { + if ( $meta_field_def['type'] === 'radio' ) { return '
      ' . $title . '' . $help_button . $help_panel . $content . $description . '
      '; } // If it's a single checkbox, ignore the title. - if ( 'checkbox' === $meta_field_def['type'] ) { + if ( $meta_field_def['type'] === 'checkbox' ) { $label = ''; } - // Special meta box sections such as the Snippet Preview, the Analysis, etc. - if ( in_array( $meta_field_def['type'], array( - 'snippetpreview', - 'pageanalysis', - 'focuskeyword', - ), true ) - ) { - return $this->create_content_box( $content, $meta_field_def['type'], $help_button, $help_panel ); - } - // Other meta box content or form fields. if ( $meta_field_def['type'] === 'hidden' ) { $html = $content; } else { - $html = $label . $help_button . $help_panel . $content . $description; + $html = $label . $description . $help_button . $help_panel . $content; } } @@ -744,30 +689,13 @@ class WPSEO_Metabox extends WPSEO_Meta { } /** - * Creates a sections specific row. - * - * @param string $content The content to show. - * @param string $hidden_help_name Escaped form key name. - * @param string $help_button The help button. - * @param string $help_panel The help text. - * - * @return string - */ - private function create_content_box( $content, $hidden_help_name, $help_button, $help_panel ) { - $html = $content; - $html .= '
      ' . $help_button . $help_panel . '
      '; - - return $html; - } - - /** - * Save the WP SEO metadata for posts. + * Saves the WP SEO metadata for posts. * * {@internal $_POST parameters are validated via sanitize_post_meta().}} * * @param int $post_id Post ID. * - * @return bool|void Boolean false if invalid save post request. + * @return bool|void Boolean false if invalid save post request. */ public function save_postdata( $post_id ) { // Bail if this is a multisite installation and the site has been switched. @@ -779,6 +707,10 @@ class WPSEO_Metabox extends WPSEO_Meta { return false; } + if ( ! isset( $_POST['yoast_free_metabox_nonce'] ) || ! wp_verify_nonce( $_POST['yoast_free_metabox_nonce'], 'yoast_free_metabox' ) ) { + return false; + } + if ( wp_is_post_revision( $post_id ) ) { $post_id = wp_is_post_revision( $post_id ); } @@ -787,11 +719,9 @@ class WPSEO_Metabox extends WPSEO_Meta { * Determine we're not accidentally updating a different post. * We can't use filter_input here as the ID isn't available at this point, other than in the $_POST data. */ - // @codingStandardsIgnoreStart if ( ! isset( $_POST['ID'] ) || $post_id !== (int) $_POST['ID'] ) { return false; } - // @codingStandardsIgnoreEnd clean_post_cache( $post_id ); $post = get_post( $post_id ); @@ -803,31 +733,57 @@ class WPSEO_Metabox extends WPSEO_Meta { do_action( 'wpseo_save_compare_data', $post ); - $meta_boxes = apply_filters( 'wpseo_save_metaboxes', array() ); - $meta_boxes = array_merge( $meta_boxes, $this->get_meta_field_defs( 'general', $post->post_type ), $this->get_meta_field_defs( 'advanced' ) ); + $social_fields = []; + if ( $this->social_is_enabled ) { + $social_fields = WPSEO_Meta::get_meta_field_defs( 'social' ); + } + + $meta_boxes = apply_filters( 'wpseo_save_metaboxes', [] ); + $meta_boxes = array_merge( + $meta_boxes, + WPSEO_Meta::get_meta_field_defs( 'general', $post->post_type ), + WPSEO_Meta::get_meta_field_defs( 'advanced' ), + $social_fields, + WPSEO_Meta::get_meta_field_defs( 'schema', $post->post_type ) + ); foreach ( $meta_boxes as $key => $meta_box ) { // If analysis is disabled remove that analysis score value from the DB. if ( $this->is_meta_value_disabled( $key ) ) { - self::delete( $key, $post_id ); + WPSEO_Meta::delete( $key, $post_id ); continue; } - $data = null; - if ( 'checkbox' === $meta_box['type'] ) { - // @codingStandardsIgnoreLine - $data = isset( $_POST[ self::$form_prefix . $key ] ) ? 'on' : 'off'; + $data = null; + $field_name = WPSEO_Meta::$form_prefix . $key; + + if ( $meta_box['type'] === 'checkbox' ) { + $data = isset( $_POST[ $field_name ] ) ? 'on' : 'off'; } else { - // @codingStandardsIgnoreLine - if ( isset( $_POST[ self::$form_prefix . $key ] ) ) { - // @codingStandardsIgnoreLine - $data = $_POST[ self::$form_prefix . $key ]; + if ( isset( $_POST[ $field_name ] ) ) { + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We're preparing to do just that. + $data = wp_unslash( $_POST[ $field_name ] ); + + // For multi-select. + if ( is_array( $data ) ) { + $data = array_map( [ 'WPSEO_Utils', 'sanitize_text_field' ], $data ); + } + + if ( is_string( $data ) ) { + $data = ( $key !== 'canonical' ) ? WPSEO_Utils::sanitize_text_field( $data ) : WPSEO_Utils::sanitize_url( $data ); + } + } + + // Reset options when no entry is present with multiselect - only applies to `meta-robots-adv` currently. + if ( ! isset( $_POST[ $field_name ] ) && ( $meta_box['type'] === 'multiselect' ) ) { + $data = []; } } - if ( isset( $data ) ) { - self::set_value( $key, $data, $post_id ); + + if ( $data !== null ) { + WPSEO_Meta::set_value( $key, $data, $post_id ); } } @@ -842,11 +798,11 @@ class WPSEO_Metabox extends WPSEO_Meta { * @return bool Whether the given meta value key is disabled. */ public function is_meta_value_disabled( $key ) { - if ( 'linkdex' === $key && ! $this->analysis_seo->is_enabled() ) { + if ( $key === 'linkdex' && ! $this->seo_analysis->is_enabled() ) { return true; } - if ( 'content_score' === $key && ! $this->analysis_readability->is_enabled() ) { + if ( $key === 'content_score' && ! $this->readability_analysis->is_enabled() ) { return true; } @@ -865,96 +821,142 @@ class WPSEO_Metabox extends WPSEO_Meta { $is_editor = self::is_post_overview( $pagenow ) || self::is_post_edit( $pagenow ); + if ( self::is_post_overview( $pagenow ) ) { + $asset_manager->enqueue_style( 'edit-page' ); + $asset_manager->enqueue_script( 'edit-page' ); + + return; + } + /* Filter 'wpseo_always_register_metaboxes_on_admin' documented in wpseo-main.php */ if ( ( $is_editor === false && apply_filters( 'wpseo_always_register_metaboxes_on_admin', false ) === false ) || $this->display_metabox() === false ) { return; } - if ( self::is_post_overview( $pagenow ) ) { - $asset_manager->enqueue_style( 'edit-page' ); - $asset_manager->enqueue_script( 'edit-page-script' ); + $post_id = get_queried_object_id(); + if ( empty( $post_id ) && isset( $_GET['post'] ) ) { + $post_id = sanitize_text_field( filter_input( INPUT_GET, 'post' ) ); } - else { - if ( get_queried_object_id() !== 0 ) { - wp_enqueue_media( array( 'post' => get_queried_object_id() ) ); // Enqueue files needed for upload functionality. - } - - $asset_manager->enqueue_style( 'metabox-css' ); - $asset_manager->enqueue_style( 'scoring' ); - $asset_manager->enqueue_style( 'snippet' ); - $asset_manager->enqueue_style( 'select2' ); - - $asset_manager->enqueue_script( 'metabox' ); - $asset_manager->enqueue_script( 'help-center' ); - $asset_manager->enqueue_script( 'admin-media' ); - - $asset_manager->enqueue_script( 'post-scraper' ); - $asset_manager->enqueue_script( 'replacevar-plugin' ); - $asset_manager->enqueue_script( 'shortcode-plugin' ); - - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'admin-media', 'wpseoMediaL10n', $this->localize_media_script() ); - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'post-scraper', 'wpseoPostScraperL10n', $this->localize_post_scraper_script() ); - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'replacevar-plugin', 'wpseoReplaceVarsL10n', $this->localize_replace_vars_script() ); - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'shortcode-plugin', 'wpseoShortcodePluginL10n', $this->localize_shortcode_plugin_script() ); - - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'metabox', 'wpseoAdminL10n', WPSEO_Help_Center::get_translated_texts() ); - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'metabox', 'wpseoSelect2Locale', WPSEO_Utils::get_language( WPSEO_Utils::get_user_locale() ) ); - - if ( post_type_supports( get_post_type(), 'thumbnail' ) ) { - $asset_manager->enqueue_style( 'featured-image' ); - - $asset_manager->enqueue_script( 'featured-image' ); - - $featured_image_l10 = array( 'featured_image_notice' => __( 'SEO issue: The featured image should be at least 200 by 200 pixels to be picked up by Facebook and other social media sites.', 'wordpress-seo' ) ); - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'metabox', 'wpseoFeaturedImageL10n', $featured_image_l10 ); - } + if ( $post_id !== 0 ) { + // Enqueue files needed for upload functionality. + wp_enqueue_media( [ 'post' => $post_id ] ); } - } - /** - * Pass some variables to js for upload module. - * - * @return array - */ - public function localize_media_script() { - return array( - 'choose_image' => __( 'Use Image', 'wordpress-seo' ), - ); + $asset_manager->enqueue_style( 'metabox-css' ); + $asset_manager->enqueue_style( 'scoring' ); + $asset_manager->enqueue_style( 'select2' ); + $asset_manager->enqueue_style( 'monorepo' ); + + $is_block_editor = WP_Screen::get()->is_block_editor(); + $post_edit_handle = 'post-edit'; + if ( ! $is_block_editor ) { + $post_edit_handle = 'post-edit-classic'; + } + $asset_manager->enqueue_script( $post_edit_handle ); + $asset_manager->enqueue_style( 'admin-css' ); + + $yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_L10n(); + $yoast_components_l10n->localize_script( $post_edit_handle ); + + /** + * Removes the emoji script as it is incompatible with both React and any + * contenteditable fields. + */ + remove_action( 'admin_print_scripts', 'print_emoji_detection_script' ); + + $asset_manager->localize_script( $post_edit_handle, 'wpseoAdminL10n', WPSEO_Utils::get_admin_l10n() ); + + $plugins_script_data = [ + 'replaceVars' => [ + 'no_parent_text' => __( '(no parent)', 'wordpress-seo' ), + 'replace_vars' => $this->get_replace_vars(), + 'recommended_replace_vars' => $this->get_recommended_replace_vars(), + 'scope' => $this->determine_scope(), + 'has_taxonomies' => $this->current_post_type_has_taxonomies(), + ], + 'shortcodes' => [ + 'wpseo_filter_shortcodes_nonce' => wp_create_nonce( 'wpseo-filter-shortcodes' ), + 'wpseo_shortcode_tags' => $this->get_valid_shortcode_tags(), + ], + ]; + + $worker_script_data = [ + 'url' => YoastSEO()->helpers->asset->get_asset_url( 'yoast-seo-analysis-worker' ), + 'dependencies' => YoastSEO()->helpers->asset->get_dependency_urls_by_handle( 'yoast-seo-analysis-worker' ), + 'keywords_assessment_url' => YoastSEO()->helpers->asset->get_asset_url( 'yoast-seo-used-keywords-assessment' ), + 'log_level' => WPSEO_Utils::get_analysis_worker_log_level(), + ]; + + $alert_dismissal_action = YoastSEO()->classes->get( \Yoast\WP\SEO\Actions\Alert_Dismissal_Action::class ); + $dismissed_alerts = $alert_dismissal_action->all_dismissed(); + + $script_data = [ + // @todo replace this translation with JavaScript translations. + 'media' => [ 'choose_image' => __( 'Use Image', 'wordpress-seo' ) ], + 'metabox' => $this->get_metabox_script_data(), + 'userLanguageCode' => WPSEO_Language_Utils::get_language( \get_user_locale() ), + 'isPost' => true, + 'isBlockEditor' => $is_block_editor, + 'analysis' => [ + 'plugins' => $plugins_script_data, + 'worker' => $worker_script_data, + 'estimatedReadingTimeEnabled' => $this->estimated_reading_time_conditional->is_met(), + ], + 'dismissedAlerts' => $dismissed_alerts, + ]; + + if ( post_type_supports( get_post_type(), 'thumbnail' ) ) { + $asset_manager->enqueue_style( 'featured-image' ); + + // @todo replace this translation with JavaScript translations. + $script_data['featuredImage'] = [ + 'featured_image_notice' => __( 'SEO issue: The featured image should be at least 200 by 200 pixels to be picked up by Facebook and other social media sites.', 'wordpress-seo' ), + ]; + } + + $asset_manager->localize_script( $post_edit_handle, 'wpseoScriptData', $script_data ); + $asset_manager->enqueue_user_language_script(); } /** * Returns post in metabox context. * - * @returns WP_Post|array + * @return WP_Post|array */ protected function get_metabox_post() { + if ( $this->post !== null ) { + return $this->post; + } + $post = filter_input( INPUT_GET, 'post' ); if ( ! empty( $post ) ) { $post_id = (int) WPSEO_Utils::validate_int( $post ); - return get_post( $post_id ); - } + $this->post = get_post( $post_id ); + return $this->post; + } if ( isset( $GLOBALS['post'] ) ) { - return $GLOBALS['post']; + $this->post = $GLOBALS['post']; + + return $this->post; } - return array(); + return []; } - /** * Returns an array with shortcode tags for all registered shortcodes. * * @return array */ private function get_valid_shortcode_tags() { - $shortcode_tags = array(); + $shortcode_tags = []; foreach ( $GLOBALS['shortcode_tags'] as $tag => $description ) { - array_push( $shortcode_tags, $tag ); + $shortcode_tags[] = $tag; } return $shortcode_tags; @@ -963,33 +965,41 @@ class WPSEO_Metabox extends WPSEO_Meta { /** * Prepares the replace vars for localization. * - * @return array replace vars + * @return array Replace vars. */ private function get_replace_vars() { - $post = $this->get_metabox_post(); + $cached_replacement_vars = []; - $cached_replacement_vars = array(); - - $vars_to_cache = array( + $vars_to_cache = [ 'date', 'id', 'sitename', 'sitedesc', 'sep', 'page', - 'currenttime', - 'currentdate', - 'currentday', - 'currentmonth', 'currentyear', - ); + ]; foreach ( $vars_to_cache as $var ) { - $cached_replacement_vars[ $var ] = wpseo_replace_vars( '%%' . $var . '%%', $post ); + $cached_replacement_vars[ $var ] = wpseo_replace_vars( '%%' . $var . '%%', $this->get_metabox_post() ); } // Merge custom replace variables with the WordPress ones. - return array_merge( $cached_replacement_vars, $this->get_custom_replace_vars( $post ) ); + return array_merge( $cached_replacement_vars, $this->get_custom_replace_vars( $this->get_metabox_post() ) ); + } + + /** + * Prepares the recommended replace vars for localization. + * + * @return array Recommended replacement variables. + */ + private function get_recommended_replace_vars() { + $recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars(); + + // What is recommended depends on the current context. + $post_type = $recommended_replace_vars->determine_for_post( $this->get_metabox_post() ); + + return $recommended_replace_vars->get_recommended_replacevars_for( $post_type ); } /** @@ -1000,10 +1010,10 @@ class WPSEO_Metabox extends WPSEO_Meta { * @return array Array containing all the replacement variables. */ private function get_custom_replace_vars( $post ) { - return array( + return [ 'custom_fields' => $this->get_custom_fields_replace_vars( $post ), 'custom_taxonomies' => $this->get_custom_taxonomies_replace_vars( $post ), - ); + ]; } /** @@ -1015,7 +1025,7 @@ class WPSEO_Metabox extends WPSEO_Meta { */ private function get_custom_taxonomies_replace_vars( $post ) { $taxonomies = get_object_taxonomies( $post, 'objects' ); - $custom_replace_vars = array(); + $custom_replace_vars = []; foreach ( $taxonomies as $taxonomy_name => $taxonomy ) { @@ -1028,10 +1038,10 @@ class WPSEO_Metabox extends WPSEO_Meta { continue; } - $custom_replace_vars[ $taxonomy_name ] = array( + $custom_replace_vars[ $taxonomy_name ] = [ 'name' => $taxonomy->name, 'description' => $taxonomy->description, - ); + ]; } return $custom_replace_vars; @@ -1045,7 +1055,7 @@ class WPSEO_Metabox extends WPSEO_Meta { * @return array Array containing all the replacement variables. */ private function get_custom_fields_replace_vars( $post ) { - $custom_replace_vars = array(); + $custom_replace_vars = []; // If no post object is passed, return the empty custom_replace_vars array. if ( ! is_object( $post ) ) { @@ -1055,10 +1065,16 @@ class WPSEO_Metabox extends WPSEO_Meta { $custom_fields = get_post_custom( $post->ID ); foreach ( $custom_fields as $custom_field_name => $custom_field ) { + // Skip private custom fields. if ( substr( $custom_field_name, 0, 1 ) === '_' ) { continue; } + // Skip custom field values that are serialized. + if ( is_serialized( $custom_field[0] ) ) { + continue; + } + $custom_replace_vars[ $custom_field_name ] = $custom_field[0]; } @@ -1066,69 +1082,34 @@ class WPSEO_Metabox extends WPSEO_Meta { } /** - * Generic tab. - */ - public function template_generic_tab() { - // This template belongs to the post scraper so don't echo it if it isn't enqueued. - if ( ! wp_script_is( WPSEO_Admin_Asset_Manager::PREFIX . 'post-scraper' ) ) { - return; - } - - echo ''; - } - - /** - * Keyword tab for enabling analysis of multiple keywords. - */ - public function template_keyword_tab() { - // This template belongs to the post scraper so don't echo it if it isn't enqueued. - if ( ! wp_script_is( WPSEO_Admin_Asset_Manager::PREFIX . 'post-scraper' ) ) { - return; - } - - echo ''; - } - - /** + * Checks if the page is the post overview page. + * * @param string $page The page to check for the post overview page. * * @return bool Whether or not the given page is the post overview page. */ public static function is_post_overview( $page ) { - return 'edit.php' === $page; + return $page === 'edit.php'; } /** + * Checks if the page is the post edit page. + * * @param string $page The page to check for the post edit page. * * @return bool Whether or not the given page is the post edit page. */ public static function is_post_edit( $page ) { - return 'post.php' === $page - || 'post-new.php' === $page; + return $page === 'post.php' + || $page === 'post-new.php'; + } + + /** + * Retrieves the product title. + * + * @return string The product title. + */ + protected function get_product_title() { + return YoastSEO()->helpers->product->get_product_name(); } } diff --git a/wp-content/plugins/wordpress-seo/admin/metabox/interface-metabox-analysis.php b/wp-content/plugins/wordpress-seo/admin/metabox/interface-metabox-analysis.php index d351b55e..756ca97d 100644 --- a/wp-content/plugins/wordpress-seo/admin/metabox/interface-metabox-analysis.php +++ b/wp-content/plugins/wordpress-seo/admin/metabox/interface-metabox-analysis.php @@ -6,7 +6,7 @@ */ /** - * Describes an interface for an analysis that can either be enabled or disabled + * Describes an interface for an analysis that can either be enabled or disabled. */ interface WPSEO_Metabox_Analysis { diff --git a/wp-content/plugins/wordpress-seo/admin/notifiers/class-configuration-notifier.php b/wp-content/plugins/wordpress-seo/admin/notifiers/class-configuration-notifier.php index f05cedba..87e9a2e4 100644 --- a/wp-content/plugins/wordpress-seo/admin/notifiers/class-configuration-notifier.php +++ b/wp-content/plugins/wordpress-seo/admin/notifiers/class-configuration-notifier.php @@ -9,9 +9,26 @@ * Represents the logic for showing the notification. */ class WPSEO_Configuration_Notifier implements WPSEO_Listener { + + /** + * Option name use to determine whether the notice has been dismissed. + * + * @var string + */ const META_NAME = 'wpseo-dismiss-configuration-notice'; + + /** + * Default value. + * + * @var string + */ const META_VALUE = 'yes'; - /** @var bool */ + + /** + * Should the notification be shown. + * + * @var bool + */ protected $show_notification; /** @@ -91,13 +108,13 @@ class WPSEO_Configuration_Notifier implements WPSEO_Listener { private function re_run_notification() { $content = sprintf( /* translators: %1$s expands to Yoast SEO, %2$s is a link start tag to the Onboarding Wizard, %3$s is the link closing tag. */ - esc_html__( 'Want to make sure your %1$s settings are still OK? %2$sOpen the configuration wizard again%3$s to validate them.', 'wordpress-seo' ), + esc_html__( 'If you want to double-check your %1$s settings, or change something, you can always %2$sreopen the configuration wizard%3$s.', 'wordpress-seo' ), 'Yoast SEO', '', '' ); - return $this->notification( __( 'Check SEO configuration', 'wordpress-seo' ), $content ); + return $this->notification( __( 'SEO settings configured', 'wordpress-seo' ), $content ); } /** @@ -129,13 +146,16 @@ class WPSEO_Configuration_Notifier implements WPSEO_Listener { private function notification( $title, $content, $show_dismissal = false ) { $notification = '
      '; $notification .= sprintf( - '', + '', esc_url( plugin_dir_url( WPSEO_FILE ) . 'images/new-to-configuration-notice.svg' ), 60, 60 ); $notification .= '
      '; - $notification .= '

      ' . esc_html( $title ) . '

      '; + $notification .= sprintf( + '

      %s

      ', + esc_html( $title ) + ); $notification .= '

      '; $notification .= $content; diff --git a/wp-content/plugins/wordpress-seo/admin/notifiers/dismissible-notification.php b/wp-content/plugins/wordpress-seo/admin/notifiers/dismissible-notification.php new file mode 100644 index 00000000..b241ad14 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/notifiers/dismissible-notification.php @@ -0,0 +1,121 @@ +get_listener_value() !== $this->notification_identifier ) { + return; + } + + $this->dismiss(); + } + + /** + * Adds the notification if applicable, otherwise removes it. + * + * @param Yoast_Notification_Center $notification_center The notification center object. + * + * @return void + */ + public function handle( Yoast_Notification_Center $notification_center ) { + if ( $this->is_applicable() ) { + $notification = $this->get_notification(); + $notification_center->add_notification( $notification ); + + return; + } + + $notification_center->remove_notification_by_id( 'wpseo-' . $this->notification_identifier ); + } + + /** + * Listens to an argument in the request URL and triggers an action. + * + * @return void + */ + protected function dismiss() { + $this->set_dismissal_state(); + $this->redirect_to_dashboard(); + } + + /** + * Checks if a notice is applicable. + * + * @return bool Whether a notice should be shown or not. + */ + protected function is_applicable() { + return $this->is_notice_dismissed() === false; + } + + /** + * Checks whether the notification has been dismissed. + * + * @codeCoverageIgnore + * + * @return bool True when notification is dismissed. + */ + protected function is_notice_dismissed() { + return get_user_meta( get_current_user_id(), 'wpseo-remove-' . $this->notification_identifier, true ) === '1'; + } + + /** + * Retrieves the value where listener is listening for. + * + * @codeCoverageIgnore + * + * @return string The listener value. + */ + protected function get_listener_value() { + return filter_input( INPUT_GET, 'yoast_dismiss' ); + } + + /** + * Dismisses the notification. + * + * @codeCoverageIgnore + * + * @return void + */ + protected function set_dismissal_state() { + update_user_meta( get_current_user_id(), 'wpseo-remove-' . $this->notification_identifier, true ); + } + + /** + * Redirects the user back to the dashboard. + * + * @codeCoverageIgnore + * + * @return void + */ + protected function redirect_to_dashboard() { + wp_safe_redirect( admin_url( 'admin.php?page=wpseo_dashboard' ) ); + exit; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/notifiers/interface-notification-handler.php b/wp-content/plugins/wordpress-seo/admin/notifiers/interface-notification-handler.php new file mode 100644 index 00000000..f798a586 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/notifiers/interface-notification-handler.php @@ -0,0 +1,21 @@ +onpage_option = $this->get_option(); - } - - /** - * Getting the status from the option. - * - * @return string - */ - public function get_status() { - if ( array_key_exists( self::STATUS, $this->onpage_option ) ) { - return $this->onpage_option[ self::STATUS ]; - } - - return self::CANNOT_FETCH; - } - - /** - * Saving the status to the options. - * - * @param string $status The status to save. - */ - public function set_status( $status ) { - $this->onpage_option[ self::STATUS ] = $status; - } - - /** - * Saving the last fetch timestamp to the options. - * - * @param integer $timestamp Timestamp with the new value. - */ - public function set_last_fetch( $timestamp ) { - $this->onpage_option[ self::LAST_FETCH ] = $timestamp; - } - - /** - * Check if the last fetch is within the time of 60 minutes - * - * @return bool - */ - public function should_be_fetched() { - return ( ( time() - $this->onpage_option[ self::LAST_FETCH ] ) > self::FETCH_LIMIT ); - } - - /** - * Saving the option with the current data - */ - public function save_option() { - update_option( self::OPTION_NAME, $this->onpage_option ); - } - - /** - * Returns the value of the onpage_enabled status - * - * @return bool - */ - public function is_enabled() { - return WPSEO_Options::get( 'onpage_indexability' ); - } - - /** - * Getting the option with the Ryte data. - * - * @return array - */ - private function get_option() { - $default = array( - self::STATUS => self::NOT_FETCHED, - self::LAST_FETCH => 0, - ); - - return get_option( self::OPTION_NAME, $default ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/onpage/class-onpage-request.php b/wp-content/plugins/wordpress-seo/admin/onpage/class-onpage-request.php deleted file mode 100644 index 421ac3a6..00000000 --- a/wp-content/plugins/wordpress-seo/admin/onpage/class-onpage-request.php +++ /dev/null @@ -1,67 +0,0 @@ - $target_url, - 'wp_version' => $GLOBALS['wp_version'], - 'yseo_version' => WPSEO_VERSION, - ), $parameters ); - - $url = add_query_arg( $parameters, $this->onpage_endpoint ); - - $response = wp_remote_get( $url ); - $response_code = wp_remote_retrieve_response_code( $response ); - - // When the request is successful, the response code will be 200. - if ( $response_code === 200 ) { - $response_body = wp_remote_retrieve_body( $response ); - - return json_decode( $response_body, true ); - } - } - - /** - * Sending a request to Ryte to check if the $home_url is indexable. - * - * @param string $target_url The URL that will be send to the API. - * @param array $parameters Array of extra parameters to send to Ryte. - * - * @return array - */ - public function do_request( $target_url, $parameters = array() ) { - $json_body = $this->get_remote( $target_url, $parameters ); - - // Ryte recognized a redirect, fetch the data of that URL by calling this method with the value from Ryte. - if ( ! empty( $json_body['passes_juice_to'] ) ) { - return $this->do_request( $json_body['passes_juice_to'], $parameters ); - } - - return $json_body; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/onpage/class-onpage.php b/wp-content/plugins/wordpress-seo/admin/onpage/class-onpage.php deleted file mode 100644 index 1e56a6ad..00000000 --- a/wp-content/plugins/wordpress-seo/admin/onpage/class-onpage.php +++ /dev/null @@ -1,290 +0,0 @@ -catch_redo_listener(); - } - - /** - * Sets up the hooks. - * - * @return void - */ - public function register_hooks() { - // Adds admin notice if necessary. - add_filter( 'admin_init', array( $this, 'show_notice' ) ); - - if ( ! self::is_active() ) { - return; - } - - // Adds weekly schedule to the cron job schedules. - add_filter( 'cron_schedules', array( $this, 'add_weekly_schedule' ) ); - - // Sets the action for the Ryte fetch. - add_action( 'wpseo_onpage_fetch', array( $this, 'fetch_from_onpage' ) ); - } - - /** - * Shows a notice when the website is not indexable. - * - * @return void - */ - public function show_notice() { - $notification = $this->get_indexability_notification(); - $notification_center = Yoast_Notification_Center::get(); - - if ( $this->should_show_notice() ) { - $notification_center->add_notification( $notification ); - - return; - } - - $notification_center->remove_notification( $notification ); - } - - /** - * Determines if we can use the functionality. - * - * @return bool True if this functionality can be used. - */ - public static function is_active() { - if ( defined( 'DOING_AJAX' ) && DOING_AJAX === true ) { - return false; - } - - if ( ! WPSEO_Options::get( 'onpage_indexability' ) ) { - return false; - } - - return true; - } - - /** - * Hooks to run on plugin activation. - */ - public function activate_hooks() { - if ( $this->get_option()->is_enabled() ) { - $this->schedule_cron(); - - return; - } - - $this->unschedule_cron(); - } - - /** - * Adds a weekly cron schedule. - * - * @param array $schedules Currently scheduled items. - * - * @return array Enriched list of schedules. - */ - public function add_weekly_schedule( array $schedules ) { - $schedules['weekly'] = array( - 'interval' => WEEK_IN_SECONDS, - 'display' => __( 'Once Weekly', 'wordpress-seo' ), - ); - - return $schedules; - } - - /** - * Fetches the data from Ryte. - * - * @return bool True if this has been run. - */ - public function fetch_from_onpage() { - $onpage_option = $this->get_option(); - if ( ! $onpage_option->should_be_fetched() ) { - return false; - } - - $new_status = $this->request_indexability(); - if ( false === $new_status ) { - return false; - } - - // Updates the timestamp in the option. - $onpage_option->set_last_fetch( time() ); - - // The currently indexability status. - $old_status = $onpage_option->get_status(); - - $onpage_option->set_status( $new_status ); - $onpage_option->save_option(); - - // Check if the status has been changed. - if ( $old_status !== $new_status && $new_status !== WPSEO_OnPage_Option::CANNOT_FETCH ) { - $this->notify_admins(); - } - - return true; - } - - /** - * Retrieves the option to use. - * - * @return WPSEO_OnPage_Option The option. - */ - protected function get_option() { - return new WPSEO_OnPage_Option(); - } - - /** - * Builds the indexability notification. - * - * @return Yoast_Notification The notification. - */ - private function get_indexability_notification() { - $notice = sprintf( - /* translators: 1: opens a link to a related knowledge base article. 2: closes the link */ - __( '%1$sYour homepage cannot be indexed by search engines%2$s. This is very bad for SEO and should be fixed.', 'wordpress-seo' ), - '', - '' - ); - - return new Yoast_Notification( - $notice, - array( - 'type' => Yoast_Notification::ERROR, - 'id' => 'wpseo-dismiss-onpageorg', - 'capabilities' => 'wpseo_manage_options', - ) - ); - } - - /** - * Sends a request to Ryte to get the indexability. - * - * @return int|bool The indexability value. - */ - protected function request_indexability() { - $parameters = array(); - if ( $this->wordfence_protection_enabled() ) { - $parameters['wf_strict'] = 1; - } - - $request = new WPSEO_OnPage_Request(); - $response = $request->do_request( get_option( 'home' ), $parameters ); - - if ( isset( $response['is_indexable'] ) ) { - return (int) $response['is_indexable']; - } - - return WPSEO_OnPage_Option::CANNOT_FETCH; - } - - /** - * Should the notice being given? - * - * @return bool True if a notice should be shown. - */ - protected function should_show_notice() { - if ( ! $this->get_option()->is_enabled() ) { - return false; - } - - // If development mode is on or the blog is not public, just don't show this notice. - if ( WPSEO_Utils::is_development_mode() || ( '0' === get_option( 'blog_public' ) ) ) { - return false; - } - - return $this->get_option()->get_status() === WPSEO_OnPage_Option::IS_NOT_INDEXABLE; - } - - /** - * Notifies the admins. - * - * @return void - */ - protected function notify_admins() { - /* - * Let's start showing the notices to all admins by removing the hide-notice meta data for each admin resulting - * in popping up the notice again. - */ - delete_metadata( 'user', 0, WPSEO_OnPage::USER_META_KEY, '', true ); - } - - /** - * Schedules the cronjob to get the new indexibility status. - * - * @return void - */ - private function schedule_cron() { - if ( wp_next_scheduled( 'wpseo_onpage_fetch' ) ) { - return; - } - - wp_schedule_event( time(), 'weekly', 'wpseo_onpage_fetch' ); - } - - /** - * Unschedules the cronjob to get the new indexibility status. - * - * @return void - */ - private function unschedule_cron() { - if ( ! wp_next_scheduled( 'wpseo_onpage_fetch' ) ) { - return; - } - - wp_unschedule_event( time(), 'wpseo_onpage_fetch' ); - } - - /** - * Redo the fetch request for Ryte. - * - * @return void - */ - private function catch_redo_listener() { - if ( ! self::is_active() ) { - return; - } - - if ( filter_input( INPUT_GET, 'wpseo-redo-onpage' ) === '1' ) { - $this->is_manual_request = true; - - add_action( 'admin_init', array( $this, 'fetch_from_onpage' ) ); - } - } - - /** - * Checks if WordFence protects the site against 'fake' Google crawlers. - * - * @return boolean True if WordFence protects the site. - */ - private function wordfence_protection_enabled() { - if ( ! class_exists( 'wfConfig' ) ) { - return false; - } - - if ( ! method_exists( 'wfConfig', 'get' ) ) { - return false; - } - - return (bool) wfConfig::get( 'blockFakeBots' ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/onpage/class-ryte-service.php b/wp-content/plugins/wordpress-seo/admin/onpage/class-ryte-service.php deleted file mode 100644 index a2cf4080..00000000 --- a/wp-content/plugins/wordpress-seo/admin/onpage/class-ryte-service.php +++ /dev/null @@ -1,102 +0,0 @@ -option = $option; - } - - /** - * Fetches statistics via REST request. - * - * @return WP_REST_Response The response object. - */ - public function get_statistics() { - $result = false; - - if ( $this->option->is_enabled() ) { - $result = $this->get_score( $this->option->get_status(), $this->option->should_be_fetched() ); - } - - return new WP_REST_Response( array( 'ryte' => $result ) ); - } - - /** - * Returns an the results of the Ryte option based on the passed status. - * - * @param string $status The option's status. - * @param bool $fetch Whether or not the data should be fetched. - * - * @return array The results, contains a score and label. - */ - private function get_score( $status, $fetch = false ) { - if ( $status === WPSEO_OnPage_Option::IS_INDEXABLE ) { - return array( - 'score' => 'good', - 'label' => __( 'Your homepage can be indexed by search engines.', 'wordpress-seo' ), - 'can_fetch' => $fetch, - ); - } - - if ( $status === WPSEO_OnPage_Option::IS_NOT_INDEXABLE ) { - return array( - 'score' => 'bad', - 'label' => sprintf( - /* translators: %1$s: opens a link to a related knowledge base article. %2$s: closes the link. */ - __( '%1$sYour homepage cannot be indexed by search engines%2$s. This is very bad for SEO and should be fixed.', 'wordpress-seo' ), - '', - '' - ), - 'can_fetch' => $fetch, - ); - } - - if ( $status === WPSEO_OnPage_Option::CANNOT_FETCH ) { - return array( - 'score' => 'na', - 'label' => sprintf( - /* translators: %1$s: opens a link to a related knowledge base article, %2$s: expands to Yoast SEO, %3$s: closes the link, %4$s: expands to Ryte. */ - __( '%1$s%2$s has not been able to fetch your site\'s indexability status%3$s from %4$s', 'wordpress-seo' ), - '', - 'Yoast SEO', - '', - 'Ryte' - ), - 'can_fetch' => $fetch, - ); - } - - if ( $status === WPSEO_OnPage_Option::NOT_FETCHED ) { - return array( - 'score' => 'na', - 'label' => esc_html( sprintf( - /* translators: %1$s: expands to Yoast SEO, %2$s: expands to Ryte. */ - __( '%1$s has not fetched your site\'s indexability status yet from %2$s', 'wordpress-seo' ), - 'Yoast SEO', - 'Ryte' - ) ), - 'can_fetch' => $fetch, - ); - } - - return array(); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/pages/dashboard.php b/wp-content/plugins/wordpress-seo/admin/pages/dashboard.php index 2dbeecb3..ecbdf462 100644 --- a/wp-content/plugins/wordpress-seo/admin/pages/dashboard.php +++ b/wp-content/plugins/wordpress-seo/admin/pages/dashboard.php @@ -11,18 +11,11 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { exit(); } -if ( filter_input( INPUT_GET, 'intro' ) ) { - update_user_meta( get_current_user_id(), 'wpseo_seen_about_version', WPSEO_VERSION ); - require WPSEO_PATH . 'admin/views/about.php'; - - return; -} - if ( isset( $_GET['allow_tracking'] ) && check_admin_referer( 'wpseo_activate_tracking', 'nonce' ) ) { WPSEO_Options::set( 'yoast_tracking', ( $_GET['allow_tracking'] === 'yes' ) ); if ( isset( $_SERVER['HTTP_REFERER'] ) ) { - wp_safe_redirect( $_SERVER['HTTP_REFERER'], 307 ); + wp_safe_redirect( wp_unslash( $_SERVER['HTTP_REFERER'] ), 307 ); exit; } } @@ -32,35 +25,38 @@ $yform->admin_header( true, 'wpseo' ); do_action( 'wpseo_all_admin_notices' ); -$tabs = new WPSEO_Option_Tabs( 'dashboard' ); -$tabs->add_tab( +$dashboard_tabs = new WPSEO_Option_Tabs( 'dashboard' ); +$dashboard_tabs->add_tab( new WPSEO_Option_Tab( 'dashboard', __( 'Dashboard', 'wordpress-seo' ), - array( - 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-notification-center' ), + [ 'save_button' => false, - ) + ] ) ); -$tabs->add_tab( +$dashboard_tabs->add_tab( new WPSEO_Option_Tab( 'features', - __( 'Features', 'wordpress-seo' ), - array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-features' ) ) + __( 'Features', 'wordpress-seo' ) ) ); -$tabs->add_tab( +$dashboard_tabs->add_tab( + new WPSEO_Option_Tab( + 'integrations', + __( 'Integrations', 'wordpress-seo' ) + ) +); +$dashboard_tabs->add_tab( new WPSEO_Option_Tab( 'webmaster-tools', - __( 'Webmaster Tools', 'wordpress-seo' ), - array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-general-search-console' ) ) + __( 'Webmaster Tools', 'wordpress-seo' ) ) ); -do_action( 'wpseo_settings_tabs_dashboard', $tabs ); +do_action( 'wpseo_settings_tabs_dashboard', $dashboard_tabs ); -$tabs->display( $yform ); +$dashboard_tabs->display( $yform ); do_action( 'wpseo_dashboard' ); diff --git a/wp-content/plugins/wordpress-seo/admin/pages/licenses.php b/wp-content/plugins/wordpress-seo/admin/pages/licenses.php index 7f92c318..fb713cdc 100644 --- a/wp-content/plugins/wordpress-seo/admin/pages/licenses.php +++ b/wp-content/plugins/wordpress-seo/admin/pages/licenses.php @@ -12,6 +12,4 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { exit(); } -$license_page_manager = new WPSEO_License_Page_Manager(); -$licenses_page = $license_page_manager->get_license_page(); -require WPSEO_PATH . 'admin/views/' . $licenses_page . '.php'; +require WPSEO_PATH . 'admin/views/licenses.php'; diff --git a/wp-content/plugins/wordpress-seo/admin/pages/metas.php b/wp-content/plugins/wordpress-seo/admin/pages/metas.php index e57291d0..31344fcd 100644 --- a/wp-content/plugins/wordpress-seo/admin/pages/metas.php +++ b/wp-content/plugins/wordpress-seo/admin/pages/metas.php @@ -11,71 +11,17 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { exit(); } -add_filter( 'wpseo_help_center_items', 'yoast_add_meta_options_help_center_tabs' ); - $yform = Yoast_Form::get_instance(); $yform->admin_header( true, 'wpseo_titles' ); -$tabs = new WPSEO_Option_Tabs( 'metas' ); -$tabs->add_tab( new WPSEO_Option_Tab( 'general', __( 'General', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-metas' ) ) ) ); -$tabs->add_tab( new WPSEO_Option_Tab( 'post-types', __( 'Content Types', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-metas-post-types' ) ) ) ); -$tabs->add_tab( new WPSEO_Option_Tab( 'media', __( 'Media', 'wordpress-seo' ) ) ); -$tabs->add_tab( new WPSEO_Option_Tab( 'taxonomies', __( 'Taxonomies', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-metas-taxonomies' ) ) ) ); -$tabs->add_tab( new WPSEO_Option_Tab( 'archives', __( 'Archives', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-metas-archives' ) ) ) ); -$tabs->add_tab( new WPSEO_Option_Tab( 'breadcrumbs', __( 'Breadcrumbs', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-breadcrumbs' ) ) ) ); -$tabs->add_tab( new WPSEO_Option_Tab( 'rss', __( 'RSS', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-rss' ) ) ) ); -$tabs->display( $yform ); +$metas_tabs = new WPSEO_Option_Tabs( 'metas' ); +$metas_tabs->add_tab( new WPSEO_Option_Tab( 'general', __( 'General', 'wordpress-seo' ) ) ); +$metas_tabs->add_tab( new WPSEO_Option_Tab( 'post-types', __( 'Content Types', 'wordpress-seo' ) ) ); +$metas_tabs->add_tab( new WPSEO_Option_Tab( 'media', __( 'Media', 'wordpress-seo' ) ) ); +$metas_tabs->add_tab( new WPSEO_Option_Tab( 'taxonomies', __( 'Taxonomies', 'wordpress-seo' ) ) ); +$metas_tabs->add_tab( new WPSEO_Option_Tab( 'archives', __( 'Archives', 'wordpress-seo' ) ) ); +$metas_tabs->add_tab( new WPSEO_Option_Tab( 'breadcrumbs', __( 'Breadcrumbs', 'wordpress-seo' ) ) ); +$metas_tabs->add_tab( new WPSEO_Option_Tab( 'rss', __( 'RSS', 'wordpress-seo' ) ) ); +$metas_tabs->display( $yform ); $yform->admin_footer(); - -/** - * Adds help tabs. - * - * @param array $tabs Current help center tabs. - * - * @return array List containing all the additional tabs. - */ -function yoast_add_meta_options_help_center_tabs( $tabs ) { - - $tabs[] = new WPSEO_Help_Center_Item( - 'template-variables', - __( 'Template explanation', 'wordpress-seo' ), - array( 'content' => wpseo_add_template_variables_helpcenter() ) - ); - - return $tabs; -} - -/** - * Adds template variables to the help center. - * - * @return string The content for the template variables tab. - */ -function wpseo_add_template_variables_helpcenter() { - $explanation = sprintf( - /* translators: %1$s expands to Yoast SEO. */ - __( 'The search appearance settings for %1$s are made up of variables that are replaced by specific values from the page when the page is displayed. The table below contains a list of the available variables.', 'wordpress-seo' ), - 'Yoast SEO' - ); - - $output_explanation = sprintf( - '

      %s

      %s

      %s

      ', - esc_html( __( 'Template explanation', 'wordpress-seo' ) ), - esc_html( $explanation ), - esc_html( __( 'Note that not all variables can be used in every template.', 'wordpress-seo' ) ) - ); - - $output_basic = sprintf( - '

      %s

      %s', - esc_html( __( 'Basic Variables', 'wordpress-seo' ) ), - WPSEO_Replace_Vars::get_basic_help_texts() - ); - - $output_advanced = sprintf( - '

      %s

      %s', - esc_html( __( 'Advanced Variables', 'wordpress-seo' ) ), - WPSEO_Replace_Vars::get_advanced_help_texts() - ); - - return $output_explanation . $output_basic . $output_advanced; -} diff --git a/wp-content/plugins/wordpress-seo/admin/pages/network.php b/wp-content/plugins/wordpress-seo/admin/pages/network.php index d91161c4..60ad2f19 100644 --- a/wp-content/plugins/wordpress-seo/admin/pages/network.php +++ b/wp-content/plugins/wordpress-seo/admin/pages/network.php @@ -12,144 +12,13 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { } $yform = Yoast_Form::get_instance(); +$yform->admin_header( true, 'wpseo_ms' ); -$options = get_site_option( 'wpseo_ms' ); +$network_tabs = new WPSEO_Option_Tabs( 'network' ); +$network_tabs->add_tab( new WPSEO_Option_Tab( 'general', __( 'General', 'wordpress-seo' ) ) ); +$network_tabs->add_tab( new WPSEO_Option_Tab( 'features', __( 'Features', 'wordpress-seo' ) ) ); +$network_tabs->add_tab( new WPSEO_Option_Tab( 'integrations', __( 'Integrations', 'wordpress-seo' ) ) ); +$network_tabs->add_tab( new WPSEO_Option_Tab( 'restore-site', __( 'Restore Site', 'wordpress-seo' ), [ 'save_button' => false ] ) ); +$network_tabs->display( $yform ); -if ( isset( $_POST['wpseo_submit'] ) ) { - check_admin_referer( 'wpseo-network-settings' ); - - foreach ( array( 'access', 'defaultblog' ) as $opt ) { - $options[ $opt ] = $_POST['wpseo_ms'][ $opt ]; - } - unset( $opt ); - WPSEO_Options::update_site_option( 'wpseo_ms', $options ); - add_settings_error( 'wpseo_ms', 'settings_updated', __( 'Settings Updated.', 'wordpress-seo' ), 'updated' ); -} - -if ( isset( $_POST['wpseo_restore_blog'] ) ) { - check_admin_referer( 'wpseo-network-restore' ); - if ( isset( $_POST['wpseo_ms']['restoreblog'] ) && is_numeric( $_POST['wpseo_ms']['restoreblog'] ) ) { - $restoreblog = (int) WPSEO_Utils::validate_int( $_POST['wpseo_ms']['restoreblog'] ); - $blog = get_blog_details( $restoreblog ); - - if ( $blog ) { - WPSEO_Options::reset_ms_blog( $restoreblog ); - /* translators: %s expands to the name of a blog within a multi-site network. */ - add_settings_error( 'wpseo_ms', 'settings_updated', sprintf( __( '%s restored to default SEO settings.', 'wordpress-seo' ), esc_html( $blog->blogname ) ), 'updated' ); - } - else { - /* translators: %s expands to the ID of a blog within a multi-site network. */ - add_settings_error( 'wpseo_ms', 'settings_updated', sprintf( __( 'Blog %s not found.', 'wordpress-seo' ), esc_html( $restoreblog ) ), 'error' ); - } - unset( $restoreblog, $blog ); - } -} - -/* Set up selectbox dropdowns for smaller networks (usability) */ -$use_dropdown = true; -if ( get_blog_count() > 100 ) { - $use_dropdown = false; -} -else { - - $sites = array_map( 'get_object_vars', get_sites( array( 'deleted' => 0 ) ) ); - - if ( is_array( $sites ) && $sites !== array() ) { - $dropdown_input = array( - '-' => __( 'None', 'wordpress-seo' ), - ); - - foreach ( $sites as $site ) { - $dropdown_input[ $site['blog_id'] ] = $site['blog_id'] . ': ' . $site['domain']; - - $blog_states = array(); - if ( $site['public'] === '1' ) { - $blog_states[] = __( 'public', 'wordpress-seo' ); - } - if ( $site['archived'] === '1' ) { - $blog_states[] = __( 'archived', 'wordpress-seo' ); - } - if ( $site['mature'] === '1' ) { - $blog_states[] = __( 'mature', 'wordpress-seo' ); - } - if ( $site['spam'] === '1' ) { - $blog_states[] = __( 'spam', 'wordpress-seo' ); - } - if ( $blog_states !== array() ) { - $dropdown_input[ $site['blog_id'] ] .= ' [' . implode( ', ', $blog_states ) . ']'; - } - } - unset( $site, $blog_states ); - } - else { - $use_dropdown = false; - } - unset( $sites ); -} - -$yform->admin_header( false, 'wpseo_ms' ); - -echo '

      ', esc_html__( 'MultiSite Settings', 'wordpress-seo' ), '

      '; -echo '
      '; -wp_nonce_field( 'wpseo-network-settings', '_wpnonce', true, true ); - -/* {@internal Important: Make sure the options added to the array here are in line with the options set in the WPSEO_Option_MS::$allowed_access_options property.}} */ -$yform->select( - 'access', - /* translators: %1$s expands to Yoast SEO */ - sprintf( __( 'Who should have access to the %1$s settings', 'wordpress-seo' ), 'Yoast SEO' ), - array( - 'admin' => __( 'Site Admins (default)', 'wordpress-seo' ), - 'superadmin' => __( 'Super Admins only', 'wordpress-seo' ), - ), - 'wpseo_ms' -); - -if ( $use_dropdown === true ) { - $yform->select( - 'defaultblog', - __( 'New sites in the network inherit their SEO settings from this site', 'wordpress-seo' ), - $dropdown_input, - 'wpseo_ms' - ); - echo '

      ' . esc_html__( 'Choose the site whose settings you want to use as default for all sites that are added to your network. If you choose \'None\', the normal plugin defaults will be used.', 'wordpress-seo' ) . '

      '; -} -else { - $yform->textinput( 'defaultblog', __( 'New sites in the network inherit their SEO settings from this site', 'wordpress-seo' ), 'wpseo_ms' ); - echo '

      '; - printf( - /* translators: 1: link open tag; 2: link close tag. */ - esc_html__( 'Enter the %1$sSite ID%2$s for the site whose settings you want to use as default for all sites that are added to your network. Leave empty for none (i.e. the normal plugin defaults will be used).', 'wordpress-seo' ), - '', - '' - ); - echo '

      '; -} - echo '

      ' . esc_html__( 'Take note:', 'wordpress-seo' ) . ' ' . esc_html__( 'Privacy sensitive (FB admins and such), theme specific (title rewrite) and a few very site specific settings will not be imported to new blogs.', 'wordpress-seo' ) . '

      '; - - -echo ''; -echo '
      '; - -echo '

      ' . esc_html__( 'Restore site to default settings', 'wordpress-seo' ) . '

      '; -echo '
      '; -wp_nonce_field( 'wpseo-network-restore', '_wpnonce', true, true ); -echo '

      ' . esc_html__( 'Using this form you can reset a site to the default SEO settings.', 'wordpress-seo' ) . '

      '; - -if ( $use_dropdown === true ) { - unset( $dropdown_input['-'] ); - $yform->select( - 'restoreblog', - __( 'Site ID', 'wordpress-seo' ), - $dropdown_input, - 'wpseo_ms' - ); -} -else { - $yform->textinput( 'restoreblog', __( 'Blog ID', 'wordpress-seo' ), 'wpseo_ms' ); -} - -echo ''; -echo '
      '; - -$yform->admin_footer( false ); +$yform->admin_footer(); diff --git a/wp-content/plugins/wordpress-seo/admin/pages/social.php b/wp-content/plugins/wordpress-seo/admin/pages/social.php index 6b4655e8..a8d5723d 100644 --- a/wp-content/plugins/wordpress-seo/admin/pages/social.php +++ b/wp-content/plugins/wordpress-seo/admin/pages/social.php @@ -14,12 +14,12 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { $yform = Yoast_Form::get_instance(); $yform->admin_header( true, 'wpseo_social' ); -$tabs = new WPSEO_Option_Tabs( 'social' ); -$tabs->add_tab( new WPSEO_Option_Tab( 'accounts', __( 'Accounts', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-social-accounts' ) ) ) ); -$tabs->add_tab( new WPSEO_Option_Tab( 'facebook', __( 'Facebook', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-social-facebook' ) ) ) ); -$tabs->add_tab( new WPSEO_Option_Tab( 'twitterbox', __( 'Twitter', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-social-twitter' ) ) ) ); -$tabs->add_tab( new WPSEO_Option_Tab( 'pinterest', __( 'Pinterest', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-social-pinterest' ) ) ) ); -$tabs->add_tab( new WPSEO_Option_Tab( 'google', __( 'Google+', 'wordpress-seo' ), array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-social-google' ) ) ) ); -$tabs->display( $yform ); +$social_tabs = new WPSEO_Option_Tabs( 'social' ); +$social_tabs->add_tab( new WPSEO_Option_Tab( 'accounts', __( 'Accounts', 'wordpress-seo' ) ) ); +$social_tabs->add_tab( new WPSEO_Option_Tab( 'facebook', __( 'Facebook', 'wordpress-seo' ) ) ); +$social_tabs->add_tab( new WPSEO_Option_Tab( 'twitterbox', __( 'Twitter', 'wordpress-seo' ) ) ); +$social_tabs->add_tab( new WPSEO_Option_Tab( 'pinterest', __( 'Pinterest', 'wordpress-seo' ) ) ); + +$social_tabs->display( $yform ); $yform->admin_footer(); diff --git a/wp-content/plugins/wordpress-seo/admin/pages/tools.php b/wp-content/plugins/wordpress-seo/admin/pages/tools.php index 21da645b..fa4aba9b 100644 --- a/wp-content/plugins/wordpress-seo/admin/pages/tools.php +++ b/wp-content/plugins/wordpress-seo/admin/pages/tools.php @@ -16,26 +16,26 @@ $tool_page = (string) filter_input( INPUT_GET, 'tool' ); $yform = Yoast_Form::get_instance(); $yform->admin_header( false ); -if ( '' === $tool_page ) { +if ( $tool_page === '' ) { - $tools = array(); + $tools = []; - $tools['import-export'] = array( + $tools['import-export'] = [ 'title' => __( 'Import and Export', 'wordpress-seo' ), 'desc' => __( 'Import settings from other SEO plugins and export your settings for re-use on (another) blog.', 'wordpress-seo' ), - ); + ]; if ( WPSEO_Utils::allow_system_file_edit() === true && ! is_multisite() ) { - $tools['file-editor'] = array( + $tools['file-editor'] = [ 'title' => __( 'File editor', 'wordpress-seo' ), 'desc' => __( 'This tool allows you to quickly change important files for your SEO, like your robots.txt and, if you have one, your .htaccess file.', 'wordpress-seo' ), - ); + ]; } - $tools['bulk-editor'] = array( + $tools['bulk-editor'] = [ 'title' => __( 'Bulk editor', 'wordpress-seo' ), 'desc' => __( 'This tool allows you to quickly change titles and descriptions of your posts and pages without having to go into the editor for each page.', 'wordpress-seo' ), - ); + ]; echo '

      '; printf( @@ -50,12 +50,12 @@ if ( '' === $tool_page ) { $admin_url = admin_url( 'admin.php?page=wpseo_tools' ); foreach ( $tools as $slug => $tool ) { - $href = ( ! empty( $tool['href'] ) ) ? $admin_url . $tool['href'] : add_query_arg( array( 'tool' => $slug ), $admin_url ); + $href = ( ! empty( $tool['href'] ) ) ? $admin_url . $tool['href'] : add_query_arg( [ 'tool' => $slug ], $admin_url ); $attr = ( ! empty( $tool['attr'] ) ) ? $tool['attr'] : ''; echo '

    • '; - echo '', esc_html( $tool['title'] ), '
      '; - echo $tool['desc']; + echo '', esc_html( $tool['title'] ), '
      '; + echo esc_html( $tool['desc'] ); echo '
    • '; } @@ -65,14 +65,11 @@ if ( '' === $tool_page ) { do_action( 'wpseo_tools_overview_list_items' ); echo '
    '; - - echo ''; - } else { echo '', esc_html__( '« Back to Tools page', 'wordpress-seo' ), ''; - $tool_pages = array( 'bulk-editor', 'import-export' ); + $tool_pages = [ 'bulk-editor', 'import-export' ]; if ( WPSEO_Utils::allow_system_file_edit() === true && ! is_multisite() ) { $tool_pages[] = 'file-editor'; diff --git a/wp-content/plugins/wordpress-seo/admin/recalculate/class-recalculate-posts.php b/wp-content/plugins/wordpress-seo/admin/recalculate/class-recalculate-posts.php deleted file mode 100644 index bddcca17..00000000 --- a/wp-content/plugins/wordpress-seo/admin/recalculate/class-recalculate-posts.php +++ /dev/null @@ -1,151 +0,0 @@ -save_score( $score ); - } - } - - /** - * Save the score. - * - * @param array $score The score to save. - */ - protected function save_score( array $score ) { - WPSEO_Meta::set_value( 'linkdex', $score['score'], $score['item_id'] ); - } - - /** - * Get the posts from the database by doing a WP_Query. - * - * @param integer $paged The page. - * - * @return string - */ - protected function get_items( $paged ) { - $items_per_page = max( 1, $this->items_per_page ); - $post_query = new WP_Query( - array( - 'post_type' => 'any', - 'meta_key' => '_yoast_wpseo_focuskw', - 'posts_per_page' => $items_per_page, - 'paged' => $paged, - ) - ); - - return $post_query->get_posts(); - } - - /** - * Map the posts to a response array - * - * @param WP_Post $item The post for which to build the analyzer data. - * - * @return array - */ - protected function item_to_response( $item ) { - $focus_keyword = WPSEO_Meta::get_value( 'focuskw', $item->ID ); - - $content = $item->post_content; - - // Check if there's a featured image. - $content .= $this->add_featured_image( $item ); - - /** - * Filter the post content for use in the SEO score recalculation. - * - * @param string $content Content of the post. Modify to reflect front-end content. - * @param WP_Post $item The Post object the content comes from. - */ - $content = apply_filters( 'wpseo_post_content_for_recalculation', $content, $item ); - - // Apply shortcodes. - $content = do_shortcode( $content ); - - return array( - 'post_id' => $item->ID, - 'text' => $content, - 'keyword' => $focus_keyword, - 'url' => urldecode( $item->post_name ), - 'pageTitle' => apply_filters( 'wpseo_title', wpseo_replace_vars( $this->get_title( $item->ID, $item->post_type ), $item ) ), - 'meta' => apply_filters( 'wpseo_metadesc', wpseo_replace_vars( $this->get_meta_description( $item->ID, $item->post_type ), $item ) ), - 'keyword_usage' => array( - $focus_keyword => WPSEO_Meta::keyword_usage( $focus_keyword, $item->ID ), - ), - ); - } - - /** - * Get the title for given post - * - * @param integer $post_id The ID of the post for which to get the title. - * @param string $post_type The post type. - * - * @return mixed|string - */ - private function get_title( $post_id, $post_type ) { - $title = WPSEO_Meta::get_value( 'title', $post_id ); - if ( '' !== $title ) { - return $title; - } - - $default_from_options = $this->default_from_options( 'title-tax', $post_type ); - if ( false !== $default_from_options ) { - return str_replace( ' %%page%% ', ' ', $default_from_options ); - } - - return '%%title%%'; - } - - /** - * Get the meta description for given post - * - * @param integer $post_id The ID of the post for which to get the meta description. - * @param string $post_type The post type. - * - * @return bool|string - */ - private function get_meta_description( $post_id, $post_type ) { - $meta_description = WPSEO_Meta::get_value( 'metadesc', $post_id ); - if ( '' !== $meta_description ) { - return $meta_description; - } - - $default_from_options = $this->default_from_options( 'metadesc', $post_type ); - if ( false !== $default_from_options ) { - return $default_from_options; - } - - return ''; - } - - /** - * Retrieves the associated featured image if there is one present. - * - * @param WP_Post $item The post item to check for a featured image. - * - * @return string The image string. - */ - private function add_featured_image( $item ) { - if ( ! has_post_thumbnail( $item->ID ) ) { - return ''; - } - - return ' ' . get_the_post_thumbnail( $item->ID ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/recalculate/class-recalculate-terms.php b/wp-content/plugins/wordpress-seo/admin/recalculate/class-recalculate-terms.php deleted file mode 100644 index 99e7734b..00000000 --- a/wp-content/plugins/wordpress-seo/admin/recalculate/class-recalculate-terms.php +++ /dev/null @@ -1,151 +0,0 @@ -items_per_page ); - - return get_terms( - get_taxonomies(), - array( - 'hide_empty' => false, - 'number' => $items_per_page, - 'offset' => $items_per_page * abs( $paged - 1 ), - ) - ); - } - - /** - * Convert the given term into a analyzable object. - * - * @param mixed $item The term for which to build the analyzer data. - * - * @return array - */ - protected function item_to_response( $item ) { - $focus_keyword = $this->get_focus_keyword( $item ); - $title = str_replace( ' %%page%% ', ' ', $this->get_title( $item ) ); - $meta = $this->get_meta_description( $item ); - - $description = $item->description; - - /** - * Filter the term description for recalculation. - * - * @param string $description Content of the term. Modify to reflect front-end content. - * @oaram WP_Term $item The term the description comes from. - */ - $description = apply_filters( 'wpseo_term_description_for_recalculation', $description, $item ); - - return array( - 'term_id' => $item->term_id, - 'taxonomy' => $item->taxonomy, - 'text' => $description, - 'keyword' => $focus_keyword, - 'url' => urldecode( $item->slug ), - 'pageTitle' => apply_filters( 'wpseo_title', wpseo_replace_vars( $title, $item, array( 'page' ) ) ), - 'meta' => apply_filters( 'wpseo_metadesc', wpseo_replace_vars( $meta, $item ) ), - 'keyword_usage' => array( - $focus_keyword => WPSEO_Taxonomy_Meta::get_keyword_usage( $focus_keyword, $item->term_id, $item->taxonomy ), - ), - ); - } - - /** - * Gets the focus keyword for the term - * - * @param stdClass|WP_Term $term Term to determine the keyword for. - * - * @return bool|string - */ - private function get_focus_keyword( $term ) { - $focus_keyword = WPSEO_Taxonomy_Meta::get_term_meta( 'focuskw', $term->term_id, $term->taxonomy ); - if ( ! empty( $focus_keyword ) ) { - return $focus_keyword; - } - - return $term->name; - } - - /** - * Get the title for given term - * - * @param stdClass|WP_Term $term The term object. - * - * @return mixed|string - */ - private function get_title( $term ) { - $title = WPSEO_Taxonomy_Meta::get_term_meta( $term->term_id, $term->taxonomy, 'title' ); - if ( '' !== $title ) { - return $title; - } - - $default_from_options = $this->default_from_options( 'title-tax', $term->taxonomy ); - if ( false !== $default_from_options ) { - return $default_from_options; - } - - return '%%title%%'; - } - - /** - * Get the meta description for given post - * - * @param stdClass|WP_Term $term The term object. - * - * @return bool|string - */ - private function get_meta_description( $term ) { - $meta_description = WPSEO_Taxonomy_Meta::get_term_meta( $term->term_id, $term->taxonomy, 'desc' ); - if ( '' !== $meta_description ) { - return $meta_description; - } - - $default_from_options = $this->default_from_options( 'metadesc-tax', $term->taxonomy ); - if ( false !== $default_from_options ) { - return $default_from_options; - } - - return ''; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/recalculate/class-recalculate.php b/wp-content/plugins/wordpress-seo/admin/recalculate/class-recalculate.php deleted file mode 100644 index a32a320f..00000000 --- a/wp-content/plugins/wordpress-seo/admin/recalculate/class-recalculate.php +++ /dev/null @@ -1,103 +0,0 @@ -get_items( $paged ); - - $return['items'] = $this->parse_items( $items ); - $return['total_items'] = count( $items ); - - if ( $return['total_items'] >= $this->items_per_page ) { - $return['next_page'] = ( $paged + 1 ); - } - - return $return; - } - - /** - * Parse the posts|terms with the value we need - * - * @param array $items The items to parse. - * - * @return array - */ - protected function parse_items( array $items ) { - $return = array(); - foreach ( $items as $item ) { - $response = $this->item_to_response( $item ); - if ( ! empty( $response ) ) { - $return[] = $response; - } - } - - return $return; - } - - /** - * Get default from the options for given field - * - * @param string $field The field for which to get the default options. - * @param string $suffix The post type. - * - * @return bool|string - */ - protected function default_from_options( $field, $suffix ) { - $target_option_field = $field . '-' . $suffix; - if ( '' !== WPSEO_Options::get( $target_option_field, '' ) ) { - return WPSEO_Options::get( $target_option_field ); - } - - return false; - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/roles/class-abstract-role-manager.php b/wp-content/plugins/wordpress-seo/admin/roles/class-abstract-role-manager.php index 23b810c9..39edad49 100644 --- a/wp-content/plugins/wordpress-seo/admin/roles/class-abstract-role-manager.php +++ b/wp-content/plugins/wordpress-seo/admin/roles/class-abstract-role-manager.php @@ -9,24 +9,28 @@ * Abstract Role Manager template. */ abstract class WPSEO_Abstract_Role_Manager implements WPSEO_Role_Manager { - /** @var array Registered roles. */ - protected $roles = array(); + + /** + * Registered roles. + * + * @var array + */ + protected $roles = []; /** * Registers a role. * * @param string $role Role to register. * @param string $display_name Display name to use. - * @param null|string $template Optional. Role to base the new role on. + * @param string|null $template Optional. Role to base the new role on. * * @return void */ public function register( $role, $display_name, $template = null ) { - $this->roles[ $role ] = - (object) array( - 'display_name' => $display_name, - 'template' => $template, - ); + $this->roles[ $role ] = (object) [ + 'display_name' => $display_name, + 'template' => $template, + ]; } /** @@ -59,7 +63,7 @@ abstract class WPSEO_Abstract_Role_Manager implements WPSEO_Role_Manager { */ public function remove() { $roles = array_keys( $this->roles ); - array_map( array( $this, 'remove_role' ), $roles ); + array_map( [ $this, 'remove_role' ], $roles ); } /** @@ -71,12 +75,12 @@ abstract class WPSEO_Abstract_Role_Manager implements WPSEO_Role_Manager { */ protected function get_capabilities( $role ) { if ( ! is_string( $role ) || empty( $role ) ) { - return array(); + return []; } $wp_role = get_role( $role ); if ( ! $wp_role ) { - return array(); + return []; } return $wp_role->capabilities; @@ -105,7 +109,7 @@ abstract class WPSEO_Abstract_Role_Manager implements WPSEO_Role_Manager { * @return array Capabilties that can be safely set. */ protected function filter_existing_capabilties( $role, array $capabilities ) { - if ( $capabilities === array() ) { + if ( $capabilities === [] ) { return $capabilities; } @@ -132,10 +136,10 @@ abstract class WPSEO_Abstract_Role_Manager implements WPSEO_Role_Manager { * * @return void */ - abstract protected function add_role( $role, $display_name, array $capabilities = array() ); + abstract protected function add_role( $role, $display_name, array $capabilities = [] ); /** - * Removes a role from the system + * Removes a role from the system. * * @param string $role Role to remove. * diff --git a/wp-content/plugins/wordpress-seo/admin/roles/class-register-roles.php b/wp-content/plugins/wordpress-seo/admin/roles/class-register-roles.php index 001bd033..9636237e 100644 --- a/wp-content/plugins/wordpress-seo/admin/roles/class-register-roles.php +++ b/wp-content/plugins/wordpress-seo/admin/roles/class-register-roles.php @@ -9,13 +9,14 @@ * Role registration class. */ class WPSEO_Register_Roles implements WPSEO_WordPress_Integration { + /** * Adds hooks. * * @return void */ public function register_hooks() { - add_action( 'wpseo_register_roles', array( $this, 'register' ) ); + add_action( 'wpseo_register_roles', [ $this, 'register' ] ); } /** diff --git a/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-factory.php b/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-factory.php index 266ac049..4fb5ec1e 100644 --- a/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-factory.php +++ b/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-factory.php @@ -9,6 +9,7 @@ * Role Manager Factory. */ class WPSEO_Role_Manager_Factory { + /** * Retrieves the Role manager to use. * diff --git a/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-vip.php b/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-vip.php index 0c545d78..3faf5ab4 100644 --- a/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-vip.php +++ b/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-vip.php @@ -9,6 +9,7 @@ * VIP implementation of the Role Manager. */ final class WPSEO_Role_Manager_VIP extends WPSEO_Abstract_Role_Manager { + /** * Adds a role to the system. * @@ -18,9 +19,9 @@ final class WPSEO_Role_Manager_VIP extends WPSEO_Abstract_Role_Manager { * * @return void */ - protected function add_role( $role, $display_name, array $capabilities = array() ) { - $enabled_capabilities = array(); - $disabled_capabilities = array(); + protected function add_role( $role, $display_name, array $capabilities = [] ) { + $enabled_capabilities = []; + $disabled_capabilities = []; // Build lists of enabled and disabled capabilities. foreach ( $capabilities as $capability => $grant ) { @@ -34,7 +35,7 @@ final class WPSEO_Role_Manager_VIP extends WPSEO_Abstract_Role_Manager { } wpcom_vip_add_role( $role, $display_name, $enabled_capabilities ); - if ( $disabled_capabilities !== array() ) { + if ( $disabled_capabilities !== [] ) { wpcom_vip_remove_role_caps( $role, $disabled_capabilities ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-wp.php b/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-wp.php index 8fca04c5..f3555670 100644 --- a/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-wp.php +++ b/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager-wp.php @@ -19,7 +19,7 @@ final class WPSEO_Role_Manager_WP extends WPSEO_Abstract_Role_Manager { * * @return void */ - protected function add_role( $role, $display_name, array $capabilities = array() ) { + protected function add_role( $role, $display_name, array $capabilities = [] ) { $wp_role = get_role( $role ); if ( $wp_role ) { foreach ( $capabilities as $capability => $grant ) { @@ -29,7 +29,6 @@ final class WPSEO_Role_Manager_WP extends WPSEO_Abstract_Role_Manager { return; } - // @codingStandardsIgnoreLine add_role( $role, $display_name, $capabilities ); } diff --git a/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager.php b/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager.php index 629afbce..7f9d82bb 100644 --- a/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager.php +++ b/wp-content/plugins/wordpress-seo/admin/roles/class-role-manager.php @@ -9,12 +9,13 @@ * Role Manager interface. */ interface WPSEO_Role_Manager { + /** * Registers a role. * * @param string $role Role to register. * @param string $display_name Display name to use. - * @param null|string $template Optional. Role to base the new role on. + * @param string|null $template Optional. Role to base the new role on. * * @return void */ diff --git a/wp-content/plugins/wordpress-seo/admin/ryte/class-ryte-option.php b/wp-content/plugins/wordpress-seo/admin/ryte/class-ryte-option.php new file mode 100644 index 00000000..dd9bd78a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/ryte/class-ryte-option.php @@ -0,0 +1,160 @@ +ryte_option = $this->get_option(); + } + + /** + * Getting the status from the option. + * + * @return string + */ + public function get_status() { + if ( array_key_exists( self::STATUS, $this->ryte_option ) ) { + return $this->ryte_option[ self::STATUS ]; + } + + return self::CANNOT_FETCH; + } + + /** + * Saving the status to the options. + * + * @param string $status The status to save. + */ + public function set_status( $status ) { + $this->ryte_option[ self::STATUS ] = $status; + } + + /** + * Saving the last fetch timestamp to the options. + * + * @param int $timestamp Timestamp with the new value. + */ + public function set_last_fetch( $timestamp ) { + $this->ryte_option[ self::LAST_FETCH ] = $timestamp; + } + + /** + * Determines whether the indexability status should be fetched. + * + * If LAST_FETCH isn't set, we assume the indexability status hasn't been fetched + * yet and return true. Then, we check whether the last fetch is within the + * FETCH_LIMIT time interval (15 seconds) to avoid too many consecutive API calls. + * + * @return bool Whether the indexability status should be fetched. + */ + public function should_be_fetched() { + if ( ! isset( $this->ryte_option[ self::LAST_FETCH ] ) ) { + return true; + } + + return ( ( time() - $this->ryte_option[ self::LAST_FETCH ] ) > self::FETCH_LIMIT ); + } + + /** + * Saving the option with the current data. + */ + public function save_option() { + update_option( self::OPTION_NAME, $this->ryte_option ); + } + + /** + * Returns the value of the onpage_enabled status. + * + * @return bool + */ + public function is_enabled() { + return WPSEO_Options::get( 'ryte_indexability' ); + } + + /** + * Getting the option with the Ryte data. + * + * @return array + */ + private function get_option() { + $default = [ + self::STATUS => self::NOT_FETCHED, + self::LAST_FETCH => 0, + ]; + + return get_option( self::OPTION_NAME, $default ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/ryte/class-ryte-request.php b/wp-content/plugins/wordpress-seo/admin/ryte/class-ryte-request.php new file mode 100644 index 00000000..d50a177e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/ryte/class-ryte-request.php @@ -0,0 +1,107 @@ + $target_url, + 'wp_version' => $GLOBALS['wp_version'], + 'yseo_version' => WPSEO_VERSION, + ]; + + $parameters = array_merge( $defaults, $parameters ); + $url = add_query_arg( $parameters, $this->ryte_endpoint ); + + // Decrease a chance of "cURL 28 (timeout)" errors by increasing the timeout to 10 seconds. + $args = [ 'timeout' => 10 ]; + $response = wp_remote_get( $url, $args ); + + return $this->process_response( $response ); + } + + /** + * Sends a request to the Ryte API to check whether a URL is indexable. + * + * @param string $target_url The URL to check indexability for. + * @param array $parameters Array of extra parameters to send to the Ryte API. + * + * @return array + */ + public function do_request( $target_url, $parameters = [] ) { + $json_body = $this->get_remote( $target_url, $parameters ); + + // Ryte recognized a redirect, fetch the data of that URL by calling this method with the value from Ryte. + if ( ! empty( $json_body['passes_juice_to'] ) ) { + return $this->do_request( $json_body['passes_juice_to'], $parameters ); + } + + return $json_body; + } + + /** + * Processes the given Ryte response. + * + * @param array|WP_Error $response The response or WP_Error to process. + * + * @return array The response body or the error detaiils on failure. + */ + protected function process_response( $response ) { + // Most of the potential errors are WP_Error(s). + if ( is_wp_error( $response ) ) { + return [ + 'is_error' => true, + 'raw_error_code' => '', + // WP_Error codes aren't that helpful for users, let's display them in a less prominent way. + 'wp_error_code' => '(' . $response->get_error_code() . ')', + 'message' => $response->get_error_message(), + ]; + } + + /* + * As of February 2020 the Ryte API returns an error 500 for non-reachable + * sites. There's also the need to handle any potential raw HTTP error. + */ + if ( wp_remote_retrieve_response_code( $response ) !== 200 ) { + // Not all HTTP errors may have a response message. Let's provide a default one. + $response_message = wp_remote_retrieve_response_message( $response ); + $message = ( $response_message ) ? $response_message : __( 'The request to Ryte returned an error.', 'wordpress-seo' ); + + return [ + 'is_error' => true, + 'raw_error_code' => wp_remote_retrieve_response_code( $response ), + 'wp_error_code' => '', + 'message' => $message, + ]; + } + + // When the request is successful, the response code will be 200. + $response_body = wp_remote_retrieve_body( $response ); + + return json_decode( $response_body, true ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/ryte/class-ryte.php b/wp-content/plugins/wordpress-seo/admin/ryte/class-ryte.php new file mode 100644 index 00000000..9537bda7 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/ryte/class-ryte.php @@ -0,0 +1,230 @@ +maybe_add_weekly_schedule(); + } + + /** + * Sets up the hooks. + * + * @return void + */ + public function register_hooks() { + if ( ! self::is_active() ) { + return; + } + + // Sets the action for the Ryte fetch cron job. + add_action( 'wpseo_ryte_fetch', [ $this, 'fetch_from_ryte' ] ); + } + + /** + * Determines if we can use the functionality. + * + * @return bool True if this functionality can be used. + */ + public static function is_active() { + if ( wp_doing_ajax() ) { + return false; + } + + if ( ! WPSEO_Options::get( 'ryte_indexability' ) ) { + return false; + } + + return true; + } + + /** + * Hooks to run on plugin activation. + */ + public function activate_hooks() { + if ( $this->get_option()->is_enabled() ) { + $this->schedule_cron(); + + return; + } + + $this->unschedule_cron(); + } + + /** + * Determines whether to add a custom cron weekly schedule. + * + * @return void + */ + public function maybe_add_weekly_schedule() { + // If there's no default cron weekly schedule, add a custom one. + add_filter( 'cron_schedules', [ $this, 'add_weekly_schedule' ] ); + } + + /** + * Adds a custom weekly cron schedule. + * + * @param array $schedules The existing custom cron schedules. + * + * @return array Enriched list of custom cron schedules. + */ + public function add_weekly_schedule( $schedules ) { + if ( ! is_array( $schedules ) ) { + $schedules = []; + } + + /* + * Starting with version 5.4, WordPress does have a default weekly cron + * schedule. See https://core.trac.wordpress.org/changeset/47062. + * We need to add a custom one only if the default one doesn't exist. + */ + if ( isset( $schedules['weekly'] ) ) { + return $schedules; + } + + $schedules['weekly'] = [ + 'interval' => WEEK_IN_SECONDS, + 'display' => __( 'Once Weekly', 'wordpress-seo' ), + ]; + + return $schedules; + } + + /** + * Fetches the data from Ryte. + * + * @return bool|null Whether the request ran. + */ + public function fetch_from_ryte() { + // Don't do anything when the WordPress environment type isn't "production". + if ( wp_get_environment_type() !== 'production' ) { + return; + } + + $ryte_option = $this->get_option(); + if ( ! $ryte_option->should_be_fetched() ) { + return false; + } + + $new_status = $this->request_indexability(); + + // Updates the timestamp in the option. + $ryte_option->set_last_fetch( time() ); + + $ryte_option->set_status( $new_status ); + $ryte_option->save_option(); + + return true; + } + + /** + * Retrieves the option to use. + * + * @return WPSEO_Ryte_Option The option. + */ + protected function get_option() { + return new WPSEO_Ryte_Option(); + } + + /** + * Sends a request to Ryte to get the indexability status. + * + * @return int The indexability status value. + */ + protected function request_indexability() { + $parameters = []; + if ( $this->wordfence_protection_enabled() ) { + $parameters['wf_strict'] = 1; + } + + $request = new WPSEO_Ryte_Request(); + $response = $request->do_request( get_option( 'home' ), $parameters ); + + // Populate the ryte_response property. + $this->ryte_response = $response; + + // It's a valid Ryte response because the array contains an `is_indexable` element. + if ( isset( $response['is_indexable'] ) ) { + return (int) $response['is_indexable']; + } + + // It's not a valid Ryte response. + return WPSEO_Ryte_Option::CANNOT_FETCH; + } + + /** + * Schedules the cronjob to get the new indexability status. + * + * @return void + */ + private function schedule_cron() { + if ( wp_next_scheduled( 'wpseo_ryte_fetch' ) ) { + return; + } + + wp_schedule_event( time(), 'weekly', 'wpseo_ryte_fetch' ); + } + + /** + * Unschedules the cronjob to get the new indexability status. + * + * @return void + */ + private function unschedule_cron() { + if ( ! wp_next_scheduled( 'wpseo_ryte_fetch' ) ) { + return; + } + + wp_clear_scheduled_hook( 'wpseo_ryte_fetch' ); + } + + /** + * Checks if WordFence protects the site against 'fake' Google crawlers. + * + * @return bool True if WordFence protects the site. + */ + private function wordfence_protection_enabled() { + if ( ! class_exists( 'wfConfig' ) ) { + return false; + } + + if ( ! method_exists( 'wfConfig', 'get' ) ) { + return false; + } + + return (bool) wfConfig::get( 'blockFakeBots' ); + } + + /** + * Retrieves the Ryte API response property. + * + * @return array|WP_Error The response or WP_Error on failure. + */ + public function get_response() { + return $this->ryte_response; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/services/class-file-size.php b/wp-content/plugins/wordpress-seo/admin/services/class-file-size.php new file mode 100644 index 00000000..a1435749 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/services/class-file-size.php @@ -0,0 +1,106 @@ +get_file_url( $request ); + + return new WP_REST_Response( + [ + 'type' => 'success', + 'size_in_bytes' => $this->get_file_size( $file_url ), + ], + 200 + ); + } + catch ( WPSEO_File_Size_Exception $exception ) { + return new WP_REST_Response( + [ + 'type' => 'failure', + 'response' => $exception->getMessage(), + ], + 404 + ); + } + } + + /** + * Retrieves the file url. + * + * @param WP_REST_Request $request The request to retrieve file url from. + * + * @return string The file url. + * @throws WPSEO_File_Size_Exception The file is hosted externally. + */ + protected function get_file_url( WP_REST_Request $request ) { + $file_url = rawurldecode( $request->get_param( 'url' ) ); + + if ( ! $this->is_externally_hosted( $file_url ) ) { + return $file_url; + } + + throw WPSEO_File_Size_Exception::externally_hosted( $file_url ); + } + + /** + * Checks if the file is hosted externally. + * + * @param string $file_url The file url. + * + * @return bool True if it is hosted externally. + */ + protected function is_externally_hosted( $file_url ) { + return wp_parse_url( home_url(), PHP_URL_HOST ) !== wp_parse_url( $file_url, PHP_URL_HOST ); + } + + /** + * Returns the file size. + * + * @param string $file_url The file url to get the size for. + * + * @return int The file size. + * @throws WPSEO_File_Size_Exception Retrieval of file size went wrong for unknown reasons. + */ + protected function get_file_size( $file_url ) { + $file_config = wp_upload_dir(); + $file_url = str_replace( $file_config['baseurl'], '', $file_url ); + $file_size = $this->calculate_file_size( $file_url ); + + if ( ! $file_size ) { + throw WPSEO_File_Size_Exception::unknown_error( $file_url ); + } + + return $file_size; + } + + /** + * Calculates the file size using the Utils class. + * + * @param string $file_url The file to retrieve the size for. + * + * @return int|bool The file size or False if it could not be retrieved. + */ + protected function calculate_file_size( $file_url ) { + return WPSEO_Image_Utils::get_file_size( + [ + 'path' => $file_url, + ] + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/statistics/class-statistics-integration.php b/wp-content/plugins/wordpress-seo/admin/statistics/class-statistics-integration.php index 5dd70191..756f314c 100644 --- a/wp-content/plugins/wordpress-seo/admin/statistics/class-statistics-integration.php +++ b/wp-content/plugins/wordpress-seo/admin/statistics/class-statistics-integration.php @@ -6,17 +6,18 @@ */ /** - * Class WPSEO_Statistic_Integration + * Class WPSEO_Statistic_Integration. */ class WPSEO_Statistic_Integration implements WPSEO_WordPress_Integration { + /** * Adds hooks to clear the cache. * * @return void */ public function register_hooks() { - add_action( 'wp_insert_post', array( $this, 'clear_cache' ) ); - add_action( 'delete_post', array( $this, 'clear_cache' ) ); + add_action( 'wp_insert_post', [ $this, 'clear_cache' ] ); + add_action( 'delete_post', [ $this, 'clear_cache' ] ); } /** @@ -25,6 +26,11 @@ class WPSEO_Statistic_Integration implements WPSEO_WordPress_Integration { * @return void */ public function clear_cache() { + // Bail if this is a multisite installation and the site has been switched. + if ( is_multisite() && ms_is_switched() ) { + return; + } + delete_transient( WPSEO_Statistics_Service::CACHE_TRANSIENT_KEY ); } } diff --git a/wp-content/plugins/wordpress-seo/admin/statistics/class-statistics-service.php b/wp-content/plugins/wordpress-seo/admin/statistics/class-statistics-service.php index c8cb6f07..f4bc49af 100644 --- a/wp-content/plugins/wordpress-seo/admin/statistics/class-statistics-service.php +++ b/wp-content/plugins/wordpress-seo/admin/statistics/class-statistics-service.php @@ -6,18 +6,27 @@ */ /** - * Class WPSEO_Statistics_Service + * Class WPSEO_Statistics_Service. */ class WPSEO_Statistics_Service { + /** + * Cache transient id. + * + * @var string + */ const CACHE_TRANSIENT_KEY = 'wpseo-statistics-totals'; /** + * Class that generates interesting statistics about things. + * * @var WPSEO_Statistics */ protected $statistics; /** + * Statistics labels. + * * @var string[] */ protected $labels; @@ -29,7 +38,6 @@ class WPSEO_Statistics_Service { */ public function __construct( WPSEO_Statistics $statistics ) { $this->statistics = $statistics; - $this->labels = $this->labels(); } /** @@ -38,12 +46,16 @@ class WPSEO_Statistics_Service { * @return WP_REST_Response The response object. */ public function get_statistics() { - $statistics = $this->statistic_items(); + // Switch to the user locale with fallback to the site locale. + switch_to_locale( \get_user_locale() ); - $data = array( + $this->labels = $this->labels(); + $statistics = $this->statistic_items(); + + $data = [ 'header' => $this->get_header_from_statistics( $statistics ), 'seo_scores' => $statistics['scores'], - ); + ]; return new WP_REST_Response( $data ); } @@ -69,7 +81,7 @@ class WPSEO_Statistics_Service { } /** - * An array representing items to be added to the At a Glance dashboard widget + * An array representing items to be added to the At a Glance dashboard widget. * * @return array The statistics for the current user. */ @@ -93,17 +105,17 @@ class WPSEO_Statistics_Service { $transient = get_transient( self::CACHE_TRANSIENT_KEY ); if ( $transient === false ) { - return array(); + return []; } return $transient; } /** - * Set the statistics transient cache for a specific user + * Set the statistics transient cache for a specific user. * * @param array $transient The current stored transient with the cached data. - * @param int $user The user's ID to assign the retrieved values to. + * @param int $user The user's ID to assign the retrieved values to. * * @return array The statistics transient for the user. */ @@ -111,11 +123,11 @@ class WPSEO_Statistics_Service { $scores = $this->get_seo_scores_with_post_count(); $division = $this->get_seo_score_division( $scores ); - $transient[ $user ] = array( + $transient[ $user ] = [ // Use array_values because array_filter may return non-zero indexed arrays. - 'scores' => array_values( array_filter( $scores, array( $this, 'filter_items' ) ) ), + 'scores' => array_values( array_filter( $scores, [ $this, 'filter_items' ] ) ), 'division' => $division, - ); + ]; set_transient( self::CACHE_TRANSIENT_KEY, $transient, DAY_IN_SECONDS ); @@ -131,7 +143,7 @@ class WPSEO_Statistics_Service { */ private function get_seo_score_division( array $scores ) { $total = 0; - $division = array(); + $division = []; foreach ( $scores as $score ) { $total += $score['count']; @@ -156,7 +168,7 @@ class WPSEO_Statistics_Service { private function get_seo_scores_with_post_count() { $ranks = WPSEO_Rank::get_all_ranks(); - return array_map( array( $this, 'map_rank_to_widget' ), $ranks ); + return array_map( [ $this, 'map_rank_to_widget' ], $ranks ); } /** @@ -167,12 +179,12 @@ class WPSEO_Statistics_Service { * @return array The mapped rank. */ private function map_rank_to_widget( WPSEO_Rank $rank ) { - return array( + return [ 'seo_rank' => $rank->get_rank(), 'label' => $this->get_label_for_rank( $rank ), 'count' => $this->statistics->get_post_count( $rank ), 'link' => $this->get_link_for_rank( $rank ), - ); + ]; } /** @@ -189,20 +201,33 @@ class WPSEO_Statistics_Service { /** * Determines the labels for the various scoring ranks that are known within Yoast SEO. * - * @return array Array containing the translateable labels. + * @return array Array containing the translatable labels. */ private function labels() { - return array( - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag */ - WPSEO_Rank::NO_FOCUS => sprintf( __( 'Posts %1$swithout%2$s a focus keyword', 'wordpress-seo' ), '', '' ), - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag */ - WPSEO_Rank::BAD => sprintf( __( 'Posts with the SEO score: %1$sneeds improvement%2$s', 'wordpress-seo' ), '', '' ), - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag */ - WPSEO_Rank::OK => sprintf( __( 'Posts with the SEO score: %1$sOK%2$s', 'wordpress-seo' ), '', '' ), - /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag */ - WPSEO_Rank::GOOD => sprintf( __( 'Posts with the SEO score: %1$sgood%2$s', 'wordpress-seo' ), '', '' ), + return [ + WPSEO_Rank::NO_FOCUS => sprintf( + /* translators: %1$s expands to an opening strong tag, %2$s expands to a closing strong tag */ + __( 'Posts %1$swithout%2$s a focus keyphrase', 'wordpress-seo' ), + '', + '' + ), + WPSEO_Rank::BAD => sprintf( + /* translators: %s expands to the score */ + __( 'Posts with the SEO score: %s', 'wordpress-seo' ), + '' . __( 'Needs improvement', 'wordpress-seo' ) . '' + ), + WPSEO_Rank::OK => sprintf( + /* translators: %s expands to the score */ + __( 'Posts with the SEO score: %s', 'wordpress-seo' ), + '' . __( 'OK', 'wordpress-seo' ) . '' + ), + WPSEO_Rank::GOOD => sprintf( + /* translators: %s expands to the score */ + __( 'Posts with the SEO score: %s', 'wordpress-seo' ), + '' . __( 'Good', 'wordpress-seo' ) . '' + ), WPSEO_Rank::NO_INDEX => __( 'Posts that should not show up in search results', 'wordpress-seo' ), - ); + ]; } /** diff --git a/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-columns.php b/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-columns.php index 5352d58f..c5920541 100644 --- a/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-columns.php +++ b/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-columns.php @@ -11,17 +11,23 @@ class WPSEO_Taxonomy_Columns { /** + * The SEO analysis. + * * @var WPSEO_Metabox_Analysis_SEO */ private $analysis_seo; /** + * The readability analysis. + * * @var WPSEO_Metabox_Analysis_Readability */ private $analysis_readability; /** - * @var string The current taxonomy + * The current taxonomy. + * + * @var string */ private $taxonomy; @@ -33,8 +39,8 @@ class WPSEO_Taxonomy_Columns { $this->taxonomy = $this->get_taxonomy(); if ( ! empty( $this->taxonomy ) ) { - add_filter( 'manage_edit-' . $this->taxonomy . '_columns', array( $this, 'add_columns' ) ); - add_filter( 'manage_' . $this->taxonomy . '_custom_column', array( $this, 'parse_column' ), 10, 3 ); + add_filter( 'manage_edit-' . $this->taxonomy . '_columns', [ $this, 'add_columns' ] ); + add_filter( 'manage_' . $this->taxonomy . '_custom_column', [ $this, 'parse_column' ], 10, 3 ); } $this->analysis_seo = new WPSEO_Metabox_Analysis_SEO(); @@ -53,7 +59,7 @@ class WPSEO_Taxonomy_Columns { return $columns; } - $new_columns = array(); + $new_columns = []; foreach ( $columns as $column_name => $column_value ) { $new_columns[ $column_name ] = $column_value; @@ -73,9 +79,9 @@ class WPSEO_Taxonomy_Columns { /** * Parses the column. * - * @param string $content The current content of the column. - * @param string $column_name The name of the column. - * @param integer $term_id ID of requested taxonomy. + * @param string $content The current content of the column. + * @param string $column_name The name of the column. + * @param int $term_id ID of requested taxonomy. * * @return string */ @@ -107,7 +113,7 @@ class WPSEO_Taxonomy_Columns { * @return string|null */ private function get_taxonomy() { - if ( defined( 'DOING_AJAX' ) && DOING_AJAX === true ) { + if ( wp_doing_ajax() ) { return FILTER_INPUT( INPUT_POST, 'taxonomy' ); } @@ -117,7 +123,7 @@ class WPSEO_Taxonomy_Columns { /** * Parses the value for the score column. * - * @param integer $term_id ID of requested term. + * @param int $term_id ID of requested term. * * @return string */ @@ -157,7 +163,7 @@ class WPSEO_Taxonomy_Columns { /** * Creates an icon by the given values. * - * @param WPSEO_Rank $rank The ranking object. + * @param WPSEO_Rank $rank The ranking object. * @param string $title Optional. The title to show. Defaults to the rank label. * * @return string The HTML for a score icon. @@ -167,7 +173,7 @@ class WPSEO_Taxonomy_Columns { $title = $rank->get_label(); } - return '' . $title . ''; + return '' . $title . ''; } /** @@ -231,7 +237,7 @@ class WPSEO_Taxonomy_Columns { * * @since 7.0 * - * @param string $taxonomy Optional. The taxonomy to test, defaults to the current taxonomy. + * @param string|null $taxonomy Optional. The taxonomy to test, defaults to the current taxonomy. * * @return bool Whether or not the meta box (and associated columns etc) should be hidden. */ @@ -244,6 +250,4 @@ class WPSEO_Taxonomy_Columns { return WPSEO_Utils::is_metabox_active( $taxonomy, 'taxonomy' ); } - - } diff --git a/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-content-fields.php b/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-content-fields.php deleted file mode 100644 index 9b36e8dd..00000000 --- a/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-content-fields.php +++ /dev/null @@ -1,78 +0,0 @@ - $this->get_field_config( - __( 'Snippet editor', 'wordpress-seo' ), - '', - 'snippetpreview', - array( - 'help-button' => __( 'Show information about the snippet editor', 'wordpress-seo' ), - /* translators: 1: link open tag; 2: link close tag. */ - 'help' => sprintf( __( 'This is a rendering of what this post might look like in Google\'s search results. %1$sLearn more about the Snippet Preview%2$s.', 'wordpress-seo' ), '', '' ), - ) - ), - 'focuskw' => $this->get_field_config( - __( 'Focus keyword', 'wordpress-seo' ), - '', - 'focuskeyword', - array( - 'help-button' => __( 'Show information about the focus keyword', 'wordpress-seo' ), - /* translators: 1: link open tag; 2: link close tag. */ - 'help' => sprintf( __( 'Pick the main keyword or keyphrase that this post/page is about. %1$sLearn more about the Focus Keyword%2$s.', 'wordpress-seo' ), '', '' ), - ) - ), - 'analysis' => $this->get_field_config( - __( 'Analysis', 'wordpress-seo' ), - '', - 'pageanalysis', - array( - 'help-button' => __( 'Show information about the content analysis', 'wordpress-seo' ), - /* translators: 1: link open tag; 2: link close tag. */ - 'help' => sprintf( __( 'This is the content analysis, a collection of content checks that analyze the content of your page. %1$sLearn more about the Content Analysis Tool%2$s.', 'wordpress-seo' ), '', '' ), - ) - ), - 'title' => $this->get_field_config( - '', - '', - 'hidden', - '' - ), - 'desc' => $this->get_field_config( - '', - '', - 'hidden', - '' - ), - 'linkdex' => $this->get_field_config( - '', - '', - 'hidden', - '' - ), - 'content_score' => $this->get_field_config( - '', - '', - 'hidden', - '' - ), - ); - - return $this->filter_hidden_fields( $fields ); - } -} diff --git a/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-fields-presenter.php b/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-fields-presenter.php index 5e08a2ff..933be47b 100644 --- a/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-fields-presenter.php +++ b/wp-content/plugins/wordpress-seo/admin/taxonomy/class-taxonomy-fields-presenter.php @@ -6,18 +6,20 @@ */ /** - * Class WPSEO_Taxonomy_Presenter + * Class WPSEO_Taxonomy_Presenter. */ class WPSEO_Taxonomy_Fields_Presenter { /** - * The taxonomy meta data for the current term + * The taxonomy meta data for the current term. * * @var array */ private $tax_meta; /** + * Constructs the WPSEO_Taxonomy_Fields_Presenter class. + * * @param stdClass $term The current term. */ public function __construct( $term ) { @@ -25,9 +27,11 @@ class WPSEO_Taxonomy_Fields_Presenter { } /** - * Displaying the form fields + * Displaying the form fields. * * @param array $fields Array with the fields that will be displayed. + * + * @return string */ public function html( array $fields ) { $content = ''; @@ -42,6 +46,8 @@ class WPSEO_Taxonomy_Fields_Presenter { * * @param string $field_name Variable the row controls. * @param array $field_configuration Array with the field configuration. + * + * @return string */ private function form_row( $field_name, array $field_configuration ) { $esc_field_name = esc_attr( $field_name ); @@ -58,10 +64,6 @@ class WPSEO_Taxonomy_Fields_Presenter { $help_button_text = isset( $field_configuration['options']['help-button'] ) ? $field_configuration['options']['help-button'] : ''; $help = new WPSEO_Admin_Help_Panel( $field_name, $help_button_text, $help_content ); - if ( in_array( $field_configuration['type'], array( 'focuskeyword', 'pageanalysis', 'snippetpreview' ), true ) ) { - return $this->parse_section_row( $field, $field_configuration['type'], $help ); - } - return $this->parse_row( $label, $help, $field ); } @@ -91,30 +93,8 @@ class WPSEO_Taxonomy_Fields_Presenter { case 'div': $field .= '
    '; break; - - case 'snippetpreview': - $field .= '
    '; - break; - case 'pageanalysis': - if ( WPSEO_Options::get( 'content_analysis_active', true ) === false && WPSEO_Options::get( 'keyword_analysis_active', true ) === false ) { - break; - } - - $field .= '
    '; - $field .= '
    '; - $field .= '

    ' . __( 'Analysis', 'wordpress-seo' ) . '

    '; - $field .= '
    '; - $field .= '
    '; - $field .= '
    '; - break; - case 'focuskeyword': - $field .= '
    '; - $field .= '
    '; - $field .= '

    ' . __( 'Focus keyword', 'wordpress-seo' ) . '

    '; - $field .= ''; - $field .= '
    '; - $field .= '
    '; - $field .= '
    '; + case 'url': + $field .= ''; break; case 'text': $field .= ''; @@ -130,11 +110,31 @@ class WPSEO_Taxonomy_Fields_Presenter { $field .= ''; break; case 'upload': - $field .= ''; - $field .= ''; + $field .= ' '; + $field .= ' '; + $field .= ''; break; case 'select': - if ( is_array( $options ) && $options !== array() ) { + if ( is_array( $options ) && $options !== [] ) { $field .= 'name="" id=""> $option_html_value ) : ?> diff --git a/wp-content/plugins/wordpress-seo/admin/views/js-templates-primary-term.php b/wp-content/plugins/wordpress-seo/admin/views/js-templates-primary-term.php index 17fb5720..a1387529 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/js-templates-primary-term.php +++ b/wp-content/plugins/wordpress-seo/admin/views/js-templates-primary-term.php @@ -12,25 +12,19 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { } ?> - - diff --git a/wp-content/plugins/wordpress-seo/admin/views/licenses.php b/wp-content/plugins/wordpress-seo/admin/views/licenses.php index f6508683..6f729f02 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/licenses.php +++ b/wp-content/plugins/wordpress-seo/admin/views/licenses.php @@ -12,132 +12,90 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { exit(); } -$extension_list = new WPSEO_Extensions(); -$extensions = $extension_list->get(); +do_action( 'wpseo_install_and_activate_addons' ); -// First invalidate all licenses. -array_map( array( $extension_list, 'invalidate' ), $extensions ); +$premium_extension = [ + 'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zz' ), + 'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zy' ), + 'title' => 'Yoast SEO Premium', + /* translators: %1$s expands to Yoast SEO */ + 'desc' => sprintf( __( 'The premium version of %1$s with more features & support.', 'wordpress-seo' ), 'Yoast SEO' ), + 'benefits' => [], +]; -$extensions = new WPSEO_Extension_Manager(); - -$extensions->add( - 'wordpress-seo-premium', - new WPSEO_Extension( - array( - 'url' => WPSEO_Shortlinker::get( 'https://yoa.st/pe-premium-page' ), - 'title' => 'Yoast SEO Premium', - /* translators: %1$s expands to Yoast SEO */ - 'desc' => sprintf( __( 'The premium version of %1$s with more features & support.', 'wordpress-seo' ), 'Yoast SEO' ), - 'image' => plugins_url( 'images/extensions-premium-ribbon.png?v=' . WPSEO_VERSION, WPSEO_FILE ), - 'benefits' => array(), - ) - ) -); - -$extensions->add( - 'wpseo-video', - new WPSEO_Extension( - array( - 'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zx/' ), - 'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zw/' ), - 'title' => 'Video SEO', - 'desc' => __( 'Optimize your videos to show them off in search results and get more clicks!', 'wordpress-seo' ), - 'image' => plugins_url( 'images/extensions-video.png?v=' . WPSEO_VERSION, WPSEO_FILE ), - 'benefits' => array( - __( 'Show your videos in Google Videos', 'wordpress-seo' ), - __( 'Enhance the experience of sharing posts with videos', 'wordpress-seo' ), - __( 'Make videos responsive through enabling fitvids.js', 'wordpress-seo' ), - ), - ) - ) -); - -$extensions->add( - 'wpseo-news', - new WPSEO_Extension( - array( - 'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zv/' ), - 'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zu/' ), - 'title' => 'News SEO', - 'desc' => __( 'Are you in Google News? Increase your traffic from Google News by optimizing for it!', 'wordpress-seo' ), - 'image' => plugins_url( 'images/extensions-news.png?v=' . WPSEO_VERSION, WPSEO_FILE ), - 'benefits' => array( - __( 'Optimize your site for Google News', 'wordpress-seo' ), - __( 'Immediately pings Google on the publication of a new post', 'wordpress-seo' ), - __( 'Creates XML News Sitemaps', 'wordpress-seo' ), - ), - ) - ) -); - -if ( ! defined( 'WPSEO_LOCAL_WOOCOMMERCE_VERSION' ) ) { - $extensions->add( - 'wpseo-local', - new WPSEO_Extension( - array( - 'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zt' ), - 'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zs' ), - 'title' => 'Local SEO', - 'desc' => __( 'Rank better locally and in Google Maps, without breaking a sweat!', 'wordpress-seo' ), - 'image' => plugins_url( 'images/extensions-local.png?v=' . WPSEO_VERSION, WPSEO_FILE ), - 'benefits' => array( - __( 'Get found by potential clients', 'wordpress-seo' ), - __( 'Easily insert Google Maps, a store locator, opening hours and more', 'wordpress-seo' ), - __( 'Improve the usability of your contact page', 'wordpress-seo' ), - ), - ) - ) - ); -} - -$extensions->add( - 'wpseo-local-woocommerce', - new WPSEO_Extension( - array( - 'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/272' ), - 'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/273' ), - 'title' => 'Local SEO for WooCommerce', - 'desc' => __( 'Rank better locally and in Google Maps, without breaking a sweat!', 'wordpress-seo' ), - 'image' => plugins_url( 'images/extensions-local-for-woocommerce.png?v=' . WPSEO_VERSION, WPSEO_FILE ), - 'benefits' => array( - esc_html__( 'Get better search results in local search', 'wordpress-seo' ), - esc_html__( 'Enhance your contact pages with Google Maps, opening hours and a store locator', 'wordpress-seo' ), - /* translators: %1$s expands to WooCommerce */ - sprintf( esc_html__( 'Allow customers to pick up their %s order locally', 'wordpress-seo' ), 'WooCommerce' ), - ), - ) - ) -); +$extensions = [ + WPSEO_Addon_Manager::LOCAL_SLUG => [ + 'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zt' ), + 'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zs' ), + 'title' => 'Local SEO', + 'display_title' => __( 'Stop losing customers to other local businesses', 'wordpress-seo' ), + 'desc' => __( 'Rank better locally and in Google Maps, without breaking a sweat!', 'wordpress-seo' ), + 'image' => plugins_url( 'images/local_plugin_assistant.svg?v=' . WPSEO_VERSION, WPSEO_FILE ), + 'benefits' => [ + __( 'Get better search results in local search', 'wordpress-seo' ), + __( 'Easily insert Google Maps, a store locator, opening hours and more', 'wordpress-seo' ), + /* translators: %1$s expands to WooCommerce */ + sprintf( __( 'Allow customers to pick up their %s order locally', 'wordpress-seo' ), 'WooCommerce' ), + ], + ], + WPSEO_Addon_Manager::VIDEO_SLUG => [ + 'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zx/' ), + 'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zw/' ), + 'title' => 'Video SEO', + 'display_title' => __( 'Start ranking better for your videos', 'wordpress-seo' ), + 'desc' => __( 'Optimize your videos to show them off in search results and get more clicks!', 'wordpress-seo' ), + 'image' => plugins_url( 'images/video_plugin_assistant.svg?v=' . WPSEO_VERSION, WPSEO_FILE ), + 'benefits' => [ + __( 'Show your videos in Google Videos', 'wordpress-seo' ), + __( 'Enhance the experience of sharing posts with videos', 'wordpress-seo' ), + __( 'Make videos responsive through enabling fitvids.js', 'wordpress-seo' ), + ], + ], + WPSEO_Addon_Manager::NEWS_SLUG => [ + 'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zv/' ), + 'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zu/' ), + 'title' => 'News SEO', + 'display_title' => __( 'Everything you need for Google News', 'wordpress-seo' ), + 'desc' => __( 'Are you in Google News? Increase your traffic from Google News by optimizing for it!', 'wordpress-seo' ), + 'image' => plugins_url( 'images/news_plugin_assistant.svg?v=' . WPSEO_VERSION, WPSEO_FILE ), + 'benefits' => [ + __( 'Optimize your site for Google News', 'wordpress-seo' ), + __( 'Immediately pings Google on the publication of a new post', 'wordpress-seo' ), + __( 'Creates XML News Sitemaps', 'wordpress-seo' ), + ], + ], +]; // Add Yoast WooCommerce SEO when WooCommerce is active. -if ( class_exists( 'Woocommerce' ) ) { - $extensions->add( - 'wpseo-woocommerce', - new WPSEO_Extension( - array( - 'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zr' ), - 'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zq' ), - 'title' => 'Yoast WooCommerce SEO', - /* translators: %1$s expands to Yoast SEO */ - 'desc' => sprintf( __( 'Seamlessly integrate WooCommerce with %1$s and get extra features!', 'wordpress-seo' ), 'Yoast SEO' ), - 'image' => plugins_url( 'images/extensions-woo.png?v=' . WPSEO_VERSION, WPSEO_FILE ), - 'benefits' => array( - sprintf( __( 'Improve sharing on Pinterest', 'wordpress-seo' ) ), - - /* translators: %1$s expands to Yoast, %2$s expands to WooCommerce */ - sprintf( __( 'Use %1$s breadcrumbs instead of %2$s ones', 'wordpress-seo' ), 'Yoast', 'WooCommerce' ), - - /* translators: %1$s expands to Yoast SEO, %2$s expands to WooCommerce */ - sprintf( __( 'A seamless integration between %1$s and %2$s', 'wordpress-seo' ), 'Yoast SEO', 'WooCommerce' ), - ), - 'buy_button' => 'WooCommerce SEO', - ) - ) - ); +if ( YoastSEO()->helpers->woocommerce->is_active() ) { + $extensions[ WPSEO_Addon_Manager::WOOCOMMERCE_SLUG ] = [ + 'buyUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zr' ), + 'infoUrl' => WPSEO_Shortlinker::get( 'https://yoa.st/zq' ), + 'title' => 'Yoast WooCommerce SEO', + 'display_title' => __( 'Make your products stand out in Google', 'wordpress-seo' ), + /* translators: %1$s expands to Yoast SEO */ + 'desc' => sprintf( __( 'Seamlessly integrate WooCommerce with %1$s and get extra features!', 'wordpress-seo' ), 'Yoast SEO' ), + 'image' => plugins_url( 'images/woo_plugin_assistant.svg?v=' . WPSEO_VERSION, WPSEO_FILE ), + 'benefits' => [ + sprintf( __( 'Improve sharing on Facebook and Pinterest', 'wordpress-seo' ) ), + /* translators: %1$s expands to Yoast, %2$s expands to WooCommerce */ + sprintf( __( 'Use %1$s breadcrumbs instead of %2$s ones', 'wordpress-seo' ), 'Yoast', 'WooCommerce' ), + /* translators: %1$s expands to Yoast SEO, %2$s expands to WooCommerce */ + sprintf( __( 'A seamless integration between %1$s and %2$s', 'wordpress-seo' ), 'Yoast SEO', 'WooCommerce' ), + ], + 'buy_button' => 'WooCommerce SEO', + ]; } +$addon_manager = new WPSEO_Addon_Manager(); +$has_valid_premium_subscription = YoastSEO()->helpers->product->is_premium() && $addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG ); + /* translators: %1$s expands to Yoast SEO. */ $wpseo_extensions_header = sprintf( __( '%1$s Extensions', 'wordpress-seo' ), 'Yoast SEO' ); +$new_tab_message = sprintf( + '%1$s', + esc_html__( '(Opens in a new browser tab)', 'wordpress-seo' ) +); ?> @@ -147,31 +105,28 @@ $wpseo_extensions_header = sprintf( __( '%1$s Extensions', 'wordpress-seo' ), 'Y
    - get( 'wordpress-seo-premium' ); - $extensions->remove( 'wordpress-seo-premium' ); - ?> -

    - ' . $extension->get_title() . '' - ); - ?> -

    +

    + ' . $premium_extension['title'] . '' + ); + ?> +

    is_activated( 'wordpress-seo-premium' ) ) : - ?> + if ( ! $has_valid_premium_subscription ) : + ?>
    • - - + +
    • @@ -183,88 +138,173 @@ $wpseo_extensions_header = sprintf( __( '%1$s Extensions', 'wordpress-seo' ), 'Y
    - is_installed( $extension->get_title() ) ) : ?> + is_installed( WPSEO_Addon_Manager::PREMIUM_SLUG ) ) : ?>
    - is_activated( 'wordpress-seo-premium' ) ) : ?> +
    - + + +
    - + + + - - + get_title() ); - ?> - - '; + ?> + + + + ', '', - $extension->get_title() ); - ?> + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: The `get_title` value is hardcoded; only passed through the WPSEO_Extensions class. + $premium_extension['title'] + ); + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: $new_tab_message is properly escaped. + echo $new_tab_message; + ?> + - is_activated( 'wordpress-seo-premium' ) ) { ?> -

    + +

    + +

    - +
    -

    + ' . $yoast_seo_extensions . ''; - /* translators: %1$s expands to Yoast SEO extensions */ - printf( __( '%1$s to optimize your site even further', 'wordpress-seo' ), $yoast_seo_extensions ); - ?>

    + printf( + /* translators: 1: expands to Yoast SEO extensions */ + esc_html__( '%1$s to optimize your site even further', 'wordpress-seo' ), + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: $yoast_seo_extensions is properly escaped. + $yoast_seo_extensions + ); + ?> +

    - get_all() as $id => $extension ) : ?> + $extension ) : ?>
    - -

    get_title() ); ?>

    - +

    + + +

      - get_benefits() as $benefit ) : ?> +
    - is_installed( $extension->get_title() ) ) : ?> + is_installed( $slug ) ) : ?>
    - is_activated( $id ) ) : ?> + has_valid_subscription( $slug ) ) : ?>
    - + + +
    - + + + - - - get_buy_button() ); ?> + + '; + ?> - "> + ', '', - $extension->get_title() ); + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: The `get_title` value is hardcoded; only passed through the WPSEO_Extensions class. + $extension['title'] + ); + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: $new_tab_message is properly escaped. + echo $new_tab_message; ?> diff --git a/wp-content/plugins/wordpress-seo/admin/views/paper-collapsible.php b/wp-content/plugins/wordpress-seo/admin/views/paper-collapsible.php new file mode 100644 index 00000000..e8e3fea4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/paper-collapsible.php @@ -0,0 +1,79 @@ + +
    > + + %4$s%5$s ', + esc_attr( 'collapsible-header ' . $collapsible_header_class ), + // phpcs:ignore WordPress.Security.EscapeOutput -- $button_id_attr is escaped above. + $button_id_attr, + esc_attr( $collapsible_config['expanded'] ), + // phpcs:ignore WordPress.Security.EscapeOutput -- $help_text is an instance of WPSEO_Admin_Help_Panel, which escapes it's own output. + $help_text->get_button_html(), + esc_html( $title ) . wp_kses_post( $title_after ), + wp_kses_post( $collapsible_config['toggle_icon'] ) + ); + } + else { + echo '

    ', + esc_html( $title ), + wp_kses_post( $title_after ), + // phpcs:ignore WordPress.Security.EscapeOutput -- $help_text is an instance of WPSEO_Admin_Help_Panel, which escapes it's own output. + $help_text->get_button_html(), + '

    '; + } + } + ?> + get_panel_html(); + + $container_id_attr = ''; + if ( ! empty( $paper_id ) ) { + $container_id_attr = sprintf( ' id="%s"', esc_attr( $paper_id_prefix . $paper_id . '-container' ) ); + } + + printf( + '%3$s
    ', + // phpcs:ignore WordPress.Security.EscapeOutput -- $container_id_attr is escaped above. + $container_id_attr, + esc_attr( 'paper-container ' . $collapsible_config['class'] ), + $content + ); + ?> + +
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/partial-alerts-errors.php b/wp-content/plugins/wordpress-seo/admin/views/partial-alerts-errors.php deleted file mode 100644 index db90601b..00000000 --- a/wp-content/plugins/wordpress-seo/admin/views/partial-alerts-errors.php +++ /dev/null @@ -1,22 +0,0 @@ -%1$s', esc_html__( 'Dismiss this item.', 'wordpress-seo' ) ); - break; - - case 'dismissed': - $button = sprintf( '', esc_html__( 'Restore this item.', 'wordpress-seo' ) ); - break; - } - - printf( - '
    %4$s%5$s
    ', - esc_attr( $notification->get_id() ), - esc_attr( $notification->get_nonce() ), - esc_attr( $notification->get_json() ), - $notification, - $button - ); - } - } -} - -$wpseo_i18n_summary = $i18n_issues; -if ( ! $active ) { - $dashicon = 'yes'; - $wpseo_i18n_summary = $i18n_no_issues; -} - -?> -

    ()

    - -
    - - -

    - -
    - -
    - - -

    - - -
    - -
    - - - -

    - - -
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/partial-alerts-warnings.php b/wp-content/plugins/wordpress-seo/admin/views/partial-alerts-warnings.php deleted file mode 100644 index b34ca7d0..00000000 --- a/wp-content/plugins/wordpress-seo/admin/views/partial-alerts-warnings.php +++ /dev/null @@ -1,22 +0,0 @@ -%1$s', + esc_html__( 'Hide this item.', 'wordpress-seo' ) + ); + break; + + case 'dismissed': + $button = sprintf( + '', + esc_html__( 'Show this item.', 'wordpress-seo' ) + ); + break; + } + + $notifications .= sprintf( + '
    %4$s%5$s
    ', + esc_attr( $notification->get_id() ), + esc_attr( $notification->get_nonce() ), + esc_attr( $notification->get_json() ), + // This needs to be fixed in https://github.com/Yoast/wordpress-seo-premium/issues/2548. + $notification, + // Note: $button is properly escaped above. + $button + ); + } + + return $notifications; + } +} + +$wpseo_i18n_summary = $yoast_seo_i18n_issues; +if ( ! $yoast_seo_active ) { + $yoast_seo_dashicon = 'yes'; + $wpseo_i18n_summary = $yoast_seo_i18n_no_issues; +} + +?> +

    + + () +

    + +
    + + +

    + +
    + +
    + + esc_attr( $yoast_seo_type . '-dismissed' ), + 'paper_id_prefix' => 'yoast-', + 'class' => 'yoast-notifications-dismissed', + 'content' => _yoast_display_notifications( $yoast_seo_dismissed, 'dismissed' ), + 'collapsible' => true, + 'collapsible_header_class' => 'yoast-notification', + ] + ); + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: get_output() output is properly escaped. + echo $dismissed_paper->get_output(); + } + ?> + + + +

    + + +
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/partial-notifications-warnings.php b/wp-content/plugins/wordpress-seo/admin/views/partial-notifications-warnings.php new file mode 100644 index 00000000..e960d6ae --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/partial-notifications-warnings.php @@ -0,0 +1,29 @@ + + diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/dashboard.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/dashboard.php index eb0041ab..69e32d5f 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/dashboard.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/dashboard.php @@ -5,8 +5,14 @@ * @package WPSEO\Admin */ -/** @noinspection PhpUnusedLocalVariableInspection */ -$alerts_data = Yoast_Alerts::get_template_variables(); +/** + * Notifications template variables. + * + * @noinspection PhpUnusedLocalVariableInspection + * + * @var array + */ +$notifications_data = Yoast_Notifications::get_template_variables(); $notifier = new WPSEO_Configuration_Notifier(); $notifier->listen(); @@ -20,34 +26,27 @@ $wpseo_contributors_phrase = sprintf( ?>
    -
    +
    - notify(); ?> + notify(); + ?> -
    - +
    +
    - +
    -

    +

    - - +

    - -' . __( 'See the XML sitemap.', 'wordpress-seo' ) . ''; -} -$feature_toggles = array( - (object) array( - 'name' => __( 'SEO analysis', 'wordpress-seo' ), - 'setting' => 'keyword_analysis_active', - 'label' => __( 'The SEO analysis offers suggestions to improve the SEO of your text.', 'wordpress-seo' ), - 'read_more_label' => __( 'Learn how the SEO analysis can help you rank.', 'wordpress-seo' ), - 'read_more_url' => 'https://yoa.st/2ak', - 'order' => 10, - ), - (object) array( - 'name' => __( 'Readability analysis', 'wordpress-seo' ), - 'setting' => 'content_analysis_active', - 'label' => __( 'The readability analysis offers suggestions to improve the structure and style of your text.', 'wordpress-seo' ), - 'read_more_label' => __( 'Discover why readability is important for SEO.', 'wordpress-seo' ), - 'read_more_url' => 'https://yoa.st/2ao', - 'order' => 20, - ), - (object) array( - 'name' => __( 'Cornerstone content', 'wordpress-seo' ), - 'setting' => 'enable_cornerstone_content', - 'label' => __( 'The cornerstone content feature lets you to mark and filter cornerstone content on your website.', 'wordpress-seo' ), - 'read_more_label' => __( 'Find out how cornerstone content can help you improve your site structure.', 'wordpress-seo' ), - 'read_more_url' => 'https://yoa.st/dashboard-help-cornerstone', - 'order' => 30, - ), - (object) array( - 'name' => __( 'Text link counter', 'wordpress-seo' ), - 'setting' => 'enable_text_link_counter', - 'label' => __( 'The text link counter helps you improve your site structure.', 'wordpress-seo' ), - 'read_more_label' => __( 'Find out how the text link counter can enhance your SEO.', 'wordpress-seo' ), - 'read_more_url' => 'https://yoa.st/2aj', - 'order' => 40, - ), - (object) array( - 'name' => __( 'XML sitemaps', 'wordpress-seo' ), - 'setting' => 'enable_xml_sitemap', - /* translators: %s expands to Yoast SEO */ - 'label' => sprintf( __( 'Enable the XML sitemaps that %s generates.', 'wordpress-seo' ), 'Yoast SEO' ), - 'read_more_label' => __( 'Read why XML Sitemaps are important for your site.', 'wordpress-seo' ), - 'read_more_url' => 'https://yoa.st/2a-', - 'extra' => $xml_sitemap_extra, - 'order' => 60, - ), - (object) array( - /* translators: %s expands to Ryte. */ - 'name' => sprintf( __( '%s integration', 'wordpress-seo' ), 'Ryte' ), - 'setting' => 'onpage_indexability', - /* translators: %1$s expands to Ryte. */ - 'label' => sprintf( __( '%1$s can check daily if your site is still indexable by search engines and will notify you when this is not the case.', 'wordpress-seo' ), 'Ryte' ), - /* translators: %s expands to Ryte. */ - 'read_more_label' => sprintf( __( 'Read more about how %s works.', 'wordpress-seo' ), 'Ryte ' ), - 'read_more_url' => 'https://yoa.st/2an', - 'order' => 70, - ), - (object) array( - 'name' => __( 'Admin bar menu', 'wordpress-seo' ), - 'setting' => 'enable_admin_bar_menu', - /* translators: %1$s expands to Yoast SEO */ - 'label' => sprintf( __( 'The %1$s admin bar menu contains useful links to third-party tools for analyzing pages and makes it easy to see if you have new notifications.', 'wordpress-seo' ), 'Yoast SEO' ), - 'order' => 80, - ), - (object) array( - 'name' => __( 'Security: no advanced settings for authors', 'wordpress-seo' ), - 'setting' => 'disableadvanced_meta', - 'label' => sprintf( - /* translators: %1$s expands to Yoast SEO, %2$s expands to the translated version of "Off" */ - __( 'The advanced section of the %1$s meta box allows a user to remove posts from the search results or change the canonical. These are things you might not want any author to do. That\'s why, by default, only editors and administrators can do this. Setting to "%2$s" allows all users to change these settings.', 'wordpress-seo' ), - 'Yoast SEO', - __( 'Off', 'wordpress-seo' ) - ), - 'order' => 90, - ), -); - -/** - * Filter to add feature toggles from add-ons. - * - * @param array $feature_toggles Array with feature toggle objects where each object should have a `name`, `setting` and `label` property. - */ -$feature_toggles = apply_filters( 'wpseo_feature_toggles', $feature_toggles ); +$feature_toggles = Yoast_Feature_Toggles::instance()->get_all(); ?>

    -
    - +
    order > $feature_b->order ); - } - - usort( $feature_toggles, 'wpseo_cmp_order' ); + echo sprintf( + /* translators: %1$s expands to Yoast SEO */ + esc_html__( '%1$s comes with a lot of features. You can enable / disable some of them below. Clicking the question mark gives more information about the feature.', 'wordpress-seo' ), + 'Yoast SEO' + ); foreach ( $feature_toggles as $feature ) { $help_text = esc_html( $feature->label ); @@ -130,27 +33,56 @@ $feature_toggles = apply_filters( 'wpseo_feature_toggles', $feature_toggles ); $help_text .= ' ' . $feature->extra; } if ( ! empty( $feature->read_more_label ) ) { - $help_text .= ' ' . sprintf( '%2$s', WPSEO_Shortlinker::get( $feature->read_more_url ), esc_html( $feature->read_more_label ) ); + $url = $feature->read_more_url; + if ( ! empty( $feature->premium ) && $feature->premium === true ) { + $url = $feature->premium_url; + } + $help_text .= ' '; + $help_text .= sprintf( + '%2$s', + esc_url( WPSEO_Shortlinker::get( $url ) ), + esc_html( $feature->read_more_label ) + ); } $feature_help = new WPSEO_Admin_Help_Panel( $feature->setting, /* translators: %s expands to a feature's name */ - sprintf( __( 'Help on: %s', 'wordpress-seo' ), $feature->name ), + sprintf( esc_html__( 'Help on: %s', 'wordpress-seo' ), esc_html( $feature->name ) ), $help_text ); + $name = $feature->name; + if ( ! empty( $feature->premium ) && $feature->premium === true ) { + $name .= ' ' . new Premium_Badge_Presenter( $feature->name ); + } + + $disabled = false; + if ( $feature->premium === true && YoastSEO()->helpers->product->is_premium() === false ) { + $disabled = true; + } + $yform->toggle_switch( $feature->setting, - array( + [ 'on' => __( 'On', 'wordpress-seo' ), 'off' => __( 'Off', 'wordpress-seo' ), - ), - '' . $feature->name . $feature_help->get_button_html() . '' . $feature_help->get_panel_html() + ], + $name, + $feature_help->get_button_html() . $feature_help->get_panel_html(), + [ 'disabled' => $disabled ] ); + + if ( ! empty( $feature->after ) ) { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaping handled in integrations. + echo $feature->after; + } } ?>
    hidden( 'show_onboarding_notice', 'wpseo_show_onboarding_notice' ); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/integrations.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/integrations.php new file mode 100644 index 00000000..a868fd40 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/integrations.php @@ -0,0 +1,88 @@ +get_all(); + +?> +

    +
    + label ); + + if ( ! empty( $integration->extra ) ) { + $help_text .= ' ' . $integration->extra; + } + + if ( ! empty( $integration->read_more_label ) ) { + $url = $integration->read_more_url; + if ( ! empty( $integration->premium ) && $integration->premium === true ) { + $url = $integration->premium_url; + } + + $help_text .= ' '; + $help_text .= sprintf( + '%2$s', + esc_url( WPSEO_Shortlinker::get( $url ) ), + esc_html( $integration->read_more_label ) + ); + } + + $feature_help = new WPSEO_Admin_Help_Panel( + $integration->setting, + /* translators: %s expands to an integration's name */ + sprintf( esc_html__( 'Help on: %s', 'wordpress-seo' ), esc_html( $integration->name ) ), + $help_text + ); + + $name = $integration->name; + if ( ! empty( $integration->premium ) && $integration->premium === true ) { + $name .= ' ' . new Premium_Badge_Presenter( $integration->name ); + } + + $disabled = false; + if ( $integration->premium === true && YoastSEO()->helpers->product->is_premium() === false ) { + $disabled = true; + } + + $yform->toggle_switch( + $integration->setting, + [ + 'on' => __( 'On', 'wordpress-seo' ), + 'off' => __( 'Off', 'wordpress-seo' ), + ], + $name, + $feature_help->get_button_html() . $feature_help->get_panel_html(), + [ 'disabled' => $disabled ] + ); + + do_action( 'Yoast\WP\SEO\admin_integration_after', $integration ); + } + ?> +
    +hidden( 'show_onboarding_notice', 'wpseo_show_onboarding_notice' ); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/site-analysis.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/site-analysis.php index a6cfe2db..60aba95e 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/site-analysis.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/site-analysis.php @@ -3,10 +3,8 @@ * WPSEO plugin file. * * @package WPSEO\Admin\Views - */ - -/** - * @var Yoast_Form $yform + * + * @uses Yoast_Form $yform Form object. */ if ( ! defined( 'WPSEO_VERSION' ) ) { diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/webmaster-tools.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/webmaster-tools.php index bcbedeac..dc01d295 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/webmaster-tools.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/dashboard/webmaster-tools.php @@ -3,10 +3,8 @@ * WPSEO plugin file. * * @package WPSEO\Admin\Views - */ - -/** - * @var Yoast_Form $yform + * + * @uses Yoast_Form $yform Form object. */ if ( ! defined( 'WPSEO_VERSION' ) ) { @@ -22,21 +20,37 @@ $webmaster_tools_help = new WPSEO_Admin_Help_Panel( 'has-wrapper' ); +// phpcs:ignore WordPress.Security.EscapeOutput -- get_button_html() output is properly escaped. echo '

    ' . esc_html__( 'Webmaster Tools verification', 'wordpress-seo' ) . $webmaster_tools_help->get_button_html() . '

    '; +// phpcs:ignore WordPress.Security.EscapeOutput -- get_panel_html() output is properly escaped. echo $webmaster_tools_help->get_panel_html(); $msverify_link = 'https://www.bing.com/toolbox/webmaster/#/Dashboard/?url=' . rawurlencode( str_replace( 'http://', '', get_bloginfo( 'url' ) ) ); $googleverify_link = add_query_arg( - array( + [ 'hl' => 'en', 'tid' => 'alternate', 'siteUrl' => rawurlencode( get_bloginfo( 'url' ) ) . '/', - ), + ], 'https://www.google.com/webmasters/verification/verification' ); +$yform->textinput( 'baiduverify', __( 'Baidu verification code', 'wordpress-seo' ) ); +echo '

    '; +printf( + /* translators: %1$s expands to a link start tag to the Baidu Webmaster Tools site add page, %2$s is the link closing tag. */ + esc_html__( 'Get your Baidu verification code in %1$sBaidu Webmaster Tools%2$s.', 'wordpress-seo' ), + /* + * Get the Baidu Webmaster Tools site add link from this 3rd party article. + * {@link http://www.dragonmetrics.com/how-to-optimize-your-site-with-baidu-webmaster-tools/} + * We are unable to create a Baidu Webmaster Tools account due to the Chinese phone number verification. + */ + '', + '' +); +echo '

    '; $yform->textinput( 'msverify', __( 'Bing verification code', 'wordpress-seo' ) ); echo '

    '; diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/archives.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/archives.php index a0169201..0e8ccc98 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/archives.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/archives.php @@ -5,144 +5,57 @@ * @package WPSEO\Admin\Views */ -/** - * @var Yoast_Form $yform - */ - if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); exit(); } -$archives_help_01 = sprintf( - /* translators: %1$s / %2$s: links to an article about duplicate content on yoast.com */ - esc_html__( 'If you\'re running a one author blog, the author archive will be exactly the same as your homepage. This is what\'s called a %1$sduplicate content problem%2$s.', 'wordpress-seo' ), - '', - '' -); +// To improve readability, this tab has been divided into separate blocks, included below. +require __DIR__ . '/archives/help.php'; -$archives_help_02 = sprintf( - /* translators: %s expands to noindex, follow */ - esc_html__( 'If this is the case on your site, you can choose to either disable it (which makes it redirect to the homepage), or to add %s to it so it doesn\'t show up in the search results.', 'wordpress-seo' ), - 'noindex,follow' -); +$wpseo_archives = [ + [ + 'title' => esc_html__( 'Author archives', 'wordpress-seo' ), + 'view_file' => 'paper-content/author-archive-settings.php', + 'paper_id' => 'settings-author-archives', + ], + [ + 'title' => esc_html__( 'Date archives', 'wordpress-seo' ), + 'view_file' => 'paper-content/date-archives-settings.php', + 'paper_id' => 'settings-date-archives', + ], + [ + 'title' => esc_html__( 'Special pages', 'wordpress-seo' ), + 'view_file' => 'paper-content/special-pages.php', + 'paper_id' => 'settings-special-pages', + ], +]; -$archives_help_03 = esc_html__( 'Note that links to archives might be still output by your theme and you would need to remove them separately.', 'wordpress-seo' ); +$view_utils = new Yoast_View_Utils(); +$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars(); +$editor_specific_replace_vars = new WPSEO_Admin_Editor_Specific_Replace_Vars(); +$opengraph_disabled_alert = $view_utils->generate_opengraph_disabled_alert( 'archives' ); -$archives_help_04 = esc_html__( 'Date-based archives could in some cases also be seen as duplicate content.', 'wordpress-seo' ); +// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Is correctly escaped in the generate_opengraph_disabled_alert() method. +echo $opengraph_disabled_alert; -$archives_help = new WPSEO_Admin_Help_Panel( - 'search-appearance-archives', - __( 'Learn more about the archives setting', 'wordpress-seo' ), - $archives_help_01 . ' ' . $archives_help_02 . ' ' . $archives_help_03 . ' ' . $archives_help_04, - 'has-wrapper' -); +foreach ( $wpseo_archives as $wpseo_archive_index => $wpseo_archive ) { + $wpseo_archive_presenter = new WPSEO_Paper_Presenter( + $wpseo_archive['title'], + __DIR__ . '/' . $wpseo_archive['view_file'], + [ + 'collapsible' => true, + 'expanded' => ( $wpseo_archive_index === 0 ), + 'paper_id' => $wpseo_archive['paper_id'], + 'recommended_replace_vars' => $recommended_replace_vars, + 'editor_specific_replace_vars' => $editor_specific_replace_vars, + 'class' => 'search-appearance', + ] + ); -echo '

    ' . esc_html__( 'Archives settings help', 'wordpress-seo' ) . $archives_help->get_button_html() . '

    '; -echo $archives_help->get_panel_html(); + // phpcs:ignore WordPress.Security.EscapeOutput -- get_output() output is properly escaped. + echo $wpseo_archive_presenter->get_output(); +} -echo '

    '; -echo '

    ' . esc_html__( 'Author archives settings', 'wordpress-seo' ) . '

    '; -$yform->toggle_switch( 'disable-author', array( - 'off' => __( 'Enabled', 'wordpress-seo' ), - 'on' => __( 'Disabled', 'wordpress-seo' ), -), __( 'Author archives', 'wordpress-seo' ) ); - -echo "
    "; - -$author_archives_help = new WPSEO_Admin_Help_Panel( - 'noindex-author-wpseo', - esc_html__( 'Help on the author archives search results setting', 'wordpress-seo' ), - sprintf( - /* translators: 1: expands to noindex; 2: link open tag; 3: link close tag. */ - esc_html__( 'Not showing the archive for authors in the search results technically means those will have a %1$s robots meta and will be excluded from XML sitemaps. %2$sMore info on the search results settings%3$s.', 'wordpress-seo' ), - 'noindex', - '', - '' - ) -); - -$yform->index_switch( - 'noindex-author-wpseo', - __( 'author archives', 'wordpress-seo' ), - $author_archives_help->get_button_html() . $author_archives_help->get_panel_html() -); - -$author_archives_no_posts_help = new WPSEO_Admin_Help_Panel( - 'noindex-author-noposts-wpseo', - esc_html__( 'Help on the authors without posts archive search results setting', 'wordpress-seo' ), - sprintf( - /* translators: 1: expands to noindex; 2: link open tag; 3: link close tag. */ - esc_html__( 'Not showing the archives for authors without posts in the search results technically means those will have a %1$s robots meta and will be excluded from XML sitemaps. %2$sMore info on the search results settings%3$s.', 'wordpress-seo' ), - 'noindex', - '', - '' - ) -); - -$yform->index_switch( - 'noindex-author-noposts-wpseo', - __( 'archives for authors without posts', 'wordpress-seo' ), - $author_archives_no_posts_help->get_button_html() . $author_archives_no_posts_help->get_panel_html() -); - -$yform->textinput( 'title-author-wpseo', __( 'Title template', 'wordpress-seo' ), 'template author-template' ); -$yform->textarea( 'metadesc-author-wpseo', __( 'Meta description template', 'wordpress-seo' ), array( 'class' => 'template author-template' ) ); -echo '
    '; -echo '
    '; - -echo '
    '; -echo '

    ' . esc_html__( 'Date archives settings', 'wordpress-seo' ) . '

    '; -$yform->toggle_switch( 'disable-date', array( - 'off' => __( 'Enabled', 'wordpress-seo' ), - 'on' => __( 'Disabled', 'wordpress-seo' ), -), __( 'Date archives', 'wordpress-seo' ) ); - -echo "
    "; - -$date_archives_help = new WPSEO_Admin_Help_Panel( - 'noindex-archive-wpseo', - esc_html__( 'Help on the date archives search results setting', 'wordpress-seo' ), - sprintf( - /* translators: 1: expands to noindex; 2: link open tag; 3: link close tag. */ - esc_html__( 'Not showing the date archives in the search results technically means those will have a %1$s robots meta and will be excluded from XML sitemaps. %2$sMore info on the search results settings%3$s.', 'wordpress-seo' ), - 'noindex', - '', - '' - ) -); - -$yform->index_switch( - 'noindex-archive-wpseo', - __( 'date archives', 'wordpress-seo' ), - $date_archives_help->get_button_html() . $date_archives_help->get_panel_html() -); - -$yform->textinput( 'title-archive-wpseo', __( 'Title template', 'wordpress-seo' ), 'template date-template' ); -$yform->textarea( 'metadesc-archive-wpseo', __( 'Meta description template', 'wordpress-seo' ), array( 'class' => 'template date-template' ) ); -echo '
    '; -echo '
    '; - -$spcia_pages_help = new WPSEO_Admin_Help_Panel( - 'search-appearance-special-pages', - __( 'Learn more about the special pages setting', 'wordpress-seo' ), - sprintf( - /* translators: %s expands to noindex, follow. */ - __( 'These pages will be %s by default, so they will never show up in search results.', 'wordpress-seo' ), - 'noindex, follow' - ), - 'has-wrapper' -); - -echo '
    '; -echo '

    ' . esc_html__( 'Special Pages', 'wordpress-seo' ) . $spcia_pages_help->get_button_html() . '

    '; -echo $spcia_pages_help->get_panel_html(); - -echo '

    ' . esc_html__( 'Search pages', 'wordpress-seo' ) . '
    '; -$yform->textinput( 'title-search-wpseo', __( 'Title template', 'wordpress-seo' ), 'template search-template' ); -echo '

    '; -echo '

    ' . esc_html__( '404 pages', 'wordpress-seo' ) . '
    '; -$yform->textinput( 'title-404-wpseo', __( 'Title template', 'wordpress-seo' ), 'template error404-template' ); -echo '

    '; -echo '
    '; +unset( $wpseo_archives, $wpseo_archive_presenter, $wpseo_archive_index ); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/archives/help.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/archives/help.php new file mode 100644 index 00000000..1118c6e9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/archives/help.php @@ -0,0 +1,35 @@ +', + '' + ), + sprintf( + /* translators: %s expands to noindex, follow */ + esc_html__( 'If this is the case on your site, you can choose to either disable it (which makes it redirect to the homepage), or to add %s to it so it doesn\'t show up in the search results.', 'wordpress-seo' ), + 'noindex,follow' + ), + esc_html__( 'Note that links to archives might be still output by your theme and you would need to remove them separately.', 'wordpress-seo' ), + esc_html__( 'Date-based archives could in some cases also be seen as duplicate content.', 'wordpress-seo' ), +]; + +$archives_help = new WPSEO_Admin_Help_Panel( + 'search-appearance-archives', + __( 'Learn more about the archives setting', 'wordpress-seo' ), + implode( ' ', $archives_help_content ), + 'has-wrapper' +); + +// phpcs:ignore WordPress.Security.EscapeOutput -- get_button_html() output is properly escaped. +echo '

    ' . esc_html__( 'Archives settings help', 'wordpress-seo' ) . $archives_help->get_button_html() . '

    '; + +// phpcs:ignore WordPress.Security.EscapeOutput -- get_panel_html() output is properly escaped. +echo $archives_help->get_panel_html(); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/breadcrumbs.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/breadcrumbs.php index d07efd8e..c13366d3 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/breadcrumbs.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/breadcrumbs.php @@ -5,109 +5,20 @@ * @package WPSEO\Admin */ -/** - * @var Yoast_Form $yform - */ - if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); exit(); } -echo '

    ' . esc_html__( 'Breadcrumbs settings', 'wordpress-seo' ) . '

    '; - -if ( ! current_theme_supports( 'yoast-seo-breadcrumbs' ) ) { - $yform->light_switch( 'breadcrumbs-enable', __( 'Enable Breadcrumbs', 'wordpress-seo' ) ); - echo '
    '; -} - -echo ' -

    -

    - ', - '' - ); - ?> -

    +// phpcs:ignore WordPress.Security.EscapeOutput -- get_output() output is properly escaped. +echo $wpseo_breadcrumbs_presenter->get_output(); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general.php index e8500694..236fb5b5 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general.php @@ -5,18 +5,76 @@ * @package WPSEO\Admin\Views */ -/** - * @var Yoast_Form $yform - */ - if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); exit(); } -// To improve readability, this tab has been divided into 5 separate blocks, included below. -require dirname( __FILE__ ) . '/general/force-rewrite-title.php'; -require dirname( __FILE__ ) . '/general/title-separator.php'; -require dirname( __FILE__ ) . '/general/homepage.php'; -require dirname( __FILE__ ) . '/general/knowledge-graph.php'; +if ( ! current_theme_supports( 'title-tag' ) ) { + $wpseo_rewrite_titles_title = esc_html__( 'Rewrite titles', 'wordpress-seo' ); + $wpseo_rewrite_titles_presenter = new WPSEO_Paper_Presenter( + $wpseo_rewrite_titles_title, + __DIR__ . '/paper-content/general/force-rewrite-title.php', + [ + 'collapsible' => true, + 'expanded' => true, + 'paper_id' => 'settings-general-rewrite-titles', + 'title' => $wpseo_rewrite_titles_title, + 'class' => 'search-appearance', + ] + ); + // phpcs:ignore WordPress.Security.EscapeOutput -- output contains HTML and we assume it's properly escape on object creation. + echo $wpseo_rewrite_titles_presenter->get_output(); +} + +$wpseo_title_separator_title = esc_html__( 'Title Separator', 'wordpress-seo' ); +$wpseo_title_separator_presenter = new WPSEO_Paper_Presenter( + $wpseo_title_separator_title, + __DIR__ . '/paper-content/general/title-separator.php', + [ + 'collapsible' => true, + 'expanded' => true, + 'paper_id' => 'settings-general-title-separator', + 'title' => $wpseo_title_separator_title, + 'class' => 'search-appearance', + ] +); +// phpcs:ignore WordPress.Security.EscapeOutput -- output contains HTML and we assume it's properly escape on object creation. +echo $wpseo_title_separator_presenter->get_output(); + +if ( get_option( 'show_on_front' ) === 'posts' ) { + $wpseo_homepage_title = esc_html__( 'Homepage', 'wordpress-seo' ); +} +else { + $wpseo_homepage_title = esc_html__( 'Homepage & Posts page', 'wordpress-seo' ); +} + +$wpseo_homepage_presenter = new WPSEO_Paper_Presenter( + $wpseo_homepage_title, + __DIR__ . '/paper-content/general/homepage.php', + [ + 'collapsible' => true, + 'expanded' => true, + 'paper_id' => 'settings-general-homepage', + 'title' => $wpseo_homepage_title, + 'class' => 'search-appearance', + ] +); +// phpcs:ignore WordPress.Security.EscapeOutput -- output contains HTML and we assume it's properly escape on object creation. +echo $wpseo_homepage_presenter->get_output(); + +$wpseo_knowledge_graph_title = esc_html__( 'Knowledge Graph & Schema.org', 'wordpress-seo' ); +$wpseo_knowledge_graph_presenter = new WPSEO_Paper_Presenter( + $wpseo_knowledge_graph_title, + __DIR__ . '/paper-content/general/knowledge-graph.php', + [ + 'collapsible' => true, + 'expanded' => true, + 'paper_id' => 'settings-general-knowledge-graph', + 'title' => $wpseo_knowledge_graph_title, + 'class' => 'search-appearance', + ] +); +// phpcs:ignore WordPress.Security.EscapeOutput -- output contains HTML and we assume it's properly escape on object creation. +echo $wpseo_knowledge_graph_presenter->get_output(); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general/force-rewrite-title.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general/force-rewrite-title.php deleted file mode 100644 index 81870000..00000000 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general/force-rewrite-title.php +++ /dev/null @@ -1,25 +0,0 @@ - -
    - light_switch( 'forcerewritetitle', __( 'Force rewrite titles', 'wordpress-seo' ) ); - echo '

    '; - printf( - /* translators: %1$s expands to Yoast SEO */ - esc_html__( '%1$s has auto-detected whether it needs to force rewrite the titles for your pages, if you think it\'s wrong and you know what you\'re doing, you can change the setting here.', 'wordpress-seo' ), - 'Yoast SEO' - ); - echo '

    '; - ?> -
    - -
    - ', esc_html__( 'Homepage', 'wordpress-seo' ), $homepage_help->get_button_html(), ''; - echo $homepage_help->get_panel_html(); - $yform->textinput( 'title-home-wpseo', __( 'Title', 'wordpress-seo' ), 'template homepage-template' ); - $yform->textarea( 'metadesc-home-wpseo', __( 'Meta description', 'wordpress-seo' ), array( 'class' => 'template homepage-template' ) ); - } - else { - echo '

    ', esc_html__( 'Homepage & Front page', 'wordpress-seo' ), '

    '; - echo '

    '; - printf( - /* translators: 1: link open tag; 2: link close tag. */ - esc_html__( 'You can determine the title and description for the front page by %1$sediting the front page itself »%2$s', 'wordpress-seo' ), - '', - '' - ); - echo '

    '; - if ( get_option( 'page_for_posts' ) > 0 ) { - echo '

    '; - printf( - /* translators: 1: link open tag; 2: link close tag. */ - esc_html__( 'You can determine the title and description for the blog page by %1$sediting the blog page itself »%2$s', 'wordpress-seo' ), - '', - '' - ); - echo '

    '; - } - } - ?> -
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general/knowledge-graph.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general/knowledge-graph.php deleted file mode 100644 index f1789aeb..00000000 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general/knowledge-graph.php +++ /dev/null @@ -1,43 +0,0 @@ -', - '' - ), - 'has-wrapper' -); -?> -
    -

    get_button_html(); ?>

    - get_panel_html(); - $yform->select( 'company_or_person', __( 'Company or person', 'wordpress-seo' ), array( - '' => __( 'Choose whether you\'re a company or person', 'wordpress-seo' ), - 'company' => __( 'Company', 'wordpress-seo' ), - 'person' => __( 'Person', 'wordpress-seo' ), - ) ); - ?> -
    -

    - textinput( 'company_name', __( 'Company name', 'wordpress-seo' ) ); - $yform->media_input( 'company_logo', __( 'Company logo', 'wordpress-seo' ) ); - ?> -
    -
    -

    - textinput( 'person_name', __( 'Your name', 'wordpress-seo' ) ); ?> -
    -
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general/title-separator.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general/title-separator.php deleted file mode 100644 index 5ba5c0f7..00000000 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/general/title-separator.php +++ /dev/null @@ -1,25 +0,0 @@ - -
    -

    get_button_html(); ?>

    - get_panel_html(); - $legend = __( 'Title separator symbol', 'wordpress-seo' ); - $legend_attr = array( 'class' => 'radiogroup screen-reader-text' ); - $yform->radio( 'separator', WPSEO_Option_Titles::get_instance()->get_separator_options(), $legend, $legend_attr ); - ?> -
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/media.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/media.php index 9d7d5599..074f6972 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/media.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/media.php @@ -5,44 +5,26 @@ * @package WPSEO\Admin\Views */ -/** - * @var Yoast_Form $yform - */ - if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); exit(); } -$media_help = new WPSEO_Admin_Help_Panel( - 'search-appearance-media', - __( 'Learn more about the Media and attachment URLs setting', 'wordpress-seo' ), - __( 'When you upload media (an image or video for example) to WordPress, it doesn\'t just save the media, it creates an attachment URL for it. These attachment pages are quite empty: they contain the media item and maybe a title if you entered one. Because of that, if you never use these attachment URLs, it\'s better to disable them, and redirect them to the media item itself.', 'wordpress-seo' ), - 'has-wrapper' -); -?> -

    get_button_html(); ?>

    - get_panel_html(); ?> -

    -toggle_switch( - 'disable-attachment', - array( - 'on' => __( 'Yes', 'wordpress-seo' ), - 'off' => __( 'No', 'wordpress-seo' ), - ), - __( 'Redirect attachment URLs to the attachment itself?', 'wordpress-seo' ) +$wpseo_media_presenter = new WPSEO_Paper_Presenter( + esc_html__( 'Media & attachment URLs', 'wordpress-seo' ), + __DIR__ . '/paper-content/media-content.php', + [ + 'help_text' => new WPSEO_Admin_Help_Panel( + 'search-appearance-media', + __( 'Learn more about the Media and attachment URLs setting', 'wordpress-seo' ), + __( 'When you upload media (an image or video for example) to WordPress, it doesn\'t just save the media, it creates an attachment URL for it. These attachment pages are quite empty: they contain the media item and maybe a title if you entered one. Because of that, if you never use these attachment URLs, it\'s better to disable them, and redirect them to the media item itself.', 'wordpress-seo' ), + 'has-wrapper' + ), + 'paper_id' => 'settings-media-attachment-url', + 'class' => 'search-appearance', + ] ); -?> -
    -
    -
    - - show_post_type_settings( 'attachment' ); - ?> -
    +// phpcs:ignore WordPress.Security.EscapeOutput -- get_output() output is properly escaped. +echo $wpseo_media_presenter->get_output(); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/author-archive-settings.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/author-archive-settings.php new file mode 100644 index 00000000..c4ca74ee --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/author-archive-settings.php @@ -0,0 +1,98 @@ +toggle_switch( + 'disable-author', + [ + 'off' => __( 'On', 'wordpress-seo' ), + 'on' => __( 'Off', 'wordpress-seo' ), + ], + __( 'Author archives', 'wordpress-seo' ) +); + +?> + +
    +
    + +noindex; 2: link open tag; 3: link close tag. */ + esc_html__( 'Not showing the archive for authors in the search results technically means those will have a %1$s robots meta and will be excluded from XML sitemaps. %2$sMore info on the search results settings%3$s.', 'wordpress-seo' ), + 'noindex', + '', + '' + ) +); + +$yform->index_switch( + 'noindex-author-wpseo', + __( 'author archives', 'wordpress-seo' ), + $author_archives_help->get_button_html() . $author_archives_help->get_panel_html() +); + +?> + +
    +noindex; 2: link open tag; 3: link close tag. */ + esc_html__( 'Not showing the archives for authors without posts in the search results technically means those will have a %1$s robots meta and will be excluded from XML sitemaps. %2$sMore info on the search results settings%3$s.', 'wordpress-seo' ), + 'noindex', + '', + '' + ) +); + +$yform->index_switch( + 'noindex-author-noposts-wpseo', + __( 'archives for authors without posts', 'wordpress-seo' ), + $author_archives_no_posts_help->get_button_html() . $author_archives_no_posts_help->get_panel_html() +); + +?> +
    +
    + +'; + +$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars(); +$editor_specific_replace_vars = new WPSEO_Admin_Editor_Specific_Replace_Vars(); +$editor = new WPSEO_Replacevar_Editor( + $yform, + [ + 'title' => 'title-author-wpseo', + 'description' => 'metadesc-author-wpseo', + 'page_type_recommended' => $recommended_replace_vars->determine_for_archive( 'author' ), + 'page_type_specific' => $editor_specific_replace_vars->determine_for_archive( 'author' ), + 'paper_style' => false, + ] +); + +$editor->render(); + +echo '
    '; + +/** + * Allow adding custom fields to the admin meta page - Author archives panel in the Archives tab. + * + * @param Yoast_Form $yform The Yoast_Form object. + */ +do_action( 'Yoast\WP\SEO\admin_author_archives_meta', $yform ); +?> +
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/breadcrumbs-content.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/breadcrumbs-content.php new file mode 100644 index 00000000..1cfa1ec7 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/breadcrumbs-content.php @@ -0,0 +1,115 @@ +'; + +$yform->textinput( 'breadcrumbs-sep', __( 'Separator between breadcrumbs', 'wordpress-seo' ) ); +$yform->textinput( 'breadcrumbs-home', __( 'Anchor text for the Homepage', 'wordpress-seo' ) ); +$yform->textinput( 'breadcrumbs-prefix', __( 'Prefix for the breadcrumb path', 'wordpress-seo' ) ); +$yform->textinput( 'breadcrumbs-archiveprefix', __( 'Prefix for Archive breadcrumbs', 'wordpress-seo' ) ); +$yform->textinput( 'breadcrumbs-searchprefix', __( 'Prefix for Search Page breadcrumbs', 'wordpress-seo' ) ); +$yform->textinput( 'breadcrumbs-404crumb', __( 'Breadcrumb for 404 Page', 'wordpress-seo' ) ); + +echo '
    '; + +if ( get_option( 'show_on_front' ) === 'page' && get_option( 'page_for_posts' ) > 0 ) { + $yform->show_hide_switch( 'breadcrumbs-display-blog-page', __( 'Show Blog page', 'wordpress-seo' ) ); +} + +$yoast_free_breadcrumb_bold_texts = [ + 'on' => __( 'Bold', 'wordpress-seo' ), + 'off' => __( 'Regular', 'wordpress-seo' ), +]; +$yform->toggle_switch( + 'breadcrumbs-boldlast', + $yoast_free_breadcrumb_bold_texts, + __( 'Bold the last page', 'wordpress-seo' ) +); + +echo '

    '; + +/* + * WPSEO_Post_Type::get_accessible_post_types() should *not* be used here. + * Even posts that are not indexed, should be able to get breadcrumbs for accessibility/usability. + */ +$post_types = get_post_types( [ 'public' => true ], 'objects' ); +if ( is_array( $post_types ) && $post_types !== [] ) { + echo '

    ' . esc_html__( 'Taxonomy to show in breadcrumbs for content types', 'wordpress-seo' ) . '

    '; + foreach ( $post_types as $pt ) { + $taxonomies = get_object_taxonomies( $pt->name, 'objects' ); + if ( is_array( $taxonomies ) && $taxonomies !== [] ) { + $values = [ 0 => __( 'None', 'wordpress-seo' ) ]; + foreach ( $taxonomies as $yoast_seo_taxonomy ) { + if ( ! $yoast_seo_taxonomy->public ) { + continue; + } + + $values[ $yoast_seo_taxonomy->name ] = $yoast_seo_taxonomy->labels->singular_name; + } + $label = $pt->labels->name . ' (' . $pt->name . ')'; + $yform->select( 'post_types-' . $pt->name . '-maintax', $label, $values ); + unset( $values, $yoast_seo_taxonomy ); + } + unset( $taxonomies ); + } + unset( $pt ); +} +echo '
    '; + +$taxonomies = get_taxonomies( + [ + 'public' => true, + ], + 'objects' +); + +if ( is_array( $taxonomies ) && $taxonomies !== [] ) { + echo '

    ' . esc_html__( 'Content type archive to show in breadcrumbs for taxonomies', 'wordpress-seo' ) . '

    '; + foreach ( $taxonomies as $yoast_seo_taxonomy ) { + $values = [ 0 => __( 'None', 'wordpress-seo' ) ]; + if ( get_option( 'show_on_front' ) === 'page' && get_option( 'page_for_posts' ) > 0 ) { + $values['post'] = __( 'Blog', 'wordpress-seo' ); + } + + if ( is_array( $post_types ) && $post_types !== [] ) { + foreach ( $post_types as $pt ) { + if ( WPSEO_Post_Type::has_archive( $pt ) ) { + $values[ $pt->name ] = $pt->labels->name; + } + } + unset( $pt ); + } + $label = $yoast_seo_taxonomy->labels->singular_name . ' (' . $yoast_seo_taxonomy->name . ')'; + $yform->select( 'taxonomy-' . $yoast_seo_taxonomy->name . '-ptparent', $label, $values ); + unset( $values, $yoast_seo_taxonomy ); + } +} +unset( $taxonomies, $post_types ); + +?> +
    +
    +

    +'; +printf( + /* translators: %1$s / %2$s: links to the breadcrumbs implementation page on the Yoast knowledgebase */ + esc_html__( 'Usage of this breadcrumbs feature is explained in %1$sour knowledge-base article on breadcrumbs implementation%2$s.', 'wordpress-seo' ), + '', + '' +); +echo '

    '; +if ( ! current_theme_supports( 'yoast-seo-breadcrumbs' ) ) { + echo '

    '; + /* translators: %1$s / %2$s: links to the breadcrumbs implementation page on the Yoast knowledgebase */ + echo esc_html_e( 'Note: You can always choose to enable / disable them for your theme below. This setting will not apply to breadcrumbs inserted through a widget, a block or a shortcode.', 'wordpress-seo' ); + echo '

    '; + + $yform->light_switch( 'breadcrumbs-enable', __( 'Enable Breadcrumbs for your theme', 'wordpress-seo' ) ); +} diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/date-archives-settings.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/date-archives-settings.php new file mode 100644 index 00000000..0f831846 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/date-archives-settings.php @@ -0,0 +1,69 @@ +toggle_switch( + 'disable-date', + [ + 'off' => __( 'On', 'wordpress-seo' ), + 'on' => __( 'Off', 'wordpress-seo' ), + ], + __( 'Date archives', 'wordpress-seo' ) +); + +?> +
    +
    + noindex; 2: link open tag; 3: link close tag. */ + esc_html__( 'Not showing the date archives in the search results technically means those will have a %1$s robots meta. %2$sMore info on the search results settings%3$s.', 'wordpress-seo' ), + 'noindex', + '', + '' + ) + ); + + $yform->index_switch( + 'noindex-archive-wpseo', + __( 'date archives', 'wordpress-seo' ), + $date_archives_help->get_button_html() . $date_archives_help->get_panel_html() + ); + + echo '
    '; + echo '
    '; + + $recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars(); + $editor_specific_replace_vars = new WPSEO_Admin_Editor_Specific_Replace_Vars(); + + $editor = new WPSEO_Replacevar_Editor( + $yform, + [ + 'title' => 'title-archive-wpseo', + 'description' => 'metadesc-archive-wpseo', + 'page_type_recommended' => $recommended_replace_vars->determine_for_archive( 'date' ), + 'page_type_specific' => $editor_specific_replace_vars->determine_for_archive( 'date' ), + 'paper_style' => false, + ] + ); + + $editor->render(); + + echo '
    '; + + /** + * Allow adding custom fields to the admin meta page - Date archives panel in the Archives tab. + * + * @param Yoast_Form $yform The Yoast_Form object. + */ + do_action( 'Yoast\WP\SEO\admin_date_archives_meta', $yform ); + ?> +
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/front-page-content.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/front-page-content.php new file mode 100644 index 00000000..e25e4137 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/front-page-content.php @@ -0,0 +1,65 @@ +generate_opengraph_disabled_alert( 'homepage' ); + +if ( ! empty( $opengraph_disabled_alert ) ) { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Is correctly escaped in the generate_opengraph_disabled_alert() method. + echo $opengraph_disabled_alert; +} +else { + echo '
    '; + + echo ''; + + echo '

    ' . esc_html__( 'These are the image, title and description used when a link to your homepage is shared on social media.', 'wordpress-seo' ) . '

    '; + + printf( + '
    ', + 'yoast-og-frontpage-image-select', + 'open_graph_frontpage_image', + 'open_graph_frontpage_image_id', + true + ); + + $yform->hidden( 'open_graph_frontpage_image', 'open_graph_frontpage_image' ); + $yform->hidden( 'open_graph_frontpage_image_id', 'open_graph_frontpage_image_id' ); + + $editor = new WPSEO_Replacevar_Editor( + $yform, + [ + 'title' => 'open_graph_frontpage_title', + 'description' => 'open_graph_frontpage_desc', + 'page_type_recommended' => 'homepage', + 'page_type_specific' => 'page', + 'paper_style' => false, + 'label_title' => __( 'Social title', 'wordpress-seo' ), + 'label_description' => __( 'Social description', 'wordpress-seo' ), + 'description_placeholder' => __( 'Modify your social description by editing it right here.', 'wordpress-seo' ), + ] + ); + $editor->render(); + echo '
    '; +} diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/force-rewrite-title.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/force-rewrite-title.php new file mode 100644 index 00000000..3190228b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/force-rewrite-title.php @@ -0,0 +1,17 @@ +light_switch( 'forcerewritetitle', __( 'Force rewrite titles', 'wordpress-seo' ) ); +echo '

    '; +printf( + /* translators: %1$s expands to Yoast SEO */ + esc_html__( '%1$s has auto-detected whether it needs to force rewrite the titles for your pages, if you think it\'s wrong and you know what you\'re doing, you can change the setting here.', 'wordpress-seo' ), + 'Yoast SEO' +); +echo '

    '; diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/homepage.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/homepage.php new file mode 100644 index 00000000..7d2a44be --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/homepage.php @@ -0,0 +1,54 @@ +'; + + echo esc_html__( 'This is what shows in the search results when people find your homepage. This means this is probably what they see when they search for your brand name.', 'wordpress-seo' ); + + $editor = new WPSEO_Replacevar_Editor( + $yform, + [ + 'title' => 'title-home-wpseo', + 'description' => 'metadesc-home-wpseo', + 'page_type_recommended' => 'homepage', + 'page_type_specific' => 'page', + 'paper_style' => false, + ] + ); + $editor->render(); + echo '
    '; + + require __DIR__ . '/../front-page-content.php'; +} +else { + $wpseo_page_on_front = get_option( 'page_on_front' ); + $wpseo_page_for_posts = get_option( 'page_for_posts' ); + if ( empty( $wpseo_page_on_front ) ) { + $wpseo_page_on_front = $wpseo_page_for_posts; + } + + printf( + /* translators: 1: link open tag; 2: link close tag. */ + esc_html__( 'You can determine the title and description for the homepage by %1$sediting the homepage itself%2$s.', 'wordpress-seo' ), + '', + '' + ); + + if ( $wpseo_page_for_posts > 0 ) { + echo '

    '; + printf( + /* translators: 1: link open tag; 2: link close tag. */ + esc_html__( 'You can determine the title and description for the posts page by %1$sediting the posts page itself%2$s.', 'wordpress-seo' ), + '', + '' + ); + echo '

    '; + } +} diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/knowledge-graph.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/knowledge-graph.php new file mode 100644 index 00000000..5c0ee389 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/knowledge-graph.php @@ -0,0 +1,69 @@ +', + '' +); + +/** + * Filter: 'wpseo_knowledge_graph_setting_msg' - Allows adding a message above these settings. + * + * @api string unsigned Message. + */ +$message = apply_filters( 'wpseo_knowledge_graph_setting_msg', '' ); +if ( ! empty( $message ) ) { + echo '

    ', esc_html( $message ), '

    '; +} +?> +

    + +

    + __( 'Organization', 'wordpress-seo' ), + 'person' => __( 'Person', 'wordpress-seo' ), +]; +$yform->select( 'company_or_person', __( 'Organization or person', 'wordpress-seo' ), $yoast_free_kg_select_options, 'styled', false ); +?> +
    +

    + +
    + textinput( 'company_name', __( 'Organization name', 'wordpress-seo' ), [ 'autocomplete' => 'organization' ] ); + $yform->hidden( 'company_logo', 'company_logo' ); + $yform->hidden( 'company_logo_id', 'company_logo_id' ); + ?> +
    +
    +
    +
    +

    + +
    +
    + hidden( 'person_logo', 'person_logo' ); + $yform->hidden( 'person_logo_id', 'person_logo_id' ); + $yform->hidden( 'company_or_person_user_id', 'person_id' ); + ?> +
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/title-separator.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/title-separator.php new file mode 100644 index 00000000..c37583a9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/general/title-separator.php @@ -0,0 +1,15 @@ + 'radiogroup screen-reader-text' ]; +$yform->radio( 'separator', WPSEO_Option_Titles::get_instance()->get_separator_options_for_display(), $legend, $legend_attr ); + diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/media-content.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/media-content.php new file mode 100644 index 00000000..e971f8a5 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/media-content.php @@ -0,0 +1,36 @@ + +

    + __( 'Yes', 'wordpress-seo' ), + 'off' => __( 'No', 'wordpress-seo' ), +]; +$yform->toggle_switch( + 'disable-attachment', + $yoast_free_disable_attachments_texts, + __( 'Redirect attachment URLs to the attachment itself?', 'wordpress-seo' ) +); + +?> +
    +
    +
    + + +
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/post-type-content.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/post-type-content.php new file mode 100644 index 00000000..7b728dd8 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/post-type-content.php @@ -0,0 +1,106 @@ +labels->singular_name; +$paper_style = false; + +/* translators: %s is the singular version of the post type's name. */ +echo '

    ' . esc_html( sprintf( __( 'Single %s settings', 'wordpress-seo' ), $wpseo_post_type->labels->singular_name ) ) . '

    '; + +require __DIR__ . '/post_type/post-type.php'; + +/** + * Allow adding custom fields to the admin meta page, just before the archive settings - Content Types tab. + * + * @param Yoast_Form $yform The Yoast_Form object. + * @param string $name The post type name. + */ +do_action( 'Yoast\WP\SEO\admin_post_types_beforearchive', $yform, $wpseo_post_type->name ); + +if ( $wpseo_post_type->name === 'product' && YoastSEO()->helpers->woocommerce->is_active() ) { + require __DIR__ . '/post_type/woocommerce-shop-page.php'; + + return; +} + +if ( WPSEO_Post_Type::has_archive( $wpseo_post_type ) ) { + $plural_label = $wpseo_post_type->labels->name; + + /* translators: %s is the plural version of the post type's name. */ + echo '

    ' . esc_html( sprintf( __( '%s archive settings', 'wordpress-seo' ), $plural_label ) ) . '

    '; + + echo '
    '; + + $custom_post_type_archive_help = $view_utils->search_results_setting_help( $wpseo_post_type, 'archive' ); + + $yform->index_switch( + 'noindex-ptarchive-' . $wpseo_post_type->name, + sprintf( + /* translators: %s expands to the post type's name. */ + __( 'the archive for %s', 'wordpress-seo' ), + $plural_label + ), + $custom_post_type_archive_help->get_button_html() . $custom_post_type_archive_help->get_panel_html() + ); + + echo '
    '; + + echo '
    '; + + $page_type = $recommended_replace_vars->determine_for_archive( $wpseo_post_type->name ); + + $editor = new WPSEO_Replacevar_Editor( + $yform, + [ + 'title' => 'title-ptarchive-' . $wpseo_post_type->name, + 'description' => 'metadesc-ptarchive-' . $wpseo_post_type->name, + 'page_type_recommended' => $recommended_replace_vars->determine_for_archive( $wpseo_post_type->name ), + 'page_type_specific' => $editor_specific_replace_vars->determine_for_archive( $wpseo_post_type->name ), + 'paper_style' => false, + ] + ); + $editor->render(); + + echo '
    '; + + if ( WPSEO_Options::get( 'breadcrumbs-enable' ) === true ) { + echo '
    '; + + $yform->textinput_extra_content( 'bctitle-ptarchive-' . $wpseo_post_type->name, __( 'Breadcrumbs title', 'wordpress-seo' ) ); + + echo '
    '; + } + + /** + * Allow adding custom fields to the admin meta page at the end of the archive settings for a post type - Content Types tab. + * + * @param Yoast_Form $yform The Yoast_Form object. + * @param string $name The post type name. + */ + do_action( 'Yoast\WP\SEO\admin_post_types_archive', $yform, $wpseo_post_type->name ); +} + +/** + * Allow adding a custom checkboxes to the admin meta page - Post Types tab. + * + * @deprecated 16.3 Use the {@see 'Yoast\WP\SEO\admin_post_types_beforearchive'} action instead. + * + * @param Yoast_Form $yform The Yoast_Form object. + * @param string $name The post type name. + */ +do_action_deprecated( + 'wpseo_admin_page_meta_post_types', + [ $yform, $wpseo_post_type->name ], + '16.3', + 'Yoast\WP\SEO\admin_post_types_beforearchive' +); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/post_type/post-type.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/post_type/post-type.php new file mode 100644 index 00000000..a698b2c4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/post_type/post-type.php @@ -0,0 +1,71 @@ +search_results_setting_help( $wpseo_post_type ); +$noindex_option_name = 'noindex-' . $wpseo_post_type->name; + +echo '
    '; + +$yform->index_switch( + $noindex_option_name, + $wpseo_post_type->labels->name, + $show_post_type_help->get_button_html() . $show_post_type_help->get_panel_html() +); + +$yform->show_hide_switch( + 'display-metabox-pt-' . $wpseo_post_type->name, + /* translators: %s expands to an indexable object's name, like a post type or taxonomy */ + sprintf( esc_html__( 'Show SEO settings for %1$s?', 'wordpress-seo' ), $wpseo_post_type->labels->name ) +); + +echo '
    '; + +echo '
    '; + +$editor = new WPSEO_Replacevar_Editor( + $yform, + [ + 'title' => 'title-' . $wpseo_post_type->name, + 'description' => 'metadesc-' . $wpseo_post_type->name, + 'page_type_recommended' => $recommended_replace_vars->determine_for_post_type( $wpseo_post_type->name ), + 'page_type_specific' => $editor_specific_replace_vars->determine_for_post_type( $wpseo_post_type->name ), + 'paper_style' => false, + ] +); +$editor->render(); + +echo '
    '; + +echo '
    '; + +// Schema settings. +$article_helper = new Article_Helper(); +$schema_page_type_option = 'schema-page-type-' . $wpseo_post_type->name; +$schema_article_type_option = 'schema-article-type-' . $wpseo_post_type->name; +$yform->hidden( $schema_page_type_option ); +if ( $wpseo_post_type->name !== 'page' && $article_helper->is_author_supported( $wpseo_post_type->name ) ) { + $yform->hidden( $schema_article_type_option ); +} +printf( + '
    ', + esc_attr( $wpseo_post_type->name ), + esc_attr( $wpseo_post_type->labels->name ), + esc_attr( 'hidden_' . $schema_page_type_option ), + esc_attr( 'hidden_' . $schema_article_type_option ), + esc_attr( WPSEO_Options::get_default( 'wpseo_titles', $schema_page_type_option ) ), + esc_attr( WPSEO_Options::get_default( 'wpseo_titles', $schema_article_type_option ) ) +); + +echo '
    '; diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/post_type/woocommerce-shop-page.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/post_type/woocommerce-shop-page.php new file mode 100644 index 00000000..548db454 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/post_type/woocommerce-shop-page.php @@ -0,0 +1,24 @@ +helpers->woocommerce->get_shop_page_id() !== -1 ) { + $description = sprintf( + /* translators: %1$s expands to an opening anchor tag, %2$s expands to a closing anchor tag. */ + esc_html__( 'You can edit the SEO meta-data for this custom type on the %1$sShop page%2$s.', 'wordpress-seo' ), + '', + '' + ); +} + +/* translators: %s expands to the post type name. */ +echo '

    ', esc_html( sprintf( __( 'Settings for %s archive', 'wordpress-seo' ), $wpseo_post_type->labels->name ) ), '

    '; +// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Output is properly escaped already, see above. +echo '

    ', $description, '

    '; diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/rss-content.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/rss-content.php new file mode 100644 index 00000000..1a474f71 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/rss-content.php @@ -0,0 +1,54 @@ + '50', + 'rows' => '5', +]; +$yform->textarea( 'rssbefore', __( 'Content to put before each post in the feed', 'wordpress-seo' ), $textarea_atts ); +$yform->textarea( 'rssafter', __( 'Content to put after each post in the feed', 'wordpress-seo' ), $textarea_atts ); + +$rss_variables_help = new WPSEO_Admin_Help_Panel( + 'search-appearance-rss-variables', + __( 'Learn more about the available variables', 'wordpress-seo' ), + __( 'You can use the following variables within the content, they will be replaced by the value on the right.', 'wordpress-seo' ), + 'has-wrapper' +); + +// phpcs:ignore WordPress.Security.EscapeOutput -- get_button_html() output is properly escaped. +echo '

    ' . esc_html__( 'Available variables', 'wordpress-seo' ) . $rss_variables_help->get_button_html() . '

    '; +// phpcs:ignore WordPress.Security.EscapeOutput -- get_panel_html() output is properly escaped. +echo $rss_variables_help->get_panel_html(); +?> + + + + + + + + + + + + + + + + + + + + + + + + + +
    %%AUTHORLINK%%
    %%POSTLINK%%
    %%BLOGLINK%%
    %%BLOGDESCLINK%%
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/special-pages.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/special-pages.php new file mode 100644 index 00000000..76414af1 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/special-pages.php @@ -0,0 +1,27 @@ +noindex, follow. */ + __( 'These pages will be %s by default, so they will never show up in search results.', 'wordpress-seo' ), + 'noindex, follow' + ), + 'has-wrapper' +); + +$editor = new WPSEO_Replacevar_Field( $yform, 'title-search-wpseo', __( 'Search pages', 'wordpress-seo' ), 'search', 'search' ); +$editor->render(); + +echo '
    '; + +$editor = new WPSEO_Replacevar_Field( $yform, 'title-404-wpseo', __( '404 pages', 'wordpress-seo' ), '404', '404' ); +$editor->render(); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/taxonomy-content.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/taxonomy-content.php new file mode 100644 index 00000000..3d37ed91 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/paper-content/taxonomy-content.php @@ -0,0 +1,86 @@ +name === 'post_format' ) { + $yform->light_switch( + 'disable-post_format', + __( 'Format-based archives', 'wordpress-seo' ), + [ __( 'On', 'wordpress-seo' ), __( 'Off', 'wordpress-seo' ) ], + false + ); +} + +echo '
    '; +echo "
    "; + +$taxonomies_help = $view_utils->search_results_setting_help( $wpseo_taxonomy ); + +$yform->index_switch( + 'noindex-tax-' . $wpseo_taxonomy->name, + $title, + $taxonomies_help->get_button_html() . $taxonomies_help->get_panel_html() +); + +if ( $wpseo_taxonomy->name !== 'post_format' ) { + $yform->show_hide_switch( + 'display-metabox-tax-' . $wpseo_taxonomy->name, + /* translators: %s: Expands to an indexable object's name, like a post type or taxonomy. */ + sprintf( __( 'Show SEO settings for %1$s?', 'wordpress-seo' ), $title ) + ); +} + +echo '
    '; +echo '
    '; + +echo '
    '; + +// Determine the page type for the term, this is needed for the recommended replacement variables. +$page_type = $recommended_replace_vars->determine_for_term( $wpseo_taxonomy->name ); + +$editor = new WPSEO_Replacevar_Editor( + $yform, + [ + 'title' => 'title-tax-' . $wpseo_taxonomy->name, + 'description' => 'metadesc-tax-' . $wpseo_taxonomy->name, + 'page_type_recommended' => $recommended_replace_vars->determine_for_term( $wpseo_taxonomy->name ), + 'page_type_specific' => $editor_specific_replace_vars->determine_for_term( $wpseo_taxonomy->name ), + 'paper_style' => false, + ] +); +$editor->render(); + +echo '
    '; + +/** + * Allow adding custom checkboxes to the admin meta page - Taxonomies tab. + * + * @param Yoast_Form $yform The Yoast_Form object. + * @param WP_Taxonomy $wpseo_taxonomy The taxonomy. + */ +do_action( 'Yoast\WP\SEO\admin_taxonomies_meta', $yform, $wpseo_taxonomy ); + +/** + * Allow adding custom checkboxes to the admin meta page - Taxonomies tab. + * + * @deprecated 16.3 Use {@see 'Yoast\WP\SEO\admin_taxonomies_meta'} instead. + * + * @param Yoast_Form $yform The Yoast_Form object. + * @param WP_Taxonomy $wpseo_taxonomy The taxonomy. + */ +do_action_deprecated( + 'wpseo_admin_page_meta_taxonomies', + [ $yform, $wpseo_taxonomy ], + '16.3', + 'Yoast\WP\SEO\admin_taxonomies_meta' +); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/post-types.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/post-types.php index f14c7dd9..02817fe0 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/post-types.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/post-types.php @@ -5,10 +5,6 @@ * @package WPSEO\Admin\Views */ -/** - * @var Yoast_Form $yform - */ - if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); @@ -20,65 +16,45 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { * Otherwise setting a post-type to `noindex` will remove it from the list, * making it very hard to restore the setting again. */ -$post_types = get_post_types( array( 'public' => true ), 'objects' ); +$wpseo_post_types = get_post_types( [ 'public' => true ], 'objects' ); // We'll show attachments on the Media tab. -$post_types = WPSEO_Post_Type::filter_attachment_post_type( $post_types ); +$wpseo_post_types = WPSEO_Post_Type::filter_attachment_post_type( $wpseo_post_types ); -$view_utils = new Yoast_View_Utils(); +echo '

    '; +esc_html_e( 'The settings on this page allow you to specify what the default search appearance should be for any type of content you have. You can choose which content types appear in search results and what their default description should be.', 'wordpress-seo' ); +echo '

    '; -if ( is_array( $post_types ) && $post_types !== array() ) { - foreach ( $post_types as $post_type ) { - echo '
    '; - echo '

    ' . esc_html( $post_type->labels->name ) . ' (' . esc_html( $post_type->name ) . ')

    '; - $view_utils->show_post_type_settings( $post_type ); - echo '
    '; - /** - * Allow adding a custom checkboxes to the admin meta page - Post Types tab - * - * @api WPSEO_Admin_Pages $yform The WPSEO_Admin_Pages object - * @api String $name The post type name - */ - do_action( 'wpseo_admin_page_meta_post_types', $yform, $post_type->name ); - } - unset( $post_type ); -} +$view_utils = new Yoast_View_Utils(); +$recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars(); +$editor_specific_replace_vars = new WPSEO_Admin_Editor_Specific_Replace_Vars(); +$opengraph_disabled_alert = $view_utils->generate_opengraph_disabled_alert(); -$post_types = get_post_types( - array( - '_builtin' => false, - 'has_archive' => true, - ), - 'objects' -); +// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Is correctly escaped in the generate_opengraph_disabled_alert() method. +echo $opengraph_disabled_alert; -if ( is_array( $post_types ) && $post_types !== array() ) { - echo '

    ' . esc_html__( 'Custom Content Type Archives', 'wordpress-seo' ) . '

    '; - echo '

    ' . esc_html__( 'Note: instead of templates these are the actual titles and meta descriptions for these custom content type archive pages.', 'wordpress-seo' ) . '

    '; - foreach ( $post_types as $post_type ) { - $name = $post_type->name; - echo '
    '; - echo '

    ' . esc_html( ucfirst( $post_type->labels->name ) ) . '

    '; - - $custom_post_type_archive_help = $view_utils->search_results_setting_help( $post_type, 'archive' ); - - $yform->index_switch( - 'noindex-ptarchive-' . $name, - sprintf( - /* translators: %s expands to the post type's name. */ - __( 'the archive for %s', 'wordpress-seo' ), - $post_type->labels->name - ), - $custom_post_type_archive_help->get_button_html() . $custom_post_type_archive_help->get_panel_html() +if ( is_array( $wpseo_post_types ) && $wpseo_post_types !== [] ) { + foreach ( array_values( $wpseo_post_types ) as $wpseo_post_type_index => $yoast_seo_post_type ) { + $wpseo_post_type_presenter = new WPSEO_Paper_Presenter( + $yoast_seo_post_type->labels->name, + __DIR__ . '/paper-content/post-type-content.php', + [ + 'collapsible' => true, + 'expanded' => ( $wpseo_post_type_index === 0 ), + 'paper_id' => 'settings-' . $yoast_seo_post_type->name, + 'view_data' => [ + 'wpseo_post_type' => $yoast_seo_post_type, + 'view_utils' => $view_utils, + 'recommended_replace_vars' => $recommended_replace_vars, + 'editor_specific_replace_vars' => $editor_specific_replace_vars, + ], + 'title' => $yoast_seo_post_type->labels->name, + 'title_after' => ' (' . esc_html( $yoast_seo_post_type->name ) . ')', + 'class' => 'search-appearance', + ] ); - $yform->textinput( 'title-ptarchive-' . $name, __( 'Title', 'wordpress-seo' ), 'template posttype-template' ); - $yform->textarea( 'metadesc-ptarchive-' . $name, __( 'Meta description', 'wordpress-seo' ), array( 'class' => 'template posttype-template' ) ); - if ( WPSEO_Options::get( 'breadcrumbs-enable' ) === true ) { - $yform->textinput( 'bctitle-ptarchive-' . $name, __( 'Breadcrumbs title', 'wordpress-seo' ) ); - } - echo '
    '; + // phpcs:ignore WordPress.Security.EscapeOutput -- get_output() output is properly escaped. + echo $wpseo_post_type_presenter->get_output(); } - unset( $post_type ); } -unset( $post_types ); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/rss.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/rss.php index fdc40b77..e2821d73 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/rss.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/rss.php @@ -5,67 +5,26 @@ * @package WPSEO\Admin */ -/** - * @var Yoast_Form $yform - */ - if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); exit(); } -$rss_help = new WPSEO_Admin_Help_Panel( - 'search-appearance-rss', - __( 'Learn more about the RSS feed setting', 'wordpress-seo' ), - __( 'This feature is used to automatically add content to your RSS, more specifically, it\'s meant to add links back to your blog and your blog posts, so dumb scrapers will automatically add these links too, helping search engines identify you as the original source of the content.', 'wordpress-seo' ), - 'has-wrapper' +$wpseo_rss_presenter = new WPSEO_Paper_Presenter( + esc_html__( 'RSS feed settings', 'wordpress-seo' ), + __DIR__ . '/paper-content/rss-content.php', + [ + 'help_text' => new WPSEO_Admin_Help_Panel( + 'search-appearance-rss', + __( 'Learn more about the RSS feed setting', 'wordpress-seo' ), + __( 'This feature is used to automatically add content to your RSS, more specifically, it\'s meant to add links back to your blog and your blog posts, so dumb scrapers will automatically add these links too, helping search engines identify you as the original source of the content.', 'wordpress-seo' ), + 'has-wrapper' + ), + 'paper_id' => 'settings-rss-feed', + 'class' => 'search-appearance', + ] ); -echo '

    ' . esc_html__( 'RSS feed settings', 'wordpress-seo' ) . $rss_help->get_button_html() . '

    '; - -echo $rss_help->get_panel_html(); - -$textarea_atts = array( - 'cols' => '50', - 'rows' => '5', -); -$yform->textarea( 'rssbefore', __( 'Content to put before each post in the feed', 'wordpress-seo' ), '', $textarea_atts ); -$yform->textarea( 'rssafter', __( 'Content to put after each post in the feed', 'wordpress-seo' ), '', $textarea_atts ); - -$rss_variables_help = new WPSEO_Admin_Help_Panel( - 'search-appearance-rss-variables', - __( 'Learn more about the available variables', 'wordpress-seo' ), - __( 'You can use the following variables within the content, they will be replaced by the value on the right.', 'wordpress-seo' ), - 'has-wrapper' -); - -echo '

    ' . esc_html__( 'Available variables', 'wordpress-seo' ) . $rss_variables_help->get_button_html() . '

    '; -echo $rss_variables_help->get_panel_html(); -?> - - - - - - - - - - - - - - - - - - - - - - - - - -
    %%AUTHORLINK%%
    %%POSTLINK%%
    %%BLOGLINK%%
    %%BLOGDESCLINK%%
    +// phpcs:ignore WordPress.Security.EscapeOutput -- get_output() output is properly escaped. +echo $wpseo_rss_presenter->get_output(); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/taxonomies.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/taxonomies.php index d9619afd..354fa999 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/taxonomies.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/taxonomies.php @@ -5,83 +5,51 @@ * @package WPSEO\Admin\Views */ -/** - * @var Yoast_Form $yform - */ - if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); exit(); } -$taxonomies = get_taxonomies( array( 'public' => true ), 'objects' ); -if ( is_array( $taxonomies ) && $taxonomies !== array() ) { - foreach ( $taxonomies as $tax ) { - // Explicitly hide all the core taxonomies we never want to do stuff for. - if ( in_array( $tax->name, array( 'link_category', 'nav_menu' ), true ) ) { - continue; - } +$wpseo_taxonomies = get_taxonomies( [ 'public' => true ], 'objects' ); +if ( is_array( $wpseo_taxonomies ) && $wpseo_taxonomies !== [] ) { + $view_utils = new Yoast_View_Utils(); + $recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars(); + $editor_specific_replace_vars = new WPSEO_Admin_Editor_Specific_Replace_Vars(); - echo '
    '; - echo '

    ' . esc_html( ucfirst( $tax->labels->name ) ) . ' (' . esc_html( $tax->name ) . ')

    '; - if ( $tax->name === 'post_format' ) { - $yform->light_switch( - 'disable-post_format', - __( 'Format-based archives', 'wordpress-seo' ), - array( __( 'Enabled', 'wordpress-seo' ), __( 'Disabled', 'wordpress-seo' ) ), - false - ); - } - echo "
    "; + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Is correctly escaped in the generate_opengraph_disabled_alert() method. + echo $view_utils->generate_opengraph_disabled_alert( 'taxonomies' ); - $view_utils = new Yoast_View_Utils(); - $taxonomies_help = $view_utils->search_results_setting_help( $tax ); + // Explicitly hide all the core taxonomies we never want to do stuff for. + $wpseo_taxonomies = array_diff_key( $wpseo_taxonomies, array_flip( [ 'link_category', 'nav_menu' ] ) ); - $yform->index_switch( - 'noindex-tax-' . $tax->name, - $tax->labels->name, - $taxonomies_help->get_button_html() . $taxonomies_help->get_panel_html() + foreach ( array_values( $wpseo_taxonomies ) as $wpseo_taxonomy_index => $wpseo_taxonomy ) { + $wpseo_taxonomy_presenter = new WPSEO_Paper_Presenter( + $wpseo_taxonomy->labels->name, + __DIR__ . '/paper-content/taxonomy-content.php', + [ + 'collapsible' => true, + 'expanded' => ( $wpseo_taxonomy_index === 0 ), + 'paper_id' => 'settings-' . $wpseo_taxonomy->name, + 'view_data' => [ + 'wpseo_taxonomy' => $wpseo_taxonomy, + 'view_utils' => $view_utils, + 'recommended_replace_vars' => $recommended_replace_vars, + 'editor_specific_replace_vars' => $editor_specific_replace_vars, + ], + 'title_after' => ' (' . esc_html( $wpseo_taxonomy->name ) . ')', + 'class' => 'search-appearance', + ] ); - $yform->textinput( 'title-tax-' . $tax->name, __( 'Title template', 'wordpress-seo' ), 'template taxonomy-template' ); - $yform->textarea( 'metadesc-tax-' . $tax->name, __( 'Meta description template', 'wordpress-seo' ), array( 'class' => 'template taxonomy-template' ) ); - if ( $tax->name !== 'post_format' ) { - /* translators: %1$s expands to Yoast SEO */ - $yform->show_hide_switch( 'display-metabox-tax-' . $tax->name, sprintf( __( '%1$s Meta Box', 'wordpress-seo' ), 'Yoast SEO' ) ); - } - /** - * Allow adding custom checkboxes to the admin meta page - Taxonomies tab - * - * @api WPSEO_Admin_Pages $yform The WPSEO_Admin_Pages object - * @api Object $tax The taxonomy - */ - do_action( 'wpseo_admin_page_meta_taxonomies', $yform, $tax ); - echo '
    '; - echo '
    '; + // phpcs:ignore WordPress.Security.EscapeOutput -- get_output() output is properly escaped. + echo $wpseo_taxonomy_presenter->get_output(); } - unset( $tax ); + + unset( $wpseo_taxonomy_index, $wpseo_taxonomy_presenter, $view_utils, $recommended_replace_vars ); } -unset( $taxonomies ); -echo '

    ', esc_html__( ' Category URLs', 'wordpress-seo' ), '

    '; +unset( $wpseo_taxonomies ); -$remove_buttons = array( __( 'Keep', 'wordpress-seo' ), __( 'Remove', 'wordpress-seo' ) ); - -$stripcategorybase_help = new WPSEO_Admin_Help_Panel( - 'opengraph', - esc_html__( 'Help on the category prefix setting', 'wordpress-seo' ), - sprintf( - /* translators: %s expands to /category/ */ - esc_html__( 'Category URLs in WordPress contain a prefix, usually %s, this feature removes that prefix, for categories only.', 'wordpress-seo' ), - '/category/' - ) -); - -$yform->light_switch( - 'stripcategorybase', - __( 'Remove the categories prefix', 'wordpress-seo' ), - $remove_buttons, - false, - $stripcategorybase_help->get_button_html() . $stripcategorybase_help->get_panel_html() -); +printf( '

    %s

    ', esc_html__( 'Category URLs', 'wordpress-seo' ) ); +require __DIR__ . '/taxonomies/category-url.php'; diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/taxonomies/category-url.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/taxonomies/category-url.php new file mode 100644 index 00000000..bc55f362 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/metas/taxonomies/category-url.php @@ -0,0 +1,28 @@ +/category/ */ + esc_html__( 'Category URLs in WordPress contain a prefix, usually %s, this feature removes that prefix, for categories only.', 'wordpress-seo' ), + '/category/' + ) +); + +$yform->light_switch( + 'stripcategorybase', + __( 'Remove the categories prefix?', 'wordpress-seo' ), + $remove_buttons, + false, + $stripcategorybase_help->get_button_html() . $stripcategorybase_help->get_panel_html() +); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/network/features.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/network/features.php new file mode 100644 index 00000000..5e29b3df --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/network/features.php @@ -0,0 +1,66 @@ +get_all(); + +?> +

    +
    + label ); + if ( ! empty( $feature->extra ) ) { + $help_text .= ' ' . $feature->extra; + } + if ( ! empty( $feature->read_more_label ) ) { + $help_text .= ' '; + $help_text .= sprintf( + '%2$s', + esc_url( WPSEO_Shortlinker::get( $feature->read_more_url ) ), + esc_html( $feature->read_more_label ) + ); + } + + $feature_help = new WPSEO_Admin_Help_Panel( + WPSEO_Option::ALLOW_KEY_PREFIX . $feature->setting, + /* translators: %s expands to a feature's name */ + sprintf( esc_html__( 'Help on: %s', 'wordpress-seo' ), esc_html( $feature->name ) ), + $help_text + ); + + $yform->toggle_switch( + WPSEO_Option::ALLOW_KEY_PREFIX . $feature->setting, + [ + 'on' => __( 'Allow Control', 'wordpress-seo' ), + 'off' => __( 'Disable', 'wordpress-seo' ), + ], + $feature->name, + $feature_help->get_button_html() . $feature_help->get_panel_html() + ); + } + ?> +
    +hidden( 'show_onboarding_notice', 'wpseo_show_onboarding_notice' ); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/network/general.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/network/general.php new file mode 100644 index 00000000..a73c722b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/network/general.php @@ -0,0 +1,56 @@ +'; + +/* + * {@internal Important: Make sure the options added to the array here are in line with the + * options set in the WPSEO_Option_MS::$allowed_access_options property.}} + */ +$yform->select( + 'access', + /* translators: %1$s expands to Yoast SEO */ + sprintf( __( 'Who should have access to the %1$s settings', 'wordpress-seo' ), 'Yoast SEO' ), + [ + 'admin' => __( 'Site Admins (default)', 'wordpress-seo' ), + 'superadmin' => __( 'Super Admins only', 'wordpress-seo' ), + ] +); + +if ( get_blog_count() <= 100 ) { + $network_admin = new Yoast_Network_Admin(); + + $yform->select( + 'defaultblog', + __( 'New sites in the network inherit their SEO settings from this site', 'wordpress-seo' ), + $network_admin->get_site_choices( true, true ) + ); + echo '

    ' . esc_html__( 'Choose the site whose settings you want to use as default for all sites that are added to your network. If you choose \'None\', the normal plugin defaults will be used.', 'wordpress-seo' ) . '

    '; +} +else { + $yform->textinput( 'defaultblog', __( 'New sites in the network inherit their SEO settings from this site', 'wordpress-seo' ) ); + echo '

    '; + printf( + /* translators: 1: link open tag; 2: link close tag. */ + esc_html__( 'Enter the %1$sSite ID%2$s for the site whose settings you want to use as default for all sites that are added to your network. Leave empty for none (i.e. the normal plugin defaults will be used).', 'wordpress-seo' ), + '', + '' + ); + echo '

    '; +} + +echo '

    ' . esc_html__( 'Take note:', 'wordpress-seo' ) . ' ' . esc_html__( 'Privacy sensitive (FB admins and such), theme specific (title rewrite) and a few very site specific settings will not be imported to new sites.', 'wordpress-seo' ) . '

    '; + +echo ''; diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/network/integrations.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/network/integrations.php new file mode 100644 index 00000000..7970b590 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/network/integrations.php @@ -0,0 +1,68 @@ +get_all(); + +?> +

    +
    + label ); + + if ( ! empty( $integration->extra ) ) { + $help_text .= ' ' . $integration->extra; + } + + if ( ! empty( $integration->read_more_label ) ) { + $help_text .= ' '; + $help_text .= sprintf( + '%2$s', + esc_url( WPSEO_Shortlinker::get( $integration->read_more_url ) ), + esc_html( $integration->read_more_label ) + ); + } + + $feature_help = new WPSEO_Admin_Help_Panel( + WPSEO_Option::ALLOW_KEY_PREFIX . $integration->setting, + /* translators: %s expands to an integration's name */ + sprintf( esc_html__( 'Help on: %s', 'wordpress-seo' ), esc_html( $integration->name ) ), + $help_text + ); + + $yform->toggle_switch( + WPSEO_Option::ALLOW_KEY_PREFIX . $integration->setting, + [ + 'on' => __( 'Allow Control', 'wordpress-seo' ), + 'off' => __( 'Disable', 'wordpress-seo' ), + ], + $integration->name, + $feature_help->get_button_html() . $feature_help->get_panel_html() + ); + } + ?> +
    +hidden( 'show_onboarding_notice', 'wpseo_show_onboarding_notice' ); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/network/restore-site.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/network/restore-site.php new file mode 100644 index 00000000..ce6701a9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/network/restore-site.php @@ -0,0 +1,32 @@ +' . esc_html__( 'Using this form you can reset a site to the default SEO settings.', 'wordpress-seo' ) . '

    '; + +if ( get_blog_count() <= 100 ) { + $network_admin = new Yoast_Network_Admin(); + + $yform->select( + 'site_id', + __( 'Site ID', 'wordpress-seo' ), + $network_admin->get_site_choices( false, true ) + ); +} +else { + $yform->textinput( 'site_id', __( 'Site ID', 'wordpress-seo' ) ); +} + +wp_nonce_field( 'wpseo-network-restore', 'restore_site_nonce', false ); +echo ''; diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/social/accounts.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/social/accounts.php index d91a2228..65a6c876 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/social/accounts.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/social/accounts.php @@ -3,10 +3,8 @@ * WPSEO plugin file. * * @package WPSEO\Admin\Views - */ - -/** - * @var Yoast_Form $yform + * + * @uses Yoast_Form $yform Form object. */ if ( ! defined( 'WPSEO_VERSION' ) ) { @@ -18,21 +16,96 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { $social_profiles_help = new WPSEO_Admin_Help_Panel( 'social-accounts', __( 'Learn more about your social profiles settings', 'wordpress-seo' ), - __( 'To let search engines know which social profiles are associated to this site, enter your site social profiles data below.', 'wordpress-seo' ), + __( 'To let search engines know which social profiles are associated to this site, enter your site social profiles data below.', 'wordpress-seo' ) . ' ' . + __( 'If a Wikipedia page for you or your organization exists, add it too.', 'wordpress-seo' ), 'has-wrapper' ); -echo '

    ' . esc_html__( 'Your social profiles', 'wordpress-seo' ) . $social_profiles_help->get_button_html() . '

    '; -echo $social_profiles_help->get_panel_html(); +$company_or_person = WPSEO_Options::get( 'company_or_person', '' ); + +$organization_social_fields = [ + [ + 'id' => 'facebook_site', + 'label' => __( 'Facebook Page URL', 'wordpress-seo' ), + 'attributes' => [ 'type' => 'url' ], + ], + [ + 'id' => 'twitter_site', + 'label' => __( 'Twitter Username', 'wordpress-seo' ), + 'attributes' => [ 'type' => 'text' ], + ], + [ + 'id' => 'instagram_url', + 'label' => __( 'Instagram URL', 'wordpress-seo' ), + 'attributes' => [ 'type' => 'url' ], + ], + [ + 'id' => 'linkedin_url', + 'label' => __( 'LinkedIn URL', 'wordpress-seo' ), + 'attributes' => [ 'type' => 'url' ], + ], + [ + 'id' => 'myspace_url', + 'label' => __( 'MySpace URL', 'wordpress-seo' ), + 'attributes' => [ 'type' => 'url' ], + ], + [ + 'id' => 'pinterest_url', + 'label' => __( 'Pinterest URL', 'wordpress-seo' ), + 'attributes' => [ 'type' => 'url' ], + ], + [ + 'id' => 'youtube_url', + 'label' => __( 'YouTube URL', 'wordpress-seo' ), + 'attributes' => [ 'type' => 'url' ], + ], + [ + 'id' => 'wikipedia_url', + 'label' => __( 'Wikipedia URL', 'wordpress-seo' ), + 'attributes' => [ 'type' => 'url' ], + ], +]; $yform = Yoast_Form::get_instance(); -$yform->textinput( 'facebook_site', __( 'Facebook Page URL', 'wordpress-seo' ) ); -$yform->textinput( 'twitter_site', __( 'Twitter Username', 'wordpress-seo' ) ); -$yform->textinput( 'instagram_url', __( 'Instagram URL', 'wordpress-seo' ) ); -$yform->textinput( 'linkedin_url', __( 'LinkedIn URL', 'wordpress-seo' ) ); -$yform->textinput( 'myspace_url', __( 'MySpace URL', 'wordpress-seo' ) ); -$yform->textinput( 'pinterest_url', __( 'Pinterest URL', 'wordpress-seo' ) ); -$yform->textinput( 'youtube_url', __( 'YouTube URL', 'wordpress-seo' ) ); -$yform->textinput( 'google_plus_url', __( 'Google+ URL', 'wordpress-seo' ) ); + +if ( $company_or_person === 'person' ) { + echo '
    '; + echo '

    ' . esc_html__( 'Your website is currently configured to represent a Person', 'wordpress-seo' ) . '

    '; + echo '

    '; + esc_html_e( 'That means that the form and information below is disabled, and not used.', 'wordpress-seo' ); + echo '

    '; + echo '

    '; + $user_id = WPSEO_Options::get( 'company_or_person_user_id', '' ); + $person = get_userdata( $user_id ); + printf( + /* translators: 1: link to edit user page. */ + esc_html__( 'To change the social accounts used for your site, update the details for %1$s.', 'wordpress-seo' ), + '' . esc_html( $person->display_name ) . '' + ); + echo ' '; + printf( + /* translators: 1: link tag to the relevant WPSEO admin page; 2: link close tag. */ + esc_html__( 'To make your site represent a Company or Organization go to %1$sSearch Appearance%2$s and set Organization or Person to "Organization".', 'wordpress-seo' ), + '', + '' + ); + echo '

    '; + + // Organization social fields should still be rendered, because other wise the values are lost on save. + foreach ( $organization_social_fields as $organization ) { + $yform->hidden( $organization['id'] ); + } +} + +if ( $company_or_person === 'company' ) { + // phpcs:ignore WordPress.Security.EscapeOutput -- get_button_html() output is properly escaped. + echo '

    ' . esc_html__( 'Organization social profiles', 'wordpress-seo' ) . $social_profiles_help->get_button_html() . '

    '; + // phpcs:ignore WordPress.Security.EscapeOutput -- get_panel_html() output is properly escaped. + echo $social_profiles_help->get_panel_html(); + + foreach ( $organization_social_fields as $organization ) { + $yform->textinput( $organization['id'], $organization['label'], $organization['attributes'] ); + } +} do_action( 'wpseo_admin_other_section' ); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/social/facebook.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/social/facebook.php index a81c24ee..5a5f9a83 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/social/facebook.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/social/facebook.php @@ -3,11 +3,11 @@ * WPSEO plugin file. * * @package WPSEO\Admin\Views + * + * @uses Yoast_Form $yform Form object. */ -/** - * @var Yoast_Form $yform - */ +use Yoast\WP\SEO\Presenters\Admin\Alert_Presenter; if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); @@ -22,63 +22,39 @@ $yform->light_switch( 'opengraph', __( 'Add Open Graph meta data', 'wordpress-se ?>

    -textinput( 'fbadminapp', __( 'Facebook App ID', 'wordpress-seo' ) ); - -if ( 'posts' === get_option( 'show_on_front' ) ) { - $social_facebook_frontpage_help = new WPSEO_Admin_Help_Panel( - 'social-facebook-frontpage', - esc_html__( 'Learn more about the title separator setting', 'wordpress-seo' ), - esc_html__( 'These are the title, description and image used in the Open Graph meta tags on the front page of your site.', 'wordpress-seo' ), - 'has-wrapper' + ' . esc_html__( 'Google+ settings', 'wordpress-seo' ) . ''; - -printf( - '

    %s

    ', - esc_html__( 'If you have a Google+ page for your business, add that URL here and link it on your Google+ page\'s about page.', 'wordpress-seo' ) -); - -$yform->textinput( 'plus-publisher', __( 'Google Publisher Page', 'wordpress-seo' ) ); - -do_action( 'wpseo_admin_googleplus_section' ); diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/social/pinterest.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/social/pinterest.php index 5453cf6a..f94bbbcc 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/social/pinterest.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/social/pinterest.php @@ -3,10 +3,8 @@ * WPSEO plugin file. * * @package WPSEO\Admin\Views - */ - -/** - * @var Yoast_Form $yform + * + * @uses Yoast_Form $yform Form object. */ if ( ! defined( 'WPSEO_VERSION' ) ) { @@ -19,7 +17,7 @@ echo '

    ' . esc_html__( 'Pinterest settings', 'wordpress-seo' ) . '

    '; printf( '

    %s

    ', - esc_html__( 'Pinterest uses Open Graph metadata just like Facebook, so be sure to keep the Open Graph checkbox on the Facebook tab checked if you want to optimize your site for Pinterest.', 'wordpress-seo' ) + esc_html__( 'Pinterest uses Open Graph metadata just like Facebook, so be sure to keep the "Add Open Graph meta data" setting on the Facebook tab enabled if you want to optimize your site for Pinterest.', 'wordpress-seo' ) ); printf( '

    %s

    ', @@ -30,7 +28,7 @@ echo '

    '; printf( /* translators: %1$s / %2$s expands to a link to pinterest.com's help page. */ esc_html__( 'To %1$sconfirm your site with Pinterest%2$s, add the meta tag here:', 'wordpress-seo' ), - '', + '', '' ); echo '

    '; diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/social/twitterbox.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/social/twitterbox.php index 642aeaee..493ddc36 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/social/twitterbox.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/social/twitterbox.php @@ -3,10 +3,9 @@ * WPSEO plugin file. * * @package WPSEO\Admin\Views - */ - -/** - * @var Yoast_Form $yform + * + * @uses Yoast_Form $yform Form object. + * @uses array WPSEO_Option_Social::$twitter_card_types */ if ( ! defined( 'WPSEO_VERSION' ) ) { @@ -17,6 +16,11 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { echo '

    ' . esc_html__( 'Twitter settings', 'wordpress-seo' ) . '

    '; +printf( + '

    %s

    ', + esc_html__( 'Twitter uses Open Graph metadata just like Facebook, so be sure to keep the "Add Open Graph meta data" setting on the Facebook tab enabled if you want to optimize your site for Twitter.', 'wordpress-seo' ) +); + $yform->light_switch( 'twitter', __( 'Add Twitter card meta data', 'wordpress-seo' ) ); echo '

    '; diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/import-seo.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/import-seo.php index dee575c1..254a8095 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/import-seo.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/import-seo.php @@ -5,11 +5,6 @@ * @package WPSEO\Admin\Views */ -/** - * @var Yoast_Form $yform - * @var WPSEO_Import_Plugins_Detector $import_check - */ - if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); @@ -22,7 +17,11 @@ $import_check->detect(); if ( count( $import_check->needs_import ) === 0 ) { echo '

    ', esc_html__( 'Import from other SEO plugins', 'wordpress-seo' ), '

    '; echo '

    '; - esc_html_e( 'Yoast SEO did not detect any plugin data from plugins it can import from.', 'wordpress-seo' ); + printf( + /* translators: %s expands to Yoast SEO */ + esc_html__( '%s did not detect any plugin data from plugins it can import from.', 'wordpress-seo' ), + 'Yoast SEO' + ); echo '

    '; return; @@ -37,11 +36,11 @@ if ( count( $import_check->needs_import ) === 0 ) { * @return void */ function wpseo_import_external_select( $name, $plugins ) { - _e( 'Plugin: ', 'wordpress-seo' ); - echo ''; foreach ( $plugins as $class => $plugin ) { /* translators: %s is replaced with the name of the plugin we're importing from. */ - echo ''; + echo ''; } echo ''; } @@ -60,12 +59,18 @@ function wpseo_import_external_select( $name, $plugins ) {
    -

    +

    - +

    + method="post" accept-charset=""> needs_import ); @@ -74,7 +79,7 @@ function wpseo_import_external_select( $name, $plugins ) { do_action( 'wpseo_import_other_plugins' ); ?> + value=""/>
    @@ -89,7 +94,11 @@ function wpseo_import_external_select( $name, $plugins ) {

    ','' ); + printf( + esc_html__( 'You should run the configuration wizard, from the SEO → General → Dashboard page, to make sure all the settings for your site are correct.', 'wordpress-seo' ), + '', + '' + ); ?>

    @@ -100,12 +109,12 @@ function wpseo_import_external_select( $name, $plugins ) {

    + method="post" accept-charset=""> needs_import ); ?> + value=""/>
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/wpseo-export.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/wpseo-export.php index ed31c005..335b9fe1 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/wpseo-export.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/wpseo-export.php @@ -5,10 +5,6 @@ * @package WPSEO\Admin\Views */ -/** - * @var Yoast_Form $yform - */ - if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); @@ -18,9 +14,15 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { /* translators: %1$s expands to Yoast SEO */ $submit_button_value = sprintf( __( 'Export your %1$s settings', 'wordpress-seo' ), 'Yoast SEO' ); +if ( filter_input( INPUT_POST, 'do_export' ) ) { + $export = new WPSEO_Export(); + $export->export(); + return; +} + $wpseo_export_phrase = sprintf( /* translators: %1$s expands to Yoast SEO */ - __( 'Export your %1$s settings here, to import them again later or to import them on another site.', 'wordpress-seo' ), + __( 'Export your %1$s settings here, to copy them on another site.', 'wordpress-seo' ), 'Yoast SEO' ); ?> @@ -30,6 +32,7 @@ $wpseo_export_phrase = sprintf( action="" method="post" accept-charset=""> - + + diff --git a/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/wpseo-import.php b/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/wpseo-import.php index 25aa37f3..18a5bfe9 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/wpseo-import.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tabs/tool/wpseo-import.php @@ -5,37 +5,42 @@ * @package WPSEO\Admin\Views */ -/** - * @var Yoast_Form $yform - */ - if ( ! defined( 'WPSEO_VERSION' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); exit(); } +if ( ! defined( 'WPSEO_NAMESPACES' ) || ! WPSEO_NAMESPACES ) { + esc_html_e( 'Import of settings is only supported on servers that run PHP 5.3 or higher.', 'wordpress-seo' ); + return; +} ?> -

    +

    ', - '' + /* translators: 1: expands to Yoast SEO, 2: expands to Import settings. */ + esc_html__( 'Import settings from another %1$s installation by pasting them here and clicking "%2$s".', 'wordpress-seo' ), + 'Yoast SEO', + esc_html__( 'Import settings', 'wordpress-seo' ) ); ?>

    - - - -
    -
    + +
    +
    diff --git a/wp-content/plugins/wordpress-seo/admin/views/tool-bulk-editor.php b/wp-content/plugins/wordpress-seo/admin/views/tool-bulk-editor.php index c8316cf1..f3c28788 100644 --- a/wp-content/plugins/wordpress-seo/admin/views/tool-bulk-editor.php +++ b/wp-content/plugins/wordpress-seo/admin/views/tool-bulk-editor.php @@ -12,39 +12,70 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { exit(); } -$wpseo_bulk_titles_table = new WPSEO_Bulk_Title_Editor_List_Table(); -$wpseo_bulk_description_table = new WPSEO_Bulk_Description_List_Table(); +/** + * Sanitizes the parameters that have been sent. + * + * @return array The sanitized fields. + */ +function yoast_free_bulk_sanitize_input_fields() { + $possible_params = [ + 'type', + 'paged', + 'post_type_filter', + 'post_status', + 'order', + 'orderby', + ]; -get_current_screen()->set_screen_reader_content( array( + $input_get = []; + foreach ( $possible_params as $param_name ) { + if ( isset( $_GET[ $param_name ] ) ) { + $input_get[ $param_name ] = sanitize_text_field( wp_unslash( $_GET[ $param_name ] ) ); + } + } + + return $input_get; +} + +$yoast_free_input_fields = yoast_free_bulk_sanitize_input_fields(); + +// Verifies the nonce. +if ( ! empty( $yoast_free_input_fields ) ) { + check_admin_referer( 'bulk-editor-table', 'nonce' ); +} + +// If type is empty, fill it with value of first tab (title). +if ( ! isset( $yoast_free_input_fields['type'] ) ) { + $yoast_free_input_fields['type'] = 'title'; +} + +$yoast_bulk_editor_arguments = [ + 'input_fields' => $yoast_free_input_fields, + 'nonce' => wp_create_nonce( 'bulk-editor-table' ), +]; + +$wpseo_bulk_titles_table = new WPSEO_Bulk_Title_Editor_List_Table( $yoast_bulk_editor_arguments ); +$wpseo_bulk_description_table = new WPSEO_Bulk_Description_List_Table( $yoast_bulk_editor_arguments ); + +$yoast_free_screen_reader_content = [ 'heading_views' => __( 'Filter posts list', 'wordpress-seo' ), 'heading_pagination' => __( 'Posts list navigation', 'wordpress-seo' ), 'heading_list' => __( 'Posts list', 'wordpress-seo' ), -) ); +]; +get_current_screen()->set_screen_reader_content( $yoast_free_screen_reader_content ); -// If type is empty, fill it with value of first tab (title). -$_GET['type'] = ( ! empty( $_GET['type'] ) ) ? $_GET['type'] : 'title'; +if ( ! empty( $_REQUEST['_wp_http_referer'] ) && isset( $_SERVER['REQUEST_URI'] ) ) { + $request_uri = sanitize_file_name( wp_unslash( $_SERVER['REQUEST_URI'] ) ); -if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) { - wp_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), stripslashes( $_SERVER['REQUEST_URI'] ) ) ); + wp_redirect( + remove_query_arg( + [ '_wp_http_referer', '_wpnonce' ], + $request_uri + ) + ); exit; } -/** - * Outputs a help center. - */ -function wpseo_render_help_center() { - $tabs = new WPSEO_Option_Tabs( '', '' ); - $tabs->add_tab( new WPSEO_Option_Tab( 'title', __( 'Bulk editor', 'wordpress-seo' ), - array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-tools-bulk-editor' ) ) ) ); - - $tabs->add_tab( new WPSEO_Option_Tab( 'description', __( 'Bulk editor', 'wordpress-seo' ), - array( 'video_url' => WPSEO_Shortlinker::get( 'https://yoa.st/screencast-tools-bulk-editor' ) ) ) ); - - $helpcenter = new WPSEO_Help_Center( '', $tabs, WPSEO_Utils::is_yoast_seo_premium() ); - $helpcenter->localize_data(); - $helpcenter->mount(); -} - /** * Renders a bulk editor tab. * @@ -63,7 +94,8 @@ function wpseo_get_rendered_tab( $table, $id ) { ?> diff --git a/wp-content/plugins/wordpress-seo/admin/watchers/class-slug-change-watcher.php b/wp-content/plugins/wordpress-seo/admin/watchers/class-slug-change-watcher.php index 6d0335ba..d892de1e 100644 --- a/wp-content/plugins/wordpress-seo/admin/watchers/class-slug-change-watcher.php +++ b/wp-content/plugins/wordpress-seo/admin/watchers/class-slug-change-watcher.php @@ -6,7 +6,7 @@ */ /** - * Class WPSEO_Slug_Change_Watcher + * Class WPSEO_Slug_Change_Watcher. */ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration { @@ -16,24 +16,32 @@ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration { * @return void */ public function register_hooks() { - // If the current plugin is Yoast SEO Premium, stop registering. - if ( WPSEO_Utils::is_yoast_seo_premium() ) { + if ( YoastSEO()->helpers->product->is_premium() ) { return; } - // Detect a post slug change. - add_action( 'post_updated', array( $this, 'detect_slug_change' ), 12, 3 ); - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) ); + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] ); + + // Detect a post trash. + add_action( 'wp_trash_post', [ $this, 'detect_post_trash' ] ); + + // Detect a post delete. + add_action( 'before_delete_post', [ $this, 'detect_post_delete' ] ); + + // Detects deletion of a term. + add_action( 'delete_term_taxonomy', [ $this, 'detect_term_delete' ] ); } /** * Enqueues the quick edit handler. + * + * @return void */ public function enqueue_assets() { global $pagenow; - if ( ! in_array( $pagenow, array( 'edit.php' ), true ) ) { + if ( ! in_array( $pagenow, [ 'edit.php', 'edit-tags.php' ], true ) ) { return; } @@ -42,38 +50,139 @@ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration { } /** - * Detects if the slug changed, hooked into 'post_updated'. + * Shows an message when a post is about to get trashed. * - * @param integer $post_id The ID of the post. Unused. - * @param WP_Post $post The post with the new values. - * @param WP_Post $post_before The post with the previous values. + * @param int $post_id The current post ID. * * @return void */ - public function detect_slug_change( $post_id, $post, $post_before ) { - // If post is a revision do not advise creating a redirect. - if ( wp_is_post_revision( $post_before ) && wp_is_post_revision( $post ) ) { + public function detect_post_trash( $post_id ) { + if ( ! $this->is_post_viewable( $post_id ) ) { return; } - // There is no slug change. - if ( $post->post_name === $post_before->post_name ) { + /* translators: %1$s expands to the translated name of the post type. */ + $first_sentence = sprintf( __( 'You just trashed a %1$s.', 'wordpress-seo' ), $this->get_post_type_label( get_post_type( $post_id ) ) ); + $message = $this->get_message( $first_sentence ); + + $this->add_notification( $message ); + } + + /** + * Shows an message when a post is about to get trashed. + * + * @param int $post_id The current post ID. + * + * @return void + */ + public function detect_post_delete( $post_id ) { + if ( ! $this->is_post_viewable( $post_id ) ) { return; } - // If the post URL wasn't visible before, or isn't visible now, don't advise creating a redirect. - if ( ! $this->check_visible_post_status( $post_before->post_status ) || ! $this->check_visible_post_status( $post->post_status ) ) { + /* translators: %1$s expands to the translated name of the post type. */ + $first_sentence = sprintf( __( 'You just deleted a %1$s.', 'wordpress-seo' ), $this->get_post_type_label( get_post_type( $post_id ) ) ); + $message = $this->get_message( $first_sentence ); + + $this->add_notification( $message ); + } + + /** + * Shows a message when a term is about to get deleted. + * + * @param int $term_id The term ID that will be deleted. + * + * @return void + */ + public function detect_term_delete( $term_id ) { + if ( ! $this->is_term_viewable( $term_id ) ) { return; } - $post_type_object = get_post_type_object( $post->post_type ); + $first_sentence = sprintf( + /* translators: 1: term label */ + __( 'You just deleted a %1$s.', 'wordpress-seo' ), + $this->get_taxonomy_label_for_term( $term_id ) + ); + + $message = $this->get_message( $first_sentence ); + + $this->add_notification( $message ); + } + + /** + * Checks if the post is viewable. + * + * @param string $post_id The post id to check. + * + * @return bool Whether the post is viewable or not. + */ + protected function is_post_viewable( $post_id ) { + $post_type = get_post_type( $post_id ); + if ( ! WPSEO_Post_Type::is_post_type_accessible( $post_type ) ) { + return false; + } + + $post_status = get_post_status( $post_id ); + if ( ! $this->check_visible_post_status( $post_status ) ) { + return false; + } + + return true; + } + + /** + * Checks if the term is viewable. + * + * @param string $term_id The term ID to check. + * + * @return bool Whether the term is viewable or not. + */ + protected function is_term_viewable( $term_id ) { + $term = get_term( $term_id ); + + if ( ! $term || is_wp_error( $term ) ) { + return false; + } + + $taxonomy = get_taxonomy( $term->taxonomy ); + if ( ! $taxonomy ) { + return false; + } + + return $taxonomy->publicly_queryable || $taxonomy->public; + } + + /** + * Gets the taxonomy label to use for a term. + * + * @param int $term_id The term ID. + * + * @return string The taxonomy's singular label. + */ + protected function get_taxonomy_label_for_term( $term_id ) { + $term = get_term( $term_id ); + $taxonomy = get_taxonomy( $term->taxonomy ); + + return $taxonomy->labels->singular_name; + } + + /** + * Retrieves the singular post type label. + * + * @param string $post_type Post type to retrieve label from. + * + * @return string The singular post type name. + */ + protected function get_post_type_label( $post_type ) { + $post_type_object = get_post_type_object( $post_type ); // If the post type of this post wasn't registered default back to post. if ( $post_type_object === null ) { $post_type_object = get_post_type_object( 'post' ); } - $this->add_notification( $post_type_object->labels->singular_name ); + return $post_type_object->labels->singular_name; } /** @@ -84,34 +193,53 @@ class WPSEO_Slug_Change_Watcher implements WPSEO_WordPress_Integration { * @return bool Whether or not the post is visible. */ protected function check_visible_post_status( $post_status ) { - $visible_post_statuses = array( + $visible_post_statuses = [ 'publish', 'static', 'private', - ); + ]; return in_array( $post_status, $visible_post_statuses, true ); } + /** + * Returns the message around changed URLs. + * + * @param string $first_sentence The first sentence of the notification. + * + * @return string The full notification. + */ + protected function get_message( $first_sentence ) { + return '

    ' . __( 'Make sure you don\'t miss out on traffic!', 'wordpress-seo' ) . '

    ' + . '

    ' + . $first_sentence + . ' ' . __( 'Search engines and other websites can still send traffic to your deleted post.', 'wordpress-seo' ) + . ' ' . __( 'You should create a redirect to ensure your visitors do not get a 404 error when they click on the no longer working URL.', 'wordpress-seo' ) + /* translators: %s expands to Yoast SEO Premium */ + . ' ' . sprintf( __( 'With %s, you can easily create such redirects.', 'wordpress-seo' ), 'Yoast SEO Premium' ) + . '

    ' + . '

    ' + /* translators: %s expands to Yoast SEO Premium */ + . sprintf( __( 'Get %s', 'wordpress-seo' ), 'Yoast SEO Premium' ) + . '' . __( '(Opens in a new browser tab)', 'wordpress-seo' ) . '' + . '' + . '

    '; + } + /** * Adds a notification to be shown on the next page request since posts are updated in an ajax request. * - * @param string $post_type_label The singular_name label from a post_type_object. + * @param string $message The message to add to the notification. * * @return void */ - protected function add_notification( $post_type_label ) { + protected function add_notification( $message ) { $notification = new Yoast_Notification( - sprintf( - /* translators: %1$s expands to the translated name of the post type, %2$s expands to the anchor opening tag, %3$s to the anchor closing tag. */ - __( - 'You just changed the URL of this %1$s. To ensure your visitors do not see a 404 on the old URL, you should create a redirect. %2$sLearn how to create redirects here.%3$s', - 'wordpress-seo' - ), - $post_type_label, - '', - '' - ), array( 'type' => 'notice-info' ) + $message, + [ + 'type' => 'notice-warning is-dismissible', + 'yoast_branding' => true, + ] ); $notification_center = Yoast_Notification_Center::get(); diff --git a/wp-content/plugins/wordpress-seo/css/dist/admin-global-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/admin-global-1720-rtl.css new file mode 100644 index 00000000..29c7ff63 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/admin-global-1720-rtl.css @@ -0,0 +1 @@ +:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")}.yoast-tooltip{position:relative}button.yoast-tooltip{overflow:visible}.yoast-tooltip:after{display:none;position:absolute;z-index:1000000;padding:6px 8px 5px;border-radius:3px;opacity:0;color:#fff;background:rgba(0,0,0,.8);text-shadow:none;font:normal normal 11px/1.45454545 Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;text-align:center;white-space:pre;text-decoration:none;letter-spacing:normal;text-transform:none;word-wrap:break-word;content:attr(aria-label);pointer-events:none;-webkit-font-smoothing:subpixel-antialiased}.yoast-tooltip-alt:after{content:attr(data-label)}.yoast-tooltip:before{display:none;position:absolute;z-index:1000001;width:0;height:0;border:5px solid transparent;opacity:0;color:rgba(0,0,0,.8);content:"\00a0";pointer-events:none}@keyframes yoast-tooltip-appear{0%{opacity:0}to{opacity:1}}.yoast-tooltip:active:after,.yoast-tooltip:active:before,.yoast-tooltip:focus:after,.yoast-tooltip:focus:before,.yoast-tooltip:hover:after,.yoast-tooltip:hover:before{display:inline-block;text-decoration:none;animation-name:yoast-tooltip-appear;animation-duration:.1s;animation-timing-function:ease-in;animation-delay:.4s;animation-fill-mode:forwards}.yoast-tooltip-no-delay:active:after,.yoast-tooltip-no-delay:active:before,.yoast-tooltip-no-delay:focus:after,.yoast-tooltip-no-delay:focus:before,.yoast-tooltip-no-delay:hover:after,.yoast-tooltip-no-delay:hover:before{opacity:1;animation:none}.yoast-tooltip-multiline:active:after,.yoast-tooltip-multiline:focus:after,.yoast-tooltip-multiline:hover:after{display:table-cell}.yoast-tooltip-s:after,.yoast-tooltip-se:after,.yoast-tooltip-sw:after{top:100%;left:50%;margin-top:5px}.yoast-tooltip-s:before,.yoast-tooltip-se:before,.yoast-tooltip-sw:before{top:auto;left:50%;bottom:-5px;margin-left:-5px;border-bottom-color:rgba(0,0,0,.8)}.yoast-tooltip-se:after{left:auto;right:50%;margin-right:-15px}.yoast-tooltip-sw:after{margin-left:-15px}.yoast-tooltip-n:after,.yoast-tooltip-ne:after,.yoast-tooltip-nw:after{left:50%;bottom:100%;margin-bottom:5px}.yoast-tooltip-n:before,.yoast-tooltip-ne:before,.yoast-tooltip-nw:before{top:-5px;left:50%;bottom:auto;margin-left:-5px;border-top-color:rgba(0,0,0,.8)}.yoast-tooltip-ne:after{left:auto;right:50%;margin-right:-15px}.yoast-tooltip-nw:after{margin-left:-15px}.yoast-tooltip-n:after,.yoast-tooltip-s:after{transform:translateX(-50%)}.yoast-tooltip-w:after{left:100%;bottom:50%;margin-left:5px;transform:translateY(50%)}.yoast-tooltip-w:before{top:50%;bottom:50%;right:-5px;margin-top:-5px;border-right-color:rgba(0,0,0,.8)}.yoast-tooltip-e:after{bottom:50%;right:100%;margin-right:5px;transform:translateY(50%)}.yoast-tooltip-e:before{top:50%;left:-5px;bottom:50%;margin-top:-5px;border-left-color:rgba(0,0,0,.8)}.yoast-tooltip-multiline:after{width:250px;width:max-content;max-width:250px;border-collapse:initial;white-space:pre-line;word-wrap:normal;word-break:break-word}.yoast-tooltip-multiline.yoast-tooltip-n:after,.yoast-tooltip-multiline.yoast-tooltip-s:after{left:auto;right:50%;transform:translateX(50%)}.yoast-tooltip-multiline.yoast-tooltip-e:after,.yoast-tooltip-multiline.yoast-tooltip-w:after{left:100%}@media screen and (min-width:0\0){.yoast-tooltip-multiline:after{width:250px}}.yoast-tooltip-sticky:after,.yoast-tooltip-sticky:before{display:inline-block}.yoast-tooltip-sticky.yoast-tooltip-multiline:after{display:table-cell}@media only screen and (-moz-min-device-pixel-ratio:2),only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.yoast-tooltip-w:after{margin-left:4.5px}}.yoast-tooltip.yoast-tooltip-hidden:after,.yoast-tooltip.yoast-tooltip-hidden:before{display:none}.wpseo-premium-indicator{width:1px;height:1px;display:inline-block}#adminmenu .wpseo-premium-indicator{margin:-2px 2px -3px 0;color:inherit}.wpseo-premium-indicator svg{height:100%;width:auto;display:none}.yoast-measure{max-width:600px}.yoast-measure.padded{max-width:632px}#TB_window .wpseo_content_wrapper p{font-size:14px;font-style:normal}#TB_window .wpseo_content_wrapper label{margin:0 0 0 10px;font-size:14px;font-weight:600}.wpseo-premium-popup-title{margin:1em 0!important;padding:0!important;font-size:1.3em!important;font-weight:600!important}.wpseo-premium-popup-icon{margin:10px}.edit-tags-php .column-description img{max-width:100%;height:auto}.select2-container .select2-search--dropdown .select2-search__field{margin:0;padding:0 8px;min-height:30px}.select2-results__option,.select2-search--inline,.select2-selection__choice{margin-bottom:0}.select2-container .select2-search--inline .select2-search__field{margin-top:6px!important;line-height:inherit;min-height:0}.wpseo-admin-page .select2-container .select2-selection--single,.wpseo-metabox .select2-container .select2-selection--single{height:auto}.wpseo-admin-page .select2-container .select2-selection--single .select2-selection__arrow,.wpseo-metabox .select2-container .select2-selection--single .select2-selection__arrow{height:100%}.yoast-label-strong{font-weight:600}.yoast-video-container-max-width{max-width:560px}.yoast-video-container{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}.yoast-video-container iframe{position:absolute;top:0;right:0;width:100%;height:100%}.yoast-settings{margin-bottom:2em;padding-right:220px}.yoast-settings h2{margin-bottom:0;margin-right:-220px}.yoast-settings label{display:inline-block;width:200px;padding-top:4px;padding-left:10px;margin-left:6px;margin-right:-220px;font-size:14px;line-height:1.3;font-weight:600;color:#23282d;vertical-align:top}.yoast-settings fieldset,.yoast-settings input[type=text],.yoast-settings label,.yoast-settings select,.yoast-settings textarea,.yoast .yoast-settings__checkbox,.yoast .yoast-settings__radio{margin-top:2em;margin-bottom:.5em}.yoast-settings__textarea--medium{width:100%;max-width:600px}.yoast .yoast-settings__checkbox,.yoast .yoast-settings__radio{vertical-align:top;position:relative;top:1px}.yoast-settings__group--checkbox,.yoast-settings__group--radio{padding-top:1em}.yoast-settings__group--checkbox .yoast-settings__checkbox,.yoast-settings__group--radio .yoast-settings__radio{margin:0 0 10px 4px}.yoast-settings__checkbox+label,.yoast-settings__radio+label{width:auto;margin-right:0;margin-left:0;padding:0;max-width:calc(100% - 25px)}.yoast-settings__group--checkbox .yoast-settings__checkbox+label,.yoast-settings__group--radio .yoast-settings__radio+label{margin-top:0;margin-bottom:10px;font-weight:400}.yoast-settings legend{font-size:14px;font-weight:600;color:#23282d}.yoast-settings .description{margin-top:0;font-size:14px}td .wpseo-score-icon{display:inline-block;width:12px;height:12px;margin-right:5px;border-radius:50%;background:#888;line-height:16px;margin-top:3px}.fixed th.column-wpseo-linked,.fixed th.column-wpseo-links,.fixed th.column-wpseo-score,.fixed th.column-wpseo-score-readability{width:3em;padding:0}th.column-wpseo-linked a,th.column-wpseo-links a,th.column-wpseo-score-readability .yoast-tooltip,th.column-wpseo-score .yoast-tooltip{overflow:visible;display:inline-block;vertical-align:middle;padding:8px 0}th.column-wpseo-score-readability .yoast-tooltip,th.column-wpseo-score .yoast-tooltip{padding:8px 11px}.column-wpseo-links .yoast-tooltip-multiline:after{max-width:160px}.column-wpseo-linked .yoast-tooltip-multiline:after{max-width:170px}.yoast-column-header-has-tooltip{position:relative}.manage-column .yoast-column-header-has-tooltip:before{content:"";display:inline-block;width:20px;height:20px;padding:0;vertical-align:top;text-decoration:none!important;color:#444}.manage-column .yoast-linked-to:before{background:transparent url(../../images/link-out-icon.svg) no-repeat 100% 0;background-size:20px}.manage-column .yoast-linked-from:before{background:transparent url(../../images/link-in-icon.svg) no-repeat 100% 0;background-size:20px}.manage-column .yoast-column-seo-score:before{background:transparent url(../../images/Yoast_SEO_negative_icon.svg) no-repeat 100% 0;background-size:20px}.manage-column .yoast-column-readability:before{background:transparent url(../../images/readability-icon.svg) no-repeat 100% 0;background-size:20px}td.column-wpseo-linked,td.column-wpseo-links{word-wrap:normal}@media screen and (max-width:782px){.yoast-settings{padding-right:0}.yoast-settings h2{margin-right:0}.yoast-settings label{width:auto;padding:0;margin-left:0;margin-right:0}.yoast-settings__radio+label,.yoast .yoast-settings__radio{margin-bottom:1em}.yoast-settings__checkbox+label,.yoast-settings__radio+label{max-width:calc(100% - 35px);padding-top:8px}.yoast-settings__group--checkbox .yoast-settings__checkbox+label,.yoast-settings__group--radio .yoast-settings__radio+label{padding-top:4px}.yoast-settings input[type=text],.yoast-settings select,.yoast-settings textarea{display:block;width:100%;margin-top:0;margin-bottom:0;padding:7px 10px;max-width:none;line-height:1.5;box-sizing:border-box}.screen-reader-text.wpseo-score-text{position:static!important;-webkit-clip-path:none;clip-path:none;width:auto;height:auto;margin:0}}.react-tabs__tab-panel{max-width:900px;margin:0 auto}.react-tabs__tab-panel li{max-width:none!important}.contact-premium-support{text-align:center}.contact-premium-support__content{margin:0 auto 1.5em;font-size:.9375rem;line-height:1.4}.contact-premium-support__content:nth-child(2){max-width:610px}.contact-premium-support__content:nth-child(3){max-width:560px}.contact-premium-support .contact-premium-support__button{margin-bottom:48px}.wpseo-premium-description{margin-top:.5em}.wpseo-premium-advantages-list{list-style:disc;padding-right:1.5em}.yoast_help.yoast-help-button,.yoast_help.yoast-help-link{position:relative;width:20px;height:20px;margin:0;padding:0;border:0;outline:none;color:#72777c;background:transparent;box-shadow:none;vertical-align:top;cursor:pointer}.yoast-section .yoast_help.yoast-help-button{float:left}.help-button-inline .yoast_help.yoast-help-button{margin-top:-4px}.yoast-section .yoast_help.yoast-help-button{margin-top:-44px}.wpseo-admin-page .yoast_help.yoast-help-button{margin-left:6px}.yoast_help .yoast-help-icon:before{position:absolute;top:0;right:0;padding:4px;content:"\f223"}.yoast_help.yoast-help-button:focus,.yoast_help.yoast-help-button:hover,.yoast_help.yoast-help-link:hover{color:#0073aa}.assessment-results__mark:focus,.yoast_help.yoast-help-button:focus .yoast-help-icon:before,.yoast_help.yoast-help-link:focus .yoast-help-icon:before{border-radius:100%;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.yoast-help-panel{display:none;clear:both;max-width:30em!important;padding:0 0 1em;font-weight:400;white-space:normal}.wpseo-admin-page .yoast-help-panel{max-width:600px!important}.copy-home-meta-description{margin-top:1em}.copy-home-meta-description .yoast-help-panel{max-width:400px!important}.yoast-modal_is-open{overflow:hidden}.yoast-notification .yoast-seo-icon{float:right;margin:20px 10px}.yoast-notification .yoast-seo-icon-wrap{margin:0 85px 0 0}.yoast-button-upsell{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-height:48px;padding:8px 1em;font-size:16px;line-height:1.5;font-family:Arial,sans-serif;color:#000;border-radius:4px;box-shadow:inset 0 -4px 0 rgba(0,0,0,.2);filter:drop-shadow(0 2px 4px rgba(0,0,0,.2));text-decoration:none;background-color:#fec228}.yoast-button-upsell:active,.yoast-button-upsell:focus,.yoast-button-upsell:hover{color:#000;background-color:#f2ae01}.yoast-button-upsell:focus{box-shadow:inset 0 -4px 0 rgba(0,0,0,.2),0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.yoast-button-upsell:active{transform:translateY(1px);box-shadow:none;filter:none}.yoast-button-upsell#wpseo-premium-button{color:#000}.yoast-button-upsell__caret{flex-shrink:0;width:8px;height:16px;margin:0 6px 0 -2px;background:transparent var(--yoast-svg-icon-caret-right) 50% no-repeat}.rtl .yoast-button-upsell__caret{background-image:var(--yoast-svg-icon-caret-left)}body.folded .wpseo-admin-submit-fixed{right:36px}@media screen and (max-width:782px){body.folded .wpseo-admin-submit-fixed{right:0}}.wpseo-admin-submit{z-index:5;display:flex;padding:16px 0;justify-content:flex-start;align-items:baseline;margin:0}.wpseo-admin-submit.wpseo-admin-submit-fixed{padding:16px;position:fixed;bottom:0;right:160px;left:281px;background-color:#fff;max-width:800px;box-shadow:0 1px 8px 1px rgba(0,0,0,.5);margin:0 16px}@media screen and (max-width:1024px){.wpseo-admin-submit.wpseo-admin-submit-fixed{left:0}}@media only screen and (max-width:960px){.wpseo-admin-submit.wpseo-admin-submit-fixed{right:36px}}@media screen and (max-width:782px){.wpseo-admin-submit.wpseo-admin-submit-fixed{right:0;margin:0}}.wpseo-admin-submit p.submit{padding:0;margin:0}.wpseo-admin-submit p.wpseo-message{margin:0 0 0 16px;padding:0;color:#008a00}.yoast-site-health__signature{display:flex;font-size:12px;line-height:20px;margin-top:2em;color:#707070}.yoast-site-health__inline-button.fetch-status,.yoast-site-health__signature-icon{margin-left:8px}#wpadminbar .yoast-badge,.yoast-badge{display:inline-block;padding:0 8px;border-radius:8px;font-weight:600;line-height:1.6}.yoast-badge{min-height:16px;font-size:10px}#wpadminbar .yoast-badge,.wp-submenu .yoast-badge{min-height:14px;font-size:9px}.yoast-new-badge{background-color:#cce5ff;color:#004973}.yoast-premium-badge{background-color:#fff3cd;color:#674e00}.yoast-badge__is-link{text-decoration:none}.yoast-badge__is-link:focus,.yoast-badge__is-link:hover{background-color:#004973;color:#fff;outline:none;box-shadow:none}.switch-container .yoast-badge{vertical-align:-1em}.switch-container legend .yoast-badge{vertical-align:0}.yoast_help+.yoast-badge{vertical-align:bottom} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/admin-global-1720.css b/wp-content/plugins/wordpress-seo/css/dist/admin-global-1720.css new file mode 100644 index 00000000..fa41037c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/admin-global-1720.css @@ -0,0 +1 @@ +:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")}.yoast-tooltip{position:relative}button.yoast-tooltip{overflow:visible}.yoast-tooltip:after{display:none;position:absolute;z-index:1000000;padding:6px 8px 5px;border-radius:3px;opacity:0;color:#fff;background:rgba(0,0,0,.8);text-shadow:none;font:normal normal 11px/1.45454545 Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;text-align:center;white-space:pre;text-decoration:none;letter-spacing:normal;text-transform:none;word-wrap:break-word;content:attr(aria-label);pointer-events:none;-webkit-font-smoothing:subpixel-antialiased}.yoast-tooltip-alt:after{content:attr(data-label)}.yoast-tooltip:before{display:none;position:absolute;z-index:1000001;width:0;height:0;border:5px solid transparent;opacity:0;color:rgba(0,0,0,.8);content:"\00a0";pointer-events:none}@keyframes yoast-tooltip-appear{0%{opacity:0}to{opacity:1}}.yoast-tooltip:active:after,.yoast-tooltip:active:before,.yoast-tooltip:focus:after,.yoast-tooltip:focus:before,.yoast-tooltip:hover:after,.yoast-tooltip:hover:before{display:inline-block;text-decoration:none;animation-name:yoast-tooltip-appear;animation-duration:.1s;animation-timing-function:ease-in;animation-delay:.4s;animation-fill-mode:forwards}.yoast-tooltip-no-delay:active:after,.yoast-tooltip-no-delay:active:before,.yoast-tooltip-no-delay:focus:after,.yoast-tooltip-no-delay:focus:before,.yoast-tooltip-no-delay:hover:after,.yoast-tooltip-no-delay:hover:before{opacity:1;animation:none}.yoast-tooltip-multiline:active:after,.yoast-tooltip-multiline:focus:after,.yoast-tooltip-multiline:hover:after{display:table-cell}.yoast-tooltip-s:after,.yoast-tooltip-se:after,.yoast-tooltip-sw:after{top:100%;right:50%;margin-top:5px}.yoast-tooltip-s:before,.yoast-tooltip-se:before,.yoast-tooltip-sw:before{top:auto;right:50%;bottom:-5px;margin-right:-5px;border-bottom-color:rgba(0,0,0,.8)}.yoast-tooltip-se:after{right:auto;left:50%;margin-left:-15px}.yoast-tooltip-sw:after{margin-right:-15px}.yoast-tooltip-n:after,.yoast-tooltip-ne:after,.yoast-tooltip-nw:after{right:50%;bottom:100%;margin-bottom:5px}.yoast-tooltip-n:before,.yoast-tooltip-ne:before,.yoast-tooltip-nw:before{top:-5px;right:50%;bottom:auto;margin-right:-5px;border-top-color:rgba(0,0,0,.8)}.yoast-tooltip-ne:after{right:auto;left:50%;margin-left:-15px}.yoast-tooltip-nw:after{margin-right:-15px}.yoast-tooltip-n:after,.yoast-tooltip-s:after{transform:translateX(50%)}.yoast-tooltip-w:after{right:100%;bottom:50%;margin-right:5px;transform:translateY(50%)}.yoast-tooltip-w:before{top:50%;bottom:50%;left:-5px;margin-top:-5px;border-left-color:rgba(0,0,0,.8)}.yoast-tooltip-e:after{bottom:50%;left:100%;margin-left:5px;transform:translateY(50%)}.yoast-tooltip-e:before{top:50%;right:-5px;bottom:50%;margin-top:-5px;border-right-color:rgba(0,0,0,.8)}.yoast-tooltip-multiline:after{width:250px;width:max-content;max-width:250px;border-collapse:initial;white-space:pre-line;word-wrap:normal;word-break:break-word}.yoast-tooltip-multiline.yoast-tooltip-n:after,.yoast-tooltip-multiline.yoast-tooltip-s:after{right:auto;left:50%;transform:translateX(-50%)}.yoast-tooltip-multiline.yoast-tooltip-e:after,.yoast-tooltip-multiline.yoast-tooltip-w:after{right:100%}@media screen and (min-width:0\0){.yoast-tooltip-multiline:after{width:250px}}.yoast-tooltip-sticky:after,.yoast-tooltip-sticky:before{display:inline-block}.yoast-tooltip-sticky.yoast-tooltip-multiline:after{display:table-cell}@media only screen and (-moz-min-device-pixel-ratio:2),only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:2dppx),only screen and (min-resolution:192dpi){.yoast-tooltip-w:after{margin-right:4.5px}}.yoast-tooltip.yoast-tooltip-hidden:after,.yoast-tooltip.yoast-tooltip-hidden:before{display:none}.wpseo-premium-indicator{width:1px;height:1px;display:inline-block}#adminmenu .wpseo-premium-indicator{margin:-2px 0 -3px 2px;color:inherit}.wpseo-premium-indicator svg{height:100%;width:auto;display:none}.yoast-measure{max-width:600px}.yoast-measure.padded{max-width:632px}#TB_window .wpseo_content_wrapper p{font-size:14px;font-style:normal}#TB_window .wpseo_content_wrapper label{margin:0 10px 0 0;font-size:14px;font-weight:600}.wpseo-premium-popup-title{margin:1em 0!important;padding:0!important;font-size:1.3em!important;font-weight:600!important}.wpseo-premium-popup-icon{margin:10px}.edit-tags-php .column-description img{max-width:100%;height:auto}.select2-container .select2-search--dropdown .select2-search__field{margin:0;padding:0 8px;min-height:30px}.select2-results__option,.select2-search--inline,.select2-selection__choice{margin-bottom:0}.select2-container .select2-search--inline .select2-search__field{margin-top:6px!important;line-height:inherit;min-height:0}.wpseo-admin-page .select2-container .select2-selection--single,.wpseo-metabox .select2-container .select2-selection--single{height:auto}.wpseo-admin-page .select2-container .select2-selection--single .select2-selection__arrow,.wpseo-metabox .select2-container .select2-selection--single .select2-selection__arrow{height:100%}.yoast-label-strong{font-weight:600}.yoast-video-container-max-width{max-width:560px}.yoast-video-container{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}.yoast-video-container iframe{position:absolute;top:0;left:0;width:100%;height:100%}.yoast-settings{margin-bottom:2em;padding-left:220px}.yoast-settings h2{margin-bottom:0;margin-left:-220px}.yoast-settings label{display:inline-block;width:200px;padding-top:4px;padding-right:10px;margin-right:6px;margin-left:-220px;font-size:14px;line-height:1.3;font-weight:600;color:#23282d;vertical-align:top}.yoast-settings fieldset,.yoast-settings input[type=text],.yoast-settings label,.yoast-settings select,.yoast-settings textarea,.yoast .yoast-settings__checkbox,.yoast .yoast-settings__radio{margin-top:2em;margin-bottom:.5em}.yoast-settings__textarea--medium{width:100%;max-width:600px}.yoast .yoast-settings__checkbox,.yoast .yoast-settings__radio{vertical-align:top;position:relative;top:1px}.yoast-settings__group--checkbox,.yoast-settings__group--radio{padding-top:1em}.yoast-settings__group--checkbox .yoast-settings__checkbox,.yoast-settings__group--radio .yoast-settings__radio{margin:0 4px 10px 0}.yoast-settings__checkbox+label,.yoast-settings__radio+label{width:auto;margin-left:0;margin-right:0;padding:0;max-width:calc(100% - 25px)}.yoast-settings__group--checkbox .yoast-settings__checkbox+label,.yoast-settings__group--radio .yoast-settings__radio+label{margin-top:0;margin-bottom:10px;font-weight:400}.yoast-settings legend{font-size:14px;font-weight:600;color:#23282d}.yoast-settings .description{margin-top:0;font-size:14px}td .wpseo-score-icon{display:inline-block;width:12px;height:12px;margin-left:5px;border-radius:50%;background:#888;line-height:16px;margin-top:3px}.fixed th.column-wpseo-linked,.fixed th.column-wpseo-links,.fixed th.column-wpseo-score,.fixed th.column-wpseo-score-readability{width:3em;padding:0}th.column-wpseo-linked a,th.column-wpseo-links a,th.column-wpseo-score-readability .yoast-tooltip,th.column-wpseo-score .yoast-tooltip{overflow:visible;display:inline-block;vertical-align:middle;padding:8px 0}th.column-wpseo-score-readability .yoast-tooltip,th.column-wpseo-score .yoast-tooltip{padding:8px 11px}.column-wpseo-links .yoast-tooltip-multiline:after{max-width:160px}.column-wpseo-linked .yoast-tooltip-multiline:after{max-width:170px}.yoast-column-header-has-tooltip{position:relative}.manage-column .yoast-column-header-has-tooltip:before{content:"";display:inline-block;width:20px;height:20px;padding:0;vertical-align:top;text-decoration:none!important;color:#444}.manage-column .yoast-linked-to:before{background:transparent url(../../images/link-out-icon.svg) no-repeat 0 0;background-size:20px}.manage-column .yoast-linked-from:before{background:transparent url(../../images/link-in-icon.svg) no-repeat 0 0;background-size:20px}.manage-column .yoast-column-seo-score:before{background:transparent url(../../images/Yoast_SEO_negative_icon.svg) no-repeat 0 0;background-size:20px}.manage-column .yoast-column-readability:before{background:transparent url(../../images/readability-icon.svg) no-repeat 0 0;background-size:20px}td.column-wpseo-linked,td.column-wpseo-links{word-wrap:normal}@media screen and (max-width:782px){.yoast-settings{padding-left:0}.yoast-settings h2{margin-left:0}.yoast-settings label{width:auto;padding:0;margin-right:0;margin-left:0}.yoast-settings__radio+label,.yoast .yoast-settings__radio{margin-bottom:1em}.yoast-settings__checkbox+label,.yoast-settings__radio+label{max-width:calc(100% - 35px);padding-top:8px}.yoast-settings__group--checkbox .yoast-settings__checkbox+label,.yoast-settings__group--radio .yoast-settings__radio+label{padding-top:4px}.yoast-settings input[type=text],.yoast-settings select,.yoast-settings textarea{display:block;width:100%;margin-top:0;margin-bottom:0;padding:7px 10px;max-width:none;line-height:1.5;box-sizing:border-box}.screen-reader-text.wpseo-score-text{position:static!important;-webkit-clip-path:none;clip-path:none;width:auto;height:auto;margin:0}}.react-tabs__tab-panel{max-width:900px;margin:0 auto}.react-tabs__tab-panel li{max-width:none!important}.contact-premium-support{text-align:center}.contact-premium-support__content{margin:0 auto 1.5em;font-size:.9375rem;line-height:1.4}.contact-premium-support__content:nth-child(2){max-width:610px}.contact-premium-support__content:nth-child(3){max-width:560px}.contact-premium-support .contact-premium-support__button{margin-bottom:48px}.wpseo-premium-description{margin-top:.5em}.wpseo-premium-advantages-list{list-style:disc;padding-left:1.5em}.yoast_help.yoast-help-button,.yoast_help.yoast-help-link{position:relative;width:20px;height:20px;margin:0;padding:0;border:0;outline:none;color:#72777c;background:transparent;box-shadow:none;vertical-align:top;cursor:pointer}.yoast-section .yoast_help.yoast-help-button{float:right}.help-button-inline .yoast_help.yoast-help-button{margin-top:-4px}.yoast-section .yoast_help.yoast-help-button{margin-top:-44px}.wpseo-admin-page .yoast_help.yoast-help-button{margin-right:6px}.yoast_help .yoast-help-icon:before{position:absolute;top:0;left:0;padding:4px;content:"\f223"}.yoast_help.yoast-help-button:focus,.yoast_help.yoast-help-button:hover,.yoast_help.yoast-help-link:hover{color:#0073aa}.assessment-results__mark:focus,.yoast_help.yoast-help-button:focus .yoast-help-icon:before,.yoast_help.yoast-help-link:focus .yoast-help-icon:before{border-radius:100%;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.yoast-help-panel{display:none;clear:both;max-width:30em!important;padding:0 0 1em;font-weight:400;white-space:normal}.wpseo-admin-page .yoast-help-panel{max-width:600px!important}.copy-home-meta-description{margin-top:1em}.copy-home-meta-description .yoast-help-panel{max-width:400px!important}.yoast-modal_is-open{overflow:hidden}.yoast-notification .yoast-seo-icon{float:left;margin:20px 10px}.yoast-notification .yoast-seo-icon-wrap{margin:0 0 0 85px}.yoast-button-upsell{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-height:48px;padding:8px 1em;font-size:16px;line-height:1.5;font-family:Arial,sans-serif;color:#000;border-radius:4px;box-shadow:inset 0 -4px 0 rgba(0,0,0,.2);filter:drop-shadow(0 2px 4px rgba(0,0,0,.2));text-decoration:none;background-color:#fec228}.yoast-button-upsell:active,.yoast-button-upsell:focus,.yoast-button-upsell:hover{color:#000;background-color:#f2ae01}.yoast-button-upsell:focus{box-shadow:inset 0 -4px 0 rgba(0,0,0,.2),0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.yoast-button-upsell:active{transform:translateY(1px);box-shadow:none;filter:none}.yoast-button-upsell#wpseo-premium-button{color:#000}.yoast-button-upsell__caret{flex-shrink:0;width:8px;height:16px;margin:0 -2px 0 6px;background:transparent var(--yoast-svg-icon-caret-right) 50% no-repeat}.rtl .yoast-button-upsell__caret{background-image:var(--yoast-svg-icon-caret-left)}body.folded .wpseo-admin-submit-fixed{left:36px}@media screen and (max-width:782px){body.folded .wpseo-admin-submit-fixed{left:0}}.wpseo-admin-submit{z-index:5;display:flex;padding:16px 0;justify-content:flex-start;align-items:baseline;margin:0}.wpseo-admin-submit.wpseo-admin-submit-fixed{padding:16px;position:fixed;bottom:0;left:160px;right:281px;background-color:#fff;max-width:800px;box-shadow:0 1px 8px 1px rgba(0,0,0,.5);margin:0 16px}@media screen and (max-width:1024px){.wpseo-admin-submit.wpseo-admin-submit-fixed{right:0}}@media only screen and (max-width:960px){.wpseo-admin-submit.wpseo-admin-submit-fixed{left:36px}}@media screen and (max-width:782px){.wpseo-admin-submit.wpseo-admin-submit-fixed{left:0;margin:0}}.wpseo-admin-submit p.submit{padding:0;margin:0}.wpseo-admin-submit p.wpseo-message{margin:0 16px 0 0;padding:0;color:#008a00}.yoast-site-health__signature{display:flex;font-size:12px;line-height:20px;margin-top:2em;color:#707070}.yoast-site-health__inline-button.fetch-status,.yoast-site-health__signature-icon{margin-right:8px}#wpadminbar .yoast-badge,.yoast-badge{display:inline-block;padding:0 8px;border-radius:8px;font-weight:600;line-height:1.6}.yoast-badge{min-height:16px;font-size:10px}#wpadminbar .yoast-badge,.wp-submenu .yoast-badge{min-height:14px;font-size:9px}.yoast-new-badge{background-color:#cce5ff;color:#004973}.yoast-premium-badge{background-color:#fff3cd;color:#674e00}.yoast-badge__is-link{text-decoration:none}.yoast-badge__is-link:focus,.yoast-badge__is-link:hover{background-color:#004973;color:#fff;outline:none;box-shadow:none}.switch-container .yoast-badge{vertical-align:-1em}.switch-container legend .yoast-badge{vertical-align:0}.yoast_help+.yoast-badge{vertical-align:bottom} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/admin-global-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/admin-global-720-rtl.min.css deleted file mode 100644 index 160311b0..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/admin-global-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -.wpseo-premium-indicator{display:inline-block;width:1px;height:1px}#adminmenu .wpseo-premium-indicator{margin:-2px 2px -3px 0;color:inherit}.wpseo-premium-indicator svg{display:none;width:auto;height:100%}.yoast-tooltip{position:relative}.yoast-tooltip::after,.yoast-tooltip::before{display:none;position:absolute;opacity:0;pointer-events:none}button.yoast-tooltip{overflow:visible}.yoast-tooltip::after{z-index:1000000;padding:6px 8px 5px;border-radius:3px;color:#fff;background:rgba(0,0,0,.8);text-shadow:none;font:normal normal 11px/1.45454545 Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";text-align:center;white-space:pre;text-decoration:none;letter-spacing:normal;text-transform:none;word-wrap:break-word;content:attr(aria-label);-webkit-font-smoothing:subpixel-antialiased}.yoast-tooltip-alt::after{content:attr(data-label)}.yoast-tooltip::before{z-index:1000001;width:0;height:0;border:5px solid transparent;color:rgba(0,0,0,.8);content:"\00a0"}@keyframes yoast-tooltip-appear{from{opacity:0}to{opacity:1}}.yoast-tooltip:active::after,.yoast-tooltip:active::before,.yoast-tooltip:focus::after,.yoast-tooltip:focus::before,.yoast-tooltip:hover::after,.yoast-tooltip:hover::before{display:inline-block;text-decoration:none;animation-name:yoast-tooltip-appear;animation-duration:.1s;animation-timing-function:ease-in;animation-delay:.4s;animation-fill-mode:forwards}.yoast-tooltip-no-delay:active::after,.yoast-tooltip-no-delay:active::before,.yoast-tooltip-no-delay:focus::after,.yoast-tooltip-no-delay:focus::before,.yoast-tooltip-no-delay:hover::after,.yoast-tooltip-no-delay:hover::before{opacity:1;animation:none}.yoast-tooltip-multiline:active::after,.yoast-tooltip-multiline:focus::after,.yoast-tooltip-multiline:hover::after{display:table-cell}.yoast-tooltip-s::after,.yoast-tooltip-se::after,.yoast-tooltip-sw::after{top:100%;left:50%;margin-top:5px}.yoast-tooltip-s::before,.yoast-tooltip-se::before,.yoast-tooltip-sw::before{top:auto;left:50%;bottom:-5px;margin-left:-5px;border-bottom-color:rgba(0,0,0,.8)}.yoast-tooltip-se::after{left:auto;right:50%;margin-right:-15px}.yoast-tooltip-sw::after{margin-left:-15px}.yoast-tooltip-n::after,.yoast-tooltip-ne::after,.yoast-tooltip-nw::after{left:50%;bottom:100%;margin-bottom:5px}.yoast-tooltip-n::before,.yoast-tooltip-ne::before,.yoast-tooltip-nw::before{top:-5px;left:50%;bottom:auto;margin-left:-5px;border-top-color:rgba(0,0,0,.8)}.yoast-tooltip-ne::after{left:auto;right:50%;margin-right:-15px}.yoast-tooltip-nw::after{margin-left:-15px}.yoast-tooltip-n::after,.yoast-tooltip-s::after{-ms-transform:translateX(-50%);transform:translateX(-50%)}.yoast-tooltip-w::after{left:100%;bottom:50%;margin-left:5px;-ms-transform:translateY(50%);transform:translateY(50%)}.yoast-tooltip-w::before{top:50%;bottom:50%;right:-5px;margin-top:-5px;border-right-color:rgba(0,0,0,.8)}.yoast-tooltip-e::after{bottom:50%;right:100%;margin-right:5px;-ms-transform:translateY(50%);transform:translateY(50%)}.yoast-tooltip-e::before{top:50%;left:-5px;bottom:50%;margin-top:-5px;border-left-color:rgba(0,0,0,.8)}.yoast-tooltip-multiline::after{width:250px;width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:250px;border-collapse:separate;white-space:pre-line;word-wrap:normal;word-break:break-word}.yoast-tooltip-multiline.yoast-tooltip-n::after,.yoast-tooltip-multiline.yoast-tooltip-s::after{left:auto;right:50%;-ms-transform:translateX(50%);transform:translateX(50%)}.yoast-tooltip-multiline.yoast-tooltip-e::after,.yoast-tooltip-multiline.yoast-tooltip-w::after{left:100%}@media screen and (min-width:0\0){.yoast-tooltip-multiline::after{width:250px}}.yoast-tooltip-sticky::after,.yoast-tooltip-sticky::before{display:inline-block}.yoast-tooltip-sticky.yoast-tooltip-multiline::after{display:table-cell}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (-moz-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:192dpi),only screen and (min-resolution:2dppx){.yoast-tooltip-w::after{margin-left:4.5px}}.yoast-tooltip.yoast-tooltip-hidden::after,.yoast-tooltip.yoast-tooltip-hidden::before{display:none}.yoast-measure{max-width:600px}#TB_window .wpseo_content_wrapper p{font-size:14px;font-style:normal}#TB_window .wpseo_content_wrapper label{margin:0 0 0 10px;font-size:14px;font-weight:600}.wpseo-premium-popup-title{margin:1em 0!important;padding:0!important;font-size:1.3em!important;font-weight:600!important}.wpseo-premium-popup-icon{margin:10px}.edit-tags-php .column-description img{max-width:100%;height:auto}.select2-search__field{margin:0}.select2-results__option,.select2-search--inline,.select2-selection__choice{margin-bottom:0}.select2-container .select2-search--inline .select2-search__field{margin-top:6px!important;line-height:inherit}.yoast-label-strong{font-weight:600}.yoast-video-container-max-width{max-width:560px}.yoast-video-container{overflow:hidden;position:relative;height:0;padding-bottom:56.25%}.yoast-video-container iframe{position:absolute;top:0;right:0;width:100%;height:100%}.yoast-settings{margin-bottom:2em;padding-right:220px}.yoast-settings h2{margin-bottom:0;margin-right:-220px}.yoast-settings label{display:inline-block;width:200px;margin-left:6px;margin-right:-220px;padding-top:4px;padding-left:10px;color:#23282d;font-size:14px;font-weight:600;line-height:1.3;vertical-align:top}.yoast .yoast-settings__checkbox,.yoast .yoast-settings__radio,.yoast-settings fieldset,.yoast-settings input[type=text],.yoast-settings label,.yoast-settings select,.yoast-settings textarea{margin-top:2em;margin-bottom:.5em}.yoast-settings__textarea--medium{width:100%;max-width:600px}.yoast .yoast-settings__checkbox,.yoast .yoast-settings__radio{position:relative;top:1px;vertical-align:top}.yoast-settings__group--checkbox,.yoast-settings__group--radio{padding-top:1em}.yoast-settings__group--checkbox .yoast-settings__checkbox,.yoast-settings__group--radio .yoast-settings__radio{margin:0 0 10px 4px}.yoast-settings__checkbox+label,.yoast-settings__radio+label{width:auto;max-width:calc(100% - 25px);margin-left:0;margin-right:0;padding:0}.yoast-settings__group--checkbox .yoast-settings__checkbox+label,.yoast-settings__group--radio .yoast-settings__radio+label{margin-top:0;margin-bottom:10px;font-weight:400}.yoast-settings legend{color:#23282d;font-size:14px;font-weight:600}.yoast-settings .description{margin-top:0;font-size:14px}td .wpseo-score-icon{display:inline-block;width:12px;height:12px;margin-right:5px;border-radius:50%;background:#888;line-height:16px;margin-top:3px}.fixed th.column-wpseo-linked,.fixed th.column-wpseo-links,.fixed th.column-wpseo-score,.fixed th.column-wpseo-score-readability{width:3em;padding:0}th.column-wpseo-linked a,th.column-wpseo-links a,th.column-wpseo-score .yoast-tooltip,th.column-wpseo-score-readability .yoast-tooltip{display:inline-block;overflow:visible;padding:8px 0;vertical-align:middle}th.column-wpseo-score .yoast-tooltip,th.column-wpseo-score-readability .yoast-tooltip{padding:8px 11px}.column-wpseo-links .yoast-tooltip-multiline::after{width:999px;max-width:160px}.column-wpseo-linked .yoast-tooltip-multiline::after{width:999px;max-width:170px}.yoast-column-header-has-tooltip{position:relative}.manage-column .yoast-column-header-has-tooltip:before{display:inline-block;width:20px;height:20px;padding:0;color:#444;vertical-align:top;text-decoration:none!important;content:""}.manage-column .yoast-linked-to:before{background:url(../../images/link-out-icon.svg) 100% 0 no-repeat;background-size:20px}.manage-column .yoast-linked-from:before{background:url(../../images/link-in-icon.svg) 100% 0 no-repeat;background-size:20px}.manage-column .yoast-column-seo-score:before{background:url(../../images/Yoast_SEO_negative_icon.svg) 100% 0 no-repeat;background-size:20px}.manage-column .yoast-column-readability:before{background:url(../../images/readability-icon.svg) 100% 0 no-repeat;background-size:20px}td.column-wpseo-linked,td.column-wpseo-links{word-wrap:normal}#screen-meta .yoast-column-header-has-tooltip .screen-reader-text{visibility:visible;position:static;width:auto;height:auto}@media screen and (max-width:782px){.yoast-settings{padding-right:0}.yoast-settings h2{margin-right:0}.yoast-settings label{width:auto;margin-left:0;margin-right:0;padding:0}.yoast .yoast-settings__radio,.yoast-settings__radio+label{margin-bottom:1em}.yoast-settings__checkbox+label,.yoast-settings__radio+label{max-width:calc(100% - 35px);padding-top:8px}.yoast-settings__group--checkbox .yoast-settings__checkbox+label,.yoast-settings__group--radio .yoast-settings__radio+label{padding-top:4px}.yoast-settings input[type=text],.yoast-settings select,.yoast-settings textarea{display:block;box-sizing:border-box;width:100%;max-width:none;margin-top:0;margin-bottom:0;padding:7px 10px;line-height:1.5}}#yoast-help-center-container{margin:16px 0 24px}.react-tabs__tab-panel{max-width:900px;margin:0 auto}.react-tabs__tab-panel li{max-width:none!important}.yoast-help-center-open #sidebar-container{display:none}.contact-premium-support{text-align:center}.contact-premium-support__content{margin:0 auto 1.5em;font-size:.9375rem;line-height:1.4}.contact-premium-support__content:nth-child(2){max-width:610px}.contact-premium-support__content:nth-child(3){max-width:560px}.contact-premium-support .contact-premium-support__button{margin-bottom:48px}.wpseo-premium-description{margin-top:.5em}.wpseo-premium-advantages-list{padding-right:1.5em;list-style:disc}.yoast_help.yoast-help-button{overflow:visible;position:relative;width:20px;height:20px;margin:0;padding:0;border:0;outline:0;color:#72777c;background:0 0;box-shadow:none;vertical-align:top;cursor:pointer}.help-button-inline .yoast_help.yoast-help-button{margin-top:-4px}.yoast-section .yoast_help.yoast-help-button{float:left;margin-top:-44px}.wpseo-admin-page .yoast_help.yoast-help-button{margin-left:6px}.yoast_help .yoast-help-icon::before{position:absolute;top:0;right:0;padding:4px;content:"\f223"}.yoast_help.yoast-help-button:focus,.yoast_help.yoast-help-button:hover{color:#0073aa}.assessment-results__mark:focus,.yoast_help.yoast-help-button:focus .yoast-help-icon::before{border-radius:100%;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.yoast-help-panel{display:none;clear:both;max-width:30em!important;padding:0 0 1em;font-weight:400;white-space:normal}.wpseo-admin-page .yoast-help-panel{max-width:600px!important}.copy-home-meta-description .yoast-help-panel{max-width:400px!important} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/admin-global-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/admin-global-720.min.css deleted file mode 100644 index 4d353831..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/admin-global-720.min.css +++ /dev/null @@ -1 +0,0 @@ -.wpseo-premium-indicator{display:inline-block;width:1px;height:1px}#adminmenu .wpseo-premium-indicator{margin:-2px 0 -3px 2px;color:inherit}.wpseo-premium-indicator svg{display:none;width:auto;height:100%}.yoast-tooltip{position:relative}.yoast-tooltip::after,.yoast-tooltip::before{display:none;position:absolute;opacity:0;pointer-events:none}button.yoast-tooltip{overflow:visible}.yoast-tooltip::after{z-index:1000000;padding:6px 8px 5px;border-radius:3px;color:#fff;background:rgba(0,0,0,.8);text-shadow:none;font:normal normal 11px/1.45454545 Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";text-align:center;white-space:pre;text-decoration:none;letter-spacing:normal;text-transform:none;word-wrap:break-word;content:attr(aria-label);-webkit-font-smoothing:subpixel-antialiased}.yoast-tooltip-alt::after{content:attr(data-label)}.yoast-tooltip::before{z-index:1000001;width:0;height:0;border:5px solid transparent;color:rgba(0,0,0,.8);content:"\00a0"}@keyframes yoast-tooltip-appear{from{opacity:0}to{opacity:1}}.yoast-tooltip:active::after,.yoast-tooltip:active::before,.yoast-tooltip:focus::after,.yoast-tooltip:focus::before,.yoast-tooltip:hover::after,.yoast-tooltip:hover::before{display:inline-block;text-decoration:none;animation-name:yoast-tooltip-appear;animation-duration:.1s;animation-timing-function:ease-in;animation-delay:.4s;animation-fill-mode:forwards}.yoast-tooltip-no-delay:active::after,.yoast-tooltip-no-delay:active::before,.yoast-tooltip-no-delay:focus::after,.yoast-tooltip-no-delay:focus::before,.yoast-tooltip-no-delay:hover::after,.yoast-tooltip-no-delay:hover::before{opacity:1;animation:none}.yoast-tooltip-multiline:active::after,.yoast-tooltip-multiline:focus::after,.yoast-tooltip-multiline:hover::after{display:table-cell}.yoast-tooltip-s::after,.yoast-tooltip-se::after,.yoast-tooltip-sw::after{top:100%;right:50%;margin-top:5px}.yoast-tooltip-s::before,.yoast-tooltip-se::before,.yoast-tooltip-sw::before{top:auto;right:50%;bottom:-5px;margin-right:-5px;border-bottom-color:rgba(0,0,0,.8)}.yoast-tooltip-se::after{right:auto;left:50%;margin-left:-15px}.yoast-tooltip-sw::after{margin-right:-15px}.yoast-tooltip-n::after,.yoast-tooltip-ne::after,.yoast-tooltip-nw::after{right:50%;bottom:100%;margin-bottom:5px}.yoast-tooltip-n::before,.yoast-tooltip-ne::before,.yoast-tooltip-nw::before{top:-5px;right:50%;bottom:auto;margin-right:-5px;border-top-color:rgba(0,0,0,.8)}.yoast-tooltip-ne::after{right:auto;left:50%;margin-left:-15px}.yoast-tooltip-nw::after{margin-right:-15px}.yoast-tooltip-n::after,.yoast-tooltip-s::after{-ms-transform:translateX(50%);transform:translateX(50%)}.yoast-tooltip-w::after{right:100%;bottom:50%;margin-right:5px;-ms-transform:translateY(50%);transform:translateY(50%)}.yoast-tooltip-w::before{top:50%;bottom:50%;left:-5px;margin-top:-5px;border-left-color:rgba(0,0,0,.8)}.yoast-tooltip-e::after{bottom:50%;left:100%;margin-left:5px;-ms-transform:translateY(50%);transform:translateY(50%)}.yoast-tooltip-e::before{top:50%;right:-5px;bottom:50%;margin-top:-5px;border-right-color:rgba(0,0,0,.8)}.yoast-tooltip-multiline::after{width:250px;width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:250px;border-collapse:separate;white-space:pre-line;word-wrap:normal;word-break:break-word}.yoast-tooltip-multiline.yoast-tooltip-n::after,.yoast-tooltip-multiline.yoast-tooltip-s::after{right:auto;left:50%;-ms-transform:translateX(-50%);transform:translateX(-50%)}.yoast-tooltip-multiline.yoast-tooltip-e::after,.yoast-tooltip-multiline.yoast-tooltip-w::after{right:100%}@media screen and (min-width:0\0){.yoast-tooltip-multiline::after{width:250px}}.yoast-tooltip-sticky::after,.yoast-tooltip-sticky::before{display:inline-block}.yoast-tooltip-sticky.yoast-tooltip-multiline::after{display:table-cell}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (-moz-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:192dpi),only screen and (min-resolution:2dppx){.yoast-tooltip-w::after{margin-right:4.5px}}.yoast-tooltip.yoast-tooltip-hidden::after,.yoast-tooltip.yoast-tooltip-hidden::before{display:none}.yoast-measure{max-width:600px}#TB_window .wpseo_content_wrapper p{font-size:14px;font-style:normal}#TB_window .wpseo_content_wrapper label{margin:0 10px 0 0;font-size:14px;font-weight:600}.wpseo-premium-popup-title{margin:1em 0!important;padding:0!important;font-size:1.3em!important;font-weight:600!important}.wpseo-premium-popup-icon{margin:10px}.edit-tags-php .column-description img{max-width:100%;height:auto}.select2-search__field{margin:0}.select2-results__option,.select2-search--inline,.select2-selection__choice{margin-bottom:0}.select2-container .select2-search--inline .select2-search__field{margin-top:6px!important;line-height:inherit}.yoast-label-strong{font-weight:600}.yoast-video-container-max-width{max-width:560px}.yoast-video-container{overflow:hidden;position:relative;height:0;padding-bottom:56.25%}.yoast-video-container iframe{position:absolute;top:0;left:0;width:100%;height:100%}.yoast-settings{margin-bottom:2em;padding-left:220px}.yoast-settings h2{margin-bottom:0;margin-left:-220px}.yoast-settings label{display:inline-block;width:200px;margin-right:6px;margin-left:-220px;padding-top:4px;padding-right:10px;color:#23282d;font-size:14px;font-weight:600;line-height:1.3;vertical-align:top}.yoast .yoast-settings__checkbox,.yoast .yoast-settings__radio,.yoast-settings fieldset,.yoast-settings input[type=text],.yoast-settings label,.yoast-settings select,.yoast-settings textarea{margin-top:2em;margin-bottom:.5em}.yoast-settings__textarea--medium{width:100%;max-width:600px}.yoast .yoast-settings__checkbox,.yoast .yoast-settings__radio{position:relative;top:1px;vertical-align:top}.yoast-settings__group--checkbox,.yoast-settings__group--radio{padding-top:1em}.yoast-settings__group--checkbox .yoast-settings__checkbox,.yoast-settings__group--radio .yoast-settings__radio{margin:0 4px 10px 0}.yoast-settings__checkbox+label,.yoast-settings__radio+label{width:auto;max-width:calc(100% - 25px);margin-right:0;margin-left:0;padding:0}.yoast-settings__group--checkbox .yoast-settings__checkbox+label,.yoast-settings__group--radio .yoast-settings__radio+label{margin-top:0;margin-bottom:10px;font-weight:400}.yoast-settings legend{color:#23282d;font-size:14px;font-weight:600}.yoast-settings .description{margin-top:0;font-size:14px}td .wpseo-score-icon{display:inline-block;width:12px;height:12px;margin-left:5px;border-radius:50%;background:#888;line-height:16px;margin-top:3px}.fixed th.column-wpseo-linked,.fixed th.column-wpseo-links,.fixed th.column-wpseo-score,.fixed th.column-wpseo-score-readability{width:3em;padding:0}th.column-wpseo-linked a,th.column-wpseo-links a,th.column-wpseo-score .yoast-tooltip,th.column-wpseo-score-readability .yoast-tooltip{display:inline-block;overflow:visible;padding:8px 0;vertical-align:middle}th.column-wpseo-score .yoast-tooltip,th.column-wpseo-score-readability .yoast-tooltip{padding:8px 11px}.column-wpseo-links .yoast-tooltip-multiline::after{width:999px;max-width:160px}.column-wpseo-linked .yoast-tooltip-multiline::after{width:999px;max-width:170px}.yoast-column-header-has-tooltip{position:relative}.manage-column .yoast-column-header-has-tooltip:before{display:inline-block;width:20px;height:20px;padding:0;color:#444;vertical-align:top;text-decoration:none!important;content:""}.manage-column .yoast-linked-to:before{background:url(../../images/link-out-icon.svg) no-repeat;background-size:20px}.manage-column .yoast-linked-from:before{background:url(../../images/link-in-icon.svg) no-repeat;background-size:20px}.manage-column .yoast-column-seo-score:before{background:url(../../images/Yoast_SEO_negative_icon.svg) no-repeat;background-size:20px}.manage-column .yoast-column-readability:before{background:url(../../images/readability-icon.svg) no-repeat;background-size:20px}td.column-wpseo-linked,td.column-wpseo-links{word-wrap:normal}#screen-meta .yoast-column-header-has-tooltip .screen-reader-text{visibility:visible;position:static;width:auto;height:auto}@media screen and (max-width:782px){.yoast-settings{padding-left:0}.yoast-settings h2{margin-left:0}.yoast-settings label{width:auto;margin-right:0;margin-left:0;padding:0}.yoast .yoast-settings__radio,.yoast-settings__radio+label{margin-bottom:1em}.yoast-settings__checkbox+label,.yoast-settings__radio+label{max-width:calc(100% - 35px);padding-top:8px}.yoast-settings__group--checkbox .yoast-settings__checkbox+label,.yoast-settings__group--radio .yoast-settings__radio+label{padding-top:4px}.yoast-settings input[type=text],.yoast-settings select,.yoast-settings textarea{display:block;box-sizing:border-box;width:100%;max-width:none;margin-top:0;margin-bottom:0;padding:7px 10px;line-height:1.5}}#yoast-help-center-container{margin:16px 0 24px}.react-tabs__tab-panel{max-width:900px;margin:0 auto}.react-tabs__tab-panel li{max-width:none!important}.yoast-help-center-open #sidebar-container{display:none}.contact-premium-support{text-align:center}.contact-premium-support__content{margin:0 auto 1.5em;font-size:.9375rem;line-height:1.4}.contact-premium-support__content:nth-child(2){max-width:610px}.contact-premium-support__content:nth-child(3){max-width:560px}.contact-premium-support .contact-premium-support__button{margin-bottom:48px}.wpseo-premium-description{margin-top:.5em}.wpseo-premium-advantages-list{padding-left:1.5em;list-style:disc}.yoast_help.yoast-help-button{overflow:visible;position:relative;width:20px;height:20px;margin:0;padding:0;border:0;outline:0;color:#72777c;background:0 0;box-shadow:none;vertical-align:top;cursor:pointer}.help-button-inline .yoast_help.yoast-help-button{margin-top:-4px}.yoast-section .yoast_help.yoast-help-button{float:right;margin-top:-44px}.wpseo-admin-page .yoast_help.yoast-help-button{margin-right:6px}.yoast_help .yoast-help-icon::before{position:absolute;top:0;left:0;padding:4px;content:"\f223"}.yoast_help.yoast-help-button:focus,.yoast_help.yoast-help-button:hover{color:#0073aa}.assessment-results__mark:focus,.yoast_help.yoast-help-button:focus .yoast-help-icon::before{border-radius:100%;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.yoast-help-panel{display:none;clear:both;max-width:30em!important;padding:0 0 1em;font-weight:400;white-space:normal}.wpseo-admin-page .yoast-help-panel{max-width:600px!important}.copy-home-meta-description .yoast-help-panel{max-width:400px!important} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/adminbar-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/adminbar-1720-rtl.css new file mode 100644 index 00000000..459e3fe4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/adminbar-1720-rtl.css @@ -0,0 +1 @@ +.wpseo-score-icon{display:inline-block!important;width:12px!important;height:12px!important;border-radius:50%!important;margin:3px 3px 0 10px;background:#888;vertical-align:top}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe}.adminbar-seo-score{margin:10px 4px 0 0!important}#wpadminbar .yoast-issue-added,#wpadminbar .yoast-issue-added:hover{position:absolute;top:32px;right:0;white-space:nowrap;padding:2px 12px;border-radius:10px 0 10px 10px;color:#fff;background-color:#a4286a;box-shadow:-1px 1px 1px 1px grey}#wpadminbar .yoast-issue-added{display:none}#wpadminbar .yoast-issue-counter{display:inline;padding:1px 6px 1px 7px!important;border-radius:9px;color:#fff}#wpadminbar .yoast-logo.svg{float:right;width:26px;height:30px;background-repeat:no-repeat;background-position:100% 6px;background-size:20px;background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBmaWxsPSIjODI4NzhjIj48cGF0aCBkPSJNMjAzLjYgMzk1YzYuOC0xNy40IDYuOC0zNi42IDAtNTRsLTc5LjQtMjA0aDcwLjlsNDcuNyAxNDkuNCA3NC44LTIwNy42SDExNi40Yy00MS44IDAtNzYgMzQuMi03NiA3NlYzNTdjMCA0MS44IDM0LjIgNzYgNzYgNzZIMTczYzE2LTguOSAyNC42LTIyLjcgMzAuNi0zOHpNNDcxLjYgMTU0LjhjMC00MS44LTM0LjItNzYtNzYtNzZoLTNMMjg1LjcgMzY1Yy05LjYgMjYuNy0xOS40IDQ5LjMtMzAuMyA2OGgyMTYuMlYxNTQuOHoiLz48cGF0aCBzdHJva2Utd2lkdGg9IjIuOTc0IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGQ9Ik0zMzggMS4zbC05My4zIDI1OS4xLTQyLjEtMTMxLjloLTg5LjFsODMuOCAyMTUuMmM2IDE1LjUgNiAzMi41IDAgNDgtNy40IDE5LTE5IDM3LjMtNTMgNDEuOWwtNy4yIDF2NzZoOC4zYzgxLjcgMCAxMTguOS01Ny4yIDE0OS42LTE0Mi45TDQzMS42IDEuM0gzMzh6TTI3OS40IDM2MmMtMzIuOSA5Mi02Ny42IDEyOC43LTEyNS43IDEzMS44di00NWMzNy41LTcuNSA1MS4zLTMxIDU5LjEtNTEuMSA3LjUtMTkuMyA3LjUtNDAuNyAwLTYwbC03NS0xOTIuN2g1Mi44bDUzLjMgMTY2LjggMTA1LjktMjk0aDU4LjFMMjc5LjQgMzYyeiIvPjwvc3ZnPg==")}#wpadminbar #wp-admin-bar-wpseo-licenses .ab-item{color:#f18500}@media screen and (max-width:782px){.adminbar-seo-score{margin:16px 2px 0 10px!important}#wpadminbar #wp-admin-bar-wpseo-menu{display:block;position:static}#wpadminbar .yoast-logo.svg{width:52px;height:46px;background-position:50% 8px;background-size:30px}#wpadminbar .yoast-logo+.yoast-issue-counter{margin-right:-5px;margin-left:10px}#wpadminbar .ab-sub-wrapper .yoast-issue-counter{vertical-align:text-top;position:relative;top:-5px}#wpadminbar .yoast-issue-added,#wpadminbar .yoast-issue-added:hover{top:46px;white-space:normal;line-height:1.8}#wp-admin-bar-wpseo-menu.menupop .ab-sub-wrapper #wp-admin-bar-wpseo-kwresearch,#wp-admin-bar-wpseo-menu.menupop .ab-sub-wrapper #wp-admin-bar-wpseo-settings{display:none}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/adminbar-1720.css b/wp-content/plugins/wordpress-seo/css/dist/adminbar-1720.css new file mode 100644 index 00000000..3a13983d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/adminbar-1720.css @@ -0,0 +1 @@ +.wpseo-score-icon{display:inline-block!important;width:12px!important;height:12px!important;border-radius:50%!important;margin:3px 10px 0 3px;background:#888;vertical-align:top}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe}.adminbar-seo-score{margin:10px 0 0 4px!important}#wpadminbar .yoast-issue-added,#wpadminbar .yoast-issue-added:hover{position:absolute;top:32px;left:0;white-space:nowrap;padding:2px 12px;border-radius:0 10px 10px 10px;color:#fff;background-color:#a4286a;box-shadow:1px 1px 1px 1px grey}#wpadminbar .yoast-issue-added{display:none}#wpadminbar .yoast-issue-counter{display:inline;padding:1px 7px 1px 6px!important;border-radius:9px;color:#fff}#wpadminbar .yoast-logo.svg{float:left;width:26px;height:30px;background-repeat:no-repeat;background-position:0 6px;background-size:20px;background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiBmaWxsPSIjODI4NzhjIj48cGF0aCBkPSJNMjAzLjYgMzk1YzYuOC0xNy40IDYuOC0zNi42IDAtNTRsLTc5LjQtMjA0aDcwLjlsNDcuNyAxNDkuNCA3NC44LTIwNy42SDExNi40Yy00MS44IDAtNzYgMzQuMi03NiA3NlYzNTdjMCA0MS44IDM0LjIgNzYgNzYgNzZIMTczYzE2LTguOSAyNC42LTIyLjcgMzAuNi0zOHpNNDcxLjYgMTU0LjhjMC00MS44LTM0LjItNzYtNzYtNzZoLTNMMjg1LjcgMzY1Yy05LjYgMjYuNy0xOS40IDQ5LjMtMzAuMyA2OGgyMTYuMlYxNTQuOHoiLz48cGF0aCBzdHJva2Utd2lkdGg9IjIuOTc0IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGQ9Ik0zMzggMS4zbC05My4zIDI1OS4xLTQyLjEtMTMxLjloLTg5LjFsODMuOCAyMTUuMmM2IDE1LjUgNiAzMi41IDAgNDgtNy40IDE5LTE5IDM3LjMtNTMgNDEuOWwtNy4yIDF2NzZoOC4zYzgxLjcgMCAxMTguOS01Ny4yIDE0OS42LTE0Mi45TDQzMS42IDEuM0gzMzh6TTI3OS40IDM2MmMtMzIuOSA5Mi02Ny42IDEyOC43LTEyNS43IDEzMS44di00NWMzNy41LTcuNSA1MS4zLTMxIDU5LjEtNTEuMSA3LjUtMTkuMyA3LjUtNDAuNyAwLTYwbC03NS0xOTIuN2g1Mi44bDUzLjMgMTY2LjggMTA1LjktMjk0aDU4LjFMMjc5LjQgMzYyeiIvPjwvc3ZnPg==")}#wpadminbar #wp-admin-bar-wpseo-licenses .ab-item{color:#f18500}@media screen and (max-width:782px){.adminbar-seo-score{margin:16px 10px 0 2px!important}#wpadminbar #wp-admin-bar-wpseo-menu{display:block;position:static}#wpadminbar .yoast-logo.svg{width:52px;height:46px;background-position:50% 8px;background-size:30px}#wpadminbar .yoast-logo+.yoast-issue-counter{margin-left:-5px;margin-right:10px}#wpadminbar .ab-sub-wrapper .yoast-issue-counter{vertical-align:text-top;position:relative;top:-5px}#wpadminbar .yoast-issue-added,#wpadminbar .yoast-issue-added:hover{top:46px;white-space:normal;line-height:1.8}#wp-admin-bar-wpseo-menu.menupop .ab-sub-wrapper #wp-admin-bar-wpseo-kwresearch,#wp-admin-bar-wpseo-menu.menupop .ab-sub-wrapper #wp-admin-bar-wpseo-settings{display:none}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/adminbar-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/adminbar-720-rtl.min.css deleted file mode 100644 index c69393ee..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/adminbar-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -.wpseo-score-icon{display:inline-block!important;float:right;width:12px!important;height:12px!important;border-radius:50%!important;background-color:#999}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#999}.wpseo-score-icon.noindex{background-color:#1e8cbe}.adminbar-seo-score{margin:10px 4px 0 10px!important}#wpadminbar .yoast-issue-added,#wpadminbar .yoast-issue-added:hover{position:absolute;top:32px;right:0;min-width:300px;padding:2px 8px;border-radius:10px 0 10px 10px;color:#fff;background-color:#a4286a;box-shadow:-1px 1px 1px 1px grey}#wpadminbar .yoast-issue-added{display:none}#wpadminbar .yoast-issue-counter{display:inline;padding:1px 6px 1px 7px!important;border-radius:50%;color:#fff}.yoast-issue-counter{background-color:#d54e21}#wpadminbar .yoast-logo.svg{float:right;width:26px;height:30px;background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgc3R5bGU9ImZpbGw6IzgyODc4YyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxnPjxnPjxnPjxnPjxwYXRoIGQ9Ik0yMDMuNiwzOTVjNi44LTE3LjQsNi44LTM2LjYsMC01NGwtNzkuNC0yMDRoNzAuOWw0Ny43LDE0OS40bDc0LjgtMjA3LjZIMTE2LjRjLTQxLjgsMC03NiwzNC4yLTc2LDc2VjM1N2MwLDQxLjgsMzQuMiw3Niw3Niw3NkgxNzNDMTg5LDQyNC4xLDE5Ny42LDQxMC4zLDIwMy42LDM5NXoiLz48L2c+PGc+PHBhdGggZD0iTTQ3MS42LDE1NC44YzAtNDEuOC0zNC4yLTc2LTc2LTc2aC0zTDI4NS43LDM2NWMtOS42LDI2LjctMTkuNCw0OS4zLTMwLjMsNjhoMjE2LjJWMTU0Ljh6Ii8+PC9nPjwvZz48cGF0aCBzdHJva2Utd2lkdGg9IjIuOTc0IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGQ9Ik0zMzgsMS4zbC05My4zLDI1OS4xbC00Mi4xLTEzMS45aC04OS4xbDgzLjgsMjE1LjJjNiwxNS41LDYsMzIuNSwwLDQ4Yy03LjQsMTktMTksMzcuMy01Myw0MS45bC03LjIsMXY3Nmg4LjNjODEuNywwLDExOC45LTU3LjIsMTQ5LjYtMTQyLjlMNDMxLjYsMS4zSDMzOHogTTI3OS40LDM2MmMtMzIuOSw5Mi02Ny42LDEyOC43LTEyNS43LDEzMS44di00NWMzNy41LTcuNSw1MS4zLTMxLDU5LjEtNTEuMWM3LjUtMTkuMyw3LjUtNDAuNywwLTYwbC03NS0xOTIuN2g1Mi44bDUzLjMsMTY2LjhsMTA1LjktMjk0aDU4LjFMMjc5LjQsMzYyeiIvPjwvZz48L2c+PC9zdmc+);background-repeat:no-repeat;background-position:100% 6px;background-size:20px}#wpadminbar #wp-admin-bar-wpseo-licenses .ab-item{color:#f18500}@media screen and (max-width:782px){#wpadminbar #wp-admin-bar-wpseo-menu{display:block;position:static}#wpadminbar .yoast-logo.svg{width:52px;height:46px;background-position:50% 8px;background-size:30px}#wpadminbar .yoast-logo+.yoast-issue-counter{margin-right:-10px}#wpadminbar .ab-sub-wrapper .yoast-issue-counter{position:relative;top:-5px;vertical-align:text-top}#wp-admin-bar-wpseo-menu.menupop .ab-sub-wrapper #wp-admin-bar-wpseo-kwresearch,#wp-admin-bar-wpseo-menu.menupop .ab-sub-wrapper #wp-admin-bar-wpseo-settings{display:none}#wpadminbar .yoast-issue-added{top:46px}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/adminbar-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/adminbar-720.min.css deleted file mode 100644 index 28543e00..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/adminbar-720.min.css +++ /dev/null @@ -1 +0,0 @@ -.wpseo-score-icon{display:inline-block!important;float:left;width:12px!important;height:12px!important;border-radius:50%!important;background-color:#999}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#999}.wpseo-score-icon.noindex{background-color:#1e8cbe}.adminbar-seo-score{margin:10px 10px 0 4px!important}#wpadminbar .yoast-issue-added,#wpadminbar .yoast-issue-added:hover{position:absolute;top:32px;left:0;min-width:300px;padding:2px 8px;border-radius:0 10px 10px;color:#fff;background-color:#a4286a;box-shadow:1px 1px 1px 1px grey}#wpadminbar .yoast-issue-added{display:none}#wpadminbar .yoast-issue-counter{display:inline;padding:1px 7px 1px 6px!important;border-radius:50%;color:#fff}.yoast-issue-counter{background-color:#d54e21}#wpadminbar .yoast-logo.svg{float:left;width:26px;height:30px;background-image:url(data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgc3R5bGU9ImZpbGw6IzgyODc4YyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxnPjxnPjxnPjxnPjxwYXRoIGQ9Ik0yMDMuNiwzOTVjNi44LTE3LjQsNi44LTM2LjYsMC01NGwtNzkuNC0yMDRoNzAuOWw0Ny43LDE0OS40bDc0LjgtMjA3LjZIMTE2LjRjLTQxLjgsMC03NiwzNC4yLTc2LDc2VjM1N2MwLDQxLjgsMzQuMiw3Niw3Niw3NkgxNzNDMTg5LDQyNC4xLDE5Ny42LDQxMC4zLDIwMy42LDM5NXoiLz48L2c+PGc+PHBhdGggZD0iTTQ3MS42LDE1NC44YzAtNDEuOC0zNC4yLTc2LTc2LTc2aC0zTDI4NS43LDM2NWMtOS42LDI2LjctMTkuNCw0OS4zLTMwLjMsNjhoMjE2LjJWMTU0Ljh6Ii8+PC9nPjwvZz48cGF0aCBzdHJva2Utd2lkdGg9IjIuOTc0IiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGQ9Ik0zMzgsMS4zbC05My4zLDI1OS4xbC00Mi4xLTEzMS45aC04OS4xbDgzLjgsMjE1LjJjNiwxNS41LDYsMzIuNSwwLDQ4Yy03LjQsMTktMTksMzcuMy01Myw0MS45bC03LjIsMXY3Nmg4LjNjODEuNywwLDExOC45LTU3LjIsMTQ5LjYtMTQyLjlMNDMxLjYsMS4zSDMzOHogTTI3OS40LDM2MmMtMzIuOSw5Mi02Ny42LDEyOC43LTEyNS43LDEzMS44di00NWMzNy41LTcuNSw1MS4zLTMxLDU5LjEtNTEuMWM3LjUtMTkuMyw3LjUtNDAuNywwLTYwbC03NS0xOTIuN2g1Mi44bDUzLjMsMTY2LjhsMTA1LjktMjk0aDU4LjFMMjc5LjQsMzYyeiIvPjwvZz48L2c+PC9zdmc+);background-repeat:no-repeat;background-position:0 6px;background-size:20px}#wpadminbar #wp-admin-bar-wpseo-licenses .ab-item{color:#f18500}@media screen and (max-width:782px){#wpadminbar #wp-admin-bar-wpseo-menu{display:block;position:static}#wpadminbar .yoast-logo.svg{width:52px;height:46px;background-position:50% 8px;background-size:30px}#wpadminbar .yoast-logo+.yoast-issue-counter{margin-left:-10px}#wpadminbar .ab-sub-wrapper .yoast-issue-counter{position:relative;top:-5px;vertical-align:text-top}#wp-admin-bar-wpseo-menu.menupop .ab-sub-wrapper #wp-admin-bar-wpseo-kwresearch,#wp-admin-bar-wpseo-menu.menupop .ab-sub-wrapper #wp-admin-bar-wpseo-settings{display:none}#wpadminbar .yoast-issue-added{top:46px}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/alerts-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/alerts-1720-rtl.css new file mode 100644 index 00000000..810097a6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/alerts-1720-rtl.css @@ -0,0 +1 @@ +.yoast-alert{display:flex;align-items:flex-start;padding:16px;border:1px solid rgba(0,0,0,.2);font-size:14px;line-height:1.5;margin:16px 0}.yoast-alert--error{color:#8f1919;background:#f9dcdc}.yoast-alert--info{color:#00468f;background:#cce5ff}.yoast-alert--success{color:#395315;background:#e2f2cc}.yoast-alert--warning{color:#674e00;background:#fff3cd}.yoast-alert__icon.yoast-alert__icon{display:block;margin-top:.125rem;margin-left:8px;height:16px;width:16px;max-width:none}.yoast-alert a{color:#004973} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/alerts-1720.css b/wp-content/plugins/wordpress-seo/css/dist/alerts-1720.css new file mode 100644 index 00000000..df8d0828 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/alerts-1720.css @@ -0,0 +1 @@ +.yoast-alert{display:flex;align-items:flex-start;padding:16px;border:1px solid rgba(0,0,0,.2);font-size:14px;line-height:1.5;margin:16px 0}.yoast-alert--error{color:#8f1919;background:#f9dcdc}.yoast-alert--info{color:#00468f;background:#cce5ff}.yoast-alert--success{color:#395315;background:#e2f2cc}.yoast-alert--warning{color:#674e00;background:#fff3cd}.yoast-alert__icon.yoast-alert__icon{display:block;margin-top:.125rem;margin-right:8px;height:16px;width:16px;max-width:none}.yoast-alert a{color:#004973} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/alerts-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/alerts-720-rtl.min.css deleted file mode 100644 index 50237eb8..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/alerts-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -.screen-reader-text{overflow:hidden;clip:rect(1px,1px,1px,1px);position:absolute!important;width:1px;height:1px;padding:0;border:0;word-wrap:normal!important;-webkit-clip-path:inset(50%);clip-path:inset(50%)}.yoast-search-result-preview__heading{margin:0 -20px 15px;padding:8px 20px;border-bottom:1px solid #f7f7f7;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.yoast-search-result-preview__field{overflow:hidden;position:relative;width:600px;cursor:pointer}.yoast-search-result-preview__field:after,.yoast-search-result-preview__field:before{display:table;content:" "}.yoast-search-result-preview__field--focus:before,.yoast-search-result-preview__field--hover:before{position:absolute;right:-3px;width:24px;height:24px;margin-top:-3px;background-size:25px;content:"";display:block}.yoast-search-result-preview__field:after{clear:both}.yoast-search-result-preview__field--hover:before{background-image:url("data:image/svg+xml;charset=utf8,_encode('')")}.yoast-search-result-preview__field--focus:before{background-image:url("data:image/svg+xml;charset=utf8,_encode('')")}.yoast-search-result-preview__title{overflow:hidden;margin:0;color:#1a0dab;font-size:18px;font-weight:400;line-height:1.2;white-space:nowrap;text-decoration:none;text-overflow:ellipsis}.yoast-search-result-preview__url{color:#006621;font-size:14px;font-style:normal;line-height:16px}.yoast-search-result-preview__date,.yoast-search-result-preview__description{font-size:13px;line-height:1.4}.yoast-search-result-preview__date{color:grey}.yoast-search-result-preview__description{color:#545454}.yoast-button,.yoast-button__edit{padding:8px 10px;border:1px solid #ccc;border-radius:4px;color:#555;background:#f7f7f7;font-size:.8rem;cursor:pointer}.yoast-button__edit{display:block;margin-top:1em;padding-right:32px;background:url("data:image/svg+xml;charset=utf8,_encode('')") 8px center/16px 16px no-repeat #f7f7f7;background-size:16px}.yoast-search-result-form{overflow:hidden;background-color:#fff;font-family:Arial,sans-serif}.yoast-search-result-form__heading{margin:0 -20px 15px;padding:8px 20px;border-bottom:1px solid #f7f7f7;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.yoast-search-result-form__container--focus:before,.yoast-search-result-form__container--hover:before{right:-3px;width:24px;height:24px;margin-top:15px;background-size:25px;display:block;position:absolute;content:""}.yoast-search-result-form__container--hover:before{background-image:url("data:image/svg+xml;charset=utf8,_encode('')")}.yoast-search-result-form__container--focus:before{background-image:url("data:image/svg+xml;charset=utf8,_encode('')")}.yoast-search-result-form__label{display:block;width:100%;margin-top:1em}.yoast-search-result-form__field{box-sizing:border-box;width:100%;border:1px solid #ddd}.yoast-search-result-form__description{display:block;box-sizing:border-box;width:100%;height:70px;border:1px solid #ddd}.yoast-search-result-form__progress{display:block;box-sizing:border-box;width:100%;height:8px;margin-top:5px;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.yoast-search-result-form__progress::-webkit-progress-bar{border:1px solid #ddd;background-color:#f7f7f7}.yoast-search-result-form__close-button{margin-top:1em}.yoast-search-result-form__progress--bad{color:#dc3232}.yoast-search-result-form__progress--bad::-webkit-progress-value{background-color:#dc3232;transition:width 250ms}.yoast-search-result-form__progress--bad::-moz-progress-bar{background-color:#dc3232}.yoast-search-result-form__progress--bad--fallback{overflow:hidden;max-width:100%;background-color:#dc3232}.yoast-search-result-form__progress--ok{color:#ee7c1b}.yoast-search-result-form__progress--ok::-webkit-progress-value{background-color:#ee7c1b;transition:width 250ms}.yoast-search-result-form__progress--ok::-moz-progress-bar{background-color:#ee7c1b}.yoast-search-result-form__progress--ok--fallback{overflow:hidden;max-width:100%;background-color:#ee7c1b}.yoast-search-result-form__progress--good{color:#7ad03a}.yoast-search-result-form__progress--good::-webkit-progress-value{background-color:#7ad03a;transition:width 250ms}.yoast-search-result-form__progress--good::-moz-progress-bar{background-color:#7ad03a}.yoast-search-result-form__progress--good--fallback{overflow:hidden;max-width:100%;background-color:#7ad03a}body{margin:0;padding:0}#container{max-width:1660px;margin:0 auto}.yoast-wizard-body{box-sizing:border-box;width:80%;max-width:60em;margin:1rem auto 4rem}@media screen and (max-width:768px){.yoast-wizard-body{width:auto;margin:0}}.yoast-wizard__logo{display:block;margin:0 auto}.yoast-wizard{box-sizing:border-box;width:100%;min-height:20px;padding:2em;background:#fff;text-align:right}@media screen and (max-width:768px){.yoast-wizard{padding:1em 1em 2em}}.yoast-wizard--header{text-align:center}.yoast-wizard--header--page-title{margin:0 0 -16px;padding:0 8px;color:#a4286a;font-size:1.25em;font-weight:400;line-height:2.5;letter-spacing:.03em}.yoast-wizard--navigation{width:100%;text-align:left}.yoast-wizard--button{margin-top:1em}.yoast-wizard--button__next{margin-right:1em}.yoast-wizard--button__next button:focus,.yoast-wizard--button__next button:hover{background-color:#6c2548!important}.yoast-wizard--button__next button:focus div,.yoast-wizard--button__next button:hover div{background-color:transparent!important}.yoast-wizard--button__previous button:focus{background:#ddd!important}.yoast-wizard--button__previous button:focus:active{background:0 0!important}.yoast-wizard--button__previous button:focus>div>span,.yoast-wizard--button__previous button:hover>div>span{color:#000!important}.yoast-wizard--step__inactive div{pointer-events:none}@media screen and (max-width:768px){.yoast-wizard--header--page-title{font-size:1.5em;line-height:1.25}.yoast-wizard--step__active{overflow:hidden;width:38px}.yoast-wizard--step__active div{display:inline-block!important;vertical-align:middle}.yoast-wizard--step__active div>span>span{display:block!important;margin-right:-7px;padding-left:99px!important}.yoast-wizard--step__inactive{display:none!important}}.yoast-wizard--step--container:focus{outline:0}.yoast-wizard--step--container h1{margin:0;color:#a4286a;font-size:2.25em;font-weight:100;line-height:3.68rem;letter-spacing:.03em}@media screen and (max-width:768px){.yoast-wizard--step--container h1{font-size:2em;line-height:1.25}}.yoast-wizard--step--container h2{color:#a4286a;font-size:1.375em;font-weight:100}.yoast-wizard--stepper{width:100%;margin:auto}.yoast-wizard-overlay{position:absolute;z-index:10;top:0;right:0;width:100%;height:100%;opacity:.2;color:#fff;background-color:#000;text-align:center}.yoast-wizard-overlay-loader{position:relative}.yoast-wizard-container{position:relative;min-height:20px;border:1px solid #ccc;box-shadow:rgba(0,0,0,.15) 0 3px 10px,rgba(0,0,0,.2) 0 3px 10px;text-align:right}.yoast-wizard-container--no-navigation{margin-top:40px}.yoast-wizard-container--no-navigation .yoast-wizard{padding-top:3em}@media screen and (max-width:768px){.yoast-wizard-container{box-shadow:none}}.yoast-wizard-container fieldset{margin:1em 0;border:0}.yoast-wizard-text-input{padding-bottom:.5em;font-size:14px}.yoast-wizard-text-input-label{display:block;margin:.5em 0 0;font-size:14px;font-weight:700;cursor:pointer}.yoast-wizard-text-input [type=text]{box-sizing:border-box;width:100%;max-width:450px}.yoast-video-container-max-width,.yoast-wizard-content-container{max-width:560px}.yoast-wizard-field-description{font-weight:700}.yoast-wizard input{margin:.5em 0;padding:5px;font-size:14px;line-height:140%}.yoast-wizard label{cursor:pointer}.yoast-wizard input[type=radio]{margin:.3em 0 .3em .7em;vertical-align:middle}.yoast-wizard-input__explanation{margin-top:0;color:#555;font-style:italic}.yoast-wizard-input-radio{font-size:14px}.yoast-wizard-input-radio-option label{padding-top:2px}.yoast-wizard-input-radio-separator{padding:0}.yoast-wizard-input-radio-separator input{position:absolute;right:-9999em;width:1px;height:1px}.yoast-wizard-input-radio-separator input+label{float:right;width:30px!important;margin:0 0 5px 5px!important;padding:6px 3px;border:1px solid #ccc;font-family:Arial,Helvetica,sans-serif!important;font-size:18px!important;line-height:24px;text-align:center;cursor:pointer}.yoast-wizard-input-radio-separator input:checked+label{border:1px solid #a4286a;background-color:#fff;box-shadow:inset 0 0 0 2px #a4286a}.yoast-wizard-input-radio-separator input:checked+label,.yoast-wizard-input-radio-separator input:focus+label{border-radius:10px 10px 10px 0}.yoast-video-container{overflow:hidden;position:relative;height:0;padding-bottom:56.25%}.yoast-video-container iframe{position:absolute;top:0;right:0;width:100%;height:100%}.yoast-wizard-notice__error{margin-bottom:15px;padding:12px;border-right:4px solid #dc3232;background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.1)}.yoast-wizard-content-container.yoast-wizard-content-container__is-full-width{max-width:none}@keyframes heartbeat{0%{opacity:.4;transform:scale(.7)}80%{opacity:1}100%{opacity:1;transform:scale(.95)}}.yoast-loader{animation:heartbeat 1.15s infinite;animation-timing-function:cubic-bezier(.96,.02,.63,.86);animation-direction:alternate}.yoast-alert{padding:0 12px;border-right:4px solid #fff;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2)}.yoast-alerts .yoast-alert-holder{margin-bottom:.8em}.yoast-alerts .yoast-alert{width:100%}.yoast-container__alert .yoast-alert{border-right-color:#dc3232}#yoast-alerts-dismissed .yoast-alert{border-right-color:#d93f69}.yoast-container__warning .yoast-alert{border-right-color:#5d237a}#yoast-warnings-dismissed .yoast-alert{border-right-color:#0075b3}.yoast-container{position:relative;max-width:1280px;margin:20px 0 1px;padding:20px 20px 0;border:1px solid #e5e5e5;background-color:#fdfdfd;box-shadow:0 1px 1px rgba(0,0,0,.04)}.yoast-alerts>h2:first-child{margin:0;padding:9px 0 4px;font-size:23px;font-weight:400;line-height:29px}.yoast-alerts .yoast-container h3{margin:-20px -20px 0;padding:1em;border-bottom:1px solid #ccc;background-color:#fdfdfd;font-size:1.4em}h3 .dashicons-warning{color:#dc3232}.yoast-container .container{max-width:980px}.yoast-container .yoast-alert-holder{display:-ms-flexbox;display:flex}.dismiss .dashicons,.restore .dashicons{width:24px;height:24px;font-size:24px}.yoast-bottom-spacing{margin-bottom:20px}.yoast-alerts .button.dismiss,.yoast-alerts .button.restore{width:45px;height:45px;margin-right:10px;padding:0;outline:0;line-height:inherit;cursor:pointer;-ms-flex:0 0 45px;flex:0 0 45px}.yoast-alerts .button.dismiss:focus,.yoast-alerts .button.dismiss:hover,.yoast-alerts .button.restore:focus,.yoast-alerts .button.restore:hover{background:0 0}.yoast-container .separator{margin-top:1em;margin-bottom:1em;border-top:1px solid #ddd}.yoast-container .dashicons-yes{color:#77b227}.yoast-container__warning .dashicons-flag{color:#5d237a}.yoast-container-disabled{display:table-cell;position:absolute;top:0;left:0;bottom:0;right:0;border-radius:4px;background-color:rgba(232,232,232,.7)}.yoast-no-issues{padding:1em 16px 1em 1em;color:#666}.yoast-muted-title{overflow:hidden;font-weight:600;font-style:italic}.yoast-muted-title:after{display:inline-block;width:100%;height:.5em;margin-left:-100%;margin-right:10px;border-top:1px solid #ddd;vertical-align:bottom;content:""}.yoast-alerts .yoast-container__configuration-wizard{display:-ms-flexbox;display:flex;min-height:0;margin-bottom:15px;padding-bottom:20px;background-color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2);align-items:center;-ms-flex-align:center}.yoast-alerts .yoast-container__configuration-wizard--content{margin:12px;padding:0;-ms-flex:1 1 auto;flex:1 1 auto}.yoast-alerts .yoast-container__configuration-wizard--content h3{margin:0 0 4px;padding:0;border-bottom:0;background:0 0;font-size:1.4em;line-height:1}.yoast-alerts .yoast-container__configuration-wizard--content p{margin:1em 0 0}.yoast-alerts .yoast-container__configuration-wizard--content p:last-child{margin:0}.yoast-alerts .yoast-container__configuration-wizard--dismiss{text-align:center}@media screen and (max-width:768px){.yoast-alerts .yoast-container__configuration-wizard img{display:none}.yoast-alerts .yoast-container__configuration-wizard--content{display:block;position:relative;padding:16px}.yoast-alerts .yoast-container__configuration-wizard--dismiss{position:absolute;top:5px;left:5px;width:40px;margin:0}}.yoast-alerts .yoast-container__configuration-wizard--dismiss .dashicons{margin-top:11px;text-decoration:none} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/alerts-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/alerts-720.min.css deleted file mode 100644 index 0a0d3107..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/alerts-720.min.css +++ /dev/null @@ -1 +0,0 @@ -.screen-reader-text{overflow:hidden;clip:rect(1px,1px,1px,1px);position:absolute!important;width:1px;height:1px;padding:0;border:0;word-wrap:normal!important;-webkit-clip-path:inset(50%);clip-path:inset(50%)}.yoast-search-result-preview__heading{margin:0 -20px 15px;padding:8px 20px;border-bottom:1px solid #f7f7f7;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.yoast-search-result-preview__field{overflow:hidden;position:relative;width:600px;cursor:pointer}.yoast-search-result-preview__field:after,.yoast-search-result-preview__field:before{display:table;content:" "}.yoast-search-result-preview__field--focus:before,.yoast-search-result-preview__field--hover:before{position:absolute;left:-3px;width:24px;height:24px;margin-top:-3px;background-size:25px;content:"";display:block}.yoast-search-result-preview__field:after{clear:both}.yoast-search-result-preview__field--hover:before{background-image:url("data:image/svg+xml;charset=utf8,_encode('')")}.yoast-search-result-preview__field--focus:before{background-image:url("data:image/svg+xml;charset=utf8,_encode('')")}.yoast-search-result-preview__title{overflow:hidden;margin:0;color:#1a0dab;font-size:18px;font-weight:400;line-height:1.2;white-space:nowrap;text-decoration:none;text-overflow:ellipsis}.yoast-search-result-preview__url{color:#006621;font-size:14px;font-style:normal;line-height:16px}.yoast-search-result-preview__date,.yoast-search-result-preview__description{font-size:13px;line-height:1.4}.yoast-search-result-preview__date{color:grey}.yoast-search-result-preview__description{color:#545454}.yoast-button,.yoast-button__edit{padding:8px 10px;border:1px solid #ccc;border-radius:4px;color:#555;background:#f7f7f7;font-size:.8rem;cursor:pointer}.yoast-button__edit{display:block;margin-top:1em;padding-left:32px;background:url("data:image/svg+xml;charset=utf8,_encode('')") 8px center/16px 16px no-repeat #f7f7f7;background-size:16px}.yoast-search-result-form{overflow:hidden;background-color:#fff;font-family:Arial,sans-serif}.yoast-search-result-form__heading{margin:0 -20px 15px;padding:8px 20px;border-bottom:1px solid #f7f7f7;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.yoast-search-result-form__container--focus:before,.yoast-search-result-form__container--hover:before{left:-3px;width:24px;height:24px;margin-top:15px;background-size:25px;display:block;position:absolute;content:""}.yoast-search-result-form__container--hover:before{background-image:url("data:image/svg+xml;charset=utf8,_encode('')")}.yoast-search-result-form__container--focus:before{background-image:url("data:image/svg+xml;charset=utf8,_encode('')")}.yoast-search-result-form__label{display:block;width:100%;margin-top:1em}.yoast-search-result-form__field{box-sizing:border-box;width:100%;border:1px solid #ddd}.yoast-search-result-form__description{display:block;box-sizing:border-box;width:100%;height:70px;border:1px solid #ddd}.yoast-search-result-form__progress{display:block;box-sizing:border-box;width:100%;height:8px;margin-top:5px;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.yoast-search-result-form__progress::-webkit-progress-bar{border:1px solid #ddd;background-color:#f7f7f7}.yoast-search-result-form__close-button{margin-top:1em}.yoast-search-result-form__progress--bad{color:#dc3232}.yoast-search-result-form__progress--bad::-webkit-progress-value{background-color:#dc3232;transition:width 250ms}.yoast-search-result-form__progress--bad::-moz-progress-bar{background-color:#dc3232}.yoast-search-result-form__progress--bad--fallback{overflow:hidden;max-width:100%;background-color:#dc3232}.yoast-search-result-form__progress--ok{color:#ee7c1b}.yoast-search-result-form__progress--ok::-webkit-progress-value{background-color:#ee7c1b;transition:width 250ms}.yoast-search-result-form__progress--ok::-moz-progress-bar{background-color:#ee7c1b}.yoast-search-result-form__progress--ok--fallback{overflow:hidden;max-width:100%;background-color:#ee7c1b}.yoast-search-result-form__progress--good{color:#7ad03a}.yoast-search-result-form__progress--good::-webkit-progress-value{background-color:#7ad03a;transition:width 250ms}.yoast-search-result-form__progress--good::-moz-progress-bar{background-color:#7ad03a}.yoast-search-result-form__progress--good--fallback{overflow:hidden;max-width:100%;background-color:#7ad03a}body{margin:0;padding:0}#container{max-width:1660px;margin:0 auto}.yoast-wizard-body{box-sizing:border-box;width:80%;max-width:60em;margin:1rem auto 4rem}@media screen and (max-width:768px){.yoast-wizard-body{width:auto;margin:0}}.yoast-wizard__logo{display:block;margin:0 auto}.yoast-wizard{box-sizing:border-box;width:100%;min-height:20px;padding:2em;background:#fff;text-align:left}@media screen and (max-width:768px){.yoast-wizard{padding:1em 1em 2em}}.yoast-wizard--header{text-align:center}.yoast-wizard--header--page-title{margin:0 0 -16px;padding:0 8px;color:#a4286a;font-size:1.25em;font-weight:400;line-height:2.5;letter-spacing:.03em}.yoast-wizard--navigation{width:100%;text-align:right}.yoast-wizard--button{margin-top:1em}.yoast-wizard--button__next{margin-left:1em}.yoast-wizard--button__next button:focus,.yoast-wizard--button__next button:hover{background-color:#6c2548!important}.yoast-wizard--button__next button:focus div,.yoast-wizard--button__next button:hover div{background-color:transparent!important}.yoast-wizard--button__previous button:focus{background:#ddd!important}.yoast-wizard--button__previous button:focus:active{background:0 0!important}.yoast-wizard--button__previous button:focus>div>span,.yoast-wizard--button__previous button:hover>div>span{color:#000!important}.yoast-wizard--step__inactive div{pointer-events:none}@media screen and (max-width:768px){.yoast-wizard--header--page-title{font-size:1.5em;line-height:1.25}.yoast-wizard--step__active{overflow:hidden;width:38px}.yoast-wizard--step__active div{display:inline-block!important;vertical-align:middle}.yoast-wizard--step__active div>span>span{display:block!important;margin-left:-7px;padding-right:99px!important}.yoast-wizard--step__inactive{display:none!important}}.yoast-wizard--step--container:focus{outline:0}.yoast-wizard--step--container h1{margin:0;color:#a4286a;font-size:2.25em;font-weight:100;line-height:3.68rem;letter-spacing:.03em}@media screen and (max-width:768px){.yoast-wizard--step--container h1{font-size:2em;line-height:1.25}}.yoast-wizard--step--container h2{color:#a4286a;font-size:1.375em;font-weight:100}.yoast-wizard--stepper{width:100%;margin:auto}.yoast-wizard-overlay{position:absolute;z-index:10;top:0;left:0;width:100%;height:100%;opacity:.2;color:#fff;background-color:#000;text-align:center}.yoast-wizard-overlay-loader{position:relative}.yoast-wizard-container{position:relative;min-height:20px;border:1px solid #ccc;box-shadow:rgba(0,0,0,.15) 0 3px 10px,rgba(0,0,0,.2) 0 3px 10px;text-align:left}.yoast-wizard-container--no-navigation{margin-top:40px}.yoast-wizard-container--no-navigation .yoast-wizard{padding-top:3em}@media screen and (max-width:768px){.yoast-wizard-container{box-shadow:none}}.yoast-wizard-container fieldset{margin:1em 0;border:0}.yoast-wizard-text-input{padding-bottom:.5em;font-size:14px}.yoast-wizard-text-input-label{display:block;margin:.5em 0 0;font-size:14px;font-weight:700;cursor:pointer}.yoast-wizard-text-input [type=text]{box-sizing:border-box;width:100%;max-width:450px}.yoast-video-container-max-width,.yoast-wizard-content-container{max-width:560px}.yoast-wizard-field-description{font-weight:700}.yoast-wizard input{margin:.5em 0;padding:5px;font-size:14px;line-height:140%}.yoast-wizard label{cursor:pointer}.yoast-wizard input[type=radio]{margin:.3em .7em .3em 0;vertical-align:middle}.yoast-wizard-input__explanation{margin-top:0;color:#555;font-style:italic}.yoast-wizard-input-radio{font-size:14px}.yoast-wizard-input-radio-option label{padding-top:2px}.yoast-wizard-input-radio-separator{padding:0}.yoast-wizard-input-radio-separator input{position:absolute;left:-9999em;width:1px;height:1px}.yoast-wizard-input-radio-separator input+label{float:left;width:30px!important;margin:0 5px 5px 0!important;padding:6px 3px;border:1px solid #ccc;font-family:Arial,Helvetica,sans-serif!important;font-size:18px!important;line-height:24px;text-align:center;cursor:pointer}.yoast-wizard-input-radio-separator input:checked+label{border:1px solid #a4286a;background-color:#fff;box-shadow:inset 0 0 0 2px #a4286a}.yoast-wizard-input-radio-separator input:checked+label,.yoast-wizard-input-radio-separator input:focus+label{border-radius:10px 10px 0}.yoast-video-container{overflow:hidden;position:relative;height:0;padding-bottom:56.25%}.yoast-video-container iframe{position:absolute;top:0;left:0;width:100%;height:100%}.yoast-wizard-notice__error{margin-bottom:15px;padding:12px;border-left:4px solid #dc3232;background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.1)}.yoast-wizard-content-container.yoast-wizard-content-container__is-full-width{max-width:none}@keyframes heartbeat{0%{opacity:.4;transform:scale(.7)}80%{opacity:1}100%{opacity:1;transform:scale(.95)}}.yoast-loader{animation:heartbeat 1.15s infinite;animation-timing-function:cubic-bezier(.96,.02,.63,.86);animation-direction:alternate}.yoast-alert{padding:0 12px;border-left:4px solid #fff;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2)}.yoast-alerts .yoast-alert-holder{margin-bottom:.8em}.yoast-alerts .yoast-alert{width:100%}.yoast-container__alert .yoast-alert{border-left-color:#dc3232}#yoast-alerts-dismissed .yoast-alert{border-left-color:#d93f69}.yoast-container__warning .yoast-alert{border-left-color:#5d237a}#yoast-warnings-dismissed .yoast-alert{border-left-color:#0075b3}.yoast-container{position:relative;max-width:1280px;margin:20px 0 1px;padding:20px 20px 0;border:1px solid #e5e5e5;background-color:#fdfdfd;box-shadow:0 1px 1px rgba(0,0,0,.04)}.yoast-alerts>h2:first-child{margin:0;padding:9px 0 4px;font-size:23px;font-weight:400;line-height:29px}.yoast-alerts .yoast-container h3{margin:-20px -20px 0;padding:1em;border-bottom:1px solid #ccc;background-color:#fdfdfd;font-size:1.4em}h3 .dashicons-warning{color:#dc3232}.yoast-container .container{max-width:980px}.yoast-container .yoast-alert-holder{display:-ms-flexbox;display:flex}.dismiss .dashicons,.restore .dashicons{width:24px;height:24px;font-size:24px}.yoast-bottom-spacing{margin-bottom:20px}.yoast-alerts .button.dismiss,.yoast-alerts .button.restore{width:45px;height:45px;margin-left:10px;padding:0;outline:0;line-height:inherit;cursor:pointer;-ms-flex:0 0 45px;flex:0 0 45px}.yoast-alerts .button.dismiss:focus,.yoast-alerts .button.dismiss:hover,.yoast-alerts .button.restore:focus,.yoast-alerts .button.restore:hover{background:0 0}.yoast-container .separator{margin-top:1em;margin-bottom:1em;border-top:1px solid #ddd}.yoast-container .dashicons-yes{color:#77b227}.yoast-container__warning .dashicons-flag{color:#5d237a}.yoast-container-disabled{display:table-cell;position:absolute;top:0;right:0;bottom:0;left:0;border-radius:4px;background-color:rgba(232,232,232,.7)}.yoast-no-issues{padding:1em 1em 1em 16px;color:#666}.yoast-muted-title{overflow:hidden;font-weight:600;font-style:italic}.yoast-muted-title:after{display:inline-block;width:100%;height:.5em;margin-right:-100%;margin-left:10px;border-top:1px solid #ddd;vertical-align:bottom;content:""}.yoast-alerts .yoast-container__configuration-wizard{display:-ms-flexbox;display:flex;min-height:0;margin-bottom:15px;padding-bottom:20px;background-color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2);align-items:center;-ms-flex-align:center}.yoast-alerts .yoast-container__configuration-wizard--content{margin:12px;padding:0;-ms-flex:1 1 auto;flex:1 1 auto}.yoast-alerts .yoast-container__configuration-wizard--content h3{margin:0 0 4px;padding:0;border-bottom:0;background:0 0;font-size:1.4em;line-height:1}.yoast-alerts .yoast-container__configuration-wizard--content p{margin:1em 0 0}.yoast-alerts .yoast-container__configuration-wizard--content p:last-child{margin:0}.yoast-alerts .yoast-container__configuration-wizard--dismiss{text-align:center}@media screen and (max-width:768px){.yoast-alerts .yoast-container__configuration-wizard img{display:none}.yoast-alerts .yoast-container__configuration-wizard--content{display:block;position:relative;padding:16px}.yoast-alerts .yoast-container__configuration-wizard--dismiss{position:absolute;top:5px;right:5px;width:40px;margin:0}}.yoast-alerts .yoast-container__configuration-wizard--dismiss .dashicons{margin-top:11px;text-decoration:none} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/dashboard-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/dashboard-1720-rtl.css similarity index 54% rename from wp-content/plugins/wordpress-seo/css/dist/dashboard-720-rtl.min.css rename to wp-content/plugins/wordpress-seo/css/dist/dashboard-1720-rtl.css index 7bdf614b..4e0ed070 100644 --- a/wp-content/plugins/wordpress-seo/css/dist/dashboard-720-rtl.min.css +++ b/wp-content/plugins/wordpress-seo/css/dist/dashboard-1720-rtl.css @@ -1 +1 @@ -#yoast-seo-dashboard-widget h3{font-weight:700}#yoast-seo-dashboard-widget .assessments,#yoast-seo-dashboard-widget .score-assessments{padding-right:0}#yoast-seo-dashboard-widget .wordpress-feed{margin:16px -12px 0;padding:12px 12px 0;border-top:1px solid #eee}#yoast-seo-dashboard-widget .wordpress-feed .wordpress-feed__post{margin-top:12px}#yoast-seo-dashboard-widget .wordpress-feed .wordpress-feed__footer{margin:0 -12px;padding:4px 12px 0;border-top:1px solid #eee}#yoast-seo-ryte-assessment{margin:12px -12px 0;padding:12px 12px 0;border-top:1px solid #eee}#yoast-seo-ryte-assessment .button{margin-left:8px}#yoast-seo-ryte-assessment .button.landing-page{border-color:#7b1e4f #6f1b47 #6f1b47;color:#fff;background:#a4286a;box-shadow:0 1px 0 #6f1b47}#yoast-seo-ryte-assessment .button.landing-page:focus,#yoast-seo-ryte-assessment .button.landing-page:hover{border-color:#6f1b47;background:#90235d}#yoast-seo-ryte-assessment .button.landing-page:focus{box-shadow:0 1px 0 #7b1e4f,0 0 2px 1px #a35685}#yoast-seo-ryte-assessment .button.landing-page:active{border-color:#6f1b47;background:#7b1e4f;box-shadow:inset 0 2px 0 #6f1b47;vertical-align:top}#yoast-seo-dashboard-widget:empty:before{display:block;width:40px;height:40px;margin:25px auto;background-image:url(../../images/Yoast_SEO_Icon.svg);content:"";animation:rotate 2s infinite linear}@keyframes rotate{0%{-webkit-transform:perspective(120px) rotateX(0) rotateY(0);transform:perspective(120px) rotateX(0) rotateY(0)}100%{-webkit-transform:perspective(120px) rotateX(0) rotateY(360deg);transform:perspective(120px) rotateX(0) rotateY(360deg)}} \ No newline at end of file +#yoast-seo-dashboard-widget h3{font-weight:700}#yoast-seo-dashboard-widget .assessments,#yoast-seo-dashboard-widget .score-assessments{padding-right:0}#yoast-seo-dashboard-widget .wordpress-feed{margin:16px -12px 0;padding:12px 12px 0;border-top:1px solid #eee}#yoast-seo-dashboard-widget .wordpress-feed .wordpress-feed__post{margin-top:12px}#yoast-seo-dashboard-widget .wordpress-feed .wordpress-feed__footer{margin:0 -12px;padding:4px 12px 0;border-top:1px solid #eee}#yoast-seo-ryte-assessment{margin:12px -12px 0;padding:12px 12px 0;border-top:1px solid #eee}#yoast-seo-ryte-assessment .button{margin-left:8px}#yoast-seo-ryte-assessment .button.landing-page{border-color:#7b1e4f #6f1b47 #6f1b47;color:#fff;background:#a4286a;box-shadow:0 1px 0 #6f1b47}#yoast-seo-ryte-assessment .button.landing-page:focus,#yoast-seo-ryte-assessment .button.landing-page:hover{background:#90235d;border-color:#6f1b47}#yoast-seo-ryte-assessment .button.landing-page:focus{box-shadow:0 1px 0 #7b1e4f,0 0 2px 1px #a35685}#yoast-seo-ryte-assessment .button.landing-page:active{background:#7b1e4f;border-color:#6f1b47;box-shadow:inset 0 2px 0 #6f1b47;vertical-align:top}#yoast-seo-dashboard-widget:empty:before{display:block;content:"";width:40px;height:40px;background-image:url(../../packages/js/images/Yoast_SEO_Icon.svg);margin:25px auto;animation:rotate 2s linear infinite}@keyframes rotate{0%{transform:perspective(120px) rotateX(0deg) rotateY(0deg);-webkit-transform:perspective(120px) rotateX(0deg) rotateY(0deg)}to{transform:perspective(120px) rotateX(0deg) rotateY(-1turn);-webkit-transform:perspective(120px) rotateX(0deg) rotateY(-1turn)}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/dashboard-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/dashboard-1720.css similarity index 54% rename from wp-content/plugins/wordpress-seo/css/dist/dashboard-720.min.css rename to wp-content/plugins/wordpress-seo/css/dist/dashboard-1720.css index 408b9312..bf105e38 100644 --- a/wp-content/plugins/wordpress-seo/css/dist/dashboard-720.min.css +++ b/wp-content/plugins/wordpress-seo/css/dist/dashboard-1720.css @@ -1 +1 @@ -#yoast-seo-dashboard-widget h3{font-weight:700}#yoast-seo-dashboard-widget .assessments,#yoast-seo-dashboard-widget .score-assessments{padding-left:0}#yoast-seo-dashboard-widget .wordpress-feed{margin:16px -12px 0;padding:12px 12px 0;border-top:1px solid #eee}#yoast-seo-dashboard-widget .wordpress-feed .wordpress-feed__post{margin-top:12px}#yoast-seo-dashboard-widget .wordpress-feed .wordpress-feed__footer{margin:0 -12px;padding:4px 12px 0;border-top:1px solid #eee}#yoast-seo-ryte-assessment{margin:12px -12px 0;padding:12px 12px 0;border-top:1px solid #eee}#yoast-seo-ryte-assessment .button{margin-right:8px}#yoast-seo-ryte-assessment .button.landing-page{border-color:#7b1e4f #6f1b47 #6f1b47;color:#fff;background:#a4286a;box-shadow:0 1px 0 #6f1b47}#yoast-seo-ryte-assessment .button.landing-page:focus,#yoast-seo-ryte-assessment .button.landing-page:hover{border-color:#6f1b47;background:#90235d}#yoast-seo-ryte-assessment .button.landing-page:focus{box-shadow:0 1px 0 #7b1e4f,0 0 2px 1px #a35685}#yoast-seo-ryte-assessment .button.landing-page:active{border-color:#6f1b47;background:#7b1e4f;box-shadow:inset 0 2px 0 #6f1b47;vertical-align:top}#yoast-seo-dashboard-widget:empty:before{display:block;width:40px;height:40px;margin:25px auto;background-image:url(../../images/Yoast_SEO_Icon.svg);content:"";animation:rotate 2s infinite linear}@keyframes rotate{0%{-webkit-transform:perspective(120px) rotateX(0) rotateY(0);transform:perspective(120px) rotateX(0) rotateY(0)}100%{-webkit-transform:perspective(120px) rotateX(0) rotateY(360deg);transform:perspective(120px) rotateX(0) rotateY(360deg)}} \ No newline at end of file +#yoast-seo-dashboard-widget h3{font-weight:700}#yoast-seo-dashboard-widget .assessments,#yoast-seo-dashboard-widget .score-assessments{padding-left:0}#yoast-seo-dashboard-widget .wordpress-feed{margin:16px -12px 0;padding:12px 12px 0;border-top:1px solid #eee}#yoast-seo-dashboard-widget .wordpress-feed .wordpress-feed__post{margin-top:12px}#yoast-seo-dashboard-widget .wordpress-feed .wordpress-feed__footer{margin:0 -12px;padding:4px 12px 0;border-top:1px solid #eee}#yoast-seo-ryte-assessment{margin:12px -12px 0;padding:12px 12px 0;border-top:1px solid #eee}#yoast-seo-ryte-assessment .button{margin-right:8px}#yoast-seo-ryte-assessment .button.landing-page{border-color:#7b1e4f #6f1b47 #6f1b47;color:#fff;background:#a4286a;box-shadow:0 1px 0 #6f1b47}#yoast-seo-ryte-assessment .button.landing-page:focus,#yoast-seo-ryte-assessment .button.landing-page:hover{background:#90235d;border-color:#6f1b47}#yoast-seo-ryte-assessment .button.landing-page:focus{box-shadow:0 1px 0 #7b1e4f,0 0 2px 1px #a35685}#yoast-seo-ryte-assessment .button.landing-page:active{background:#7b1e4f;border-color:#6f1b47;box-shadow:inset 0 2px 0 #6f1b47;vertical-align:top}#yoast-seo-dashboard-widget:empty:before{display:block;content:"";width:40px;height:40px;background-image:url(../../packages/js/images/Yoast_SEO_Icon.svg);margin:25px auto;animation:rotate 2s linear infinite}@keyframes rotate{0%{transform:perspective(120px) rotateX(0deg) rotateY(0deg);-webkit-transform:perspective(120px) rotateX(0deg) rotateY(0deg)}to{transform:perspective(120px) rotateX(0deg) rotateY(1turn);-webkit-transform:perspective(120px) rotateX(0deg) rotateY(1turn)}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/edit-page-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/edit-page-1720-rtl.css new file mode 100644 index 00000000..0051ba5c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/edit-page-1720-rtl.css @@ -0,0 +1 @@ +.wpseo-score-icon{display:inline-block!important;width:12px!important;height:12px!important;border-radius:50%!important;margin:3px 3px 0 10px;background:#888;vertical-align:top}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe}@media screen and (max-width:782px){.column-wpseo-focuskw,.column-wpseo-metadesc,.column-wpseo-score,.column-wpseo-title{display:none}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/edit-page-1720.css b/wp-content/plugins/wordpress-seo/css/dist/edit-page-1720.css new file mode 100644 index 00000000..0a447cd6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/edit-page-1720.css @@ -0,0 +1 @@ +.wpseo-score-icon{display:inline-block!important;width:12px!important;height:12px!important;border-radius:50%!important;margin:3px 10px 0 3px;background:#888;vertical-align:top}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe}@media screen and (max-width:782px){.column-wpseo-focuskw,.column-wpseo-metadesc,.column-wpseo-score,.column-wpseo-title{display:none}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/edit-page-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/edit-page-720-rtl.min.css deleted file mode 100644 index 969f17a0..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/edit-page-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe}@media screen and (max-width:782px){.column-wpseo-focuskw,.column-wpseo-metadesc,.column-wpseo-score,.column-wpseo-title{display:none}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/edit-page-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/edit-page-720.min.css deleted file mode 100644 index 969f17a0..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/edit-page-720.min.css +++ /dev/null @@ -1 +0,0 @@ -.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe}@media screen and (max-width:782px){.column-wpseo-focuskw,.column-wpseo-metadesc,.column-wpseo-score,.column-wpseo-title{display:none}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/elementor-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/elementor-1720-rtl.css new file mode 100644 index 00000000..abbe3e5e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/elementor-1720-rtl.css @@ -0,0 +1 @@ +:root{--yoast-elementor-color-paragraph:#555d66}.yoast,.yoast h2,.yoast h3{font-family:var(--yoast-font-family)!important}.yoast h2{color:var(--yoast-color-dark);font-size:1.3em;font-weight:var(--yoast-font-weight-bold);margin-bottom:1em}.yoast input,.yoast input:focus,.yoast label,.yoast select:focus,.yoast select:not(:focus){color:var(--yoast-color-font-default);background-color:transparent;border-color:var(--yoast-color-secondary-darker)}.yoast label{color:var(--yoast-color-label)}.yoast input[disabled]{background-color:var(--yoast-color-inactive-grey-light)}.yoast.components-panel__body .yoast-title{font-weight:500}.yoast-field-group__title b{font-weight:var(--yoast-font-weight-bold)}.yoast h3 span>span{font-weight:400}.elementor-panel .elementor-tab-control-yoast-tab a:before,.yoast-element-menu-icon:before{mask-image:var(--yoast-svg-icon-yoast);-webkit-mask-image:var(--yoast-svg-icon-yoast);mask-size:100% 100%;-webkit-mask-size:100% 100%;height:16px;width:16px;margin:0 auto;content:".";color:transparent;background-color:#6d7882}.yoast-element-menu-icon{display:inline-flex}.yoast-element-menu-icon:before{height:19px;width:19px;background-color:#a4afb7}.yoast-elementor-panel__fills{margin-top:10px;padding:5px 5px 0;color:var(--yoast-color-dark);background-color:var(--yoast-color-white);-webkit-font-smoothing:subpixel-antialiased}.yoast li,.yoast p,.yoast small{margin-bottom:6px;line-height:1.5}.yoast p,.yoast small,.yoast ul[role=list] li{color:var(--yoast-elementor-color-paragraph)}.button-link,.yoast-elementor-panel__fills p a,.yoast a,.yoast a p{color:var(--yoast-color-link);text-decoration:underline}.yoast a.dashicons{color:var(--yoast-color-inactive-text);height:24px;width:24px;vertical-align:text-bottom}.button-link{border:none;background:none;cursor:pointer;font-size:1em;line-height:1.5}.yoast-elementor-panel__fills .UpsellLinkButton,.yoast .yoast-button-upsell{line-height:1.4em;color:var(--yoast-color-label);text-decoration:none}.yoast-elementor-panel__fills h3>button{border:none;box-shadow:none;background:none}.yoast-gutenberg-modal .yoast-notice-container>hr{border-top-color:#ddd;border-top-style:solid}.yoast-gutenberg-modal input[type=radio]{-webkit-appearance:none;-moz-appearance:none;width:18px;height:18px;padding:2px;margin:0 0 0 8px;vertical-align:text-bottom;border-radius:50%;transition:all .15s ease-out 0s;border:var(--yoast-border-default);box-shadow:inset 0 2px 4px rgba(0,0,0,.1);position:relative;overflow:hidden;cursor:pointer}.yoast-gutenberg-modal input[type=radio]:checked{border-color:var(--yoast-color-primary);background-color:inherit}.yoast-gutenberg-modal input[type=radio]:checked:after{width:10px;height:10px;background:var(--yoast-color-primary);position:absolute;right:3px;top:3px;content:"";display:block;border-radius:50%}.yoast-post-settings-modal .yoast-notice-container{bottom:auto}.yoast-gutenberg-modal .components-popover.components-tooltip{position:relative;right:unset!important;top:15px!important;left:40px}.yoast div:focus,div.yoast:focus{outline:0}.yoast .button-link:focus,.yoast a:focus{color:#124964;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8);outline:1px solid transparent}.yoast a.dashicons:focus{color:#1e8cbe}.yoast input[type=radio]:checked:focus{box-shadow:var(--yoast-color-focus);border-color:#fff}.yoast .yoast-button-upsell:focus{color:#000;box-shadow:inset 0 -4px 0 rgba(0,0,0,.2),0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}#yoast-introduction{z-index:1;top:5px!important;right:41px!important;box-shadow:var(--yoast-shadow-default);text-align:right;padding:20px}#yoast-introduction:before{right:-12px;top:8px;transform:rotate(90deg)}#yoast-introduction>div{color:var(--yoast-color-default)}#yoast-introduction>.dialog-header{font-weight:var(--yoast-font-weight-bold);line-height:1.3}#yoast-introduction>.dialog-buttons-wrapper{justify-content:flex-end;margin-top:12px}@media(hover:hover){.button-link:hover,.yoast-elementor-panel__fills p a:hover,.yoast a:hover,.yoast a:hover p{color:var(--yoast-color-primary-darker)}.yoast a.dashicons:hover{color:var(--yoast-color-link)}.yoast-elementor-panel__fills .UpsellLinkButton:hover,.yoast .yoast-button-upsell:hover{color:var(--yoast-color-label)}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/elementor-1720.css b/wp-content/plugins/wordpress-seo/css/dist/elementor-1720.css new file mode 100644 index 00000000..e2a16470 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/elementor-1720.css @@ -0,0 +1 @@ +:root{--yoast-elementor-color-paragraph:#555d66}.yoast,.yoast h2,.yoast h3{font-family:var(--yoast-font-family)!important}.yoast h2{color:var(--yoast-color-dark);font-size:1.3em;font-weight:var(--yoast-font-weight-bold);margin-bottom:1em}.yoast input,.yoast input:focus,.yoast label,.yoast select:focus,.yoast select:not(:focus){color:var(--yoast-color-font-default);background-color:transparent;border-color:var(--yoast-color-secondary-darker)}.yoast label{color:var(--yoast-color-label)}.yoast input[disabled]{background-color:var(--yoast-color-inactive-grey-light)}.yoast.components-panel__body .yoast-title{font-weight:500}.yoast-field-group__title b{font-weight:var(--yoast-font-weight-bold)}.yoast h3 span>span{font-weight:400}.elementor-panel .elementor-tab-control-yoast-tab a:before,.yoast-element-menu-icon:before{mask-image:var(--yoast-svg-icon-yoast);-webkit-mask-image:var(--yoast-svg-icon-yoast);mask-size:100% 100%;-webkit-mask-size:100% 100%;height:16px;width:16px;margin:0 auto;content:".";color:transparent;background-color:#6d7882}.yoast-element-menu-icon{display:inline-flex}.yoast-element-menu-icon:before{height:19px;width:19px;background-color:#a4afb7}.yoast-elementor-panel__fills{margin-top:10px;padding:5px 5px 0;color:var(--yoast-color-dark);background-color:var(--yoast-color-white);-webkit-font-smoothing:subpixel-antialiased}.yoast li,.yoast p,.yoast small{margin-bottom:6px;line-height:1.5}.yoast p,.yoast small,.yoast ul[role=list] li{color:var(--yoast-elementor-color-paragraph)}.button-link,.yoast-elementor-panel__fills p a,.yoast a,.yoast a p{color:var(--yoast-color-link);text-decoration:underline}.yoast a.dashicons{color:var(--yoast-color-inactive-text);height:24px;width:24px;vertical-align:text-bottom}.button-link{border:none;background:none;cursor:pointer;font-size:1em;line-height:1.5}.yoast-elementor-panel__fills .UpsellLinkButton,.yoast .yoast-button-upsell{line-height:1.4em;color:var(--yoast-color-label);text-decoration:none}.yoast-elementor-panel__fills h3>button{border:none;box-shadow:none;background:none}.yoast-gutenberg-modal .yoast-notice-container>hr{border-top-color:#ddd;border-top-style:solid}.yoast-gutenberg-modal input[type=radio]{-webkit-appearance:none;-moz-appearance:none;width:18px;height:18px;padding:2px;margin:0 8px 0 0;vertical-align:text-bottom;border-radius:50%;transition:all .15s ease-out 0s;border:var(--yoast-border-default);box-shadow:inset 0 2px 4px rgba(0,0,0,.1);position:relative;overflow:hidden;cursor:pointer}.yoast-gutenberg-modal input[type=radio]:checked{border-color:var(--yoast-color-primary);background-color:inherit}.yoast-gutenberg-modal input[type=radio]:checked:after{width:10px;height:10px;background:var(--yoast-color-primary);position:absolute;left:3px;top:3px;content:"";display:block;border-radius:50%}.yoast-post-settings-modal .yoast-notice-container{bottom:auto}.yoast-gutenberg-modal .components-popover.components-tooltip{position:relative;left:unset!important;top:15px!important;right:40px}.yoast div:focus,div.yoast:focus{outline:0}.yoast .button-link:focus,.yoast a:focus{color:#124964;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8);outline:1px solid transparent}.yoast a.dashicons:focus{color:#1e8cbe}.yoast input[type=radio]:checked:focus{box-shadow:var(--yoast-color-focus);border-color:#fff}.yoast .yoast-button-upsell:focus{color:#000;box-shadow:inset 0 -4px 0 rgba(0,0,0,.2),0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}#yoast-introduction{z-index:1;top:5px!important;left:41px!important;box-shadow:var(--yoast-shadow-default);text-align:left;padding:20px}#yoast-introduction:before{left:-12px;top:8px;transform:rotate(-90deg)}#yoast-introduction>div{color:var(--yoast-color-default)}#yoast-introduction>.dialog-header{font-weight:var(--yoast-font-weight-bold);line-height:1.3}#yoast-introduction>.dialog-buttons-wrapper{justify-content:flex-end;margin-top:12px}@media(hover:hover){.button-link:hover,.yoast-elementor-panel__fills p a:hover,.yoast a:hover,.yoast a:hover p{color:var(--yoast-color-primary-darker)}.yoast a.dashicons:hover{color:var(--yoast-color-link)}.yoast-elementor-panel__fills .UpsellLinkButton:hover,.yoast .yoast-button-upsell:hover{color:var(--yoast-color-label)}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/featured-image-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/featured-image-1720-rtl.css similarity index 100% rename from wp-content/plugins/wordpress-seo/css/dist/featured-image-720-rtl.min.css rename to wp-content/plugins/wordpress-seo/css/dist/featured-image-1720-rtl.css diff --git a/wp-content/plugins/wordpress-seo/css/dist/featured-image-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/featured-image-1720.css similarity index 100% rename from wp-content/plugins/wordpress-seo/css/dist/featured-image-720.min.css rename to wp-content/plugins/wordpress-seo/css/dist/featured-image-1720.css diff --git a/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-1720-rtl.css new file mode 100644 index 00000000..d629b7fb --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-1720-rtl.css @@ -0,0 +1 @@ +#posts-filter .wpseo-filter-explanation{margin:10px 1px 5px;clear:both} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-1720.css b/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-1720.css new file mode 100644 index 00000000..d629b7fb --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-1720.css @@ -0,0 +1 @@ +#posts-filter .wpseo-filter-explanation{margin:10px 1px 5px;clear:both} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-720-rtl.min.css deleted file mode 100644 index 01b9a723..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -#posts-filter .wpseo-filter-explanation{margin:10px 1px 5px} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-720.min.css deleted file mode 100644 index 01b9a723..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/filter-explanation-720.min.css +++ /dev/null @@ -1 +0,0 @@ -#posts-filter .wpseo-filter-explanation{margin:10px 1px 5px} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/icons-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/icons-1720-rtl.css new file mode 100644 index 00000000..6b6947d9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/icons-1720-rtl.css @@ -0,0 +1 @@ +:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/icons-1720.css b/wp-content/plugins/wordpress-seo/css/dist/icons-1720.css new file mode 100644 index 00000000..6b6947d9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/icons-1720.css @@ -0,0 +1 @@ +:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/inside-editor-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/inside-editor-1720-rtl.css similarity index 60% rename from wp-content/plugins/wordpress-seo/css/dist/inside-editor-720-rtl.min.css rename to wp-content/plugins/wordpress-seo/css/dist/inside-editor-1720-rtl.css index d16fec52..c7e4aab5 100644 --- a/wp-content/plugins/wordpress-seo/css/dist/inside-editor-720-rtl.min.css +++ b/wp-content/plugins/wordpress-seo/css/dist/inside-editor-1720-rtl.css @@ -1 +1 @@ -.yoast-text-mark{background-color:#e1bee7}.yoast-text-mark__highlight{color:#fff;background-color:#4a148c} \ No newline at end of file +.yoast-text-mark{background-color:#e1bee7}.yoast-text-mark__highlight{background-color:#4a148c;color:#fff} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/inside-editor-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/inside-editor-1720.css similarity index 60% rename from wp-content/plugins/wordpress-seo/css/dist/inside-editor-720.min.css rename to wp-content/plugins/wordpress-seo/css/dist/inside-editor-1720.css index d16fec52..c7e4aab5 100644 --- a/wp-content/plugins/wordpress-seo/css/dist/inside-editor-720.min.css +++ b/wp-content/plugins/wordpress-seo/css/dist/inside-editor-1720.css @@ -1 +1 @@ -.yoast-text-mark{background-color:#e1bee7}.yoast-text-mark__highlight{color:#fff;background-color:#4a148c} \ No newline at end of file +.yoast-text-mark{background-color:#e1bee7}.yoast-text-mark__highlight{background-color:#4a148c;color:#fff} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/metabox-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/metabox-1720-rtl.css new file mode 100644 index 00000000..6f1664f9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/metabox-1720-rtl.css @@ -0,0 +1 @@ +:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")}.yoast-modal__screen-overlay{position:fixed;top:0;left:0;bottom:0;right:0;background-color:rgba(164,40,106,.6);z-index:100000;animation:edit-post__fade-in-animation .2s ease-out 0s;animation-fill-mode:forwards}.yoast-modal{background:#fff;display:flex;flex-direction:column;overflow:hidden;position:fixed;height:calc(100% - 96px);top:48px;bottom:48px;right:calc(50% - 440px);max-width:880px;width:100%}.yoast-gutenberg-modal .yoast-icon{background-color:var(--yoast-color-primary);mask-image:var(--yoast-svg-icon-yoast);-webkit-mask-image:var(--yoast-svg-icon-yoast);mask-size:100% 100%;-webkit-mask-size:100% 100%;display:inline-block;width:20px;height:20px;margin-left:8px}.yoast-tabs .yoast-modal__content{display:grid;grid-template-areas:"heading heading" "menu content" "menu footer";grid-template-rows:72px 1fr 88px;grid-template-columns:280px 1fr}.yoast-modal__heading{display:flex;align-items:center;box-sizing:border-box;min-height:72px;border-bottom:var(--yoast-border-default);padding:0 24px;grid-area:heading;background:var(--yoast-color-white)}.yoast-modal__heading .yoast-close{position:absolute;left:16px}.yoast-gutenberg-modal .components-modal__header-heading,.yoast-modal__heading h1{font-size:20px;font-weight:400;color:var(--yoast-color-primary);line-height:1.2;margin:0}.yoast-gutenberg-modal .components-modal__icon-container{display:inline-flex}.yoast-gutenberg-modal .components-modal__icon-container svg,.yoast-modal__heading-icon{fill:var(--yoast-color-primary);margin-left:16px;width:19px;height:20px;flex-shrink:0}.yoast-modal__menu{grid-area:menu;border-left:var(--yoast-border-default);overflow-y:auto}.yoast-modal__menu ul{padding:0;margin:0;list-style:none}.yoast-modal__menu li{padding:12px 16px 11px;border-bottom:var(--yoast-border-default);font-size:16px;cursor:pointer;text-decoration:none;color:var(--yoast-color-default);display:block}.yoast-modal__menu li:hover{background-color:#edd4e1}.yoast-modal__menu li.yoast-tabs__tab--selected{background-color:var(--yoast-color-primary);border-bottom:var(--yoast-border-default);color:#fff}.yoast-modal__content,.yoast-modal__section{grid-area:content;overflow-y:auto;flex-grow:1;position:relative;display:flex;flex-direction:column}.yoast-modal__section *{max-width:600px}.yoast-modal__section-header{position:sticky;top:0;background:var(--yoast-color-white);padding:24px 24px 0;z-index:10}.yoast-modal__section .yoast-h2{border-bottom:var(--yoast-border-default);padding-bottom:24px}.yoast-modal__footer{grid-area:footer;padding:0;border-top:var(--yoast-border-default);display:flex;align-self:flex-end;align-items:center;justify-content:flex-end;position:sticky;bottom:0;background:var(--yoast-color-white);margin:0 24px;z-index:10;box-sizing:border-box;min-height:88px;width:calc(100% - 48px)}.yoast-modal__settings-saved{position:relative;margin-left:16px;display:inline-flex;align-items:center}.yoast-modal__settings-saved:before{content:"";background:var(--yoast-checkmark--green) no-repeat 50%;height:13px;width:14px;display:inline-block;margin-left:8px}.yoast-modal__footer .yoast-button{display:block}.yoast-modal__section-content{padding:24px;flex-grow:1}@media screen and (max-width:880px){.yoast-modal{top:0;bottom:0;right:0;left:0;height:auto}}@media screen and (max-width:782px){.yoast-modal{overflow-y:initial}.yoast-modal.yoast-modal-collapsible{padding-bottom:72px}.yoast-tabs .yoast-modal__content{grid-template-rows:48px 1fr 72px}.yoast-modal__heading{padding:0 16px;position:fixed;top:0;width:100%;min-height:48px;z-index:11}.yoast-modal__heading h1{font-size:var(--yoast-font-size-default)}.yoast-close svg{width:10px}.yoast-modal__heading-icon{height:15px;margin-left:8px}.yoast .yoast-close{left:3px}.yoast-modal__heading .yoast-h2{font-size:var(--yoast-font-size-default)}.yoast-modal__section{overflow:initial;flex-grow:0}.yoast-modal__section-content{padding:24px 0;margin:0 16px}.yoast-modal__section:first-of-type{margin-top:48px}.yoast-modal__section:last-of-type{margin-bottom:72px}.yoast-modal__section-header{top:48px;position:sticky;padding:0;margin:0}.yoast-modal__section-open .yoast-modal__section-header{padding-right:0;padding-left:0;margin-right:16px;margin-left:16px}.yoast-modal__section-open{border-bottom:var(--yoast-border-default)}.yoast-modal__footer{width:100%;min-height:72px;margin:0;padding:0 16px;position:fixed;z-index:11}.yoast-modal-collapsible .yoast-modal__footer{min-height:72px}.yoast-modal-collapsible .yoast-modal__section-content{padding:24px 16px;border-bottom:var(--yoast-border-default);margin:0}.yoast-collapsible__hidden{display:none}.yoast-collapsible__trigger{padding:16px;border:none;border-bottom:var(--yoast-border-default);cursor:pointer;justify-content:space-between;font-size:var(--yoast-font-size-default);width:100%;text-align:right;background:#fff;color:var(--yoast-color-primary)}.yoast-collapsible__trigger[aria-expanded=true] .yoast-collapsible__icon{transform:rotate(-180deg)}.yoast-collapsible__trigger[aria-expanded=true]{padding:16px 0;width:calc(100% - 32px);margin:0 16px}.yoast-collapsible__icon{background-color:var(--yoast-color-white);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='%23404040'%3E%3Cpath d='M1.4 0L6 4.6 10.6 0 12 1.4 6 7.5 0 1.4z'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:10px auto;width:19px;height:19px;border:none;display:block;float:left}.yoast-collapsible-block{width:100%;margin-top:48px}.yoast-collapsible-block+.yoast-collapsible-block{margin-top:0}}.yoast-post-settings-modal{width:880px;height:100%;max-width:calc(100% - 96px);max-height:calc(100% - 96px);overflow:hidden}.yoast-modal-content{padding:16px}@media (min-width:782px){.yoast-modal-content--columns{display:grid;grid-template-columns:1fr 1fr;grid-gap:24px}}.yoast-post-settings-modal__button-container{padding:16px;display:flex;flex-direction:column;border-bottom:1px solid rgba(0,0,0,.2)}.yoast-post-settings-modal .components-modal__content{padding:0;display:flex;flex-direction:column}.yoast-post-settings-modal .components-modal__header{margin:0;flex-shrink:0;border-bottom:var(--yoast-border-default)}.yoast-post-settings-modal .yoast-notice-container{z-index:1;position:sticky;bottom:0;right:0;width:100%;margin-top:auto}.yoast-post-settings-modal .yoast-notice-container>hr{margin-top:-1px;margin-bottom:0}.yoast-post-settings-modal .yoast-content-container{overflow-y:auto;flex-grow:1}.yoast-post-settings-modal .yoast-button-container{display:flex;flex-direction:row;justify-content:flex-end;padding:24px;margin:0}.yoast-post-settings-modal .yoast-button-container p{color:var(--yoast-color-label-help);padding-left:24px;align-self:center}.yoast-post-settings-modal .yoast-button-container button{flex-shrink:0;max-height:45px;align-self:center}@media only screen and (max-width:600px){.yoast-post-settings-modal{max-height:100%;max-width:100%}.yoast-post-settings-modal .yoast-button-container{padding:16px;justify-content:space-between}.yoast-post-settings-modal .yoast-button-container p{padding-left:0}}.yoast-related-keyphrases-modal{max-width:712px}#yoast-get-related-keyphrases-metabox,#yoast-get-related-keyphrases-sidebar{margin-top:8px}.yoast-gutenberg-modal .yoast-related-keyphrases-modal__content{min-height:66vh;position:relative}#yoast-semrush-country-selector{position:relative;border:none}.yoast-related-keyphrases-modal__chart{display:block}.draftJsMentionPlugin__mention__29BEd,.draftJsMentionPlugin__mention__29BEd:visited{color:#575f67;cursor:pointer;display:inline-block;background:#e6f3ff;padding-right:2px;padding-left:2px;border-radius:2px;text-decoration:none}.draftJsMentionPlugin__mention__29BEd:focus,.draftJsMentionPlugin__mention__29BEd:hover{color:#677584;background:#edf5fd;outline:0}.draftJsMentionPlugin__mention__29BEd:active{color:#222;background:#455261}.draftJsMentionPlugin__mentionSuggestionsEntry__3mSwm{padding:7px 10px 3px;transition:background-color .4s cubic-bezier(.27,1.27,.48,.56)}.draftJsMentionPlugin__mentionSuggestionsEntry__3mSwm:active{background-color:#cce7ff}.draftJsMentionPlugin__mentionSuggestionsEntryFocused__3LcTd{background-color:#e6f3ff}.draftJsMentionPlugin__mentionSuggestionsEntryText__3Jobq{display:inline-block;margin-right:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:368px;font-size:.9em;margin-bottom:.2em}.draftJsMentionPlugin__mentionSuggestionsEntryAvatar__1xgA9{display:inline-block;width:24px;height:24px;border-radius:12px}.draftJsMentionPlugin__mentionSuggestions__2DWjA{border:1px solid #eee;margin-top:.4em;position:absolute;min-width:220px;max-width:440px;background:#fff;border-radius:2px;box-shadow:0 4px 30px 0 #dcdcdc;cursor:pointer;padding-top:8px;padding-bottom:8px;z-index:2;display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column;box-sizing:border-box;-webkit-transform:scale(0);transform:scale(0)}.DraftEditor-editorContainer,.DraftEditor-root,.public-DraftEditor-content{height:inherit;text-align:initial}.public-DraftEditor-content[contenteditable=true]{-webkit-user-modify:read-write-plaintext-only}.DraftEditor-root{position:relative}.DraftEditor-editorContainer{background-color:hsla(0,0%,100%,0);border-left:.1px solid transparent;position:relative;z-index:1}.public-DraftEditor-block{position:relative}.DraftEditor-alignLeft .public-DraftStyleDefault-block{text-align:left}.DraftEditor-alignLeft .public-DraftEditorPlaceholder-root{left:0;text-align:left}.DraftEditor-alignCenter .public-DraftStyleDefault-block{text-align:center}.DraftEditor-alignCenter .public-DraftEditorPlaceholder-root{margin:0 auto;text-align:center;width:100%}.DraftEditor-alignRight .public-DraftStyleDefault-block{text-align:right}.DraftEditor-alignRight .public-DraftEditorPlaceholder-root{right:0;text-align:right}.public-DraftEditorPlaceholder-root{color:#9197a3;position:absolute;z-index:1}.public-DraftEditorPlaceholder-hasFocus{color:#bdc1c9}.DraftEditorPlaceholder-hidden{display:none}.public-DraftStyleDefault-block{position:relative;white-space:pre-wrap}.public-DraftStyleDefault-ltr{direction:ltr;text-align:left}.public-DraftStyleDefault-rtl{direction:rtl;text-align:right}.public-DraftStyleDefault-listLTR{direction:ltr}.public-DraftStyleDefault-listRTL{direction:rtl}.public-DraftStyleDefault-ol,.public-DraftStyleDefault-ul{margin:16px 0;padding:0}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR{margin-left:1.5em}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listRTL{margin-right:1.5em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listLTR{margin-left:3em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listRTL{margin-right:3em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listLTR{margin-left:4.5em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listRTL{margin-right:4.5em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listLTR{margin-left:6em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listRTL{margin-right:6em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listLTR{margin-left:7.5em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listRTL{margin-right:7.5em}.public-DraftStyleDefault-unorderedListItem{list-style-type:square;position:relative}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth0{list-style-type:disc}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth1{list-style-type:circle}.public-DraftStyleDefault-orderedListItem{list-style-type:none;position:relative}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR:before{left:-36px;position:absolute;text-align:right;width:30px}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listRTL:before{position:absolute;right:-36px;text-align:left;width:30px}.public-DraftStyleDefault-orderedListItem:before{content:counter(ol0) ". ";counter-increment:ol0}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth1:before{content:counter(ol1) ". ";counter-increment:ol1}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth2:before{content:counter(ol2) ". ";counter-increment:ol2}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth3:before{content:counter(ol3) ". ";counter-increment:ol3}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth4:before{content:counter(ol4) ". ";counter-increment:ol4}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-reset{counter-reset:ol0}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-reset{counter-reset:ol1}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-reset{counter-reset:ol2}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-reset{counter-reset:ol3}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset{counter-reset:ol4}#wpseo_meta{box-sizing:border-box}#wpseo_meta *,#wpseo_meta :after,#wpseo_meta :before{box-sizing:inherit}.DraftEditor-root [data-block]{margin:0}#edittag>#wp-description-wrap{display:none}#wp-description-wrap .wp-editor-area{border:0}.term-description-wrap td>textarea#description{min-height:530px}ul.wpseo-metabox-tabs{display:none;margin-top:6px;margin-bottom:0}ul.wpseo-metabox-tabs:after{content:"";display:table;clear:both}.wpseo-metabox-tabs-div{margin:0 5px 5px}.wpseo-metabox-tabs-div ul{list-style:none}#wpseo-meta-section-addons{padding:0 5px 5px}#wpseo-meta-section-addons .wpseo-metabox-tabs-div{margin:0}ul.wpseo-metabox-tabs li.active{background-color:#fdfdfd}.wpseo-meta-section,.wpseo-meta-section-react{display:none;max-width:600px;width:100%;min-height:100%;height:auto;vertical-align:top;border:1px solid rgba(0,0,0,.2)}.wpseo-meta-section-react.active,.wpseo-meta-section.active{background:#fff;position:relative;z-index:12}.wpseo-meta-section.active{display:inline-block}.wpseo-meta-section-react.active{display:block;margin-bottom:10px}.wpseo-meta-section-content{padding:16px}.wpseo-metabox-content{max-width:800px;padding-top:16px}.wpseo-metabox-menu{max-width:600px;padding:0;background-color:#fff}.wpseo-metabox-menu ul{margin:0 0 0 1px;padding:0 16px 0 0;display:flex;align-items:flex-end;flex-wrap:wrap;flex-flow:wrap-reverse}.wpseo-metabox-menu ul li:first-child{z-index:10}.wpseo-metabox-menu ul li:nth-child(2){z-index:9}.wpseo-metabox-menu ul li:nth-child(3){z-index:8}.wpseo-metabox-menu ul li:nth-child(4){z-index:7}.wpseo-metabox-menu ul li:nth-child(5){z-index:6}.wpseo-metabox-menu ul li:nth-child(6){z-index:5}.wpseo-metabox-menu ul li{box-shadow:0 0 4px 0 rgba(0,0,0,.1);height:32px;margin-right:-1px;margin-bottom:-1px;text-align:center;position:relative;background-color:#f8f8f8}.wpseo-metabox-menu ul li a{color:#0073aa;display:flex;align-items:center;border:1px solid rgba(0,0,0,.2);border-bottom:2px transparent}.wpseo-metabox-menu ul li a:focus{box-shadow:inherit}.wpseo-metabox-menu ul li .yst-traffic-light{height:20px;width:auto;margin-left:10px;margin-right:4px}.wpseo-metabox-menu ul li span.dashicons{margin-left:8px}.wpseo-metabox-menu ul li span.wpseo-buy-premium{color:#a4286a}.wpseo-metabox-menu ul li span.wpseo-buy-premium:hover{color:#832055}.wpseo-metabox-menu ul li.active{height:36px;margin-top:-4px;z-index:13;background-color:#fff;border-bottom:2px transparent;box-shadow:none}.wpseo-metabox-menu ul li.active a{height:36px;color:#444}.wpseo-metabox-menu ul li.active span.wpseo-buy-premium{color:#a4286a;border-color:#a4286a}.wpseo-metabox-menu ul li.active span.wpseo-buy-premium:hover{color:#832055;border-color:#832055}.wpseo-metabox-menu a{height:32px;padding:0 8px;text-decoration:none}ul.wpseo-metabox-tabs li{float:right;margin-left:5px;margin-bottom:-1px;padding:0;border:1px solid #dfdfdf;border-bottom:0}ul.wpseo-metabox-tabs li .wpseo-keyword{display:inline-block;vertical-align:top;max-width:8em;max-width:8rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.wpseotab{display:none;padding:16px;border:1px solid #ddd;background-color:#fdfdfd}.wpseotab .wpseo-cornerstone-checkbox{margin-left:.5em}.wpseotab.content{padding:20px 15px}.wpseotab.active{display:block}.wpseo-metabox-tabs .wpseo_tablink{display:inline-block;vertical-align:top;padding:5px 12px 6px;text-decoration:none}.wpseo-metabox-tabs .wpseo_content_tab a{padding-left:12px}.wpseo-metabox-tabs .wpseo-score-icon{margin-right:0}#wpseo-meta-section-social .wpseo-metabox-tabs .wpseo_tablink{padding:5px 7px}.wpseo-metabox-tabs .wpseo_tablink .dashicons{width:16px;height:16px;font-size:16px}.wpseo-metabox-sidebar .dashicons{width:30px;height:30px;font-size:30px}.wpseo-metabox-tabs-div div.wpseo-tabs-panel{overflow:auto;padding:.5em .9em;border:1px solid}#wpseo_meta .inside{margin:0}#wpseo_meta .inside:after{content:"";display:table;clear:both}#wpseo_meta .postbox .inside .wpseotab{font-size:13px!important}.wpseo-form .select2-container,.wpseo-form input,.wpseo-form label,.wpseo-form p.error-message,.wpseo-form textarea{max-width:600px}.wpseo-form fieldset{padding-top:5px}.wpseo-form legend{font-weight:600}.wpseo-form label{display:block;font-weight:600}.wpseo-form input[type=checkbox]+label,.wpseo-form input[type=radio]+label{display:inline-block;font-weight:400}.wpseo-form fieldset,.wpseo-form label{margin-top:2em;margin-bottom:.5em}.wpseo-form input[type=checkbox],.wpseo-form input[type=checkbox]+label{margin-top:2em;margin-bottom:0;font-size:1em}.wpseo-form fieldset:first-child,.wpseo-form input[type=checkbox]:first-child,.wpseo-form input[type=checkbox]:first-child+label,.wpseo-form label:first-child{margin-top:10px}.wpseo-form input[type=radio]{margin-top:0}.wpseo-form input[type=radio]+label{margin:0 0 0 1em}.wpseo-form p.error-message{margin:.5em 0}.wpseo-form select[multiple]{margin-top:0}.yoast-metabox__description{max-width:600px;margin:.5em 0}.wpseo_image_upload_button{margin-right:3px}.good,.warn,.wrong{font-weight:600}.good{color:green}.warn{color:maroon}.wrong{color:#dc3232}#current_seo_title span{padding:2px 5px;background-color:#ffffe0}#focuskwresults ul{margin:0}#focuskwresults li,#focuskwresults p{font-size:13px}#focuskwresults li{margin:0 20px 0 0;list-style-type:disc}.wpseo_hidden{display:none}.wpseo_msg{margin:5px 0 10px;padding:0 5px;border:1px solid #e6db55;background-color:#ffffe0}ul.wpseo-metabox-tabs li.wpseo-tab-add-keyword{border:1px dashed #dfdfdf;border-bottom:none}.wpseo-tab-add-keyword .wpseo-add-keyword.button{height:auto;padding:5px 10px 5px 12px;vertical-align:top;font-size:inherit;line-height:inherit;font-weight:700;box-shadow:none;background:none;text-decoration:none}.wpseo-tab-add-keyword .wpseo-add-keyword.button:focus{box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.wpseo-tab-add-keyword .wpseo-add-keyword.button:active{transform:none}.wpseo-add-keyword-plus{display:inline-block;vertical-align:top;margin:-1px 0 0 3px;font-size:20px}#wpseo-add-keyword-popup-title{margin:1em 0;font-size:1.3em}.snippet-editor__button.snippet-editor__edit-button:focus{border-color:#5b9dd9;outline:none;color:#23282d;background-color:#fafafa;box-shadow:0 0 3px rgba(0,115,170,.8)}.wpseo-admin-page .subsubsub li{display:inline;max-width:none}.yoast-seo-help-container{float:right;width:100%;max-width:none}.yoast-seo-help-container .yoast-help-panel{margin:.5em 0!important}.wpseo_content_wrapper p.search-box{margin:10px 0 5px}.wpseo-metabox-tabs .active a{color:#333}#wpseotab .ui-widget-content .ui-state-hover{border:1px solid #dfdfdf;color:#333;background:#f1f1f1}.yst-traffic-light{width:19px;height:30px;margin:0 5px 0 0}.yst-traffic-light .traffic-light-color{display:none}.yst-traffic-light.bad .traffic-light-red,.yst-traffic-light.good .traffic-light-green,.yst-traffic-light.init .traffic-light-init,.yst-traffic-light.na .traffic-light-empty,.yst-traffic-light.ok .traffic-light-orange{display:inline}.yoast-seo-score .yoast-logo.svg{float:right;width:18px;margin-left:7px;height:18px;background:var(--yoast-svg-icon-yoast) no-repeat;background-size:18px}.yoast-seo-score .yoast-logo.svg.good{background-image:var(--yoast-svg-icon-yoast-good)}.yoast-seo-score .yoast-logo.svg.ok{background-image:var(--yoast-svg-icon-yoast-ok)}.yoast-seo-score .yoast-logo.svg.bad{background-image:var(--yoast-svg-icon-yoast-bad)}.yoast-seo-score .yoast-logo.svg.na,.yoast-seo-score .yoast-logo.svg.noindex{background-image:var(--yoast-svg-icon-yoast)}.term-php .wpseo-taxonomy-metabox-postbox>h2{margin:0;padding:8px 12px;border-bottom:1px solid #eee;font-size:14px;line-height:1.4}#TB_window #TB_ajaxContent p{padding:5px 0 0;margin:5px 0 0}#TB_window #TB_ajaxContent ul{margin:5px 0 10px}#TB_window #TB_ajaxContent li{list-style:none;margin:5px 0 0}#TB_window #TB_ajaxContent li:before{content:"+";margin:0 0 0 10px;font-weight:700}.yoast-section__heading-icon-list{background-image:var(--yoast-svg-icon-list)}.yoast-section__heading-icon-key{background-image:var(--yoast-svg-icon-key)}.yoast-section__heading-icon-edit{background-image:var(--yoast-svg-icon-edit)}.yoast-tooltip.yoast-tooltip-hidden:after,.yoast-tooltip.yoast-tooltip-hidden:before{display:none}.screen-reader-text.wpseo-generic-tab-textual-score,.screen-reader-text.wpseo-keyword-tab-textual-score{display:block}.yoast-notice-go-premium{border-right-color:#a4286a;background:#f1f1f1;margin:0}.editor-styles-wrapper mark.annotation-text-yoast{background-color:#e1bee7}@media screen and (max-width:782px){.wpseo-metabox-buy-premium .wpseo-buy-premium{display:inline-block;width:20px;height:20px;margin-left:5px;padding:0}.yoast-help-panel{max-width:none!important}#wpseo-crawl-issues-table-form .subsubsub{float:none;max-width:calc(100vw - 20px)}#wpseo-crawl-issues-table-form .yoast-help-button{margin-top:3px}.wpseotab select[multiple]{height:auto!important}}@media screen and (max-width:600px){.wpseotab.content{padding:16px 0}}.wpseo-score-icon-container{height:20px;width:20px;margin-left:8px;display:flex;justify-content:center;align-items:center}.yoast-seo-sidebar-panel div{line-height:2}.yoast-seo-sidebar-panel div svg{vertical-align:middle}ul.yoast-seo-social-share-buttons li{display:inline-block;margin-left:16px}ul.yoast-seo-social-share-buttons svg{width:32px;height:32px;margin-bottom:8px}ul.yoast-seo-social-share-buttons a{display:flex;flex-direction:column;align-items:center}.edit-post-pinned-plugins button.components-button[aria-label="Yoast SEO"]>svg,.edit-post-pinned-plugins button.components-button[aria-label="Yoast SEO Premium"]>svg,div.interface-pinned-items button.components-button[aria-label="Yoast SEO"]>svg,div.interface-pinned-items button.components-button[aria-label="Yoast SEO Premium"]>svg{max-width:28px;max-height:28px;width:28px;height:28px}div.interface-pinned-items button.components-button.is-pressed[aria-label="Yoast SEO"]>svg path,div.interface-pinned-items button.components-button.is-pressed[aria-label="Yoast SEO Premium"]>svg path{fill:#fff}.wpseo-schema-icon{height:16px;width:16px;margin-left:8px;display:flex;justify-content:center;align-items:center;background-image:var(--yoast-svg-icon-schema);background-size:cover}.wpseo-metabox-menu ul li.active a .wpseo-schema-icon{background-image:var(--yoast-svg-icon-schema-active)}.yoast-icon-span svg{margin-left:8px;fill:inherit}.yoast.components-panel__body{border-top:0}.components-button>.yoast-title-container{flex-grow:1;overflow-x:hidden;line-height:normal}.yoast-title-container>.yoast-title{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.yoast-title-container>.yoast-subtitle{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-size:.8125rem;font-weight:300;margin-top:2px}.yoast.components-panel__body .yoast-chevron{background-color:#1e1e1e;-webkit-mask-image:var(--yoast-svg-icon-chevron-down);mask-image:var(--yoast-svg-icon-chevron-down);-webkit-mask-size:100% 100%;mask-size:100% 100%;display:inline-block;width:24px;height:24px}.yoast.components-panel__body.is-opened .yoast-chevron{-webkit-mask-image:var(--yoast-svg-icon-chevron-up);mask-image:var(--yoast-svg-icon-chevron-up)}.yoast .components-form-token-field__remove-token.components-button,.yoast .components-form-token-field__token-text{background-color:var(--yoast-color-primary);color:var(--yoast-color-white)} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/metabox-1720.css b/wp-content/plugins/wordpress-seo/css/dist/metabox-1720.css new file mode 100644 index 00000000..44ddafa2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/metabox-1720.css @@ -0,0 +1,3 @@ +:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")}.yoast-modal__screen-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background-color:rgba(164,40,106,.6);z-index:100000;animation:edit-post__fade-in-animation .2s ease-out 0s;animation-fill-mode:forwards}.yoast-modal{background:#fff;display:flex;flex-direction:column;overflow:hidden;position:fixed;height:calc(100% - 96px);top:48px;bottom:48px;left:calc(50% - 440px);max-width:880px;width:100%}.yoast-gutenberg-modal .yoast-icon{background-color:var(--yoast-color-primary);mask-image:var(--yoast-svg-icon-yoast);-webkit-mask-image:var(--yoast-svg-icon-yoast);mask-size:100% 100%;-webkit-mask-size:100% 100%;display:inline-block;width:20px;height:20px;margin-right:8px}.yoast-tabs .yoast-modal__content{display:grid;grid-template-areas:"heading heading" "menu content" "menu footer";grid-template-rows:72px 1fr 88px;grid-template-columns:280px 1fr}.yoast-modal__heading{display:flex;align-items:center;box-sizing:border-box;min-height:72px;border-bottom:var(--yoast-border-default);padding:0 24px;grid-area:heading;background:var(--yoast-color-white)}.yoast-modal__heading .yoast-close{position:absolute;right:16px}.yoast-gutenberg-modal .components-modal__header-heading,.yoast-modal__heading h1{font-size:20px;font-weight:400;color:var(--yoast-color-primary);line-height:1.2;margin:0}.yoast-gutenberg-modal .components-modal__icon-container{display:inline-flex}.yoast-gutenberg-modal .components-modal__icon-container svg,.yoast-modal__heading-icon{fill:var(--yoast-color-primary);margin-right:16px;width:19px;height:20px;flex-shrink:0}.yoast-modal__menu{grid-area:menu;border-right:var(--yoast-border-default);overflow-y:auto}.yoast-modal__menu ul{padding:0;margin:0;list-style:none}.yoast-modal__menu li{padding:12px 16px 11px;border-bottom:var(--yoast-border-default);font-size:16px;cursor:pointer;text-decoration:none;color:var(--yoast-color-default);display:block}.yoast-modal__menu li:hover{background-color:#edd4e1}.yoast-modal__menu li.yoast-tabs__tab--selected{background-color:var(--yoast-color-primary);border-bottom:var(--yoast-border-default);color:#fff}.yoast-modal__content,.yoast-modal__section{grid-area:content;overflow-y:auto;flex-grow:1;position:relative;display:flex;flex-direction:column}.yoast-modal__section *{max-width:600px}.yoast-modal__section-header{position:sticky;top:0;background:var(--yoast-color-white);padding:24px 24px 0;z-index:10}.yoast-modal__section .yoast-h2{border-bottom:var(--yoast-border-default);padding-bottom:24px}.yoast-modal__footer{grid-area:footer;padding:0;border-top:var(--yoast-border-default);display:flex;align-self:flex-end;align-items:center;justify-content:flex-end;position:sticky;bottom:0;background:var(--yoast-color-white);margin:0 24px;z-index:10;box-sizing:border-box;min-height:88px;width:calc(100% - 48px)}.yoast-modal__settings-saved{position:relative;margin-right:16px;display:inline-flex;align-items:center}.yoast-modal__settings-saved:before{content:"";background:var(--yoast-checkmark--green) no-repeat 50%;height:13px;width:14px;display:inline-block;margin-right:8px}.yoast-modal__footer .yoast-button{display:block}.yoast-modal__section-content{padding:24px;flex-grow:1}@media screen and (max-width:880px){.yoast-modal{top:0;bottom:0;left:0;right:0;height:auto}}@media screen and (max-width:782px){.yoast-modal{overflow-y:initial}.yoast-modal.yoast-modal-collapsible{padding-bottom:72px}.yoast-tabs .yoast-modal__content{grid-template-rows:48px 1fr 72px}.yoast-modal__heading{padding:0 16px;position:fixed;top:0;width:100%;min-height:48px;z-index:11}.yoast-modal__heading h1{font-size:var(--yoast-font-size-default)}.yoast-close svg{width:10px}.yoast-modal__heading-icon{height:15px;margin-right:8px}.yoast .yoast-close{right:3px}.yoast-modal__heading .yoast-h2{font-size:var(--yoast-font-size-default)}.yoast-modal__section{overflow:initial;flex-grow:0}.yoast-modal__section-content{padding:24px 0;margin:0 16px}.yoast-modal__section:first-of-type{margin-top:48px}.yoast-modal__section:last-of-type{margin-bottom:72px}.yoast-modal__section-header{top:48px;position:sticky;padding:0;margin:0}.yoast-modal__section-open .yoast-modal__section-header{padding-left:0;padding-right:0;margin-left:16px;margin-right:16px}.yoast-modal__section-open{border-bottom:var(--yoast-border-default)}.yoast-modal__footer{width:100%;min-height:72px;margin:0;padding:0 16px;position:fixed;z-index:11}.yoast-modal-collapsible .yoast-modal__footer{min-height:72px}.yoast-modal-collapsible .yoast-modal__section-content{padding:24px 16px;border-bottom:var(--yoast-border-default);margin:0}.yoast-collapsible__hidden{display:none}.yoast-collapsible__trigger{padding:16px;border:none;border-bottom:var(--yoast-border-default);cursor:pointer;justify-content:space-between;font-size:var(--yoast-font-size-default);width:100%;text-align:left;background:#fff;color:var(--yoast-color-primary)}.yoast-collapsible__trigger[aria-expanded=true] .yoast-collapsible__icon{transform:rotate(180deg)}.yoast-collapsible__trigger[aria-expanded=true]{padding:16px 0;width:calc(100% - 32px);margin:0 16px}.yoast-collapsible__icon{background-color:var(--yoast-color-white);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='%23404040'%3E%3Cpath d='M1.4 0L6 4.6 10.6 0 12 1.4 6 7.5 0 1.4z'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:10px auto;width:19px;height:19px;border:none;display:block;float:right}.yoast-collapsible-block{width:100%;margin-top:48px}.yoast-collapsible-block+.yoast-collapsible-block{margin-top:0}}.yoast-post-settings-modal{width:880px;height:100%;max-width:calc(100% - 96px);max-height:calc(100% - 96px);overflow:hidden}.yoast-modal-content{padding:16px}@media (min-width:782px){.yoast-modal-content--columns{display:grid;grid-template-columns:1fr 1fr;grid-gap:24px}}.yoast-post-settings-modal__button-container{padding:16px;display:flex;flex-direction:column;border-bottom:1px solid rgba(0,0,0,.2)}.yoast-post-settings-modal .components-modal__content{padding:0;display:flex;flex-direction:column}.yoast-post-settings-modal .components-modal__header{margin:0;flex-shrink:0;border-bottom:var(--yoast-border-default)}.yoast-post-settings-modal .yoast-notice-container{z-index:1;position:sticky;bottom:0;left:0;width:100%;margin-top:auto}.yoast-post-settings-modal .yoast-notice-container>hr{margin-top:-1px;margin-bottom:0}.yoast-post-settings-modal .yoast-content-container{overflow-y:auto;flex-grow:1}.yoast-post-settings-modal .yoast-button-container{display:flex;flex-direction:row;justify-content:flex-end;padding:24px;margin:0}.yoast-post-settings-modal .yoast-button-container p{color:var(--yoast-color-label-help);padding-right:24px;align-self:center}.yoast-post-settings-modal .yoast-button-container button{flex-shrink:0;max-height:45px;align-self:center}@media only screen and (max-width:600px){.yoast-post-settings-modal{max-height:100%;max-width:100%}.yoast-post-settings-modal .yoast-button-container{padding:16px;justify-content:space-between}.yoast-post-settings-modal .yoast-button-container p{padding-right:0}}.yoast-related-keyphrases-modal{max-width:712px}#yoast-get-related-keyphrases-metabox,#yoast-get-related-keyphrases-sidebar{margin-top:8px}.yoast-gutenberg-modal .yoast-related-keyphrases-modal__content{min-height:66vh;position:relative}#yoast-semrush-country-selector{position:relative;border:none}.yoast-related-keyphrases-modal__chart{display:block}.draftJsMentionPlugin__mention__29BEd,.draftJsMentionPlugin__mention__29BEd:visited{color:#575f67;cursor:pointer;display:inline-block;background:#e6f3ff;padding-left:2px;padding-right:2px;border-radius:2px;text-decoration:none}.draftJsMentionPlugin__mention__29BEd:focus,.draftJsMentionPlugin__mention__29BEd:hover{color:#677584;background:#edf5fd;outline:0}.draftJsMentionPlugin__mention__29BEd:active{color:#222;background:#455261}.draftJsMentionPlugin__mentionSuggestionsEntry__3mSwm{padding:7px 10px 3px;transition:background-color .4s cubic-bezier(.27,1.27,.48,.56)}.draftJsMentionPlugin__mentionSuggestionsEntry__3mSwm:active{background-color:#cce7ff}.draftJsMentionPlugin__mentionSuggestionsEntryFocused__3LcTd{background-color:#e6f3ff}.draftJsMentionPlugin__mentionSuggestionsEntryText__3Jobq{display:inline-block;margin-left:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:368px;font-size:.9em;margin-bottom:.2em}.draftJsMentionPlugin__mentionSuggestionsEntryAvatar__1xgA9{display:inline-block;width:24px;height:24px;border-radius:12px}.draftJsMentionPlugin__mentionSuggestions__2DWjA{border:1px solid #eee;margin-top:.4em;position:absolute;min-width:220px;max-width:440px;background:#fff;border-radius:2px;box-shadow:0 4px 30px 0 #dcdcdc;cursor:pointer;padding-top:8px;padding-bottom:8px;z-index:2;display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-direction:column;box-sizing:border-box;-webkit-transform:scale(0);transform:scale(0)} +/*!rtl:begin:ignore*/.DraftEditor-editorContainer,.DraftEditor-root,.public-DraftEditor-content{height:inherit;text-align:initial}.public-DraftEditor-content[contenteditable=true]{-webkit-user-modify:read-write-plaintext-only}.DraftEditor-root{position:relative}.DraftEditor-editorContainer{background-color:hsla(0,0%,100%,0);border-left:.1px solid transparent;position:relative;z-index:1}.public-DraftEditor-block{position:relative}.DraftEditor-alignLeft .public-DraftStyleDefault-block{text-align:left}.DraftEditor-alignLeft .public-DraftEditorPlaceholder-root{left:0;text-align:left}.DraftEditor-alignCenter .public-DraftStyleDefault-block{text-align:center}.DraftEditor-alignCenter .public-DraftEditorPlaceholder-root{margin:0 auto;text-align:center;width:100%}.DraftEditor-alignRight .public-DraftStyleDefault-block{text-align:right}.DraftEditor-alignRight .public-DraftEditorPlaceholder-root{right:0;text-align:right}.public-DraftEditorPlaceholder-root{color:#9197a3;position:absolute;z-index:1}.public-DraftEditorPlaceholder-hasFocus{color:#bdc1c9}.DraftEditorPlaceholder-hidden{display:none}.public-DraftStyleDefault-block{position:relative;white-space:pre-wrap}.public-DraftStyleDefault-ltr{direction:ltr;text-align:left}.public-DraftStyleDefault-rtl{direction:rtl;text-align:right}.public-DraftStyleDefault-listLTR{direction:ltr}.public-DraftStyleDefault-listRTL{direction:rtl}.public-DraftStyleDefault-ol,.public-DraftStyleDefault-ul{margin:16px 0;padding:0}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR{margin-left:1.5em}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listRTL{margin-right:1.5em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listLTR{margin-left:3em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listRTL{margin-right:3em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listLTR{margin-left:4.5em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listRTL{margin-right:4.5em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listLTR{margin-left:6em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listRTL{margin-right:6em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listLTR{margin-left:7.5em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listRTL{margin-right:7.5em}.public-DraftStyleDefault-unorderedListItem{list-style-type:square;position:relative}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth0{list-style-type:disc}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth1{list-style-type:circle}.public-DraftStyleDefault-orderedListItem{list-style-type:none;position:relative}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR:before{left:-36px;position:absolute;text-align:right;width:30px}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listRTL:before{position:absolute;right:-36px;text-align:left;width:30px}.public-DraftStyleDefault-orderedListItem:before{content:counter(ol0) ". ";counter-increment:ol0}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth1:before{content:counter(ol1) ". ";counter-increment:ol1}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth2:before{content:counter(ol2) ". ";counter-increment:ol2}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth3:before{content:counter(ol3) ". ";counter-increment:ol3}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth4:before{content:counter(ol4) ". ";counter-increment:ol4}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-reset{counter-reset:ol0}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-reset{counter-reset:ol1}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-reset{counter-reset:ol2}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-reset{counter-reset:ol3}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset{counter-reset:ol4} +/*!rtl:end:ignore*/#wpseo_meta{box-sizing:border-box}#wpseo_meta *,#wpseo_meta :after,#wpseo_meta :before{box-sizing:inherit}.DraftEditor-root [data-block]{margin:0}#edittag>#wp-description-wrap{display:none}#wp-description-wrap .wp-editor-area{border:0}.term-description-wrap td>textarea#description{min-height:530px}ul.wpseo-metabox-tabs{display:none;margin-top:6px;margin-bottom:0}ul.wpseo-metabox-tabs:after{content:"";display:table;clear:both}.wpseo-metabox-tabs-div{margin:0 5px 5px}.wpseo-metabox-tabs-div ul{list-style:none}#wpseo-meta-section-addons{padding:0 5px 5px}#wpseo-meta-section-addons .wpseo-metabox-tabs-div{margin:0}ul.wpseo-metabox-tabs li.active{background-color:#fdfdfd}.wpseo-meta-section,.wpseo-meta-section-react{display:none;max-width:600px;width:100%;min-height:100%;height:auto;vertical-align:top;border:1px solid rgba(0,0,0,.2)}.wpseo-meta-section-react.active,.wpseo-meta-section.active{background:#fff;position:relative;z-index:12}.wpseo-meta-section.active{display:inline-block}.wpseo-meta-section-react.active{display:block;margin-bottom:10px}.wpseo-meta-section-content{padding:16px}.wpseo-metabox-content{max-width:800px;padding-top:16px}.wpseo-metabox-menu{max-width:600px;padding:0;background-color:#fff}.wpseo-metabox-menu ul{margin:0 1px 0 0;padding:0 0 0 16px;display:flex;align-items:flex-end;flex-wrap:wrap;flex-flow:wrap-reverse}.wpseo-metabox-menu ul li:first-child{z-index:10}.wpseo-metabox-menu ul li:nth-child(2){z-index:9}.wpseo-metabox-menu ul li:nth-child(3){z-index:8}.wpseo-metabox-menu ul li:nth-child(4){z-index:7}.wpseo-metabox-menu ul li:nth-child(5){z-index:6}.wpseo-metabox-menu ul li:nth-child(6){z-index:5}.wpseo-metabox-menu ul li{box-shadow:0 0 4px 0 rgba(0,0,0,.1);height:32px;margin-left:-1px;margin-bottom:-1px;text-align:center;position:relative;background-color:#f8f8f8}.wpseo-metabox-menu ul li a{color:#0073aa;display:flex;align-items:center;border:1px solid rgba(0,0,0,.2);border-bottom:2px transparent}.wpseo-metabox-menu ul li a:focus{box-shadow:inherit}.wpseo-metabox-menu ul li .yst-traffic-light{height:20px;width:auto;margin-right:10px;margin-left:4px}.wpseo-metabox-menu ul li span.dashicons{margin-right:8px}.wpseo-metabox-menu ul li span.wpseo-buy-premium{color:#a4286a}.wpseo-metabox-menu ul li span.wpseo-buy-premium:hover{color:#832055}.wpseo-metabox-menu ul li.active{height:36px;margin-top:-4px;z-index:13;background-color:#fff;border-bottom:2px transparent;box-shadow:none}.wpseo-metabox-menu ul li.active a{height:36px;color:#444}.wpseo-metabox-menu ul li.active span.wpseo-buy-premium{color:#a4286a;border-color:#a4286a}.wpseo-metabox-menu ul li.active span.wpseo-buy-premium:hover{color:#832055;border-color:#832055}.wpseo-metabox-menu a{height:32px;padding:0 8px;text-decoration:none}ul.wpseo-metabox-tabs li{float:left;margin-right:5px;margin-bottom:-1px;padding:0;border:1px solid #dfdfdf;border-bottom:0}ul.wpseo-metabox-tabs li .wpseo-keyword{display:inline-block;vertical-align:top;max-width:8em;max-width:8rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.wpseotab{display:none;padding:16px;border:1px solid #ddd;background-color:#fdfdfd}.wpseotab .wpseo-cornerstone-checkbox{margin-right:.5em}.wpseotab.content{padding:20px 15px}.wpseotab.active{display:block}.wpseo-metabox-tabs .wpseo_tablink{display:inline-block;vertical-align:top;padding:5px 12px 6px;text-decoration:none}.wpseo-metabox-tabs .wpseo_content_tab a{padding-right:12px}.wpseo-metabox-tabs .wpseo-score-icon{margin-left:0}#wpseo-meta-section-social .wpseo-metabox-tabs .wpseo_tablink{padding:5px 7px}.wpseo-metabox-tabs .wpseo_tablink .dashicons{width:16px;height:16px;font-size:16px}.wpseo-metabox-sidebar .dashicons{width:30px;height:30px;font-size:30px}.wpseo-metabox-tabs-div div.wpseo-tabs-panel{overflow:auto;padding:.5em .9em;border:1px solid}#wpseo_meta .inside{margin:0}#wpseo_meta .inside:after{content:"";display:table;clear:both}#wpseo_meta .postbox .inside .wpseotab{font-size:13px!important}.wpseo-form .select2-container,.wpseo-form input,.wpseo-form label,.wpseo-form p.error-message,.wpseo-form textarea{max-width:600px}.wpseo-form fieldset{padding-top:5px}.wpseo-form legend{font-weight:600}.wpseo-form label{display:block;font-weight:600}.wpseo-form input[type=checkbox]+label,.wpseo-form input[type=radio]+label{display:inline-block;font-weight:400}.wpseo-form fieldset,.wpseo-form label{margin-top:2em;margin-bottom:.5em}.wpseo-form input[type=checkbox],.wpseo-form input[type=checkbox]+label{margin-top:2em;margin-bottom:0;font-size:1em}.wpseo-form fieldset:first-child,.wpseo-form input[type=checkbox]:first-child,.wpseo-form input[type=checkbox]:first-child+label,.wpseo-form label:first-child{margin-top:10px}.wpseo-form input[type=radio]{margin-top:0}.wpseo-form input[type=radio]+label{margin:0 1em 0 0}.wpseo-form p.error-message{margin:.5em 0}.wpseo-form select[multiple]{margin-top:0}.yoast-metabox__description{max-width:600px;margin:.5em 0}.wpseo_image_upload_button{margin-left:3px}.good,.warn,.wrong{font-weight:600}.good{color:green}.warn{color:maroon}.wrong{color:#dc3232}#current_seo_title span{padding:2px 5px;background-color:#ffffe0}#focuskwresults ul{margin:0}#focuskwresults li,#focuskwresults p{font-size:13px}#focuskwresults li{margin:0 0 0 20px;list-style-type:disc}.wpseo_hidden{display:none}.wpseo_msg{margin:5px 0 10px;padding:0 5px;border:1px solid #e6db55;background-color:#ffffe0}ul.wpseo-metabox-tabs li.wpseo-tab-add-keyword{border:1px dashed #dfdfdf;border-bottom:none}.wpseo-tab-add-keyword .wpseo-add-keyword.button{height:auto;padding:5px 12px 5px 10px;vertical-align:top;font-size:inherit;line-height:inherit;font-weight:700;box-shadow:none;background:none;text-decoration:none}.wpseo-tab-add-keyword .wpseo-add-keyword.button:focus{box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.wpseo-tab-add-keyword .wpseo-add-keyword.button:active{transform:none}.wpseo-add-keyword-plus{display:inline-block;vertical-align:top;margin:-1px 3px 0 0;font-size:20px}#wpseo-add-keyword-popup-title{margin:1em 0;font-size:1.3em}.snippet-editor__button.snippet-editor__edit-button:focus{border-color:#5b9dd9;outline:none;color:#23282d;background-color:#fafafa;box-shadow:0 0 3px rgba(0,115,170,.8)}.wpseo-admin-page .subsubsub li{display:inline;max-width:none}.yoast-seo-help-container{float:left;width:100%;max-width:none}.yoast-seo-help-container .yoast-help-panel{margin:.5em 0!important}.wpseo_content_wrapper p.search-box{margin:10px 0 5px}.wpseo-metabox-tabs .active a{color:#333}#wpseotab .ui-widget-content .ui-state-hover{border:1px solid #dfdfdf;color:#333;background:#f1f1f1}.yst-traffic-light{width:19px;height:30px;margin:0 0 0 5px}.yst-traffic-light .traffic-light-color{display:none}.yst-traffic-light.bad .traffic-light-red,.yst-traffic-light.good .traffic-light-green,.yst-traffic-light.init .traffic-light-init,.yst-traffic-light.na .traffic-light-empty,.yst-traffic-light.ok .traffic-light-orange{display:inline}.yoast-seo-score .yoast-logo.svg{float:left;width:18px;margin-right:7px;height:18px;background:var(--yoast-svg-icon-yoast) no-repeat;background-size:18px}.yoast-seo-score .yoast-logo.svg.good{background-image:var(--yoast-svg-icon-yoast-good)}.yoast-seo-score .yoast-logo.svg.ok{background-image:var(--yoast-svg-icon-yoast-ok)}.yoast-seo-score .yoast-logo.svg.bad{background-image:var(--yoast-svg-icon-yoast-bad)}.yoast-seo-score .yoast-logo.svg.na,.yoast-seo-score .yoast-logo.svg.noindex{background-image:var(--yoast-svg-icon-yoast)}.term-php .wpseo-taxonomy-metabox-postbox>h2{margin:0;padding:8px 12px;border-bottom:1px solid #eee;font-size:14px;line-height:1.4}#TB_window #TB_ajaxContent p{padding:5px 0 0;margin:5px 0 0}#TB_window #TB_ajaxContent ul{margin:5px 0 10px}#TB_window #TB_ajaxContent li{list-style:none;margin:5px 0 0}#TB_window #TB_ajaxContent li:before{content:"+";margin:0 10px 0 0;font-weight:700}.yoast-section__heading-icon-list{background-image:var(--yoast-svg-icon-list)}.yoast-section__heading-icon-key{background-image:var(--yoast-svg-icon-key)}.yoast-section__heading-icon-edit{background-image:var(--yoast-svg-icon-edit)}.yoast-tooltip.yoast-tooltip-hidden:after,.yoast-tooltip.yoast-tooltip-hidden:before{display:none}.screen-reader-text.wpseo-generic-tab-textual-score,.screen-reader-text.wpseo-keyword-tab-textual-score{display:block}.yoast-notice-go-premium{border-left-color:#a4286a;background:#f1f1f1;margin:0}.editor-styles-wrapper mark.annotation-text-yoast{background-color:#e1bee7}@media screen and (max-width:782px){.wpseo-metabox-buy-premium .wpseo-buy-premium{display:inline-block;width:20px;height:20px;margin-right:5px;padding:0}.yoast-help-panel{max-width:none!important}#wpseo-crawl-issues-table-form .subsubsub{float:none;max-width:calc(100vw - 20px)}#wpseo-crawl-issues-table-form .yoast-help-button{margin-top:3px}.wpseotab select[multiple]{height:auto!important}}@media screen and (max-width:600px){.wpseotab.content{padding:16px 0}}.wpseo-score-icon-container{height:20px;width:20px;margin-right:8px;display:flex;justify-content:center;align-items:center}.yoast-seo-sidebar-panel div{line-height:2}.yoast-seo-sidebar-panel div svg{vertical-align:middle}ul.yoast-seo-social-share-buttons li{display:inline-block;margin-right:16px}ul.yoast-seo-social-share-buttons svg{width:32px;height:32px;margin-bottom:8px}ul.yoast-seo-social-share-buttons a{display:flex;flex-direction:column;align-items:center}.edit-post-pinned-plugins button.components-button[aria-label="Yoast SEO"]>svg,.edit-post-pinned-plugins button.components-button[aria-label="Yoast SEO Premium"]>svg,div.interface-pinned-items button.components-button[aria-label="Yoast SEO"]>svg,div.interface-pinned-items button.components-button[aria-label="Yoast SEO Premium"]>svg{max-width:28px;max-height:28px;width:28px;height:28px}div.interface-pinned-items button.components-button.is-pressed[aria-label="Yoast SEO"]>svg path,div.interface-pinned-items button.components-button.is-pressed[aria-label="Yoast SEO Premium"]>svg path{fill:#fff}.wpseo-schema-icon{height:16px;width:16px;margin-right:8px;display:flex;justify-content:center;align-items:center;background-image:var(--yoast-svg-icon-schema);background-size:cover}.wpseo-metabox-menu ul li.active a .wpseo-schema-icon{background-image:var(--yoast-svg-icon-schema-active)}.yoast-icon-span svg{margin-right:8px;fill:inherit}.yoast.components-panel__body{border-top:0}.components-button>.yoast-title-container{flex-grow:1;overflow-x:hidden;line-height:normal}.yoast-title-container>.yoast-title{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.yoast-title-container>.yoast-subtitle{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-size:.8125rem;font-weight:300;margin-top:2px}.yoast.components-panel__body .yoast-chevron{background-color:#1e1e1e;-webkit-mask-image:var(--yoast-svg-icon-chevron-down);mask-image:var(--yoast-svg-icon-chevron-down);-webkit-mask-size:100% 100%;mask-size:100% 100%;display:inline-block;width:24px;height:24px}.yoast.components-panel__body.is-opened .yoast-chevron{-webkit-mask-image:var(--yoast-svg-icon-chevron-up);mask-image:var(--yoast-svg-icon-chevron-up)}.yoast .components-form-token-field__remove-token.components-button,.yoast .components-form-token-field__token-text{background-color:var(--yoast-color-primary);color:var(--yoast-color-white)} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/metabox-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/metabox-720-rtl.min.css deleted file mode 100644 index 31455246..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/metabox-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -.yoast-section{width:auto;max-width:640px}.snippet_container:after,.snippet_container:before{display:table;content:" "}.snippet_container:after{clear:both}.snippet-editor__view{clear:both;background:#fff}.snippet-editor__view-toggle{display:inline-block;margin-top:10px;margin-right:20px;border:1px solid #dbdbdb;border-radius:4px;background-color:#f7f7f7;vertical-align:top}.snippet-editor__view-icon{float:right;width:31px;height:31px;border:none;border-bottom:4px solid transparent;outline:0;background-color:transparent;background-repeat:no-repeat;background-position:center,center;cursor:pointer}.snippet-editor__view-icon:focus,.snippet-editor__view-icon:hover{border-color:#1074a8;background-color:#fff;transition:.15s color ease-in-out,.15s background-color ease-in-out,.15s border-color ease-in-out}.snippet-editor__view-icon--active{border-color:#555;transition:.15s color ease-in-out,.15s background-color ease-in-out,.15s border-color ease-in-out}.snippet-editor__view-icon.yoast-tooltip:before{bottom:-10px}.snippet-editor__view-icon.yoast-tooltip:after{margin-top:10px}.snippet-editor__view-icon-desktop{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M1728%20992v%2D832q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D1600q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v832q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h1600q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm128%2D832v1088q0%2066%2D47%20113t%2D113%2047h%2D544q0%2037%2016%2077%2E5t32%2071%2016%2043%2E5q0%2026%2D19%2045t%2D45%2019h%2D512q%2D26%200%2D45%2D19t%2D19%2D45q0%2D14%2016%2D44t32%2D70%2016%2D78h%2D544q%2D66%200%2D113%2D47t%2D47%2D113v%2D1088q0%2D66%2047%2D113t113%2D47h1600q66%200%20113%2047t47%20113z%22%2F%3E%3C%2Fsvg%3E");background-size:18px}.snippet-editor__view-icon-desktop:focus,.snippet-editor__view-icon-desktop:hover{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M1728%20992v%2D832q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D1600q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v832q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h1600q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm128%2D832v1088q0%2066%2D47%20113t%2D113%2047h%2D544q0%2037%2016%2077%2E5t32%2071%2016%2043%2E5q0%2026%2D19%2045t%2D45%2019h%2D512q%2D26%200%2D45%2D19t%2D19%2D45q0%2D14%2016%2D44t32%2D70%2016%2D78h%2D544q%2D66%200%2D113%2D47t%2D47%2D113v%2D1088q0%2D66%2047%2D113t113%2D47h1600q66%200%20113%2047t47%20113z%22%2F%3E%3C%2Fsvg%3E")}.snippet-editor__view-icon-mobile{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M976%201408q0%2D33%2D23%2E5%2D56%2E5t%2D56%2E5%2D23%2E5%2D56%2E5%2023%2E5%2D23%2E5%2056%2E5%2023%2E5%2056%2E5%2056%2E5%2023%2E5%2056%2E5%2D23%2E5%2023%2E5%2D56%2E5zm208%2D160v%2D704q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D512q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v704q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h512q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm%2D192%2D848q0%2D16%2D16%2D16h%2D160q%2D16%200%2D16%2016t16%2016h160q16%200%2016%2D16zm288%2D16v1024q0%2052%2D38%2090t%2D90%2038h%2D512q%2D52%200%2D90%2D38t%2D38%2D90v%2D1024q0%2D52%2038%2D90t90%2D38h512q52%200%2090%2038t38%2090z%22%2F%3E%3C%2Fsvg%3E");background-size:22px}.snippet-editor__view-icon-mobile:focus,.snippet-editor__view-icon-mobile:hover{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M976%201408q0%2D33%2D23%2E5%2D56%2E5t%2D56%2E5%2D23%2E5%2D56%2E5%2023%2E5%2D23%2E5%2056%2E5%2023%2E5%2056%2E5%2056%2E5%2023%2E5%2056%2E5%2D23%2E5%2023%2E5%2D56%2E5zm208%2D160v%2D704q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D512q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v704q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h512q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm%2D192%2D848q0%2D16%2D16%2D16h%2D160q%2D16%200%2D16%2016t16%2016h160q16%200%2016%2D16zm288%2D16v1024q0%2052%2D38%2090t%2D90%2038h%2D512q%2D52%200%2D90%2D38t%2D38%2D90v%2D1024q0%2D52%2038%2D90t90%2D38h512q52%200%2090%2038t38%2090z%22%2F%3E%3C%2Fsvg%3E")}.snippet-editor__view--desktop{overflow:auto;width:640px;max-width:100%;padding:0 20px}.snippet-editor__view .snippet_container__title{width:600px;white-space:nowrap}.snippet-editor__view .snippet_container__title .title{display:inline-block;overflow:hidden;max-width:600px;vertical-align:top;text-overflow:ellipsis}.snippet-editor__view .snippet_container__title .title#snippet_sitename{display:inline}.snippet-editor__view .snippet_container__url{width:600px;line-height:1;white-space:nowrap}.snippet-editor__view .snippet_container__url .urlFull{display:inline-block;overflow:hidden;max-width:586px;font-size:14px;line-height:16px;vertical-align:top;text-overflow:ellipsis}.snippet-editor__view .snippet_container .down_arrow{display:inline-block;margin-top:6px;margin-right:6px;border-top:5px solid #006621;border-left:4px solid transparent;border-right:4px solid transparent;vertical-align:top}.snippet-editor__view .snippet_container__meta{width:600px}.snippet-editor__view--mobile{margin:0 20px 10px;padding:11px 0;border-bottom:1px hidden #fff;border-radius:2px;box-shadow:0 1px 2px rgba(0,0,0,.2)}.snippet-editor__view--mobile .snippet_container{display:block;line-height:20px}.snippet-editor__view--mobile .snippet_container__meta,.snippet-editor__view--mobile .snippet_container__title,.snippet-editor__view--mobile .snippet_container__url{box-sizing:border-box;width:100%}.snippet-editor__view--mobile .snippet_container__title{overflow:visible;padding:0 16px;white-space:normal;word-wrap:break-word}.snippet-editor__view--mobile .snippet_container__title .title{font-size:16px;line-height:20px}.snippet-editor__view--mobile .snippet_container__url{margin-bottom:9px;padding:0 16px 9px;border-bottom:1px solid #ebebeb}.snippet-editor__view--mobile .snippet_container__url .urlFull{max-width:100%;font-size:14px;line-height:20px}.snippet-editor__view--mobile .snippet_container .down_arrow{display:none}.snippet-editor__view--mobile .snippet_container__meta{padding:0 16px;font-size:14px;line-height:20px}.snippet-editor__view--mobile .snippet_container .desc{font-size:14px;line-height:20px}.snippet-editor__is-scrollable-hintwrapper{display:none;margin:1em 0 5px;text-align:center}.snippet-editor__view--desktop.snippet-editor__view--desktop-has-scroll+.snippet-editor__is-scrollable-hintwrapper{display:block}.snippet-editor__is-scrollable-hint{display:inline-block}.snippet-editor__is-scrollable-hint:before{display:inline-block;margin-left:10px;font-size:20px;line-height:inherit;vertical-align:text-top;content:"\21c4"}.snippet-editor__container{position:relative;cursor:pointer}.snippet-editor__container.editable-preview__container--no-caret{cursor:auto}.snippet-editor__heading{margin:0 0 15px;padding:8px 20px;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.snippet-editor__heading-editor{border-top:1px solid #f7f7f7}.snippet-editor__heading-icon{padding-right:45px;background-repeat:no-repeat;background-position:right 20px top .6em;background-size:16px}.snippet-editor__container--focus:before,.snippet-editor__container--focus:hover:before,.snippet-editor__container:hover:before{position:absolute;right:-22px;width:24px;height:24px;background-size:25px;content:"";display:block;top:-3px}.snippet-editor__heading-icon-eye{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__container:hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__container--focus:before,.snippet-editor__container--focus:hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__preview{max-width:640px;padding:0 0 15px}.snippet-editor__preview #help-yoast-snippetpreview{padding:0 20px}.snippet-editor__button{padding:8px 10px;border:1px solid #dbdbdb;border-radius:4px;color:#555;background:#f7f7f7;font-size:.8rem;line-height:15px;cursor:pointer}.snippet-editor__edit-button{display:inline-block;box-sizing:border-box;margin-top:10px;padding-right:32px;background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M491%201536l91%2D91%2D235%2D235%2D91%2091v107h128v128h107zm523%2D928q0%2D22%2D22%2D22%2D10%200%2D17%207l%2D542%20542q%2D7%207%2D7%2017%200%2022%2022%2022%2010%200%2017%2D7l542%2D542q7%2D7%207%2D17zm%2D54%2D192l416%20416%2D832%20832h%2D416v%2D416zm683%2096q0%2053%2D37%2090l%2D166%20166%2D416%2D416%20166%2D165q36%2D38%2090%2D38%2053%200%2091%2038l235%20234q37%2039%2037%2091z%22%20%2F%3E%3C%2Fsvg%3E") right 8px top 50% no-repeat #f7f7f7;background-size:16px}.snippet-editor__form{padding:20px}.snippet-editor__label{display:block;position:relative;width:100%;margin-top:1em}.snippet-editor__label--focus:before,.snippet-editor__label--hover:before{right:-22px;width:24px;height:24px;background-size:25px;display:block;position:absolute;content:""}.snippet-editor__label:first-child{margin-top:0}.snippet-editor__label--hover:before{top:-3px;top:20px;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__label--focus:before{top:-3px;top:20px;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__input{display:block;box-sizing:border-box;width:100%;max-width:100%;margin-top:5px;border:1px solid #bfbfbf}.snippet-editor__input:focus{border:1px solid #1074a8;outline:0}.rtl .snippet-editor__container:hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.rtl .snippet-editor__container--focus:before,.rtl .snippet-editor__container--focus:hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.rtl .snippet-editor__label--hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.rtl .snippet-editor__label--focus:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.snippet-editor__meta-description{height:84px}.snippet-editor__submit{margin-top:1em}#snippet_cite{min-width:20px}#meta_container{clear:both;min-height:20px}.snippet_container .title{margin:0;color:#1e0fbe;font-size:18px;font-weight:400;line-height:1.2;text-decoration:none}.snippet-editor__date,.snippet_container .desc{font-size:13px;line-height:1.4}.snippet_container .url{color:#006621;font-style:normal}.snippet_container .url strong{font-weight:700}.snippet_container .desc-default{color:#545454}.snippet_container .desc-default strong{color:#6a6a6a;font-weight:700}.snippet_container .desc-render{color:#777}.snippet_container .tooLong{color:red!important}.snippet-editor__field--invalid{color:red}.snippet-editor__progress{display:block;box-sizing:border-box;width:100%;height:8px;margin-top:5px;border:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.snippet-editor__progress::-webkit-progress-bar{height:8px;border:1px solid #bfbfbf;background-color:#f7f7f7}.snippet-editor__progress--fallback{height:8px;border:1px solid #bfbfbf;background-color:#f7f7f7}.snippet-editor__progress-bar{width:0;max-width:100%;height:100%}.snippet-editor__date{color:grey}.snippet-editor--hidden{display:none}.yoast-measurement-elements-holder{position:absolute;right:-9999em}.snippet-editor__progress--bad[value]{color:#dc3232}.snippet-editor__progress--bad[value]::-webkit-progress-value{background-color:#dc3232;transition:width 250ms}.snippet-editor__progress--bad[value]::-moz-progress-bar{background-color:#dc3232}.snippet-editor__progress--bad[value] .snippet-editor__progress-bar{background-color:#dc3232}.snippet-editor__progress--ok[value]{color:#ee7c1b}.snippet-editor__progress--ok[value]::-webkit-progress-value{background-color:#ee7c1b;transition:width 250ms}.snippet-editor__progress--ok[value]::-moz-progress-bar{background-color:#ee7c1b}.snippet-editor__progress--ok[value] .snippet-editor__progress-bar{background-color:#ee7c1b}.snippet-editor__progress--good[value]{color:#7ad03a}.snippet-editor__progress--good[value]::-webkit-progress-value{background-color:#7ad03a;transition:width 250ms}.snippet-editor__progress--good[value]::-moz-progress-bar{background-color:#7ad03a}.snippet-editor__progress--good[value] .snippet-editor__progress-bar{background-color:#7ad03a}.wpseoanalysis{padding-left:0}.wpseo-score-text{float:right;width:86%;width:calc(100% - 56px)}.assessment-results .wpseo-score-icon{float:right;width:12px;height:12px;margin:3px 0 0 10px;border-radius:50%;background:#888}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#999}.wpseo-score-icon.noindex{background-color:#1e8cbe}li.score{margin-bottom:6px;list-style-type:none!important}li.score:after{display:table;clear:both;content:""}.screen-reader-text{overflow:hidden;clip:rect(1px,1px,1px,1px);position:absolute!important;width:1px;height:1px}.assessment-results{clear:both}.assessment-results__mark.icon-eye-active,.assessment-results__mark.icon-eye-disabled,.assessment-results__mark.icon-eye-inactive{float:right;width:28px;height:28px;margin:-5px 3px 0;padding:4px;border:0;border-radius:100%;outline:0;background:center no-repeat;background-size:16px;cursor:pointer}.assessment-results__mark.icon-eye-inactive{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.assessment-results__mark.icon-eye-active{background-color:#a4286a;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23ffffff%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.assessment-results__mark.icon-eye-disabled{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23e6e6e6%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.assessment-results__mark:focus{border-radius:100%;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.assessment-results__mark-container{display:inline-block;float:left;width:33px;min-height:1px}.YoastSEO_msg .left,.YoastSEO_msg .right{display:none}@keyframes animatedBackground{from{background-position:100% 0}to{background-position:0 0}}.YoastSEO_msg .bufferbar{display:block;width:100%;height:12px;margin:10px 0;border:1px solid #dfdfdf;background-image:linear-gradient(to right,#fff,#0063ff,#fff,#0063ff);background-position:100% 0;background-size:300% 100%;animation:animatedBackground 5s linear infinite}.yoast-tooltip{position:relative}.yoast-tooltip::after,.yoast-tooltip::before{display:none;position:absolute;opacity:0;pointer-events:none}button.yoast-tooltip{overflow:visible}.yoast-tooltip::after{z-index:1000000;padding:6px 8px 5px;border-radius:3px;color:#fff;background:rgba(0,0,0,.8);text-shadow:none;font:normal normal 11px/1.45454545 Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";text-align:center;white-space:pre;text-decoration:none;letter-spacing:normal;text-transform:none;word-wrap:break-word;content:attr(aria-label);-webkit-font-smoothing:subpixel-antialiased}.yoast-tooltip-alt::after{content:attr(data-label)}.yoast-tooltip::before{z-index:1000001;width:0;height:0;border:5px solid transparent;color:rgba(0,0,0,.8);content:"\00a0"}@keyframes yoast-tooltip-appear{from{opacity:0}to{opacity:1}}.yoast-tooltip:active::after,.yoast-tooltip:active::before,.yoast-tooltip:focus::after,.yoast-tooltip:focus::before,.yoast-tooltip:hover::after,.yoast-tooltip:hover::before{display:inline-block;text-decoration:none;animation-name:yoast-tooltip-appear;animation-duration:.1s;animation-timing-function:ease-in;animation-delay:.4s;animation-fill-mode:forwards}.yoast-tooltip-no-delay:active::after,.yoast-tooltip-no-delay:active::before,.yoast-tooltip-no-delay:focus::after,.yoast-tooltip-no-delay:focus::before,.yoast-tooltip-no-delay:hover::after,.yoast-tooltip-no-delay:hover::before{opacity:1;animation:none}.yoast-tooltip-multiline:active::after,.yoast-tooltip-multiline:focus::after,.yoast-tooltip-multiline:hover::after{display:table-cell}.yoast-tooltip-s::after,.yoast-tooltip-se::after,.yoast-tooltip-sw::after{top:100%;left:50%;margin-top:5px}.yoast-tooltip-s::before,.yoast-tooltip-se::before,.yoast-tooltip-sw::before{top:auto;left:50%;bottom:-5px;margin-left:-5px;border-bottom-color:rgba(0,0,0,.8)}.yoast-tooltip-se::after{left:auto;right:50%;margin-right:-15px}.yoast-tooltip-sw::after{margin-left:-15px}.yoast-tooltip-n::after,.yoast-tooltip-ne::after,.yoast-tooltip-nw::after{left:50%;bottom:100%;margin-bottom:5px}.yoast-tooltip-n::before,.yoast-tooltip-ne::before,.yoast-tooltip-nw::before{top:-5px;left:50%;bottom:auto;margin-left:-5px;border-top-color:rgba(0,0,0,.8)}.yoast-tooltip-ne::after{left:auto;right:50%;margin-right:-15px}.yoast-tooltip-nw::after{margin-left:-15px}.yoast-tooltip-n::after,.yoast-tooltip-s::after{-ms-transform:translateX(-50%);transform:translateX(-50%)}.yoast-tooltip-w::after{left:100%;bottom:50%;margin-left:5px;-ms-transform:translateY(50%);transform:translateY(50%)}.yoast-tooltip-w::before{top:50%;bottom:50%;right:-5px;margin-top:-5px;border-right-color:rgba(0,0,0,.8)}.yoast-tooltip-e::after{bottom:50%;right:100%;margin-right:5px;-ms-transform:translateY(50%);transform:translateY(50%)}.yoast-tooltip-e::before{top:50%;left:-5px;bottom:50%;margin-top:-5px;border-left-color:rgba(0,0,0,.8)}.yoast-tooltip-multiline::after{width:250px;width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:250px;border-collapse:separate;white-space:pre-line;word-wrap:normal;word-break:break-word}.yoast-tooltip-multiline.yoast-tooltip-n::after,.yoast-tooltip-multiline.yoast-tooltip-s::after{left:auto;right:50%;-ms-transform:translateX(50%);transform:translateX(50%)}.yoast-tooltip-multiline.yoast-tooltip-e::after,.yoast-tooltip-multiline.yoast-tooltip-w::after{left:100%}@media screen and (min-width:0\0){.yoast-tooltip-multiline::after{width:250px}}.yoast-tooltip-sticky::after,.yoast-tooltip-sticky::before{display:inline-block}.yoast-tooltip-sticky.yoast-tooltip-multiline::after{display:table-cell}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (-moz-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:192dpi),only screen and (min-resolution:2dppx){.yoast-tooltip-w::after{margin-left:4.5px}}.postbox .yoast-help-center__button{min-height:0;margin:0;padding:8px 0;border:none;color:#0073aa;box-shadow:none;font:inherit;text-decoration:underline;text-transform:none}.wpseotab label,.wpseotab legend{font-weight:600}.postbox .yoast-help-center__button svg{margin:0 13px}#edittag .yoast-video-tutorial__video-container{float:none;max-width:100%;margin:0 auto}#edittag .yoast-video-tutorial__descriptions{margin:0 auto;padding:0}@media screen and (max-width:1480px){#poststuff .yoast-video-tutorial__video-container{float:none;max-width:100%;margin:0 auto}#poststuff .yoast-video-tutorial__descriptions{margin:0 auto;padding:0}}.wpseo-metabox #yoast-help-center-container{margin:8px 0}#edittag>#wp-description-wrap{display:none}#wp-description-wrap .wp-editor-area{border:0}.term-description-wrap td>textarea#description{min-height:530px}ul.wpseo-metabox-tabs{display:none;margin-top:6px;margin-bottom:0}ul.wpseo-metabox-tabs:after{display:table;clear:both;content:""}.wpseo-metabox-tabs-div ul{list-style:none}ul.wpseo-metabox-tabs li.active{background-color:#fdfdfd}.wpseo-meta-section{display:none;width:100%;max-width:calc(100% - 50px);vertical-align:top}.wpseo-meta-section.active{display:inline-block}.wpseo-metabox-sidebar{float:right;width:50px;padding:0;background-color:#fff}.wpseo-metabox-sidebar ul{margin:0}.wpseo-metabox-sidebar li{display:inline-block;margin-bottom:0;padding:5px}.wpseo-metabox-sidebar a{display:inline-block;width:35px;height:35px;font-size:20px;line-height:30px;text-decoration:none}.wpseo-metabox-sidebar li span{margin:3px -5px 0 0;padding:0 5px 0 2px;border:0 solid transparent;border-right-width:3px;border-radius:3px}.wpseo-metabox-sidebar li span.wpseo-buy-premium{color:#a4286a}.wpseo-metabox-sidebar li span.wpseo-buy-premium:hover{color:#832055}.wpseo-metabox-sidebar li.active span{border-color:#333;color:#333}.wpseo-metabox-sidebar li.active span.wpseo-buy-premium{border-color:#a4286a;color:#a4286a}.wpseo-metabox-sidebar li.active span.wpseo-buy-premium:hover{border-color:#832055;color:#832055}ul.wpseo-metabox-tabs li{float:right;margin-left:5px;margin-bottom:-1px;padding:0;border:1px solid #dfdfdf;border-bottom:0 none}ul.wpseo-metabox-tabs li .wpseo-keyword{display:inline-block;overflow:hidden;max-width:8em;max-width:8rem;vertical-align:top;white-space:nowrap;text-overflow:ellipsis}.wpseotab{display:none;padding:20px 35px;border:1px solid #ddd;background-color:#fdfdfd}.wpseotab .wpseo-cornerstone-checkbox{margin-left:.5em}.wpseotab.content{padding:20px 15px}.wpseotab.active{display:block}#wpseofocuskeyword,#wpseosnippet{margin-bottom:2em}.wpseo-metabox-tabs .wpseo_tablink{display:inline-block;padding:5px 12px 6px;vertical-align:top;text-decoration:none}.wpseo-metabox-tabs .wpseo_content_tab a,.wpseo-metabox-tabs .wpseo_content_tab+.wpseo_keyword_tab a{padding-left:12px}.wpseo-metabox-tabs .wpseo-score-icon{margin-right:0}#wpseo-meta-section-social .wpseo-metabox-tabs .wpseo_tablink{padding:5px 7px}.wpseo-metabox-tabs .wpseo_tablink .dashicons{width:16px;height:16px;font-size:16px}.wpseo-metabox-sidebar .dashicons{width:30px;height:30px;font-size:30px}.wpseo-metabox-tabs-div div.wpseo-tabs-panel{overflow:auto;padding:.5em .9em;border:1px solid}#wpseo_meta .inside{margin:0}#wpseo_meta .inside::after{display:table;clear:both;content:""}#wpseo_meta .postbox .inside .wpseotab{font-size:13px!important}.wpseotab .select2-container,.wpseotab input,.wpseotab label,.wpseotab p.error-message,.wpseotab textarea,.yoast-metabox__description{max-width:600px}.wpseotab fieldset{padding-top:5px}.wpseotab label{display:block}.wpseotab input[type=radio]+label,.wpseotab input[type=checkbox]+label{display:inline-block;font-weight:400}.wpseotab fieldset,.wpseotab label{margin-top:2em;margin-bottom:.5em}.wpseotab input[type=checkbox],.wpseotab input[type=checkbox]+label{margin-top:2em;margin-bottom:0;font-size:1em}.wpseotab fieldset:first-child,.wpseotab input[type=checkbox]:first-child,.wpseotab input[type=checkbox]:first-child+label,.wpseotab label:first-child{margin-top:10px}.wpseotab input[type=radio]{margin-top:0}.wpseotab input[type=radio]+label{margin:0 0 0 1em}.wpseotab p.error-message,.yoast-metabox__description{margin:.5em 0}.wpseotab #yoast_wpseo_focuskw_text_input,.wpseotab select[multiple]{margin-top:0}.wpseotab .wpseo_image_upload_button{margin-right:3px}.good,.warn,.wrong{font-weight:600}.good{color:green}.warn{color:maroon}.wrong{color:#dc3232}#current_seo_title span{padding:2px 5px;background-color:#ffffe0}#focuskwresults ul{margin:0}#focuskwresults li,#focuskwresults p{font-size:13px}#focuskwresults li{margin:0 20px 0 0;list-style-type:disc}.wpseo_hidden{display:none}.wpseo_msg{margin:5px 0 10px;padding:0 5px;border:1px solid #e6db55;background-color:#ffffe0}ul.wpseo-metabox-tabs li.wpseo-tab-add-keyword{border:1px dashed #dfdfdf;border-bottom:none}.wpseo-tab-add-keyword .wpseo-add-keyword.button{height:auto;padding:5px 10px 5px 12px;background:0 0;box-shadow:none;font-size:inherit;font-weight:700;line-height:inherit;vertical-align:top;text-decoration:none}.wpseo-tab-add-keyword .wpseo-add-keyword.button:focus{box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.wpseo-tab-add-keyword .wpseo-add-keyword.button:active{-ms-transform:none;transform:none}.wpseo-add-keyword-plus{display:inline-block;margin:-1px 0 0 3px;font-size:20px;vertical-align:top}#wpseo-add-keyword-popup-title{margin:1em 0;font-size:1.3em}.snippet-editor__button.snippet-editor__edit-button:focus{border-color:#5b9dd9;outline:0;color:#23282d;background-color:#fafafa;box-shadow:0 0 3px rgba(0,115,170,.8)}.wpseo-admin-page .subsubsub li{display:inline;max-width:none}.yoast-seo-help-container{float:right;width:100%;max-width:none}.yoast-seo-help-container .yoast-help-panel{margin:.5em 0!important}.wpseo_content_wrapper p.search-box{margin:10px 0 5px}.wpseo-metabox-tabs .active a{color:#333}#wpseotab .ui-widget-content .ui-state-hover{border:1px solid #dfdfdf;color:#333;background:#f1f1f1}.yst-traffic-light-container{display:block;height:30px}.yst-traffic-light{width:19px;height:30px;margin:0 5px 0 0}.yst-traffic-light .traffic-light-color{display:none}.yst-traffic-light.bad .traffic-light-red,.yst-traffic-light.good .traffic-light-green,.yst-traffic-light.init .traffic-light-init,.yst-traffic-light.na .traffic-light-empty,.yst-traffic-light.ok .traffic-light-orange{display:inline}#wpseo-score{float:right;margin:0 -5px 0 5px}.yoast-seo-score .yoast-logo.svg{float:right;width:18px;height:18px;margin-left:5px;background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23999%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E") no-repeat;background-size:18px}.yoast-seo-score .yoast-logo.svg.good{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%237ad03a%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E")}.yoast-seo-score .yoast-logo.svg.ok{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23ee7c1b%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E")}.yoast-seo-score .yoast-logo.svg.bad{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23dc3232%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E")}.yoast-seo-score .yoast-logo.svg.na{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23999%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E")}.yoast-seo-score .yoast-logo.svg.noindex{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231e8cbe%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E")}.term-php .wpseo-taxonomy-metabox-postbox>h2{margin:0;padding:8px 12px;border-bottom:1px solid #eee;font-size:14px;line-height:1.4}.wpseo-buy-premium{padding-left:5px;color:#a4286a}.wpseo-metabox-go-to::after{position:static;top:auto;left:auto;width:auto;height:auto;border:none;content:" \00BB"}#wpseo-buy-premium-popup-button.button-buy-premium{border-color:#a4286a;color:#fff;background:#a4286a}.wpseo-metabox-buy-premium{position:absolute;top:0;left:12px;padding:8px 0}.wpseo-metabox-buy-premium .dashicons{text-decoration:none}.wpseosnippet .yoast-section{width:auto;max-width:640px;padding:0}#TB_window #TB_ajaxContent p{margin:5px 0 0;padding:5px 0 0}#TB_window #TB_ajaxContent ul{margin:5px 0 10px}#TB_window #TB_ajaxContent li{margin:5px 0 0;list-style:none}#TB_window #TB_ajaxContent li::before{margin:0 0 0 10px;font-weight:700;content:"+"}.yoast-section__heading-icon-list{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M384%201408q0%2080%2D56%20136t%2D136%2056%2D136%2D56%2D56%2D136%2056%2D136%20136%2D56%20136%2056%2056%20136zm0%2D512q0%2080%2D56%20136t%2D136%2056%2D136%2D56%2D56%2D136%2056%2D136%20136%2D56%20136%2056%2056%20136zm1408%20416v192q0%2013%2D9%2E5%2022%2E5t%2D22%2E5%209%2E5h%2D1216q%2D13%200%2D22%2E5%2D9%2E5t%2D9%2E5%2D22%2E5v%2D192q0%2D13%209%2E5%2D22%2E5t22%2E5%2D9%2E5h1216q13%200%2022%2E5%209%2E5t9%2E5%2022%2E5zm%2D1408%2D928q0%2080%2D56%20136t%2D136%2056%2D136%2D56%2D56%2D136%2056%2D136%20136%2D56%20136%2056%2056%20136zm1408%20416v192q0%2013%2D9%2E5%2022%2E5t%2D22%2E5%209%2E5h%2D1216q%2D13%200%2D22%2E5%2D9%2E5t%2D9%2E5%2D22%2E5v%2D192q0%2D13%209%2E5%2D22%2E5t22%2E5%2D9%2E5h1216q13%200%2022%2E5%209%2E5t9%2E5%2022%2E5zm0%2D512v192q0%2013%2D9%2E5%2022%2E5t%2D22%2E5%209%2E5h%2D1216q%2D13%200%2D22%2E5%2D9%2E5t%2D9%2E5%2D22%2E5v%2D192q0%2D13%209%2E5%2D22%2E5t22%2E5%2D9%2E5h1216q13%200%2022%2E5%209%2E5t9%2E5%2022%2E5z%22%2F%3E%3C%2Fsvg%3E")}.yoast-section__heading-icon-key{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M832%20512q0%2D80%2D56%2D136t%2D136%2D56%2D136%2056%2D56%20136q0%2042%2019%2083%2D41%2D19%2D83%2D19%2D80%200%2D136%2056t%2D56%20136%2056%20136%20136%2056%20136%2D56%2056%2D136q0%2D42%2D19%2D83%2041%2019%2083%2019%2080%200%20136%2D56t56%2D136zm851%20704q0%2017%2D49%2066t%2D66%2049q%2D9%200%2D28%2E5%2D16t%2D36%2E5%2D33%2D38%2E5%2D40%2D24%2E5%2D26l%2D96%2096%20220%20220q28%2028%2028%2068%200%2042%2D39%2081t%2D81%2039q%2D40%200%2D68%2D28l%2D671%2D671q%2D176%20131%2D365%20131%2D163%200%2D265%2E5%2D102%2E5t%2D102%2E5%2D265%2E5q0%2D160%2095%2D313t248%2D248%20313%2D95q163%200%20265%2E5%20102%2E5t102%2E5%20265%2E5q0%20189%2D131%20365l355%20355%2096%2D96q%2D3%2D3%2D26%2D24%2E5t%2D40%2D38%2E5%2D33%2D36%2E5%2D16%2D28%2E5q0%2D17%2049%2D66t66%2D49q13%200%2023%2010%206%206%2046%2044%2E5t82%2079%2E5%2086%2E5%2086%2073%2078%2028%2E5%2041z%22%2F%3E%3C%2Fsvg%3E")}.yoast-section__heading-icon-edit{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M491%201536l91%2D91%2D235%2D235%2D91%2091v107h128v128h107zm523%2D928q0%2D22%2D22%2D22%2D10%200%2D17%207l%2D542%20542q%2D7%207%2D7%2017%200%2022%2022%2022%2010%200%2017%2D7l542%2D542q7%2D7%207%2D17zm%2D54%2D192l416%20416%2D832%20832h%2D416v%2D416zm683%2096q0%2053%2D37%2090l%2D166%20166%2D416%2D416%20166%2D165q36%2D38%2090%2D38%2053%200%2091%2038l235%20234q37%2039%2037%2091z%22%20%2F%3E%3C%2Fsvg%3E")}.yoast-section{position:relative;padding:0 20px 15px;background-color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2)}.yoast-section__heading{margin:0 -20px 15px;padding:8px 20px;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.yoast-section__heading-icon{padding-right:44px;background-repeat:no-repeat;background-position:right 20px top .6em;background-size:16px}.yoast-section,.yoast-section *,.yoast-section :after,.yoast-section :before,.yoast-section:after,.yoast-section:before{box-sizing:border-box}.yoast-tooltip.yoast-tooltip-hidden::after,.yoast-tooltip.yoast-tooltip-hidden::before{display:none}.screen-reader-text.wpseo-generic-tab-textual-score,.screen-reader-text.wpseo-keyword-tab-textual-score{display:block}.yoast-notice-go-premium{margin:0;border-right-color:#a4286a;background:#f1f1f1}@media screen and (max-width:782px){.wpseo-metabox-sidebar{display:inline-block;float:none;width:auto;margin:0 -5px 10px 0;padding:0;vertical-align:top}.wpseo-meta-section.active{display:block;clear:both;max-width:none}.wpseo-metabox-sidebar ul{display:inline-block}.wpseo-metabox-sidebar li{float:right;text-align:center}.wpseo-metabox-sidebar .wpseo-meta-section-link{width:40px;height:40px}.wpseo-meta-section-link .dashicons,.wpseo-meta-section-link .yst-traffic-light-container{display:block;width:40px;height:35px;margin:0;padding:5px 0 2px;border-bottom-width:3px;border-right-width:0}.wpseo-meta-section-link .dashicons:before,.wpseo-meta-section-link .yst-traffic-light{margin:0}.wpseo-meta-section-link .dashicons-admin-generic:before{position:relative;right:1px}.wpseo-metabox-buy-premium .wpseo-buy-premium{display:inline-block;width:20px;height:20px;padding:0 5px}.yoast-help-panel{max-width:none!important}#wpseo-crawl-issues-table-form .subsubsub{float:none;max-width:calc(100vw - 20px)}#wpseo-crawl-issues-table-form .yoast-help-button{margin-top:3px}.wpseotab select[multiple]{height:auto!important}}@media screen and (max-width:600px){.wpseotab{padding:20px}.wpseotab.content{padding:20px 0}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/metabox-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/metabox-720.min.css deleted file mode 100644 index d7cea5b4..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/metabox-720.min.css +++ /dev/null @@ -1 +0,0 @@ -.yoast-section{width:auto;max-width:640px}.snippet_container:after,.snippet_container:before{display:table;content:" "}.snippet_container:after{clear:both}.snippet-editor__view{clear:both;background:#fff}.snippet-editor__view-toggle{display:inline-block;margin-top:10px;margin-left:20px;border:1px solid #dbdbdb;border-radius:4px;background-color:#f7f7f7;vertical-align:top}.snippet-editor__view-icon{float:left;width:31px;height:31px;border:none;border-bottom:4px solid transparent;outline:0;background-color:transparent;background-repeat:no-repeat;background-position:center,center;cursor:pointer}.snippet-editor__view-icon:focus,.snippet-editor__view-icon:hover{border-color:#1074a8;background-color:#fff;transition:.15s color ease-in-out,.15s background-color ease-in-out,.15s border-color ease-in-out}.snippet-editor__view-icon--active{border-color:#555;transition:.15s color ease-in-out,.15s background-color ease-in-out,.15s border-color ease-in-out}.snippet-editor__view-icon.yoast-tooltip:before{bottom:-10px}.snippet-editor__view-icon.yoast-tooltip:after{margin-top:10px}.snippet-editor__view-icon-desktop{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M1728%20992v%2D832q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D1600q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v832q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h1600q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm128%2D832v1088q0%2066%2D47%20113t%2D113%2047h%2D544q0%2037%2016%2077%2E5t32%2071%2016%2043%2E5q0%2026%2D19%2045t%2D45%2019h%2D512q%2D26%200%2D45%2D19t%2D19%2D45q0%2D14%2016%2D44t32%2D70%2016%2D78h%2D544q%2D66%200%2D113%2D47t%2D47%2D113v%2D1088q0%2D66%2047%2D113t113%2D47h1600q66%200%20113%2047t47%20113z%22%2F%3E%3C%2Fsvg%3E");background-size:18px}.snippet-editor__view-icon-desktop:focus,.snippet-editor__view-icon-desktop:hover{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M1728%20992v%2D832q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D1600q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v832q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h1600q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm128%2D832v1088q0%2066%2D47%20113t%2D113%2047h%2D544q0%2037%2016%2077%2E5t32%2071%2016%2043%2E5q0%2026%2D19%2045t%2D45%2019h%2D512q%2D26%200%2D45%2D19t%2D19%2D45q0%2D14%2016%2D44t32%2D70%2016%2D78h%2D544q%2D66%200%2D113%2D47t%2D47%2D113v%2D1088q0%2D66%2047%2D113t113%2D47h1600q66%200%20113%2047t47%20113z%22%2F%3E%3C%2Fsvg%3E")}.snippet-editor__view-icon-mobile{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M976%201408q0%2D33%2D23%2E5%2D56%2E5t%2D56%2E5%2D23%2E5%2D56%2E5%2023%2E5%2D23%2E5%2056%2E5%2023%2E5%2056%2E5%2056%2E5%2023%2E5%2056%2E5%2D23%2E5%2023%2E5%2D56%2E5zm208%2D160v%2D704q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D512q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v704q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h512q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm%2D192%2D848q0%2D16%2D16%2D16h%2D160q%2D16%200%2D16%2016t16%2016h160q16%200%2016%2D16zm288%2D16v1024q0%2052%2D38%2090t%2D90%2038h%2D512q%2D52%200%2D90%2D38t%2D38%2D90v%2D1024q0%2D52%2038%2D90t90%2D38h512q52%200%2090%2038t38%2090z%22%2F%3E%3C%2Fsvg%3E");background-size:22px}.snippet-editor__view-icon-mobile:focus,.snippet-editor__view-icon-mobile:hover{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M976%201408q0%2D33%2D23%2E5%2D56%2E5t%2D56%2E5%2D23%2E5%2D56%2E5%2023%2E5%2D23%2E5%2056%2E5%2023%2E5%2056%2E5%2056%2E5%2023%2E5%2056%2E5%2D23%2E5%2023%2E5%2D56%2E5zm208%2D160v%2D704q0%2D13%2D9%2E5%2D22%2E5t%2D22%2E5%2D9%2E5h%2D512q%2D13%200%2D22%2E5%209%2E5t%2D9%2E5%2022%2E5v704q0%2013%209%2E5%2022%2E5t22%2E5%209%2E5h512q13%200%2022%2E5%2D9%2E5t9%2E5%2D22%2E5zm%2D192%2D848q0%2D16%2D16%2D16h%2D160q%2D16%200%2D16%2016t16%2016h160q16%200%2016%2D16zm288%2D16v1024q0%2052%2D38%2090t%2D90%2038h%2D512q%2D52%200%2D90%2D38t%2D38%2D90v%2D1024q0%2D52%2038%2D90t90%2D38h512q52%200%2090%2038t38%2090z%22%2F%3E%3C%2Fsvg%3E")}.snippet-editor__view--desktop{overflow:auto;width:640px;max-width:100%;padding:0 20px}.snippet-editor__view .snippet_container__title{width:600px;white-space:nowrap}.snippet-editor__view .snippet_container__title .title{display:inline-block;overflow:hidden;max-width:600px;vertical-align:top;text-overflow:ellipsis}.snippet-editor__view .snippet_container__title .title#snippet_sitename{display:inline}.snippet-editor__view .snippet_container__url{width:600px;line-height:1;white-space:nowrap}.snippet-editor__view .snippet_container__url .urlFull{display:inline-block;overflow:hidden;max-width:586px;font-size:14px;line-height:16px;vertical-align:top;text-overflow:ellipsis}.snippet-editor__view .snippet_container .down_arrow{display:inline-block;margin-top:6px;margin-left:6px;border-top:5px solid #006621;border-right:4px solid transparent;border-left:4px solid transparent;vertical-align:top}.snippet-editor__view .snippet_container__meta{width:600px}.snippet-editor__view--mobile{margin:0 20px 10px;padding:11px 0;border-bottom:1px hidden #fff;border-radius:2px;box-shadow:0 1px 2px rgba(0,0,0,.2)}.snippet-editor__view--mobile .snippet_container{display:block;line-height:20px}.snippet-editor__view--mobile .snippet_container__meta,.snippet-editor__view--mobile .snippet_container__title,.snippet-editor__view--mobile .snippet_container__url{box-sizing:border-box;width:100%}.snippet-editor__view--mobile .snippet_container__title{overflow:visible;padding:0 16px;white-space:normal;word-wrap:break-word}.snippet-editor__view--mobile .snippet_container__title .title{font-size:16px;line-height:20px}.snippet-editor__view--mobile .snippet_container__url{margin-bottom:9px;padding:0 16px 9px;border-bottom:1px solid #ebebeb}.snippet-editor__view--mobile .snippet_container__url .urlFull{max-width:100%;font-size:14px;line-height:20px}.snippet-editor__view--mobile .snippet_container .down_arrow{display:none}.snippet-editor__view--mobile .snippet_container__meta{padding:0 16px;font-size:14px;line-height:20px}.snippet-editor__view--mobile .snippet_container .desc{font-size:14px;line-height:20px}.snippet-editor__is-scrollable-hintwrapper{display:none;margin:1em 0 5px;text-align:center}.snippet-editor__view--desktop.snippet-editor__view--desktop-has-scroll+.snippet-editor__is-scrollable-hintwrapper{display:block}.snippet-editor__is-scrollable-hint{display:inline-block}.snippet-editor__is-scrollable-hint:before{display:inline-block;margin-right:10px;font-size:20px;line-height:inherit;vertical-align:text-top;content:"\21c4"}.snippet-editor__container{position:relative;cursor:pointer}.snippet-editor__container.editable-preview__container--no-caret{cursor:auto}.snippet-editor__heading{margin:0 0 15px;padding:8px 20px;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.snippet-editor__heading-editor{border-top:1px solid #f7f7f7}.snippet-editor__heading-icon{padding-left:45px;background-repeat:no-repeat;background-position:left 20px top .6em;background-size:16px}.snippet-editor__container--focus:before,.snippet-editor__container--focus:hover:before,.snippet-editor__container:hover:before{position:absolute;left:-22px;width:24px;height:24px;background-size:25px;content:"";display:block;top:-3px}.snippet-editor__heading-icon-eye{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__container:hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__container--focus:before,.snippet-editor__container--focus:hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__preview{max-width:640px;padding:0 0 15px}.snippet-editor__preview #help-yoast-snippetpreview{padding:0 20px}.snippet-editor__button{padding:8px 10px;border:1px solid #dbdbdb;border-radius:4px;color:#555;background:#f7f7f7;font-size:.8rem;line-height:15px;cursor:pointer}.snippet-editor__edit-button{display:inline-block;box-sizing:border-box;margin-top:10px;padding-left:32px;background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M491%201536l91%2D91%2D235%2D235%2D91%2091v107h128v128h107zm523%2D928q0%2D22%2D22%2D22%2D10%200%2D17%207l%2D542%20542q%2D7%207%2D7%2017%200%2022%2022%2022%2010%200%2017%2D7l542%2D542q7%2D7%207%2D17zm%2D54%2D192l416%20416%2D832%20832h%2D416v%2D416zm683%2096q0%2053%2D37%2090l%2D166%20166%2D416%2D416%20166%2D165q36%2D38%2090%2D38%2053%200%2091%2038l235%20234q37%2039%2037%2091z%22%20%2F%3E%3C%2Fsvg%3E") left 8px top 50% no-repeat #f7f7f7;background-size:16px}.snippet-editor__form{padding:20px}.snippet-editor__label{display:block;position:relative;width:100%;margin-top:1em}.snippet-editor__label--focus:before,.snippet-editor__label--hover:before{left:-22px;width:24px;height:24px;background-size:25px;display:block;position:absolute;content:""}.snippet-editor__label:first-child{margin-top:0}.snippet-editor__label--hover:before{top:-3px;top:20px;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__label--focus:before{top:-3px;top:20px;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.snippet-editor__input{display:block;box-sizing:border-box;width:100%;max-width:100%;margin-top:5px;border:1px solid #bfbfbf}.snippet-editor__input:focus{border:1px solid #1074a8;outline:0}.rtl .snippet-editor__container:hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.rtl .snippet-editor__container--focus:before,.rtl .snippet-editor__container--focus:hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.rtl .snippet-editor__label--hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23bfbfbf%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.rtl .snippet-editor__label--focus:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231074a8%22%20d%3D%22M1216%20448v896q0%2026%2D19%2045t%2D45%2019%2D45%2D19l%2D448%2D448q%2D19%2D19%2D19%2D45t19%2D45l448%2D448q19%2D19%2045%2D19t45%2019%2019%2045z%22%2F%3E%3C%2Fsvg%3E")}.snippet-editor__meta-description{height:84px}.snippet-editor__submit{margin-top:1em}#snippet_cite{min-width:20px}#meta_container{clear:both;min-height:20px}.snippet_container .title{margin:0;color:#1e0fbe;font-size:18px;font-weight:400;line-height:1.2;text-decoration:none}.snippet-editor__date,.snippet_container .desc{font-size:13px;line-height:1.4}.snippet_container .url{color:#006621;font-style:normal}.snippet_container .url strong{font-weight:700}.snippet_container .desc-default{color:#545454}.snippet_container .desc-default strong{color:#6a6a6a;font-weight:700}.snippet_container .desc-render{color:#777}.snippet_container .tooLong{color:red!important}.snippet-editor__field--invalid{color:red}.snippet-editor__progress{display:block;box-sizing:border-box;width:100%;height:8px;margin-top:5px;border:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.snippet-editor__progress::-webkit-progress-bar{height:8px;border:1px solid #bfbfbf;background-color:#f7f7f7}.snippet-editor__progress--fallback{height:8px;border:1px solid #bfbfbf;background-color:#f7f7f7}.snippet-editor__progress-bar{width:0;max-width:100%;height:100%}.snippet-editor__date{color:grey}.snippet-editor--hidden{display:none}.yoast-measurement-elements-holder{position:absolute;left:-9999em}.snippet-editor__progress--bad[value]{color:#dc3232}.snippet-editor__progress--bad[value]::-webkit-progress-value{background-color:#dc3232;transition:width 250ms}.snippet-editor__progress--bad[value]::-moz-progress-bar{background-color:#dc3232}.snippet-editor__progress--bad[value] .snippet-editor__progress-bar{background-color:#dc3232}.snippet-editor__progress--ok[value]{color:#ee7c1b}.snippet-editor__progress--ok[value]::-webkit-progress-value{background-color:#ee7c1b;transition:width 250ms}.snippet-editor__progress--ok[value]::-moz-progress-bar{background-color:#ee7c1b}.snippet-editor__progress--ok[value] .snippet-editor__progress-bar{background-color:#ee7c1b}.snippet-editor__progress--good[value]{color:#7ad03a}.snippet-editor__progress--good[value]::-webkit-progress-value{background-color:#7ad03a;transition:width 250ms}.snippet-editor__progress--good[value]::-moz-progress-bar{background-color:#7ad03a}.snippet-editor__progress--good[value] .snippet-editor__progress-bar{background-color:#7ad03a}.wpseoanalysis{padding-right:0}.wpseo-score-text{float:left;width:86%;width:calc(100% - 56px)}.assessment-results .wpseo-score-icon{float:left;width:12px;height:12px;margin:3px 10px 0 0;border-radius:50%;background:#888}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#999}.wpseo-score-icon.noindex{background-color:#1e8cbe}li.score{margin-bottom:6px;list-style-type:none!important}li.score:after{display:table;clear:both;content:""}.screen-reader-text{overflow:hidden;clip:rect(1px,1px,1px,1px);position:absolute!important;width:1px;height:1px}.assessment-results{clear:both}.assessment-results__mark.icon-eye-active,.assessment-results__mark.icon-eye-disabled,.assessment-results__mark.icon-eye-inactive{float:left;width:28px;height:28px;margin:-5px 3px 0;padding:4px;border:0;border-radius:100%;outline:0;background:center no-repeat;background-size:16px;cursor:pointer}.assessment-results__mark.icon-eye-inactive{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.assessment-results__mark.icon-eye-active{background-color:#a4286a;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23ffffff%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.assessment-results__mark.icon-eye-disabled{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23e6e6e6%22%20d%3D%22M1664%20960q%2D152%2D236%2D381%2D353%2061%20104%2061%20225%200%20185%2D131%2E5%20316%2E5t%2D316%2E5%20131%2E5%2D316%2E5%2D131%2E5%2D131%2E5%2D316%2E5q0%2D121%2061%2D225%2D229%20117%2D381%20353%20133%20205%20333%2E5%20326%2E5t434%2E5%20121%2E5%20434%2E5%2D121%2E5%20333%2E5%2D326%2E5zm%2D720%2D384q0%2D20%2D14%2D34t%2D34%2D14q%2D125%200%2D214%2E5%2089%2E5t%2D89%2E5%20214%2E5q0%2020%2014%2034t34%2014%2034%2D14%2014%2D34q0%2D86%2061%2D147t147%2D61q20%200%2034%2D14t14%2D34zm848%20384q0%2034%2D20%2069%2D140%20230%2D376%2E5%20368%2E5t%2D499%2E5%20138%2E5%2D499%2E5%2D139%2D376%2E5%2D368q%2D20%2D35%2D20%2D69t20%2D69q140%2D229%20376%2E5%2D368t499%2E5%2D139%20499%2E5%20139%20376%2E5%20368q20%2035%2020%2069z%22%20%2F%3E%3C%2Fsvg%3E")}.assessment-results__mark:focus{border-radius:100%;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.assessment-results__mark-container{display:inline-block;float:right;width:33px;min-height:1px}.YoastSEO_msg .left,.YoastSEO_msg .right{display:none}@keyframes animatedBackground{from{background-position:0 0}to{background-position:100% 0}}.YoastSEO_msg .bufferbar{display:block;width:100%;height:12px;margin:10px 0;border:1px solid #dfdfdf;background-image:linear-gradient(to left,#fff,#0063ff,#fff,#0063ff);background-position:0 0;background-size:300% 100%;animation:animatedBackground 5s linear infinite}.yoast-tooltip{position:relative}.yoast-tooltip::after,.yoast-tooltip::before{display:none;position:absolute;opacity:0;pointer-events:none}button.yoast-tooltip{overflow:visible}.yoast-tooltip::after{z-index:1000000;padding:6px 8px 5px;border-radius:3px;color:#fff;background:rgba(0,0,0,.8);text-shadow:none;font:normal normal 11px/1.45454545 Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";text-align:center;white-space:pre;text-decoration:none;letter-spacing:normal;text-transform:none;word-wrap:break-word;content:attr(aria-label);-webkit-font-smoothing:subpixel-antialiased}.yoast-tooltip-alt::after{content:attr(data-label)}.yoast-tooltip::before{z-index:1000001;width:0;height:0;border:5px solid transparent;color:rgba(0,0,0,.8);content:"\00a0"}@keyframes yoast-tooltip-appear{from{opacity:0}to{opacity:1}}.yoast-tooltip:active::after,.yoast-tooltip:active::before,.yoast-tooltip:focus::after,.yoast-tooltip:focus::before,.yoast-tooltip:hover::after,.yoast-tooltip:hover::before{display:inline-block;text-decoration:none;animation-name:yoast-tooltip-appear;animation-duration:.1s;animation-timing-function:ease-in;animation-delay:.4s;animation-fill-mode:forwards}.yoast-tooltip-no-delay:active::after,.yoast-tooltip-no-delay:active::before,.yoast-tooltip-no-delay:focus::after,.yoast-tooltip-no-delay:focus::before,.yoast-tooltip-no-delay:hover::after,.yoast-tooltip-no-delay:hover::before{opacity:1;animation:none}.yoast-tooltip-multiline:active::after,.yoast-tooltip-multiline:focus::after,.yoast-tooltip-multiline:hover::after{display:table-cell}.yoast-tooltip-s::after,.yoast-tooltip-se::after,.yoast-tooltip-sw::after{top:100%;right:50%;margin-top:5px}.yoast-tooltip-s::before,.yoast-tooltip-se::before,.yoast-tooltip-sw::before{top:auto;right:50%;bottom:-5px;margin-right:-5px;border-bottom-color:rgba(0,0,0,.8)}.yoast-tooltip-se::after{right:auto;left:50%;margin-left:-15px}.yoast-tooltip-sw::after{margin-right:-15px}.yoast-tooltip-n::after,.yoast-tooltip-ne::after,.yoast-tooltip-nw::after{right:50%;bottom:100%;margin-bottom:5px}.yoast-tooltip-n::before,.yoast-tooltip-ne::before,.yoast-tooltip-nw::before{top:-5px;right:50%;bottom:auto;margin-right:-5px;border-top-color:rgba(0,0,0,.8)}.yoast-tooltip-ne::after{right:auto;left:50%;margin-left:-15px}.yoast-tooltip-nw::after{margin-right:-15px}.yoast-tooltip-n::after,.yoast-tooltip-s::after{-ms-transform:translateX(50%);transform:translateX(50%)}.yoast-tooltip-w::after{right:100%;bottom:50%;margin-right:5px;-ms-transform:translateY(50%);transform:translateY(50%)}.yoast-tooltip-w::before{top:50%;bottom:50%;left:-5px;margin-top:-5px;border-left-color:rgba(0,0,0,.8)}.yoast-tooltip-e::after{bottom:50%;left:100%;margin-left:5px;-ms-transform:translateY(50%);transform:translateY(50%)}.yoast-tooltip-e::before{top:50%;right:-5px;bottom:50%;margin-top:-5px;border-right-color:rgba(0,0,0,.8)}.yoast-tooltip-multiline::after{width:250px;width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:250px;border-collapse:separate;white-space:pre-line;word-wrap:normal;word-break:break-word}.yoast-tooltip-multiline.yoast-tooltip-n::after,.yoast-tooltip-multiline.yoast-tooltip-s::after{right:auto;left:50%;-ms-transform:translateX(-50%);transform:translateX(-50%)}.yoast-tooltip-multiline.yoast-tooltip-e::after,.yoast-tooltip-multiline.yoast-tooltip-w::after{right:100%}@media screen and (min-width:0\0){.yoast-tooltip-multiline::after{width:250px}}.yoast-tooltip-sticky::after,.yoast-tooltip-sticky::before{display:inline-block}.yoast-tooltip-sticky.yoast-tooltip-multiline::after{display:table-cell}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min--moz-device-pixel-ratio:2),only screen and (-moz-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2),only screen and (min-resolution:192dpi),only screen and (min-resolution:2dppx){.yoast-tooltip-w::after{margin-right:4.5px}}.postbox .yoast-help-center__button{min-height:0;margin:0;padding:8px 0;border:none;color:#0073aa;box-shadow:none;font:inherit;text-decoration:underline;text-transform:none}.wpseotab label,.wpseotab legend{font-weight:600}.postbox .yoast-help-center__button svg{margin:0 13px}#edittag .yoast-video-tutorial__video-container{float:none;max-width:100%;margin:0 auto}#edittag .yoast-video-tutorial__descriptions{margin:0 auto;padding:0}@media screen and (max-width:1480px){#poststuff .yoast-video-tutorial__video-container{float:none;max-width:100%;margin:0 auto}#poststuff .yoast-video-tutorial__descriptions{margin:0 auto;padding:0}}.wpseo-metabox #yoast-help-center-container{margin:8px 0}#edittag>#wp-description-wrap{display:none}#wp-description-wrap .wp-editor-area{border:0}.term-description-wrap td>textarea#description{min-height:530px}ul.wpseo-metabox-tabs{display:none;margin-top:6px;margin-bottom:0}ul.wpseo-metabox-tabs:after{display:table;clear:both;content:""}.wpseo-metabox-tabs-div ul{list-style:none}ul.wpseo-metabox-tabs li.active{background-color:#fdfdfd}.wpseo-meta-section{display:none;width:100%;max-width:calc(100% - 50px);vertical-align:top}.wpseo-meta-section.active{display:inline-block}.wpseo-metabox-sidebar{float:left;width:50px;padding:0;background-color:#fff}.wpseo-metabox-sidebar ul{margin:0}.wpseo-metabox-sidebar li{display:inline-block;margin-bottom:0;padding:5px}.wpseo-metabox-sidebar a{display:inline-block;width:35px;height:35px;font-size:20px;line-height:30px;text-decoration:none}.wpseo-metabox-sidebar li span{margin:3px 0 0 -5px;padding:0 2px 0 5px;border:0 solid transparent;border-left-width:3px;border-radius:3px}.wpseo-metabox-sidebar li span.wpseo-buy-premium{color:#a4286a}.wpseo-metabox-sidebar li span.wpseo-buy-premium:hover{color:#832055}.wpseo-metabox-sidebar li.active span{border-color:#333;color:#333}.wpseo-metabox-sidebar li.active span.wpseo-buy-premium{border-color:#a4286a;color:#a4286a}.wpseo-metabox-sidebar li.active span.wpseo-buy-premium:hover{border-color:#832055;color:#832055}ul.wpseo-metabox-tabs li{float:left;margin-right:5px;margin-bottom:-1px;padding:0;border:1px solid #dfdfdf;border-bottom:0 none}ul.wpseo-metabox-tabs li .wpseo-keyword{display:inline-block;overflow:hidden;max-width:8em;max-width:8rem;vertical-align:top;white-space:nowrap;text-overflow:ellipsis}.wpseotab{display:none;padding:20px 35px;border:1px solid #ddd;background-color:#fdfdfd}.wpseotab .wpseo-cornerstone-checkbox{margin-right:.5em}.wpseotab.content{padding:20px 15px}.wpseotab.active{display:block}#wpseofocuskeyword,#wpseosnippet{margin-bottom:2em}.wpseo-metabox-tabs .wpseo_tablink{display:inline-block;padding:5px 12px 6px;vertical-align:top;text-decoration:none}.wpseo-metabox-tabs .wpseo_content_tab a,.wpseo-metabox-tabs .wpseo_content_tab+.wpseo_keyword_tab a{padding-right:12px}.wpseo-metabox-tabs .wpseo-score-icon{margin-left:0}#wpseo-meta-section-social .wpseo-metabox-tabs .wpseo_tablink{padding:5px 7px}.wpseo-metabox-tabs .wpseo_tablink .dashicons{width:16px;height:16px;font-size:16px}.wpseo-metabox-sidebar .dashicons{width:30px;height:30px;font-size:30px}.wpseo-metabox-tabs-div div.wpseo-tabs-panel{overflow:auto;padding:.5em .9em;border:1px solid}#wpseo_meta .inside{margin:0}#wpseo_meta .inside::after{display:table;clear:both;content:""}#wpseo_meta .postbox .inside .wpseotab{font-size:13px!important}.wpseotab .select2-container,.wpseotab input,.wpseotab label,.wpseotab p.error-message,.wpseotab textarea,.yoast-metabox__description{max-width:600px}.wpseotab fieldset{padding-top:5px}.wpseotab label{display:block}.wpseotab input[type=radio]+label,.wpseotab input[type=checkbox]+label{display:inline-block;font-weight:400}.wpseotab fieldset,.wpseotab label{margin-top:2em;margin-bottom:.5em}.wpseotab input[type=checkbox],.wpseotab input[type=checkbox]+label{margin-top:2em;margin-bottom:0;font-size:1em}.wpseotab fieldset:first-child,.wpseotab input[type=checkbox]:first-child,.wpseotab input[type=checkbox]:first-child+label,.wpseotab label:first-child{margin-top:10px}.wpseotab input[type=radio]{margin-top:0}.wpseotab input[type=radio]+label{margin:0 1em 0 0}.wpseotab p.error-message,.yoast-metabox__description{margin:.5em 0}.wpseotab #yoast_wpseo_focuskw_text_input,.wpseotab select[multiple]{margin-top:0}.wpseotab .wpseo_image_upload_button{margin-left:3px}.good,.warn,.wrong{font-weight:600}.good{color:green}.warn{color:maroon}.wrong{color:#dc3232}#current_seo_title span{padding:2px 5px;background-color:#ffffe0}#focuskwresults ul{margin:0}#focuskwresults li,#focuskwresults p{font-size:13px}#focuskwresults li{margin:0 0 0 20px;list-style-type:disc}.wpseo_hidden{display:none}.wpseo_msg{margin:5px 0 10px;padding:0 5px;border:1px solid #e6db55;background-color:#ffffe0}ul.wpseo-metabox-tabs li.wpseo-tab-add-keyword{border:1px dashed #dfdfdf;border-bottom:none}.wpseo-tab-add-keyword .wpseo-add-keyword.button{height:auto;padding:5px 12px 5px 10px;background:0 0;box-shadow:none;font-size:inherit;font-weight:700;line-height:inherit;vertical-align:top;text-decoration:none}.wpseo-tab-add-keyword .wpseo-add-keyword.button:focus{box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.wpseo-tab-add-keyword .wpseo-add-keyword.button:active{-ms-transform:none;transform:none}.wpseo-add-keyword-plus{display:inline-block;margin:-1px 3px 0 0;font-size:20px;vertical-align:top}#wpseo-add-keyword-popup-title{margin:1em 0;font-size:1.3em}.snippet-editor__button.snippet-editor__edit-button:focus{border-color:#5b9dd9;outline:0;color:#23282d;background-color:#fafafa;box-shadow:0 0 3px rgba(0,115,170,.8)}.wpseo-admin-page .subsubsub li{display:inline;max-width:none}.yoast-seo-help-container{float:left;width:100%;max-width:none}.yoast-seo-help-container .yoast-help-panel{margin:.5em 0!important}.wpseo_content_wrapper p.search-box{margin:10px 0 5px}.wpseo-metabox-tabs .active a{color:#333}#wpseotab .ui-widget-content .ui-state-hover{border:1px solid #dfdfdf;color:#333;background:#f1f1f1}.yst-traffic-light-container{display:block;height:30px}.yst-traffic-light{width:19px;height:30px;margin:0 0 0 5px}.yst-traffic-light .traffic-light-color{display:none}.yst-traffic-light.bad .traffic-light-red,.yst-traffic-light.good .traffic-light-green,.yst-traffic-light.init .traffic-light-init,.yst-traffic-light.na .traffic-light-empty,.yst-traffic-light.ok .traffic-light-orange{display:inline}#wpseo-score{float:left;margin:0 5px 0 -5px}.yoast-seo-score .yoast-logo.svg{float:left;width:18px;height:18px;margin-right:5px;background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23999%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E") no-repeat;background-size:18px}.yoast-seo-score .yoast-logo.svg.good{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%237ad03a%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E")}.yoast-seo-score .yoast-logo.svg.ok{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23ee7c1b%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E")}.yoast-seo-score .yoast-logo.svg.bad{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23dc3232%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E")}.yoast-seo-score .yoast-logo.svg.na{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23999%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E")}.yoast-seo-score .yoast-logo.svg.noindex{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%231e8cbe%22%20d%3D%22M403%20218h691l%2D26%2072h%2D665q%2D110%200%2D188%2E5%2079t%2D78%2E5%20189v771q0%2095%2060%2E5%20169%2E5t153%2E5%2093%2E5q23%205%2098%205v72h%2D45q%2D140%200%2D239%2E5%2D100t%2D99%2E5%2D240v%2D771q0%2D140%2099%2E5%2D240t239%2E5%2D100zm851%2D218h247l%2D482%201294q%2D23%2061%2D40%2E5%20103%2E5t%2D45%2098%2D54%2093%2E5%2D64%2E5%2078%2E5%2D79%2E5%2065%2D95%2E5%2041%2D116%2018%2E5v%2D195q163%2D26%20220%2D182%2020%2D52%2020%2D105%200%2D54%2D20%2D106l%2D285%2D733h228l187%20585zm474%20558v1111h%2D795q37%2D55%2045%2D73h678v%2D1038q0%2D85%2D49%2E5%2D155t%2D129%2E5%2D99l25%2D67q101%2034%20163%2E5%20123%2E5t62%2E5%20197%2E5z%22%2F%3E%3C%2Fsvg%3E")}.term-php .wpseo-taxonomy-metabox-postbox>h2{margin:0;padding:8px 12px;border-bottom:1px solid #eee;font-size:14px;line-height:1.4}.wpseo-buy-premium{padding-right:5px;color:#a4286a}.wpseo-metabox-go-to::after{position:static;top:auto;right:auto;width:auto;height:auto;border:none;content:" \00BB"}#wpseo-buy-premium-popup-button.button-buy-premium{border-color:#a4286a;color:#fff;background:#a4286a}.wpseo-metabox-buy-premium{position:absolute;top:0;right:12px;padding:8px 0}.wpseo-metabox-buy-premium .dashicons{text-decoration:none}.wpseosnippet .yoast-section{width:auto;max-width:640px;padding:0}#TB_window #TB_ajaxContent p{margin:5px 0 0;padding:5px 0 0}#TB_window #TB_ajaxContent ul{margin:5px 0 10px}#TB_window #TB_ajaxContent li{margin:5px 0 0;list-style:none}#TB_window #TB_ajaxContent li::before{margin:0 10px 0 0;font-weight:700;content:"+"}.yoast-section__heading-icon-list{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M384%201408q0%2080%2D56%20136t%2D136%2056%2D136%2D56%2D56%2D136%2056%2D136%20136%2D56%20136%2056%2056%20136zm0%2D512q0%2080%2D56%20136t%2D136%2056%2D136%2D56%2D56%2D136%2056%2D136%20136%2D56%20136%2056%2056%20136zm1408%20416v192q0%2013%2D9%2E5%2022%2E5t%2D22%2E5%209%2E5h%2D1216q%2D13%200%2D22%2E5%2D9%2E5t%2D9%2E5%2D22%2E5v%2D192q0%2D13%209%2E5%2D22%2E5t22%2E5%2D9%2E5h1216q13%200%2022%2E5%209%2E5t9%2E5%2022%2E5zm%2D1408%2D928q0%2080%2D56%20136t%2D136%2056%2D136%2D56%2D56%2D136%2056%2D136%20136%2D56%20136%2056%2056%20136zm1408%20416v192q0%2013%2D9%2E5%2022%2E5t%2D22%2E5%209%2E5h%2D1216q%2D13%200%2D22%2E5%2D9%2E5t%2D9%2E5%2D22%2E5v%2D192q0%2D13%209%2E5%2D22%2E5t22%2E5%2D9%2E5h1216q13%200%2022%2E5%209%2E5t9%2E5%2022%2E5zm0%2D512v192q0%2013%2D9%2E5%2022%2E5t%2D22%2E5%209%2E5h%2D1216q%2D13%200%2D22%2E5%2D9%2E5t%2D9%2E5%2D22%2E5v%2D192q0%2D13%209%2E5%2D22%2E5t22%2E5%2D9%2E5h1216q13%200%2022%2E5%209%2E5t9%2E5%2022%2E5z%22%2F%3E%3C%2Fsvg%3E")}.yoast-section__heading-icon-key{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M832%20512q0%2D80%2D56%2D136t%2D136%2D56%2D136%2056%2D56%20136q0%2042%2019%2083%2D41%2D19%2D83%2D19%2D80%200%2D136%2056t%2D56%20136%2056%20136%20136%2056%20136%2D56%2056%2D136q0%2D42%2D19%2D83%2041%2019%2083%2019%2080%200%20136%2D56t56%2D136zm851%20704q0%2017%2D49%2066t%2D66%2049q%2D9%200%2D28%2E5%2D16t%2D36%2E5%2D33%2D38%2E5%2D40%2D24%2E5%2D26l%2D96%2096%20220%20220q28%2028%2028%2068%200%2042%2D39%2081t%2D81%2039q%2D40%200%2D68%2D28l%2D671%2D671q%2D176%20131%2D365%20131%2D163%200%2D265%2E5%2D102%2E5t%2D102%2E5%2D265%2E5q0%2D160%2095%2D313t248%2D248%20313%2D95q163%200%20265%2E5%20102%2E5t102%2E5%20265%2E5q0%20189%2D131%20365l355%20355%2096%2D96q%2D3%2D3%2D26%2D24%2E5t%2D40%2D38%2E5%2D33%2D36%2E5%2D16%2D28%2E5q0%2D17%2049%2D66t66%2D49q13%200%2023%2010%206%206%2046%2044%2E5t82%2079%2E5%2086%2E5%2086%2073%2078%2028%2E5%2041z%22%2F%3E%3C%2Fsvg%3E")}.yoast-section__heading-icon-edit{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555555%22%20d%3D%22M491%201536l91%2D91%2D235%2D235%2D91%2091v107h128v128h107zm523%2D928q0%2D22%2D22%2D22%2D10%200%2D17%207l%2D542%20542q%2D7%207%2D7%2017%200%2022%2022%2022%2010%200%2017%2D7l542%2D542q7%2D7%207%2D17zm%2D54%2D192l416%20416%2D832%20832h%2D416v%2D416zm683%2096q0%2053%2D37%2090l%2D166%20166%2D416%2D416%20166%2D165q36%2D38%2090%2D38%2053%200%2091%2038l235%20234q37%2039%2037%2091z%22%20%2F%3E%3C%2Fsvg%3E")}.yoast-section{position:relative;padding:0 20px 15px;background-color:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2)}.yoast-section__heading{margin:0 -20px 15px;padding:8px 20px;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.yoast-section__heading-icon{padding-left:44px;background-repeat:no-repeat;background-position:left 20px top .6em;background-size:16px}.yoast-section,.yoast-section *,.yoast-section :after,.yoast-section :before,.yoast-section:after,.yoast-section:before{box-sizing:border-box}.yoast-tooltip.yoast-tooltip-hidden::after,.yoast-tooltip.yoast-tooltip-hidden::before{display:none}.screen-reader-text.wpseo-generic-tab-textual-score,.screen-reader-text.wpseo-keyword-tab-textual-score{display:block}.yoast-notice-go-premium{margin:0;border-left-color:#a4286a;background:#f1f1f1}@media screen and (max-width:782px){.wpseo-metabox-sidebar{display:inline-block;float:none;width:auto;margin:0 0 10px -5px;padding:0;vertical-align:top}.wpseo-meta-section.active{display:block;clear:both;max-width:none}.wpseo-metabox-sidebar ul{display:inline-block}.wpseo-metabox-sidebar li{float:left;text-align:center}.wpseo-metabox-sidebar .wpseo-meta-section-link{width:40px;height:40px}.wpseo-meta-section-link .dashicons,.wpseo-meta-section-link .yst-traffic-light-container{display:block;width:40px;height:35px;margin:0;padding:5px 0 2px;border-bottom-width:3px;border-left-width:0}.wpseo-meta-section-link .dashicons:before,.wpseo-meta-section-link .yst-traffic-light{margin:0}.wpseo-meta-section-link .dashicons-admin-generic:before{position:relative;left:1px}.wpseo-metabox-buy-premium .wpseo-buy-premium{display:inline-block;width:20px;height:20px;padding:0 5px}.yoast-help-panel{max-width:none!important}#wpseo-crawl-issues-table-form .subsubsub{float:none;max-width:calc(100vw - 20px)}#wpseo-crawl-issues-table-form .yoast-help-button{margin-top:3px}.wpseotab select[multiple]{height:auto!important}}@media screen and (max-width:600px){.wpseotab{padding:20px}.wpseotab.content{padding:20px 0}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-1720-rtl.css similarity index 81% rename from wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-720-rtl.min.css rename to wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-1720-rtl.css index a84238fa..020eafe0 100644 --- a/wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-720-rtl.min.css +++ b/wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-1720-rtl.css @@ -1 +1 @@ -.wpseo-is-primary-term,.wpseo-primary-term>label{font-weight:600}.wpseo-non-primary-term>.wpseo-is-primary-term,.wpseo-primary-term>.wpseo-make-primary-term,.wpseo-term-unchecked>.wpseo-is-primary-term,.wpseo-term-unchecked>.wpseo-make-primary-term{display:none}.wpseo-is-primary-term,.wpseo-make-primary-term{float:left}.wpseo-non-primary-term:after,.wpseo-non-primary-term:before,.wpseo-primary-term:after,.wpseo-primary-term:before{display:table;content:""}.wpseo-non-primary-term:after,.wpseo-primary-term:after{clear:both}.wpseo-make-primary-term{margin:4px 0 0;padding:0;border:none;color:#0073aa;background:0 0;text-decoration:underline;cursor:pointer}.wpseo-make-primary-term:hover{color:#00a0d2} \ No newline at end of file +.wpseo-is-primary-term,.wpseo-primary-term>label{font-weight:600}.wpseo-non-primary-term>.wpseo-is-primary-term,.wpseo-primary-term>.wpseo-make-primary-term,.wpseo-term-unchecked>.wpseo-is-primary-term,.wpseo-term-unchecked>.wpseo-make-primary-term{display:none}.wpseo-is-primary-term,.wpseo-make-primary-term{float:left}.wpseo-non-primary-term:after,.wpseo-non-primary-term:before,.wpseo-primary-term:after,.wpseo-primary-term:before{display:table;content:""}.wpseo-non-primary-term:after,.wpseo-primary-term:after{clear:both}.wpseo-make-primary-term{margin:4px 0 0;padding:0;border:none;color:#0073aa;background:none;text-decoration:underline;cursor:pointer}.wpseo-make-primary-term:hover{color:#00a0d2} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-1720.css similarity index 81% rename from wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-720.min.css rename to wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-1720.css index 04564fad..f73e4133 100644 --- a/wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-720.min.css +++ b/wp-content/plugins/wordpress-seo/css/dist/metabox-primary-category-1720.css @@ -1 +1 @@ -.wpseo-is-primary-term,.wpseo-primary-term>label{font-weight:600}.wpseo-non-primary-term>.wpseo-is-primary-term,.wpseo-primary-term>.wpseo-make-primary-term,.wpseo-term-unchecked>.wpseo-is-primary-term,.wpseo-term-unchecked>.wpseo-make-primary-term{display:none}.wpseo-is-primary-term,.wpseo-make-primary-term{float:right}.wpseo-non-primary-term:after,.wpseo-non-primary-term:before,.wpseo-primary-term:after,.wpseo-primary-term:before{display:table;content:""}.wpseo-non-primary-term:after,.wpseo-primary-term:after{clear:both}.wpseo-make-primary-term{margin:4px 0 0;padding:0;border:none;color:#0073aa;background:0 0;text-decoration:underline;cursor:pointer}.wpseo-make-primary-term:hover{color:#00a0d2} \ No newline at end of file +.wpseo-is-primary-term,.wpseo-primary-term>label{font-weight:600}.wpseo-non-primary-term>.wpseo-is-primary-term,.wpseo-primary-term>.wpseo-make-primary-term,.wpseo-term-unchecked>.wpseo-is-primary-term,.wpseo-term-unchecked>.wpseo-make-primary-term{display:none}.wpseo-is-primary-term,.wpseo-make-primary-term{float:right}.wpseo-non-primary-term:after,.wpseo-non-primary-term:before,.wpseo-primary-term:after,.wpseo-primary-term:before{display:table;content:""}.wpseo-non-primary-term:after,.wpseo-primary-term:after{clear:both}.wpseo-make-primary-term{margin:4px 0 0;padding:0;border:none;color:#0073aa;background:none;text-decoration:underline;cursor:pointer}.wpseo-make-primary-term:hover{color:#00a0d2} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/modal-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/modal-1720-rtl.css new file mode 100644 index 00000000..a694e270 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/modal-1720-rtl.css @@ -0,0 +1 @@ +.yoast-modal__screen-overlay{position:fixed;top:0;left:0;bottom:0;right:0;background-color:rgba(164,40,106,.6);z-index:100000;animation:edit-post__fade-in-animation .2s ease-out 0s;animation-fill-mode:forwards}.yoast-modal{background:#fff;display:flex;flex-direction:column;overflow:hidden;position:fixed;height:calc(100% - 96px);top:48px;bottom:48px;right:calc(50% - 440px);max-width:880px;width:100%}.yoast-gutenberg-modal .yoast-icon{background-color:var(--yoast-color-primary);mask-image:var(--yoast-svg-icon-yoast);-webkit-mask-image:var(--yoast-svg-icon-yoast);mask-size:100% 100%;-webkit-mask-size:100% 100%;display:inline-block;width:20px;height:20px;margin-left:8px}.yoast-tabs .yoast-modal__content{display:grid;grid-template-areas:"heading heading" "menu content" "menu footer";grid-template-rows:72px 1fr 88px;grid-template-columns:280px 1fr}.yoast-modal__heading{display:flex;align-items:center;box-sizing:border-box;min-height:72px;border-bottom:var(--yoast-border-default);padding:0 24px;grid-area:heading;background:var(--yoast-color-white)}.yoast-modal__heading .yoast-close{position:absolute;left:16px}.yoast-gutenberg-modal .components-modal__header-heading,.yoast-modal__heading h1{font-size:20px;font-weight:400;color:var(--yoast-color-primary);line-height:1.2;margin:0}.yoast-gutenberg-modal .components-modal__icon-container{display:inline-flex}.yoast-gutenberg-modal .components-modal__icon-container svg,.yoast-modal__heading-icon{fill:var(--yoast-color-primary);margin-left:16px;width:19px;height:20px;flex-shrink:0}.yoast-modal__menu{grid-area:menu;border-left:var(--yoast-border-default);overflow-y:auto}.yoast-modal__menu ul{padding:0;margin:0;list-style:none}.yoast-modal__menu li{padding:12px 16px 11px;border-bottom:var(--yoast-border-default);font-size:16px;cursor:pointer;text-decoration:none;color:var(--yoast-color-default);display:block}.yoast-modal__menu li:hover{background-color:#edd4e1}.yoast-modal__menu li.yoast-tabs__tab--selected{background-color:var(--yoast-color-primary);border-bottom:var(--yoast-border-default);color:#fff}.yoast-modal__content,.yoast-modal__section{grid-area:content;overflow-y:auto;flex-grow:1;position:relative;display:flex;flex-direction:column}.yoast-modal__section *{max-width:600px}.yoast-modal__section-header{position:sticky;top:0;background:var(--yoast-color-white);padding:24px 24px 0;z-index:10}.yoast-modal__section .yoast-h2{border-bottom:var(--yoast-border-default);padding-bottom:24px}.yoast-modal__footer{grid-area:footer;padding:0;border-top:var(--yoast-border-default);display:flex;align-self:flex-end;align-items:center;justify-content:flex-end;position:sticky;bottom:0;background:var(--yoast-color-white);margin:0 24px;z-index:10;box-sizing:border-box;min-height:88px;width:calc(100% - 48px)}.yoast-modal__settings-saved{position:relative;margin-left:16px;display:inline-flex;align-items:center}.yoast-modal__settings-saved:before{content:"";background:var(--yoast-checkmark--green) no-repeat 50%;height:13px;width:14px;display:inline-block;margin-left:8px}.yoast-modal__footer .yoast-button{display:block}.yoast-modal__section-content{padding:24px;flex-grow:1}@media screen and (max-width:880px){.yoast-modal{top:0;bottom:0;right:0;left:0;height:auto}}@media screen and (max-width:782px){.yoast-modal{overflow-y:initial}.yoast-modal.yoast-modal-collapsible{padding-bottom:72px}.yoast-tabs .yoast-modal__content{grid-template-rows:48px 1fr 72px}.yoast-modal__heading{padding:0 16px;position:fixed;top:0;width:100%;min-height:48px;z-index:11}.yoast-modal__heading h1{font-size:var(--yoast-font-size-default)}.yoast-close svg{width:10px}.yoast-modal__heading-icon{height:15px;margin-left:8px}.yoast .yoast-close{left:3px}.yoast-modal__heading .yoast-h2{font-size:var(--yoast-font-size-default)}.yoast-modal__section{overflow:initial;flex-grow:0}.yoast-modal__section-content{padding:24px 0;margin:0 16px}.yoast-modal__section:first-of-type{margin-top:48px}.yoast-modal__section:last-of-type{margin-bottom:72px}.yoast-modal__section-header{top:48px;position:sticky;padding:0;margin:0}.yoast-modal__section-open .yoast-modal__section-header{padding-right:0;padding-left:0;margin-right:16px;margin-left:16px}.yoast-modal__section-open{border-bottom:var(--yoast-border-default)}.yoast-modal__footer{width:100%;min-height:72px;margin:0;padding:0 16px;position:fixed;z-index:11}.yoast-modal-collapsible .yoast-modal__footer{min-height:72px}.yoast-modal-collapsible .yoast-modal__section-content{padding:24px 16px;border-bottom:var(--yoast-border-default);margin:0}.yoast-collapsible__hidden{display:none}.yoast-collapsible__trigger{padding:16px;border:none;border-bottom:var(--yoast-border-default);cursor:pointer;justify-content:space-between;font-size:var(--yoast-font-size-default);width:100%;text-align:right;background:#fff;color:var(--yoast-color-primary)}.yoast-collapsible__trigger[aria-expanded=true] .yoast-collapsible__icon{transform:rotate(-180deg)}.yoast-collapsible__trigger[aria-expanded=true]{padding:16px 0;width:calc(100% - 32px);margin:0 16px}.yoast-collapsible__icon{background-color:var(--yoast-color-white);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='%23404040'%3E%3Cpath d='M1.4 0L6 4.6 10.6 0 12 1.4 6 7.5 0 1.4z'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:10px auto;width:19px;height:19px;border:none;display:block;float:left}.yoast-collapsible-block{width:100%;margin-top:48px}.yoast-collapsible-block+.yoast-collapsible-block{margin-top:0}}.yoast-post-settings-modal{width:880px;height:100%;max-width:calc(100% - 96px);max-height:calc(100% - 96px);overflow:hidden}.yoast-modal-content{padding:16px}@media (min-width:782px){.yoast-modal-content--columns{display:grid;grid-template-columns:1fr 1fr;grid-gap:24px}}.yoast-post-settings-modal__button-container{padding:16px;display:flex;flex-direction:column;border-bottom:1px solid rgba(0,0,0,.2)}.yoast-post-settings-modal .components-modal__content{padding:0;display:flex;flex-direction:column}.yoast-post-settings-modal .components-modal__header{margin:0;flex-shrink:0;border-bottom:var(--yoast-border-default)}.yoast-post-settings-modal .yoast-notice-container{z-index:1;position:sticky;bottom:0;right:0;width:100%;margin-top:auto}.yoast-post-settings-modal .yoast-notice-container>hr{margin-top:-1px;margin-bottom:0}.yoast-post-settings-modal .yoast-content-container{overflow-y:auto;flex-grow:1}.yoast-post-settings-modal .yoast-button-container{display:flex;flex-direction:row;justify-content:flex-end;padding:24px;margin:0}.yoast-post-settings-modal .yoast-button-container p{color:var(--yoast-color-label-help);padding-left:24px;align-self:center}.yoast-post-settings-modal .yoast-button-container button{flex-shrink:0;max-height:45px;align-self:center}@media only screen and (max-width:600px){.yoast-post-settings-modal{max-height:100%;max-width:100%}.yoast-post-settings-modal .yoast-button-container{padding:16px;justify-content:space-between}.yoast-post-settings-modal .yoast-button-container p{padding-left:0}}.yoast-related-keyphrases-modal{max-width:712px}#yoast-get-related-keyphrases-metabox,#yoast-get-related-keyphrases-sidebar{margin-top:8px}.yoast-gutenberg-modal .yoast-related-keyphrases-modal__content{min-height:66vh;position:relative}#yoast-semrush-country-selector{position:relative;border:none}.yoast-related-keyphrases-modal__chart{display:block} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/modal-1720.css b/wp-content/plugins/wordpress-seo/css/dist/modal-1720.css new file mode 100644 index 00000000..86291988 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/modal-1720.css @@ -0,0 +1 @@ +.yoast-modal__screen-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background-color:rgba(164,40,106,.6);z-index:100000;animation:edit-post__fade-in-animation .2s ease-out 0s;animation-fill-mode:forwards}.yoast-modal{background:#fff;display:flex;flex-direction:column;overflow:hidden;position:fixed;height:calc(100% - 96px);top:48px;bottom:48px;left:calc(50% - 440px);max-width:880px;width:100%}.yoast-gutenberg-modal .yoast-icon{background-color:var(--yoast-color-primary);mask-image:var(--yoast-svg-icon-yoast);-webkit-mask-image:var(--yoast-svg-icon-yoast);mask-size:100% 100%;-webkit-mask-size:100% 100%;display:inline-block;width:20px;height:20px;margin-right:8px}.yoast-tabs .yoast-modal__content{display:grid;grid-template-areas:"heading heading" "menu content" "menu footer";grid-template-rows:72px 1fr 88px;grid-template-columns:280px 1fr}.yoast-modal__heading{display:flex;align-items:center;box-sizing:border-box;min-height:72px;border-bottom:var(--yoast-border-default);padding:0 24px;grid-area:heading;background:var(--yoast-color-white)}.yoast-modal__heading .yoast-close{position:absolute;right:16px}.yoast-gutenberg-modal .components-modal__header-heading,.yoast-modal__heading h1{font-size:20px;font-weight:400;color:var(--yoast-color-primary);line-height:1.2;margin:0}.yoast-gutenberg-modal .components-modal__icon-container{display:inline-flex}.yoast-gutenberg-modal .components-modal__icon-container svg,.yoast-modal__heading-icon{fill:var(--yoast-color-primary);margin-right:16px;width:19px;height:20px;flex-shrink:0}.yoast-modal__menu{grid-area:menu;border-right:var(--yoast-border-default);overflow-y:auto}.yoast-modal__menu ul{padding:0;margin:0;list-style:none}.yoast-modal__menu li{padding:12px 16px 11px;border-bottom:var(--yoast-border-default);font-size:16px;cursor:pointer;text-decoration:none;color:var(--yoast-color-default);display:block}.yoast-modal__menu li:hover{background-color:#edd4e1}.yoast-modal__menu li.yoast-tabs__tab--selected{background-color:var(--yoast-color-primary);border-bottom:var(--yoast-border-default);color:#fff}.yoast-modal__content,.yoast-modal__section{grid-area:content;overflow-y:auto;flex-grow:1;position:relative;display:flex;flex-direction:column}.yoast-modal__section *{max-width:600px}.yoast-modal__section-header{position:sticky;top:0;background:var(--yoast-color-white);padding:24px 24px 0;z-index:10}.yoast-modal__section .yoast-h2{border-bottom:var(--yoast-border-default);padding-bottom:24px}.yoast-modal__footer{grid-area:footer;padding:0;border-top:var(--yoast-border-default);display:flex;align-self:flex-end;align-items:center;justify-content:flex-end;position:sticky;bottom:0;background:var(--yoast-color-white);margin:0 24px;z-index:10;box-sizing:border-box;min-height:88px;width:calc(100% - 48px)}.yoast-modal__settings-saved{position:relative;margin-right:16px;display:inline-flex;align-items:center}.yoast-modal__settings-saved:before{content:"";background:var(--yoast-checkmark--green) no-repeat 50%;height:13px;width:14px;display:inline-block;margin-right:8px}.yoast-modal__footer .yoast-button{display:block}.yoast-modal__section-content{padding:24px;flex-grow:1}@media screen and (max-width:880px){.yoast-modal{top:0;bottom:0;left:0;right:0;height:auto}}@media screen and (max-width:782px){.yoast-modal{overflow-y:initial}.yoast-modal.yoast-modal-collapsible{padding-bottom:72px}.yoast-tabs .yoast-modal__content{grid-template-rows:48px 1fr 72px}.yoast-modal__heading{padding:0 16px;position:fixed;top:0;width:100%;min-height:48px;z-index:11}.yoast-modal__heading h1{font-size:var(--yoast-font-size-default)}.yoast-close svg{width:10px}.yoast-modal__heading-icon{height:15px;margin-right:8px}.yoast .yoast-close{right:3px}.yoast-modal__heading .yoast-h2{font-size:var(--yoast-font-size-default)}.yoast-modal__section{overflow:initial;flex-grow:0}.yoast-modal__section-content{padding:24px 0;margin:0 16px}.yoast-modal__section:first-of-type{margin-top:48px}.yoast-modal__section:last-of-type{margin-bottom:72px}.yoast-modal__section-header{top:48px;position:sticky;padding:0;margin:0}.yoast-modal__section-open .yoast-modal__section-header{padding-left:0;padding-right:0;margin-left:16px;margin-right:16px}.yoast-modal__section-open{border-bottom:var(--yoast-border-default)}.yoast-modal__footer{width:100%;min-height:72px;margin:0;padding:0 16px;position:fixed;z-index:11}.yoast-modal-collapsible .yoast-modal__footer{min-height:72px}.yoast-modal-collapsible .yoast-modal__section-content{padding:24px 16px;border-bottom:var(--yoast-border-default);margin:0}.yoast-collapsible__hidden{display:none}.yoast-collapsible__trigger{padding:16px;border:none;border-bottom:var(--yoast-border-default);cursor:pointer;justify-content:space-between;font-size:var(--yoast-font-size-default);width:100%;text-align:left;background:#fff;color:var(--yoast-color-primary)}.yoast-collapsible__trigger[aria-expanded=true] .yoast-collapsible__icon{transform:rotate(180deg)}.yoast-collapsible__trigger[aria-expanded=true]{padding:16px 0;width:calc(100% - 32px);margin:0 16px}.yoast-collapsible__icon{background-color:var(--yoast-color-white);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='%23404040'%3E%3Cpath d='M1.4 0L6 4.6 10.6 0 12 1.4 6 7.5 0 1.4z'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:10px auto;width:19px;height:19px;border:none;display:block;float:right}.yoast-collapsible-block{width:100%;margin-top:48px}.yoast-collapsible-block+.yoast-collapsible-block{margin-top:0}}.yoast-post-settings-modal{width:880px;height:100%;max-width:calc(100% - 96px);max-height:calc(100% - 96px);overflow:hidden}.yoast-modal-content{padding:16px}@media (min-width:782px){.yoast-modal-content--columns{display:grid;grid-template-columns:1fr 1fr;grid-gap:24px}}.yoast-post-settings-modal__button-container{padding:16px;display:flex;flex-direction:column;border-bottom:1px solid rgba(0,0,0,.2)}.yoast-post-settings-modal .components-modal__content{padding:0;display:flex;flex-direction:column}.yoast-post-settings-modal .components-modal__header{margin:0;flex-shrink:0;border-bottom:var(--yoast-border-default)}.yoast-post-settings-modal .yoast-notice-container{z-index:1;position:sticky;bottom:0;left:0;width:100%;margin-top:auto}.yoast-post-settings-modal .yoast-notice-container>hr{margin-top:-1px;margin-bottom:0}.yoast-post-settings-modal .yoast-content-container{overflow-y:auto;flex-grow:1}.yoast-post-settings-modal .yoast-button-container{display:flex;flex-direction:row;justify-content:flex-end;padding:24px;margin:0}.yoast-post-settings-modal .yoast-button-container p{color:var(--yoast-color-label-help);padding-right:24px;align-self:center}.yoast-post-settings-modal .yoast-button-container button{flex-shrink:0;max-height:45px;align-self:center}@media only screen and (max-width:600px){.yoast-post-settings-modal{max-height:100%;max-width:100%}.yoast-post-settings-modal .yoast-button-container{padding:16px;justify-content:space-between}.yoast-post-settings-modal .yoast-button-container p{padding-right:0}}.yoast-related-keyphrases-modal{max-width:712px}#yoast-get-related-keyphrases-metabox,#yoast-get-related-keyphrases-sidebar{margin-top:8px}.yoast-gutenberg-modal .yoast-related-keyphrases-modal__content{min-height:66vh;position:relative}#yoast-semrush-country-selector{position:relative;border:none}.yoast-related-keyphrases-modal__chart{display:block} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/monorepo-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/monorepo-1720-rtl.css new file mode 100644 index 00000000..3762c379 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/monorepo-1720-rtl.css @@ -0,0 +1 @@ +:root{--yoast-border-default:1px solid rgba(0,0,0,0.2);--yoast-color-default:#404040;--yoast-color-default-darker:#303030;--yoast-color-primary:#a4286a;--yoast-color-secondary:#f7f7f7;--yoast-color-white:#fff;--yoast-color-green:#6ea029;--yoast-color-primary-darker:#7b1e50;--yoast-color-primary-lighter:#f5d6e6;--yoast-color-secondary-darker:#d9d9d9;--yoast-color-button-upsell:#fec228;--yoast-color-button-upsell-hover:#f2ae01;--yoast-color-dark:#303030;--yoast-color-sale:#fec228;--yoast-color-sale-darker:#feb601;--yoast-color-border:rgba(0,0,0,0.2);--yoast-color-label:#303030;--yoast-color-label-help:#707070;--yoast-color-active:#6ea029;--yoast-color-inactive:#dc3232;--yoast-color-inactive-text:#707070;--yoast-color-inactive-grey:#9e9e9e;--yoast-color-inactive-grey-light:#f1f1f1;--yoast-color-active-light:#b6cf94;--yoast-transition-default:all 150ms ease-out;--yoast-color-link:#006dac;--yoast-color-border--default:rgba(0,0,0,0.2);--yoast-color-focus:0 0 0 2px #007fff,0 0 0 5px #bfdfff;--yoast-svg-icon-chevron-down:url('data:image/svg+xml;charset=utf-8,');--yoast-svg-icon-chevron-up:url('data:image/svg+xml;charset=utf-8,');--yoast-checkmark--white:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23FFF' viewBox='0 0 512 512'%3E%3Cpath d='M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z'/%3E%3C/svg%3E");--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url('data:image/svg+xml;charset=utf-8,');--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url('data:image/svg+xml;charset=utf-8,');--yoast-svg-icon-edit:url('data:image/svg+xml;charset=utf-8,');--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url('data:image/svg+xml;charset=utf-8,');--yoast-checkmark--green:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%236EA029' viewBox='0 0 512 512'%3E%3Cpath d='M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z'/%3E%3C/svg%3E");--yoast-exclamation-mark:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23DC3232' viewBox='0 0 512 512'%3E%3Cpath d='M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z'/%3E%3C/svg%3E");--yoast-svg-icon-schema:url("data:image/svg+xml;charset=utf-8,%3Csvg width='512' height='512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M149.333 56v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zm181.334 240v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm32-240v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24zm-32 80V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm-205.334 56H24c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zm386.667-56H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm0 160H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zM181.333 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24z'/%3E%3C/svg%3E");--yoast-svg-icon-schema-active:url("data:image/svg+xml;charset=utf-8,%3Csvg width='512' height='512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='D4444' d='M149.333 56v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zm181.334 240v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm32-240v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24zm-32 80V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm-205.334 56H24c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zm386.667-56H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm0 160H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zM181.333 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24z'/%3E%3C/svg%3E");--yoast-svg-icon-image:url("data:image/svg+xml;charset=utf-8,%3Csvg fill='none' stroke='%23707070' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 16l4.586-4.586a2 2 0 0 1 2.828 0L16 16m-2-2l1.586-1.586a2 2 0 0 1 2.828 0L20 14m-6-6h.01M6 20h12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2z'/%3E%3C/svg%3E");--yoast-font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;--yoast-font-size-default:14px;--yoast-font-weight-default:400;--yoast-font-weight-bold:600;--yoast-color-font-default:#404040;--yoast-shadow-default:0px 3px 6px rgba(0,0,0,0.15)}.yoast-h1,.yoast-h2,.yoast-h3{font-weight:400;color:var(--yoast-color-primary);line-height:1.2;margin:0}.yoast-h1 a,.yoast-h2 a,.yoast-h3 a{color:var(--yoast-color-primary);text-decoration:none}.yoast-h1{font-size:24px}.yoast-h2{font-size:20px}.yoast-h3{font-size:16px}.yoast-paragraph{font-size:14px;font-size:var(--yoast-font-size-default);margin-top:0}.screen-reader-text{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.visually-hidden{position:absolute;overflow:hidden;height:1px;width:1px;clip:rect(1px,1px,1px,1px);white-space:nowrap;word-wrap:normal}@media (max-width:782px){.yoast-show-on-mobile{display:initial!important}}@media (min-width:782px){.yoast-hide-on-desktop{display:none}}.yoast-field-group__title-separator{display:flex;flex-wrap:wrap}.yoast-field-group__title-separator label{display:flex;align-items:center;justify-content:center;flex-direction:column;border:var(--yoast-border-default);cursor:pointer;height:42px;width:42px;margin:0 0 6px 6px;box-sizing:border-box}.yoast-field-group__title-separator input[type=radio]:checked+label{border:3px solid var(--yoast-color-primary)}.yoast .yoast-button{display:inline-flex;align-items:center;justify-content:center;position:relative;padding:10px 12px 12px;text-decoration:none;border-radius:4px;border:1px solid rgba(0,0,0,.2);box-shadow:inset 0 -2px 0 rgba(0,0,0,.1);transition:background-color .15s ease-out 0s;line-height:1.2;font-size:14px;cursor:pointer}.yoast-close:focus,.yoast-hide:focus,.yoast-remove:focus,.yoast .yoast-button:focus{box-shadow:var(--yoast-color-focus);outline:none}.yoast-close::-moz-focus-inner,.yoast-hide::-moz-focus-inner,.yoast-remove::-moz-focus-inner,.yoast .yoast-button::-moz-focus-inner{border:0}.yoast .yoast-button:not(:disabled):active{box-shadow:none;top:2px}.yoast .yoast-button:disabled{opacity:.5;cursor:default}.yoast .yoast-button--primary{color:var(--yoast-color-white);background-color:var(--yoast-color-primary);border:1px solid rgba(0,0,0,.2)}.yoast .yoast-button--primary:visited{color:var(--yoast-color-white);border:1px solid rgba(0,0,0,.2)}.yoast .yoast-button--primary:active,.yoast .yoast-button--primary:not(:disabled):hover{color:var(--yoast-color-white);background-color:var(--yoast-color-primary-darker);border:1px solid rgba(0,0,0,.2)}.yoast .yoast-button--primary:focus{color:var(--yoast-color-white);background-color:var(--yoast-color-primary)}.yoast .yoast-button--secondary{color:var(--yoast-color-dark);background-color:var(--yoast-color-secondary);box-shadow:inset 0 -2px 0 rgba(0,0,0,.1)}.yoast .yoast-button--secondary:visited{color:var(--yoast-color-dark)}.yoast .yoast-button--secondary:active,.yoast .yoast-button--secondary:not(:disabled):hover{color:var(--yoast-color-dark);background-color:var(--yoast-color-secondary-darker);border:1px solid rgba(0,0,0,.2)}.yoast .yoast-button--buy{color:var(--yoast-color-dark);background-color:var(--yoast-color-sale)}.yoast .yoast-button--buy:visited{color:var(--yoast-color-dark)}.yoast .yoast-button--buy:active,.yoast .yoast-button--buy:not(:disabled):hover{color:var(--yoast-color-dark);background-color:var(--yoast-color-sale-darker)}.yoast .yoast-button--buy__caret{flex-shrink:0;display:inline-block;width:6px;height:16px;margin:0 6px 0 -2px;background-color:currentColor;-webkit-mask-image:var(--yoast-svg-icon-caret-right);mask-image:var(--yoast-svg-icon-caret-right)}.yoast .yoast-button--edit{width:20.25px;height:18px;flex-shrink:0;display:inline-block;background-color:currentColor;-webkit-mask-image:var(--yoast-svg-icon-edit);mask-image:var(--yoast-svg-icon-edit);margin-left:8px}html[dir=rtl] .yoast .yoast-button--edit{margin-left:0;margin-right:8px}html[dir=rtl] .yoast .yoast-button--buy{flex-direction:row-reverse}.yoast .yoast-button--small{font-size:13px;padding:5px 8px 8px}.yoast .yoast-button--small .yoast-button--buy__caret{width:4px;height:10px}.yoast-hide,.yoast-remove{color:#dc3232;background-color:initial;border:none;cursor:pointer;text-decoration:underline;padding:0;font-size:14px}.yoast-hide{color:var(--yoast-color-link)}.yoast-field-group__upload .yoast-button{margin-left:24px}.yoast-close{display:flex;justify-content:center;align-items:center;border:none;background:none;height:44px;width:44px;cursor:pointer;box-shadow:none;padding:0}.yoast-close svg{fill:var(--yoast-color-default);width:14px}@media screen and (max-width:782px){.yoast-close svg{width:10px}}.yoast-field-group__checkbox{display:flex;align-items:center}.yoast-field-group__checkbox:not(.yoast-field-group__checkbox--horizontal)+.yoast-field-group__checkbox{margin-top:4px}.yoast-field-group__checkbox label{cursor:pointer}.yoast-field-group__checkbox input[type=checkbox]{-webkit-appearance:none;-moz-appearance:none;width:18px;height:18px;padding:2px;margin:2px 0 0 8px;border-radius:2px;transition:background-color .15s ease-out 0s;border:var(--yoast-border-default);box-shadow:inset 0 2px 4px rgba(0,0,0,.1);position:relative;overflow:hidden;cursor:pointer}.yoast-field-group__checkbox input[type=checkbox]:checked:focus,.yoast-field-group__checkbox input[type=checkbox]:focus{box-shadow:var(--yoast-color-focus);outline:none}.yoast label+input[type=checkbox]{margin-right:16px}.yoast-field-group__checkbox input[type=checkbox]:checked{background:var(--yoast-checkmark--white) var(--yoast-color-primary) no-repeat 50%/13px;border:1px solid var(--yoast-color-primary);box-shadow:none}.yoast-field-group__checkbox input[type=checkbox]:checked:before{content:""}.yoast-field-group{position:relative;border:none;padding:0;margin:0 0 24px}.yoast-field-group__title{display:flex;align-items:center;font-weight:var(--yoast-font-weight-bold);margin:0 0 8px;color:var(--yoast-color-label);line-height:1.5;padding:0;font-size:var(--yoast-font-size-default)}.yoast-field-group__title.yoast-field-group__title--light{font-weight:var(--yoast-font-weight-default)}.yoast-field-group .field-group-description{margin:0 0 1em}.yoast-field-group__inline{display:flex;align-items:center}.yoast-field-group__inline .yoast-field-group__inputfield{margin-left:8px}.yoast-field-group__inline .yoast-button{flex-shrink:0}.yoast-field-group .components-form-token-field__label{display:none}@media screen and (max-width:782px){.yoast-field-group__inline{display:block}.yoast-field-group__inline .yoast-field-group__inputfield{margin-left:0;margin-bottom:8px}}.yoast-help{margin-right:4px}.yoast-help__icon svg{width:12px;height:12px;fill:var(--yoast-color-inactive-text);transition:var(--yoast-transition-default)}.yoast-help:focus svg,.yoast-help:hover svg{fill:var(--yoast-color-link)}.yoast-data-model{padding:0;list-style:none}.yoast-data-model li{line-height:1.4;padding:0 8px;position:relative;z-index:2;font-weight:var(--yoast-font-weight-bold)}.yoast-data-model span{float:left;font-weight:var(--yoast-font-weight-default)}.yoast-data-model li+li{margin-top:9px}.yoast-data-model li:after{position:absolute;right:0;height:20px;background:#f5d6e6;content:"";width:var(--yoast-width);z-index:-1}.yoast-image-select__preview{display:flex;justify-content:center;align-items:center;overflow:hidden;width:300px;max-width:100%;min-height:165px;max-height:200px;border:1px solid rgba(0,0,0,.2);background-color:initial;padding:0}.yoast-image-select__preview--no-preview{background:var(--yoast-color-inactive-grey-light) var(--yoast-svg-icon-image) no-repeat 50%/64px 64px}.yoast-image-select__preview.yoast-image-select__preview-has-warnings{margin-bottom:16px}.yoast-image-select__preview .yoast-image-select__preview--image{max-width:100%;height:100%;object-fit:contain}.yoast-image-select .yoast-field-group__inputfield{margin-bottom:1em}.yoast-image-select .yoast-button{margin-left:1.5em}.yoast-image-select{margin-top:1.7em;margin-bottom:1.7em}.yoast-image-select .yoast-image-select-buttons button{margin-top:1em}#organization-image-select .yoast-image-select{margin-top:0}:root{--yoast-color-placeholder:#707070}.yoast .yoast-field-group__inputfield,.yoast .yoast-field-group__textarea{width:100%;font-size:var(--yoast-font-size-default);padding:8px;background:var(--yoast-color-white);border:var(--yoast-border-default);box-shadow:inset 0 2px 4px rgba(0,0,0,.1);box-sizing:border-box;border-radius:0}.yoast .yoast-field-group__inputfield:focus,.yoast .yoast-field-group__textarea:focus{box-shadow:var(--yoast-color-focus);outline:none}.yoast-field-group__upload .yoast-field-group__inputfield{margin-bottom:8px}.yoast-field-group__inputfield{height:40px}.yoast-field-group__textarea{min-height:200px}.yoast-field-group .description+.yoast-field-group__inputfield,.yoast-field-group .description+input,.yoast-field-group__inputfield+.description,.yoast input+.description{margin-top:8px;margin-bottom:24px}.yoast .yoast-field-group__inputfield:disabled,.yoast .yoast-field-group__inputfield:read-only,.yoast .yoast-field-group__inputfield[aria-disabled=true]{background:var(--yoast-color-inactive-grey-light)}.yoast .duration-inputs__wrapper{display:flex;flex-direction:row}.yoast .duration-inputs__input-wrapper{display:flex;flex-direction:column}.yoast .duration-inputs__input{width:4em;margin:0 0 0 8px}::-ms-input-placeholder{color:#707070;color:var(--yoast-color-placeholder)}::placeholder{color:#707070;color:var(--yoast-color-placeholder);opacity:1}.yoast-insights-card{margin-top:24px;border-top:1px solid rgba(0,0,0,.1);padding-top:24px}@media(min-width:782px){.yoast-modal-content .yoast-insights-card{margin-top:inherit;border-top:none;padding-top:inherit;padding-bottom:24px;border-bottom:1px solid rgba(0,0,0,.1);margin-bottom:24px}}.yoast-insights-card__content{display:flex}.yoast-insights-card__score{flex-shrink:0;margin-left:2em;text-align:center}.yoast-insights-card__amount{display:block;font-size:3.5em;line-height:1}.yoast-field-group__radiobutton{display:flex;align-items:center}.yoast-field-group__radiobutton--vertical:not(:last-of-type){margin-bottom:8px}.yoast-field-group__radiobutton label{cursor:pointer;margin-left:16px}.yoast-field-group__radiobutton input[type=radio]{-webkit-appearance:none;-moz-appearance:none;width:18px;height:18px;padding:2px;margin:0 0 0 8px;border-radius:50%;transition:border-color .15s ease-out 0s;border:var(--yoast-border-default);box-shadow:inset 0 2px 4px rgba(0,0,0,.1);position:relative;overflow:hidden;cursor:pointer}.yoast-field-group__radiobutton input[type=radio]:checked:focus,.yoast-field-group__radiobutton input[type=radio]:focus{box-shadow:var(--yoast-color-focus);outline:none}.yoast-field-group__radiobutton input[type=radio]:checked{border-color:var(--yoast-color-primary);background-color:inherit}.yoast-field-group__radiobutton input[type=radio]:after{background-color:initial;transition:background-color .15s ease-out 0s;width:10px;height:10px;position:absolute;right:3px;top:3px;content:"";display:block;border-radius:50%}.yoast-field-group__radiobutton input[type=radio]:checked:after{background-color:var(--yoast-color-primary)}.yoast-field-group__select{display:flex;cursor:pointer;align-items:center}.yoast-select__indicator-separator{display:none}.yoast-select-container{padding:0;width:100%;display:block;min-height:2.85em;position:relative;background-color:#fff;box-shadow:inset 0 2px 4px rgba(0,0,0,.1);border-radius:0;border:var(--yoast-border-default)}.yoast-select-container .yoast-select__control--is-focused{box-shadow:var(--yoast-color-focus);outline:none}.yoast-select-container .yoast-select__indicator>svg{color:#212121}.yoast-select-container .yoast-select__menu{z-index:2;margin:0}.yoast-select-container .yoast-select__multi-value__label{color:inherit;font-size:14px;display:flex;align-items:center;box-sizing:border-box;padding:0}.yoast-select-container .yoast-select__multi-value{background-color:var(--yoast-color-primary);border:0;border-radius:12px;color:var(--yoast-color-white);padding:1px 10px 2px;margin-bottom:3px;margin-top:3px;margin-left:8px;line-height:1.5;font-weight:500;display:flex;flex-direction:row-reverse}.yoast-select-container .yoast-select__menu-list{padding:0}.yoast-select-container .yoast-select__multi-value__remove{padding:2px 0 0;display:flex;align-items:center;border-radius:2px;box-sizing:border-box;-webkit-box-align:center;margin-left:6px}.yoast-select-container .yoast-select__multi-value__remove:hover{background-color:inherit;color:var(--yoast-color-white);cursor:pointer}.yoast-select-container .yoast-select__control{border-radius:0;border:none;background-color:initial}.yoast-select-container .yoast-select__option{color:inherit;cursor:default;display:block;padding:8px 12px;width:100%;box-sizing:border-box;-webkit-user-select:none;user-select:none}.yoast-select-container .yoast-select__option--is-focused{background-color:var(--yoast-color-primary-lighter);color:var(--yoast-color-font-default)}.yoast-select-container .yoast-select__option.yoast-select__option--is-selected{background-color:var(--yoast-color-primary);color:var(--yoast-color-white)}.yoast-select-container input[type=text]:focus{box-shadow:none}.yoast-field-group__select select,.yoast-field-group select{-webkit-appearance:none;-moz-appearance:none;width:100%;font-size:var(--yoast-font-size-default);padding:5px 8px;background-color:#fff;background-image:url('data:image/svg+xml;charset=utf-8,');background-position:left 15px center;background-repeat:no-repeat;background-size:13px auto;border-radius:0;border:var(--yoast-border-default);box-shadow:inset 0 2px 4px rgba(0,0,0,.1);position:relative;max-width:300px;display:block;min-height:2.85em}.yoast-field-group .yoast-select__value-container{padding:0 8px!important}.yoast-field-group__select select:focus,.yoast-field-group select:focus{box-shadow:var(--yoast-color-focus);outline:none}.yoast-field-group__select select,.yoast-field-group select{line-height:1.9;padding-left:40px}.yoast-field-group select.yoast-select--inline{display:inline-block}.yoast-field-group--inline{max-width:300px;display:inline-block;width:100%;margin-left:8px}.yoast-star-rating{width:65px;height:12px;display:inline-block}.yoast-star-rating span{height:100%;width:100%;background-size:13px 12px;background-repeat:repeat-x}.yoast-star-rating__placeholder{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAAmCAQAAAAYCMGrAAAA+klEQVR4AcWV4cbtMBBFF0MIVUopoVSrhDDv/3gf/RFRpzdNOty1HiBO99mzeYWgCMZMKCPGrCgrxiSUhCkDeukxJKCXAUMiehkxw6FZhxEzmp0x4kCzByYISqlYdal0supS6WrVpdLEK0YSamJiJOPY0c/uOG4s6CcXfuKJaJcRzyNCQJsNiF1sRTR1hP11NNJ8RCrONOPRf+r7J+TZgQ5CNfMOYvW/2YxDqzqA/57+gVY9eiakrnyZEGXDsaE3p/4JScwPX3rtnZATDxnPWT7X16XAHaH8HWNrlxJD9TyGti5tCM84zpZe+RxNjeX9tZqLaGoMxN/P/wHP5Vw+8ZxnEQAAAABJRU5ErkJggg==);display:inline-block;overflow:hidden;position:relative}.yoast-star-rating__fill{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAAmBAMAAABALxQTAAAAFVBMVEVMaXH4twP4twP4twP4twP4twP4twP7w8S/AAAAB3RSTlMAFv5uPpvQloUsTQAAAMFJREFUeAGE0TEOgzAMQFEXoDNiYC6/wFxxAsTADDkB5f6HqNRENXUi8TYiRfnY8lNXkjBOkuBWSeAhsYJOYiW9xO4MEqshkTbCSyIH7GLdgFasHHgmwkikZQD6OROZRG4Hxju8o/TNhbNhCqkOxaZDVKdxNnq/EjUS/A2o0PuXpyVeb9bjDWY9QSWXDQfBbtbjtWY9bM4sqfx+5yYt8wNcAFEzrGGkk5668KsFrKewPtQ3aFqh8WOnYZ+lIBQkgykAWk8rlAqcHfQAAAAASUVORK5CYII=);display:block}.yoast-table{font-size:var(--yoast-font-size-default);color:var(--yoast-color-default);line-height:1.2;border-spacing:0;border:var(--yoast-border-default);border-bottom:0;width:100%}.yoast-table tbody tr:nth-child(odd){background-color:#f9f9f9}.yoast-table th{color:var(--yoast-color-dark);text-align:right;padding:18px 12px;border-bottom:var(--yoast-border-default);white-space:nowrap;font-weight:var(--yoast-font-weight-bold)}.yoast-table td{padding:18px 12px;border-bottom:var(--yoast-border-default)}.yoast-table td:first-child,.yoast-table th:first-child{padding-right:16px}.yoast-table td:last-child,.yoast-table th:last-child{padding-left:16px}td.yoast-table__button,td.yoast-table__image{padding:10px 18px 9px}.yoast-table.yoast-table--nobreak td,td.yoast-table--nobreak,tr.yoast-table--nobreak td{white-space:nowrap}th.yoast-table--primary{width:100%}td.yoast-table--nopadding{padding:0 12px}.yoast-badge{display:inline-block;min-height:16px;padding:0 8px;border-radius:8px;font-weight:600;font-size:10px;line-height:1.6}.yoast-badge__in-label{margin-right:8px;vertical-align:text-top}.yoast-new-badge{background-color:#cce5ff;color:#004973}.yoast-premium-badge{background-color:#fff3cd;color:#674e00}.yoast-feature{max-width:600px;margin-left:150px}.yoast-toggle__item{display:flex;justify-content:space-between;padding-bottom:16px;border-bottom:1px solid var(--yoast-color-border);margin-bottom:16px}.yoast-toggle__item-disabled{position:relative}.yoast-toggle__item-disabled .yoast-button.yoast-button--buy{position:absolute;right:100%;margin-right:32px;white-space:nowrap}.yoast-toggle__item-disabled .yoast-toggle,.yoast-toggle__item-disabled .yoast-toggle__item-title{opacity:.5}.yoast-toggle__item-title{display:flex;font-weight:700;align-items:center}input[type=checkbox].yoast-toggle__checkbox{height:23px;overflow:hidden;position:absolute;margin-right:8px;width:34px;z-index:1;box-shadow:none;border:0;background-color:initial;-webkit-appearance:none;-moz-appearance:none}input[type=checkbox].yoast-toggle__checkbox:checked:before{content:none}.yoast-toggle__switch{display:inline-block;position:relative;background-color:var(--yoast-color-inactive-grey);width:34px;height:14px;border-radius:8px;margin-right:8px;margin-left:8px}.yoast-toggle__checkbox:focus~.yoast-toggle__switch:before{box-shadow:var(--yoast-color-focus)}.yoast-toggle__switch:before{content:"";position:absolute;top:-3px;right:0;background-color:var(--yoast-color-inactive-grey-light);width:20px;height:20px;border-radius:50%;box-shadow:0 1px 2px 0 rgba(0,0,0,.4);border:.5px solid rgba(0,0,0,.1);box-sizing:border-box}.yoast-toggle,.yoast-toggle--inverse{position:relative;display:grid;grid-template:1fr/repeat(3,auto);align-items:center}.yoast-toggle--inverse>*,.yoast-toggle>*{grid-row:1}.yoast-toggle--inactive,.yoast-toggle--inverse .yoast-toggle--active{grid-column:1}.yoast-toggle__checkbox,.yoast-toggle__switch{grid-column:2}.yoast-toggle--active,.yoast-toggle--inverse .yoast-toggle--inactive{grid-column:3}.yoast-toggle--inverse .yoast-toggle__checkbox:not(:checked)~.yoast-toggle__switch,.yoast-toggle .yoast-toggle__checkbox:checked~.yoast-toggle__switch{background-color:var(--yoast-color-active-light)}.yoast-toggle--inverse .yoast-toggle__checkbox:not(:checked)~.yoast-toggle__switch:before,.yoast-toggle .yoast-toggle__checkbox:checked~.yoast-toggle__switch:before{background-color:var(--yoast-color-active);left:0;right:auto}.yoast-toggle--inverse .yoast-toggle__checkbox:checked~.yoast-toggle__switch:before{left:auto;right:0}.yoast-toggle--inverse .yoast-toggle__checkbox~.yoast-toggle--inactive,.yoast-toggle .yoast-toggle__checkbox~.yoast-toggle--inactive{color:var(--yoast-color-default-darker)}.yoast-toggle--inverse .yoast-toggle__checkbox:checked~.yoast-toggle--inactive,.yoast-toggle--inverse .yoast-toggle__checkbox~.yoast-toggle--active,.yoast-toggle .yoast-toggle__checkbox:checked~.yoast-toggle--inactive,.yoast-toggle .yoast-toggle__checkbox~.yoast-toggle--active{color:var(--yoast-color-inactive-text)}.yoast-toggle--inverse .yoast-toggle__checkbox:checked~.yoast-toggle--active,.yoast-toggle .yoast-toggle__checkbox:checked~.yoast-toggle--active{color:var(--yoast-color-default-darker)}@media(max-width:400px){.yoast-feature{margin-left:0}.yoast-toggle__item-disabled{flex-wrap:wrap}.yoast-toggle__item-disabled .yoast-button.yoast-button--buy{position:static;margin-right:0;margin-top:8px}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/monorepo-1720.css b/wp-content/plugins/wordpress-seo/css/dist/monorepo-1720.css new file mode 100644 index 00000000..9e7c9f91 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/monorepo-1720.css @@ -0,0 +1 @@ +:root{--yoast-border-default:1px solid rgba(0,0,0,0.2);--yoast-color-default:#404040;--yoast-color-default-darker:#303030;--yoast-color-primary:#a4286a;--yoast-color-secondary:#f7f7f7;--yoast-color-white:#fff;--yoast-color-green:#6ea029;--yoast-color-primary-darker:#7b1e50;--yoast-color-primary-lighter:#f5d6e6;--yoast-color-secondary-darker:#d9d9d9;--yoast-color-button-upsell:#fec228;--yoast-color-button-upsell-hover:#f2ae01;--yoast-color-dark:#303030;--yoast-color-sale:#fec228;--yoast-color-sale-darker:#feb601;--yoast-color-border:rgba(0,0,0,0.2);--yoast-color-label:#303030;--yoast-color-label-help:#707070;--yoast-color-active:#6ea029;--yoast-color-inactive:#dc3232;--yoast-color-inactive-text:#707070;--yoast-color-inactive-grey:#9e9e9e;--yoast-color-inactive-grey-light:#f1f1f1;--yoast-color-active-light:#b6cf94;--yoast-transition-default:all 150ms ease-out;--yoast-color-link:#006dac;--yoast-color-border--default:rgba(0,0,0,0.2);--yoast-color-focus:0 0 0 2px #007fff,0 0 0 5px #bfdfff;--yoast-svg-icon-chevron-down:url('data:image/svg+xml;charset=utf-8,');--yoast-svg-icon-chevron-up:url('data:image/svg+xml;charset=utf-8,');--yoast-checkmark--white:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23FFF' viewBox='0 0 512 512'%3E%3Cpath d='M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z'/%3E%3C/svg%3E");--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url('data:image/svg+xml;charset=utf-8,');--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url('data:image/svg+xml;charset=utf-8,');--yoast-svg-icon-edit:url('data:image/svg+xml;charset=utf-8,');--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url('data:image/svg+xml;charset=utf-8,');--yoast-checkmark--green:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%236EA029' viewBox='0 0 512 512'%3E%3Cpath d='M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z'/%3E%3C/svg%3E");--yoast-exclamation-mark:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23DC3232' viewBox='0 0 512 512'%3E%3Cpath d='M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z'/%3E%3C/svg%3E");--yoast-svg-icon-schema:url("data:image/svg+xml;charset=utf-8,%3Csvg width='512' height='512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M149.333 56v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zm181.334 240v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm32-240v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24zm-32 80V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm-205.334 56H24c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zm386.667-56H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm0 160H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zM181.333 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24z'/%3E%3C/svg%3E");--yoast-svg-icon-schema-active:url("data:image/svg+xml;charset=utf-8,%3Csvg width='512' height='512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='D4444' d='M149.333 56v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zm181.334 240v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm32-240v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24zm-32 80V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm-205.334 56H24c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zm386.667-56H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm0 160H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zM181.333 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24z'/%3E%3C/svg%3E");--yoast-svg-icon-image:url("data:image/svg+xml;charset=utf-8,%3Csvg fill='none' stroke='%23707070' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 16l4.586-4.586a2 2 0 0 1 2.828 0L16 16m-2-2l1.586-1.586a2 2 0 0 1 2.828 0L20 14m-6-6h.01M6 20h12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2z'/%3E%3C/svg%3E");--yoast-font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;--yoast-font-size-default:14px;--yoast-font-weight-default:400;--yoast-font-weight-bold:600;--yoast-color-font-default:#404040;--yoast-shadow-default:0px 3px 6px rgba(0,0,0,0.15)}.yoast-h1,.yoast-h2,.yoast-h3{font-weight:400;color:var(--yoast-color-primary);line-height:1.2;margin:0}.yoast-h1 a,.yoast-h2 a,.yoast-h3 a{color:var(--yoast-color-primary);text-decoration:none}.yoast-h1{font-size:24px}.yoast-h2{font-size:20px}.yoast-h3{font-size:16px}.yoast-paragraph{font-size:14px;font-size:var(--yoast-font-size-default);margin-top:0}.screen-reader-text{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.visually-hidden{position:absolute;overflow:hidden;height:1px;width:1px;clip:rect(1px,1px,1px,1px);white-space:nowrap;word-wrap:normal}@media (max-width:782px){.yoast-show-on-mobile{display:initial!important}}@media (min-width:782px){.yoast-hide-on-desktop{display:none}}.yoast-field-group__title-separator{display:flex;flex-wrap:wrap}.yoast-field-group__title-separator label{display:flex;align-items:center;justify-content:center;flex-direction:column;border:var(--yoast-border-default);cursor:pointer;height:42px;width:42px;margin:0 6px 6px 0;box-sizing:border-box}.yoast-field-group__title-separator input[type=radio]:checked+label{border:3px solid var(--yoast-color-primary)}.yoast .yoast-button{display:inline-flex;align-items:center;justify-content:center;position:relative;padding:10px 12px 12px;text-decoration:none;border-radius:4px;border:1px solid rgba(0,0,0,.2);box-shadow:inset 0 -2px 0 rgba(0,0,0,.1);transition:background-color .15s ease-out 0s;line-height:1.2;font-size:14px;cursor:pointer}.yoast-close:focus,.yoast-hide:focus,.yoast-remove:focus,.yoast .yoast-button:focus{box-shadow:var(--yoast-color-focus);outline:none}.yoast-close::-moz-focus-inner,.yoast-hide::-moz-focus-inner,.yoast-remove::-moz-focus-inner,.yoast .yoast-button::-moz-focus-inner{border:0}.yoast .yoast-button:not(:disabled):active{box-shadow:none;top:2px}.yoast .yoast-button:disabled{opacity:.5;cursor:default}.yoast .yoast-button--primary{color:var(--yoast-color-white);background-color:var(--yoast-color-primary);border:1px solid rgba(0,0,0,.2)}.yoast .yoast-button--primary:visited{color:var(--yoast-color-white);border:1px solid rgba(0,0,0,.2)}.yoast .yoast-button--primary:active,.yoast .yoast-button--primary:not(:disabled):hover{color:var(--yoast-color-white);background-color:var(--yoast-color-primary-darker);border:1px solid rgba(0,0,0,.2)}.yoast .yoast-button--primary:focus{color:var(--yoast-color-white);background-color:var(--yoast-color-primary)}.yoast .yoast-button--secondary{color:var(--yoast-color-dark);background-color:var(--yoast-color-secondary);box-shadow:inset 0 -2px 0 rgba(0,0,0,.1)}.yoast .yoast-button--secondary:visited{color:var(--yoast-color-dark)}.yoast .yoast-button--secondary:active,.yoast .yoast-button--secondary:not(:disabled):hover{color:var(--yoast-color-dark);background-color:var(--yoast-color-secondary-darker);border:1px solid rgba(0,0,0,.2)}.yoast .yoast-button--buy{color:var(--yoast-color-dark);background-color:var(--yoast-color-sale)}.yoast .yoast-button--buy:visited{color:var(--yoast-color-dark)}.yoast .yoast-button--buy:active,.yoast .yoast-button--buy:not(:disabled):hover{color:var(--yoast-color-dark);background-color:var(--yoast-color-sale-darker)}.yoast .yoast-button--buy__caret{flex-shrink:0;display:inline-block;width:6px;height:16px;margin:0 -2px 0 6px;background-color:currentColor;-webkit-mask-image:var(--yoast-svg-icon-caret-right);mask-image:var(--yoast-svg-icon-caret-right)}.yoast .yoast-button--edit{width:20.25px;height:18px;flex-shrink:0;display:inline-block;background-color:currentColor;-webkit-mask-image:var(--yoast-svg-icon-edit);mask-image:var(--yoast-svg-icon-edit);margin-right:8px}html[dir=rtl] .yoast .yoast-button--edit{margin-right:0;margin-left:8px}html[dir=rtl] .yoast .yoast-button--buy{flex-direction:row-reverse}.yoast .yoast-button--small{font-size:13px;padding:5px 8px 8px}.yoast .yoast-button--small .yoast-button--buy__caret{width:4px;height:10px}.yoast-hide,.yoast-remove{color:#dc3232;background-color:initial;border:none;cursor:pointer;text-decoration:underline;padding:0;font-size:14px}.yoast-hide{color:var(--yoast-color-link)}.yoast-field-group__upload .yoast-button{margin-right:24px}.yoast-close{display:flex;justify-content:center;align-items:center;border:none;background:none;height:44px;width:44px;cursor:pointer;box-shadow:none;padding:0}.yoast-close svg{fill:var(--yoast-color-default);width:14px}@media screen and (max-width:782px){.yoast-close svg{width:10px}}.yoast-field-group__checkbox{display:flex;align-items:center}.yoast-field-group__checkbox:not(.yoast-field-group__checkbox--horizontal)+.yoast-field-group__checkbox{margin-top:4px}.yoast-field-group__checkbox label{cursor:pointer}.yoast-field-group__checkbox input[type=checkbox]{-webkit-appearance:none;-moz-appearance:none;width:18px;height:18px;padding:2px;margin:2px 8px 0 0;border-radius:2px;transition:background-color .15s ease-out 0s;border:var(--yoast-border-default);box-shadow:inset 0 2px 4px rgba(0,0,0,.1);position:relative;overflow:hidden;cursor:pointer}.yoast-field-group__checkbox input[type=checkbox]:checked:focus,.yoast-field-group__checkbox input[type=checkbox]:focus{box-shadow:var(--yoast-color-focus);outline:none}.yoast label+input[type=checkbox]{margin-left:16px}.yoast-field-group__checkbox input[type=checkbox]:checked{background:var(--yoast-checkmark--white) var(--yoast-color-primary) no-repeat 50%/13px;border:1px solid var(--yoast-color-primary);box-shadow:none}.yoast-field-group__checkbox input[type=checkbox]:checked:before{content:""}.yoast-field-group{position:relative;border:none;padding:0;margin:0 0 24px}.yoast-field-group__title{display:flex;align-items:center;font-weight:var(--yoast-font-weight-bold);margin:0 0 8px;color:var(--yoast-color-label);line-height:1.5;padding:0;font-size:var(--yoast-font-size-default)}.yoast-field-group__title.yoast-field-group__title--light{font-weight:var(--yoast-font-weight-default)}.yoast-field-group .field-group-description{margin:0 0 1em}.yoast-field-group__inline{display:flex;align-items:center}.yoast-field-group__inline .yoast-field-group__inputfield{margin-right:8px}.yoast-field-group__inline .yoast-button{flex-shrink:0}.yoast-field-group .components-form-token-field__label{display:none}@media screen and (max-width:782px){.yoast-field-group__inline{display:block}.yoast-field-group__inline .yoast-field-group__inputfield{margin-right:0;margin-bottom:8px}}.yoast-help{margin-left:4px}.yoast-help__icon svg{width:12px;height:12px;fill:var(--yoast-color-inactive-text);transition:var(--yoast-transition-default)}.yoast-help:focus svg,.yoast-help:hover svg{fill:var(--yoast-color-link)}.yoast-data-model{padding:0;list-style:none}.yoast-data-model li{line-height:1.4;padding:0 8px;position:relative;z-index:2;font-weight:var(--yoast-font-weight-bold)}.yoast-data-model span{float:right;font-weight:var(--yoast-font-weight-default)}.yoast-data-model li+li{margin-top:9px}.yoast-data-model li:after{position:absolute;left:0;height:20px;background:#f5d6e6;content:"";width:var(--yoast-width);z-index:-1}.yoast-image-select__preview{display:flex;justify-content:center;align-items:center;overflow:hidden;width:300px;max-width:100%;min-height:165px;max-height:200px;border:1px solid rgba(0,0,0,.2);background-color:initial;padding:0}.yoast-image-select__preview--no-preview{background:var(--yoast-color-inactive-grey-light) var(--yoast-svg-icon-image) no-repeat 50%/64px 64px}.yoast-image-select__preview.yoast-image-select__preview-has-warnings{margin-bottom:16px}.yoast-image-select__preview .yoast-image-select__preview--image{max-width:100%;height:100%;object-fit:contain}.yoast-image-select .yoast-field-group__inputfield{margin-bottom:1em}.yoast-image-select .yoast-button{margin-right:1.5em}.yoast-image-select{margin-top:1.7em;margin-bottom:1.7em}.yoast-image-select .yoast-image-select-buttons button{margin-top:1em}#organization-image-select .yoast-image-select{margin-top:0}:root{--yoast-color-placeholder:#707070}.yoast .yoast-field-group__inputfield,.yoast .yoast-field-group__textarea{width:100%;font-size:var(--yoast-font-size-default);padding:8px;background:var(--yoast-color-white);border:var(--yoast-border-default);box-shadow:inset 0 2px 4px rgba(0,0,0,.1);box-sizing:border-box;border-radius:0}.yoast .yoast-field-group__inputfield:focus,.yoast .yoast-field-group__textarea:focus{box-shadow:var(--yoast-color-focus);outline:none}.yoast-field-group__upload .yoast-field-group__inputfield{margin-bottom:8px}.yoast-field-group__inputfield{height:40px}.yoast-field-group__textarea{min-height:200px}.yoast-field-group .description+.yoast-field-group__inputfield,.yoast-field-group .description+input,.yoast-field-group__inputfield+.description,.yoast input+.description{margin-top:8px;margin-bottom:24px}.yoast .yoast-field-group__inputfield:disabled,.yoast .yoast-field-group__inputfield:read-only,.yoast .yoast-field-group__inputfield[aria-disabled=true]{background:var(--yoast-color-inactive-grey-light)}.yoast .duration-inputs__wrapper{display:flex;flex-direction:row}.yoast .duration-inputs__input-wrapper{display:flex;flex-direction:column}.yoast .duration-inputs__input{width:4em;margin:0 8px 0 0}::-ms-input-placeholder{color:#707070;color:var(--yoast-color-placeholder)}::placeholder{color:#707070;color:var(--yoast-color-placeholder);opacity:1}.yoast-insights-card{margin-top:24px;border-top:1px solid rgba(0,0,0,.1);padding-top:24px}@media(min-width:782px){.yoast-modal-content .yoast-insights-card{margin-top:inherit;border-top:none;padding-top:inherit;padding-bottom:24px;border-bottom:1px solid rgba(0,0,0,.1);margin-bottom:24px}}.yoast-insights-card__content{display:flex}.yoast-insights-card__score{flex-shrink:0;margin-right:2em;text-align:center}.yoast-insights-card__amount{display:block;font-size:3.5em;line-height:1}.yoast-field-group__radiobutton{display:flex;align-items:center}.yoast-field-group__radiobutton--vertical:not(:last-of-type){margin-bottom:8px}.yoast-field-group__radiobutton label{cursor:pointer;margin-right:16px}.yoast-field-group__radiobutton input[type=radio]{-webkit-appearance:none;-moz-appearance:none;width:18px;height:18px;padding:2px;margin:0 8px 0 0;border-radius:50%;transition:border-color .15s ease-out 0s;border:var(--yoast-border-default);box-shadow:inset 0 2px 4px rgba(0,0,0,.1);position:relative;overflow:hidden;cursor:pointer}.yoast-field-group__radiobutton input[type=radio]:checked:focus,.yoast-field-group__radiobutton input[type=radio]:focus{box-shadow:var(--yoast-color-focus);outline:none}.yoast-field-group__radiobutton input[type=radio]:checked{border-color:var(--yoast-color-primary);background-color:inherit}.yoast-field-group__radiobutton input[type=radio]:after{background-color:initial;transition:background-color .15s ease-out 0s;width:10px;height:10px;position:absolute;left:3px;top:3px;content:"";display:block;border-radius:50%}.yoast-field-group__radiobutton input[type=radio]:checked:after{background-color:var(--yoast-color-primary)}.yoast-field-group__select{display:flex;cursor:pointer;align-items:center}.yoast-select__indicator-separator{display:none}.yoast-select-container{padding:0;width:100%;display:block;min-height:2.85em;position:relative;background-color:#fff;box-shadow:inset 0 2px 4px rgba(0,0,0,.1);border-radius:0;border:var(--yoast-border-default)}.yoast-select-container .yoast-select__control--is-focused{box-shadow:var(--yoast-color-focus);outline:none}.yoast-select-container .yoast-select__indicator>svg{color:#212121}.yoast-select-container .yoast-select__menu{z-index:2;margin:0}.yoast-select-container .yoast-select__multi-value__label{color:inherit;font-size:14px;display:flex;align-items:center;box-sizing:border-box;padding:0}.yoast-select-container .yoast-select__multi-value{background-color:var(--yoast-color-primary);border:0;border-radius:12px;color:var(--yoast-color-white);padding:1px 10px 2px;margin-bottom:3px;margin-top:3px;margin-right:8px;line-height:1.5;font-weight:500;display:flex;flex-direction:row-reverse}.yoast-select-container .yoast-select__menu-list{padding:0}.yoast-select-container .yoast-select__multi-value__remove{padding:2px 0 0;display:flex;align-items:center;border-radius:2px;box-sizing:border-box;-webkit-box-align:center;margin-right:6px}.yoast-select-container .yoast-select__multi-value__remove:hover{background-color:inherit;color:var(--yoast-color-white);cursor:pointer}.yoast-select-container .yoast-select__control{border-radius:0;border:none;background-color:initial}.yoast-select-container .yoast-select__option{color:inherit;cursor:default;display:block;padding:8px 12px;width:100%;box-sizing:border-box;-webkit-user-select:none;user-select:none}.yoast-select-container .yoast-select__option--is-focused{background-color:var(--yoast-color-primary-lighter);color:var(--yoast-color-font-default)}.yoast-select-container .yoast-select__option.yoast-select__option--is-selected{background-color:var(--yoast-color-primary);color:var(--yoast-color-white)}.yoast-select-container input[type=text]:focus{box-shadow:none}.yoast-field-group__select select,.yoast-field-group select{-webkit-appearance:none;-moz-appearance:none;width:100%;font-size:var(--yoast-font-size-default);padding:5px 8px;background-color:#fff;background-image:url('data:image/svg+xml;charset=utf-8,');background-position:right 15px center;background-repeat:no-repeat;background-size:13px auto;border-radius:0;border:var(--yoast-border-default);box-shadow:inset 0 2px 4px rgba(0,0,0,.1);position:relative;max-width:300px;display:block;min-height:2.85em}.yoast-field-group .yoast-select__value-container{padding:0 8px!important}.yoast-field-group__select select:focus,.yoast-field-group select:focus{box-shadow:var(--yoast-color-focus);outline:none}.yoast-field-group__select select,.yoast-field-group select{line-height:1.9;padding-right:40px}.yoast-field-group select.yoast-select--inline{display:inline-block}.yoast-field-group--inline{max-width:300px;display:inline-block;width:100%;margin-right:8px}.yoast-star-rating{width:65px;height:12px;display:inline-block}.yoast-star-rating span{height:100%;width:100%;background-size:13px 12px;background-repeat:repeat-x}.yoast-star-rating__placeholder{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAAmCAQAAAAYCMGrAAAA+klEQVR4AcWV4cbtMBBFF0MIVUopoVSrhDDv/3gf/RFRpzdNOty1HiBO99mzeYWgCMZMKCPGrCgrxiSUhCkDeukxJKCXAUMiehkxw6FZhxEzmp0x4kCzByYISqlYdal0supS6WrVpdLEK0YSamJiJOPY0c/uOG4s6CcXfuKJaJcRzyNCQJsNiF1sRTR1hP11NNJ8RCrONOPRf+r7J+TZgQ5CNfMOYvW/2YxDqzqA/57+gVY9eiakrnyZEGXDsaE3p/4JScwPX3rtnZATDxnPWT7X16XAHaH8HWNrlxJD9TyGti5tCM84zpZe+RxNjeX9tZqLaGoMxN/P/wHP5Vw+8ZxnEQAAAABJRU5ErkJggg==);display:inline-block;overflow:hidden;position:relative}.yoast-star-rating__fill{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAAmBAMAAABALxQTAAAAFVBMVEVMaXH4twP4twP4twP4twP4twP4twP7w8S/AAAAB3RSTlMAFv5uPpvQloUsTQAAAMFJREFUeAGE0TEOgzAMQFEXoDNiYC6/wFxxAsTADDkB5f6HqNRENXUi8TYiRfnY8lNXkjBOkuBWSeAhsYJOYiW9xO4MEqshkTbCSyIH7GLdgFasHHgmwkikZQD6OROZRG4Hxju8o/TNhbNhCqkOxaZDVKdxNnq/EjUS/A2o0PuXpyVeb9bjDWY9QSWXDQfBbtbjtWY9bM4sqfx+5yYt8wNcAFEzrGGkk5668KsFrKewPtQ3aFqh8WOnYZ+lIBQkgykAWk8rlAqcHfQAAAAASUVORK5CYII=);display:block}.yoast-table{font-size:var(--yoast-font-size-default);color:var(--yoast-color-default);line-height:1.2;border-spacing:0;border:var(--yoast-border-default);border-bottom:0;width:100%}.yoast-table tbody tr:nth-child(odd){background-color:#f9f9f9}.yoast-table th{color:var(--yoast-color-dark);text-align:left;padding:18px 12px;border-bottom:var(--yoast-border-default);white-space:nowrap;font-weight:var(--yoast-font-weight-bold)}.yoast-table td{padding:18px 12px;border-bottom:var(--yoast-border-default)}.yoast-table td:first-child,.yoast-table th:first-child{padding-left:16px}.yoast-table td:last-child,.yoast-table th:last-child{padding-right:16px}td.yoast-table__button,td.yoast-table__image{padding:10px 18px 9px}.yoast-table.yoast-table--nobreak td,td.yoast-table--nobreak,tr.yoast-table--nobreak td{white-space:nowrap}th.yoast-table--primary{width:100%}td.yoast-table--nopadding{padding:0 12px}.yoast-badge{display:inline-block;min-height:16px;padding:0 8px;border-radius:8px;font-weight:600;font-size:10px;line-height:1.6}.yoast-badge__in-label{margin-left:8px;vertical-align:text-top}.yoast-new-badge{background-color:#cce5ff;color:#004973}.yoast-premium-badge{background-color:#fff3cd;color:#674e00}.yoast-feature{max-width:600px;margin-right:150px}.yoast-toggle__item{display:flex;justify-content:space-between;padding-bottom:16px;border-bottom:1px solid var(--yoast-color-border);margin-bottom:16px}.yoast-toggle__item-disabled{position:relative}.yoast-toggle__item-disabled .yoast-button.yoast-button--buy{position:absolute;left:100%;margin-left:32px;white-space:nowrap}.yoast-toggle__item-disabled .yoast-toggle,.yoast-toggle__item-disabled .yoast-toggle__item-title{opacity:.5}.yoast-toggle__item-title{display:flex;font-weight:700;align-items:center}input[type=checkbox].yoast-toggle__checkbox{height:23px;overflow:hidden;position:absolute;margin-left:8px;width:34px;z-index:1;box-shadow:none;border:0;background-color:initial;-webkit-appearance:none;-moz-appearance:none}input[type=checkbox].yoast-toggle__checkbox:checked:before{content:none}.yoast-toggle__switch{display:inline-block;position:relative;background-color:var(--yoast-color-inactive-grey);width:34px;height:14px;border-radius:8px;margin-left:8px;margin-right:8px}.yoast-toggle__checkbox:focus~.yoast-toggle__switch:before{box-shadow:var(--yoast-color-focus)}.yoast-toggle__switch:before{content:"";position:absolute;top:-3px;left:0;background-color:var(--yoast-color-inactive-grey-light);width:20px;height:20px;border-radius:50%;box-shadow:0 1px 2px 0 rgba(0,0,0,.4);border:.5px solid rgba(0,0,0,.1);box-sizing:border-box}.yoast-toggle,.yoast-toggle--inverse{position:relative;display:grid;grid-template:1fr/repeat(3,auto);align-items:center}.yoast-toggle--inverse>*,.yoast-toggle>*{grid-row:1}.yoast-toggle--inactive,.yoast-toggle--inverse .yoast-toggle--active{grid-column:1}.yoast-toggle__checkbox,.yoast-toggle__switch{grid-column:2}.yoast-toggle--active,.yoast-toggle--inverse .yoast-toggle--inactive{grid-column:3}.yoast-toggle--inverse .yoast-toggle__checkbox:not(:checked)~.yoast-toggle__switch,.yoast-toggle .yoast-toggle__checkbox:checked~.yoast-toggle__switch{background-color:var(--yoast-color-active-light)}.yoast-toggle--inverse .yoast-toggle__checkbox:not(:checked)~.yoast-toggle__switch:before,.yoast-toggle .yoast-toggle__checkbox:checked~.yoast-toggle__switch:before{background-color:var(--yoast-color-active);right:0;left:auto}.yoast-toggle--inverse .yoast-toggle__checkbox:checked~.yoast-toggle__switch:before{right:auto;left:0}.yoast-toggle--inverse .yoast-toggle__checkbox~.yoast-toggle--inactive,.yoast-toggle .yoast-toggle__checkbox~.yoast-toggle--inactive{color:var(--yoast-color-default-darker)}.yoast-toggle--inverse .yoast-toggle__checkbox:checked~.yoast-toggle--inactive,.yoast-toggle--inverse .yoast-toggle__checkbox~.yoast-toggle--active,.yoast-toggle .yoast-toggle__checkbox:checked~.yoast-toggle--inactive,.yoast-toggle .yoast-toggle__checkbox~.yoast-toggle--active{color:var(--yoast-color-inactive-text)}.yoast-toggle--inverse .yoast-toggle__checkbox:checked~.yoast-toggle--active,.yoast-toggle .yoast-toggle__checkbox:checked~.yoast-toggle--active{color:var(--yoast-color-default-darker)}@media(max-width:400px){.yoast-feature{margin-right:0}.yoast-toggle__item-disabled{flex-wrap:wrap}.yoast-toggle__item-disabled .yoast-button.yoast-button--buy{position:static;margin-left:0;margin-top:8px}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/notifications-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/notifications-1720-rtl.css new file mode 100644 index 00000000..440979b4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/notifications-1720-rtl.css @@ -0,0 +1 @@ +:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")}.screen-reader-text{position:absolute!important;clip:rect(1px,1px,1px,1px);clip-path:inset(50%);width:1px;height:1px;border:0;padding:0;overflow:hidden;word-wrap:normal!important}.yoast-notification{padding:0 12px;border-right:4px solid #fff;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2)}.yoast-container{position:relative;max-width:1280px;margin:20px 0 1px;padding:20px 20px 0;border:1px solid #e5e5e5;background-color:#fdfdfd;box-shadow:0 1px 1px rgba(0,0,0,.04)}.yoast-notifications>h2:first-child{margin:0;padding:9px 0 4px;font-size:23px;font-weight:400;line-height:29px}.yoast-notifications .yoast-container h3{margin:-20px -20px 0;padding:1em;border-bottom:1px solid #ccc;background-color:#fdfdfd;font-size:1.4em}.yoast-container .container{max-width:980px}.yoast-container .yoast-notification-holder{display:flex;position:relative}.dismiss .dashicons,.restore .dashicons{font-size:20px;width:20px;height:20px}.yoast-bottom-spacing{margin-bottom:20px}.yoast-notifications .button.dismiss,.yoast-notifications .button.restore{position:absolute;left:0;width:52px;height:100%;line-height:inherit;padding:0;outline:none;cursor:pointer;background:transparent;border:none;box-shadow:none;border-radius:0}.yoast-notifications .button.dismiss:focus,.yoast-notifications .button.dismiss:hover,.yoast-notifications .button.restore:focus,.yoast-notifications .button.restore:hover{background:transparent}.yoast-notifications .button.dismiss:focus:before,.yoast-notifications .button.restore:focus:before{content:"";display:block;width:32px;height:32px;border-radius:50%;position:absolute;top:50%;right:50%;transform:translate(50%,-50%);box-shadow:0 0 0 1px #007cba;outline:2px solid transparent}.yoast-notifications .button.dismiss.yoast-container__configuration-wizard--dismiss:before{top:0;transform:translate(50%,6px)}.yoast-container .separator{margin-top:1em;margin-bottom:1em;border-top:1px solid #ddd}.yoast-container .dashicons-yes{color:#77b227}.yoast-container-disabled{display:table-cell;position:absolute;top:0;left:0;bottom:0;right:0;border-radius:4px;background-color:hsla(0,0%,91%,.7)}.yoast-no-issues{padding:1em 16px 1em 1em;color:#666}.yoast-muted-title{overflow:hidden;font-weight:600;font-style:italic}.yoast-muted-title:after{content:"";display:inline-block;height:.5em;vertical-align:bottom;width:100%;margin-left:-100%;margin-right:10px;border-top:1px solid #ddd}.yoast-notifications-active .yoast-notification,.yoast-notifications-dismissed .yoast-notification{padding-left:52px;flex:1}.yoast-notifications-active .yoast-notification-holder{margin-bottom:20px}.yoast-notifications-dismissed.paper.tab-block{margin:20px 0}.yoast-notifications-dismissed.paper.tab-block .paper-container.toggleable-container{padding:0}.yoast-notifications-dismissed.paper.tab-block .paper-container.toggleable-container .yoast-notification-holder:nth-child(odd){background-color:#f7f7f7}.yoast-notifications-dismissed.paper.tab-block .paper-container.toggleable-container .yoast-notification-holder:nth-child(odd) .yoast-notification{background-color:initial}.yoast-notifications-dismissed .yoast-svg-icon-eye{background:transparent var(--yoast-svg-icon-eye) no-repeat 100% 0;background-size:20px}#yoast-errors-header .dashicons{color:#dc3232}#yoast-errors-active .yoast-notification{border-right-color:#dc3232}#yoast-errors-dismissed .yoast-notification{border-right-color:#d93f69}#yoast-warnings-header .dashicons{color:#5d237a}#yoast-warnings-active .yoast-notification{border-right-color:#5d237a}#yoast-warnings-dismissed .yoast-notification{border-right-color:#0075b3}.yoast-notifications .yoast-container__configuration-wizard{display:flex;align-items:center;box-shadow:0 1px 2px rgba(0,0,0,.2);background-color:#fff;min-height:0;padding-bottom:20px;margin-bottom:15px}@media screen and (max-width:768px){.yoast-notifications .yoast-container__configuration-wizard img{display:none}}.yoast-notifications .yoast-container__configuration-wizard--content{flex:1 1 auto;margin:12px;padding:0}.yoast-notifications .yoast-container__configuration-wizard--content h3{border-bottom:0;font-size:1.4em;line-height:1;margin:0 0 4px;padding:0;background:transparent}.yoast-notifications .yoast-container__configuration-wizard--content p{margin:1em 0 0}.yoast-notifications .yoast-container__configuration-wizard--content p:last-child{margin:0}@media screen and (max-width:768px){.yoast-notifications .yoast-container__configuration-wizard--content{display:block;position:relative;padding:16px}}.yoast-notifications .yoast-container__configuration-wizard--dismiss{text-align:center}@media screen and (max-width:768px){.yoast-notifications .yoast-container__configuration-wizard--dismiss{width:40px;position:absolute;top:5px;left:5px;margin:0}}.yoast-notifications .yoast-container__configuration-wizard--dismiss .dashicons{text-decoration:none;margin-top:12px} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/notifications-1720.css b/wp-content/plugins/wordpress-seo/css/dist/notifications-1720.css new file mode 100644 index 00000000..a8db845c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/notifications-1720.css @@ -0,0 +1 @@ +:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")}.screen-reader-text{position:absolute!important;clip:rect(1px,1px,1px,1px);clip-path:inset(50%);width:1px;height:1px;border:0;padding:0;overflow:hidden;word-wrap:normal!important}.yoast-notification{padding:0 12px;border-left:4px solid #fff;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.2)}.yoast-container{position:relative;max-width:1280px;margin:20px 0 1px;padding:20px 20px 0;border:1px solid #e5e5e5;background-color:#fdfdfd;box-shadow:0 1px 1px rgba(0,0,0,.04)}.yoast-notifications>h2:first-child{margin:0;padding:9px 0 4px;font-size:23px;font-weight:400;line-height:29px}.yoast-notifications .yoast-container h3{margin:-20px -20px 0;padding:1em;border-bottom:1px solid #ccc;background-color:#fdfdfd;font-size:1.4em}.yoast-container .container{max-width:980px}.yoast-container .yoast-notification-holder{display:flex;position:relative}.dismiss .dashicons,.restore .dashicons{font-size:20px;width:20px;height:20px}.yoast-bottom-spacing{margin-bottom:20px}.yoast-notifications .button.dismiss,.yoast-notifications .button.restore{position:absolute;right:0;width:52px;height:100%;line-height:inherit;padding:0;outline:none;cursor:pointer;background:transparent;border:none;box-shadow:none;border-radius:0}.yoast-notifications .button.dismiss:focus,.yoast-notifications .button.dismiss:hover,.yoast-notifications .button.restore:focus,.yoast-notifications .button.restore:hover{background:transparent}.yoast-notifications .button.dismiss:focus:before,.yoast-notifications .button.restore:focus:before{content:"";display:block;width:32px;height:32px;border-radius:50%;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 1px #007cba;outline:2px solid transparent}.yoast-notifications .button.dismiss.yoast-container__configuration-wizard--dismiss:before{top:0;transform:translate(-50%,6px)}.yoast-container .separator{margin-top:1em;margin-bottom:1em;border-top:1px solid #ddd}.yoast-container .dashicons-yes{color:#77b227}.yoast-container-disabled{display:table-cell;position:absolute;top:0;right:0;bottom:0;left:0;border-radius:4px;background-color:hsla(0,0%,91%,.7)}.yoast-no-issues{padding:1em 1em 1em 16px;color:#666}.yoast-muted-title{overflow:hidden;font-weight:600;font-style:italic}.yoast-muted-title:after{content:"";display:inline-block;height:.5em;vertical-align:bottom;width:100%;margin-right:-100%;margin-left:10px;border-top:1px solid #ddd}.yoast-notifications-active .yoast-notification,.yoast-notifications-dismissed .yoast-notification{padding-right:52px;flex:1}.yoast-notifications-active .yoast-notification-holder{margin-bottom:20px}.yoast-notifications-dismissed.paper.tab-block{margin:20px 0}.yoast-notifications-dismissed.paper.tab-block .paper-container.toggleable-container{padding:0}.yoast-notifications-dismissed.paper.tab-block .paper-container.toggleable-container .yoast-notification-holder:nth-child(odd){background-color:#f7f7f7}.yoast-notifications-dismissed.paper.tab-block .paper-container.toggleable-container .yoast-notification-holder:nth-child(odd) .yoast-notification{background-color:initial}.yoast-notifications-dismissed .yoast-svg-icon-eye{background:transparent var(--yoast-svg-icon-eye) no-repeat 0 0;background-size:20px}#yoast-errors-header .dashicons{color:#dc3232}#yoast-errors-active .yoast-notification{border-left-color:#dc3232}#yoast-errors-dismissed .yoast-notification{border-left-color:#d93f69}#yoast-warnings-header .dashicons{color:#5d237a}#yoast-warnings-active .yoast-notification{border-left-color:#5d237a}#yoast-warnings-dismissed .yoast-notification{border-left-color:#0075b3}.yoast-notifications .yoast-container__configuration-wizard{display:flex;align-items:center;box-shadow:0 1px 2px rgba(0,0,0,.2);background-color:#fff;min-height:0;padding-bottom:20px;margin-bottom:15px}@media screen and (max-width:768px){.yoast-notifications .yoast-container__configuration-wizard img{display:none}}.yoast-notifications .yoast-container__configuration-wizard--content{flex:1 1 auto;margin:12px;padding:0}.yoast-notifications .yoast-container__configuration-wizard--content h3{border-bottom:0;font-size:1.4em;line-height:1;margin:0 0 4px;padding:0;background:transparent}.yoast-notifications .yoast-container__configuration-wizard--content p{margin:1em 0 0}.yoast-notifications .yoast-container__configuration-wizard--content p:last-child{margin:0}@media screen and (max-width:768px){.yoast-notifications .yoast-container__configuration-wizard--content{display:block;position:relative;padding:16px}}.yoast-notifications .yoast-container__configuration-wizard--dismiss{text-align:center}@media screen and (max-width:768px){.yoast-notifications .yoast-container__configuration-wizard--dismiss{width:40px;position:absolute;top:5px;right:5px;margin:0}}.yoast-notifications .yoast-container__configuration-wizard--dismiss .dashicons{text-decoration:none;margin-top:12px} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/schema-blocks-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/schema-blocks-1720-rtl.css new file mode 100644 index 00000000..cc320cd7 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/schema-blocks-1720-rtl.css @@ -0,0 +1 @@ +.yoast-labeled-inserter{position:relative;width:100%}.yoast-labeled-inserter:before{content:attr(data-label);position:absolute;right:0;height:100%;color:#000}.yoast-labeled-inserter>.block-editor-inserter{width:100%}.yoast-warning-block{border-width:0 4px 0 0;border-style:solid;padding:16px;font-size:13px;font-family:Arial,Roboto-Regular,HelveticaNeue,sans-serif}.yoast-warning-block.required{background:#f8ebea;border-color:#cd423b}.yoast-warning-block.recommended{background:#fef8ee;border-color:#f0b650}.yoast-warning-block>.yoast-warning-block-message{margin:0;font-family:Arial,Roboto-Regular,HelveticaNeue,sans-serif}.yoast-warning-block>div{text-align:left;padding-top:8px}.yoast-warning-block>div>button{background:none;border:none;text-decoration:underline;color:#0073aa}.yoast-schema-block-appender__content{color:rgba(30,30,30,.6)}.wp-block .yoast-warning-block>.yoast-warning-block-message>a{text-decoration:underline;color:#0073aa}.yoast-warning-block>div>button:not(:last-child){margin-left:24px}.yoast-block-sidebar-input label,.yoast-block-sidebar-title{font-weight:600;color:#303030;margin-bottom:0;padding-top:10px}.yoast-block-label-with-help-link{width:100%;margin-bottom:3px}.yoast-block-suggestions{width:100%;padding:0 15px 0 5px}.yoast-question-mark-icon{color:#767676}.yoast-question-mark-icon:hover{color:#1e8cbe}.yoast-inline-icon{vertical-align:middle}.yoast-block-sidebar-warnings{width:100%}.yoast-block-sidebar-warning{list-style:none;color:#404040;padding:0 17px 0 0}.yoast-block-sidebar-warning>.yoast-svg-icon{margin-right:-1.5em;margin-left:.5em;color:red}.yoast-block-suggestion{list-style:disc;color:#707070}.yoast-block-suggestion--added{color:#404040}.yoast-block-suggestion-checkmark{color:#6ea029}.yoast-block-suggestion-button{cursor:pointer;float:left;color:#006dac;text-decoration:underline;border:0;background:100%}.yoast-block-date-picker-container>button{background:none;border:none;color:#747474;font-family:inherit}.yoast-block-date-picker{z-index:1}.yoast-block-date-picker .components-datetime__time>fieldset{margin:0}.yoast-block-date-picker .components-datetime__time>fieldset:last-child{display:none}.yoast-schema-blocks-icon svg{fill:none}.yoast-schema-analysis{margin-bottom:24px}.yoast-schema-flex.yoast-schema-duration{align-items:baseline;overflow:visible}.yoast-schema-flex.yoast-schema-duration p{margin-top:0;white-space:pre}.yoast-schema-duration .minutes-input{display:inline-block;max-width:100px;min-width:40px}.yoast-schema-flex{display:flex;line-height:1.25}.yoast-schema-select select.components-select-control__input{height:100%;padding:6px 8px 6px 33px}.yoast-schema-flex .components-text-control__input,.yoast-schema-select div.components-input-control__backdrop{border:1px solid #ccc;border-radius:0} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/schema-blocks-1720.css b/wp-content/plugins/wordpress-seo/css/dist/schema-blocks-1720.css new file mode 100644 index 00000000..7775a0a2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/schema-blocks-1720.css @@ -0,0 +1 @@ +.yoast-labeled-inserter{position:relative;width:100%}.yoast-labeled-inserter:before{content:attr(data-label);position:absolute;left:0;height:100%;color:#000}.yoast-labeled-inserter>.block-editor-inserter{width:100%}.yoast-warning-block{border-width:0 0 0 4px;border-style:solid;padding:16px;font-size:13px;font-family:Arial,Roboto-Regular,HelveticaNeue,sans-serif}.yoast-warning-block.required{background:#f8ebea;border-color:#cd423b}.yoast-warning-block.recommended{background:#fef8ee;border-color:#f0b650}.yoast-warning-block>.yoast-warning-block-message{margin:0;font-family:Arial,Roboto-Regular,HelveticaNeue,sans-serif}.yoast-warning-block>div{text-align:right;padding-top:8px}.yoast-warning-block>div>button{background:none;border:none;text-decoration:underline;color:#0073aa}.yoast-schema-block-appender__content{color:rgba(30,30,30,.6)}.wp-block .yoast-warning-block>.yoast-warning-block-message>a{text-decoration:underline;color:#0073aa}.yoast-warning-block>div>button:not(:last-child){margin-right:24px}.yoast-block-sidebar-input label,.yoast-block-sidebar-title{font-weight:600;color:#303030;margin-bottom:0;padding-top:10px}.yoast-block-label-with-help-link{width:100%;margin-bottom:3px}.yoast-block-suggestions{width:100%;padding:0 5px 0 15px}.yoast-question-mark-icon{color:#767676}.yoast-question-mark-icon:hover{color:#1e8cbe}.yoast-inline-icon{vertical-align:middle}.yoast-block-sidebar-warnings{width:100%}.yoast-block-sidebar-warning{list-style:none;color:#404040;padding:0 0 0 17px}.yoast-block-sidebar-warning>.yoast-svg-icon{margin-left:-1.5em;margin-right:.5em;color:red}.yoast-block-suggestion{list-style:disc;color:#707070}.yoast-block-suggestion--added{color:#404040}.yoast-block-suggestion-checkmark{color:#6ea029}.yoast-block-suggestion-button{cursor:pointer;float:right;color:#006dac;text-decoration:underline;border:0;background:0}.yoast-block-date-picker-container>button{background:none;border:none;color:#747474;font-family:inherit}.yoast-block-date-picker{z-index:1}.yoast-block-date-picker .components-datetime__time>fieldset{margin:0}.yoast-block-date-picker .components-datetime__time>fieldset:last-child{display:none}.yoast-schema-blocks-icon svg{fill:none}.yoast-schema-analysis{margin-bottom:24px}.yoast-schema-flex.yoast-schema-duration{align-items:baseline;overflow:visible}.yoast-schema-flex.yoast-schema-duration p{margin-top:0;white-space:pre}.yoast-schema-duration .minutes-input{display:inline-block;max-width:100px;min-width:40px}.yoast-schema-flex{display:flex;line-height:1.25}.yoast-schema-select select.components-select-control__input{height:100%;padding:6px 33px 6px 8px}.yoast-schema-flex .components-text-control__input,.yoast-schema-select div.components-input-control__backdrop{border:1px solid #ccc;border-radius:0} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/score_icon-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/score_icon-1720-rtl.css new file mode 100644 index 00000000..5092dc9c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/score_icon-1720-rtl.css @@ -0,0 +1 @@ +.wpseo-score-icon{display:inline-block!important;width:12px!important;height:12px!important;border-radius:50%!important;margin:3px 3px 0 10px;background:#888;vertical-align:top}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/score_icon-1720.css b/wp-content/plugins/wordpress-seo/css/dist/score_icon-1720.css new file mode 100644 index 00000000..f583eba5 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/score_icon-1720.css @@ -0,0 +1 @@ +.wpseo-score-icon{display:inline-block!important;width:12px!important;height:12px!important;border-radius:50%!important;margin:3px 10px 0 3px;background:#888;vertical-align:top}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/search-appearance-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/search-appearance-1720-rtl.css new file mode 100644 index 00000000..ac7b1038 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/search-appearance-1720-rtl.css @@ -0,0 +1 @@ +.draftJsMentionPlugin__mentionSuggestions__2DWjA{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-transform:scale(0)}.yoast-schema-settings-container{margin-top:18px}.yoast-schema-settings-container:first-child{margin-top:0}.yoast-schema-settings-container .yoast-help{position:relative;flex:0 0 20px;height:20px;margin:2px 6px 0 0}.yoast-schema-settings-container .yoast-help:focus{outline:none;box-shadow:none}.yoast-schema-settings-container .yoast-help .yoast-help__icon{display:flex;align-items:center;justify-content:center;width:28px;height:28px;position:absolute;top:-4px;right:-4px;border-radius:100%}.yoast-schema-settings-container .yoast-help:focus .yoast-help__icon{box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.collapsible-header .toggleable-container-trigger code{font-weight:300}#yoast-organization-image-select .yoast-field-group,#yoast-organization-image-select .yoast-image-select,#yoast-person-image-select .yoast-field-group,#yoast-person-image-select .yoast-image-select{margin-bottom:0}.social-settings-heading-container{display:flex;align-items:center;flex-wrap:wrap}.social-settings-heading-container .social-settings-heading{margin:0}.social-settings-heading-container .yoast-badge{margin-right:8px}.yoast-settings-section-upsell .yoast-alert{margin:0 16px}.draftJsMentionPlugin__mention__29BEd,.draftJsMentionPlugin__mention__29BEd:visited{color:#575f67;cursor:pointer;display:inline-block;background:#e6f3ff;padding-right:2px;padding-left:2px;border-radius:2px;text-decoration:none}.draftJsMentionPlugin__mention__29BEd:focus,.draftJsMentionPlugin__mention__29BEd:hover{color:#677584;background:#edf5fd;outline:0}.draftJsMentionPlugin__mention__29BEd:active{color:#222;background:#455261}.draftJsMentionPlugin__mentionSuggestionsEntry__3mSwm{padding:7px 10px 3px;transition:background-color .4s cubic-bezier(.27,1.27,.48,.56)}.draftJsMentionPlugin__mentionSuggestionsEntry__3mSwm:active{background-color:#cce7ff}.draftJsMentionPlugin__mentionSuggestionsEntryFocused__3LcTd{background-color:#e6f3ff}.draftJsMentionPlugin__mentionSuggestionsEntryText__3Jobq{display:inline-block;margin-right:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:368px;font-size:.9em;margin-bottom:.2em}.draftJsMentionPlugin__mentionSuggestionsEntryAvatar__1xgA9{display:inline-block;width:24px;height:24px;border-radius:12px}.draftJsMentionPlugin__mentionSuggestions__2DWjA{border:1px solid #eee;margin-top:.4em;position:absolute;min-width:220px;max-width:440px;background:#fff;border-radius:2px;box-shadow:0 4px 30px 0 #dcdcdc;cursor:pointer;padding-top:8px;padding-bottom:8px;z-index:2;display:flex;flex-direction:column;box-sizing:border-box;transform:scale(0)}.DraftEditor-editorContainer,.DraftEditor-root,.public-DraftEditor-content{height:inherit;text-align:initial}.public-DraftEditor-content[contenteditable=true]{-webkit-user-modify:read-write-plaintext-only}.DraftEditor-root{position:relative}.DraftEditor-editorContainer{background-color:hsla(0,0%,100%,0);border-right:.1px solid transparent;position:relative;z-index:1}.public-DraftEditor-block{position:relative}.DraftEditor-alignLeft .public-DraftStyleDefault-block{text-align:right}.DraftEditor-alignLeft .public-DraftEditorPlaceholder-root{right:0;text-align:right}.DraftEditor-alignCenter .public-DraftStyleDefault-block{text-align:center}.DraftEditor-alignCenter .public-DraftEditorPlaceholder-root{margin:0 auto;text-align:center;width:100%}.DraftEditor-alignRight .public-DraftStyleDefault-block{text-align:left}.DraftEditor-alignRight .public-DraftEditorPlaceholder-root{left:0;text-align:left}.public-DraftEditorPlaceholder-root{color:#9197a3;position:absolute;z-index:1}.public-DraftEditorPlaceholder-hasFocus{color:#bdc1c9}.DraftEditorPlaceholder-hidden{display:none}.public-DraftStyleDefault-block{position:relative;white-space:pre-wrap}.public-DraftStyleDefault-ltr{direction:rtl;text-align:right}.public-DraftStyleDefault-rtl{direction:ltr;text-align:left}.public-DraftStyleDefault-listLTR{direction:rtl}.public-DraftStyleDefault-listRTL{direction:ltr}.public-DraftStyleDefault-ol,.public-DraftStyleDefault-ul{margin:16px 0;padding:0}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR{margin-right:1.5em}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listRTL{margin-left:1.5em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listLTR{margin-right:3em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listRTL{margin-left:3em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listLTR{margin-right:4.5em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listRTL{margin-left:4.5em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listLTR{margin-right:6em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listRTL{margin-left:6em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listLTR{margin-right:7.5em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listRTL{margin-left:7.5em}.public-DraftStyleDefault-unorderedListItem{list-style-type:square;position:relative}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth0{list-style-type:disc}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth1{list-style-type:circle}.public-DraftStyleDefault-orderedListItem{list-style-type:none;position:relative}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR:before{right:-36px;position:absolute;text-align:left;width:30px}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listRTL:before{position:absolute;left:-36px;text-align:right;width:30px}.public-DraftStyleDefault-orderedListItem:before{content:counter(ol0) ". ";counter-increment:ol0}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth1:before{content:counter(ol1) ". ";counter-increment:ol1}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth2:before{content:counter(ol2) ". ";counter-increment:ol2}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth3:before{content:counter(ol3) ". ";counter-increment:ol3}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth4:before{content:counter(ol4) ". ";counter-increment:ol4}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-reset{counter-reset:ol0}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-reset{counter-reset:ol1}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-reset{counter-reset:ol2}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-reset{counter-reset:ol3}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset{counter-reset:ol4}#person-selector{width:100%} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/search-appearance-1720.css b/wp-content/plugins/wordpress-seo/css/dist/search-appearance-1720.css new file mode 100644 index 00000000..72261fcb --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/search-appearance-1720.css @@ -0,0 +1 @@ +.draftJsMentionPlugin__mentionSuggestions__2DWjA{display:-webkit-box;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-transform:scale(0)}.yoast-schema-settings-container{margin-top:18px}.yoast-schema-settings-container:first-child{margin-top:0}.yoast-schema-settings-container .yoast-help{position:relative;flex:0 0 20px;height:20px;margin:2px 0 0 6px}.yoast-schema-settings-container .yoast-help:focus{outline:none;box-shadow:none}.yoast-schema-settings-container .yoast-help .yoast-help__icon{display:flex;align-items:center;justify-content:center;width:28px;height:28px;position:absolute;top:-4px;left:-4px;border-radius:100%}.yoast-schema-settings-container .yoast-help:focus .yoast-help__icon{box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.collapsible-header .toggleable-container-trigger code{font-weight:300}#yoast-organization-image-select .yoast-field-group,#yoast-organization-image-select .yoast-image-select,#yoast-person-image-select .yoast-field-group,#yoast-person-image-select .yoast-image-select{margin-bottom:0}.social-settings-heading-container{display:flex;align-items:center;flex-wrap:wrap}.social-settings-heading-container .social-settings-heading{margin:0}.social-settings-heading-container .yoast-badge{margin-left:8px}.yoast-settings-section-upsell .yoast-alert{margin:0 16px}.draftJsMentionPlugin__mention__29BEd,.draftJsMentionPlugin__mention__29BEd:visited{color:#575f67;cursor:pointer;display:inline-block;background:#e6f3ff;padding-left:2px;padding-right:2px;border-radius:2px;text-decoration:none}.draftJsMentionPlugin__mention__29BEd:focus,.draftJsMentionPlugin__mention__29BEd:hover{color:#677584;background:#edf5fd;outline:0}.draftJsMentionPlugin__mention__29BEd:active{color:#222;background:#455261}.draftJsMentionPlugin__mentionSuggestionsEntry__3mSwm{padding:7px 10px 3px;transition:background-color .4s cubic-bezier(.27,1.27,.48,.56)}.draftJsMentionPlugin__mentionSuggestionsEntry__3mSwm:active{background-color:#cce7ff}.draftJsMentionPlugin__mentionSuggestionsEntryFocused__3LcTd{background-color:#e6f3ff}.draftJsMentionPlugin__mentionSuggestionsEntryText__3Jobq{display:inline-block;margin-left:8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:368px;font-size:.9em;margin-bottom:.2em}.draftJsMentionPlugin__mentionSuggestionsEntryAvatar__1xgA9{display:inline-block;width:24px;height:24px;border-radius:12px}.draftJsMentionPlugin__mentionSuggestions__2DWjA{border:1px solid #eee;margin-top:.4em;position:absolute;min-width:220px;max-width:440px;background:#fff;border-radius:2px;box-shadow:0 4px 30px 0 #dcdcdc;cursor:pointer;padding-top:8px;padding-bottom:8px;z-index:2;display:flex;flex-direction:column;box-sizing:border-box;transform:scale(0)}.DraftEditor-editorContainer,.DraftEditor-root,.public-DraftEditor-content{height:inherit;text-align:initial}.public-DraftEditor-content[contenteditable=true]{-webkit-user-modify:read-write-plaintext-only}.DraftEditor-root{position:relative}.DraftEditor-editorContainer{background-color:hsla(0,0%,100%,0);border-left:.1px solid transparent;position:relative;z-index:1}.public-DraftEditor-block{position:relative}.DraftEditor-alignLeft .public-DraftStyleDefault-block{text-align:left}.DraftEditor-alignLeft .public-DraftEditorPlaceholder-root{left:0;text-align:left}.DraftEditor-alignCenter .public-DraftStyleDefault-block{text-align:center}.DraftEditor-alignCenter .public-DraftEditorPlaceholder-root{margin:0 auto;text-align:center;width:100%}.DraftEditor-alignRight .public-DraftStyleDefault-block{text-align:right}.DraftEditor-alignRight .public-DraftEditorPlaceholder-root{right:0;text-align:right}.public-DraftEditorPlaceholder-root{color:#9197a3;position:absolute;z-index:1}.public-DraftEditorPlaceholder-hasFocus{color:#bdc1c9}.DraftEditorPlaceholder-hidden{display:none}.public-DraftStyleDefault-block{position:relative;white-space:pre-wrap}.public-DraftStyleDefault-ltr{direction:ltr;text-align:left}.public-DraftStyleDefault-rtl{direction:rtl;text-align:right}.public-DraftStyleDefault-listLTR{direction:ltr}.public-DraftStyleDefault-listRTL{direction:rtl}.public-DraftStyleDefault-ol,.public-DraftStyleDefault-ul{margin:16px 0;padding:0}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR{margin-left:1.5em}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-listRTL{margin-right:1.5em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listLTR{margin-left:3em}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-listRTL{margin-right:3em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listLTR{margin-left:4.5em}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-listRTL{margin-right:4.5em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listLTR{margin-left:6em}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-listRTL{margin-right:6em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listLTR{margin-left:7.5em}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-listRTL{margin-right:7.5em}.public-DraftStyleDefault-unorderedListItem{list-style-type:square;position:relative}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth0{list-style-type:disc}.public-DraftStyleDefault-unorderedListItem.public-DraftStyleDefault-depth1{list-style-type:circle}.public-DraftStyleDefault-orderedListItem{list-style-type:none;position:relative}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR:before{left:-36px;position:absolute;text-align:right;width:30px}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listRTL:before{position:absolute;right:-36px;text-align:left;width:30px}.public-DraftStyleDefault-orderedListItem:before{content:counter(ol0) ". ";counter-increment:ol0}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth1:before{content:counter(ol1) ". ";counter-increment:ol1}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth2:before{content:counter(ol2) ". ";counter-increment:ol2}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth3:before{content:counter(ol3) ". ";counter-increment:ol3}.public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-depth4:before{content:counter(ol4) ". ";counter-increment:ol4}.public-DraftStyleDefault-depth0.public-DraftStyleDefault-reset{counter-reset:ol0}.public-DraftStyleDefault-depth1.public-DraftStyleDefault-reset{counter-reset:ol1}.public-DraftStyleDefault-depth2.public-DraftStyleDefault-reset{counter-reset:ol2}.public-DraftStyleDefault-depth3.public-DraftStyleDefault-reset{counter-reset:ol3}.public-DraftStyleDefault-depth4.public-DraftStyleDefault-reset{counter-reset:ol4}#person-selector{width:100%} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/select2/select2-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/select2/select2-rtl.css new file mode 100644 index 00000000..238f6734 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/select2/select2-rtl.css @@ -0,0 +1 @@ +.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-right:8px;padding-left:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-left:8px;padding-right:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-right:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:right}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;right:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{right:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-right-radius:0;border-bottom-left-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-right-radius:0;border-top-left-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;right:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:left;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;left:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;right:50%;margin-right:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:right}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{right:1px;left:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:left;font-weight:bold;margin-top:5px;margin-left:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:right;margin-left:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-left:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:left}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-right:5px;margin-left:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-right:2px;margin-left:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-right-radius:0;border-top-left-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-right-radius:0;border-bottom-left-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-right:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-right:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-right:-1em;padding-right:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-right:-2em;padding-right:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-right:-3em;padding-right:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-right:-4em;padding-right:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-right:-5em;padding-right:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:left;font-weight:bold;margin-left:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-right:1px solid #aaa;border-top-left-radius:4px;border-bottom-left-radius:4px;height:26px;position:absolute;top:1px;left:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;right:50%;margin-right:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:right}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-left:1px solid #aaa;border-radius:0;border-top-right-radius:4px;border-bottom-right-radius:4px;right:1px;left:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-right-radius:0;border-top-left-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-right-radius:0;border-bottom-left-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:right;margin-left:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-left:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:left;margin-right:5px;margin-left:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-right:2px;margin-left:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-right-radius:0;border-top-left-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-right-radius:0;border-bottom-left-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} diff --git a/wp-content/plugins/wordpress-seo/css/dist/select2/select2.min.css b/wp-content/plugins/wordpress-seo/css/dist/select2/select2.min.css index 76de04d9..7c18ad59 100644 --- a/wp-content/plugins/wordpress-seo/css/dist/select2/select2.min.css +++ b/wp-content/plugins/wordpress-seo/css/dist/select2/select2.min.css @@ -1 +1 @@ -.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;height:1px !important;margin:-1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:#999;margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} +.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} diff --git a/wp-content/plugins/wordpress-seo/css/dist/snippet-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/snippet-720-rtl.min.css deleted file mode 100644 index 0d539c51..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/snippet-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -#snippet_preview{font-family:Arial,Helvetica,sans-serif;font-style:normal}.wpseosnippet .snippet-editor__label{font-size:1rem;font-weight:400;line-height:1}input[type=text].snippet-editor__field--invalid{color:#dc3232} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/snippet-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/snippet-720.min.css deleted file mode 100644 index 0d539c51..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/snippet-720.min.css +++ /dev/null @@ -1 +0,0 @@ -#snippet_preview{font-family:Arial,Helvetica,sans-serif;font-style:normal}.wpseosnippet .snippet-editor__label{font-size:1rem;font-weight:400;line-height:1}input[type=text].snippet-editor__field--invalid{color:#dc3232} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/structured-data-blocks-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/structured-data-blocks-1720-rtl.css new file mode 100644 index 00000000..bc8b978c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/structured-data-blocks-1720-rtl.css @@ -0,0 +1 @@ +.schema-faq-section,.schema-how-to-step{position:relative;padding:8px 32px 8px 4px;margin:4px 0;border:1px solid rgba(145,151,162,.25);list-style-type:none}.schema-faq-buttons,.schema-how-to-buttons{display:flex;justify-content:center}.schema-faq-buttons button.components-icon-button:not(:disabled):not([aria-disabled=true]):not(.is-default):hover,.schema-how-to-buttons button.components-icon-button:not(:disabled):not([aria-disabled=true]):not(.is-default):hover{box-shadow:none;color:#007cba}.schema-faq-section-mover,.schema-how-to-step-mover{display:inline-block}.schema-faq-section-mover .editor-block-mover__control,.schema-how-to-step-mover .editor-block-mover__control{display:inline-flex;width:36px;height:36px}.schema-faq-question,.schema-how-to-step-name{font-weight:600}.schema-faq .schema-faq-answer,.schema-faq .schema-faq-question,.schema-how-to .schema-how-to-description,.schema-how-to .schema-how-to-step-name,.schema-how-to .schema-how-to-step-text,.schema-how-to .schema-how-to-steps{margin:0;line-height:inherit}.schema-how-to .schema-how-to-steps{padding-top:0}.schema-faq-section-button-container,.schema-how-to-step-button-container{display:inline-flex;text-align:left}.schema-faq-section-button-container button.components-icon-button:not(:disabled):not([aria-disabled=true]):not(.is-default):hover,.schema-how-to-step-button-container button.components-icon-button:not(:disabled):not([aria-disabled=true]):not(.is-default):hover{box-shadow:none;color:#007cba}.schema-faq-section-controls-container,.schema-how-to-step-controls-container{text-align:left;margin-right:-28px}.schema-faq-section-controls-container .dashicons-arrow-up-alt2,.schema-how-to-step-controls-container .dashicons-arrow-up-alt2{position:relative;top:-1px}.faq-section-add-media .dashicon,.how-to-step-add-media .dashicon,.schema-faq-add-question .dashicon,.schema-how-to-add-step .dashicon,.schema-how-to-duration-button .dashicon{margin-left:4px}.schema-how-to{padding-top:4px}.schema-how-to-step-number{position:absolute;right:4px;width:24px;text-align:left}.schema-how-to-duration-flex-container{display:flex;align-items:center}.schema-how-to-duration-time-input{display:inline-flex;align-items:center;flex-wrap:nowrap}legend.schema-how-to-duration-legend{margin-left:4px}#schema-how-to-duration-days{margin-left:8px}.schema-how-to-duration .schema-how-to-duration-input[type=number]{width:40px;margin:0 2px;padding:6px 4px;text-align:center;-moz-appearance:textfield}.schema-how-to-duration .schema-how-to-duration-input[type=number]::-webkit-inner-spin-button,.schema-how-to-duration .schema-how-to-duration-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.schema-how-to-duration-button.components-icon-button{margin-right:-8px;vertical-align:top}.schema-how-to-duration-button.components-icon-button:not(:disabled):not([aria-disabled=true]):not(.is-default):hover{box-shadow:none;color:#007cba}.schema-how-to-description{margin:8px 0} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/structured-data-blocks-1720.css b/wp-content/plugins/wordpress-seo/css/dist/structured-data-blocks-1720.css new file mode 100644 index 00000000..1ab3978b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/structured-data-blocks-1720.css @@ -0,0 +1 @@ +.schema-faq-section,.schema-how-to-step{position:relative;padding:8px 4px 8px 32px;margin:4px 0;border:1px solid rgba(145,151,162,.25);list-style-type:none}.schema-faq-buttons,.schema-how-to-buttons{display:flex;justify-content:center}.schema-faq-buttons button.components-icon-button:not(:disabled):not([aria-disabled=true]):not(.is-default):hover,.schema-how-to-buttons button.components-icon-button:not(:disabled):not([aria-disabled=true]):not(.is-default):hover{box-shadow:none;color:#007cba}.schema-faq-section-mover,.schema-how-to-step-mover{display:inline-block}.schema-faq-section-mover .editor-block-mover__control,.schema-how-to-step-mover .editor-block-mover__control{display:inline-flex;width:36px;height:36px}.schema-faq-question,.schema-how-to-step-name{font-weight:600}.schema-faq .schema-faq-answer,.schema-faq .schema-faq-question,.schema-how-to .schema-how-to-description,.schema-how-to .schema-how-to-step-name,.schema-how-to .schema-how-to-step-text,.schema-how-to .schema-how-to-steps{margin:0;line-height:inherit}.schema-how-to .schema-how-to-steps{padding-top:0}.schema-faq-section-button-container,.schema-how-to-step-button-container{display:inline-flex;text-align:right}.schema-faq-section-button-container button.components-icon-button:not(:disabled):not([aria-disabled=true]):not(.is-default):hover,.schema-how-to-step-button-container button.components-icon-button:not(:disabled):not([aria-disabled=true]):not(.is-default):hover{box-shadow:none;color:#007cba}.schema-faq-section-controls-container,.schema-how-to-step-controls-container{text-align:right;margin-left:-28px}.schema-faq-section-controls-container .dashicons-arrow-up-alt2,.schema-how-to-step-controls-container .dashicons-arrow-up-alt2{position:relative;top:-1px}.faq-section-add-media .dashicon,.how-to-step-add-media .dashicon,.schema-faq-add-question .dashicon,.schema-how-to-add-step .dashicon,.schema-how-to-duration-button .dashicon{margin-right:4px}.schema-how-to{padding-top:4px}.schema-how-to-step-number{position:absolute;left:4px;width:24px;text-align:right}.schema-how-to-duration-flex-container{display:flex;align-items:center}.schema-how-to-duration-time-input{display:inline-flex;align-items:center;flex-wrap:nowrap}legend.schema-how-to-duration-legend{margin-right:4px}#schema-how-to-duration-days{margin-right:8px}.schema-how-to-duration .schema-how-to-duration-input[type=number]{width:40px;margin:0 2px;padding:6px 4px;text-align:center;-moz-appearance:textfield}.schema-how-to-duration .schema-how-to-duration-input[type=number]::-webkit-inner-spin-button,.schema-how-to-duration .schema-how-to-duration-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.schema-how-to-duration-button.components-icon-button{margin-left:-8px;vertical-align:top}.schema-how-to-duration-button.components-icon-button:not(:disabled):not([aria-disabled=true]):not(.is-default):hover{box-shadow:none;color:#007cba}.schema-how-to-description{margin:8px 0} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-1720-rtl.css new file mode 100644 index 00000000..1604e56b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-1720-rtl.css @@ -0,0 +1 @@ +.switch-light span span,.switch-toggle a{display:none}@media only screen{.switch-light,.switch-toggle{position:relative;display:block;padding:0!important}.switch-light:after,.switch-toggle:after{clear:both;content:"";display:table}.switch-light *,.switch-light :after,.switch-light :before,.switch-toggle *,.switch-toggle :after,.switch-toggle :before{box-sizing:border-box}.switch-light a,.switch-toggle a{display:block;transition:all .2s ease-out}.switch-light-visual-label,.switch-light>span,.switch-light label,.switch-toggle>span,.switch-toggle label{line-height:2;vertical-align:middle}.switch-light input{position:absolute;opacity:0;z-index:3}.switch-light input[type=checkbox].disabled,.switch-light input[type=checkbox].disabled:checked:before,.switch-light input[type=checkbox]:disabled,.switch-light input[type=checkbox]:disabled:checked:before{opacity:0}.switch-light input:checked~span a{left:0}.switch-light strong{font-weight:inherit}.switch-light>span{position:relative;min-height:2em;padding:0;text-align:right}.switch-light span span{position:relative;z-index:2;display:block;float:right;width:50%;text-align:center;-webkit-user-select:none;user-select:none}.switch-light a{position:absolute;left:50%;top:0;z-index:1;display:block;width:50%;height:100%;padding:0}.switch-toggle input{position:absolute;right:0;opacity:0}.switch-toggle input[type=radio].disabled,.switch-toggle input[type=radio].disabled:checked:before,.switch-toggle input[type=radio]:disabled,.switch-toggle input[type=radio]:disabled:checked:before{opacity:0}.switch-toggle input+label{float:right;padding:0 .5em;margin:0;text-align:center}.switch-toggle input:checked+label{position:relative;z-index:2}.switch-toggle a{position:absolute;top:0;right:0;padding:0;z-index:1;width:10px;height:100%}.switch-toggle label:nth-child(2):nth-last-child(4),.switch-toggle label:nth-child(2):nth-last-child(4)~a,.switch-toggle label:nth-child(2):nth-last-child(4)~label{width:50%}.switch-toggle label:nth-child(2):nth-last-child(4)~input:checked:nth-child(3)+label~a{right:50%}.switch-toggle label:nth-child(2):nth-last-child(6),.switch-toggle label:nth-child(2):nth-last-child(6)~a,.switch-toggle label:nth-child(2):nth-last-child(6)~label{width:33.33%}.switch-toggle label:nth-child(2):nth-last-child(6)~input:checked:nth-child(3)+label~a{right:33.33%}.switch-toggle label:nth-child(2):nth-last-child(6)~input:checked:nth-child(5)+label~a{right:66.66%}.switch-toggle label:nth-child(2):nth-last-child(8),.switch-toggle label:nth-child(2):nth-last-child(8)~a,.switch-toggle label:nth-child(2):nth-last-child(8)~label{width:25%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(3)+label~a{right:25%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(5)+label~a{right:50%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(7)+label~a{right:75%}.switch-toggle label:nth-child(2):nth-last-child(10),.switch-toggle label:nth-child(2):nth-last-child(10)~a,.switch-toggle label:nth-child(2):nth-last-child(10)~label{width:20%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(3)+label~a{right:20%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(5)+label~a{right:40%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(7)+label~a{right:60%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(9)+label~a{right:80%}.switch-toggle label:nth-child(2):nth-last-child(12),.switch-toggle label:nth-child(2):nth-last-child(12)~a,.switch-toggle label:nth-child(2):nth-last-child(12)~label{width:16.6%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(3)+label~a{right:16.6%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(5)+label~a{right:33.2%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(7)+label~a{right:49.8%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(9)+label~a{right:66.4%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(11)+label~a{right:83%}.switch-candy a{box-shadow:0 1px 1px rgba(0,0,0,.2),inset 0 1px 1px hsla(0,0%,100%,.45)}}@media only screen and (-webkit-max-device-pixel-ratio:2) and (max-device-width:80em){.switch-light,.switch-toggle{-webkit-animation:webkitSiblingBugfix 1s infinite}}.fieldset-switch-toggle label{float:none}@media only screen{.fieldset-switch-toggle legend{float:right;box-sizing:border-box;min-width:200px;margin:8px 0;padding-left:16px;line-height:2;vertical-align:middle;font-weight:600}.fieldset-switch-toggle .disabled-note{clear:both}.switch-container__has-help .switch-light-visual-label,.switch-container__has-help legend{float:right;min-width:0;padding-left:0}.switch-container__has-help .yoast_help.yoast-help-button{margin:8px 2px 0 0}.switch-light.switch-yoast-seo>span,.switch-toggle.switch-yoast-seo{width:250px;border:1px solid #ccc;border-radius:.5em;background-color:#dcdcdc;box-shadow:inset 0 2px 4px rgba(0,0,0,.15)}.switch-light.switch-yoast-seo,.switch-toggle.switch-yoast-seo{clear:both;float:right}.switch-light.switch-yoast-seo>span{display:inline-block;overflow:visible}.switch-light.switch-yoast-seo a,.switch-toggle.switch-yoast-seo a{border:1px solid #b5b5b5;border-radius:.5em;background:#a4286a}.switch-light.switch-yoast-seo input.disabled+span a,.switch-light.switch-yoast-seo input.disabled:checked+span a,.switch-light.switch-yoast-seo input:disabled+span a,.switch-light.switch-yoast-seo input:disabled:checked+span a,.switch-toggle.switch-yoast-seo input.disabled+a,.switch-toggle.switch-yoast-seo input.disabled~a,.switch-toggle.switch-yoast-seo input:disabled+a,.switch-toggle.switch-yoast-seo input:disabled~a{background:#9b9b9b;border:0}.switch-light.switch-yoast-seo input:focus+label,.switch-light.switch-yoast-seo input:focus~span a,.switch-toggle.switch-yoast-seo input:focus+label,.switch-toggle.switch-yoast-seo input:focus~span a{outline:none}.switch-light.switch-yoast-seo input:focus~span a,.switch-toggle.switch-yoast-seo input:focus~a{border-color:#5b9dd9!important;box-shadow:0 0 2px rgba(0,115,170,.8)!important}.switch-light.switch-yoast-seo input:checked~span a,.switch-toggle.switch-yoast-seo input:checked~span a{border:1px solid #b5b5b5;background:#a4286a}.switch-light.switch-yoast-seo input:checked~span span:first-child,.switch-light.switch-yoast-seo span span,.switch-toggle.switch-yoast-seo label{color:#333;text-shadow:none;font-weight:inherit}.switch-candy.switch-yoast-seo input:checked+label,.switch-candy.switch-yoast-seo input:checked~span span:nth-child(2),.switch-candy.switch-yoast-seo input~span span:first-child{color:#fff;text-shadow:none}.switch-candy.switch-yoast-seo input+label:after{content:"";display:block;width:100%;height:100%;position:absolute;top:0;right:0;z-index:3}.switch-candy.switch-yoast-seo input:checked+label:after{content:none}.switch-light.switch-yoast-seo-reverse input:checked~span a{right:0}.switch-light.switch-yoast-seo-reverse a{right:50%}.switch-light.switch-yoast-seo-reverse span span{float:left}.switch-toggle.switch-yoast-seo label,label.switch-light.switch-yoast-seo{margin-right:0;cursor:pointer}.switch-light.switch-yoast-seo input.disabled+span,.switch-light.switch-yoast-seo input:disabled+span,.switch-toggle.switch-yoast-seo input.disabled+label,.switch-toggle.switch-yoast-seo input:disabled+label{cursor:not-allowed}.switch-yoast-seo .switch-yoast-seo-jaws-a11y{display:block;overflow:hidden;height:1px;margin-bottom:-1px}.switch-light.switch-yoast-seo label code,.switch-toggle.switch-yoast-seo label code{background-color:inherit;vertical-align:top}.switch-light-visual-label{display:block;margin:8px 0;font-weight:400;line-height:2;font-weight:600}.switch-light-visual-label__strong{font-weight:600}.switch-container{clear:both;margin:0 0 .8em}.switch-container+.switch-container{margin-top:8px}.switch-container+p{margin:0 0 16px}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-1720.css b/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-1720.css new file mode 100644 index 00000000..6276ff0b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-1720.css @@ -0,0 +1 @@ +.switch-light span span,.switch-toggle a{display:none}@media only screen{.switch-light,.switch-toggle{position:relative;display:block;padding:0!important}.switch-light:after,.switch-toggle:after{clear:both;content:"";display:table}.switch-light *,.switch-light :after,.switch-light :before,.switch-toggle *,.switch-toggle :after,.switch-toggle :before{box-sizing:border-box}.switch-light a,.switch-toggle a{display:block;transition:all .2s ease-out}.switch-light-visual-label,.switch-light>span,.switch-light label,.switch-toggle>span,.switch-toggle label{line-height:2;vertical-align:middle}.switch-light input{position:absolute;opacity:0;z-index:3}.switch-light input[type=checkbox].disabled,.switch-light input[type=checkbox].disabled:checked:before,.switch-light input[type=checkbox]:disabled,.switch-light input[type=checkbox]:disabled:checked:before{opacity:0}.switch-light input:checked~span a{right:0}.switch-light strong{font-weight:inherit}.switch-light>span{position:relative;min-height:2em;padding:0;text-align:left}.switch-light span span{position:relative;z-index:2;display:block;float:left;width:50%;text-align:center;-webkit-user-select:none;user-select:none}.switch-light a{position:absolute;right:50%;top:0;z-index:1;display:block;width:50%;height:100%;padding:0}.switch-toggle input{position:absolute;left:0;opacity:0}.switch-toggle input[type=radio].disabled,.switch-toggle input[type=radio].disabled:checked:before,.switch-toggle input[type=radio]:disabled,.switch-toggle input[type=radio]:disabled:checked:before{opacity:0}.switch-toggle input+label{float:left;padding:0 .5em;margin:0;text-align:center}.switch-toggle input:checked+label{position:relative;z-index:2}.switch-toggle a{position:absolute;top:0;left:0;padding:0;z-index:1;width:10px;height:100%}.switch-toggle label:nth-child(2):nth-last-child(4),.switch-toggle label:nth-child(2):nth-last-child(4)~a,.switch-toggle label:nth-child(2):nth-last-child(4)~label{width:50%}.switch-toggle label:nth-child(2):nth-last-child(4)~input:checked:nth-child(3)+label~a{left:50%}.switch-toggle label:nth-child(2):nth-last-child(6),.switch-toggle label:nth-child(2):nth-last-child(6)~a,.switch-toggle label:nth-child(2):nth-last-child(6)~label{width:33.33%}.switch-toggle label:nth-child(2):nth-last-child(6)~input:checked:nth-child(3)+label~a{left:33.33%}.switch-toggle label:nth-child(2):nth-last-child(6)~input:checked:nth-child(5)+label~a{left:66.66%}.switch-toggle label:nth-child(2):nth-last-child(8),.switch-toggle label:nth-child(2):nth-last-child(8)~a,.switch-toggle label:nth-child(2):nth-last-child(8)~label{width:25%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(3)+label~a{left:25%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(5)+label~a{left:50%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(7)+label~a{left:75%}.switch-toggle label:nth-child(2):nth-last-child(10),.switch-toggle label:nth-child(2):nth-last-child(10)~a,.switch-toggle label:nth-child(2):nth-last-child(10)~label{width:20%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(3)+label~a{left:20%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(5)+label~a{left:40%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(7)+label~a{left:60%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(9)+label~a{left:80%}.switch-toggle label:nth-child(2):nth-last-child(12),.switch-toggle label:nth-child(2):nth-last-child(12)~a,.switch-toggle label:nth-child(2):nth-last-child(12)~label{width:16.6%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(3)+label~a{left:16.6%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(5)+label~a{left:33.2%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(7)+label~a{left:49.8%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(9)+label~a{left:66.4%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(11)+label~a{left:83%}.switch-candy a{box-shadow:0 1px 1px rgba(0,0,0,.2),inset 0 1px 1px hsla(0,0%,100%,.45)}}@media only screen and (-webkit-max-device-pixel-ratio:2) and (max-device-width:80em){.switch-light,.switch-toggle{-webkit-animation:webkitSiblingBugfix 1s infinite}}.fieldset-switch-toggle label{float:none}@media only screen{.fieldset-switch-toggle legend{float:left;box-sizing:border-box;min-width:200px;margin:8px 0;padding-right:16px;line-height:2;vertical-align:middle;font-weight:600}.fieldset-switch-toggle .disabled-note{clear:both}.switch-container__has-help .switch-light-visual-label,.switch-container__has-help legend{float:left;min-width:0;padding-right:0}.switch-container__has-help .yoast_help.yoast-help-button{margin:8px 0 0 2px}.switch-light.switch-yoast-seo>span,.switch-toggle.switch-yoast-seo{width:250px;border:1px solid #ccc;border-radius:.5em;background-color:#dcdcdc;box-shadow:inset 0 2px 4px rgba(0,0,0,.15)}.switch-light.switch-yoast-seo,.switch-toggle.switch-yoast-seo{clear:both;float:left}.switch-light.switch-yoast-seo>span{display:inline-block;overflow:visible}.switch-light.switch-yoast-seo a,.switch-toggle.switch-yoast-seo a{border:1px solid #b5b5b5;border-radius:.5em;background:#a4286a}.switch-light.switch-yoast-seo input.disabled+span a,.switch-light.switch-yoast-seo input.disabled:checked+span a,.switch-light.switch-yoast-seo input:disabled+span a,.switch-light.switch-yoast-seo input:disabled:checked+span a,.switch-toggle.switch-yoast-seo input.disabled+a,.switch-toggle.switch-yoast-seo input.disabled~a,.switch-toggle.switch-yoast-seo input:disabled+a,.switch-toggle.switch-yoast-seo input:disabled~a{background:#9b9b9b;border:0}.switch-light.switch-yoast-seo input:focus+label,.switch-light.switch-yoast-seo input:focus~span a,.switch-toggle.switch-yoast-seo input:focus+label,.switch-toggle.switch-yoast-seo input:focus~span a{outline:none}.switch-light.switch-yoast-seo input:focus~span a,.switch-toggle.switch-yoast-seo input:focus~a{border-color:#5b9dd9!important;box-shadow:0 0 2px rgba(0,115,170,.8)!important}.switch-light.switch-yoast-seo input:checked~span a,.switch-toggle.switch-yoast-seo input:checked~span a{border:1px solid #b5b5b5;background:#a4286a}.switch-light.switch-yoast-seo input:checked~span span:first-child,.switch-light.switch-yoast-seo span span,.switch-toggle.switch-yoast-seo label{color:#333;text-shadow:none;font-weight:inherit}.switch-candy.switch-yoast-seo input:checked+label,.switch-candy.switch-yoast-seo input:checked~span span:nth-child(2),.switch-candy.switch-yoast-seo input~span span:first-child{color:#fff;text-shadow:none}.switch-candy.switch-yoast-seo input+label:after{content:"";display:block;width:100%;height:100%;position:absolute;top:0;left:0;z-index:3}.switch-candy.switch-yoast-seo input:checked+label:after{content:none}.switch-light.switch-yoast-seo-reverse input:checked~span a{left:0}.switch-light.switch-yoast-seo-reverse a{left:50%}.switch-light.switch-yoast-seo-reverse span span{float:right}.switch-toggle.switch-yoast-seo label,label.switch-light.switch-yoast-seo{margin-left:0;cursor:pointer}.switch-light.switch-yoast-seo input.disabled+span,.switch-light.switch-yoast-seo input:disabled+span,.switch-toggle.switch-yoast-seo input.disabled+label,.switch-toggle.switch-yoast-seo input:disabled+label{cursor:not-allowed}.switch-yoast-seo .switch-yoast-seo-jaws-a11y{display:block;overflow:hidden;height:1px;margin-bottom:-1px}.switch-light.switch-yoast-seo label code,.switch-toggle.switch-yoast-seo label code{background-color:inherit;vertical-align:top}.switch-light-visual-label{display:block;margin:8px 0;font-weight:400;line-height:2;font-weight:600}.switch-light-visual-label__strong{font-weight:600}.switch-container{clear:both;margin:0 0 .8em}.switch-container+.switch-container{margin-top:8px}.switch-container+p{margin:0 0 16px}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-720-rtl.min.css deleted file mode 100644 index f7cef9f0..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";.switch-light span span,.switch-toggle a{display:none}@media only screen{.switch-light,.switch-toggle{display:block;position:relative;padding:0!important}.switch-light::after,.switch-toggle::after{display:table;clear:both;content:""}.switch-light *,.switch-light :after,.switch-light :before,.switch-toggle *,.switch-toggle :after,.switch-toggle :before{box-sizing:border-box}.switch-light a,.switch-toggle a{display:block;transition:all .2s ease-out}.switch-light label,.switch-light-visual-label,.switch-light>span,.switch-toggle label,.switch-toggle>span{line-height:2;vertical-align:middle}.switch-light input{position:absolute;z-index:3;opacity:0}.switch-light input:checked~span a{left:0}.switch-light strong{font-weight:inherit}.switch-light>span{position:relative;min-height:2em;padding:0;text-align:right}.switch-light span span{display:block;float:right;position:relative;z-index:2;width:50%;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-light a{display:block;position:absolute;z-index:1;top:0;left:50%;width:50%;height:100%;padding:0}.switch-toggle input{position:absolute;right:0;opacity:0}.switch-toggle input+label{display:block;float:right;position:relative;z-index:2;margin:0;padding:0 .5em;text-align:center}.switch-toggle a{position:absolute;z-index:1;top:0;right:0;width:10px;height:100%;padding:0}.switch-toggle label:nth-child(2):nth-last-child(4),.switch-toggle label:nth-child(2):nth-last-child(4)~a,.switch-toggle label:nth-child(2):nth-last-child(4)~label{width:50%}.switch-toggle label:nth-child(2):nth-last-child(4)~input:checked:nth-child(3)+label~a{right:50%}.switch-toggle label:nth-child(2):nth-last-child(6),.switch-toggle label:nth-child(2):nth-last-child(6)~a,.switch-toggle label:nth-child(2):nth-last-child(6)~label{width:33.33%}.switch-toggle label:nth-child(2):nth-last-child(6)~input:checked:nth-child(3)+label~a{right:33.33%}.switch-toggle label:nth-child(2):nth-last-child(6)~input:checked:nth-child(5)+label~a{right:66.66%}.switch-toggle label:nth-child(2):nth-last-child(8),.switch-toggle label:nth-child(2):nth-last-child(8)~a,.switch-toggle label:nth-child(2):nth-last-child(8)~label{width:25%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(3)+label~a{right:25%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(5)+label~a{right:50%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(7)+label~a{right:75%}.switch-toggle label:nth-child(2):nth-last-child(10),.switch-toggle label:nth-child(2):nth-last-child(10)~a,.switch-toggle label:nth-child(2):nth-last-child(10)~label{width:20%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(3)+label~a{right:20%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(5)+label~a{right:40%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(7)+label~a{right:60%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(9)+label~a{right:80%}.switch-toggle label:nth-child(2):nth-last-child(12),.switch-toggle label:nth-child(2):nth-last-child(12)~a,.switch-toggle label:nth-child(2):nth-last-child(12)~label{width:16.6%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(3)+label~a{right:16.6%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(5)+label~a{right:33.2%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(7)+label~a{right:49.8%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(9)+label~a{right:66.4%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(11)+label~a{right:83%}.switch-candy a{box-shadow:0 1px 1px rgba(0,0,0,.2),inset 0 1px 1px rgba(255,255,255,.45)}}@media only screen and (-webkit-max-device-pixel-ratio:2) and (max-device-width:80em){.switch-light,.switch-toggle{-webkit-animation:webkitSiblingBugfix infinite 1s}}.fieldset-switch-toggle label{float:none}@media only screen{.fieldset-switch-toggle legend{float:right;box-sizing:border-box;min-width:200px;margin:8px 0;padding-left:16px;line-height:2;vertical-align:middle}.switch-container__has-help .switch-light-visual-label,.switch-container__has-help legend{float:right;min-width:0;padding-left:0}.switch-container__has-help .yoast_help.yoast-help-button{margin:8px 4px 0 0}.switch-light.switch-yoast-seo>span,.switch-toggle.switch-yoast-seo{width:250px;border:1px solid #ccc;border-radius:.5em;background-color:#dcdcdc;box-shadow:inset 0 2px 4px rgba(0,0,0,.15)}.switch-light.switch-yoast-seo,.switch-toggle.switch-yoast-seo{float:right;clear:both}.switch-light.switch-yoast-seo>span{display:inline-block;overflow:visible}.switch-light.switch-yoast-seo a,.switch-toggle.switch-yoast-seo a{border:1px solid #b5b5b5;border-radius:.5em;background:#a4286a}.switch-light.switch-yoast-seo input:focus+label,.switch-light.switch-yoast-seo input:focus~span a,.switch-toggle.switch-yoast-seo input:focus+label,.switch-toggle.switch-yoast-seo input:focus~span a{outline:0}.switch-light.switch-yoast-seo input:focus~span a,.switch-toggle.switch-yoast-seo input:focus~a{border-color:#5b9dd9!important;box-shadow:0 0 2px rgba(0,115,170,.8)!important}.switch-light.switch-yoast-seo input:checked~span a,.switch-toggle.switch-yoast-seo input:checked~span a{border:1px solid #b5b5b5;background:#a4286a}.switch-light.switch-yoast-seo input:checked~span span:first-child,.switch-light.switch-yoast-seo span span,.switch-toggle.switch-yoast-seo label{color:#333;text-shadow:none;font-weight:inherit}.switch-candy.switch-yoast-seo input:checked+label,.switch-candy.switch-yoast-seo input:checked~span span:nth-child(2),.switch-candy.switch-yoast-seo input~span span:first-child{color:#fff;text-shadow:none}.switch-light.switch-yoast-seo-reverse input:checked~span a{right:0}.switch-light.switch-yoast-seo-reverse a{right:50%}.switch-light.switch-yoast-seo-reverse span span{float:left}.switch-toggle.switch-yoast-seo label,label.switch-light.switch-yoast-seo{margin-right:0;cursor:pointer}.switch-yoast-seo .switch-yoast-seo-jaws-a11y{display:block;overflow:hidden;height:1px;margin-bottom:-1px}.switch-light.switch-yoast-seo label code,.switch-toggle.switch-yoast-seo label code{background-color:inherit;vertical-align:top}.switch-container .label-text,.switch-light-visual-label{display:block;margin:8px 0;font-weight:400;line-height:2}.switch-container{clear:both;margin:0 0 2em}.switch-container+.switch-container{margin-top:8px}.switch-container+p{margin:-8px 0 16px}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-720.min.css deleted file mode 100644 index 12ee391c..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/toggle-switch-720.min.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";.switch-light span span,.switch-toggle a{display:none}@media only screen{.switch-light,.switch-toggle{display:block;position:relative;padding:0!important}.switch-light::after,.switch-toggle::after{display:table;clear:both;content:""}.switch-light *,.switch-light :after,.switch-light :before,.switch-toggle *,.switch-toggle :after,.switch-toggle :before{box-sizing:border-box}.switch-light a,.switch-toggle a{display:block;transition:all .2s ease-out}.switch-light label,.switch-light-visual-label,.switch-light>span,.switch-toggle label,.switch-toggle>span{line-height:2;vertical-align:middle}.switch-light input{position:absolute;z-index:3;opacity:0}.switch-light input:checked~span a{right:0}.switch-light strong{font-weight:inherit}.switch-light>span{position:relative;min-height:2em;padding:0;text-align:left}.switch-light span span{display:block;float:left;position:relative;z-index:2;width:50%;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch-light a{display:block;position:absolute;z-index:1;top:0;right:50%;width:50%;height:100%;padding:0}.switch-toggle input{position:absolute;left:0;opacity:0}.switch-toggle input+label{display:block;float:left;position:relative;z-index:2;margin:0;padding:0 .5em;text-align:center}.switch-toggle a{position:absolute;z-index:1;top:0;left:0;width:10px;height:100%;padding:0}.switch-toggle label:nth-child(2):nth-last-child(4),.switch-toggle label:nth-child(2):nth-last-child(4)~a,.switch-toggle label:nth-child(2):nth-last-child(4)~label{width:50%}.switch-toggle label:nth-child(2):nth-last-child(4)~input:checked:nth-child(3)+label~a{left:50%}.switch-toggle label:nth-child(2):nth-last-child(6),.switch-toggle label:nth-child(2):nth-last-child(6)~a,.switch-toggle label:nth-child(2):nth-last-child(6)~label{width:33.33%}.switch-toggle label:nth-child(2):nth-last-child(6)~input:checked:nth-child(3)+label~a{left:33.33%}.switch-toggle label:nth-child(2):nth-last-child(6)~input:checked:nth-child(5)+label~a{left:66.66%}.switch-toggle label:nth-child(2):nth-last-child(8),.switch-toggle label:nth-child(2):nth-last-child(8)~a,.switch-toggle label:nth-child(2):nth-last-child(8)~label{width:25%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(3)+label~a{left:25%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(5)+label~a{left:50%}.switch-toggle label:nth-child(2):nth-last-child(8)~input:checked:nth-child(7)+label~a{left:75%}.switch-toggle label:nth-child(2):nth-last-child(10),.switch-toggle label:nth-child(2):nth-last-child(10)~a,.switch-toggle label:nth-child(2):nth-last-child(10)~label{width:20%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(3)+label~a{left:20%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(5)+label~a{left:40%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(7)+label~a{left:60%}.switch-toggle label:nth-child(2):nth-last-child(10)~input:checked:nth-child(9)+label~a{left:80%}.switch-toggle label:nth-child(2):nth-last-child(12),.switch-toggle label:nth-child(2):nth-last-child(12)~a,.switch-toggle label:nth-child(2):nth-last-child(12)~label{width:16.6%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(3)+label~a{left:16.6%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(5)+label~a{left:33.2%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(7)+label~a{left:49.8%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(9)+label~a{left:66.4%}.switch-toggle label:nth-child(2):nth-last-child(12)~input:checked:nth-child(11)+label~a{left:83%}.switch-candy a{box-shadow:0 1px 1px rgba(0,0,0,.2),inset 0 1px 1px rgba(255,255,255,.45)}}@media only screen and (-webkit-max-device-pixel-ratio:2) and (max-device-width:80em){.switch-light,.switch-toggle{-webkit-animation:webkitSiblingBugfix infinite 1s}}.fieldset-switch-toggle label{float:none}@media only screen{.fieldset-switch-toggle legend{float:left;box-sizing:border-box;min-width:200px;margin:8px 0;padding-right:16px;line-height:2;vertical-align:middle}.switch-container__has-help .switch-light-visual-label,.switch-container__has-help legend{float:left;min-width:0;padding-right:0}.switch-container__has-help .yoast_help.yoast-help-button{margin:8px 0 0 4px}.switch-light.switch-yoast-seo>span,.switch-toggle.switch-yoast-seo{width:250px;border:1px solid #ccc;border-radius:.5em;background-color:#dcdcdc;box-shadow:inset 0 2px 4px rgba(0,0,0,.15)}.switch-light.switch-yoast-seo,.switch-toggle.switch-yoast-seo{float:left;clear:both}.switch-light.switch-yoast-seo>span{display:inline-block;overflow:visible}.switch-light.switch-yoast-seo a,.switch-toggle.switch-yoast-seo a{border:1px solid #b5b5b5;border-radius:.5em;background:#a4286a}.switch-light.switch-yoast-seo input:focus+label,.switch-light.switch-yoast-seo input:focus~span a,.switch-toggle.switch-yoast-seo input:focus+label,.switch-toggle.switch-yoast-seo input:focus~span a{outline:0}.switch-light.switch-yoast-seo input:focus~span a,.switch-toggle.switch-yoast-seo input:focus~a{border-color:#5b9dd9!important;box-shadow:0 0 2px rgba(0,115,170,.8)!important}.switch-light.switch-yoast-seo input:checked~span a,.switch-toggle.switch-yoast-seo input:checked~span a{border:1px solid #b5b5b5;background:#a4286a}.switch-light.switch-yoast-seo input:checked~span span:first-child,.switch-light.switch-yoast-seo span span,.switch-toggle.switch-yoast-seo label{color:#333;text-shadow:none;font-weight:inherit}.switch-candy.switch-yoast-seo input:checked+label,.switch-candy.switch-yoast-seo input:checked~span span:nth-child(2),.switch-candy.switch-yoast-seo input~span span:first-child{color:#fff;text-shadow:none}.switch-light.switch-yoast-seo-reverse input:checked~span a{left:0}.switch-light.switch-yoast-seo-reverse a{left:50%}.switch-light.switch-yoast-seo-reverse span span{float:right}.switch-toggle.switch-yoast-seo label,label.switch-light.switch-yoast-seo{margin-left:0;cursor:pointer}.switch-yoast-seo .switch-yoast-seo-jaws-a11y{display:block;overflow:hidden;height:1px;margin-bottom:-1px}.switch-light.switch-yoast-seo label code,.switch-toggle.switch-yoast-seo label code{background-color:inherit;vertical-align:top}.switch-container .label-text,.switch-light-visual-label{display:block;margin:8px 0;font-weight:400;line-height:2}.switch-container{clear:both;margin:0 0 2em}.switch-container+.switch-container{margin-top:8px}.switch-container+p{margin:-8px 0 16px}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/workouts-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/workouts-1720-rtl.css new file mode 100644 index 00000000..6077e57e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/workouts-1720-rtl.css @@ -0,0 +1 @@ +#wpseo-workouts-container h1,#wpseo-workouts-container h3{color:#a4286a;font-weight:500}#wpseo-workouts-container h2{font-size:12px;text-transform:uppercase}.workflow tr.cornerstone{font-weight:700}#wpseo-workouts-container div.card{max-width:600px;width:100%;padding:24px;border-radius:8px;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);border:0}.workflow{list-style:none;counter-reset:line-number;margin-right:48px}.workflow li{position:relative;counter-increment:line-number;padding-bottom:16px}.workflow>li:before{content:"";position:absolute;width:2px;background:#a4286a;right:-33px;top:0;bottom:-20px}.workflow>li:last-of-type:before{display:none}.workflow>li:after{content:counter(line-number);width:28px;height:28px;text-align:center;border:2px solid #a4286a;color:#a4286a;background:#fff;position:absolute;display:block;border-radius:100%;line-height:28px;top:-8px;right:-48px}.workflow li.finished:after{content:"";background:url("data:image/svg+xml;charset=utf-8,%3Csvg width='24' fill='none' stroke='%23FFF' height='24' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 13l4 4L19 7'/%3E%3C/svg%3E") #a4286a;background-size:20px 20px;background-repeat:no-repeat;background-position:50%}.workflow li.finished p,.workflow li.finished table{opacity:.5}.workflow li img{max-width:100%}.workflow li img.workflow__image{max-height:100px;max-width:100px}.workflow li.yoast-fadeout:before{background:linear-gradient(-180deg,#a4286a,#fff 75%);display:block}.workflow__grid{display:grid;grid-template-columns:auto 100px;gap:8px}.workflow__grid>div:last-of-type{display:flex;flex-wrap:wrap;justify-content:flex-end}table.yoast_help.yoast_link_suggestions thead td{padding:16px 8px}table.yoast_help.yoast_link_suggestions td{vertical-align:middle} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/workouts-1720.css b/wp-content/plugins/wordpress-seo/css/dist/workouts-1720.css new file mode 100644 index 00000000..6467b433 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/workouts-1720.css @@ -0,0 +1 @@ +#wpseo-workouts-container h1,#wpseo-workouts-container h3{color:#a4286a;font-weight:500}#wpseo-workouts-container h2{font-size:12px;text-transform:uppercase}.workflow tr.cornerstone{font-weight:700}#wpseo-workouts-container div.card{max-width:600px;width:100%;padding:24px;border-radius:8px;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);border:0}.workflow{list-style:none;counter-reset:line-number;margin-left:48px}.workflow li{position:relative;counter-increment:line-number;padding-bottom:16px}.workflow>li:before{content:"";position:absolute;width:2px;background:#a4286a;left:-33px;top:0;bottom:-20px}.workflow>li:last-of-type:before{display:none}.workflow>li:after{content:counter(line-number);width:28px;height:28px;text-align:center;border:2px solid #a4286a;color:#a4286a;background:#fff;position:absolute;display:block;border-radius:100%;line-height:28px;top:-8px;left:-48px}.workflow li.finished:after{content:"";background:url("data:image/svg+xml;charset=utf-8,%3Csvg width='24' fill='none' stroke='%23FFF' height='24' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 13l4 4L19 7'/%3E%3C/svg%3E") #a4286a;background-size:20px 20px;background-repeat:no-repeat;background-position:50%}.workflow li.finished p,.workflow li.finished table{opacity:.5}.workflow li img{max-width:100%}.workflow li img.workflow__image{max-height:100px;max-width:100px}.workflow li.yoast-fadeout:before{background:linear-gradient(180deg,#a4286a,#fff 75%);display:block}.workflow__grid{display:grid;grid-template-columns:auto 100px;gap:8px}.workflow__grid>div:last-of-type{display:flex;flex-wrap:wrap;justify-content:flex-end}table.yoast_help.yoast_link_suggestions thead td{padding:16px 8px}table.yoast_help.yoast_link_suggestions td{vertical-align:middle} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-1720-rtl.css new file mode 100644 index 00000000..0660a283 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-1720-rtl.css @@ -0,0 +1 @@ +.yoast-notice-dismiss:before{display:block!important;width:20px;height:20px;color:#b4b9be;background:none;font:normal 16px/1 dashicons;text-align:center;content:"\f153";-webkit-font-smoothing:antialiased!important;speak:none}.yoast-notice-dismiss{position:absolute;top:0;left:1px;margin:0;padding:9px;border:none;color:#b4b9be;background:none;cursor:pointer}.yoast-notice-dismiss:before{position:relative;top:0;right:0;line-height:20px}.yoast-notice-dismiss:active:before,.yoast-notice-dismiss:focus:before,.yoast-notice-dismiss:hover:before{color:#c00}.yoast-notice-dismiss:focus{outline:none;color:#c00;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.yoast-notice.is-dismissible{position:relative}.yoast-notice-dismiss{text-decoration:none} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-1720.css b/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-1720.css new file mode 100644 index 00000000..19e7c137 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-1720.css @@ -0,0 +1 @@ +.yoast-notice-dismiss:before{display:block!important;width:20px;height:20px;color:#b4b9be;background:none;font:normal 16px/1 dashicons;text-align:center;content:"\f153";-webkit-font-smoothing:antialiased!important;speak:none}.yoast-notice-dismiss{position:absolute;top:0;right:1px;margin:0;padding:9px;border:none;color:#b4b9be;background:none;cursor:pointer}.yoast-notice-dismiss:before{position:relative;top:0;left:0;line-height:20px}.yoast-notice-dismiss:active:before,.yoast-notice-dismiss:focus:before,.yoast-notice-dismiss:hover:before{color:#c00}.yoast-notice-dismiss:focus{outline:none;color:#c00;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.yoast-notice.is-dismissible{position:relative}.yoast-notice-dismiss{text-decoration:none} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-720-rtl.min.css deleted file mode 100644 index f7d21e53..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -.yoast-notice-dismiss{position:absolute;top:0;left:1px;margin:0;padding:9px;border:none;color:#b4b9be;background:0 0;cursor:pointer;text-decoration:none}.yoast-notice-dismiss:before{display:block!important;width:20px;height:20px;color:#b4b9be;background:0 0;font:400 16px/1 dashicons;text-align:center;content:"\f153";-webkit-font-smoothing:antialiased!important;speak:none;position:relative;top:0;right:0;line-height:20px}.yoast-notice-dismiss:active:before,.yoast-notice-dismiss:focus:before,.yoast-notice-dismiss:hover:before{color:#c00}.yoast-notice-dismiss:focus{outline:0;color:#c00;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.ie8 .yoast-notice-dismiss:focus{outline:#5b9dd9 solid 1px}.yoast-notice.is-dismissible{position:relative} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-720.min.css deleted file mode 100644 index f90fda18..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/wpseo-dismissible-720.min.css +++ /dev/null @@ -1 +0,0 @@ -.yoast-notice-dismiss{position:absolute;top:0;right:1px;margin:0;padding:9px;border:none;color:#b4b9be;background:0 0;cursor:pointer;text-decoration:none}.yoast-notice-dismiss:before{display:block!important;width:20px;height:20px;color:#b4b9be;background:0 0;font:400 16px/1 dashicons;text-align:center;content:"\f153";-webkit-font-smoothing:antialiased!important;speak:none;position:relative;top:0;left:0;line-height:20px}.yoast-notice-dismiss:active:before,.yoast-notice-dismiss:focus:before,.yoast-notice-dismiss:hover:before{color:#c00}.yoast-notice-dismiss:focus{outline:0;color:#c00;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.ie8 .yoast-notice-dismiss:focus{outline:#5b9dd9 solid 1px}.yoast-notice.is-dismissible{position:relative} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yoast-components-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/yoast-components-1720-rtl.css new file mode 100644 index 00000000..41e3397c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/yoast-components-1720-rtl.css @@ -0,0 +1 @@ +.screen-reader-text{position:absolute!important;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);width:1px;height:1px;border:0;padding:0;overflow:hidden;word-wrap:normal!important}body{background:#f1f1f1;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:1.375}a{color:#0073aa;outline:0;transition-property:border,background,color;transition-duration:.05s;transition-timing-function:ease-in-out}a:active,a:hover{color:#00a0d2}a:focus{color:#124964;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}body{margin:0;padding:0}.yoast-wizard-body{box-sizing:border-box;width:80%;max-width:60em;margin:1rem auto 4rem}@media screen and (max-width:768px){.yoast-wizard-body{width:auto;margin:0}}.yoast-wizard__logo{margin:0 auto;display:block}.yoast-wizard{text-align:right;min-height:20px;background:#fff;padding:2em;box-sizing:border-box;width:100%}@media screen and (max-width:768px){.yoast-wizard{padding:1em 1em 2em}}.yoast-wizard--header{text-align:center}.yoast-wizard--header--page-title{color:#a4286a;margin:0 0 -16px;font-size:1.25em;letter-spacing:.03em;line-height:2.5;font-weight:400;padding:0 8px}@media screen and (max-width:768px){.yoast-wizard--header--page-title{font-size:1.5em;line-height:1.25}}.yoast-wizard--navigation{display:flex;justify-content:space-between}.yoast-wizard--button{margin:1em -8px 0;padding:8px;background:none;color:#0073aa;border:none;font:inherit;cursor:pointer}.yoast-wizard--button:after{content:"";display:block;height:0;border-bottom:1px solid #0073aa}.yoast-wizard--button:focus{outline:1px solid #5b9dd9;box-shadow:0 0 2px 1px rgba(30,140,190,.8)}@media screen and (max-width:768px){.yoast-wizard--step__active{width:38px;overflow:hidden}.yoast-wizard--step__active div{display:inline-block!important;vertical-align:middle}.yoast-wizard--step__active div>span>span{display:block!important;margin-right:-7px;padding-left:99px!important}}.yoast-wizard--step__inactive div{pointer-events:none}@media screen and (max-width:768px){.yoast-wizard--step__inactive{display:none!important}}.yoast-wizard--step--container:focus{outline:none}.yoast-wizard--step--container h1{color:#a4286a;margin:0;font-size:2.25em;letter-spacing:.03em;line-height:3.68rem;font-weight:100}@media screen and (max-width:768px){.yoast-wizard--step--container h1{font-size:2em;line-height:1.25}}.yoast-wizard--step--container h2{color:#a4286a;font-size:1.375em;font-weight:100}.yoast-wizard--stepper{width:100%;margin:auto}.yoast-wizard-overlay{z-index:10;opacity:.2;background-color:#000;position:absolute;top:0;right:0;height:100%;color:#fff;text-align:center;width:100%}.yoast-wizard-overlay-loader{position:relative}.yoast-wizard-container{border:1px solid #ccc;text-align:right;min-height:20px;position:relative;box-shadow:0 3px 10px rgba(0,0,0,.15),0 3px 10px rgba(0,0,0,.2)}.yoast-wizard-container--no-navigation{margin-top:40px}.yoast-wizard-container--no-navigation .yoast-wizard{padding-top:3em}@media screen and (max-width:768px){.yoast-wizard-container{box-shadow:none}}.yoast-wizard-container fieldset{border:0;margin:1em 0}.yoast-wizard-text-input{font-size:14px;padding-bottom:.5em}.yoast-wizard-text-input-label{cursor:pointer;display:block;margin:.5em 0 0;font-weight:700;font-size:14px}.yoast-wizard-text-input [type=text]{width:100%;max-width:450px;box-sizing:border-box}.yoast-wizard-field-description{font-weight:700}.yoast-wizard input{line-height:140%;font-size:14px;margin:.5em 0;padding:5px}.yoast-wizard label{cursor:pointer}.yoast-wizard input[type=radio]{margin:.3em 0 .3em .7em;vertical-align:middle}.yoast-wizard-input__explanation{color:#555;margin-top:0;font-style:italic}.yoast-wizard-input-radio{font-size:14px}.yoast-wizard-input-radio-option label{padding-top:2px}.yoast-wizard-input-radio-separator{padding:0}.yoast-wizard-input-radio-separator input{position:absolute;right:-9999em;width:1px;height:1px}.yoast-wizard-input-radio-separator input+label{float:right;width:30px!important;margin:0 0 .5em 5px!important;padding:9px 6px;border:1px solid #ccc;font-family:Arial,Helvetica,sans-serif!important;font-size:18px!important;line-height:24px;text-align:center;cursor:pointer}.yoast-wizard-input-radio-separator input:checked+label{border:3px solid #a4286a;background-color:#fff;padding:7px 4px}.yoast-wizard-input-radio-separator input:focus+label{outline:2px solid #5b9dd9}.yoast-video-container-max-width{max-width:560px}.yoast-video-container{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}.yoast-video-container iframe{position:absolute;top:0;right:0;width:100%;height:100%}.yoast-wizard-notice__error{margin-bottom:15px;padding:12px;border-right:4px solid #dc3232;background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.1)}.yoast-wizard-content-container{max-width:560px}.yoast-wizard-content-container.yoast-wizard-content-container__is-full-width{max-width:none}#wizard{overflow:hidden}.yoast-wizard{padding-top:2em}.yoast-wizard input[type=email],.yoast-wizard input[type=text]{min-width:250px}.yoast-wizard input[type=email]+div,.yoast-wizard input[type=text]+div{margin-left:1em}.yoast-wizard-body{max-width:80em}.yoast-wizard-return-link-container{text-align:center}.wp-core-ui .yoast-wizard-return-link.button{display:inline-flex;align-items:center;height:36px;border-color:transparent;margin:0 0 1em;padding:0 10px 0 16px;border-radius:2px;background:#fff;color:#646d78;text-align:center;text-transform:uppercase;box-shadow:0 1px 6px rgba(0,0,0,.12),0 1px 4px rgba(0,0,0,.12);transition:all .45s cubic-bezier(.23,1,.32,1) 0ms}.wp-core-ui .yoast-wizard-return-link.button:hover{background:#ebebeb;border-color:transparent}.wp-core-ui .yoast-wizard-return-link.button:focus{outline:none;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.wp-core-ui .yoast-wizard-return-link.button:active{background:#ebebeb;box-shadow:0 3px 10px rgba(0,0,0,.16),0 3px 10px rgba(0,0,0,.23);transform:none}.wp-core-ui .yoast-wizard-return-link.button .dashicons{margin-left:8px}.yoast-wizard-mailchimp-message-error{color:#dc3232}.yoast-wizard-mailchimp-message-success{color:#008a00}.yoast-wizard-input{padding-bottom:.5em}.yoast-wizard-input__select{margin:1em 0;font-size:14px}.yoast-wizard-image-upload-container__image{max-width:151px}.yoast-wizard-image-upload-container-buttons{margin-top:1em}.yoast-wizard-image-upload-container-buttons__remove{margin-right:1em}.yoast-wizard-image-upload-container-description{display:block}.yoast-wizard--emphasis{font-weight:700}.yoast-wizard--navigation{margin-top:2em;padding-top:1em;border-top:1px solid #a4286a}.yoast-wizard--rows{display:flex;flex-direction:column}.yoast-wizard--columns{display:flex}.yoast-wizard--columns .yoast-wizard-text-input-field{max-width:100%}.yoast-wizard--columns__even>div{flex-basis:50%}.yoast-wizard--columns>div{margin-right:1em}.yoast-wizard--columns>div:first-child{margin-right:0}.yoast-wizard--columns .yoast-wizard--heading{margin:0;color:#a4286a}.yoast-wizard--columns>.yoast-wizard--column__push_right{order:2}.yoast-wizard--columns>.yoast-wizard--column__push_left{order:1;margin-right:0;margin-left:1em}.yoast-wizard--columns>.yoast-wizard--column__push_left #plugin-training-image-link:focus{outline:3px auto #0073aa;box-shadow:none}.yoast-wizard--choice>.yoast-wizard--rows{height:100%}.yoast-wizard--choice div{align-self:flex-start}.yoast-wizard--choice p{margin-top:.3em;height:100%}.yoast-wizard--box{border:1px solid #a4286a;padding:1em}.yoast-wizard--box>div:first-child{flex-basis:100px}.yoast-wizard-newsletter{margin-bottom:2em}.yoast-wizard-newsletter--header svg{fill:#a4286a;top:4px;position:relative;margin-left:6px}.yoast-wizard-newsletter--decoration{width:100%;max-width:490px}.yoast-wizard-newsletter--decoration img{width:490px;max-width:100%;margin-top:-3em}@media screen and (max-width:80em){.yoast-wizard--columns{display:block}.yoast-wizard--columns>div{margin-right:0}.yoast-wizard--columns>.yoast-wizard--column__push_left{margin-left:0;margin-top:2em}.yoast-wizard--box{display:flex;margin-top:1em}.yoast-wizard--box:first-child{margin-top:0}.yoast-wizard--box>div{margin-right:1em}.yoast-wizard .hide-on-tablet{display:none}}.yoast-wizard--suggestion{border-top:1px solid #a4286a;padding-top:2em;margin-bottom:2em}@media screen and (max-width:50rem){.yoast-wizard .hide-on-mobile{display:none}.yoast-wizard--box{display:block}.yoast-wizard--box>div{margin-right:0}.yoast-wizard--video-frame{position:relative;padding-bottom:56.25%;height:0}.yoast-wizard--video-frame iframe{position:absolute;top:0;right:0;width:100%;height:100%}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yoast-components-1720.css b/wp-content/plugins/wordpress-seo/css/dist/yoast-components-1720.css new file mode 100644 index 00000000..7aaafee2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/yoast-components-1720.css @@ -0,0 +1 @@ +.screen-reader-text{position:absolute!important;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);width:1px;height:1px;border:0;padding:0;overflow:hidden;word-wrap:normal!important}body{background:#f1f1f1;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:1.375}a{color:#0073aa;outline:0;transition-property:border,background,color;transition-duration:.05s;transition-timing-function:ease-in-out}a:active,a:hover{color:#00a0d2}a:focus{color:#124964;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}body{margin:0;padding:0}.yoast-wizard-body{box-sizing:border-box;width:80%;max-width:60em;margin:1rem auto 4rem}@media screen and (max-width:768px){.yoast-wizard-body{width:auto;margin:0}}.yoast-wizard__logo{margin:0 auto;display:block}.yoast-wizard{text-align:left;min-height:20px;background:#fff;padding:2em;box-sizing:border-box;width:100%}@media screen and (max-width:768px){.yoast-wizard{padding:1em 1em 2em}}.yoast-wizard--header{text-align:center}.yoast-wizard--header--page-title{color:#a4286a;margin:0 0 -16px;font-size:1.25em;letter-spacing:.03em;line-height:2.5;font-weight:400;padding:0 8px}@media screen and (max-width:768px){.yoast-wizard--header--page-title{font-size:1.5em;line-height:1.25}}.yoast-wizard--navigation{display:flex;justify-content:space-between}.yoast-wizard--button{margin:1em -8px 0;padding:8px;background:none;color:#0073aa;border:none;font:inherit;cursor:pointer}.yoast-wizard--button:after{content:"";display:block;height:0;border-bottom:1px solid #0073aa}.yoast-wizard--button:focus{outline:1px solid #5b9dd9;box-shadow:0 0 2px 1px rgba(30,140,190,.8)}@media screen and (max-width:768px){.yoast-wizard--step__active{width:38px;overflow:hidden}.yoast-wizard--step__active div{display:inline-block!important;vertical-align:middle}.yoast-wizard--step__active div>span>span{display:block!important;margin-left:-7px;padding-right:99px!important}}.yoast-wizard--step__inactive div{pointer-events:none}@media screen and (max-width:768px){.yoast-wizard--step__inactive{display:none!important}}.yoast-wizard--step--container:focus{outline:none}.yoast-wizard--step--container h1{color:#a4286a;margin:0;font-size:2.25em;letter-spacing:.03em;line-height:3.68rem;font-weight:100}@media screen and (max-width:768px){.yoast-wizard--step--container h1{font-size:2em;line-height:1.25}}.yoast-wizard--step--container h2{color:#a4286a;font-size:1.375em;font-weight:100}.yoast-wizard--stepper{width:100%;margin:auto}.yoast-wizard-overlay{z-index:10;opacity:.2;background-color:#000;position:absolute;top:0;left:0;height:100%;color:#fff;text-align:center;width:100%}.yoast-wizard-overlay-loader{position:relative}.yoast-wizard-container{border:1px solid #ccc;text-align:left;min-height:20px;position:relative;box-shadow:0 3px 10px rgba(0,0,0,.15),0 3px 10px rgba(0,0,0,.2)}.yoast-wizard-container--no-navigation{margin-top:40px}.yoast-wizard-container--no-navigation .yoast-wizard{padding-top:3em}@media screen and (max-width:768px){.yoast-wizard-container{box-shadow:none}}.yoast-wizard-container fieldset{border:0;margin:1em 0}.yoast-wizard-text-input{font-size:14px;padding-bottom:.5em}.yoast-wizard-text-input-label{cursor:pointer;display:block;margin:.5em 0 0;font-weight:700;font-size:14px}.yoast-wizard-text-input [type=text]{width:100%;max-width:450px;box-sizing:border-box}.yoast-wizard-field-description{font-weight:700}.yoast-wizard input{line-height:140%;font-size:14px;margin:.5em 0;padding:5px}.yoast-wizard label{cursor:pointer}.yoast-wizard input[type=radio]{margin:.3em .7em .3em 0;vertical-align:middle}.yoast-wizard-input__explanation{color:#555;margin-top:0;font-style:italic}.yoast-wizard-input-radio{font-size:14px}.yoast-wizard-input-radio-option label{padding-top:2px}.yoast-wizard-input-radio-separator{padding:0}.yoast-wizard-input-radio-separator input{position:absolute;left:-9999em;width:1px;height:1px}.yoast-wizard-input-radio-separator input+label{float:left;width:30px!important;margin:0 5px .5em 0!important;padding:9px 6px;border:1px solid #ccc;font-family:Arial,Helvetica,sans-serif!important;font-size:18px!important;line-height:24px;text-align:center;cursor:pointer}.yoast-wizard-input-radio-separator input:checked+label{border:3px solid #a4286a;background-color:#fff;padding:7px 4px}.yoast-wizard-input-radio-separator input:focus+label{outline:2px solid #5b9dd9}.yoast-video-container-max-width{max-width:560px}.yoast-video-container{position:relative;padding-bottom:56.25%;height:0;overflow:hidden}.yoast-video-container iframe{position:absolute;top:0;left:0;width:100%;height:100%}.yoast-wizard-notice__error{margin-bottom:15px;padding:12px;border-left:4px solid #dc3232;background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.1)}.yoast-wizard-content-container{max-width:560px}.yoast-wizard-content-container.yoast-wizard-content-container__is-full-width{max-width:none}#wizard{overflow:hidden}.yoast-wizard{padding-top:2em}.yoast-wizard input[type=email],.yoast-wizard input[type=text]{min-width:250px}.yoast-wizard input[type=email]+div,.yoast-wizard input[type=text]+div{margin-right:1em}.yoast-wizard-body{max-width:80em}.yoast-wizard-return-link-container{text-align:center}.wp-core-ui .yoast-wizard-return-link.button{display:inline-flex;align-items:center;height:36px;border-color:transparent;margin:0 0 1em;padding:0 16px 0 10px;border-radius:2px;background:#fff;color:#646d78;text-align:center;text-transform:uppercase;box-shadow:0 1px 6px rgba(0,0,0,.12),0 1px 4px rgba(0,0,0,.12);transition:all .45s cubic-bezier(.23,1,.32,1) 0ms}.wp-core-ui .yoast-wizard-return-link.button:hover{background:#ebebeb;border-color:transparent}.wp-core-ui .yoast-wizard-return-link.button:focus{outline:none;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.wp-core-ui .yoast-wizard-return-link.button:active{background:#ebebeb;box-shadow:0 3px 10px rgba(0,0,0,.16),0 3px 10px rgba(0,0,0,.23);transform:none}.wp-core-ui .yoast-wizard-return-link.button .dashicons{margin-right:8px}.yoast-wizard-mailchimp-message-error{color:#dc3232}.yoast-wizard-mailchimp-message-success{color:#008a00}.yoast-wizard-input{padding-bottom:.5em}.yoast-wizard-input__select{margin:1em 0;font-size:14px}.yoast-wizard-image-upload-container__image{max-width:151px}.yoast-wizard-image-upload-container-buttons{margin-top:1em}.yoast-wizard-image-upload-container-buttons__remove{margin-left:1em}.yoast-wizard-image-upload-container-description{display:block}.yoast-wizard--emphasis{font-weight:700}.yoast-wizard--navigation{margin-top:2em;padding-top:1em;border-top:1px solid #a4286a}.yoast-wizard--rows{display:flex;flex-direction:column}.yoast-wizard--columns{display:flex}.yoast-wizard--columns .yoast-wizard-text-input-field{max-width:100%}.yoast-wizard--columns__even>div{flex-basis:50%}.yoast-wizard--columns>div{margin-left:1em}.yoast-wizard--columns>div:first-child{margin-left:0}.yoast-wizard--columns .yoast-wizard--heading{margin:0;color:#a4286a}.yoast-wizard--columns>.yoast-wizard--column__push_right{order:2}.yoast-wizard--columns>.yoast-wizard--column__push_left{order:1;margin-left:0;margin-right:1em}.yoast-wizard--columns>.yoast-wizard--column__push_left #plugin-training-image-link:focus{outline:3px auto #0073aa;box-shadow:none}.yoast-wizard--choice>.yoast-wizard--rows{height:100%}.yoast-wizard--choice div{align-self:flex-start}.yoast-wizard--choice p{margin-top:.3em;height:100%}.yoast-wizard--box{border:1px solid #a4286a;padding:1em}.yoast-wizard--box>div:first-child{flex-basis:100px}.yoast-wizard-newsletter{margin-bottom:2em}.yoast-wizard-newsletter--header svg{fill:#a4286a;top:4px;position:relative;margin-right:6px}.yoast-wizard-newsletter--decoration{width:100%;max-width:490px}.yoast-wizard-newsletter--decoration img{width:490px;max-width:100%;margin-top:-3em}@media screen and (max-width:80em){.yoast-wizard--columns{display:block}.yoast-wizard--columns>div{margin-left:0}.yoast-wizard--columns>.yoast-wizard--column__push_left{margin-right:0;margin-top:2em}.yoast-wizard--box{display:flex;margin-top:1em}.yoast-wizard--box:first-child{margin-top:0}.yoast-wizard--box>div{margin-left:1em}.yoast-wizard .hide-on-tablet{display:none}}.yoast-wizard--suggestion{border-top:1px solid #a4286a;padding-top:2em;margin-bottom:2em}@media screen and (max-width:50rem){.yoast-wizard .hide-on-mobile{display:none}.yoast-wizard--box{display:block}.yoast-wizard--box>div{margin-left:0}.yoast-wizard--video-frame{position:relative;padding-bottom:56.25%;height:0}.yoast-wizard--video-frame iframe{position:absolute;top:0;left:0;width:100%;height:100%}} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yoast-components-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/yoast-components-720-rtl.min.css deleted file mode 100644 index e6e75b9f..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/yoast-components-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -.yoast-wizard--step--container:focus,a{outline:0}body{background:#f1f1f1;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;line-height:1.375}a{color:#0073aa;transition-timing-function:ease-in-out;transition-duration:50ms;transition-property:border,background,color}a:active,a:hover{color:#00a0d2}a:focus{color:#124964;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.screen-reader-text{overflow:hidden;clip:rect(1px,1px,1px,1px);position:absolute!important;width:1px;height:1px;padding:0;border:0;word-wrap:normal!important;-webkit-clip-path:inset(50%);clip-path:inset(50%)}.yoast-search-result-preview__heading{margin:0 -20px 15px;padding:8px 20px;border-bottom:1px solid #f7f7f7;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.yoast-search-result-preview__field{overflow:hidden;position:relative;width:600px;cursor:pointer}.yoast-search-result-preview__field:after,.yoast-search-result-preview__field:before{display:table;content:" "}.yoast-search-result-preview__field--focus:before,.yoast-search-result-preview__field--hover:before{position:absolute;right:-3px;width:24px;height:24px;margin-top:-3px;background-size:25px;content:"";display:block}.yoast-search-result-preview__field:after{clear:both}.yoast-search-result-preview__field--hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23646464%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.yoast-search-result-preview__field--focus:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%230066cd%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.yoast-search-result-preview__title{overflow:hidden;margin:0;color:#1a0dab;font-size:18px;font-weight:400;line-height:1.2;white-space:nowrap;text-decoration:none;text-overflow:ellipsis}.yoast-search-result-preview__url{color:#006621;font-size:14px;font-style:normal;line-height:16px}.yoast-search-result-preview__date,.yoast-search-result-preview__description{font-size:13px;line-height:1.4}.yoast-search-result-preview__date{color:grey}.yoast-search-result-preview__description{color:#545454}.yoast-button,.yoast-button__edit{padding:8px 10px;border:1px solid #ccc;border-radius:4px;color:#555;background:#f7f7f7;font-size:.8rem;cursor:pointer}.yoast-button__edit{display:block;margin-top:1em;padding-right:32px;background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555%22%20d%3D%22M491%201536l91%2D91%2D235%2D235%2D91%2091v107h128v128h107zm523%2D928q0%2D22%2D22%2D22%2D10%200%2D17%207l%2D542%20542q%2D7%207%2D7%2017%200%2022%2022%2022%2010%200%2017%2D7l542%2D542q7%2D7%207%2D17zm%2D54%2D192l416%20416%2D832%20832h%2D416v%2D416zm683%2096q0%2053%2D37%2090l%2D166%20166%2D416%2D416%20166%2D165q36%2D38%2090%2D38%2053%200%2091%2038l235%20234q37%2039%2037%2091z%22%20%2F%3E%3C%2Fsvg%3E") 8px center/16px 16px no-repeat #f7f7f7;background-size:16px}.yoast-search-result-form{overflow:hidden;background-color:#fff;font-family:Arial,sans-serif}.yoast-search-result-form__heading{margin:0 -20px 15px;padding:8px 20px;border-bottom:1px solid #f7f7f7;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.yoast-search-result-form__container--focus:before,.yoast-search-result-form__container--hover:before{right:-3px;width:24px;height:24px;margin-top:15px;background-size:25px;content:"";display:block;position:absolute}.yoast-search-result-form__container--hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23646464%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.yoast-search-result-form__container--focus:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%230066cd%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.yoast-search-result-form__label{display:block;width:100%;margin-top:1em}.yoast-search-result-form__field{box-sizing:border-box;width:100%;border:1px solid #ddd}.yoast-search-result-form__description{display:block;box-sizing:border-box;width:100%;height:70px;border:1px solid #ddd}.yoast-search-result-form__progress{display:block;box-sizing:border-box;width:100%;height:8px;margin-top:5px;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.yoast-search-result-form__progress::-webkit-progress-bar{border:1px solid #ddd;background-color:#f7f7f7}.yoast-search-result-form__close-button{margin-top:1em}.yoast-search-result-form__progress--bad{color:#dc3232}.yoast-search-result-form__progress--bad::-webkit-progress-value{background-color:#dc3232;transition:width 250ms}.yoast-search-result-form__progress--bad::-moz-progress-bar{background-color:#dc3232}.yoast-search-result-form__progress--bad--fallback{overflow:hidden;max-width:100%;background-color:#dc3232}.yoast-search-result-form__progress--ok{color:#ee7c1b}.yoast-search-result-form__progress--ok::-webkit-progress-value{background-color:#ee7c1b;transition:width 250ms}.yoast-search-result-form__progress--ok::-moz-progress-bar{background-color:#ee7c1b}.yoast-search-result-form__progress--ok--fallback{overflow:hidden;max-width:100%;background-color:#ee7c1b}.yoast-search-result-form__progress--good{color:#7ad03a}.yoast-search-result-form__progress--good::-webkit-progress-value{background-color:#7ad03a;transition:width 250ms}.yoast-search-result-form__progress--good::-moz-progress-bar{background-color:#7ad03a}.yoast-search-result-form__progress--good--fallback{overflow:hidden;max-width:100%;background-color:#7ad03a}body{margin:0;padding:0}#container{max-width:1660px;margin:0 auto}.yoast-wizard-body{box-sizing:border-box;width:80%;margin:1rem auto 4rem}@media screen and (max-width:768px){.yoast-wizard-body{width:auto;margin:0}}.yoast-wizard__logo{display:block;margin:0 auto}.yoast-wizard{box-sizing:border-box;width:100%;min-height:20px;padding:2em;background:#fff;text-align:right}@media screen and (max-width:768px){.yoast-wizard{padding:1em 1em 2em}}.yoast-wizard--header{text-align:center}.yoast-wizard--header--page-title{margin:0 0 -16px;padding:0 8px;color:#a4286a;font-size:1.25em;font-weight:400;line-height:2.5;letter-spacing:.03em}.yoast-wizard--navigation{width:100%;text-align:left}.yoast-wizard--button{margin-top:1em}.yoast-wizard--button__next{margin-right:1em}.yoast-wizard--button__next button:focus,.yoast-wizard--button__next button:hover{background-color:#6c2548!important}.yoast-wizard--button__next button:focus div,.yoast-wizard--button__next button:hover div{background-color:transparent!important}.yoast-wizard--button__previous button:focus{background:#ddd!important}.yoast-wizard--button__previous button:focus:active{background:0 0!important}.yoast-wizard--button__previous button:focus>div>span,.yoast-wizard--button__previous button:hover>div>span{color:#000!important}.yoast-wizard--step__inactive div{pointer-events:none}@media screen and (max-width:768px){.yoast-wizard--header--page-title{font-size:1.5em;line-height:1.25}.yoast-wizard--step__active{overflow:hidden;width:38px}.yoast-wizard--step__active div{display:inline-block!important;vertical-align:middle}.yoast-wizard--step__active div>span>span{display:block!important;margin-right:-7px;padding-left:99px!important}.yoast-wizard--step__inactive{display:none!important}}.yoast-wizard--step--container h1{margin:0;color:#a4286a;font-size:2.25em;font-weight:100;line-height:3.68rem;letter-spacing:.03em}@media screen and (max-width:768px){.yoast-wizard--step--container h1{font-size:2em;line-height:1.25}}.yoast-wizard--step--container h2{color:#a4286a;font-size:1.375em;font-weight:100}.yoast-wizard--emphasis,.yoast-wizard-field-description{font-weight:700}.yoast-wizard--stepper{width:100%;margin:auto}.yoast-wizard-overlay{position:absolute;z-index:10;top:0;right:0;width:100%;height:100%;opacity:.2;color:#fff;background-color:#000;text-align:center}.yoast-wizard-overlay-loader{position:relative}.yoast-wizard-container{position:relative;min-height:20px;border:1px solid #ccc;box-shadow:rgba(0,0,0,.15) 0 3px 10px,rgba(0,0,0,.2) 0 3px 10px;text-align:right}.yoast-wizard-container--no-navigation{margin-top:40px}.yoast-wizard-container--no-navigation .yoast-wizard{padding-top:3em}@media screen and (max-width:768px){.yoast-wizard-container{box-shadow:none}}.yoast-wizard-container fieldset{margin:1em 0;border:0}.yoast-wizard-text-input{padding-bottom:.5em;font-size:14px}.yoast-wizard-text-input-label{display:block;margin:.5em 0 0;font-size:14px;font-weight:700;cursor:pointer}.yoast-wizard-text-input [type=text]{box-sizing:border-box;width:100%;max-width:450px}.yoast-video-container-max-width,.yoast-wizard-content-container{max-width:560px}.yoast-wizard input{margin:.5em 0;padding:5px;font-size:14px;line-height:140%}.yoast-wizard label{cursor:pointer}.yoast-wizard input[type=radio]{margin:.3em 0 .3em .7em;vertical-align:middle}.yoast-wizard-input__explanation{margin-top:0;color:#555;font-style:italic}.yoast-wizard-input-radio{font-size:14px}.yoast-wizard-input-radio-option label{padding-top:2px}.yoast-wizard-input-radio-separator{padding:0}.yoast-wizard-input-radio-separator input{position:absolute;right:-9999em;width:1px;height:1px}.yoast-wizard-input-radio-separator input+label{float:right;width:30px!important;margin:0 0 5px 5px!important;padding:6px 3px;border:1px solid #ccc;font-family:Arial,Helvetica,sans-serif!important;font-size:18px!important;line-height:24px;text-align:center;cursor:pointer}.yoast-wizard-input-radio-separator input:checked+label{border:1px solid #a4286a;background-color:#fff;box-shadow:inset 0 0 0 2px #a4286a}.yoast-wizard-input-radio-separator input:checked+label,.yoast-wizard-input-radio-separator input:focus+label{border-radius:10px 10px 10px 0}.yoast-video-container{overflow:hidden;position:relative;height:0;padding-bottom:56.25%}.yoast-video-container iframe{position:absolute;top:0;right:0;width:100%;height:100%}.yoast-wizard-notice__error{margin-bottom:15px;padding:12px;border-right:4px solid #dc3232;background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.1)}.yoast-wizard-content-container.yoast-wizard-content-container__is-full-width{max-width:none}@keyframes heartbeat{0%{opacity:.4;transform:scale(.7)}80%{opacity:1}100%{opacity:1;transform:scale(.95)}}.yoast-loader{animation:heartbeat 1.15s infinite;animation-timing-function:cubic-bezier(.96,.02,.63,.86);animation-direction:alternate}#wizard{overflow:hidden}.yoast-wizard{padding-top:2em}.yoast-wizard input[type=text]{min-width:250px}.yoast-wizard #gsc_authorization_code,.yoast-wizard input[type=text]+div{margin-left:1em}.yoast-wizard-body{max-width:80em}.yoast-wizard-return-link-container{text-align:center}.wp-core-ui .yoast-wizard-return-link.button{display:-ms-inline-flexbox;display:inline-flex;height:36px;margin:0 0 1em;padding:0 10px 0 16px;border-color:transparent;border-radius:2px;color:#646d78;background:#fff;box-shadow:rgba(0,0,0,.12) 0 1px 6px,rgba(0,0,0,.12) 0 1px 4px;text-align:center;text-transform:uppercase;transition:all 450ms cubic-bezier(.23,1,.32,1) 0s;align-items:center;-ms-flex-align:center}.wp-core-ui .yoast-wizard-return-link.button:hover{border-color:transparent;background:#ebebeb}.wp-core-ui .yoast-wizard-return-link.button:focus{outline:0;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.wp-core-ui .yoast-wizard-return-link.button:active{background:#ebebeb;box-shadow:rgba(0,0,0,.16) 0 3px 10px,rgba(0,0,0,.23) 0 3px 10px;-ms-transform:none;transform:none}.wp-core-ui .yoast-wizard-return-link.button .dashicons{margin-left:8px}.yoast-wizard-mailchimp-message-error{color:#dc3232}.yoast-wizard-mailchimp-message-success{color:#008a00}.yoast-wizard-input{padding-bottom:.5em}.yoast-wizard-input__select{margin:1em 0;font-size:14px}.yoast-wizard--columns>div,.yoast-wizard-image-upload-container-buttons__remove{margin-right:1em}.yoast-wizard-image-upload-container__image{max-width:151px}.yoast-wizard-image-upload-container-buttons{margin-top:1em}.yoast-wizard-image-upload-container-description{display:block}.yoast-wizard--navigation{margin-top:2em;padding-top:1em;border-top:1px solid #a4286a}.yoast-wizard--rows{display:-ms-flexbox;display:flex;flex-direction:column;-ms-flex-direction:column}.yoast-wizard--columns{display:-ms-flexbox;display:flex}.yoast-wizard--columns .yoast-wizard-text-input-field{max-width:100%}.yoast-wizard--columns__even>div{flex-basis:50%;-ms-flex-preferred-size:50%}.yoast-wizard--columns>div:first-child{margin-right:0}.yoast-wizard--columns .yoast-wizard--heading{margin:0;color:#a4286a}.yoast-wizard--columns>.yoast-wizard--column__push_right{-ms-flex-order:2;order:2}.yoast-wizard--columns>.yoast-wizard--column__push_left{margin-left:1em;margin-right:0;-ms-flex-order:1;order:1}.yoast-wizard--choice>.yoast-wizard--rows{height:100%}.yoast-wizard--choice div{align-self:flex-start;-ms-flex-item-align:start}.yoast-wizard--choice p{height:100%;margin-top:.3em}.yoast-wizard--box{padding:1em;border:1px solid #a4286a}.yoast-wizard--box>div:first-child{flex-basis:100px;-ms-flex-preferred-size:100px}.yoast-wizard-newsletter--header svg{position:relative;top:4px;margin-left:6px;fill:#a4286a}.yoast-wizard-newsletter--decoration{width:100%;max-width:490px}.yoast-wizard-newsletter--decoration img{width:490px;max-width:100%;margin-top:-3em}.yoast-wizard--video-frame iframe{border:none}@media screen and (max-width:80em){.yoast-wizard--columns{display:block}.yoast-wizard--columns>div{margin-right:0}.yoast-wizard--columns>.yoast-wizard--column__push_left{margin-top:2em;margin-left:0}.yoast-wizard--box{display:-ms-flexbox;display:flex;margin-top:1em}.yoast-wizard--box:first-child{margin-top:0}.yoast-wizard--box>div{margin-right:1em}.yoast-wizard .hide-on-tablet{display:none}}.yoast-wizard--suggestion{margin-bottom:2em;padding-top:2em;border-top:1px solid #a4286a}.yoast-wizard--suggestion:first-child{padding-top:0;border-top:none}@media screen and (max-width:50rem){.yoast-wizard .hide-on-mobile{display:none}.yoast-wizard--box{display:block}.yoast-wizard--box>div{margin-right:0}.yoast-wizard--video-frame{position:relative;height:0;padding-bottom:56.25%}.yoast-wizard--video-frame iframe{position:absolute;top:0;right:0;width:100%;height:100%}}.ie9 .yoast-wizard--stepper{display:none} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yoast-components-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/yoast-components-720.min.css deleted file mode 100644 index 6f7ce308..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/yoast-components-720.min.css +++ /dev/null @@ -1 +0,0 @@ -.yoast-wizard--step--container:focus,a{outline:0}body{background:#f1f1f1;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;line-height:1.375}a{color:#0073aa;transition-timing-function:ease-in-out;transition-duration:50ms;transition-property:border,background,color}a:active,a:hover{color:#00a0d2}a:focus{color:#124964;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.screen-reader-text{overflow:hidden;clip:rect(1px,1px,1px,1px);position:absolute!important;width:1px;height:1px;padding:0;border:0;word-wrap:normal!important;-webkit-clip-path:inset(50%);clip-path:inset(50%)}.yoast-search-result-preview__heading{margin:0 -20px 15px;padding:8px 20px;border-bottom:1px solid #f7f7f7;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.yoast-search-result-preview__field{overflow:hidden;position:relative;width:600px;cursor:pointer}.yoast-search-result-preview__field:after,.yoast-search-result-preview__field:before{display:table;content:" "}.yoast-search-result-preview__field--focus:before,.yoast-search-result-preview__field--hover:before{position:absolute;left:-3px;width:24px;height:24px;margin-top:-3px;background-size:25px;content:"";display:block}.yoast-search-result-preview__field:after{clear:both}.yoast-search-result-preview__field--hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23646464%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.yoast-search-result-preview__field--focus:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%230066cd%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.yoast-search-result-preview__title{overflow:hidden;margin:0;color:#1a0dab;font-size:18px;font-weight:400;line-height:1.2;white-space:nowrap;text-decoration:none;text-overflow:ellipsis}.yoast-search-result-preview__url{color:#006621;font-size:14px;font-style:normal;line-height:16px}.yoast-search-result-preview__date,.yoast-search-result-preview__description{font-size:13px;line-height:1.4}.yoast-search-result-preview__date{color:grey}.yoast-search-result-preview__description{color:#545454}.yoast-button,.yoast-button__edit{padding:8px 10px;border:1px solid #ccc;border-radius:4px;color:#555;background:#f7f7f7;font-size:.8rem;cursor:pointer}.yoast-button__edit{display:block;margin-top:1em;padding-left:32px;background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23555%22%20d%3D%22M491%201536l91%2D91%2D235%2D235%2D91%2091v107h128v128h107zm523%2D928q0%2D22%2D22%2D22%2D10%200%2D17%207l%2D542%20542q%2D7%207%2D7%2017%200%2022%2022%2022%2010%200%2017%2D7l542%2D542q7%2D7%207%2D17zm%2D54%2D192l416%20416%2D832%20832h%2D416v%2D416zm683%2096q0%2053%2D37%2090l%2D166%20166%2D416%2D416%20166%2D165q36%2D38%2090%2D38%2053%200%2091%2038l235%20234q37%2039%2037%2091z%22%20%2F%3E%3C%2Fsvg%3E") 8px center/16px 16px no-repeat #f7f7f7;background-size:16px}.yoast-search-result-form{overflow:hidden;background-color:#fff;font-family:Arial,sans-serif}.yoast-search-result-form__heading{margin:0 -20px 15px;padding:8px 20px;border-bottom:1px solid #f7f7f7;color:#555;font-family:"Open Sans",sans-serif;font-size:.9rem;font-weight:300}.yoast-search-result-form__container--focus:before,.yoast-search-result-form__container--hover:before{left:-3px;width:24px;height:24px;margin-top:15px;background-size:25px;content:"";display:block;position:absolute}.yoast-search-result-form__container--hover:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23646464%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.yoast-search-result-form__container--focus:before{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%230066cd%22%20d%3D%22M1152%20896q0%2026%2D19%2045l%2D448%20448q%2D19%2019%2D45%2019t%2D45%2D19%2D19%2D45v%2D896q0%2D26%2019%2D45t45%2D19%2045%2019l448%20448q19%2019%2019%2045z%22%20%2F%3E%3C%2Fsvg%3E")}.yoast-search-result-form__label{display:block;width:100%;margin-top:1em}.yoast-search-result-form__field{box-sizing:border-box;width:100%;border:1px solid #ddd}.yoast-search-result-form__description{display:block;box-sizing:border-box;width:100%;height:70px;border:1px solid #ddd}.yoast-search-result-form__progress{display:block;box-sizing:border-box;width:100%;height:8px;margin-top:5px;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.yoast-search-result-form__progress::-webkit-progress-bar{border:1px solid #ddd;background-color:#f7f7f7}.yoast-search-result-form__close-button{margin-top:1em}.yoast-search-result-form__progress--bad{color:#dc3232}.yoast-search-result-form__progress--bad::-webkit-progress-value{background-color:#dc3232;transition:width 250ms}.yoast-search-result-form__progress--bad::-moz-progress-bar{background-color:#dc3232}.yoast-search-result-form__progress--bad--fallback{overflow:hidden;max-width:100%;background-color:#dc3232}.yoast-search-result-form__progress--ok{color:#ee7c1b}.yoast-search-result-form__progress--ok::-webkit-progress-value{background-color:#ee7c1b;transition:width 250ms}.yoast-search-result-form__progress--ok::-moz-progress-bar{background-color:#ee7c1b}.yoast-search-result-form__progress--ok--fallback{overflow:hidden;max-width:100%;background-color:#ee7c1b}.yoast-search-result-form__progress--good{color:#7ad03a}.yoast-search-result-form__progress--good::-webkit-progress-value{background-color:#7ad03a;transition:width 250ms}.yoast-search-result-form__progress--good::-moz-progress-bar{background-color:#7ad03a}.yoast-search-result-form__progress--good--fallback{overflow:hidden;max-width:100%;background-color:#7ad03a}body{margin:0;padding:0}#container{max-width:1660px;margin:0 auto}.yoast-wizard-body{box-sizing:border-box;width:80%;margin:1rem auto 4rem}@media screen and (max-width:768px){.yoast-wizard-body{width:auto;margin:0}}.yoast-wizard__logo{display:block;margin:0 auto}.yoast-wizard{box-sizing:border-box;width:100%;min-height:20px;padding:2em;background:#fff;text-align:left}@media screen and (max-width:768px){.yoast-wizard{padding:1em 1em 2em}}.yoast-wizard--header{text-align:center}.yoast-wizard--header--page-title{margin:0 0 -16px;padding:0 8px;color:#a4286a;font-size:1.25em;font-weight:400;line-height:2.5;letter-spacing:.03em}.yoast-wizard--navigation{width:100%;text-align:right}.yoast-wizard--button{margin-top:1em}.yoast-wizard--button__next{margin-left:1em}.yoast-wizard--button__next button:focus,.yoast-wizard--button__next button:hover{background-color:#6c2548!important}.yoast-wizard--button__next button:focus div,.yoast-wizard--button__next button:hover div{background-color:transparent!important}.yoast-wizard--button__previous button:focus{background:#ddd!important}.yoast-wizard--button__previous button:focus:active{background:0 0!important}.yoast-wizard--button__previous button:focus>div>span,.yoast-wizard--button__previous button:hover>div>span{color:#000!important}.yoast-wizard--step__inactive div{pointer-events:none}@media screen and (max-width:768px){.yoast-wizard--header--page-title{font-size:1.5em;line-height:1.25}.yoast-wizard--step__active{overflow:hidden;width:38px}.yoast-wizard--step__active div{display:inline-block!important;vertical-align:middle}.yoast-wizard--step__active div>span>span{display:block!important;margin-left:-7px;padding-right:99px!important}.yoast-wizard--step__inactive{display:none!important}}.yoast-wizard--step--container h1{margin:0;color:#a4286a;font-size:2.25em;font-weight:100;line-height:3.68rem;letter-spacing:.03em}@media screen and (max-width:768px){.yoast-wizard--step--container h1{font-size:2em;line-height:1.25}}.yoast-wizard--step--container h2{color:#a4286a;font-size:1.375em;font-weight:100}.yoast-wizard--emphasis,.yoast-wizard-field-description{font-weight:700}.yoast-wizard--stepper{width:100%;margin:auto}.yoast-wizard-overlay{position:absolute;z-index:10;top:0;left:0;width:100%;height:100%;opacity:.2;color:#fff;background-color:#000;text-align:center}.yoast-wizard-overlay-loader{position:relative}.yoast-wizard-container{position:relative;min-height:20px;border:1px solid #ccc;box-shadow:rgba(0,0,0,.15) 0 3px 10px,rgba(0,0,0,.2) 0 3px 10px;text-align:left}.yoast-wizard-container--no-navigation{margin-top:40px}.yoast-wizard-container--no-navigation .yoast-wizard{padding-top:3em}@media screen and (max-width:768px){.yoast-wizard-container{box-shadow:none}}.yoast-wizard-container fieldset{margin:1em 0;border:0}.yoast-wizard-text-input{padding-bottom:.5em;font-size:14px}.yoast-wizard-text-input-label{display:block;margin:.5em 0 0;font-size:14px;font-weight:700;cursor:pointer}.yoast-wizard-text-input [type=text]{box-sizing:border-box;width:100%;max-width:450px}.yoast-video-container-max-width,.yoast-wizard-content-container{max-width:560px}.yoast-wizard input{margin:.5em 0;padding:5px;font-size:14px;line-height:140%}.yoast-wizard label{cursor:pointer}.yoast-wizard input[type=radio]{margin:.3em .7em .3em 0;vertical-align:middle}.yoast-wizard-input__explanation{margin-top:0;color:#555;font-style:italic}.yoast-wizard-input-radio{font-size:14px}.yoast-wizard-input-radio-option label{padding-top:2px}.yoast-wizard-input-radio-separator{padding:0}.yoast-wizard-input-radio-separator input{position:absolute;left:-9999em;width:1px;height:1px}.yoast-wizard-input-radio-separator input+label{float:left;width:30px!important;margin:0 5px 5px 0!important;padding:6px 3px;border:1px solid #ccc;font-family:Arial,Helvetica,sans-serif!important;font-size:18px!important;line-height:24px;text-align:center;cursor:pointer}.yoast-wizard-input-radio-separator input:checked+label{border:1px solid #a4286a;background-color:#fff;box-shadow:inset 0 0 0 2px #a4286a}.yoast-wizard-input-radio-separator input:checked+label,.yoast-wizard-input-radio-separator input:focus+label{border-radius:10px 10px 0}.yoast-video-container{overflow:hidden;position:relative;height:0;padding-bottom:56.25%}.yoast-video-container iframe{position:absolute;top:0;left:0;width:100%;height:100%}.yoast-wizard-notice__error{margin-bottom:15px;padding:12px;border-left:4px solid #dc3232;background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.1)}.yoast-wizard-content-container.yoast-wizard-content-container__is-full-width{max-width:none}@keyframes heartbeat{0%{opacity:.4;transform:scale(.7)}80%{opacity:1}100%{opacity:1;transform:scale(.95)}}.yoast-loader{animation:heartbeat 1.15s infinite;animation-timing-function:cubic-bezier(.96,.02,.63,.86);animation-direction:alternate}#wizard{overflow:hidden}.yoast-wizard{padding-top:2em}.yoast-wizard input[type=text]{min-width:250px}.yoast-wizard #gsc_authorization_code,.yoast-wizard input[type=text]+div{margin-right:1em}.yoast-wizard-body{max-width:80em}.yoast-wizard-return-link-container{text-align:center}.wp-core-ui .yoast-wizard-return-link.button{display:-ms-inline-flexbox;display:inline-flex;height:36px;margin:0 0 1em;padding:0 16px 0 10px;border-color:transparent;border-radius:2px;color:#646d78;background:#fff;box-shadow:rgba(0,0,0,.12) 0 1px 6px,rgba(0,0,0,.12) 0 1px 4px;text-align:center;text-transform:uppercase;transition:all 450ms cubic-bezier(.23,1,.32,1) 0s;align-items:center;-ms-flex-align:center}.wp-core-ui .yoast-wizard-return-link.button:hover{border-color:transparent;background:#ebebeb}.wp-core-ui .yoast-wizard-return-link.button:focus{outline:0;box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8)}.wp-core-ui .yoast-wizard-return-link.button:active{background:#ebebeb;box-shadow:rgba(0,0,0,.16) 0 3px 10px,rgba(0,0,0,.23) 0 3px 10px;-ms-transform:none;transform:none}.wp-core-ui .yoast-wizard-return-link.button .dashicons{margin-right:8px}.yoast-wizard-mailchimp-message-error{color:#dc3232}.yoast-wizard-mailchimp-message-success{color:#008a00}.yoast-wizard-input{padding-bottom:.5em}.yoast-wizard-input__select{margin:1em 0;font-size:14px}.yoast-wizard--columns>div,.yoast-wizard-image-upload-container-buttons__remove{margin-left:1em}.yoast-wizard-image-upload-container__image{max-width:151px}.yoast-wizard-image-upload-container-buttons{margin-top:1em}.yoast-wizard-image-upload-container-description{display:block}.yoast-wizard--navigation{margin-top:2em;padding-top:1em;border-top:1px solid #a4286a}.yoast-wizard--rows{display:-ms-flexbox;display:flex;flex-direction:column;-ms-flex-direction:column}.yoast-wizard--columns{display:-ms-flexbox;display:flex}.yoast-wizard--columns .yoast-wizard-text-input-field{max-width:100%}.yoast-wizard--columns__even>div{flex-basis:50%;-ms-flex-preferred-size:50%}.yoast-wizard--columns>div:first-child{margin-left:0}.yoast-wizard--columns .yoast-wizard--heading{margin:0;color:#a4286a}.yoast-wizard--columns>.yoast-wizard--column__push_right{-ms-flex-order:2;order:2}.yoast-wizard--columns>.yoast-wizard--column__push_left{margin-right:1em;margin-left:0;-ms-flex-order:1;order:1}.yoast-wizard--choice>.yoast-wizard--rows{height:100%}.yoast-wizard--choice div{align-self:flex-start;-ms-flex-item-align:start}.yoast-wizard--choice p{height:100%;margin-top:.3em}.yoast-wizard--box{padding:1em;border:1px solid #a4286a}.yoast-wizard--box>div:first-child{flex-basis:100px;-ms-flex-preferred-size:100px}.yoast-wizard-newsletter--header svg{position:relative;top:4px;margin-right:6px;fill:#a4286a}.yoast-wizard-newsletter--decoration{width:100%;max-width:490px}.yoast-wizard-newsletter--decoration img{width:490px;max-width:100%;margin-top:-3em}.yoast-wizard--video-frame iframe{border:none}@media screen and (max-width:80em){.yoast-wizard--columns{display:block}.yoast-wizard--columns>div{margin-left:0}.yoast-wizard--columns>.yoast-wizard--column__push_left{margin-top:2em;margin-right:0}.yoast-wizard--box{display:-ms-flexbox;display:flex;margin-top:1em}.yoast-wizard--box:first-child{margin-top:0}.yoast-wizard--box>div{margin-left:1em}.yoast-wizard .hide-on-tablet{display:none}}.yoast-wizard--suggestion{margin-bottom:2em;padding-top:2em;border-top:1px solid #a4286a}.yoast-wizard--suggestion:first-child{padding-top:0;border-top:none}@media screen and (max-width:50rem){.yoast-wizard .hide-on-mobile{display:none}.yoast-wizard--box{display:block}.yoast-wizard--box>div{margin-left:0}.yoast-wizard--video-frame{position:relative;height:0;padding-bottom:56.25%}.yoast-wizard--video-frame iframe{position:absolute;top:0;left:0;width:100%;height:100%}}.ie9 .yoast-wizard--stepper{display:none} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-1720-rtl.css new file mode 100644 index 00000000..9dfb16d5 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-1720-rtl.css @@ -0,0 +1 @@ +@charset "UTF-8";.yoast-modal__screen-overlay{position:fixed;top:0;left:0;bottom:0;right:0;background-color:rgba(164,40,106,.6);z-index:100000;animation:edit-post__fade-in-animation .2s ease-out 0s;animation-fill-mode:forwards}.yoast-modal{background:#fff;display:flex;flex-direction:column;overflow:hidden;position:fixed;height:calc(100% - 96px);top:48px;bottom:48px;right:calc(50% - 440px);max-width:880px;width:100%}.yoast-gutenberg-modal .yoast-icon{background-color:var(--yoast-color-primary);mask-image:var(--yoast-svg-icon-yoast);-webkit-mask-image:var(--yoast-svg-icon-yoast);mask-size:100% 100%;-webkit-mask-size:100% 100%;display:inline-block;width:20px;height:20px;margin-left:8px}.yoast-tabs .yoast-modal__content{display:grid;grid-template-areas:"heading heading" "menu content" "menu footer";grid-template-rows:72px 1fr 88px;grid-template-columns:280px 1fr}.yoast-modal__heading{display:flex;align-items:center;box-sizing:border-box;min-height:72px;border-bottom:var(--yoast-border-default);padding:0 24px;grid-area:heading;background:var(--yoast-color-white)}.yoast-modal__heading .yoast-close{position:absolute;left:16px}.yoast-gutenberg-modal .components-modal__header-heading,.yoast-modal__heading h1{font-size:20px;font-weight:400;color:var(--yoast-color-primary);line-height:1.2;margin:0}.yoast-gutenberg-modal .components-modal__icon-container{display:inline-flex}.yoast-gutenberg-modal .components-modal__icon-container svg,.yoast-modal__heading-icon{fill:var(--yoast-color-primary);margin-left:16px;width:19px;height:20px;flex-shrink:0}.yoast-modal__menu{grid-area:menu;border-left:var(--yoast-border-default);overflow-y:auto}.yoast-modal__menu ul{padding:0;margin:0;list-style:none}.yoast-modal__menu li{padding:12px 16px 11px;border-bottom:var(--yoast-border-default);font-size:16px;cursor:pointer;text-decoration:none;color:var(--yoast-color-default);display:block}.yoast-modal__menu li:hover{background-color:#edd4e1}.yoast-modal__menu li.yoast-tabs__tab--selected{background-color:var(--yoast-color-primary);border-bottom:var(--yoast-border-default);color:#fff}.yoast-modal__content,.yoast-modal__section{grid-area:content;overflow-y:auto;flex-grow:1;position:relative;display:flex;flex-direction:column}.yoast-modal__section *{max-width:600px}.yoast-modal__section-header{position:sticky;top:0;background:var(--yoast-color-white);padding:24px 24px 0;z-index:10}.yoast-modal__section .yoast-h2{border-bottom:var(--yoast-border-default);padding-bottom:24px}.yoast-modal__footer{grid-area:footer;padding:0;border-top:var(--yoast-border-default);display:flex;align-self:flex-end;align-items:center;justify-content:flex-end;position:sticky;bottom:0;background:var(--yoast-color-white);margin:0 24px;z-index:10;box-sizing:border-box;min-height:88px;width:calc(100% - 48px)}.yoast-modal__settings-saved{position:relative;margin-left:16px;display:inline-flex;align-items:center}.yoast-modal__settings-saved:before{content:"";background:var(--yoast-checkmark--green) no-repeat 50%;height:13px;width:14px;display:inline-block;margin-left:8px}.yoast-modal__footer .yoast-button{display:block}.yoast-modal__section-content{padding:24px;flex-grow:1}@media screen and (max-width:880px){.yoast-modal{top:0;bottom:0;right:0;left:0;height:auto}}@media screen and (max-width:782px){.yoast-modal{overflow-y:initial}.yoast-modal.yoast-modal-collapsible{padding-bottom:72px}.yoast-tabs .yoast-modal__content{grid-template-rows:48px 1fr 72px}.yoast-modal__heading{padding:0 16px;position:fixed;top:0;width:100%;min-height:48px;z-index:11}.yoast-modal__heading h1{font-size:var(--yoast-font-size-default)}.yoast-close svg{width:10px}.yoast-modal__heading-icon{height:15px;margin-left:8px}.yoast .yoast-close{left:3px}.yoast-modal__heading .yoast-h2{font-size:var(--yoast-font-size-default)}.yoast-modal__section{overflow:initial;flex-grow:0}.yoast-modal__section-content{padding:24px 0;margin:0 16px}.yoast-modal__section:first-of-type{margin-top:48px}.yoast-modal__section:last-of-type{margin-bottom:72px}.yoast-modal__section-header{top:48px;position:sticky;padding:0;margin:0}.yoast-modal__section-open .yoast-modal__section-header{padding-right:0;padding-left:0;margin-right:16px;margin-left:16px}.yoast-modal__section-open{border-bottom:var(--yoast-border-default)}.yoast-modal__footer{width:100%;min-height:72px;margin:0;padding:0 16px;position:fixed;z-index:11}.yoast-modal-collapsible .yoast-modal__footer{min-height:72px}.yoast-modal-collapsible .yoast-modal__section-content{padding:24px 16px;border-bottom:var(--yoast-border-default);margin:0}.yoast-collapsible__hidden{display:none}.yoast-collapsible__trigger{padding:16px;border:none;border-bottom:var(--yoast-border-default);cursor:pointer;justify-content:space-between;font-size:var(--yoast-font-size-default);width:100%;text-align:right;background:#fff;color:var(--yoast-color-primary)}.yoast-collapsible__trigger[aria-expanded=true] .yoast-collapsible__icon{transform:rotate(-180deg)}.yoast-collapsible__trigger[aria-expanded=true]{padding:16px 0;width:calc(100% - 32px);margin:0 16px}.yoast-collapsible__icon{background-color:var(--yoast-color-white);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='%23404040'%3E%3Cpath d='M1.4 0L6 4.6 10.6 0 12 1.4 6 7.5 0 1.4z'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:10px auto;width:19px;height:19px;border:none;display:block;float:left}.yoast-collapsible-block{width:100%;margin-top:48px}.yoast-collapsible-block+.yoast-collapsible-block{margin-top:0}}.yoast-post-settings-modal{width:880px;height:100%;max-width:calc(100% - 96px);max-height:calc(100% - 96px);overflow:hidden}.yoast-modal-content{padding:16px}@media (min-width:782px){.yoast-modal-content--columns{display:grid;grid-template-columns:1fr 1fr;grid-gap:24px}}.yoast-post-settings-modal__button-container{padding:16px;display:flex;flex-direction:column;border-bottom:1px solid rgba(0,0,0,.2)}.yoast-post-settings-modal .components-modal__content{padding:0;display:flex;flex-direction:column}.yoast-post-settings-modal .components-modal__header{margin:0;flex-shrink:0;border-bottom:var(--yoast-border-default)}.yoast-post-settings-modal .yoast-notice-container{z-index:1;position:sticky;bottom:0;right:0;width:100%;margin-top:auto}.yoast-post-settings-modal .yoast-notice-container>hr{margin-top:-1px;margin-bottom:0}.yoast-post-settings-modal .yoast-content-container{overflow-y:auto;flex-grow:1}.yoast-post-settings-modal .yoast-button-container{display:flex;flex-direction:row;justify-content:flex-end;padding:24px;margin:0}.yoast-post-settings-modal .yoast-button-container p{color:var(--yoast-color-label-help);padding-left:24px;align-self:center}.yoast-post-settings-modal .yoast-button-container button{flex-shrink:0;max-height:45px;align-self:center}@media only screen and (max-width:600px){.yoast-post-settings-modal{max-height:100%;max-width:100%}.yoast-post-settings-modal .yoast-button-container{padding:16px;justify-content:space-between}.yoast-post-settings-modal .yoast-button-container p{padding-left:0}}.yoast-related-keyphrases-modal{max-width:712px}#yoast-get-related-keyphrases-metabox,#yoast-get-related-keyphrases-sidebar{margin-top:8px}.yoast-gutenberg-modal .yoast-related-keyphrases-modal__content{min-height:66vh;position:relative}#yoast-semrush-country-selector{position:relative;border:none}.yoast-related-keyphrases-modal__chart{display:block}:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")}.yoast-list--usp{padding:0;margin-bottom:1em;font-family:Arial,sans-serif}.yoast-list--usp li{list-style:none!important;position:relative;padding-right:1.2533333333rem}.yoast-list--usp li:before{content:"\f00c\0020";position:absolute;right:0;top:0;font-family:FontAwesome,Open Sans,Arial,sans-serif;color:#77b227}.yoast .h1,.yoast .h2,.yoast .h3,.yoast .h4,.yoast .h5,.yoast .h6,.yoast h1,.yoast h2,.yoast h3,.yoast h4,.yoast h5,.yoast h6{font-family:Arial,sans-serif;font-weight:300;margin-top:0;display:block}.yoast .h1,.yoast h1{font-size:2.5em;line-height:3.68rem;margin-bottom:1.35rem;letter-spacing:normal}@media only screen and (min-width:30rem){.yoast .h1,.yoast h1{font-size:2.75em}}.yoast .h2,.yoast h2{font-size:1.88em;line-height:2.5rem;margin-bottom:1.2rem}.yoast .h2.tight,.yoast h2.tight{margin-bottom:.6rem}.yoast .h3,.yoast h3{font-size:1.25em;line-height:1.88rem;margin-bottom:.8rem}.yoast .h3.tight,.yoast h3.tight{margin-bottom:.4rem}@media only screen and (min-width:30rem){.yoast .h3,.yoast h3{font-size:1.375em}}@media only screen and (min-width:50rem){.yoast .h3,.yoast h3{font-size:1.5em}}.yoast .h4,.yoast .h5,.yoast .h6,.yoast h4,.yoast h5,.yoast h6{font-size:1.13em;font-weight:400;line-height:1.88rem;margin-bottom:.2rem}.yoast-button{font-family:Arial,sans-serif;position:relative;display:inline-block;width:100%;padding:.345em 1em .345em 1.5em;font-size:1.1em;background-color:initial;background-color:#dc5c04;color:#dc5c04;border:0;text-decoration:none;cursor:pointer}@media only screen and (min-width:30rem){.yoast-button{margin-left:1.36rem;width:auto;max-height:2.86rem}.yoast-button:after{content:"";position:absolute;top:0;left:-1.36rem;height:0;width:0;border-left:0;border-right:1.43rem solid #dc5c04;border-top:1.43rem solid transparent;border-bottom:1.44rem solid transparent}.yoast-button.left{margin-left:0;margin-right:1.36rem}.yoast-button.left:after{content:none}.yoast-button.left:before{content:"";position:absolute;top:0;right:-1.36rem;height:0;width:0;border-right:0;border-left:1.43rem solid #dc5c04;border-top:1.43rem solid transparent;border-bottom:1.44rem solid transparent}}.yoast-button.alignleft{margin:1rem 0 0 2.5rem!important}.yoast-button .arrow{display:none}.yoast-button+.yoast-button{margin-top:1em;margin-right:1.88rem}.yoast-button--full{width:100%}.yoast-button--full:after{content:none}.yoast-button.default{color:#fff;background-color:#dc5c04}.yoast-button.default:after{border-right-color:#dc5c04}.yoast-button.default:before{border-left-color:#dc5c04}.yoast-button:hover,.yoast-button a:focus{background-color:#f58223;color:#fff;text-decoration:underline}.yoast-button:hover:after,.yoast-button a:focus:after{border-right-color:#f58223}.yoast-button:hover:before,.yoast-button a:focus:before{border-left-color:#f58223}.yoast-button.academy{color:#fff;background-color:#5d237a}.yoast-button.academy:after{border-right-color:#5d237a}.yoast-button.academy:before{border-left-color:#5d237a}@media only screen and (max-width:20rem){.yoast-button.academy{background-color:#5d237a}}.yoast-button.academy--secondary{color:#fff;background-color:#a4286a}.yoast-button.academy--secondary:after{border-right-color:#a4286a}.yoast-button.academy--secondary:before{border-left-color:#a4286a}@media only screen and (max-width:20rem){.yoast-button.academy--secondary{background-color:#a4286a}}.yoast-button.software{color:#fff;background-color:#0075b3}.yoast-button.software:after{border-right-color:#0075b3}.yoast-button.software:before{border-left-color:#0075b3}.yoast-button.review{color:#fff;background-color:#009288}.yoast-button.review:after{border-right-color:#009288}.yoast-button.review:before{border-left-color:#009288}.yoast-button.about{color:#fff;background-color:#d93f69}.yoast-button.about:after{border-right-color:#d93f69}.yoast-button.about:before{border-left-color:#d93f69}.yoast_academy .yoast-button{color:#fff;background-color:#d93f69}.yoast_academy .yoast-button:after{border-right-color:#d93f69}.yoast_academy .yoast-button:before{border-left-color:#d93f69}.yoast_academy .yoast-button:hover,.yoast_academy .yoast-button a:focus{background-color:#d42a59;color:#fff;text-decoration:underline}.yoast_academy .yoast-button:hover:after,.yoast_academy .yoast-button a:focus:after{border-right-color:#d42a59}.yoast_academy .yoast-button:hover:before,.yoast_academy .yoast-button a:focus:before{border-left-color:#d42a59}.yoast_academy .yoast-button.dimmed,body .yoast-button.dimmed{color:#646464;background-color:#dcdcdc}.yoast_academy .yoast-button.dimmed:after,body .yoast-button.dimmed:after{border-right-color:#dcdcdc}.yoast_academy .yoast-button.dimmed:before,body .yoast-button.dimmed:before{border-left-color:#dcdcdc}.yoast_academy .yoast-button.dimmed:hover,.yoast_academy .yoast-button.dimmed a:focus,body .yoast-button.dimmed:hover,body .yoast-button.dimmed a:focus{background-color:#cdcdcd;color:#646464;text-decoration:underline}.yoast_academy .yoast-button.dimmed:hover:after,.yoast_academy .yoast-button.dimmed a:focus:after,body .yoast-button.dimmed:hover:after,body .yoast-button.dimmed a:focus:after{border-right-color:#cdcdcd}.yoast_academy .yoast-button.dimmed:hover:before,.yoast_academy .yoast-button.dimmed a:focus:before,body .yoast-button.dimmed:hover:before,body .yoast-button.dimmed a:focus:before{border-left-color:#cdcdcd}.yoast-button--noarrow:after{content:none}.yoast-button--naked{border:none;background-color:initial;padding:0}.yoast-button--naked:after{content:none}.yoast-button i.fa{font-size:140%;margin:4px 0 0 10px}.yoast-promoblock{margin-bottom:1.88rem;box-shadow:0 1px 6px 0 rgba(0,0,0,.3);border:1px solid #dcdcdc;padding:16px}.yoast-promoblock p{color:#000}.yoast-promoblock p:last-of-type{margin-bottom:0}.yoast-promoblock i.blockicon{position:absolute;left:10px;bottom:10px;padding:0 .5em 0 0;font-size:2.25em}.yoast-promoblock a img{border:1px solid #dcdcdc}.yoast-promoblock p a{font-weight:600!important;text-decoration:underline}.yoast-promoblock form a{font-weight:400!important;text-decoration:none}.yoast-promoblock .h4,.yoast-promoblock h4{margin-bottom:.7rem}.yoast-promoblock.link{border-color:#dc5c04}.yoast-promoblock.link a,.yoast-promoblock.link a:hover{color:#dc5c04}.yoast-promoblock--white{border-color:#fff!important}.product .yoast-promoblock{overflow:hidden}.yoast-promoblock--hometitle{max-width:16em;height:11em;margin:1rem auto 2rem;display:flex;font-size:16px;font-size:1rem;line-height:1;background-color:rgba(217,63,105,.25);border-color:#fff!important}@media only screen and (max-width:30rem){.yoast-promoblock--hometitle:after{content:none!important}}.yoast-promoblock--imageholder{padding:0;margin-bottom:0}.yoast-promoblock--imageholdersmall{position:absolute}.yoast-promoblock--imageholdersmall:first-child{right:4rem}.yoast-promoblock--imageholdersmall:last-child{top:4rem}@media only screen and (max-width:50rem){.yoast-promoblock h2{margin-bottom:0}}a.promoblock{text-decoration:none;color:#000}a.promoblock:hover{text-decoration:none}.promoblockimage__holder{width:240px;height:295px;position:relative}.yoast{font-family:Open Sans,Arial,sans-serif;font-size:1rem;line-height:1.88;letter-spacing:.01em;color:#000}.yoast *,.yoast :after,.yoast :before{box-sizing:border-box}.yoast-hr{margin:0;border:0;padding-bottom:1.88rem;position:relative}.yoast-list--usp li:before{content:"";background:var(--yoast-svg-icon-check) no-repeat;background-size:contain;width:1em;height:100%;background-position:right .4em}.yoast-button--purple{background-color:#5d237a}.yoast-button-go-to:after{content:" \00BB";position:static;top:auto;left:auto;width:auto;height:auto;border:none}.yoast-button--extension{color:#fff;text-transform:uppercase;padding-right:.8em;padding-left:.8em}.yoast-button--extension+.yoast-button--extension-activated,.yoast-button--extension+.yoast-button--extension-not-activated{margin-right:0}.yoast-button--extension-activated:hover,.yoast-button--extension-installed:hover,.yoast-button--extension-not-activated:hover{text-decoration:none}.yoast-button--extension-installed{margin-left:.2rem}.yoast-button--extension-installed,.yoast-button--extension-installed:hover{background-color:#008a00}.yoast-button--extension-not-activated,.yoast-button--extension-not-activated:hover{background-color:#dc3232}.yoast-button--extension-activated,.yoast-button--extension-activated:hover{background-color:#008a00}.yoast-button-upsell{width:100%;margin-bottom:1em}@media only screen and (min-width:30rem){.yoast-button-upsell{width:auto;margin-left:1.36rem}}.yoast-promo-extensions{display:flex;flex-wrap:wrap;margin-right:-24px}.yoast-promo-extensions>h2{width:100%;margin-right:32px;margin-bottom:32px}.yoast-promo-extension{display:flex;flex-direction:column;max-width:340px;background-color:#fff;margin-right:32px}.yoast-promo-extension:first-child{margin-right:0}.yoast-promo-extension img{float:left;width:100px;height:100px;margin-bottom:.8rem}@media screen and (max-width:900px){.yoast-promo-extension img{display:none}}.yoast-promo-extension .yoast-button-container{margin-top:auto}.yoast-promo-extension .yoast-button-container div.yoast-button--extension{cursor:default}.yoast-promo-extension .yoast-button{width:100%;max-height:none;font-size:.9rem}.yoast-promo-extension .yoast-button--installed{color:#fff}.yoast-promo-extension .yoast-button--extension{font-size:.9rem;text-align:center;margin-top:0}.yoast-promo-extension .yoast-button--extension-installed{margin:0 0 0 2%;width:48%}.yoast-promo-extension .yoast-button--extension-activated,.yoast-promo-extension .yoast-button--extension-not-activated{margin-right:0;margin-left:0;width:48%}.yoast-promo-extension .yoast-button-upsell{width:100%}.yoast-promo-extension h3{color:#a4286a}@media screen and (max-width:900px){.yoast-promo-extension{max-width:none;width:100%}}.yoast-seo-premium-extension{margin:2em .5em 1.5em}.yoast-seo-premium-extension:after,.yoast-seo-premium-extension:before{content:"";display:table}.yoast-seo-premium-extension:after{clear:both}.yoast-seo-premium-benefits__title{font-weight:600}.yoast-seo-premium-benefits__description:before{content:"– "}.yoast-link--license,.yoast-link--more-info{color:#a4286a;font-weight:600}.yoast-link--license{margin:1em 0 0}.yoast-promo-extension .yoast-link--license{display:block;margin:1em 0 0}.yoast-link--license:after{content:" \00BB"}.yoast-link--more-info{background:var(--yoast-svg-icon-info);padding-right:calc(1em + 5px);background-size:1em;background-repeat:no-repeat;background-position:100%}.yoast-link--more-info:after{content:" \00BB"}.yoast-promo-extension .yoast-link--more-info{display:block;margin:0;background-position:100%}.yoast-heading-highlight{color:#a4286a;font-weight:600}.yoast-money-back-guarantee{font-style:italic;font-size:1.1em}.yoast-license-status-active{padding:3px 6px;color:#fff;background:#008a00}.yoast-license-status-inactive{padding:3px 6px;color:#fff;background:#dc3232} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-1720.css b/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-1720.css new file mode 100644 index 00000000..100aa570 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-1720.css @@ -0,0 +1 @@ +@charset "UTF-8";.yoast-modal__screen-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background-color:rgba(164,40,106,.6);z-index:100000;animation:edit-post__fade-in-animation .2s ease-out 0s;animation-fill-mode:forwards}.yoast-modal{background:#fff;display:flex;flex-direction:column;overflow:hidden;position:fixed;height:calc(100% - 96px);top:48px;bottom:48px;left:calc(50% - 440px);max-width:880px;width:100%}.yoast-gutenberg-modal .yoast-icon{background-color:var(--yoast-color-primary);mask-image:var(--yoast-svg-icon-yoast);-webkit-mask-image:var(--yoast-svg-icon-yoast);mask-size:100% 100%;-webkit-mask-size:100% 100%;display:inline-block;width:20px;height:20px;margin-right:8px}.yoast-tabs .yoast-modal__content{display:grid;grid-template-areas:"heading heading" "menu content" "menu footer";grid-template-rows:72px 1fr 88px;grid-template-columns:280px 1fr}.yoast-modal__heading{display:flex;align-items:center;box-sizing:border-box;min-height:72px;border-bottom:var(--yoast-border-default);padding:0 24px;grid-area:heading;background:var(--yoast-color-white)}.yoast-modal__heading .yoast-close{position:absolute;right:16px}.yoast-gutenberg-modal .components-modal__header-heading,.yoast-modal__heading h1{font-size:20px;font-weight:400;color:var(--yoast-color-primary);line-height:1.2;margin:0}.yoast-gutenberg-modal .components-modal__icon-container{display:inline-flex}.yoast-gutenberg-modal .components-modal__icon-container svg,.yoast-modal__heading-icon{fill:var(--yoast-color-primary);margin-right:16px;width:19px;height:20px;flex-shrink:0}.yoast-modal__menu{grid-area:menu;border-right:var(--yoast-border-default);overflow-y:auto}.yoast-modal__menu ul{padding:0;margin:0;list-style:none}.yoast-modal__menu li{padding:12px 16px 11px;border-bottom:var(--yoast-border-default);font-size:16px;cursor:pointer;text-decoration:none;color:var(--yoast-color-default);display:block}.yoast-modal__menu li:hover{background-color:#edd4e1}.yoast-modal__menu li.yoast-tabs__tab--selected{background-color:var(--yoast-color-primary);border-bottom:var(--yoast-border-default);color:#fff}.yoast-modal__content,.yoast-modal__section{grid-area:content;overflow-y:auto;flex-grow:1;position:relative;display:flex;flex-direction:column}.yoast-modal__section *{max-width:600px}.yoast-modal__section-header{position:sticky;top:0;background:var(--yoast-color-white);padding:24px 24px 0;z-index:10}.yoast-modal__section .yoast-h2{border-bottom:var(--yoast-border-default);padding-bottom:24px}.yoast-modal__footer{grid-area:footer;padding:0;border-top:var(--yoast-border-default);display:flex;align-self:flex-end;align-items:center;justify-content:flex-end;position:sticky;bottom:0;background:var(--yoast-color-white);margin:0 24px;z-index:10;box-sizing:border-box;min-height:88px;width:calc(100% - 48px)}.yoast-modal__settings-saved{position:relative;margin-right:16px;display:inline-flex;align-items:center}.yoast-modal__settings-saved:before{content:"";background:var(--yoast-checkmark--green) no-repeat 50%;height:13px;width:14px;display:inline-block;margin-right:8px}.yoast-modal__footer .yoast-button{display:block}.yoast-modal__section-content{padding:24px;flex-grow:1}@media screen and (max-width:880px){.yoast-modal{top:0;bottom:0;left:0;right:0;height:auto}}@media screen and (max-width:782px){.yoast-modal{overflow-y:initial}.yoast-modal.yoast-modal-collapsible{padding-bottom:72px}.yoast-tabs .yoast-modal__content{grid-template-rows:48px 1fr 72px}.yoast-modal__heading{padding:0 16px;position:fixed;top:0;width:100%;min-height:48px;z-index:11}.yoast-modal__heading h1{font-size:var(--yoast-font-size-default)}.yoast-close svg{width:10px}.yoast-modal__heading-icon{height:15px;margin-right:8px}.yoast .yoast-close{right:3px}.yoast-modal__heading .yoast-h2{font-size:var(--yoast-font-size-default)}.yoast-modal__section{overflow:initial;flex-grow:0}.yoast-modal__section-content{padding:24px 0;margin:0 16px}.yoast-modal__section:first-of-type{margin-top:48px}.yoast-modal__section:last-of-type{margin-bottom:72px}.yoast-modal__section-header{top:48px;position:sticky;padding:0;margin:0}.yoast-modal__section-open .yoast-modal__section-header{padding-left:0;padding-right:0;margin-left:16px;margin-right:16px}.yoast-modal__section-open{border-bottom:var(--yoast-border-default)}.yoast-modal__footer{width:100%;min-height:72px;margin:0;padding:0 16px;position:fixed;z-index:11}.yoast-modal-collapsible .yoast-modal__footer{min-height:72px}.yoast-modal-collapsible .yoast-modal__section-content{padding:24px 16px;border-bottom:var(--yoast-border-default);margin:0}.yoast-collapsible__hidden{display:none}.yoast-collapsible__trigger{padding:16px;border:none;border-bottom:var(--yoast-border-default);cursor:pointer;justify-content:space-between;font-size:var(--yoast-font-size-default);width:100%;text-align:left;background:#fff;color:var(--yoast-color-primary)}.yoast-collapsible__trigger[aria-expanded=true] .yoast-collapsible__icon{transform:rotate(180deg)}.yoast-collapsible__trigger[aria-expanded=true]{padding:16px 0;width:calc(100% - 32px);margin:0 16px}.yoast-collapsible__icon{background-color:var(--yoast-color-white);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='%23404040'%3E%3Cpath d='M1.4 0L6 4.6 10.6 0 12 1.4 6 7.5 0 1.4z'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:10px auto;width:19px;height:19px;border:none;display:block;float:right}.yoast-collapsible-block{width:100%;margin-top:48px}.yoast-collapsible-block+.yoast-collapsible-block{margin-top:0}}.yoast-post-settings-modal{width:880px;height:100%;max-width:calc(100% - 96px);max-height:calc(100% - 96px);overflow:hidden}.yoast-modal-content{padding:16px}@media (min-width:782px){.yoast-modal-content--columns{display:grid;grid-template-columns:1fr 1fr;grid-gap:24px}}.yoast-post-settings-modal__button-container{padding:16px;display:flex;flex-direction:column;border-bottom:1px solid rgba(0,0,0,.2)}.yoast-post-settings-modal .components-modal__content{padding:0;display:flex;flex-direction:column}.yoast-post-settings-modal .components-modal__header{margin:0;flex-shrink:0;border-bottom:var(--yoast-border-default)}.yoast-post-settings-modal .yoast-notice-container{z-index:1;position:sticky;bottom:0;left:0;width:100%;margin-top:auto}.yoast-post-settings-modal .yoast-notice-container>hr{margin-top:-1px;margin-bottom:0}.yoast-post-settings-modal .yoast-content-container{overflow-y:auto;flex-grow:1}.yoast-post-settings-modal .yoast-button-container{display:flex;flex-direction:row;justify-content:flex-end;padding:24px;margin:0}.yoast-post-settings-modal .yoast-button-container p{color:var(--yoast-color-label-help);padding-right:24px;align-self:center}.yoast-post-settings-modal .yoast-button-container button{flex-shrink:0;max-height:45px;align-self:center}@media only screen and (max-width:600px){.yoast-post-settings-modal{max-height:100%;max-width:100%}.yoast-post-settings-modal .yoast-button-container{padding:16px;justify-content:space-between}.yoast-post-settings-modal .yoast-button-container p{padding-right:0}}.yoast-related-keyphrases-modal{max-width:712px}#yoast-get-related-keyphrases-metabox,#yoast-get-related-keyphrases-sidebar{margin-top:8px}.yoast-gutenberg-modal .yoast-related-keyphrases-modal__content{min-height:66vh;position:relative}#yoast-semrush-country-selector{position:relative;border:none}.yoast-related-keyphrases-modal__chart{display:block}:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")}.yoast-list--usp{padding:0;margin-bottom:1em;font-family:Arial,sans-serif}.yoast-list--usp li{list-style:none!important;position:relative;padding-left:1.2533333333rem}.yoast-list--usp li:before{content:"\f00c\0020";position:absolute;left:0;top:0;font-family:FontAwesome,Open Sans,Arial,sans-serif;color:#77b227}.yoast .h1,.yoast .h2,.yoast .h3,.yoast .h4,.yoast .h5,.yoast .h6,.yoast h1,.yoast h2,.yoast h3,.yoast h4,.yoast h5,.yoast h6{font-family:Arial,sans-serif;font-weight:300;margin-top:0;display:block}.yoast .h1,.yoast h1{font-size:2.5em;line-height:3.68rem;margin-bottom:1.35rem;letter-spacing:normal}@media only screen and (min-width:30rem){.yoast .h1,.yoast h1{font-size:2.75em}}.yoast .h2,.yoast h2{font-size:1.88em;line-height:2.5rem;margin-bottom:1.2rem}.yoast .h2.tight,.yoast h2.tight{margin-bottom:.6rem}.yoast .h3,.yoast h3{font-size:1.25em;line-height:1.88rem;margin-bottom:.8rem}.yoast .h3.tight,.yoast h3.tight{margin-bottom:.4rem}@media only screen and (min-width:30rem){.yoast .h3,.yoast h3{font-size:1.375em}}@media only screen and (min-width:50rem){.yoast .h3,.yoast h3{font-size:1.5em}}.yoast .h4,.yoast .h5,.yoast .h6,.yoast h4,.yoast h5,.yoast h6{font-size:1.13em;font-weight:400;line-height:1.88rem;margin-bottom:.2rem}.yoast-button{font-family:Arial,sans-serif;position:relative;display:inline-block;width:100%;padding:.345em 1.5em .345em 1em;font-size:1.1em;background-color:initial;background-color:#dc5c04;color:#dc5c04;border:0;text-decoration:none;cursor:pointer}@media only screen and (min-width:30rem){.yoast-button{margin-right:1.36rem;width:auto;max-height:2.86rem}.yoast-button:after{content:"";position:absolute;top:0;right:-1.36rem;height:0;width:0;border-right:0;border-left:1.43rem solid #dc5c04;border-top:1.43rem solid transparent;border-bottom:1.44rem solid transparent}.yoast-button.left{margin-right:0;margin-left:1.36rem}.yoast-button.left:after{content:none}.yoast-button.left:before{content:"";position:absolute;top:0;left:-1.36rem;height:0;width:0;border-left:0;border-right:1.43rem solid #dc5c04;border-top:1.43rem solid transparent;border-bottom:1.44rem solid transparent}}.yoast-button.alignleft{margin:1rem 2.5rem 0 0!important}.yoast-button .arrow{display:none}.yoast-button+.yoast-button{margin-top:1em;margin-left:1.88rem}.yoast-button--full{width:100%}.yoast-button--full:after{content:none}.yoast-button.default{color:#fff;background-color:#dc5c04}.yoast-button.default:after{border-left-color:#dc5c04}.yoast-button.default:before{border-right-color:#dc5c04}.yoast-button:hover,.yoast-button a:focus{background-color:#f58223;color:#fff;text-decoration:underline}.yoast-button:hover:after,.yoast-button a:focus:after{border-left-color:#f58223}.yoast-button:hover:before,.yoast-button a:focus:before{border-right-color:#f58223}.yoast-button.academy{color:#fff;background-color:#5d237a}.yoast-button.academy:after{border-left-color:#5d237a}.yoast-button.academy:before{border-right-color:#5d237a}@media only screen and (max-width:20rem){.yoast-button.academy{background-color:#5d237a}}.yoast-button.academy--secondary{color:#fff;background-color:#a4286a}.yoast-button.academy--secondary:after{border-left-color:#a4286a}.yoast-button.academy--secondary:before{border-right-color:#a4286a}@media only screen and (max-width:20rem){.yoast-button.academy--secondary{background-color:#a4286a}}.yoast-button.software{color:#fff;background-color:#0075b3}.yoast-button.software:after{border-left-color:#0075b3}.yoast-button.software:before{border-right-color:#0075b3}.yoast-button.review{color:#fff;background-color:#009288}.yoast-button.review:after{border-left-color:#009288}.yoast-button.review:before{border-right-color:#009288}.yoast-button.about{color:#fff;background-color:#d93f69}.yoast-button.about:after{border-left-color:#d93f69}.yoast-button.about:before{border-right-color:#d93f69}.yoast_academy .yoast-button{color:#fff;background-color:#d93f69}.yoast_academy .yoast-button:after{border-left-color:#d93f69}.yoast_academy .yoast-button:before{border-right-color:#d93f69}.yoast_academy .yoast-button:hover,.yoast_academy .yoast-button a:focus{background-color:#d42a59;color:#fff;text-decoration:underline}.yoast_academy .yoast-button:hover:after,.yoast_academy .yoast-button a:focus:after{border-left-color:#d42a59}.yoast_academy .yoast-button:hover:before,.yoast_academy .yoast-button a:focus:before{border-right-color:#d42a59}.yoast_academy .yoast-button.dimmed,body .yoast-button.dimmed{color:#646464;background-color:#dcdcdc}.yoast_academy .yoast-button.dimmed:after,body .yoast-button.dimmed:after{border-left-color:#dcdcdc}.yoast_academy .yoast-button.dimmed:before,body .yoast-button.dimmed:before{border-right-color:#dcdcdc}.yoast_academy .yoast-button.dimmed:hover,.yoast_academy .yoast-button.dimmed a:focus,body .yoast-button.dimmed:hover,body .yoast-button.dimmed a:focus{background-color:#cdcdcd;color:#646464;text-decoration:underline}.yoast_academy .yoast-button.dimmed:hover:after,.yoast_academy .yoast-button.dimmed a:focus:after,body .yoast-button.dimmed:hover:after,body .yoast-button.dimmed a:focus:after{border-left-color:#cdcdcd}.yoast_academy .yoast-button.dimmed:hover:before,.yoast_academy .yoast-button.dimmed a:focus:before,body .yoast-button.dimmed:hover:before,body .yoast-button.dimmed a:focus:before{border-right-color:#cdcdcd}.yoast-button--noarrow:after{content:none}.yoast-button--naked{border:none;background-color:initial;padding:0}.yoast-button--naked:after{content:none}.yoast-button i.fa{font-size:140%;margin:4px 10px 0 0}.yoast-promoblock{margin-bottom:1.88rem;box-shadow:0 1px 6px 0 rgba(0,0,0,.3);border:1px solid #dcdcdc;padding:16px}.yoast-promoblock p{color:#000}.yoast-promoblock p:last-of-type{margin-bottom:0}.yoast-promoblock i.blockicon{position:absolute;right:10px;bottom:10px;padding:0 0 0 .5em;font-size:2.25em}.yoast-promoblock a img{border:1px solid #dcdcdc}.yoast-promoblock p a{font-weight:600!important;text-decoration:underline}.yoast-promoblock form a{font-weight:400!important;text-decoration:none}.yoast-promoblock .h4,.yoast-promoblock h4{margin-bottom:.7rem}.yoast-promoblock.link{border-color:#dc5c04}.yoast-promoblock.link a,.yoast-promoblock.link a:hover{color:#dc5c04}.yoast-promoblock--white{border-color:#fff!important}.product .yoast-promoblock{overflow:hidden}.yoast-promoblock--hometitle{max-width:16em;height:11em;margin:1rem auto 2rem;display:flex;font-size:16px;font-size:1rem;line-height:1;background-color:rgba(217,63,105,.25);border-color:#fff!important}@media only screen and (max-width:30rem){.yoast-promoblock--hometitle:after{content:none!important}}.yoast-promoblock--imageholder{padding:0;margin-bottom:0}.yoast-promoblock--imageholdersmall{position:absolute}.yoast-promoblock--imageholdersmall:first-child{left:4rem}.yoast-promoblock--imageholdersmall:last-child{top:4rem}@media only screen and (max-width:50rem){.yoast-promoblock h2{margin-bottom:0}}a.promoblock{text-decoration:none;color:#000}a.promoblock:hover{text-decoration:none}.promoblockimage__holder{width:240px;height:295px;position:relative}.yoast{font-family:Open Sans,Arial,sans-serif;font-size:1rem;line-height:1.88;letter-spacing:.01em;color:#000}.yoast *,.yoast :after,.yoast :before{box-sizing:border-box}.yoast-hr{margin:0;border:0;padding-bottom:1.88rem;position:relative}.yoast-list--usp li:before{content:"";background:var(--yoast-svg-icon-check) no-repeat;background-size:contain;width:1em;height:100%;background-position:left .4em}.yoast-button--purple{background-color:#5d237a}.yoast-button-go-to:after{content:" \00BB";position:static;top:auto;right:auto;width:auto;height:auto;border:none}.yoast-button--extension{color:#fff;text-transform:uppercase;padding-left:.8em;padding-right:.8em}.yoast-button--extension+.yoast-button--extension-activated,.yoast-button--extension+.yoast-button--extension-not-activated{margin-left:0}.yoast-button--extension-activated:hover,.yoast-button--extension-installed:hover,.yoast-button--extension-not-activated:hover{text-decoration:none}.yoast-button--extension-installed{margin-right:.2rem}.yoast-button--extension-installed,.yoast-button--extension-installed:hover{background-color:#008a00}.yoast-button--extension-not-activated,.yoast-button--extension-not-activated:hover{background-color:#dc3232}.yoast-button--extension-activated,.yoast-button--extension-activated:hover{background-color:#008a00}.yoast-button-upsell{width:100%;margin-bottom:1em}@media only screen and (min-width:30rem){.yoast-button-upsell{width:auto;margin-right:1.36rem}}.yoast-promo-extensions{display:flex;flex-wrap:wrap;margin-left:-24px}.yoast-promo-extensions>h2{width:100%;margin-left:32px;margin-bottom:32px}.yoast-promo-extension{display:flex;flex-direction:column;max-width:340px;background-color:#fff;margin-left:32px}.yoast-promo-extension:first-child{margin-left:0}.yoast-promo-extension img{float:right;width:100px;height:100px;margin-bottom:.8rem}@media screen and (max-width:900px){.yoast-promo-extension img{display:none}}.yoast-promo-extension .yoast-button-container{margin-top:auto}.yoast-promo-extension .yoast-button-container div.yoast-button--extension{cursor:default}.yoast-promo-extension .yoast-button{width:100%;max-height:none;font-size:.9rem}.yoast-promo-extension .yoast-button--installed{color:#fff}.yoast-promo-extension .yoast-button--extension{font-size:.9rem;text-align:center;margin-top:0}.yoast-promo-extension .yoast-button--extension-installed{margin:0 2% 0 0;width:48%}.yoast-promo-extension .yoast-button--extension-activated,.yoast-promo-extension .yoast-button--extension-not-activated{margin-left:0;margin-right:0;width:48%}.yoast-promo-extension .yoast-button-upsell{width:100%}.yoast-promo-extension h3{color:#a4286a}@media screen and (max-width:900px){.yoast-promo-extension{max-width:none;width:100%}}.yoast-seo-premium-extension{margin:2em .5em 1.5em}.yoast-seo-premium-extension:after,.yoast-seo-premium-extension:before{content:"";display:table}.yoast-seo-premium-extension:after{clear:both}.yoast-seo-premium-benefits__title{font-weight:600}.yoast-seo-premium-benefits__description:before{content:"– "}.yoast-link--license,.yoast-link--more-info{color:#a4286a;font-weight:600}.yoast-link--license{margin:1em 0 0}.yoast-promo-extension .yoast-link--license{display:block;margin:1em 0 0}.yoast-link--license:after{content:" \00BB"}.yoast-link--more-info{background:var(--yoast-svg-icon-info);padding-left:calc(1em + 5px);background-size:1em;background-repeat:no-repeat;background-position:0}.yoast-link--more-info:after{content:" \00BB"}.yoast-promo-extension .yoast-link--more-info{display:block;margin:0;background-position:0}.yoast-heading-highlight{color:#a4286a;font-weight:600}.yoast-money-back-guarantee{font-style:italic;font-size:1.1em}.yoast-license-status-active{padding:3px 6px;color:#fff;background:#008a00}.yoast-license-status-inactive{padding:3px 6px;color:#fff;background:#dc3232} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-720-rtl.min.css deleted file mode 100644 index 347b34f2..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";.yoast-list--usp{margin-bottom:1em;padding:0;font-family:"Open Sans",Arial,sans-serif}.yoast-list--usp li{position:relative;padding-right:1.2533333333rem;list-style:none!important}.yoast-list--usp li::before{position:absolute;top:0;right:0;color:#77b227;font-family:FontAwesome,"Open Sans",Arial,sans-serif;content:"\f00c\0020"}.yoast .h1,.yoast .h2,.yoast .h3,.yoast .h4,.yoast .h5,.yoast .h6,.yoast h1,.yoast h2,.yoast h3,.yoast h4,.yoast h5,.yoast h6{display:block;margin-top:0;font-family:"Open Sans",Arial,sans-serif;font-weight:300}.yoast .h1,.yoast h1{margin-bottom:1.35rem;font-size:2.5em;line-height:3.68rem;letter-spacing:normal}@media only screen and (min-width:30rem){.yoast .h1,.yoast h1{font-size:2.75em}}.yoast .h2,.yoast h2{margin-bottom:1.2rem;font-size:1.88em;line-height:2.5rem}.yoast .h2.tight,.yoast h2.tight{margin-bottom:.6rem}.yoast .h3,.yoast h3{margin-bottom:.8rem;font-size:1.25em;line-height:1.88rem}.yoast .h3.tight,.yoast h3.tight{margin-bottom:.4rem}@media only screen and (min-width:30rem){.yoast .h3,.yoast h3{font-size:1.375em}}@media only screen and (min-width:50rem){.yoast .h3,.yoast h3{font-size:1.5em}}.yoast .h4,.yoast .h5,.yoast .h6,.yoast h4,.yoast h5,.yoast h6{margin-bottom:.2rem;font-size:1.13em;font-weight:400;line-height:1.88rem}.yoast-button{display:inline-block;position:relative;width:100%;padding:.345em 1em .345em 1.5em;border:0;color:#dc5c04;background-color:#dc5c04;font-family:"Open Sans",Arial,sans-serif;font-size:1.1em;text-decoration:none;cursor:pointer}@media only screen and (min-width:30rem){.yoast-button{width:auto;max-height:2.86rem;margin-left:1.36rem}.yoast-button.left::before,.yoast-button::after{position:absolute;top:0;width:0;height:0;border-top:1.43rem solid transparent;border-bottom:1.44rem solid transparent}.yoast-button::after{left:-1.36rem;border-left:0;border-right:1.43rem solid #dc5c04;content:""}.yoast-button.left{margin-left:0;margin-right:1.36rem}.yoast-button.left::after{content:none}.yoast-button.left::before{right:-1.36rem;border-left:1.43rem solid #dc5c04;border-right:0;content:""}}.yoast-button--full::after,.yoast-button--naked::after,.yoast-button--noarrow::after{content:none}.yoast-button.alignleft{margin:1rem 0 0 2.5rem!important}.yoast-button .arrow{display:none}.yoast-button+.yoast-button{margin-top:1em;margin-right:1.88rem}.yoast-button--full{width:100%}.yoast-button.default{color:#fff;background-color:#dc5c04}.yoast-button.default::after{border-right-color:#dc5c04}.yoast-button.default::before{border-left-color:#dc5c04}.yoast-button a:focus,.yoast-button:hover{color:#fff;background-color:#f58223;text-decoration:underline}.yoast-button a:focus::after,.yoast-button:hover::after{border-right-color:#f58223}.yoast-button a:focus::before,.yoast-button:hover::before{border-left-color:#f58223}.yoast-button.academy{color:#fff;background-color:#5d237a}.yoast-button.academy::after{border-right-color:#5d237a}.yoast-button.academy::before{border-left-color:#5d237a}@media only screen and (max-width:20rem){.yoast-button.academy{background-color:#5d237a}.yoast-button.academy--secondary{background-color:#a4286a}}.yoast-button.academy--secondary{color:#fff;background-color:#a4286a}.yoast-button.academy--secondary::after{border-right-color:#a4286a}.yoast-button.academy--secondary::before{border-left-color:#a4286a}.yoast-button.software{color:#fff;background-color:#0075b3}.yoast-button.software::after{border-right-color:#0075b3}.yoast-button.software::before{border-left-color:#0075b3}.yoast-button.review{color:#fff;background-color:#009288}.yoast-button.about,.yoast_academy .yoast-button{background-color:#d93f69;color:#fff}.yoast-button.review::after{border-right-color:#009288}.yoast-button.about::after,.yoast_academy .yoast-button::after{border-right-color:#d93f69}.yoast-button.review::before{border-left-color:#009288}.yoast-button.about::before,.yoast_academy .yoast-button::before{border-left-color:#d93f69}.yoast_academy .yoast-button a:focus,.yoast_academy .yoast-button:hover{color:#fff;background-color:#d42a59;text-decoration:underline}.yoast_academy .yoast-button a:focus::after,.yoast_academy .yoast-button:hover::after{border-right-color:#d42a59}.yoast_academy .yoast-button a:focus::before,.yoast_academy .yoast-button:hover::before{border-left-color:#d42a59}.yoast_academy .yoast-button.dimmed,body .yoast-button.dimmed{color:#646464;background-color:#dcdcdc}.yoast_academy .yoast-button.dimmed::after,body .yoast-button.dimmed::after{border-right-color:#dcdcdc}.yoast_academy .yoast-button.dimmed::before,body .yoast-button.dimmed::before{border-left-color:#dcdcdc}.yoast_academy .yoast-button.dimmed a:focus,.yoast_academy .yoast-button.dimmed:hover,body .yoast-button.dimmed a:focus,body .yoast-button.dimmed:hover{color:#646464;background-color:#cdcdcd;text-decoration:underline}.yoast_academy .yoast-button.dimmed a:focus::after,.yoast_academy .yoast-button.dimmed:hover::after,body .yoast-button.dimmed a:focus::after,body .yoast-button.dimmed:hover::after{border-right-color:#cdcdcd}.yoast_academy .yoast-button.dimmed a:focus:before,.yoast_academy .yoast-button.dimmed:hover:before,body .yoast-button.dimmed a:focus:before,body .yoast-button.dimmed:hover:before{border-left-color:#cdcdcd}.yoast-button--naked{padding:0;border:none;background-color:transparent}.yoast-button i.fa{margin:4px 0 0 10px;font-size:140%}.theme-academy .yoast-promoblock{border-color:#5d237a}.theme-academy--secondary .yoast-promoblock{border-color:#a4286a}.theme-software .yoast-promoblock{border-color:#0075b3}.theme-review .yoast-promoblock{border-color:#009288}.theme-about .yoast-promoblock,.theme-home .yoast-promoblock{border-color:#d93f69}.theme-academy.yoast-promoblock{border-color:#5d237a}.theme-academy--secondary.yoast-promoblock{border-color:#a4286a}.theme-software.yoast-promoblock{border-color:#0075b3}.theme-review.yoast-promoblock,.theme-software--secondary.yoast-promoblock{border-color:#009288}.theme-review--secondary.yoast-promoblock{border-color:#77b227}.theme-about.yoast-promoblock{border-color:#d93f69}.theme-about--secondary.yoast-promoblock{border-color:#a4286a}.cta.yoast-promoblock,.link.yoast-promoblock{border-color:#dc5c04}.link.yoast-promoblock::after{-moz-filter:drop-shadow(1px 0 0 #dc5c04);-ms-filter:drop-shadow(1px 0 0 #dc5c04);-o-filter:drop-shadow(1px 0 0 #dc5c04);filter:drop-shadow(1px 0 0 #dc5c04)}.cta.yoast-promoblock::after{-moz-filter:drop-shadow(1px 0 0 #dc5c04);-ms-filter:drop-shadow(1px 0 0 #dc5c04);-o-filter:drop-shadow(1px 0 0 #dc5c04);filter:drop-shadow(1px 0 0 #dc5c04)}.yoast-promoblock{display:block;position:relative;margin-bottom:1.88rem;padding:20px;border:1px solid;border-radius:30px 30px 30px 0;background-color:#fff;font-family:Merriweather,Georgia,serif}.yoast-promoblock p{color:#000}.yoast-promoblock p:last-of-type{margin-bottom:0}.yoast-promoblock i.blockicon{position:absolute;left:10px;bottom:10px;padding:0 .5em 0 0;font-size:2.25em}.yoast-promoblock a img{border:1px solid #dcdcdc}.yoast-promoblock p a{font-weight:600!important;text-decoration:underline}.yoast-button--extension-activated:hover,.yoast-button--extension-installed:hover,.yoast-button--extension-not-activated:hover,a.promoblock,a.promoblock:hover{text-decoration:none}.yoast-promoblock form a{font-family:"Open Sans",Arial,sans-serif;font-weight:400!important;text-decoration:none}.yoast-heading-highlight,.yoast-link--license,.yoast-link--more-info{font-weight:600;color:#a4286a}.yoast-promoblock .h4,.yoast-promoblock h4{margin-bottom:.7rem}.yoast-promoblock.link{border-color:#dc5c04}.yoast-promoblock.link a,.yoast-promoblock.link a:hover{color:#dc5c04}.yoast-promoblock--white{border-color:#fff!important}.yoast-promoblock.theme-academy a{color:#5d237a!important}.yoast-promoblock.theme-academy.secondary a{color:#a4286a!important}.yoast-promoblock.theme-software a{color:#0075b3!important}.yoast-promoblock.theme-review a{color:#009288!important}.yoast-promoblock.theme-review.secondary a{color:#77b227!important}.yoast-promoblock.theme-about a{color:#d93f69!important}.product .yoast-promoblock{overflow:hidden}.yoast-promoblock--hometitle{display:-ms-flexbox;display:flex;max-width:16em;height:11em;margin:1rem auto 2rem;border-color:#fff!important;background-color:rgba(217,63,105,.25);font-size:16px;font-size:1rem;line-height:1;-webkit-box-pack:center;-ms-flex-align:center;-ms-flex-line-pack:center;-ms-flex-pack:justify}.old-ie .yoast-promoblock--hometitle{text-align:justify}.old-ie .yoast-promoblock--hometitle::after{display:inline-block;width:100%;content:""}.old-ie .yoast-promoblock--hometitle>*{display:inline-block;text-align:right}@media only screen and (max-width:30rem){.yoast-promoblock--hometitle::after{content:none!important}}.yoast-promoblock--imageholder{margin-bottom:0;padding:0}.yoast-promoblock--imageholdersmall{position:absolute}.yoast-promoblock--imageholdersmall:first-child{right:4rem}.yoast-promoblock--imageholdersmall:last-child{top:4rem}@media only screen and (max-width:50rem){.yoast-promoblock h2{margin-bottom:0}}a.promoblock{color:#000}.promoblockimage__holder{position:relative;width:240px;height:295px}@media only screen and (min-width:50rem){[class*=promoblock--icon]::before{position:absolute;left:.47rem;bottom:.47rem;font-family:FontAwesome,"Open Sans",Arial,sans-serif;font-size:2.2rem;line-height:1}body.theme-about [class*=promoblock--icon]::before{color:#d93f69}body.theme-about .promoblock a.color-cta{color:#009288!important}body.theme-academy [class*=promoblock--icon]::before{color:#5d237a}body.theme-software [class*=promoblock--icon]::before{color:#0075b3}.promoblock--icon-academy::before{content:"\f19d"}.promoblock--icon-blog::before{content:"\f1ea"}.promoblock--icon-book::before{content:"\f02d"}.promoblock--icon-calendar::before{content:"\f073"}.promoblock--icon-check::before{content:"\f046"}.promoblock--icon-drupal::before{content:"\f1a9"}.promoblock--icon-gears::before{content:"\f085"}.promoblock--icon-pencil::before{content:"\f040"}.promoblock--icon-plug::before{content:"\f1e6"}.promoblock--icon-video::before{content:"\f008"}.promoblock--icon-wordpress::before{content:"\f19a"}}.yoast,.yoast-link--license,.yoast-link--more-info{font-family:"Open Sans",Arial,sans-serif}.yoast{color:#000;font-size:1rem;line-height:1.88;letter-spacing:.01em}.yoast-button--extension-buy:visited,.yoast-promo-extension .yoast-button--installed{color:#fff}.yoast *,.yoast :after,.yoast :before{box-sizing:border-box}.yoast-hr{position:relative;margin:0;padding-bottom:1.88rem;border:0;border-top:1px solid #a4286a}.yoast-list--usp li:before{width:1em;height:100%;background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%2377B227%22%20d%3D%22M1671%20566q0%2040%2D28%2068l%2D724%20724%2D136%20136q%2D28%2028%2D68%2028t%2D68%2D28l%2D136%2D136%2D362%2D362q%2D28%2D28%2D28%2D68t28%2D68l136%2D136q28%2D28%2068%2D28t68%2028l294%20295%20656%2D657q28%2D28%2068%2D28t68%2028l136%20136q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E") right .4em no-repeat;background-size:contain;content:""}.yoast-button--purple{background-color:#5d237a}.yoast-button-go-to:after{position:static;top:auto;left:auto;width:auto;height:auto;border:none;content:" \00BB"}.yoast-button--extension{padding-left:.8em;padding-right:.8em;color:#fff;text-transform:uppercase}.yoast-button--extension+.yoast-button--extension-activated,.yoast-button--extension+.yoast-button--extension-not-activated{margin-right:0}.yoast-button--extension-buy,.yoast-button--extension-buy:hover{background-color:#a4286a}.yoast-button--extension-installed{margin-left:.2rem}.yoast-button--extension-installed,.yoast-button--extension-installed:hover{background-color:#008a00}.yoast-button--extension-not-activated,.yoast-button--extension-not-activated:hover{background-color:#dc3232}.yoast-button--extension-activated,.yoast-button--extension-activated:hover{background-color:#008a00}.yoast-promo-extensions{display:-ms-flexbox;display:flex;margin-right:-24px;-ms-flex-wrap:wrap;flex-wrap:wrap}.yoast-promo-extensions>h2{width:100%;margin-bottom:32px;margin-right:32px}.yoast-promo-extension{max-width:340px;margin-right:32px;padding-bottom:120px;border-color:#a4286a;background-color:transparent}.yoast-promo-extension:first-child{margin-right:0}.yoast-promo-extension img{width:100%;height:auto;margin-bottom:.8rem}.yoast-promo-extension .yoast-button-container{position:absolute;left:20px;bottom:20px;right:20px}.yoast-promo-extension .yoast-button-container div.yoast-button--extension{cursor:default}.yoast-promo-extension .yoast-button{width:100%;max-height:none;font-size:.9rem}.yoast-promo-extension .yoast-button--extension{margin-top:0;font-size:.9rem;text-align:center}.yoast-promo-extension .yoast-button--extension-installed{width:48%;margin:0 0 0 2%}.yoast-promo-extension .yoast-button--extension-activated,.yoast-promo-extension .yoast-button--extension-not-activated{width:48%;margin-left:0;margin-right:0}.yoast-promo-extension h3{color:#a4286a}@media screen and (max-width:900px){.yoast-promo-extension img{display:none}.yoast-promo-extension{width:100%;max-width:none}}.yoast-seo-premium-extension{margin:2em .5em 1.5em}.yoast-seo-premium-extension:after,.yoast-seo-premium-extension:before{display:table;content:""}.yoast-seo-premium-extension:after{clear:both}.yoast-seo-premium-benefits__title{font-weight:600}.yoast-seo-premium-benefits__description:before{content:"– "}.yoast-link--license:after,.yoast-link--more-info:after{content:" \00BB"}.yoast-link--license{margin:1em 0 0}.yoast-promo-extension .yoast-link--license{display:block;margin:1em 0 0}.yoast-link--more-info{padding-right:calc(1em + 5px);background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23A4286A%22%20d%3D%22M1152%201376v%2D160q0%2D14%2D9%2D23t%2D23%2D9h%2D96v%2D512q0%2D14%2D9%2D23t%2D23%2D9h%2D320q%2D14%200%2D23%209t%2D9%2023v160q0%2014%209%2023t23%209h96v320h%2D96q%2D14%200%2D23%209t%2D9%2023v160q0%2014%209%2023t23%209h448q14%200%2023%2D9t9%2D23zm%2D128%2D896v%2D160q0%2D14%2D9%2D23t%2D23%2D9h%2D192q%2D14%200%2D23%209t%2D9%2023v160q0%2014%209%2023t23%209h192q14%200%2023%2D9t9%2D23zm640%20416q0%20209%2D103%20385%2E5t%2D279%2E5%20279%2E5%2D385%2E5%20103%2D385%2E5%2D103%2D279%2E5%2D279%2E5%2D103%2D385%2E5%20103%2D385%2E5%20279%2E5%2D279%2E5%20385%2E5%2D103%20385%2E5%20103%20279%2E5%20279%2E5%20103%20385%2E5z%22%2F%3E%3C%2Fsvg%3E") right .2em no-repeat;background-size:1em}.yoast-promo-extension .yoast-link--more-info{display:block;margin:1em 0 0;background-position:right .4em}.yoast-money-back-guarantee{font-size:1.1em;font-style:italic}.yoast-license-status-active{padding:3px 6px;color:#fff;background:#008a00}.yoast-license-status-inactive{padding:3px 6px;color:#fff;background:#dc3232} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-720.min.css deleted file mode 100644 index d8d513d4..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/yoast-extensions-720.min.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";.yoast-list--usp{margin-bottom:1em;padding:0;font-family:"Open Sans",Arial,sans-serif}.yoast-list--usp li{position:relative;padding-left:1.2533333333rem;list-style:none!important}.yoast-list--usp li::before{position:absolute;top:0;left:0;color:#77b227;font-family:FontAwesome,"Open Sans",Arial,sans-serif;content:"\f00c\0020"}.yoast .h1,.yoast .h2,.yoast .h3,.yoast .h4,.yoast .h5,.yoast .h6,.yoast h1,.yoast h2,.yoast h3,.yoast h4,.yoast h5,.yoast h6{display:block;margin-top:0;font-family:"Open Sans",Arial,sans-serif;font-weight:300}.yoast .h1,.yoast h1{margin-bottom:1.35rem;font-size:2.5em;line-height:3.68rem;letter-spacing:normal}@media only screen and (min-width:30rem){.yoast .h1,.yoast h1{font-size:2.75em}}.yoast .h2,.yoast h2{margin-bottom:1.2rem;font-size:1.88em;line-height:2.5rem}.yoast .h2.tight,.yoast h2.tight{margin-bottom:.6rem}.yoast .h3,.yoast h3{margin-bottom:.8rem;font-size:1.25em;line-height:1.88rem}.yoast .h3.tight,.yoast h3.tight{margin-bottom:.4rem}@media only screen and (min-width:30rem){.yoast .h3,.yoast h3{font-size:1.375em}}@media only screen and (min-width:50rem){.yoast .h3,.yoast h3{font-size:1.5em}}.yoast .h4,.yoast .h5,.yoast .h6,.yoast h4,.yoast h5,.yoast h6{margin-bottom:.2rem;font-size:1.13em;font-weight:400;line-height:1.88rem}.yoast-button{display:inline-block;position:relative;width:100%;padding:.345em 1.5em .345em 1em;border:0;color:#dc5c04;background-color:#dc5c04;font-family:"Open Sans",Arial,sans-serif;font-size:1.1em;text-decoration:none;cursor:pointer}@media only screen and (min-width:30rem){.yoast-button{width:auto;max-height:2.86rem;margin-right:1.36rem}.yoast-button.left::before,.yoast-button::after{position:absolute;top:0;width:0;height:0;border-top:1.43rem solid transparent;border-bottom:1.44rem solid transparent}.yoast-button::after{right:-1.36rem;border-right:0;border-left:1.43rem solid #dc5c04;content:""}.yoast-button.left{margin-right:0;margin-left:1.36rem}.yoast-button.left::after{content:none}.yoast-button.left::before{left:-1.36rem;border-right:1.43rem solid #dc5c04;border-left:0;content:""}}.yoast-button--full::after,.yoast-button--naked::after,.yoast-button--noarrow::after{content:none}.yoast-button.alignleft{margin:1rem 2.5rem 0 0!important}.yoast-button .arrow{display:none}.yoast-button+.yoast-button{margin-top:1em;margin-left:1.88rem}.yoast-button--full{width:100%}.yoast-button.default{color:#fff;background-color:#dc5c04}.yoast-button.default::after{border-left-color:#dc5c04}.yoast-button.default::before{border-right-color:#dc5c04}.yoast-button a:focus,.yoast-button:hover{color:#fff;background-color:#f58223;text-decoration:underline}.yoast-button a:focus::after,.yoast-button:hover::after{border-left-color:#f58223}.yoast-button a:focus::before,.yoast-button:hover::before{border-right-color:#f58223}.yoast-button.academy{color:#fff;background-color:#5d237a}.yoast-button.academy::after{border-left-color:#5d237a}.yoast-button.academy::before{border-right-color:#5d237a}@media only screen and (max-width:20rem){.yoast-button.academy{background-color:#5d237a}.yoast-button.academy--secondary{background-color:#a4286a}}.yoast-button.academy--secondary{color:#fff;background-color:#a4286a}.yoast-button.academy--secondary::after{border-left-color:#a4286a}.yoast-button.academy--secondary::before{border-right-color:#a4286a}.yoast-button.software{color:#fff;background-color:#0075b3}.yoast-button.software::after{border-left-color:#0075b3}.yoast-button.software::before{border-right-color:#0075b3}.yoast-button.review{color:#fff;background-color:#009288}.yoast-button.about,.yoast_academy .yoast-button{background-color:#d93f69;color:#fff}.yoast-button.review::after{border-left-color:#009288}.yoast-button.about::after,.yoast_academy .yoast-button::after{border-left-color:#d93f69}.yoast-button.review::before{border-right-color:#009288}.yoast-button.about::before,.yoast_academy .yoast-button::before{border-right-color:#d93f69}.yoast_academy .yoast-button a:focus,.yoast_academy .yoast-button:hover{color:#fff;background-color:#d42a59;text-decoration:underline}.yoast_academy .yoast-button a:focus::after,.yoast_academy .yoast-button:hover::after{border-left-color:#d42a59}.yoast_academy .yoast-button a:focus::before,.yoast_academy .yoast-button:hover::before{border-right-color:#d42a59}.yoast_academy .yoast-button.dimmed,body .yoast-button.dimmed{color:#646464;background-color:#dcdcdc}.yoast_academy .yoast-button.dimmed::after,body .yoast-button.dimmed::after{border-left-color:#dcdcdc}.yoast_academy .yoast-button.dimmed::before,body .yoast-button.dimmed::before{border-right-color:#dcdcdc}.yoast_academy .yoast-button.dimmed a:focus,.yoast_academy .yoast-button.dimmed:hover,body .yoast-button.dimmed a:focus,body .yoast-button.dimmed:hover{color:#646464;background-color:#cdcdcd;text-decoration:underline}.yoast_academy .yoast-button.dimmed a:focus::after,.yoast_academy .yoast-button.dimmed:hover::after,body .yoast-button.dimmed a:focus::after,body .yoast-button.dimmed:hover::after{border-left-color:#cdcdcd}.yoast_academy .yoast-button.dimmed a:focus:before,.yoast_academy .yoast-button.dimmed:hover:before,body .yoast-button.dimmed a:focus:before,body .yoast-button.dimmed:hover:before{border-right-color:#cdcdcd}.yoast-button--naked{padding:0;border:none;background-color:transparent}.yoast-button i.fa{margin:4px 10px 0 0;font-size:140%}.theme-academy .yoast-promoblock{border-color:#5d237a}.theme-academy--secondary .yoast-promoblock{border-color:#a4286a}.theme-software .yoast-promoblock{border-color:#0075b3}.theme-review .yoast-promoblock{border-color:#009288}.theme-about .yoast-promoblock,.theme-home .yoast-promoblock{border-color:#d93f69}.theme-academy.yoast-promoblock{border-color:#5d237a}.theme-academy--secondary.yoast-promoblock{border-color:#a4286a}.theme-software.yoast-promoblock{border-color:#0075b3}.theme-review.yoast-promoblock,.theme-software--secondary.yoast-promoblock{border-color:#009288}.theme-review--secondary.yoast-promoblock{border-color:#77b227}.theme-about.yoast-promoblock{border-color:#d93f69}.theme-about--secondary.yoast-promoblock{border-color:#a4286a}.cta.yoast-promoblock,.link.yoast-promoblock{border-color:#dc5c04}.link.yoast-promoblock::after{-moz-filter:drop-shadow(1px 0 0 #dc5c04);-ms-filter:drop-shadow(1px 0 0 #dc5c04);-o-filter:drop-shadow(1px 0 0 #dc5c04);filter:drop-shadow(1px 0 0 #dc5c04)}.cta.yoast-promoblock::after{-moz-filter:drop-shadow(1px 0 0 #dc5c04);-ms-filter:drop-shadow(1px 0 0 #dc5c04);-o-filter:drop-shadow(1px 0 0 #dc5c04);filter:drop-shadow(1px 0 0 #dc5c04)}.yoast-promoblock{display:block;position:relative;margin-bottom:1.88rem;padding:20px;border:1px solid;border-radius:30px 30px 0;background-color:#fff;font-family:Merriweather,Georgia,serif}.yoast-promoblock p{color:#000}.yoast-promoblock p:last-of-type{margin-bottom:0}.yoast-promoblock i.blockicon{position:absolute;right:10px;bottom:10px;padding:0 0 0 .5em;font-size:2.25em}.yoast-promoblock a img{border:1px solid #dcdcdc}.yoast-promoblock p a{font-weight:600!important;text-decoration:underline}.yoast-button--extension-activated:hover,.yoast-button--extension-installed:hover,.yoast-button--extension-not-activated:hover,a.promoblock,a.promoblock:hover{text-decoration:none}.yoast-promoblock form a{font-family:"Open Sans",Arial,sans-serif;font-weight:400!important;text-decoration:none}.yoast-heading-highlight,.yoast-link--license,.yoast-link--more-info{font-weight:600;color:#a4286a}.yoast-promoblock .h4,.yoast-promoblock h4{margin-bottom:.7rem}.yoast-promoblock.link{border-color:#dc5c04}.yoast-promoblock.link a,.yoast-promoblock.link a:hover{color:#dc5c04}.yoast-promoblock--white{border-color:#fff!important}.yoast-promoblock.theme-academy a{color:#5d237a!important}.yoast-promoblock.theme-academy.secondary a{color:#a4286a!important}.yoast-promoblock.theme-software a{color:#0075b3!important}.yoast-promoblock.theme-review a{color:#009288!important}.yoast-promoblock.theme-review.secondary a{color:#77b227!important}.yoast-promoblock.theme-about a{color:#d93f69!important}.product .yoast-promoblock{overflow:hidden}.yoast-promoblock--hometitle{display:-ms-flexbox;display:flex;max-width:16em;height:11em;margin:1rem auto 2rem;border-color:#fff!important;background-color:rgba(217,63,105,.25);font-size:16px;font-size:1rem;line-height:1;-webkit-box-pack:center;-ms-flex-align:center;-ms-flex-line-pack:center;-ms-flex-pack:justify}.old-ie .yoast-promoblock--hometitle{text-align:justify}.old-ie .yoast-promoblock--hometitle::after{display:inline-block;width:100%;content:""}.old-ie .yoast-promoblock--hometitle>*{display:inline-block;text-align:left}@media only screen and (max-width:30rem){.yoast-promoblock--hometitle::after{content:none!important}}.yoast-promoblock--imageholder{margin-bottom:0;padding:0}.yoast-promoblock--imageholdersmall{position:absolute}.yoast-promoblock--imageholdersmall:first-child{left:4rem}.yoast-promoblock--imageholdersmall:last-child{top:4rem}@media only screen and (max-width:50rem){.yoast-promoblock h2{margin-bottom:0}}a.promoblock{color:#000}.promoblockimage__holder{position:relative;width:240px;height:295px}@media only screen and (min-width:50rem){[class*=promoblock--icon]::before{position:absolute;right:.47rem;bottom:.47rem;font-family:FontAwesome,"Open Sans",Arial,sans-serif;font-size:2.2rem;line-height:1}body.theme-about [class*=promoblock--icon]::before{color:#d93f69}body.theme-about .promoblock a.color-cta{color:#009288!important}body.theme-academy [class*=promoblock--icon]::before{color:#5d237a}body.theme-software [class*=promoblock--icon]::before{color:#0075b3}.promoblock--icon-academy::before{content:"\f19d"}.promoblock--icon-blog::before{content:"\f1ea"}.promoblock--icon-book::before{content:"\f02d"}.promoblock--icon-calendar::before{content:"\f073"}.promoblock--icon-check::before{content:"\f046"}.promoblock--icon-drupal::before{content:"\f1a9"}.promoblock--icon-gears::before{content:"\f085"}.promoblock--icon-pencil::before{content:"\f040"}.promoblock--icon-plug::before{content:"\f1e6"}.promoblock--icon-video::before{content:"\f008"}.promoblock--icon-wordpress::before{content:"\f19a"}}.yoast,.yoast-link--license,.yoast-link--more-info{font-family:"Open Sans",Arial,sans-serif}.yoast{color:#000;font-size:1rem;line-height:1.88;letter-spacing:.01em}.yoast-button--extension-buy:visited,.yoast-promo-extension .yoast-button--installed{color:#fff}.yoast *,.yoast :after,.yoast :before{box-sizing:border-box}.yoast-hr{position:relative;margin:0;padding-bottom:1.88rem;border:0;border-top:1px solid #a4286a}.yoast-list--usp li:before{width:1em;height:100%;background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%2377B227%22%20d%3D%22M1671%20566q0%2040%2D28%2068l%2D724%20724%2D136%20136q%2D28%2028%2D68%2028t%2D68%2D28l%2D136%2D136%2D362%2D362q%2D28%2D28%2D28%2D68t28%2D68l136%2D136q28%2D28%2068%2D28t68%2028l294%20295%20656%2D657q28%2D28%2068%2D28t68%2028l136%20136q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E") left .4em no-repeat;background-size:contain;content:""}.yoast-button--purple{background-color:#5d237a}.yoast-button-go-to:after{position:static;top:auto;right:auto;width:auto;height:auto;border:none;content:" \00BB"}.yoast-button--extension{padding-right:.8em;padding-left:.8em;color:#fff;text-transform:uppercase}.yoast-button--extension+.yoast-button--extension-activated,.yoast-button--extension+.yoast-button--extension-not-activated{margin-left:0}.yoast-button--extension-buy,.yoast-button--extension-buy:hover{background-color:#a4286a}.yoast-button--extension-installed{margin-right:.2rem}.yoast-button--extension-installed,.yoast-button--extension-installed:hover{background-color:#008a00}.yoast-button--extension-not-activated,.yoast-button--extension-not-activated:hover{background-color:#dc3232}.yoast-button--extension-activated,.yoast-button--extension-activated:hover{background-color:#008a00}.yoast-promo-extensions{display:-ms-flexbox;display:flex;margin-left:-24px;-ms-flex-wrap:wrap;flex-wrap:wrap}.yoast-promo-extensions>h2{width:100%;margin-bottom:32px;margin-left:32px}.yoast-promo-extension{max-width:340px;margin-left:32px;padding-bottom:120px;border-color:#a4286a;background-color:transparent}.yoast-promo-extension:first-child{margin-left:0}.yoast-promo-extension img{width:100%;height:auto;margin-bottom:.8rem}.yoast-promo-extension .yoast-button-container{position:absolute;right:20px;bottom:20px;left:20px}.yoast-promo-extension .yoast-button-container div.yoast-button--extension{cursor:default}.yoast-promo-extension .yoast-button{width:100%;max-height:none;font-size:.9rem}.yoast-promo-extension .yoast-button--extension{margin-top:0;font-size:.9rem;text-align:center}.yoast-promo-extension .yoast-button--extension-installed{width:48%;margin:0 2% 0 0}.yoast-promo-extension .yoast-button--extension-activated,.yoast-promo-extension .yoast-button--extension-not-activated{width:48%;margin-right:0;margin-left:0}.yoast-promo-extension h3{color:#a4286a}@media screen and (max-width:900px){.yoast-promo-extension img{display:none}.yoast-promo-extension{width:100%;max-width:none}}.yoast-seo-premium-extension{margin:2em .5em 1.5em}.yoast-seo-premium-extension:after,.yoast-seo-premium-extension:before{display:table;content:""}.yoast-seo-premium-extension:after{clear:both}.yoast-seo-premium-benefits__title{font-weight:600}.yoast-seo-premium-benefits__description:before{content:"– "}.yoast-link--license:after,.yoast-link--more-info:after{content:" \00BB"}.yoast-link--license{margin:1em 0 0}.yoast-promo-extension .yoast-link--license{display:block;margin:1em 0 0}.yoast-link--more-info{padding-left:calc(1em + 5px);background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%23A4286A%22%20d%3D%22M1152%201376v%2D160q0%2D14%2D9%2D23t%2D23%2D9h%2D96v%2D512q0%2D14%2D9%2D23t%2D23%2D9h%2D320q%2D14%200%2D23%209t%2D9%2023v160q0%2014%209%2023t23%209h96v320h%2D96q%2D14%200%2D23%209t%2D9%2023v160q0%2014%209%2023t23%209h448q14%200%2023%2D9t9%2D23zm%2D128%2D896v%2D160q0%2D14%2D9%2D23t%2D23%2D9h%2D192q%2D14%200%2D23%209t%2D9%2023v160q0%2014%209%2023t23%209h192q14%200%2023%2D9t9%2D23zm640%20416q0%20209%2D103%20385%2E5t%2D279%2E5%20279%2E5%2D385%2E5%20103%2D385%2E5%2D103%2D279%2E5%2D279%2E5%2D103%2D385%2E5%20103%2D385%2E5%20279%2E5%2D279%2E5%20385%2E5%2D103%20385%2E5%20103%20279%2E5%20279%2E5%20103%20385%2E5z%22%2F%3E%3C%2Fsvg%3E") left .2em no-repeat;background-size:1em}.yoast-promo-extension .yoast-link--more-info{display:block;margin:1em 0 0;background-position:left .4em}.yoast-money-back-guarantee{font-size:1.1em;font-style:italic}.yoast-license-status-active{padding:3px 6px;color:#fff;background:#008a00}.yoast-license-status-inactive{padding:3px 6px;color:#fff;background:#dc3232} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-1720-rtl.css new file mode 100644 index 00000000..aa0d31b3 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-1720-rtl.css @@ -0,0 +1 @@ +:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")}.wpseo_content_wrapper{display:table;width:100%;table-layout:fixed}.wpseo_content_cell{display:table-cell;height:500px;margin:0;padding:0;vertical-align:top}#wpseo_content_top{width:100%}tr.yst_row{margin:5px 0 0;padding:5px 0 0}#sidebar-container{width:300px;padding-right:20px}tr.yst_row.even{background-color:#f6f6f6}.wpseo_content_wrapper label.select,.wpseo_content_wrapper label.textinput{float:right;width:200px;margin:5px 0}.wpseo_content_wrapper label.select.error,.wpseo_content_wrapper label.textinput.error{color:#dc3232;font-weight:700}.wpseo_content_wrapper .yoast-inline-label{float:none;display:inline-block;margin:0 0 8px}.wpseo_content_wrapper input.textinput,.wpseo_content_wrapper select,.wpseo_content_wrapper textarea{width:400px}.wpseo_content_wrapper input.large-text,.wpseo_content_wrapper textarea.large-text{width:99%}.wpseo_content_wrapper .select2-container,.wpseo_content_wrapper input.textinput,.wpseo_content_wrapper select.select,.wpseo_content_wrapper textarea.textinput{margin:0 0 15px}.wpseo_content_wrapper input.textinput[aria-invalid=true]{color:#000;background:#f9dcdc url(../../images/error-icon.svg) no-repeat calc(100% - (100% - 6px)) 50%;background-size:12px;border:1px solid #dc3232;padding-left:24px}.wpseo_content_wrapper input.textinput[aria-invalid=true][aria-describedby]{margin-bottom:.5rem}.wpseo_content_wrapper .yoast-input-validation__error-description{width:400px;padding-right:200px;margin:0 0 1rem;color:#8f1919}.wpseo_content_wrapper input.checkbox,.wpseo_content_wrapper input.checkbox.double,.wpseo_content_wrapper input.radio{margin:6px 0 6px 10px}.wpseo_content_wrapper .textinput.metadesc{height:50px}.wpseo_content_wrapper textarea.import{width:500px;height:100px}.wpseo_content_wrapper p.desc{margin:6px 0 10px;padding:0 25px 8px 0}.wpseo_content_wrapper div.desc.label,.wpseo_content_wrapper p.desc.label{margin:0 0 20px;padding:0 200px 10px 0}.wpseo_content_wrapper h4{clear:both;margin:1.2em 0 .5em}.wpseo_content_wrapper .postbox{margin:10px 0 0 10px}.wpseo_content_wrapper .postbox form{line-height:150%}.wpseo_content_wrapper .text{width:250px}.wpseo_content_wrapper .correct{padding:5px;color:#fff;background-color:green}.wpseo_content_wrapper .wrong{padding:5px;color:#fff;background-color:#dc3232}.wpseo_content_wrapper .wrong code{padding:3px 8px;color:#000}.wpseo_content_wrapper .button.fixit{float:left;margin:0 5px}.wpseo_content_wrapper .button.checkit{float:left;margin:0 5px;padding:5px 8px}.wpseo_content_wrapper .disabled-note{margin:0 0 8px;color:#888}.wpseo_content_wrapper #separator{margin:1em 0 0}.wpseo_content_wrapper #separator input.radio{position:absolute;right:-9999em;width:1px;height:1px}.wpseo_content_wrapper #separator input.radio+label{float:right;width:30px!important;margin:.5em 0 0 5px!important;padding:9px 6px;border:1px solid #ccc;font-family:Arial,Helvetica,sans-serif!important;font-size:18px!important;line-height:24px;text-align:center;cursor:pointer}.wpseo_content_wrapper #separator input.radio:checked+label{border:3px solid #a4286a;background-color:#fff;padding:7px 4px}.wpseo_content_wrapper #separator input.radio:focus+label{outline:2px solid #5b9dd9}.wpseo_content_wrapper .svg-container{text-align:center}.wpseo_content_wrapper .svg-container .dashicons{width:200px;height:100px;font-size:100px}.wpseo_content_wrapper .paper.tab-block button.toggleable-container-trigger{width:100%;padding:16px;font-size:1.0625rem}.wpseo_content_wrapper .paper.tab-block button.toggleable-container-trigger:focus{outline:1px solid #0066cd;outline-offset:-1px;box-shadow:0 0 3px rgba(8,74,103,.8)}.wpseo_content_wrapper .paper.tab-block button.toggleable-container-trigger:active{box-shadow:none}.wpseo_content_wrapper .paper.tab-block h2.collapsible-header{margin:0!important;padding:0!important}.wpseo_content_wrapper .paper.tab-block.metabox button.toggleable-container-trigger{color:#555}.wpseo_content_wrapper .paper.tab-block.metabox.wpseotab{padding:0;border:0}.wpseo_content_wrapper .paper.tab-block.search-appearance{max-width:632px;box-shadow:0 1px 2px rgba(0,0,0,.2);background-color:#fff}.wpseo_content_wrapper .paper.tab-block .paper-container{padding:16px}.wpseo_content_wrapper .paper.tab-block.has-paper-container-no-top-padding .paper-container{padding-top:0}.wpseo_content_wrapper .paper.tab-block .paper-container:first-child{margin-top:0}.wpseo_content_wrapper .paper.tab-block .paper-title{padding:16px}.wpseo_content_wrapper .paper.tab-block .paper-title h2{margin:0}.wpseo_content_wrapper .paper.tab-block .tab-block:first-child{margin-top:0}.wpseo_content_wrapper .wpseo-collapsible-container{background-color:#fff;border-top:1px solid #e2e4e7;border-bottom:1px solid #e2e4e7;margin-top:-1px}.wpseo_content_wrapper .toggleable-container-trigger{border:0;background:none;cursor:pointer;width:100%;padding:0;text-align:right}.wpseo_content_wrapper .toggleable-container-icon{float:left;width:20px;height:20px;position:relative}.wpseo_content_wrapper .toggleable-container-trigger .toggleable-container-icon:after{content:"";display:block;padding:14px;position:absolute;top:-4px;right:-4px}.wpseo_content_wrapper .toggleable-container-hidden{display:none}.wpseo_content_wrapper h3{font-size:1.15em;margin:1em 0 .5em}.wpseo_content_wrapper h3.h2{font-size:1.3em}.wpseo_content_wrapper li,.wpseo_content_wrapper p{max-width:600px}.wpseo_content_wrapper .notice p,.yoast-container .container,.yoast-notification p,.yoast .search-box{max-width:none}table.wpseo th{text-align:right}#wpseo-tabs+.notice{margin-top:1.5em}.wpseo-variable-warning-element{border:1px solid #c62d2d!important}.wpseo-variable-warning{clear:both;margin:5px 0 0;padding:5px;color:#c62d2d}.wpseo-variable-warning code{color:#b02828}.wpseo-variable-warning a{color:#c62d2d}.wpseo_content_wrapper h1.wpseo-redirect-url-title{margin:1em 0 .5em;font-size:1.3em}table.yoast_help{border-collapse:collapse;width:100%}table.yoast_help,table.yoast_help td,table.yoast_help th{border:1px solid #ddd;color:#444}table.yoast_help td,table.yoast_help th{padding:5px 10px;text-align:right;vertical-align:top}table.yoast_help tr{background-color:#f1f1f1}table.yoast_help tr:nth-child(2n){background-color:#fbfbfe}table.yoast_help tr:hover{background-color:#ddd}table.yoast_help thead tr,table.yoast_help thead tr:hover{background-color:#fff}table.yoast_help .yoast-variable-name{font-weight:600;white-space:nowrap}table.yoast_help .yoast-variable-desc{min-width:300px}.yoast-notice-blocking-files code{line-height:2;color:#000}.yoast-notice-blocking-files .button{margin:.5em 0}.wpseo_content_wrapper .yoast-blocking-files-error p{max-width:none}.wpseotab{display:none}.wpseotab.active{display:block}.wpseotab p.expl{margin-right:6px}.wpseotab .tab-block{display:block;margin:30px 0}.wpseotab p.expl strong{font-size:115%}#wpseo-debug-info{clear:both;margin:20px 0 0;padding:20px 20px 0;border:1px solid #e5e5e5;background-color:#fff;box-shadow:0 1px 1px rgba(0,0,0,.04)}#wpseo-debug-info h2{margin:0;cursor:auto}#wpseo-debug-info .wpseo-debug-heading{font-size:1em}#wpseo-debug-info .wpseo-debug{display:inline-block;padding-right:20px;color:#c00}input.wpseo-new-title,textarea.wpseo-new-metadesc{width:100%;max-width:100%}body.toplevel_page_wpseo_dashboard .wp-badge{background:transparent url(../../packages/js/images/Yoast_SEO_Icon.svg) no-repeat 50% 10px;background-size:140px 140px;box-shadow:none}#wpseo_progressbar{height:25px;border:1px solid #006691}#wpseo_progressbar .ui-progressbar-value{height:25px;background:#006691}.wpseo-progressbar-wrapper{display:inline;width:100%}.wpseo-progressbar{display:block;width:100%;height:25px;border:1px solid #006691}.wpseo-progressbar .ui-progressbar-value{height:25px;background:#006691}.yoast-sidebar__title{width:100%;margin:5px 0;padding:10px 0;color:#a4286a;text-align:right;box-sizing:border-box;line-height:19px;border-bottom:1px solid #a4286a}.yoast-sidebar__section{box-shadow:0 1px 6px 0 rgba(0,0,0,.3);border:1px solid #dcdcdc;background-color:#fff;padding:16px;margin:10px 0 20px}.yoast-sidebar__section h2{margin-top:0;color:#a4286a}.yoast-sidebar__section a{color:#0085ba}.yoast-sidebar__section ul{position:relative}.yoast-sidebar__section li{list-style:none;margin-right:20px}.yoast-sidebar__section li:before{content:"+";position:absolute;right:0;font-weight:700}.yoast-sidebar__section div{position:relative;margin:10px 0 20px}.yoast-sidebar__section div img{float:left;width:70px;height:70px;margin:0 10px 0 0}.yoast-sidebar__section div img.alignleft{margin:0 0 0 10px;float:right}.yoast-sidebar__section div p{float:right;width:100%;margin:0}.wpseo-banner__link{display:inline-block}.wpseo-banner__image{vertical-align:top}.yoast_premium_upsell{box-shadow:0 1px 6px 0 rgba(0,0,0,.3);border:1px solid #dcdcdc;padding:16px;background-color:#fff;max-width:640px;overflow:hidden;margin-top:2em}.yoast_premium_upsell--header{color:#a4286a;margin-top:.3em;font-size:1.7em;font-weight:700}.yoast_premium_upsell--motivation{display:flex;flex-wrap:wrap}.yoast_premium_upsell--motivation li{flex:0 0 50%;list-style:none}.yoast_premium_upsell--argument{padding:0 20px 0 8px}.yoast_premium_upsell--argument:before{position:relative;right:-16px;margin-left:-10px;font-weight:700;content:"+";top:-1px}@media screen and (max-width:480px){.yoast_premium_upsell--motivation{display:block}}.yoast-variable-desc{min-width:300px}.yoast-table-scrollable,.yoast-table-scrollable td,.yoast-table-scrollable th{box-sizing:border-box}.yoast-table-scrollable__container.yoast-has-scroll{position:relative;overflow:hidden}.yoast-table-scrollable__container.yoast-has-scroll:after{content:"";position:absolute;top:0;right:100%;width:50px;height:calc(100% - 16px);border-radius:0 10px 10px 0/0 50% 50% 0;box-shadow:5px 0 10px rgba(0,0,0,.25)}.yoast-table-scrollable__container.yoast-has-scroll .yoast-table-scrollable__inner{overflow-x:scroll;padding-bottom:16px}.yoast-table-scrollable__hintwrapper{display:none}.yoast-table-scrollable__hintwrapper.yoast-has-scroll{display:block;margin:1em 0;text-align:center}.yoast-has-scroll .yoast-table-scrollable__hint{display:inline-block}.yoast-has-scroll .yoast-table-scrollable__hint:before{content:"\21c4";display:inline-block;margin-left:10px;font-size:20px;line-height:inherit;vertical-align:text-top}.yoast-styled-select{display:inline-flex;align-items:center;position:relative;margin-bottom:1em}.yoast-styled-select:after,.yoast-styled-select:before{content:"";position:absolute;top:0;bottom:0;pointer-events:none}.yoast-styled-select:before{width:28px;left:0}.yoast-styled-select:after{width:0;height:0;border-top:4px solid transparent;border-color:#555 transparent transparent;border-style:solid;border-width:5px 4px 0;margin:auto;left:6px;z-index:1}.yoast-styled-select select{height:28px;box-sizing:border-box;margin:0;padding:4px 8px 4px 32px;max-width:100%;-webkit-appearance:none;appearance:none;background:transparent;border:1px solid #aaa;border-radius:4px;line-height:1;color:#32373c}.yoast-styled-select select.error{border-color:#dc3232;border-width:2px}.wpseo_content_wrapper .yoast-styled-select select.select{margin:0}.yoast-styled-select select:focus{border-color:#5b9dd9}.yoast-styled-select select:-moz-focusring{color:transparent;text-shadow:0 0 0 #32373c}.yoast-styled-select select[disabled]{opacity:.75}.yoast-styled-select select::-ms-expand{display:none}@media screen and (max-width:1024px){.wpseo_content_cell,.wpseo_content_wrapper{display:block;height:auto}#wpseo_content_top{width:auto}#sidebar-container{width:auto;padding:0}.yoast-sidebar__product-list{display:flex;border-bottom:1px solid #ddd}.yoast-sidebar__product-list div p{word-wrap:break-word;width:calc(100% - 50px)}.yoast-sidebar__product-list .yoast-sidebar__section{border-bottom:none}.yoast-sidebar__product-list .yoast-sidebar__section:first-child{margin-left:40px}}@media screen and (max-width:782px){.wpseo_content_wrapper label.select,.wpseo_content_wrapper label.textinput{display:inline-block;float:none;width:auto}.wpseo_content_wrapper input.textinput,.wpseo_content_wrapper textarea,.wpseo_content_wrapper textarea.textinput{display:block;width:100%}.wpseo_content_wrapper .select2-container,.wpseo_content_wrapper select,.wpseo_content_wrapper select.select{display:block;max-width:100%;margin:0 0 5px}.wpseo_content_wrapper div.desc.label,.wpseo_content_wrapper p.desc.label{padding-right:0}.wpseo_content_wrapper .textinput[aria-invalid=true][aria-describedby]+br{display:none}.wpseo_content_wrapper .yoast-input-validation__error-description{width:auto;padding-right:0}}@media screen and (max-width:600px){.yoast-sidebar__product-list{display:block;border-bottom:none}.yoast-sidebar__product-list .yoast-sidebar__section{border-bottom:1px solid #ddd}.yoast-sidebar__product-list .yoast-sidebar__section p{word-wrap:break-word;width:calc(100% - 50px);padding-right:50px}}@media screen and (max-width:500px){body.toplevel_page_wpseo_dashboard .wp-badge{padding-top:80px;background-size:100px 100px;background-color:#a4286a;box-shadow:0 1px 3px rgba(0,0,0,.2)}}.wpseo-checkmark-ok-icon{float:right;width:18px;margin-left:5px;height:18px;background:var(--yoast-svg-icon-check-ok) no-repeat;background-size:18px;vertical-align:top}.yoast-settings-section:not(:last-child){margin-bottom:40px}.yoast-settings-section .yoast-field-group__title .yoast_help.yoast-help-link{margin:-6px 2px 0 0}#yoast-og-default-image-select .yoast-field-group__title{display:none}.yoast-settings-section.yoast-settings-section-disabled{position:relative;padding:16px;border:1px solid #ccc}.yoast-settings-section.yoast-settings-section-disabled>*{opacity:.5}.yoast-settings-section.yoast-settings-section-disabled .yoast-settings-section-upsell{opacity:1;position:absolute;top:0;bottom:0;right:0;left:0;display:flex;justify-content:center;align-items:center} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-1720.css b/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-1720.css new file mode 100644 index 00000000..9bb96641 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-1720.css @@ -0,0 +1 @@ +:root{--yoast-svg-icon-info:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23A4286A' d='M1152 1376v-160q0-14-9-23t-23-9h-96V672q0-14-9-23t-23-9H672q-14 0-23 9t-9 23v160q0 14 9 23t23 9h96v320h-96q-14 0-23 9t-9 23v160q0 14 9 23t23 9h448q14 0 23-9t9-23zm-128-896V320q0-14-9-23t-23-9H800q-14 0-23 9t-9 23v160q0 14 9 23t23 9h192q14 0 23-9t9-23zm640 416q0 209-103 385.5T1281.5 1561 896 1664t-385.5-103T231 1281.5 128 896t103-385.5T510.5 231 896 128t385.5 103T1561 510.5 1664 896z'/%3E%3C/svg%3E");--yoast-svg-icon-check:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-check-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%2377B227' d='M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-right:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z'/%3E%3C/svg%3E");--yoast-svg-icon-caret-left:url("data:image/svg+xml;charset=utf-8,%3Csvg width='16' height='16' viewBox='0 0 192 512' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z'/%3E%3C/svg%3E");--yoast-svg-icon-eye:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5T896 1280t-316.5-131.5T448 832q0-121 61-225-229 117-381 353 133 205 333.5 326.5T896 1408t434.5-121.5T1664 960zM944 576q0-20-14-34t-34-14q-125 0-214.5 89.5T592 832q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5T896 1536t-499.5-139T20 1029Q0 994 0 960t20-69q140-229 376.5-368T896 384t499.5 139T1772 891q20 35 20 69z'/%3E%3C/svg%3E");--yoast-svg-icon-list:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M384 1408q0 80-56 136t-136 56-136-56-56-136 56-136 136-56 136 56 56 136zm0-512q0 80-56 136t-136 56-136-56T0 896t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 1504v-192q0-13 9.5-22.5t22.5-9.5h1216q13 0 22.5 9.5t9.5 22.5zM384 384q0 80-56 136t-136 56-136-56T0 384t56-136 136-56 136 56 56 136zm1408 416v192q0 13-9.5 22.5t-22.5 9.5H544q-13 0-22.5-9.5T512 992V800q0-13 9.5-22.5T544 768h1216q13 0 22.5 9.5t9.5 22.5zm0-512v192q0 13-9.5 22.5T1760 512H544q-13 0-22.5-9.5T512 480V288q0-13 9.5-22.5T544 256h1216q13 0 22.5 9.5t9.5 22.5z'/%3E%3C/svg%3E");--yoast-svg-icon-key:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M832 512q0-80-56-136t-136-56-136 56-56 136q0 42 19 83-41-19-83-19-80 0-136 56t-56 136 56 136 136 56 136-56 56-136q0-42-19-83 41 19 83 19 80 0 136-56t56-136zm851 704q0 17-49 66t-66 49q-9 0-28.5-16t-36.5-33-38.5-40-24.5-26l-96 96 220 220q28 28 28 68 0 42-39 81t-81 39q-40 0-68-28l-671-671q-176 131-365 131-163 0-265.5-102.5T0 784q0-160 95-313t248-248 313-95q163 0 265.5 102.5T1024 496q0 189-131 365l355 355 96-96q-3-3-26-24.5t-40-38.5-33-36.5-16-28.5q0-17 49-66t66-49q13 0 23 10 6 6 46 44.5t82 79.5 86.5 86 73 78 28.5 41z'/%3E%3C/svg%3E");--yoast-svg-icon-edit:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23555' d='M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832H128v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23999' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-good:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%237ad03a' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-ok:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23ee7c1b' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-bad:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%23dc3232' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E");--yoast-svg-icon-yoast-noindex:url("data:image/svg+xml;charset=utf-8,%3Csvg width='1792' height='1792' xmlns='http://www.w3.org/2000/svg' aria-hidden='true'%3E%3Cpath fill='%231e8cbe' d='M403 218h691l-26 72H403q-110 0-188.5 79T136 558v771q0 95 60.5 169.5T350 1592q23 5 98 5v72h-45q-140 0-239.5-100T64 1329V558q0-140 99.5-240T403 218zM1254 0h247l-482 1294q-23 61-40.5 103.5t-45 98-54 93.5-64.5 78.5-79.5 65-95.5 41-116 18.5v-195q163-26 220-182 20-52 20-105 0-54-20-106L459 471h228l187 585zm474 558v1111H933q37-55 45-73h678V558q0-85-49.5-155T1477 304l25-67q101 34 163.5 123.5T1728 558z'/%3E%3C/svg%3E")}.wpseo_content_wrapper{display:table;width:100%;table-layout:fixed}.wpseo_content_cell{display:table-cell;height:500px;margin:0;padding:0;vertical-align:top}#wpseo_content_top{width:100%}tr.yst_row{margin:5px 0 0;padding:5px 0 0}#sidebar-container{width:300px;padding-left:20px}tr.yst_row.even{background-color:#f6f6f6}.wpseo_content_wrapper label.select,.wpseo_content_wrapper label.textinput{float:left;width:200px;margin:5px 0}.wpseo_content_wrapper label.select.error,.wpseo_content_wrapper label.textinput.error{color:#dc3232;font-weight:700}.wpseo_content_wrapper .yoast-inline-label{float:none;display:inline-block;margin:0 0 8px}.wpseo_content_wrapper input.textinput,.wpseo_content_wrapper select,.wpseo_content_wrapper textarea{width:400px}.wpseo_content_wrapper input.large-text,.wpseo_content_wrapper textarea.large-text{width:99%}.wpseo_content_wrapper .select2-container,.wpseo_content_wrapper input.textinput,.wpseo_content_wrapper select.select,.wpseo_content_wrapper textarea.textinput{margin:0 0 15px}.wpseo_content_wrapper input.textinput[aria-invalid=true]{color:#000;background:#f9dcdc url(../../images/error-icon.svg) no-repeat calc(100% - 6px) 50%;background-size:12px;border:1px solid #dc3232;padding-right:24px}.wpseo_content_wrapper input.textinput[aria-invalid=true][aria-describedby]{margin-bottom:.5rem}.wpseo_content_wrapper .yoast-input-validation__error-description{width:400px;padding-left:200px;margin:0 0 1rem;color:#8f1919}.wpseo_content_wrapper input.checkbox,.wpseo_content_wrapper input.checkbox.double,.wpseo_content_wrapper input.radio{margin:6px 10px 6px 0}.wpseo_content_wrapper .textinput.metadesc{height:50px}.wpseo_content_wrapper textarea.import{width:500px;height:100px}.wpseo_content_wrapper p.desc{margin:6px 0 10px;padding:0 0 8px 25px}.wpseo_content_wrapper div.desc.label,.wpseo_content_wrapper p.desc.label{margin:0 0 20px;padding:0 0 10px 200px}.wpseo_content_wrapper h4{clear:both;margin:1.2em 0 .5em}.wpseo_content_wrapper .postbox{margin:10px 10px 0 0}.wpseo_content_wrapper .postbox form{line-height:150%}.wpseo_content_wrapper .text{width:250px}.wpseo_content_wrapper .correct{padding:5px;color:#fff;background-color:green}.wpseo_content_wrapper .wrong{padding:5px;color:#fff;background-color:#dc3232}.wpseo_content_wrapper .wrong code{padding:3px 8px;color:#000}.wpseo_content_wrapper .button.fixit{float:right;margin:0 5px}.wpseo_content_wrapper .button.checkit{float:right;margin:0 5px;padding:5px 8px}.wpseo_content_wrapper .disabled-note{margin:0 0 8px;color:#888}.wpseo_content_wrapper #separator{margin:1em 0 0}.wpseo_content_wrapper #separator input.radio{position:absolute;left:-9999em;width:1px;height:1px}.wpseo_content_wrapper #separator input.radio+label{float:left;width:30px!important;margin:.5em 5px 0 0!important;padding:9px 6px;border:1px solid #ccc;font-family:Arial,Helvetica,sans-serif!important;font-size:18px!important;line-height:24px;text-align:center;cursor:pointer}.wpseo_content_wrapper #separator input.radio:checked+label{border:3px solid #a4286a;background-color:#fff;padding:7px 4px}.wpseo_content_wrapper #separator input.radio:focus+label{outline:2px solid #5b9dd9}.wpseo_content_wrapper .svg-container{text-align:center}.wpseo_content_wrapper .svg-container .dashicons{width:200px;height:100px;font-size:100px}.wpseo_content_wrapper .paper.tab-block button.toggleable-container-trigger{width:100%;padding:16px;font-size:1.0625rem}.wpseo_content_wrapper .paper.tab-block button.toggleable-container-trigger:focus{outline:1px solid #0066cd;outline-offset:-1px;box-shadow:0 0 3px rgba(8,74,103,.8)}.wpseo_content_wrapper .paper.tab-block button.toggleable-container-trigger:active{box-shadow:none}.wpseo_content_wrapper .paper.tab-block h2.collapsible-header{margin:0!important;padding:0!important}.wpseo_content_wrapper .paper.tab-block.metabox button.toggleable-container-trigger{color:#555}.wpseo_content_wrapper .paper.tab-block.metabox.wpseotab{padding:0;border:0}.wpseo_content_wrapper .paper.tab-block.search-appearance{max-width:632px;box-shadow:0 1px 2px rgba(0,0,0,.2);background-color:#fff}.wpseo_content_wrapper .paper.tab-block .paper-container{padding:16px}.wpseo_content_wrapper .paper.tab-block.has-paper-container-no-top-padding .paper-container{padding-top:0}.wpseo_content_wrapper .paper.tab-block .paper-container:first-child{margin-top:0}.wpseo_content_wrapper .paper.tab-block .paper-title{padding:16px}.wpseo_content_wrapper .paper.tab-block .paper-title h2{margin:0}.wpseo_content_wrapper .paper.tab-block .tab-block:first-child{margin-top:0}.wpseo_content_wrapper .wpseo-collapsible-container{background-color:#fff;border-top:1px solid #e2e4e7;border-bottom:1px solid #e2e4e7;margin-top:-1px}.wpseo_content_wrapper .toggleable-container-trigger{border:0;background:none;cursor:pointer;width:100%;padding:0;text-align:left}.wpseo_content_wrapper .toggleable-container-icon{float:right;width:20px;height:20px;position:relative}.wpseo_content_wrapper .toggleable-container-trigger .toggleable-container-icon:after{content:"";display:block;padding:14px;position:absolute;top:-4px;left:-4px}.wpseo_content_wrapper .toggleable-container-hidden{display:none}.wpseo_content_wrapper h3{font-size:1.15em;margin:1em 0 .5em}.wpseo_content_wrapper h3.h2{font-size:1.3em}.wpseo_content_wrapper li,.wpseo_content_wrapper p{max-width:600px}.wpseo_content_wrapper .notice p,.yoast-container .container,.yoast-notification p,.yoast .search-box{max-width:none}table.wpseo th{text-align:left}#wpseo-tabs+.notice{margin-top:1.5em}.wpseo-variable-warning-element{border:1px solid #c62d2d!important}.wpseo-variable-warning{clear:both;margin:5px 0 0;padding:5px;color:#c62d2d}.wpseo-variable-warning code{color:#b02828}.wpseo-variable-warning a{color:#c62d2d}.wpseo_content_wrapper h1.wpseo-redirect-url-title{margin:1em 0 .5em;font-size:1.3em}table.yoast_help{border-collapse:collapse;width:100%}table.yoast_help,table.yoast_help td,table.yoast_help th{border:1px solid #ddd;color:#444}table.yoast_help td,table.yoast_help th{padding:5px 10px;text-align:left;vertical-align:top}table.yoast_help tr{background-color:#f1f1f1}table.yoast_help tr:nth-child(2n){background-color:#fbfbfe}table.yoast_help tr:hover{background-color:#ddd}table.yoast_help thead tr,table.yoast_help thead tr:hover{background-color:#fff}table.yoast_help .yoast-variable-name{font-weight:600;white-space:nowrap}table.yoast_help .yoast-variable-desc{min-width:300px}.yoast-notice-blocking-files code{line-height:2;color:#000}.yoast-notice-blocking-files .button{margin:.5em 0}.wpseo_content_wrapper .yoast-blocking-files-error p{max-width:none}.wpseotab{display:none}.wpseotab.active{display:block}.wpseotab p.expl{margin-left:6px}.wpseotab .tab-block{display:block;margin:30px 0}.wpseotab p.expl strong{font-size:115%}#wpseo-debug-info{clear:both;margin:20px 0 0;padding:20px 20px 0;border:1px solid #e5e5e5;background-color:#fff;box-shadow:0 1px 1px rgba(0,0,0,.04)}#wpseo-debug-info h2{margin:0;cursor:auto}#wpseo-debug-info .wpseo-debug-heading{font-size:1em}#wpseo-debug-info .wpseo-debug{display:inline-block;padding-left:20px;color:#c00}input.wpseo-new-title,textarea.wpseo-new-metadesc{width:100%;max-width:100%}body.toplevel_page_wpseo_dashboard .wp-badge{background:transparent url(../../packages/js/images/Yoast_SEO_Icon.svg) no-repeat 50% 10px;background-size:140px 140px;box-shadow:none}#wpseo_progressbar{height:25px;border:1px solid #006691}#wpseo_progressbar .ui-progressbar-value{height:25px;background:#006691}.wpseo-progressbar-wrapper{display:inline;width:100%}.wpseo-progressbar{display:block;width:100%;height:25px;border:1px solid #006691}.wpseo-progressbar .ui-progressbar-value{height:25px;background:#006691}.yoast-sidebar__title{width:100%;margin:5px 0;padding:10px 0;color:#a4286a;text-align:left;box-sizing:border-box;line-height:19px;border-bottom:1px solid #a4286a}.yoast-sidebar__section{box-shadow:0 1px 6px 0 rgba(0,0,0,.3);border:1px solid #dcdcdc;background-color:#fff;padding:16px;margin:10px 0 20px}.yoast-sidebar__section h2{margin-top:0;color:#a4286a}.yoast-sidebar__section a{color:#0085ba}.yoast-sidebar__section ul{position:relative}.yoast-sidebar__section li{list-style:none;margin-left:20px}.yoast-sidebar__section li:before{content:"+";position:absolute;left:0;font-weight:700}.yoast-sidebar__section div{position:relative;margin:10px 0 20px}.yoast-sidebar__section div img{float:right;width:70px;height:70px;margin:0 0 0 10px}.yoast-sidebar__section div img.alignleft{margin:0 10px 0 0;float:left}.yoast-sidebar__section div p{float:left;width:100%;margin:0}.wpseo-banner__link{display:inline-block}.wpseo-banner__image{vertical-align:top}.yoast_premium_upsell{box-shadow:0 1px 6px 0 rgba(0,0,0,.3);border:1px solid #dcdcdc;padding:16px;background-color:#fff;max-width:640px;overflow:hidden;margin-top:2em}.yoast_premium_upsell--header{color:#a4286a;margin-top:.3em;font-size:1.7em;font-weight:700}.yoast_premium_upsell--motivation{display:flex;flex-wrap:wrap}.yoast_premium_upsell--motivation li{flex:0 0 50%;list-style:none}.yoast_premium_upsell--argument{padding:0 8px 0 20px}.yoast_premium_upsell--argument:before{position:relative;left:-16px;margin-right:-10px;font-weight:700;content:"+";top:-1px}@media screen and (max-width:480px){.yoast_premium_upsell--motivation{display:block}}.yoast-variable-desc{min-width:300px}.yoast-table-scrollable,.yoast-table-scrollable td,.yoast-table-scrollable th{box-sizing:border-box}.yoast-table-scrollable__container.yoast-has-scroll{position:relative;overflow:hidden}.yoast-table-scrollable__container.yoast-has-scroll:after{content:"";position:absolute;top:0;left:100%;width:50px;height:calc(100% - 16px);border-radius:10px 0 0 10px/50% 0 0 50%;box-shadow:-5px 0 10px rgba(0,0,0,.25)}.yoast-table-scrollable__container.yoast-has-scroll .yoast-table-scrollable__inner{overflow-x:scroll;padding-bottom:16px}.yoast-table-scrollable__hintwrapper{display:none}.yoast-table-scrollable__hintwrapper.yoast-has-scroll{display:block;margin:1em 0;text-align:center}.yoast-has-scroll .yoast-table-scrollable__hint{display:inline-block}.yoast-has-scroll .yoast-table-scrollable__hint:before{content:"\21c4";display:inline-block;margin-right:10px;font-size:20px;line-height:inherit;vertical-align:text-top}.yoast-styled-select{display:inline-flex;align-items:center;position:relative;margin-bottom:1em}.yoast-styled-select:after,.yoast-styled-select:before{content:"";position:absolute;top:0;bottom:0;pointer-events:none}.yoast-styled-select:before{width:28px;right:0}.yoast-styled-select:after{width:0;height:0;border-top:4px solid transparent;border-color:#555 transparent transparent;border-style:solid;border-width:5px 4px 0;margin:auto;right:6px;z-index:1}.yoast-styled-select select{height:28px;box-sizing:border-box;margin:0;padding:4px 32px 4px 8px;max-width:100%;-webkit-appearance:none;appearance:none;background:transparent;border:1px solid #aaa;border-radius:4px;line-height:1;color:#32373c}.yoast-styled-select select.error{border-color:#dc3232;border-width:2px}.wpseo_content_wrapper .yoast-styled-select select.select{margin:0}.yoast-styled-select select:focus{border-color:#5b9dd9}.yoast-styled-select select:-moz-focusring{color:transparent;text-shadow:0 0 0 #32373c}.yoast-styled-select select[disabled]{opacity:.75}.yoast-styled-select select::-ms-expand{display:none}@media screen and (max-width:1024px){.wpseo_content_cell,.wpseo_content_wrapper{display:block;height:auto}#wpseo_content_top{width:auto}#sidebar-container{width:auto;padding:0}.yoast-sidebar__product-list{display:flex;border-bottom:1px solid #ddd}.yoast-sidebar__product-list div p{word-wrap:break-word;width:calc(100% - 50px)}.yoast-sidebar__product-list .yoast-sidebar__section{border-bottom:none}.yoast-sidebar__product-list .yoast-sidebar__section:first-child{margin-right:40px}}@media screen and (max-width:782px){.wpseo_content_wrapper label.select,.wpseo_content_wrapper label.textinput{display:inline-block;float:none;width:auto}.wpseo_content_wrapper input.textinput,.wpseo_content_wrapper textarea,.wpseo_content_wrapper textarea.textinput{display:block;width:100%}.wpseo_content_wrapper .select2-container,.wpseo_content_wrapper select,.wpseo_content_wrapper select.select{display:block;max-width:100%;margin:0 0 5px}.wpseo_content_wrapper div.desc.label,.wpseo_content_wrapper p.desc.label{padding-left:0}.wpseo_content_wrapper .textinput[aria-invalid=true][aria-describedby]+br{display:none}.wpseo_content_wrapper .yoast-input-validation__error-description{width:auto;padding-left:0}}@media screen and (max-width:600px){.yoast-sidebar__product-list{display:block;border-bottom:none}.yoast-sidebar__product-list .yoast-sidebar__section{border-bottom:1px solid #ddd}.yoast-sidebar__product-list .yoast-sidebar__section p{word-wrap:break-word;width:calc(100% - 50px);padding-left:50px}}@media screen and (max-width:500px){body.toplevel_page_wpseo_dashboard .wp-badge{padding-top:80px;background-size:100px 100px;background-color:#a4286a;box-shadow:0 1px 3px rgba(0,0,0,.2)}}.wpseo-checkmark-ok-icon{float:left;width:18px;margin-right:5px;height:18px;background:var(--yoast-svg-icon-check-ok) no-repeat;background-size:18px;vertical-align:top}.yoast-settings-section:not(:last-child){margin-bottom:40px}.yoast-settings-section .yoast-field-group__title .yoast_help.yoast-help-link{margin:-6px 0 0 2px}#yoast-og-default-image-select .yoast-field-group__title{display:none}.yoast-settings-section.yoast-settings-section-disabled{position:relative;padding:16px;border:1px solid #ccc}.yoast-settings-section.yoast-settings-section-disabled>*{opacity:.5}.yoast-settings-section.yoast-settings-section-disabled .yoast-settings-section-upsell{opacity:1;position:absolute;top:0;bottom:0;left:0;right:0;display:flex;justify-content:center;align-items:center} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-720-rtl.min.css deleted file mode 100644 index bc81e16b..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -.yoast-variable-desc,table.yoast_help .yoast-variable-desc{min-width:300px}.yoast-sidebar__title,.yoast-table-scrollable,.yoast-table-scrollable td,.yoast-table-scrollable th{box-sizing:border-box}.wpseo_content_wrapper{display:table;width:100%;table-layout:fixed}.wpseo_content_cell{display:table-cell;height:500px;margin:0;padding:0;vertical-align:top}#wpseo_content_top{width:100%}#sidebar-container{width:261px;padding:0 19px 0 0}tr.yst_row{margin:5px 0 0;padding:5px 0 0}tr.yst_row.even{background-color:#f6f6f6}.postbox{margin:10px 0 0 10px}label.select,label.textinput{float:right;width:200px;margin:5px 0}.yoast-inline-label{float:none;margin:0}input.textinput,select,textarea{width:400px}input.textinput,select.select,textarea.textinput{margin:0 0 15px}input.checkbox,input.checkbox.double,input.radio{margin:6px 0 6px 10px}.textinput.metadesc{height:50px}textarea.import{width:500px;height:100px}p.desc{margin:6px 0 10px;padding:0 25px 8px 0}div.desc.label,p.desc.label{margin:0 0 20px;padding:0 200px 10px 0}.wpseo-gsc-reload-crawl-issues-form{position:relative;top:9px}.wp-core-ui .button.wpseo-gsc-save-profile{margin-right:200px}.wpseo_content_wrapper h3{margin:1em 0 .5em;font-size:1.15em}h4{clear:both;margin:1.2em 0 .5em}.wpseo_content_wrapper li,.wpseo_content_wrapper p{max-width:600px}.wpseo_content_wrapper .notice p,.wpseo_content_wrapper .yoast-blocking-files-error p,.yoast .search-box,.yoast-alert p,.yoast-container .container{max-width:none}table.wpseo th{text-align:right}#wpseo-tabs+.notice{margin-top:1.5em}.wpseo-variable-warning-element{border:1px solid #c62d2d!important}.wpseo-variable-warning{clear:both;margin:5px 0 0;padding:5px;color:#c62d2d}.wpseo-variable-warning code{color:#b02828}.wpseo-variable-warning a{color:#c62d2d}.wpseo_content_wrapper h1.wpseo-redirect-url-title{margin:1em 0 .5em;font-size:1.3em}.postbox form{line-height:150%}.text{width:250px}table.yoast_help{width:100%;border-collapse:collapse}table.yoast_help,table.yoast_help td,table.yoast_help th{border:1px solid #ddd;color:#444}table.yoast_help td,table.yoast_help th{padding:5px 10px;text-align:right;vertical-align:top}.correct,.wrong{padding:5px;color:#fff}table.yoast_help tr{background-color:#f1f1f1}table.yoast_help tr:nth-child(2n){background-color:#fbfbfe}table.yoast_help tr:hover{background-color:#ddd}table.yoast_help thead tr,table.yoast_help thead tr:hover{background-color:#fff}table.yoast_help .yoast-variable-name{font-weight:600;white-space:nowrap}.correct{background-color:green}.wrong{background-color:#dc3232}.wrong code{padding:3px 8px;color:#000}.yoast-notice-blocking-files code{color:#000;line-height:2}.yoast-notice-blocking-files .button{margin:.5em 0}.button.checkit,.button.fixit{float:left;margin:0 5px}.button.checkit{padding:5px 8px}.wpseotab{display:none}.wpseotab.active{display:block}.wpseotab p.expl{margin-right:6px}.wpseotab .tab-block{display:block;margin:30px 0}.wpseotab p.expl strong{font-size:115%}#wpseo-debug-info{clear:both;margin:20px 0 0;padding:20px 20px 0;border:1px solid #e5e5e5;background-color:#fff;box-shadow:0 1px 1px rgba(0,0,0,.04)}#wpseo-debug-info h2{margin:0;cursor:auto}#wpseo-debug-info .wpseo-debug-heading{font-size:1em}#wpseo-debug-info .wpseo-debug{display:inline-block;padding-right:20px;color:#c00}input.wpseo-new-title,textarea.wpseo-new-metadesc{width:100%;max-width:100%}#separator{margin:1.5em 0 .5em}#separator input.radio{position:absolute;right:-9999em;width:1px;height:1px}#separator input.radio+label{float:right;width:30px!important;margin:0 0 .5em 5px!important;padding:9px 6px;border:1px solid #ccc;font-family:Arial,Helvetica,sans-serif!important;font-size:18px!important;line-height:24px;text-align:center;cursor:pointer}#separator input.radio:checked+label{border:1px solid #a4286a;background-color:#fff;box-shadow:inset 0 0 0 2px #a4286a}#separator input.radio:focus+label{border-radius:10px 10px 10px 0}.svg-container{text-align:center}.svg-container .dashicons{width:200px;height:100px;font-size:100px}body.toplevel_page_wpseo_dashboard .wp-badge{background:url(../../images/Yoast_SEO_Icon.svg) 50% 10px no-repeat;background-size:140px 140px;box-shadow:none}.nav-tab .dashicons{width:18px;height:18px;font-size:18px;line-height:24px}.nav-tab .pinteresticon{width:12px;height:24px;margin-left:2px;background-image:url(../../images/pinterest-23x30.png);background-repeat:no-repeat;background-position:center center;background-size:contain}#wpseo_progressbar .ui-progressbar-value,.wpseo-progressbar .ui-progressbar-value{height:25px;background:#006691}#wpseo_progressbar{height:25px;border:1px solid #006691}.wpseo-progressbar-wrapper{display:inline;width:100%}.wpseo-progressbar{display:block;width:100%;height:25px;border:1px solid #006691}.archives-titles-metas-content{padding-top:1em}.yoast-sidebar__title{width:100%;margin:46px 0 20px;padding:10px 0;border-bottom:1px solid #a4286a;color:#a4286a;line-height:19px;text-align:right}.yoast-sidebar__spot{padding:10px 0;border-bottom:1px solid #ddd}.yoast-sidebar__spot a,.yoast-sidebar__spot h2{color:#a4286a}.yoast-sidebar__spot h2{margin-top:0}.yoast-sidebar__spot ul{position:relative}.yoast-sidebar__spot li{margin-right:20px;list-style:none}.yoast-sidebar__spot li::before{position:absolute;right:0;font-weight:700;content:"+"}.wpseo-banner__link{display:inline-block}.wpseo-banner__image{vertical-align:top}.yoast_premium_upsell_admin_block{overflow:hidden;max-width:650px;margin-top:2em;padding:10px;border:1px solid #ccc;background-color:#fff}.yoast_premium_upsell_admin_block--close{padding:1px 4px;border:1px solid #ccc;color:#333;font-size:16px;font-weight:700;text-decoration:none}.yoast_premium_upsell_admin_block--header{margin-top:.3em;font-size:1.7em;font-weight:700}.yoast_premium_upsell_admin_block--motivation{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.yoast_premium_upsell_admin_block--motivation li{list-style:none;-ms-flex:0 0 50%;flex:0 0 50%}.yoast_premium_upsell_admin_block--argument{padding:0 20px 0 8px}.yoast_premium_upsell_admin_block--argument::before{position:relative;top:-1px;right:-16px;margin-left:-10px;font-weight:700;content:"+"}@media screen and (max-width:480px){.yoast_premium_upsell_admin_block--motivation{display:block}}.yoast-table-scrollable__container.yoast-has-scroll{overflow:hidden;position:relative}.yoast-table-scrollable__container.yoast-has-scroll:after{position:absolute;top:0;right:100%;width:50px;height:calc(100% - 16px);border-radius:0 10px 10px 0/0 50% 50% 0;box-shadow:5px 0 10px rgba(0,0,0,.25);content:""}.yoast-table-scrollable__container.yoast-has-scroll .yoast-table-scrollable__inner{overflow-x:scroll;padding-bottom:16px}.yoast-table-scrollable__hintwrapper{display:none}.yoast-table-scrollable__hintwrapper.yoast-has-scroll{display:block;margin:1em 0;text-align:center}.yoast-has-scroll .yoast-table-scrollable__hint{display:inline-block}.yoast-has-scroll .yoast-table-scrollable__hint:before{display:inline-block;margin-left:10px;font-size:20px;line-height:inherit;vertical-align:text-top;content:"\21c4"}@media screen and (max-width:1024px){.wpseo_content_cell,.wpseo_content_wrapper{display:block;height:auto}#wpseo_content_top{width:auto}#sidebar-container{width:auto;padding:0}.yoast-sidebar__spot{float:right;width:50%;border:none;text-align:center}.yoast-sidebar__spot>strong:first-child{display:block;max-width:261px;margin:0 auto;text-align:right}.yoast-sidebar__spot p,.yoast-sidebar__spot ul{max-width:261px;margin:1em auto;text-align:right}}@media screen and (max-width:782px){label.select,label.textinput{display:inline-block;float:none;width:auto}input.textinput,textarea,textarea.textinput{display:block;width:100%}.select2-container,select,select.select{display:block;max-width:100%}div.desc.label,p.desc.label{padding-right:0}.wp-core-ui .button.wpseo-gsc-save-profile{margin-right:0}.wpseo-gsc-reload-crawl-issues-form{top:0;margin:1em 0}.wpseo-gsc-reload-crawl-issues-form .alignright{float:none}}@media screen and (max-width:600px){.wpseo-gsc-reload-crawl-issues-form{margin-bottom:0}.yoast-sidebar__spot{float:none;width:261px;margin:0 auto;border-bottom:1px solid #ddd}}@media screen and (max-width:500px){body.toplevel_page_wpseo_dashboard .wp-badge{padding-top:80px;background-color:#a4286a;background-size:100px 100px;box-shadow:0 1px 3px rgba(0,0,0,.2)}}.wpseo-checkmark-ok-icon{float:right;width:18px;height:18px;margin-left:5px;background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%2377B227%22%20d%3D%22M1671%20566q0%2040%2D28%2068l%2D724%20724%2D136%20136q%2D28%2028%2D68%2028t%2D68%2D28l%2D136%2D136%2D362%2D362q%2D28%2D28%2D28%2D68t28%2D68l136%2D136q28%2D28%2068%2D28t68%2028l294%20295%20656%2D657q28%2D28%2068%2D28t68%2028l136%20136q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E") no-repeat;background-size:18px;vertical-align:top} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-720.min.css deleted file mode 100644 index 93aa0fce..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/yst_plugin_tools-720.min.css +++ /dev/null @@ -1 +0,0 @@ -.yoast-variable-desc,table.yoast_help .yoast-variable-desc{min-width:300px}.yoast-sidebar__title,.yoast-table-scrollable,.yoast-table-scrollable td,.yoast-table-scrollable th{box-sizing:border-box}.wpseo_content_wrapper{display:table;width:100%;table-layout:fixed}.wpseo_content_cell{display:table-cell;height:500px;margin:0;padding:0;vertical-align:top}#wpseo_content_top{width:100%}#sidebar-container{width:261px;padding:0 0 0 19px}tr.yst_row{margin:5px 0 0;padding:5px 0 0}tr.yst_row.even{background-color:#f6f6f6}.postbox{margin:10px 10px 0 0}label.select,label.textinput{float:left;width:200px;margin:5px 0}.yoast-inline-label{float:none;margin:0}input.textinput,select,textarea{width:400px}input.textinput,select.select,textarea.textinput{margin:0 0 15px}input.checkbox,input.checkbox.double,input.radio{margin:6px 10px 6px 0}.textinput.metadesc{height:50px}textarea.import{width:500px;height:100px}p.desc{margin:6px 0 10px;padding:0 0 8px 25px}div.desc.label,p.desc.label{margin:0 0 20px;padding:0 0 10px 200px}.wpseo-gsc-reload-crawl-issues-form{position:relative;top:9px}.wp-core-ui .button.wpseo-gsc-save-profile{margin-left:200px}.wpseo_content_wrapper h3{margin:1em 0 .5em;font-size:1.15em}h4{clear:both;margin:1.2em 0 .5em}.wpseo_content_wrapper li,.wpseo_content_wrapper p{max-width:600px}.wpseo_content_wrapper .notice p,.wpseo_content_wrapper .yoast-blocking-files-error p,.yoast .search-box,.yoast-alert p,.yoast-container .container{max-width:none}table.wpseo th{text-align:left}#wpseo-tabs+.notice{margin-top:1.5em}.wpseo-variable-warning-element{border:1px solid #c62d2d!important}.wpseo-variable-warning{clear:both;margin:5px 0 0;padding:5px;color:#c62d2d}.wpseo-variable-warning code{color:#b02828}.wpseo-variable-warning a{color:#c62d2d}.wpseo_content_wrapper h1.wpseo-redirect-url-title{margin:1em 0 .5em;font-size:1.3em}.postbox form{line-height:150%}.text{width:250px}table.yoast_help{width:100%;border-collapse:collapse}table.yoast_help,table.yoast_help td,table.yoast_help th{border:1px solid #ddd;color:#444}table.yoast_help td,table.yoast_help th{padding:5px 10px;text-align:left;vertical-align:top}.correct,.wrong{padding:5px;color:#fff}table.yoast_help tr{background-color:#f1f1f1}table.yoast_help tr:nth-child(2n){background-color:#fbfbfe}table.yoast_help tr:hover{background-color:#ddd}table.yoast_help thead tr,table.yoast_help thead tr:hover{background-color:#fff}table.yoast_help .yoast-variable-name{font-weight:600;white-space:nowrap}.correct{background-color:green}.wrong{background-color:#dc3232}.wrong code{padding:3px 8px;color:#000}.yoast-notice-blocking-files code{color:#000;line-height:2}.yoast-notice-blocking-files .button{margin:.5em 0}.button.checkit,.button.fixit{float:right;margin:0 5px}.button.checkit{padding:5px 8px}.wpseotab{display:none}.wpseotab.active{display:block}.wpseotab p.expl{margin-left:6px}.wpseotab .tab-block{display:block;margin:30px 0}.wpseotab p.expl strong{font-size:115%}#wpseo-debug-info{clear:both;margin:20px 0 0;padding:20px 20px 0;border:1px solid #e5e5e5;background-color:#fff;box-shadow:0 1px 1px rgba(0,0,0,.04)}#wpseo-debug-info h2{margin:0;cursor:auto}#wpseo-debug-info .wpseo-debug-heading{font-size:1em}#wpseo-debug-info .wpseo-debug{display:inline-block;padding-left:20px;color:#c00}input.wpseo-new-title,textarea.wpseo-new-metadesc{width:100%;max-width:100%}#separator{margin:1.5em 0 .5em}#separator input.radio{position:absolute;left:-9999em;width:1px;height:1px}#separator input.radio+label{float:left;width:30px!important;margin:0 5px .5em 0!important;padding:9px 6px;border:1px solid #ccc;font-family:Arial,Helvetica,sans-serif!important;font-size:18px!important;line-height:24px;text-align:center;cursor:pointer}#separator input.radio:checked+label{border:1px solid #a4286a;background-color:#fff;box-shadow:inset 0 0 0 2px #a4286a}#separator input.radio:focus+label{border-radius:10px 10px 0}.svg-container{text-align:center}.svg-container .dashicons{width:200px;height:100px;font-size:100px}body.toplevel_page_wpseo_dashboard .wp-badge{background:url(../../images/Yoast_SEO_Icon.svg) 50% 10px no-repeat;background-size:140px 140px;box-shadow:none}.nav-tab .dashicons{width:18px;height:18px;font-size:18px;line-height:24px}.nav-tab .pinteresticon{width:12px;height:24px;margin-right:2px;background-image:url(../../images/pinterest-23x30.png);background-repeat:no-repeat;background-position:center center;background-size:contain}#wpseo_progressbar .ui-progressbar-value,.wpseo-progressbar .ui-progressbar-value{height:25px;background:#006691}#wpseo_progressbar{height:25px;border:1px solid #006691}.wpseo-progressbar-wrapper{display:inline;width:100%}.wpseo-progressbar{display:block;width:100%;height:25px;border:1px solid #006691}.archives-titles-metas-content{padding-top:1em}.yoast-sidebar__title{width:100%;margin:46px 0 20px;padding:10px 0;border-bottom:1px solid #a4286a;color:#a4286a;line-height:19px;text-align:left}.yoast-sidebar__spot{padding:10px 0;border-bottom:1px solid #ddd}.yoast-sidebar__spot a,.yoast-sidebar__spot h2{color:#a4286a}.yoast-sidebar__spot h2{margin-top:0}.yoast-sidebar__spot ul{position:relative}.yoast-sidebar__spot li{margin-left:20px;list-style:none}.yoast-sidebar__spot li::before{position:absolute;left:0;font-weight:700;content:"+"}.wpseo-banner__link{display:inline-block}.wpseo-banner__image{vertical-align:top}.yoast_premium_upsell_admin_block{overflow:hidden;max-width:650px;margin-top:2em;padding:10px;border:1px solid #ccc;background-color:#fff}.yoast_premium_upsell_admin_block--close{padding:1px 4px;border:1px solid #ccc;color:#333;font-size:16px;font-weight:700;text-decoration:none}.yoast_premium_upsell_admin_block--header{margin-top:.3em;font-size:1.7em;font-weight:700}.yoast_premium_upsell_admin_block--motivation{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}.yoast_premium_upsell_admin_block--motivation li{list-style:none;-ms-flex:0 0 50%;flex:0 0 50%}.yoast_premium_upsell_admin_block--argument{padding:0 8px 0 20px}.yoast_premium_upsell_admin_block--argument::before{position:relative;top:-1px;left:-16px;margin-right:-10px;font-weight:700;content:"+"}@media screen and (max-width:480px){.yoast_premium_upsell_admin_block--motivation{display:block}}.yoast-table-scrollable__container.yoast-has-scroll{overflow:hidden;position:relative}.yoast-table-scrollable__container.yoast-has-scroll:after{position:absolute;top:0;left:100%;width:50px;height:calc(100% - 16px);border-radius:10px 0 0 10px/50% 0 0 50%;box-shadow:-5px 0 10px rgba(0,0,0,.25);content:""}.yoast-table-scrollable__container.yoast-has-scroll .yoast-table-scrollable__inner{overflow-x:scroll;padding-bottom:16px}.yoast-table-scrollable__hintwrapper{display:none}.yoast-table-scrollable__hintwrapper.yoast-has-scroll{display:block;margin:1em 0;text-align:center}.yoast-has-scroll .yoast-table-scrollable__hint{display:inline-block}.yoast-has-scroll .yoast-table-scrollable__hint:before{display:inline-block;margin-right:10px;font-size:20px;line-height:inherit;vertical-align:text-top;content:"\21c4"}@media screen and (max-width:1024px){.wpseo_content_cell,.wpseo_content_wrapper{display:block;height:auto}#wpseo_content_top{width:auto}#sidebar-container{width:auto;padding:0}.yoast-sidebar__spot{float:left;width:50%;border:none;text-align:center}.yoast-sidebar__spot>strong:first-child{display:block;max-width:261px;margin:0 auto;text-align:left}.yoast-sidebar__spot p,.yoast-sidebar__spot ul{max-width:261px;margin:1em auto;text-align:left}}@media screen and (max-width:782px){label.select,label.textinput{display:inline-block;float:none;width:auto}input.textinput,textarea,textarea.textinput{display:block;width:100%}.select2-container,select,select.select{display:block;max-width:100%}div.desc.label,p.desc.label{padding-left:0}.wp-core-ui .button.wpseo-gsc-save-profile{margin-left:0}.wpseo-gsc-reload-crawl-issues-form{top:0;margin:1em 0}.wpseo-gsc-reload-crawl-issues-form .alignright{float:none}}@media screen and (max-width:600px){.wpseo-gsc-reload-crawl-issues-form{margin-bottom:0}.yoast-sidebar__spot{float:none;width:261px;margin:0 auto;border-bottom:1px solid #ddd}}@media screen and (max-width:500px){body.toplevel_page_wpseo_dashboard .wp-badge{padding-top:80px;background-color:#a4286a;background-size:100px 100px;box-shadow:0 1px 3px rgba(0,0,0,.2)}}.wpseo-checkmark-ok-icon{float:left;width:18px;height:18px;margin-right:5px;background:url("data:image/svg+xml;charset=utf8,%3Csvg%20width%3D%221792%22%20height%3D%221792%22%20viewBox%3D%220%200%201792%201792%22%20xmlns%3D%22http%3A%2F%2Fwww%2Ew3%2Eorg%2F2000%2Fsvg%22%3E%3Cpath%20fill%3D%22%2377B227%22%20d%3D%22M1671%20566q0%2040%2D28%2068l%2D724%20724%2D136%20136q%2D28%2028%2D68%2028t%2D68%2D28l%2D136%2D136%2D362%2D362q%2D28%2D28%2D28%2D68t28%2D68l136%2D136q28%2D28%2068%2D28t68%2028l294%20295%20656%2D657q28%2D28%2068%2D28t68%2028l136%20136q28%2028%2028%2068z%22%2F%3E%3C%2Fsvg%3E") no-repeat;background-size:18px;vertical-align:top} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-1720-rtl.css b/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-1720-rtl.css new file mode 100644 index 00000000..9c66a51b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-1720-rtl.css @@ -0,0 +1 @@ +.wpseo-score-icon{display:inline-block!important;width:12px!important;height:12px!important;border-radius:50%!important;margin:3px 3px 0 10px;background:#888;vertical-align:top}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe}.wpseo-score-title{font-weight:600}#taxonomy_overall{position:absolute;top:0;margin-right:87.5%} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-1720.css b/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-1720.css new file mode 100644 index 00000000..fb977ff6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-1720.css @@ -0,0 +1 @@ +.wpseo-score-icon{display:inline-block!important;width:12px!important;height:12px!important;border-radius:50%!important;margin:3px 10px 0 3px;background:#888;vertical-align:top}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe}.wpseo-score-title{font-weight:600}#taxonomy_overall{position:absolute;top:0;margin-left:87.5%} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-720-rtl.min.css b/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-720-rtl.min.css deleted file mode 100644 index 01c4325f..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-720-rtl.min.css +++ /dev/null @@ -1 +0,0 @@ -.wpseo-score-icon{display:inline-block;width:12px;height:12px;margin:3px 3px 0 10px;border-radius:50%;background:#888;vertical-align:top}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe}.wpseo-score-title{font-weight:600}#taxonomy_overall{position:absolute;top:0;margin-right:87.5%} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-720.min.css b/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-720.min.css deleted file mode 100644 index df91e15b..00000000 --- a/wp-content/plugins/wordpress-seo/css/dist/yst_seo_score-720.min.css +++ /dev/null @@ -1 +0,0 @@ -.wpseo-score-icon{display:inline-block;width:12px;height:12px;margin:3px 10px 0 3px;border-radius:50%;background:#888;vertical-align:top}.wpseo-score-icon.good{background-color:#7ad03a}.wpseo-score-icon.ok{background-color:#ee7c1b}.wpseo-score-icon.bad{background-color:#dc3232}.wpseo-score-icon.na{background-color:#888}.wpseo-score-icon.noindex{background-color:#1e8cbe}.wpseo-score-title{font-weight:600}#taxonomy_overall{position:absolute;top:0;margin-left:87.5%} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/deprecated/class-submenu-hider.php b/wp-content/plugins/wordpress-seo/deprecated/class-submenu-hider.php deleted file mode 100644 index fec70b87..00000000 --- a/wp-content/plugins/wordpress-seo/deprecated/class-submenu-hider.php +++ /dev/null @@ -1,39 +0,0 @@ -post = ( isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null ); - $this->show_on_front = get_option( 'show_on_front' ); - $this->page_for_posts = get_option( 'page_for_posts' ); - - $this->filter_element(); - $this->filter_separator(); - $this->filter_wrapper(); - - $this->set_crumbs(); - $this->prepare_links(); - $this->links_to_string(); - $this->wrap_breadcrumb(); - } - - /** - * Get breadcrumb string using the singleton instance of this class. - * - * @param string $before Optional string to prepend. - * @param string $after Optional string to append. - * @param bool $display Echo or return flag. - * - * @return string Returns the breadcrumbs as a string. - */ - public static function breadcrumb( $before = '', $after = '', $display = true ) { - if ( ! ( self::$instance instanceof self ) ) { - self::$instance = new self(); - } - // Remember the last used before/after for use in case the object goes __toString(). - self::$before = $before; - self::$after = $after; - - $output = $before . self::$instance->output . $after; - - if ( $display === true ) { - echo $output; - - return ''; - } - - return $output; - } - - /** - * Magic method to use in case the class would be send to string. - * - * @return string - */ - public function __toString() { - return self::$before . $this->output . self::$after; - } - - /** - * Returns the link url for a single id. - * - * When the target is private and the user isn't allowed to access it, just return an empty string. - * - * @param int $id The target id. - * - * @return string Empty string when post isn't accessible. An URL if accessible. - */ - protected function get_link_url_for_id( $id ) { - $post_status = get_post_status( $id ); - $post_type = get_post_type_object( get_post_type( $id ) ); - - // Don't link if item is private and user does't have capability to read it. - if ( $post_status === 'private' && $post_type !== null && ! current_user_can( $post_type->cap->read_private_posts ) ) { - return ''; - } - - $url = get_permalink( $id ); - if ( $url === false ) { - return ''; - } - - return $url; - } - - - /** - * Filter: 'wpseo_breadcrumb_single_link_wrapper' - Allows developer to change or wrap each breadcrumb element. - * - * @api string $element - */ - private function filter_element() { - $this->element = esc_attr( apply_filters( 'wpseo_breadcrumb_single_link_wrapper', $this->element ) ); - } - - /** - * Filter: 'wpseo_breadcrumb_separator' - Allow (theme) developer to change the Yoast SEO breadcrumb separator. - * - * @api string $breadcrumbs_sep Breadcrumbs separator. - */ - private function filter_separator() { - $separator = apply_filters( 'wpseo_breadcrumb_separator', WPSEO_Options::get( 'breadcrumbs-sep' ) ); - $this->separator = ' ' . $separator . ' '; - } - - /** - * Filter: 'wpseo_breadcrumb_output_wrapper' - Allow changing the HTML wrapper element for the Yoast SEO breadcrumbs output. - * - * @api string $wrapper The wrapper element. - */ - private function filter_wrapper() { - $wrapper = apply_filters( 'wpseo_breadcrumb_output_wrapper', $this->wrapper ); - $wrapper = tag_escape( $wrapper ); - if ( is_string( $wrapper ) && '' !== $wrapper ) { - $this->wrapper = $wrapper; - } - } - - - /** - * Get a term's parents. - * - * @param object $term Term to get the parents for. - * - * @return array - */ - private function get_term_parents( $term ) { - $tax = $term->taxonomy; - $parents = array(); - while ( $term->parent !== 0 ) { - $term = get_term( $term->parent, $tax ); - $parents[] = $term; - } - - return array_reverse( $parents ); - } - - /** - * Find the deepest term in an array of term objects. - * - * @param array $terms Terms set. - * - * @return object - */ - private function find_deepest_term( $terms ) { - /* - * Let's find the deepest term in this array, by looping through and then - * unsetting every term that is used as a parent by another one in the array. - */ - $terms_by_id = array(); - foreach ( $terms as $term ) { - $terms_by_id[ $term->term_id ] = $term; - } - foreach ( $terms as $term ) { - unset( $terms_by_id[ $term->parent ] ); - } - unset( $term ); - - /* - * As we could still have two subcategories, from different parent categories, - * let's pick the one with the lowest ordered ancestor. - */ - $parents_count = 0; - $term_order = 9999; // Because ASC. - reset( $terms_by_id ); - $deepest_term = current( $terms_by_id ); - foreach ( $terms_by_id as $term ) { - $parents = $this->get_term_parents( $term ); - - if ( count( $parents ) >= $parents_count ) { - - $parents_count = count( $parents ); - - $parent_order = 9999; // Set default order. - foreach ( $parents as $parent ) { - if ( $parent->parent === 0 && isset( $parent->term_order ) ) { - $parent_order = $parent->term_order; - } - } - unset( $parent ); - - // Check if parent has lowest order. - if ( $parent_order < $term_order ) { - $term_order = $parent_order; - $deepest_term = $term; - } - } - } - - return $deepest_term; - } - - /** - * Retrieve the hierachical ancestors for the current 'post'. - * - * @return array - */ - private function get_post_ancestors() { - $ancestors = array(); - - if ( isset( $this->post->ancestors ) ) { - if ( is_array( $this->post->ancestors ) ) { - $ancestors = array_values( $this->post->ancestors ); - } - else { - $ancestors = array( $this->post->ancestors ); - } - } - elseif ( isset( $this->post->post_parent ) ) { - $ancestors = array( $this->post->post_parent ); - } - - /** - * Filter: Allow changing the ancestors for the Yoast SEO breadcrumbs output. - * - * @api array $ancestors Ancestors. - */ - $ancestors = apply_filters( 'wp_seo_get_bc_ancestors', $ancestors ); - - if ( ! is_array( $ancestors ) ) { - trigger_error( 'The return value for the "wp_seo_get_bc_ancestors" filter should be an array.', E_USER_WARNING ); - $ancestors = (array) $ancestors; - } - - // Reverse the order so it's oldest to newest. - $ancestors = array_reverse( $ancestors ); - - return $ancestors; - } - - /** - * Determine the crumbs which should form the breadcrumb. - */ - private function set_crumbs() { - /** @var WP_Query $wp_query */ - global $wp_query; - - $this->maybe_add_home_crumb(); - $this->maybe_add_blog_crumb(); - - // Ignore coding standards for empty if statement. - // @codingStandardsIgnoreStart - if ( $this->is_front_page() ) { - // Do nothing. - // @codingStandardsIgnoreEnd - } - elseif ( $this->show_on_front === 'page' && is_home() ) { - $this->add_blog_crumb(); - } - elseif ( is_singular() ) { - $this->maybe_add_pt_archive_crumb_for_post(); - - if ( isset( $this->post->post_parent ) && 0 === $this->post->post_parent ) { - $this->maybe_add_taxonomy_crumbs_for_post(); - } - if ( isset( $this->post->post_parent ) && $this->post->post_parent !== 0 ) { - $this->add_post_ancestor_crumbs(); - } - - if ( isset( $this->post->ID ) ) { - $this->add_single_post_crumb( $this->post->ID ); - } - } - elseif ( is_post_type_archive() ) { - $post_type = $wp_query->get( 'post_type' ); - - if ( $post_type && is_string( $post_type ) ) { - $this->add_ptarchive_crumb( $post_type ); - } - } - elseif ( is_tax() || is_tag() || is_category() ) { - $this->add_crumbs_for_taxonomy(); - } - elseif ( is_date() ) { - if ( is_day() ) { - $this->add_linked_month_year_crumb(); - $this->add_date_crumb(); - } - elseif ( is_month() ) { - $this->add_month_crumb(); - } - elseif ( is_year() ) { - $this->add_year_crumb(); - } - } - elseif ( is_author() ) { - $user = $wp_query->get_queried_object(); - $display_name = get_the_author_meta( 'display_name', $user->ID ); - $this->add_predefined_crumb( - WPSEO_Options::get( 'breadcrumbs-archiveprefix' ) . ' ' . $display_name, - null, - true - ); - } - elseif ( is_search() ) { - $this->add_predefined_crumb( - WPSEO_Options::get( 'breadcrumbs-searchprefix' ) . ' "' . esc_html( get_search_query() ) . '"', - null, - true - ); - } - elseif ( is_404() ) { - $this->add_predefined_crumb( - WPSEO_Options::get( 'breadcrumbs-404crumb' ), - null, - true - ); - } - - /** - * Filter: 'wpseo_breadcrumb_links' - Allow the developer to filter the Yoast SEO breadcrumb links, add to them, change order, etc. - * - * @api array $crumbs The crumbs array. - */ - $this->crumbs = apply_filters( 'wpseo_breadcrumb_links', $this->crumbs ); - - $this->crumb_count = count( $this->crumbs ); - } - - /** - * Determine whether we are on the front page of the site. - * - * @return bool - */ - private function is_front_page() { - if ( $this->show_on_front === 'page' && is_front_page() ) { - return true; - } - - if ( $this->show_on_front === 'posts' && is_home() ) { - return true; - } - - return false; - } - - /** - * Add a single id based crumb to the crumbs property. - * - * @param int $id Post ID. - */ - private function add_single_post_crumb( $id ) { - $this->crumbs[] = array( - 'id' => $id, - ); - } - - /** - * Add a term based crumb to the crumbs property. - * - * @param object $term Term data object. - */ - private function add_term_crumb( $term ) { - $this->crumbs[] = array( - 'term' => $term, - ); - } - - /** - * Add a ptarchive based crumb to the crumbs property. - * - * @param string $pt Post type. - */ - private function add_ptarchive_crumb( $pt ) { - $this->crumbs[] = array( - 'ptarchive' => $pt, - ); - } - - /** - * Add a predefined crumb to the crumbs property. - * - * @param string $text Text string. - * @param string $url URL string. - * @param bool $allow_html Flag to allow HTML. - */ - private function add_predefined_crumb( $text, $url = '', $allow_html = false ) { - $this->crumbs[] = array( - 'text' => $text, - 'url' => $url, - 'allow_html' => $allow_html, - ); - } - - /** - * Add Homepage crumb to the crumbs property. - */ - private function maybe_add_home_crumb() { - if ( WPSEO_Options::get( 'breadcrumbs-home' ) !== '' ) { - $this->add_predefined_crumb( - WPSEO_Options::get( 'breadcrumbs-home' ), - WPSEO_Utils::home_url(), - true - ); - } - } - - /** - * Add Blog crumb to the crumbs property. - */ - private function add_blog_crumb() { - $this->add_single_post_crumb( $this->page_for_posts ); - } - - /** - * Add Blog crumb to the crumbs property for single posts where Home != blogpage. - */ - private function maybe_add_blog_crumb() { - if ( ( 'page' === $this->show_on_front && 'post' === get_post_type() ) && ( ! is_home() && ! is_search() ) ) { - if ( $this->page_for_posts && WPSEO_Options::get( 'breadcrumbs-display-blog-page' ) === true ) { - $this->add_blog_crumb(); - } - } - } - - /** - * Add ptarchive crumb to the crumbs property if it can be linked to, for a single post. - */ - private function maybe_add_pt_archive_crumb_for_post() { - // Never do this for the Post type archive for posts, as that would break `maybe_add_blog_crumb`. - if ( $this->post->post_type === 'post' ) { - return; - } - if ( isset( $this->post->post_type ) && get_post_type_archive_link( $this->post->post_type ) ) { - $this->add_ptarchive_crumb( $this->post->post_type ); - } - } - - /** - * Add taxonomy crumbs to the crumbs property for a single post. - */ - private function maybe_add_taxonomy_crumbs_for_post() { - if ( WPSEO_Options::get( 'post_types-' . $this->post->post_type . '-maintax' ) && (string) WPSEO_Options::get( 'post_types-' . $this->post->post_type . '-maintax' ) !== '0' ) { - $main_tax = WPSEO_Options::get( 'post_types-' . $this->post->post_type . '-maintax' ); - if ( isset( $this->post->ID ) ) { - $terms = get_the_terms( $this->post, $main_tax ); - - if ( is_array( $terms ) && $terms !== array() ) { - - $primary_term = new WPSEO_Primary_Term( $main_tax, $this->post->ID ); - if ( $primary_term->get_primary_term() ) { - $breadcrumb_term = get_term( $primary_term->get_primary_term(), $main_tax ); - } - else { - $breadcrumb_term = $this->find_deepest_term( $terms ); - } - - if ( is_taxonomy_hierarchical( $main_tax ) && $breadcrumb_term->parent !== 0 ) { - $parent_terms = $this->get_term_parents( $breadcrumb_term ); - foreach ( $parent_terms as $parent_term ) { - $this->add_term_crumb( $parent_term ); - } - } - - $this->add_term_crumb( $breadcrumb_term ); - } - } - } - } - - /** - * Add hierarchical ancestor crumbs to the crumbs property for a single post. - */ - private function add_post_ancestor_crumbs() { - $ancestors = $this->get_post_ancestors(); - if ( is_array( $ancestors ) && $ancestors !== array() ) { - foreach ( $ancestors as $ancestor ) { - $this->add_single_post_crumb( $ancestor ); - } - } - } - - /** - * Add taxonomy parent crumbs to the crumbs property for a taxonomy. - */ - private function add_crumbs_for_taxonomy() { - $term = $GLOBALS['wp_query']->get_queried_object(); - - // @todo adjust function name!! - $this->maybe_add_preferred_term_parent_crumb( $term ); - - $this->maybe_add_term_parent_crumbs( $term ); - - $this->add_term_crumb( $term ); - } - - /** - * Add parent taxonomy crumb based on user defined preference. - * - * @param object $term Term data object. - */ - private function maybe_add_preferred_term_parent_crumb( $term ) { - if ( WPSEO_Options::get( 'taxonomy-' . $term->taxonomy . '-ptparent' ) && (string) WPSEO_Options::get( 'taxonomy-' . $term->taxonomy . '-ptparent' ) !== '0' ) { - if ( 'post' === WPSEO_Options::get( 'taxonomy-' . $term->taxonomy . '-ptparent' ) && $this->show_on_front === 'page' ) { - if ( $this->page_for_posts ) { - $this->add_blog_crumb(); - } - return; - } - $this->add_ptarchive_crumb( WPSEO_Options::get( 'taxonomy-' . $term->taxonomy . '-ptparent' ) ); - } - } - - /** - * Add parent taxonomy crumbs to the crumb property for hierachical taxonomy. - * - * @param object $term Term data object. - */ - private function maybe_add_term_parent_crumbs( $term ) { - if ( is_taxonomy_hierarchical( $term->taxonomy ) && $term->parent !== 0 ) { - foreach ( $this->get_term_parents( $term ) as $parent_term ) { - $this->add_term_crumb( $parent_term ); - } - } - } - - /** - * Add month-year crumb to crumbs property. - */ - private function add_linked_month_year_crumb() { - $this->add_predefined_crumb( - $GLOBALS['wp_locale']->get_month( get_query_var( 'monthnum' ) ) . ' ' . get_query_var( 'year' ), - get_month_link( get_query_var( 'year' ), get_query_var( 'monthnum' ) ) - ); - } - - /** - * Add (non-link) month crumb to crumbs property. - */ - private function add_month_crumb() { - $this->add_predefined_crumb( - WPSEO_Options::get( 'breadcrumbs-archiveprefix' ) . ' ' . esc_html( single_month_title( ' ', false ) ), - null, - true - ); - } - - /** - * Add (non-link) year crumb to crumbs property. - */ - private function add_year_crumb() { - $this->add_predefined_crumb( - WPSEO_Options::get( 'breadcrumbs-archiveprefix' ) . ' ' . esc_html( get_query_var( 'year' ) ), - null, - true - ); - } - - /** - * Add (non-link) date crumb to crumbs property. - * - * @param string $date Optional date string, defaults to post's date. - */ - private function add_date_crumb( $date = null ) { - if ( is_null( $date ) ) { - $date = get_the_date(); - } - else { - $date = mysql2date( get_option( 'date_format' ), $date, true ); - $date = apply_filters( 'get_the_date', $date, '' ); - } - - $this->add_predefined_crumb( - WPSEO_Options::get( 'breadcrumbs-archiveprefix' ) . ' ' . esc_html( $date ), - null, - true - ); - } - - - /** - * Take the crumbs array and convert each crumb to a single breadcrumb string. - * - * @link http://support.google.com/webmasters/bin/answer.py?hl=en&answer=185417 Google documentation on RDFA - */ - private function prepare_links() { - if ( ! is_array( $this->crumbs ) || $this->crumbs === array() ) { - return; - } - - foreach ( $this->crumbs as $index => $crumb ) { - $link_info = $crumb; // Keep pre-set url/text combis. - - if ( isset( $crumb['id'] ) ) { - $link_info = $this->get_link_info_for_id( $crumb['id'] ); - } - if ( isset( $crumb['term'] ) ) { - $link_info = $this->get_link_info_for_term( $crumb['term'] ); - } - if ( isset( $crumb['ptarchive'] ) ) { - $link_info = $this->get_link_info_for_ptarchive( $crumb['ptarchive'] ); - } - - /** - * Filter: 'wpseo_breadcrumb_single_link_info' - Allow developers to filter the Yoast SEO Breadcrumb link information. - * - * @api array $link_info The breadcrumb link information. - * - * @param int $index The index of the breadcrumb in the list. - * @param array $crumbs The complete list of breadcrumbs. - */ - $link_info = apply_filters( 'wpseo_breadcrumb_single_link_info', $link_info, $index, $this->crumbs ); - - $this->links[] = $this->crumb_to_link( $link_info, $index ); - } - } - - /** - * Retrieve link url and text based on post id - * - * @param int $id Post ID. - * - * @return array Array of link text and url - */ - private function get_link_info_for_id( $id ) { - $link = array(); - $link['url'] = $this->get_link_url_for_id( $id ); - $link['text'] = WPSEO_Meta::get_value( 'bctitle', $id ); - - if ( $link['text'] === '' ) { - $link['text'] = wp_strip_all_tags( get_the_title( $id ), true ); - } - - /** - * Filter: 'wp_seo_get_bc_title' - Allow developer to filter the Yoast SEO Breadcrumb title. - * - * @deprecated 5.8 - * @api string $link_text The Breadcrumb title text. - * - * @param int $link_id The post ID. - */ - $link['text'] = apply_filters_deprecated( 'wp_seo_get_bc_title', array( $link['text'], $id ), 'WPSEO 5.8', 'wpseo_breadcrumb_single_link_info' ); - - return $link; - } - - /** - * Retrieve link url and text based on term object. - * - * @param object $term Term object. - * - * @return array Array of link text and url. - */ - private function get_link_info_for_term( $term ) { - $link = array(); - - $bctitle = WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'bctitle' ); - if ( ! is_string( $bctitle ) || $bctitle === '' ) { - $bctitle = $term->name; - } - - $link['url'] = get_term_link( $term ); - $link['text'] = $bctitle; - - return $link; - } - - /** - * Retrieve link url and text based on post type. - * - * @param string $pt Post type. - * - * @return array Array of link text and url. - */ - private function get_link_info_for_ptarchive( $pt ) { - $link = array(); - $archive_title = ''; - - if ( WPSEO_Options::get( 'bctitle-ptarchive-' . $pt, '' ) !== '' ) { - - $archive_title = WPSEO_Options::get( 'bctitle-ptarchive-' . $pt ); - } - else { - $post_type_obj = get_post_type_object( $pt ); - if ( is_object( $post_type_obj ) ) { - if ( isset( $post_type_obj->label ) && $post_type_obj->label !== '' ) { - $archive_title = $post_type_obj->label; - } - elseif ( isset( $post_type_obj->labels->menu_name ) && $post_type_obj->labels->menu_name !== '' ) { - $archive_title = $post_type_obj->labels->menu_name; - } - else { - $archive_title = $post_type_obj->name; - } - } - } - - $link['url'] = get_post_type_archive_link( $pt ); - $link['text'] = $archive_title; - - return $link; - } - - - /** - * Create a breadcrumb element string. - * - * @todo The `$paged` variable only works for archives, not for paged articles, so this does not work - * for paged article at this moment. - * - * @param array $link Link info array containing the keys: - * 'text' => (string) link text. - * 'url' => (string) link url. - * (optional) 'title' => (string) link title attribute text. - * (optional) 'allow_html' => (bool) whether to (not) escape html in the link text. - * This prevents html stripping from the text strings set in the - * WPSEO -> Internal Links options page. - * @param int $i Index for the current breadcrumb. - * - * @return string - */ - private function crumb_to_link( $link, $i ) { - $link_output = ''; - - if ( isset( $link['text'] ) && ( is_string( $link['text'] ) && $link['text'] !== '' ) ) { - - $link['text'] = trim( $link['text'] ); - if ( ! isset( $link['allow_html'] ) || $link['allow_html'] !== true ) { - $link['text'] = esc_html( $link['text'] ); - } - - $inner_elm = 'span'; - if ( WPSEO_Options::get( 'breadcrumbs-boldlast' ) === true && $i === ( $this->crumb_count - 1 ) ) { - $inner_elm = 'strong'; - } - - if ( ( isset( $link['url'] ) && ( is_string( $link['url'] ) && $link['url'] !== '' ) ) - && ( $i < ( $this->crumb_count - 1 ) ) - ) { - if ( $i === 0 ) { - $link_output .= '<' . $this->element . ' typeof="v:Breadcrumb">'; - } - else { - $link_output .= '<' . $this->element . ' rel="v:child" typeof="v:Breadcrumb">'; - } - $title_attr = isset( $link['title'] ) ? ' title="' . esc_attr( $link['title'] ) . '"' : ''; - $link_output .= '' . $link['text'] . ''; - } - else { - $link_output .= '<' . $inner_elm . ' class="breadcrumb_last">' . $link['text'] . ''; - // This is the last element, now close all previous elements. - while ( $i > 0 ) { - $link_output .= 'element . '>'; - $i--; - } - } - } - - /** - * Filter: 'wpseo_breadcrumb_single_link' - Allow changing of each link being put out by the Yoast SEO breadcrumbs class. - * - * @api string $link_output The output string. - * - * @param array $link The link array. - */ - - return apply_filters( 'wpseo_breadcrumb_single_link', $link_output, $link ); - } - - - /** - * Create a complete breadcrumb string from an array of breadcrumb element strings. - */ - private function links_to_string() { - if ( is_array( $this->links ) && $this->links !== array() ) { - // Remove any effectively empty links. - $links = array_map( 'trim', $this->links ); - $links = array_filter( $links ); - - $this->output = implode( $this->separator, $links ); - } - } - - /** - * Wrap a complete breadcrumb string in a Breadcrumb RDFA wrapper. - */ - private function wrap_breadcrumb() { - if ( is_string( $this->output ) && $this->output !== '' ) { - $output = '<' . $this->wrapper . $this->get_output_id() . $this->get_output_class() . ' xmlns:v="http://rdf.data-vocabulary.org/#">' . $this->output . 'wrapper . '>'; - - /** - * Filter: 'wpseo_breadcrumb_output' - Allow changing the HTML output of the Yoast SEO breadcrumbs class. - * - * @api string $unsigned HTML output. - */ - $output = apply_filters( 'wpseo_breadcrumb_output', $output ); - - if ( WPSEO_Options::get( 'breadcrumbs-prefix' ) !== '' ) { - $output = "\t" . WPSEO_Options::get( 'breadcrumbs-prefix' ) . "\n" . $output; - } - - $this->output = $output; - } - } - - - /** - * Filter: 'wpseo_breadcrumb_output_id' - Allow changing the HTML ID on the Yoast SEO breadcrumbs wrapper element. - * - * @api string $unsigned ID to add to the wrapper element. - */ - private function get_output_id() { - $id = apply_filters( 'wpseo_breadcrumb_output_id', '' ); - if ( is_string( $id ) && '' !== $id ) { - $id = ' id="' . esc_attr( $id ) . '"'; - } - - return $id; - } - - /** - * Filter: 'wpseo_breadcrumb_output_class' - Allow changing the HTML class on the Yoast SEO breadcrumbs wrapper element. - * - * @api string $unsigned Class to add to the wrapper element. - */ - private function get_output_class() { - $class = apply_filters( 'wpseo_breadcrumb_output_class', '' ); - if ( is_string( $class ) && '' !== $class ) { - $class = ' class="' . esc_attr( $class ) . '"'; - } - - return $class; - } -} diff --git a/wp-content/plugins/wordpress-seo/frontend/class-frontend-page-type.php b/wp-content/plugins/wordpress-seo/frontend/class-frontend-page-type.php deleted file mode 100644 index 146ef323..00000000 --- a/wp-content/plugins/wordpress-seo/frontend/class-frontend-page-type.php +++ /dev/null @@ -1,43 +0,0 @@ -get_simple_page_id() > 0; - } - - /** - * Returns the id of the currently opened page. - * - * @return int The id of the currently opened page. - */ - public function get_simple_page_id() { - if ( is_singular() ) { - return get_the_ID(); - } - - if ( is_home() && 'page' === get_option( 'show_on_front' ) ) { - return get_option( 'page_for_posts' ); - } - - /** - * Filter: Allow changing the default page id. - * - * @api int $page_id The default page id. - */ - return apply_filters( 'wpseo_frontend_page_type_simple_page_id', 0 ); - } -} diff --git a/wp-content/plugins/wordpress-seo/frontend/class-frontend.php b/wp-content/plugins/wordpress-seo/frontend/class-frontend.php deleted file mode 100644 index 0efc6eaa..00000000 --- a/wp-content/plugins/wordpress-seo/frontend/class-frontend.php +++ /dev/null @@ -1,1845 +0,0 @@ - 0 ) { - add_filter( 'wpseo_title', array( $this, 'title_test_helper' ) ); - } - - $this->woocommerce_shop_page = new WPSEO_WooCommerce_Shop_Page(); - $this->frontend_page_type = new WPSEO_Frontend_Page_Type(); - - $integrations = array( - new WPSEO_Frontend_Primary_Category(), - new WPSEO_JSON_LD(), - new WPSEO_Remove_Reply_To_Com(), - $this->woocommerce_shop_page, - ); - - foreach ( $integrations as $integration ) { - $integration->register_hooks(); - } - } - - /** - * Initialize the functions that only need to run on the frontpage. - */ - public function front_page_specific_init() { - if ( ! is_front_page() ) { - return; - } - - add_action( 'wpseo_head', array( $this, 'webmaster_tools_authentication' ), 90 ); - } - - /** - * Resets the entire class so canonicals, titles etc can be regenerated. - */ - public function reset() { - foreach ( get_class_vars( __CLASS__ ) as $name => $default ) { - switch ( $name ) { - // Clear the class instance to be re-initialized. - case 'instance': - self::$instance = null; - break; - - // Exclude these properties from being reset. - case 'woocommerce_shop_page': - case 'frontend_page_type': - break; - - // Reset property to the class default. - default: - $this->$name = $default; - break; - } - } - WPSEO_Options::ensure_options_exist(); - } - - /** - * Get the singleton instance of this class. - * - * @return WPSEO_Frontend - */ - public static function get_instance() { - if ( ! ( self::$instance instanceof self ) ) { - self::$instance = new self(); - } - - return self::$instance; - } - - /** - * Override Woo's title with our own. - * - * @param string $title Title string. - * - * @return string - */ - public function fix_woo_title( $title ) { - return $this->title( $title ); - } - - /** - * Determine whether this is the homepage and shows posts. - * - * @return bool - */ - public function is_home_posts_page() { - return ( is_home() && 'posts' === get_option( 'show_on_front' ) ); - } - - /** - * Determine whether the this is the static frontpage. - * - * @return bool - */ - public function is_home_static_page() { - return ( is_front_page() && 'page' === get_option( 'show_on_front' ) && is_page( get_option( 'page_on_front' ) ) ); - } - - /** - * Determine whether this is the posts page, when it's not the frontpage. - * - * @return bool - */ - public function is_posts_page() { - return ( is_home() && 'page' === get_option( 'show_on_front' ) ); - } - - /** - * Used for static home and posts pages as well as singular titles. - * - * @param object|null $object If filled, object to get the title for. - * - * @return string - */ - public function get_content_title( $object = null ) { - if ( $object === null ) { - $object = $GLOBALS['wp_query']->get_queried_object(); - } - - $title = $this->get_seo_title( $object ); - if ( $title !== '' ) { - return $title; - } - - $post_type = ( isset( $object->post_type ) ? $object->post_type : $object->query_var ); - - return $this->get_title_from_options( 'title-' . $post_type, $object ); - } - - /** - * Retrieves the SEO title set in the SEO widget. - * - * @param null $object Object to retrieve the title from. - * - * @return string The SEO title for the specified object, or queried object if not supplied. - */ - public function get_seo_title( $object = null ) { - if ( $object === null ) { - $object = $GLOBALS['wp_query']->get_queried_object(); - } - - if ( ! is_object( $object ) ) { - return $this->get_title_from_options( 'title-404-wpseo' ); - } - - $title = $this->get_seo_meta_value( 'title', $object->ID ); - - if ( $title !== '' ) { - return $this->replace_vars( $title, $object ); - } - - return $title; - } - - /** - * Used for category, tag, and tax titles. - * - * @return string - */ - public function get_taxonomy_title() { - $object = $GLOBALS['wp_query']->get_queried_object(); - - $title = WPSEO_Taxonomy_Meta::get_term_meta( $object, $object->taxonomy, 'title' ); - - if ( is_string( $title ) && $title !== '' ) { - return $this->replace_vars( $title, $object ); - } - - return $this->get_title_from_options( 'title-tax-' . $object->taxonomy, $object ); - } - - /** - * Used for author titles. - * - * @return string - */ - public function get_author_title() { - $author_id = get_query_var( 'author' ); - $title = trim( get_the_author_meta( 'wpseo_title', $author_id ) ); - - if ( $title !== '' ) { - return $this->replace_vars( $title, array() ); - } - - return $this->get_title_from_options( 'title-author-wpseo' ); - } - - /** - * Simple function to use to pull data from $options. - * - * All titles pulled from options will be run through the $this->replace_vars function. - * - * @param string $index Name of the page to get the title from the settings for. - * @param object|array $var_source Possible object to pull variables from. - * - * @return string - */ - public function get_title_from_options( $index, $var_source = array() ) { - $template = WPSEO_Options::get( $index, '' ); - if ( $template === '' ) { - if ( is_singular() ) { - return $this->replace_vars( '%%title%% %%sep%% %%sitename%%', $var_source ); - } - - return ''; - } - - return $this->replace_vars( $template, $var_source ); - } - - /** - * Get the default title for the current page. - * - * This is the fallback title generator used when a title hasn't been set for the specific content, taxonomy, author - * details, or in the options. It scrubs off any present prefix before or after the title (based on $seplocation) in - * order to prevent duplicate seperations from appearing in the title (this happens when a prefix is supplied to the - * wp_title call on singular pages). - * - * @param string $sep The separator used between variables. - * @param string $seplocation Whether the separator should be left or right. - * @param string $title Possible title that's already set. - * - * @return string - */ - public function get_default_title( $sep, $seplocation, $title = '' ) { - if ( 'right' === $seplocation ) { - $regex = '`\s*' . preg_quote( trim( $sep ), '`' ) . '\s*`u'; - } - else { - $regex = '`^\s*' . preg_quote( trim( $sep ), '`' ) . '\s*`u'; - } - $title = preg_replace( $regex, '', $title ); - - if ( ! is_string( $title ) || ( is_string( $title ) && $title === '' ) ) { - $title = WPSEO_Utils::get_site_name(); - $title = $this->add_paging_to_title( $sep, $seplocation, $title ); - $title = $this->add_to_title( $sep, $seplocation, $title, wp_strip_all_tags( get_bloginfo( 'description' ), true ) ); - - return $title; - } - - $title = $this->add_paging_to_title( $sep, $seplocation, $title ); - $title = $this->add_to_title( $sep, $seplocation, $title, wp_strip_all_tags( get_bloginfo( 'name' ), true ) ); - - return $title; - } - - /** - * This function adds paging details to the title. - * - * @param string $sep Separator used in the title. - * @param string $seplocation Whether the separator should be left or right. - * @param string $title The title to append the paging info to. - * - * @return string - */ - public function add_paging_to_title( $sep, $seplocation, $title ) { - global $wp_query; - - if ( ! empty( $wp_query->query_vars['paged'] ) && $wp_query->query_vars['paged'] > 1 ) { - return $this->add_to_title( $sep, $seplocation, $title, $wp_query->query_vars['paged'] . '/' . $wp_query->max_num_pages ); - } - - return $title; - } - - /** - * Add part to title, while ensuring that the $seplocation variable is respected. - * - * @param string $sep Separator used in the title. - * @param string $seplocation Whether the separator should be left or right. - * @param string $title The title to append the title_part to. - * @param string $title_part The part to append to the title. - * - * @return string - */ - public function add_to_title( $sep, $seplocation, $title, $title_part ) { - if ( 'right' === $seplocation ) { - return $title . $sep . $title_part; - } - - return $title_part . $sep . $title; - } - - /** - * Main title function. - * - * @param string $title Title that might have already been set. - * @param string $separator Separator determined in theme (unused). - * @param string $separator_location Whether the separator should be left or right. - * - * @return string - */ - public function title( $title, $separator = '', $separator_location = '' ) { - if ( is_null( $this->title ) ) { - $this->title = $this->generate_title( $title, $separator_location ); - } - - return $this->title; - } - - /** - * Main title generation function. - * - * @param string $title Title that might have already been set. - * @param string $separator_location Whether the separator should be left or right. - * - * @return string - */ - private function generate_title( $title, $separator_location ) { - - if ( is_feed() ) { - return $title; - } - - $separator = $this->replace_vars( '%%sep%%', array() ); - $separator = ' ' . trim( $separator ) . ' '; - - if ( '' === trim( $separator_location ) ) { - $separator_location = ( is_rtl() ) ? 'left' : 'right'; - } - - // This needs to be kept track of in order to generate - // default titles for singular pages. - $original_title = $title; - - // This flag is used to determine if any additional - // processing should be done to the title after the - // main section of title generation completes. - $modified_title = true; - - // This variable holds the page-specific title part - // that is used to generate default titles. - $title_part = ''; - - if ( $this->is_home_static_page() ) { - $title = $this->get_content_title(); - } - elseif ( $this->is_home_posts_page() ) { - $title = $this->get_title_from_options( 'title-home-wpseo' ); - } - elseif ( $this->woocommerce_shop_page->is_shop_page() ) { - $post = get_post( $this->woocommerce_shop_page->get_shop_page_id() ); - $title = $this->get_seo_title( $post ); - - if ( ! is_string( $title ) || $title === '' ) { - $title = $this->get_post_type_archive_title( $separator, $separator_location ); - } - } - elseif ( $this->frontend_page_type->is_simple_page() ) { - $post = get_post( $this->frontend_page_type->get_simple_page_id() ); - $title = $this->get_content_title( $post ); - - if ( ! is_string( $title ) || '' === $title ) { - $title_part = $original_title; - } - } - elseif ( is_search() ) { - $title = $this->get_title_from_options( 'title-search-wpseo' ); - - if ( ! is_string( $title ) || '' === $title ) { - /* translators: %s expands to the search phrase. */ - $title_part = sprintf( __( 'Search for "%s"', 'wordpress-seo' ), esc_html( get_search_query() ) ); - } - } - elseif ( is_category() || is_tag() || is_tax() ) { - $title = $this->get_taxonomy_title(); - - if ( ! is_string( $title ) || '' === $title ) { - if ( is_category() ) { - $title_part = single_cat_title( '', false ); - } - elseif ( is_tag() ) { - $title_part = single_tag_title( '', false ); - } - else { - $title_part = single_term_title( '', false ); - if ( $title_part === '' ) { - $term = $GLOBALS['wp_query']->get_queried_object(); - $title_part = $term->name; - } - } - } - } - elseif ( is_author() ) { - $title = $this->get_author_title(); - - if ( ! is_string( $title ) || '' === $title ) { - $title_part = get_the_author_meta( 'display_name', get_query_var( 'author' ) ); - } - } - elseif ( is_post_type_archive() ) { - $title = $this->get_post_type_archive_title( $separator, $separator_location ); - } - elseif ( is_archive() ) { - $title = $this->get_title_from_options( 'title-archive-wpseo' ); - - // @todo [JRF => Yoast] Should these not use the archive default if no title found ? - // WPSEO_Options::get_default( 'wpseo_titles', 'title-archive-wpseo' ) - // Replacement would be needed! - if ( empty( $title ) ) { - if ( is_month() ) { - /* translators: %s expands to a time period, i.e. month name, year or specific date. */ - $title_part = sprintf( __( '%s Archives', 'wordpress-seo' ), single_month_title( ' ', false ) ); - } - elseif ( is_year() ) { - /* translators: %s expands to a time period, i.e. month name, year or specific date. */ - $title_part = sprintf( __( '%s Archives', 'wordpress-seo' ), get_query_var( 'year' ) ); - } - elseif ( is_day() ) { - /* translators: %s expands to a time period, i.e. month name, year or specific date. */ - $title_part = sprintf( __( '%s Archives', 'wordpress-seo' ), get_the_date() ); - } - else { - $title_part = __( 'Archives', 'wordpress-seo' ); - } - } - } - elseif ( is_404() ) { - - $title = $this->get_title_from_options( 'title-404-wpseo' ); - - // @todo [JRF => Yoast] Should these not use the 404 default if no title found ? - // WPSEO_Options::get_default( 'wpseo_titles', 'title-404-wpseo' ) - // Replacement would be needed! - if ( empty( $title ) ) { - $title_part = __( 'Page not found', 'wordpress-seo' ); - } - } - else { - // In case the page type is unknown, leave the title alone. - $modified_title = false; - - // If you would like to generate a default title instead, - // the following code could be used - // $title_part = $title; - // instead of the line above. - } - - if ( ( $modified_title && empty( $title ) ) || ! empty( $title_part ) ) { - $title = $this->get_default_title( $separator, $separator_location, $title_part ); - } - - if ( defined( 'ICL_LANGUAGE_CODE' ) && false !== strpos( $title, ICL_LANGUAGE_CODE ) ) { - $title = str_replace( ' @' . ICL_LANGUAGE_CODE, '', $title ); - } - - /** - * Filter: 'wpseo_title' - Allow changing the Yoast SEO output. - * - * @api string $title The page title being put out. - */ - - return esc_html( wp_strip_all_tags( stripslashes( apply_filters( 'wpseo_title', $title ) ), true ) ); - } - - /** - * Function used when title needs to be force overridden. - * - * @return string - */ - public function force_wp_title() { - global $wp_query; - $old_wp_query = null; - - if ( ! $wp_query->is_main_query() ) { - $old_wp_query = $wp_query; - wp_reset_query(); - } - - $title = $this->title( '' ); - - if ( ! empty( $old_wp_query ) ) { - $GLOBALS['wp_query'] = $old_wp_query; - unset( $old_wp_query ); - } - - return $title; - } - - /** - * Outputs or returns the debug marker, which is also used for title replacement when force rewrite is active. - * - * @param bool $echo Deprecated. Since 5.9. Whether or not to echo the debug marker. - * - * @return string The marker that will be echoed. - */ - public function debug_mark( $echo = true ) { - $marker = $this->get_debug_mark(); - if ( $echo === false ) { - _deprecated_argument( 'WPSEO_Frontend::debug_mark', '5.9', 'WPSEO_Frontend::get_debug_mark' ); - - return $marker; - } - - echo "\n${marker}\n"; - - return ''; - } - - /** - * Returns the debug marker, which is also used for title replacement when force rewrite is active. - * - * @return string The generated marker. - */ - public function get_debug_mark() { - return sprintf( - '<!-- This site is optimized with the %1$s %2$s - https://yoast.com/wordpress/plugins/seo/ -->', - esc_html( $this->head_product_name() ), - /** - * Filter: 'wpseo_hide_version' - can be used to hide the Yoast SEO version in the debug marker (only available in Yoast SEO Premium). - * - * @api bool - */ - ( ( apply_filters( 'wpseo_hide_version', false ) && $this->is_premium() ) ? '' : 'v' . WPSEO_VERSION ) - ); - } - - /** - * Output Webmaster Tools authentication strings. - */ - public function webmaster_tools_authentication() { - // Bing. - $this->webmaster_tools_helper( 'msverify', 'msvalidate.01' ); - - // Google. - $this->webmaster_tools_helper( 'googleverify', 'google-site-verification' ); - - // Pinterest. - $this->webmaster_tools_helper( 'pinterestverify', 'p:domain_verify' ); - - // Yandex. - $this->webmaster_tools_helper( 'yandexverify', 'yandex-verification' ); - } - - /** - * Helper function for authentication. - * - * @param string $option_key Option key. - * @param string $tag_name The tag name. - * - * @return void - */ - private function webmaster_tools_helper( $option_key, $tag_name ) { - $auth = WPSEO_Options::get( $option_key, '' ); - if ( $auth !== '' ) { - printf( '<meta name="%1$s" content="%2$s" />' . "\n", $tag_name, $auth ); - } - } - - /** - * Main wrapper function attached to wp_head. This combines all the output on the frontend of the Yoast SEO plugin. - */ - public function head() { - global $wp_query; - - $old_wp_query = null; - - if ( ! $wp_query->is_main_query() ) { - $old_wp_query = $wp_query; - wp_reset_query(); - } - - /** - * Action: 'wpseo_head' - Allow other plugins to output inside the Yoast SEO section of the head section. - */ - do_action( 'wpseo_head' ); - - echo $this->show_closing_debug_mark(); - - if ( ! empty( $old_wp_query ) ) { - $GLOBALS['wp_query'] = $old_wp_query; - unset( $old_wp_query ); - } - } - - /** - * Output the meta robots value. - * - * @return string - */ - public function robots() { - global $wp_query, $post; - - $robots = array(); - $robots['index'] = 'index'; - $robots['follow'] = 'follow'; - $robots['other'] = array(); - - if ( is_object( $post ) && is_singular() ) { - $private = 'private' === $post->post_status; - $noindex = ! WPSEO_Post_Type::is_post_type_indexable( $post->post_type ); - - if ( $noindex || $private ) { - $robots['index'] = 'noindex'; - } - - $robots = $this->robots_for_single_post( $robots ); - } - else { - if ( is_search() || is_404() ) { - $robots['index'] = 'noindex'; - } - elseif ( is_tax() || is_tag() || is_category() ) { - $term = $wp_query->get_queried_object(); - if ( is_object( $term ) && ( WPSEO_Options::get( 'noindex-tax-' . $term->taxonomy, false ) ) ) { - $robots['index'] = 'noindex'; - } - - // Three possible values, index, noindex and default, do nothing for default. - $term_meta = WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'noindex' ); - if ( is_string( $term_meta ) && 'default' !== $term_meta ) { - $robots['index'] = $term_meta; - } - - if ( $this->is_multiple_terms_query() ) { - $robots['index'] = 'noindex'; - } - } - elseif ( is_author() ) { - if ( WPSEO_Options::get( 'noindex-author-wpseo', false ) ) { - $robots['index'] = 'noindex'; - } - $curauth = $wp_query->get_queried_object(); - if ( WPSEO_Options::get( 'noindex-author-noposts-wpseo', false ) && count_user_posts( $curauth->ID, 'any' ) === 0 ) { - $robots['index'] = 'noindex'; - } - if ( get_user_meta( $curauth->ID, 'wpseo_noindex_author', true ) === 'on' ) { - $robots['index'] = 'noindex'; - } - } - elseif ( is_date() && WPSEO_Options::get( 'noindex-archive-wpseo', false ) ) { - $robots['index'] = 'noindex'; - } - elseif ( is_home() ) { - $page_for_posts = get_option( 'page_for_posts' ); - if ( $page_for_posts ) { - $robots = $this->robots_for_single_post( $robots, $page_for_posts ); - } - unset( $page_for_posts ); - } - elseif ( is_post_type_archive() ) { - $post_type = $this->get_queried_post_type(); - - if ( WPSEO_Options::get( 'noindex-ptarchive-' . $post_type, false ) ) { - $robots['index'] = 'noindex'; - } - } - - unset( $robot ); - } - - // Force override to respect the WP settings. - if ( '0' === (string) get_option( 'blog_public' ) || isset( $_GET['replytocom'] ) ) { - $robots['index'] = 'noindex'; - } - - $robotsstr = $robots['index'] . ',' . $robots['follow']; - - if ( $robots['other'] !== array() ) { - $robots['other'] = array_unique( $robots['other'] ); // @todo Most likely no longer needed, needs testing. - $robotsstr .= ',' . implode( ',', $robots['other'] ); - } - - $robotsstr = preg_replace( '`^index,follow,?`', '', $robotsstr ); - $robotsstr = str_replace( array( 'noodp,', 'noodp' ), '', $robotsstr ); - - /** - * Filter: 'wpseo_robots' - Allows filtering of the meta robots output of Yoast SEO. - * - * @api string $robotsstr The meta robots directives to be echoed. - */ - $robotsstr = apply_filters( 'wpseo_robots', $robotsstr ); - - if ( is_string( $robotsstr ) && $robotsstr !== '' ) { - echo '<meta name="robots" content="', esc_attr( $robotsstr ), '"/>', "\n"; - } - - // If a page has a noindex, it should _not_ have a canonical, as these are opposing indexing directives. - if ( strpos( $robotsstr, 'noindex' ) !== false ) { - remove_action( 'wpseo_head', array( $this, 'canonical' ), 20 ); - } - - return $robotsstr; - } - - /** - * Determine $robots values for a single post. - * - * @param array $robots Robots data array. - * @param int $post_id The post ID for which to determine the $robots values, defaults to current post. - * - * @return array - */ - public function robots_for_single_post( $robots, $post_id = 0 ) { - $noindex = $this->get_seo_meta_value( 'meta-robots-noindex', $post_id ); - if ( $noindex === '1' ) { - $robots['index'] = 'noindex'; - } - elseif ( $noindex === '2' ) { - $robots['index'] = 'index'; - } - - if ( $this->get_seo_meta_value( 'meta-robots-nofollow', $post_id ) === '1' ) { - $robots['follow'] = 'nofollow'; - } - - $meta_robots_adv = $this->get_seo_meta_value( 'meta-robots-adv', $post_id ); - - if ( $meta_robots_adv !== '' && ( $meta_robots_adv !== '-' && $meta_robots_adv !== 'none' ) ) { - $meta_robots_adv = explode( ',', $meta_robots_adv ); - foreach ( $meta_robots_adv as $robot ) { - $robots['other'][] = $robot; - } - unset( $robot ); - } - unset( $meta_robots_adv ); - - return $robots; - } - - /** - * This function normally outputs the canonical but is also used in other places to retrieve - * the canonical URL for the current page. - * - * @param bool $echo Whether or not to output the canonical element. - * @param bool $un_paged Whether or not to return the canonical with or without pagination added to the URL. - * @param bool $no_override Whether or not to return a manually overridden canonical. - * - * @return string $canonical - */ - public function canonical( $echo = true, $un_paged = false, $no_override = false ) { - if ( is_null( $this->canonical ) ) { - $this->generate_canonical(); - } - - $canonical = $this->canonical; - - if ( $un_paged ) { - $canonical = $this->canonical_unpaged; - } - elseif ( $no_override ) { - $canonical = $this->canonical_no_override; - } - - if ( $echo === false ) { - return $canonical; - } - - if ( is_string( $canonical ) && '' !== $canonical ) { - echo '<link rel="canonical" href="' . esc_url( $canonical, null, 'other' ) . '" />' . "\n"; - } - } - - /** - * This function normally outputs the canonical but is also used in other places to retrieve - * the canonical URL for the current page. - * - * @return void - */ - private function generate_canonical() { - $canonical = false; - $canonical_override = false; - - // Set decent canonicals for homepage, singulars and taxonomy pages. - if ( is_singular() ) { - $obj = get_queried_object(); - $canonical = get_permalink( $obj->ID ); - - $this->canonical_unpaged = $canonical; - - $canonical_override = $this->get_seo_meta_value( 'canonical' ); - - // Fix paginated pages canonical, but only if the page is truly paginated. - if ( get_query_var( 'page' ) > 1 ) { - $num_pages = ( substr_count( $obj->post_content, '<!--nextpage-->' ) + 1 ); - if ( $num_pages && get_query_var( 'page' ) <= $num_pages ) { - if ( ! $GLOBALS['wp_rewrite']->using_permalinks() ) { - $canonical = add_query_arg( 'page', get_query_var( 'page' ), $canonical ); - } - else { - $canonical = user_trailingslashit( trailingslashit( $canonical ) . get_query_var( 'page' ) ); - } - } - } - } - else { - if ( is_search() ) { - $search_query = get_search_query(); - - // Regex catches case when /search/page/N without search term is itself mistaken for search term. R. - if ( ! empty( $search_query ) && ! preg_match( '|^page/\d+$|', $search_query ) ) { - $canonical = get_search_link(); - } - } - elseif ( is_front_page() ) { - $canonical = WPSEO_Utils::home_url(); - } - elseif ( $this->is_posts_page() ) { - - $posts_page_id = get_option( 'page_for_posts' ); - $canonical = $this->get_seo_meta_value( 'canonical', $posts_page_id ); - - if ( empty( $canonical ) ) { - $canonical = get_permalink( $posts_page_id ); - } - } - elseif ( is_tax() || is_tag() || is_category() ) { - - $term = get_queried_object(); - - if ( ! empty( $term ) && ! $this->is_multiple_terms_query() ) { - - $canonical_override = WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'canonical' ); - $term_link = get_term_link( $term, $term->taxonomy ); - - if ( ! is_wp_error( $term_link ) ) { - $canonical = $term_link; - } - } - } - elseif ( is_post_type_archive() ) { - $post_type = $this->get_queried_post_type(); - $canonical = get_post_type_archive_link( $post_type ); - } - elseif ( is_author() ) { - $canonical = get_author_posts_url( get_query_var( 'author' ), get_query_var( 'author_name' ) ); - } - elseif ( is_archive() ) { - if ( is_date() ) { - if ( is_day() ) { - $canonical = get_day_link( get_query_var( 'year' ), get_query_var( 'monthnum' ), get_query_var( 'day' ) ); - } - elseif ( is_month() ) { - $canonical = get_month_link( get_query_var( 'year' ), get_query_var( 'monthnum' ) ); - } - elseif ( is_year() ) { - $canonical = get_year_link( get_query_var( 'year' ) ); - } - } - } - - $this->canonical_unpaged = $canonical; - - if ( $canonical && get_query_var( 'paged' ) > 1 ) { - global $wp_rewrite; - if ( ! $wp_rewrite->using_permalinks() ) { - if ( is_front_page() ) { - $canonical = trailingslashit( $canonical ); - } - $canonical = add_query_arg( 'paged', get_query_var( 'paged' ), $canonical ); - } - else { - if ( is_front_page() ) { - $canonical = WPSEO_Sitemaps_Router::get_base_url( '' ); - } - $canonical = user_trailingslashit( trailingslashit( $canonical ) . trailingslashit( $wp_rewrite->pagination_base ) . get_query_var( 'paged' ) ); - } - } - } - - $this->canonical_no_override = $canonical; - - if ( is_string( $canonical ) && $canonical !== '' ) { - // Force canonical links to be absolute, relative is NOT an option. - if ( WPSEO_Utils::is_url_relative( $canonical ) === true ) { - $canonical = $this->base_url( $canonical ); - } - } - - if ( is_string( $canonical_override ) && $canonical_override !== '' ) { - $canonical = $canonical_override; - } - - /** - * Filter: 'wpseo_canonical' - Allow filtering of the canonical URL put out by Yoast SEO. - * - * @api string $canonical The canonical URL. - */ - $this->canonical = apply_filters( 'wpseo_canonical', $canonical ); - } - - /** - * Parse the home URL setting to find the base URL for relative URLs. - * - * @param string $path Optional path string. - * - * @return string - */ - private function base_url( $path = null ) { - $url = get_option( 'home' ); - - $parts = wp_parse_url( $url ); - - $base_url = trailingslashit( $parts['scheme'] . '://' . $parts['host'] ); - - if ( ! is_null( $path ) ) { - $base_url .= ltrim( $path, '/' ); - } - - return $base_url; - } - - /** - * Adds 'prev' and 'next' links to archives. - * - * @link http://googlewebmastercentral.blogspot.com/2011/09/pagination-with-relnext-and-relprev.html - * @since 1.0.3 - */ - public function adjacent_rel_links() { - // Don't do this for Genesis, as the way Genesis handles homepage functionality is different and causes issues sometimes. - /** - * Filter 'wpseo_genesis_force_adjacent_rel_home' - Allows devs to allow echoing rel="next" / rel="prev" by Yoast SEO on Genesis installs. - * - * @api bool $unsigned Whether or not to rel=next / rel=prev . - */ - if ( is_home() && function_exists( 'genesis' ) && apply_filters( 'wpseo_genesis_force_adjacent_rel_home', false ) === false ) { - return; - } - - /** - * Filter: 'wpseo_disable_adjacent_rel_links' - Allows disabling of Yoast adjacent links if this is being handled by other code. - * - * @api bool $links_generated Indicates if other code has handled adjacent links. - */ - if ( true === apply_filters( 'wpseo_disable_adjacent_rel_links', false ) ) { - return; - } - - if ( is_singular() ) { - $this->rel_links_single(); - return; - } - - $this->rel_links_archive(); - } - - /** - * Output the rel next/prev links for a single post / page. - * - * @return void - */ - protected function rel_links_single() { - $num_pages = 1; - - $queried_object = get_queried_object(); - if ( ! empty( $queried_object ) ) { - $num_pages = ( substr_count( $queried_object->post_content, '<!--nextpage-->' ) + 1 ); - } - - if ( $num_pages === 1 ) { - return; - } - - $page = max( 1, (int) get_query_var( 'page' ) ); - $url = get_permalink( get_queried_object_id() ); - - if ( $page > 1 ) { - $this->adjacent_rel_link( 'prev', $url, ( $page - 1 ), 'page' ); - } - - if ( $page < $num_pages ) { - $this->adjacent_rel_link( 'next', $url, ( $page + 1 ), 'page' ); - } - } - - /** - * Output the rel next/prev links for an archive page. - */ - protected function rel_links_archive() { - $url = $this->canonical( false, true, true ); - - if ( ! is_string( $url ) || $url === '' ) { - return; - } - - $paged = max( 1, (int) get_query_var( 'paged' ) ); - - if ( $paged === 2 ) { - $this->adjacent_rel_link( 'prev', $url, ( $paged - 1 ) ); - } - - // Make sure to use index.php when needed, done after paged == 2 check so the prev links to homepage will not have index.php erroneously. - if ( is_front_page() ) { - $url = WPSEO_Sitemaps_Router::get_base_url( '' ); - } - - if ( $paged > 2 ) { - $this->adjacent_rel_link( 'prev', $url, ( $paged - 1 ) ); - } - - if ( $paged < $GLOBALS['wp_query']->max_num_pages ) { - $this->adjacent_rel_link( 'next', $url, ( $paged + 1 ) ); - } - } - - /** - * Get adjacent pages link for archives. - * - * @since 1.0.2 - * @since 7.1 Added $query_arg parameter for single post/page pagination. - * - * @param string $rel Link relationship, prev or next. - * @param string $url The un-paginated URL of the current archive. - * @param string $page The page number to add on to $url for the $link tag. - * @param string $query_arg Optional. The argument to use to set for the page to load. - * - * @return void - */ - private function adjacent_rel_link( $rel, $url, $page, $query_arg = 'paged' ) { - global $wp_rewrite; - if ( ! $wp_rewrite->using_permalinks() ) { - if ( $page > 1 ) { - $url = add_query_arg( $query_arg, $page, $url ); - } - } - else { - if ( $page > 1 ) { - $url = user_trailingslashit( trailingslashit( $url ) . $this->get_pagination_base() . $page ); - } - } - - /** - * Filter: 'wpseo_' . $rel . '_rel_link' - Allow changing link rel output by Yoast SEO. - * - * @api string $unsigned The full `<link` element. - */ - $link = apply_filters( 'wpseo_' . $rel . '_rel_link', '<link rel="' . esc_attr( $rel ) . '" href="' . esc_url( $url ) . "\" />\n" ); - - if ( is_string( $link ) && $link !== '' ) { - echo $link; - } - } - - /** - * Return the base for pagination. - * - * @return string The pagination base. - */ - private function get_pagination_base() { - // If the current page is the frontpage, pagination should use /base/. - $base = ''; - if ( ! is_singular() || $this->is_home_static_page() ) { - $base = trailingslashit( $GLOBALS['wp_rewrite']->pagination_base ); - } - return $base; - } - - /** - * Output the rel=publisher code on every page of the site. - * - * @return boolean Boolean indicating whether the publisher link was printed. - */ - public function publisher() { - $publisher = WPSEO_Options::get( 'plus-publisher', '' ); - if ( $publisher !== '' ) { - echo '<link rel="publisher" href="', esc_url( $publisher ), '"/>', "\n"; - - return true; - } - - return false; - } - - /** - * Outputs the meta description element or returns the description text. - * - * @param bool $echo Echo or return output flag. - * - * @return string - */ - public function metadesc( $echo = true ) { - if ( is_null( $this->metadesc ) ) { - $this->generate_metadesc(); - } - - if ( $echo !== false ) { - if ( is_string( $this->metadesc ) && $this->metadesc !== '' ) { - echo '<meta name="description" content="', esc_attr( wp_strip_all_tags( stripslashes( $this->metadesc ) ) ), '"/>', "\n"; - } - elseif ( current_user_can( 'wpseo_manage_options' ) && is_singular() ) { - echo '<!-- ', esc_html__( 'Admin only notice: this page doesn\'t show a meta description because it doesn\'t have one, either write it for this page specifically or go into the SEO -> Search Appearance menu and set up a template.', 'wordpress-seo' ), ' -->', "\n"; - } - } - else { - return $this->metadesc; - } - } - - /** - * Generates the meta description text. - */ - private function generate_metadesc() { - global $post, $wp_query; - - $metadesc = ''; - $metadesc_override = false; - $post_type = ''; - $template = ''; - - if ( is_object( $post ) && ( isset( $post->post_type ) && $post->post_type !== '' ) ) { - $post_type = $post->post_type; - } - - if ( $this->woocommerce_shop_page->is_shop_page() ) { - $post = get_post( $this->woocommerce_shop_page->get_shop_page_id() ); - $post_type = $this->get_queried_post_type(); - - if ( ( $metadesc === '' && $post_type !== '' ) && WPSEO_Options::get( 'metadesc-ptarchive-' . $post_type, '' ) !== '' ) { - $template = WPSEO_Options::get( 'metadesc-ptarchive-' . $post_type ); - $term = $post; - } - $metadesc_override = $this->get_seo_meta_value( 'metadesc', $post->ID ); - } - elseif ( $this->frontend_page_type->is_simple_page() ) { - $post = get_post( $this->frontend_page_type->get_simple_page_id() ); - $post_type = $post->post_type; - - if ( ( $metadesc === '' && $post_type !== '' ) && WPSEO_Options::get( 'metadesc-' . $post_type, '' ) !== '' ) { - $template = WPSEO_Options::get( 'metadesc-' . $post_type ); - $term = $post; - } - $metadesc_override = $this->get_seo_meta_value( 'metadesc', $post->ID ); - } - else { - if ( is_search() ) { - $metadesc = ''; - } - elseif ( $this->is_home_posts_page() ) { - $template = WPSEO_Options::get( 'metadesc-home-wpseo' ); - $term = array(); - - if ( empty( $template ) ) { - $template = get_bloginfo( 'description' ); - } - } - elseif ( $this->is_home_static_page() ) { - $metadesc = $this->get_seo_meta_value( 'metadesc' ); - if ( ( $metadesc === '' && $post_type !== '' ) && WPSEO_Options::get( 'metadesc-' . $post_type, '' ) !== '' ) { - $template = WPSEO_Options::get( 'metadesc-' . $post_type ); - } - } - elseif ( is_category() || is_tag() || is_tax() ) { - $term = $wp_query->get_queried_object(); - $metadesc_override = WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'desc' ); - if ( is_object( $term ) && isset( $term->taxonomy ) && WPSEO_Options::get( 'metadesc-tax-' . $term->taxonomy, '' ) !== '' ) { - $template = WPSEO_Options::get( 'metadesc-tax-' . $term->taxonomy ); - } - } - elseif ( is_author() ) { - $author_id = get_query_var( 'author' ); - $metadesc = get_the_author_meta( 'wpseo_metadesc', $author_id ); - if ( ( ! is_string( $metadesc ) || $metadesc === '' ) && WPSEO_Options::get( 'metadesc-author-wpseo', '' ) !== '' ) { - $template = WPSEO_Options::get( 'metadesc-author-wpseo' ); - } - } - elseif ( is_post_type_archive() ) { - $post_type = $this->get_queried_post_type(); - if ( WPSEO_Options::get( 'metadesc-ptarchive-' . $post_type, '' ) !== '' ) { - $template = WPSEO_Options::get( 'metadesc-ptarchive-' . $post_type ); - } - } - elseif ( is_archive() ) { - $template = WPSEO_Options::get( 'metadesc-archive-wpseo' ); - } - - // If we're on a paginated page, and the template doesn't change for paginated pages, bail. - if ( ( ! is_string( $metadesc ) || $metadesc === '' ) && get_query_var( 'paged' ) && get_query_var( 'paged' ) > 1 && $template !== '' ) { - if ( strpos( $template, '%%page' ) === false ) { - $metadesc = ''; - } - } - } - - $post_data = $post; - - if ( is_string( $metadesc_override ) && '' !== $metadesc_override ) { - $metadesc = $metadesc_override; - if ( isset( $term ) ) { - $post_data = $term; - } - } - elseif ( ( ! is_string( $metadesc ) || '' === $metadesc ) && '' !== $template ) { - if ( ! isset( $term ) ) { - $term = $wp_query->get_queried_object(); - } - - $metadesc = $template; - $post_data = $term; - } - - $metadesc = $this->replace_vars( $metadesc, $post_data ); - - /** - * Filter: 'wpseo_metadesc' - Allow changing the Yoast SEO meta description sentence. - * - * @api string $metadesc The description sentence. - */ - $this->metadesc = apply_filters( 'wpseo_metadesc', trim( $metadesc ) ); - } - - /** - * Based on the redirect meta value, this function determines whether it should redirect the current post / page. - * - * @return boolean - */ - public function page_redirect() { - if ( is_singular() ) { - global $post; - if ( ! isset( $post ) || ! is_object( $post ) ) { - return false; - } - - $redir = $this->get_seo_meta_value( 'redirect', $post->ID ); - if ( $redir !== '' ) { - wp_redirect( $redir, 301 ); - exit; - } - } - - return false; - } - - /** - * Outputs noindex values for the current page. - */ - public function noindex_page() { - remove_action( 'wpseo_head', array( $this, 'canonical' ), 20 ); - echo '<meta name="robots" content="noindex" />', "\n"; - } - - /** - * Send a Robots HTTP header preventing URL from being indexed in the search results while allowing search engines - * to follow the links in the object at the URL. - * - * @since 1.1.7 - * @return boolean Boolean indicating whether the noindex header was sent. - */ - public function noindex_feed() { - - if ( ( is_feed() || is_robots() ) && headers_sent() === false ) { - header( 'X-Robots-Tag: noindex, follow', true ); - - return true; - } - - return false; - } - - /** - * Adds rel="nofollow" to a link, only used for login / registration links. - * - * @param string $input The link element as a string. - * - * @return string - */ - public function nofollow_link( $input ) { - return str_replace( '<a ', '<a rel="nofollow" ', $input ); - } - - /** - * When certain archives are disabled, this redirects those to the homepage. - * - * @return boolean False when no redirect was triggered. - */ - public function archive_redirect() { - global $wp_query; - - if ( - ( WPSEO_Options::get( 'disable-date', false ) && $wp_query->is_date ) || - ( WPSEO_Options::get( 'disable-author', false ) && $wp_query->is_author ) || - ( WPSEO_Options::get( 'disable-post_format', false ) && $wp_query->is_tax( 'post_format' ) ) - ) { - $this->redirect( get_bloginfo( 'url' ), 301 ); - - return true; - } - - return false; - } - - /** - * If the option to disable attachment URLs is checked, this performs the redirect to the attachment. - * - * @return bool Returns succes status. - */ - public function attachment_redirect() { - if ( WPSEO_Options::get( 'disable-attachment', false ) === false ) { - return false; - } - if ( ! is_attachment() ) { - return false; - } - - $url = wp_get_attachment_url( get_queried_object_id() ); - - if ( ! empty( $url ) ) { - $this->redirect( $url, 301 ); - - return true; - } - - return false; - } - - /** - * Replaces the possible RSS variables with their actual values. - * - * @param string $content The RSS content that should have the variables replaced. - * - * @return string - */ - public function rss_replace_vars( $content ) { - global $post; - - /** - * Allow the developer to determine whether or not to follow the links in the bits Yoast SEO adds to the RSS feed, defaults to true. - * - * @api bool $unsigned Whether or not to follow the links in RSS feed, defaults to true. - * - * @since 1.4.20 - */ - $no_follow = apply_filters( 'nofollow_rss_links', true ); - $no_follow_attr = ''; - if ( $no_follow === true ) { - $no_follow_attr = 'rel="nofollow" '; - } - - $author_link = ''; - if ( is_object( $post ) ) { - $author_link = '<a ' . $no_follow_attr . 'href="' . esc_url( get_author_posts_url( $post->post_author ) ) . '">' . esc_html( get_the_author() ) . '</a>'; - } - - $post_link = '<a ' . $no_follow_attr . 'href="' . esc_url( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a>'; - $blog_link = '<a ' . $no_follow_attr . 'href="' . esc_url( get_bloginfo( 'url' ) ) . '">' . esc_html( get_bloginfo( 'name' ) ) . '</a>'; - $blog_desc_link = '<a ' . $no_follow_attr . 'href="' . esc_url( get_bloginfo( 'url' ) ) . '">' . esc_html( get_bloginfo( 'name' ) ) . ' - ' . esc_html( get_bloginfo( 'description' ) ) . '</a>'; - - $content = stripslashes( trim( $content ) ); - $content = str_replace( '%%AUTHORLINK%%', $author_link, $content ); - $content = str_replace( '%%POSTLINK%%', $post_link, $content ); - $content = str_replace( '%%BLOGLINK%%', $blog_link, $content ); - $content = str_replace( '%%BLOGDESCLINK%%', $blog_desc_link, $content ); - - return $content; - } - - /** - * Adds the RSS footer (or header) to the full RSS feed item. - * - * @param string $content Feed item content. - * - * @return string - */ - public function embed_rssfooter( $content ) { - return $this->embed_rss( $content, 'full' ); - } - - /** - * Adds the RSS footer (or header) to the excerpt RSS feed item. - * - * @param string $content Feed item excerpt. - * - * @return string - */ - public function embed_rssfooter_excerpt( $content ) { - return $this->embed_rss( $content, 'excerpt' ); - } - - /** - * Adds the RSS footer and/or header to an RSS feed item. - * - * @since 1.4.14 - * - * @param string $content Feed item content. - * @param string $context Feed item context, either 'excerpt' or 'full'. - * - * @return string - */ - public function embed_rss( $content, $context = 'full' ) { - - /** - * Filter: 'wpseo_include_rss_footer' - Allow the RSS footer to be dynamically shown/hidden. - * - * @api boolean $show_embed Indicates if the RSS footer should be shown or not. - * - * @param string $context The context of the RSS content - 'full' or 'excerpt'. - */ - if ( ! apply_filters( 'wpseo_include_rss_footer', true, $context ) ) { - return $content; - } - - if ( is_feed() ) { - $before = ''; - $after = ''; - - if ( WPSEO_Options::get( 'rssbefore', '' ) !== '' ) { - $before = wpautop( $this->rss_replace_vars( WPSEO_Options::get( 'rssbefore' ) ) ); - } - if ( WPSEO_Options::get( 'rssafter', '' ) !== '' ) { - $after = wpautop( $this->rss_replace_vars( WPSEO_Options::get( 'rssafter' ) ) ); - } - if ( $before !== '' || $after !== '' ) { - if ( ( isset( $context ) && $context === 'excerpt' ) && trim( $content ) !== '' ) { - $content = wpautop( $content ); - } - $content = $before . $content . $after; - } - } - - return $content; - } - - /** - * Used in the force rewrite functionality this retrieves the output, replaces the title with the proper SEO - * title and then flushes the output. - */ - public function flush_cache() { - - global $wp_query; - - if ( $this->ob_started !== true ) { - return false; - } - - $content = ob_get_clean(); - - $old_wp_query = $wp_query; - - wp_reset_query(); - - // Only replace the debug marker when it is hooked. - if ( $this->show_debug_marker() ) { - $title = $this->title( '' ); - $debug_mark = $this->get_debug_mark(); - - // Find all titles, strip them out and add the new one in within the debug marker, so it's easily identified whether a site uses force rewrite. - $content = preg_replace( '/<title.*?\/title>/i', '', $content ); - $content = str_replace( $debug_mark, $debug_mark . "\n" . '<title>' . esc_html( $title ) . '', $content ); - } - - $GLOBALS['wp_query'] = $old_wp_query; - - echo $content; - - return true; - } - - /** - * Starts the output buffer so it can later be fixed by flush_cache(). - */ - public function force_rewrite_output_buffer() { - $this->ob_started = true; - ob_start(); - } - - /** - * Function used in testing whether the title should be force rewritten or not. - * - * @param string $title Title string. - * - * @return string - */ - public function title_test_helper( $title ) { - WPSEO_Options::set( 'title_test', ( WPSEO_Options::get( 'title_test' ) + 1 ) ); - - // Prevent this setting from being on forever when something breaks, as it breaks caching. - if ( WPSEO_Options::get( 'title_test' ) > 5 ) { - WPSEO_Options::set( 'title_test', 0 ); - - remove_filter( 'wpseo_title', array( $this, 'title_test_helper' ) ); - - return $title; - } - - if ( ! defined( 'DONOTCACHEPAGE' ) ) { - define( 'DONOTCACHEPAGE', true ); - } - if ( ! defined( 'DONOTCACHCEOBJECT' ) ) { - define( 'DONOTCACHCEOBJECT', true ); - } - if ( ! defined( 'DONOTMINIFY' ) ) { - define( 'DONOTMINIFY', true ); - } - - if ( $_SERVER['HTTP_USER_AGENT'] === "WordPress/{$GLOBALS['wp_version']}; " . get_bloginfo( 'url' ) . ' - Yoast' ) { - return 'This is a Yoast Test Title'; - } - - return $title; - } - - /** - * Get the product name in the head section. - * - * @return string - */ - private function head_product_name() { - if ( $this->is_premium() ) { - return 'Yoast SEO Premium plugin'; - } - - return 'Yoast SEO plugin'; - } - - /** - * Check if this plugin is the premium version of WPSEO. - * - * @return bool - */ - protected function is_premium() { - return WPSEO_Utils::is_yoast_seo_premium(); - } - - /** - * Check if term archive query is for multiple terms (/term-1,term2/ or /term-1+term-2/). - * - * @return bool - */ - protected function is_multiple_terms_query() { - - global $wp_query; - - if ( ! is_tax() && ! is_tag() && ! is_category() ) { - return false; - } - - $term = get_queried_object(); - $queried_terms = $wp_query->tax_query->queried_terms; - - if ( empty( $queried_terms[ $term->taxonomy ]['terms'] ) ) { - return false; - } - - return count( $queried_terms[ $term->taxonomy ]['terms'] ) > 1; - } - - /** - * Wraps wp_safe_redirect to allow testing for redirects. - * - * @param string $location The path to redirect to. - * @param int $status Status code to use. - */ - public function redirect( $location, $status = 302 ) { - wp_safe_redirect( $location, $status ); - exit; - } - - /** - * Checks if the debug mark action has been added. - * - * @return bool True when the action exists. - */ - protected function show_debug_marker() { - return has_action( 'wpseo_head', array( $this, 'debug_mark' ) ) !== false; - } - - /** - * Shows the closing debug mark. - * - * @return string The closing debug mark comment. - */ - protected function show_closing_debug_mark() { - if ( ! $this->show_debug_marker() ) { - return ''; - } - - return sprintf( - "\n\n", - esc_html( $this->head_product_name() ) - ); - } - - /** - * Builds the title for a post type archive. - * - * @param string $separator The title separator. - * @param string $separator_location The location of the title separator. - * - * @return string The title to use on a post type archive. - */ - protected function get_post_type_archive_title( $separator, $separator_location ) { - $post_type = $this->get_queried_post_type(); - - $title = $this->get_title_from_options( 'title-ptarchive-' . $post_type ); - - if ( ! is_string( $title ) || '' === $title ) { - $post_type_obj = get_post_type_object( $post_type ); - $title_part = ''; - - if ( isset( $post_type_obj->labels->menu_name ) ) { - $title_part = $post_type_obj->labels->menu_name; - } - elseif ( isset( $post_type_obj->name ) ) { - $title_part = $post_type_obj->name; - } - - $title = $this->get_default_title( $separator, $separator_location, $title_part ); - } - - return $title; - } - - /** - * Retrieves the queried post type. - * - * @return string The queried post type. - */ - protected function get_queried_post_type() { - $post_type = get_query_var( 'post_type' ); - if ( is_array( $post_type ) ) { - $post_type = reset( $post_type ); - } - - return $post_type; - } - - /** - * Retrieves the SEO Meta value for the supplied key and optional post. - * - * @param string $key The key to retrieve. - * @param int $post_id Optional. The post to retrieve the key for. - * - * @return string Meta value. - */ - protected function get_seo_meta_value( $key, $post_id = 0 ) { - return WPSEO_Meta::get_value( $key, $post_id ); - } - - /** - * Replaces the dynamic variables in a string. - * - * @param string $string The string to replace the variables in. - * @param array $args The object some of the replacement values might come from, - * could be a post, taxonomy or term. - * @param array $omit Variables that should not be replaced by this function. - * - * @return string The replaced string. - */ - protected function replace_vars( $string, $args, $omit = array() ) { - $replacer = new WPSEO_Replace_Vars(); - - return $replacer->replace( $string, $args, $omit ); - } - - /** Deprecated functions */ - // @codeCoverageIgnoreStart - /** - * Outputs or returns the debug marker, which is also used for title replacement when force rewrite is active. - * - * @deprecated 4.4 - * - * @param bool $echo Whether or not to echo the debug marker. - * - * @return string - */ - public function debug_marker( $echo = false ) { - if ( function_exists( 'wp_get_current_user' ) && current_user_can( 'manage_options' ) ) { - _deprecated_function( 'WPSEO_Frontend::debug_marker', '4.4', 'WPSEO_Frontend::debug_mark' ); - } - - return $this->debug_mark( $echo ); - } - - /** - * Outputs the meta keywords element. - * - * @deprecated 6.3 - * - * @return void - */ - public function metakeywords() { - if ( function_exists( 'wp_get_current_user' ) && current_user_can( 'manage_options' ) ) { - _deprecated_function( 'WPSEO_Frontend::metakeywords', '6.3' ); - } - } - - /** - * Removes unneeded query variables from the URL. - * - * @deprecated 7.0 - * - * @return void - */ - public function clean_permalink() { - // As this is a frontend method, we want to make sure it is not displayed for non-logged in users. - if ( function_exists( 'wp_get_current_user' ) && current_user_can( 'manage_options' ) ) { - _deprecated_function( 'WPSEO_Frontend::clean_permalink', '7.0' ); - } - } - - /** - * Trailing slashes for everything except is_single(). - * - * @deprecated 7.0 - */ - public function add_trailingslash() { - // As this is a frontend method, we want to make sure it is not displayed for non-logged in users. - if ( function_exists( 'wp_get_current_user' ) && current_user_can( 'manage_options' ) ) { - _deprecated_function( 'WPSEO_Frontend::add_trailingslash', '7.0', null ); - } - } - - /** - * Removes the ?replytocom variable from the link, replacing it with a #comment- anchor. - * - * @deprecated 7.0 - * - * @param string $link The comment link as a string. - * - * @return string The modified link. - */ - public function remove_reply_to_com( $link ) { - _deprecated_function( 'WPSEO_Frontend::remove_reply_to_com', '7.0', 'WPSEO_Remove_Reply_To_Com::remove_reply_to_com' ); - - $remove_replytocom = new WPSEO_Remove_Reply_To_Com(); - return $remove_replytocom->remove_reply_to_com( $link ); - } - - /** - * Redirects out the ?replytocom variables. - * - * @deprecated 7.0 - * - * @return boolean True when redirect has been done. - */ - public function replytocom_redirect() { - _deprecated_function( 'WPSEO_Frontend::replytocom_redirect', '7.0', 'WPSEO_Remove_Reply_To_Com::replytocom_redirect' ); - - $remove_replytocom = new WPSEO_Remove_Reply_To_Com(); - return $remove_replytocom->replytocom_redirect(); - } - // @codeCoverageIgnoreEnd -} diff --git a/wp-content/plugins/wordpress-seo/frontend/class-json-ld.php b/wp-content/plugins/wordpress-seo/frontend/class-json-ld.php deleted file mode 100644 index 0b86ef33..00000000 --- a/wp-content/plugins/wordpress-seo/frontend/class-json-ld.php +++ /dev/null @@ -1,255 +0,0 @@ -prepare_organization_person_markup(); - - switch ( $company_or_person ) { - case 'company': - $this->organization(); - break; - case 'person': - $this->person(); - break; - } - - $this->output( $company_or_person ); - } - - /** - * Outputs code to allow recognition of the internal search engine. - * - * @since 1.5.7 - * - * @link https://developers.google.com/structured-data/site-name - */ - public function website() { - if ( ! is_front_page() ) { - return; - } - $this->data = array( - '@context' => 'https://schema.org', - '@type' => 'WebSite', - '@id' => '#website', - 'url' => $this->get_home_url(), - 'name' => $this->get_website_name(), - ); - - $this->add_alternate_name(); - $this->internal_search_section(); - - $this->output( 'website' ); - } - - /** - * Outputs the JSON LD code in a valid JSON+LD wrapper. - * - * @since 1.8 - * - * @param string $context The context of the output, useful for filtering. - */ - private function output( $context ) { - /** - * Filter: 'wpseo_json_ld_output' - Allows filtering of the JSON+LD output. - * - * @api array $output The output array, before its JSON encoded. - * - * @param string $context The context of the output, useful to determine whether to filter or not. - */ - $this->data = apply_filters( 'wpseo_json_ld_output', $this->data, $context ); - - if ( is_array( $this->data ) && ! empty( $this->data ) ) { - echo "', "\n"; - } - - // Empty the $data array so we don't output it twice. - $this->data = array(); - } - - /** - * Schema for Organization. - */ - private function organization() { - if ( '' !== WPSEO_Options::get( 'company_name', '' ) ) { - $this->data['@type'] = 'Organization'; - $this->data['@id'] = '#organization'; - $this->data['name'] = WPSEO_Options::get( 'company_name' ); - $this->data['logo'] = WPSEO_Options::get( 'company_logo', '' ); - - return; - } - $this->data = false; - } - - /** - * Schema for Person. - */ - private function person() { - if ( '' !== WPSEO_Options::get( 'person_name', '' ) ) { - $this->data['@type'] = 'Person'; - $this->data['@id'] = '#person'; - $this->data['name'] = WPSEO_Options::get( 'person_name' ); - - return; - } - $this->data = false; - } - - /** - * Prepares the organization or person markup. - */ - private function prepare_organization_person_markup() { - $this->fetch_social_profiles(); - - $this->data = array( - '@context' => 'https://schema.org', - '@type' => '', - 'url' => $this->get_home_url(), - 'sameAs' => $this->profiles, - ); - } - - /** - * Retrieve the social profiles to display in the organization output. - * - * @since 1.8 - * - * @link https://developers.google.com/webmasters/structured-data/customize/social-profiles - */ - private function fetch_social_profiles() { - $social_profiles = array( - 'facebook_site', - 'instagram_url', - 'linkedin_url', - 'plus-publisher', - 'myspace_url', - 'youtube_url', - 'pinterest_url', - ); - foreach ( $social_profiles as $profile ) { - if ( WPSEO_Options::get( $profile, '' ) !== '' ) { - $this->profiles[] = WPSEO_Options::get( $profile ); - } - } - - if ( WPSEO_Options::get( 'twitter_site', '' ) !== '' ) { - $this->profiles[] = 'https://twitter.com/' . WPSEO_Options::get( 'twitter_site' ); - } - } - - /** - * Retrieves the home URL. - * - * @return string - */ - private function get_home_url() { - /** - * Filter: 'wpseo_json_home_url' - Allows filtering of the home URL for Yoast SEO's JSON+LD output. - * - * @api unsigned string - */ - return apply_filters( 'wpseo_json_home_url', WPSEO_Utils::home_url() ); - } - - /** - * Returns an alternate name if one was specified in the Yoast SEO settings. - */ - private function add_alternate_name() { - if ( '' !== WPSEO_Options::get( 'alternate_website_name', '' ) ) { - $this->data['alternateName'] = WPSEO_Options::get( 'alternate_website_name' ); - } - } - - /** - * Adds the internal search JSON LD code to the homepage if it's not disabled. - * - * @link https://developers.google.com/structured-data/slsb-overview - * - * @return void - */ - private function internal_search_section() { - /** - * Filter: 'disable_wpseo_json_ld_search' - Allow disabling of the json+ld output. - * - * @api bool $display_search Whether or not to display json+ld search on the frontend. - */ - if ( ! apply_filters( 'disable_wpseo_json_ld_search', false ) ) { - /** - * Filter: 'wpseo_json_ld_search_url' - Allows filtering of the search URL for Yoast SEO. - * - * @api string $search_url The search URL for this site with a `{search_term_string}` variable. - */ - $search_url = apply_filters( 'wpseo_json_ld_search_url', $this->get_home_url() . '?s={search_term_string}' ); - - $this->data['potentialAction'] = array( - '@type' => 'SearchAction', - 'target' => $search_url, - 'query-input' => 'required name=search_term_string', - ); - } - } - - /** - * Returns the website name either from Yoast SEO's options or from the site settings. - * - * @since 2.1 - * - * @return string - */ - private function get_website_name() { - if ( '' !== WPSEO_Options::get( 'website_name', '' ) ) { - return WPSEO_Options::get( 'website_name' ); - } - - return get_bloginfo( 'name' ); - } -} diff --git a/wp-content/plugins/wordpress-seo/frontend/class-opengraph-image.php b/wp-content/plugins/wordpress-seo/frontend/class-opengraph-image.php deleted file mode 100644 index 84991abf..00000000 --- a/wp-content/plugins/wordpress-seo/frontend/class-opengraph-image.php +++ /dev/null @@ -1,322 +0,0 @@ -add_image( $image ) ) { - $this->set_images(); - } - } - - /** - * Return the images array. - * - * @return array - */ - public function get_images() { - return $this->images; - } - - /** - * Return the dimensions array. - * - * @return array - */ - public function get_dimensions() { - return $this->dimensions; - } - - /** - * Display an OpenGraph image tag. - * - * @param string $img Source URL to the image. - * - * @return bool - */ - public function add_image( $img ) { - - $original = trim( $img ); - - // Filter: 'wpseo_opengraph_image' - Allow changing the OpenGraph image. - $img = trim( apply_filters( 'wpseo_opengraph_image', $img ) ); - - if ( $original !== $img ) { - $this->dimensions = array(); - } - - if ( empty( $img ) ) { - return false; - } - - if ( WPSEO_Utils::is_url_relative( $img ) === true ) { - $img = $this->get_relative_path( $img ); - } - - if ( in_array( $img, $this->images, true ) ) { - return false; - } - array_push( $this->images, $img ); - - return true; - } - - /** - * Check if page is front page or singular and call the corresponding functions. If not, call get_default_image. - */ - private function set_images() { - - /** - * Filter: wpseo_add_opengraph_images - Allow developers to add images to the OpenGraph tags. - * - * @api WPSEO_OpenGraph_Image The current object. - */ - do_action( 'wpseo_add_opengraph_images', $this ); - - if ( is_front_page() ) { - $this->get_front_page_image(); - } - elseif ( is_home() ) { // Posts page, which won't be caught by is_singular() below. - $this->get_posts_page_image(); - } - - $frontend_page_type = new WPSEO_Frontend_Page_Type(); - if ( $frontend_page_type->is_simple_page() ) { - $this->get_singular_image( $frontend_page_type->get_simple_page_id() ); - } - - if ( is_category() || is_tax() || is_tag() ) { - $this->get_opengraph_image_taxonomy(); - } - - /** - * Filter: wpseo_add_opengraph_additional_images - Allows to add additional images to the OpenGraph tags. - * - * @api WPSEO_OpenGraph_Image The current object. - */ - do_action( 'wpseo_add_opengraph_additional_images', $this ); - - $this->get_default_image(); - } - - /** - * If the frontpage image exists, call add_image. - */ - private function get_front_page_image() { - if ( WPSEO_Options::get( 'og_frontpage_image', '' ) !== '' ) { - $this->add_image( WPSEO_Options::get( 'og_frontpage_image' ) ); - } - } - - /** - * Get the images of the posts page. - */ - private function get_posts_page_image() { - - $post_id = get_option( 'page_for_posts' ); - - if ( $this->get_opengraph_image_post( $post_id ) ) { - return; - } - - if ( $this->get_featured_image( $post_id ) ) { - return; - } - } - - /** - * Get the images of the singular post. - * - * @param null|int $post_id The post id to get the images for. - */ - private function get_singular_image( $post_id = null ) { - if ( $post_id === null ) { - $post_id = get_the_ID(); - } - - if ( $this->get_opengraph_image_post( $post_id ) ) { - return; - } - - if ( $this->get_attachment_page_image( $post_id ) ) { - return; - } - - if ( $this->get_featured_image( $post_id ) ) { - return; - } - - $this->get_content_images( get_post( $post_id ) ); - } - - /** - * Get default image and call add_image. - */ - private function get_default_image() { - if ( count( $this->images ) === 0 && WPSEO_Options::get( 'og_default_image', '' ) !== '' ) { - $this->add_image( WPSEO_Options::get( 'og_default_image' ) ); - } - } - - /** - * If opengraph-image is set, call add_image and return true. - * - * @param int $post_id Optional post ID to use. - * - * @return bool - */ - private function get_opengraph_image_post( $post_id = 0 ) { - $ogimg = WPSEO_Meta::get_value( 'opengraph-image', $post_id ); - if ( $ogimg !== '' ) { - $this->add_image( $ogimg ); - - return true; - } - - return false; - } - - /** - * Check if taxonomy has an image and add this image. - */ - private function get_opengraph_image_taxonomy() { - $ogimg = WPSEO_Taxonomy_Meta::get_meta_without_term( 'opengraph-image' ); - if ( $ogimg !== '' ) { - $this->add_image( $ogimg ); - } - } - - /** - * If there is a featured image, check image size. If image size is correct, call add_image and return true. - * - * @param int $post_id The post ID. - * - * @return bool - */ - private function get_featured_image( $post_id ) { - - if ( has_post_thumbnail( $post_id ) ) { - /** - * Filter: 'wpseo_opengraph_image_size' - Allow changing the image size used for OpenGraph sharing. - * - * @api string $unsigned Size string. - */ - $thumb = wp_get_attachment_image_src( get_post_thumbnail_id( $post_id ), apply_filters( 'wpseo_opengraph_image_size', 'original' ) ); - - if ( $this->check_featured_image_size( $thumb ) ) { - - $this->dimensions['width'] = $thumb[1]; - $this->dimensions['height'] = $thumb[2]; - - return $this->add_image( $thumb[0] ); - } - } - - return false; - } - - /** - * If this is an attachment page, call add_image with the attachment and return true. - * - * @param int $post_id The post ID. - * - * @return bool - */ - private function get_attachment_page_image( $post_id ) { - if ( get_post_type( $post_id ) === 'attachment' ) { - $mime_type = get_post_mime_type( $post_id ); - switch ( $mime_type ) { - case 'image/jpeg': - case 'image/png': - case 'image/gif': - return $this->add_image( wp_get_attachment_url( $post_id ) ); - } - } - - return false; - } - - /** - * Filter: 'wpseo_pre_analysis_post_content' - Allow filtering the content before analysis. - * - * @api string $post_content The Post content string. - * - * @param object $post The post object. - */ - private function get_content_images( $post ) { - $content = apply_filters( 'wpseo_pre_analysis_post_content', $post->post_content, $post ); - - if ( preg_match_all( '`]+>`', $content, $matches ) ) { - foreach ( $matches[0] as $img ) { - if ( preg_match( '`src=(["\'])(.*?)\1`', $img, $match ) ) { - $this->add_image( $match[2] ); - } - } - } - } - - /** - * Check size of featured image. If image is too small, return false, else return true. - * - * @param array $img_data Image info from wp_get_attachment_image_src: url, width, height, icon. - * - * @return bool - */ - private function check_featured_image_size( $img_data ) { - - if ( ! is_array( $img_data ) ) { - return false; - } - - // Get the width and height of the image. - if ( $img_data[1] < 200 || $img_data[2] < 200 ) { - return false; - } - - return true; - } - - /** - * Get the relative path of the image. - * - * @param array $img Image data array. - * - * @return bool|string - */ - private function get_relative_path( $img ) { - if ( $img[0] !== '/' ) { - return false; - } - - // If it's a relative URL, it's relative to the domain, not necessarily to the WordPress install, we - // want to preserve domain name and URL scheme (http / https) though. - $parsed_url = wp_parse_url( home_url() ); - $img = $parsed_url['scheme'] . '://' . $parsed_url['host'] . $img; - - return $img; - } -} diff --git a/wp-content/plugins/wordpress-seo/frontend/class-opengraph.php b/wp-content/plugins/wordpress-seo/frontend/class-opengraph.php deleted file mode 100644 index 8ac3c6bc..00000000 --- a/wp-content/plugins/wordpress-seo/frontend/class-opengraph.php +++ /dev/null @@ -1,782 +0,0 @@ -frontend_page_type = new WPSEO_Frontend_Page_Type(); - } - - /** - * Main OpenGraph output. - */ - public function opengraph() { - wp_reset_query(); - /** - * Action: 'wpseo_opengraph' - Hook to add all Facebook OpenGraph output to so they're close together. - */ - do_action( 'wpseo_opengraph' ); - } - - /** - * Internal function to output FB tags. This also adds an output filter to each bit of output based on the property. - * - * @param string $property Property attribute value. - * @param string $content Content attribute value. - * - * @return boolean - */ - public function og_tag( $property, $content ) { - $og_property = str_replace( ':', '_', $property ); - /** - * Filter: 'wpseo_og_' . $og_property - Allow developers to change the content of specific OG meta tags. - * - * @api string $content The content of the property. - */ - $content = apply_filters( 'wpseo_og_' . $og_property, $content ); - if ( empty( $content ) ) { - return false; - } - - echo '', "\n"; - - return true; - } - - /** - * Filter the Facebook plugins metadata. - * - * @param array $meta_tags The array to fix. - * - * @return array $meta_tags - */ - public function facebook_filter( $meta_tags ) { - $meta_tags['http://ogp.me/ns#type'] = $this->type( false ); - $meta_tags['http://ogp.me/ns#title'] = $this->og_title( false ); - - // Filter the locale too because the Facebook plugin locale code is not as good as ours. - $meta_tags['http://ogp.me/ns#locale'] = $this->locale( false ); - - $ogdesc = $this->description( false ); - if ( ! empty( $ogdesc ) ) { - $meta_tags['http://ogp.me/ns#description'] = $ogdesc; - } - - return $meta_tags; - } - - /** - * Filter for the namespace, adding the OpenGraph namespace. - * - * @link https://developers.facebook.com/docs/web/tutorials/scrumptious/open-graph-object/ - * - * @param string $input The input namespace string. - * - * @return string - */ - public function add_opengraph_namespace( $input ) { - $namespaces = array( - 'og: http://ogp.me/ns#', - ); - - /** - * Allow for adding additional namespaces to the prefix attributes. - * - * @since 3.9.0 - * - * @param array $namespaces Currently registered namespaces which are to be - * added to the prefix attribute. - * Namespaces are strings and have the following syntax: - * ns: http://url.to.namespace/definition - */ - $namespaces = apply_filters( 'wpseo_html_namespaces', $namespaces ); - $namespace_string = implode( ' ', array_unique( $namespaces ) ); - - if ( strpos( $input, ' prefix=' ) !== false ) { - $regex = '`prefix=([\'"])(.+?)\1`'; - $replace = 'prefix="$2 ' . $namespace_string . '"'; - $input = preg_replace( $regex, $replace, $input ); - } - else { - $input .= ' prefix="' . $namespace_string . '"'; - } - - return $input; - } - - /** - * Outputs the authors FB page. - * - * @link https://developers.facebook.com/blog/post/2013/06/19/platform-updates--new-open-graph-tags-for-media-publishers-and-more/ - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/article/ - * - * @return boolean - */ - public function article_author_facebook() { - if ( ! is_singular() ) { - return false; - } - - /** - * Filter: 'wpseo_opengraph_author_facebook' - Allow developers to filter the Yoast SEO post authors facebook profile URL. - * - * @api bool|string $unsigned The Facebook author URL, return false to disable. - */ - $facebook = apply_filters( 'wpseo_opengraph_author_facebook', get_the_author_meta( 'facebook', $GLOBALS['post']->post_author ) ); - - if ( $facebook && ( is_string( $facebook ) && $facebook !== '' ) ) { - $this->og_tag( 'article:author', $facebook ); - - return true; - } - - return false; - } - - /** - * Outputs the websites FB page. - * - * @link https://developers.facebook.com/blog/post/2013/06/19/platform-updates--new-open-graph-tags-for-media-publishers-and-more/ - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/article/ - * @return boolean - */ - public function website_facebook() { - - if ( 'article' === $this->type( false ) && WPSEO_Options::get( 'facebook_site', '' ) !== '' ) { - $this->og_tag( 'article:publisher', WPSEO_Options::get( 'facebook_site' ) ); - - return true; - } - - return false; - } - - /** - * Outputs the SEO title as OpenGraph title. - * - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/article/ - * - * @param bool $echo Whether or not to echo the output. - * - * @return string|boolean - */ - public function og_title( $echo = true ) { - - $frontend = WPSEO_Frontend::get_instance(); - - if ( $this->frontend_page_type->is_simple_page() ) { - $post_id = $this->frontend_page_type->get_simple_page_id(); - $post = get_post( $post_id ); - $title = WPSEO_Meta::get_value( 'opengraph-title', $post_id ); - - if ( $title === '' ) { - $title = $frontend->title( '' ); - } - else { - // Replace Yoast SEO Variables. - $title = wpseo_replace_vars( $title, $post ); - } - } - elseif ( is_front_page() ) { - $title = ( WPSEO_Options::get( 'og_frontpage_title', '' ) !== '' ) ? WPSEO_Options::get( 'og_frontpage_title' ) : $frontend->title( '' ); - } - elseif ( is_category() || is_tax() || is_tag() ) { - $title = WPSEO_Taxonomy_Meta::get_meta_without_term( 'opengraph-title' ); - if ( $title === '' ) { - $title = $frontend->title( '' ); - } - else { - // Replace Yoast SEO Variables. - $title = wpseo_replace_vars( $title, $GLOBALS['wp_query']->get_queried_object() ); - } - } - else { - $title = $frontend->title( '' ); - } - - /** - * Filter: 'wpseo_opengraph_title' - Allow changing the title specifically for OpenGraph. - * - * @api string $unsigned The title string. - */ - $title = trim( apply_filters( 'wpseo_opengraph_title', $title ) ); - - if ( is_string( $title ) && $title !== '' ) { - if ( $echo !== false ) { - $this->og_tag( 'og:title', $title ); - - return true; - } - } - - if ( $echo === false ) { - return $title; - } - - return false; - } - - /** - * Outputs the canonical URL as OpenGraph URL, which consolidates likes and shares. - * - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/article/ - * @return boolean - */ - public function url() { - /** - * Filter: 'wpseo_opengraph_url' - Allow changing the OpenGraph URL. - * - * @api string $unsigned Canonical URL. - */ - $url = apply_filters( 'wpseo_opengraph_url', WPSEO_Frontend::get_instance()->canonical( false ) ); - - if ( is_string( $url ) && $url !== '' ) { - $this->og_tag( 'og:url', esc_url( $url ) ); - - return true; - } - - return false; - } - - /** - * Output the locale, doing some conversions to make sure the proper Facebook locale is outputted. - * - * Last update/compare with FB list done on 2015-03-16 by Rarst - * - * @see http://www.facebook.com/translations/FacebookLocales.xml for the list of supported locales - * - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/article/ - * - * @param bool $echo Whether to echo or return the locale. - * - * @return string $locale - */ - public function locale( $echo = true ) { - /** - * Filter: 'wpseo_locale' - Allow changing the locale output. - * - * @api string $unsigned Locale string. - */ - $locale = apply_filters( 'wpseo_locale', get_locale() ); - - // Catch some weird locales served out by WP that are not easily doubled up. - $fix_locales = array( - 'ca' => 'ca_ES', - 'en' => 'en_US', - 'el' => 'el_GR', - 'et' => 'et_EE', - 'ja' => 'ja_JP', - 'sq' => 'sq_AL', - 'uk' => 'uk_UA', - 'vi' => 'vi_VN', - 'zh' => 'zh_CN', - ); - - if ( isset( $fix_locales[ $locale ] ) ) { - $locale = $fix_locales[ $locale ]; - } - - // Convert locales like "es" to "es_ES", in case that works for the given locale (sometimes it does). - if ( strlen( $locale ) === 2 ) { - $locale = strtolower( $locale ) . '_' . strtoupper( $locale ); - } - - // These are the locales FB supports. - $fb_valid_fb_locales = array( - 'af_ZA', // Afrikaans. - 'ak_GH', // Akan. - 'am_ET', // Amharic. - 'ar_AR', // Arabic. - 'as_IN', // Assamese. - 'ay_BO', // Aymara. - 'az_AZ', // Azerbaijani. - 'be_BY', // Belarusian. - 'bg_BG', // Bulgarian. - 'bn_IN', // Bengali. - 'br_FR', // Breton. - 'bs_BA', // Bosnian. - 'ca_ES', // Catalan. - 'cb_IQ', // Sorani Kurdish. - 'ck_US', // Cherokee. - 'co_FR', // Corsican. - 'cs_CZ', // Czech. - 'cx_PH', // Cebuano. - 'cy_GB', // Welsh. - 'da_DK', // Danish. - 'de_DE', // German. - 'el_GR', // Greek. - 'en_GB', // English (UK). - 'en_IN', // English (India). - 'en_PI', // English (Pirate). - 'en_UD', // English (Upside Down). - 'en_US', // English (US). - 'eo_EO', // Esperanto. - 'es_CL', // Spanish (Chile). - 'es_CO', // Spanish (Colombia). - 'es_ES', // Spanish (Spain). - 'es_LA', // Spanish. - 'es_MX', // Spanish (Mexico). - 'es_VE', // Spanish (Venezuela). - 'et_EE', // Estonian. - 'eu_ES', // Basque. - 'fa_IR', // Persian. - 'fb_LT', // Leet Speak. - 'ff_NG', // Fulah. - 'fi_FI', // Finnish. - 'fo_FO', // Faroese. - 'fr_CA', // French (Canada). - 'fr_FR', // French (France). - 'fy_NL', // Frisian. - 'ga_IE', // Irish. - 'gl_ES', // Galician. - 'gn_PY', // Guarani. - 'gu_IN', // Gujarati. - 'gx_GR', // Classical Greek. - 'ha_NG', // Hausa. - 'he_IL', // Hebrew. - 'hi_IN', // Hindi. - 'hr_HR', // Croatian. - 'hu_HU', // Hungarian. - 'hy_AM', // Armenian. - 'id_ID', // Indonesian. - 'ig_NG', // Igbo. - 'is_IS', // Icelandic. - 'it_IT', // Italian. - 'ja_JP', // Japanese. - 'ja_KS', // Japanese (Kansai). - 'jv_ID', // Javanese. - 'ka_GE', // Georgian. - 'kk_KZ', // Kazakh. - 'km_KH', // Khmer. - 'kn_IN', // Kannada. - 'ko_KR', // Korean. - 'ku_TR', // Kurdish (Kurmanji). - 'ky_KG', // Kyrgyz. - 'la_VA', // Latin. - 'lg_UG', // Ganda. - 'li_NL', // Limburgish. - 'ln_CD', // Lingala. - 'lo_LA', // Lao. - 'lt_LT', // Lithuanian. - 'lv_LV', // Latvian. - 'mg_MG', // Malagasy. - 'mi_NZ', // Maori. - 'mk_MK', // Macedonian. - 'ml_IN', // Malayalam. - 'mn_MN', // Mongolian. - 'mr_IN', // Marathi. - 'ms_MY', // Malay. - 'mt_MT', // Maltese. - 'my_MM', // Burmese. - 'nb_NO', // Norwegian (bokmal). - 'nd_ZW', // Ndebele. - 'ne_NP', // Nepali. - 'nl_BE', // Dutch (Belgie). - 'nl_NL', // Dutch. - 'nn_NO', // Norwegian (nynorsk). - 'ny_MW', // Chewa. - 'or_IN', // Oriya. - 'pa_IN', // Punjabi. - 'pl_PL', // Polish. - 'ps_AF', // Pashto. - 'pt_BR', // Portuguese (Brazil). - 'pt_PT', // Portuguese (Portugal). - 'qu_PE', // Quechua. - 'rm_CH', // Romansh. - 'ro_RO', // Romanian. - 'ru_RU', // Russian. - 'rw_RW', // Kinyarwanda. - 'sa_IN', // Sanskrit. - 'sc_IT', // Sardinian. - 'se_NO', // Northern Sami. - 'si_LK', // Sinhala. - 'sk_SK', // Slovak. - 'sl_SI', // Slovenian. - 'sn_ZW', // Shona. - 'so_SO', // Somali. - 'sq_AL', // Albanian. - 'sr_RS', // Serbian. - 'sv_SE', // Swedish. - 'sw_KE', // Swahili. - 'sy_SY', // Syriac. - 'sz_PL', // Silesian. - 'ta_IN', // Tamil. - 'te_IN', // Telugu. - 'tg_TJ', // Tajik. - 'th_TH', // Thai. - 'tk_TM', // Turkmen. - 'tl_PH', // Filipino. - 'tl_ST', // Klingon. - 'tr_TR', // Turkish. - 'tt_RU', // Tatar. - 'tz_MA', // Tamazight. - 'uk_UA', // Ukrainian. - 'ur_PK', // Urdu. - 'uz_UZ', // Uzbek. - 'vi_VN', // Vietnamese. - 'wo_SN', // Wolof. - 'xh_ZA', // Xhosa. - 'yi_DE', // Yiddish. - 'yo_NG', // Yoruba. - 'zh_CN', // Simplified Chinese (China). - 'zh_HK', // Traditional Chinese (Hong Kong). - 'zh_TW', // Traditional Chinese (Taiwan). - 'zu_ZA', // Zulu. - 'zz_TR', // Zazaki. - ); - - // Check to see if the locale is a valid FB one, if not, use en_US as a fallback. - if ( ! in_array( $locale, $fb_valid_fb_locales, true ) ) { - $locale = strtolower( substr( $locale, 0, 2 ) ) . '_' . strtoupper( substr( $locale, 0, 2 ) ); - if ( ! in_array( $locale, $fb_valid_fb_locales, true ) ) { - $locale = 'en_US'; - } - } - - if ( $echo !== false ) { - $this->og_tag( 'og:locale', $locale ); - } - - return $locale; - } - - /** - * Output the OpenGraph type. - * - * @param boolean $echo Whether to echo or return the type. - * - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/object/ - * - * @return string $type - */ - public function type( $echo = true ) { - - if ( is_front_page() || is_home() ) { - $type = 'website'; - } - elseif ( is_singular() ) { - - // This'll usually only be changed by plugins right now. - $type = WPSEO_Meta::get_value( 'og_type' ); - - if ( $type === '' ) { - $type = 'article'; - } - } - else { - // We use "object" for archives etc. as article doesn't apply there. - $type = 'object'; - } - - /** - * Filter: 'wpseo_opengraph_type' - Allow changing the OpenGraph type of the page. - * - * @api string $type The OpenGraph type string. - */ - $type = apply_filters( 'wpseo_opengraph_type', $type ); - - if ( is_string( $type ) && $type !== '' ) { - if ( $echo !== false ) { - $this->og_tag( 'og:type', $type ); - } - else { - return $type; - } - } - - return ''; - } - - /** - * Create new WPSEO_OpenGraph_Image class and get the images to set the og:image. - * - * @param string|boolean $image Optional image URL. - */ - public function image( $image = false ) { - $opengraph_images = new WPSEO_OpenGraph_Image( $image ); - - foreach ( $opengraph_images->get_images() as $img ) { - $this->og_tag( 'og:image', esc_url( $img ) ); - - if ( 0 === strpos( $img, 'https://' ) ) { - $this->og_tag( 'og:image:secure_url', esc_url( $img ) ); - } - } - - $dimensions = $opengraph_images->get_dimensions(); - - if ( ! empty( $dimensions['width'] ) ) { - $this->og_tag( 'og:image:width', absint( $dimensions['width'] ) ); - } - - if ( ! empty( $dimensions['height'] ) ) { - $this->og_tag( 'og:image:height', absint( $dimensions['height'] ) ); - } - } - - /** - * Fallback method for plugins using image_output. - * - * @param string $image Image URL. - */ - public function image_output( $image ) { - $this->image( $image ); - } - - /** - * Output the OpenGraph description, specific OG description first, if not, grab the meta description. - * - * @param bool $echo Whether to echo or return the description. - * - * @return string $ogdesc - */ - public function description( $echo = true ) { - $ogdesc = ''; - $frontend = WPSEO_Frontend::get_instance(); - - if ( is_front_page() ) { - if ( WPSEO_Options::get( 'og_frontpage_desc', '' ) !== '' ) { - $ogdesc = wpseo_replace_vars( WPSEO_Options::get( 'og_frontpage_desc' ), null ); - } - else { - $ogdesc = $frontend->metadesc( false ); - } - } - - if ( $this->frontend_page_type->is_simple_page() ) { - $post_id = $this->frontend_page_type->get_simple_page_id(); - $post = get_post( $post_id ); - $ogdesc = WPSEO_Meta::get_value( 'opengraph-description', $post_id ); - - // Replace Yoast SEO Variables. - $ogdesc = wpseo_replace_vars( $ogdesc, $post ); - - // Use metadesc if $ogdesc is empty. - if ( $ogdesc === '' ) { - $ogdesc = $frontend->metadesc( false ); - } - - // Tag og:description is still blank so grab it from get_the_excerpt(). - if ( ! is_string( $ogdesc ) || ( is_string( $ogdesc ) && $ogdesc === '' ) ) { - $ogdesc = str_replace( '[…]', '…', wp_strip_all_tags( get_the_excerpt() ) ); - } - } - - if ( is_category() || is_tag() || is_tax() ) { - $ogdesc = WPSEO_Taxonomy_Meta::get_meta_without_term( 'opengraph-description' ); - if ( $ogdesc === '' ) { - $ogdesc = $frontend->metadesc( false ); - } - - if ( $ogdesc === '' ) { - $ogdesc = wp_strip_all_tags( term_description() ); - } - - if ( $ogdesc === '' ) { - $ogdesc = WPSEO_Taxonomy_Meta::get_meta_without_term( 'desc' ); - } - } - - // Strip shortcodes if any. - $ogdesc = strip_shortcodes( $ogdesc ); - - /** - * Filter: 'wpseo_opengraph_desc' - Allow changing the OpenGraph description. - * - * @api string $ogdesc The description string. - */ - $ogdesc = trim( apply_filters( 'wpseo_opengraph_desc', $ogdesc ) ); - - if ( is_string( $ogdesc ) && $ogdesc !== '' ) { - if ( $echo !== false ) { - $this->og_tag( 'og:description', $ogdesc ); - } - } - - return $ogdesc; - } - - /** - * Output the site name straight from the blog info. - */ - public function site_name() { - /** - * Filter: 'wpseo_opengraph_site_name' - Allow changing the OpenGraph site name. - * - * @api string $unsigned Blog name string. - */ - $name = apply_filters( 'wpseo_opengraph_site_name', get_bloginfo( 'name' ) ); - if ( is_string( $name ) && $name !== '' ) { - $this->og_tag( 'og:site_name', $name ); - } - } - - /** - * Output the article tags as article:tag tags. - * - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/article/ - * @return boolean - */ - public function tags() { - if ( ! is_singular() ) { - return false; - } - - $tags = get_the_tags(); - if ( ! is_wp_error( $tags ) && ( is_array( $tags ) && $tags !== array() ) ) { - - foreach ( $tags as $tag ) { - $this->og_tag( 'article:tag', $tag->name ); - } - - return true; - } - - return false; - } - - /** - * Output the article category as an article:section tag. - * - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/article/ - * @return boolean; - */ - public function category() { - - if ( ! is_singular() ) { - return false; - } - - $post = get_post(); - if ( ! $post ) { - return false; - } - - $primary_term = new WPSEO_Primary_Term( 'category', $post->ID ); - $primary_category = $primary_term->get_primary_term(); - - if ( $primary_category ) { - // We can only show one section here, so we take the first one. - $this->og_tag( 'article:section', get_cat_name( $primary_category ) ); - - return true; - } - - $terms = get_the_category(); - - if ( ! is_wp_error( $terms ) && ( is_array( $terms ) && $terms !== array() ) ) { - // We can only show one section here, so we take the first one. - $this->og_tag( 'article:section', $terms[0]->name ); - - return true; - } - - return false; - } - - /** - * Output the article publish and last modification date. - * - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/article/ - * @return boolean; - */ - public function publish_date() { - - if ( ! is_singular( 'post' ) ) { - /** - * Filter: 'wpseo_opengraph_show_publish_date' - Allow showing publication date for other post types. - * - * @api bool $unsigned Whether or not to show publish date. - * - * @param string $post_type The current URL's post type. - */ - if ( false === apply_filters( 'wpseo_opengraph_show_publish_date', false, get_post_type() ) ) { - return false; - } - } - - $pub = get_the_date( DATE_W3C ); - $this->og_tag( 'article:published_time', $pub ); - - $mod = get_the_modified_date( DATE_W3C ); - if ( $mod !== $pub ) { - $this->og_tag( 'article:modified_time', $mod ); - $this->og_tag( 'og:updated_time', $mod ); - } - - return true; - } - - /** - * Outputs the Facebook app_id. - * - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/article/ - * - * @return void - */ - public function app_id() { - $app_id = WPSEO_Options::get( 'fbadminapp', '' ); - if ( $app_id !== '' ) { - $this->og_tag( 'fb:app_id', $app_id ); - } - } - - - /** - * Outputs the site owner. - * - * @link https://developers.facebook.com/docs/reference/opengraph/object-type/article/ - * @return void - * - * @deprecated 7.1 - * @codeCoverageIgnore - */ - public function site_owner() { - // As this is a frontend method, we want to make sure it is not displayed for non-logged in users. - if ( function_exists( 'wp_get_current_user' ) && current_user_can( 'manage_options' ) ) { - _deprecated_function( 'WPSEO_OpenGraph::site_owner', '7.1', null ); - } - } - -} /* End of class */ diff --git a/wp-content/plugins/wordpress-seo/frontend/class-primary-category.php b/wp-content/plugins/wordpress-seo/frontend/class-primary-category.php deleted file mode 100644 index d2cf35bf..00000000 --- a/wp-content/plugins/wordpress-seo/frontend/class-primary-category.php +++ /dev/null @@ -1,71 +0,0 @@ -get_primary_category( $post ); - - if ( false !== $primary_category && $primary_category !== $category->cat_ID ) { - $category = $this->get_category( $primary_category ); - } - - return $category; - } - - /** - * Get the id of the primary category. - * - * @param WP_Post $post The post in question. - * - * @return int Primary category id. - */ - protected function get_primary_category( $post = null ) { - $post = get_post( $post ); - - if ( $post === null ) { - return false; - } - - $primary_term = new WPSEO_Primary_Term( 'category', $post->ID ); - - return $primary_term->get_primary_term(); - } - - /** - * Wrapper for get category to make mocking easier. - * - * @param int $primary_category ID of primary category. - * - * @return array|null|object|WP_Error - */ - protected function get_category( $primary_category ) { - $category = get_category( $primary_category ); - - return $category; - } -} diff --git a/wp-content/plugins/wordpress-seo/frontend/class-remove-reply-to-com.php b/wp-content/plugins/wordpress-seo/frontend/class-remove-reply-to-com.php deleted file mode 100644 index 88cc3041..00000000 --- a/wp-content/plugins/wordpress-seo/frontend/class-remove-reply-to-com.php +++ /dev/null @@ -1,80 +0,0 @@ -clean_reply_to_com() ) { - add_filter( 'comment_reply_link', array( $this, 'remove_reply_to_com' ) ); - add_action( 'template_redirect', array( $this, 'replytocom_redirect' ), 1 ); - } - } - - /** - * Removes the ?replytocom variable from the link, replacing it with a #comment- anchor. - * - * @todo Should this function also allow for relative urls ? - * - * @param string $link The comment link as a string. - * - * @return string The modified link. - */ - public function remove_reply_to_com( $link ) { - return preg_replace( '`href=(["\'])(?:.*(?:\?|&|&)replytocom=(\d+)#respond)`', 'href=$1#comment-$2', $link ); - } - - /** - * Redirects out the ?replytocom variables. - * - * @since 1.4.13 - * @return boolean True when redirect has been done. - */ - public function replytocom_redirect() { - if ( isset( $_GET['replytocom'] ) && is_singular() ) { - $url = get_permalink( $GLOBALS['post']->ID ); - $hash = sanitize_text_field( $_GET['replytocom'] ); - $query_string = remove_query_arg( 'replytocom', sanitize_text_field( $_SERVER['QUERY_STRING'] ) ); - if ( ! empty( $query_string ) ) { - $url .= '?' . $query_string; - } - $url .= '#comment-' . $hash; - - $front = WPSEO_Frontend::get_instance(); - $front->redirect( $url, 301 ); - - return true; - } - - return false; - } - - /** - * Checks whether we can allow the feature that removes ?replytocom query parameters. - * - * @return bool True to remove, false not to remove. - */ - private function clean_reply_to_com() { - /** - * Filter: 'wpseo_remove_reply_to_com' - Allow disabling the feature that removes ?replytocom query parameters. - * - * @param bool $return True to remove, false not to remove. - */ - return (bool) apply_filters( 'wpseo_remove_reply_to_com', true ); - } -} diff --git a/wp-content/plugins/wordpress-seo/frontend/class-twitter.php b/wp-content/plugins/wordpress-seo/frontend/class-twitter.php deleted file mode 100644 index 1badfa56..00000000 --- a/wp-content/plugins/wordpress-seo/frontend/class-twitter.php +++ /dev/null @@ -1,653 +0,0 @@ -frontend_page_type = new WPSEO_Frontend_Page_Type(); - - $this->twitter(); - } - - /** - * Outputs the Twitter Card code on singular pages. - */ - public function twitter() { - - /** - * Filter: 'wpseo_output_twitter_card' - Allow disabling of the Twitter card - * - * @api bool $enabled Enabled/disabled flag - */ - if ( false === apply_filters( 'wpseo_output_twitter_card', true ) ) { - return; - } - - wp_reset_query(); - - $this->type(); - $this->description(); - $this->title(); - $this->site_twitter(); - $this->image(); - if ( is_singular() ) { - $this->author(); - } - - /** - * Action: 'wpseo_twitter' - Hook to add all Yoast SEO Twitter output to so they're close together. - */ - do_action( 'wpseo_twitter' ); - } - - /** - * Display the Twitter card type. - * - * This defaults to summary but can be filtered using the wpseo_twitter_card_type filter. - * - * @link https://dev.twitter.com/docs/cards - */ - protected function type() { - $this->determine_card_type(); - $this->sanitize_card_type(); - - $this->output_metatag( 'card', $this->type ); - } - - /** - * Determines the twitter card type for the current page - */ - private function determine_card_type() { - $this->type = WPSEO_Options::get( 'twitter_card_type' ); - - // @todo This should be reworked to use summary_large_image for any fitting image R. - if ( is_singular() && has_shortcode( $GLOBALS['post']->post_content, 'gallery' ) ) { - - $this->images = get_post_gallery_images(); - - if ( count( $this->images ) > 0 ) { - $this->type = 'summary_large_image'; - } - } - - /** - * Filter: 'wpseo_twitter_card_type' - Allow changing the Twitter Card type as output in the Twitter card by Yoast SEO - * - * @api string $unsigned The type string - */ - $this->type = apply_filters( 'wpseo_twitter_card_type', $this->type ); - } - - /** - * Determines whether the card type is of a type currently allowed by Twitter - * - * @link https://dev.twitter.com/cards/types - */ - private function sanitize_card_type() { - if ( ! in_array( $this->type, array( - 'summary', - 'summary_large_image', - 'app', - 'player', - ), true ) - ) { - $this->type = 'summary'; - } - } - - /** - * Output the metatag - * - * @param string $name Tag name string. - * @param string $value Tag value string. - * @param bool $escaped Force escape flag. - */ - private function output_metatag( $name, $value, $escaped = false ) { - - // Escape the value if not escaped. - if ( false === $escaped ) { - $value = esc_attr( $value ); - } - - /** - * Filter: 'wpseo_twitter_metatag_key' - Make the Twitter metatag key filterable - * - * @api string $key The Twitter metatag key - */ - $metatag_key = apply_filters( 'wpseo_twitter_metatag_key', 'name' ); - - // Output meta. - echo '', "\n"; - } - - /** - * Displays the description for Twitter. - * - * Only used when OpenGraph is inactive. - */ - protected function description() { - if ( $this->frontend_page_type->is_simple_page() ) { - $meta_desc = $this->single_description( $this->frontend_page_type->get_simple_page_id() ); - } - elseif ( is_category() || is_tax() || is_tag() ) { - $meta_desc = $this->taxonomy_description(); - } - else { - $meta_desc = $this->fallback_description(); - } - - /** - * Filter: 'wpseo_twitter_description' - Allow changing the Twitter description as output in the Twitter card by Yoast SEO - * - * @api string $twitter The description string - */ - $meta_desc = apply_filters( 'wpseo_twitter_description', $meta_desc ); - if ( is_string( $meta_desc ) && $meta_desc !== '' ) { - $this->output_metatag( 'description', $meta_desc ); - } - } - - /** - * Returns the description for a singular page - * - * @param int $post_id Post ID. - * - * @return string - */ - private function single_description( $post_id = 0 ) { - $meta_desc = trim( WPSEO_Meta::get_value( 'twitter-description', $post_id ) ); - - if ( is_string( $meta_desc ) && '' !== $meta_desc ) { - return $meta_desc; - } - - $meta_desc = $this->fallback_description(); - if ( is_string( $meta_desc ) && '' !== $meta_desc ) { - return $meta_desc; - } - - return wp_strip_all_tags( get_the_excerpt() ); - } - - - /** - * Getting the description for the taxonomy - * - * @return bool|mixed|string - */ - private function taxonomy_description() { - $meta_desc = WPSEO_Taxonomy_Meta::get_meta_without_term( 'twitter-description' ); - - if ( ! is_string( $meta_desc ) || $meta_desc === '' ) { - $meta_desc = $this->fallback_description(); - } - - if ( is_string( $meta_desc ) || $meta_desc !== '' ) { - return $meta_desc; - } - - return wp_strip_all_tags( term_description() ); - - } - - /** - * Returns a fallback description - * - * @return string - */ - private function fallback_description() { - return trim( WPSEO_Frontend::get_instance()->metadesc( false ) ); - } - - /** - * Displays the title for Twitter. - * - * Only used when OpenGraph is inactive. - */ - protected function title() { - if ( $this->frontend_page_type->is_simple_page() ) { - $title = $this->single_title( $this->frontend_page_type->get_simple_page_id() ); - } - elseif ( is_category() || is_tax() || is_tag() ) { - $title = $this->taxonomy_title(); - } - else { - $title = $this->fallback_title(); - } - - /** - * Filter: 'wpseo_twitter_title' - Allow changing the Twitter title as output in the Twitter card by Yoast SEO - * - * @api string $twitter The title string - */ - $title = apply_filters( 'wpseo_twitter_title', $title ); - if ( is_string( $title ) && $title !== '' ) { - $this->output_metatag( 'title', $title ); - } - } - - /** - * Returns the Twitter title for a single post - * - * @param int $post_id Post ID. - * - * @return string - */ - private function single_title( $post_id = 0 ) { - $title = WPSEO_Meta::get_value( 'twitter-title', $post_id ); - if ( ! is_string( $title ) || $title === '' ) { - return $this->fallback_title(); - } - - return $title; - } - - /** - * Getting the title for the taxonomy - * - * @return bool|mixed|string - */ - private function taxonomy_title() { - $title = WPSEO_Taxonomy_Meta::get_meta_without_term( 'twitter-title' ); - - if ( ! is_string( $title ) || $title === '' ) { - return $this->fallback_title(); - } - - return $title; - } - - /** - * Returns the Twitter title for any page - * - * @return string - */ - private function fallback_title() { - return WPSEO_Frontend::get_instance()->title( '' ); - } - - /** - * Displays the Twitter account for the site. - */ - protected function site_twitter() { - /** - * Filter: 'wpseo_twitter_site' - Allow changing the Twitter site account as output in the Twitter card by Yoast SEO - * - * @api string $unsigned Twitter site account string - */ - $site = apply_filters( 'wpseo_twitter_site', WPSEO_Options::get( 'twitter_site' ) ); - $site = $this->get_twitter_id( $site ); - - if ( is_string( $site ) && $site !== '' ) { - $this->output_metatag( 'site', '@' . $site ); - } - } - - /** - * Checks if the given id is actually an id or a url and if url, distills the id from it. - * - * Solves issues with filters returning urls and theme's/other plugins also adding a user meta - * twitter field which expects url rather than an id (which is what we expect). - * - * @param string $id Twitter ID or url. - * - * @return string|bool Twitter ID or false if it failed to get a valid Twitter ID. - */ - private function get_twitter_id( $id ) { - if ( preg_match( '`([A-Za-z0-9_]{1,25})$`', $id, $match ) ) { - return $match[1]; - } - - return false; - } - - /** - * Displays the image for Twitter - * - * Only used when OpenGraph is inactive or Summary Large Image card is chosen. - */ - protected function image() { - if ( is_category() || is_tax() || is_tag() ) { - $this->taxonomy_image_output(); - } - else { - $this->single_image_output(); - } - - if ( count( $this->shown_images ) === 0 && WPSEO_Options::get( 'og_default_image', '' ) !== '' ) { - $this->image_output( WPSEO_Options::get( 'og_default_image' ) ); - } - } - - /** - * Outputs the first image of a gallery. - */ - private function gallery_images_output() { - - $this->image_output( reset( $this->images ) ); - } - - /** - * @return bool - */ - private function taxonomy_image_output() { - foreach ( array( 'twitter-image', 'opengraph-image' ) as $tag ) { - $img = WPSEO_Taxonomy_Meta::get_meta_without_term( $tag ); - if ( is_string( $img ) && $img !== '' ) { - $this->image_output( $img ); - - return true; - } - } - - /** - * Filter: wpseo_twitter_taxonomy_image - Allow developers to set a custom Twitter image for taxonomies. - * - * @api bool|string $unsigned Return string to supply image to use, false to use no image. - */ - $img = apply_filters( 'wpseo_twitter_taxonomy_image', false ); - if ( is_string( $img ) && $img !== '' ) { - $this->image_output( $img ); - - return true; - } - - return false; - } - - /** - * Takes care of image output when we only need to display a single image. - */ - private function single_image_output() { - if ( $this->homepage_image_output() ) { - return; - } - - if ( $this->posts_page_image_output() ) { // Posts page, which won't be caught by is_singular() below. - return; - } - - if ( $this->frontend_page_type->is_simple_page() ) { - $post_id = $this->frontend_page_type->get_simple_page_id(); - - if ( $this->image_from_meta_values_output( $post_id ) ) { - return; - } - - $post_id = get_the_ID(); - - if ( $this->image_of_attachment_page_output( $post_id ) ) { - return; - } - if ( $this->image_thumbnail_output( $post_id ) ) { - return; - } - if ( count( $this->images ) > 0 ) { - $this->gallery_images_output(); - return; - } - if ( $this->image_from_content_output( $post_id ) ) { - return; - } - } - } - - /** - * Show the front page image - * - * @return bool - */ - private function homepage_image_output() { - if ( is_front_page() ) { - if ( WPSEO_Options::get( 'og_frontpage_image', '' ) !== '' ) { - $this->image_output( WPSEO_Options::get( 'og_frontpage_image' ) ); - - return true; - } - } - - return false; - } - - /** - * Show the posts page image. - * - * @return bool - */ - private function posts_page_image_output() { - - if ( is_front_page() || ! is_home() ) { - return false; - } - - $post_id = get_option( 'page_for_posts' ); - - if ( $this->image_from_meta_values_output( $post_id ) ) { - return true; - } - - if ( $this->image_thumbnail_output( $post_id ) ) { - return true; - } - - return false; - } - - /** - * Outputs a Twitter image tag for a given image - * - * @param string $img The source URL to the image. - * @param boolean $tag Deprecated argument, previously used for gallery images. - * - * @return bool - */ - protected function image_output( $img, $tag = false ) { - - if ( $tag ) { - _deprecated_argument( __METHOD__, 'WPSEO 2.4' ); - } - - /** - * Filter: 'wpseo_twitter_image' - Allow changing the Twitter Card image - * - * @api string $img Image URL string - */ - $img = apply_filters( 'wpseo_twitter_image', $img ); - - if ( WPSEO_Utils::is_url_relative( $img ) === true && $img[0] === '/' ) { - $parsed_url = wp_parse_url( home_url() ); - $img = $parsed_url['scheme'] . '://' . $parsed_url['host'] . $img; - } - - $escaped_img = esc_url( $img ); - - if ( in_array( $escaped_img, $this->shown_images, true ) ) { - return false; - } - - if ( is_string( $escaped_img ) && $escaped_img !== '' ) { - $this->output_metatag( 'image', $escaped_img, true ); - array_push( $this->shown_images, $escaped_img ); - - return true; - } - - return false; - } - - /** - * Retrieve images from the post meta values - * - * @param int $post_id Optional post ID to use. - * - * @return bool - */ - private function image_from_meta_values_output( $post_id = 0 ) { - foreach ( array( 'twitter-image', 'opengraph-image' ) as $tag ) { - $img = WPSEO_Meta::get_value( $tag, $post_id ); - if ( $img !== '' ) { - $this->image_output( $img ); - - return true; - } - } - - return false; - } - - /** - * Retrieve an attachment page's attachment - * - * @param string $attachment_id The ID of the attachment for which to retrieve the image. - * - * @return bool - */ - private function image_of_attachment_page_output( $attachment_id ) { - if ( get_post_type( $attachment_id ) === 'attachment' ) { - $mime_type = get_post_mime_type( $attachment_id ); - switch ( $mime_type ) { - case 'image/jpeg': - case 'image/png': - case 'image/gif': - $this->image_output( wp_get_attachment_url( $attachment_id ) ); - return true; - } - } - - return false; - } - - /** - * Retrieve the featured image - * - * @param int $post_id Optional post ID to use. - * - * @return bool - */ - private function image_thumbnail_output( $post_id = 0 ) { - - if ( empty( $post_id ) ) { - $post_id = get_the_ID(); - } - - if ( function_exists( 'has_post_thumbnail' ) && has_post_thumbnail( $post_id ) ) { - /** - * Filter: 'wpseo_twitter_image_size' - Allow changing the Twitter Card image size - * - * @api string $featured_img Image size string - */ - $featured_img = wp_get_attachment_image_src( get_post_thumbnail_id( $post_id ), apply_filters( 'wpseo_twitter_image_size', 'full' ) ); - - if ( $featured_img ) { - $this->image_output( $featured_img[0] ); - - return true; - } - } - - return false; - } - - /** - * Retrieve the image from the content - * - * @param int $post_id The post id to extract the images from. - * - * @return bool - */ - private function image_from_content_output( $post_id ) { - /** - * Filter: 'wpseo_pre_analysis_post_content' - Allow filtering the content before analysis - * - * @api string $post_content The Post content string - * - * @param object $post - The post object. - */ - $post = get_post( $post_id ); - $content = apply_filters( 'wpseo_pre_analysis_post_content', $post->post_content, $post ); - - if ( preg_match_all( '`]+>`', $content, $matches ) ) { - foreach ( $matches[0] as $img ) { - if ( preg_match( '`src=(["\'])(.*?)\1`', $img, $match ) ) { - $this->image_output( $match[2] ); - - return true; - } - } - } - - return false; - } - - /** - * Displays the authors Twitter account. - */ - protected function author() { - $twitter = ltrim( trim( get_the_author_meta( 'twitter', get_post()->post_author ) ), '@' ); - /** - * Filter: 'wpseo_twitter_creator_account' - Allow changing the Twitter account as output in the Twitter card by Yoast SEO - * - * @api string $twitter The twitter account name string - */ - $twitter = apply_filters( 'wpseo_twitter_creator_account', $twitter ); - $twitter = $this->get_twitter_id( $twitter ); - - if ( is_string( $twitter ) && $twitter !== '' ) { - $this->output_metatag( 'creator', '@' . $twitter ); - } - elseif ( WPSEO_Options::get( 'twitter_site', '' ) !== '' && is_string( WPSEO_Options::get( 'twitter_site' ) ) ) { - $this->output_metatag( 'creator', '@' . WPSEO_Options::get( 'twitter_site' ) ); - } - } - - /** - * Get the singleton instance of this class - * - * @return object - */ - public static function get_instance() { - if ( ! ( self::$instance instanceof self ) ) { - self::$instance = new self(); - } - - return self::$instance; - } -} /* End of class */ diff --git a/wp-content/plugins/wordpress-seo/frontend/index.php b/wp-content/plugins/wordpress-seo/frontend/index.php deleted file mode 100644 index e94d9a42..00000000 --- a/wp-content/plugins/wordpress-seo/frontend/index.php +++ /dev/null @@ -1,4 +0,0 @@ -YoastSEO_02 \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/Yoast_SEO_negative_icon.svg b/wp-content/plugins/wordpress-seo/images/Yoast_SEO_negative_icon.svg index 282952c8..ad6a6b3e 100644 --- a/wp-content/plugins/wordpress-seo/images/Yoast_SEO_negative_icon.svg +++ b/wp-content/plugins/wordpress-seo/images/Yoast_SEO_negative_icon.svg @@ -1 +1 @@ -Artboard 1 \ No newline at end of file + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/alert-error-icon.svg b/wp-content/plugins/wordpress-seo/images/alert-error-icon.svg new file mode 100644 index 00000000..80fa0626 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/alert-error-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/alert-info-icon.svg b/wp-content/plugins/wordpress-seo/images/alert-info-icon.svg new file mode 100644 index 00000000..332d7af5 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/alert-info-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/alert-success-icon.svg b/wp-content/plugins/wordpress-seo/images/alert-success-icon.svg new file mode 100644 index 00000000..30519e54 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/alert-success-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/alert-warning-icon.svg b/wp-content/plugins/wordpress-seo/images/alert-warning-icon.svg new file mode 100644 index 00000000..f52df867 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/alert-warning-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/banner/basic-seo-training.png b/wp-content/plugins/wordpress-seo/images/banner/basic-seo-training.png deleted file mode 100644 index 60c98246..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/basic-seo-training.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/configuration-service.png b/wp-content/plugins/wordpress-seo/images/banner/configuration-service.png deleted file mode 100644 index 2e472d03..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/configuration-service.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/keyword-research-training.png b/wp-content/plugins/wordpress-seo/images/banner/keyword-research-training.png deleted file mode 100644 index 2fec4c45..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/keyword-research-training.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/local-seo-for-woocommerce.png b/wp-content/plugins/wordpress-seo/images/banner/local-seo-for-woocommerce.png deleted file mode 100644 index 5252d87c..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/local-seo-for-woocommerce.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/local-seo.png b/wp-content/plugins/wordpress-seo/images/banner/local-seo.png deleted file mode 100644 index a0f12513..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/local-seo.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/news-seo.png b/wp-content/plugins/wordpress-seo/images/banner/news-seo.png deleted file mode 100644 index 31981eef..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/news-seo.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/premium-seo.png b/wp-content/plugins/wordpress-seo/images/banner/premium-seo.png deleted file mode 100644 index a9519a9f..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/premium-seo.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/seo-care.png b/wp-content/plugins/wordpress-seo/images/banner/seo-care.png deleted file mode 100644 index d5abb7d7..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/seo-care.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/seo-copywriting-training.png b/wp-content/plugins/wordpress-seo/images/banner/seo-copywriting-training.png deleted file mode 100644 index 4be73be4..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/seo-copywriting-training.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/site-structure-training.png b/wp-content/plugins/wordpress-seo/images/banner/site-structure-training.png deleted file mode 100644 index 10b07ed3..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/site-structure-training.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/structured-data-course.png b/wp-content/plugins/wordpress-seo/images/banner/structured-data-course.png deleted file mode 100644 index d9c1aff1..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/structured-data-course.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/technical-seo-training.png b/wp-content/plugins/wordpress-seo/images/banner/technical-seo-training.png deleted file mode 100644 index 1ceb947c..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/technical-seo-training.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/video-seo.png b/wp-content/plugins/wordpress-seo/images/banner/video-seo.png deleted file mode 100644 index 6e4950cf..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/video-seo.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/website-review.png b/wp-content/plugins/wordpress-seo/images/banner/website-review.png deleted file mode 100644 index 231793af..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/website-review.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/woocommerce-seo.png b/wp-content/plugins/wordpress-seo/images/banner/woocommerce-seo.png deleted file mode 100644 index 58a74b22..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/woocommerce-seo.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/banner/yoast-seo-for-wordpress-training.png b/wp-content/plugins/wordpress-seo/images/banner/yoast-seo-for-wordpress-training.png deleted file mode 100644 index 3520ef12..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/banner/yoast-seo-for-wordpress-training.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/brushstroke_background.svg b/wp-content/plugins/wordpress-seo/images/brushstroke_background.svg new file mode 100644 index 00000000..f7d8ff43 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/brushstroke_background.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/editicon.png b/wp-content/plugins/wordpress-seo/images/editicon.png deleted file mode 100644 index 2463f1b2..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/editicon.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/error-icon.svg b/wp-content/plugins/wordpress-seo/images/error-icon.svg new file mode 100644 index 00000000..43e859de --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/error-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/extensions-local-for-woocommerce.png b/wp-content/plugins/wordpress-seo/images/extensions-local-for-woocommerce.png deleted file mode 100644 index b7b73f26..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/extensions-local-for-woocommerce.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/extensions-local.png b/wp-content/plugins/wordpress-seo/images/extensions-local.png deleted file mode 100644 index 7d65fde9..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/extensions-local.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/extensions-news.png b/wp-content/plugins/wordpress-seo/images/extensions-news.png deleted file mode 100644 index ceec4df2..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/extensions-news.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/extensions-premium-ribbon.png b/wp-content/plugins/wordpress-seo/images/extensions-premium-ribbon.png deleted file mode 100644 index 4345f252..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/extensions-premium-ribbon.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/extensions-video.png b/wp-content/plugins/wordpress-seo/images/extensions-video.png deleted file mode 100644 index 63c045f0..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/extensions-video.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/extensions-woo.png b/wp-content/plugins/wordpress-seo/images/extensions-woo.png deleted file mode 100644 index f32eabb8..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/extensions-woo.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/link-in-icon.svg b/wp-content/plugins/wordpress-seo/images/link-in-icon.svg index 15b74d1b..c3748559 100644 --- a/wp-content/plugins/wordpress-seo/images/link-in-icon.svg +++ b/wp-content/plugins/wordpress-seo/images/link-in-icon.svg @@ -1 +1 @@ -Link_in_icon \ No newline at end of file + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/link-out-icon.svg b/wp-content/plugins/wordpress-seo/images/link-out-icon.svg index 5504ec8f..202082bc 100644 --- a/wp-content/plugins/wordpress-seo/images/link-out-icon.svg +++ b/wp-content/plugins/wordpress-seo/images/link-out-icon.svg @@ -1 +1 @@ -Artboard 1 \ No newline at end of file + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/local_plugin_assistant.svg b/wp-content/plugins/wordpress-seo/images/local_plugin_assistant.svg new file mode 100644 index 00000000..68aacd4f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/local_plugin_assistant.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/new-to-configuration-notice.svg b/wp-content/plugins/wordpress-seo/images/new-to-configuration-notice.svg index 204bb3af..2343c570 100644 --- a/wp-content/plugins/wordpress-seo/images/new-to-configuration-notice.svg +++ b/wp-content/plugins/wordpress-seo/images/new-to-configuration-notice.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/news_plugin_assistant.svg b/wp-content/plugins/wordpress-seo/images/news_plugin_assistant.svg new file mode 100644 index 00000000..f178f9c2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/news_plugin_assistant.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/pinterest-23x30.png b/wp-content/plugins/wordpress-seo/images/pinterest-23x30.png deleted file mode 100644 index 174438ab..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/pinterest-23x30.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/readability-icon.svg b/wp-content/plugins/wordpress-seo/images/readability-icon.svg index c73153d9..439f52f8 100644 --- a/wp-content/plugins/wordpress-seo/images/readability-icon.svg +++ b/wp-content/plugins/wordpress-seo/images/readability-icon.svg @@ -1 +1 @@ -Readability_icon \ No newline at end of file + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/seo_fitness_assistants_fit.svg b/wp-content/plugins/wordpress-seo/images/seo_fitness_assistants_fit.svg new file mode 100644 index 00000000..67129064 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/seo_fitness_assistants_fit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/seo_fitness_assistants_unfit.svg b/wp-content/plugins/wordpress-seo/images/seo_fitness_assistants_unfit.svg new file mode 100644 index 00000000..fd2fe82d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/seo_fitness_assistants_unfit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/stale-cornerstone-content-in-yoast-seo.png b/wp-content/plugins/wordpress-seo/images/stale-cornerstone-content-in-yoast-seo.png new file mode 100644 index 00000000..581509a3 Binary files /dev/null and b/wp-content/plugins/wordpress-seo/images/stale-cornerstone-content-in-yoast-seo.png differ diff --git a/wp-content/plugins/wordpress-seo/images/support-team.svg b/wp-content/plugins/wordpress-seo/images/support-team.svg index 6f61ab10..11d635a9 100644 --- a/wp-content/plugins/wordpress-seo/images/support-team.svg +++ b/wp-content/plugins/wordpress-seo/images/support-team.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/video_plugin_assistant.svg b/wp-content/plugins/wordpress-seo/images/video_plugin_assistant.svg new file mode 100644 index 00000000..403d0fd9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/video_plugin_assistant.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/waiting.gif b/wp-content/plugins/wordpress-seo/images/waiting.gif deleted file mode 100644 index 2593fa1c..00000000 Binary files a/wp-content/plugins/wordpress-seo/images/waiting.gif and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/images/woo_plugin_assistant.svg b/wp-content/plugins/wordpress-seo/images/woo_plugin_assistant.svg new file mode 100644 index 00000000..d086f807 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/images/woo_plugin_assistant.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/images/yoast-configuration-icon.svg b/wp-content/plugins/wordpress-seo/images/yoast-configuration-icon.svg deleted file mode 100644 index a483ce3b..00000000 --- a/wp-content/plugins/wordpress-seo/images/yoast-configuration-icon.svg +++ /dev/null @@ -1 +0,0 @@ -Config_service_Yoast_SEO \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/inc/class-addon-manager.php b/wp-content/plugins/wordpress-seo/inc/class-addon-manager.php new file mode 100644 index 00000000..ada534a7 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/class-addon-manager.php @@ -0,0 +1,766 @@ + self::PREMIUM_SLUG, + 'wpseo-news.php' => self::NEWS_SLUG, + 'video-seo.php' => self::VIDEO_SLUG, + 'wpseo-woocommerce.php' => self::WOOCOMMERCE_SLUG, + 'local-seo.php' => self::LOCAL_SLUG, + ]; + + /** + * Holds the site information data. + * + * @var stdClass + */ + private $site_information; + + /** + * Hooks into WordPress. + * + * @codeCoverageIgnore + * + * @return void + */ + public function register_hooks() { + add_action( 'admin_init', [ $this, 'validate_addons' ], 15 ); + add_filter( 'pre_set_site_transient_update_plugins', [ $this, 'check_for_updates' ] ); + add_filter( 'plugins_api', [ $this, 'get_plugin_information' ], 10, 3 ); + + foreach ( array_keys( $this->get_installed_addons() ) as $plugin_file ) { + add_action( 'in_plugin_update_message-' . $plugin_file, [ $this, 'expired_subscription_warning' ], 10, 2 ); + } + } + + /** + * Gets the subscriptions for current site. + * + * @return stdClass The subscriptions. + */ + public function get_subscriptions() { + return $this->get_site_information()->subscriptions; + } + + /** + * Provides a list of addon filenames. + * + * @return string[] List of addon filenames with their slugs. + */ + public function get_addon_filenames() { + return self::$addons; + } + + /** + * Finds the plugin file. + * + * @param string $plugin_slug The plugin slug to search. + * + * @return boolean|string Plugin file when installed, False when plugin isn't installed. + **/ + public function get_plugin_file( $plugin_slug ) { + $plugins = $this->get_plugins(); + $plugin_files = array_keys( $plugins ); + $target_plugin_file = array_search( $plugin_slug, $this->get_addon_filenames(), true ); + + if ( ! $target_plugin_file ) { + return false; + } + + foreach ( $plugin_files as $plugin_file ) { + if ( strpos( $plugin_file, $target_plugin_file ) !== false ) { + return $plugin_file; + } + } + + return false; + } + + /** + * Retrieves the subscription for the given slug. + * + * @param string $slug The plugin slug to retrieve. + * + * @return stdClass|false Subscription data when found, false when not found. + */ + public function get_subscription( $slug ) { + foreach ( $this->get_subscriptions() as $subscription ) { + if ( $subscription->product->slug === $slug ) { + return $subscription; + } + } + + return false; + } + + /** + * Retrieves a list of (subscription) slugs by the active addons. + * + * @return array The slugs. + */ + public function get_subscriptions_for_active_addons() { + $active_addons = array_keys( $this->get_active_addons() ); + $subscription_slugs = array_map( [ $this, 'get_slug_by_plugin_file' ], $active_addons ); + $subscriptions = []; + foreach ( $subscription_slugs as $subscription_slug ) { + $subscriptions[ $subscription_slug ] = $this->get_subscription( $subscription_slug ); + } + + return $subscriptions; + } + + /** + * Retrieves a list of versions for each addon. + * + * @return array The addon versions. + */ + public function get_installed_addons_versions() { + $addon_versions = []; + foreach ( $this->get_installed_addons() as $plugin_file => $installed_addon ) { + $addon_versions[ $this->get_slug_by_plugin_file( $plugin_file ) ] = $installed_addon['Version']; + } + + return $addon_versions; + } + + /** + * Retrieves the plugin information from the subscriptions. + * + * @param stdClass|false $data The result object. Default false. + * @param string $action The type of information being requested from the Plugin Installation API. + * @param stdClass $args Plugin API arguments. + * + * @return object Extended plugin data. + */ + public function get_plugin_information( $data, $action, $args ) { + if ( $action !== 'plugin_information' ) { + return $data; + } + + if ( ! isset( $args->slug ) ) { + return $data; + } + + $subscription = $this->get_subscription( $args->slug ); + if ( ! $subscription ) { + return $data; + } + + $data = $this->convert_subscription_to_plugin( $subscription ); + + if ( $this->has_subscription_expired( $subscription ) ) { + unset( $data->package, $data->download_link ); + } + + return $data; + } + + /** + * Retrieves information from MyYoast about which addons are connected to the current site. + * + * @return stdClass The list of addons activated for this site. + */ + public function get_myyoast_site_information() { + if ( $this->site_information === null ) { + $this->site_information = $this->get_site_information_transient(); + } + + if ( $this->site_information ) { + return $this->site_information; + } + + $this->site_information = $this->request_current_sites(); + if ( $this->site_information ) { + $this->site_information = $this->map_site_information( $this->site_information ); + + $this->set_site_information_transient( $this->site_information ); + + return $this->site_information; + } + + return $this->get_site_information_default(); + } + + /** + * Checks if the subscription for the given slug is valid. + * + * @param string $slug The plugin slug to retrieve. + * + * @return bool True when the subscription is valid. + */ + public function has_valid_subscription( $slug ) { + $subscription = $this->get_subscription( $slug ); + + // An non-existing subscription is never valid. + if ( ! $subscription ) { + return false; + } + + return ! $this->has_subscription_expired( $subscription ); + } + + /** + * Checks if there are addon updates. + * + * @param stdClass|mixed $data The current data for update_plugins. + * + * @return stdClass Extended data for update_plugins. + */ + public function check_for_updates( $data ) { + if ( empty( $data ) ) { + return $data; + } + + foreach ( $this->get_installed_addons() as $plugin_file => $installed_plugin ) { + $subscription_slug = $this->get_slug_by_plugin_file( $plugin_file ); + $subscription = $this->get_subscription( $subscription_slug ); + + if ( ! $subscription ) { + continue; + } + + if ( version_compare( $installed_plugin['Version'], $subscription->product->version, '<' ) ) { + $data->response[ $plugin_file ] = $this->convert_subscription_to_plugin( $subscription ); + + if ( $this->has_subscription_expired( $subscription ) ) { + unset( $data->response[ $plugin_file ]->package, $data->response[ $plugin_file ]->download_link ); + } + } + else { + // Still convert subscription when no updates is available. + $data->no_update[ $plugin_file ] = $this->convert_subscription_to_plugin( $subscription ); + + if ( $this->has_subscription_expired( $subscription ) ) { + unset( $data->no_update[ $plugin_file ]->package, $data->no_update[ $plugin_file ]->download_link ); + } + } + } + + return $data; + } + + /** + * If the plugin is lacking an active subscription, throw a warning. + * + * @param array $plugin_data The data for the plugin in this row. + */ + public function expired_subscription_warning( $plugin_data ) { + $subscription = $this->get_subscription( $plugin_data['slug'] ); + if ( $subscription && $this->has_subscription_expired( $subscription ) ) { + echo '

    '; + // translators: %1$s is the plugin name, %2$s and %3$s are a link. + echo ' ' . sprintf( esc_html__( 'A new version of %1$s is available. %2$sRenew your subscription%3$s if you want to update to the latest version.', 'wordpress-seo' ), esc_html( $plugin_data['name'] ), '', '' ) . ''; + } + } + + /** + * Checks if there are any installed addons. + * + * @return bool True when there are installed Yoast addons. + */ + public function has_installed_addons() { + $installed_addons = $this->get_installed_addons(); + + return ! empty( $installed_addons ); + } + + /** + * Checks if the plugin is installed and activated in WordPress. + * + * @param string $slug The class' slug. + * + * @return bool True when installed and activated. + */ + public function is_installed( $slug ) { + $slug_to_class_map = [ + static::PREMIUM_SLUG => 'WPSEO_Premium', + static::NEWS_SLUG => 'WPSEO_News', + static::WOOCOMMERCE_SLUG => 'Yoast_WooCommerce_SEO', + static::VIDEO_SLUG => 'WPSEO_Video_Sitemap', + static::LOCAL_SLUG => 'WPSEO_Local_Core', + ]; + + if ( ! isset( $slug_to_class_map[ $slug ] ) ) { + return false; + } + + return class_exists( $slug_to_class_map[ $slug ] ); + } + + /** + * Validates the addons and show a notice for the ones that are invalid. + */ + public function validate_addons() { + $notification_center = Yoast_Notification_Center::get(); + + if ( $notification_center === null ) { + return; + } + + $addons = [ + 'Yoast SEO Premium' => static::PREMIUM_SLUG, + 'News SEO' => static::NEWS_SLUG, + 'Yoast WooCommerce SEO' => static::WOOCOMMERCE_SLUG, + 'Video SEO' => static::VIDEO_SLUG, + 'Local SEO' => static::LOCAL_SLUG, + ]; + + foreach ( $addons as $product_name => $slug ) { + $notification = $this->create_notification( $product_name ); + + // Add a notification when the installed plugin isn't activated in My Yoast. + if ( $this->is_installed( $slug ) && ! $this->has_valid_subscription( $slug ) ) { + $notification_center->add_notification( $notification ); + + continue; + } + + $notification_center->remove_notification( $notification ); + } + } + + /** + * Removes the site information transients. + * + * @codeCoverageIgnore + * + * @return void + */ + public function remove_site_information_transients() { + delete_transient( self::SITE_INFORMATION_TRANSIENT ); + delete_transient( self::SITE_INFORMATION_TRANSIENT_QUICK ); + } + + /** + * 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 = [ + 'type' => Yoast_Notification::ERROR, + 'id' => 'wpseo-dismiss-' . sanitize_title_with_dashes( $product_name, null, 'save' ), + 'capabilities' => 'wpseo_manage_options', + ]; + + return 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, + 'My Yoast' + ), + $notification_options + ); + } + + /** + * Checks whether a plugin expiry date has been passed. + * + * @param stdClass $subscription Plugin subscription. + * + * @return bool Has the plugin expired. + */ + protected function has_subscription_expired( $subscription ) { + return ( strtotime( $subscription->expiry_date ) - time() ) < 0; + } + + /** + * Converts a subscription to plugin based format. + * + * @param stdClass $subscription The subscription to convert. + * + * @return stdClass The converted subscription. + */ + protected function convert_subscription_to_plugin( $subscription ) { + // We need to replace h2's and h3's with h4's because the styling expects that. + $changelog = str_replace( 'product->changelog ) ); + $changelog = str_replace( ' $subscription->product->version, + 'name' => $subscription->product->name, + 'slug' => $subscription->product->slug, + 'url' => $subscription->product->store_url, + 'last_update' => $subscription->product->last_updated, + 'homepage' => $subscription->product->store_url, + 'download_link' => $subscription->product->download, + 'package' => $subscription->product->download, + 'sections' => [ + 'changelog' => $changelog, + 'support' => $this->get_support_section(), + ], + 'icons' => [ + '2x' => $this->get_icon( $subscription->product->slug ), + ], + 'update_supported' => true, + 'banners' => $this->get_banners( $subscription->product->slug ), + 'tested' => YOAST_SEO_WP_TESTED, + 'requires' => YOAST_SEO_WP_REQUIRED, + 'requires_php' => YOAST_SEO_PHP_REQUIRED, + ]; + } + + /** + * Returns the plugin's icon URL. + * + * @param string $slug The plugin slug. + * + * @return string The icon URL for this plugin. + */ + protected function get_icon( $slug ) { + switch ( $slug ) { + case self::LOCAL_SLUG: + return 'https://yoa.st/local-seo-icon'; + case self::NEWS_SLUG: + return 'https://yoa.st/news-seo-icon'; + case self::PREMIUM_SLUG: + return 'https://yoa.st/yoast-seo-icon'; + case self::VIDEO_SLUG: + return 'https://yoa.st/video-seo-icon'; + case self::WOOCOMMERCE_SLUG: + return 'https://yoa.st/woo-seo-icon'; + } + } + + /** + * Return an array of plugin banner URLs. + * + * @param string $slug The plugin slug. + * + * @return string[] + */ + protected function get_banners( $slug ) { + switch ( $slug ) { + case self::LOCAL_SLUG: + return [ + 'high' => 'https://yoa.st/yoast-seo-banner-local', + 'low' => 'https://yoa.st/yoast-seo-banner-low-local', + ]; + case self::NEWS_SLUG: + return [ + 'high' => 'https://yoa.st/yoast-seo-banner-news', + 'low' => 'https://yoa.st/yoast-seo-banner-low-news', + ]; + case self::PREMIUM_SLUG: + return [ + 'high' => 'https://yoa.st/yoast-seo-banner-premium', + 'low' => 'https://yoa.st/yoast-seo-banner-low-premium', + ]; + case self::VIDEO_SLUG: + return [ + 'high' => 'https://yoa.st/yoast-seo-banner-video', + 'low' => 'https://yoa.st/yoast-seo-banner-low-video', + ]; + case self::WOOCOMMERCE_SLUG: + return [ + 'high' => 'https://yoa.st/yoast-seo-banner-woo', + 'low' => 'https://yoa.st/yoast-seo-banner-low-woo', + ]; + } + } + + /** + * Checks if the given plugin_file belongs to a Yoast addon. + * + * @param string $plugin_file Path to the plugin. + * + * @return bool True when plugin file is for a Yoast addon. + */ + protected function is_yoast_addon( $plugin_file ) { + return $this->get_slug_by_plugin_file( $plugin_file ) !== ''; + } + + /** + * Retrieves the addon slug by given plugin file path. + * + * @param string $plugin_file The file path to the plugin. + * + * @return string The slug when found or empty string when not. + */ + protected function get_slug_by_plugin_file( $plugin_file ) { + $addons = self::$addons; + + // Yoast SEO Free isn't an addon, but we needed it in Premium to fetch translations. + if ( YoastSEO()->helpers->product->is_premium() ) { + $addons['wp-seo.php'] = self::FREE_SLUG; + } + + foreach ( $addons as $addon => $addon_slug ) { + if ( strpos( $plugin_file, $addon ) !== false ) { + return $addon_slug; + } + } + + return ''; + } + + /** + * Retrieves the installed Yoast addons. + * + * @return array The installed plugins. + */ + protected function get_installed_addons() { + return array_filter( $this->get_plugins(), [ $this, 'is_yoast_addon' ], ARRAY_FILTER_USE_KEY ); + } + + /** + * Retrieves a list of active addons. + * + * @return array The active addons. + */ + protected function get_active_addons() { + return array_filter( $this->get_installed_addons(), [ $this, 'is_plugin_active' ], ARRAY_FILTER_USE_KEY ); + } + + /** + * Retrieves the current sites from the API. + * + * @codeCoverageIgnore + * + * @return bool|stdClass Object when request is successful. False if not. + */ + protected function request_current_sites() { + $api_request = new WPSEO_MyYoast_Api_Request( 'sites/current' ); + if ( $api_request->fire() ) { + return $api_request->get_response(); + } + + return $this->get_site_information_default(); + } + + /** + * Retrieves the transient value with the site information. + * + * @codeCoverageIgnore + * + * @return stdClass|false The transient value. + */ + protected function get_site_information_transient() { + global $pagenow; + + // 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. + $quick = ( $current_page === 'wpseo_licenses' || $current_page === 'wpseo_dashboard' ); + + // Also do a fresh request on Plugins & Core Update pages. + $quick = $quick || $pagenow === 'plugins.php'; + $quick = $quick || $pagenow === 'update-core.php'; + + if ( $quick ) { + return get_transient( self::SITE_INFORMATION_TRANSIENT_QUICK ); + } + + return get_transient( self::SITE_INFORMATION_TRANSIENT ); + } + + /** + * Returns the current page. + * + * @codeCoverageIgnore + * + * @return string The current page. + */ + protected function get_current_page() { + return filter_input( INPUT_GET, 'page' ); + } + + /** + * Sets the site information transient. + * + * @codeCoverageIgnore + * + * @param stdClass $site_information The site information to save. + * + * @return void + */ + protected function set_site_information_transient( $site_information ) { + set_transient( self::SITE_INFORMATION_TRANSIENT, $site_information, DAY_IN_SECONDS ); + set_transient( self::SITE_INFORMATION_TRANSIENT_QUICK, $site_information, 60 ); + } + + /** + * Retrieves all installed WordPress plugins. + * + * @codeCoverageIgnore + * + * @return array The plugins. + */ + protected function get_plugins() { + if ( ! function_exists( 'get_plugins' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + + return get_plugins(); + } + + /** + * Checks if the given plugin file belongs to an active plugin. + * + * @codeCoverageIgnore + * + * @param string $plugin_file The file path to the plugin. + * + * @return bool True when plugin is active. + */ + protected function is_plugin_active( $plugin_file ) { + return is_plugin_active( $plugin_file ); + } + + /** + * Returns an object with no subscriptions. + * + * @codeCoverageIgnore + * + * @return stdClass Site information. + */ + protected function get_site_information_default() { + return (object) [ + 'url' => WPSEO_Utils::get_home_url(), + 'subscriptions' => [], + ]; + } + + /** + * Maps the plugin API response. + * + * @param object $site_information Site information as received from the API. + * + * @return stdClass Mapped site information. + */ + protected function map_site_information( $site_information ) { + return (object) [ + 'url' => $site_information->url, + 'subscriptions' => array_map( [ $this, 'map_subscription' ], $site_information->subscriptions ), + ]; + } + + /** + * Maps a plugin subscription. + * + * @param object $subscription Subscription information as received from the API. + * + * @return stdClass Mapped subscription. + */ + protected function map_subscription( $subscription ) { + // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Not our properties. + return (object) [ + 'renewal_url' => $subscription->renewalUrl, + 'expiry_date' => $subscription->expiryDate, + 'product' => (object) [ + 'version' => $subscription->product->version, + 'name' => $subscription->product->name, + 'slug' => $subscription->product->slug, + 'last_updated' => $subscription->product->lastUpdated, + 'store_url' => $subscription->product->storeUrl, + // Ternary operator is necessary because download can be undefined. + 'download' => isset( $subscription->product->download ) ? $subscription->product->download : null, + 'changelog' => $subscription->product->changelog, + ], + ]; + // phpcs:enable + } + + /** + * Retrieves the site information. + * + * @return stdClass The site information. + */ + private function get_site_information() { + if ( ! $this->has_installed_addons() ) { + return $this->get_site_information_default(); + } + + return $this->get_myyoast_site_information(); + } + + /** + * Retrieves the contents for the support section. + * + * @return string The support section content. + */ + protected function get_support_section() { + return '

    ' . __( 'Need support?', 'wordpress-seo' ) . '

    ' + . '

    ' + /* translators: 1: expands to that refers to the help page, 2: closing tag. */ + . sprintf( __( 'You can probably find an answer to your question in our %1$shelp center%2$s.', 'wordpress-seo' ), '', '' ) + . ' ' + /* translators: %s expands to a mailto support link. */ + . sprintf( __( 'If you still need support and have an active subscription for this product, please email %s.', 'wordpress-seo' ), 'support@yoast.com' ) + . '

    '; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-my-yoast-api-request.php b/wp-content/plugins/wordpress-seo/inc/class-my-yoast-api-request.php new file mode 100644 index 00000000..48d365c7 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/class-my-yoast-api-request.php @@ -0,0 +1,207 @@ + 'GET', + 'timeout' => 5, + 'headers' => [ + 'Accept-Encoding' => '*', + 'Expect' => '', + ], + ]; + + /** + * Contains the fetched response. + * + * @var stdClass + */ + protected $response; + + /** + * Contains the error message when request went wrong. + * + * @var string + */ + protected $error_message = ''; + + /** + * Constructor. + * + * @codeCoverageIgnore + * + * @param string $url The request url. + * @param array $args The request arguments. + */ + public function __construct( $url, array $args = [] ) { + $this->url = 'https://my.yoast.com/api/' . $url; + $this->args = wp_parse_args( $args, $this->args ); + } + + /** + * Fires the request. + * + * @return bool True when request is successful. + */ + public function fire() { + try { + $response = $this->do_request( $this->url, $this->args ); + $this->response = $this->decode_response( $response ); + + return true; + } + catch ( WPSEO_MyYoast_Bad_Request_Exception $bad_request_exception ) { + $this->error_message = $bad_request_exception->getMessage(); + + return false; + } + } + + /** + * Retrieves the error message. + * + * @return string The set error message. + */ + public function get_error_message() { + return $this->error_message; + } + + /** + * Retrieves the response. + * + * @return stdClass The response object. + */ + public function get_response() { + return $this->response; + } + + /** + * Performs the request using WordPress internals. + * + * @codeCoverageIgnore + * + * @param string $url The request URL. + * @param array $request_arguments The request arguments. + * + * @return string The retrieved body. + * @throws WPSEO_MyYoast_Bad_Request_Exception When request is invalid. + */ + protected function do_request( $url, $request_arguments ) { + $request_arguments = $this->enrich_request_arguments( $request_arguments ); + $response = wp_remote_request( $url, $request_arguments ); + + if ( is_wp_error( $response ) ) { + throw new WPSEO_MyYoast_Bad_Request_Exception( $response->get_error_message() ); + } + + $response_code = wp_remote_retrieve_response_code( $response ); + $response_message = wp_remote_retrieve_response_message( $response ); + + // Do nothing, response code is okay. + if ( $response_code === 200 || strpos( $response_code, '200' ) !== false ) { + return wp_remote_retrieve_body( $response ); + } + + throw new WPSEO_MyYoast_Bad_Request_Exception( esc_html( $response_message ), (int) $response_code ); + } + + /** + * Decodes the JSON encoded response. + * + * @param string $response The response to decode. + * + * @return stdClass The json decoded response. + * @throws WPSEO_MyYoast_Invalid_JSON_Exception When decoded string is not a JSON object. + */ + protected function decode_response( $response ) { + $response = json_decode( $response ); + + if ( ! is_object( $response ) ) { + throw new WPSEO_MyYoast_Invalid_JSON_Exception( + esc_html__( 'No JSON object was returned.', 'wordpress-seo' ) + ); + } + + return $response; + } + + /** + * Checks if MyYoast tokens are allowed and adds the token to the request body. + * + * When tokens are disallowed it will add the url to the request body. + * + * @param array $request_arguments The arguments to enrich. + * + * @return array The enriched arguments. + */ + protected function enrich_request_arguments( array $request_arguments ) { + $request_arguments = wp_parse_args( $request_arguments, [ 'headers' => [] ] ); + $addon_version_headers = $this->get_installed_addon_versions(); + + foreach ( $addon_version_headers as $addon => $version ) { + $request_arguments['headers'][ $addon . '-version' ] = $version; + } + + $request_body = $this->get_request_body(); + if ( $request_body !== [] ) { + $request_arguments['body'] = $request_body; + } + + return $request_arguments; + } + + /** + * Retrieves the request body based on URL or access token support. + * + * @codeCoverageIgnore + * + * @return array The request body. + */ + public function get_request_body() { + return [ 'url' => WPSEO_Utils::get_home_url() ]; + } + + /** + * Wraps the get current user id function. + * + * @codeCoverageIgnore + * + * @return int The user id. + */ + protected function get_current_user_id() { + return get_current_user_id(); + } + + /** + * Retrieves the installed addons as http headers. + * + * @codeCoverageIgnore + * + * @return array The installed addon versions. + */ + protected function get_installed_addon_versions() { + $addon_manager = new WPSEO_Addon_Manager(); + + return $addon_manager->get_installed_addons_versions(); + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-post-type.php b/wp-content/plugins/wordpress-seo/inc/class-post-type.php index 43dcdfde..52b93acc 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-post-type.php +++ b/wp-content/plugins/wordpress-seo/inc/class-post-type.php @@ -18,21 +18,7 @@ class WPSEO_Post_Type { * @return array Array with all the accessible post_types. */ public static function get_accessible_post_types() { - $post_types = get_post_types( array( 'public' => true ) ); - - /** - * Filter: 'wpseo_accessible_post_types' - Allow changing the accessible post types. - * - * @api array $post_types The public post types. - */ - $post_types = apply_filters( 'wpseo_accessible_post_types', $post_types ); - - // When the array gets messed up somewhere. - if ( ! is_array( $post_types ) ) { - return array(); - } - - return $post_types; + return YoastSEO()->helpers->post_type->get_accessible_post_types(); } /** @@ -54,11 +40,7 @@ class WPSEO_Post_Type { * @return bool True when post type is set to index. */ public static function is_post_type_indexable( $post_type_name ) { - if ( WPSEO_Options::get( 'disable-' . $post_type_name, false ) ) { - return false; - } - - return ( false === WPSEO_Options::get( 'noindex-' . $post_type_name, false ) ); + return YoastSEO()->helpers->post_type->is_indexable( $post_type_name ); } /** @@ -84,10 +66,36 @@ class WPSEO_Post_Type { public static function is_rest_enabled( $post_type ) { $post_type_object = get_post_type_object( $post_type ); - if ( is_null( $post_type_object ) ) { + if ( $post_type_object === null ) { return false; } return $post_type_object->show_in_rest === true; } + + /** + * Checks if the current post type has an archive. + * + * Context: The has_archive value can be a string or a boolean. In most case it will be a boolean, + * but it can be defined as a string. When it is a string the archive_slug will be overwritten to + * define another endpoint. + * + * @param WP_Post_Type $post_type The post type object. + * + * @return bool True whether the post type has an archive. + */ + public static function has_archive( $post_type ) { + return YoastSEO()->helpers->post_type->has_archive( $post_type ); + } + + /** + * Checks if the Yoast Metabox has been enabled for the post type. + * + * @param string $post_type The post type name. + * + * @return bool True whether the metabox is enabled. + */ + public static function has_metabox_enabled( $post_type ) { + return WPSEO_Options::get( 'display-metabox-pt-' . $post_type, false ); + } } diff --git a/wp-content/plugins/wordpress-seo/inc/class-rewrite.php b/wp-content/plugins/wordpress-seo/inc/class-rewrite.php index 59259540..a42668b1 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-rewrite.php +++ b/wp-content/plugins/wordpress-seo/inc/class-rewrite.php @@ -11,19 +11,19 @@ class WPSEO_Rewrite { /** - * Class constructor + * Class constructor. */ public function __construct() { - add_filter( 'query_vars', array( $this, 'query_vars' ) ); - add_filter( 'category_link', array( $this, 'no_category_base' ) ); - add_filter( 'request', array( $this, 'request' ) ); - add_filter( 'category_rewrite_rules', array( $this, 'category_rewrite_rules' ) ); + add_filter( 'query_vars', [ $this, 'query_vars' ] ); + add_filter( 'term_link', [ $this, 'no_category_base' ], 10, 3 ); + add_filter( 'request', [ $this, 'request' ] ); + add_filter( 'category_rewrite_rules', [ $this, 'category_rewrite_rules' ] ); - add_action( 'created_category', array( $this, 'schedule_flush' ) ); - add_action( 'edited_category', array( $this, 'schedule_flush' ) ); - add_action( 'delete_category', array( $this, 'schedule_flush' ) ); + add_action( 'created_category', [ $this, 'schedule_flush' ] ); + add_action( 'edited_category', [ $this, 'schedule_flush' ] ); + add_action( 'delete_category', [ $this, 'schedule_flush' ] ); - add_action( 'init', array( $this, 'flush' ), 999 ); + add_action( 'init', [ $this, 'flush' ], 999 ); } /** @@ -39,6 +39,7 @@ class WPSEO_Rewrite { * If the flush option is set, flush the rewrite rules. * * @since 1.2.8 + * * @return bool */ public function flush() { @@ -56,19 +57,28 @@ class WPSEO_Rewrite { /** * Override the category link to remove the category base. * - * @param string $link Unused, overridden by the function. + * @param string $link Term link, overridden by the function for categories. + * @param WP_Term $term Unused, term object. + * @param string $taxonomy Taxonomy slug. * * @return string */ - public function no_category_base( $link ) { + public function no_category_base( $link, $term, $taxonomy ) { + if ( $taxonomy !== 'category' ) { + return $link; + } + $category_base = get_option( 'category_base' ); if ( empty( $category_base ) ) { $category_base = 'category'; } - // Remove initial slash, if there is one (we remove the trailing slash in the regex replacement and don't want to end up short a slash). - if ( '/' === substr( $category_base, 0, 1 ) ) { + /* + * Remove initial slash, if there is one (we remove the trailing slash + * in the regex replacement and don't want to end up short a slash). + */ + if ( substr( $category_base, 0, 1 ) === '/' ) { $category_base = substr( $category_base, 1 ); } @@ -78,7 +88,7 @@ class WPSEO_Rewrite { } /** - * Update the query vars with the redirect var when stripcategorybase is active + * Update the query vars with the redirect var when stripcategorybase is active. * * @param array $query_vars Main query vars to filter. * @@ -93,62 +103,64 @@ class WPSEO_Rewrite { } /** - * Redirect the "old" category URL to the new one. + * Checks whether the redirect needs to be created. * * @param array $query_vars Query vars to check for existence of redirect var. * - * @return array + * @return array|void The query vars. */ public function request( $query_vars ) { - if ( isset( $query_vars['wpseo_category_redirect'] ) ) { - $catlink = trailingslashit( get_option( 'home' ) ) . user_trailingslashit( $query_vars['wpseo_category_redirect'], 'category' ); - - wp_redirect( $catlink, 301 ); - exit; + if ( ! isset( $query_vars['wpseo_category_redirect'] ) ) { + return $query_vars; } - return $query_vars; + $this->redirect( $query_vars['wpseo_category_redirect'] ); } /** - * This function taken and only slightly adapted from WP No Category Base plugin by Saurabh Gupta + * This function taken and only slightly adapted from WP No Category Base plugin by Saurabh Gupta. * * @return array */ public function category_rewrite_rules() { global $wp_rewrite; - $category_rewrite = array(); + $category_rewrite = []; $taxonomy = get_taxonomy( 'category' ); $permalink_structure = get_option( 'permalink_structure' ); $blog_prefix = ''; - if ( is_multisite() && ! is_subdomain_install() && is_main_site() && 0 === strpos( $permalink_structure, '/blog/' ) ) { + if ( is_multisite() && ! is_subdomain_install() && is_main_site() && strpos( $permalink_structure, '/blog/' ) === 0 ) { $blog_prefix = 'blog/'; } - $categories = get_categories( array( 'hide_empty' => false ) ); - if ( is_array( $categories ) && $categories !== array() ) { + $categories = get_categories( [ 'hide_empty' => false ] ); + if ( is_array( $categories ) && $categories !== [] ) { foreach ( $categories as $category ) { $category_nicename = $category->slug; - if ( $category->parent == $category->cat_ID ) { + if ( $category->parent === $category->cat_ID ) { // Recursive recursion. $category->parent = 0; } - elseif ( $taxonomy->rewrite['hierarchical'] != 0 && $category->parent !== 0 ) { - $parents = get_category_parents( $category->parent, false, '/', true ); + elseif ( $taxonomy->rewrite['hierarchical'] !== false && $category->parent !== 0 ) { + $parents = get_category_parents( $category->parent, false, '/', true ); if ( ! is_wp_error( $parents ) ) { $category_nicename = $parents . $category_nicename; } unset( $parents ); } - $category_rewrite[ $blog_prefix . '(' . $category_nicename . ')/(?:feed/)?(feed|rdf|rss|rss2|atom)/?$' ] = 'index.php?category_name=$matches[1]&feed=$matches[2]'; - $category_rewrite[ $blog_prefix . '(' . $category_nicename . ')/' . $wp_rewrite->pagination_base . '/?([0-9]{1,})/?$' ] = 'index.php?category_name=$matches[1]&paged=$matches[2]'; - $category_rewrite[ $blog_prefix . '(' . $category_nicename . ')/?$' ] = 'index.php?category_name=$matches[1]'; + $category_rewrite = $this->add_category_rewrites( $category_rewrite, $category_nicename, $blog_prefix, $wp_rewrite->pagination_base ); + + // Adds rules for the uppercase encoded URIs. + $category_nicename_filtered = $this->convert_encoded_to_upper( $category_nicename ); + + if ( $category_nicename_filtered !== $category_nicename ) { + $category_rewrite = $this->add_category_rewrites( $category_rewrite, $category_nicename_filtered, $blog_prefix, $wp_rewrite->pagination_base ); + } } - unset( $categories, $category, $category_nicename ); + unset( $categories, $category, $category_nicename, $category_nicename_filtered ); } // Redirect support from Old Category Base. @@ -159,4 +171,74 @@ class WPSEO_Rewrite { return $category_rewrite; } -} /* End of class */ + + /** + * Adds required category rewrites rules. + * + * @param array $rewrites The current set of rules. + * @param string $category_name Category nicename. + * @param string $blog_prefix Multisite blog prefix. + * @param string $pagination_base WP_Query pagination base. + * + * @return array The added set of rules. + */ + protected function add_category_rewrites( $rewrites, $category_name, $blog_prefix, $pagination_base ) { + $rewrite_name = $blog_prefix . '(' . $category_name . ')'; + + $rewrites[ $rewrite_name . '/(?:feed/)?(feed|rdf|rss|rss2|atom)/?$' ] = 'index.php?category_name=$matches[1]&feed=$matches[2]'; + $rewrites[ $rewrite_name . '/' . $pagination_base . '/?([0-9]{1,})/?$' ] = 'index.php?category_name=$matches[1]&paged=$matches[2]'; + $rewrites[ $rewrite_name . '/?$' ] = 'index.php?category_name=$matches[1]'; + + return $rewrites; + } + + /** + * Walks through category nicename and convert encoded parts + * into uppercase using $this->encode_to_upper(). + * + * @param string $name The encoded category URI string. + * + * @return string The convered URI string. + */ + protected function convert_encoded_to_upper( $name ) { + // Checks if name has any encoding in it. + if ( strpos( $name, '%' ) === false ) { + return $name; + } + + $names = explode( '/', $name ); + $names = array_map( [ $this, 'encode_to_upper' ], $names ); + + return implode( '/', $names ); + } + + /** + * Converts the encoded URI string to uppercase. + * + * @param string $encoded The encoded string. + * + * @return string The uppercased string. + */ + public function encode_to_upper( $encoded ) { + if ( strpos( $encoded, '%' ) === false ) { + return $encoded; + } + + return strtoupper( $encoded ); + } + + /** + * Redirect the "old" category URL to the new one. + * + * @codeCoverageIgnore + * + * @param string $category_redirect The category page to redirect to. + * @return void + */ + protected function redirect( $category_redirect ) { + $catlink = trailingslashit( get_option( 'home' ) ) . user_trailingslashit( $category_redirect, 'category' ); + + wp_safe_redirect( $catlink, 301, 'Yoast SEO' ); + exit; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-upgrade-history.php b/wp-content/plugins/wordpress-seo/inc/class-upgrade-history.php new file mode 100644 index 00000000..4103ed11 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/class-upgrade-history.php @@ -0,0 +1,133 @@ +option_name = $option_name; + } + } + + /** + * Retrieves the content of the history items currently stored. + * + * @return array The contents of the history option. + */ + public function get() { + $data = get_option( $this->get_option_name(), [] ); + if ( ! is_array( $data ) ) { + return []; + } + + return $data; + } + + /** + * Adds a new history entry in the storage. + * + * @param string $old_version The version we are upgrading from. + * @param string $new_version The version we are upgrading to. + * @param array $option_names The options that need to be stored. + */ + public function add( $old_version, $new_version, array $option_names ) { + $option_data = []; + if ( $option_names !== [] ) { + $option_data = $this->get_options_data( $option_names ); + } + + // Retrieve current history. + $data = $this->get(); + + // Add new entry. + $data[ time() ] = [ + 'options' => $option_data, + 'old_version' => $old_version, + 'new_version' => $new_version, + ]; + + // Store the data. + $this->set( $data ); + } + + /** + * Retrieves the data for the specified option names from the database. + * + * @param array $option_names The option names to retrieve. + * + * @return array + */ + protected function get_options_data( array $option_names ) { + $wpdb = $this->get_wpdb(); + + $sql = $wpdb->prepare( + ' + SELECT option_value, option_name FROM ' . $wpdb->options . ' WHERE + option_name IN ( ' . implode( ',', array_fill( 0, count( $option_names ), '%s' ) ) . ' ) + ', + $option_names + ); + + $results = $wpdb->get_results( $sql, ARRAY_A ); + + $data = []; + foreach ( $results as $result ) { + $data[ $result['option_name'] ] = maybe_unserialize( $result['option_value'] ); + } + + return $data; + } + + /** + * Stores the new history state. + * + * @param array $data The data to store. + * + * @return void + */ + protected function set( array $data ) { + // This should not be autoloaded! + update_option( $this->get_option_name(), $data, false ); + } + + /** + * Retrieves the WPDB object. + * + * @return wpdb The WPDB object to use. + */ + protected function get_wpdb() { + global $wpdb; + + return $wpdb; + } + + /** + * Retrieves the option name to store the history in. + * + * @return string The option name to store the history in. + */ + protected function get_option_name() { + return $this->option_name; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-upgrade.php b/wp-content/plugins/wordpress-seo/inc/class-upgrade.php index 93dbe010..cf73bdaa 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-upgrade.php +++ b/wp-content/plugins/wordpress-seo/inc/class-upgrade.php @@ -5,98 +5,87 @@ * @package WPSEO\Internal */ +use Yoast\WP\Lib\Model; + /** - * This code handles the option upgrades + * This code handles the option upgrades. */ class WPSEO_Upgrade { + /** - * Class constructor + * The taxonomy helper. + * + * @var \Yoast\WP\SEO\Helpers\Taxonomy_Helper + */ + private $taxonomy_helper; + + /** + * Class constructor. */ public function __construct() { + $this->taxonomy_helper = YoastSEO()->helpers->taxonomy; + $version = WPSEO_Options::get( 'version' ); WPSEO_Options::maybe_set_multisite_defaults( false ); - if ( version_compare( $version, '1.5.0', '<' ) ) { - $this->upgrade_15( $version ); - } + $routines = [ + '1.5.0' => 'upgrade_15', + '2.0' => 'upgrade_20', + '2.1' => 'upgrade_21', + '2.2' => 'upgrade_22', + '2.3' => 'upgrade_23', + '3.0' => 'upgrade_30', + '3.3' => 'upgrade_33', + '3.6' => 'upgrade_36', + '4.0' => 'upgrade_40', + '4.4' => 'upgrade_44', + '4.7' => 'upgrade_47', + '4.9' => 'upgrade_49', + '5.0' => 'upgrade_50', + '5.5' => 'upgrade_55', + '6.3' => 'upgrade_63', + '7.0-RC0' => 'upgrade_70', + '7.1-RC0' => 'upgrade_71', + '7.3-RC0' => 'upgrade_73', + '7.4-RC0' => 'upgrade_74', + '7.5.3' => 'upgrade_753', + '7.7-RC0' => 'upgrade_77', + '7.7.2-RC0' => 'upgrade_772', + '9.0-RC0' => 'upgrade_90', + '10.0-RC0' => 'upgrade_100', + '11.1-RC0' => 'upgrade_111', + // Reset notifications because we removed the AMP Glue plugin notification. + '12.1-RC0' => 'clean_all_notifications', + '12.3-RC0' => 'upgrade_123', + '12.4-RC0' => 'upgrade_124', + '12.8-RC0' => 'upgrade_128', + '13.2-RC0' => 'upgrade_132', + '14.0.3-RC0' => 'upgrade_1403', + '14.1-RC0' => 'upgrade_141', + '14.2-RC0' => 'upgrade_142', + '14.5-RC0' => 'upgrade_145', + '14.9-RC0' => 'upgrade_149', + '15.1-RC0' => 'upgrade_151', + '15.3-RC0' => 'upgrade_153', + '15.5-RC0' => 'upgrade_155', + '15.7-RC0' => 'upgrade_157', + '15.9.1-RC0' => 'upgrade_1591', + '16.2-RC0' => 'upgrade_162', + '16.5-RC0' => 'upgrade_165', + '17.1-RC0' => 'upgrade_171', + '17.2-RC0' => 'upgrade_172', + ]; - if ( version_compare( $version, '2.0', '<' ) ) { - $this->upgrade_20(); - } + array_walk( $routines, [ $this, 'run_upgrade_routine' ], $version ); - if ( version_compare( $version, '2.1', '<' ) ) { - $this->upgrade_21(); - } - - if ( version_compare( $version, '2.2', '<' ) ) { - $this->upgrade_22(); - } - - if ( version_compare( $version, '2.3', '<' ) ) { - $this->upgrade_23(); - } - - if ( version_compare( $version, '3.0', '<' ) ) { - $this->upgrade_30(); - } - - if ( version_compare( $version, '3.3', '<' ) ) { - $this->upgrade_33(); - } - - if ( version_compare( $version, '3.6', '<' ) ) { - $this->upgrade_36(); - } - - if ( version_compare( $version, '4.0', '<' ) ) { - $this->upgrade_40(); - } - - if ( version_compare( $version, '4.4', '<' ) ) { - $this->upgrade_44(); - } - - if ( version_compare( $version, '4.7', '<' ) ) { - $this->upgrade_47(); - } - - if ( version_compare( $version, '4.9', '<' ) ) { - $this->upgrade_49(); - } - - if ( version_compare( $version, '5.0', '<' ) ) { - $this->upgrade_50(); - } - - if ( version_compare( $version, '5.0', '>=' ) - && version_compare( $version, '5.1', '<' ) - ) { - $this->upgrade_50_51(); - } - - if ( version_compare( $version, '5.5', '<' ) ) { - $this->upgrade_55(); - } - - if ( version_compare( $version, '5.6', '<' ) ) { - $this->upgrade_56(); - } - - if ( version_compare( $version, '6.1', '<' ) ) { - $this->upgrade_61(); - } - - if ( version_compare( $version, '6.3', '<' ) ) { - $this->upgrade_63(); - } - - if ( version_compare( $version, '7.0-RC0', '<' ) ) { - $this->upgrade_70(); - } - - if ( version_compare( $version, '7.1-RC0', '<' ) ) { - $this->upgrade_71(); + if ( version_compare( $version, '12.5-RC0', '<' ) ) { + /* + * We have to run this by hook, because otherwise: + * - the theme support check isn't available. + * - the notification center notifications are not filled yet. + */ + add_action( 'init', [ $this, 'upgrade_125' ] ); } // Since 3.7. @@ -104,29 +93,66 @@ class WPSEO_Upgrade { $upsell_notice->set_upgrade_notice(); /** - * Filter: 'wpseo_run_upgrade' - Runs the upgrade hook which are dependent on Yoast SEO + * Filter: 'wpseo_run_upgrade' - Runs the upgrade hook which are dependent on Yoast SEO. * - * @api string - The current version of Yoast SEO + * @api string - The current version of Yoast SEO */ do_action( 'wpseo_run_upgrade', $version ); - $this->finish_up(); + $this->finish_up( $version ); + } + + /** + * Runs the upgrade routine. + * + * @param string $routine The method to call. + * @param string $version The new version. + * @param string $current_version The current set version. + * + * @return void + */ + protected function run_upgrade_routine( $routine, $version, $current_version ) { + if ( version_compare( $current_version, $version, '<' ) ) { + $this->$routine( $current_version ); + } + } + + /** + * Adds a new upgrade history entry. + * + * @param string $current_version The old version from which we are upgrading. + * @param string $new_version The version we are upgrading to. + */ + protected function add_upgrade_history( $current_version, $new_version ) { + $upgrade_history = new WPSEO_Upgrade_History(); + $upgrade_history->add( $current_version, $new_version, array_keys( WPSEO_Options::$options ) ); } /** * Runs the needed cleanup after an update, setting the DB version to latest version, flushing caches etc. + * + * @param string|null $previous_version The previous version. + * + * @return void */ - protected function finish_up() { + protected function finish_up( $previous_version = null ) { + if ( $previous_version ) { + WPSEO_Options::set( 'previous_version', $previous_version ); + } WPSEO_Options::set( 'version', WPSEO_VERSION ); - add_action( 'shutdown', 'flush_rewrite_rules' ); // Just flush rewrites, always, to at least make them work after an upgrade. - WPSEO_Sitemaps_Cache::clear(); // Flush the sitemap cache. + // Just flush rewrites, always, to at least make them work after an upgrade. + add_action( 'shutdown', 'flush_rewrite_rules' ); - WPSEO_Options::ensure_options_exist(); // Make sure all our options always exist - issue #1245. + // Flush the sitemap cache. + WPSEO_Sitemaps_Cache::clear(); + + // Make sure all our options always exist - issue #1245. + WPSEO_Options::ensure_options_exist(); } /** - * Run the Yoast SEO 1.5 upgrade routine + * Run the Yoast SEO 1.5 upgrade routine. * * @param string $version Current plugin version. */ @@ -137,12 +163,12 @@ class WPSEO_Upgrade { } /** - * Moves options that moved position in WPSEO 2.0 + * Moves options that moved position in WPSEO 2.0. */ private function upgrade_20() { /** * Clean up stray wpseo_ms options from the options table, option should only exist in the sitemeta table. - * This could have been caused in many version of Yoast SEO, so deleting it for everything below 2.0 + * This could have been caused in many version of Yoast SEO, so deleting it for everything below 2.0. */ delete_option( 'wpseo_ms' ); @@ -157,7 +183,7 @@ class WPSEO_Upgrade { * Detects if taxonomy terms were split and updates the corresponding taxonomy meta's accordingly. */ private function upgrade_21() { - $taxonomies = get_option( 'wpseo_taxonomy_meta', array() ); + $taxonomies = get_option( 'wpseo_taxonomy_meta', [] ); if ( ! empty( $taxonomies ) ) { foreach ( $taxonomies as $taxonomy => $tax_metas ) { @@ -177,7 +203,7 @@ class WPSEO_Upgrade { } /** - * Performs upgrade functions to Yoast SEO 2.2 + * Performs upgrade functions to Yoast SEO 2.2. */ private function upgrade_22() { // Unschedule our tracking. @@ -187,15 +213,15 @@ class WPSEO_Upgrade { } /** - * Schedules upgrade function to Yoast SEO 2.3 + * Schedules upgrade function to Yoast SEO 2.3. */ private function upgrade_23() { - add_action( 'wp', array( $this, 'upgrade_23_query' ), 90 ); - add_action( 'admin_head', array( $this, 'upgrade_23_query' ), 90 ); + add_action( 'wp', [ $this, 'upgrade_23_query' ], 90 ); + add_action( 'admin_head', [ $this, 'upgrade_23_query' ], 90 ); } /** - * Performs upgrade query to Yoast SEO 2.3 + * Performs upgrade query to Yoast SEO 2.3. */ public function upgrade_23_query() { $wp_query = new WP_Query( 'post_type=any&meta_key=_yoast_wpseo_sitemap-include&meta_value=never&order=ASC' ); @@ -203,13 +229,13 @@ class WPSEO_Upgrade { if ( ! empty( $wp_query->posts ) ) { $options = get_option( 'wpseo_xml' ); - $excluded_posts = array(); + $excluded_posts = []; if ( $options['excluded-posts'] !== '' ) { $excluded_posts = explode( ',', $options['excluded-posts'] ); } foreach ( $wp_query->posts as $post ) { - if ( ! in_array( $post->ID, $excluded_posts ) ) { + if ( ! in_array( (string) $post->ID, $excluded_posts, true ) ) { $excluded_posts[] = $post->ID; } } @@ -255,12 +281,8 @@ class WPSEO_Upgrade { * Removes the about notice when its still in the database. */ private function upgrade_40() { - $center = Yoast_Notification_Center::get(); - $notification = $center->get_notification_by_id( 'wpseo-dismiss-about' ); - - if ( $notification ) { - $center->remove_notification( $notification ); - } + $center = Yoast_Notification_Center::get(); + $center->remove_notification_by_id( 'wpseo-dismiss-about' ); } /** @@ -286,7 +308,7 @@ class WPSEO_Upgrade { $wpdb->query( $wpdb->prepare( 'UPDATE ' . $wpdb->postmeta . ' SET meta_key = %s WHERE meta_key = "yst_is_cornerstone"', - WPSEO_Cornerstone::META_NAME + WPSEO_Cornerstone_Filter::META_NAME ) ); } @@ -303,12 +325,13 @@ class WPSEO_Upgrade { * notifications on shutdown. This causes the returning notification. By adding this filter the shutdown * routine on the notification center will remove the notification. */ - add_filter( 'yoast_notifications_before_storage', array( $this, 'remove_about_notice' ) ); + add_filter( 'yoast_notifications_before_storage', [ $this, 'remove_about_notice' ] ); $meta_key = $wpdb->get_blog_prefix() . Yoast_Notification_Center::STORAGE_KEY; $usermetas = $wpdb->get_results( - $wpdb->prepare( ' + $wpdb->prepare( + ' SELECT user_id, meta_value FROM ' . $wpdb->usermeta . ' WHERE meta_key = %s AND meta_value LIKE %s @@ -359,27 +382,10 @@ class WPSEO_Upgrade { private function upgrade_50() { global $wpdb; - $link_installer = new WPSEO_Link_Installer(); - $link_installer->install(); - - // Trigger reindex notification. - $notifier = new WPSEO_Link_Notifier(); - $notifier->manage_notification(); - // Deletes the post meta value, which might created in the RC. $wpdb->query( 'DELETE FROM ' . $wpdb->postmeta . ' WHERE meta_key = "_yst_content_links_processed"' ); } - /** - * Updates the internal_link_count column to support improved functionality. - */ - private function upgrade_50_51() { - global $wpdb; - - $count_storage = new WPSEO_Meta_Storage(); - $wpdb->query( 'ALTER TABLE ' . $count_storage->get_table_name() . ' MODIFY internal_link_count int(10) UNSIGNED NULL DEFAULT NULL' ); - } - /** * Register new capabilities and roles. */ @@ -393,41 +399,6 @@ class WPSEO_Upgrade { WPSEO_Capability_Manager_Factory::get()->add(); } - /** - * Updates legacy license page options to the latest version. - */ - private function upgrade_56() { - global $wpdb; - - // Make sure License Server checks are on the latest server version by default. - update_option( 'wpseo_license_server_version', WPSEO_License_Page_Manager::VERSION_BACKWARDS_COMPATIBILITY ); - - // Make sure incoming link count entries are at least 0, not NULL. - $count_storage = new WPSEO_Meta_Storage(); - $wpdb->query( 'UPDATE ' . $count_storage->get_table_name() . ' SET incoming_link_count = 0 WHERE incoming_link_count IS NULL' ); - } - - /** - * Updates the links for the link count when there is a difference between the site and home url. We've used the - * site url instead of the home url. - * - * @return void - */ - private function upgrade_61() { - // When the home url is the same as the site url, just do nothing. - if ( home_url() === site_url() ) { - return; - } - - global $wpdb; - - $link_storage = new WPSEO_Link_Storage(); - $wpdb->query( 'DELETE FROM ' . $link_storage->get_table_name() ); - - $meta_storage = new WPSEO_Meta_Storage(); - $wpdb->query( 'DELETE FROM ' . $meta_storage->get_table_name() ); - } - /** * Removes some no longer used options for noindexing subpages and for meta keywords and its associated templates. * @@ -509,6 +480,8 @@ class WPSEO_Upgrade { /** * Perform the 7.1 upgrade. + * + * @return void */ private function upgrade_71() { $this->cleanup_option_data( 'wpseo_social' ); @@ -523,6 +496,522 @@ class WPSEO_Upgrade { } } + /** + * Perform the 7.3 upgrade. + * + * @return void + */ + private function upgrade_73() { + global $wpdb; + // We've moved the cornerstone checkbox to our proper namespace. + $wpdb->query( "UPDATE $wpdb->postmeta SET meta_key = '_yoast_wpseo_is_cornerstone' WHERE meta_key = '_yst_is_cornerstone'" ); + + // Remove the previous Whip dismissed message, as this is a new one regarding PHP 5.2. + delete_option( 'whip_dismiss_timestamp' ); + } + + /** + * Performs the 7.4 upgrade. + * + * @return void + */ + private function upgrade_74() { + $this->remove_sitemap_validators(); + } + + /** + * Performs the 7.5.3 upgrade. + * + * When upgrading purging media is potentially relevant. + * + * @return void + */ + private function upgrade_753() { + // Only when attachments are not disabled. + if ( WPSEO_Options::get( 'disable-attachment' ) === true ) { + return; + } + + // Only when attachments are not no-indexed. + if ( WPSEO_Options::get( 'noindex-attachment' ) === true ) { + return; + } + + // Set purging relevancy. + WPSEO_Options::set( 'is-media-purge-relevant', true ); + } + + /** + * Performs the 7.7 upgrade. + * + * @return void + */ + private function upgrade_77() { + // Remove all OpenGraph content image cache. + $this->delete_post_meta( '_yoast_wpseo_post_image_cache' ); + } + + /** + * Performs the 7.7.2 upgrade. + * + * @return void + */ + private function upgrade_772() { + if ( YoastSEO()->helpers->woocommerce->is_active() ) { + $this->migrate_woocommerce_archive_setting_to_shop_page(); + } + } + + /** + * Performs the 9.0 upgrade. + * + * @return void + */ + private function upgrade_90() { + global $wpdb; + + // Invalidate all sitemap cache transients. + WPSEO_Sitemaps_Cache_Validator::cleanup_database(); + + // Removes all scheduled tasks for hitting the sitemap index. + wp_clear_scheduled_hook( 'wpseo_hit_sitemap_index' ); + + $wpdb->query( 'DELETE FROM ' . $wpdb->options . ' WHERE option_name LIKE "wpseo_sitemap_%"' ); + } + + /** + * Performs the 10.0 upgrade. + * + * @return void + */ + private function upgrade_100() { + // Removes recalibration notifications. + $this->clean_all_notifications(); + + // Removes recalibration options. + WPSEO_Options::clean_up( 'wpseo' ); + delete_option( 'wpseo_recalibration_beta_mailinglist_subscription' ); + } + + /** + * Performs the 11.1 upgrade. + * + * @return void + */ + private function upgrade_111() { + // Set company_or_person to company when it's an invalid value. + $company_or_person = WPSEO_Options::get( 'company_or_person', '' ); + + if ( ! in_array( $company_or_person, [ 'company', 'person' ], true ) ) { + WPSEO_Options::set( 'company_or_person', 'company' ); + } + } + + /** + * Performs the 12.3 upgrade. + * + * Removes the about notice when its still in the database. + */ + private function upgrade_123() { + $plugins = [ + 'yoast-seo-premium', + 'video-seo-for-wordpress-seo-by-yoast', + 'yoast-news-seo', + 'local-seo-for-yoast-seo', + 'yoast-woocommerce-seo', + 'yoast-acf-analysis', + ]; + + $center = Yoast_Notification_Center::get(); + foreach ( $plugins as $plugin ) { + $center->remove_notification_by_id( 'wpseo-outdated-yoast-seo-plugin-' . $plugin ); + } + } + + /** + * Performs the 12.4 upgrade. + * + * Removes the Google plus defaults from the database. + */ + private function upgrade_124() { + $this->cleanup_option_data( 'wpseo_social' ); + } + + /** + * Performs the 12.5 upgrade. + */ + public function upgrade_125() { + // Disables the force rewrite title when the theme supports it through WordPress. + if ( WPSEO_Options::get( 'forcerewritetitle', false ) && current_theme_supports( 'title-tag' ) ) { + WPSEO_Options::set( 'forcerewritetitle', false ); + } + + global $wpdb; + $wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key = 'wp_yoast_promo_hide_premium_upsell_admin_block'" ); + + // Removes the WordPress update notification, because it is no longer necessary when WordPress 5.3 is released. + $center = Yoast_Notification_Center::get(); + $center->remove_notification_by_id( 'wpseo-dismiss-wordpress-upgrade' ); + } + + /** + * Performs the 12.8 upgrade. + */ + private function upgrade_128() { + // Re-save wpseo to make sure bf_banner_2019_dismissed key is gone. + $this->cleanup_option_data( 'wpseo' ); + + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-dismiss-page_comments-notice' ); + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-dismiss-wordpress-upgrade' ); + } + + /** + * Performs the 13.2 upgrade. + */ + private function upgrade_132() { + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-dismiss-tagline-notice' ); + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-dismiss-permalink-notice' ); + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-dismiss-onpageorg' ); + + // Transfers the onpage option value to the ryte option. + $ryte_option = get_option( 'wpseo_ryte' ); + $onpage_option = get_option( 'wpseo_onpage' ); + if ( ! $ryte_option && $onpage_option ) { + update_option( 'wpseo_ryte', $onpage_option ); + delete_option( 'wpseo_onpage' ); + } + + // Changes onpage_indexability to ryte_indexability. + $wpseo_option = get_option( 'wpseo' ); + if ( isset( $wpseo_option['onpage_indexability'] ) && ! isset( $wpseo_option['ryte_indexability'] ) ) { + $wpseo_option['ryte_indexability'] = $wpseo_option['onpage_indexability']; + unset( $wpseo_option['onpage_indexability'] ); + update_option( 'wpseo', $wpseo_option ); + } + + if ( wp_next_scheduled( 'wpseo_ryte_fetch' ) ) { + wp_clear_scheduled_hook( 'wpseo_ryte_fetch' ); + } + + /* + * Re-register capabilities to add the new `view_site_health_checks` + * capability to the SEO Manager role. + */ + do_action( 'wpseo_register_capabilities' ); + WPSEO_Capability_Manager_Factory::get()->add(); + } + + /** + * Perform the 14.0.3 upgrade. + */ + private function upgrade_1403() { + WPSEO_Options::set( 'ignore_indexation_warning', false ); + } + + /** + * Performs the 14.1 upgrade. + */ + private function upgrade_141() { + /* + * These notifications are retrieved from storage on the `init` hook with + * priority 1. We need to remove them after they're retrieved. + */ + add_action( 'init', [ $this, 'remove_notifications_for_141' ] ); + add_action( 'init', [ $this, 'clean_up_private_taxonomies_for_141' ] ); + + $this->reset_permalinks_of_attachments_for_141(); + } + + /** + * Performs the 14.2 upgrade. + * + * Removes the yoast-acf-analysis notice when it's still in the database. + */ + private function upgrade_142() { + add_action( 'init', [ $this, 'remove_acf_notification_for_142' ] ); + } + + /** + * Performs the 14.5 upgrade. + */ + private function upgrade_145() { + add_action( 'init', [ $this, 'set_indexation_completed_option_for_145' ] ); + } + + /** + * Performs the 14.9 upgrade. + */ + private function upgrade_149() { + $version = get_option( 'wpseo_license_server_version', 2 ); + WPSEO_Options::set( 'license_server_version', $version ); + delete_option( 'wpseo_license_server_version' ); + } + + /** + * Performs the 15.1 upgrade. + * + * @return void + */ + private function upgrade_151() { + $this->set_home_url_for_151(); + $this->move_indexables_indexation_reason_for_151(); + + add_action( 'init', [ $this, 'set_permalink_structure_option_for_151' ] ); + add_action( 'init', [ $this, 'store_custom_taxonomy_slugs_for_151' ] ); + } + + /** + * Performs the 15.3 upgrade. + * + * @return void + */ + private function upgrade_153() { + WPSEO_Options::set( 'category_base_url', get_option( 'category_base' ) ); + WPSEO_Options::set( 'tag_base_url', get_option( 'tag_base' ) ); + + // Rename a couple of options. + $indexation_started_value = WPSEO_Options::get( 'indexation_started' ); + WPSEO_Options::set( 'indexing_started', $indexation_started_value ); + + $indexables_indexing_completed_value = WPSEO_Options::get( 'indexables_indexation_completed' ); + WPSEO_Options::set( 'indexables_indexing_completed', $indexables_indexing_completed_value ); + } + + /** + * Performs the 15.5 upgrade. + * + * @return void + */ + private function upgrade_155() { + // Unset the fbadminapp value in the wpseo_social option. + $wpseo_social_option = get_option( 'wpseo_social' ); + + if ( isset( $wpseo_social_option['fbadminapp'] ) ) { + unset( $wpseo_social_option['fbadminapp'] ); + update_option( 'wpseo_social', $wpseo_social_option ); + } + } + + /** + * Performs the 15.7 upgrade. + * + * @return void + */ + private function upgrade_157() { + add_action( 'init', [ $this, 'remove_plugin_updated_notification_for_157' ] ); + } + + /** + * Performs the 15.9.1 upgrade routine. + */ + private function upgrade_1591() { + $enabled_auto_updates = \get_option( 'auto_update_plugins' ); + $addon_update_watcher = YoastSEO()->classes->get( \Yoast\WP\SEO\Integrations\Watchers\Addon_Update_Watcher::class ); + $addon_update_watcher->toggle_auto_updates_for_add_ons( 'auto_update_plugins', [], $enabled_auto_updates ); + } + + /** + * Performs the 16.2 upgrade routine. + */ + private function upgrade_162() { + $enabled_auto_updates = \get_site_option( 'auto_update_plugins' ); + $addon_update_watcher = YoastSEO()->classes->get( \Yoast\WP\SEO\Integrations\Watchers\Addon_Update_Watcher::class ); + $addon_update_watcher->toggle_auto_updates_for_add_ons( 'auto_update_plugins', $enabled_auto_updates, [] ); + } + + /** + * Performs the 16.5 upgrade. + * + * @return void + */ + private function upgrade_165() { + add_action( 'init', [ $this, 'copy_og_settings_from_social_to_titles' ], 99 ); + + // Run after the WPSEO_Options::enrich_defaults method which has priority 99. + add_action( 'init', [ $this, 'reset_og_settings_to_default_values' ], 100 ); + } + + /** + * Performs the 17.2 upgrade. Cleans out any unnecessary indexables. See $cleanup_integration->get_cleanup_tasks() to see what will be cleaned out. + * + * @return void + */ + private function upgrade_172() { + \wp_unschedule_hook( 'wpseo_cleanup_orphaned_indexables' ); + \wp_unschedule_hook( 'wpseo_cleanup_indexables' ); + + if ( ! \wp_next_scheduled( \Yoast\WP\SEO\Integrations\Cleanup_Integration::START_HOOK ) ) { + \wp_schedule_single_event( ( time() + ( MINUTE_IN_SECONDS * 5 ) ), \Yoast\WP\SEO\Integrations\Cleanup_Integration::START_HOOK ); + } + } + + /** + * Performs the 17.1 upgrade. Removes the pipe and tilde separators and replaces them with the dash separator. + * + * @return void + */ + private function upgrade_171() { + $separator = WPSEO_Options::get( 'separator' ); + if ( $separator === 'sc-pipe' || $separator === 'sc-tilde' ) { + WPSEO_Options::set( 'separator', 'sc-dash' ); + } + } + + /** + * Sets the home_url option for the 15.1 upgrade routine. + * + * @return void + */ + protected function set_home_url_for_151() { + $home_url = WPSEO_Options::get( 'home_url' ); + + if ( empty( $home_url ) ) { + WPSEO_Options::set( 'home_url', get_home_url() ); + } + } + + /** + * Moves the `indexables_indexation_reason` option to the + * renamed `indexing_reason` option. + * + * @return void + */ + protected function move_indexables_indexation_reason_for_151() { + $reason = WPSEO_Options::get( 'indexables_indexation_reason', '' ); + WPSEO_Options::set( 'indexing_reason', $reason ); + } + + /** + * Checks if the indexable indexation is completed. + * If so, sets the `indexables_indexation_completed` option to `true`, + * else to `false`. + */ + public function set_indexation_completed_option_for_145() { + WPSEO_Options::set( 'indexables_indexation_completed', YoastSEO()->helpers->indexing->get_unindexed_count() === 0 ); + } + + /** + * Cleans up the private taxonomies from the indexables table for the upgrade routine to 14.1. + */ + public function clean_up_private_taxonomies_for_141() { + global $wpdb; + + // If migrations haven't been completed successfully the following may give false errors. So suppress them. + $show_errors = $wpdb->show_errors; + $wpdb->show_errors = false; + + // Clean up indexables of private taxonomies. + $private_taxonomies = \get_taxonomies( [ 'public' => false ], 'names' ); + + if ( empty( $private_taxonomies ) ) { + return; + } + + $indexable_table = Model::get_table_name( 'Indexable' ); + + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Reason: Is it prepared already. + $query = $wpdb->prepare( + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: Too hard to fix. + "DELETE FROM $indexable_table + WHERE object_type = 'term' + AND object_sub_type IN (" + . \implode( ', ', \array_fill( 0, \count( $private_taxonomies ), '%s' ) ) + . ')', + $private_taxonomies + ); + $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Reason: Is it prepared already. + + $wpdb->show_errors = $show_errors; + } + + /** + * Resets the permalinks of attachments to `null` in the indexable table for the upgrade routine to 14.1. + */ + private function reset_permalinks_of_attachments_for_141() { + global $wpdb; + + // If migrations haven't been completed succesfully the following may give false errors. So suppress them. + $show_errors = $wpdb->show_errors; + $wpdb->show_errors = false; + + // Reset the permalinks of the attachments in the indexable table. + $indexable_table = Model::get_table_name( 'Indexable' ); + $query = "UPDATE $indexable_table SET permalink = NULL WHERE object_type = 'post' AND object_sub_type = 'attachment'"; + $wpdb->query( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Reason: There is no user input. + + $wpdb->show_errors = $show_errors; + } + + /** + * Removes notifications from the Notification center for the 14.1 upgrade. + * + * @return void + */ + public function remove_notifications_for_141() { + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-dismiss-recalculate' ); + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-dismiss-blog-public-notice' ); + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-links-table-not-accessible' ); + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-post-type-archive-notification' ); + } + + /** + * Removes the wpseo-suggested-plugin-yoast-acf-analysis notification from the Notification center for the 14.2 upgrade. + * + * @return void + */ + public function remove_acf_notification_for_142() { + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-suggested-plugin-yoast-acf-analysis' ); + } + + /** + * Removes the wpseo-plugin-updated notification from the Notification center for the 15.7 upgrade. + * + * @return void + */ + public function remove_plugin_updated_notification_for_157() { + Yoast_Notification_Center::get()->remove_notification_by_id( 'wpseo-plugin-updated' ); + } + + /** + * Removes all notifications saved in the database under 'wp_yoast_notifications'. + * + * @return void + */ + private function clean_all_notifications() { + global $wpdb; + delete_metadata( 'user', 0, $wpdb->get_blog_prefix() . Yoast_Notification_Center::STORAGE_KEY, '', true ); + } + + /** + * Removes the post meta fields for a given meta key. + * + * @param string $meta_key The meta key. + * + * @return void + */ + private function delete_post_meta( $meta_key ) { + global $wpdb; + $deleted = $wpdb->delete( $wpdb->postmeta, [ 'meta_key' => $meta_key ], [ '%s' ] ); + + if ( $deleted ) { + wp_cache_set( 'last_changed', microtime(), 'posts' ); + } + } + + /** + * Removes all sitemap validators. + * + * This should be executed on every upgrade routine until we have removed the sitemap caching in the database. + * + * @return void + */ + private function remove_sitemap_validators() { + global $wpdb; + + // Remove all sitemap validators. + $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE 'wpseo_sitemap%validator%'" ); + } + /** * Retrieves the option value directly from the database. * @@ -535,12 +1024,12 @@ class WPSEO_Upgrade { // Load option directly from the database, to avoid filtering and sanitization. $sql = $wpdb->prepare( 'SELECT option_value FROM ' . $wpdb->options . ' WHERE option_name = %s', $option_name ); - $results = $wpdb->get_results( $sql, ARRAY_A ); + $results = $wpdb->get_results( $sql, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Reason: Is is already prepared. if ( ! empty( $results ) ) { return maybe_unserialize( $results[0]['option_value'] ); } - return array(); + return []; } /** @@ -551,8 +1040,8 @@ class WPSEO_Upgrade { * @return void */ protected function cleanup_option_data( $option_name ) { - $data = get_option( $option_name, array() ); - if ( ! is_array( $data ) || $data === array() ) { + $data = get_option( $option_name, [] ); + if ( ! is_array( $data ) || $data === [] ) { return; } @@ -583,4 +1072,182 @@ class WPSEO_Upgrade { WPSEO_Options::set( $target_setting, $source_data[ $source_setting ] ); } } + + /** + * Migrates WooCommerce archive settings to the WooCommerce Shop page meta-data settings. + * + * If no Shop page is defined, nothing will be migrated. + * + * @return void + */ + private function migrate_woocommerce_archive_setting_to_shop_page() { + $shop_page_id = wc_get_page_id( 'shop' ); + + if ( $shop_page_id === -1 ) { + return; + } + + $title = WPSEO_Meta::get_value( 'title', $shop_page_id ); + + if ( empty( $title ) ) { + $option_title = WPSEO_Options::get( 'title-ptarchive-product' ); + + WPSEO_Meta::set_value( + 'title', + $option_title, + $shop_page_id + ); + + WPSEO_Options::set( 'title-ptarchive-product', '' ); + } + + $meta_description = WPSEO_Meta::get_value( 'metadesc', $shop_page_id ); + + if ( empty( $meta_description ) ) { + $option_metadesc = WPSEO_Options::get( 'metadesc-ptarchive-product' ); + + WPSEO_Meta::set_value( + 'metadesc', + $option_metadesc, + $shop_page_id + ); + + WPSEO_Options::set( 'metadesc-ptarchive-product', '' ); + } + + $bc_title = WPSEO_Meta::get_value( 'bctitle', $shop_page_id ); + + if ( empty( $bc_title ) ) { + $option_bctitle = WPSEO_Options::get( 'bctitle-ptarchive-product' ); + + WPSEO_Meta::set_value( + 'bctitle', + $option_bctitle, + $shop_page_id + ); + + WPSEO_Options::set( 'bctitle-ptarchive-product', '' ); + } + + $noindex = WPSEO_Meta::get_value( 'meta-robots-noindex', $shop_page_id ); + + if ( $noindex === '0' ) { + $option_noindex = WPSEO_Options::get( 'noindex-ptarchive-product' ); + + WPSEO_Meta::set_value( + 'meta-robots-noindex', + $option_noindex, + $shop_page_id + ); + + WPSEO_Options::set( 'noindex-ptarchive-product', false ); + } + } + + /** + * Stores the initial `permalink_structure` option. + * + * @return void + */ + public function set_permalink_structure_option_for_151() { + WPSEO_Options::set( 'permalink_structure', get_option( 'permalink_structure' ) ); + } + + /** + * Stores the initial slugs of custom taxonomies. + * + * @return void + */ + public function store_custom_taxonomy_slugs_for_151() { + $taxonomies = $this->taxonomy_helper->get_custom_taxonomies(); + + $custom_taxonomies = []; + + foreach ( $taxonomies as $taxonomy ) { + $slug = $this->taxonomy_helper->get_taxonomy_slug( $taxonomy ); + + $custom_taxonomies[ $taxonomy ] = $slug; + } + + WPSEO_Options::set( 'custom_taxonomy_slugs', $custom_taxonomies ); + } + + /** + * Copies the frontpage social settings to the titles options. + * + * @return void + */ + public function copy_og_settings_from_social_to_titles() { + $wpseo_social = get_option( 'wpseo_social' ); + $wpseo_titles = get_option( 'wpseo_titles' ); + + $copied_options = []; + // Reset to the correct default value. + $copied_options['open_graph_frontpage_title'] = '%%sitename%%'; + + $options = [ + 'og_frontpage_title' => 'open_graph_frontpage_title', + 'og_frontpage_desc' => 'open_graph_frontpage_desc', + 'og_frontpage_image' => 'open_graph_frontpage_image', + 'og_frontpage_image_id' => 'open_graph_frontpage_image_id', + ]; + + foreach ( $options as $social_option => $titles_option ) { + if ( ! empty( $wpseo_social[ $social_option ] ) ) { + $copied_options[ $titles_option ] = $wpseo_social[ $social_option ]; + } + } + + $wpseo_titles = array_merge( $wpseo_titles, $copied_options ); + + update_option( 'wpseo_titles', $wpseo_titles ); + } + + /** + * Reset the social options with the correct default values. + * + * @return void + */ + public function reset_og_settings_to_default_values() { + $wpseo_titles = get_option( 'wpseo_titles' ); + $updated_options = []; + + $updated_options['social-title-author-wpseo'] = '%%name%%'; + $updated_options['social-title-archive-wpseo'] = '%%date%%'; + + /* translators: %s expands to the name of a post type (plural). */ + $post_type_archive_default = sprintf( __( '%s Archive', 'wordpress-seo' ), '%%pt_plural%%' ); + + /* translators: %s expands to the variable used for term title. */ + $term_archive_default = sprintf( __( '%s Archives', 'wordpress-seo' ), '%%term_title%%' ); + + $post_type_objects = get_post_types( [ 'public' => true ], 'objects' ); + + if ( $post_type_objects ) { + foreach ( $post_type_objects as $pt ) { + // Post types. + if ( isset( $wpseo_titles[ 'social-title-' . $pt->name ] ) ) { + $updated_options[ 'social-title-' . $pt->name ] = '%%title%%'; + } + // Post type archives. + if ( isset( $wpseo_titles[ 'social-title-ptarchive-' . $pt->name ] ) ) { + $updated_options[ 'social-title-ptarchive-' . $pt->name ] = $post_type_archive_default; + } + } + } + + $taxonomy_objects = get_taxonomies( [ 'public' => true ], 'object' ); + + if ( $taxonomy_objects ) { + foreach ( $taxonomy_objects as $tax ) { + if ( isset( $wpseo_titles[ 'social-title-tax-' . $tax->name ] ) ) { + $updated_options[ 'social-title-tax-' . $tax->name ] = $term_archive_default; + } + } + } + + $wpseo_titles = array_merge( $wpseo_titles, $updated_options ); + + update_option( 'wpseo_titles', $wpseo_titles ); + } } diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-admin-bar-menu.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-admin-bar-menu.php new file mode 100644 index 00000000..8d8f56c8 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-admin-bar-menu.php @@ -0,0 +1,690 @@ +asset_manager = $asset_manager; + } + + /** + * Adds the admin bar menu. + * + * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to. + * + * @return void + */ + public function add_menu( WP_Admin_Bar $wp_admin_bar ) { + + // On block editor pages, the admin bar only shows on mobile, where having this menu icon is not very helpful. + if ( is_admin() ) { + $screen = get_current_screen(); + if ( isset( $screen ) && $screen->is_block_editor() ) { + return; + } + } + + // If the current user can't write posts, this is all of no use, so let's not output an admin menu. + if ( ! current_user_can( 'edit_posts' ) ) { + return; + } + + $this->add_root_menu( $wp_admin_bar ); + $this->add_keyword_research_submenu( $wp_admin_bar ); + + if ( ! is_admin() ) { + $this->add_analysis_submenu( $wp_admin_bar ); + } + + if ( ! is_admin() || is_blog_admin() ) { + $this->add_settings_submenu( $wp_admin_bar ); + } + elseif ( is_network_admin() ) { + $this->add_network_settings_submenu( $wp_admin_bar ); + } + } + + /** + * Enqueues admin bar assets. + * + * @return void + */ + public function enqueue_assets() { + if ( ! is_admin_bar_showing() ) { + return; + } + + // If the current user can't write posts, this is all of no use, so let's not output an admin menu. + if ( ! current_user_can( 'edit_posts' ) ) { + return; + } + + $this->asset_manager->register_assets(); + $this->asset_manager->enqueue_style( 'adminbar' ); + } + + /** + * Registers the hooks. + * + * @return void + */ + public function register_hooks() { + if ( ! $this->meets_requirements() ) { + return; + } + + add_action( 'admin_bar_menu', [ $this, 'add_menu' ], 95 ); + + add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_assets' ] ); + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] ); + } + + /** + * Checks whether the requirements to use this class are met. + * + * @return bool True if requirements are met, false otherwise. + */ + public function meets_requirements() { + if ( is_network_admin() ) { + return WPSEO_Utils::is_plugin_network_active(); + } + + if ( WPSEO_Options::get( 'enable_admin_bar_menu' ) !== true ) { + return false; + } + + return ! is_admin() || is_blog_admin(); + } + + /** + * Adds the admin bar root menu. + * + * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to. + * + * @return void + */ + protected function add_root_menu( WP_Admin_Bar $wp_admin_bar ) { + $title = $this->get_title(); + + $score = ''; + $settings_url = ''; + $counter = ''; + $notification_popup = ''; + + $post = $this->get_singular_post(); + if ( $post ) { + $score = $this->get_post_score( $post ); + } + + $term = $this->get_singular_term(); + if ( $term ) { + $score = $this->get_term_score( $term ); + } + + $can_manage_options = $this->can_manage_options(); + + if ( $can_manage_options ) { + $settings_url = $this->get_settings_page_url(); + } + + if ( empty( $score ) && ! is_network_admin() && $can_manage_options ) { + $counter = $this->get_notification_counter(); + $notification_popup = $this->get_notification_popup(); + } + + $admin_bar_menu_args = [ + 'id' => self::MENU_IDENTIFIER, + 'title' => $title . $score . $counter . $notification_popup, + 'href' => $settings_url, + 'meta' => [ 'tabindex' => ! empty( $settings_url ) ? false : '0' ], + ]; + $wp_admin_bar->add_menu( $admin_bar_menu_args ); + + if ( ! empty( $counter ) ) { + $admin_bar_menu_args = [ + 'parent' => self::MENU_IDENTIFIER, + 'id' => 'wpseo-notifications', + 'title' => __( 'Notifications', 'wordpress-seo' ) . $counter, + 'href' => $settings_url, + 'meta' => [ 'tabindex' => ! empty( $settings_url ) ? false : '0' ], + ]; + $wp_admin_bar->add_menu( $admin_bar_menu_args ); + } + + if ( ! is_network_admin() && $can_manage_options ) { + $admin_bar_menu_args = [ + 'parent' => self::MENU_IDENTIFIER, + 'id' => 'wpseo-configuration-wizard', + 'title' => __( 'Configuration Wizard', 'wordpress-seo' ), + 'href' => admin_url( 'admin.php?page=' . WPSEO_Configuration_Page::PAGE_IDENTIFIER ), + ]; + $wp_admin_bar->add_menu( $admin_bar_menu_args ); + } + } + + /** + * Adds the admin bar keyword research submenu. + * + * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to. + * + * @return void + */ + protected function add_keyword_research_submenu( WP_Admin_Bar $wp_admin_bar ) { + $adwords_url = 'https://yoa.st/keywordplanner'; + $trends_url = 'https://yoa.st/google-trends'; + + $post = $this->get_singular_post(); + if ( $post ) { + $focus_keyword = $this->get_post_focus_keyword( $post ); + + if ( ! empty( $focus_keyword ) ) { + $trends_url .= '#q=' . urlencode( $focus_keyword ); + } + } + + $menu_args = [ + 'parent' => self::MENU_IDENTIFIER, + 'id' => self::KEYWORD_RESEARCH_SUBMENU_IDENTIFIER, + 'title' => __( 'Keyword Research', 'wordpress-seo' ), + 'meta' => [ 'tabindex' => '0' ], + ]; + $wp_admin_bar->add_menu( $menu_args ); + + $submenu_items = [ + [ + 'id' => 'wpseo-kwresearchtraining', + 'title' => __( 'Keyword research training', 'wordpress-seo' ), + 'href' => WPSEO_Shortlinker::get( 'https://yoa.st/wp-admin-bar' ), + ], + [ + 'id' => 'wpseo-adwordsexternal', + 'title' => __( 'Google Ads', 'wordpress-seo' ), + 'href' => $adwords_url, + ], + [ + 'id' => 'wpseo-googleinsights', + 'title' => __( 'Google Trends', 'wordpress-seo' ), + 'href' => $trends_url, + ], + ]; + + foreach ( $submenu_items as $menu_item ) { + $menu_args = [ + 'parent' => self::KEYWORD_RESEARCH_SUBMENU_IDENTIFIER, + 'id' => $menu_item['id'], + 'title' => $menu_item['title'], + 'href' => $menu_item['href'], + 'meta' => [ 'target' => '_blank' ], + ]; + $wp_admin_bar->add_menu( $menu_args ); + } + } + + /** + * Adds the admin bar analysis submenu. + * + * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to. + * + * @return void + */ + protected function add_analysis_submenu( WP_Admin_Bar $wp_admin_bar ) { + try { + $url = YoastSEO()->meta->for_current_page()->canonical; + } catch ( Exception $e ) { + // This is not the type of error we can handle here. + return; + } + + $focus_keyword = ''; + + if ( ! $url ) { + return; + } + + $post = $this->get_singular_post(); + if ( $post ) { + $focus_keyword = $this->get_post_focus_keyword( $post ); + } + + $menu_args = [ + 'parent' => self::MENU_IDENTIFIER, + 'id' => self::ANALYSIS_SUBMENU_IDENTIFIER, + 'title' => __( 'Analyze this page', 'wordpress-seo' ), + 'meta' => [ 'tabindex' => '0' ], + ]; + $wp_admin_bar->add_menu( $menu_args ); + + $encoded_url = urlencode( $url ); + $submenu_items = [ + [ + 'id' => 'wpseo-inlinks', + 'title' => __( 'Check links to this URL', 'wordpress-seo' ), + 'href' => 'https://search.google.com/search-console/links/drilldown?resource_id=' . urlencode( get_option( 'siteurl' ) ) . '&type=EXTERNAL&target=' . $encoded_url . '&domain=', + ], + [ + 'id' => 'wpseo-kwdensity', + 'title' => __( 'Check Keyphrase Density', 'wordpress-seo' ), + // HTTPS not available. + 'href' => 'http://www.zippy.co.uk/keyworddensity/index.php?url=' . $encoded_url . '&keyword=' . urlencode( $focus_keyword ), + ], + [ + 'id' => 'wpseo-cache', + 'title' => __( 'Check Google Cache', 'wordpress-seo' ), + 'href' => '//webcache.googleusercontent.com/search?strip=1&q=cache:' . $encoded_url, + ], + [ + 'id' => 'wpseo-structureddata', + 'title' => __( 'Google Rich Results Test', 'wordpress-seo' ), + 'href' => 'https://search.google.com/test/rich-results?url=' . $encoded_url, + ], + [ + 'id' => 'wpseo-facebookdebug', + 'title' => __( 'Facebook Debugger', 'wordpress-seo' ), + 'href' => '//developers.facebook.com/tools/debug/?q=' . $encoded_url, + ], + [ + 'id' => 'wpseo-pinterestvalidator', + 'title' => __( 'Pinterest Rich Pins Validator', 'wordpress-seo' ), + 'href' => 'https://developers.pinterest.com/tools/url-debugger/?link=' . $encoded_url, + ], + [ + 'id' => 'wpseo-htmlvalidation', + 'title' => __( 'HTML Validator', 'wordpress-seo' ), + 'href' => '//validator.w3.org/check?uri=' . $encoded_url, + ], + [ + 'id' => 'wpseo-cssvalidation', + 'title' => __( 'CSS Validator', 'wordpress-seo' ), + 'href' => '//jigsaw.w3.org/css-validator/validator?uri=' . $encoded_url, + ], + [ + 'id' => 'wpseo-pagespeed', + 'title' => __( 'Google Page Speed Test', 'wordpress-seo' ), + 'href' => '//developers.google.com/speed/pagespeed/insights/?url=' . $encoded_url, + ], + [ + 'id' => 'wpseo-google-mobile-friendly', + 'title' => __( 'Mobile-Friendly Test', 'wordpress-seo' ), + 'href' => 'https://www.google.com/webmasters/tools/mobile-friendly/?url=' . $encoded_url, + ], + ]; + + foreach ( $submenu_items as $menu_item ) { + $menu_args = [ + 'parent' => self::ANALYSIS_SUBMENU_IDENTIFIER, + 'id' => $menu_item['id'], + 'title' => $menu_item['title'], + 'href' => $menu_item['href'], + 'meta' => [ 'target' => '_blank' ], + ]; + $wp_admin_bar->add_menu( $menu_args ); + } + } + + /** + * Adds the admin bar settings submenu. + * + * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to. + * + * @return void + */ + protected function add_settings_submenu( WP_Admin_Bar $wp_admin_bar ) { + if ( ! $this->can_manage_options() ) { + return; + } + + $admin_menu = new WPSEO_Admin_Menu( new WPSEO_Menu() ); + $submenu_pages = $admin_menu->get_submenu_pages(); + + $menu_args = [ + 'parent' => self::MENU_IDENTIFIER, + 'id' => self::SETTINGS_SUBMENU_IDENTIFIER, + 'title' => __( 'SEO Settings', 'wordpress-seo' ), + 'meta' => [ 'tabindex' => '0' ], + ]; + $wp_admin_bar->add_menu( $menu_args ); + + foreach ( $submenu_pages as $submenu_page ) { + if ( ! current_user_can( $submenu_page[3] ) ) { + continue; + } + + // Don't add the Google Search Console menu item. + if ( $submenu_page[4] === 'wpseo_search_console' ) { + continue; + } + + $id = 'wpseo-' . str_replace( '_', '-', str_replace( 'wpseo_', '', $submenu_page[4] ) ); + if ( $id === 'wpseo-dashboard' ) { + $id = 'wpseo-general'; + } + + $menu_args = [ + 'parent' => self::SETTINGS_SUBMENU_IDENTIFIER, + 'id' => $id, + 'title' => $submenu_page[2], + 'href' => admin_url( 'admin.php?page=' . urlencode( $submenu_page[4] ) ), + ]; + $wp_admin_bar->add_menu( $menu_args ); + } + } + + /** + * Adds the admin bar network settings submenu. + * + * @param WP_Admin_Bar $wp_admin_bar Admin bar instance to add the menu to. + * + * @return void + */ + protected function add_network_settings_submenu( WP_Admin_Bar $wp_admin_bar ) { + if ( ! $this->can_manage_options() ) { + return; + } + + $network_admin_menu = new WPSEO_Network_Admin_Menu( new WPSEO_Menu() ); + $submenu_pages = $network_admin_menu->get_submenu_pages(); + + $menu_args = [ + 'parent' => self::MENU_IDENTIFIER, + 'id' => self::NETWORK_SETTINGS_SUBMENU_IDENTIFIER, + 'title' => __( 'SEO Settings', 'wordpress-seo' ), + 'meta' => [ 'tabindex' => '0' ], + ]; + $wp_admin_bar->add_menu( $menu_args ); + + foreach ( $submenu_pages as $submenu_page ) { + if ( ! current_user_can( $submenu_page[3] ) ) { + continue; + } + + $id = 'wpseo-' . str_replace( '_', '-', str_replace( 'wpseo_', '', $submenu_page[4] ) ); + if ( $id === 'wpseo-dashboard' ) { + $id = 'wpseo-general'; + } + + $menu_args = [ + 'parent' => self::NETWORK_SETTINGS_SUBMENU_IDENTIFIER, + 'id' => $id, + 'title' => $submenu_page[2], + 'href' => network_admin_url( 'admin.php?page=' . urlencode( $submenu_page[4] ) ), + ]; + $wp_admin_bar->add_menu( $menu_args ); + } + } + + /** + * Gets the menu title markup. + * + * @return string Admin bar title markup. + */ + protected function get_title() { + return ''; + } + + /** + * Gets the current post if in a singular post context. + * + * @global string $pagenow Current page identifier. + * @global WP_Post|null $post Current post object, or null if none available. + * + * @return WP_Post|null Post object, or null if not in singular context. + */ + protected function get_singular_post() { + global $pagenow, $post; + + if ( ! is_singular() && ( ! is_blog_admin() || ! WPSEO_Metabox::is_post_edit( $pagenow ) ) ) { + return null; + } + + if ( ! isset( $post ) || ! is_object( $post ) || ! $post instanceof WP_Post ) { + return null; + } + + return $post; + } + + /** + * Gets the focus keyword for a given post. + * + * @param WP_Post $post Post object to get its focus keyword. + * + * @return string Focus keyword, or empty string if none available. + */ + protected function get_post_focus_keyword( $post ) { + if ( ! is_object( $post ) || ! property_exists( $post, 'ID' ) ) { + return ''; + } + + /** + * Filter: 'wpseo_use_page_analysis' Determines if the analysis should be enabled. + * + * @api bool Determines if the analysis should be enabled. + */ + if ( apply_filters( 'wpseo_use_page_analysis', true ) !== true ) { + return ''; + } + + return WPSEO_Meta::get_value( 'focuskw', $post->ID ); + } + + /** + * Gets the score for a given post. + * + * @param WP_Post $post Post object to get its score. + * + * @return string Score markup, or empty string if none available. + */ + protected function get_post_score( $post ) { + if ( ! is_object( $post ) || ! property_exists( $post, 'ID' ) ) { + return ''; + } + + if ( apply_filters( 'wpseo_use_page_analysis', true ) !== true ) { + return ''; + } + + $analysis_seo = new WPSEO_Metabox_Analysis_SEO(); + $analysis_readability = new WPSEO_Metabox_Analysis_Readability(); + + if ( $analysis_seo->is_enabled() ) { + return $this->get_score( WPSEO_Meta::get_value( 'linkdex', $post->ID ) ); + } + + if ( $analysis_readability->is_enabled() ) { + return $this->get_score( WPSEO_Meta::get_value( 'content_score', $post->ID ) ); + } + + return ''; + } + + /** + * Gets the current term if in a singular term context. + * + * @global string $pagenow Current page identifier. + * @global WP_Query $wp_query Current query object. + * @global WP_Term|null $tag Current term object, or null if none available. + * + * @return WP_Term|null Term object, or null if not in singular context. + */ + protected function get_singular_term() { + global $pagenow, $wp_query, $tag; + + if ( is_category() || is_tag() || is_tax() ) { + return $wp_query->get_queried_object(); + } + + if ( WPSEO_Taxonomy::is_term_edit( $pagenow ) && ! WPSEO_Taxonomy::is_term_overview( $pagenow ) && isset( $tag ) && is_object( $tag ) && ! is_wp_error( $tag ) ) { + return get_term( $tag->term_id ); + } + + return null; + } + + /** + * Gets the score for a given term. + * + * @param WP_Term $term Term object to get its score. + * + * @return string Score markup, or empty string if none available. + */ + protected function get_term_score( $term ) { + if ( ! is_object( $term ) || ! property_exists( $term, 'term_id' ) || ! property_exists( $term, 'taxonomy' ) ) { + return ''; + } + + $analysis_seo = new WPSEO_Metabox_Analysis_SEO(); + $analysis_readability = new WPSEO_Metabox_Analysis_Readability(); + + if ( $analysis_seo->is_enabled() ) { + return $this->get_score( WPSEO_Taxonomy_Meta::get_term_meta( $term->term_id, $term->taxonomy, 'linkdex' ) ); + } + + if ( $analysis_readability->is_enabled() ) { + return $this->get_score( WPSEO_Taxonomy_Meta::get_term_meta( $term->term_id, $term->taxonomy, 'content_score' ) ); + } + + return ''; + } + + /** + * Takes the SEO score and makes the score icon for the admin bar for it. + * + * @param int $score The 0-100 rating of the score. Can be either SEO score or content score. + * + * @return string Score markup. + */ + protected function get_score( $score ) { + $score_class = WPSEO_Utils::translate_score( $score ); + $translated_score = WPSEO_Utils::translate_score( $score, false ); + /* translators: %s expands to the SEO score. */ + $screen_reader_text = sprintf( __( 'SEO score: %s', 'wordpress-seo' ), $translated_score ); + + $score_adminbar_element = '
    ' . $screen_reader_text . '
    '; + + return $score_adminbar_element; + } + + /** + * Gets the URL to the main admin settings page. + * + * @return string Admin settings page URL. + */ + protected function get_settings_page_url() { + return self_admin_url( 'admin.php?page=' . WPSEO_Admin::PAGE_IDENTIFIER ); + } + + /** + * Gets the notification counter if in a valid context. + * + * @return string Notification counter markup, or empty string if not available. + */ + protected function get_notification_counter() { + $notification_center = Yoast_Notification_Center::get(); + $notification_count = $notification_center->get_notification_count(); + + if ( ! $notification_count ) { + return ''; + } + + /* translators: %s: number of notifications */ + $counter_screen_reader_text = sprintf( _n( '%s notification', '%s notifications', $notification_count, 'wordpress-seo' ), number_format_i18n( $notification_count ) ); + + return sprintf( '
    %s
    ', $notification_count, $counter_screen_reader_text ); + } + + /** + * Gets the notification popup if in a valid context. + * + * @return string Notification popup markup, or empty string if not available. + */ + protected function get_notification_popup() { + $notification_center = Yoast_Notification_Center::get(); + $new_notifications = $notification_center->get_new_notifications(); + $new_notifications_count = count( $new_notifications ); + + if ( ! $new_notifications_count ) { + return ''; + } + + $notification = sprintf( + _n( + 'There is a new notification.', + 'There are new notifications.', + $new_notifications_count, + 'wordpress-seo' + ), + $new_notifications_count + ); + + return '
    ' . $notification . '
    '; + } + + /** + * Checks whether the current user can manage options in the current context. + * + * @return bool True if capabilities are sufficient, false otherwise. + */ + protected function can_manage_options() { + return is_network_admin() && current_user_can( 'wpseo_manage_network_options' ) || ! is_network_admin() && WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-content-images.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-content-images.php new file mode 100644 index 00000000..fa63e4b5 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-content-images.php @@ -0,0 +1,111 @@ +get_images_from_content( $this->get_post_content( $post_id, $post ) ); + } + + /** + * Grabs the images from the content. + * + * @param string $content The post content string. + * + * @return array An array of image URLs. + */ + public function get_images_from_content( $content ) { + if ( ! is_string( $content ) ) { + return []; + } + + $content_images = $this->get_img_tags_from_content( $content ); + $images = array_map( [ $this, 'get_img_tag_source' ], $content_images ); + $images = array_filter( $images ); + $images = array_unique( $images ); + $images = array_values( $images ); // Reset the array keys. + + return $images; + } + + /** + * Gets the image tags from a given content string. + * + * @param string $content The content to search for image tags. + * + * @return array An array of `` tags. + */ + private function get_img_tags_from_content( $content ) { + if ( strpos( $content, ']+>`', $content, $matches ); + if ( isset( $matches[0] ) ) { + return $matches[0]; + } + + return []; + } + + /** + * Retrieves the image URL from an image tag. + * + * @param string $image Image HTML element. + * + * @return string|bool The image URL on success, false on failure. + */ + private function get_img_tag_source( $image ) { + preg_match( '`src=(["\'])(.*?)\1`', $image, $matches ); + if ( isset( $matches[2] ) ) { + return $matches[2]; + } + return false; + } + + /** + * Retrieves the post content we want to work with. + * + * @param int $post_id The post ID. + * @param WP_Post|array|null $post The post. + * + * @return string The content of the supplied post. + */ + private function get_post_content( $post_id, $post ) { + if ( $post === null ) { + $post = get_post( $post_id ); + } + + if ( $post === null ) { + return ''; + } + + /** + * Filter: 'wpseo_pre_analysis_post_content' - Allow filtering the content before analysis. + * + * @api string $post_content The Post content string. + */ + $content = apply_filters( 'wpseo_pre_analysis_post_content', $post->post_content, $post ); + + if ( ! is_string( $content ) ) { + $content = ''; + } + + return $content; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-custom-fields.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-custom-fields.php new file mode 100644 index 00000000..46abc977 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-custom-fields.php @@ -0,0 +1,67 @@ +postmeta + WHERE meta_key NOT BETWEEN '_' AND '_z' AND SUBSTRING(meta_key, 1, 1) != '_' + LIMIT %d"; + $fields = $wpdb->get_col( $wpdb->prepare( $sql, $limit ) ); + + if ( is_array( $fields ) ) { + self::$custom_fields = array_map( [ 'WPSEO_Custom_Fields', 'add_custom_field_prefix' ], $fields ); + } + + return self::$custom_fields; + } + + /** + * Adds the cf_ prefix to a field. + * + * @param string $field The field to prefix. + * + * @return string The prefixed field. + */ + private static function add_custom_field_prefix( $field ) { + return 'cf_' . $field; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-custom-taxonomies.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-custom-taxonomies.php new file mode 100644 index 00000000..40b8ba23 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-custom-taxonomies.php @@ -0,0 +1,72 @@ + true, + '_builtin' => false, + ]; + $custom_taxonomies = get_taxonomies( $args, 'names', 'and' ); + + if ( is_array( $custom_taxonomies ) ) { + foreach ( $custom_taxonomies as $custom_taxonomy ) { + array_push( + self::$custom_taxonomies, + self::add_custom_taxonomies_prefix( $custom_taxonomy ), + self::add_custom_taxonomies_description_prefix( $custom_taxonomy ) + ); + } + } + + return self::$custom_taxonomies; + } + + /** + * Adds the ct_ prefix to a taxonomy. + * + * @param string $taxonomy The taxonomy to prefix. + * + * @return string The prefixed taxonomy. + */ + private static function add_custom_taxonomies_prefix( $taxonomy ) { + return 'ct_' . $taxonomy; + } + + /** + * Adds the ct_desc_ prefix to a taxonomy. + * + * @param string $taxonomy The taxonomy to prefix. + * + * @return string The prefixed taxonomy. + */ + private static function add_custom_taxonomies_description_prefix( $taxonomy ) { + return 'ct_desc_' . $taxonomy; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-features.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-features.php index cba0c5b5..11f406aa 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-wpseo-features.php +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-features.php @@ -7,24 +7,34 @@ /** * Class containing method for WPSEO Features. + * + * @deprecated 16.0 */ class WPSEO_Features { /** * Checks if the premium constant exists to make sure if plugin is the premium one. * + * @deprecated 16.0 + * @codeCoverageIgnore + * * @return bool */ public function is_premium() { - return ( defined( 'WPSEO_PREMIUM_FILE' ) ); + _deprecated_function( __FUNCTION__, '16.0', 'YoastSEO()->helpers->product->is_premium' ); + return YoastSEO()->helpers->product->is_premium(); } /** * Checks if using the free version of the plugin. * + * @deprecated 16.0 + * @codeCoverageIgnore + * * @return bool */ public function is_free() { - return ! $this->is_premium(); + _deprecated_function( __FUNCTION__, '16.0', 'YoastSEO()->helpers->product->is_premium' ); + return true; } } diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-image-utils.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-image-utils.php new file mode 100644 index 00000000..ba4f79f8 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-image-utils.php @@ -0,0 +1,484 @@ + $maximum ) ) { + return false; + } + } + + return true; + } + + /** + * Gets the post's first usable content image. Null if none is available. + * + * @param int|null $post_id The post id. + * + * @return string|null The image URL. + */ + public static function get_first_usable_content_image_for_post( $post_id = null ) { + $post = get_post( $post_id ); + + // We know get_post() returns the post or null. + if ( ! $post ) { + return null; + } + + $image_finder = new WPSEO_Content_Images(); + $images = $image_finder->get_images( $post->ID, $post ); + + return self::get_first_image( $images ); + } + + /** + * Gets the term's first usable content image. Null if none is available. + * + * @param int $term_id The term id. + * + * @return string|null The image URL. + */ + public static function get_first_content_image_for_term( $term_id ) { + $term_description = term_description( $term_id ); + + // We know term_description() returns a string which may be empty. + if ( $term_description === '' ) { + return null; + } + + $image_finder = new WPSEO_Content_Images(); + $images = $image_finder->get_images_from_content( $term_description ); + + return self::get_first_image( $images ); + } + + /** + * Retrieves an attachment ID for an image uploaded in the settings. + * + * Due to self::get_attachment_by_url returning 0 instead of false. + * 0 is also a possibility when no ID is available. + * + * @param string $setting The setting the image is stored in. + * + * @return int|bool The attachment id, or false or 0 if no ID is available. + */ + public static function get_attachment_id_from_settings( $setting ) { + $image_id = WPSEO_Options::get( $setting . '_id', false ); + if ( ! $image_id ) { + $image = WPSEO_Options::get( $setting, false ); + if ( $image ) { + // There is not an option to put a URL in an image field in the settings anymore, only to upload it through the media manager. + // This means an attachment always exists, so doing this is only needed once. + $image_id = self::get_attachment_by_url( $image ); + WPSEO_Options::set( $setting . '_id', $image_id ); + } + } + + return $image_id; + } + + /** + * Retrieves the first possible image url from an array of images. + * + * @param array $images The array to extract image url from. + * + * @return string|null The extracted image url when found, null when not found. + */ + protected static function get_first_image( $images ) { + if ( ! is_array( $images ) ) { + return null; + } + + $images = array_filter( $images ); + if ( empty( $images ) ) { + return null; + } + + return reset( $images ); + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-installation.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-installation.php index f9459273..662f445e 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-wpseo-installation.php +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-installation.php @@ -19,7 +19,7 @@ class WPSEO_Installation { $is_first_install = $this->is_first_install(); if ( $is_first_install && WPSEO_Utils::is_api_available() ) { - add_action( 'wpseo_activate', array( $this, 'set_first_install_options' ) ); + add_action( 'wpseo_activate', [ $this, 'set_first_install_options' ] ); } } diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-meta.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-meta.php index c1353d37..fc1f6262 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-wpseo-meta.php +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-meta.php @@ -6,19 +6,23 @@ * @since 1.5.0 */ +use Yoast\WP\SEO\Config\Schema_Types; +use Yoast\WP\SEO\Helpers\Schema\Article_Helper; +use Yoast\WP\SEO\Repositories\Indexable_Repository; + /** * This class implements defaults and value validation for all WPSEO Post Meta values. * * Some guidelines: * - To update a meta value, you can just use update_post_meta() with the full (prefixed) meta key - * or the convenience method WPSEO_Meta::set_value() with the internal key. - * All updates will be automatically validated. - * Meta values will only be saved to the database if they are *not* the same as the default to - * keep database load low. + * or the convenience method WPSEO_Meta::set_value() with the internal key. + * All updates will be automatically validated. + * Meta values will only be saved to the database if they are *not* the same as the default to + * keep database load low. * - To retrieve a WPSEO meta value, you **must** use WPSEO_Meta::get_value() which will always return a - * string value, either the saved value or the default. - * This method can also retrieve a complete set of WPSEO meta values for one specific post, see - * the method documentation for the parameters. + * string value, either the saved value or the default. + * This method can also retrieve a complete set of WPSEO meta values for one specific post, see + * the method documentation for the parameters. * * {@internal Unfortunately there isn't a filter available to hook into before returning the results * for get_post_meta(), get_post_custom() and the likes. That would have been the @@ -31,104 +35,88 @@ class WPSEO_Meta { /** - * @var string Prefix for all WPSEO meta values in the database - * @static + * Prefix for all WPSEO meta values in the database. * * {@internal If at any point this would change, quite apart from an upgrade routine, * this also will need to be changed in the wpml-config.xml file.}} + * + * @var string */ public static $meta_prefix = '_yoast_wpseo_'; - /** - * @var string Prefix for all WPSEO meta value form field names and ids - * @static + * Prefix for all WPSEO meta value form field names and ids. + * + * @var string */ public static $form_prefix = 'yoast_wpseo_'; - /** - * @var int Allowed length of the meta description. - * @static + * Allowed length of the meta description. + * + * @var int */ public static $meta_length = 156; - /** - * @var string Reason the meta description is not the default length. - * @static + * Reason the meta description is not the default length. + * + * @var string */ public static $meta_length_reason = ''; - /** - * @var array $meta_fields Meta box field definitions for the meta box form - * Array format: - * (required) 'type' => (string) field type. i.e. text / textarea / checkbox / - * radio / select / multiselect / upload / snippetpreview etc - * (required) 'title' => (string) table row title - * (recommended) 'default_value' => (string|array) default value for the field - * IMPORTANT: - * - if the field has options, the default has to be the - * key of one of the options - * - if the field is a text field, the default **has** to be - * an empty string as otherwise the user can't save - * an empty value/delete the meta value - * - if the field is a checkbox, the only valid values - * are 'on' or 'off' - * (semi-required) 'options' => (array) options for used with (multi-)select and radio - * fields, required if that's the field type - * key = (string) value which will be saved to db - * value = (string) text label for the option - * (optional) 'autocomplete' => (bool) whether autocomplete is on for text fields, - * defaults to true - * (optional) 'class' => (string) classname(s) to add to the actual tag - * (optional) 'description' => (string) description to show underneath the field - * (optional) 'expl' => (string) label for a checkbox - * (optional) 'help' => (string) help text to show on mouse over ? image - * (optional) 'rows' => (int) number of rows for a textarea, defaults to 3 - * - * (optional) 'placeholder' => (string) Currently only used by add-on plugins - * (optional) 'serialized' => (bool) whether the value is expected to be serialized, - * i.e. an array or object, defaults to false - * Currently only used by add-on plugins - * - * @static + * Meta box field definitions for the meta box form. * * {@internal * - Titles, help texts, description text and option labels are added via a translate_meta_boxes() method - * in the relevant child classes (WPSEO_Metabox and WPSEO_Social_admin) as they are only needed there. + * in the relevant child classes (WPSEO_Metabox and WPSEO_Social_admin) as they are only needed there. * - Beware: even though the meta keys are divided into subsets, they still have to be uniquely named!}} + * + * @var array + * Array format: + * (required) 'type' => (string) field type. i.e. text / textarea / checkbox / + * radio / select / multiselect / upload etc. + * (required) 'title' => (string) table row title. + * (recommended) 'default_value' => (string|array) default value for the field. + * IMPORTANT: + * - if the field has options, the default has to be the + * key of one of the options. + * - if the field is a text field, the default **has** to be + * an empty string as otherwise the user can't save + * an empty value/delete the meta value. + * - if the field is a checkbox, the only valid values + * are 'on' or 'off'. + * (semi-required) 'options' => (array) options for used with (multi-)select and radio + * fields, required if that's the field type. + * key = (string) value which will be saved to db. + * value = (string) text label for the option. + * (optional) 'autocomplete' => (bool) whether autocomplete is on for text fields, + * defaults to true. + * (optional) 'class' => (string) classname(s) to add to the actual tag. + * (optional) 'description' => (string) description to show underneath the field. + * (optional) 'expl' => (string) label for a checkbox. + * (optional) 'help' => (string) help text to show on mouse over ? image. + * (optional) 'rows' => (int) number of rows for a textarea, defaults to 3. + * (optional) 'placeholder' => (string) Currently only used by add-on plugins. + * (optional) 'serialized' => (bool) whether the value is expected to be serialized, + * i.e. an array or object, defaults to false. + * Currently only used by add-on plugins. */ - public static $meta_fields = array( - 'general' => array( - 'snippetpreview' => array( - 'type' => 'snippetpreview', - 'title' => '', // Translation added later. - 'help' => '', // Translation added later. - 'help-button' => '', // Translation added later. - ), - 'focuskw_text_input' => array( - 'type' => 'focuskeyword', - 'title' => '', // Translation added later. - 'default_value' => '', - 'autocomplete' => false, - 'help' => '', // Translation added later. - 'description' => '
    ', - 'help-button' => '', // Translation added later. - ), - 'focuskw' => array( + public static $meta_fields = [ + 'general' => [ + 'focuskw' => [ 'type' => 'hidden', 'title' => '', - ), - 'title' => array( + ], + 'title' => [ 'type' => 'hidden', 'title' => '', // Translation added later. 'default_value' => '', 'description' => '', // Translation added later. 'help' => '', // Translation added later. - ), - 'metadesc' => array( + ], + 'metadesc' => [ 'type' => 'hidden', 'title' => '', // Translation added later. 'default_value' => '', @@ -136,209 +124,216 @@ class WPSEO_Meta { 'rows' => 2, 'description' => '', // Translation added later. 'help' => '', // Translation added later. - ), - 'linkdex' => array( + ], + 'linkdex' => [ 'type' => 'hidden', 'title' => 'linkdex', 'default_value' => '0', 'description' => '', - ), - 'content_score' => array( + ], + 'content_score' => [ 'type' => 'hidden', 'title' => 'content_score', 'default_value' => '0', 'description' => '', - ), - 'pageanalysis' => array( - 'type' => 'pageanalysis', - 'title' => '', // Translation added later. - 'help' => '', // Translation added later. - 'help-button' => '', // Translation added later. - ), - ), - 'advanced' => array( - 'meta-robots-noindex' => array( - 'type' => 'select', + ], + 'is_cornerstone' => [ + 'type' => 'hidden', + 'title' => 'is_cornerstone', + 'default_value' => 'false', + 'description' => '', + ], + ], + 'advanced' => [ + 'meta-robots-noindex' => [ + 'type' => 'hidden', 'title' => '', // Translation added later. 'default_value' => '0', // = post-type default. - 'options' => array( + 'options' => [ '0' => '', // Post type default - translation added later. '2' => '', // Index - translation added later. '1' => '', // No-index - translation added later. - ), - ), - 'meta-robots-nofollow' => array( - 'type' => 'radio', + ], + ], + 'meta-robots-nofollow' => [ + 'type' => 'hidden', 'title' => '', // Translation added later. 'default_value' => '0', // = follow. - 'options' => array( + 'options' => [ '0' => '', // Follow - translation added later. '1' => '', // No-follow - translation added later. - ), - ), - 'meta-robots-adv' => array( - 'type' => 'multiselect', + ], + ], + 'meta-robots-adv' => [ + 'type' => 'hidden', 'title' => '', // Translation added later. - 'default_value' => '-', // = site-wide default. + 'default_value' => '', 'description' => '', // Translation added later. - 'options' => array( - '-' => '', // Site-wide default - translation added later. - 'none' => '', // Translation added later. + 'options' => [ 'noimageindex' => '', // Translation added later. 'noarchive' => '', // Translation added later. 'nosnippet' => '', // Translation added later. - ), - ), - 'bctitle' => array( - 'type' => 'text', + ], + ], + 'bctitle' => [ + 'type' => 'hidden', 'title' => '', // Translation added later. 'default_value' => '', 'description' => '', // Translation added later. - ), - 'canonical' => array( - 'type' => 'text', + ], + 'canonical' => [ + 'type' => 'hidden', 'title' => '', // Translation added later. 'default_value' => '', 'description' => '', // Translation added later. - ), - 'redirect' => array( - 'type' => 'text', + ], + 'redirect' => [ + 'type' => 'url', 'title' => '', // Translation added later. 'default_value' => '', 'description' => '', // Translation added later. - ), - ), - 'social' => array(), - /* Fields we should validate & save, but not show on any form */ - 'non_form' => array( - 'linkdex' => array( + ], + ], + 'social' => [], + 'schema' => [ + 'schema_page_type' => [ + 'type' => 'hidden', + 'title' => '', + 'options' => Schema_Types::PAGE_TYPES, + ], + 'schema_article_type' => [ + 'type' => 'hidden', + 'title' => '', + 'hide_on_pages' => true, + 'options' => Schema_Types::ARTICLE_TYPES, + ], + ], + /* Fields we should validate & save, but not show on any form. */ + 'non_form' => [ + 'linkdex' => [ 'type' => null, 'default_value' => '0', - ), - ), - ); - + ], + 'zapier_trigger_sent' => [ + 'type' => null, + 'default_value' => '0', + ], + ], + ]; /** - * @var array Helper property - reverse index of the definition array - * Format: [full meta key including prefix] => array - * ['subset'] => (string) primary index - * ['key'] => (string) internal key - * @static + * Helper property - reverse index of the definition array. + * + * Format: [full meta key including prefix] => array + * ['subset'] => (string) primary index + * ['key'] => (string) internal key + * + * @var array */ - public static $fields_index = array(); - + public static $fields_index = []; /** - * @var array Helper property - array containing only the defaults in the format: - * [full meta key including prefix] => (string) default value - * @static + * Helper property - array containing only the defaults in the format: + * [full meta key including prefix] => (string) default value + * + * @var array */ - public static $defaults = array(); + public static $defaults = []; /** - * @var array Helper property to define the social network meta field definitions - networks - * @static + * Helper property to define the social network meta field definitions - networks. + * + * @var array */ - private static $social_networks = array( + private static $social_networks = [ 'opengraph' => 'opengraph', 'twitter' => 'twitter', - ); + ]; /** - * @var array Helper property to define the social network meta field definitions - fields and their type - * @static - */ - private static $social_fields = array( - 'title' => 'text', - 'description' => 'textarea', - 'image' => 'upload', - ); - - - /** - * Register our actions and filters + * Helper property to define the social network meta field definitions - fields and their type. + * + * @var array + */ + private static $social_fields = [ + 'title' => 'hidden', + 'description' => 'hidden', + 'image' => 'hidden', + 'image-id' => 'hidden', + ]; + + /** + * Register our actions and filters. * - * @static * @return void */ public static function init() { - foreach ( self::$social_networks as $option => $network ) { - if ( true === WPSEO_Options::get( $option, false ) ) { + if ( WPSEO_Options::get( $option, false ) === true ) { foreach ( self::$social_fields as $box => $type ) { - self::$meta_fields['social'][ $network . '-' . $box ] = array( + self::$meta_fields['social'][ $network . '-' . $box ] = [ 'type' => $type, 'title' => '', // Translation added later. 'default_value' => '', 'description' => '', // Translation added later. - ); + ]; } } } unset( $option, $network, $box, $type ); /** - * Allow add-on plugins to register their meta fields for management by this class - * add_filter() calls must be made before plugins_loaded prio 14 + * Allow add-on plugins to register their meta fields for management by this class. + * Calls to add_filter() must be made before plugins_loaded prio 14. */ - $extra_fields = apply_filters( 'add_extra_wpseo_meta_fields', array() ); + $extra_fields = apply_filters( 'add_extra_wpseo_meta_fields', [] ); if ( is_array( $extra_fields ) ) { self::$meta_fields = self::array_merge_recursive_distinct( $extra_fields, self::$meta_fields ); } unset( $extra_fields ); - $register = function_exists( 'register_meta' ); - foreach ( self::$meta_fields as $subset => $field_group ) { foreach ( $field_group as $key => $field_def ) { - if ( $field_def['type'] !== 'snippetpreview' ) { - if ( $register === true ) { - register_meta( 'post', self::$meta_prefix . $key, array( - 'sanitize_callback' => array( __CLASS__, 'sanitize_post_meta' ), - ) ); - } - else { - add_filter( 'sanitize_post_meta_' . self::$meta_prefix . $key, array( __CLASS__, 'sanitize_post_meta' ), 10, 2 ); - } - // Set the $fields_index property for efficiency. - self::$fields_index[ self::$meta_prefix . $key ] = array( - 'subset' => $subset, - 'key' => $key, - ); + register_meta( + 'post', + self::$meta_prefix . $key, + [ 'sanitize_callback' => [ __CLASS__, 'sanitize_post_meta' ] ] + ); - // Set the $defaults property for efficiency. - if ( isset( $field_def['default_value'] ) ) { - self::$defaults[ self::$meta_prefix . $key ] = $field_def['default_value']; - } - else { - // Meta will always be a string, so let's make the meta meta default also a string. - self::$defaults[ self::$meta_prefix . $key ] = ''; - } + // Set the $fields_index property for efficiency. + self::$fields_index[ self::$meta_prefix . $key ] = [ + 'subset' => $subset, + 'key' => $key, + ]; + + // Set the $defaults property for efficiency. + if ( isset( $field_def['default_value'] ) ) { + self::$defaults[ self::$meta_prefix . $key ] = $field_def['default_value']; + } + else { + // Meta will always be a string, so let's make the meta meta default also a string. + self::$defaults[ self::$meta_prefix . $key ] = ''; } } } - unset( $subset, $field_group, $key, $field_def, $register ); + unset( $subset, $field_group, $key, $field_def ); - add_filter( 'update_post_metadata', array( __CLASS__, 'remove_meta_if_default' ), 10, 5 ); - add_filter( 'add_post_metadata', array( __CLASS__, 'dont_save_meta_if_default' ), 10, 4 ); + add_filter( 'update_post_metadata', [ __CLASS__, 'remove_meta_if_default' ], 10, 5 ); + add_filter( 'add_post_metadata', [ __CLASS__, 'dont_save_meta_if_default' ], 10, 4 ); } - /** * Retrieve the meta box form field definitions for the given tab and post type. * - * @static + * @param string $tab Tab for which to retrieve the field definitions. + * @param string $post_type Post type of the current post. * - * @param string $tab Tab for which to retrieve the field definitions. - * @param string $post_type Post type of the current post. - * - * @return array Array containing the meta box field definitions + * @return array Array containing the meta box field definitions. */ public static function get_meta_field_defs( $tab, $post_type = 'post' ) { if ( ! isset( self::$meta_fields[ $tab ] ) ) { - return array(); + return []; } $field_defs = self::$meta_fields[ $tab ]; @@ -346,31 +341,14 @@ class WPSEO_Meta { switch ( $tab ) { case 'non-form': // Prevent non-form fields from being passed to forms. - $field_defs = array(); + $field_defs = []; break; - - case 'general': - /** - * Filter the WPSEO metabox form field definitions for the general tab, backward compatibility - * - * @deprecated 1.5.0 - * @deprecated use the 'wpseo_metabox_entries_general' filter instead - * @see WPSEO_Meta::get_meta_field_defs() - * - * @param array $field_defs Metabox orm definitions. - * - * @return array - */ - $field_defs = apply_filters_deprecated( 'wpseo_metabox_entries', array( $field_defs ), 'WPSEO 7.0','wpseo_metabox_entries_general' ); - break; - - case 'advanced': global $post; if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) && WPSEO_Options::get( 'disableadvanced_meta' ) ) { - return array(); + return []; } $post_type = ''; @@ -381,6 +359,10 @@ class WPSEO_Meta { $post_type = sanitize_text_field( $_GET['post_type'] ); } + if ( $post_type === '' ) { + return []; + } + /* Adjust the no-index text strings based on the post type. */ $post_type_object = get_post_type_object( $post_type ); @@ -388,14 +370,7 @@ class WPSEO_Meta { $field_defs['meta-robots-noindex']['options']['0'] = sprintf( $field_defs['meta-robots-noindex']['options']['0'], ( ( WPSEO_Options::get( 'noindex-' . $post_type, false ) === true ) ? $field_defs['meta-robots-noindex']['options']['1'] : $field_defs['meta-robots-noindex']['options']['2'] ), $post_type_object->label ); $field_defs['meta-robots-nofollow']['title'] = sprintf( $field_defs['meta-robots-nofollow']['title'], $post_type_object->labels->singular_name ); - /* Adjust the robots advanced 'site-wide default' text string based on those settings */ - $robots_adv = __( 'None', 'wordpress-seo' ); - - $field_defs['meta-robots-adv']['options']['-'] = sprintf( $field_defs['meta-robots-adv']['options']['-'], $robots_adv ); - unset( $robots_adv ); - - - /* Don't show the breadcrumb title field if breadcrumbs aren't enabled */ + /* Don't show the breadcrumb title field if breadcrumbs aren't enabled. */ if ( WPSEO_Options::get( 'breadcrumbs-enable', false ) !== true && ! current_theme_supports( 'yoast-seo-breadcrumbs' ) ) { unset( $field_defs['bctitle'] ); } @@ -406,31 +381,44 @@ class WPSEO_Meta { unset( $field_defs['redirect'] ); } break; + + case 'schema': + if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) && WPSEO_Options::get( 'disableadvanced_meta' ) ) { + return []; + } + + $field_defs['schema_page_type']['default'] = WPSEO_Options::get( 'schema-page-type-' . $post_type ); + + $article_helper = new Article_Helper(); + if ( $post_type !== 'page' && $article_helper->is_author_supported( $post_type ) ) { + $field_defs['schema_article_type']['default'] = WPSEO_Options::get( 'schema-article-type-' . $post_type ); + } + else { + unset( $field_defs['schema_article_type'] ); + } + + break; } /** - * Filter the WPSEO metabox form field definitions for a tab - * {tab} can be 'general', 'advanced' or 'social' + * Filter the WPSEO metabox form field definitions for a tab. + * {tab} can be 'general', 'advanced' or 'social'. * - * @param array $field_defs Metabox form definitions. - * @param string $post_type Post type of the post the metabox is for, defaults to 'post'. + * @param array $field_defs Metabox form field definitions. + * @param string $post_type Post type of the post the metabox is for, defaults to 'post'. * * @return array */ - return apply_filters( 'wpseo_metabox_entries_' . $tab, $field_defs, $post_type ); } - /** - * Validate the post meta values + * Validate the post meta values. * - * @static + * @param mixed $meta_value The new value. + * @param string $meta_key The full meta key (including prefix). * - * @param mixed $meta_value The new value. - * @param string $meta_key The full meta key (including prefix). - * - * @return string Validated meta value + * @return string Validated meta value. */ public static function sanitize_post_meta( $meta_value, $meta_key ) { $field_def = self::$meta_fields[ self::$fields_index[ $meta_key ]['subset'] ][ self::$fields_index[ $meta_key ]['key'] ]; @@ -446,7 +434,7 @@ class WPSEO_Meta { case ( $field_def['type'] === 'checkbox' ): // Only allow value if it's one of the predefined options. - if ( in_array( $meta_value, array( 'on', 'off' ), true ) ) { + if ( in_array( $meta_value, [ 'on', 'off' ], true ) ) { $clean = $meta_value; } break; @@ -460,13 +448,12 @@ class WPSEO_Meta { break; - case ( $field_def['type'] === 'multiselect' && $meta_key === self::$meta_prefix . 'meta-robots-adv' ): + case ( $field_def['type'] === 'hidden' && $meta_key === self::$meta_prefix . 'meta-robots-adv' ): $clean = self::validate_meta_robots_adv( $meta_value ); break; - case ( $field_def['type'] === 'text' && $meta_key === self::$meta_prefix . 'canonical' ): - case ( $field_def['type'] === 'text' && $meta_key === self::$meta_prefix . 'redirect' ): + case ( $field_def['type'] === 'url' || $meta_key === self::$meta_prefix . 'canonical' ): // Validate as url(-part). $url = WPSEO_Utils::sanitize_url( $meta_value ); if ( $url !== '' ) { @@ -475,25 +462,43 @@ class WPSEO_Meta { break; - case ( $field_def['type'] === 'upload' && in_array( $meta_key, array( self::$meta_prefix . 'opengraph-image', self::$meta_prefix . 'twitter-image' ), true ) ): + case ( $field_def['type'] === 'upload' && in_array( $meta_key, [ self::$meta_prefix . 'opengraph-image', self::$meta_prefix . 'twitter-image' ], true ) ): // Validate as url. - $url = WPSEO_Utils::sanitize_url( $meta_value, array( 'http', 'https', 'ftp', 'ftps' ) ); + $url = WPSEO_Utils::sanitize_url( $meta_value, [ 'http', 'https', 'ftp', 'ftps' ] ); if ( $url !== '' ) { $clean = $url; } break; + case ( $field_def['type'] === 'hidden' && $meta_key === self::$meta_prefix . 'is_cornerstone' ): + $clean = $meta_value; + + /* + * This used to be a checkbox, then became a hidden input. + * To make sure the value remains consistent, we cast 'true' to '1'. + */ + if ( $meta_value === 'true' ) { + $clean = '1'; + } + break; + + case ( $field_def['type'] === 'hidden' && isset( $field_def['options'] ) ): + // Only allow value if it's one of the predefined options. + if ( isset( $field_def['options'][ $meta_value ] ) ) { + $clean = $meta_value; + } + break; case ( $field_def['type'] === 'textarea' ): if ( is_string( $meta_value ) ) { // Remove line breaks and tabs. - // @todo [JRF => Yoast] verify that line breaks and the likes aren't allowed/recommended in meta header fields. - $meta_value = str_replace( array( "\n", "\r", "\t", ' ' ), ' ', $meta_value ); + // @todo [JRF => Yoast] Verify that line breaks and the likes aren't allowed/recommended in meta header fields. + $meta_value = str_replace( [ "\n", "\r", "\t", ' ' ], ' ', $meta_value ); $clean = WPSEO_Utils::sanitize_text_field( trim( $meta_value ) ); } break; - case ( 'multiselect' === $field_def['type'] ): + case ( $field_def['type'] === 'multiselect' ): $clean = $meta_value; break; @@ -504,18 +509,6 @@ class WPSEO_Meta { $clean = WPSEO_Utils::sanitize_text_field( trim( $meta_value ) ); } - if ( $meta_key === self::$meta_prefix . 'focuskw' ) { - $clean = str_replace( array( - '<', - '>', - '"', - '`', - '<', - '>', - '"', - '`', - ), '', $clean ); - } break; } @@ -524,17 +517,14 @@ class WPSEO_Meta { return $clean; } - /** - * Validate a meta-robots-adv meta value + * Validate a meta-robots-adv meta value. * - * @todo [JRF => Yoast] Verify that this logic for the prioritisation is correct + * @todo [JRF => Yoast] Verify that this logic for the prioritisation is correct. * - * @static + * @param array|string $meta_value The value to validate. * - * @param array|string $meta_value The value to validate. - * - * @return string Clean value + * @return string Clean value. */ public static function validate_meta_robots_adv( $meta_value ) { $clean = self::$meta_fields['advanced']['meta-robots-adv']['default_value']; @@ -544,52 +534,39 @@ class WPSEO_Meta { $meta_value = explode( ',', $meta_value ); } - if ( is_array( $meta_value ) && $meta_value !== array() ) { + if ( is_array( $meta_value ) && $meta_value !== [] ) { $meta_value = array_map( 'trim', $meta_value ); - if ( in_array( 'none', $meta_value, true ) ) { - // None is one of the selected values, takes priority over everything else. - $clean = 'none'; - } - elseif ( in_array( '-', $meta_value, true ) ) { - // Site-wide defaults is one of the selected values, takes priority over individual selected entries. - $clean = '-'; - } - else { - // Individual selected entries. - $cleaning = array(); - foreach ( $meta_value as $value ) { - if ( isset( $options[ $value ] ) ) { - $cleaning[] = $value; - } + // Individual selected entries. + $cleaning = []; + foreach ( $meta_value as $value ) { + if ( isset( $options[ $value ] ) ) { + $cleaning[] = $value; } + } - if ( $cleaning !== array() ) { - $clean = implode( ',', $cleaning ); - } - unset( $cleaning, $value ); + if ( $cleaning !== [] ) { + $clean = implode( ',', $cleaning ); } + unset( $cleaning, $value ); } return $clean; } - /** - * Prevent saving of default values and remove potential old value from the database if replaced by a default + * Prevent saving of default values and remove potential old value from the database if replaced by a default. * - * @static + * @param bool $check The current status to allow updating metadata for the given type. + * @param int $object_id ID of the current object for which the meta is being updated. + * @param string $meta_key The full meta key (including prefix). + * @param string $meta_value New meta value. + * @param string $prev_value The old meta value. * - * @param bool $check The current status to allow updating metadata for the given type. - * @param int $object_id ID of the current object for which the meta is being updated. - * @param string $meta_key The full meta key (including prefix). - * @param string $meta_value New meta value. - * @param string $prev_value The old meta value. - * - * @return null|bool true = stop saving, null = continue saving + * @return bool|null True = stop saving, null = continue saving. */ public static function remove_meta_if_default( $check, $object_id, $meta_key, $meta_value, $prev_value = '' ) { - /* If it's one of our meta fields, check against default */ + /* If it's one of our meta fields, check against default. */ if ( isset( self::$fields_index[ $meta_key ] ) && self::meta_value_is_default( $meta_key, $meta_value ) === true ) { if ( $prev_value !== '' ) { delete_post_meta( $object_id, $meta_key, $prev_value ); @@ -604,21 +581,18 @@ class WPSEO_Meta { return $check; // Go on with the normal execution (update) in meta.php. } - /** - * Prevent adding of default values to the database + * Prevent adding of default values to the database. * - * @static + * @param bool $check The current status to allow adding metadata for the given type. + * @param int $object_id ID of the current object for which the meta is being added. + * @param string $meta_key The full meta key (including prefix). + * @param string $meta_value New meta value. * - * @param bool $check The current status to allow adding metadata for the given type. - * @param int $object_id ID of the current object for which the meta is being added. - * @param string $meta_key The full meta key (including prefix). - * @param string $meta_value New meta value. - * - * @return null|bool true = stop saving, null = continue saving + * @return bool|null True = stop saving, null = continue saving. */ public static function dont_save_meta_if_default( $check, $object_id, $meta_key, $meta_value ) { - /* If it's one of our meta fields, check against default */ + /* If it's one of our meta fields, check against default. */ if ( isset( self::$fields_index[ $meta_key ] ) && self::meta_value_is_default( $meta_key, $meta_value ) === true ) { return true; // Stop saving the value. } @@ -626,14 +600,11 @@ class WPSEO_Meta { return $check; // Go on with the normal execution (add) in meta.php. } - /** * Is the given meta value the same as the default value ? * - * @static - * - * @param string $meta_key The full meta key (including prefix). - * @param mixed $meta_value The value to check. + * @param string $meta_key The full meta key (including prefix). + * @param mixed $meta_value The value to check. * * @return bool */ @@ -641,27 +612,25 @@ class WPSEO_Meta { return ( isset( self::$defaults[ $meta_key ] ) && $meta_value === self::$defaults[ $meta_key ] ); } - /** - * Get a custom post meta value - * Returns the default value if the meta value has not been set + * Get a custom post meta value. + * + * Returns the default value if the meta value has not been set. * * {@internal Unfortunately there isn't a filter available to hook into before returning * the results for get_post_meta(), get_post_custom() and the likes. That * would have been the preferred solution.}} * - * @static + * @param string $key Internal key of the value to get (without prefix). + * @param int $postid Post ID of the post to get the value for. * - * @param string $key Internal key of the value to get (without prefix). - * @param int $postid Post ID of the post to get the value for. - * - * @return string All 'normal' values returned from get_post_meta() are strings. - * Objects and arrays are possible, but not used by this plugin - * and therefore discarted (except when the special 'serialized' field def - * value is set to true - only used by add-on plugins for now). - * Will return the default value if no value was found.. - * Will return empty string if no default was found (not one of our keys) or - * if the post does not exist. + * @return string All 'normal' values returned from get_post_meta() are strings. + * Objects and arrays are possible, but not used by this plugin + * and therefore discarted (except when the special 'serialized' field def + * value is set to true - only used by add-on plugins for now). + * Will return the default value if no value was found. + * Will return empty string if no default was found (not one of our keys) or + * if the post does not exist. */ public static function get_value( $key, $postid = 0 ) { global $post; @@ -676,60 +645,76 @@ class WPSEO_Meta { } } - $custom = get_post_custom( $postid ); // Array of strings or empty array. + $custom = get_post_custom( $postid ); // Array of strings or empty array. + $table_key = self::$meta_prefix . $key; - if ( isset( $custom[ self::$meta_prefix . $key ][0] ) ) { - $unserialized = maybe_unserialize( $custom[ self::$meta_prefix . $key ][0] ); - if ( $custom[ self::$meta_prefix . $key ][0] === $unserialized ) { - return $custom[ self::$meta_prefix . $key ][0]; + // Populate the field_def using the field_index lookup array. + $field_def = []; + if ( isset( self::$fields_index[ $table_key ] ) ) { + $field_def = self::$meta_fields[ self::$fields_index[ $table_key ]['subset'] ][ self::$fields_index[ $table_key ]['key'] ]; + } + + // Check if we have a custom post meta entry. + if ( isset( $custom[ $table_key ][0] ) ) { + $unserialized = maybe_unserialize( $custom[ $table_key ][0] ); + + // Check if it is already unserialized. + if ( $custom[ $table_key ][0] === $unserialized ) { + return $custom[ $table_key ][0]; } - else { - $field_def = self::$meta_fields[ self::$fields_index[ self::$meta_prefix . $key ]['subset'] ][ self::$fields_index[ self::$meta_prefix . $key ]['key'] ]; - if ( isset( $field_def['serialized'] ) && $field_def['serialized'] === true ) { - // Ok, serialize value expected/allowed. - return $unserialized; - } + + // Check whether we need to unserialize it. + if ( isset( $field_def['serialized'] ) && $field_def['serialized'] === true ) { + // Ok, serialize value expected/allowed. + return $unserialized; } } // Meta was either not found or found, but object/array while not allowed to be. if ( isset( self::$defaults[ self::$meta_prefix . $key ] ) ) { + // Update the default value to the current post type. + switch ( $key ) { + case 'schema_page_type': + case 'schema_article_type': + return ''; + } + return self::$defaults[ self::$meta_prefix . $key ]; } - else { - /* - * Shouldn't ever happen, means not one of our keys as there will always be a default available - * for all our keys. - */ - return ''; - } + + /* + * Shouldn't ever happen, means not one of our keys as there will always be a default available + * for all our keys. + */ + return ''; } - /** - * Update a meta value for a post + * Update a meta value for a post. * - * @static + * @param string $key The internal key of the meta value to change (without prefix). + * @param mixed $meta_value The value to set the meta to. + * @param int $post_id The ID of the post to change the meta for. * - * @param string $key The internal key of the meta value to change (without prefix). - * @param mixed $meta_value The value to set the meta to. - * @param int $post_id The ID of the post to change the meta for. - * - * @return bool whether the value was changed + * @return bool Whether the value was changed. */ public static function set_value( $key, $meta_value, $post_id ) { + /* + * Slash the data, because `update_metadata` will unslash it and we have already unslashed it. + * Related issue: https://github.com/Yoast/YoastSEO.js/issues/2158 + */ + $meta_value = wp_slash( $meta_value ); + return update_post_meta( $post_id, self::$meta_prefix . $key, $meta_value ); } /** - * Deletes a meta value for a post + * Deletes a meta value for a post. * - * @static - * - * @param string $key The internal key of the meta value to change (without prefix). + * @param string $key The internal key of the meta value to change (without prefix). * @param int $post_id The ID of the post to change the meta for. * - * @return bool Whether the value was changed + * @return bool Whether the value was changed. */ public static function delete( $key, $post_id ) { return delete_post_meta( $post_id, self::$meta_prefix . $key ); @@ -740,11 +725,9 @@ class WPSEO_Meta { * where no WPSEO meta data has been set. * Optionally deletes the $old_metakey values. * - * @static - * - * @param string $old_metakey The old key of the meta value. - * @param string $new_metakey The new key, usually the WPSEO meta key (including prefix). - * @param bool $delete_old Whether to delete the old meta key/value-sets. + * @param string $old_metakey The old key of the meta value. + * @param string $new_metakey The new key, usually the WPSEO meta key (including prefix). + * @param bool $delete_old Whether to delete the old meta key/value-sets. * * @return void */ @@ -777,7 +760,7 @@ class WPSEO_Meta { ); $oldies = $wpdb->get_results( $query ); - if ( is_array( $oldies ) && $oldies !== array() ) { + if ( is_array( $oldies ) && $oldies !== [] ) { foreach ( $oldies as $old ) { update_post_meta( $old->post_id, $new_metakey, $old->meta_value ); } @@ -789,27 +772,25 @@ class WPSEO_Meta { } } - /** - * General clean-up of the saved meta values - * - Remove potentially lingering old meta keys - * - Remove all default and invalid values + * General clean-up of the saved meta values. + * - Remove potentially lingering old meta keys; + * - Remove all default and invalid values. * - * @static * @return void */ public static function clean_up() { global $wpdb; - /** - * Clean up '_yoast_wpseo_meta-robots' + /* + * Clean up '_yoast_wpseo_meta-robots'. * - * Retrieve all '_yoast_wpseo_meta-robots' meta values and convert if no new values found + * Retrieve all '_yoast_wpseo_meta-robots' meta values and convert if no new values found. * * {@internal Query is pretty well optimized this way.}} * - * @todo [JRF => Yoast] find out all possible values which the old '_yoast_wpseo_meta-robots' could contain - * to convert the data correctly + * @todo [JRF => Yoast] Find out all possible values which the old '_yoast_wpseo_meta-robots' could contain + * to convert the data correctly. */ $query = $wpdb->prepare( " @@ -831,7 +812,7 @@ class WPSEO_Meta { ); $oldies = $wpdb->get_results( $query ); - if ( is_array( $oldies ) && $oldies !== array() ) { + if ( is_array( $oldies ) && $oldies !== [] ) { foreach ( $oldies as $old ) { $old_values = explode( ',', $old->meta_value ); foreach ( $old_values as $value ) { @@ -849,10 +830,9 @@ class WPSEO_Meta { // Delete old keys. delete_post_meta_by_key( self::$meta_prefix . 'meta-robots' ); - - /** - * Remove all default values and (most) invalid option values - * Invalid option values for the multiselect (meta-robots-adv) field will be dealt with seperately + /* + * Remove all default values and (most) invalid option values. + * Invalid option values for the multiselect (meta-robots-adv) field will be dealt with seperately. * * {@internal Some of the defaults have changed in v1.5, but as the defaults will * be removed and new defaults will now automatically be passed when no @@ -864,21 +844,15 @@ class WPSEO_Meta { * with that key being deleted, not just the empty fields. * Still, the below implementation is largely based on the delete_meta() function.}} */ - $query = array(); + $query = []; foreach ( self::$meta_fields as $subset => $field_group ) { foreach ( $field_group as $key => $field_def ) { - if ( $field_def['type'] === 'snippetpreview' || ! isset( $field_def['default_value'] ) ) { + if ( ! isset( $field_def['default_value'] ) ) { continue; } - if ( $key === 'meta-robots-adv' ) { - $query[] = $wpdb->prepare( - "( meta_key = %s AND ( meta_value = 'none' OR meta_value = '-' ) )", - self::$meta_prefix . $key - ); - } - elseif ( isset( $field_def['options'] ) && is_array( $field_def['options'] ) && $field_def['options'] !== array() ) { + if ( isset( $field_def['options'] ) && is_array( $field_def['options'] ) && $field_def['options'] !== [] ) { $valid = $field_def['options']; // Remove the default value from the valid options. unset( $valid[ $field_def['default_value'] ] ); @@ -910,7 +884,7 @@ class WPSEO_Meta { $query = "SELECT meta_id FROM {$wpdb->postmeta} WHERE " . implode( ' OR ', $query ) . ';'; $meta_ids = $wpdb->get_col( $query ); - if ( is_array( $meta_ids ) && $meta_ids !== array() ) { + if ( is_array( $meta_ids ) && $meta_ids !== [] ) { // WP native action. do_action( 'delete_post_meta', $meta_ids, null, null, null ); @@ -928,11 +902,10 @@ class WPSEO_Meta { } unset( $query, $meta_ids, $count, $object_id ); - - /** - * Deal with the multiselect (meta-robots-adv) field + /* + * Deal with the multiselect (meta-robots-adv) field. * - * Removes invalid option combinations, such as 'none,noarchive' + * Removes invalid option combinations, such as 'none,noarchive'. * * Default values have already been removed, so we should have a small result set and * (hopefully) even smaller set of invalid results. @@ -943,7 +916,7 @@ class WPSEO_Meta { ); $oldies = $wpdb->get_results( $query ); - if ( is_array( $oldies ) && $oldies !== array() ) { + if ( is_array( $oldies ) && $oldies !== [] ) { foreach ( $oldies as $old ) { $clean = self::validate_meta_robots_adv( $old->meta_value ); @@ -962,7 +935,6 @@ class WPSEO_Meta { do_action( 'wpseo_meta_clean_up' ); } - /** * Recursively merge a variable number of arrays, using the left array as base, * giving priority to the right array. @@ -985,8 +957,8 @@ class WPSEO_Meta { $arrays = func_get_args(); if ( count( $arrays ) < 2 ) { - if ( $arrays === array() ) { - return array(); + if ( $arrays === [] ) { + return []; } else { return $arrays[0]; @@ -1011,67 +983,70 @@ class WPSEO_Meta { } /** - * Get a value from $_POST for a given key - * Returns the $_POST value if exists, returns an empty string if key does not exist + * Counts the total of all the keywords being used for posts except the given one. * - * @static - * - * @param string $key Key of the value to get from $_POST. - * - * @return string Returns $_POST value, which will be a string the majority of the time - * Will return empty string if key does not exists in $_POST - */ - public static function get_post_value( $key ) { - // @codingStandardsIgnoreLine - return ( array_key_exists( $key, $_POST ) ) ? $_POST[ $key ] : ''; - } - - /** - * Counts the total of all the keywords being used for posts except the given one - * - * @param string $keyword The keyword to be counted. - * @param integer $post_id The is of the post to which the keyword belongs. + * @param string $keyword The keyword to be counted. + * @param int $post_id The id of the post to which the keyword belongs. * * @return array */ public static function keyword_usage( $keyword, $post_id ) { if ( empty( $keyword ) ) { - return array(); + return []; } - $query = array( - 'meta_query' => array( - 'relation' => 'OR', - array( - 'key' => '_yoast_wpseo_focuskw', - 'value' => $keyword, - ), - ), - 'post__not_in' => array( $post_id ), - 'fields' => 'ids', - 'post_type' => 'any', + /** + * The indexable repository. + * + * @var Indexable_Repository + */ + $repository = YoastSEO()->classes->get( Indexable_Repository::class ); - /* - * We only need to return zero, one or two results: - * - Zero: keyword hasn't been used before - * - One: Keyword has been used once before - * - Two or more: Keyword has been used twice before - */ - 'posts_per_page' => 2, - ); + $post_ids = $repository->query() + ->select( 'object_id' ) + ->where( 'primary_focus_keyword', $keyword ) + ->where( 'object_type', 'post' ) + ->where_not_equal( 'object_id', $post_id ) + ->limit( 2 ) + ->find_array(); - // If Yoast SEO Premium is active, get the additional keywords as well. - if ( WPSEO_Utils::is_yoast_seo_premium() ) { - $query['meta_query'][] = array( - 'key' => '_yoast_wpseo_focuskeywords', - 'value' => sprintf( '"keyword":"%s"', $keyword ), - 'compare' => 'LIKE', - ); + $callback = static function ( $row ) { + return (int) $row['object_id']; + }; + $post_ids = array_map( $callback, $post_ids ); + + /* + * If Yoast SEO Premium is active, get the additional keywords as well. + * We only check for the additional keywords if we've not already found two. + * In that case there's no use for an additional query as we already know + * that the keyword has been used multiple times before. + */ + if ( YoastSEO()->helpers->product->is_premium() && count( $post_ids ) < 2 ) { + $query = [ + 'meta_query' => [ + [ + 'key' => '_yoast_wpseo_focuskeywords', + 'value' => sprintf( '"keyword":"%s"', $keyword ), + 'compare' => 'LIKE', + ], + ], + 'post__not_in' => [ $post_id ], + 'fields' => 'ids', + 'post_type' => 'any', + + /* + * We only need to return zero, one or two results: + * - Zero: keyword hasn't been used before + * - One: Keyword has been used once before + * - Two or more: Keyword has been used twice or more before + */ + 'posts_per_page' => 2, + ]; + $get_posts = new WP_Query( $query ); + $post_ids = array_merge( $post_ids, $get_posts->posts ); } - $get_posts = new WP_Query( $query ); - - return $get_posts->posts; + return $post_ids; } -} /* End of class */ +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-primary-term.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-primary-term.php index 7d3c883b..ed7cd263 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-wpseo-primary-term.php +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-primary-term.php @@ -6,22 +6,26 @@ */ /** - * Represents a post's primary term + * Represents a post's primary term. */ class WPSEO_Primary_Term { /** + * Taxonomy name for the term. + * * @var string */ protected $taxonomy_name; /** + * Post ID for the term. + * * @var int */ protected $post_ID; /** - * The taxonomy this term is part of + * The taxonomy this term is part of. * * @param string $taxonomy_name Taxonomy name for the term. * @param int $post_id Post ID for the term. @@ -32,7 +36,7 @@ class WPSEO_Primary_Term { } /** - * Returns the primary term ID + * Returns the primary term ID. * * @return int|bool */ @@ -41,7 +45,7 @@ class WPSEO_Primary_Term { $terms = $this->get_terms(); - if ( ! in_array( $primary_term, wp_list_pluck( $terms, 'term_id' ) ) ) { + if ( ! in_array( (int) $primary_term, wp_list_pluck( $terms, 'term_id' ), true ) ) { $primary_term = false; } @@ -50,7 +54,7 @@ class WPSEO_Primary_Term { } /** - * Sets the new primary term ID + * Sets the new primary term ID. * * @param int $new_primary_term New primary term ID. */ @@ -68,7 +72,7 @@ class WPSEO_Primary_Term { $terms = get_the_terms( $this->post_ID, $this->taxonomy_name ); if ( ! is_array( $terms ) ) { - $terms = array(); + $terms = []; } return $terms; diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-rank.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-rank.php index 19712c4b..ffe1b6c1 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-wpseo-rank.php +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-rank.php @@ -6,57 +6,92 @@ */ /** - * Holder for SEO Rank information + * Holder for SEO Rank information. */ class WPSEO_Rank { - const BAD = 'bad'; - const OK = 'ok'; - const GOOD = 'good'; + /** + * Constant used for determining a bad SEO rating. + * + * @var string + */ + const BAD = 'bad'; + + /** + * Constant used for determining an OK SEO rating. + * + * @var string + */ + const OK = 'ok'; + + /** + * Constant used for determining a good SEO rating. + * + * @var string + */ + const GOOD = 'good'; + + /** + * Constant used for determining that no focus keyphrase is set. + * + * @var string + */ const NO_FOCUS = 'na'; + + /** + * Constant used for determining that this content is not indexed. + * + * @var string + */ const NO_INDEX = 'noindex'; /** - * @var array All possible ranks. + * All possible ranks. + * + * @var array */ - protected static $ranks = array( + protected static $ranks = [ self::BAD, self::OK, self::GOOD, self::NO_FOCUS, self::NO_INDEX, - ); + ]; /** - * Holds the translation from seo score slug to actual score range + * Holds the translation from seo score slug to actual score range. * * @var array */ - protected static $ranges = array( - self::NO_FOCUS => array( + protected static $ranges = [ + self::NO_FOCUS => [ 'start' => 0, 'end' => 0, - ), - self::BAD => array( + ], + self::BAD => [ 'start' => 1, 'end' => 40, - ), - self::OK => array( + ], + self::OK => [ 'start' => 41, 'end' => 70, - ), - self::GOOD => array( + ], + self::GOOD => [ 'start' => 71, 'end' => 100, - ), - ); + ], + ]; /** + * The current rank. + * * @var int */ protected $rank; /** + * WPSEO_Rank constructor. + * * @param int $rank The actual rank. */ public function __construct( $rank ) { @@ -77,52 +112,72 @@ class WPSEO_Rank { } /** - * Returns a CSS class for this rank + * Returns a CSS class for this rank. * * @return string */ public function get_css_class() { - $labels = array( + $labels = [ self::NO_FOCUS => 'na', self::NO_INDEX => 'noindex', self::BAD => 'bad', self::OK => 'ok', self::GOOD => 'good', - ); + ]; return $labels[ $this->rank ]; } /** - * Returns a label for this rank + * Returns a label for this rank. * * @return string */ public function get_label() { - $labels = array( + $labels = [ self::NO_FOCUS => __( 'Not available', 'wordpress-seo' ), self::NO_INDEX => __( 'No index', 'wordpress-seo' ), self::BAD => __( 'Needs improvement', 'wordpress-seo' ), self::OK => __( 'OK', 'wordpress-seo' ), self::GOOD => __( 'Good', 'wordpress-seo' ), - ); + ]; return $labels[ $this->rank ]; } /** - * Returns a label for use in a drop down + * Returns a label for use in a drop down. * * @return mixed */ public function get_drop_down_label() { - $labels = array( - self::NO_FOCUS => __( 'SEO: No Focus Keyword', 'wordpress-seo' ), - self::BAD => __( 'SEO: Needs improvement', 'wordpress-seo' ), - self::OK => __( 'SEO: OK', 'wordpress-seo' ), - self::GOOD => __( 'SEO: Good', 'wordpress-seo' ), - self::NO_INDEX => __( 'SEO: Post Noindexed', 'wordpress-seo' ), - ); + $labels = [ + self::NO_FOCUS => sprintf( + /* translators: %s expands to the SEO score */ + __( 'SEO: %s', 'wordpress-seo' ), + __( 'No Focus Keyphrase', 'wordpress-seo' ) + ), + self::BAD => sprintf( + /* translators: %s expands to the SEO score */ + __( 'SEO: %s', 'wordpress-seo' ), + __( 'Needs improvement', 'wordpress-seo' ) + ), + self::OK => sprintf( + /* translators: %s expands to the SEO score */ + __( 'SEO: %s', 'wordpress-seo' ), + __( 'OK', 'wordpress-seo' ) + ), + self::GOOD => sprintf( + /* translators: %s expands to the SEO score */ + __( 'SEO: %s', 'wordpress-seo' ), + __( 'Good', 'wordpress-seo' ) + ), + self::NO_INDEX => sprintf( + /* translators: %s expands to the SEO score */ + __( 'SEO: %s', 'wordpress-seo' ), + __( 'Post Noindexed', 'wordpress-seo' ) + ), + ]; return $labels[ $this->rank ]; } @@ -133,21 +188,35 @@ class WPSEO_Rank { * @return string The readability rank label. */ public function get_drop_down_readability_labels() { - $labels = array( - self::BAD => __( 'Readability: Needs improvement', 'wordpress-seo' ), - self::OK => __( 'Readability: OK', 'wordpress-seo' ), - self::GOOD => __( 'Readability: Good', 'wordpress-seo' ), - ); + $labels = [ + self::BAD => sprintf( + /* translators: %s expands to the readability score */ + __( 'Readability: %s', 'wordpress-seo' ), + __( 'Needs improvement', 'wordpress-seo' ) + ), + self::OK => sprintf( + /* translators: %s expands to the readability score */ + __( 'Readability: %s', 'wordpress-seo' ), + __( 'OK', 'wordpress-seo' ) + ), + self::GOOD => sprintf( + /* translators: %s expands to the readability score */ + __( 'Readability: %s', 'wordpress-seo' ), + __( 'Good', 'wordpress-seo' ) + ), + ]; return $labels[ $this->rank ]; } /** - * @return int The starting score for this rank. + * Get the starting score for this rank. + * + * @return int The start score. */ public function get_starting_score() { // No index does not have a starting score. - if ( self::NO_INDEX === $this->rank ) { + if ( $this->rank === self::NO_INDEX ) { return -1; } @@ -155,11 +224,13 @@ class WPSEO_Rank { } /** - * @return int The end score for this rank. + * Get the ending score for this rank. + * + * @return int The end score. */ public function get_end_score() { // No index does not have an end score. - if ( self::NO_INDEX === $this->rank ) { + if ( $this->rank === self::NO_INDEX ) { return -1; } @@ -167,7 +238,7 @@ class WPSEO_Rank { } /** - * Returns a rank for a specific numeric score + * Returns a rank for a specific numeric score. * * @param int $score The score to determine a rank for. * @@ -188,25 +259,25 @@ class WPSEO_Rank { } /** - * Returns a list of all possible SEO Ranks + * Returns a list of all possible SEO Ranks. * * @return WPSEO_Rank[] */ public static function get_all_ranks() { - return array_map( array( 'WPSEO_Rank', 'create_rank' ), self::$ranks ); + return array_map( [ 'WPSEO_Rank', 'create_rank' ], self::$ranks ); } /** - * Returns a list of all possible Readability Ranks + * Returns a list of all possible Readability Ranks. * * @return WPSEO_Rank[] */ public static function get_all_readability_ranks() { - return array_map( array( 'WPSEO_Rank', 'create_rank' ), array( self::BAD, self::OK, self::GOOD ) ); + return array_map( [ 'WPSEO_Rank', 'create_rank' ], [ self::BAD, self::OK, self::GOOD ] ); } /** - * Converts a numeric rank into a WPSEO_Rank object, for use in functional array_* functions + * Converts a numeric rank into a WPSEO_Rank object, for use in functional array_* functions. * * @param string $rank SEO Rank. * diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-replace-vars.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-replace-vars.php index 04bde07e..8aab0fd6 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-wpseo-replace-vars.php +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-replace-vars.php @@ -22,9 +22,11 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { class WPSEO_Replace_Vars { /** - * @var array Default post/page/cpt information. + * Default post/page/cpt information. + * + * @var array */ - protected $defaults = array( + protected $defaults = [ 'ID' => '', 'name' => '', 'post_author' => '', @@ -36,43 +38,39 @@ class WPSEO_Replace_Vars { 'taxonomy' => '', 'term_id' => '', 'term404' => '', - ); + ]; /** - * @var object Current post/page/cpt information. + * Current post/page/cpt information. + * + * @var stdClass */ protected $args; /** - * @var array Help texts for use in WPSEO -> Titles and Meta's help tabs. - */ - protected static $help_texts = array(); - - /** - * @var array Register of additional variable replacements registered by other plugins/themes. - */ - protected static $external_replacements = array(); - - - /** - * Constructor. + * Help texts for use in WPSEO -> Search appearance tabs. * - * @return \WPSEO_Replace_Vars + * @var array */ - public function __construct() { - } + protected static $help_texts = []; + /** + * Register of additional variable replacements registered by other plugins/themes. + * + * @var array + */ + protected static $external_replacements = []; /** * Setup the help texts and external replacements as statics so they will be available to all instances. */ public static function setup_statics_once() { - if ( self::$help_texts === array() ) { + if ( self::$help_texts === [] ) { self::set_basic_help_texts(); self::set_advanced_help_texts(); } - if ( self::$external_replacements === array() ) { + if ( self::$external_replacements === [] ) { /** * Action: 'wpseo_register_extra_replacements' - Allows for registration of additional * variables to replace. @@ -81,22 +79,21 @@ class WPSEO_Replace_Vars { } } - /** * Register new replacement %%variables%%. * For use by other plugins/themes to register extra variables. * * @see wpseo_register_var_replacement() for a usage example. * - * @param string $var The name of the variable to replace, i.e. '%%var%%' - * - the surrounding %% are optional. - * @param mixed $replace_function Function or method to call to retrieve the replacement value for the variable - * Uses the same format as add_filter/add_action function parameter and - * should *return* the replacement value. DON'T echo it. - * @param string $type Type of variable: 'basic' or 'advanced', defaults to 'advanced'. - * @param string $help_text Help text to be added to the help tab for this variable. + * @param string $var The name of the variable to replace, i.e. '%%var%%'. + * Note: the surrounding %% are optional. + * @param mixed $replace_function Function or method to call to retrieve the replacement value for the variable. + * Uses the same format as add_filter/add_action function parameter and + * should *return* the replacement value. DON'T echo it. + * @param string $type Type of variable: 'basic' or 'advanced', defaults to 'advanced'. + * @param string $help_text Help text to be added to the help tab for this variable. * - * @return bool Whether the replacement function was succesfully registered. + * @return bool Whether the replacement function was succesfully registered. */ public static function register_replacement( $var, $replace_function, $type = 'advanced', $help_text = '' ) { $success = false; @@ -111,9 +108,10 @@ class WPSEO_Replace_Vars { trigger_error( esc_html__( 'A replacement variable can not start with "%%cf_" or "%%ct_" as these are reserved for the WPSEO standard variable variables for custom fields and custom taxonomies. Try making your variable name unique.', 'wordpress-seo' ), E_USER_WARNING ); } elseif ( ! method_exists( __CLASS__, 'retrieve_' . $var ) ) { - if ( ! isset( self::$external_replacements[ $var ] ) ) { + if ( $var !== '' && ! isset( self::$external_replacements[ $var ] ) ) { self::$external_replacements[ $var ] = $replace_function; - self::register_help_text( $type, $var, $help_text ); + $replacement_variable = new WPSEO_Replacement_Variable( $var, $var, $help_text ); + self::register_help_text( $type, $replacement_variable ); $success = true; } else { @@ -128,7 +126,6 @@ class WPSEO_Replace_Vars { return $success; } - /** * Replace `%%variable_placeholders%%` with their real value based on the current requested page/post/cpt/etc. * @@ -139,30 +136,30 @@ class WPSEO_Replace_Vars { * * @return string */ - public function replace( $string, $args, $omit = array() ) { + public function replace( $string, $args, $omit = [] ) { $string = wp_strip_all_tags( $string ); // Let's see if we can bail super early. if ( strpos( $string, '%%' ) === false ) { - return WPSEO_Utils::standardize_whitespace( $string ); + return YoastSEO()->helpers->string->standardize_whitespace( $string ); } $args = (array) $args; if ( isset( $args['post_content'] ) && ! empty( $args['post_content'] ) ) { - $args['post_content'] = WPSEO_Utils::strip_shortcode( $args['post_content'] ); + $args['post_content'] = YoastSEO()->helpers->string->strip_shortcode( $args['post_content'] ); } if ( isset( $args['post_excerpt'] ) && ! empty( $args['post_excerpt'] ) ) { - $args['post_excerpt'] = WPSEO_Utils::strip_shortcode( $args['post_excerpt'] ); + $args['post_excerpt'] = YoastSEO()->helpers->string->strip_shortcode( $args['post_excerpt'] ); } $this->args = (object) wp_parse_args( $args, $this->defaults ); // Clean $omit array. - if ( is_array( $omit ) && $omit !== array() ) { - $omit = array_map( array( __CLASS__, 'remove_var_delimiter' ), $omit ); + if ( is_array( $omit ) && $omit !== [] ) { + $omit = array_map( [ __CLASS__, 'remove_var_delimiter' ], $omit ); } - $replacements = array(); + $replacements = []; if ( preg_match_all( '`%%([^%]+(%%single)?)%%?`iu', $string, $matches ) ) { $replacements = $this->set_up_replacements( $matches, $omit ); } @@ -172,14 +169,19 @@ class WPSEO_Replace_Vars { * * @api array $replacements The replacements. * - * @param array $args The object some of the replacement values might come from, - * could be a post, taxonomy or term. + * @param array $args The object some of the replacement values might come from, + * could be a post, taxonomy or term. */ $replacements = apply_filters( 'wpseo_replacements', $replacements, $this->args ); // Do the actual replacements. - if ( is_array( $replacements ) && $replacements !== array() ) { - $string = str_replace( array_keys( $replacements ), array_values( $replacements ), $string ); + if ( is_array( $replacements ) && $replacements !== [] ) { + $string = str_replace( + array_keys( $replacements ), + // Make sure to exclude replacement values that are arrays e.g. coming from a custom field serialized value. + array_filter( array_values( $replacements ), 'is_scalar' ), + $string + ); } /** @@ -193,7 +195,7 @@ class WPSEO_Replace_Vars { if ( apply_filters( 'wpseo_replacements_final', true ) === true && ( isset( $matches[1] ) && is_array( $matches[1] ) ) ) { // Remove non-replaced variables. $remove = array_diff( $matches[1], $omit ); // Make sure the $omit variables do not get removed. - $remove = array_map( array( __CLASS__, 'add_var_delimiter' ), $remove ); + $remove = array_map( [ __CLASS__, 'add_var_delimiter' ], $remove ); $string = str_replace( $remove, '', $string ); } @@ -204,11 +206,43 @@ class WPSEO_Replace_Vars { } // Remove superfluous whitespace. - $string = WPSEO_Utils::standardize_whitespace( $string ); + $string = YoastSEO()->helpers->string->standardize_whitespace( $string ); return $string; } + /** + * Register a new replacement variable if it has not been registered already. + * + * @param string $var The name of the variable to replace, i.e. '%%var%%'. + * Note: the surrounding %% are optional. + * @param mixed $replace_function Function or method to call to retrieve the replacement value for the variable. + * Uses the same format as add_filter/add_action function parameter and + * should *return* the replacement value. DON'T echo it. + * @param string $type Type of variable: 'basic' or 'advanced', defaults to 'advanced'. + * @param string $help_text Help text to be added to the help tab for this variable. + * + * @return bool `true` if the replace var has been registered, `false` if not. + */ + public function safe_register_replacement( $var, $replace_function, $type = 'advanced', $help_text = '' ) { + if ( ! $this->has_been_registered( $var ) ) { + return self::register_replacement( $var, $replace_function, $type, $help_text ); + } + return false; + } + + /** + * Checks whether the given replacement variable has already been registered or not. + * + * @param string $replacement_variable The replacement variable to check, including the variable delimiter (e.g. `%%var%%`). + * + * @return bool `true` if the replacement variable has already been registered. + */ + public function has_been_registered( $replacement_variable ) { + $replacement_variable = self::remove_var_delimiter( $replacement_variable ); + + return isset( self::$external_replacements[ $replacement_variable ] ); + } /** * Retrieve the replacements for the variables found. @@ -221,9 +255,9 @@ class WPSEO_Replace_Vars { */ private function set_up_replacements( $matches, $omit ) { - $replacements = array(); + $replacements = []; - // @todo -> Figure out a way to deal with external functions starting with cf_/ct_. + // @todo Figure out a way to deal with external functions starting with cf_/ct_. foreach ( $matches[1] as $k => $var ) { // Don't set up replacements which should be omitted. @@ -239,13 +273,15 @@ class WPSEO_Replace_Vars { $replacement = $this->retrieve_ct_desc_custom_tax_name( $var ); } elseif ( strpos( $var, 'ct_' ) === 0 ) { - $single = ( isset( $matches[2][ $k ] ) && $matches[2][ $k ] !== '' ) ? true : false; + $single = ( isset( $matches[2][ $k ] ) && $matches[2][ $k ] !== '' ); $replacement = $this->retrieve_ct_custom_tax_name( $var, $single ); - } // Deal with non-variable variable names. + } + // Deal with non-variable variable names. elseif ( method_exists( $this, 'retrieve_' . $var ) ) { $method_name = 'retrieve_' . $var; $replacement = $this->$method_name(); - } // Deal with externally defined variable names. + } + // Deal with externally defined variable names. elseif ( isset( self::$external_replacements[ $var ] ) && ! is_null( self::$external_replacements[ $var ] ) ) { $replacement = call_user_func( self::$external_replacements[ $var ], $var, $this->args ); } @@ -261,8 +297,6 @@ class WPSEO_Replace_Vars { return $replacements; } - - /* *********************** BASIC VARIABLES ************************** */ /** @@ -276,11 +310,11 @@ class WPSEO_Replace_Vars { if ( ! empty( $this->args->ID ) ) { $cat = $this->get_terms( $this->args->ID, 'category' ); if ( $cat !== '' ) { - $replacement = $cat; + return $cat; } } - if ( ( ! isset( $replacement ) || $replacement === '' ) && ( isset( $this->args->cat_name ) && ! empty( $this->args->cat_name ) ) ) { + if ( isset( $this->args->cat_name ) && ! empty( $this->args->cat_name ) ) { $replacement = $this->args->cat_name; } @@ -305,18 +339,22 @@ class WPSEO_Replace_Vars { $replacement = null; if ( $this->args->post_date !== '' ) { - $replacement = mysql2date( get_option( 'date_format' ), $this->args->post_date, true ); + // Returns a string. + $replacement = YoastSEO()->helpers->date->format_translated( $this->args->post_date, get_option( 'date_format' ) ); } else { if ( get_query_var( 'day' ) && get_query_var( 'day' ) !== '' ) { + // Returns a string. $replacement = get_the_date(); } else { if ( single_month_title( ' ', false ) && single_month_title( ' ', false ) !== '' ) { + // Returns a string. $replacement = single_month_title( ' ', false ); } elseif ( get_query_var( 'year' ) !== '' ) { - $replacement = get_query_var( 'year' ); + // Returns an integer, let's cast to string. + $replacement = (string) get_query_var( 'year' ); } } } @@ -339,7 +377,15 @@ class WPSEO_Replace_Vars { $replacement = wp_strip_all_tags( $this->args->post_excerpt ); } elseif ( $this->args->post_content !== '' ) { - $replacement = wp_html_excerpt( strip_shortcodes( $this->args->post_content ), 320 ); + $content = strip_shortcodes( $this->args->post_content ); + $content = wp_strip_all_tags( $content ); + + if ( strlen( utf8_decode( $content ) ) <= 156 ) { + return $content; + } + + $replacement = wp_html_excerpt( $content, 156 ); + // Trim the auto-generated string to a word boundary. $replacement = substr( $replacement, 0, strrpos( $replacement, ' ' ) ); } @@ -375,9 +421,10 @@ class WPSEO_Replace_Vars { private function retrieve_parent_title() { $replacement = null; - if ( ! isset( $replacement ) && ( ( is_singular() || is_admin() ) && isset( $GLOBALS['post'] ) ) ) { - if ( isset( $GLOBALS['post']->post_parent ) && 0 !== $GLOBALS['post']->post_parent ) { - $replacement = get_the_title( $GLOBALS['post']->post_parent ); + if ( ! empty( $this->args->ID ) ) { + $parent_id = wp_get_post_parent_id( $this->args->ID ); + if ( $parent_id ) { + $replacement = get_the_title( $parent_id ); } } @@ -392,11 +439,9 @@ class WPSEO_Replace_Vars { private function retrieve_searchphrase() { $replacement = null; - if ( ! isset( $replacement ) ) { - $search = get_query_var( 's' ); - if ( $search !== '' ) { - $replacement = esc_html( $search ); - } + $search = get_query_var( 's' ); + if ( $search !== '' ) { + $replacement = esc_html( $search ); } return $replacement; @@ -405,15 +450,18 @@ class WPSEO_Replace_Vars { /** * Retrieve the separator for use as replacement string. * - * @return string + * @return string Retrieves the title separator. */ private function retrieve_sep() { - return WPSEO_Utils::get_title_separator(); + return YoastSEO()->helpers->options->get_title_separator(); } /** * Retrieve the site's tag line / description for use as replacement string. * + * The `$replacement` variable is static because it doesn't change depending + * on the context. See https://github.com/Yoast/wordpress-seo/pull/1172#issuecomment-46019482. + * * @return string|null */ private function retrieve_sitedesc() { @@ -429,17 +477,19 @@ class WPSEO_Replace_Vars { return $replacement; } - /** * Retrieve the site's name for use as replacement string. * + * The `$replacement` variable is static because it doesn't change depending + * on the context. See https://github.com/Yoast/wordpress-seo/pull/1172#issuecomment-46019482. + * * @return string|null */ private function retrieve_sitename() { static $replacement; if ( ! isset( $replacement ) ) { - $sitename = WPSEO_Utils::get_site_name(); + $sitename = YoastSEO()->helpers->site->get_site_name(); if ( $sitename !== '' ) { $replacement = $sitename; } @@ -456,7 +506,7 @@ class WPSEO_Replace_Vars { private function retrieve_tag() { $replacement = null; - if ( isset( $this->args->ID ) ) { + if ( ! empty( $this->args->ID ) ) { $tags = $this->get_terms( $this->args->ID, 'post_tag' ); if ( $tags !== '' ) { $replacement = $tags; @@ -483,7 +533,7 @@ class WPSEO_Replace_Vars { private function retrieve_term_description() { $replacement = null; - if ( isset( $this->args->term_id ) && ! empty( $this->args->taxonomy ) ) { + if ( ! empty( $this->args->term_id ) && ! empty( $this->args->taxonomy ) ) { $term_desc = get_term_field( 'description', $this->args->term_id, $this->args->taxonomy ); if ( $term_desc !== '' ) { $replacement = wp_strip_all_tags( $term_desc ); @@ -517,7 +567,7 @@ class WPSEO_Replace_Vars { $replacement = null; if ( is_string( $this->args->post_title ) && $this->args->post_title !== '' ) { - $replacement = stripslashes( $this->args->post_title ); + $replacement = $this->args->post_title; } return $replacement; @@ -545,7 +595,6 @@ class WPSEO_Replace_Vars { return $primary_category; } - /** * Retrieve the string generated by get_the_archive_title(). * @@ -606,7 +655,6 @@ class WPSEO_Replace_Vars { return $return; } - /** * Determine the post type names for the current post/page/cpt. * @@ -618,8 +666,9 @@ class WPSEO_Replace_Vars { global $wp_query; $pt_single = null; $pt_plural = null; + $post_type = ''; - if ( isset( $wp_query->query_vars['post_type'] ) && ( ( is_string( $wp_query->query_vars['post_type'] ) && $wp_query->query_vars['post_type'] !== '' ) || ( is_array( $wp_query->query_vars['post_type'] ) && $wp_query->query_vars['post_type'] !== array() ) ) ) { + if ( isset( $wp_query->query_vars['post_type'] ) && ( ( is_string( $wp_query->query_vars['post_type'] ) && $wp_query->query_vars['post_type'] !== '' ) || ( is_array( $wp_query->query_vars['post_type'] ) && $wp_query->query_vars['post_type'] !== [] ) ) ) { $post_type = $wp_query->query_vars['post_type']; } elseif ( isset( $this->args->post_type ) && ( is_string( $this->args->post_type ) && $this->args->post_type !== '' ) ) { @@ -627,7 +676,10 @@ class WPSEO_Replace_Vars { } else { // Make it work in preview mode. - $post_type = $wp_query->get_queried_object()->post_type; + $post = $wp_query->get_queried_object(); + if ( $post instanceof WP_Post ) { + $post_type = $post->post_type; + } } if ( is_array( $post_type ) ) { @@ -669,7 +721,6 @@ class WPSEO_Replace_Vars { return $this->retrieve_excerpt_only(); } - /** * Retrieve a post/page/cpt's custom field value for use as replacement string. * @@ -679,13 +730,19 @@ class WPSEO_Replace_Vars { * @return string|null */ private function retrieve_cf_custom_field_name( $var ) { - global $post; $replacement = null; if ( is_string( $var ) && $var !== '' ) { $field = substr( $var, 3 ); - if ( ( is_singular() || is_admin() ) && ( is_object( $post ) && isset( $post->ID ) ) ) { - $name = get_post_meta( $post->ID, $field, true ); + if ( ! empty( $this->args->ID ) ) { + // Post meta can be arrays and in this case we need to exclude them. + $name = get_post_meta( $this->args->ID, $field, true ); + if ( $name !== '' && ! is_array( $name ) ) { + $replacement = $name; + } + } + elseif ( ! empty( $this->args->term_id ) ) { + $name = get_term_meta( $this->args->term_id, $field, true ); if ( $name !== '' ) { $replacement = $name; } @@ -695,7 +752,6 @@ class WPSEO_Replace_Vars { return $replacement; } - /** * Retrieve a post/page/cpt's custom taxonomies for use as replacement string. * @@ -719,7 +775,6 @@ class WPSEO_Replace_Vars { return $replacement; } - /** * Retrieve a post/page/cpt's custom taxonomies description for use as replacement string. * @@ -729,14 +784,13 @@ class WPSEO_Replace_Vars { * @return string|null */ private function retrieve_ct_desc_custom_tax_name( $var ) { - global $post; $replacement = null; if ( is_string( $var ) && $var !== '' ) { $tax = substr( $var, 8 ); - if ( is_object( $post ) && isset( $post->ID ) ) { - $terms = get_the_terms( $post->ID, $tax ); - if ( is_array( $terms ) && $terms !== array() ) { + if ( ! empty( $this->args->ID ) ) { + $terms = get_the_terms( $this->args->ID, $tax ); + if ( is_array( $terms ) && $terms !== [] ) { $term = current( $terms ); $term_desc = get_term_field( 'description', $term->term_id, $tax ); if ( $term_desc !== '' ) { @@ -752,7 +806,10 @@ class WPSEO_Replace_Vars { /** * Retrieve the current date for use as replacement string. * - * @return string + * The `$replacement` variable is static because it doesn't change depending + * on the context. See https://github.com/Yoast/wordpress-seo/pull/1172#issuecomment-46019482. + * + * @return string The formatted current date. */ private function retrieve_currentdate() { static $replacement; @@ -767,7 +824,10 @@ class WPSEO_Replace_Vars { /** * Retrieve the current day for use as replacement string. * - * @return string + * The `$replacement` variable is static because it doesn't change depending + * on the context. See https://github.com/Yoast/wordpress-seo/pull/1172#issuecomment-46019482. + * + * @return string The current day. */ private function retrieve_currentday() { static $replacement; @@ -782,7 +842,10 @@ class WPSEO_Replace_Vars { /** * Retrieve the current month for use as replacement string. * - * @return string + * The `$replacement` variable is static because it doesn't change depending + * on the context. See https://github.com/Yoast/wordpress-seo/pull/1172#issuecomment-46019482. + * + * @return string The current month. */ private function retrieve_currentmonth() { static $replacement; @@ -797,7 +860,10 @@ class WPSEO_Replace_Vars { /** * Retrieve the current time for use as replacement string. * - * @return string + * The `$replacement` variable is static because it doesn't change depending + * on the context. See https://github.com/Yoast/wordpress-seo/pull/1172#issuecomment-46019482. + * + * @return string The formatted current time. */ private function retrieve_currenttime() { static $replacement; @@ -812,7 +878,10 @@ class WPSEO_Replace_Vars { /** * Retrieve the current year for use as replacement string. * - * @return string + * The `$replacement` variable is static because it doesn't change depending + * on the context. See https://github.com/Yoast/wordpress-seo/pull/1172#issuecomment-46019482. + * + * @return string The current year. */ private function retrieve_currentyear() { static $replacement; @@ -830,16 +899,25 @@ class WPSEO_Replace_Vars { * @return string|null */ private function retrieve_focuskw() { - $replacement = null; - + // Retrieve focuskw from a Post. if ( ! empty( $this->args->ID ) ) { $focus_kw = WPSEO_Meta::get_value( 'focuskw', $this->args->ID ); if ( $focus_kw !== '' ) { - $replacement = $focus_kw; + return $focus_kw; + } + + return null; + } + + // Retrieve focuskw from a Term. + if ( ! empty( $this->args->term_id ) ) { + $focus_kw = WPSEO_Taxonomy_Meta::get_term_meta( $this->args->term_id, $this->args->taxonomy, 'focuskw' ); + if ( $focus_kw !== '' ) { + return $focus_kw; } } - return $replacement; + return null; } /** @@ -851,7 +929,8 @@ class WPSEO_Replace_Vars { $replacement = null; if ( ! empty( $this->args->ID ) ) { - $replacement = $this->args->ID; + // The post/page/cpt ID is an integer, let's cast to string. + $replacement = (string) $this->args->ID; } return $replacement; @@ -866,7 +945,7 @@ class WPSEO_Replace_Vars { $replacement = null; if ( ! empty( $this->args->post_modified ) ) { - $replacement = mysql2date( get_option( 'date_format' ), $this->args->post_modified, true ); + $replacement = YoastSEO()->helpers->date->format_translated( $this->args->post_modified, get_option( 'date_format' ) ); } return $replacement; @@ -880,7 +959,7 @@ class WPSEO_Replace_Vars { private function retrieve_name() { $replacement = null; - $user_id = $this->retrieve_userid(); + $user_id = (int) $this->retrieve_userid(); $name = get_the_author_meta( 'display_name', $user_id ); if ( $name !== '' ) { $replacement = $name; @@ -892,12 +971,12 @@ class WPSEO_Replace_Vars { /** * Retrieve the post/page/cpt author's users description for use as a replacement string. * - * @return null|string + * @return string|null */ private function retrieve_user_description() { $replacement = null; - $user_id = $this->retrieve_userid(); + $user_id = (int) $this->retrieve_userid(); $description = get_the_author_meta( 'description', $user_id ); if ( $description !== '' ) { $replacement = $description; @@ -1023,161 +1102,225 @@ class WPSEO_Replace_Vars { * @return string */ private function retrieve_userid() { - $replacement = ! empty( $this->args->post_author ) ? $this->args->post_author : get_query_var( 'author' ); + // The user ID is an integer, let's cast to string. + $replacement = ! empty( $this->args->post_author ) ? (string) $this->args->post_author : (string) get_query_var( 'author' ); return $replacement; } - - /* *********************** HELP TEXT RELATED ************************** */ - /** - * Create a variable help text table. - * - * @param string $type Either 'basic' or 'advanced'. - * - * @return string Help text table. - */ - private static function create_variable_help_table( $type ) { - if ( ! in_array( $type, array( 'basic', 'advanced' ), true ) ) { - return ''; - } - - $table = ' - - - - - - - - '; - - foreach ( self::$help_texts[ $type ] as $replace => $help_text ) { - $table .= ' - - - - '; - } - - $table .= ' - -
    ' . esc_html__( 'Variable', 'wordpress-seo' ) . '' . esc_html__( 'Description', 'wordpress-seo' ) . '
    %%' . esc_html( $replace ) . '%%' . $help_text . '
    '; - - return $table; - } - - /** - * Create the help text table for the basic variables for use in a help tab. - * - * @return string - */ - public static function get_basic_help_texts() { - return self::create_variable_help_table( 'basic' ); - } - - - /** - * Create the help text table for the advanced variables for use in a help tab. - * - * @return string - */ - public static function get_advanced_help_texts() { - return self::create_variable_help_table( 'advanced' ); - } - - /** * Set the help text for a user/plugin/theme defined extra variable. * - * @param string $type Type of variable: 'basic' or 'advanced'. - * @param string $replace Variable to replace, i.e. '%%var%%'. - * @param string $help_text The actual help text string. + * @param string $type Type of variable: 'basic' or 'advanced'. + * @param WPSEO_Replacement_Variable $replacement_variable The replacement variable to register. */ - private static function register_help_text( $type, $replace, $help_text = '' ) { - if ( is_string( $replace ) && $replace !== '' ) { - $replace = self::remove_var_delimiter( $replace ); + private static function register_help_text( $type, WPSEO_Replacement_Variable $replacement_variable ) { + $identifier = $replacement_variable->get_variable(); - if ( ( is_string( $type ) && in_array( $type, array( - 'basic', - 'advanced', - ), true ) ) && ( $replace !== '' && ! isset( self::$help_texts[ $type ][ $replace ] ) ) - ) { - self::$help_texts[ $type ][ $replace ] = $help_text; - } + if ( ( is_string( $type ) && in_array( $type, [ 'basic', 'advanced' ], true ) ) + && ( $identifier !== '' && ! isset( self::$help_texts[ $type ][ $identifier ] ) ) + ) { + self::$help_texts[ $type ][ $identifier ] = $replacement_variable; } } + /** + * Generates a list of replacement variables based on the help texts. + * + * @return array List of replace vars. + */ + public function get_replacement_variables_list() { + self::setup_statics_once(); + + $replacement_variables = array_merge( + $this->get_replacement_variables(), + WPSEO_Custom_Fields::get_custom_fields(), + WPSEO_Custom_Taxonomies::get_custom_taxonomies() + ); + + return array_map( [ $this, 'format_replacement_variable' ], $replacement_variables ); + } + + /** + * Creates a merged associative array of both the basic and advanced help texts. + * + * @return array Array with the replacement variables. + */ + private function get_replacement_variables() { + $help_texts = array_merge( self::$help_texts['basic'], self::$help_texts['advanced'] ); + + return array_filter( array_keys( $help_texts ), [ $this, 'is_not_prefixed' ] ); + } + + /** + * Checks whether the replacement variable contains a `ct_` or `cf_` prefix, because they follow different logic. + * + * @param string $replacement_variable The replacement variable. + * + * @return bool True when the replacement variable is not prefixed. + */ + private function is_not_prefixed( $replacement_variable ) { + $prefixes = [ 'cf_', 'ct_' ]; + $prefix = $this->get_prefix( $replacement_variable ); + + return ! in_array( $prefix, $prefixes, true ); + } + + /** + * Strip the prefix from a replacement variable name. + * + * @param string $replacement_variable The replacement variable. + * + * @return string The replacement variable name without the prefix. + */ + private function strip_prefix( $replacement_variable ) { + return substr( $replacement_variable, 3 ); + } + + /** + * Gets the prefix from a replacement variable name. + * + * @param string $replacement_variable The replacement variable. + * + * @return string The prefix of the replacement variable. + */ + private function get_prefix( $replacement_variable ) { + return substr( $replacement_variable, 0, 3 ); + } + + /** + * Strips 'desc_' if present, and appends ' description' at the end. + * + * @param string $label The replacement variable. + * + * @return string The altered replacement variable name. + */ + private function handle_description( $label ) { + if ( strpos( $label, 'desc_' ) === 0 ) { + return substr( $label, 5 ) . ' description'; + } + + return $label; + } + + /** + * Creates a label for prefixed replacement variables that matches the format in the editors. + * + * @param string $replacement_variable The replacement variable. + * + * @return string The replacement variable label. + */ + private function get_label( $replacement_variable ) { + $prefix = $this->get_prefix( $replacement_variable ); + if ( $prefix === 'cf_' ) { + return $this->strip_prefix( $replacement_variable ) . ' (custom field)'; + } + + if ( $prefix === 'ct_' ) { + $label = $this->strip_prefix( $replacement_variable ); + $label = $this->handle_description( $label ); + return ucfirst( $label . ' (custom taxonomy)' ); + } + + if ( $prefix === 'pt_' ) { + if ( $replacement_variable === 'pt_single' ) { + return 'Post type (singular)'; + } + + return 'Post type (plural)'; + } + + return ''; + } + + /** + * Formats the replacement variables. + * + * @param string $replacement_variable The replacement variable to format. + * + * @return array The formatted replacement variable. + */ + private function format_replacement_variable( $replacement_variable ) { + return [ + 'name' => $replacement_variable, + 'value' => '', + 'label' => $this->get_label( $replacement_variable ), + ]; + } /** * Set/translate the help texts for the WPSEO standard basic variables. */ private static function set_basic_help_texts() { - self::$help_texts['basic'] = array( - 'date' => __( 'Replaced with the date of the post/page', 'wordpress-seo' ), - 'title' => __( 'Replaced with the title of the post/page', 'wordpress-seo' ), - 'parent_title' => __( 'Replaced with the title of the parent page of the current page', 'wordpress-seo' ), - 'archive_title' => __( 'Replaced with the normal title for an archive generated by WordPress', 'wordpress-seo' ), - 'sitename' => __( 'The site\'s name', 'wordpress-seo' ), - 'sitedesc' => __( 'The site\'s tag line / description', 'wordpress-seo' ), - 'excerpt' => __( 'Replaced with the post/page excerpt (or auto-generated if it does not exist)', 'wordpress-seo' ), - 'excerpt_only' => __( 'Replaced with the post/page excerpt (without auto-generation)', 'wordpress-seo' ), - 'tag' => __( 'Replaced with the current tag/tags', 'wordpress-seo' ), - 'category' => __( 'Replaced with the post categories (comma separated)', 'wordpress-seo' ), - 'primary_category' => __( 'Replaced with the primary category of the post/page', 'wordpress-seo' ), - 'category_description' => __( 'Replaced with the category description', 'wordpress-seo' ), - 'tag_description' => __( 'Replaced with the tag description', 'wordpress-seo' ), - 'term_description' => __( 'Replaced with the term description', 'wordpress-seo' ), - 'term_title' => __( 'Replaced with the term name', 'wordpress-seo' ), - 'searchphrase' => __( 'Replaced with the current search phrase', 'wordpress-seo' ), - 'sep' => sprintf( - /* translators: %s: wp_title() function. */ - __( 'The separator defined in your theme\'s %s tag.', 'wordpress-seo' ), - 'wp_title()' - ), + /* translators: %s: wp_title() function. */ + $separator_description = __( 'The separator defined in your theme\'s %s tag.', 'wordpress-seo' ); + $separator_description = sprintf( + $separator_description, + // 'wp_title()' + 'wp_title()' ); + + $replacement_variables = [ + new WPSEO_Replacement_Variable( 'date', __( 'Date', 'wordpress-seo' ), __( 'Replaced with the date of the post/page', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'title', __( 'Title', 'wordpress-seo' ), __( 'Replaced with the title of the post/page', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'parent_title', __( 'Parent title', 'wordpress-seo' ), __( 'Replaced with the title of the parent page of the current page', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'archive_title', __( 'Archive title', 'wordpress-seo' ), __( 'Replaced with the normal title for an archive generated by WordPress', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'sitename', __( 'Site title', 'wordpress-seo' ), __( 'The site\'s name', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'sitedesc', __( 'Tagline', 'wordpress-seo' ), __( 'The site\'s tagline', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'excerpt', __( 'Excerpt', 'wordpress-seo' ), __( 'Replaced with the post/page excerpt (or auto-generated if it does not exist)', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'excerpt_only', __( 'Excerpt only', 'wordpress-seo' ), __( 'Replaced with the post/page excerpt (without auto-generation)', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'tag', __( 'Tag', 'wordpress-seo' ), __( 'Replaced with the current tag/tags', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'category', __( 'Category', 'wordpress-seo' ), __( 'Replaced with the post categories (comma separated)', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'primary_category', __( 'Primary category', 'wordpress-seo' ), __( 'Replaced with the primary category of the post/page', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'category_description', __( 'Category description', 'wordpress-seo' ), __( 'Replaced with the category description', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'tag_description', __( 'Tag description', 'wordpress-seo' ), __( 'Replaced with the tag description', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'term_description', __( 'Term description', 'wordpress-seo' ), __( 'Replaced with the term description', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'term_title', __( 'Term title', 'wordpress-seo' ), __( 'Replaced with the term name', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'searchphrase', __( 'Search phrase', 'wordpress-seo' ), __( 'Replaced with the current search phrase', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'term_hierarchy', __( 'Term hierarchy', 'wordpress-seo' ), __( 'Replaced with the term ancestors hierarchy', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'sep', __( 'Separator', 'wordpress-seo' ), $separator_description ), + ]; + + foreach ( $replacement_variables as $replacement_variable ) { + self::register_help_text( 'basic', $replacement_variable ); + } } /** * Set/translate the help texts for the WPSEO standard advanced variables. */ private static function set_advanced_help_texts() { - self::$help_texts['advanced'] = array( - 'pt_single' => __( 'Replaced with the content type single label', 'wordpress-seo' ), - 'pt_plural' => __( 'Replaced with the content type plural label', 'wordpress-seo' ), - 'modified' => __( 'Replaced with the post/page modified time', 'wordpress-seo' ), - 'id' => __( 'Replaced with the post/page ID', 'wordpress-seo' ), - 'name' => __( 'Replaced with the post/page author\'s \'nicename\'', 'wordpress-seo' ), - 'user_description' => __( 'Replaced with the post/page author\'s \'Biographical Info\'', 'wordpress-seo' ), - 'userid' => __( 'Replaced with the post/page author\'s userid', 'wordpress-seo' ), - 'currenttime' => __( 'Replaced with the current time', 'wordpress-seo' ), - 'currentdate' => __( 'Replaced with the current date', 'wordpress-seo' ), - 'currentday' => __( 'Replaced with the current day', 'wordpress-seo' ), - 'currentmonth' => __( 'Replaced with the current month', 'wordpress-seo' ), - 'currentyear' => __( 'Replaced with the current year', 'wordpress-seo' ), - 'page' => __( 'Replaced with the current page number with context (i.e. page 2 of 4)', 'wordpress-seo' ), - 'pagetotal' => __( 'Replaced with the current page total', 'wordpress-seo' ), - 'pagenumber' => __( 'Replaced with the current page number', 'wordpress-seo' ), - 'caption' => __( 'Attachment caption', 'wordpress-seo' ), - 'focuskw' => __( 'Replaced with the posts focus keyword', 'wordpress-seo' ), - 'term404' => __( 'Replaced with the slug which caused the 404', 'wordpress-seo' ), - 'cf_' => __( 'Replaced with a posts custom field value', 'wordpress-seo' ), - 'ct_' => __( 'Replaced with a posts custom taxonomies, comma separated.', 'wordpress-seo' ), - 'ct_desc_' => __( 'Replaced with a custom taxonomies description', 'wordpress-seo' ), - ); + $replacement_variables = [ + new WPSEO_Replacement_Variable( 'pt_single', __( 'Post type (singular)', 'wordpress-seo' ), __( 'Replaced with the content type single label', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'pt_plural', __( 'Post type (plural)', 'wordpress-seo' ), __( 'Replaced with the content type plural label', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'modified', __( 'Modified', 'wordpress-seo' ), __( 'Replaced with the post/page modified time', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'id', __( 'ID', 'wordpress-seo' ), __( 'Replaced with the post/page ID', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'name', __( 'Name', 'wordpress-seo' ), __( 'Replaced with the post/page author\'s \'nicename\'', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'user_description', __( 'User description', 'wordpress-seo' ), __( 'Replaced with the post/page author\'s \'Biographical Info\'', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'page', __( 'Page number', 'wordpress-seo' ), __( 'Replaced with the current page number with context (i.e. page 2 of 4)', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'pagetotal', __( 'Pagetotal', 'wordpress-seo' ), __( 'Replaced with the current page total', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'pagenumber', __( 'Pagenumber', 'wordpress-seo' ), __( 'Replaced with the current page number', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'caption', __( 'Caption', 'wordpress-seo' ), __( 'Attachment caption', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'focuskw', __( 'Focus keyword', 'wordpress-seo' ), __( 'Replaced with the posts focus keyphrase', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'term404', __( 'Term404', 'wordpress-seo' ), __( 'Replaced with the slug which caused the 404', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'cf_', ' ' . __( '(custom field)', 'wordpress-seo' ), __( 'Replaced with a posts custom field value', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'ct_', ' ' . __( '(custom taxonomy)', 'wordpress-seo' ), __( 'Replaced with a posts custom taxonomies, comma separated.', 'wordpress-seo' ) ), + new WPSEO_Replacement_Variable( 'ct_desc_', ' ' . __( 'description (custom taxonomy)', 'wordpress-seo' ), __( 'Replaced with a custom taxonomies description', 'wordpress-seo' ) ), + ]; + + foreach ( $replacement_variables as $replacement_variable ) { + self::register_help_text( 'advanced', $replacement_variable ); + } } - - - /* *********************** GENERAL HELPER METHODS ************************** */ /** * Remove the '%%' delimiters from a variable string. * - * @param string $string Variable string to be cleaned. + * @param string $string Variable string to be cleaned. * * @return string */ @@ -1188,7 +1331,7 @@ class WPSEO_Replace_Vars { /** * Add the '%%' delimiters to a variable string. * - * @param string $string Variable string to be delimited. + * @param string $string Variable string to be delimited. * * @return string */ @@ -1206,17 +1349,15 @@ class WPSEO_Replace_Vars { * @return string Either a single term or a comma delimited string of terms. */ public function get_terms( $id, $taxonomy, $return_single = false ) { - $output = ''; // If we're on a specific tag, category or taxonomy page, use that. - if ( is_category() || is_tag() || is_tax() ) { - $term = $GLOBALS['wp_query']->get_queried_object(); - $output = $term->name; + if ( ! empty( $this->args->term_id ) ) { + $output = $this->args->name; } elseif ( ! empty( $id ) && ! empty( $taxonomy ) ) { $terms = get_the_terms( $id, $taxonomy ); - if ( is_array( $terms ) && $terms !== array() ) { + if ( is_array( $terms ) && $terms !== [] ) { foreach ( $terms as $term ) { if ( $return_single ) { $output = $term->name; @@ -1232,16 +1373,56 @@ class WPSEO_Replace_Vars { unset( $terms, $term ); /** - * Allows filtering of the terms list used to replace %%category%%, %%tag%% and %%ct_%% variables. + * Allows filtering of the terms list used to replace %%category%%, %%tag%% + * and %%ct_%% variables. * * @api string $output Comma-delimited string containing the terms. + * @api string $taxonomy The taxonomy of the terms. */ - return apply_filters( 'wpseo_terms', $output ); + return apply_filters( 'wpseo_terms', $output, $taxonomy ); } -} /* End of class WPSEO_Replace_Vars */ + /** + * Gets a taxonomy term hierarchy including the term to get the parents for. + * + * @return string + */ + private function get_term_hierarchy() { + if ( ! is_taxonomy_hierarchical( $this->args->taxonomy ) ) { + return ''; + } -/** - * Setup the class statics when the file is first loaded. - */ -WPSEO_Replace_Vars::setup_statics_once(); + $separator = ' ' . $this->retrieve_sep() . ' '; + + $args = [ + 'format' => 'name', + 'separator' => $separator, + 'link' => false, + 'inclusive' => true, + ]; + + return rtrim( + get_term_parents_list( $this->args->term_id, $this->args->taxonomy, $args ), + $separator + ); + } + + /** + * Retrieves the term ancestors hierarchy. + * + * @return string|null The term ancestors hierarchy. + */ + private function retrieve_term_hierarchy() { + $replacement = null; + + if ( ! empty( $this->args->term_id ) && ! empty( $this->args->taxonomy ) ) { + $hierarchy = $this->get_term_hierarchy(); + + if ( $hierarchy !== '' ) { + $replacement = esc_html( $hierarchy ); + } + } + + return $replacement; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-replacement-variable.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-replacement-variable.php new file mode 100644 index 00000000..83dfc8c5 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-replacement-variable.php @@ -0,0 +1,76 @@ +variable = $variable; + $this->label = $label; + $this->description = $description; + } + + /** + * Returns the variable to use. + * + * @return string + */ + public function get_variable() { + return $this->variable; + } + + /** + * Returns the label of the replacement variable. + * + * @return string + */ + public function get_label() { + return $this->label; + } + + /** + * Returns the description of the replacement variable. + * + * @return string + */ + public function get_description() { + return $this->description; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-shortlinker.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-shortlinker.php index 4f97e7f1..ad7e41df 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-wpseo-shortlinker.php +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-shortlinker.php @@ -6,9 +6,34 @@ */ /** - * Helps with creating shortlinks in the plugin + * Helps with creating shortlinks in the plugin. */ class WPSEO_Shortlinker { + + /** + * Collects the additional data necessary for the shortlink. + * + * @return array The shortlink data. + */ + protected function collect_additional_shortlink_data() { + $data = [ + 'php_version' => $this->get_php_version(), + 'platform' => 'wordpress', + 'platform_version' => $this->get_platform_version(), + 'software' => $this->get_software(), + 'software_version' => WPSEO_VERSION, + 'days_active' => $this->get_days_active(), + 'user_language' => $this->get_user_language(), + ]; + + $admin_page = filter_input( INPUT_GET, 'page' ); + if ( ! empty( $admin_page ) ) { + $data['screen'] = $admin_page; + } + + return $data; + } + /** * Builds a URL to use in the plugin as shortlink. * @@ -17,17 +42,7 @@ class WPSEO_Shortlinker { * @return string The final URL. */ public function build_shortlink( $url ) { - return add_query_arg( - array( - 'php_version' => $this->get_php_version(), - 'platform' => 'wordpress', - 'platform_version' => $GLOBALS['wp_version'], - 'software' => $this->get_software(), - 'software_version' => WPSEO_VERSION, - 'role' => $this->get_filtered_user_role(), - ), - $url - ); + return add_query_arg( $this->collect_additional_shortlink_data(), $url ); } /** @@ -38,7 +53,7 @@ class WPSEO_Shortlinker { * @return string The final URL. */ public static function get( $url ) { - $shortlinker = new WPSEO_Shortlinker(); + $shortlinker = new self(); return $shortlinker->build_shortlink( $url ); } @@ -52,6 +67,17 @@ class WPSEO_Shortlinker { echo esc_url( self::get( $url ) ); } + /** + * Gets the shortlink's query params. + * + * @return array The shortlink's query params. + */ + public static function get_query_params() { + $shortlinker = new self(); + + return $shortlinker->collect_additional_shortlink_data(); + } + /** * Gets the current site's PHP version, without the extra info. * @@ -60,7 +86,16 @@ class WPSEO_Shortlinker { private function get_php_version() { $version = explode( '.', PHP_VERSION ); - return (int) $version[0] . '.' . (int) $version[1] . '.' . (int) $version[2]; + return (int) $version[0] . '.' . (int) $version[1]; + } + + /** + * Gets the current site's platform version. + * + * @return string The wp_version. + */ + protected function get_platform_version() { + return $GLOBALS['wp_version']; } /** @@ -69,47 +104,59 @@ class WPSEO_Shortlinker { * @return string The software name + activation state. */ private function get_software() { - if ( ! class_exists( 'WPSEO_Product_Premium' ) ) { - return 'free'; + if ( YoastSEO()->helpers->product->is_premium() ) { + return 'premium'; } - static $software; - - if ( $software === null ) { - $software = 'premium-inactive'; - $product_premium = new WPSEO_Product_Premium(); - $extension_manager = new WPSEO_Extension_Manager(); - - if ( $extension_manager->is_activated( $product_premium->get_slug() ) ) { - $software = 'premium-activated'; - } - } - - return $software; + return 'free'; } /** - * Gets the current user's role without leaking roles that shouldn't be public. + * Gets the number of days the plugin has been active. * - * @return string The filtered user role. + * @return int The number of days the plugin is active. */ - private function get_filtered_user_role() { - $user = wp_get_current_user(); - $built_in_roles = array( - 'administrator', - 'wpseo_manager', - 'wpseo_editor', - 'editor', - 'author', - 'contributor', - 'subscriber', - ); - $filtered_roles = array_intersect( $built_in_roles, $user->roles ); - - $role = current( $filtered_roles ); - if ( ! $role ) { - $role = 'unknown'; + private function get_days_active() { + $date_activated = WPSEO_Options::get( 'first_activated_on' ); + $datediff = ( time() - $date_activated ); + $days = (int) round( $datediff / DAY_IN_SECONDS ); + switch ( $days ) { + case 0: + case 1: + $cohort = '0-1'; + break; + case ( $days < 5 ): + $cohort = '2-5'; + break; + case ( $days < 30 ): + $cohort = '6-30'; + break; + case ( $days < 91 ): + $cohort = '31-90'; + break; + case ( $days < 181 ): + $cohort = '91-180'; + break; + case ( $days < 366 ): + $cohort = '181-365'; + break; + default: + $cohort = '365plus'; } - return $role; + + return $cohort; + } + + /** + * Gets the user's language. + * + * @return string|false The user's language or `false` when it couldn't be retrieved. + */ + private function get_user_language() { + if ( function_exists( 'get_user_locale' ) ) { + return get_user_locale(); + } + + return false; } } diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-statistics.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-statistics.php index 6f501081..687b8fab 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-wpseo-statistics.php +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-statistics.php @@ -6,46 +6,46 @@ */ /** - * Class that generates interesting statistics about things + * Class that generates interesting statistics about things. */ class WPSEO_Statistics { /** - * Returns the post count for a certain SEO rank + * Returns the post count for a certain SEO rank. * - * @todo Merge/DRY this with the logic virtually the same in WPSEO_Metabox::column_sort_orderby() + * @todo Merge/DRY this with the logic virtually the same in WPSEO_Metabox::column_sort_orderby(). * * @param WPSEO_Rank $rank The SEO rank to get the post count for. * * @return int */ public function get_post_count( $rank ) { - if ( WPSEO_Rank::NO_FOCUS === $rank->get_rank() ) { - $posts = array( - 'meta_query' => array( + if ( $rank->get_rank() === WPSEO_Rank::NO_FOCUS ) { + $posts = [ + 'meta_query' => [ 'relation' => 'OR', - array( + [ 'key' => WPSEO_Meta::$meta_prefix . 'focuskw', 'value' => 'needs-a-value-anyway', 'compare' => 'NOT EXISTS', - ), - ), - ); + ], + ], + ]; } - elseif ( WPSEO_Rank::NO_INDEX === $rank->get_rank() ) { - $posts = array( + elseif ( $rank->get_rank() === WPSEO_Rank::NO_INDEX ) { + $posts = [ 'meta_key' => WPSEO_Meta::$meta_prefix . 'meta-robots-noindex', 'meta_value' => '1', 'compare' => '=', - ); + ]; } else { - $posts = array( + $posts = [ 'meta_key' => WPSEO_Meta::$meta_prefix . 'linkdex', - 'meta_value' => array( $rank->get_starting_score(), $rank->get_end_score() ), + 'meta_value' => [ $rank->get_starting_score(), $rank->get_end_score() ], 'meta_compare' => 'BETWEEN', 'meta_type' => 'NUMERIC', - ); + ]; } $posts['fields'] = 'ids'; @@ -57,6 +57,6 @@ class WPSEO_Statistics { $posts = new WP_Query( $posts ); - return $posts->found_posts; + return (int) $posts->found_posts; } } diff --git a/wp-content/plugins/wordpress-seo/inc/class-wpseo-utils.php b/wp-content/plugins/wordpress-seo/inc/class-wpseo-utils.php index 6532d2de..bbf22c10 100644 --- a/wp-content/plugins/wordpress-seo/inc/class-wpseo-utils.php +++ b/wp-content/plugins/wordpress-seo/inc/class-wpseo-utils.php @@ -6,6 +6,8 @@ * @since 1.8.0 */ +use Yoast\WP\SEO\Integrations\Feature_Flag_Integration; + /** * Group of utility methods for use by WPSEO. * All methods are static, this is just a sort of namespacing class wrapper. @@ -13,51 +15,20 @@ class WPSEO_Utils { /** - * @var bool $has_filters Whether the PHP filter extension is enabled. - * @static + * Whether the PHP filter extension is enabled. + * * @since 1.8.0 + * + * @var bool */ public static $has_filters; - /** - * @var array Notifications to be shown in the JavaScript console. - * @static - * @since 3.3.2 - */ - protected static $console_notifications = array(); - - /** - * Check whether the current user is allowed to access the configuration. - * - * @static - * - * @since 1.8.0 - * - * @return boolean - */ - public static function grant_access() { - // @todo Add deprecation warning. - if ( ! is_multisite() ) { - return true; - } - - $options = get_site_option( 'wpseo_ms' ); - - if ( empty( $options['access'] ) || $options['access'] === 'admin' ) { - return current_user_can( 'wpseo_manage_options' ); - } - - return is_super_admin(); - } - /** * Check whether file editing is allowed for the .htaccess and robots.txt files. * * {@internal current_user_can() checks internally whether a user is on wp-ms and adjusts accordingly.}} * - * @static - * - * @since 1.8.0 + * @since 1.8.0 * * @return bool */ @@ -74,85 +45,41 @@ class WPSEO_Utils { * * @api bool $allowed Whether file editing is allowed. */ - return apply_filters( 'wpseo_allow_system_file_edit', $allowed ); } /** - * Check if the web server is running on Apache. - * - * @static + * Check if the web server is running on Apache or compatible (LiteSpeed). * * @since 1.8.0 * * @return bool */ public static function is_apache() { - if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && stristr( $_SERVER['SERVER_SOFTWARE'], 'apache' ) !== false ) { - return true; + if ( ! isset( $_SERVER['SERVER_SOFTWARE'] ) ) { + return false; } - return false; + $software = sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ); + + return stripos( $software, 'apache' ) !== false || stripos( $software, 'litespeed' ) !== false; } /** * Check if the web server is running on Nginx. * - * @static - * * @since 1.8.0 * * @return bool */ public static function is_nginx() { - if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && stristr( $_SERVER['SERVER_SOFTWARE'], 'nginx' ) !== false ) { - return true; + if ( ! isset( $_SERVER['SERVER_SOFTWARE'] ) ) { + return false; } - return false; - } + $software = sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ); - /** - * Register a notification to be shown in the JavaScript console. - * - * @since 3.3.2 - * - * @param string $identifier Notification identifier. - * @param string $message Message to be shown. - * @param bool $one_time_only Only show once (if added multiple times). - */ - public static function javascript_console_notification( $identifier, $message, $one_time_only = false ) { - static $registered_hook; - - if ( is_null( $registered_hook ) ) { - add_action( 'admin_footer', array( __CLASS__, 'localize_console_notices' ), 999 ); - $registered_hook = true; - } - - $prefix = 'Yoast SEO: '; - if ( substr( $message, 0, strlen( $prefix ) ) !== $prefix ) { - $message = $prefix . $message; - } - - if ( $one_time_only ) { - self::$console_notifications[ $identifier ] = $message; - } - else { - self::$console_notifications[] = $message; - } - } - - /** - * Localize the console notifications to JavaScript. - * - * @since 3.3.2 - */ - public static function localize_console_notices() { - if ( empty( self::$console_notifications ) ) { - return; - } - - wp_localize_script( WPSEO_Admin_Asset_Manager::PREFIX . 'admin-global-script', 'wpseoConsoleNotifications', array_values( self::$console_notifications ) ); + return stripos( $software, 'nginx' ) !== false; } /** @@ -165,67 +92,13 @@ class WPSEO_Utils { * @return bool */ public static function is_url_relative( $url ) { - return ( strpos( $url, 'http' ) !== 0 && strpos( $url, '//' ) !== 0 ); - } - - /** - * List all the available user roles. - * - * @since 1.8.0 - * - * @static - * - * @return array $roles - */ - public static function get_roles() { - global $wp_roles; - - if ( ! isset( $wp_roles ) ) { - $wp_roles = new WP_Roles(); - } - - $roles = $wp_roles->get_names(); - - return $roles; - } - - /** - * Standardize whitespace in a string. - * - * Replace line breaks, carriage returns, tabs with a space, then remove double spaces. - * - * @since 1.8.0 - * - * @param string $string String input to standardize. - * - * @return string - */ - public static function standardize_whitespace( $string ) { - return trim( str_replace( ' ', ' ', str_replace( array( "\t", "\n", "\r", "\f" ), ' ', $string ) ) ); - } - - /** - * First strip out registered and enclosing shortcodes using native WordPress strip_shortcodes function. - * Then strip out the shortcodes with a filthy regex, because people don't properly register their shortcodes. - * - * @static - * - * @since 1.8.0 - * - * @param string $text Input string that might contain shortcodes. - * - * @return string $text String without shortcodes. - */ - public static function strip_shortcode( $text ) { - return preg_replace( '`\[[^\]]+\]`s', '', strip_shortcodes( $text ) ); + return YoastSEO()->helpers->url->is_relative( $url ); } /** * Recursively trim whitespace round a string value or of string values within an array. * Only trims strings to avoid typecasting a variable (to string). * - * @static - * * @since 1.8.0 * * @param mixed $value Value to trim or array of values to trim. @@ -237,7 +110,7 @@ class WPSEO_Utils { $value = trim( $value ); } elseif ( is_array( $value ) ) { - $value = array_map( array( __CLASS__, 'trim_recursive' ), $value ); + $value = array_map( [ __CLASS__, 'trim_recursive' ], $value ); } return $value; @@ -246,8 +119,6 @@ class WPSEO_Utils { /** * Translates a decimal analysis score into a textual one. * - * @static - * * @since 1.8.0 * * @param int $val The decimal score to translate. @@ -268,17 +139,15 @@ class WPSEO_Utils { /** * Emulate the WP native sanitize_text_field function in a %%variable%% safe way. * - * @see https://core.trac.wordpress.org/browser/trunk/src/wp-includes/formatting.php for the original - * * Sanitize a string from user input or from the db. * - * - Check for invalid UTF-8, - * - Convert single < characters to entity, - * - Strip all tags, - * - Remove line breaks, tabs and extra white space, + * - Check for invalid UTF-8; + * - Convert single < characters to entity; + * - Strip all tags; + * - Remove line breaks, tabs and extra white space; * - Strip octets - BUT DO NOT REMOVE (part of) VARIABLES WHICH WILL BE REPLACED. * - * @static + * @link https://core.trac.wordpress.org/browser/trunk/src/wp-includes/formatting.php for the original. * * @since 1.8.0 * @@ -318,16 +187,13 @@ class WPSEO_Utils { * @param string $filtered The sanitized string. * @param string $str The string prior to being sanitized. */ - - return apply_filters( 'sanitize_text_field', $filtered, $value ); + return apply_filters( 'sanitize_text_field', $filtered, $value ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Using WP native filter. } /** * Sanitize a url for saving to the database. * Not to be confused with the old native WP function. * - * @todo [JRF => whomever] Check/improve url verification. - * * @since 1.8.0 * * @param string $value String URL value to sanitize. @@ -335,15 +201,87 @@ class WPSEO_Utils { * * @return string */ - public static function sanitize_url( $value, $allowed_protocols = array( 'http', 'https' ) ) { - return esc_url_raw( sanitize_text_field( rawurldecode( $value ) ), $allowed_protocols ); + public static function sanitize_url( $value, $allowed_protocols = [ 'http', 'https' ] ) { + + $url = ''; + $parts = wp_parse_url( $value ); + + if ( isset( $parts['scheme'], $parts['host'] ) ) { + $url = $parts['scheme'] . '://'; + + if ( isset( $parts['user'] ) ) { + $url .= rawurlencode( $parts['user'] ); + $url .= isset( $parts['pass'] ) ? ':' . rawurlencode( $parts['pass'] ) : ''; + $url .= '@'; + } + + $parts['host'] = preg_replace( + '`[^a-z0-9-.:\[\]\\x80-\\xff]`', + '', + strtolower( $parts['host'] ) + ); + + $url .= $parts['host'] . ( isset( $parts['port'] ) ? ':' . intval( $parts['port'] ) : '' ); + } + + if ( isset( $parts['path'] ) && strpos( $parts['path'], '/' ) === 0 ) { + $path = explode( '/', wp_strip_all_tags( $parts['path'] ) ); + $path = self::sanitize_encoded_text_field( $path ); + $url .= implode( '/', $path ); + } + + if ( ! $url ) { + return ''; + } + + if ( isset( $parts['query'] ) ) { + wp_parse_str( $parts['query'], $parsed_query ); + + $parsed_query = array_combine( + self::sanitize_encoded_text_field( array_keys( $parsed_query ) ), + self::sanitize_encoded_text_field( array_values( $parsed_query ) ) + ); + + $url = add_query_arg( $parsed_query, $url ); + } + + if ( isset( $parts['fragment'] ) ) { + $url .= '#' . self::sanitize_encoded_text_field( $parts['fragment'] ); + } + + if ( strpos( $url, '%' ) !== false ) { + $url = preg_replace_callback( + '`%[a-fA-F0-9]{2}`', + static function( $octects ) { + return strtolower( $octects[0] ); + }, + $url + ); + } + + return esc_url_raw( $url, $allowed_protocols ); + } + + /** + * Decode, sanitize and encode the array of strings or the string. + * + * @since 13.3 + * + * @param array|string $value The value to sanitize and encode. + * + * @return array|string The sanitized value. + */ + public static function sanitize_encoded_text_field( $value ) { + if ( is_array( $value ) ) { + return array_map( [ __CLASS__, 'sanitize_encoded_text_field' ], $value ); + } + + return rawurlencode( sanitize_text_field( rawurldecode( $value ) ) ); } /** * Validate a value as boolean. * - * @static - * * @since 1.8.0 * * @param mixed $value Value to validate. @@ -366,8 +304,6 @@ class WPSEO_Utils { /** * Cast a value to bool. * - * @static - * * @since 1.8.0 * * @param mixed $value Value to cast. @@ -375,7 +311,7 @@ class WPSEO_Utils { * @return bool */ public static function emulate_filter_bool( $value ) { - $true = array( + $true = [ '1', 'true', 'True', @@ -388,9 +324,8 @@ class WPSEO_Utils { 'on', 'On', 'ON', - - ); - $false = array( + ]; + $false = [ '0', 'false', 'False', @@ -403,7 +338,7 @@ class WPSEO_Utils { 'off', 'Off', 'OFF', - ); + ]; if ( is_bool( $value ) ) { return $value; @@ -433,8 +368,6 @@ class WPSEO_Utils { /** * Validate a value as integer. * - * @static - * * @since 1.8.0 * * @param mixed $value Value to validate. @@ -457,8 +390,6 @@ class WPSEO_Utils { /** * Cast a value to integer. * - * @static - * * @since 1.8.0 * * @param mixed $value Value to cast. @@ -470,6 +401,7 @@ class WPSEO_Utils { return $value; } elseif ( is_float( $value ) ) { + // phpcs:ignore WordPress.PHP.StrictComparisons -- Purposeful loose comparison. if ( (int) $value == $value && ! is_nan( $value ) ) { return (int) $value; } @@ -499,8 +431,6 @@ class WPSEO_Utils { /** * Clears the WP or W3TC cache depending on which is used. * - * @static - * * @since 1.8.0 */ public static function clear_cache() { @@ -512,24 +442,9 @@ class WPSEO_Utils { } } - /** - * Flush W3TC cache after succesfull update/add of taxonomy meta option. - * - * @static - * - * @since 1.8.0 - */ - public static function flush_w3tc_cache() { - if ( defined( 'W3TC_DIR' ) && function_exists( 'w3tc_objectcache_flush' ) ) { - w3tc_objectcache_flush(); - } - } - /** * Clear rewrite rules. * - * @static - * * @since 1.8.0 */ public static function clear_rewrites() { @@ -539,35 +454,33 @@ class WPSEO_Utils { /** * Do simple reliable math calculations without the risk of wrong results. * - * @see http://floating-point-gui.de/ - * @see the big red warning on http://php.net/language.types.float.php - * * In the rare case that the bcmath extension would not be loaded, it will return the normal calculation results. * - * @static + * @link http://floating-point-gui.de/ + * @link http://php.net/language.types.float.php See the big red warning. * * @since 1.5.0 * @since 1.8.0 Moved from stand-alone function to this class. * - * @param mixed $number1 Scalar (string/int/float/bool). - * @param string $action Calculation action to execute. Valid input: - * '+' or 'add' or 'addition', - * '-' or 'sub' or 'subtract', - * '*' or 'mul' or 'multiply', - * '/' or 'div' or 'divide', - * '%' or 'mod' or 'modulus' - * '=' or 'comp' or 'compare'. - * @param mixed $number2 Scalar (string/int/float/bool). - * @param bool $round Whether or not to round the result. Defaults to false. - * Will be disregarded for a compare operation. - * @param int $decimals Decimals for rounding operation. Defaults to 0. - * @param int $precision Calculation precision. Defaults to 10. + * @param mixed $number1 Scalar (string/int/float/bool). + * @param string $action Calculation action to execute. Valid input: + * '+' or 'add' or 'addition', + * '-' or 'sub' or 'subtract', + * '*' or 'mul' or 'multiply', + * '/' or 'div' or 'divide', + * '%' or 'mod' or 'modulus' + * '=' or 'comp' or 'compare'. + * @param mixed $number2 Scalar (string/int/float/bool). + * @param bool $round Whether or not to round the result. Defaults to false. + * Will be disregarded for a compare operation. + * @param int $decimals Decimals for rounding operation. Defaults to 0. + * @param int $precision Calculation precision. Defaults to 10. * - * @return mixed Calculation Result or false if either or the numbers isn't scalar or - * an invalid operation was passed. - * - for compare the result will always be an integer. - * - for all other operations, the result will either be an integer (preferred) - * or a float. + * @return mixed Calculation Result or false if either or the numbers isn't scalar or + * an invalid operation was passed. + * - For compare the result will always be an integer. + * - For all other operations, the result will either be an integer (preferred) + * or a float. */ public static function calc( $number1, $action, $number2, $round = false, $decimals = 0, $precision = 10 ) { static $bc; @@ -613,7 +526,7 @@ class WPSEO_Utils { if ( $bc ) { $result = bcdiv( $number1, $number2, $precision ); // String, or NULL if right_operand is 0. } - elseif ( $number2 != 0 ) { + elseif ( $number2 != 0 ) { // phpcs:ignore WordPress.PHP.StrictComparisons -- Purposeful loose comparison. $result = ( $number1 / $number2 ); } @@ -628,7 +541,7 @@ class WPSEO_Utils { if ( $bc ) { $result = bcmod( $number1, $number2 ); // String, or NULL if modulus is 0. } - elseif ( $number2 != 0 ) { + elseif ( $number2 != 0 ) { // phpcs:ignore WordPress.PHP.StrictComparisons -- Purposeful loose comparison. $result = ( $number1 % $number2 ); } @@ -645,7 +558,8 @@ class WPSEO_Utils { $result = bccomp( $number1, $number2, $precision ); // Returns int 0, 1 or -1. } else { - $result = ( $number1 == $number2 ) ? 0 : ( ( $number1 > $number2 ) ? 1 : - 1 ); + // phpcs:ignore WordPress.PHP.StrictComparisons -- Purposeful loose comparison. + $result = ( $number1 == $number2 ) ? 0 : ( ( $number1 > $number2 ) ? 1 : -1 ); } break; } @@ -659,6 +573,7 @@ class WPSEO_Utils { } } else { + // phpcs:ignore WordPress.PHP.StrictComparisons -- Purposeful loose comparison. $result = ( intval( $result ) == $result ) ? intval( $result ) : floatval( $result ); } } @@ -679,7 +594,7 @@ class WPSEO_Utils { * @return string */ public static function trim_nbsp_from_string( $string ) { - $find = array( ' ', chr( 0xC2 ) . chr( 0xA0 ) ); + $find = [ ' ', chr( 0xC2 ) . chr( 0xA0 ) ]; $string = str_replace( $find, ' ', $string ); $string = trim( $string ); @@ -696,16 +611,7 @@ class WPSEO_Utils { * @return bool */ public static function is_valid_datetime( $datetime ) { - - if ( substr( $datetime, 0, 1 ) === '-' ) { - return false; - } - - try { - return new DateTime( $datetime ) !== false; - } catch ( Exception $exc ) { - return false; - } + return YoastSEO()->helpers->date->is_valid_datetime( $datetime ); } /** @@ -740,26 +646,6 @@ class WPSEO_Utils { return apply_filters( 'wpseo_format_admin_url', $formatted_url ); } - - /** - * Get plugin name from file. - * - * @since 2.3.3 - * - * @param string $plugin Plugin path relative to plugins directory. - * - * @return string|bool - */ - public static function get_plugin_name( $plugin ) { - $plugin_details = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); - - if ( $plugin_details['Name'] !== '' ) { - return $plugin_details['Name']; - } - - return false; - } - /** * Retrieves the sitename. * @@ -768,35 +654,7 @@ class WPSEO_Utils { * @return string */ public static function get_site_name() { - return wp_strip_all_tags( get_bloginfo( 'name' ), true ); - } - - /** - * Retrieves the title separator. - * - * @since 3.0.0 - * - * @return string - */ - public static function get_title_separator() { - $replacement = WPSEO_Options::get_default( 'wpseo_titles', 'separator' ); - - // Get the titles option and the separator options. - $separator = WPSEO_Options::get( 'separator' ); - $seperator_options = WPSEO_Option_Titles::get_instance()->get_separator_options(); - - // This should always be set, but just to be sure. - if ( isset( $seperator_options[ $separator ] ) ) { - // Set the new replacement. - $replacement = $seperator_options[ $separator ]; - } - - /** - * Filter: 'wpseo_replacements_filter_sep' - Allow customization of the separator character(s). - * - * @api string $replacement The current separator. - */ - return apply_filters( 'wpseo_replacements_filter_sep', $replacement ); + return YoastSEO()->helpers->site->get_site_name(); } /** @@ -807,14 +665,7 @@ class WPSEO_Utils { * @return bool */ public static function is_yoast_seo_page() { - static $is_yoast_seo; - - if ( $is_yoast_seo === null ) { - $current_page = filter_input( INPUT_GET, 'page' ); - $is_yoast_seo = ( substr( $current_page, 0, 6 ) === 'wpseo_' ); - } - - return $is_yoast_seo; + return YoastSEO()->helpers->current_page->is_yoast_seo_page(); } /** @@ -827,7 +678,7 @@ class WPSEO_Utils { * @return bool */ public static function is_yoast_seo_free_page( $current_page ) { - $yoast_seo_free_pages = array( + $yoast_seo_free_pages = [ 'wpseo_dashboard', 'wpseo_titles', 'wpseo_social', @@ -835,7 +686,7 @@ class WPSEO_Utils { 'wpseo_tools', 'wpseo_search_console', 'wpseo_licenses', - ); + ]; return in_array( $current_page, $yoast_seo_free_pages, true ); } @@ -843,10 +694,14 @@ class WPSEO_Utils { /** * Checks if we are in the premium or free plugin. * + * @deprecated 16.0 + * @codeCoverageIgnore + * * @return bool True when we are in the premium plugin. */ public static function is_yoast_seo_premium() { - return defined( 'WPSEO_PREMIUM_PLUGIN_FILE' ); + _deprecated_function( __FUNCTION__, '16.0', 'YoastSEO()->helpers->product->is_premium' ); + return YoastSEO()->helpers->product->is_premium(); } /** @@ -861,10 +716,13 @@ class WPSEO_Utils { public static function is_development_mode() { $development_mode = false; - if ( defined( 'WPSEO_DEBUG' ) ) { + if ( defined( 'YOAST_ENVIRONMENT' ) && YOAST_ENVIRONMENT === 'development' ) { + $development_mode = true; + } + elseif ( defined( 'WPSEO_DEBUG' ) ) { $development_mode = WPSEO_DEBUG; } - elseif ( site_url() && false === strpos( site_url(), '.' ) ) { + elseif ( site_url() && strpos( site_url(), '.' ) === false ) { $development_mode = true; } @@ -875,7 +733,6 @@ class WPSEO_Utils { * * @param bool $development_mode Is Yoast SEOs development mode active. */ - return apply_filters( 'yoast_seo_development_mode', $development_mode ); } @@ -890,56 +747,560 @@ class WPSEO_Utils { * @return string Home URL with optional path, appropriately slashed if not. */ public static function home_url( $path = '', $scheme = null ) { - - $home_url = home_url( $path, $scheme ); - - if ( ! empty( $path ) ) { - return $home_url; - } - - $home_path = wp_parse_url( $home_url, PHP_URL_PATH ); - - if ( '/' === $home_path ) { // Home at site root, already slashed. - return $home_url; - } - - if ( is_null( $home_path ) ) { // Home at site root, always slash. - return trailingslashit( $home_url ); - } - - if ( is_string( $home_path ) ) { // Home in subdirectory, slash if permalink structure has slash. - return user_trailingslashit( $home_url ); - } - - return $home_url; + return YoastSEO()->helpers->url->home( $path, $scheme ); } /** - * Returns a base64 URL for the svg for use in the menu. + * Checks if the WP-REST-API is available. * - * @since 3.3.0 + * @since 3.6 + * @since 3.7 Introduced the $minimum_version parameter. * - * @param bool $base64 Whether or not to return base64'd output. + * @param string $minimum_version The minimum version the API should be. + * + * @return bool Returns true if the API is available. + */ + public static function is_api_available( $minimum_version = '2.0' ) { + return ( defined( 'REST_API_VERSION' ) + && version_compare( REST_API_VERSION, $minimum_version, '>=' ) ); + } + + /** + * Determine whether or not the metabox should be displayed for a post type. + * + * @param string|null $post_type Optional. The post type to check the visibility of the metabox for. + * + * @return bool Whether or not the metabox should be displayed. + */ + protected static function display_post_type_metabox( $post_type = null ) { + if ( ! isset( $post_type ) ) { + $post_type = get_post_type(); + } + + if ( ! isset( $post_type ) || ! WPSEO_Post_Type::is_post_type_accessible( $post_type ) ) { + return false; + } + + if ( $post_type === 'attachment' && WPSEO_Options::get( 'disable-attachment' ) ) { + return false; + } + + return apply_filters( 'wpseo_enable_editor_features_' . $post_type, WPSEO_Options::get( 'display-metabox-pt-' . $post_type ) ); + } + + /** + * Determine whether or not the metabox should be displayed for a taxonomy. + * + * @param string|null $taxonomy Optional. The post type to check the visibility of the metabox for. + * + * @return bool Whether or not the metabox should be displayed. + */ + protected static function display_taxonomy_metabox( $taxonomy = null ) { + if ( ! isset( $taxonomy ) || ! in_array( $taxonomy, get_taxonomies( [ 'public' => true ], 'names' ), true ) ) { + return false; + } + + return WPSEO_Options::get( 'display-metabox-tax-' . $taxonomy ); + } + + /** + * Determines whether the metabox is active for the given identifier and type. + * + * @param string $identifier The identifier to check for. + * @param string $type The type to check for. + * + * @return bool Whether or not the metabox is active. + */ + public static function is_metabox_active( $identifier, $type ) { + if ( $type === 'post_type' ) { + return self::display_post_type_metabox( $identifier ); + } + + if ( $type === 'taxonomy' ) { + return self::display_taxonomy_metabox( $identifier ); + } + + return false; + } + + /** + * Determines whether the plugin is active for the entire network. + * + * @return bool Whether or not the plugin is network-active. + */ + public static function is_plugin_network_active() { + return YoastSEO()->helpers->url->is_plugin_network_active(); + } + + /** + * Gets the type of the current post. + * + * @return string The post type, or an empty string. + */ + public static function get_post_type() { + global $post; + + if ( isset( $post->post_type ) ) { + return $post->post_type; + } + elseif ( isset( $_GET['post_type'] ) ) { + return sanitize_text_field( wp_unslash( $_GET['post_type'] ) ); + } + + return ''; + } + + /** + * Gets the type of the current page. + * + * @return string Returns 'post' if the current page is a post edit page. Taxonomy in other cases. + */ + public static function get_page_type() { + global $pagenow; + if ( WPSEO_Metabox::is_post_edit( $pagenow ) ) { + return 'post'; + } + + return 'taxonomy'; + } + + /** + * Getter for the Adminl10n array. Applies the wpseo_admin_l10n filter. + * + * @return array The Adminl10n array. + */ + public static function get_admin_l10n() { + $post_type = self::get_post_type(); + $page_type = self::get_page_type(); + + $label_object = false; + $no_index = false; + + if ( $page_type === 'post' ) { + $label_object = get_post_type_object( $post_type ); + $no_index = WPSEO_Options::get( 'noindex-' . $post_type, false ); + } + else { + $label_object = WPSEO_Taxonomy::get_labels(); + + $taxonomy_slug = filter_input( INPUT_GET, 'taxonomy', FILTER_DEFAULT, [ 'options' => [ 'default' => '' ] ] ); + $no_index = WPSEO_Options::get( 'noindex-tax-' . $taxonomy_slug, false ); + } + + $wpseo_admin_l10n = [ + 'displayAdvancedTab' => WPSEO_Capability_Utils::current_user_can( 'wpseo_edit_advanced_metadata' ) || ! WPSEO_Options::get( 'disableadvanced_meta' ), + 'noIndex' => (bool) $no_index, + 'isPostType' => (bool) get_post_type(), + 'postType' => get_post_type(), + 'postTypeNamePlural' => ( $page_type === 'post' ) ? $label_object->label : $label_object->name, + 'postTypeNameSingular' => ( $page_type === 'post' ) ? $label_object->labels->singular_name : $label_object->singular_name, + 'isBreadcrumbsDisabled' => WPSEO_Options::get( 'breadcrumbs-enable', false ) !== true && ! current_theme_supports( 'yoast-seo-breadcrumbs' ), + // phpcs:ignore Generic.ControlStructures.DisallowYodaConditions -- Bug: squizlabs/PHP_CodeSniffer#2962. + 'isPrivateBlog' => ( (string) get_option( 'blog_public' ) ) === '0', + ]; + + $additional_entries = apply_filters( 'wpseo_admin_l10n', [] ); + if ( is_array( $additional_entries ) ) { + $wpseo_admin_l10n = array_merge( $wpseo_admin_l10n, $additional_entries ); + } + + return $wpseo_admin_l10n; + } + + /** + * Retrieves the analysis worker log level. Defaults to errors only. + * + * Uses bool YOAST_SEO_DEBUG as flag to enable logging. Off equals ERROR. + * Uses string YOAST_SEO_DEBUG_ANALYSIS_WORKER as log level for the Analysis + * Worker. Defaults to INFO. + * Can be: TRACE, DEBUG, INFO, WARN or ERROR. + * + * @return string The log level to use. + */ + public static function get_analysis_worker_log_level() { + if ( defined( 'YOAST_SEO_DEBUG' ) && YOAST_SEO_DEBUG ) { + return defined( 'YOAST_SEO_DEBUG_ANALYSIS_WORKER' ) ? YOAST_SEO_DEBUG_ANALYSIS_WORKER : 'INFO'; + } + + return 'ERROR'; + } + + /** + * Returns the unfiltered home URL. + * + * In case WPML is installed, returns the original home_url and not the WPML version. + * In case of a multisite setup we return the network_home_url. + * + * @codeCoverageIgnore + * + * @return string The home url. + */ + public static function get_home_url() { + return YoastSEO()->helpers->url->network_safe_home_url(); + } + + /** + * Prepares data for outputting as JSON. + * + * @param array $data The data to format. + * + * @return false|string The prepared JSON string. + */ + public static function format_json_encode( $data ) { + $flags = JSON_UNESCAPED_SLASHES; + + if ( self::is_development_mode() ) { + $flags = ( $flags | JSON_PRETTY_PRINT ); + + /** + * Filter the Yoast SEO development mode. + * + * @api array $data Allows filtering of the JSON data for debug purposes. + */ + $data = apply_filters( 'wpseo_debug_json_data', $data ); + } + + // phpcs:ignore Yoast.Yoast.AlternativeFunctions.json_encode_wp_json_encodeWithAdditionalParams -- This is the definition of format_json_encode. + return wp_json_encode( $data, $flags ); + } + + /** + * Extends the allowed post tags with accessibility-related attributes. + * + * @codeCoverageIgnore + * + * @param array $allowed_post_tags The allowed post tags. + * + * @return array The allowed tags including post tags, input tags and select tags. + */ + public static function extend_kses_post_with_a11y( $allowed_post_tags ) { + static $a11y_tags; + + if ( isset( $a11y_tags ) === false ) { + $a11y_tags = [ + 'button' => [ + 'aria-expanded' => true, + 'aria-controls' => true, + ], + 'div' => [ + 'tabindex' => true, + ], + // Below are attributes that are needed for backwards compatibility (WP < 5.1). + 'span' => [ + 'aria-hidden' => true, + ], + 'input' => [ + 'aria-describedby' => true, + ], + 'select' => [ + 'aria-describedby' => true, + ], + 'textarea' => [ + 'aria-describedby' => true, + ], + ]; + + // Add the global allowed attributes to each html element. + $a11y_tags = array_map( '_wp_add_global_attributes', $a11y_tags ); + } + + return array_merge_recursive( $allowed_post_tags, $a11y_tags ); + } + + /** + * Extends the allowed post tags with input, select and option tags. + * + * @codeCoverageIgnore + * + * @param array $allowed_post_tags The allowed post tags. + * + * @return array The allowed tags including post tags, input tags, select tags and option tags. + */ + public static function extend_kses_post_with_forms( $allowed_post_tags ) { + static $input_tags; + + if ( isset( $input_tags ) === false ) { + $input_tags = [ + 'input' => [ + 'accept' => true, + 'accesskey' => true, + 'align' => true, + 'alt' => true, + 'autocomplete' => true, + 'autofocus' => true, + 'checked' => true, + 'contenteditable' => true, + 'dirname' => true, + 'disabled' => true, + 'draggable' => true, + 'dropzone' => true, + 'form' => true, + 'formaction' => true, + 'formenctype' => true, + 'formmethod' => true, + 'formnovalidate' => true, + 'formtarget' => true, + 'height' => true, + 'hidden' => true, + 'lang' => true, + 'list' => true, + 'max' => true, + 'maxlength' => true, + 'min' => true, + 'multiple' => true, + 'name' => true, + 'pattern' => true, + 'placeholder' => true, + 'readonly' => true, + 'required' => true, + 'size' => true, + 'spellcheck' => true, + 'src' => true, + 'step' => true, + 'tabindex' => true, + 'translate' => true, + 'type' => true, + 'value' => true, + 'width' => true, + + /* + * Below are attributes that are needed for backwards compatibility (WP < 5.1). + * They are used for the social media image in the metabox. + * These can be removed once we move to the React versions of the social previews. + */ + 'data-target' => true, + 'data-target-id' => true, + ], + 'select' => [ + 'accesskey' => true, + 'autofocus' => true, + 'contenteditable' => true, + 'disabled' => true, + 'draggable' => true, + 'dropzone' => true, + 'form' => true, + 'hidden' => true, + 'lang' => true, + 'multiple' => true, + 'name' => true, + 'onblur' => true, + 'onchange' => true, + 'oncontextmenu' => true, + 'onfocus' => true, + 'oninput' => true, + 'oninvalid' => true, + 'onreset' => true, + 'onsearch' => true, + 'onselect' => true, + 'onsubmit' => true, + 'required' => true, + 'size' => true, + 'spellcheck' => true, + 'tabindex' => true, + 'translate' => true, + ], + 'option' => [ + 'class' => true, + 'disabled' => true, + 'id' => true, + 'label' => true, + 'selected' => true, + 'value' => true, + ], + ]; + + // Add the global allowed attributes to each html element. + $input_tags = array_map( '_wp_add_global_attributes', $input_tags ); + } + + return array_merge_recursive( $allowed_post_tags, $input_tags ); + } + + /** + * Gets an array of enabled features. + * + * @return string[] The array of enabled features. + */ + public static function retrieve_enabled_features() { + /** + * The feature flag integration. + * + * @var Feature_Flag_Integration $feature_flag_integration; + */ + $feature_flag_integration = YoastSEO()->classes->get( Feature_Flag_Integration::class ); + return $feature_flag_integration->get_enabled_features(); + } + + /* ********************* DEPRECATED METHODS ********************* */ + + /** + * List all the available user roles. + * + * @since 1.8.0 + * @deprecated 15.0 + * @codeCoverageIgnore + * + * @return array + */ + public static function get_roles() { + _deprecated_function( __METHOD__, '15.0', 'wp_roles()->get_names()' ); + $yoast_seo_wp_roles = wp_roles(); + + $roles = $yoast_seo_wp_roles->get_names(); + + return $roles; + } + + /** + * Checks if the current installation supports MyYoast access tokens. + * + * @deprecated 15.0 + * @codeCoverageIgnore + * + * @return bool True if access_tokens are supported. + */ + public static function has_access_token_support() { + _deprecated_function( __METHOD__, 'WPSEO 15.0' ); + return false; + } + + /** + * Standardize whitespace in a string. + * + * Replace line breaks, carriage returns, tabs with a space, then remove double spaces. + * + * @since 1.8.0 + * @deprecated 15.2 + * @codeCoverageIgnore + * + * @param string $string String input to standardize. * * @return string */ - public static function get_icon_svg( $base64 = true ) { - $svg = ''; + public static function standardize_whitespace( $string ) { + _deprecated_function( __METHOD__, 'WPSEO 15.2' ); - if ( $base64 ) { - return 'data:image/svg+xml;base64,' . base64_encode( $svg ); + return YoastSEO()->helpers->string->standardize_whitespace( $string ); + } + + /** + * First strip out registered and enclosing shortcodes using native WordPress strip_shortcodes function. + * Then strip out the shortcodes with a filthy regex, because people don't properly register their shortcodes. + * + * @since 1.8.0 + * @deprecated 15.2 + * @codeCoverageIgnore + * + * @param string $text Input string that might contain shortcodes. + * + * @return string String without shortcodes. + */ + public static function strip_shortcode( $text ) { + _deprecated_function( __METHOD__, 'WPSEO 15.2' ); + + return YoastSEO()->helpers->string->strip_shortcode( $text ); + } + + /** + * Retrieves the title separator. + * + * @since 3.0.0 + * @deprecated 15.2 + * @codeCoverageIgnore + * + * @return string + */ + public static function get_title_separator() { + _deprecated_function( __METHOD__, 'WPSEO 15.2', 'Yoast\WP\SEO\Helpers\Options_Helper::get_title_separator' ); + + return YoastSEO()->helpers->options->get_title_separator(); + } + + /** + * Flush W3TC cache after successful update/add of taxonomy meta option. + * + * @since 1.8.0 + * @deprecated 15.3 + * @codeCoverageIgnore + */ + public static function flush_w3tc_cache() { + _deprecated_function( __METHOD__, 'WPSEO 15.3' ); + } + + /** + * Determines whether or not WooCommerce is active. + * + * @deprecated 15.3 + * @codeCoverageIgnore + * + * @return bool Whether or not WooCommerce is active. + */ + public static function is_woocommerce_active() { + _deprecated_function( __METHOD__, 'WPSEO 15.3' ); + + return YoastSEO()->helpers->woocommerce->is_active(); + } + + /** + * Outputs a Schema blob. + * + * @deprecated 15.5 + * @codeCoverageIgnore + * + * @param array $graph The Schema graph array to output. + * @param string $class The (optional) class to add to the script tag. + * + * @return bool + */ + public static function schema_output( $graph, $class = 'yoast-schema-graph' ) { + _deprecated_function( __METHOD__, 'WPSEO 15.5' ); + + if ( ! is_array( $graph ) || empty( $graph ) ) { + return false; } - return $svg; + // phpcs:ignore WordPress.Security.EscapeOutput -- Escaping happens in WPSEO_Utils::schema_tag, which should be whitelisted. + echo self::schema_tag( $graph, $class ); + return true; + } + + /** + * Returns a script tag with Schema blob. + * + * @deprecated 15.5 + * @codeCoverageIgnore + * + * @param array $graph The Schema graph array to output. + * @param string $class The (optional) class to add to the script tag. + * + * @return false|string A schema blob with script tags. + */ + public static function schema_tag( $graph, $class = 'yoast-schema-graph' ) { + _deprecated_function( __METHOD__, 'WPSEO 15.5' ); + + if ( ! is_array( $graph ) || empty( $graph ) ) { + return false; + } + + $output = [ + '@context' => 'https://schema.org', + '@graph' => $graph, + ]; + return "' . "\n"; } /** * Returns the SVG for the traffic light in the metabox. * + * @deprecated 15.5 + * @codeCoverageIgnore + * * @return string */ public static function traffic_light_svg() { - return <<', + '', + '', + WPSEO_Admin_Utils::get_new_tab_message() . '', + 'Yoast SEO', + 'my.yoast.com' + ); + + return; + } + + // Note: as of January 2020, the most recent cURL version is 7.67.0. + if ( ! $this->is_my_yoast_api_reachable() && ! $this->is_recent_curl_version() ) { + $this->label = sprintf( + /* translators: %1$s expands to 'Yoast'. */ + esc_html__( '%1$s premium plugins cannot update', 'wordpress-seo' ), + 'Yoast' + ); + $this->status = self::STATUS_CRITICAL; + $this->badge['color'] = 'red'; + $this->description = sprintf( + /* translators: %1$s Emphasis open tag, %2$s: Emphasis close tag, %3$s Link start tag to the Yoast help center, %4$s Link closing tag, %5$s to Yoast SEO, %6$s to my.yoast.com. */ + esc_html__( 'You can %1$snot%2$s activate your premium plugin(s) and receive updates because %5$s cannot connect to %6$s. The cause for this error is probably that the cURL software on your server is too old. Please contact your host and ask them to update it to at least version 7.34. %3$sRead more about cURL in our help center%4$s.', 'wordpress-seo' ), + '', + '', + '', + WPSEO_Admin_Utils::get_new_tab_message() . '', + 'Yoast SEO', + 'my.yoast.com' + ); + return; + } + + $this->label = sprintf( + /* translators: %1$s expands to 'Yoast'. */ + esc_html__( '%1$s premium plugin updates work fine', 'wordpress-seo' ), + 'Yoast' + ); + $this->status = self::STATUS_GOOD; + $this->badge['color'] = 'blue'; + $this->description = esc_html__( 'Great! You can activate your premium plugin(s) and receive updates.', 'wordpress-seo' ); + } + + /** + * Gets the current cURL version. + * + * @return string|bool The cURL version as a string or false if cURL is not installed. + */ + protected function get_curl_version() { + if ( function_exists( 'curl_version' ) ) { + $curl_version = curl_version(); + + if ( isset( $curl_version['version'] ) ) { + return $curl_version['version']; + } + } + + return false; + } + + /** + * Checks if the cURL version is a recent one. + * + * @return bool Whether the cURL version is a recent one. + */ + protected function is_recent_curl_version() { + $curl_version = $this->get_curl_version(); + + if ( $curl_version && version_compare( $curl_version, '7.34.0', '>=' ) ) { + return true; + } + + return false; + } + + /** + * Checks whether Yoast SEO Premium or premium add-ons are installed. + * + * @return bool Whether Yoast SEO Premium or premium add-ons are installed. + */ + protected function has_premium_plugins_installed() { + $addon_manager = new WPSEO_Addon_Manager(); + + return $addon_manager->has_installed_addons(); + } + + /** + * Checks whether the MyYoast API is reachable. + * + * @return bool Whether the MyYoast API is reachable. + */ + protected function is_my_yoast_api_reachable() { + $api_request = new WPSEO_MyYoast_Api_Request( 'sites/current' ); + + return $api_request->fire(); + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/health-check-default-tagline.php b/wp-content/plugins/wordpress-seo/inc/health-check-default-tagline.php new file mode 100644 index 00000000..d8a70c52 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/health-check-default-tagline.php @@ -0,0 +1,66 @@ +has_default_tagline() ) { + $this->label = esc_html__( 'You changed the default WordPress tagline', 'wordpress-seo' ); + $this->status = self::STATUS_GOOD; + $this->badge['color'] = 'blue'; + $this->description = esc_html__( 'You are using a custom tagline or an empty one.', 'wordpress-seo' ); + + return; + } + + $this->label = esc_html__( 'You should change the default WordPress tagline', 'wordpress-seo' ); + $this->status = self::STATUS_RECOMMENDED; + $this->badge['color'] = 'red'; + + $this->description = esc_html__( 'You still have the default WordPress tagline. Even an empty one is probably better.', 'wordpress-seo' ); + + $query_args = [ + 'autofocus[control]' => 'blogdescription', + ]; + $customize_url = add_query_arg( $query_args, wp_customize_url() ); + + $this->actions = sprintf( + /* translators: 1: link open tag; 2: link close tag. */ + esc_html__( '%1$sYou can change the tagline in the customizer%2$s.', 'wordpress-seo' ), + '', + '' + ); + } + + /** + * Returns whether or not the site has the default tagline. + * + * @return bool + */ + public function has_default_tagline() { + $blog_description = get_option( 'blogdescription' ); + $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; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/health-check-links-table-not-accessible.php b/wp-content/plugins/wordpress-seo/inc/health-check-links-table-not-accessible.php new file mode 100644 index 00000000..63fcd978 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/health-check-links-table-not-accessible.php @@ -0,0 +1,70 @@ +is_text_link_counter_enabled() ) { + return; + } + + if ( YoastSEO()->classes->get( Migration_Status::class )->is_version( 'free', WPSEO_VERSION ) ) { + $this->label = esc_html__( 'The text link counter is working as expected', 'wordpress-seo' ); + $this->status = self::STATUS_GOOD; + $this->badge['color'] = 'blue'; + $this->description = sprintf( + /* translators: 1: Link to the Yoast SEO blog, 2: Link closing tag. */ + esc_html__( 'The text link counter helps you improve your site structure. %1$sFind out how the text link counter can enhance your SEO%2$s.', 'wordpress-seo' ), + '', + WPSEO_Admin_Utils::get_new_tab_message() . '' + ); + + return; + } + + $this->label = esc_html__( 'The text link counter feature is not working as expected', 'wordpress-seo' ); + $this->status = self::STATUS_RECOMMENDED; + $this->badge['color'] = 'red'; + + $this->description = sprintf( + /* translators: 1: Yoast SEO. */ + esc_html__( 'For this feature to work, %1$s needs to create a table in your database. We were unable to create this table automatically.', 'wordpress-seo' ), + 'Yoast SEO' + ); + + $this->actions = sprintf( + /* translators: 1: Link to the Yoast help center, 2: Link closing tag. */ + esc_html__( '%1$sFind out how to solve this problem on our help center%2$s.', 'wordpress-seo' ), + '', + WPSEO_Admin_Utils::get_new_tab_message() . '' + ); + } + + /** + * Checks whether the text link counter feature is enabled. + * + * @return bool Whether the text link counter feature is enabled. + */ + protected function is_text_link_counter_enabled() { + return WPSEO_Options::get( 'enable_text_link_counter' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/health-check-page-comments.php b/wp-content/plugins/wordpress-seo/inc/health-check-page-comments.php new file mode 100644 index 00000000..7435f29f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/health-check-page-comments.php @@ -0,0 +1,52 @@ +has_page_comments() ) { + $this->label = esc_html__( 'Comments are displayed on a single page', 'wordpress-seo' ); + $this->status = self::STATUS_GOOD; + $this->badge['color'] = 'blue'; + $this->description = esc_html__( 'Comments on your posts are displayed on a single page. This is just like we\'d suggest it. You\'re doing well!', 'wordpress-seo' ); + return; + } + + $this->label = esc_html__( 'Comments break into multiple pages', 'wordpress-seo' ); + $this->status = self::STATUS_RECOMMENDED; + $this->badge['color'] = 'red'; + $this->description = esc_html__( 'Comments on your posts break into multiple pages. As this is not needed in 999 out of 1000 cases, we recommend you disable it. To fix this, uncheck "Break comments into pages..." on the Discussion Settings page.', 'wordpress-seo' ); + $this->actions = sprintf( + /* translators: 1: Opening tag of the link to the discussion settings page, 2: Link closing tag. */ + esc_html__( '%1$sGo to the Discussion Settings page%2$s', 'wordpress-seo' ), + '', + '' + ); + } + + /** + * Are page comments enabled. + * + * @return bool True when page comments are enabled. + */ + protected function has_page_comments() { + return get_option( 'page_comments' ) === '1'; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/health-check-postname-permalink.php b/wp-content/plugins/wordpress-seo/inc/health-check-postname-permalink.php new file mode 100644 index 00000000..c108ec48 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/health-check-postname-permalink.php @@ -0,0 +1,59 @@ +has_postname_in_permalink() ) { + $this->label = esc_html__( 'Your permalink structure includes the post name', 'wordpress-seo' ); + $this->status = self::STATUS_GOOD; + $this->badge['color'] = 'blue'; + $this->description = esc_html__( 'You do have your postname in the URL of your posts and pages.', 'wordpress-seo' ); + + return; + } + + $this->label = esc_html__( 'You do not have your postname in the URL of your posts and pages', 'wordpress-seo' ); + $this->status = self::STATUS_RECOMMENDED; + $this->badge['color'] = 'red'; + + $this->description = sprintf( + /* translators: %s expands to '/%postname%/' */ + __( 'It\'s highly recommended to have your postname in the URL of your posts and pages. Consider setting your permalink structure to %s.', 'wordpress-seo' ), + '/%postname%/' + ); + + $this->actions = sprintf( + /* translators: %1$s is a link start tag to the permalink settings page, %2$s is the link closing tag. */ + __( 'You can fix this on the %1$sPermalink settings page%2$s.', 'wordpress-seo' ), + '', + '' + ); + } + + /** + * Check if the permalink uses %postname%. + * + * @return bool + */ + private function has_postname_in_permalink() { + return ( strpos( get_option( 'permalink_structure' ), '%postname%' ) !== false ); + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/health-check-ryte.php b/wp-content/plugins/wordpress-seo/inc/health-check-ryte.php new file mode 100644 index 00000000..c4c9c20c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/health-check-ryte.php @@ -0,0 +1,259 @@ +should_run() ) { + return; + } + + /* + * Run the request to fetch the indexability status. Set last fetch time. + * Update the Ryte option status. Will run a new request only if the last + * one is not within the `WPSEO_Ryte_Option::FETCH_LIMIT` time interval. + */ + $wpseo_ryte = new WPSEO_Ryte(); + $wpseo_ryte->fetch_from_ryte(); + + // Get the Ryte API response to properly handle errors. + $response = $wpseo_ryte->get_response(); + + if ( is_array( $response ) && isset( $response['is_error'] ) ) { + $this->response_error( $response ); + + return; + } + + // The request was successful: get the updated Ryte option. + $ryte_option = $this->get_ryte_option(); + + switch ( $ryte_option->get_status() ) { + case WPSEO_Ryte_Option::IS_NOT_INDEXABLE: + $this->is_not_indexable_response(); + break; + case WPSEO_Ryte_Option::IS_INDEXABLE: + $this->is_indexable_response(); + break; + case WPSEO_Ryte_Option::NOT_FETCHED: + default: // WPSEO_Ryte_Option::CANNOT_FETCH. + $this->unknown_indexability_response(); + break; + } + } + + /** + * Checks whether the Ryte Site Health check should run. + * + * Checks for the WordPress environment type, checks if Ryte integration is + * enabled, the blog is public, and the Yoast SEO environment is not development mode. + * + * @return bool Whether the Ryte Site Health check should run. + */ + protected function should_run() { + if ( wp_get_environment_type() !== 'production' ) { + return false; + } + + $ryte_option = $this->get_ryte_option(); + if ( ! $ryte_option->is_enabled() ) { + return false; + } + + if ( get_option( 'blog_public' ) === '0' ) { + return false; + } + + return ! $this->is_development_mode(); + } + + /** + * Checks if debug mode is on but Yoast development mode is not on (i.e. for non-Yoast developers). + * + * @return bool True when debug mode is on and Yoast development mode is not on. + */ + protected function is_development_mode() { + return wp_debug_mode() && ! WPSEO_Utils::is_development_mode(); + } + + /** + * Returns a new instance of WPSEO_Ryte_Option. + * + * @return WPSEO_Ryte_Option New Ryte Option. + */ + protected function get_ryte_option() { + return new WPSEO_Ryte_Option(); + } + + /** + * Adds the content for a failed Ryte API request. + * + * @param array $response The error details. + * + * @return void + */ + protected function response_error( $response ) { + $this->label = esc_html__( 'An error occurred while checking whether your site can be found by search engines', 'wordpress-seo' ); + $this->status = self::STATUS_RECOMMENDED; + $this->badge['color'] = 'red'; + + $this->description = sprintf( + '%s

    %s', + sprintf( + /* translators: %1$s: Expands to 'Ryte', %2$s: Expands to 'Yoast SEO'. */ + esc_html__( '%1$s offers a free indexability check for %2$s users. The request to %1$s to check whether your site can be found by search engines failed due to an error.', 'wordpress-seo' ), + 'Ryte', + 'Yoast SEO' + ), + sprintf( + /* translators: 1: The Ryte response raw error code, if any. 2: The error message. 3: The WordPress error code, if any. */ + __( 'Error details: %1$s %2$s %3$s', 'wordpress-seo' ), + $response['raw_error_code'], + $response['message'], + $response['wp_error_code'] + ) + ); + + $this->actions = sprintf( + /* translators: %1$s: Opening tag of the link to the Yoast help center, %2$s: Link closing tag. */ + esc_html__( 'If this is a live site, %1$sit is recommended that you figure out why the check failed.%2$s', 'wordpress-seo' ), + '', + WPSEO_Admin_Utils::get_new_tab_message() . '' + ); + $this->actions .= '

    '; + + $this->add_ryte_link(); + } + + /** + * Adds the content for the "Cannot be indexed" response. + * + * @return void + */ + protected function is_not_indexable_response() { + $this->label = esc_html__( 'Your site cannot be found by search engines', 'wordpress-seo' ); + $this->status = self::STATUS_CRITICAL; + $this->badge['color'] = 'red'; + + $this->description = sprintf( + /* translators: %1$s: Expands to 'Ryte', %2$s: Expands to 'Yoast SEO'. */ + esc_html__( '%1$s offers a free indexability check for %2$s users and it has determined that your site cannot be found by search engines. If this site is live or about to become live, this should be fixed.', 'wordpress-seo' ), + 'Ryte', + 'Yoast SEO' + ); + + $this->actions = sprintf( + /* translators: %1$s: Opening tag of the link to the Yoast help center, %2$s: Link closing tag. */ + esc_html__( '%1$sRead more about troubleshooting search engine visibility.%2$s', 'wordpress-seo' ), + '', + WPSEO_Admin_Utils::get_new_tab_message() . '' + ); + $this->actions .= '

    '; + + $this->add_ryte_link(); + } + + /** + * Adds the content for the "Cannot tell if it can be indexed" response. + * + * @return void + */ + protected function unknown_indexability_response() { + $this->label = sprintf( + /* translators: %1$s: Expands to 'Ryte'. */ + esc_html__( '%1$s cannot determine whether your site can be found by search engines', 'wordpress-seo' ), + 'Ryte' + ); + $this->status = self::STATUS_RECOMMENDED; + $this->badge['color'] = 'red'; + + /* translators: %1$s: Expands to 'Ryte', %2$s: Expands to 'Yoast SEO'. */ + $description = esc_html__( + '%1$s offers a free indexability check for %2$s users and right now it has trouble determining + whether search engines can find your site. This could have several (legitimate) reasons and + is not a problem in itself. If this is a live site, it is recommended that you figure out why + the %1$s check failed.', + 'wordpress-seo' + ); + $this->description = sprintf( + $description, + 'Ryte', + 'Yoast SEO' + ); + $this->description .= '
    '; + + /* translators: %1$s: Expands to 'Ryte', %2$s: Link start tag to the Yoast help center, %3$s: Link closing tag. */ + $alert_text = esc_html__( + 'As the indexability status of your website can only be fetched from %1$s every 15 seconds, + a first step could be to wait at least 15 seconds and refresh the Site Health page. If that did not help, + %2$sread more about troubleshooting search engine visibility%3$s.', + 'wordpress-seo' + ); + $alert_content = sprintf( + $alert_text, + 'Ryte', + '', + WPSEO_Admin_Utils::get_new_tab_message() . '' + ); + + $alert = new Alert_Presenter( $alert_content, 'info' ); + $this->description .= $alert->present(); + + $this->add_ryte_link(); + } + + /** + * Adds the content for the "Can be indexed" response. + * + * @return void + */ + protected function is_indexable_response() { + $this->label = esc_html__( 'Your site can be found by search engines', 'wordpress-seo' ); + $this->status = self::STATUS_GOOD; + $this->badge['color'] = 'blue'; + + /* translators: %1$s: Expands to 'Ryte', %2$s: Expands to 'Yoast SEO'. */ + $description = esc_html__( + '%1$s offers a free indexability check for %2$s users, and it shows that your site can be found by search engines.', + 'wordpress-seo' + ); + $this->description = sprintf( $description, 'Ryte', 'Yoast SEO' ); + } + + /** + * Adds the link to the Ryte site to the actions. + * + * @return void + */ + protected function add_ryte_link() { + $this->actions .= sprintf( + /* translators: %1$s: Opening tag of the link to the Yoast Ryte website, %2$s: Expands to 'Ryte', %3$s: Link closing tag. */ + esc_html__( '%1$sGo to %2$s to analyze your entire site%3$s', 'wordpress-seo' ), + '', + 'Ryte', + WPSEO_Admin_Utils::get_new_tab_message() . '' + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/health-check.php b/wp-content/plugins/wordpress-seo/inc/health-check.php new file mode 100644 index 00000000..6e0d905a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/health-check.php @@ -0,0 +1,214 @@ + '', + 'color' => '', + ]; + + /** + * Additional details about the results of the test. + * + * @var string + */ + protected $description = ''; + + /** + * A link or button to allow the end user to take action on the result. + * + * @var string + */ + protected $actions = ''; + + /** + * The name of the test. + * + * @var string + */ + protected $test = ''; + + /** + * Whether or not the test should be ran on AJAX as well. + * + * @var bool True when is async, default false. + */ + protected $async = false; + + /** + * Runs the test and returns the result. + */ + abstract public function run(); + + /** + * Registers the test to WordPress. + */ + public function register_test() { + if ( $this->is_async() ) { + add_filter( 'site_status_tests', [ $this, 'add_async_test' ] ); + + add_action( 'wp_ajax_health-check-' . $this->get_test_name(), [ $this, 'get_async_test_result' ] ); + + return; + } + + add_filter( 'site_status_tests', [ $this, 'add_test' ] ); + } + + /** + * Runs the test. + * + * @param array $tests Array with the current tests. + * + * @return array The extended array. + */ + public function add_test( $tests ) { + $tests['direct'][ $this->get_test_name() ] = [ + 'test' => [ $this, 'get_test_result' ], + ]; + + return $tests; + } + + /** + * Runs the test in async mode. + * + * @param array $tests Array with the current tests. + * + * @return array The extended array. + */ + public function add_async_test( $tests ) { + $tests['async'][ $this->get_test_name() ] = [ + 'test' => $this->get_test_name(), + ]; + + return $tests; + } + + /** + * Formats the test result as an array. + * + * @return array The formatted test result. + */ + public function get_test_result() { + $this->run(); + $this->add_yoast_signature(); + + return [ + 'label' => $this->label, + 'status' => $this->status, + 'badge' => $this->get_badge(), + 'description' => $this->description, + 'actions' => $this->actions, + 'test' => $this->test, + ]; + } + + /** + * Formats the test result as an array. + */ + public function get_async_test_result() { + wp_send_json_success( $this->get_test_result() ); + } + + /** + * Retrieves the badge and ensure usable values are set. + * + * @return array The proper formatted badge. + */ + protected function get_badge() { + if ( ! is_array( $this->badge ) ) { + $this->badge = []; + } + + if ( empty( $this->badge['label'] ) ) { + $this->badge['label'] = __( 'SEO', 'wordpress-seo' ); + } + + if ( empty( $this->badge['color'] ) ) { + $this->badge['color'] = 'green'; + } + + return $this->badge; + } + + /** + * WordPress converts the underscores to dashes. To prevent issues we have + * to do it as well. + * + * @return string The formatted testname. + */ + protected function get_test_name() { + return str_replace( '_', '-', $this->test ); + } + + /** + * Checks if the health check is async. + * + * @return bool True when check is async. + */ + protected function is_async() { + return ! empty( $this->async ); + } + + /** + * Adds a text to the bottom of the Site Health check to indicate it is a Yoast SEO Site Health Check. + */ + protected function add_yoast_signature() { + $this->actions .= sprintf( + /* translators: 1: Start of a paragraph beginning with the Yoast icon, 2: Expands to 'Yoast SEO', 3: Paragraph closing tag. */ + esc_html__( '%1$sThis was reported by the %2$s plugin%3$s', 'wordpress-seo' ), + '

    ', + 'Yoast SEO', + '

    ' + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/interface-wpseo-wordpress-ajax-integration.php b/wp-content/plugins/wordpress-seo/inc/interface-wpseo-wordpress-ajax-integration.php new file mode 100644 index 00000000..efb23d5b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/inc/interface-wpseo-wordpress-ajax-integration.php @@ -0,0 +1,19 @@ + esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/3r3' ) ), + /* translators: 1: expands to a link opening tag; 2: expands to a link closing tag */ + 'message' => esc_html__( + 'A company name and logo need to be set for structured data to work properly. %1$sLearn more about the importance of structured data.%2$s', + 'wordpress-seo' + ), + ]; + } } diff --git a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-ms.php b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-ms.php index c57b33ef..b7b69bcb 100644 --- a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-ms.php +++ b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-ms.php @@ -14,52 +14,58 @@ class WPSEO_Option_MS extends WPSEO_Option { /** - * @var string option name + * Option name. + * + * @var string */ public $option_name = 'wpseo_ms'; /** - * @var string option group name for use in settings forms + * Option group name for use in settings forms. + * + * @var string */ public $group_name = 'yoast_wpseo_multisite_options'; /** - * @var bool whether to include the option in the return for WPSEO_Options::get_all() + * Whether to include the option in the return for WPSEO_Options::get_all(). + * + * @var bool */ public $include_in_all = false; /** - * @var bool whether this option is only for when the install is multisite + * Whether this option is only for when the install is multisite. + * + * @var bool */ public $multisite_only = true; /** - * @var array Array of defaults for the option - * Shouldn't be requested directly, use $this->get_defaults(); + * Array of defaults for the option. + * + * Shouldn't be requested directly, use $this->get_defaults(); + * + * @var array */ - protected $defaults = array( - 'access' => 'admin', - 'defaultblog' => '', // Numeric blog ID or empty. - ); + protected $defaults = []; /** - * @var array $allowed_access_options Available options for the 'access' setting - * Used for input validation - * - * @static + * Available options for the 'access' setting. Used for input validation. * * {@internal Important: Make sure the options added to the array here are in line * with the keys for the options set for the select box in the * admin/pages/network.php file.}} + * + * @var array */ - public static $allowed_access_options = array( + public static $allowed_access_options = [ 'admin', 'superadmin', - ); - + ]; /** - * Get the singleton instance of this class + * Get the singleton instance of this class. * * @return object */ @@ -75,70 +81,88 @@ class WPSEO_Option_MS extends WPSEO_Option { * Only run parent constructor in multisite context. */ public function __construct() { + $allow_prefix = self::ALLOW_KEY_PREFIX; + $this->defaults = [ + 'access' => 'admin', + 'defaultblog' => '', // Numeric blog ID or empty. + "{$allow_prefix}disableadvanced_meta" => true, + "{$allow_prefix}ryte_indexability" => true, + "{$allow_prefix}content_analysis_active" => true, + "{$allow_prefix}keyword_analysis_active" => true, + "{$allow_prefix}enable_admin_bar_menu" => true, + "{$allow_prefix}enable_cornerstone_content" => true, + "{$allow_prefix}enable_xml_sitemap" => true, + "{$allow_prefix}enable_text_link_counter" => true, + "{$allow_prefix}enable_headless_rest_endpoints" => true, + "{$allow_prefix}enable_metabox_insights" => true, + "{$allow_prefix}enable_link_suggestions" => true, + "{$allow_prefix}tracking" => true, + "{$allow_prefix}enable_enhanced_slack_sharing" => true, + "{$allow_prefix}semrush_integration_active" => true, + "{$allow_prefix}zapier_integration_active" => true, + ]; + if ( is_multisite() ) { parent::__construct(); + + add_filter( 'admin_title', [ 'Yoast_Input_Validation', 'add_yoast_admin_document_title_errors' ] ); } } /** * Add filters to make sure that the option default is returned if the option is not set * - * @return void + * @return void */ public function add_default_filters() { // Don't change, needs to check for false as could return prio 0 which would evaluate to false. - if ( has_filter( 'default_site_option_' . $this->option_name, array( $this, 'get_defaults' ) ) === false ) { - add_filter( 'default_site_option_' . $this->option_name, array( $this, 'get_defaults' ) ); + if ( has_filter( 'default_site_option_' . $this->option_name, [ $this, 'get_defaults' ] ) === false ) { + add_filter( 'default_site_option_' . $this->option_name, [ $this, 'get_defaults' ] ); } } - /** * Remove the default filters. - * Called from the validate() method to prevent failure to add new options + * Called from the validate() method to prevent failure to add new options. * - * @return void + * @return void */ public function remove_default_filters() { - remove_filter( 'default_site_option_' . $this->option_name, array( $this, 'get_defaults' ) ); + remove_filter( 'default_site_option_' . $this->option_name, [ $this, 'get_defaults' ] ); } - /** - * Add filters to make sure that the option is merged with its defaults before being returned + * Add filters to make sure that the option is merged with its defaults before being returned. * - * @return void + * @return void */ public function add_option_filters() { // Don't change, needs to check for false as could return prio 0 which would evaluate to false. - if ( has_filter( 'site_option_' . $this->option_name, array( $this, 'get_option' ) ) === false ) { - add_filter( 'site_option_' . $this->option_name, array( $this, 'get_option' ) ); + if ( has_filter( 'site_option_' . $this->option_name, [ $this, 'get_option' ] ) === false ) { + add_filter( 'site_option_' . $this->option_name, [ $this, 'get_option' ] ); } } - /** * Remove the option filters. - * Called from the clean_up methods to make sure we retrieve the original old option + * Called from the clean_up methods to make sure we retrieve the original old option. * - * @return void + * @return void */ public function remove_option_filters() { - remove_filter( 'site_option_' . $this->option_name, array( $this, 'get_option' ) ); + remove_filter( 'site_option_' . $this->option_name, [ $this, 'get_option' ] ); } - /* *********** METHODS influencing add_uption(), update_option() and saving from admin pages *********** */ - /** - * Validate the option + * Validate the option. * - * @param array $dirty New value for the option. - * @param array $clean Clean value for the option, normally the defaults. - * @param array $old Old value of the option. + * @param array $dirty New value for the option. + * @param array $clean Clean value for the option, normally the defaults. + * @param array $old Old value of the option. * - * @return array Validated clean value for the option to be saved to the database + * @return array Validated clean value for the option to be saved to the database. */ protected function validate_option( $dirty, $clean, $old ) { @@ -151,10 +175,10 @@ class WPSEO_Option_MS extends WPSEO_Option { elseif ( function_exists( 'add_settings_error' ) ) { add_settings_error( $this->group_name, // Slug title of the setting. - '_' . $key, // Suffix-id for the error message box. + $key, // Suffix-ID for the error message box. /* translators: %1$s expands to the option name and %2$sexpands to Yoast SEO */ sprintf( __( '%1$s is not a valid choice for who should be allowed access to the %2$s settings. Value reset to the default.', 'wordpress-seo' ), esc_html( sanitize_text_field( $dirty[ $key ] ) ), 'Yoast SEO' ), // The error message. - 'error' // Error type, either 'error' or 'updated'. + 'error' // Message type. ); } break; @@ -172,7 +196,7 @@ class WPSEO_Option_MS extends WPSEO_Option { elseif ( function_exists( 'add_settings_error' ) ) { add_settings_error( $this->group_name, // Slug title of the setting. - '_' . $key, // Suffix-id for the error message box. + $key, // Suffix-ID for the error message box. esc_html__( 'The default blog setting must be the numeric blog id of the blog you want to use as default.', 'wordpress-seo' ) . '
    ' . sprintf( @@ -180,7 +204,7 @@ class WPSEO_Option_MS extends WPSEO_Option { esc_html__( 'This must be an existing blog. Blog %s does not exist or has been marked as deleted.', 'wordpress-seo' ), '' . esc_html( sanitize_text_field( $dirty[ $key ] ) ) . '' ), // The error message. - 'error' // Error type, either 'error' or 'updated'. + 'error' // Message type. ); } unset( $exists ); @@ -188,9 +212,9 @@ class WPSEO_Option_MS extends WPSEO_Option { elseif ( function_exists( 'add_settings_error' ) ) { add_settings_error( $this->group_name, // Slug title of the setting. - '_' . $key, // Suffix-id for the error message box. + $key, // Suffix-ID for the error message box. esc_html__( 'The default blog setting must be the numeric blog id of the blog you want to use as default.', 'wordpress-seo' ) . '
    ' . esc_html__( 'No numeric value was received.', 'wordpress-seo' ), // The error message. - 'error' // Error type, either 'error' or 'updated'. + 'error' // Message type. ); } unset( $int ); @@ -205,25 +229,4 @@ class WPSEO_Option_MS extends WPSEO_Option { return $clean; } - - - /** - * Clean a given option value - * - * @param array $option_value Old (not merged with defaults or filtered) option value to - * clean according to the rules for this option. - * @param string $current_version (optional) Version from which to upgrade, if not set, - * version specific upgrades will be disregarded. - * @param array $all_old_option_values (optional) Only used when importing old options to have - * access to the real old values, in contrast to the saved ones. - * - * @return array Cleaned option - */ - - /* - Protected function clean_option( $option_value, $current_version = null, $all_old_option_values = null ) { - - return $option_value; - } - */ } diff --git a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-social.php b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-social.php index 2353fb4f..82f934bf 100644 --- a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-social.php +++ b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-social.php @@ -11,56 +11,63 @@ class WPSEO_Option_Social extends WPSEO_Option { /** - * @var string Option name. + * Option name. + * + * @var string */ public $option_name = 'wpseo_social'; /** - * @var array Array of defaults for the option. - * Shouldn't be requested directly, use $this->get_defaults(); + * Array of defaults for the option. + * + * Shouldn't be requested directly, use $this->get_defaults(); + * + * @var array */ - protected $defaults = array( + protected $defaults = [ // Form fields. - 'facebook_site' => '', // Text field. - 'instagram_url' => '', - 'linkedin_url' => '', - 'myspace_url' => '', - 'og_default_image' => '', // Text field. - 'og_frontpage_title' => '', // Text field. - 'og_frontpage_desc' => '', // Text field. - 'og_frontpage_image' => '', // Text field. - 'opengraph' => true, - 'pinterest_url' => '', - 'pinterestverify' => '', - 'plus-publisher' => '', // Text field. - 'twitter' => true, - 'twitter_site' => '', // Text field. - 'twitter_card_type' => 'summary_large_image', - 'youtube_url' => '', - 'google_plus_url' => '', - // Form field, but not always available. - 'fbadminapp' => '', // Facebook app ID. - ); + 'facebook_site' => '', // Text field. + 'instagram_url' => '', + 'linkedin_url' => '', + 'myspace_url' => '', + 'og_default_image' => '', // Text field. + 'og_default_image_id' => '', + 'og_frontpage_title' => '', // Text field. + 'og_frontpage_desc' => '', // Text field. + 'og_frontpage_image' => '', // Text field. + 'og_frontpage_image_id' => '', + 'opengraph' => true, + 'pinterest_url' => '', + 'pinterestverify' => '', + 'twitter' => true, + 'twitter_site' => '', // Text field. + 'twitter_card_type' => 'summary_large_image', + 'youtube_url' => '', + 'wikipedia_url' => '', + ]; /** - * @var array Array of sub-options which should not be overloaded with multi-site defaults. + * Array of sub-options which should not be overloaded with multi-site defaults. + * + * @var array */ - public $ms_exclude = array( + public $ms_exclude = [ /* Privacy. */ 'pinterestverify', - 'fbadminapp', - ); - + ]; /** - * @var array Array of allowed twitter card types. - * While we only have the options summary and summary_large_image in the - * interface now, we might change that at some point. + * Array of allowed twitter card types. + * + * While we only have the options summary and summary_large_image in the + * interface now, we might change that at some point. * * {@internal Uncomment any of these to allow them in validation *and* automatically * add them as a choice in the options page.}} + * + * @var array */ - public static $twitter_card_types = array( + public static $twitter_card_types = [ 'summary' => '', 'summary_large_image' => '', // 'photo' => '', @@ -68,8 +75,16 @@ class WPSEO_Option_Social extends WPSEO_Option { // 'app' => '', // 'player' => '', // 'product' => '', - ); + ]; + /** + * Add the actions and filters for the option. + */ + protected function __construct() { + parent::__construct(); + + add_filter( 'admin_title', [ 'Yoast_Input_Validation', 'add_yoast_admin_document_title_errors' ] ); + } /** * Get the singleton instance of this class. @@ -97,17 +112,17 @@ class WPSEO_Option_Social extends WPSEO_Option { /** * Validate the option. * - * @param array $dirty New value for the option. - * @param array $clean Clean value for the option, normally the defaults. - * @param array $old Old value of the option. + * @param array $dirty New value for the option. + * @param array $clean Clean value for the option, normally the defaults. + * @param array $old Old value of the option. * - * @return array Validated clean value for the option to be saved to the database. + * @return array Validated clean value for the option to be saved to the database. */ protected function validate_option( $dirty, $clean, $old ) { foreach ( $clean as $key => $value ) { switch ( $key ) { - /* text fields */ + /* Text fields. */ case 'og_frontpage_desc': case 'og_frontpage_title': if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) { @@ -115,6 +130,16 @@ class WPSEO_Option_Social extends WPSEO_Option { } break; + case 'og_default_image_id': + case 'og_frontpage_image_id': + if ( isset( $dirty[ $key ] ) ) { + $clean[ $key ] = (int) $dirty[ $key ]; + + if ( $dirty[ $key ] === '' ) { + $clean[ $key ] = $dirty[ $key ]; + } + } + break; /* URL text fields - no ftp allowed. */ case 'facebook_site': @@ -122,11 +147,10 @@ class WPSEO_Option_Social extends WPSEO_Option { case 'linkedin_url': case 'myspace_url': case 'pinterest_url': - case 'plus-publisher': case 'og_default_image': case 'og_frontpage_image': case 'youtube_url': - case 'google_plus_url': + case 'wikipedia_url': $this->validate_url( $key, $dirty, $old, $clean ); break; @@ -134,11 +158,12 @@ class WPSEO_Option_Social extends WPSEO_Option { $this->validate_verification_string( $key, $dirty, $old, $clean ); break; - /* twitter user name */ + /* Twitter user name. */ case 'twitter_site': if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) { $twitter_id = sanitize_text_field( ltrim( $dirty[ $key ], '@' ) ); - /** + + /* * From the Twitter documentation about twitter screen names: * Typically a maximum of 15 characters long, but some historical accounts * may exist with longer names. @@ -146,7 +171,6 @@ class WPSEO_Option_Social extends WPSEO_Option { * with the exception of underscores. * * @link https://support.twitter.com/articles/101299-why-can-t-i-register-certain-usernames - * @link https://dev.twitter.com/docs/platform-objects/users */ if ( preg_match( '`^[A-Za-z0-9_]{1,25}$`', $twitter_id ) ) { $clean[ $key ] = $twitter_id; @@ -164,17 +188,19 @@ class WPSEO_Option_Social extends WPSEO_Option { if ( function_exists( 'add_settings_error' ) ) { add_settings_error( $this->group_name, // Slug title of the setting. - '_' . $key, // Suffix-id for the error message box. + $key, // Suffix-ID for the error message box. sprintf( /* translators: %s expands to a twitter user name. */ - __( '%s does not seem to be a valid Twitter user-id. Please correct.', 'wordpress-seo' ), + __( '%s does not seem to be a valid Twitter Username. Please correct.', 'wordpress-seo' ), '' . esc_html( sanitize_text_field( $dirty[ $key ] ) ) . '' ), // The error message. - 'error' // Error type, either 'error' or 'updated'. + 'error' // Message type. ); } } unset( $twitter_id ); + + Yoast_Input_Validation::add_dirty_value_to_settings_errors( $key, $dirty[ $key ] ); } break; @@ -184,35 +210,28 @@ class WPSEO_Option_Social extends WPSEO_Option { } break; - /* boolean fields */ + /* Boolean fields. */ case 'opengraph': case 'twitter': $clean[ $key ] = ( isset( $dirty[ $key ] ) ? WPSEO_Utils::validate_bool( $dirty[ $key ] ) : false ); break; - - case 'fbadminapp' : - if ( isset( $dirty[ $key ] ) && ! empty( $dirty[ $key ] ) ) { - $clean[ $key ] = $dirty[ $key ]; - } - break; } } return $clean; } - /** * Clean a given option value. * - * @param array $option_value Old (not merged with defaults or filtered) option value to - * clean according to the rules for this option. - * @param string $current_version Optional. Version from which to upgrade, if not set, - * version specific upgrades will be disregarded. - * @param array $all_old_option_values Optional. Only used when importing old options to have - * access to the real old values, in contrast to the saved ones. + * @param array $option_value Old (not merged with defaults or filtered) option value to + * clean according to the rules for this option. + * @param string|null $current_version Optional. Version from which to upgrade, if not set, + * version specific upgrades will be disregarded. + * @param array|null $all_old_option_values Optional. Only used when importing old options to have + * access to the real old values, in contrast to the saved ones. * - * @return array Cleaned option. + * @return array Cleaned option. */ protected function clean_option( $option_value, $current_version = null, $all_old_option_values = null ) { @@ -220,7 +239,7 @@ class WPSEO_Option_Social extends WPSEO_Option { $old_option = null; if ( isset( $all_old_option_values ) ) { // Ok, we have an import. - if ( isset( $all_old_option_values['wpseo_indexation'] ) && is_array( $all_old_option_values['wpseo_indexation'] ) && $all_old_option_values['wpseo_indexation'] !== array() ) { + if ( isset( $all_old_option_values['wpseo_indexation'] ) && is_array( $all_old_option_values['wpseo_indexation'] ) && $all_old_option_values['wpseo_indexation'] !== [] ) { $old_option = $all_old_option_values['wpseo_indexation']; } } @@ -228,10 +247,10 @@ class WPSEO_Option_Social extends WPSEO_Option { $old_option = get_option( 'wpseo_indexation' ); } - if ( is_array( $old_option ) && $old_option !== array() ) { - $move = array( + if ( is_array( $old_option ) && $old_option !== [] ) { + $move = [ 'opengraph', - ); + ]; foreach ( $move as $key ) { if ( isset( $old_option[ $key ] ) && ! isset( $option_value[ $key ] ) ) { $option_value[ $key ] = $old_option[ $key ]; diff --git a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-titles.php b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-titles.php index 4e93af7e..d7c3c2c8 100644 --- a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-titles.php +++ b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-titles.php @@ -5,129 +5,151 @@ * @package WPSEO\Internals\Options */ +use Yoast\WP\SEO\Config\Schema_Types; + /** * Option: wpseo_titles. */ class WPSEO_Option_Titles extends WPSEO_Option { /** - * @var string Option name. + * Option name. + * + * @var string */ public $option_name = 'wpseo_titles'; /** - * @var array Array of defaults for the option. - * Shouldn't be requested directly, use $this->get_defaults(); + * Array of defaults for the option. + * + * Shouldn't be requested directly, use $this->get_defaults(); * * {@internal Note: Some of the default values are added via the translate_defaults() method.}} + * + * @var array */ - protected $defaults = array( - // Non-form fields, set via (ajax) function. - 'title_test' => 0, + protected $defaults = [ // Form fields. - 'forcerewritetitle' => false, - 'separator' => 'sc-dash', - 'title-home-wpseo' => '%%sitename%% %%page%% %%sep%% %%sitedesc%%', // Text field. - 'title-author-wpseo' => '', // Text field. - 'title-archive-wpseo' => '%%date%% %%page%% %%sep%% %%sitename%%', // Text field. - 'title-search-wpseo' => '', // Text field. - 'title-404-wpseo' => '', // Text field. + 'forcerewritetitle' => false, + 'separator' => 'sc-dash', + 'title-home-wpseo' => '%%sitename%% %%page%% %%sep%% %%sitedesc%%', // Text field. + 'title-author-wpseo' => '', // Text field. + 'title-archive-wpseo' => '%%date%% %%page%% %%sep%% %%sitename%%', // Text field. + 'title-search-wpseo' => '', // Text field. + 'title-404-wpseo' => '', // Text field. - 'metadesc-home-wpseo' => '', // Text area. - 'metadesc-author-wpseo' => '', // Text area. - 'metadesc-archive-wpseo' => '', // Text area. - 'rssbefore' => '', // Text area. - 'rssafter' => '', // Text area. + 'social-title-author-wpseo' => '%%name%%', // Text field. + 'social-title-archive-wpseo' => '%%date%%', // Text field. + 'social-description-author-wpseo' => '', // Text area. + 'social-description-archive-wpseo' => '', // Text area. + 'social-image-url-author-wpseo' => '', // Hidden input field. + 'social-image-url-archive-wpseo' => '', // Hidden input field. + 'social-image-id-author-wpseo' => 0, // Hidden input field. + 'social-image-id-archive-wpseo' => 0, // Hidden input field. - 'noindex-author-wpseo' => false, - 'noindex-author-noposts-wpseo' => true, - 'noindex-archive-wpseo' => true, + 'metadesc-home-wpseo' => '', // Text area. + 'metadesc-author-wpseo' => '', // Text area. + 'metadesc-archive-wpseo' => '', // Text area. + 'rssbefore' => '', // Text area. + 'rssafter' => '', // Text area. - 'disable-author' => false, - 'disable-date' => false, - 'disable-post_format' => false, - 'disable-attachment' => true, + 'noindex-author-wpseo' => false, + 'noindex-author-noposts-wpseo' => true, + 'noindex-archive-wpseo' => true, - 'breadcrumbs-404crumb' => '', // Text field. - 'breadcrumbs-display-blog-page' => true, - 'breadcrumbs-boldlast' => false, - 'breadcrumbs-archiveprefix' => '', // Text field. - 'breadcrumbs-enable' => false, - 'breadcrumbs-home' => '', // Text field. - 'breadcrumbs-prefix' => '', // Text field. - 'breadcrumbs-searchprefix' => '', // Text field. - 'breadcrumbs-sep' => '»', // Text field. + 'disable-author' => false, + 'disable-date' => false, + 'disable-post_format' => false, + 'disable-attachment' => true, - 'website_name' => '', - 'person_name' => '', - 'alternate_website_name' => '', - 'company_logo' => '', - 'company_name' => '', - 'company_or_person' => '', + 'breadcrumbs-404crumb' => '', // Text field. + 'breadcrumbs-display-blog-page' => true, + 'breadcrumbs-boldlast' => false, + 'breadcrumbs-archiveprefix' => '', // Text field. + 'breadcrumbs-enable' => true, + 'breadcrumbs-home' => '', // Text field. + 'breadcrumbs-prefix' => '', // Text field. + 'breadcrumbs-searchprefix' => '', // Text field. + 'breadcrumbs-sep' => '»', // Text field. - 'stripcategorybase' => false, + 'website_name' => '', + 'person_name' => '', + 'person_logo' => '', + 'person_logo_id' => 0, + 'alternate_website_name' => '', + 'company_logo' => '', + 'company_logo_id' => 0, + 'company_logo_meta' => false, + 'person_logo_meta' => false, + 'company_name' => '', + 'company_or_person' => 'company', + 'company_or_person_user_id' => false, - /** + 'stripcategorybase' => false, + + 'open_graph_frontpage_title' => '%%sitename%%', // Text field. + 'open_graph_frontpage_desc' => '', // Text field. + 'open_graph_frontpage_image' => '', // Text field. + 'open_graph_frontpage_image_id' => 0, + + /* * Uses enrich_defaults to add more along the lines of: - * - 'title-' . $pt->name => ''; // Text field. - * - 'metadesc-' . $pt->name => ''; // Text field. - * - 'noindex-' . $pt->name => false; - * - 'showdate-' . $pt->name => false; - * - 'display-metabox-pt-' . $pt->name => false; + * - 'title-' . $pt->name => ''; // Text field. + * - 'metadesc-' . $pt->name => ''; // Text field. + * - 'noindex-' . $pt->name => false; + * - 'display-metabox-pt-' . $pt->name => false; * - * - 'title-ptarchive-' . $pt->name => ''; // Text field. - * - 'metadesc-ptarchive-' . $pt->name => ''; // Text field. - * - 'bctitle-ptarchive-' . $pt->name => ''; // Text field. - * - 'noindex-ptarchive-' . $pt->name => false; + * - 'title-ptarchive-' . $pt->name => ''; // Text field. + * - 'metadesc-ptarchive-' . $pt->name => ''; // Text field. + * - 'bctitle-ptarchive-' . $pt->name => ''; // Text field. + * - 'noindex-ptarchive-' . $pt->name => false; * - * - 'title-tax-' . $tax->name => '''; // Text field. - * - 'metadesc-tax-' . $tax->name => ''; // Text field. - * - 'noindex-tax-' . $tax->name => false; - * - 'display-metabox-tax-' . $tax->name => false; + * - 'title-tax-' . $tax->name => '''; // Text field. + * - 'metadesc-tax-' . $tax->name => ''; // Text field. + * - 'noindex-tax-' . $tax->name => false; + * - 'display-metabox-tax-' . $tax->name => false; + * + * - 'schema-page-type-' . $pt->name => 'WebPage'; + * - 'schema-article-type-' . $pt->name => 'Article'; */ - ); + ]; /** - * @var array Array of variable option name patterns for the option. + * Used for "caching" during pageload. + * + * @var array */ - protected $variable_array_key_patterns = array( + protected $enriched_defaults = null; + + /** + * Array of variable option name patterns for the option. + * + * @var array + */ + protected $variable_array_key_patterns = [ 'title-', 'metadesc-', 'noindex-', - 'showdate-', 'display-metabox-pt-', 'bctitle-ptarchive-', 'post_types-', 'taxonomy-', - ); + 'schema-page-type-', + 'schema-article-type-', + 'social-title-', + 'social-description-', + 'social-image-url-', + 'social-image-id-', + ]; /** - * @var array Array of sub-options which should not be overloaded with multi-site defaults. + * Array of sub-options which should not be overloaded with multi-site defaults. + * + * @var array */ - public $ms_exclude = array( - /* theme dependent */ - 'title_test', + public $ms_exclude = [ 'forcerewritetitle', - ); - - /** - * @var array Array of the separator options. To get these options use WPSEO_Option_Titles::get_instance()->get_separator_options(). - */ - private $separator_options = array( - 'sc-dash' => '-', - 'sc-ndash' => '–', - 'sc-mdash' => '—', - 'sc-middot' => '·', - 'sc-bull' => '•', - 'sc-star' => '*', - 'sc-smstar' => '⋆', - 'sc-pipe' => '|', - 'sc-tilde' => '~', - 'sc-laquo' => '«', - 'sc-raquo' => '»', - 'sc-lt' => '<', - 'sc-gt' => '>', - ); + ]; /** * Add the actions and filters for the option. @@ -135,15 +157,19 @@ class WPSEO_Option_Titles extends WPSEO_Option { * @todo [JRF => testers] Check if the extra actions below would run into problems if an option * is updated early on and if so, change the call to schedule these for a later action on add/update * instead of running them straight away. - * - * @return \WPSEO_Option_Titles */ protected function __construct() { parent::__construct(); - add_action( 'update_option_' . $this->option_name, array( 'WPSEO_Utils', 'clear_cache' ) ); - add_action( 'init', array( $this, 'end_of_init' ), 999 ); - } + add_action( 'update_option_' . $this->option_name, [ 'WPSEO_Utils', 'clear_cache' ] ); + add_action( 'init', [ $this, 'end_of_init' ], 999 ); + add_action( 'registered_post_type', [ $this, 'invalidate_enrich_defaults_cache' ] ); + add_action( 'unregistered_post_type', [ $this, 'invalidate_enrich_defaults_cache' ] ); + add_action( 'registered_taxonomy', [ $this, 'invalidate_enrich_defaults_cache' ] ); + add_action( 'unregistered_taxonomy', [ $this, 'invalidate_enrich_defaults_cache' ] ); + + add_filter( 'admin_title', [ 'Yoast_Input_Validation', 'add_yoast_admin_document_title_errors' ] ); + } /** * Make sure we can recognize the right action for the double cleaning. @@ -155,7 +181,7 @@ class WPSEO_Option_Titles extends WPSEO_Option { /** * Get the singleton instance of this class. * - * @return object + * @return self */ public static function get_instance() { if ( ! ( self::$instance instanceof self ) ) { @@ -171,22 +197,45 @@ class WPSEO_Option_Titles extends WPSEO_Option { * @return array */ public function get_separator_options() { - $separators = $this->separator_options; + $separators = wp_list_pluck( self::get_separator_option_list(), 'option' ); /** * Allow altering the array with separator options. * - * @api array $separator_options Array with the separator options. + * @api array $separator_options Array with the separator options. */ $filtered_separators = apply_filters( 'wpseo_separator_options', $separators ); - if ( is_array( $filtered_separators ) && $filtered_separators !== array() ) { + if ( is_array( $filtered_separators ) && $filtered_separators !== [] ) { $separators = array_merge( $separators, $filtered_separators ); } return $separators; } + /** + * Get the available separator options aria-labels. + * + * @return array Array with the separator options aria-labels. + */ + public function get_separator_options_for_display() { + $separators = $this->get_separator_options(); + $separator_list = self::get_separator_option_list(); + + $separator_options = []; + + foreach ( $separators as $key => $label ) { + $aria_label = isset( $separator_list[ $key ]['label'] ) ? $separator_list[ $key ]['label'] : ''; + + $separator_options[ $key ] = [ + 'label' => $label, + 'aria_label' => $aria_label, + ]; + } + + return $separator_options; + } + /** * Translate strings used in the option defaults. * @@ -207,118 +256,111 @@ class WPSEO_Option_Titles extends WPSEO_Option { $this->defaults['breadcrumbs-searchprefix'] = __( 'You searched for', 'wordpress-seo' ); } - /** * Add dynamically created default options based on available post types and taxonomies. * * @return void */ public function enrich_defaults() { + $enriched_defaults = $this->enriched_defaults; + if ( $enriched_defaults !== null ) { + $this->defaults += $enriched_defaults; + return; + } + + $enriched_defaults = []; + /* * Retrieve all the relevant post type and taxonomy arrays. * * WPSEO_Post_Type::get_accessible_post_types() should *not* be used here. * These are the defaults and can be prepared for any public post type. */ - $post_type_names = get_post_types( array( 'public' => true ), 'names' ); + $post_type_objects = get_post_types( [ 'public' => true ], 'objects' ); - $post_type_objects_custom = get_post_types( - array( - 'public' => true, - '_builtin' => false, - ), - 'objects' - ); - - $taxonomy_names = get_taxonomies( array( 'public' => true ), 'names' ); - - - if ( $post_type_names !== array() ) { - foreach ( $post_type_names as $pt ) { - $this->defaults[ 'title-' . $pt ] = '%%title%% %%page%% %%sep%% %%sitename%%'; // Text field. - $this->defaults[ 'metadesc-' . $pt ] = ''; // Text area. - $this->defaults[ 'noindex-' . $pt ] = false; - $this->defaults[ 'showdate-' . $pt ] = false; - $this->defaults[ 'display-metabox-pt-' . $pt ] = true; - } - unset( $pt ); - } - - if ( $post_type_objects_custom !== array() ) { + if ( $post_type_objects ) { /* translators: %s expands to the name of a post type (plural). */ $archive = sprintf( __( '%s Archive', 'wordpress-seo' ), '%%pt_plural%%' ); - foreach ( $post_type_objects_custom as $pt ) { - if ( ! $pt->has_archive ) { - continue; + + foreach ( $post_type_objects as $pt ) { + $enriched_defaults[ 'title-' . $pt->name ] = '%%title%% %%page%% %%sep%% %%sitename%%'; // Text field. + $enriched_defaults[ 'metadesc-' . $pt->name ] = ''; // Text area. + $enriched_defaults[ 'noindex-' . $pt->name ] = false; + $enriched_defaults[ 'display-metabox-pt-' . $pt->name ] = true; + $enriched_defaults[ 'post_types-' . $pt->name . '-maintax' ] = 0; // Select box. + $enriched_defaults[ 'schema-page-type-' . $pt->name ] = 'WebPage'; + $enriched_defaults[ 'schema-article-type-' . $pt->name ] = ( YoastSEO()->helpers->schema->article->is_article_post_type( $pt->name ) ) ? 'Article' : 'None'; + + if ( $pt->name !== 'attachment' ) { + $enriched_defaults[ 'social-title-' . $pt->name ] = '%%title%%'; // Text field. + $enriched_defaults[ 'social-description-' . $pt->name ] = ''; // Text area. + $enriched_defaults[ 'social-image-url-' . $pt->name ] = ''; // Hidden input field. + $enriched_defaults[ 'social-image-id-' . $pt->name ] = 0; // Hidden input field. } - $this->defaults[ 'title-ptarchive-' . $pt->name ] = $archive . ' %%page%% %%sep%% %%sitename%%'; // Text field. - $this->defaults[ 'metadesc-ptarchive-' . $pt->name ] = ''; // Text area. - $this->defaults[ 'bctitle-ptarchive-' . $pt->name ] = ''; // Text field. - $this->defaults[ 'noindex-ptarchive-' . $pt->name ] = false; + // Custom post types that have archives. + if ( ! $pt->_builtin && WPSEO_Post_Type::has_archive( $pt ) ) { + $enriched_defaults[ 'title-ptarchive-' . $pt->name ] = $archive . ' %%page%% %%sep%% %%sitename%%'; // Text field. + $enriched_defaults[ 'metadesc-ptarchive-' . $pt->name ] = ''; // Text area. + $enriched_defaults[ 'bctitle-ptarchive-' . $pt->name ] = ''; // Text field. + $enriched_defaults[ 'noindex-ptarchive-' . $pt->name ] = false; + $enriched_defaults[ 'social-title-ptarchive-' . $pt->name ] = $archive; // Text field. + $enriched_defaults[ 'social-description-ptarchive-' . $pt->name ] = ''; // Text area. + $enriched_defaults[ 'social-image-url-ptarchive-' . $pt->name ] = ''; // Hidden input field. + $enriched_defaults[ 'social-image-id-ptarchive-' . $pt->name ] = 0; // Hidden input field. + } } - unset( $pt ); } - if ( $taxonomy_names !== array() ) { + $taxonomy_objects = get_taxonomies( [ 'public' => true ], 'object' ); + + if ( $taxonomy_objects ) { /* translators: %s expands to the variable used for term title. */ $archives = sprintf( __( '%s Archives', 'wordpress-seo' ), '%%term_title%%' ); - foreach ( $taxonomy_names as $tax ) { - $this->defaults[ 'title-tax-' . $tax ] = $archives . ' %%page%% %%sep%% %%sitename%%'; // Text field. - $this->defaults[ 'metadesc-tax-' . $tax ] = ''; // Text area. - $this->defaults[ 'display-metabox-tax-' . $tax ] = true; - if ( $tax !== 'post_format' ) { - $this->defaults[ 'noindex-tax-' . $tax ] = false; - } - else { - $this->defaults[ 'noindex-tax-' . $tax ] = true; + foreach ( $taxonomy_objects as $tax ) { + $enriched_defaults[ 'title-tax-' . $tax->name ] = $archives . ' %%page%% %%sep%% %%sitename%%'; // Text field. + $enriched_defaults[ 'metadesc-tax-' . $tax->name ] = ''; // Text area. + $enriched_defaults[ 'display-metabox-tax-' . $tax->name ] = true; + + $enriched_defaults[ 'noindex-tax-' . $tax->name ] = ( $tax->name === 'post_format' ); + + $enriched_defaults[ 'social-title-tax-' . $tax->name ] = $archives; // Text field. + $enriched_defaults[ 'social-description-tax-' . $tax->name ] = ''; // Text area. + $enriched_defaults[ 'social-image-url-tax-' . $tax->name ] = ''; // Hidden input field. + $enriched_defaults[ 'social-image-id-tax-' . $tax->name ] = 0; // Hidden input field. + + if ( ! $tax->_builtin ) { + $enriched_defaults[ 'taxonomy-' . $tax->name . '-ptparent' ] = 0; // Select box;. } } - unset( $tax ); } - /* - * Retrieve all the relevant post type and taxonomy arrays. - * - * WPSEO_Post_Type::get_accessible_post_types() should *not* be used here. - */ - $post_type_names = get_post_types( array( 'public' => true ), 'names' ); - $taxonomy_names_custom = get_taxonomies( - array( - 'public' => true, - '_builtin' => false, - ), - 'names' - ); + $this->enriched_defaults = $enriched_defaults; + $this->defaults += $enriched_defaults; + } - if ( $post_type_names !== array() ) { - foreach ( $post_type_names as $pt ) { - $pto_taxonomies = get_object_taxonomies( $pt, 'names' ); - if ( $pto_taxonomies !== array() ) { - $this->defaults[ 'post_types-' . $pt . '-maintax' ] = 0; // Select box. - } - unset( $pto_taxonomies ); - } - unset( $pt ); - } - - if ( $taxonomy_names_custom !== array() ) { - foreach ( $taxonomy_names_custom as $tax ) { - $this->defaults[ 'taxonomy-' . $tax . '-ptparent' ] = 0; // Select box;. - } - unset( $tax ); - } + /** + * Invalidates enrich_defaults() cache. + * + * Called from actions: + * - (un)registered_post_type + * - (un)registered_taxonomy + * + * @return void + */ + public function invalidate_enrich_defaults_cache() { + $this->enriched_defaults = null; } /** * Validate the option. * - * @param array $dirty New value for the option. - * @param array $clean Clean value for the option, normally the defaults. - * @param array $old Old value of the option. + * @param array $dirty New value for the option. + * @param array $clean Clean value for the option, normally the defaults. + * @param array $old Old value of the option. * - * @return array Validated clean value for the option to be saved to the database. + * @return array Validated clean value for the option to be saved to the database. */ protected function validate_option( $dirty, $clean, $old ) { $allowed_post_types = $this->get_allowed_post_types(); @@ -327,6 +369,14 @@ class WPSEO_Option_Titles extends WPSEO_Option { $switch_key = $this->get_switch_key( $key ); switch ( $switch_key ) { + // Only ever set programmatically, so no reason for intense validation. + case 'company_logo_meta': + case 'person_logo_meta': + if ( isset( $dirty[ $key ] ) ) { + $clean[ $key ] = $dirty[ $key ]; + } + break; + /* Breadcrumbs text fields. */ case 'breadcrumbs-404crumb': case 'breadcrumbs-archiveprefix': @@ -345,29 +395,60 @@ class WPSEO_Option_Titles extends WPSEO_Option { /* * Covers: - * 'title-home-wpseo', 'title-author-wpseo', 'title-archive-wpseo', + * 'title-home-wpseo', 'title-author-wpseo', 'title-archive-wpseo', // phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- This isn't commented out code. * 'title-search-wpseo', 'title-404-wpseo' * 'title-' . $pt->name * 'title-ptarchive-' . $pt->name * 'title-tax-' . $tax->name + * 'social-title-' . $pt->name + * 'social-title-ptarchive-' . $pt->name + * 'social-title-tax-' . $tax->name + * 'social-title-author-wpseo', 'social-title-archive-wpseo' + * 'open_graph_frontpage_title' */ case 'website_name': case 'alternate_website_name': case 'title-': + case 'social-title-': + case 'open_graph_frontpage_title': if ( isset( $dirty[ $key ] ) ) { $clean[ $key ] = WPSEO_Utils::sanitize_text_field( $dirty[ $key ] ); } break; case 'company_or_person': - if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) { - if ( in_array( $dirty[ $key ], array( 'company', 'person' ), true ) ) { + if ( isset( $dirty[ $key ] ) ) { + if ( in_array( $dirty[ $key ], [ 'company', 'person' ], true ) ) { $clean[ $key ] = $dirty[ $key ]; } + else { + $defaults = $this->get_defaults(); + $clean[ $key ] = $defaults['company_or_person']; + } } break; + /* + * Covers: + * 'company_logo', 'person_logo' // phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- This isn't commented out code. + */ case 'company_logo': + case 'person_logo': + case 'open_graph_frontpage_image': + // When a logo changes, we need to ditch the caches we have for it. + unset( $clean[ $switch_key . '_id' ] ); + unset( $clean[ $switch_key . '_meta' ] ); + $this->validate_url( $key, $dirty, $old, $clean ); + break; + + /* + * Covers: + * 'social-image-url-' . $pt->name + * 'social-image-url-ptarchive-' . $pt->name + * 'social-image-url-tax-' . $tax->name + * 'social-image-url-author-wpseo', 'social-image-url-archive-wpseo' + */ + case 'social-image-url-': $this->validate_url( $key, $dirty, $old, $clean ); break; @@ -377,23 +458,28 @@ class WPSEO_Option_Titles extends WPSEO_Option { * 'metadesc-' . $pt->name * 'metadesc-ptarchive-' . $pt->name * 'metadesc-tax-' . $tax->name + * and also: + * 'bctitle-ptarchive-' . $pt->name + * 'social-description-' . $pt->name + * 'social-description-ptarchive-' . $pt->name + * 'social-description-tax-' . $tax->name + * 'social-description-author-wpseo', 'social-description-archive-wpseo' + * 'open_graph_frontpage_desc' */ case 'metadesc-': - /* - * Covers: - * 'bctitle-ptarchive-' . $pt->name - */ case 'bctitle-ptarchive-': case 'company_name': case 'person_name': + case 'social-description-': + case 'open_graph_frontpage_desc': if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) { $clean[ $key ] = WPSEO_Utils::sanitize_text_field( $dirty[ $key ] ); } break; - /* - * Covers: 'rssbefore', 'rssafter' - */ + /* + * Covers: 'rssbefore', 'rssafter' // phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- This isn't commented out code. + */ case 'rssbefore': case 'rssafter': if ( isset( $dirty[ $key ] ) ) { @@ -403,11 +489,11 @@ class WPSEO_Option_Titles extends WPSEO_Option { /* 'post_types-' . $pt->name . '-maintax' fields. */ case 'post_types-': - $post_type = str_replace( array( 'post_types-', '-maintax' ), '', $key ); + $post_type = str_replace( [ 'post_types-', '-maintax' ], '', $key ); $taxonomies = get_object_taxonomies( $post_type, 'names' ); if ( isset( $dirty[ $key ] ) ) { - if ( $taxonomies !== array() && in_array( $dirty[ $key ], $taxonomies, true ) ) { + if ( $taxonomies !== [] && in_array( $dirty[ $key ], $taxonomies, true ) ) { $clean[ $key ] = $dirty[ $key ]; } elseif ( (string) $dirty[ $key ] === '0' || (string) $dirty[ $key ] === '' ) { @@ -421,16 +507,17 @@ class WPSEO_Option_Titles extends WPSEO_Option { if ( isset( $old[ $key ] ) ) { $clean[ $key ] = sanitize_title_with_dashes( $old[ $key ] ); } - /** - * @todo [JRF => whomever] maybe change the untranslated $pt name in the + + /* + * @todo [JRF => whomever] Maybe change the untranslated $pt name in the * error message to the nicely translated label ? */ add_settings_error( $this->group_name, // Slug title of the setting. - '_' . $key, // Suffix-id for the error message box. + $key, // Suffix-id for the error message box. /* translators: %s expands to a post type. */ sprintf( __( 'Please select a valid taxonomy for post type "%s"', 'wordpress-seo' ), $post_type ), // The error message. - 'error' // Error type, either 'error' or 'updated'. + 'error' // Message type. ); } } @@ -443,7 +530,7 @@ class WPSEO_Option_Titles extends WPSEO_Option { /* 'taxonomy-' . $tax->name . '-ptparent' fields. */ case 'taxonomy-': if ( isset( $dirty[ $key ] ) ) { - if ( $allowed_post_types !== array() && in_array( $dirty[ $key ], $allowed_post_types, true ) ) { + if ( $allowed_post_types !== [] && in_array( $dirty[ $key ], $allowed_post_types, true ) ) { $clean[ $key ] = $dirty[ $key ]; } elseif ( (string) $dirty[ $key ] === '0' || (string) $dirty[ $key ] === '' ) { @@ -457,17 +544,18 @@ class WPSEO_Option_Titles extends WPSEO_Option { if ( isset( $old[ $key ] ) ) { $clean[ $key ] = sanitize_key( $old[ $key ] ); } - /** - * @todo [JRF =? whomever] maybe change the untranslated $tax name in the + + /* + * @todo [JRF =? whomever] Maybe change the untranslated $tax name in the * error message to the nicely translated label ? */ - $tax = str_replace( array( 'taxonomy-', '-ptparent' ), '', $key ); + $tax = str_replace( [ 'taxonomy-', '-ptparent' ], '', $key ); add_settings_error( $this->group_name, // Slug title of the setting. - '_' . $tax, // Suffix-id for the error message box. + '_' . $tax, // Suffix-ID for the error message box. /* translators: %s expands to a taxonomy slug. */ sprintf( __( 'Please select a valid post type for taxonomy "%s"', 'wordpress-seo' ), $tax ), // The error message. - 'error' // Error type, either 'error' or 'updated'. + 'error' // Message type. ); unset( $tax ); } @@ -477,8 +565,20 @@ class WPSEO_Option_Titles extends WPSEO_Option { } break; - /* Integer field - not in form. */ - case 'title_test': + /* + * Covers: + * 'company_or_person_user_id' + * 'company_logo_id', 'person_logo_id', 'open_graph_frontpage_image_id' + * 'social-image-id-' . $pt->name + * 'social-image-id-ptarchive-' . $pt->name + * 'social-image-id-tax-' . $tax->name + * 'social-image-id-author-wpseo', 'social-image-id-archive-wpseo' + */ + case 'company_or_person_user_id': + case 'company_logo_id': + case 'person_logo_id': + case 'social-image-id-': + case 'open_graph_frontpage_image_id': if ( isset( $dirty[ $key ] ) ) { $int = WPSEO_Utils::validate_int( $dirty[ $key ] ); if ( $int !== false && $int >= 0 ) { @@ -493,20 +593,45 @@ class WPSEO_Option_Titles extends WPSEO_Option { } break; - /* Separator field - Radio */ + /* Separator field - Radio. */ case 'separator': if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) { // Get separator fields. $separator_fields = $this->get_separator_options(); - // Check if the given separator is exists. + // Check if the given separator exists. if ( isset( $separator_fields[ $dirty[ $key ] ] ) ) { $clean[ $key ] = $dirty[ $key ]; } } break; + case 'schema-page-type-': + if ( isset( $dirty[ $key ] ) && is_string( $dirty[ $key ] ) ) { + if ( array_key_exists( $dirty[ $key ], Schema_Types::PAGE_TYPES ) ) { + $clean[ $key ] = $dirty[ $key ]; + } + else { + $defaults = $this->get_defaults(); + $post_type = str_replace( $switch_key, '', $key ); + $clean[ $key ] = $defaults[ $switch_key . $post_type ]; + } + } + break; + case 'schema-article-type-': + if ( isset( $dirty[ $key ] ) && is_string( $dirty[ $key ] ) ) { + if ( array_key_exists( $dirty[ $key ], Schema_Types::ARTICLE_TYPES ) ) { + $clean[ $key ] = $dirty[ $key ]; + } + else { + $defaults = $this->get_defaults(); + $post_type = str_replace( $switch_key, '', $key ); + $clean[ $key ] = $defaults[ $switch_key . $post_type ]; + } + } + break; + /* * Boolean fields. */ @@ -524,8 +649,6 @@ class WPSEO_Option_Titles extends WPSEO_Option { * 'disable-date': * 'disable-post_format'; * 'noindex-' - * 'showdate-' - * 'showdate-'. $pt->name * 'display-metabox-pt-' * 'display-metabox-pt-'. $pt->name * 'display-metabox-tax-' @@ -553,20 +676,20 @@ class WPSEO_Option_Titles extends WPSEO_Option { * @return array */ protected function get_allowed_post_types() { - $allowed_post_types = array(); + $allowed_post_types = []; /* * WPSEO_Post_Type::get_accessible_post_types() should *not* be used here. */ - $post_types = get_post_types( array( 'public' => true ), 'objects' ); + $post_types = get_post_types( [ 'public' => true ], 'objects' ); if ( get_option( 'show_on_front' ) === 'page' && get_option( 'page_for_posts' ) > 0 ) { $allowed_post_types[] = 'post'; } - if ( is_array( $post_types ) && $post_types !== array() ) { + if ( is_array( $post_types ) && $post_types !== [] ) { foreach ( $post_types as $type ) { - if ( $type->has_archive ) { + if ( WPSEO_Post_Type::has_archive( $type ) ) { $allowed_post_types[] = $type->name; } } @@ -578,25 +701,23 @@ class WPSEO_Option_Titles extends WPSEO_Option { /** * Clean a given option value. * - * @param array $option_value Old (not merged with defaults or filtered) option value to - * clean according to the rules for this option. - * @param string $current_version Optional. Version from which to upgrade, if not set, - * version specific upgrades will be disregarded. - * @param array $all_old_option_values Optional. Only used when importing old options to have - * access to the real old values, in contrast to the saved ones. + * @param array $option_value Old (not merged with defaults or filtered) option value to + * clean according to the rules for this option. + * @param string|null $current_version Optional. Version from which to upgrade, if not set, + * version specific upgrades will be disregarded. + * @param array|null $all_old_option_values Optional. Only used when importing old options to have + * access to the real old values, in contrast to the saved ones. * - * @return array Cleaned option. + * @return array Cleaned option. */ protected function clean_option( $option_value, $current_version = null, $all_old_option_values = null ) { static $original = null; // Double-run this function to ensure renaming of the taxonomy options will work. - if ( ! isset( $original ) && has_action( 'wpseo_double_clean_titles', array( - $this, - 'clean', - ) ) === false + if ( ! isset( $original ) + && has_action( 'wpseo_double_clean_titles', [ $this, 'clean' ] ) === false ) { - add_action( 'wpseo_double_clean_titles', array( $this, 'clean' ) ); + add_action( 'wpseo_double_clean_titles', [ $this, 'clean' ] ); $original = $option_value; } @@ -606,27 +727,27 @@ class WPSEO_Option_Titles extends WPSEO_Option { * {@internal Don't rename to the 'current' names straight away as that would prevent * the rename/unset combi below from working.}} * - * @todo [JRF] maybe figure out a smarter way to deal with this. + * @todo [JRF] Maybe figure out a smarter way to deal with this. */ $old_option = null; if ( isset( $all_old_option_values ) ) { // Ok, we have an import. - if ( isset( $all_old_option_values['wpseo_indexation'] ) && is_array( $all_old_option_values['wpseo_indexation'] ) && $all_old_option_values['wpseo_indexation'] !== array() ) { + if ( isset( $all_old_option_values['wpseo_indexation'] ) && is_array( $all_old_option_values['wpseo_indexation'] ) && $all_old_option_values['wpseo_indexation'] !== [] ) { $old_option = $all_old_option_values['wpseo_indexation']; } } else { $old_option = get_option( 'wpseo_indexation' ); } - if ( is_array( $old_option ) && $old_option !== array() ) { - $move = array( + if ( is_array( $old_option ) && $old_option !== [] ) { + $move = [ 'noindexauthor' => 'noindex-author', 'disableauthor' => 'disable-author', 'noindexdate' => 'noindex-archive', 'noindexcat' => 'noindex-category', 'noindextag' => 'noindex-post_tag', 'noindexpostformat' => 'noindex-post_format', - ); + ]; foreach ( $move as $old => $new ) { if ( isset( $old_option[ $old ] ) && ! isset( $option_value[ $new ] ) ) { $option_value[ $new ] = $old_option[ $old ]; @@ -651,7 +772,7 @@ class WPSEO_Option_Titles extends WPSEO_Option { * Similarly, renaming the tax options to avoid a custom post type and a taxonomy * with the same name occupying the same option. */ - $rename = array( + $rename = [ 'title-home' => 'title-home-wpseo', 'title-author' => 'title-author-wpseo', 'title-archive' => 'title-archive-wpseo', @@ -662,7 +783,7 @@ class WPSEO_Option_Titles extends WPSEO_Option { 'metadesc-archive' => 'metadesc-archive-wpseo', 'noindex-author' => 'noindex-author-wpseo', 'noindex-archive' => 'noindex-archive-wpseo', - ); + ]; foreach ( $rename as $old => $new ) { if ( isset( $option_value[ $old ] ) && ! isset( $option_value[ $new ] ) ) { $option_value[ $new ] = $option_value[ $old ]; @@ -672,23 +793,23 @@ class WPSEO_Option_Titles extends WPSEO_Option { unset( $rename, $old, $new ); - /** + /* * {@internal This clean-up action can only be done effectively once the taxonomies * and post_types have been registered, i.e. at the end of the init action.}} */ if ( isset( $original ) && current_filter() === 'wpseo_double_clean_titles' || did_action( 'wpseo_double_clean_titles' ) > 0 ) { - $rename = array( + $rename = [ 'title-' => 'title-tax-', 'metadesc-' => 'metadesc-tax-', 'noindex-' => 'noindex-tax-', 'tax-hideeditbox-' => 'hideeditbox-tax-', - ); + ]; - $taxonomy_names = get_taxonomies( array( 'public' => true ), 'names' ); - $post_type_names = get_post_types( array( 'public' => true ), 'names' ); + $taxonomy_names = get_taxonomies( [ 'public' => true ], 'names' ); + $post_type_names = get_post_types( [ 'public' => true ], 'names' ); $defaults = $this->get_defaults(); - if ( $taxonomy_names !== array() ) { + if ( $taxonomy_names !== [] ) { foreach ( $taxonomy_names as $tax ) { foreach ( $rename as $old_prefix => $new_prefix ) { if ( @@ -722,18 +843,17 @@ class WPSEO_Option_Titles extends WPSEO_Option { unset( $rename, $taxonomy_names, $post_type_names, $defaults, $tax, $old_prefix, $new_prefix ); } - /* * Make sure the values of the variable option key options are cleaned as they * may be retained and would not be cleaned/validated then. */ - if ( is_array( $option_value ) && $option_value !== array() ) { + if ( is_array( $option_value ) && $option_value !== [] ) { foreach ( $option_value as $key => $value ) { $switch_key = $this->get_switch_key( $key ); // Similar to validation routine - any changes made there should be made here too. switch ( $switch_key ) { - /* text fields */ + /* Text fields. */ case 'title-': case 'metadesc-': case 'bctitle-ptarchive-': @@ -753,7 +873,6 @@ class WPSEO_Option_Titles extends WPSEO_Option { /* * Covers: * 'noindex-' - * 'showdate-' * 'hideeditbox-' */ default: @@ -767,7 +886,6 @@ class WPSEO_Option_Titles extends WPSEO_Option { return $option_value; } - /** * Make sure that any set option values relating to post_types and/or taxonomies are retained, * even when that post_type or taxonomy may not yet have been registered. @@ -776,15 +894,15 @@ class WPSEO_Option_Titles extends WPSEO_Option { * variable key does not get removed. IMPORTANT: keep this method in line with * the parent on which it is based!}} * - * @param array $dirty Original option as retrieved from the database. - * @param array $clean Filtered option where any options which shouldn't be in our option - * have already been removed and any options which weren't set - * have been set to their defaults. + * @param array $dirty Original option as retrieved from the database. + * @param array $clean Filtered option where any options which shouldn't be in our option + * have already been removed and any options which weren't set + * have been set to their defaults. * - * @return array + * @return array */ protected function retain_variable_keys( $dirty, $clean ) { - if ( ( is_array( $this->variable_array_key_patterns ) && $this->variable_array_key_patterns !== array() ) && ( is_array( $dirty ) && $dirty !== array() ) ) { + if ( ( is_array( $this->variable_array_key_patterns ) && $this->variable_array_key_patterns !== [] ) && ( is_array( $dirty ) && $dirty !== [] ) ) { // Add the extra pattern. $patterns = $this->variable_array_key_patterns; @@ -815,4 +933,75 @@ class WPSEO_Option_Titles extends WPSEO_Option { return $clean; } + + /** + * Retrieves a list of separator options. + * + * @return array An array of the separator options. + */ + protected static function get_separator_option_list() { + $separators = [ + 'sc-dash' => [ + 'option' => '-', + 'label' => __( 'Dash', 'wordpress-seo' ), + ], + 'sc-ndash' => [ + 'option' => '–', + 'label' => __( 'En dash', 'wordpress-seo' ), + ], + 'sc-mdash' => [ + 'option' => '—', + 'label' => __( 'Em dash', 'wordpress-seo' ), + ], + 'sc-colon' => [ + 'option' => ':', + 'label' => __( 'Colon', 'wordpress-seo' ), + ], + 'sc-middot' => [ + 'option' => '·', + 'label' => __( 'Middle dot', 'wordpress-seo' ), + ], + 'sc-bull' => [ + 'option' => '•', + 'label' => __( 'Bullet', 'wordpress-seo' ), + ], + 'sc-star' => [ + 'option' => '*', + 'label' => __( 'Asterisk', 'wordpress-seo' ), + ], + 'sc-smstar' => [ + 'option' => '⋆', + 'label' => __( 'Low asterisk', 'wordpress-seo' ), + ], + 'sc-laquo' => [ + 'option' => '«', + 'label' => __( 'Left angle quotation mark', 'wordpress-seo' ), + ], + 'sc-raquo' => [ + 'option' => '»', + 'label' => __( 'Right angle quotation mark', 'wordpress-seo' ), + ], + 'sc-lt' => [ + 'option' => '<', + 'label' => __( 'Less than sign', 'wordpress-seo' ), + ], + 'sc-gt' => [ + 'option' => '>', + 'label' => __( 'Greater than sign', 'wordpress-seo' ), + ], + ]; + + /** + * Allows altering the separator options array. + * + * @api array $separators Array with the separator options. + */ + $separator_list = apply_filters( 'wpseo_separator_option_list', $separators ); + + if ( ! is_array( $separator_list ) ) { + return $separators; + } + + return $separator_list; + } } diff --git a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-wpseo.php b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-wpseo.php index a8909756..0d331544 100644 --- a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-wpseo.php +++ b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option-wpseo.php @@ -11,51 +11,96 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { /** - * @var string Option name. + * Option name. + * + * @var string */ public $option_name = 'wpseo'; /** - * @var array Array of defaults for the option. - * Shouldn't be requested directly, use $this->get_defaults(); + * Array of defaults for the option. + * + * {@internal Shouldn't be requested directly, use $this->get_defaults();}} + * + * @var array */ - protected $defaults = array( + protected $defaults = [ // Non-form fields, set via (ajax) function. - 'ms_defaults_set' => false, + 'tracking' => null, + 'license_server_version' => false, + 'ms_defaults_set' => false, + 'ignore_search_engines_discouraged_notice' => false, + 'indexing_first_time' => true, + 'indexing_started' => null, + 'indexing_reason' => '', + 'indexables_indexing_completed' => false, // Non-form field, should only be set via validation routine. - 'version' => '', // Leave default as empty to ensure activation/upgrade works. - + 'version' => '', // Leave default as empty to ensure activation/upgrade works. + 'previous_version' => '', // Form fields. - 'disableadvanced_meta' => true, - 'onpage_indexability' => true, - 'googleverify' => '', // Text field. - 'msverify' => '', // Text field. - 'yandexverify' => '', - 'site_type' => '', // List of options. - 'has_multiple_authors' => '', - 'environment_type' => '', - 'content_analysis_active' => true, - 'keyword_analysis_active' => true, - 'enable_admin_bar_menu' => true, - 'enable_cornerstone_content' => true, - 'enable_xml_sitemap' => true, - 'enable_text_link_counter' => true, - 'show_onboarding_notice' => false, - 'first_activated_on' => false, - ); + 'disableadvanced_meta' => true, + 'enable_headless_rest_endpoints' => true, + 'ryte_indexability' => true, + 'baiduverify' => '', // Text field. + 'googleverify' => '', // Text field. + 'msverify' => '', // Text field. + 'yandexverify' => '', + 'site_type' => '', // List of options. + 'has_multiple_authors' => '', + 'environment_type' => '', + 'content_analysis_active' => true, + 'keyword_analysis_active' => true, + 'enable_admin_bar_menu' => true, + 'enable_cornerstone_content' => true, + 'enable_xml_sitemap' => true, + 'enable_text_link_counter' => true, + 'show_onboarding_notice' => false, + 'first_activated_on' => false, + 'myyoast-oauth' => [ + 'config' => [ + 'clientId' => null, + 'secret' => null, + ], + 'access_tokens' => [], + ], + 'semrush_integration_active' => true, + 'semrush_tokens' => [], + 'semrush_country_code' => 'us', + 'permalink_structure' => '', + 'home_url' => '', + 'dynamic_permalinks' => false, + 'category_base_url' => '', + 'tag_base_url' => '', + 'custom_taxonomy_slugs' => [], + 'enable_enhanced_slack_sharing' => true, + 'zapier_integration_active' => false, + 'zapier_subscription' => [], + 'zapier_api_key' => '', + 'enable_metabox_insights' => true, + 'enable_link_suggestions' => true, + 'algolia_integration_active' => false, + ]; /** - * @var array Sub-options which should not be overloaded with multi-site defaults. + * Sub-options which should not be overloaded with multi-site defaults. + * + * @var array */ - public $ms_exclude = array( + public $ms_exclude = [ + 'ignore_search_engines_discouraged_notice', /* Privacy. */ + 'baiduverify', 'googleverify', 'msverify', 'yandexverify', - ); + ]; - /** @var array Possible values for the site_type option. */ - protected $site_types = array( + /** + * Possible values for the site_type option. + * + * @var array + */ + protected $site_types = [ '', 'blog', 'shop', @@ -63,39 +108,60 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { 'smallBusiness', 'corporateOther', 'personalOther', - ); + ]; - /** @var array Possible environment types. */ - protected $environment_types = array( + /** + * Possible environment types. + * + * @var array + */ + protected $environment_types = [ '', 'production', 'staging', 'development', - ); + ]; - /** @var array Possible has_multiple_authors options. */ - protected $has_multiple_authors_options = array( + /** + * Possible has_multiple_authors options. + * + * @var array + */ + protected $has_multiple_authors_options = [ '', true, false, - ); + ]; + /** + * Name for an option higher in the hierarchy to override setting access. + * + * @var string + */ + protected $override_option_name = 'wpseo_ms'; /** * Add the actions and filters for the option. * * @todo [JRF => testers] Check if the extra actions below would run into problems if an option - * is updated early on and if so, change the call to schedule these for a later action on add/update - * instead of running them straight away. - * - * @return \WPSEO_Option_Wpseo + * is updated early on and if so, change the call to schedule these for a later action on add/update + * instead of running them straight away. */ protected function __construct() { parent::__construct(); + /** + * Filter: 'wpseo_enable_tracking' - Enables the data tracking of Yoast SEO Premium. + * + * @api string $is_enabled The enabled state. Default is false. + */ + $this->defaults['tracking'] = apply_filters( 'wpseo_enable_tracking', false ); + /* Clear the cache on update/add. */ - add_action( 'add_option_' . $this->option_name, array( 'WPSEO_Utils', 'clear_cache' ) ); - add_action( 'update_option_' . $this->option_name, array( 'WPSEO_Utils', 'clear_cache' ) ); + add_action( 'add_option_' . $this->option_name, [ 'WPSEO_Utils', 'clear_cache' ] ); + add_action( 'update_option_' . $this->option_name, [ 'WPSEO_Utils', 'clear_cache' ] ); + + add_filter( 'admin_title', [ 'Yoast_Input_Validation', 'add_yoast_admin_document_title_errors' ] ); /** * Filter the `wpseo` option defaults. @@ -105,7 +171,6 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { $this->defaults = apply_filters( 'wpseo_option_wpseo_defaults', $this->defaults ); } - /** * Get the singleton instance of this class. * @@ -119,14 +184,72 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { return self::$instance; } + /** + * Add filters to make sure that the option is merged with its defaults before being returned. + * + * @return void + */ + public function add_option_filters() { + parent::add_option_filters(); + + list( $hookname, $callback, $priority ) = $this->get_verify_features_option_filter_hook(); + + if ( has_filter( $hookname, $callback ) === false ) { + add_filter( $hookname, $callback, $priority ); + } + } + + /** + * Remove the option filters. + * Called from the clean_up methods to make sure we retrieve the original old option. + * + * @return void + */ + public function remove_option_filters() { + parent::remove_option_filters(); + + list( $hookname, $callback, $priority ) = $this->get_verify_features_option_filter_hook(); + + remove_filter( $hookname, $callback, $priority ); + } + + /** + * Add filters to make sure that the option default is returned if the option is not set. + * + * @return void + */ + public function add_default_filters() { + parent::add_default_filters(); + + list( $hookname, $callback, $priority ) = $this->get_verify_features_default_option_filter_hook(); + + if ( has_filter( $hookname, $callback ) === false ) { + add_filter( $hookname, $callback, $priority ); + } + } + + /** + * Remove the default filters. + * Called from the validate() method to prevent failure to add new options. + * + * @return void + */ + public function remove_default_filters() { + parent::remove_default_filters(); + + list( $hookname, $callback, $priority ) = $this->get_verify_features_default_option_filter_hook(); + + remove_filter( $hookname, $callback, $priority ); + } + /** * Validate the option. * - * @param array $dirty New value for the option. - * @param array $clean Clean value for the option, normally the defaults. - * @param array $old Old value of the option. + * @param array $dirty New value for the option. + * @param array $clean Clean value for the option, normally the defaults. + * @param array $old Old value of the option. * - * @return array Validated clean value for the option to be saved to the database. + * @return array Validated clean value for the option to be saved to the database. */ protected function validate_option( $dirty, $clean, $old ) { @@ -135,8 +258,23 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { case 'version': $clean[ $key ] = WPSEO_VERSION; break; + case 'previous_version': + case 'semrush_country_code': + case 'license_server_version': + case 'home_url': + case 'zapier_api_key': + if ( isset( $dirty[ $key ] ) ) { + $clean[ $key ] = $dirty[ $key ]; + } + break; + case 'indexing_reason': + if ( isset( $dirty[ $key ] ) ) { + $clean[ $key ] = sanitize_text_field( $dirty[ $key ] ); + } + break; /* Verification strings. */ + case 'baiduverify': case 'googleverify': case 'msverify': case 'yandexverify': @@ -147,6 +285,7 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { * Boolean dismiss warnings - not fields - may not be in form * (and don't need to be either as long as the default is false). */ + case 'ignore_search_engines_discouraged_notice': case 'ms_defaults_set': if ( isset( $dirty[ $key ] ) ) { $clean[ $key ] = WPSEO_Utils::validate_bool( $dirty[ $key ] ); @@ -179,6 +318,7 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { break; case 'first_activated_on': + case 'indexing_started': $clean[ $key ] = false; if ( isset( $dirty[ $key ] ) ) { if ( $dirty[ $key ] === false || WPSEO_Utils::validate_int( $dirty[ $key ] ) ) { @@ -187,6 +327,37 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { } break; + case 'tracking': + $clean[ $key ] = ( isset( $dirty[ $key ] ) ? WPSEO_Utils::validate_bool( $dirty[ $key ] ) : null ); + break; + + case 'myyoast_oauth': + case 'semrush_tokens': + case 'custom_taxonomy_slugs': + case 'zapier_subscription': + $clean[ $key ] = $old[ $key ]; + + if ( isset( $dirty[ $key ] ) ) { + $items = $dirty[ $key ]; + if ( ! is_array( $items ) ) { + $items = json_decode( $dirty[ $key ], true ); + } + + if ( is_array( $items ) ) { + $clean[ $key ] = $dirty[ $key ]; + } + } + + break; + + case 'permalink_structure': + case 'category_base_url': + case 'tag_base_url': + if ( isset( $dirty[ $key ] ) ) { + $clean[ $key ] = sanitize_option( $key, $dirty[ $key ] ); + } + break; + /* * Boolean (checkbox) fields. */ @@ -194,7 +365,11 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { /* * Covers: * 'disableadvanced_meta' + * 'enable_headless_rest_endpoints' * 'yoast_tracking' + * 'dynamic_permalinks' + * 'indexing_first_time' + * and most of the feature variables. */ default: $clean[ $key ] = ( isset( $dirty[ $key ] ) ? WPSEO_Utils::validate_bool( $dirty[ $key ] ) : false ); @@ -205,20 +380,103 @@ class WPSEO_Option_Wpseo extends WPSEO_Option { return $clean; } + /** + * Verifies that the feature variables are turned off if the network is configured so. + * + * @param mixed $options Value of the option to be returned. Typically an array. + * + * @return mixed Filtered $options value. + */ + public function verify_features_against_network( $options = [] ) { + if ( ! is_array( $options ) || empty( $options ) ) { + return $options; + } + + // For the feature variables, set their values to off in case they are disabled. + $feature_vars = [ + 'disableadvanced_meta' => false, + 'ryte_indexability' => false, + 'content_analysis_active' => false, + 'keyword_analysis_active' => false, + 'enable_admin_bar_menu' => false, + 'enable_cornerstone_content' => false, + 'enable_xml_sitemap' => false, + 'enable_text_link_counter' => false, + 'enable_metabox_insights' => false, + 'enable_link_suggestions' => false, + 'enable_headless_rest_endpoints' => false, + 'tracking' => false, + 'enable_enhanced_slack_sharing' => false, + 'semrush_integration_active' => false, + 'zapier_integration_active' => false, + ]; + + // We can reuse this logic from the base class with the above defaults to parse with the correct feature values. + $options = $this->prevent_disabled_options_update( $options, $feature_vars ); + + return $options; + } + + /** + * Gets the filter hook name and callback for adjusting the retrieved option value + * against the network-allowed features. + * + * @return array Array where the first item is the hook name, the second is the hook callback, + * and the third is the hook priority. + */ + protected function get_verify_features_option_filter_hook() { + return [ + "option_{$this->option_name}", + [ $this, 'verify_features_against_network' ], + 11, + ]; + } + + /** + * Gets the filter hook name and callback for adjusting the default option value against the network-allowed features. + * + * @return array Array where the first item is the hook name, the second is the hook callback, + * and the third is the hook priority. + */ + protected function get_verify_features_default_option_filter_hook() { + return [ + "default_option_{$this->option_name}", + [ $this, 'verify_features_against_network' ], + 11, + ]; + } /** * Clean a given option value. * - * @param array $option_value Old (not merged with defaults or filtered) option value to - * clean according to the rules for this option. - * @param string $current_version Optional. Version from which to upgrade, if not set, - * version specific upgrades will be disregarded. - * @param array $all_old_option_values Optional. Only used when importing old options to have - * access to the real old values, in contrast to the saved ones. + * @param array $option_value Old (not merged with defaults or filtered) option value to + * clean according to the rules for this option. + * @param string|null $current_version Optional. Version from which to upgrade, if not set, + * version specific upgrades will be disregarded. + * @param array|null $all_old_option_values Optional. Only used when importing old options to have + * access to the real old values, in contrast to the saved ones. * - * @return array Cleaned option. + * @return array Cleaned option. */ protected function clean_option( $option_value, $current_version = null, $all_old_option_values = null ) { + // Deal with value change from text string to boolean. + $value_change = [ + 'ignore_search_engines_discouraged_notice', + ]; + + $target_values = [ + 'ignore', + 'done', + ]; + + foreach ( $value_change as $key ) { + if ( isset( $option_value[ $key ] ) + && in_array( $option_value[ $key ], $target_values, true ) + ) { + $option_value[ $key ] = true; + } + } + return $option_value; } } diff --git a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option.php b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option.php index ed974ae9..7ad424fa 100644 --- a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option.php +++ b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-option.php @@ -12,95 +12,128 @@ * Some guidelines: * [Retrieving options] * - Use the normal get_option() to retrieve an option. You will receive a complete array for the option. - * Any subkeys which were not set, will have their default values in place. + * Any subkeys which were not set, will have their default values in place. * - In other words, you will normally not have to check whether a subkey isset() as they will *always* be set. - * They will also *always* be of the correct variable type. - * The only exception to this are the options with variable option names based on post_type or taxonomy - * as those will not always be available before the taxonomy/post_type is registered. - * (they will be available if a value was set, they won't be if it wasn't as the class won't know - * that a default needs to be injected). + * They will also *always* be of the correct variable type. + * The only exception to this are the options with variable option names based on post_type or taxonomy + * as those will not always be available before the taxonomy/post_type is registered. + * (they will be available if a value was set, they won't be if it wasn't as the class won't know + * that a default needs to be injected). * * [Updating/Adding options] * - For multisite site_options, please use the WPSEO_Options::update_site_option() method. * - For normal options, use the normal add/update_option() functions. As long a the classes here * are instantiated, validation for all options and their subkeys will be automatic. * - On (succesfull) update of a couple of options, certain related actions will be run automatically. - * Some examples: - * - on change of wpseo[yoast_tracking], the cron schedule will be adjusted accordingly - * - on change of wpseo and wpseo_title, some caches will be cleared - * + * Some examples: + * - on change of wpseo[yoast_tracking], the cron schedule will be adjusted accordingly + * - on change of wpseo and wpseo_title, some caches will be cleared * * [Important information about add/updating/changing these classes] * - Make sure that option array key names are unique across options. The WPSEO_Options::get_all() - * method merges most options together. If any of them have non-unique names, even if they - * are in a different option, they *will* overwrite each other. + * method merges most options together. If any of them have non-unique names, even if they + * are in a different option, they *will* overwrite each other. * - When you add a new array key in an option: make sure you add proper defaults and add the key - * to the validation routine in the proper place or add a new validation case. - * You don't need to do any upgrading as any option returned will always be merged with the - * defaults, so new options will automatically be available. - * If the default value is a string which need translating, add this to the concrete class - * translate_defaults() method. + * to the validation routine in the proper place or add a new validation case. + * You don't need to do any upgrading as any option returned will always be merged with the + * defaults, so new options will automatically be available. + * If the default value is a string which need translating, add this to the concrete class + * translate_defaults() method. * - When you remove an array key from an option: if it's important that the option is really removed, - * add the WPSEO_Option::clean_up( $option_name ) method to the upgrade run. - * This will re-save the option and automatically remove the array key no longer in existance. + * add the WPSEO_Option::clean_up( $option_name ) method to the upgrade run. + * This will re-save the option and automatically remove the array key no longer in existance. * - When you rename a sub-option: add it to the clean_option() routine and run that in the upgrade run. * - When you change the default for an option sub-key, make sure you verify that the validation routine will - * still work the way it should. - * Example: changing a default from '' (empty string) to 'text' with a validation routine with tests - * for an empty string will prevent a user from saving an empty string as the real value. So the - * test for '' with the validation routine would have to be removed in that case. + * still work the way it should. + * Example: changing a default from '' (empty string) to 'text' with a validation routine with tests + * for an empty string will prevent a user from saving an empty string as the real value. So the + * test for '' with the validation routine would have to be removed in that case. * - If an option needs specific actions different from defined in this abstract class, you can just overrule - * a method by defining it in the concrete class. + * a method by defining it in the concrete class. * - * @todo - [JRF => testers] Double check that validation will not cause errors when called - * from upgrade routine (some of the WP functions may not yet be available). + * @todo [JRF => testers] Double check that validation will not cause errors when called + * from upgrade routine (some of the WP functions may not yet be available). */ abstract class WPSEO_Option { /** - * @var string Option name - MUST be set in concrete class and set to public. + * Prefix for override option keys that allow or disallow the option key of the same name. + * + * @var string + */ + const ALLOW_KEY_PREFIX = 'allow_'; + + /** + * Option name - MUST be set in concrete class and set to public. + * + * @var string */ protected $option_name; /** - * @var string Option group name for use in settings forms - * - will be set automagically if not set in concrete class - * (i.e. if it confirm to the normal pattern 'yoast' . $option_name . 'options', - * only set in conrete class if it doesn't) + * Option group name for use in settings forms. + * + * Will be set automagically if not set in concrete class (i.e. + * if it confirm to the normal pattern 'yoast' . $option_name . 'options', + * only set in conrete class if it doesn't). + * + * @var string */ public $group_name; /** - * @var bool Whether to include the option in the return for WPSEO_Options::get_all(). - * Also determines which options are copied over for ms_(re)set_blog(). + * Whether to include the option in the return for WPSEO_Options::get_all(). + * + * Also determines which options are copied over for ms_(re)set_blog(). + * + * @var bool */ public $include_in_all = true; /** - * @var bool Whether this option is only for when the install is multisite. + * Whether this option is only for when the install is multisite. + * + * @var bool */ public $multisite_only = false; /** - * @var array Array of defaults for the option - MUST be set in concrete class. - * Shouldn't be requested directly, use $this->get_defaults(); + * Array of defaults for the option - MUST be set in concrete class. + * + * Shouldn't be requested directly, use $this->get_defaults(); + * + * @var array */ protected $defaults; /** - * @var array Array of variable option name patterns for the option - if any - - * Set this when the option contains array keys which vary based on post_type - * or taxonomy. + * Array of variable option name patterns for the option - if any -. + * + * Set this when the option contains array keys which vary based on post_type + * or taxonomy. + * + * @var array */ protected $variable_array_key_patterns; /** - * @var array Array of sub-options which should not be overloaded with multi-site defaults. + * Array of sub-options which should not be overloaded with multi-site defaults. + * + * @var array */ - public $ms_exclude = array(); + public $ms_exclude = []; /** - * @var object Instance of this class. + * Name for an option higher in the hierarchy to override setting access. + * + * @var string + */ + protected $override_option_name; + + /** + * Instance of this class. + * + * @var WPSEO_Option */ protected static $instance; @@ -109,8 +142,6 @@ abstract class WPSEO_Option { /** * Add all the actions and filters for the option. - * - * @return \WPSEO_Option */ protected function __construct() { @@ -124,9 +155,14 @@ abstract class WPSEO_Option { * The option validation routines remove the default filters to prevent failing * to insert an option if it's new. Let's add them back afterwards. */ - add_action( 'add_option', array( $this, 'add_default_filters' ) ); // Adding back after INSERT. + add_action( 'add_option', [ $this, 'add_default_filters_if_same_option' ] ); // Adding back after INSERT. - add_action( 'update_option', array( $this, 'add_default_filters' ) ); + add_action( 'update_option', [ $this, 'add_default_filters_if_same_option' ] ); + + add_filter( 'pre_update_option', [ $this, 'add_default_filters_if_not_changed' ], PHP_INT_MAX, 3 ); + + // Refills the cache when the option has been updated. + add_action( 'update_option_' . $this->option_name, [ 'WPSEO_Options', 'clear_cache' ], 10 ); } elseif ( is_multisite() ) { /* @@ -137,23 +173,26 @@ abstract class WPSEO_Option { * on an insert/update failure. Please use the WPSEO_Options::update_site_option() method * for updating site options to make sure the filters are in place. */ - add_action( 'add_site_option_' . $this->option_name, array( $this, 'add_default_filters' ) ); - add_action( 'update_site_option_' . $this->option_name, array( $this, 'add_default_filters' ) ); + add_action( 'add_site_option_' . $this->option_name, [ $this, 'add_default_filters' ] ); + add_action( 'update_site_option_' . $this->option_name, [ $this, 'add_default_filters' ] ); + add_filter( 'pre_update_site_option_' . $this->option_name, [ $this, 'add_default_filters_if_not_changed' ], PHP_INT_MAX, 3 ); + // Refills the cache when the option has been updated. + add_action( 'update_site_option_' . $this->option_name, [ 'WPSEO_Options', 'clear_cache' ], 1, 0 ); } /* * Make sure the option will always get validated, independently of register_setting() * (only available on back-end). - */ - add_filter( 'sanitize_option_' . $this->option_name, array( $this, 'validate' ) ); + */ + add_filter( 'sanitize_option_' . $this->option_name, [ $this, 'validate' ] ); // Flushes the rewrite rules when option is updated. - add_action( 'update_option_' . $this->option_name, array( 'WPSEO_Utils', 'clear_rewrites' ) ); + add_action( 'update_option_' . $this->option_name, [ 'WPSEO_Utils', 'clear_rewrites' ] ); /* Register our option for the admin pages */ - add_action( 'admin_init', array( $this, 'register_setting' ) ); + add_action( 'admin_init', [ $this, 'register_setting' ] ); /* Set option group name if not given */ @@ -163,66 +202,103 @@ abstract class WPSEO_Option { /* Translate some defaults as early as possible - textdomain is loaded in init on priority 1. */ if ( method_exists( $this, 'translate_defaults' ) ) { - add_action( 'init', array( $this, 'translate_defaults' ), 2 ); + add_action( 'init', [ $this, 'translate_defaults' ], 2 ); } /** * Enrich defaults once custom post types and taxonomies have been registered * which is normally done on the init action. * - * @todo - [JRF/testers] Verify that none of the options which are only available after + * @todo [JRF/testers] Verify that none of the options which are only available after * enrichment are used before the enriching. */ if ( method_exists( $this, 'enrich_defaults' ) ) { - add_action( 'init', array( $this, 'enrich_defaults' ), 99 ); + add_action( 'init', [ $this, 'enrich_defaults' ], 99 ); } } -// @codingStandardsIgnoreStart - - /** + /* * All concrete classes *must* contain the get_instance method. * * {@internal Unfortunately I can't define it as an abstract as it also *has* to be static...}} - */ - // abstract protected static function get_instance(); - - - /** + * + * ``` + * abstract protected static function get_instance(); + * ``` + * --------------- + * * Concrete classes *may* contain a translate_defaults method. - */ - // abstract public function translate_defaults(); - - - /** + * ``` + * abstract public function translate_defaults(); + * ``` + * --------------- + * * Concrete classes *may* contain a enrich_defaults method to add additional defaults once * all post_types and taxonomies have been registered. + * + * ``` + * abstract public function enrich_defaults(); + * ``` */ - // abstract public function enrich_defaults(); /* *********** METHODS INFLUENCING get_option() *********** */ /** * Add filters to make sure that the option default is returned if the option is not set. * - * @return void + * @return void */ public function add_default_filters() { // Don't change, needs to check for false as could return prio 0 which would evaluate to false. - if ( has_filter( 'default_option_' . $this->option_name, array( $this, 'get_defaults' ) ) === false ) { - add_filter( 'default_option_' . $this->option_name, array( $this, 'get_defaults' ) ); + if ( has_filter( 'default_option_' . $this->option_name, [ $this, 'get_defaults' ] ) === false ) { + add_filter( 'default_option_' . $this->option_name, [ $this, 'get_defaults' ] ); } } - // @codingStandardsIgnoreStart + /** + * Adds back the default filters that were removed during validation if the option was changed. + * Checks if this option was changed to prevent constantly checking if filters are present. + * + * @param string $option_name The option name. + * + * @return void + */ + public function add_default_filters_if_same_option( $option_name ) { + if ( $option_name === $this->option_name ) { + $this->add_default_filters(); + } + } + + /** + * Adds back the default filters that were removed during validation if the option was not changed. + * This is because in that case the latter actions are not called and thus the filters are never + * added back. + * + * @param mixed $value The current value. + * @param string $option_name The option name. + * @param mixed $old_value The old value. + * + * @return string The current value. + */ + public function add_default_filters_if_not_changed( $value, $option_name, $old_value ) { + if ( $option_name !== $this->option_name ) { + return $value; + } + + if ( $value === $old_value || maybe_serialize( $value ) === maybe_serialize( $old_value ) ) { + $this->add_default_filters(); + } + + return $value; + } /** * Validate webmaster tools & Pinterest verification strings. * * @param string $key Key to check, by type of service. - * @param array $dirty Dirty data. + * @param array $dirty Dirty data with the new values. * @param array $old Old data. - * @param array $clean Clean data by reference. + * @param array $clean Clean data by reference, normally the default values. */ public function validate_verification_string( $key, $dirty, $old, &$clean ) { if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) { @@ -242,6 +318,11 @@ abstract class WPSEO_Option { $service = ''; switch ( $key ) { + case 'baiduverify': + $regex = '`^[A-Za-z0-9_-]+$`'; + $service = 'Baidu Webmaster tools'; + break; + case 'googleverify': $regex = '`^[A-Za-z0-9_-]+$`'; $service = 'Google Webmaster tools'; @@ -264,56 +345,148 @@ abstract class WPSEO_Option { $clean[ $key ] = $meta; } else { + // Restore the previous value, if any. if ( isset( $old[ $key ] ) && preg_match( $regex, $old[ $key ] ) ) { $clean[ $key ] = $old[ $key ]; } + if ( function_exists( 'add_settings_error' ) ) { add_settings_error( $this->group_name, // Slug title of the setting. - '_' . $key, // Suffix-id for the error message box. + $key, // Suffix-ID for the error message box. WordPress prepends `setting-error-`. /* translators: 1: Verification string from user input; 2: Service name. */ sprintf( __( '%1$s does not seem to be a valid %2$s verification string. Please correct.', 'wordpress-seo' ), '' . esc_html( $meta ) . '', $service ), // The error message. - 'error' // Error type, either 'error' or 'updated'. + 'error' // CSS class for the WP notice, either the legacy 'error' / 'updated' or the new `notice-*` ones. ); } + + Yoast_Input_Validation::add_dirty_value_to_settings_errors( $key, $meta ); } } } } /** - * @param string $key Key to check, by type of service. - * @param array $dirty Dirty data. + * Validates an option as a valid URL. Prints out a WordPress settings error + * notice if the URL is invalid. + * + * @param string $key Key to check, by type of URL setting. + * @param array $dirty Dirty data with the new values. * @param array $old Old data. - * @param array $clean Clean data by reference. + * @param array $clean Clean data by reference, normally the default values. */ public function validate_url( $key, $dirty, $old, &$clean ) { if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) { - $url = WPSEO_Utils::sanitize_url( $dirty[ $key ] ); - if ( $url !== '' ) { - $clean[ $key ] = $url; - } - else { + + $submitted_url = trim( htmlspecialchars( $dirty[ $key ], ENT_COMPAT, get_bloginfo( 'charset' ), true ) ); + $validated_url = filter_var( WPSEO_Utils::sanitize_url( $submitted_url ), FILTER_VALIDATE_URL ); + + if ( $validated_url === false ) { + if ( function_exists( 'add_settings_error' ) ) { + add_settings_error( + // Slug title of the setting. + $this->group_name, + // Suffix-ID for the error message box. WordPress prepends `setting-error-`. + $key, + // The error message. + sprintf( + /* translators: %s expands to an invalid URL. */ + __( '%s does not seem to be a valid url. Please correct.', 'wordpress-seo' ), + '' . esc_html( $submitted_url ) . '' + ), + // Message type. + 'error' + ); + } + + // Restore the previous URL value, if any. if ( isset( $old[ $key ] ) && $old[ $key ] !== '' ) { $url = WPSEO_Utils::sanitize_url( $old[ $key ] ); if ( $url !== '' ) { $clean[ $key ] = $url; } } - if ( function_exists( 'add_settings_error' ) ) { - $url = WPSEO_Utils::sanitize_url( $dirty[ $key ] ); - add_settings_error( - $this->group_name, // Slug title of the setting. - '_' . $key, // Suffix-id for the error message box. - sprintf( - /* translators: %s expands to an invalid URL. */ - __( '%s does not seem to be a valid url. Please correct.', 'wordpress-seo' ), - '' . esc_html( $url ) . '' - ), // The error message. - 'error' // Error type, either 'error' or 'updated'. - ); - } + + Yoast_Input_Validation::add_dirty_value_to_settings_errors( $key, $submitted_url ); + + return; } + + // The URL format is valid, let's sanitize it. + $url = WPSEO_Utils::sanitize_url( $validated_url ); + + if ( $url !== '' ) { + $clean[ $key ] = $url; + } + } + } + + /** + * Validates a Facebook App ID. + * + * @deprecated 15.5 + * @codeCoverageIgnore + * + * @param string $key Key to check, in this case: the Facebook App ID field name. + * @param array $dirty Dirty data with the new values. + * @param array $old Old data. + * @param array $clean Clean data by reference, normally the default values. + */ + public function validate_facebook_app_id( $key, $dirty, $old, &$clean ) { + _deprecated_function( __METHOD__, 'WPSEO 15.5' ); + + if ( isset( $dirty[ $key ] ) && $dirty[ $key ] !== '' ) { + $url = 'https://graph.facebook.com/' . $dirty[ $key ]; + + $response = wp_remote_get( $url ); + + /** + * Filter: 'validate_facebook_app_id_api_response_code' - Allows to filter the Faceboook API response code. + * + * @deprecated 15.5 + * + * @api int $response_code The Facebook API response header code. + */ + $response_code = apply_filters_deprecated( 'validate_facebook_app_id_api_response_code', wp_remote_retrieve_response_code( $response ), 'WPSEO 15.5' ); + + /** + * Filter: 'validate_facebook_app_id_api_response_body' - Allows to filter the Faceboook API response body. + * + * @deprecated 15.5 + * + * @api string $response_body The Facebook API JSON response body. + */ + $response_body = apply_filters_deprecated( 'validate_facebook_app_id_api_response_body', wp_remote_retrieve_body( $response ), 'WPSEO 15.5' ); + $response_object = json_decode( $response_body ); + + /* + * When the request is successful the response code will be 200 and + * the response object will contain an `id` property. + */ + if ( $response_code === 200 && isset( $response_object->id ) ) { + $clean[ $key ] = $dirty[ $key ]; + return; + } + + // Restore the previous value, if any. + if ( isset( $old[ $key ] ) && $old[ $key ] !== '' ) { + $clean[ $key ] = $old[ $key ]; + } + + if ( function_exists( 'add_settings_error' ) ) { + add_settings_error( + $this->group_name, // Slug title of the setting. + $key, // Suffix-ID for the error message box. WordPress prepends `setting-error-`. + sprintf( + /* translators: %s expands to an invalid Facebook App ID. */ + __( '%s does not seem to be a valid Facebook App ID. Please correct.', 'wordpress-seo' ), + '' . esc_html( $dirty[ $key ] ) . '' + ), // The error message. + 'error' // CSS class for the WP notice, either the legacy 'error' / 'updated' or the new `notice-*` ones. + ); + } + + Yoast_Input_Validation::add_dirty_value_to_settings_errors( $key, $dirty[ $key ] ); } } @@ -321,13 +494,12 @@ abstract class WPSEO_Option { * Remove the default filters. * Called from the validate() method to prevent failure to add new options. * - * @return void + * @return void */ public function remove_default_filters() { - remove_filter( 'default_option_' . $this->option_name, array( $this, 'get_defaults' ) ); + remove_filter( 'default_option_' . $this->option_name, [ $this, 'get_defaults' ] ); } - /** * Get the enriched default value for an option. * @@ -336,7 +508,7 @@ abstract class WPSEO_Option { * {@internal The enrich_defaults method is used to set defaults for variable array keys * in an option, such as array keys depending on post_types and/or taxonomies.}} * - * @return array + * @return array */ public function get_defaults() { if ( method_exists( $this, 'translate_defaults' ) ) { @@ -350,39 +522,36 @@ abstract class WPSEO_Option { return apply_filters( 'wpseo_defaults', $this->defaults, $this->option_name ); } - /** * Add filters to make sure that the option is merged with its defaults before being returned. * - * @return void + * @return void */ public function add_option_filters() { // Don't change, needs to check for false as could return prio 0 which would evaluate to false. - if ( has_filter( 'option_' . $this->option_name, array( $this, 'get_option' ) ) === false ) { - add_filter( 'option_' . $this->option_name, array( $this, 'get_option' ) ); + if ( has_filter( 'option_' . $this->option_name, [ $this, 'get_option' ] ) === false ) { + add_filter( 'option_' . $this->option_name, [ $this, 'get_option' ] ); } } - /** * Remove the option filters. * Called from the clean_up methods to make sure we retrieve the original old option. * - * @return void + * @return void */ public function remove_option_filters() { - remove_filter( 'option_' . $this->option_name, array( $this, 'get_option' ) ); + remove_filter( 'option_' . $this->option_name, [ $this, 'get_option' ] ); } - /** * Merge an option with its default values. * * This method should *not* be called directly!!! It is only meant to filter the get_option() results. * - * @param mixed $options Option value. + * @param mixed $options Option value. * - * @return mixed Option merged with the defaults for that option. + * @return mixed Option merged with the defaults for that option. */ public function get_option( $options = null ) { $filtered = $this->array_filter_merge( $options ); @@ -400,7 +569,6 @@ abstract class WPSEO_Option { return $filtered; } - /* *********** METHODS influencing add_uption(), update_option() and saving from admin pages. *********** */ /** @@ -411,37 +579,49 @@ abstract class WPSEO_Option { * @return void */ public function register_setting() { - if ( WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) { - register_setting( $this->group_name, $this->option_name ); + if ( ! WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) { + return; } - } + if ( $this->multisite_only === true ) { + $network_settings_api = Yoast_Network_Settings_API::get(); + if ( $network_settings_api->meets_requirements() ) { + $network_settings_api->register_setting( $this->group_name, $this->option_name ); + } + return; + } + + register_setting( $this->group_name, $this->option_name ); + } /** * Validate the option * - * @param mixed $option_value The unvalidated new value for the option. + * @param mixed $option_value The unvalidated new value for the option. * - * @return array Validated new value for the option. + * @return array Validated new value for the option. */ public function validate( $option_value ) { $clean = $this->get_defaults(); /* Return the defaults if the new value is empty. */ - if ( ! is_array( $option_value ) || $option_value === array() ) { + if ( ! is_array( $option_value ) || $option_value === [] ) { return $clean; } + $option_value = array_map( [ 'WPSEO_Utils', 'trim_recursive' ], $option_value ); - $option_value = array_map( array( 'WPSEO_Utils', 'trim_recursive' ), $option_value ); - if ( $this->multisite_only !== true ) { - $old = get_option( $this->option_name ); - } - else { - $old = get_site_option( $this->option_name ); + $old = $this->get_original_option(); + if ( ! is_array( $old ) ) { + $old = []; } + $old = array_merge( $clean, $old ); + $clean = $this->validate_option( $option_value, $clean, $old ); + // Prevent updates to variables that are disabled via the override option. + $clean = $this->prevent_disabled_options_update( $clean, $old ); + /* Retain the values for variable array keys even when the post type/taxonomy is not yet registered. */ if ( isset( $this->variable_array_key_patterns ) ) { $clean = $this->retain_variable_keys( $option_value, $clean ); @@ -452,18 +632,35 @@ abstract class WPSEO_Option { return $clean; } + /** + * Checks whether a specific option key is disabled. + * + * This is determined by whether an override option is available with a key that equals the given key prefixed + * with 'allow_'. + * + * @param string $key Option key. + * + * @return bool True if option key is disabled, false otherwise. + */ + public function is_disabled( $key ) { + $override_option = $this->get_override_option(); + if ( empty( $override_option ) ) { + return false; + } + + return isset( $override_option[ self::ALLOW_KEY_PREFIX . $key ] ) && ! $override_option[ self::ALLOW_KEY_PREFIX . $key ]; + } /** * All concrete classes must contain a validate_option() method which validates all * values within the option. * - * @param array $dirty New value for the option. - * @param array $clean Clean value for the option, normally the defaults. - * @param array $old Old value of the option. + * @param array $dirty New value for the option. + * @param array $clean Clean value for the option, normally the defaults. + * @param array $old Old value of the option. */ abstract protected function validate_option( $dirty, $clean, $old ); - /* *********** METHODS for ADDING/UPDATING/UPGRADING the option. *********** */ /** @@ -507,7 +704,6 @@ abstract class WPSEO_Option { } } - /** * Update a site_option. * @@ -536,14 +732,14 @@ abstract class WPSEO_Option { } } - /** * Retrieve the real old value (unmerged with defaults), clean and re-save the option. * * @uses WPSEO_Option::get_original_option() * @uses WPSEO_Option::import() * - * @param string $current_version Optional. Version from which to upgrade, if not set, version specific upgrades will be disregarded. + * @param string|null $current_version Optional. Version from which to upgrade, if not set, + * version specific upgrades will be disregarded. * * @return void */ @@ -552,7 +748,6 @@ abstract class WPSEO_Option { $this->import( $option_value, $current_version ); } - /** * Clean and re-save the option. * @@ -567,9 +762,12 @@ abstract class WPSEO_Option { * once the admin has dismissed the message (add ajax function) * Important: all validation routines which add_settings_errors would need to be changed for this to work * - * @param array $option_value Option value to be imported. - * @param string $current_version Optional. Version from which to upgrade, if not set, version specific upgrades will be disregarded. - * @param array $all_old_option_values Optional. Only used when importing old options to have access to the real old values, in contrast to the saved ones. + * @param array $option_value Option value to be imported. + * @param string|null $current_version Optional. Version from which to upgrade, if not set, + * version specific upgrades will be disregarded. + * @param array|null $all_old_option_values Optional. Only used when importing old options to + * have access to the real old values, in contrast to + * the saved ones. * * @return void */ @@ -603,10 +801,23 @@ abstract class WPSEO_Option { } /** + * Retrieves the option name. + * + * @return string The set option name. + */ + public function get_option_name() { + return $this->option_name; + } + + /* * Concrete classes *may* contain a clean_option method which will clean out old/renamed * values within the option. + * + * ``` + * abstract public function clean_option( $option_value, $current_version = null, $all_old_option_values = null ); + * ``` */ - // abstract public function clean_option( $option_value, $current_version = null, $all_old_option_values = null ); + /* *********** HELPER METHODS for internal use. *********** */ /** @@ -616,22 +827,23 @@ abstract class WPSEO_Option { * @todo [JRF] - shouldn't this be a straight array merge ? at the end of the day, the validation * removes any invalid keys on save. * - * @param array $options Optional. Current options. If not set, the option defaults for the $option_key will be returned. + * @param array|null $options Optional. Current options. If not set, the option defaults + * for the $option_key will be returned. * - * @return array Combined and filtered options array. + * @return array Combined and filtered options array. */ protected function array_filter_merge( $options = null ) { $defaults = $this->get_defaults(); - if ( ! isset( $options ) || $options === false || $options === array() ) { + if ( ! isset( $options ) || $options === false || $options === [] ) { return $defaults; } $options = (array) $options; /* - $filtered = array(); + $filtered = array(); if ( $defaults !== array() ) { foreach ( $defaults as $key => $default_value ) { @@ -645,6 +857,51 @@ abstract class WPSEO_Option { return $filtered; } + /** + * Sets updated values for variables that are disabled via the override option back to their previous values. + * + * @param array $updated Updated option value. + * @param array $old Old option value. + * + * @return array Updated option value, with all disabled variables set to their old values. + */ + protected function prevent_disabled_options_update( $updated, $old ) { + $override_option = $this->get_override_option(); + if ( empty( $override_option ) ) { + return $updated; + } + + /* + * This loop could as well call `is_disabled( $key )` for each iteration, + * however this would be worse performance-wise. + */ + foreach ( $old as $key => $value ) { + if ( isset( $override_option[ self::ALLOW_KEY_PREFIX . $key ] ) && ! $override_option[ self::ALLOW_KEY_PREFIX . $key ] ) { + $updated[ $key ] = $old[ $key ]; + } + } + + return $updated; + } + + /** + * Retrieves the value of the override option, if available. + * + * An override option contains values that may determine access to certain sub-variables + * of this option. + * + * Only regular options in multisite can have override options, which in that case + * would be network options. + * + * @return array Override option value, or empty array if unavailable. + */ + protected function get_override_option() { + if ( empty( $this->override_option_name ) || $this->multisite_only === true || ! is_multisite() ) { + return []; + } + + return get_site_option( $this->override_option_name, [] ); + } /** * Make sure that any set option values relating to post_types and/or taxonomies are retained, @@ -653,15 +910,15 @@ abstract class WPSEO_Option { * {@internal The wpseo_titles concrete class overrules this method. Make sure that any * changes applied here, also get ported to that version.}} * - * @param array $dirty Original option as retrieved from the database. - * @param array $clean Filtered option where any options which shouldn't be in our option - * have already been removed and any options which weren't set - * have been set to their defaults. + * @param array $dirty Original option as retrieved from the database. + * @param array $clean Filtered option where any options which shouldn't be in our option + * have already been removed and any options which weren't set + * have been set to their defaults. * - * @return array + * @return array */ protected function retain_variable_keys( $dirty, $clean ) { - if ( ( is_array( $this->variable_array_key_patterns ) && $this->variable_array_key_patterns !== array() ) && ( is_array( $dirty ) && $dirty !== array() ) ) { + if ( ( is_array( $this->variable_array_key_patterns ) && $this->variable_array_key_patterns !== [] ) && ( is_array( $dirty ) && $dirty !== [] ) ) { foreach ( $dirty as $key => $value ) { // Do nothing if already in filtered options. @@ -687,13 +944,13 @@ abstract class WPSEO_Option { * * @usedby validate_option() methods for options with variable array keys. * - * @param string $key Array key to check. + * @param string $key Array key to check. * - * @return string Pattern if it conforms, original array key if it doesn't or if the option - * does not have variable array keys. + * @return string Pattern if it conforms, original array key if it doesn't or if the option + * does not have variable array keys. */ protected function get_switch_key( $key ) { - if ( ! isset( $this->variable_array_key_patterns ) || ( ! is_array( $this->variable_array_key_patterns ) || $this->variable_array_key_patterns === array() ) ) { + if ( ! isset( $this->variable_array_key_patterns ) || ( ! is_array( $this->variable_array_key_patterns ) || $this->variable_array_key_patterns === [] ) ) { return $key; } diff --git a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-options-backfill.php b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-options-backfill.php deleted file mode 100644 index e67d0263..00000000 --- a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-options-backfill.php +++ /dev/null @@ -1,312 +0,0 @@ -hooked ) { - return; - } - - $this->hooked = true; - - // Backfill options that were removed. - foreach ( $this->get_lookups() as $option ) { - add_filter( 'pre_option_' . $option, array( $this, 'backfill_option' ), 10, 2 ); - } - - // Make sure renamed meta key is backfilled. - add_filter( 'get_user_metadata', array( $this, 'backfill_usermeta' ), 10, 3 ); - - // Extend the options that have removed items. - add_filter( 'option_wpseo_titles', array( $this, 'extend_wpseo_titles' ), 10, 1 ); - add_filter( 'option_wpseo', array( $this, 'extend_wpseo' ), 10, 1 ); - } - - /** - * Removes the option filters. - */ - public function remove_hooks() { - // Remove backfill options filter. - foreach ( $this->get_lookups() as $option ) { - remove_filter( 'pre_option_' . $option, array( $this, 'backfill_option' ), 10 ); - } - - // Remove user meta filter. - remove_filter( 'get_user_metadata', array( $this, 'backfill_usermeta' ), 10 ); - - // Remove option extending filters. - remove_filter( 'option_wpseo_titles', array( $this, 'extend_wpseo_titles' ), 10 ); - remove_filter( 'option_wpseo', array( $this, 'extend_wpseo' ), 10 ); - - $this->hooked = false; - } - - /** - * Retrieves the options that need to be backfilled. - * - * @since 7.0.2 - * - * @return array List of options that need to be backfilled. - */ - protected function get_lookups() { - return array( - 'wpseo_internallinks', - 'wpseo_rss', - 'wpseo_xml', - 'wpseo_permalinks', - ); - } - - /** - * Retrieves the settings for the specified option. - * - * @since 7.0.2 - * - * @param string $option The option to get the settings for. - * - * @return array The settings for the provided option. - */ - protected function get_settings( $option ) { - $settings = array( - 'wpseo' => array( - 'website_name' => 'website_name', - 'alternate_website_name' => 'alternate_website_name', - 'company_logo' => 'company_logo', - 'company_name' => 'company_name', - 'company_or_person' => 'company_or_person', - 'person_name' => 'person_name', - ), - 'wpseo_internallinks' => - array( - 'breadcrumbs-404crumb' => 'breadcrumbs-404crumb', - 'breadcrumbs-blog-remove' => 'breadcrumbs-display-blog-page', - 'breadcrumbs-boldlast' => 'breadcrumbs-boldlast', - 'breadcrumbs-archiveprefix' => 'breadcrumbs-archiveprefix', - 'breadcrumbs-enable' => 'breadcrumbs-enable', - 'breadcrumbs-home' => 'breadcrumbs-home', - 'breadcrumbs-prefix' => 'breadcrumbs-prefix', - 'breadcrumbs-searchprefix' => 'breadcrumbs-searchprefix', - 'breadcrumbs-sep' => 'breadcrumbs-sep', - ), - - 'wpseo_rss' => - array( - 'rssbefore' => 'rssbefore', - 'rssafter' => 'rssafter', - ), - 'wpseo_xml' => - array( - 'enablexmlsitemap' => 'enable_xml_sitemap', - 'disable_author_sitemap' => 'noindex-author-wpseo', - 'disable_author_noposts' => 'noindex-author-noposts-wpseo', - ), - 'wpseo_permalinks' => array( - 'redirectattachment' => 'disable-attachment', - 'stripcategorybase' => 'stripcategorybase', - ), - ); - - if ( ! isset( $settings[ $option ] ) ) { - return array(); - } - - return $settings[ $option ]; - } - - /** - * Extends the WPSEO option with the removed option values. - * - * @since 7.0.2 - * - * @param array $data The data of the option. - * - * @return array Modified data. - */ - public function extend_wpseo( $data ) { - // Make sure we don't get stuck in an infinite loop. - static $running = false; - - // If we are already running, don't run again. - if ( $running ) { - return $data; - } - $running = true; - - foreach ( $this->get_settings( 'wpseo' ) as $old_key => $new_key ) { - $data[ $old_key ] = WPSEO_Options::get( $new_key ); - } - - // Ended running. - $running = false; - - return $data; - } - - /** - * Extends the WPSEO Title with removed attributes. - * - * @since 7.0.2 - * - * @param array $data Data of the option. - * - * @return array Extended data. - */ - public function extend_wpseo_titles( $data ) { - // Make sure we don't get stuck in an infinite loop. - static $running = false; - - // If we are already running, don't run again. - if ( $running ) { - return $data; - } - $running = true; - - $data['breadcrumbs-blog-remove'] = ! WPSEO_Options::get( 'breadcrumbs-display-blog-page' ); - - $running = false; - - $data = $this->add_hideeditbox( $data ); - - return $data; - } - - /** - * Backfills the options that have been removed with the current values. - * - * @since 7.0.2 - * - * @param mixed $value Current value for the option. - * @param string $option Name of the option. - * - * @return array Option data. - */ - public function backfill_option( $value, $option ) { - $output = array(); - - foreach ( $this->get_settings( $option ) as $old_key => $new_key ) { - $output[ $old_key ] = WPSEO_Options::get( $new_key ); - } - - $output = $this->apply_permalinks_settings( $output, $option ); - $output = $this->apply_xml_settings( $output, $option ); - - return $output; - } - - /** - * Backfills removed user meta fields. - * - * @since 7.0.2 - * - * @param mixed $value The current value. - * @param int $object_id The user ID. - * @param string $meta_key The meta key. - * - * @return mixed The backfilled value if applicable. - */ - public function backfill_usermeta( $value, $object_id, $meta_key ) { - if ( $meta_key !== 'wpseo_excludeauthorsitemap' ) { - return $value; - } - - return get_user_meta( $object_id, 'wpseo_noindex_author' ); - } - - /** - * Extends the data of the option with the deprecated values. - * - * @since 7.0.2 - * - * @param array $data Current data of the option. - * - * @return array Extended data. - */ - protected function add_hideeditbox( $data ) { - foreach ( $data as $key => $value ) { - if ( strpos( $key, 'display-metabox-tax-' ) === 0 ) { - $taxonomy = substr( $key, strlen( 'display-metabox-tax-' ) ); - $data[ 'hideeditbox-tax-' . $taxonomy ] = ! $value; - continue; - } - - if ( strpos( $key, 'display-metabox-pt-' ) === 0 ) { - $post_type = substr( $key, strlen( 'display-metabox-pt-' ) ); - $data[ 'hideeditbox-' . $post_type ] = ! $value; - continue; - } - } - - return $data; - } - - /** - * Adds the permalinks specific data to the option when requested. - * - * @since 7.0.2 - * - * @param array $data Current data. - * @param string $option The option that is being parsed. - * - * @return array Extended data. - */ - protected function apply_permalinks_settings( $data, $option ) { - if ( $option !== 'wpseo_permalinks' ) { - return $data; - } - - // Add defaults for completely removed settings in the option. - return array_merge( - $data, - array( - 'cleanpermalinks' => false, - 'cleanpermalink-extravars' => '', - 'cleanpermalink-googlecampaign' => false, - 'cleanpermalink-googlesitesearch' => false, - 'cleanreplytocom' => false, - 'cleanslugs' => false, - 'trailingslash' => false, - ) - ); - } - - /** - * Adds the XML specific data to the option when requested. - * - * @since 7.0.2 - * - * @param array $data Current data. - * @param string $option The option that is being parsed. - * - * @return array Extended data. - */ - protected function apply_xml_settings( $data, $option ) { - if ( $option !== 'wpseo_xml' ) { - return $data; - } - - // Add dynamic implementations for settings that are not in any option anymore. - return array_merge( - $data, - array( - 'entries-per-page' => (int) apply_filters( 'wpseo_sitemap_entries_per_page', 1000 ), - 'excluded-posts' => apply_filters( 'wpseo_exclude_from_sitemap_by_post_ids', array() ), - ) - ); - } -} diff --git a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-options.php b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-options.php index 68330227..83099613 100644 --- a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-options.php +++ b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-options.php @@ -6,80 +6,127 @@ */ /** - * Overal Option Management class. + * Overall Option Management class. * * Instantiates all the options and offers a number of utility methods to work with the options. */ class WPSEO_Options { + /** - * @var array Options this class uses. - * Array format: (string) option_name => (string) name of concrete class for the option - * @static + * The option values. + * + * @var null */ - public static $options = array( + protected static $option_values = null; + + /** + * Options this class uses. + * + * @var array Array format: (string) option_name => (string) name of concrete class for the option. + */ + public static $options = [ 'wpseo' => 'WPSEO_Option_Wpseo', 'wpseo_titles' => 'WPSEO_Option_Titles', 'wpseo_social' => 'WPSEO_Option_Social', 'wpseo_ms' => 'WPSEO_Option_MS', 'wpseo_taxonomy_meta' => 'WPSEO_Taxonomy_Meta', - ); + ]; + /** - * @var array Array of instantiated option objects. + * Array of instantiated option objects. + * + * @var array */ - protected static $option_instances = array(); + protected static $option_instances = []; + /** - * @var object Instance of this class. + * Array with the option names. + * + * @var array + */ + protected static $option_names = []; + + /** + * Instance of this class. + * + * @var WPSEO_Options */ protected static $instance; - /** @var WPSEO_Options_Backfill Backfill instance. */ - protected static $backfill; - /** * Instantiate all the WPSEO option management classes. */ protected function __construct() { - // Backfill option values after transferring them to another base. - self::$backfill = new WPSEO_Options_Backfill(); - self::$backfill->register_hooks(); + $this->register_hooks(); - $is_multisite = is_multisite(); - - foreach ( self::$options as $option_name => $option_class ) { - $instance = call_user_func( array( $option_class, 'get_instance' ) ); - - if ( ! $instance->multisite_only || $is_multisite ) { - self::$option_instances[ $option_name ] = $instance; - } - else { - unset( self::$options[ $option_name ] ); - } + foreach ( static::$options as $option_name => $option_class ) { + static::register_option( call_user_func( [ $option_class, 'get_instance' ] ) ); } } + /** + * Register our hooks. + */ + public function register_hooks() { + add_action( 'registered_taxonomy', [ $this, 'clear_cache' ] ); + add_action( 'unregistered_taxonomy', [ $this, 'clear_cache' ] ); + add_action( 'registered_post_type', [ $this, 'clear_cache' ] ); + add_action( 'unregistered_post_type', [ $this, 'clear_cache' ] ); + } + /** * Get the singleton instance of this class. * * @return object */ public static function get_instance() { - if ( ! ( self::$instance instanceof self ) ) { - self::$instance = new self(); + if ( ! ( static::$instance instanceof self ) ) { + static::$instance = new self(); } - return self::$instance; + return static::$instance; + } + + /** + * Registers an option to the options list. + * + * @param WPSEO_Option $option_instance Instance of the option. + */ + public static function register_option( WPSEO_Option $option_instance ) { + $option_name = $option_instance->get_option_name(); + + if ( $option_instance->multisite_only && ! static::is_multisite() ) { + unset( static::$options[ $option_name ], static::$option_names[ $option_name ] ); + + return; + } + + $is_already_registered = array_key_exists( $option_name, static::$options ); + if ( ! $is_already_registered ) { + static::$options[ $option_name ] = get_class( $option_instance ); + } + + if ( $option_instance->include_in_all === true ) { + static::$option_names[ $option_name ] = $option_name; + } + + static::$option_instances[ $option_name ] = $option_instance; + + if ( ! $is_already_registered ) { + static::clear_cache(); + } } /** * Get the group name of an option for use in the settings form. * - * @param string $option_name The option for which you want to retrieve the option group name. + * @param string $option_name The option for which you want to retrieve the option group name. * - * @return string|bool + * @return string|bool */ public static function get_group_name( $option_name ) { - if ( isset( self::$option_instances[ $option_name ] ) ) { - return self::$option_instances[ $option_name ]->group_name; + if ( isset( static::$option_instances[ $option_name ] ) ) { + return static::$option_instances[ $option_name ]->group_name; } return false; @@ -88,14 +135,14 @@ class WPSEO_Options { /** * Get a specific default value for an option. * - * @param string $option_name The option for which you want to retrieve a default. - * @param string $key The key within the option who's default you want. + * @param string $option_name The option for which you want to retrieve a default. + * @param string $key The key within the option who's default you want. * - * @return mixed + * @return mixed */ public static function get_default( $option_name, $key ) { - if ( isset( self::$option_instances[ $option_name ] ) ) { - $defaults = self::$option_instances[ $option_name ]->get_defaults(); + if ( isset( static::$option_instances[ $option_name ] ) ) { + $defaults = static::$option_instances[ $option_name ]->get_defaults(); if ( isset( $defaults[ $key ] ) ) { return $defaults[ $key ]; } @@ -107,14 +154,14 @@ class WPSEO_Options { /** * Update a site_option. * - * @param string $option_name The option name of the option to save. - * @param mixed $value The new value for the option. + * @param string $option_name The option name of the option to save. + * @param mixed $value The new value for the option. * * @return bool */ public static function update_site_option( $option_name, $value ) { - if ( is_network_admin() && isset( self::$option_instances[ $option_name ] ) ) { - return self::$option_instances[ $option_name ]->update_site_option( $value ); + if ( is_multisite() && isset( static::$option_instances[ $option_name ] ) ) { + return static::$option_instances[ $option_name ]->update_site_option( $value ); } return false; @@ -123,13 +170,13 @@ class WPSEO_Options { /** * Get the instantiated option instance. * - * @param string $option_name The option for which you want to retrieve the instance. + * @param string $option_name The option for which you want to retrieve the instance. * - * @return object|bool + * @return object|bool */ public static function get_option_instance( $option_name ) { - if ( isset( self::$option_instances[ $option_name ] ) ) { - return self::$option_instances[ $option_name ]; + if ( isset( static::$option_instances[ $option_name ] ) ) { + return static::$option_instances[ $option_name ]; } return false; @@ -138,53 +185,54 @@ class WPSEO_Options { /** * Retrieve an array of the options which should be included in get_all() and reset(). * - * @static - * @return array Array of option names + * @return array Array of option names. */ public static function get_option_names() { - static $option_names = array(); - - if ( $option_names === array() ) { - foreach ( self::$option_instances as $option_name => $option_object ) { + $option_names = array_values( static::$option_names ); + if ( $option_names === [] ) { + foreach ( static::$option_instances as $option_name => $option_object ) { if ( $option_object->include_in_all === true ) { $option_names[] = $option_name; } } - $option_names = apply_filters( 'wpseo_options', $option_names ); } - return $option_names; + /** + * Filter: wpseo_options - Allow developers to change the option name to include. + * + * @api array The option names to include in get_all and reset(). + */ + return apply_filters( 'wpseo_options', $option_names ); } /** * Retrieve all the options for the SEO plugin in one go. * - * @todo [JRF] see if we can get some extra efficiency for this one, though probably not as options may - * well change between calls (enriched defaults and such) - * - * @static - * @return array Array combining the values of all the options + * @return array Array combining the values of all the options. */ public static function get_all() { - return self::get_options( self::get_option_names() ); + static::$option_values = static::get_options( static::get_option_names() ); + + return static::$option_values; } /** * Retrieve one or more options for the SEO plugin. * - * @static - * * @param array $option_names An array of option names of the options you want to get. * - * @return array Array combining the values of the requested options + * @return array Array combining the values of the requested options. */ public static function get_options( array $option_names ) { - $options = array(); + $options = []; $option_names = array_filter( $option_names, 'is_string' ); foreach ( $option_names as $option_name ) { - if ( isset( self::$option_instances[ $option_name ] ) ) { - $option = self::get_option( $option_name ); - $options = array_merge( $options, $option ); + if ( isset( static::$option_instances[ $option_name ] ) ) { + $option = static::get_option( $option_name ); + + if ( $option !== null ) { + $options = array_merge( $options, $option ); + } } } @@ -194,8 +242,6 @@ class WPSEO_Options { /** * Retrieve a single option for the SEO plugin. * - * @static - * * @param string $option_name The name of the option you want to get. * * @return array Array containing the requested option. @@ -203,8 +249,8 @@ class WPSEO_Options { public static function get_option( $option_name ) { $option = null; if ( is_string( $option_name ) && ! empty( $option_name ) ) { - if ( isset( self::$option_instances[ $option_name ] ) ) { - if ( self::$option_instances[ $option_name ]->multisite_only !== true ) { + if ( isset( static::$option_instances[ $option_name ] ) ) { + if ( static::$option_instances[ $option_name ]->multisite_only !== true ) { $option = get_option( $option_name ); } else { @@ -225,19 +271,31 @@ class WPSEO_Options { * @return mixed|null Returns value if found, $default if not. */ public static function get( $key, $default = null ) { - self::$backfill->remove_hooks(); - - $option = self::get_all(); - - self::$backfill->register_hooks(); - - if ( isset( $option[ $key ] ) ) { - return $option[ $key ]; + if ( static::$option_values === null ) { + static::prime_cache(); + } + if ( isset( static::$option_values[ $key ] ) ) { + return static::$option_values[ $key ]; } return $default; } + /** + * Resets the cache to null. + */ + public static function clear_cache() { + static::$option_values = null; + } + + /** + * Primes our cache. + */ + private static function prime_cache() { + static::$option_values = static::get_all(); + static::$option_values = static::add_ms_option( static::$option_values ); + } + /** * Retrieve a single field from an option for the SEO plugin. * @@ -247,25 +305,25 @@ class WPSEO_Options { * @return mixed|null Returns value if found, $default if not. */ public static function set( $key, $value ) { - $lookup_table = self::get_lookup_table(); + $lookup_table = static::get_lookup_table(); if ( isset( $lookup_table[ $key ] ) ) { - return self::save_option( $lookup_table[ $key ], $key, $value ); + return static::save_option( $lookup_table[ $key ], $key, $value ); } - $patterns = self::get_pattern_table(); + $patterns = static::get_pattern_table(); foreach ( $patterns as $pattern => $option ) { if ( strpos( $key, $pattern ) === 0 ) { - return self::save_option( $option, $key, $value ); + return static::save_option( $option, $key, $value ); } } + + static::$option_values[ $key ] = $value; } /** * Get an option only if it's been auto-loaded. * - * @static - * * @param string $option The option to retrieve. * @param bool|mixed $default A default value to return. * @@ -273,42 +331,44 @@ class WPSEO_Options { */ public static function get_autoloaded_option( $option, $default = false ) { $value = wp_cache_get( $option, 'options' ); - if ( false === $value ) { + if ( $value === false ) { $passed_default = func_num_args() > 1; + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Using WP native filter. return apply_filters( "default_option_{$option}", $default, $option, $passed_default ); } + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Using WP native filter. return apply_filters( "option_{$option}", maybe_unserialize( $value ), $option ); } /** * Run the clean up routine for one or all options. * - * @param array|string $option_name Optional. the option you want to clean or an array of - * option names for the options you want to clean. - * If not set, all options will be cleaned. - * @param string $current_version Optional. Version from which to upgrade, if not set, - * version specific upgrades will be disregarded. + * @param array|string|null $option_name Optional. the option you want to clean or an array of + * option names for the options you want to clean. + * If not set, all options will be cleaned. + * @param string|null $current_version Optional. Version from which to upgrade, if not set, + * version specific upgrades will be disregarded. * - * @return void + * @return void */ public static function clean_up( $option_name = null, $current_version = null ) { if ( isset( $option_name ) && is_string( $option_name ) && $option_name !== '' ) { - if ( isset( self::$option_instances[ $option_name ] ) ) { - self::$option_instances[ $option_name ]->clean( $current_version ); + if ( isset( static::$option_instances[ $option_name ] ) ) { + static::$option_instances[ $option_name ]->clean( $current_version ); } } - elseif ( isset( $option_name ) && is_array( $option_name ) && $option_name !== array() ) { + elseif ( isset( $option_name ) && is_array( $option_name ) && $option_name !== [] ) { foreach ( $option_name as $option ) { - if ( isset( self::$option_instances[ $option ] ) ) { - self::$option_instances[ $option ]->clean( $current_version ); + if ( isset( static::$option_instances[ $option ] ) ) { + static::$option_instances[ $option ]->clean( $current_version ); } } unset( $option ); } else { - foreach ( self::$option_instances as $instance ) { + foreach ( static::$option_instances as $instance ) { $instance->clean( $current_version ); } unset( $instance ); @@ -321,10 +381,10 @@ class WPSEO_Options { /** * Check that all options exist in the database and add any which don't. * - * @return void + * @return void */ public static function ensure_options_exist() { - foreach ( self::$option_instances as $instance ) { + foreach ( static::$option_instances as $instance ) { $instance->maybe_add_option(); } } @@ -332,7 +392,6 @@ class WPSEO_Options { /** * Initialize some options on first install/activate/reset. * - * @static * @return void */ public static function initialize() { @@ -345,13 +404,12 @@ class WPSEO_Options { /** * Reset all options to their default values and rerun some tests. * - * @static * @return void */ public static function reset() { if ( ! is_multisite() ) { - $option_names = self::get_option_names(); - if ( is_array( $option_names ) && $option_names !== array() ) { + $option_names = static::get_option_names(); + if ( is_array( $option_names ) && $option_names !== [] ) { foreach ( $option_names as $option_name ) { delete_option( $option_name ); update_option( $option_name, get_option( $option_name ) ); @@ -361,18 +419,16 @@ class WPSEO_Options { } else { // Reset MS blog based on network default blog setting. - self::reset_ms_blog( get_current_blog_id() ); + static::reset_ms_blog( get_current_blog_id() ); } - self::initialize(); + static::initialize(); } /** * Initialize default values for a new multisite blog. * - * @static - * - * @param bool $force_init Whether to always do the initialization routine (title/desc test). + * @param bool $force_init Whether to always do the initialization routine (title/desc test). * * @return void */ @@ -381,11 +437,11 @@ class WPSEO_Options { if ( is_multisite() ) { if ( $option['ms_defaults_set'] === false ) { - self::reset_ms_blog( get_current_blog_id() ); - self::initialize(); + static::reset_ms_blog( get_current_blog_id() ); + static::initialize(); } elseif ( $force_init === true ) { - self::initialize(); + static::initialize(); } } } @@ -394,18 +450,16 @@ class WPSEO_Options { * Reset all options for a specific multisite blog to their default values based upon a * specified default blog if one was chosen on the network page or the plugin defaults if it was not. * - * @static + * @param int|string $blog_id Blog id of the blog for which to reset the options. * - * @param int|string $blog_id Blog id of the blog for which to reset the options. - * - * @return void + * @return void */ public static function reset_ms_blog( $blog_id ) { if ( is_multisite() ) { $options = get_site_option( 'wpseo_ms' ); - $option_names = self::get_option_names(); + $option_names = static::get_option_names(); - if ( is_array( $option_names ) && $option_names !== array() ) { + if ( is_array( $option_names ) && $option_names !== [] ) { $base_blog_id = $blog_id; if ( $options['defaultblog'] !== '' && $options['defaultblog'] !== 0 ) { $base_blog_id = $options['defaultblog']; @@ -417,8 +471,8 @@ class WPSEO_Options { $new_option = get_blog_option( $base_blog_id, $option_name ); /* Remove sensitive, theme dependent and site dependent info. */ - if ( isset( self::$option_instances[ $option_name ] ) && self::$option_instances[ $option_name ]->ms_exclude !== array() ) { - foreach ( self::$option_instances[ $option_name ]->ms_exclude as $key ) { + if ( isset( static::$option_instances[ $option_name ] ) && static::$option_instances[ $option_name ]->ms_exclude !== [] ) { + foreach ( static::$option_instances[ $option_name ]->ms_exclude as $key ) { unset( $new_option[ $key ] ); } } @@ -438,40 +492,81 @@ class WPSEO_Options { * * @param string $wpseo_options_group_name The name for the wpseo option group in the database. * @param string $option_name The name for the option to set. - * @param * $option_value The value for the option. + * @param mixed $option_value The value for the option. * - * @return boolean Returns true if the option is successfully saved in the database. + * @return bool Returns true if the option is successfully saved in the database. */ public static function save_option( $wpseo_options_group_name, $option_name, $option_value ) { - $options = WPSEO_Options::get_option( $wpseo_options_group_name ); + $options = static::get_option( $wpseo_options_group_name ); $options[ $option_name ] = $option_value; - update_option( $wpseo_options_group_name, $options ); + + if ( isset( static::$option_instances[ $wpseo_options_group_name ] ) && static::$option_instances[ $wpseo_options_group_name ]->multisite_only === true ) { + static::update_site_option( $wpseo_options_group_name, $options ); + } + else { + update_option( $wpseo_options_group_name, $options ); + } // Check if everything got saved properly. - $saved_option = self::get_option( $wpseo_options_group_name ); + $saved_option = static::get_option( $wpseo_options_group_name ); + + // Clear our cache. + static::clear_cache(); return $saved_option[ $option_name ] === $options[ $option_name ]; } + /** + * Adds the multisite options to the option stack if relevant. + * + * @param array $option The currently present options settings. + * + * @return array Options possibly including multisite. + */ + protected static function add_ms_option( $option ) { + if ( ! is_multisite() ) { + return $option; + } + + $ms_option = static::get_option( 'wpseo_ms' ); + if ( $ms_option === null ) { + return $option; + } + + return array_merge( $option, $ms_option ); + } + + /** + * Checks if installation is multisite. + * + * @return bool True when is multisite. + */ + protected static function is_multisite() { + static $is_multisite; + + if ( $is_multisite === null ) { + $is_multisite = is_multisite(); + } + + return $is_multisite; + } + /** * Retrieves a lookup table to find in which option_group a key is stored. * * @return array The lookup table. */ private static function get_lookup_table() { - $lookup_table = array(); + $lookup_table = []; - self::$backfill->remove_hooks(); - foreach ( array_keys( self::$options ) as $option_name ) { - $full_option = self::get_option( $option_name ); + foreach ( array_keys( static::$options ) as $option_name ) { + $full_option = static::get_option( $option_name ); foreach ( $full_option as $key => $value ) { $lookup_table[ $key ] = $option_name; } } - self::$backfill->register_hooks(); - return $lookup_table; } @@ -481,10 +576,9 @@ class WPSEO_Options { * @return array The lookup table. */ private static function get_pattern_table() { - $pattern_table = array(); - foreach ( self::$options as $option_name => $option_class ) { - /** @var WPSEO_Option $instance */ - $instance = call_user_func( array( $option_class, 'get_instance' ) ); + $pattern_table = []; + foreach ( static::$options as $option_name => $option_class ) { + $instance = call_user_func( [ $option_class, 'get_instance' ] ); foreach ( $instance->get_patterns() as $key ) { $pattern_table[ $key ] = $option_name; } @@ -492,15 +586,4 @@ class WPSEO_Options { return $pattern_table; } - - /** - * Correct the inadvertent removal of the fallback to default values from the breadcrumbs. - * - * @since 1.5.2.3 - * - * @deprecated 7.0 - */ - public static function bring_back_breadcrumb_defaults() { - _deprecated_function( __METHOD__, 'WPSEO 7.0' ); - } } diff --git a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-taxonomy-meta.php b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-taxonomy-meta.php index b80107d9..3f3ec405 100644 --- a/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-taxonomy-meta.php +++ b/wp-content/plugins/wordpress-seo/inc/options/class-wpseo-taxonomy-meta.php @@ -11,38 +11,46 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { /** - * @var string Option name. + * Option name. + * + * @var string */ public $option_name = 'wpseo_taxonomy_meta'; /** - * @var bool Whether to include the option in the return for WPSEO_Options::get_all(). + * Whether to include the option in the return for WPSEO_Options::get_all(). + * + * @var bool */ public $include_in_all = false; /** - * @var array Array of defaults for the option. - * Shouldn't be requested directly, use $this->get_defaults(); + * Array of defaults for the option. + * + * Shouldn't be requested directly, use $this->get_defaults(); * * {@internal Important: in contrast to most defaults, the below array format is * very bare. The real option is in the format [taxonomy_name][term_id][...] * where [...] is any of the $defaults_per_term options shown below. * This is of course taken into account in the below methods.}} + * + * @var array */ - protected $defaults = array(); - + protected $defaults = []; /** - * @var string Option name - same as $option_name property, but now also available to static methods. - * @static + * Option name - same as $option_name property, but now also available to static methods. + * + * @var string */ public static $name; /** - * @var array Array of defaults for individual taxonomy meta entries. - * @static + * Array of defaults for individual taxonomy meta entries. + * + * @var array */ - public static $defaults_per_term = array( + public static $defaults_per_term = [ 'wpseo_title' => '', 'wpseo_desc' => '', 'wpseo_canonical' => '', @@ -51,29 +59,35 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { 'wpseo_focuskw' => '', 'wpseo_linkdex' => '', 'wpseo_content_score' => '', + 'wpseo_focuskeywords' => '[]', + 'wpseo_keywordsynonyms' => '[]', + 'wpseo_is_cornerstone' => '0', // Social fields. 'wpseo_opengraph-title' => '', 'wpseo_opengraph-description' => '', 'wpseo_opengraph-image' => '', + 'wpseo_opengraph-image-id' => '', 'wpseo_twitter-title' => '', 'wpseo_twitter-description' => '', 'wpseo_twitter-image' => '', - ); + 'wpseo_twitter-image-id' => '', + ]; /** - * @var array Available index options. - * Used for form generation and input validation. + * Available index options. * - * @static + * Used for form generation and input validation. * * {@internal Labels (translation) added on admin_init via WPSEO_Taxonomy::translate_meta_options().}} + * + * @var array */ - public static $no_index_options = array( + public static $no_index_options = [ 'default' => '', 'index' => '', 'noindex' => '', - ); + ]; /** * Add the actions and filters for the option. @@ -81,20 +95,13 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { * @todo [JRF => testers] Check if the extra actions below would run into problems if an option * is updated early on and if so, change the call to schedule these for a later action on add/update * instead of running them straight away. - * - * @return \WPSEO_Taxonomy_Meta */ protected function __construct() { parent::__construct(); self::$name = $this->option_name; - - /* On succesfull update/add of the option, flush the W3TC cache. */ - add_action( 'add_option_' . $this->option_name, array( 'WPSEO_Utils', 'flush_w3tc_cache' ) ); - add_action( 'update_option_' . $this->option_name, array( 'WPSEO_Utils', 'flush_w3tc_cache' ) ); } - /** * Get the singleton instance of this class. * @@ -109,82 +116,24 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { return self::$instance; } - /** * Add extra default options received from a filter. */ public function enrich_defaults() { - $extra_defaults_per_term = apply_filters( 'wpseo_add_extra_taxmeta_term_defaults', array() ); + $extra_defaults_per_term = apply_filters( 'wpseo_add_extra_taxmeta_term_defaults', [] ); if ( is_array( $extra_defaults_per_term ) ) { self::$defaults_per_term = array_merge( $extra_defaults_per_term, self::$defaults_per_term ); } } - - /** - * Helper method - Combines a fixed array of default values with an options array - * while filtering out any keys which are not in the defaults array. - * - * @static - * - * @param string $option_key Option name of the option we're doing the merge for. - * @param array $options Optional. Current options. If not set, the option defaults for the $option_key will be returned. - * - * @return array Combined and filtered options array. - */ - - /* - Public function array_filter_merge( $option_key, $options = null ) { - - $defaults = $this->get_defaults( $option_key ); - - if ( ! isset( $options ) || $options === false ) { - return $defaults; - } - - / * - {@internal Adding the defaults to all taxonomy terms each time the option is retrieved - will be quite inefficient if there are a lot of taxonomy terms. - As long as taxonomy_meta is only retrieved via methods in this class, we shouldn't need this.}} - - $options = (array) $options; - $filtered = array(); - - if ( $options !== array() ) { - foreach ( $options as $taxonomy => $terms ) { - if ( is_array( $terms ) && $terms !== array() ) { - foreach ( $terms as $id => $term_meta ) { - foreach ( self::$defaults_per_term as $name => $default ) { - if ( isset( $options[ $taxonomy ][ $id ][ $name ] ) ) { - $filtered[ $taxonomy ][ $id ][ $name ] = $options[ $taxonomy ][ $id ][ $name ]; - } - else { - $filtered[ $name ] = $default; - } - } - } - } - } - unset( $taxonomy, $terms, $id, $term_meta, $name, $default ); - } - // end of may be remove. - - return $filtered; - * / - - return (array) $options; - } - */ - - /** * Validate the option. * - * @param array $dirty New value for the option. - * @param array $clean Clean value for the option, normally the defaults. - * @param array $old Old value of the option. + * @param array $dirty New value for the option. + * @param array $clean Clean value for the option, normally the defaults. + * @param array $old Old value of the option. * - * @return array Validated clean value for the option to be saved to the database. + * @return array Validated clean value for the option to be saved to the database. */ protected function validate_option( $dirty, $clean, $old ) { /* @@ -197,10 +146,9 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { return $dirty; } - foreach ( $dirty as $taxonomy => $terms ) { /* Don't validate taxonomy - may not be registered yet and we don't want to remove valid ones. */ - if ( is_array( $terms ) && $terms !== array() ) { + if ( is_array( $terms ) && $terms !== [] ) { foreach ( $terms as $term_id => $meta_data ) { /* Only validate term if the taxonomy exists. */ if ( taxonomy_exists( $taxonomy ) && get_term_by( 'id', $term_id, $taxonomy ) === false ) { @@ -211,11 +159,11 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { continue; } - if ( is_array( $meta_data ) && $meta_data !== array() ) { + if ( is_array( $meta_data ) && $meta_data !== [] ) { /* Validate meta data. */ $old_meta = self::get_term_meta( $term_id, $taxonomy ); $meta_data = self::validate_term_meta_data( $meta_data, $old_meta ); - if ( $meta_data !== array() ) { + if ( $meta_data !== [] ) { $clean[ $taxonomy ][ $term_id ] = $meta_data; } } @@ -231,23 +179,20 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { return $clean; } - /** * Validate the meta data for one individual term and removes default values (no need to save those). * - * @static + * @param array $meta_data New values. + * @param array $old_meta The original values. * - * @param array $meta_data New values. - * @param array $old_meta The original values. - * - * @return array Validated and filtered value. + * @return array Validated and filtered value. */ public static function validate_term_meta_data( $meta_data, $old_meta ) { $clean = self::$defaults_per_term; - $meta_data = array_map( array( 'WPSEO_Utils', 'trim_recursive' ), $meta_data ); + $meta_data = array_map( [ 'WPSEO_Utils', 'trim_recursive' ], $meta_data ); - if ( ! is_array( $meta_data ) || $meta_data === array() ) { + if ( ! is_array( $meta_data ) || $meta_data === [] ) { return $clean; } @@ -278,33 +223,69 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { case 'wpseo_bctitle': if ( isset( $meta_data[ $key ] ) ) { - $clean[ $key ] = WPSEO_Utils::sanitize_text_field( stripslashes( $meta_data[ $key ] ) ); + $clean[ $key ] = WPSEO_Utils::sanitize_text_field( $meta_data[ $key ] ); } elseif ( isset( $old_meta[ $key ] ) ) { // Retain old value if field currently not in use. $clean[ $key ] = $old_meta[ $key ]; } break; + + case 'wpseo_keywordsynonyms': + if ( isset( $meta_data[ $key ] ) && is_string( $meta_data[ $key ] ) ) { + // The data is stringified JSON. Use `json_decode` and `json_encode` around the sanitation. + $input = json_decode( $meta_data[ $key ], true ); + $sanitized = array_map( [ 'WPSEO_Utils', 'sanitize_text_field' ], $input ); + $clean[ $key ] = WPSEO_Utils::format_json_encode( $sanitized ); + } + elseif ( isset( $old_meta[ $key ] ) ) { + // Retain old value if field currently not in use. + $clean[ $key ] = $old_meta[ $key ]; + } + break; + + case 'wpseo_focuskeywords': + if ( isset( $meta_data[ $key ] ) && is_string( $meta_data[ $key ] ) ) { + // The data is stringified JSON. Use `json_decode` and `json_encode` around the sanitation. + $input = json_decode( $meta_data[ $key ], true ); + + // This data has two known keys: `keyword` and `score`. + $sanitized = []; + foreach ( $input as $entry ) { + $sanitized[] = [ + 'keyword' => WPSEO_Utils::sanitize_text_field( $entry['keyword'] ), + 'score' => WPSEO_Utils::sanitize_text_field( $entry['score'] ), + ]; + } + + $clean[ $key ] = WPSEO_Utils::format_json_encode( $sanitized ); + } + elseif ( isset( $old_meta[ $key ] ) ) { + // Retain old value if field currently not in use. + $clean[ $key ] = $old_meta[ $key ]; + } + break; + case 'wpseo_focuskw': case 'wpseo_title': case 'wpseo_desc': case 'wpseo_linkdex': default: if ( isset( $meta_data[ $key ] ) && is_string( $meta_data[ $key ] ) ) { - $clean[ $key ] = WPSEO_Utils::sanitize_text_field( stripslashes( $meta_data[ $key ] ) ); + $clean[ $key ] = WPSEO_Utils::sanitize_text_field( $meta_data[ $key ] ); } - if ( 'wpseo_focuskw' === $key ) { - $clean[ $key ] = str_replace( array( + if ( $key === 'wpseo_focuskw' ) { + $search = [ '<', '>', - '"', '`', '<', '>', - '"', '`', - ), '', $clean[ $key ] ); + ]; + + $clean[ $key ] = str_replace( $search, '', $clean[ $key ] ); } break; } @@ -316,32 +297,31 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { return array_diff_assoc( $clean, self::$defaults_per_term ); } - /** * Clean a given option value. * - Convert old option values to new * - Fixes strings which were escaped (should have been sanitized - escaping is for output) * - * @param array $option_value Old (not merged with defaults or filtered) option value to - * clean according to the rules for this option. - * @param string $current_version Optional. Version from which to upgrade, if not set, - * version specific upgrades will be disregarded. - * @param array $all_old_option_values Optional. Only used when importing old options to have - * access to the real old values, in contrast to the saved ones. + * @param array $option_value Old (not merged with defaults or filtered) option value to + * clean according to the rules for this option. + * @param string|null $current_version Optional. Version from which to upgrade, if not set, + * version specific upgrades will be disregarded. + * @param array|null $all_old_option_values Optional. Only used when importing old options to have + * access to the real old values, in contrast to the saved ones. * - * @return array Cleaned option. + * @return array Cleaned option. */ protected function clean_option( $option_value, $current_version = null, $all_old_option_values = null ) { /* Clean up old values and remove empty arrays. */ - if ( is_array( $option_value ) && $option_value !== array() ) { + if ( is_array( $option_value ) && $option_value !== [] ) { foreach ( $option_value as $taxonomy => $terms ) { - if ( is_array( $terms ) && $terms !== array() ) { + if ( is_array( $terms ) && $terms !== [] ) { foreach ( $terms as $term_id => $meta_data ) { - if ( ! is_array( $meta_data ) || $meta_data === array() ) { + if ( ! is_array( $meta_data ) || $meta_data === [] ) { // Remove empty term arrays. unset( $option_value[ $taxonomy ][ $term_id ] ); } @@ -361,7 +341,7 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { case 'wpseo_title': case 'wpseo_desc': case 'wpseo_linkdex': - // @todo [JRF => whomever] needs checking, I don't have example data [JRF]. + // @todo [JRF => whomever] Needs checking, I don't have example data [JRF]. if ( $value !== '' ) { // Fix incorrectly saved (encoded) canonical urls and texts. $option_value[ $taxonomy ][ $term_id ][ $key ] = wp_specialchars_decode( stripslashes( $value ), ENT_QUOTES ); @@ -369,7 +349,7 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { break; default: - // @todo [JRF => whomever] needs checking, I don't have example data [JRF]. + // @todo [JRF => whomever] Needs checking, I don't have example data [JRF]. if ( $value !== '' ) { // Fix incorrectly saved (escaped) text strings. $option_value[ $taxonomy ][ $term_id ][ $key ] = wp_specialchars_decode( $value, ENT_QUOTES ); @@ -390,20 +370,17 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { return $option_value; } - /** * Retrieve a taxonomy term's meta value(s). * - * @static + * @param mixed $term Term to get the meta value for + * either (string) term name, (int) term id or (object) term. + * @param string $taxonomy Name of the taxonomy to which the term is attached. + * @param string|null $meta Optional. Meta value to get (without prefix). * - * @param mixed $term Term to get the meta value for - * either (string) term name, (int) term id or (object) term. - * @param string $taxonomy Name of the taxonomy to which the term is attached. - * @param string $meta Optional. Meta value to get (without prefix). - * - * @return mixed|bool Value for the $meta if one is given, might be the default. - * If no meta is given, an array of all the meta data for the term. - * False if the term does not exist or the $meta provided is invalid. + * @return mixed|bool Value for the $meta if one is given, might be the default. + * If no meta is given, an array of all the meta data for the term. + * False if the term does not exist or the $meta provided is invalid. */ public static function get_term_meta( $term, $taxonomy, $meta = null ) { /* Figure out the term id. */ @@ -448,9 +425,11 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { */ public static function get_meta_without_term( $meta ) { $term = $GLOBALS['wp_query']->get_queried_object(); + if ( ! $term || empty( $term->taxonomy ) ) { + return false; + } return self::get_term_meta( $term, $term->taxonomy, $meta ); - } /** @@ -482,7 +461,7 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { $meta_key = 'wpseo_' . $meta_key; } - self::set_values( $term_id, $taxonomy, array( $meta_key => $meta_value ) ); + self::set_values( $term_id, $taxonomy, [ $meta_key => $meta_value ] ); } /** @@ -498,7 +477,7 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { $tax_meta = self::get_tax_meta(); - $found = array(); + $found = []; // @todo Check for terms of all taxonomies, not only the current taxonomy. foreach ( $tax_meta as $taxonomy_name => $terms ) { foreach ( $terms as $term_id => $meta_values ) { @@ -509,7 +488,7 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { } } - return array( $keyword => $found ); + return [ $keyword => $found ]; } /** @@ -523,12 +502,12 @@ class WPSEO_Taxonomy_Meta extends WPSEO_Option { $tax_meta = self::get_tax_meta(); /* Add/remove the result to/from the original option value. */ - if ( $clean !== array() ) { + if ( $clean !== [] ) { $tax_meta[ $taxonomy ][ $term_id ] = $clean; } else { unset( $tax_meta[ $taxonomy ][ $term_id ] ); - if ( isset( $tax_meta[ $taxonomy ] ) && $tax_meta[ $taxonomy ] === array() ) { + if ( isset( $tax_meta[ $taxonomy ] ) && $tax_meta[ $taxonomy ] === [] ) { unset( $tax_meta[ $taxonomy ] ); } } diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-author-sitemap-provider.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-author-sitemap-provider.php index 35f04da0..db42849a 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-author-sitemap-provider.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-author-sitemap-provider.php @@ -5,6 +5,8 @@ * @package WPSEO\XML_Sitemaps */ +use Yoast\WP\SEO\Helpers\Author_Archive_Helper; + /** * Sitemap provider for author archives. */ @@ -15,22 +17,28 @@ class WPSEO_Author_Sitemap_Provider implements WPSEO_Sitemap_Provider { * * @param string $type Type string to check for. * - * @return boolean + * @return bool */ public function handles_type( $type ) { + // If the author archives have been disabled, we don't do anything. + if ( WPSEO_Options::get( 'disable-author', false ) || WPSEO_Options::get( 'noindex-author-wpseo', false ) ) { + return false; + } return $type === 'author'; } /** + * Get the links for the sitemap index. + * * @param int $max_entries Entries per sitemap. * * @return array */ public function get_index_links( $max_entries ) { - if ( WPSEO_Options::get( 'disable-author', false ) || WPSEO_Options::get( 'noindex-author-wpseo', false ) ) { - return array(); + if ( ! $this->handles_type( 'author' ) ) { + return []; } // @todo Consider doing this less often / when necessary. R. @@ -38,7 +46,7 @@ class WPSEO_Author_Sitemap_Provider implements WPSEO_Sitemap_Provider { $has_exclude_filter = has_filter( 'wpseo_sitemap_exclude_author' ); - $query_arguments = array(); + $query_arguments = []; if ( ! $has_exclude_filter ) { // We only need full users if legacy filter(s) hooked to exclusion logic. R. $query_arguments['fields'] = 'ID'; @@ -52,10 +60,10 @@ class WPSEO_Author_Sitemap_Provider implements WPSEO_Sitemap_Provider { } if ( empty( $users ) ) { - return array(); + return []; } - $index = array(); + $index = []; $page = 1; $user_pages = array_chunk( $users, $max_entries ); @@ -67,12 +75,12 @@ class WPSEO_Author_Sitemap_Provider implements WPSEO_Sitemap_Provider { $user_id = array_shift( $users_page ); // Time descending, first user on page is most recently updated. $user = get_user_by( 'id', $user_id ); - $index[] = array( + $index[] = [ 'loc' => WPSEO_Sitemaps_Router::get_base_url( 'author-sitemap' . $page . '.xml' ), - 'lastmod' => '@' . $user->_yoast_wpseo_profile_updated, // @ for explicit timestamp format - ); + 'lastmod' => ( $user->_yoast_wpseo_profile_updated ) ? YoastSEO()->helpers->date->format_timestamp( $user->_yoast_wpseo_profile_updated ) : null, + ]; - $page++; + ++$page; } return $index; @@ -85,41 +93,41 @@ class WPSEO_Author_Sitemap_Provider implements WPSEO_Sitemap_Provider { * * @return array */ - protected function get_users( $arguments = array() ) { + protected function get_users( $arguments = [] ) { global $wpdb; - $defaults = array( - // @todo Re-enable after plugin requirements raised to WP 4.6 with the fix. - // 'who' => 'authors', Breaks meta keys, see https://core.trac.wordpress.org/ticket/36724#ticket R. + $defaults = [ + 'who' => 'authors', 'meta_key' => '_yoast_wpseo_profile_updated', 'orderby' => 'meta_value_num', 'order' => 'DESC', - 'meta_query' => array( + 'meta_query' => [ 'relation' => 'AND', - array( + [ 'key' => $wpdb->get_blog_prefix() . 'user_level', 'value' => '0', 'compare' => '!=', - ), - array( + ], + [ 'relation' => 'OR', - array( + [ 'key' => 'wpseo_noindex_author', 'value' => 'on', 'compare' => '!=', - ), - array( + ], + [ 'key' => 'wpseo_noindex_author', 'compare' => 'NOT EXISTS', - ), - ), - ), - ); + ], + ], + ], + ]; if ( WPSEO_Options::get( 'noindex-author-noposts-wpseo', true ) ) { - // $defaults['who'] = ''; // Otherwise it cancels out next argument. - $defaults['has_published_posts'] = true; + $defaults['who'] = ''; // Otherwise it cancels out next argument. + $author_archive = new Author_Archive_Helper(); + $defaults['has_published_posts'] = $author_archive->get_author_archive_post_types(); } return get_users( array_merge( $defaults, $arguments ) ); @@ -133,24 +141,32 @@ class WPSEO_Author_Sitemap_Provider implements WPSEO_Sitemap_Provider { * @param int $current_page Current page of the sitemap. * * @return array + * + * @throws OutOfBoundsException When an invalid page is requested. */ public function get_sitemap_links( $type, $max_entries, $current_page ) { - $links = array(); + $links = []; - if ( WPSEO_Options::get( 'disable-author', false ) || WPSEO_Options::get( 'noindex-author-wpseo', false ) ) { + if ( ! $this->handles_type( 'author' ) ) { return $links; } - $users = $this->get_users( array( - 'offset' => ( $current_page - 1 ) * $max_entries, + $user_criteria = [ + 'offset' => ( ( $current_page - 1 ) * $max_entries ), 'number' => $max_entries, - ) ); + ]; + + $users = $this->get_users( $user_criteria ); + + // Throw an exception when there are no users in the sitemap. + if ( count( $users ) === 0 ) { + throw new OutOfBoundsException( 'Invalid sitemap page requested' ); + } $users = $this->exclude_users( $users ); - if ( empty( $users ) ) { - $users = array(); + $users = []; } $time = time(); @@ -169,14 +185,14 @@ class WPSEO_Author_Sitemap_Provider implements WPSEO_Sitemap_Provider { $mod = $user->_yoast_wpseo_profile_updated; } - $url = array( + $url = [ 'loc' => $author_link, 'mod' => date( DATE_W3C, $mod ), // Deprecated, kept for backwards data compat. R. 'chf' => 'daily', 'pri' => 1, - ); + ]; /** This filter is documented at inc/sitemaps/class-post-type-sitemap-provider.php */ $url = apply_filters( 'wpseo_sitemap_entry', $url, 'user', $user ); @@ -196,15 +212,16 @@ class WPSEO_Author_Sitemap_Provider implements WPSEO_Sitemap_Provider { */ protected function update_user_meta() { - $users = get_users( array( + $user_criteria = [ 'who' => 'authors', - 'meta_query' => array( - array( + 'meta_query' => [ + [ 'key' => '_yoast_wpseo_profile_updated', 'compare' => 'NOT EXISTS', - ), - ), - ) ); + ], + ], + ]; + $users = get_users( $user_criteria ); $time = time(); diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-post-type-sitemap-provider.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-post-type-sitemap-provider.php index 49745c13..a552e83d 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-post-type-sitemap-provider.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-post-type-sitemap-provider.php @@ -5,70 +5,50 @@ * @package WPSEO\XML_Sitemaps */ +use Yoast\WP\SEO\Models\SEO_Links; + /** * Sitemap provider for author archives. */ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { - /** @var string $home_url Holds the home_url() value. */ - protected static $home_url; - - /** @var WPSEO_Sitemap_Image_Parser $image_parser Holds image parser instance. */ + /** + * Holds image parser instance. + * + * @var WPSEO_Sitemap_Image_Parser + */ protected static $image_parser; - /** @var object $classifier Holds instance of classifier for a link. */ - protected static $classifier; + /** + * Holds the parsed home url. + * + * @var array + */ + protected static $parsed_home_url; - /** @var int $page_on_front_id Static front page ID. */ - protected static $page_on_front_id; - - /** @var int $page_for_posts_id Posts page ID. */ - protected static $page_for_posts_id; + /** + * Determines whether images should be included in the XML sitemap. + * + * @var bool + */ + private $include_images; /** * Set up object properties for data reuse. */ public function __construct() { - add_filter( 'save_post', array( $this, 'save_post' ) ); + add_filter( 'save_post', [ $this, 'save_post' ] ); + + /** + * Filter - Allows excluding images from the XML sitemap. + * + * @param bool $include True to include, false to exclude. + */ + $this->include_images = apply_filters( 'wpseo_xml_sitemap_include_images', true ); } /** - * Get all the options - * - * @deprecated 7.0 - */ - protected function get_options() { - _deprecated_function( __METHOD__, 'WPSEO 7.0', 'WPSEO_Options::get' ); - } - - /** - * Get front page ID - * - * @return int - */ - protected function get_page_on_front_id() { - if ( ! isset( self::$page_on_front_id ) ) { - self::$page_on_front_id = (int) get_option( 'page_on_front' ); - } - - return self::$page_on_front_id; - } - - /** - * Get page for posts ID - * - * @return int - */ - protected function get_page_for_posts_id() { - if ( ! isset( self::$page_for_posts_id ) ) { - self::$page_for_posts_id = (int) get_option( 'page_for_posts' ); - } - - return self::$page_for_posts_id; - } - - /** - * Get the Image Parser + * Get the Image Parser. * * @return WPSEO_Sitemap_Image_Parser */ @@ -81,32 +61,16 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { } /** - * Get the Classifier for a link + * Gets the parsed home url. * - * @return WPSEO_Link_Type_Classifier + * @return array The home url, as parsed by wp_parse_url. */ - protected function get_classifier() { - if ( ! isset( self::$classifier ) ) { - self::$classifier = new WPSEO_Link_Type_Classifier( $this->get_home_url() ); + protected function get_parsed_home_url() { + if ( ! isset( self::$parsed_home_url ) ) { + self::$parsed_home_url = wp_parse_url( home_url() ); } - return self::$classifier; - } - - /** - * Get Home URL - * - * This has been moved from the constructor because wp_rewrite is not available on plugins_loaded in multisite. - * It will now be requested on need and not on initialization. - * - * @return string - */ - protected function get_home_url() { - if ( ! isset( self::$home_url ) ) { - self::$home_url = WPSEO_Utils::home_url(); - } - - return self::$home_url; + return self::$parsed_home_url; } /** @@ -114,7 +78,7 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { * * @param string $type Type string to check for. * - * @return boolean + * @return bool */ public function handles_type( $type ) { @@ -122,43 +86,39 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { } /** + * Retrieves the sitemap links. + * * @param int $max_entries Entries per sitemap. * * @return array */ public function get_index_links( $max_entries ) { - global $wpdb; - // Consider using WPSEO_Post_Type::get_accessible_post_types() to filter out any `no-index` post-types. $post_types = WPSEO_Post_Type::get_accessible_post_types(); - $post_types = array_filter( $post_types, array( $this, 'is_valid_post_type' ) ); + $post_types = array_filter( $post_types, [ $this, 'is_valid_post_type' ] ); $last_modified_times = WPSEO_Sitemaps::get_last_modified_gmt( $post_types, true ); - $index = array(); + $index = []; foreach ( $post_types as $post_type ) { $total_count = $this->get_post_type_count( $post_type ); - if ( $total_count === 0 ) { - continue; - } - $max_pages = 1; - if ( $total_count > $max_entries ) { $max_pages = (int) ceil( $total_count / $max_entries ); } - $all_dates = array(); + $all_dates = []; if ( $max_pages > 1 ) { + $post_statuses = array_map( 'esc_sql', WPSEO_Sitemaps::get_post_statuses( $post_type ) ); $sql = " SELECT post_modified_gmt - FROM ( SELECT @rownum:=0 ) init + FROM ( SELECT @rownum:=0 ) init JOIN {$wpdb->posts} USE INDEX( type_status_date ) - WHERE post_status IN ( 'publish', 'inherit' ) + WHERE post_status IN ('" . implode( "','", $post_statuses ) . "') AND post_type = %s AND ( @rownum:=@rownum+1 ) %% %d = 0 ORDER BY post_modified_gmt ASC @@ -182,10 +142,10 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { $date = $all_dates[ $page_counter ]; } - $index[] = array( + $index[] = [ 'loc' => WPSEO_Sitemaps_Router::get_base_url( $post_type . '-sitemap' . $current_page . '.xml' ), 'lastmod' => $date, - ); + ]; } } @@ -200,37 +160,42 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { * @param int $current_page Current page of the sitemap. * * @return array + * + * @throws OutOfBoundsException When an invalid page is requested. */ public function get_sitemap_links( $type, $max_entries, $current_page ) { - $links = array(); + $links = []; $post_type = $type; if ( ! $this->is_valid_post_type( $post_type ) ) { - return $links; + throw new OutOfBoundsException( 'Invalid sitemap page requested' ); } $steps = min( 100, $max_entries ); $offset = ( $current_page > 1 ) ? ( ( $current_page - 1 ) * $max_entries ) : 0; $total = ( $offset + $max_entries ); - $typecount = $this->get_post_type_count( $post_type ); + $post_type_entries = $this->get_post_type_count( $post_type ); - if ( $total > $typecount ) { - $total = $typecount; + if ( $total > $post_type_entries ) { + $total = $post_type_entries; } if ( $current_page === 1 ) { $links = array_merge( $links, $this->get_first_links( $post_type ) ); } - if ( $typecount === 0 ) { + // If total post type count is lower than the offset, an invalid page is requested. + if ( $post_type_entries < $offset ) { + throw new OutOfBoundsException( 'Invalid sitemap page requested' ); + } + if ( $post_type_entries === 0 ) { return $links; } - $stacked_urls = array(); - $posts_to_exclude = $this->get_excluded_posts(); + $posts_to_exclude = $this->get_excluded_posts( $type ); while ( $total > $offset ) { @@ -267,16 +232,9 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { */ $url = apply_filters( 'wpseo_sitemap_entry', $url, 'post', $post ); - if ( empty( $url ) ) { - continue; + if ( ! empty( $url ) ) { + $links[] = $url; } - - if ( $post->ID === $this->get_page_for_posts_id() || $post->ID === $this->get_page_on_front_id() ) { - - array_unshift( $links, $url ); - continue; - } - $links[] = $url; } unset( $post, $url ); @@ -305,7 +263,7 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { * @return bool */ public function is_valid_post_type( $post_type ) { - if ( ! WPSEO_Post_Type::is_post_type_indexable( $post_type ) ) { + if ( ! WPSEO_Post_Type::is_post_type_accessible( $post_type ) || ! WPSEO_Post_Type::is_post_type_indexable( $post_type ) ) { return false; } @@ -325,20 +283,36 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { /** * Retrieves a list with the excluded post ids. * + * @param string $post_type Post type. + * * @return array Array with post ids to exclude. */ - protected function get_excluded_posts() { + protected function get_excluded_posts( $post_type ) { + $excluded_posts_ids = []; + + $page_on_front_id = ( $post_type === 'page' ) ? (int) get_option( 'page_on_front' ) : 0; + if ( $page_on_front_id > 0 ) { + $excluded_posts_ids[] = $page_on_front_id; + } + /** * Filter: 'wpseo_exclude_from_sitemap_by_post_ids' - Allow extending and modifying the posts to exclude. * * @api array $posts_to_exclude The posts to exclude. */ - $excluded_posts_ids = apply_filters( 'wpseo_exclude_from_sitemap_by_post_ids', array() ); - if ( ! is_array( $excluded_posts_ids ) || $excluded_posts_ids === array() ) { - return array(); + $excluded_posts_ids = apply_filters( 'wpseo_exclude_from_sitemap_by_post_ids', $excluded_posts_ids ); + if ( ! is_array( $excluded_posts_ids ) ) { + $excluded_posts_ids = []; } - return array_map( 'intval', $excluded_posts_ids ); + $excluded_posts_ids = array_map( 'intval', $excluded_posts_ids ); + + $page_for_posts_id = ( $post_type === 'page' ) ? (int) get_option( 'page_for_posts' ) : 0; + if ( $page_for_posts_id > 0 ) { + $excluded_posts_ids[] = $page_for_posts_id; + } + + return array_unique( $excluded_posts_ids ); } /** @@ -390,66 +364,54 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { */ protected function get_first_links( $post_type ) { - $links = array(); + $links = []; + $archive_url = false; - $needs_archive = true; + if ( $post_type === 'page' ) { - if ( ! $this->get_page_on_front_id() && ( $post_type === 'post' || $post_type === 'page' ) ) { + $page_on_front_id = (int) get_option( 'page_on_front' ); + if ( $page_on_front_id > 0 ) { + $front_page = $this->get_url( + get_post( $page_on_front_id ) + ); + } - $links[] = array( - 'loc' => $this->get_home_url(), + if ( empty( $front_page ) ) { + $front_page = [ + 'loc' => YoastSEO()->helpers->url->home(), + ]; + } - // Deprecated, kept for backwards data compat. R. - 'chf' => 'daily', - 'pri' => 1, + // Deprecated, kept for backwards data compat. R. + $front_page['chf'] = 'daily'; + $front_page['pri'] = 1; + + $links[] = $front_page; + } + elseif ( $post_type !== 'page' ) { + /** + * Filter the URL Yoast SEO uses in the XML sitemap for this post type archive. + * + * @param string $archive_url The URL of this archive + * @param string $post_type The post type this archive is for. + */ + $archive_url = apply_filters( + 'wpseo_sitemap_post_type_archive_link', + $this->get_post_type_archive_link( $post_type ), + $post_type ); - - $needs_archive = false; } - elseif ( $this->get_page_on_front_id() && $post_type === 'post' && $this->get_page_for_posts_id() ) { - - $page_for_posts_url = get_permalink( $this->get_page_for_posts_id() ); - - $links[] = array( - 'loc' => $page_for_posts_url, - - // Deprecated, kept for backwards data compat. R. - 'chf' => 'daily', - 'pri' => 1, - ); - - $needs_archive = false; - } - - if ( ! $needs_archive ) { - return $links; - } - - $archive_url = $this->get_post_type_archive_link( $post_type ); - - /** - * Filter the URL Yoast SEO uses in the XML sitemap for this post type archive. - * - * @param string $archive_url The URL of this archive - * @param string $post_type The post type this archive is for. - */ - $archive_url = apply_filters( 'wpseo_sitemap_post_type_archive_link', $archive_url, $post_type ); if ( $archive_url ) { - /** - * Filter the priority of the URL Yoast SEO uses in the XML sitemap. - * - * @param float $priority The priority for this URL, ranging from 0 to 1 - * @param string $post_type The post type this archive is for. - */ - $links[] = array( + + $links[] = [ 'loc' => $archive_url, 'mod' => WPSEO_Sitemaps::get_last_modified_gmt( $post_type ), // Deprecated, kept for backwards data compat. R. 'chf' => 'daily', 'pri' => 1, - ); + ]; } return $links; @@ -458,26 +420,68 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { /** * Get URL for a post type archive. * - * @since 5.3 + * @since 5.3 * - * @param string $post_type Post type. + * @param string $post_type Post type. * * @return string|bool URL or false if it should be excluded. */ protected function get_post_type_archive_link( $post_type ) { + $pt_archive_page_id = -1; + + if ( $post_type === 'post' ) { + + if ( get_option( 'show_on_front' ) === 'posts' ) { + return YoastSEO()->helpers->url->home(); + } + + $pt_archive_page_id = (int) get_option( 'page_for_posts' ); + + // Post archive should be excluded if posts page isn't set. + if ( $pt_archive_page_id <= 0 ) { + return false; + } + } + + if ( ! $this->is_post_type_archive_indexable( $post_type, $pt_archive_page_id ) ) { + return false; + } + + return get_post_type_archive_link( $post_type ); + } + + /** + * Determines whether a post type archive is indexable. + * + * @since 11.5 + * + * @param string $post_type Post type. + * @param int $archive_page_id The page id. + * + * @return bool True when post type archive is indexable. + */ + protected function is_post_type_archive_indexable( $post_type, $archive_page_id = -1 ) { + if ( WPSEO_Options::get( 'noindex-ptarchive-' . $post_type, false ) ) { return false; } - // Post archive should be excluded if it isn't front page or posts page. - if ( $post_type === 'post' && get_option( 'show_on_front' ) !== 'posts' && ! $this->get_page_for_posts_id() ) { + /** + * Filter the page which is dedicated to this post type archive. + * + * @since 9.3 + * + * @param string $archive_page_id The post_id of the page. + * @param string $post_type The post type this archive is for. + */ + $archive_page_id = (int) apply_filters( 'wpseo_sitemap_page_for_post_type_archive', $archive_page_id, $post_type ); + + if ( $archive_page_id > 0 && WPSEO_Meta::get_value( 'meta-robots-noindex', $archive_page_id ) === '1' ) { return false; } - $archive_url = get_post_type_archive_link( $post_type ); - - return $archive_url; + return true; } /** @@ -493,11 +497,11 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { global $wpdb; - static $filters = array(); + static $filters = []; if ( ! isset( $filters[ $post_type ] ) ) { // Make sure you're wpdb->preparing everything you throw into this!! - $filters[ $post_type ] = array( + $filters[ $post_type ] = [ /** * Filter JOIN query part for the post type. * @@ -507,23 +511,26 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { 'join' => apply_filters( 'wpseo_posts_join', false, $post_type ), /** - * Filter Where query part for the post type. + * Filter WHERE query part for the post type. * * @param string $where SQL part, defaults to false. * @param string $post_type Post type name. */ 'where' => apply_filters( 'wpseo_posts_where', false, $post_type ), - ); + ]; } $join_filter = $filters[ $post_type ]['join']; $where_filter = $filters[ $post_type ]['where']; $where = $this->get_sql_where_clause( $post_type ); - // Optimized query per this thread: http://wordpress.org/support/topic/plugin-wordpress-seo-by-yoast-performance-suggestion. - // Also see http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/. + /* + * Optimized query per this thread: + * {@link http://wordpress.org/support/topic/plugin-wordpress-seo-by-yoast-performance-suggestion}. + * Also see {@link http://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/}. + */ $sql = " - SELECT l.ID, post_title, post_content, post_name, post_parent, post_author, post_modified_gmt, post_date, post_date_gmt + SELECT l.ID, post_title, post_content, post_name, post_parent, post_author, post_status, post_modified_gmt, post_date, post_date_gmt FROM ( SELECT {$wpdb->posts}.ID FROM {$wpdb->posts} @@ -537,16 +544,14 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { $posts = $wpdb->get_results( $wpdb->prepare( $sql, $count, $offset ) ); - $post_ids = array(); + $post_ids = []; - foreach ( $posts as $post ) { - $post->post_type = $post_type; - $post->post_status = 'publish'; - $post->filter = 'sample'; - $post->ID = (int) $post->ID; - $post->post_parent = (int) $post->post_parent; - $post->post_author = (int) $post->post_author; - $post_ids[] = $post->ID; + foreach ( $posts as $post_index => $post ) { + $post->post_type = $post_type; + $sanitized_post = sanitize_post( $post, 'raw' ); + $posts[ $post_index ] = new WP_Post( $sanitized_post ); + + $post_ids[] = $sanitized_post->ID; } update_meta_cache( 'post', $post_ids ); @@ -555,6 +560,8 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { } /** + * Constructs an SQL where clause for a given post type. + * * @param string $post_type Post type slug. * * @return string @@ -563,21 +570,23 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { global $wpdb; - $join = ''; - $status = "{$wpdb->posts}.post_status = 'publish'"; + $join = ''; + $post_statuses = array_map( 'esc_sql', WPSEO_Sitemaps::get_post_statuses( $post_type ) ); + $status_where = "{$wpdb->posts}.post_status IN ('" . implode( "','", $post_statuses ) . "')"; // Based on WP_Query->get_posts(). R. - if ( 'attachment' === $post_type ) { - $join = " LEFT JOIN {$wpdb->posts} AS p2 ON ({$wpdb->posts}.post_parent = p2.ID) "; - $status = "p2.post_status = 'publish' AND p2.post_password = ''"; + if ( $post_type === 'attachment' ) { + $join = " LEFT JOIN {$wpdb->posts} AS p2 ON ({$wpdb->posts}.post_parent = p2.ID) "; + $parent_statuses = array_diff( $post_statuses, [ 'inherit' ] ); + $status_where = "p2.post_status IN ('" . implode( "','", $parent_statuses ) . "') AND p2.post_password = ''"; } $where_clause = " - {$join} - WHERE {$status} - AND {$wpdb->posts}.post_type = %s - AND {$wpdb->posts}.post_password = '' - AND {$wpdb->posts}.post_date != '0000-00-00 00:00:00' + {$join} + WHERE {$status_where} + AND {$wpdb->posts}.post_type = %s + AND {$wpdb->posts}.post_password = '' + AND {$wpdb->posts}.post_date != '0000-00-00 00:00:00' "; return $wpdb->prepare( $where_clause, $post_type ); @@ -592,7 +601,7 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { */ protected function get_url( $post ) { - $url = array(); + $url = []; /** * Filter the URL Yoast SEO uses in the XML sitemap. @@ -603,13 +612,17 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { * @param object $post Post object for the URL. */ $url['loc'] = apply_filters( 'wpseo_xml_sitemap_post_url', get_permalink( $post ), $post ); + $link_type = YoastSEO()->helpers->url->get_link_type( + wp_parse_url( $url['loc'] ), + $this->get_parsed_home_url() + ); - /** + /* * Do not include external URLs. * - * @see https://wordpress.org/plugins/page-links-to/ can rewrite permalinks to external URLs. + * {@link https://wordpress.org/plugins/page-links-to/} can rewrite permalinks to external URLs. */ - if ( $this->get_classifier()->classify( $url['loc'] ) === WPSEO_Link::TYPE_EXTERNAL ) { + if ( $link_type === SEO_Links::TYPE_EXTERNAL ) { return false; } @@ -633,8 +646,11 @@ class WPSEO_Post_Type_Sitemap_Provider implements WPSEO_Sitemap_Provider { } unset( $canonical ); - $url['pri'] = 1; // Deprecated, kept for backwards data compat. R. - $url['images'] = $this->get_image_parser()->get_images( $post ); + $url['pri'] = 1; // Deprecated, kept for backwards data compat. R. + + if ( $this->include_images ) { + $url['images'] = $this->get_image_parser()->get_images( $post ); + } return $url; } diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-cache-data.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-cache-data.php index 88b1eda7..4579f3f6 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-cache-data.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-cache-data.php @@ -6,14 +6,22 @@ */ /** - * Sitemap Cache Data object, manages sitemap data stored in cache + * Sitemap Cache Data object, manages sitemap data stored in cache. */ -class WPSEO_Sitemap_Cache_Data implements WPSEO_Sitemap_Cache_Data_Interface, Serializable { +class WPSEO_Sitemap_Cache_Data implements Serializable, WPSEO_Sitemap_Cache_Data_Interface { - /** @var string Sitemap XML data. */ + /** + * Sitemap XML data. + * + * @var string + */ private $sitemap = ''; - /** @var string Status of the sitemap, usable or not. */ + /** + * Status of the sitemap, usable or not. + * + * @var string + */ private $status = self::UNKNOWN; /** @@ -29,7 +37,7 @@ class WPSEO_Sitemap_Cache_Data implements WPSEO_Sitemap_Cache_Data_Interface, Se $this->sitemap = $sitemap; - /** + /* * Empty sitemap is not usable. */ if ( ! empty( $sitemap ) ) { @@ -49,13 +57,13 @@ class WPSEO_Sitemap_Cache_Data implements WPSEO_Sitemap_Cache_Data_Interface, Se */ public function set_status( $valid ) { - if ( self::OK === $valid ) { + if ( $valid === self::OK ) { $this->status = self::OK; return; } - if ( self::ERROR === $valid ) { + if ( $valid === self::ERROR ) { $this->status = self::ERROR; $this->sitemap = ''; @@ -72,7 +80,7 @@ class WPSEO_Sitemap_Cache_Data implements WPSEO_Sitemap_Cache_Data_Interface, Se */ public function is_usable() { - return self::OK === $this->status; + return $this->status === self::OK; } /** @@ -88,7 +96,7 @@ class WPSEO_Sitemap_Cache_Data implements WPSEO_Sitemap_Cache_Data_Interface, Se /** * Get the status of the sitemap. * - * @return string Status of the sitemap, 'ok'/'error'/'unknown' + * @return string Status of the sitemap, 'ok'/'error'/'unknown'. */ public function get_status() { @@ -96,31 +104,34 @@ class WPSEO_Sitemap_Cache_Data implements WPSEO_Sitemap_Cache_Data_Interface, Se } /** - * String representation of object + * String representation of object. + * + * @link http://php.net/manual/en/serializable.serialize.php * - * @link http://php.net/manual/en/serializable.serialize.php - * @return string the string representation of the object or null * @since 5.1.0 + * + * @return string The string representation of the object or null. */ public function serialize() { - $data = array( + $data = [ 'status' => $this->status, 'xml' => $this->sitemap, - ); + ]; return serialize( $data ); } /** - * Constructs the object + * Constructs the object. * - * @link http://php.net/manual/en/serializable.unserialize.php + * @link http://php.net/manual/en/serializable.unserialize.php + * + * @since 5.1.0 * * @param string $serialized The string representation of the object. * * @return void - * @since 5.1.0 */ public function unserialize( $serialized ) { diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-image-parser.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-image-parser.php index 4fd8646b..274325b3 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-image-parser.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-image-parser.php @@ -10,19 +10,39 @@ */ class WPSEO_Sitemap_Image_Parser { - /** @var string $home_url Holds the home_url() value to speed up loops. */ + /** + * Holds the home_url() value to speed up loops. + * + * @var string + */ protected $home_url = ''; - /** @var string $host Holds site URL hostname. */ + /** + * Holds site URL hostname. + * + * @var string + */ protected $host = ''; - /** @var string $scheme Holds site URL protocol. */ + /** + * Holds site URL protocol. + * + * @var string + */ protected $scheme = 'http'; - /** @var array $attachments Cached set of attachments for multiple posts. */ - protected $attachments = array(); + /** + * Cached set of attachments for multiple posts. + * + * @var array + */ + protected $attachments = []; - /** @var string $charset Holds blog charset value for use in DOM parsing. */ + /** + * Holds blog charset value for use in DOM parsing. + * + * @var string + */ protected $charset = 'UTF-8'; /** @@ -53,7 +73,7 @@ class WPSEO_Sitemap_Image_Parser { */ public function get_images( $post ) { - $images = array(); + $images = []; if ( ! is_object( $post ) ) { return $images; @@ -64,7 +84,7 @@ class WPSEO_Sitemap_Image_Parser { if ( $thumbnail_id ) { $src = $this->get_absolute_url( $this->image_url( $thumbnail_id ) ); - $alt = get_post_meta( $thumbnail_id, '_wp_attachment_image_alt', true ); + $alt = WPSEO_Image_Utils::get_alt_tag( $thumbnail_id ); $title = get_post_field( 'post_title', $thumbnail_id ); $images[] = $this->get_image_item( $post, $src, $title, $alt ); } @@ -83,18 +103,18 @@ class WPSEO_Sitemap_Image_Parser { $images[] = $this->get_image_item( $post, $image['src'], $image['title'], $image['alt'] ); } - foreach ( $this->parse_galleries( $post->post_content, $post->ID ) as $attachment ) { + foreach ( $this->parse_galleries( $content, $post->ID ) as $attachment ) { $src = $this->get_absolute_url( $this->image_url( $attachment->ID ) ); - $alt = get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ); + $alt = WPSEO_Image_Utils::get_alt_tag( $attachment->ID ); $images[] = $this->get_image_item( $post, $src, $attachment->post_title, $alt ); } - if ( 'attachment' === $post->post_type && wp_attachment_is_image( $post ) ) { + if ( $post->post_type === 'attachment' && wp_attachment_is_image( $post ) ) { $src = $this->get_absolute_url( $this->image_url( $post->ID ) ); - $alt = get_post_meta( $post->ID, '_wp_attachment_image_alt', true ); + $alt = WPSEO_Image_Utils::get_alt_tag( $post->ID ); $images[] = $this->get_image_item( $post, $src, $post->post_title, $alt ); } @@ -118,6 +138,8 @@ class WPSEO_Sitemap_Image_Parser { } /** + * Get the images in the term description. + * * @param object $term Term to get images from description for. * * @return array @@ -128,11 +150,11 @@ class WPSEO_Sitemap_Image_Parser { foreach ( $this->parse_galleries( $term->description ) as $attachment ) { - $images[] = array( + $images[] = [ 'src' => $this->get_absolute_url( $this->image_url( $attachment->ID ) ), 'title' => $attachment->post_title, - 'alt' => get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ), - ); + 'alt' => WPSEO_Image_Utils::get_alt_tag( $attachment->ID ), + ]; } return $images; @@ -147,7 +169,7 @@ class WPSEO_Sitemap_Image_Parser { */ private function parse_html_images( $content ) { - $images = array(); + $images = []; if ( ! class_exists( 'DOMDocument' ) ) { return $images; @@ -179,7 +201,7 @@ class WPSEO_Sitemap_Image_Parser { if ( // This detects WP-inserted images, which we need to upsize. R. ! empty( $class ) - && false === strpos( $class, 'size-full' ) + && ( strpos( $class, 'size-full' ) === false ) && preg_match( '|wp-image-(?P\d+)|', $class, $matches ) && get_post_status( $matches['id'] ) ) { @@ -196,11 +218,11 @@ class WPSEO_Sitemap_Image_Parser { continue; } - $images[] = array( + $images[] = [ 'src' => $src, 'title' => $img->getAttribute( 'title' ), 'alt' => $img->getAttribute( 'alt' ), - ); + ]; } return $images; @@ -210,13 +232,13 @@ class WPSEO_Sitemap_Image_Parser { * Parse gallery shortcodes in a given content. * * @param string $content Content string. - * @param int $post_id Optional ID of post being parsed. + * @param int $post_id Optional. ID of post being parsed. * * @return array Set of attachment objects. */ protected function parse_galleries( $content, $post_id = 0 ) { - $attachments = array(); + $attachments = []; $galleries = $this->get_content_galleries( $content ); foreach ( $galleries as $gallery ) { @@ -234,16 +256,10 @@ class WPSEO_Sitemap_Image_Parser { $gallery_attachments = $this->get_gallery_attachments( $id, $gallery ); - $attachments = array_merge( $attachments, $gallery_attachments ); } - if ( PHP_VERSION_ID >= 50209 ) { - // phpcs:ignore PHPCompatibility.PHP.NewFunctionParameters.array_unique_sort_flagsFound -- Wrapped in version check. - return array_unique( $attachments, SORT_REGULAR ); - } - - return $attachments; + return array_unique( $attachments, SORT_REGULAR ); } /** @@ -257,27 +273,21 @@ class WPSEO_Sitemap_Image_Parser { */ protected function get_content_galleries( $content ) { - if ( ! has_shortcode( $content, 'gallery' ) ) { - return array(); - } + $galleries = []; - $galleries = array(); - - if ( ! preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches, PREG_SET_ORDER ) ) { + if ( ! preg_match_all( '/' . get_shortcode_regex( [ 'gallery' ] ) . '/s', $content, $matches, PREG_SET_ORDER ) ) { return $galleries; } foreach ( $matches as $shortcode ) { - if ( 'gallery' === $shortcode[2] ) { - $attributes = shortcode_parse_atts( $shortcode[3] ); + $attributes = shortcode_parse_atts( $shortcode[3] ); - if ( '' === $attributes ) { // Valid shortcode without any attributes. R. - $attributes = array(); - } - - $galleries[] = $attributes; + if ( $attributes === '' ) { // Valid shortcode without any attributes. R. + $attributes = []; } + + $galleries[] = $attributes; } return $galleries; @@ -295,7 +305,7 @@ class WPSEO_Sitemap_Image_Parser { */ protected function get_image_item( $post, $src, $title = '', $alt = '' ) { - $image = array(); + $image = []; /** * Filter image URL to be included in XML sitemap for the post. @@ -317,11 +327,11 @@ class WPSEO_Sitemap_Image_Parser { * Filter image data to be included in XML sitemap for the post. * * @param array $image { - * Array of image data. + * Array of image data. * - * @type string $src Image URL. - * @type string $title Image title attribute (optional). - * @type string $alt Image alt attribute (optional). + * @type string $src Image URL. + * @type string $title Image title attribute (optional). + * @type string $alt Image alt attribute (optional). * } * * @param object $post Post object. @@ -344,7 +354,7 @@ class WPSEO_Sitemap_Image_Parser { $uploads = wp_upload_dir(); } - if ( false !== $uploads['error'] ) { + if ( $uploads['error'] !== false ) { return ''; } @@ -355,10 +365,10 @@ class WPSEO_Sitemap_Image_Parser { } // Check that the upload base exists in the file location. - if ( 0 === strpos( $file, $uploads['basedir'] ) ) { + if ( strpos( $file, $uploads['basedir'] ) === 0 ) { $src = str_replace( $uploads['basedir'], $uploads['baseurl'], $file ); } - elseif ( false !== strpos( $file, 'wp-content/uploads' ) ) { + elseif ( strpos( $file, 'wp-content/uploads' ) !== false ) { $src = $uploads['baseurl'] . substr( $file, ( strpos( $file, 'wp-content/uploads' ) + 18 ) ); } else { @@ -382,7 +392,7 @@ class WPSEO_Sitemap_Image_Parser { return $src; } - if ( WPSEO_Utils::is_url_relative( $src ) === true ) { + if ( YoastSEO()->helpers->url->is_relative( $src ) === true ) { if ( $src[0] !== '/' ) { return $src; @@ -393,7 +403,7 @@ class WPSEO_Sitemap_Image_Parser { } if ( strpos( $src, 'http' ) !== 0 ) { - // Protocol relative url, we add the scheme as the standard requires a protocol. + // Protocol relative URL, we add the scheme as the standard requires a protocol. return $this->scheme . ':' . $src; } @@ -403,7 +413,7 @@ class WPSEO_Sitemap_Image_Parser { /** * Returns the attachments for a gallery. * - * @param int $id The post id. + * @param int $id The post ID. * @param array $gallery The gallery config. * * @return array The selected attachments. @@ -417,25 +427,25 @@ class WPSEO_Sitemap_Image_Parser { // When $id is empty, just return empty array. if ( empty( $id ) ) { - return array(); + return []; } return $this->get_gallery_attachments_for_parent( $id, $gallery ); } /** - * Returns the attachments for the given id. + * Returns the attachments for the given ID. * - * @param int $id The post id. + * @param int $id The post ID. * @param array $gallery The gallery config. * * @return array The selected attachments. */ protected function get_gallery_attachments_for_parent( $id, $gallery ) { - $query = array( + $query = [ 'posts_per_page' => -1, 'post_parent' => $id, - ); + ]; // When there are posts that should be excluded from result set. if ( ! empty( $gallery['exclude'] ) ) { @@ -446,22 +456,22 @@ class WPSEO_Sitemap_Image_Parser { } /** - * Returns an array with attachments for the post ids that will be included. + * Returns an array with attachments for the post IDs that will be included. * - * @param array $include Array with ids to include. + * @param array $include Array with IDs to include. * * @return array The found attachments. */ protected function get_gallery_attachments_for_included( $include ) { $ids_to_include = wp_parse_id_list( $include ); $attachments = $this->get_attachments( - array( + [ 'posts_per_page' => count( $ids_to_include ), 'post__in' => $ids_to_include, - ) + ] ); - $gallery_attachments = array(); + $gallery_attachments = []; foreach ( $attachments as $key => $val ) { $gallery_attachments[ $val->ID ] = $val; } @@ -477,7 +487,7 @@ class WPSEO_Sitemap_Image_Parser { * @return array The found attachments. */ protected function get_attachments( $args ) { - $default_args = array( + $default_args = [ 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', @@ -490,7 +500,7 @@ class WPSEO_Sitemap_Image_Parser { 'suppress_filters' => true, 'ignore_sticky_posts' => true, 'no_found_rows' => true, - ); + ]; $args = wp_parse_args( $args, $default_args ); diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-timezone.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-timezone.php deleted file mode 100644 index b18ecc45..00000000 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemap-timezone.php +++ /dev/null @@ -1,121 +0,0 @@ -get_datetime_with_timezone( $datetime_string ); - - if ( is_null( $date_time ) ) { - return ''; - } - - return $date_time->format( $format ); - } - /** - * Get the datetime object, in site's time zone, if the datetime string was valid - * - * @param string $datetime_string The datetime string in UTC time zone, that needs to be converted to a DateTime object. - * - * @return DateTime|null in site's time zone - */ - public function get_datetime_with_timezone( $datetime_string ) { - - static $utc_timezone, $local_timezone; - - if ( ! isset( $utc_timezone ) ) { - $utc_timezone = new DateTimeZone( 'UTC' ); - $local_timezone = new DateTimeZone( $this->get_timezone_string() ); - } - - if ( ! empty( $datetime_string ) && WPSEO_Utils::is_valid_datetime( $datetime_string ) ) { - $datetime = new DateTime( $datetime_string, $utc_timezone ); - $datetime->setTimezone( $local_timezone ); - - return $datetime; - } - - return null; - } - - /** - * Returns the timezone string for a site, even if it's set to a UTC offset - * - * Adapted from http://www.php.net/manual/en/function.timezone-name-from-abbr.php#89155 - * - * @return string valid PHP timezone string - */ - private function determine_timezone_string() { - - // If site timezone string exists, return it. - $timezone = get_option( 'timezone_string' ); - if ( ! empty( $timezone ) ) { - return $timezone; - } - - // Get UTC offset, if it isn't set then return UTC. - $utc_offset = (int) get_option( 'gmt_offset', 0 ); - if ( 0 === $utc_offset ) { - return 'UTC'; - } - - // Adjust UTC offset from hours to seconds. - $utc_offset *= HOUR_IN_SECONDS; - - // Attempt to guess the timezone string from the UTC offset. - $timezone = timezone_name_from_abbr( '', $utc_offset ); - - if ( false !== $timezone ) { - return $timezone; - } - - // Last try, guess timezone string manually. - $timezone_list = timezone_abbreviations_list(); - foreach ( $timezone_list as $abbr ) { - foreach ( $abbr as $city ) { - if ( $city['offset'] === $utc_offset ) { - return $city['timezone_id']; - } - } - } - - // Fallback to UTC. - return 'UTC'; - } - - /** - * Returns the correct timezone string - * - * @return string - */ - private function get_timezone_string() { - if ( '' === $this->timezone_string ) { - $this->timezone_string = $this->determine_timezone_string(); - } - - return $this->timezone_string; - } -} diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-admin.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-admin.php index 82113f05..1b6e2433 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-admin.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-admin.php @@ -6,20 +6,23 @@ */ /** - * Class that handles the Admin side of XML sitemaps + * Class that handles the Admin side of XML sitemaps. */ class WPSEO_Sitemaps_Admin { - /** - * @var array Post_types that are being imported. - */ - private $importing_post_types = array(); /** - * Class constructor + * Post_types that are being imported. + * + * @var array + */ + private $importing_post_types = []; + + /** + * Class constructor. */ public function __construct() { - add_action( 'transition_post_status', array( $this, 'status_transition' ), 10, 3 ); - add_action( 'admin_footer', array( $this, 'status_transition_bulk_finished' ) ); + add_action( 'transition_post_status', [ $this, 'status_transition' ], 10, 3 ); + add_action( 'admin_footer', [ $this, 'status_transition_bulk_finished' ] ); WPSEO_Sitemaps_Cache::register_clear_on_option_update( 'wpseo_titles', '' ); WPSEO_Sitemaps_Cache::register_clear_on_option_update( 'wpseo', '' ); @@ -49,8 +52,8 @@ class WPSEO_Sitemaps_Admin { wp_cache_delete( 'lastpostmodified:gmt:' . $post_type, 'timeinfo' ); // #17455. - // None of our interest.. - if ( 'nav_menu_item' === $post_type ) { + // Not something we're interested in. + if ( $post_type === 'nav_menu_item' ) { return; } @@ -59,12 +62,12 @@ class WPSEO_Sitemaps_Admin { return; } - if ( WP_CACHE ) { - wp_schedule_single_event( ( time() + 300 ), 'wpseo_hit_sitemap_index' ); + if ( wp_get_environment_type() !== 'production' ) { + return; } /** - * Filter: 'wpseo_allow_xml_sitemap_ping' - Check if pinging is not allowed (allowed by default) + * Filter: 'wpseo_allow_xml_sitemap_ping' - Check if pinging is not allowed (allowed by default). * * @api boolean $allow_ping The boolean that is set to true by default. */ @@ -81,10 +84,10 @@ class WPSEO_Sitemaps_Admin { } /** - * While bulk importing, just save unique post_types + * While bulk importing, just save unique post_types. * * When importing is done, if we have a post_type that is saved in the sitemap - * try to ping the search engines + * try to ping the search engines. * * @param string $new_status New post status. * @param string $old_status Old post status. @@ -113,7 +116,7 @@ class WPSEO_Sitemaps_Admin { wp_cache_delete( 'lastpostmodified:gmt:' . $post_type, 'timeinfo' ); // #17455. // Just have the cache deleted for nav_menu_item. - if ( 'nav_menu_item' === $post_type ) { + if ( $post_type === 'nav_menu_item' ) { continue; } @@ -123,7 +126,7 @@ class WPSEO_Sitemaps_Admin { } // Nothing to do. - if ( false === $ping_search_engines ) { + if ( $ping_search_engines === false ) { return; } @@ -133,24 +136,4 @@ class WPSEO_Sitemaps_Admin { WPSEO_Sitemaps::ping_search_engines(); } - - // @codeCoverageIgnoreStart - /** - * Find sitemaps residing on disk as they will block our rewrite. - * - * @deprecated 7.0 - */ - public function delete_sitemaps() { - _deprecated_function( 'WPSEO_Sitemaps_Admin::delete_sitemaps', '7.0' ); - } - - /** - * Find sitemaps residing on disk as they will block our rewrite. - * - * @deprecated 7.0 - */ - public function detect_blocking_filesystem_sitemaps() { - _deprecated_function( 'WPSEO_Sitemaps_Admin::delete_sitemaps', '7.0' ); - } - // @codeCoverageIgnoreEnd -} /* End of class */ +} diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-cache-validator.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-cache-validator.php index 28523167..acb56c56 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-cache-validator.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-cache-validator.php @@ -12,25 +12,37 @@ */ class WPSEO_Sitemaps_Cache_Validator { - /** @var string Prefix of the transient key for sitemap caches */ + /** + * Prefix of the transient key for sitemap caches. + * + * @var string + */ const STORAGE_KEY_PREFIX = 'yst_sm_'; - /** Name of the option that holds the global validation value */ + /** + * Name of the option that holds the global validation value. + * + * @var string + */ const VALIDATION_GLOBAL_KEY = 'wpseo_sitemap_cache_validator_global'; - /** The format which creates the key of the option that holds the type validation value */ + /** + * The format which creates the key of the option that holds the type validation value. + * + * @var string + */ const VALIDATION_TYPE_KEY_FORMAT = 'wpseo_sitemap_%s_cache_validator'; /** - * Get the cache key for a certain type and page + * Get the cache key for a certain type and page. * * A type of cache would be something like 'page', 'post' or 'video'. * - * Example key format for sitemap type "post", page 1: wpseo_sitemap_post_1:akfw3e_23azBa + * Example key format for sitemap type "post", page 1: wpseo_sitemap_post_1:akfw3e_23azBa . * * @since 3.2 * - * @param null|string $type The type to get the key for. Null or self::SITEMAP_INDEX_TYPE for index cache. + * @param string|null $type The type to get the key for. Null or self::SITEMAP_INDEX_TYPE for index cache. * @param int $page The page of cache to get the key for. * * @return bool|string The key where the cache is stored on. False if the key could not be generated. @@ -60,7 +72,7 @@ class WPSEO_Sitemaps_Cache_Validator { } /** - * If the type is over length make sure we compact it so we don't have any database problems + * If the type is over length make sure we compact it so we don't have any database problems. * * When there are more 'extremely long' post types, changes are they have variations in either the start or ending. * Because of this, we cut out the excess in the middle which should result in less chance of collision. @@ -76,7 +88,7 @@ class WPSEO_Sitemaps_Cache_Validator { * @throws OutOfRangeException When there is less than 15 characters of space for a key that is originally longer. */ public static function truncate_type( $type, $prefix = '', $postfix = '' ) { - /** + /* * This length has been restricted by the database column length of 64 in the past. * The prefix added by WordPress is '_transient_' because we are saving to a transient. * We need to use a timeout on the transient, otherwise the values get autoloaded, this adds @@ -89,10 +101,10 @@ class WPSEO_Sitemaps_Cache_Validator { if ( strlen( $type ) > $max_length ) { if ( $max_length < 15 ) { - /** + /* * If this happens the most likely cause is a page number that is too high. * - * So this would not happen unintentionally.. + * So this would not happen unintentionally. * Either by trying to cause a high server load, finding backdoors or misconfiguration. */ throw new OutOfRangeException( @@ -115,11 +127,11 @@ class WPSEO_Sitemaps_Cache_Validator { } /** - * Invalidate sitemap cache + * Invalidate sitemap cache. * * @since 3.2 * - * @param null|string $type The type to get the key for. Null for all caches. + * @param string|null $type The type to get the key for. Null for all caches. * * @return void */ @@ -145,12 +157,12 @@ class WPSEO_Sitemaps_Cache_Validator { } /** - * Cleanup invalidated database cache + * Cleanup invalidated database cache. * * @since 3.2 * - * @param null|string $type The type of sitemap to clear cache for. - * @param null|string $validator The validator to clear cache of. + * @param string|null $type The type of sitemap to clear cache for. + * @param string|null $validator The validator to clear cache of. * * @return void */ @@ -167,34 +179,35 @@ class WPSEO_Sitemaps_Cache_Validator { $like = sprintf( '%1$s%2$s_%%', self::STORAGE_KEY_PREFIX, $type ); } - /** + /* * Add slashes to the LIKE "_" single character wildcard. * * We can't use `esc_like` here because we need the % in the query. */ - $where = array(); + $where = []; $where[] = sprintf( "option_name LIKE '%s'", addcslashes( '_transient_' . $like, '_' ) ); $where[] = sprintf( "option_name LIKE '%s'", addcslashes( '_transient_timeout_' . $like, '_' ) ); // Delete transients. $query = sprintf( 'DELETE FROM %1$s WHERE %2$s', $wpdb->options, implode( ' OR ', $where ) ); $wpdb->query( $query ); + + wp_cache_delete( 'alloptions', 'options' ); } /** - * Get the current cache validator + * Get the current cache validator. * * Without the type the global validator is returned. - * This can invalidate -all- keys in cache at once + * This can invalidate -all- keys in cache at once. * - * With the type parameter the validator for that specific - * type can be invalidated + * With the type parameter the validator for that specific type can be invalidated. * * @since 3.2 * * @param string $type Provide a type for a specific type validator, empty for global validator. * - * @return null|string The validator for the supplied type. + * @return string|null The validator for the supplied type. */ public static function get_validator( $type = '' ) { @@ -213,7 +226,7 @@ class WPSEO_Sitemaps_Cache_Validator { } /** - * Get the cache validator option key for the specified type + * Get the cache validator option key for the specified type. * * @since 3.2 * @@ -231,7 +244,7 @@ class WPSEO_Sitemaps_Cache_Validator { } /** - * Refresh the cache validator value + * Refresh the cache validator value. * * @since 3.2 * @@ -265,10 +278,10 @@ class WPSEO_Sitemaps_Cache_Validator { /** * Encode to base61 format. * - * @since 3.2 - * * This is base64 (numeric + alpha + alpha upper case) without the 0. * + * @since 3.2 + * * @param int $base10 The number that has to be converted to base 61. * * @return string Base 61 converted string. diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-cache.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-cache.php index caa0303e..4b56ecd8 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-cache.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-cache.php @@ -12,37 +12,53 @@ */ class WPSEO_Sitemaps_Cache { - /** @var array $cache_clear Holds the options that, when updated, should cause the cache to clear. */ - protected static $cache_clear = array(); + /** + * Holds the options that, when updated, should cause the cache to clear. + * + * @var array + */ + protected static $cache_clear = []; - /** @var bool $is_enabled Mirror of enabled status for static calls. */ - protected static $is_enabled = true; + /** + * Mirror of enabled status for static calls. + * + * @var bool + */ + protected static $is_enabled = false; - /** @var bool $clear_all Holds the flag to clear all cache. */ + /** + * Holds the flag to clear all cache. + * + * @var bool + */ protected static $clear_all = false; - /** @var array $clear_types Holds the array of types to clear. */ - protected static $clear_types = array(); + /** + * Holds the array of types to clear. + * + * @var array + */ + protected static $clear_types = []; /** * Hook methods for invalidation on necessary events. */ public function __construct() { - add_action( 'init', array( $this, 'init' ) ); + add_action( 'init', [ $this, 'init' ] ); - add_action( 'deleted_term_relationships', array( __CLASS__, 'invalidate' ) ); + add_action( 'deleted_term_relationships', [ __CLASS__, 'invalidate' ] ); - add_action( 'update_option', array( __CLASS__, 'clear_on_option_update' ) ); + add_action( 'update_option', [ __CLASS__, 'clear_on_option_update' ] ); - add_action( 'edited_terms', array( __CLASS__, 'invalidate_helper' ), 10, 2 ); - add_action( 'clean_term_cache', array( __CLASS__, 'invalidate_helper' ), 10, 2 ); - add_action( 'clean_object_term_cache', array( __CLASS__, 'invalidate_helper' ), 10, 2 ); + add_action( 'edited_terms', [ __CLASS__, 'invalidate_helper' ], 10, 2 ); + add_action( 'clean_term_cache', [ __CLASS__, 'invalidate_helper' ], 10, 2 ); + add_action( 'clean_object_term_cache', [ __CLASS__, 'invalidate_helper' ], 10, 2 ); - add_action( 'user_register', array( __CLASS__, 'invalidate_author' ) ); - add_action( 'delete_user', array( __CLASS__, 'invalidate_author' ) ); + add_action( 'user_register', [ __CLASS__, 'invalidate_author' ] ); + add_action( 'delete_user', [ __CLASS__, 'invalidate_author' ] ); - add_action( 'shutdown', array( __CLASS__, 'clear_queued' ) ); + add_action( 'shutdown', [ __CLASS__, 'clear_queued' ] ); } /** @@ -58,19 +74,18 @@ class WPSEO_Sitemaps_Cache { * * @since 3.2 * - * @return boolean + * @return bool */ public function is_enabled() { /** * Filter if XML sitemap transient cache is enabled. * - * @param bool $unsigned Enable cache or not, defaults to true + * @param bool $unsigned Enable cache or not, defaults to true. */ - return apply_filters( 'wpseo_enable_xml_sitemap_transient_caching', true ); + return apply_filters( 'wpseo_enable_xml_sitemap_transient_caching', false ); } - /** * Retrieve the sitemap page from cache. * @@ -79,12 +94,12 @@ class WPSEO_Sitemaps_Cache { * @param string $type Sitemap type. * @param int $page Page number to retrieve. * - * @return string|boolean + * @return string|bool */ public function get_sitemap( $type, $page ) { $transient_key = WPSEO_Sitemaps_Cache_Validator::get_storage_key( $type, $page ); - if ( false === $transient_key ) { + if ( $transient_key === false ) { return false; } @@ -92,12 +107,12 @@ class WPSEO_Sitemaps_Cache { } /** - * Get the sitemap that is cached + * Get the sitemap that is cached. * * @param string $type Sitemap type. * @param int $page Page number to retrieve. * - * @return null|WPSEO_Sitemap_Cache_Data Null on no cache found otherwise object containing sitemap and meta data. + * @return WPSEO_Sitemap_Cache_Data|null Null on no cache found otherwise object containing sitemap and meta data. */ public function get_sitemap_data( $type, $page ) { @@ -108,7 +123,7 @@ class WPSEO_Sitemaps_Cache { } // Unserialize Cache Data object (is_serialized doesn't recognize classes). - if ( is_string( $sitemap ) && 0 === strpos( $sitemap, 'C:24:"WPSEO_Sitemap_Cache_Data"' ) ) { + if ( is_string( $sitemap ) && strpos( $sitemap, 'C:24:"WPSEO_Sitemap_Cache_Data"' ) === 0 ) { $sitemap = unserialize( $sitemap ); } @@ -137,7 +152,7 @@ class WPSEO_Sitemaps_Cache { $transient_key = WPSEO_Sitemaps_Cache_Validator::get_storage_key( $type, $page ); - if ( false === $transient_key ) { + if ( $transient_key === false ) { return false; } @@ -164,7 +179,7 @@ class WPSEO_Sitemaps_Cache { */ public static function invalidate( $type ) { - self::clear( array( $type ) ); + self::clear( [ $type ] ); } /** @@ -180,8 +195,8 @@ class WPSEO_Sitemaps_Cache { public static function invalidate_helper( $unused, $type ) { if ( - WPSEO_Options::get( 'noindex-' . $type ) === false || - WPSEO_Options::get( 'noindex-tax-' . $type ) === false + WPSEO_Options::get( 'noindex-' . $type ) === false + || WPSEO_Options::get( 'noindex-tax-' . $type ) === false ) { self::invalidate( $type ); } @@ -191,18 +206,28 @@ class WPSEO_Sitemaps_Cache { * Invalidate sitemap cache for authors. * * @param int $user_id User ID. + * + * @return bool True if the sitemap was properly invalidated. False otherwise. */ public static function invalidate_author( $user_id ) { $user = get_user_by( 'id', $user_id ); - if ( 'user_register' === current_action() ) { + if ( $user === false ) { + return false; + } + + if ( current_action() === 'user_register' ) { update_user_meta( $user_id, '_yoast_wpseo_profile_updated', time() ); } - if ( ! in_array( 'subscriber', $user->roles, true ) ) { - self::invalidate( 'author' ); + if ( empty( $user->roles ) || in_array( 'subscriber', $user->roles, true ) ) { + return false; } + + self::invalidate( 'author' ); + + return true; } /** @@ -236,7 +261,7 @@ class WPSEO_Sitemaps_Cache { * * @return void */ - public static function clear( $types = array() ) { + public static function clear( $types = [] ) { if ( ! self::$is_enabled ) { return; @@ -250,12 +275,12 @@ class WPSEO_Sitemaps_Cache { } // Always invalidate the index sitemap as well. - if ( ! in_array( WPSEO_Sitemaps::SITEMAP_INDEX_TYPE, $types ) ) { + if ( ! in_array( WPSEO_Sitemaps::SITEMAP_INDEX_TYPE, $types, true ) ) { array_unshift( $types, WPSEO_Sitemaps::SITEMAP_INDEX_TYPE ); } foreach ( $types as $type ) { - if ( ! in_array( $type, self::$clear_types ) ) { + if ( ! in_array( $type, self::$clear_types, true ) ) { self::$clear_types[] = $type; } } @@ -270,7 +295,7 @@ class WPSEO_Sitemaps_Cache { WPSEO_Sitemaps_Cache_Validator::invalidate_storage(); self::$clear_all = false; - self::$clear_types = array(); + self::$clear_types = []; return; } @@ -279,11 +304,11 @@ class WPSEO_Sitemaps_Cache { WPSEO_Sitemaps_Cache_Validator::invalidate_storage( $type ); } - self::$clear_types = array(); + self::$clear_types = []; } /** - * Adds a hook that when given option is updated, the cache is cleared + * Adds a hook that when given option is updated, the cache is cleared. * * @since 3.2 * @@ -296,7 +321,7 @@ class WPSEO_Sitemaps_Cache { } /** - * Clears the transient cache when a given option is updated, if that option has been registered before + * Clears the transient cache when a given option is updated, if that option has been registered before. * * @since 3.2 * diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-renderer.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-renderer.php index 1e23b6d0..f5a0cf56 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-renderer.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-renderer.php @@ -10,21 +10,34 @@ */ class WPSEO_Sitemaps_Renderer { - /** @var string $stylesheet XSL stylesheet for styling a sitemap for web browsers. */ + /** + * XSL stylesheet for styling a sitemap for web browsers. + * + * @var string + */ protected $stylesheet = ''; - /** @var string $charset Holds the get_bloginfo( 'charset' ) value to reuse for performance. */ + /** + * Holds the get_bloginfo( 'charset' ) value to reuse for performance. + * + * @var string + */ protected $charset = 'UTF-8'; - /** @var string $output_charset Holds charset of output, might be converted. */ + /** + * Holds charset of output, might be converted. + * + * @var string + */ protected $output_charset = 'UTF-8'; - /** @var bool $needs_conversion If data encoding needs to be converted for output. */ + /** + * If data encoding needs to be converted for output. + * + * @var bool + */ protected $needs_conversion = false; - /** @var WPSEO_Sitemap_Timezone $timezone */ - protected $timezone; - /** * Set up object properties. */ @@ -33,10 +46,9 @@ class WPSEO_Sitemaps_Renderer { $this->stylesheet = ''; $this->charset = get_bloginfo( 'charset' ); $this->output_charset = $this->charset; - $this->timezone = new WPSEO_Sitemap_Timezone(); if ( - 'UTF-8' !== $this->charset + $this->charset !== 'UTF-8' && function_exists( 'mb_list_encodings' ) && in_array( $this->charset, mb_list_encodings(), true ) ) { @@ -47,6 +59,8 @@ class WPSEO_Sitemaps_Renderer { } /** + * Builds the sitemap index. + * * @param array $links Set of sitemaps index links. * * @return string @@ -71,6 +85,8 @@ class WPSEO_Sitemaps_Renderer { } /** + * Builds the sitemap. + * * @param array $links Set of sitemap links. * @param string $type Sitemap type. * @param int $current_page Current sitemap page number. @@ -114,8 +130,8 @@ class WPSEO_Sitemaps_Renderer { /** * Produce final XML output with debug information. * - * @param string $sitemap Sitemap XML. - * @param boolean $transient Transient cache flag. + * @param string $sitemap Sitemap XML. + * @param bool $transient Transient cache flag. * * @return string */ @@ -135,23 +151,6 @@ class WPSEO_Sitemaps_Renderer { $output .= $sitemap; $output .= "\n"; - $debug = WP_DEBUG || ( defined( 'WPSEO_DEBUG' ) && true === WPSEO_DEBUG ); - - if ( ! WP_DEBUG_DISPLAY || ! $debug ) { - return $output; - } - - $memory_used = number_format( ( memory_get_peak_usage() / 1048576 ), 2 ); - $queries_run = ( $transient ) ? 'Served from transient cache' : 'Queries executed ' . absint( $GLOBALS['wpdb']->num_queries ); - - $output .= "\n"; - - if ( defined( 'SAVEQUERIES' ) && SAVEQUERIES ) { - - $queries = print_r( $GLOBALS['wpdb']->queries, true ); - $output .= "\n"; - } - return $output; } @@ -167,7 +166,7 @@ class WPSEO_Sitemaps_Renderer { /** * Set a custom stylesheet for this sitemap. Set to empty to just remove the default stylesheet. * - * @param string $stylesheet Full xml-stylesheet declaration. + * @param string $stylesheet Full XML-stylesheet declaration. */ public function set_stylesheet( $stylesheet ) { $this->stylesheet = $stylesheet; @@ -185,14 +184,14 @@ class WPSEO_Sitemaps_Renderer { $date = null; if ( ! empty( $url['lastmod'] ) ) { - $date = $this->timezone->format_date( $url['lastmod'] ); + $date = YoastSEO()->helpers->date->format( $url['lastmod'] ); } - $url['loc'] = htmlspecialchars( $url['loc'] ); + $url['loc'] = htmlspecialchars( $url['loc'], ENT_COMPAT, $this->output_charset, false ); $output = "\t\n"; $output .= "\t\t" . $url['loc'] . "\n"; - $output .= empty( $date ) ? '' : "\t\t" . htmlspecialchars( $date ) . "\n"; + $output .= empty( $date ) ? '' : "\t\t" . htmlspecialchars( $date, ENT_COMPAT, $this->output_charset, false ) . "\n"; $output .= "\t\n"; return $output; @@ -214,17 +213,17 @@ class WPSEO_Sitemaps_Renderer { if ( ! empty( $url['mod'] ) ) { // Create a DateTime object date in the correct timezone. - $date = $this->timezone->format_date( $url['mod'] ); + $date = YoastSEO()->helpers->date->format( $url['mod'] ); } - $url['loc'] = htmlspecialchars( $url['loc'] ); + $url['loc'] = htmlspecialchars( $url['loc'], ENT_COMPAT, $this->output_charset, false ); $output = "\t\n"; $output .= "\t\t" . $this->encode_url_rfc3986( $url['loc'] ) . "\n"; - $output .= empty( $date ) ? '' : "\t\t" . htmlspecialchars( $date ) . "\n"; + $output .= empty( $date ) ? '' : "\t\t" . htmlspecialchars( $date, ENT_COMPAT, $this->output_charset, false ) . "\n"; if ( empty( $url['images'] ) ) { - $url['images'] = array(); + $url['images'] = []; } foreach ( $url['images'] as $img ) { @@ -267,11 +266,11 @@ class WPSEO_Sitemaps_Renderer { $output .= "\t\n"; /** - * Filters the output for the sitemap url tag. + * Filters the output for the sitemap URL tag. * * @api string $output The output for the sitemap url tag. * - * @param array $url The sitemap url array on which the output is based. + * @param array $url The sitemap URL array on which the output is based. */ return apply_filters( 'wpseo_sitemap_url', $output, $url ); } @@ -291,7 +290,7 @@ class WPSEO_Sitemaps_Renderer { $path = wp_parse_url( $url, PHP_URL_PATH ); - if ( ! empty( $path ) && '/' !== $path ) { + if ( ! empty( $path ) && $path !== '/' ) { $encoded_path = explode( '/', $path ); // First decode the path, to prevent double encoding. @@ -299,7 +298,6 @@ class WPSEO_Sitemaps_Renderer { $encoded_path = array_map( 'rawurlencode', $encoded_path ); $encoded_path = implode( '/', $encoded_path ); - $encoded_path = str_replace( '%7E', '~', $encoded_path ); // PHP <5.3. $url = str_replace( $path, $encoded_path, $url ); } @@ -310,14 +308,7 @@ class WPSEO_Sitemaps_Renderer { parse_str( $query, $parsed_query ); - if ( defined( 'PHP_QUERY_RFC3986' ) ) { // PHP 5.4+. - $parsed_query = http_build_query( $parsed_query, null, '&', PHP_QUERY_RFC3986 ); - } - else { - $parsed_query = http_build_query( $parsed_query, null, '&' ); - $parsed_query = str_replace( '+', '%20', $parsed_query ); - $parsed_query = str_replace( '%7E', '~', $parsed_query ); - } + $parsed_query = http_build_query( $parsed_query, null, '&', PHP_QUERY_RFC3986 ); $url = str_replace( $query, $parsed_query, $url ); } @@ -339,6 +330,14 @@ class WPSEO_Sitemaps_Renderer { return home_url( 'main-sitemap.xsl' ); } + /* + * Fallback to circumvent a cross-domain security problem when the XLS file is + * loaded from a different (sub)domain. + */ + if ( strpos( plugins_url(), home_url() ) !== 0 ) { + return home_url( 'main-sitemap.xsl' ); + } + return plugin_dir_url( WPSEO_FILE ) . 'css/main-sitemap.xsl'; } } diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-router.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-router.php index 8b6a4728..d00a8def 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-router.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps-router.php @@ -15,9 +15,9 @@ class WPSEO_Sitemaps_Router { */ public function __construct() { - add_action( 'init', array( $this, 'init' ), 1 ); - add_filter( 'redirect_canonical', array( $this, 'redirect_canonical' ) ); - add_action( 'template_redirect', array( $this, 'template_redirect' ), 0 ); + add_action( 'init', [ $this, 'init' ], 1 ); + add_filter( 'redirect_canonical', [ $this, 'redirect_canonical' ] ); + add_action( 'template_redirect', [ $this, 'template_redirect' ], 0 ); } /** @@ -29,11 +29,11 @@ class WPSEO_Sitemaps_Router { $wp->add_query_var( 'sitemap' ); $wp->add_query_var( 'sitemap_n' ); - $wp->add_query_var( 'xsl' ); + $wp->add_query_var( 'yoast-sitemap-xsl' ); add_rewrite_rule( 'sitemap_index\.xml$', 'index.php?sitemap=1', 'top' ); add_rewrite_rule( '([^/]+?)-sitemap([0-9]+)?\.xml$', 'index.php?sitemap=$matches[1]&sitemap_n=$matches[2]', 'top' ); - add_rewrite_rule( '([a-z]+)?-?sitemap\.xsl$', 'index.php?xsl=$matches[1]', 'top' ); + add_rewrite_rule( '([a-z]+)?-?sitemap\.xsl$', 'index.php?yoast-sitemap-xsl=$matches[1]', 'top' ); } /** @@ -41,11 +41,11 @@ class WPSEO_Sitemaps_Router { * * @param string $redirect The redirect URL currently determined. * - * @return bool|string $redirect + * @return bool|string */ public function redirect_canonical( $redirect ) { - if ( get_query_var( 'sitemap' ) || get_query_var( 'xsl' ) ) { + if ( get_query_var( 'sitemap' ) || get_query_var( 'yoast-sitemap-xsl' ) ) { return false; } @@ -56,22 +56,46 @@ class WPSEO_Sitemaps_Router { * Redirects sitemap.xml to sitemap_index.xml. */ public function template_redirect() { + if ( ! $this->needs_sitemap_index_redirect() ) { + return; + } + wp_safe_redirect( home_url( '/sitemap_index.xml' ), 301, 'Yoast SEO' ); + exit; + } + + /** + * Checks whether the current request needs to be redirected to sitemap_index.xml. + * + * @global WP_Query $wp_query Current query. + * + * @return bool True if redirect is needed, false otherwise. + */ + public function needs_sitemap_index_redirect() { global $wp_query; - $current_url = 'http://'; - + $protocol = 'http://'; if ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] === 'on' ) { - $current_url = 'https://'; + $protocol = 'https://'; } - $current_url .= sanitize_text_field( $_SERVER['SERVER_NAME'] ); - $current_url .= sanitize_text_field( $_SERVER['REQUEST_URI'] ); - - if ( home_url( '/sitemap.xml' ) === $current_url && $wp_query->is_404 ) { - wp_redirect( home_url( '/sitemap_index.xml' ), 301 ); - exit; + $domain = ''; + if ( isset( $_SERVER['SERVER_NAME'] ) ) { + $domain = sanitize_text_field( wp_unslash( $_SERVER['SERVER_NAME'] ) ); } + + $path = ''; + if ( isset( $_SERVER['REQUEST_URI'] ) ) { + $path = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ); + } + + // Due to different environment configurations, we need to check both SERVER_NAME and HTTP_HOST. + $check_urls = [ $protocol . $domain . $path ]; + if ( ! empty( $_SERVER['HTTP_HOST'] ) ) { + $check_urls[] = $protocol . sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) . $path; + } + + return $wp_query->is_404 && in_array( home_url( '/sitemap.xml' ), $check_urls, true ); } /** @@ -88,13 +112,16 @@ class WPSEO_Sitemaps_Router { $base = $wp_rewrite->using_index_permalinks() ? 'index.php/' : '/'; /** - * Filter the base URL of the sitemaps + * Filter the base URL of the sitemaps. * * @param string $base The string that should be added to home_url() to make the full base URL. */ $base = apply_filters( 'wpseo_sitemaps_base_url', $base ); - // Get the scheme from the configured home url instead of letting WordPress determine the scheme based on the requested URI. + /* + * Get the scheme from the configured home URL instead of letting WordPress + * determine the scheme based on the requested URI. + */ return home_url( $base . $page, wp_parse_url( get_option( 'home' ), PHP_URL_SCHEME ) ); } } diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps.php index 43f70716..5d9c5230 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-sitemaps.php @@ -6,78 +6,109 @@ */ /** - * Class WPSEO_Sitemaps + * Class WPSEO_Sitemaps. * * @todo This class could use a general description with some explanation on sitemaps. OR. */ class WPSEO_Sitemaps { - /** Sitemap index identifier. */ + /** + * Sitemap index identifier. + * + * @var string + */ const SITEMAP_INDEX_TYPE = '1'; - /** @var string $sitemap Content of the sitemap to output. */ + /** + * Content of the sitemap to output. + * + * @var string + */ protected $sitemap = ''; - /** @var bool $bad_sitemap Flag to indicate if this is an invalid or empty sitemap. */ + /** + * Flag to indicate if this is an invalid or empty sitemap. + * + * @var bool + */ public $bad_sitemap = false; - /** @var bool $transient Whether or not the XML sitemap was served from a transient or not. */ + /** + * Whether or not the XML sitemap was served from a transient or not. + * + * @var bool + */ private $transient = false; /** - * @var string $http_protocol HTTP protocol to use in headers. + * HTTP protocol to use in headers. + * * @since 3.2 + * + * @var string */ protected $http_protocol = 'HTTP/1.1'; - /** @var int $current_page Holds the n variable. */ + /** + * Holds the n variable. + * + * @var int + */ private $current_page = 1; - /** @var WPSEO_Sitemap_Timezone $timezone */ - private $timezone; - /** - * @var WPSEO_Sitemaps_Router $router + * The sitemaps router. + * * @since 3.2 + * + * @var WPSEO_Sitemaps_Router */ public $router; /** - * @var WPSEO_Sitemaps_Renderer $renderer + * The sitemap renderer. + * * @since 3.2 + * + * @var WPSEO_Sitemaps_Renderer */ public $renderer; /** - * @var WPSEO_Sitemaps_Cache $cache + * The sitemap cache. + * * @since 3.2 + * + * @var WPSEO_Sitemaps_Cache */ public $cache; /** - * @var WPSEO_Sitemap_Provider[] $providers + * The sitemap providers. + * * @since 3.2 + * + * @var WPSEO_Sitemap_Provider[] */ public $providers; /** - * Class constructor + * Class constructor. */ public function __construct() { - add_action( 'after_setup_theme', array( $this, 'init_sitemaps_providers' ) ); - add_action( 'after_setup_theme', array( $this, 'reduce_query_load' ), 99 ); - add_action( 'pre_get_posts', array( $this, 'redirect' ), 1 ); - add_action( 'wpseo_hit_sitemap_index', array( $this, 'hit_sitemap_index' ) ); - add_action( 'wpseo_ping_search_engines', array( __CLASS__, 'ping_search_engines' ) ); + add_action( 'after_setup_theme', [ $this, 'init_sitemaps_providers' ] ); + add_action( 'after_setup_theme', [ $this, 'reduce_query_load' ], 99 ); + add_action( 'pre_get_posts', [ $this, 'redirect' ], 1 ); + add_action( 'wpseo_hit_sitemap_index', [ $this, 'hit_sitemap_index' ] ); + add_action( 'wpseo_ping_search_engines', [ __CLASS__, 'ping_search_engines' ] ); - $this->timezone = new WPSEO_Sitemap_Timezone(); - $this->router = new WPSEO_Sitemaps_Router(); - $this->renderer = new WPSEO_Sitemaps_Renderer(); - $this->cache = new WPSEO_Sitemaps_Cache(); + $this->router = new WPSEO_Sitemaps_Router(); + $this->renderer = new WPSEO_Sitemaps_Renderer(); + $this->cache = new WPSEO_Sitemaps_Cache(); if ( ! empty( $_SERVER['SERVER_PROTOCOL'] ) ) { - $this->http_protocol = sanitize_text_field( $_SERVER['SERVER_PROTOCOL'] ); + $this->http_protocol = sanitize_text_field( wp_unslash( $_SERVER['SERVER_PROTOCOL'] ) ); } } @@ -88,13 +119,13 @@ class WPSEO_Sitemaps { */ public function init_sitemaps_providers() { - $this->providers = array( + $this->providers = [ new WPSEO_Post_Type_Sitemap_Provider(), new WPSEO_Taxonomy_Sitemap_Provider(), new WPSEO_Author_Sitemap_Provider(), - ); + ]; - $external_providers = apply_filters( 'wpseo_sitemaps_providers', array() ); + $external_providers = apply_filters( 'wpseo_sitemaps_providers', [] ); foreach ( $external_providers as $provider ) { if ( is_object( $provider ) && $provider instanceof WPSEO_Sitemap_Provider ) { @@ -104,18 +135,15 @@ class WPSEO_Sitemaps { } /** - * Check the current request URI, if we can determine it's probably an XML sitemap, kill loading the widgets + * Check the current request URI, if we can determine it's probably an XML sitemap, kill loading the widgets. */ public function reduce_query_load() { - if ( ! isset( $_SERVER['REQUEST_URI'] ) ) { return; } - - $request_uri = $_SERVER['REQUEST_URI']; + $request_uri = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ); $extension = substr( $request_uri, -4 ); - - if ( false !== stripos( $request_uri, 'sitemap' ) && in_array( $extension, array( '.xml', '.xsl' ), true ) ) { + if ( stripos( $request_uri, 'sitemap' ) !== false && in_array( $extension, [ '.xml', '.xsl' ], true ) ) { remove_all_actions( 'widgets_init' ); } } @@ -146,15 +174,15 @@ class WPSEO_Sitemaps { public function register_xsl( $name, $function, $rewrite = '' ) { add_action( 'wpseo_xsl_' . $name, $function ); if ( ! empty( $rewrite ) ) { - add_rewrite_rule( $rewrite, 'index.php?xsl=' . $name, 'top' ); + add_rewrite_rule( $rewrite, 'index.php?yoast-sitemap-xsl=' . $name, 'top' ); } } /** - * Set the sitemap current page to allow creating partial sitemaps with wp-cli + * Set the sitemap current page to allow creating partial sitemaps with WP-CLI * in a one-off process. * - * @param integer $current_page The part that should be generated. + * @param int $current_page The part that should be generated. */ public function set_n( $current_page ) { if ( is_scalar( $current_page ) && intval( $current_page ) > 0 ) { @@ -201,9 +229,9 @@ class WPSEO_Sitemaps { return; } - $xsl = get_query_var( 'xsl' ); + $yoast_sitemap_xsl = get_query_var( 'yoast-sitemap-xsl' ); - if ( ! empty( $xsl ) ) { + if ( ! empty( $yoast_sitemap_xsl ) ) { /* * This is a method to provide the XSL via the home_url. * Needed when the site_url and home_url are not the same. @@ -211,7 +239,7 @@ class WPSEO_Sitemaps { * * Whenever home_url and site_url are the same, the file can be loaded directly. */ - $this->xsl_output( $xsl ); + $this->xsl_output( $yoast_sitemap_xsl ); $this->sitemap_close(); return; @@ -241,7 +269,7 @@ class WPSEO_Sitemaps { } /** - * Try to get the sitemap from cache + * Try to get the sitemap from cache. * * @param string $type Sitemap type. * @param int $page_number The page number to retrieve. @@ -252,7 +280,7 @@ class WPSEO_Sitemaps { $this->transient = false; - if ( true !== $this->cache->is_enabled() ) { + if ( $this->cache->is_enabled() !== true ) { return false; } @@ -323,9 +351,9 @@ class WPSEO_Sitemaps { continue; } - $links = $provider->get_sitemap_links( $type, $entries_per_page, $this->current_page ); - - if ( empty( $links ) ) { + try { + $links = $provider->get_sitemap_links( $type, $entries_per_page, $this->current_page ); + } catch ( OutOfBoundsException $exception ) { $this->bad_sitemap = true; return; @@ -353,13 +381,20 @@ class WPSEO_Sitemaps { */ public function build_root_map() { - $links = array(); + $links = []; $entries_per_page = $this->get_entries_per_page(); foreach ( $this->providers as $provider ) { $links = array_merge( $links, $provider->get_index_links( $entries_per_page ) ); } + /** + * Filter the sitemap links array before the index sitemap is built. + * + * @param array $links Array of sitemap links + */ + $links = apply_filters( 'wpseo_sitemap_index_links', $links ); + if ( empty( $links ) ) { $this->bad_sitemap = true; $this->sitemap = ''; @@ -373,9 +408,9 @@ class WPSEO_Sitemaps { /** * Spits out the XSL for the XML sitemap. * - * @param string $type Type to output. - * * @since 1.4.13 + * + * @param string $type Type to output. */ public function xsl_output( $type ) { @@ -397,31 +432,31 @@ class WPSEO_Sitemaps { // Make the browser cache this file properly. $expires = YEAR_IN_SECONDS; header( 'Pragma: public' ); - header( 'Cache-Control: maxage=' . $expires ); - header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', ( time() + $expires ) ) . ' GMT' ); + header( 'Cache-Control: max-age=' . $expires ); + header( 'Expires: ' . YoastSEO()->helpers->date->format_timestamp( ( time() + $expires ), 'D, d M Y H:i:s' ) . ' GMT' ); + // Don't use WP_Filesystem() here because that's not initialized yet. See https://yoast.atlassian.net/browse/QAK-2043. readfile( WPSEO_PATH . 'css/main-sitemap.xsl' ); } /** - * Spit out the generated sitemap and relevant headers and encoding information. + * Spit out the generated sitemap. */ public function output() { - - if ( ! headers_sent() ) { - header( $this->http_protocol . ' 200 OK', true, 200 ); - // Prevent the search engines from indexing the XML Sitemap. - header( 'X-Robots-Tag: noindex, follow', true ); - header( 'Content-Type: text/xml; charset=' . esc_attr( $this->renderer->get_output_charset() ) ); - } - + $this->send_headers(); echo $this->renderer->get_output( $this->sitemap, $this->transient ); } /** - * Make a request for the sitemap index so as to cache it before the arrival of the search engines. + * Makes a request to the sitemap index to cache it before the arrival of the search engines. + * + * @return void */ public function hit_sitemap_index() { + if ( ! $this->cache->is_enabled() ) { + return; + } + wp_remote_get( WPSEO_Sitemaps_Router::get_base_url( 'sitemap_index.xml' ) ); } @@ -442,7 +477,7 @@ class WPSEO_Sitemaps { static $post_type_dates = null; if ( ! is_array( $post_types ) ) { - $post_types = array( $post_types ); + $post_types = [ $post_types ]; } foreach ( $post_types as $post_type ) { @@ -454,20 +489,20 @@ class WPSEO_Sitemaps { if ( is_null( $post_type_dates ) ) { - $post_type_dates = array(); - - // Consider using WPSEO_Post_Type::get_accessible_post_types() to filter out any `no-index` post-types. - $post_type_names = get_post_types( array( 'public' => true ) ); + $post_type_dates = []; + $post_type_names = WPSEO_Post_Type::get_accessible_post_types(); if ( ! empty( $post_type_names ) ) { + $post_statuses = array_map( 'esc_sql', self::get_post_statuses() ); + $sql = " - SELECT post_type, MAX(post_modified_gmt) AS date - FROM $wpdb->posts - WHERE post_status IN ('publish','inherit') - AND post_type IN ('" . implode( "','", $post_type_names ) . "') - GROUP BY post_type - ORDER BY post_modified_gmt DESC - "; + SELECT post_type, MAX(post_modified_gmt) AS date + FROM $wpdb->posts + WHERE post_status IN ('" . implode( "','", $post_statuses ) . "') + AND post_type IN ('" . implode( "','", $post_type_names ) . "') + GROUP BY post_type + ORDER BY date DESC + "; foreach ( $wpdb->get_results( $sql ) as $obj ) { $post_type_dates[ $obj->post_type ] = $obj->date; @@ -496,8 +531,7 @@ class WPSEO_Sitemaps { * @return string */ public function get_last_modified( $post_types ) { - - return $this->timezone->format_date( self::get_last_modified_gmt( $post_types ) ); + return YoastSEO()->helpers->date->format( self::get_last_modified_gmt( $post_types ) ); } /** @@ -516,17 +550,17 @@ class WPSEO_Sitemaps { return; } - if ( '0' === get_option( 'blog_public' ) ) { // Don't ping if blog is not public. + if ( get_option( 'blog_public' ) === '0' ) { // Don't ping if blog is not public. return; } if ( empty( $url ) ) { - $url = urlencode( WPSEO_Sitemaps_Router::get_base_url( 'sitemap_index.xml' ) ); + $url = rawurlencode( WPSEO_Sitemaps_Router::get_base_url( 'sitemap_index.xml' ) ); } // Ping Google and Bing. - wp_remote_get( 'http://www.google.com/webmasters/tools/ping?sitemap=' . $url, array( 'blocking' => false ) ); - wp_remote_get( 'http://www.bing.com/ping?sitemap=' . $url, array( 'blocking' => false ) ); + wp_remote_get( 'https://www.google.com/ping?sitemap=' . $url, [ 'blocking' => false ] ); + wp_remote_get( 'https://www.bing.com/ping?sitemap=' . $url, [ 'blocking' => false ] ); } /** @@ -547,4 +581,66 @@ class WPSEO_Sitemaps { return $entries; } + + /** + * Get post statuses for post_type or the root sitemap. + * + * @since 10.2 + * + * @param string $type Provide a type for a post_type sitemap, SITEMAP_INDEX_TYPE for the root sitemap. + * + * @return array List of post statuses. + */ + public static function get_post_statuses( $type = self::SITEMAP_INDEX_TYPE ) { + /** + * Filter post status list for sitemap query for the post type. + * + * @param array $post_statuses Post status list, defaults to array( 'publish' ). + * @param string $type Post type or SITEMAP_INDEX_TYPE. + */ + $post_statuses = apply_filters( 'wpseo_sitemap_post_statuses', [ 'publish' ], $type ); + + if ( ! is_array( $post_statuses ) || empty( $post_statuses ) ) { + $post_statuses = [ 'publish' ]; + } + + if ( ( $type === self::SITEMAP_INDEX_TYPE || $type === 'attachment' ) + && ! in_array( 'inherit', $post_statuses, true ) + ) { + $post_statuses[] = 'inherit'; + } + + return $post_statuses; + } + + /** + * Sends all the required HTTP Headers. + */ + private function send_headers() { + if ( headers_sent() ) { + return; + } + + $headers = [ + $this->http_protocol . ' 200 OK' => 200, + // Prevent the search engines from indexing the XML Sitemap. + 'X-Robots-Tag: noindex, follow' => '', + 'Content-Type: text/xml; charset=' . esc_attr( $this->renderer->get_output_charset() ) => '', + ]; + + /** + * Filter the HTTP headers we send before an XML sitemap. + * + * @param array $headers The HTTP headers we're going to send out. + */ + $headers = apply_filters( 'wpseo_sitemap_http_headers', $headers ); + + foreach ( $headers as $header => $status ) { + if ( is_numeric( $status ) ) { + header( $header, true, $status ); + continue; + } + header( $header, true ); + } + } } diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-taxonomy-sitemap-provider.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-taxonomy-sitemap-provider.php index e10a46a4..8d8b394f 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/class-taxonomy-sitemap-provider.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/class-taxonomy-sitemap-provider.php @@ -10,70 +10,101 @@ */ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider { - /** @var WPSEO_Sitemap_Image_Parser $image_parser Holds image parser instance. */ + /** + * Holds image parser instance. + * + * @var WPSEO_Sitemap_Image_Parser + */ protected static $image_parser; + /** + * Determines whether images should be included in the XML sitemap. + * + * @var bool + */ + private $include_images; + + /** + * Set up object properties for data reuse. + */ + public function __construct() { + /** + * Filter - Allows excluding images from the XML sitemap. + * + * @param bool $include True to include, false to exclude. + */ + $this->include_images = apply_filters( 'wpseo_xml_sitemap_include_images', true ); + } + /** * Check if provider supports given item type. * * @param string $type Type string to check for. * - * @return boolean + * @return bool */ public function handles_type( $type ) { - return taxonomy_exists( $type ); + $taxonomy = get_taxonomy( $type ); + + if ( $taxonomy === false || ! $this->is_valid_taxonomy( $taxonomy->name ) || ! $taxonomy->public ) { + return false; + } + + return true; } /** - * Get all the options + * Retrieves the links for the sitemap. * - * @deprecated 7.0 - */ - protected function get_options() { - _deprecated_function( __METHOD__, 'WPSEO 7.0', 'WPSEO_Options::get' ); - } - - /** * @param int $max_entries Entries per sitemap. * * @return array */ public function get_index_links( $max_entries ) { - $taxonomies = get_taxonomies( array( 'public' => true ), 'objects' ); + $taxonomies = get_taxonomies( [ 'public' => true ], 'objects' ); if ( empty( $taxonomies ) ) { - return array(); + return []; } - $taxonomy_names = array_filter( array_keys( $taxonomies ), array( $this, 'is_valid_taxonomy' ) ); + $taxonomy_names = array_filter( array_keys( $taxonomies ), [ $this, 'is_valid_taxonomy' ] ); $taxonomies = array_intersect_key( $taxonomies, array_flip( $taxonomy_names ) ); // Retrieve all the taxonomies and their terms so we can do a proper count on them. + /** * Filter the setting of excluding empty terms from the XML sitemap. * - * @param boolean $exclude Defaults to true. - * @param array $taxonomy_names Array of names for the taxonomies being processed. + * @param bool $exclude Defaults to true. + * @param array $taxonomy_names Array of names for the taxonomies being processed. */ $hide_empty = apply_filters( 'wpseo_sitemap_exclude_empty_terms', true, $taxonomy_names ); - $all_taxonomies = array(); + $all_taxonomies = []; foreach ( $taxonomy_names as $taxonomy_name ) { + /** + * Filter the setting of excluding empty terms from the XML sitemap for a specific taxonomy. + * + * @param bool $exclude Defaults to the sitewide setting. + * @param string $taxonomy_name The name of the taxonomy being processed. + */ + $hide_empty_tax = apply_filters( 'wpseo_sitemap_exclude_empty_terms_taxonomy', $hide_empty, $taxonomy_name ); - $taxonomy_terms = get_terms( $taxonomy_name, array( - 'hide_empty' => $hide_empty, + $term_args = [ + 'hide_empty' => $hide_empty_tax, 'fields' => 'ids', - ) ); + ]; + $taxonomy_terms = get_terms( $taxonomy_name, $term_args ); if ( count( $taxonomy_terms ) > 0 ) { $all_taxonomies[ $taxonomy_name ] = $taxonomy_terms; } } - $index = array(); + $index = []; foreach ( $taxonomies as $tax_name => $tax ) { @@ -104,18 +135,18 @@ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider { continue; } - $args = array( + $args = [ 'post_type' => $tax->object_type, - 'tax_query' => array( - array( + 'tax_query' => [ + [ 'taxonomy' => $tax_name, 'terms' => $terms, - ), - ), + ], + ], 'orderby' => 'modified', 'order' => 'DESC', 'posts_per_page' => 1, - ); + ]; $query = new WP_Query( $args ); if ( $query->have_posts() ) { @@ -125,10 +156,10 @@ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider { $date = $last_modified_gmt; } - $index[] = array( + $index[] = [ 'loc' => WPSEO_Sitemaps_Router::get_base_url( $tax_name . '-sitemap' . $current_page . '.xml' ), 'lastmod' => $date, - ); + ]; } } @@ -143,30 +174,43 @@ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider { * @param int $current_page Current page of the sitemap. * * @return array + * + * @throws OutOfBoundsException When an invalid page is requested. */ public function get_sitemap_links( $type, $max_entries, $current_page ) { - global $wpdb; - $links = array(); - $taxonomy = get_taxonomy( $type ); - - if ( $taxonomy === false || ! $this->is_valid_taxonomy( $taxonomy->name ) || ! $taxonomy->public ) { + $links = []; + if ( ! $this->handles_type( $type ) ) { return $links; } + $taxonomy = get_taxonomy( $type ); + $steps = $max_entries; $offset = ( $current_page > 1 ) ? ( ( $current_page - 1 ) * $max_entries ) : 0; /** This filter is documented in inc/sitemaps/class-taxonomy-sitemap-provider.php */ - $hide_empty = apply_filters( 'wpseo_sitemap_exclude_empty_terms', true, $taxonomy ); - $terms = get_terms( $taxonomy->name, array( 'hide_empty' => $hide_empty ) ); - $terms = array_splice( $terms, $offset, $steps ); + $hide_empty = apply_filters( 'wpseo_sitemap_exclude_empty_terms', true, [ $taxonomy->name ] ); + /** This filter is documented in inc/sitemaps/class-taxonomy-sitemap-provider.php */ + $hide_empty_tax = apply_filters( 'wpseo_sitemap_exclude_empty_terms_taxonomy', $hide_empty, $taxonomy->name ); + $terms = get_terms( + [ + 'taxonomy' => $taxonomy->name, + 'hide_empty' => $hide_empty_tax, + 'update_term_meta_cache' => false, + 'offset' => $offset, + 'number' => $steps, + ] + ); + // If there are no terms fetched for this range, we are on an invalid page. if ( empty( $terms ) ) { - $terms = array(); + throw new OutOfBoundsException( 'Invalid sitemap page requested' ); } + $post_statuses = array_map( 'esc_sql', WPSEO_Sitemaps::get_post_statuses() ); + // Grab last modified date. $sql = " SELECT MAX(p.post_modified_gmt) AS lastmod @@ -177,13 +221,24 @@ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider { ON term_tax.term_taxonomy_id = term_rel.term_taxonomy_id AND term_tax.taxonomy = %s AND term_tax.term_id = %d - WHERE p.post_status IN ('publish','inherit') + WHERE p.post_status IN ('" . implode( "','", $post_statuses ) . "') AND p.post_password = '' "; + /** + * Filter: 'wpseo_exclude_from_sitemap_by_term_ids' - Allow excluding terms by ID. + * + * @api array $terms_to_exclude The terms to exclude. + */ + $terms_to_exclude = apply_filters( 'wpseo_exclude_from_sitemap_by_term_ids', [] ); + foreach ( $terms as $term ) { - $url = array(); + if ( in_array( $term->term_id, $terms_to_exclude, true ) ) { + continue; + } + + $url = []; $tax_noindex = WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'noindex' ); @@ -197,8 +252,11 @@ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider { $url['loc'] = get_term_link( $term, $term->taxonomy ); } - $url['mod'] = $wpdb->get_var( $wpdb->prepare( $sql, $term->taxonomy, $term->term_id ) ); - $url['images'] = $this->get_image_parser()->get_term_images( $term ); + $url['mod'] = $wpdb->get_var( $wpdb->prepare( $sql, $term->taxonomy, $term->term_id ) ); + + if ( $this->include_images ) { + $url['images'] = $this->get_image_parser()->get_term_images( $term ); + } // Deprecated, kept for backwards data compat. R. $url['chf'] = 'daily'; @@ -228,19 +286,19 @@ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider { return false; } - if ( in_array( $taxonomy_name, array( 'link_category', 'nav_menu' ), true ) ) { + if ( in_array( $taxonomy_name, [ 'link_category', 'nav_menu' ], true ) ) { return false; } - if ( 'post_format' === $taxonomy_name && ! WPSEO_Options::get( 'disable-post_format', false ) ) { + if ( $taxonomy_name === 'post_format' && WPSEO_Options::get( 'disable-post_format', false ) ) { return false; } /** * Filter to exclude the taxonomy from the XML sitemap. * - * @param boolean $exclude Defaults to false. - * @param string $taxonomy_name Name of the taxonomy to exclude.. + * @param bool $exclude Defaults to false. + * @param string $taxonomy_name Name of the taxonomy to exclude.. */ if ( apply_filters( 'wpseo_sitemap_exclude_taxonomy', false, $taxonomy_name ) ) { return false; @@ -250,7 +308,7 @@ class WPSEO_Taxonomy_Sitemap_Provider implements WPSEO_Sitemap_Provider { } /** - * Get the Image Parser + * Get the Image Parser. * * @return WPSEO_Sitemap_Image_Parser */ diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/interface-sitemap-cache-data.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/interface-sitemap-cache-data.php index 4dc0c47c..136f6d65 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/interface-sitemap-cache-data.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/interface-sitemap-cache-data.php @@ -6,21 +6,33 @@ */ /** - * Cache Data interface + * Cache Data interface. */ interface WPSEO_Sitemap_Cache_Data_Interface { - /** Status for normal, usable sitemap. */ + /** + * Status for normal, usable sitemap. + * + * @var string + */ const OK = 'ok'; - /** Status for unusable sitemap. */ + /** + * Status for unusable sitemap. + * + * @var string + */ const ERROR = 'error'; - /** Status for unusable sitemap because it cannot be identified. */ + /** + * Status for unusable sitemap because it cannot be identified. + * + * @var string + */ const UNKNOWN = 'unknown'; /** - * Set the content of the sitemap + * Set the content of the sitemap. * * @param string $sitemap The XML content of the sitemap. * @@ -29,7 +41,7 @@ interface WPSEO_Sitemap_Cache_Data_Interface { public function set_sitemap( $sitemap ); /** - * Set the status of the sitemap + * Set the status of the sitemap. * * @param bool|string $usable True/False or 'ok'/'error' for status. * @@ -38,19 +50,21 @@ interface WPSEO_Sitemap_Cache_Data_Interface { public function set_status( $usable ); /** + * Builds the sitemap. + * * @return string The XML content of the sitemap. */ public function get_sitemap(); /** - * Get the status of this sitemap + * Get the status of this sitemap. * * @return string Status 'ok', 'error' or 'unknown'. */ public function get_status(); /** - * Is the sitemap content usable + * Is the sitemap content usable ? * * @return bool True if the sitemap is usable, False if not. */ diff --git a/wp-content/plugins/wordpress-seo/inc/sitemaps/interface-sitemap-provider.php b/wp-content/plugins/wordpress-seo/inc/sitemaps/interface-sitemap-provider.php index 658f9efa..c18ac9c9 100644 --- a/wp-content/plugins/wordpress-seo/inc/sitemaps/interface-sitemap-provider.php +++ b/wp-content/plugins/wordpress-seo/inc/sitemaps/interface-sitemap-provider.php @@ -6,7 +6,7 @@ */ /** - * Sitemap Provider interface + * Sitemap Provider interface. */ interface WPSEO_Sitemap_Provider { @@ -15,7 +15,7 @@ interface WPSEO_Sitemap_Provider { * * @param string $type Type string to check for. * - * @return boolean + * @return bool */ public function handles_type( $type ); diff --git a/wp-content/plugins/wordpress-seo/inc/wpseo-functions-deprecated.php b/wp-content/plugins/wordpress-seo/inc/wpseo-functions-deprecated.php index 13db6945..afea7e09 100644 --- a/wp-content/plugins/wordpress-seo/inc/wpseo-functions-deprecated.php +++ b/wp-content/plugins/wordpress-seo/inc/wpseo-functions-deprecated.php @@ -5,26 +5,14 @@ * @package WPSEO\Deprecated */ -/** - * Remove the bulk edit capability from the proper default roles. - * - * Contributor is still removed for legacy reasons. - * - * @deprecated 5.5 - */ -function wpseo_remove_capabilities() { - _deprecated_function( __FUNCTION__, 'WPSEO 5.5.0', 'WPSEO_Capability_Manager_Factory::get()->remove()' ); - - WPSEO_Capability_Manager_Factory::get()->remove(); -} - -/** - * Add the bulk edit capability to the proper default roles. - * - * @deprecated 5.5.0 - */ -function wpseo_add_capabilities() { - _deprecated_function( __FUNCTION__, 'WPSEO 5.5.0', 'WPSEO_Capability_Manager_Factory::get()->add()' ); - - WPSEO_Capability_Manager_Factory::get()->add(); +if ( ! function_exists( 'initialize_wpseo_front' ) ) { + /** + * Wraps frontend class. + * + * @deprecated 14.0 + * @codeCoverageIgnore + */ + function initialize_wpseo_front() { + _deprecated_function( __FUNCTION__, 'WPSEO 14.0' ); + } } diff --git a/wp-content/plugins/wordpress-seo/inc/wpseo-functions.php b/wp-content/plugins/wordpress-seo/inc/wpseo-functions.php index c87c2698..71442e8b 100644 --- a/wp-content/plugins/wordpress-seo/inc/wpseo-functions.php +++ b/wp-content/plugins/wordpress-seo/inc/wpseo-functions.php @@ -11,15 +11,6 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { exit(); } -if ( ! function_exists( 'initialize_wpseo_front' ) ) { - /** - * Wraps frontend class. - */ - function initialize_wpseo_front() { - WPSEO_Frontend::get_instance(); - } -} - if ( ! function_exists( 'yoast_breadcrumb' ) ) { /** * Template tag for breadcrumbs. @@ -47,7 +38,7 @@ if ( ! function_exists( 'yoast_get_primary_term_id' ) ) { * Get the primary term ID. * * @param string $taxonomy Optional. The taxonomy to get the primary term ID for. Defaults to category. - * @param null|int|WP_Post $post Optional. Post to get the primary term ID for. + * @param int|WP_Post|null $post Optional. Post to get the primary term ID for. * * @return bool|int */ @@ -64,7 +55,7 @@ if ( ! function_exists( 'yoast_get_primary_term' ) ) { * Get the primary term name. * * @param string $taxonomy Optional. The taxonomy to get the primary term for. Defaults to category. - * @param null|int|WP_Post $post Optional. Post to get the primary term for. + * @param int|WP_Post|null $post Optional. Post to get the primary term for. * * @return string Name of the primary term. */ @@ -84,12 +75,13 @@ if ( ! function_exists( 'yoast_get_primary_term' ) ) { * Replace `%%variable_placeholders%%` with their real value based on the current requested page/post/cpt. * * @param string $string The string to replace the variables in. - * @param object $args The object some of the replacement values might come from, could be a post, taxonomy or term. + * @param object $args The object some of the replacement values might come from, + * could be a post, taxonomy or term. * @param array $omit Variables that should not be replaced by this function. * * @return string */ -function wpseo_replace_vars( $string, $args, $omit = array() ) { +function wpseo_replace_vars( $string, $args, $omit = [] ) { $replacer = new WPSEO_Replace_Vars(); return $replacer->replace( $string, $args, $omit ); @@ -128,15 +120,15 @@ function wpseo_replace_vars( $string, $args, $omit = array() ) { * * @since 1.5.4 * - * @param string $var The name of the variable to replace, i.e. '%%var%%' - * - the surrounding %% are optional, name can only contain [A-Za-z0-9_-]. - * @param mixed $replace_function Function or method to call to retrieve the replacement value for the variable - * Uses the same format as add_filter/add_action function parameter and - * should *return* the replacement value. DON'T echo it. - * @param string $type Type of variable: 'basic' or 'advanced', defaults to 'advanced'. - * @param string $help_text Help text to be added to the help tab for this variable. + * @param string $var The name of the variable to replace, i.e. '%%var%%'. + * Note: the surrounding %% are optional, name can only contain [A-Za-z0-9_-]. + * @param mixed $replace_function Function or method to call to retrieve the replacement value for the variable. + * Uses the same format as add_filter/add_action function parameter and + * should *return* the replacement value. DON'T echo it. + * @param string $type Type of variable: 'basic' or 'advanced', defaults to 'advanced'. + * @param string $help_text Help text to be added to the help tab for this variable. * - * @return bool Whether the replacement function was succesfully registered. + * @return bool Whether the replacement function was successfully registered. */ function wpseo_register_var_replacement( $var, $replace_function, $type = 'advanced', $help_text = '' ) { return WPSEO_Replace_Vars::register_replacement( $var, $replace_function, $type, $help_text ); @@ -144,10 +136,12 @@ function wpseo_register_var_replacement( $var, $replace_function, $type = 'advan /** * WPML plugin support: Set titles for custom types / taxonomies as translatable. - * It adds new keys to a wpml-config.xml file for a custom post type title, metadesc, title-ptarchive and metadesc-ptarchive fields translation. + * + * It adds new keys to a wpml-config.xml file for a custom post type title, metadesc, + * title-ptarchive and metadesc-ptarchive fields translation. * Documentation: http://wpml.org/documentation/support/language-configuration-files/ * - * @global $sitepress + * @global $sitepress * * @param array $config WPML configuration data to filter. * @@ -156,12 +150,12 @@ function wpseo_register_var_replacement( $var, $replace_function, $type = 'advan function wpseo_wpml_config( $config ) { global $sitepress; - if ( ( is_array( $config ) && isset( $config['wpml-config']['admin-texts']['key'] ) ) && ( is_array( $config['wpml-config']['admin-texts']['key'] ) && $config['wpml-config']['admin-texts']['key'] !== array() ) ) { + if ( ( is_array( $config ) && isset( $config['wpml-config']['admin-texts']['key'] ) ) && ( is_array( $config['wpml-config']['admin-texts']['key'] ) && $config['wpml-config']['admin-texts']['key'] !== [] ) ) { $admin_texts = $config['wpml-config']['admin-texts']['key']; foreach ( $admin_texts as $k => $val ) { if ( $val['attr']['name'] === 'wpseo_titles' ) { $translate_cp = array_keys( $sitepress->get_translatable_documents() ); - if ( is_array( $translate_cp ) && $translate_cp !== array() ) { + if ( is_array( $translate_cp ) && $translate_cp !== [] ) { foreach ( $translate_cp as $post_type ) { $admin_texts[ $k ]['key'][]['attr']['name'] = 'title-' . $post_type; $admin_texts[ $k ]['key'][]['attr']['name'] = 'metadesc-' . $post_type; @@ -169,7 +163,7 @@ function wpseo_wpml_config( $config ) { $admin_texts[ $k ]['key'][]['attr']['name'] = 'metadesc-ptarchive-' . $post_type; $translate_tax = $sitepress->get_translatable_taxonomies( false, $post_type ); - if ( is_array( $translate_tax ) && $translate_tax !== array() ) { + if ( is_array( $translate_tax ) && $translate_tax !== [] ) { foreach ( $translate_tax as $taxonomy ) { $admin_texts[ $k ]['key'][]['attr']['name'] = 'title-tax-' . $taxonomy; $admin_texts[ $k ]['key'][]['attr']['name'] = 'metadesc-tax-' . $taxonomy; @@ -192,25 +186,22 @@ add_filter( 'icl_wpml_config_array', 'wpseo_wpml_config' ); * Yoast SEO breadcrumb shortcode. * [wpseo_breadcrumb] * + * @deprecated 14.0 + * @codeCoverageIgnore + * * @return string */ function wpseo_shortcode_yoast_breadcrumb() { - return yoast_breadcrumb( '', '', false ); + _deprecated_function( __FUNCTION__, 'WPSEO 14.0' ); + + return ''; } -add_shortcode( 'wpseo_breadcrumb', 'wpseo_shortcode_yoast_breadcrumb' ); - -/** - * Emulate PHP native ctype_digit() function for when the ctype extension would be disabled *sigh*. - * Only emulates the behaviour for when the input is a string, does not handle integer input as ascii value. - * - * @param string $string - * - * @return bool - */ -if ( ! extension_loaded( 'ctype' ) || ! function_exists( 'ctype_digit' ) ) { - +if ( ! function_exists( 'ctype_digit' ) ) { /** + * Emulate PHP native ctype_digit() function for when the ctype extension would be disabled *sigh*. + * Only emulates the behaviour for when the input is a string, does not handle integer input as ascii value. + * * @param string $string String input to validate. * * @return bool @@ -236,7 +227,7 @@ if ( ! extension_loaded( 'ctype' ) || ! function_exists( 'ctype_digit' ) ) { * @param string $taxonomy The taxonomy that the taxonomy term was splitted for. */ function wpseo_split_shared_term( $old_term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) { - $tax_meta = get_option( 'wpseo_taxonomy_meta', array() ); + $tax_meta = get_option( 'wpseo_taxonomy_meta', [] ); if ( ! empty( $tax_meta[ $taxonomy ][ $old_term_id ] ) ) { $tax_meta[ $taxonomy ][ $new_term_id ] = $tax_meta[ $taxonomy ][ $old_term_id ]; @@ -246,3 +237,80 @@ function wpseo_split_shared_term( $old_term_id, $new_term_id, $term_taxonomy_id, } add_action( 'split_shared_term', 'wpseo_split_shared_term', 10, 4 ); + +/** + * Get all WPSEO related capabilities. + * + * @since 8.3 + * @return array + */ +function wpseo_get_capabilities() { + if ( ! did_action( 'wpseo_register_capabilities' ) ) { + do_action( 'wpseo_register_capabilities' ); + } + return WPSEO_Capability_Manager_Factory::get()->get_capabilities(); +} + +if ( ! function_exists( 'wp_get_environment_type' ) ) { + /** + * Retrieves the current environment type. + * + * The type can be set via the `WP_ENVIRONMENT_TYPE` global system variable, + * or a constant of the same name. + * + * Possible values include 'local', 'development', 'staging', 'production'. + * If not set, the type defaults to 'production'. + * + * Backfill for `wp_get_environment_type()` introduced in WordPress 5.5. Code + * is adapted to the Yoast PHP coding standards. + * + * @return string The current environment type. + */ + function wp_get_environment_type() { + static $current_env = ''; + + if ( $current_env ) { + return $current_env; + } + + $wp_environments = [ + 'local', + 'development', + 'staging', + 'production', + ]; + + // Check if the environment variable has been set, if `getenv` is available on the system. + if ( function_exists( 'getenv' ) ) { + $has_env = getenv( 'WP_ENVIRONMENT_TYPES' ); + if ( $has_env !== false ) { + $wp_environments = explode( ',', $has_env ); + } + } + + // Fetch the environment types from a constant, this overrides the global system variable. + if ( defined( 'WP_ENVIRONMENT_TYPES' ) ) { + $wp_environments = WP_ENVIRONMENT_TYPES; + } + + // Check if the environment variable has been set, if `getenv` is available on the system. + if ( function_exists( 'getenv' ) ) { + $has_env = getenv( 'WP_ENVIRONMENT_TYPE' ); + if ( $has_env !== false ) { + $current_env = $has_env; + } + } + + // Fetch the environment from a constant, this overrides the global system variable. + if ( defined( 'WP_ENVIRONMENT_TYPE' ) ) { + $current_env = WP_ENVIRONMENT_TYPE; + } + + // Make sure the environment is an allowed one, and not accidentally set to an invalid value. + if ( ! in_array( $current_env, $wp_environments, true ) ) { + $current_env = 'production'; + } + + return $current_env; + } +} diff --git a/wp-content/plugins/wordpress-seo/inc/wpseo-non-ajax-functions.php b/wp-content/plugins/wordpress-seo/inc/wpseo-non-ajax-functions.php index 067993fc..3563be68 100644 --- a/wp-content/plugins/wordpress-seo/inc/wpseo-non-ajax-functions.php +++ b/wp-content/plugins/wordpress-seo/inc/wpseo-non-ajax-functions.php @@ -12,412 +12,46 @@ if ( ! defined( 'WPSEO_VERSION' ) ) { } /** - * Adds an SEO admin bar menu with several options. If the current user is an admin he can also go straight to several settings menu's from here. - */ -function wpseo_admin_bar_menu() { - // If the current user can't write posts, this is all of no use, so let's not output an admin menu. - if ( ! current_user_can( 'edit_posts' ) ) { - return; - } - - $options = WPSEO_Options::get_options( array( 'wpseo', 'wpseo_ms' ) ); - - if ( $options['enable_admin_bar_menu'] !== true ) { - return; - } - - global $wp_admin_bar, $post; - - $focuskw = ''; - $score = ''; - // By default, the top level menu item has no link. - $seo_url = ''; - // By default, make the no-link top level menu item focusable. - $top_level_link_tabindex = '0'; - - $analysis_seo = new WPSEO_Metabox_Analysis_SEO(); - $analysis_readability = new WPSEO_Metabox_Analysis_Readability(); - - if ( ( is_singular() || ( is_admin() && WPSEO_Metabox::is_post_edit( $GLOBALS['pagenow'] ) ) ) && isset( $post ) && is_object( $post ) && apply_filters( 'wpseo_use_page_analysis', true ) === true - ) { - $focuskw = WPSEO_Meta::get_value( 'focuskw', $post->ID ); - - if ( $analysis_seo->is_enabled() ) { - $score = wpseo_adminbar_seo_score(); - } - elseif ( $analysis_readability->is_enabled() ) { - $score = wpseo_adminbar_content_score(); - } - } - - if ( is_category() || is_tag() || ( WPSEO_Taxonomy::is_term_edit( $GLOBALS['pagenow'] ) && ! WPSEO_Taxonomy::is_term_overview( $GLOBALS['pagenow'] ) ) || is_tax() ) { - if ( $analysis_seo->is_enabled() ) { - $score = wpseo_tax_adminbar_seo_score(); - } - elseif ( $analysis_readability->is_enabled() ) { - $score = wpseo_tax_adminbar_content_score(); - } - } - - // Never display notifications for network admin. - $counter = ''; - $alert_popup = ''; - - // Determine is user is admin or network admin. - $can_manage_seo = WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ); - - // Set the top level menu item content for admins and network admins. - if ( $can_manage_seo ) { - - // Link the top level menu item to the Yoast Dashboard page. - $seo_url = get_admin_url( null, 'admin.php?page=' . WPSEO_Admin::PAGE_IDENTIFIER ); - // Since admins will get a real link, there's no need for a tabindex attribute. - $top_level_link_tabindex = false; - - if ( '' === $score ) { - - // Notification information. - $notification_center = Yoast_Notification_Center::get(); - $notification_count = $notification_center->get_notification_count(); - $new_notifications = $notification_center->get_new_notifications(); - $new_notifications_count = count( $new_notifications ); - - if ( $notification_count > 0 ) { - // Always show Alerts page when clicking on the main link. - /* translators: %s: number of notifications */ - $counter_screen_reader_text = sprintf( _n( '%s notification', '%s notifications', $notification_count, 'wordpress-seo' ), number_format_i18n( $notification_count ) ); - - $counter = sprintf( '
    %s
    ', $notification_count, $counter_screen_reader_text ); - } - - if ( $new_notifications_count ) { - $notification = sprintf( - /* translators: %d resolves to the number of alerts being added. */ - _n( 'You have %d new issue concerning your SEO!', 'You have %d new issues concerning your SEO!', $new_notifications_count, 'wordpress-seo' ), - $new_notifications_count - ); - if ( $new_notifications_count === 1 ) { - $notification = sprintf( - __( 'You have a new issue concerning your SEO!', 'wordpress-seo' ), - $new_notifications_count - ); - } - $alert_popup = '
    ' . $notification . '
    '; - } - } - } - - $title = ''; - - $wp_admin_bar->add_menu( array( - 'id' => 'wpseo-menu', - 'title' => $title . $score . $counter . $alert_popup, - 'href' => $seo_url, - 'meta' => array( 'tabindex' => $top_level_link_tabindex ), - ) ); - if ( ! empty( $notification_count ) ) { - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-menu', - 'id' => 'wpseo-notifications', - 'title' => __( 'Notifications', 'wordpress-seo' ) . $counter, - 'href' => $seo_url, - 'meta' => array( 'tabindex' => $top_level_link_tabindex ), - ) ); - } - - if ( WPSEO_Capability_Utils::current_user_can( 'wpseo_manage_options' ) ) { - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-menu', - 'id' => 'wpseo-configuration-wizard', - 'title' => __( 'Configuration Wizard', 'wordpress-seo' ), - 'href' => admin_url( 'admin.php?page=' . WPSEO_Configuration_Page::PAGE_IDENTIFIER ), - ) ); - } - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-menu', - 'id' => 'wpseo-kwresearch', - 'title' => __( 'Keyword Research', 'wordpress-seo' ), - 'meta' => array( 'tabindex' => '0' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-kwresearch', - 'id' => 'wpseo-adwordsexternal', - 'title' => __( 'AdWords External', 'wordpress-seo' ), - 'href' => 'https://adwords.google.com/keywordplanner', - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-kwresearch', - 'id' => 'wpseo-googleinsights', - 'title' => __( 'Google Trends', 'wordpress-seo' ), - 'href' => 'https://www.google.com/trends/explore#q=' . urlencode( $focuskw ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-kwresearch', - 'id' => 'wpseo-wordtracker', - 'title' => __( 'SEO Book', 'wordpress-seo' ), - 'href' => 'http://tools.seobook.com/keyword-tools/seobook/?keyword=' . urlencode( $focuskw ), - 'meta' => array( 'target' => '_blank' ), - ) ); - - if ( ! is_admin() ) { - $url = WPSEO_Frontend::get_instance()->canonical( false ); - - if ( is_string( $url ) ) { - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-menu', - 'id' => 'wpseo-analysis', - 'title' => __( 'Analyze this page', 'wordpress-seo' ), - 'meta' => array( 'tabindex' => '0' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-inlinks-ose', - 'title' => __( 'Check Inlinks (OSE)', 'wordpress-seo' ), - 'href' => '//moz.com/researchtools/ose/links?site=' . urlencode( $url ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-kwdensity', - 'title' => __( 'Check Keyword Density', 'wordpress-seo' ), - // HTTPS not available. - 'href' => 'http://www.zippy.co.uk/keyworddensity/index.php?url=' . urlencode( $url ) . '&keyword=' . urlencode( $focuskw ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-cache', - 'title' => __( 'Check Google Cache', 'wordpress-seo' ), - 'href' => '//webcache.googleusercontent.com/search?strip=1&q=cache:' . urlencode( $url ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-header', - 'title' => __( 'Check Headers', 'wordpress-seo' ), - 'href' => '//quixapp.com/headers/?r=' . urlencode( $url ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-structureddata', - 'title' => __( 'Google Structured Data Test', 'wordpress-seo' ), - 'href' => 'https://search.google.com/structured-data/testing-tool#url=' . urlencode( $url ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-facebookdebug', - 'title' => __( 'Facebook Debugger', 'wordpress-seo' ), - 'href' => '//developers.facebook.com/tools/debug/og/object?q=' . urlencode( $url ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-pinterestvalidator', - 'title' => __( 'Pinterest Rich Pins Validator', 'wordpress-seo' ), - 'href' => 'https://developers.pinterest.com/tools/url-debugger/?link=' . urlencode( $url ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-htmlvalidation', - 'title' => __( 'HTML Validator', 'wordpress-seo' ), - 'href' => '//validator.w3.org/check?uri=' . urlencode( $url ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-cssvalidation', - 'title' => __( 'CSS Validator', 'wordpress-seo' ), - 'href' => '//jigsaw.w3.org/css-validator/validator?uri=' . urlencode( $url ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-pagespeed', - 'title' => __( 'Google Page Speed Test', 'wordpress-seo' ), - 'href' => '//developers.google.com/speed/pagespeed/insights/?url=' . urlencode( $url ), - 'meta' => array( 'target' => '_blank' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-analysis', - 'id' => 'wpseo-google-mobile-friendly', - 'title' => __( 'Mobile-Friendly Test', 'wordpress-seo' ), - 'href' => 'https://www.google.com/webmasters/tools/mobile-friendly/?url=' . urlencode( $url ), - 'meta' => array( 'target' => '_blank' ), - ) ); - } - } - - if ( $can_manage_seo ) { - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-menu', - 'id' => 'wpseo-settings', - 'title' => __( 'SEO Settings', 'wordpress-seo' ), - 'meta' => array( 'tabindex' => '0' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-settings', - 'id' => 'wpseo-general', - 'title' => __( 'Dashboard', 'wordpress-seo' ), - 'href' => admin_url( 'admin.php?page=wpseo_dashboard' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-settings', - 'id' => 'wpseo-titles', - 'title' => __( 'Search Appearance', 'wordpress-seo' ), - 'href' => admin_url( 'admin.php?page=wpseo_titles' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-settings', - 'id' => 'wpseo-search-console', - 'title' => __( 'Search Console', 'wordpress-seo' ), - 'href' => admin_url( 'admin.php?page=wpseo_search_console' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-settings', - 'id' => 'wpseo-social', - 'title' => __( 'Social', 'wordpress-seo' ), - 'href' => admin_url( 'admin.php?page=wpseo_social' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-settings', - 'id' => 'wpseo-tools', - 'title' => __( 'Tools', 'wordpress-seo' ), - 'href' => admin_url( 'admin.php?page=wpseo_tools' ), - ) ); - $wp_admin_bar->add_menu( array( - 'parent' => 'wpseo-settings', - 'id' => 'wpseo-licenses', - 'title' => __( 'Premium', 'wordpress-seo' ), - 'href' => admin_url( 'admin.php?page=wpseo_licenses' ), - ) ); - } -} - -/** - * Returns the SEO score element for the admin bar. + * Initializes the admin bar. * - * @return string + * @return void */ -function wpseo_adminbar_seo_score() { - $rating = WPSEO_Meta::get_value( 'linkdex', get_the_ID() ); - - return wpseo_adminbar_score( $rating ); +function wpseo_initialize_admin_bar() { + $admin_bar_menu = new WPSEO_Admin_Bar_Menu(); + $admin_bar_menu->register_hooks(); } - -/** - * Returns the content score element for the adminbar. - * - * @return string - */ -function wpseo_adminbar_content_score() { - $rating = WPSEO_Meta::get_value( 'content_score', get_the_ID() ); - - return wpseo_adminbar_score( $rating ); -} - -/** - * Returns the SEO score element for the adminbar. - * - * @return string - */ -function wpseo_tax_adminbar_seo_score() { - $rating = 0; - - if ( is_tax() || is_category() || is_tag() ) { - $rating = WPSEO_Taxonomy_Meta::get_meta_without_term( 'linkdex' ); - } - - return wpseo_adminbar_score( $rating ); -} - -/** - * Returns the Content score element for the adminbar. - * - * @return string - */ -function wpseo_tax_adminbar_content_score() { - $rating = 0; - - if ( is_tax() || is_category() || is_tag() ) { - $rating = WPSEO_Taxonomy_Meta::get_meta_without_term( 'content_score' ); - } - - return wpseo_adminbar_score( $rating ); -} - -/** - * Takes The SEO score and makes the score icon for the adminbar with it. - * - * @param int $score The 0-100 rating of the score. Can be either SEO score or content score. - * - * @return string $score_adminbar_element - */ -function wpseo_adminbar_score( $score ) { - $score = WPSEO_Utils::translate_score( $score ); - - $score_adminbar_element = '
    '; - - return $score_adminbar_element; -} - -add_action( 'admin_bar_menu', 'wpseo_admin_bar_menu', 95 ); - -/** - * Enqueue CSS to format the Yoast SEO adminbar item. - */ -function wpseo_admin_bar_style() { - if ( ! is_admin_bar_showing() || WPSEO_Options::get( 'enable_admin_bar_menu' ) !== true ) { - return; - } - - $asset_manager = new WPSEO_Admin_Asset_Manager(); - $asset_manager->register_assets(); - $asset_manager->enqueue_style( 'adminbar' ); -} - -add_action( 'wp_enqueue_scripts', 'wpseo_admin_bar_style' ); -add_action( 'admin_enqueue_scripts', 'wpseo_admin_bar_style' ); +add_action( 'wp_loaded', 'wpseo_initialize_admin_bar' ); /** * Allows editing of the meta fields through weblog editors like Marsedit. * - * @param array $allcaps Capabilities that must all be true to allow action. - * @param array $cap Array of capabilities to be checked, unused here. - * @param array $args List of arguments for the specific cap to be checked. + * @param array $required_capabilities Capabilities that must all be true to allow action. + * @param array $capabilities Array of capabilities to be checked, unused here. + * @param array $args List of arguments for the specific capabilities to be checked. * - * @return array $allcaps + * @return array Filtered capabilities. */ -function allow_custom_field_edits( $allcaps, $cap, $args ) { - // $args[0] holds the capability. - // $args[2] holds the post ID. - // $args[3] holds the custom field. - // Make sure the request is to edit or add a post meta (this is usually also the second value in $cap, - // but this is safer to check). - if ( in_array( $args[0], array( 'edit_post_meta', 'add_post_meta' ), true ) ) { - // Only allow editing rights for users who have the rights to edit this post and make sure - // the meta value starts with _yoast_wpseo (WPSEO_Meta::$meta_prefix). - if ( ( isset( $args[2] ) && current_user_can( 'edit_post', $args[2] ) ) && ( ( isset( $args[3] ) && $args[3] !== '' ) && strpos( $args[3], WPSEO_Meta::$meta_prefix ) === 0 ) ) { - $allcaps[ $args[0] ] = true; - } +function allow_custom_field_edits( $required_capabilities, $capabilities, $args ) { + if ( ! in_array( $args[0], [ 'edit_post_meta', 'add_post_meta' ], true ) ) { + return $required_capabilities; } - return $allcaps; + // If this is provided, it is the post ID. + if ( empty( $args[2] ) ) { + return $required_capabilities; + } + + // If this is provided, it is the custom field. + if ( empty( $args[3] ) ) { + return $required_capabilities; + } + + // If the meta key is part of the plugin, grant capabilities accordingly. + if ( strpos( $args[3], WPSEO_Meta::$meta_prefix ) === 0 && current_user_can( 'edit_post', $args[2] ) ) { + $required_capabilities[ $args[0] ] = true; + } + + return $required_capabilities; } add_filter( 'user_has_cap', 'allow_custom_field_edits', 0, 3 ); - -/********************** DEPRECATED FUNCTIONS **********************/ - -/** - * Detects if the advanced settings are enabled. - * - * @deprecated 7.0 - */ -function wpseo_advanced_settings_enabled() { - _deprecated_function( __FUNCTION__, 'WPSEO 7.0', null ); -} diff --git a/wp-content/plugins/wordpress-seo/js/dist/addon-installation-1720.js b/wp-content/plugins/wordpress-seo/js/dist/addon-installation-1720.js new file mode 100644 index 00000000..3b685c2c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/js/dist/addon-installation-1720.js @@ -0,0 +1,5 @@ +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=357)}({0:function(e,t){e.exports=window.wp.element},1:function(e,t){e.exports=window.yoast.propTypes},100:function(e,t){e.exports=function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var n=[],_n=!0,o=!1,r=void 0;try{for(var a,i=e[Symbol.iterator]();!(_n=(a=i.next()).done)&&(n.push(a.value),!t||n.length!==t);_n=!0);}catch(e){o=!0,r=e}finally{try{_n||null==i.return||i.return()}finally{if(o)throw r}}return n}}},101:function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},102:function(e,t){e.exports=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}},111:function(e,t,n){"use strict";n.d(t,"a",(function(){return s}));var o,r,a=n(16);function i(){return(i=Object.assign||function(e){for(var t=1;t=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}},53:function(e,t,n){"use strict";n.d(t,"b",(function(){return d}));var o=n(27),r=n.n(o),a=n(46),i=n.n(a),s=n(0),c=n(1),l=n.n(c),u=n(18),d="yoast yoast-gutenberg-modal",p=function(e){var t=e.title,n=e.className,o=e.showYoastIcon,a=e.additionalClassName,c=i()(e,["title","className","showYoastIcon","additionalClassName"]),l=o?Object(s.createElement)("span",{className:"yoast-icon"}):null;return Object(s.createElement)(u.Modal,r()({title:t,className:"".concat(n," ").concat(a),icon:l},c),e.children)};p.propTypes={title:l.a.string,className:l.a.string,showYoastIcon:l.a.bool,children:l.a.oneOfType([l.a.node,l.a.arrayOf(l.a.node)]),additionalClassName:l.a.string},p.defaultProps={title:"Yoast SEO",className:d,showYoastIcon:!0,children:null,additionalClassName:""},t.a=p},6:function(e,t){e.exports=window.yoast.componentsNew},99:function(e,t){e.exports=function(e){if(Array.isArray(e))return e}}}); \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/js/dist/admin-global-1720.js b/wp-content/plugins/wordpress-seo/js/dist/admin-global-1720.js new file mode 100644 index 00000000..18380cc0 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/js/dist/admin-global-1720.js @@ -0,0 +1 @@ +!function(t){var o={};function n(a){if(o[a])return o[a].exports;var e=o[a]={i:a,l:!1,exports:{}};return t[a].call(e.exports,e,e.exports,n),e.l=!0,e.exports}n.m=t,n.c=o,n.d=function(t,o,a){n.o(t,o)||Object.defineProperty(t,o,{enumerable:!0,get:a})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,o){if(1&o&&(t=n(t)),8&o)return t;if(4&o&&"object"==typeof t&&t&&t.__esModule)return t;var a=Object.create(null);if(n.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:t}),2&o&&"string"!=typeof t)for(var e in t)n.d(a,e,function(o){return t[o]}.bind(null,e));return a},n.n=function(t){var o=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(o,"a",o),o},n.o=function(t,o){return Object.prototype.hasOwnProperty.call(t,o)},n.p="",n(n.s=257)}({21:function(t,o){t.exports=window.jQuery},257:function(t,o,n){"use strict";n.r(o);var a=n(21),e=n.n(a);!function(t){function o(t,o,n){e.a.post(ajaxurl,{action:"wpseo_set_ignore",option:t,_wpnonce:n},(function(n){n&&(e()("#"+o).hide(),e()("#hidden_ignore_"+t).val("ignore"))}))}function n(){t("#wp-admin-bar-root-default > li").off("mouseenter.yoastalertpopup mouseleave.yoastalertpopup"),t(".yoast-issue-added").fadeOut(200)}function a(o,n){if(t(".yoast-notification-holder").off("click",".restore").off("click",".dismiss"),void 0!==n.html){n.html&&(o.closest(".yoast-container").html(n.html),s());var a=t("#wp-admin-bar-wpseo-menu"),e=a.find(".yoast-issue-counter");e.length||(a.find("> a:first-child").append('
    '),e=a.find(".yoast-issue-counter")),e.html(n.total),0===n.total?e.hide():e.show(),t("#toplevel_page_wpseo_dashboard .update-plugins").removeClass().addClass("update-plugins count-"+n.total),t("#toplevel_page_wpseo_dashboard .plugin-count").html(n.total)}}function s(){var o=t(".yoast-notification-holder");o.on("click",".dismiss",(function(){var o=t(this),n=o.closest(".yoast-notification-holder");o.closest(".yoast-container").append('
    '),t.post(ajaxurl,{action:"yoast_dismiss_notification",notification:n.attr("id"),nonce:n.data("nonce"),data:o.data("json")||n.data("json")},a.bind(this,n),"json")})),o.on("click",".restore",(function(){var o=t(this),n=o.closest(".yoast-notification-holder");o.closest(".yoast-container").append('
    '),t.post(ajaxurl,{action:"yoast_restore_notification",notification:n.attr("id"),nonce:n.data("nonce"),data:n.data("json")},a.bind(this,n),"json")}))}function i(t){t.is(":hidden")||(t.outerWidth()>t.parent().outerWidth()?(t.data("scrollHint").addClass("yoast-has-scroll"),t.data("scrollContainer").addClass("yoast-has-scroll")):(t.data("scrollHint").removeClass("yoast-has-scroll"),t.data("scrollContainer").removeClass("yoast-has-scroll")))}function l(){window.wpseoScrollableTables=t(".yoast-table-scrollable"),window.wpseoScrollableTables.length&&window.wpseoScrollableTables.each((function(){var o=t(this);if(!o.data("scrollContainer")){var n=t("
    ",{class:"yoast-table-scrollable__hintwrapper",html:"
    ",{class:"yoast-table-scrollable__container",html:"
    "}).insertBefore(o);n.find(".yoast-table-scrollable__hint").text(wpseoAdminGlobalL10n.scrollable_table_hint),o.data("scrollContainer",a),o.data("scrollHint",n),o.appendTo(a.find(".yoast-table-scrollable__inner")),i(o)}}))}e()(document).ready((function(){e()(".yoast-dismissible").on("click",".yoast-notice-dismiss",(function(){var t=e()(this).parent();return e.a.post(ajaxurl,{action:t.attr("id").replace(/-/g,"_"),_wpnonce:t.data("nonce"),data:t.data("json")}),e.a.post(ajaxurl,{action:"yoast_dismiss_notification",notification:t.attr("id"),nonce:t.data("nonce"),data:t.data("json")}),t.fadeTo(100,0,(function(){t.slideUp(100,(function(){t.remove()}))})),!1})),e()(".yoast-help-button").on("click",(function(){var t=e()(this),o=e()("#"+t.attr("aria-controls")),n=o.is(":visible");e()(o).slideToggle(200,(function(){t.attr("aria-expanded",!n)}))})),e()("#robotsmessage button").on("click",(function(){o("search_engines_discouraged_notice","robotsmessage",e()(this).data("nonce"))}))})),window.wpseoSetIgnore=o,window.wpseoDismissLink=function(t){return e()('Dismiss this notice.')},t(window).on("wp-window-resized orientationchange",(function(){window.wpseoScrollableTables&&window.wpseoScrollableTables.length&&window.wpseoScrollableTables.each((function(){i(t(this))}))})),t(window).on({"Yoast:YoastTabsMounted":function(){setTimeout((function(){l()}),100)},"Yoast:YoastTabsSelected":function(){setTimeout((function(){l()}),100)}}),t(document).ready((function(){t(".yoast-issue-added").on("mouseenter mouseleave",(function(t){t.stopPropagation(),n()})).fadeIn(),t("#wp-admin-bar-root-default > li").on("mouseenter.yoastalertpopup mouseleave.yoastalertpopup",n),setTimeout(n,3e3),s(),function(){var t=e()(".wpseo-js-premium-indicator"),o=t.find("svg");if(t.hasClass("wpseo-premium-indicator--no")){var n=o.find("path"),a=t.css("backgroundColor");n.css("fill",a)}o.css("display","block"),t.css({backgroundColor:"transparent",width:"20px",height:"20px"})}(),l()}))}(e.a)}}); \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/js/dist/analysis-worker-1720.js b/wp-content/plugins/wordpress-seo/js/dist/analysis-worker-1720.js new file mode 100644 index 00000000..429b248a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/js/dist/analysis-worker-1720.js @@ -0,0 +1 @@ +!function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=258)}({258:function(e,n){self.window=self,self.onmessage=function(e){var n=e.data;if(n&&n.dependencies){for(var t in n.dependencies)Object.prototype.hasOwnProperty.call(n.dependencies,t)&&(self.importScripts(n.dependencies[t]),"lodash"===t&&(self.lodash=_.noConflict()));var r=self.yoast.Researcher.default;new self.yoast.analysis.AnalysisWebWorker(self,new r).register()}}}}); \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/js/dist/api-client-1720.js b/wp-content/plugins/wordpress-seo/js/dist/api-client-1720.js new file mode 100644 index 00000000..e4f6cc7c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/js/dist/api-client-1720.js @@ -0,0 +1 @@ +!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=259)}({259:function(e,t){!function(e,t){window.wpseoApi={get:function(e,t,n,o){this.request("GET",e,t,n,o)},post:function(e,t,n,o){this.request("POST",e,t,n,o)},put:function(e,t,n,o){this.request("PUT",e,t,n,o)},patch:function(e,t,n,o){this.request("PATCH",e,t,n,o)},delete:function(e,t,n,o){this.request("DELETE",e,t,n,o)},request:function(n,o,r,u,i){e.isFunction(r)&&void 0===i&&(i=u,u=r,r={}),"POST"!==n&&"GET"!==n&&(r._method=n,n="POST"),e.ajax({url:t.root+"yoast/v1/"+o,method:n,beforeSend:function(e){e.setRequestHeader("X-WP-Nonce",t.nonce)},data:r}).done(u).fail(i)}}}(jQuery,wpApiSettings)}}); \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/js/dist/block-editor-1720.js b/wp-content/plugins/wordpress-seo/js/dist/block-editor-1720.js new file mode 100644 index 00000000..6a4b69e4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/js/dist/block-editor-1720.js @@ -0,0 +1,83 @@ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=348)}([function(e,t){e.exports=window.wp.element},function(e,t){e.exports=window.yoast.propTypes},function(e,t){e.exports=window.lodash},function(e,t){e.exports=window.wp.i18n},function(e,t){e.exports=window.wp.data},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t){e.exports=window.yoast.componentsNew},function(e,t){function n(e,t){for(var n=0;n2&&void 0!==arguments[2]?arguments[2]:"",o="string"==typeof t?Object(r.decodeHTML)(t):t;return{type:i,name:e,value:o,label:n}}function m(e){return{type:l,wordsToHighlight:e}}function b(e){return{type:s,name:e}}function h(){return{type:c,time:(new Date).getMilliseconds()}}},function(e,t){e.exports=window.wp.components},function(e,t){e.exports=window.wp.compose},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=n(2);function o(){return Object(r.get)(window,"wpseoScriptData.metabox",{intl:{},isRtl:!1})}},,function(e,t){e.exports=window.yoast.components},function(e,t){e.exports=window.yoast.analysis},function(e,t){e.exports=window.yoast.styleGuide},function(e,t,n){"use strict";n.r(t),n.d(t,"SET_ACTIVE_MARKER",(function(){return a.a})),n.d(t,"setActiveMarker",(function(){return a.b})),n.d(t,"SET_NO_INDEX",(function(){return i.f})),n.d(t,"SET_NO_FOLLOW",(function(){return i.e})),n.d(t,"SET_ADVANCED",(function(){return i.b})),n.d(t,"SET_BREADCRUMBS_TITLE",(function(){return i.c})),n.d(t,"SET_CANONICAL_URL",(function(){return i.d})),n.d(t,"LOAD_ADVANCED_SETTINGS",(function(){return i.a})),n.d(t,"setNoIndex",(function(){return i.l})),n.d(t,"setNoFollow",(function(){return i.k})),n.d(t,"setAdvanced",(function(){return i.h})),n.d(t,"setBreadcrumbsTitle",(function(){return i.i})),n.d(t,"setCanonical",(function(){return i.j})),n.d(t,"loadAdvancedSettingsData",(function(){return i.g})),n.d(t,"UPDATE_SNIPPET_DATA",(function(){return s})),n.d(t,"RUN_ANALYSIS",(function(){return c})),n.d(t,"updateAnalysisData",(function(){return l})),n.d(t,"runAnalysis",(function(){return u})),n.d(t,"LOAD_CORNERSTONE_CONTENT",(function(){return d.a})),n.d(t,"TOGGLE_CORNERSTONE_CONTENT",(function(){return d.c})),n.d(t,"SET_CORNERSTONE_CONTENT",(function(){return d.b})),n.d(t,"loadCornerstoneContent",(function(){return d.d})),n.d(t,"setCornerstoneContent",(function(){return d.e})),n.d(t,"toggleCornerstoneContent",(function(){return d.f})),n.d(t,"SET_EDITOR_DATA_CONTENT",(function(){return p})),n.d(t,"SET_EDITOR_DATA_TITLE",(function(){return f})),n.d(t,"SET_EDITOR_DATA_EXCERPT",(function(){return m})),n.d(t,"SET_EDITOR_DATA_IMAGE_URL",(function(){return b})),n.d(t,"setEditorDataContent",(function(){return h})),n.d(t,"setEditorDataTitle",(function(){return y})),n.d(t,"setEditorDataExcerpt",(function(){return g})),n.d(t,"setEditorDataImageUrl",(function(){return O})),n.d(t,"OPEN_EDITOR_MODAL",(function(){return v})),n.d(t,"CLOSE_EDITOR_MODAL",(function(){return E})),n.d(t,"openEditorModal",(function(){return j})),n.d(t,"closeEditorModal",(function(){return w})),n.d(t,"SET_ESTIMATED_READING_TIME",(function(){return _.b})),n.d(t,"LOAD_ESTIMATED_READING_TIME",(function(){return _.a})),n.d(t,"setEstimatedReadingTime",(function(){return _.d})),n.d(t,"loadEstimatedReadingTime",(function(){return _.c})),n.d(t,"LOAD_FOCUS_KEYWORD",(function(){return T.a})),n.d(t,"SET_FOCUS_KEYWORD",(function(){return T.b})),n.d(t,"loadFocusKeyword",(function(){return T.c})),n.d(t,"setFocusKeyword",(function(){return T.d})),n.d(t,"SET_MARKER_STATUS",(function(){return k.a})),n.d(t,"setMarkerStatus",(function(){return k.b})),n.d(t,"SET_MARKER_PAUSE_STATUS",(function(){return S.a})),n.d(t,"setMarkerPauseStatus",(function(){return S.b})),n.d(t,"DISMISS_ALERT",(function(){return R.a})),n.d(t,"DISMISS_ALERT_SUCCESS",(function(){return R.b})),n.d(t,"dismissAlert",(function(){return R.c})),n.d(t,"SET_PRIMARY_TAXONOMY",(function(){return P.a})),n.d(t,"setPrimaryTaxonomyId",(function(){return P.b})),n.d(t,"SET_PAGE_TYPE",(function(){return A.d})),n.d(t,"SET_ARTICLE_TYPE",(function(){return A.c})),n.d(t,"GET_SCHEMA_PAGE_DATA",(function(){return A.b})),n.d(t,"GET_SCHEMA_ARTICLE_DATA",(function(){return A.a})),n.d(t,"setPageType",(function(){return A.h})),n.d(t,"setArticleType",(function(){return A.g})),n.d(t,"getSchemaPageData",(function(){return A.f})),n.d(t,"getSchemaArticleData",(function(){return A.e})),n.d(t,"MODAL_DISMISS",(function(){return C})),n.d(t,"MODAL_OPEN",(function(){return x})),n.d(t,"MODAL_OPEN_NO_KEYPHRASE",(function(){return I})),n.d(t,"setSEMrushDismissModal",(function(){return D})),n.d(t,"setSEMrushOpenModal",(function(){return N})),n.d(t,"setSEMrushNoKeyphraseMessage",(function(){return L})),n.d(t,"CHANGE_COUNTRY",(function(){return M.a})),n.d(t,"SET_REQUEST_SUCCEEDED",(function(){return M.g})),n.d(t,"SET_REQUEST_FAILED",(function(){return M.e})),n.d(t,"SET_REQUEST_LIMIT_REACHED",(function(){return M.f})),n.d(t,"NEW_REQUEST",(function(){return M.b})),n.d(t,"NO_DATA_FOUND",(function(){return M.c})),n.d(t,"SET_LOGIN_STATUS",(function(){return M.d})),n.d(t,"setSEMrushNewRequest",(function(){return M.j})),n.d(t,"setSEMrushRequestSucceeded",(function(){return M.m})),n.d(t,"setSEMrushRequestFailed",(function(){return M.l})),n.d(t,"setSEMrushSetRequestLimitReached",(function(){return M.n})),n.d(t,"setSEMrushChangeCountry",(function(){return M.h})),n.d(t,"setSEMrushNoResultsFound",(function(){return M.k})),n.d(t,"setSEMrushLoginStatus",(function(){return M.i})),n.d(t,"SET_SETTINGS",(function(){return F.b})),n.d(t,"SET_CONTENT_IMAGE",(function(){return F.a})),n.d(t,"setSettings",(function(){return F.d})),n.d(t,"setContentImage",(function(){return F.c})),n.d(t,"SET_SHOPPING_DATA",(function(){return q.a})),n.d(t,"setShoppingData",(function(){return q.b})),n.d(t,"SWITCH_MODE",(function(){return B.d})),n.d(t,"UPDATE_DATA",(function(){return B.e})),n.d(t,"UPDATE_REPLACEMENT_VARIABLE",(function(){return B.f})),n.d(t,"REMOVE_REPLACEMENT_VARIABLE",(function(){return B.c})),n.d(t,"REFRESH",(function(){return B.b})),n.d(t,"UPDATE_WORDS_TO_HIGHLIGHT",(function(){return B.g})),n.d(t,"LOAD_SNIPPET_EDITOR_DATA",(function(){return B.a})),n.d(t,"switchMode",(function(){return B.j})),n.d(t,"updateData",(function(){return B.k})),n.d(t,"updateReplacementVariable",(function(){return B.l})),n.d(t,"updateWordsToHighlight",(function(){return B.m})),n.d(t,"removeReplacementVariable",(function(){return B.i})),n.d(t,"refreshSnippetEditor",(function(){return B.h})),n.d(t,"SET_TWITTER_TITLE",(function(){return U.e})),n.d(t,"SET_TWITTER_DESCRIPTION",(function(){return U.c})),n.d(t,"SET_TWITTER_IMAGE",(function(){return U.d})),n.d(t,"CLEAR_TWITTER_IMAGE",(function(){return U.a})),n.d(t,"LOAD_TWITTER_PREVIEW",(function(){return U.b})),n.d(t,"setTwitterPreviewTitle",(function(){return U.j})),n.d(t,"setTwitterPreviewDescription",(function(){return U.h})),n.d(t,"setTwitterPreviewImage",(function(){return U.i})),n.d(t,"clearTwitterPreviewImage",(function(){return U.f})),n.d(t,"loadTwitterPreviewData",(function(){return U.g})),n.d(t,"SET_FACEBOOK_TITLE",(function(){return K.e})),n.d(t,"SET_FACEBOOK_DESCRIPTION",(function(){return K.c})),n.d(t,"SET_FACEBOOK_IMAGE",(function(){return K.d})),n.d(t,"CLEAR_FACEBOOK_IMAGE",(function(){return K.a})),n.d(t,"LOAD_FACEBOOK_PREVIEW",(function(){return K.b})),n.d(t,"setFacebookPreviewTitle",(function(){return K.j})),n.d(t,"setFacebookPreviewDescription",(function(){return K.h})),n.d(t,"setFacebookPreviewImage",(function(){return K.i})),n.d(t,"clearFacebookPreviewImage",(function(){return K.f})),n.d(t,"loadFacebookPreviewData",(function(){return K.g})),n.d(t,"SET_WARNING_MESSAGE",(function(){return H.a})),n.d(t,"setWarningMessage",(function(){return H.b})),n.d(t,"setOverallReadabilityScore",(function(){return W})),n.d(t,"setOverallSeoScore",(function(){return G})),n.d(t,"setReadabilityResults",(function(){return r.setReadabilityResults})),n.d(t,"setSeoResultsForKeyword",(function(){return r.setSeoResultsForKeyword}));var r=n(22),o=n(29),a=n(74),i=n(44),s="SNIPPET_EDITOR_UPDATE_ANALYSIS_DATA",c="RUN_ANALYSIS";function l(e){return{type:s,data:e}}function u(){return{type:c,timestamp:Date.now()}}var d=n(59),p="SET_EDITOR_DATA_CONTENT",f="SET_EDITOR_DATA_TITLE",m="SET_EDITOR_DATA_EXCERPT",b="SET_EDITOR_DATA_IMAGE_URL";function h(e){return{type:p,content:e}}function y(e){return{type:f,title:e}}function g(e){return{type:m,excerpt:e}}function O(e){return{type:b,imageUrl:e}}var v="OPEN_MODAL",E="CLOSE_MODAL";function j(e){return{type:v,modalKey:e}}function w(){return{type:E}}var _=n(67),T=n(60),k=n(45),S=n(75),R=n(69),P=n(76),A=n(56),C="MODAL_DISMISS",x="MODAL_OPEN",I="MODAL_OPEN_NO_KEYPHRASE";function D(){return{type:C}}function N(e){return{type:x,location:e}}function L(){return{type:I}}var M=n(41),F=n(43),q=n(77),B=n(17),U=n(48),K=n(49),H=n(78),W=function(e){return o.a.readabilityScore=e,Object(r.setOverallReadabilityScore)(e)},G=function(e,t){return o.a.seoScore=e,Object(r.setOverallSeoScore)(e,t)}},function(e,t){e.exports=window.regeneratorRuntime},function(e,t){function n(){return e.exports=n=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:"",n=e.getIdentifier(),o={score:e.score,rating:r.interpreters.scoreToRating(e.score),hasMarks:e.hasMarks(),marker:e.getMarker(),id:n,text:e.text,markerId:t.length>0?"".concat(t,":").concat(n):n};return"ok"===o.rating&&(o.rating="OK"),o}function i(e,t){switch(e.rating){case"error":t.errorsResults.push(e);break;case"feedback":t.considerationsResults.push(e);break;case"bad":t.problemsResults.push(e);break;case"OK":t.improvementsResults.push(e);break;case"good":t.goodResults.push(e)}return t}function s(e){var t={icon:"seo-score-none",color:o.colors.$color_grey_disabled};switch(e){case"loading":t={icon:"loading-spinner",color:o.colors.$color_green_medium_light};break;case"good":t={icon:"seo-score-good",color:o.colors.$color_green_medium};break;case"ok":t={icon:"seo-score-ok",color:o.colors.$color_ok};break;case"bad":t={icon:"seo-score-bad",color:o.colors.$color_red}}return t}function c(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n={errorsResults:[],problemsResults:[],improvementsResults:[],goodResults:[],considerationsResults:[]};if(!e)return n;for(var r=0;r "+c);if("componentClose"===d.type)throw new Error("Missing opening component token: `"+d.value+"`");if("componentOpen"===d.type){i=n[d.value],l=p;break}b.push(n[d.value])}else b.push(d.value);return i&&(u=function(e,t){var n,r,o=t[e],a=0;for(r=e+1;r1&&void 0!==arguments[1]?arguments[1]:"_";return e.replace(/\s/g,t)}function g(e){return{name:"cf_"+y(e),label:c(e+" (custom field)")}}function O(e){var t=y(e);return{name:"ct_"+t,label:c(e+" (custom taxonomy)"),descriptionName:"ct_desc_"+t,descriptionLabel:c(e+" description (custom taxonomy)")}}function v(e,t){return e.custom_taxonomies?(Object(a.forEach)(e.custom_taxonomies,(function(e,n){var r=O(n),o=r.name,a=r.label,i=r.descriptionName,c=r.descriptionLabel;t.dispatch(Object(s.l)(o,e.name,a)),t.dispatch(Object(s.l)(i,e.description,c))})),Object(a.omit)(u({},e),"custom_taxonomies")):e}function E(e,t){return e.custom_fields?(Object(a.forEach)(e.custom_fields,(function(e,n){var r=g(n),o=r.name,a=r.label;t.dispatch(Object(s.l)(o,e,a))})),Object(a.omit)(u({},e),"custom_fields")):e}function j(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:156;return(e=(e=Object(i.stripTags)(e)).trim()).length<=t?e:(e=e.substring(0,t)).substring(0,e.lastIndexOf(" "))}var w=function(e){var t=Object(a.get)(window,["YoastSEO","app","pluggable"],!1);if(!t||!Object(a.get)(window,["YoastSEO","app","pluggable","loaded"],!1))return function(e){var t=Object(a.get)(window,["YoastSEO","wp","replaceVarsPlugin","replaceVariables"],a.identity);return{url:e.url,title:d(t(e.title)),description:d(t(e.description))}}(e);var n=t._applyModifications.bind(t);return{url:e.url,title:d(n("data_page_title",e.title)),description:d(n("data_meta_desc",e.description))}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return r})),n.d(t,"g",(function(){return o})),n.d(t,"e",(function(){return a})),n.d(t,"f",(function(){return i})),n.d(t,"b",(function(){return s})),n.d(t,"c",(function(){return c})),n.d(t,"d",(function(){return l})),n.d(t,"j",(function(){return u})),n.d(t,"m",(function(){return d})),n.d(t,"l",(function(){return p})),n.d(t,"n",(function(){return f})),n.d(t,"h",(function(){return m})),n.d(t,"k",(function(){return b})),n.d(t,"i",(function(){return h}));var r="CHANGE_COUNTRY",o="SET_REQUEST_SUCCEEDED",a="SET_REQUEST_FAILED",i="SET_LIMIT_REACHED",s="NEW_REQUEST",c="NO_DATA_FOUND",l="SET_LOGIN_STATUS";function u(e,t){return{type:s,countryCode:e,keyphrase:t}}function d(e){return{type:o,response:e}}function p(e){return{type:a,response:e}}function f(){return{type:i}}function m(e){return{type:r,countryCode:e}}function b(){return{type:c}}function h(e){return{type:l,loginStatus:e}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return i}));var r=n(3),o=n(23),a=n(2);function i(e){return Object(a.isNil)(e)||(e/=10),function(e){switch(e){case"feedback":return{className:"na",screenReaderText:Object(r.__)("Feedback","wordpress-seo"),screenReaderReadabilityText:""};case"bad":return{className:"bad",screenReaderText:Object(r.__)("Needs improvement","wordpress-seo"),screenReaderReadabilityText:Object(r.__)("Needs improvement","wordpress-seo")};case"ok":return{className:"ok",screenReaderText:Object(r.__)("OK SEO score","wordpress-seo"),screenReaderReadabilityText:Object(r.__)("OK","wordpress-seo")};case"good":return{className:"good",screenReaderText:Object(r.__)("Good SEO score","wordpress-seo"),screenReaderReadabilityText:Object(r.__)("Good","wordpress-seo")};default:return{className:"loading",screenReaderText:"",screenReaderReadabilityText:""}}}(o.interpreters.scoreToRating(e))}},function(e,t,n){"use strict";n.d(t,"b",(function(){return r})),n.d(t,"a",(function(){return o})),n.d(t,"d",(function(){return a})),n.d(t,"c",(function(){return i}));var r="SET_SETTINGS",o="SET_CONTENT_IMAGE",a=function(e){return{type:r,settings:e}},i=function(e){return{type:o,src:e}}},function(e,t,n){"use strict";n.d(t,"f",(function(){return c})),n.d(t,"e",(function(){return l})),n.d(t,"b",(function(){return u})),n.d(t,"c",(function(){return d})),n.d(t,"d",(function(){return p})),n.d(t,"a",(function(){return f})),n.d(t,"l",(function(){return m})),n.d(t,"k",(function(){return b})),n.d(t,"h",(function(){return h})),n.d(t,"i",(function(){return y})),n.d(t,"j",(function(){return g})),n.d(t,"g",(function(){return O}));var r=n(5),o=n.n(r),a=n(7),i=n.n(a),s=function(){function e(){o()(this,e)}return i()(e,null,[{key:"noIndexElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_meta-robots-noindex":"hidden_wpseo_noindex")}},{key:"noFollowElement",get:function(){return document.getElementById("yoast_wpseo_meta-robots-nofollow")}},{key:"advancedElement",get:function(){return document.getElementById("yoast_wpseo_meta-robots-adv")}},{key:"breadcrumbsTitleElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_bctitle":"hidden_wpseo_bctitle")}},{key:"canonicalElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_canonical":"hidden_wpseo_canonical")}},{key:"noIndex",get:function(){return e.noIndexElement&&e.noIndexElement.value||""},set:function(t){e.noIndexElement.value=t}},{key:"noFollow",get:function(){return e.noFollowElement&&e.noFollowElement.value||""},set:function(t){e.noFollowElement.value=t}},{key:"advanced",get:function(){return e.advancedElement&&e.advancedElement.value||""},set:function(t){e.advancedElement.value=t}},{key:"breadcrumbsTitle",get:function(){return e.breadcrumbsTitleElement&&e.breadcrumbsTitleElement.value||""},set:function(t){e.breadcrumbsTitleElement.value=t}},{key:"canonical",get:function(){return e.canonicalElement&&e.canonicalElement.value||""},set:function(t){e.canonicalElement.value=t}}]),e}(),c="SET_NO_INDEX",l="SET_NO_FOLLOW",u="SET_ADVANCED",d="SET_BREADCRUMBS_TITLE",p="SET_CANONICAL_URL",f="LOAD_ADVANCED_SETTINGS",m=function(e){return s.noIndex=e,{type:c,value:e}},b=function(e){return s.noFollow=e,{type:l,value:e}},h=function(e){return s.advanced=e.join(","),{type:u,value:e}},y=function(e){return s.breadcrumbsTitle=e,{type:d,value:e}},g=function(e){return s.canonical=e,{type:p,value:e}},O=function(){return{type:f,settings:{noIndex:s.noIndex,noFollow:s.noFollow,advanced:s.advanced.split(","),breadcrumbsTitle:s.breadcrumbsTitle,canonical:s.canonical,isLoading:!1}}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return r})),n.d(t,"b",(function(){return o}));var r="WPSEO_SET_MARKER_STATUS",o=function(e){return{type:r,marksButtonStatus:e}}},function(e,t,n){var r=n(102);e.exports=function(e,t){if(null==e)return{};var n,o,a=r(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}},function(e,t){function n(e,t,n,r,o,a,i){try{var s=e[a](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,o)}e.exports=function(e){return function(){var t=this,r=arguments;return new Promise((function(o,a){var i=e.apply(t,r);function s(e){n(i,o,a,s,c,"next",e)}function c(e){n(i,o,a,s,c,"throw",e)}s(void 0)}))}}},function(e,t,n){"use strict";n.d(t,"e",(function(){return l})),n.d(t,"c",(function(){return u})),n.d(t,"d",(function(){return d})),n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return f})),n.d(t,"j",(function(){return m})),n.d(t,"h",(function(){return b})),n.d(t,"i",(function(){return h})),n.d(t,"f",(function(){return y})),n.d(t,"g",(function(){return g}));var r=n(4),o=n(5),a=n.n(o),i=n(7),s=n.n(i),c=function(){function e(){a()(this,e)}return s()(e,null,[{key:"titleElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_twitter-title":"hidden_wpseo_twitter-title")}},{key:"descriptionElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_twitter-description":"hidden_wpseo_twitter-description")}},{key:"imageIdElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_twitter-image-id":"hidden_wpseo_twitter-image-id")}},{key:"imageUrlElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_twitter-image":"hidden_wpseo_twitter-image")}},{key:"title",get:function(){return e.titleElement.value},set:function(t){e.titleElement.value=t}},{key:"description",get:function(){return e.descriptionElement.value},set:function(t){e.descriptionElement.value=t}},{key:"imageId",get:function(){return e.imageIdElement.value},set:function(t){e.imageIdElement.value=t}},{key:"imageUrl",get:function(){return e.imageUrlElement.value},set:function(t){e.imageUrlElement.value=t}}]),e}(),l="SET_TWITTER_TITLE",u="SET_TWITTER_DESCRIPTION",d="SET_TWITTER_IMAGE",p="CLEAR_TWITTER_IMAGE",f="LOAD_TWITTER_PREVIEW",m=function(e){return e.trim()===Object(r.select)("yoast-seo/editor").getSocialTitleTemplate().trim()?c.title="":c.title=e,{type:l,title:e}},b=function(e){return e.trim()===Object(r.select)("yoast-seo/editor").getSocialDescriptionTemplate().trim()?c.description="":c.description=e,{type:u,description:e}},h=function(e){return c.imageId=e.id,c.imageUrl=e.url,{type:d,image:e}},y=function(){return c.imageId="",c.imageUrl="",{type:p}},g=function(){var e=Object(r.select)("yoast-seo/editor"),t=e.getSocialDescriptionTemplate,n=e.getSocialTitleTemplate;return{type:f,imageId:c.imageId,imageUrl:c.imageUrl,description:c.description||t(),title:c.title||n()}}},function(e,t,n){"use strict";n.d(t,"e",(function(){return l})),n.d(t,"c",(function(){return u})),n.d(t,"d",(function(){return d})),n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return f})),n.d(t,"j",(function(){return m})),n.d(t,"h",(function(){return b})),n.d(t,"i",(function(){return h})),n.d(t,"f",(function(){return y})),n.d(t,"g",(function(){return g}));var r=n(4),o=n(5),a=n.n(o),i=n(7),s=n.n(i),c=function(){function e(){a()(this,e)}return s()(e,null,[{key:"titleElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_opengraph-title":"hidden_wpseo_opengraph-title")}},{key:"descriptionElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_opengraph-description":"hidden_wpseo_opengraph-description")}},{key:"imageIdElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_opengraph-image-id":"hidden_wpseo_opengraph-image-id")}},{key:"imageUrlElement",get:function(){return document.getElementById(window.wpseoScriptData.isPost?"yoast_wpseo_opengraph-image":"hidden_wpseo_opengraph-image")}},{key:"title",get:function(){return e.titleElement.value},set:function(t){e.titleElement.value=t}},{key:"description",get:function(){return e.descriptionElement.value},set:function(t){e.descriptionElement.value=t}},{key:"imageId",get:function(){return e.imageIdElement.value},set:function(t){e.imageIdElement.value=t}},{key:"imageUrl",get:function(){return e.imageUrlElement.value},set:function(t){e.imageUrlElement.value=t}}]),e}(),l="SET_FACEBOOK_TITLE",u="SET_FACEBOOK_DESCRIPTION",d="SET_FACEBOOK_IMAGE",p="CLEAR_FACEBOOK_IMAGE",f="LOAD_FACEBOOK_PREVIEW",m=function(e){return e.trim()===Object(r.select)("yoast-seo/editor").getSocialTitleTemplate().trim()?c.title="":c.title=e,{type:l,title:e}},b=function(e){return e.trim()===Object(r.select)("yoast-seo/editor").getSocialDescriptionTemplate().trim()?c.description="":c.description=e,{type:u,description:e}},h=function(e){return c.imageUrl=e.url,c.imageId=e.id,{type:d,image:e}},y=function(){return c.imageId="",c.imageUrl="",{type:p}},g=function(){var e=Object(r.select)("yoast-seo/editor"),t=e.getSocialDescriptionTemplate,n=e.getSocialTitleTemplate;return{type:f,imageId:c.imageId,imageUrl:c.imageUrl,description:c.description||t(),title:c.title||n()}}},function(e,t,n){"use strict";var r=n(39),o=n.n(r),a=n(0),i=n(6),s=n(1),c=n.n(s),l=function(e){var t=Object(a.useState)(!1),n=o()(t,2),r=n[0],s=n[1],c=e.prefixIcon;return Object(a.createElement)("div",{className:"yoast components-panel__body ".concat(r?"is-opened":"")},Object(a.createElement)("h2",{className:"components-panel__body-title"},Object(a.createElement)("button",{onClick:function(){s(!r)},className:"components-button components-panel__body-toggle"},Object(a.createElement)("span",{className:"yoast-icon-span",style:{fill:"".concat(c&&c.color||"")}},c&&Object(a.createElement)(i.SvgIcon,{icon:c.icon,color:c.color,size:c.size})),Object(a.createElement)("span",{className:"yoast-title-container"},Object(a.createElement)("div",{className:"yoast-title"},e.title),Object(a.createElement)("div",{className:"yoast-subtitle"},e.subTitle)),Object(a.createElement)("span",{className:"yoast-chevron","aria-hidden":"true"}))),r&&e.children)};t.a=l,l.propTypes={title:c.a.string.isRequired,children:c.a.oneOfType([c.a.node,c.a.arrayOf(c.a.node)]).isRequired,prefixIcon:c.a.object,subTitle:c.a.string},l.defaultProps={prefixIcon:null,subTitle:""}},function(e,t,n){"use strict";var r,o=n(27),a=n.n(o),i=n(15),s=n.n(i),c=n(0),l=n(6),u=n(12),d=n.n(u)()(l.Collapsible)(r||(r=s()(['\n\th2 > button {\n\t\tpadding-left: 24px;\n\t\tpadding-top: 16px;\n\n\t\t&:hover {\n\t\t\tbackground-color: #f0f0f0;\n\t\t}\n\t}\n\n\tdiv[class^="collapsible_content"] {\n\t\tpadding: 24px 0;\n\t\tmargin: 0 24px;\n\t\tborder-top: 1px solid rgba(0,0,0,0.2);\n\t}\n\n'])));t.a=function(e){return Object(c.createElement)(d,a()({hasPadding:!0,hasSeparator:!0},e))}},function(e,t){e.exports=window.wp.url},function(e,t,n){"use strict";n.d(t,"b",(function(){return d}));var r=n(27),o=n.n(r),a=n(46),i=n.n(a),s=n(0),c=n(1),l=n.n(c),u=n(18),d="yoast yoast-gutenberg-modal",p=function(e){var t=e.title,n=e.className,r=e.showYoastIcon,a=e.additionalClassName,c=i()(e,["title","className","showYoastIcon","additionalClassName"]),l=r?Object(s.createElement)("span",{className:"yoast-icon"}):null;return Object(s.createElement)(u.Modal,o()({title:t,className:"".concat(n," ").concat(a),icon:l},c),e.children)};p.propTypes={title:l.a.string,className:l.a.string,showYoastIcon:l.a.bool,children:l.a.oneOfType([l.a.node,l.a.arrayOf(l.a.node)]),additionalClassName:l.a.string},p.defaultProps={title:"Yoast SEO",className:d,showYoastIcon:!0,children:null,additionalClassName:""},t.a=p},function(e,t,n){"use strict";var r,o=n(15),a=n.n(o),i=n(24),s=n(9),c=n(12),l=n.n(c),u=Object(s.makeOutboundLink)(l.a.a(r||(r=a()(["\n\tdisplay: inline-block;\n\tposition: relative;\n\toutline: none;\n\ttext-decoration: none;\n\tborder-radius: 100%;\n\twidth: 24px;\n\theight: 24px;\n\tmargin: -4px 0;\n\tvertical-align: middle;\n\n\tcolor: ",";\n\t\n\t&:hover,\n\t&:focus {\n\t\tcolor: ",";\t\n\t}\n\t\n\t// Overwrite the default blue active color for links.\n\t&:active {\n\t\tcolor: ",';\t\n\t}\n\n\t&::before {\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\tpadding: 2px;\n\t\tcontent: "\f223";\n\t}\n'],["\n\tdisplay: inline-block;\n\tposition: relative;\n\toutline: none;\n\ttext-decoration: none;\n\tborder-radius: 100%;\n\twidth: 24px;\n\theight: 24px;\n\tmargin: -4px 0;\n\tvertical-align: middle;\n\n\tcolor: ",";\n\t\n\t&:hover,\n\t&:focus {\n\t\tcolor: ",";\t\n\t}\n\t\n\t// Overwrite the default blue active color for links.\n\t&:active {\n\t\tcolor: ",';\t\n\t}\n\n\t&::before {\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\tpadding: 2px;\n\t\tcontent: "\\f223";\n\t}\n'])),i.colors.$color_help_text,i.colors.$color_snippet_focus,i.colors.$color_help_text));t.a=u},,function(e,t,n){"use strict";n.d(t,"d",(function(){return o})),n.d(t,"c",(function(){return a})),n.d(t,"b",(function(){return i})),n.d(t,"a",(function(){return s})),n.d(t,"h",(function(){return c})),n.d(t,"g",(function(){return l})),n.d(t,"f",(function(){return u})),n.d(t,"e",(function(){return d}));var r=n(33),o="SET_PAGE_TYPE",a="SET_ARTICLE_TYPE",i="GET_SCHEMA_PAGE_DATA",s="GET_SCHEMA_ARTICLE_DATA",c=function(e){return r.a.pageType=e,{type:o,pageType:e}},l=function(e){return r.a.articleType=e,{type:a,articleType:e}},u=function(){return{type:i,pageType:r.a.pageType,defaultPageType:r.a.defaultPageType}},d=function(){return{type:s,articleType:r.a.articleType,defaultArticleType:r.a.defaultArticleType}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return u}));var r=n(10),o=n.n(r),a=n(19),i=n(0),s=n(28);function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t0?"".concat(this.props.keywordKey,":").concat(e):e;n===this.props.activeMarker?(this.props.setActiveMarker(null),this.props.setMarkerPauseStatus(!1),this.removeMarkers()):(this.props.setActiveMarker(n),t())}},{key:"removeMarkers",value:function(){window.YoastSEO.analysis.applyMarks(new E.Paper("",{}),[])}},{key:"render",value:function(){var e=this.state.mappedResults,t=e.errorsResults,n=e.improvementsResults,r=e.goodResults,o=e.considerationsResults,a=e.problemsResults;return Object(y.createElement)(y.Fragment,null,Object(y.createElement)(v.ContentAnalysis,{errorsResults:t,problemsResults:a,improvementsResults:n,considerationsResults:o,goodResults:r,activeMarker:this.props.activeMarker,onMarkButtonClick:this.handleMarkButtonClick,marksButtonClassName:this.props.marksButtonClassName,marksButtonStatus:this.props.marksButtonStatus,headingLevel:3,keywordKey:this.props.keywordKey}))}}]),o}(y.Component);w.propTypes={results:O.a.array,marksButtonClassName:O.a.string,marksButtonStatus:O.a.string,setActiveMarker:O.a.func.isRequired,setMarkerPauseStatus:O.a.func.isRequired,activeMarker:O.a.string,keywordKey:O.a.string},w.defaultProps={results:null,marksButtonStatus:"enabled",marksButtonClassName:"",activeMarker:null,keywordKey:""};var _=w;t.a=Object(o.compose)([Object(r.withSelect)((function(e){return{activeMarker:(0,e("yoast-seo/editor").getActiveMarker)()}})),Object(r.withDispatch)((function(e){var t=e("yoast-seo/editor");return{setActiveMarker:t.setActiveMarker,setMarkerPauseStatus:t.setMarkerPauseStatus}}))])(_)},,function(e,t){e.exports=window.yoast.featureFlag},function(e,t,n){"use strict";var r=n(19),o=n(4),a=n(92);t.a=Object(r.compose)([Object(o.withSelect)((function(e,t){var n=e("yoast-seo/editor"),r=n.getPostOrPageString,o=n.getIsModalOpen;return{postTypeName:r(),isOpen:o(t.id)}})),Object(o.withDispatch)((function(e,t){var n=e("yoast-seo/editor"),r=n.openEditorModal;return{open:function(){return r(t.id)},close:n.closeEditorModal}}))])(a.a)},function(e,t,n){"use strict";n.d(t,"b",(function(){return _}));var r=n(10),o=n.n(r),a=n(5),i=n.n(a),s=n(7),c=n.n(s),l=n(11),u=n.n(l),d=n(13),p=n.n(d),f=n(14),m=n.n(f),b=n(8),h=n.n(b),y=n(0),g=n(3),O=n(6),v=n(1),E=n.n(v),j=n(62);var w=function(e){p()(a,e);var t,n,r=(t=a,n=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}(),function(){var e,r=h()(t);if(n){var o=h()(this).constructor;e=Reflect.construct(r,arguments,o)}else e=r.apply(this,arguments);return m()(this,e)});function a(e){var t;return i()(this,a),(t=r.call(this,e)).initialPageType=e.pageType.value,t.initialArticleType=e.articleType?e.articleType.value:"None",t.state={schema_page_type:t.initialPageType,schema_article_type:t.initialArticleType},t.handleOptionFocus=t.handleOptionFocus.bind(u()(t)),t}return c()(a,[{key:"shouldShowAlert",value:function(){return this.state.schema_page_type!==this.initialPageType||this.state.schema_article_type!==this.initialArticleType}},{key:"handleOptionFocus",value:function(e,t){this.setState(o()({},e,t))}},{key:"render",value:function(){return Object(y.createElement)(y.Fragment,null,Object(y.createElement)(O.FieldGroup,{label:Object(g.__)("Schema settings","wordpress-seo"),linkTo:"https://yoa.st/404",linkText:Object(g.__)("Learn more about the schema settings","wordpress-seo"),description:Object(g.sprintf)( +/* translators: %1$s expands to an indexable object's name, e.g. Posts or Pages. */ +Object(g.__)("Choose how your %1$s should be described by default in your site's schema.org markup. You can change these settings for individual %1$s.","wordpress-seo"),this.props.postTypeName)}),this.shouldShowAlert()&&Object(y.createElement)(O.Alert,{type:"warning"},Object(g.sprintf)( +/* translators: %1$s expands to an indexable object's name, e.g. Posts or Pages. */ +Object(g._n)("Upon saving, this setting will apply to all of your %1$s. %1$s that are manually configured will be left untouched.","Upon saving, these settings will apply to all of your %1$s. %1$s that are manually configured will be left untouched.",this.props.articleType?2:1,"wordpress-seo"),this.props.postTypeName)),Object(y.createElement)(O.Select,{id:"schema-page-type-".concat(this.props.postType),name:"schema_page_type",options:this.props.pageTypeOptions,label:Object(g.__)("Default Page type","wordpress-seo"),onChange:this.props.pageType.onChange,selected:this.props.pageType.value,onOptionFocus:this.handleOptionFocus}),this.props.articleType&&Object(y.createElement)(O.Select,{id:"schema-article-type-".concat(this.props.postType),name:"schema_article_type",options:this.props.articleTypeOptions,label:Object(g.__)("Default Article type","wordpress-seo"),onChange:this.props.articleType.onChange,onOptionFocus:this.handleOptionFocus,selected:this.props.articleType.value}))}}]),a}(y.Component),_=E.a.arrayOf(E.a.shape({name:E.a.string,value:E.a.string}));w.propTypes={postType:E.a.string.isRequired,postTypeName:E.a.string.isRequired,pageType:j.b.isRequired,articleType:j.b,pageTypeOptions:_.isRequired,articleTypeOptions:_.isRequired},w.defaultProps={articleType:null},t.a=Object(j.a)((function(e){return[{name:"pageType",fieldId:e.pageTypeFieldId},{name:"articleType",fieldId:e.articleTypeFieldId}]}))(w)},,function(e,t){e.exports=function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t=0||(o[n]=e[n]);return o}},function(e,t,n){"use strict";var r=n(0),o=n(1),a=n.n(o),i=n(12),s=n(28),c=function(e){var t=e.theme,n=e.location,o=e.children;return Object(r.createElement)(s.LocationProvider,{value:n},Object(r.createElement)(i.ThemeProvider,{theme:t},o))};c.propTypes={theme:a.a.object.isRequired,location:a.a.oneOf(["sidebar","metabox","modal"]).isRequired,children:a.a.element.isRequired},t.a=c},,,,,function(e,t,n){"use strict";n.d(t,"b",(function(){return h})),n.d(t,"a",(function(){return v})),n.d(t,"c",(function(){return E}));var r=n(10),o=n.n(r),a=n(2),i=(n(179),n(66)),s=n(4);function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t]+)>)/gi,""),r=t.getMarked().replace(/(<(?!\/?yoastmark)[^>]+>)/gi,""),o=function(e,t){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],r=[];if(0===e.length)return r;var o,a=0;for(n||(t=t.toLowerCase(),e=e.toLowerCase());(o=e.indexOf(t,a))>-1;)r.push(o),a=o+t.length;return r}(e,n);if(0===o.length)return[];var a=function(e){for(var t=e.indexOf(u),n=null,r=[];t>=0;){if((n=(e=e.replace(u,"")).indexOf(""))",""),r.push({startOffset:t,endOffset:n}),t=e.indexOf(u),n=null}return r}(r),i=[];return a.forEach((function(e){o.forEach((function(r){var o=r+e.startOffset,a=r+e.endOffset;0===e.startOffset&&e.endOffset===t.getOriginal().length&&(a=r+n.length),i.push({startOffset:o,endOffset:a})}))})),i}(c,e);return n?n.map((function(e){return l(l({},e),{},{block:t.clientId,richTextIdentifier:r})})):[]}))}function O(e){d=e.map((function(e){return{blockClientId:e.block,source:"yoast",richTextIdentifier:e.richTextIdentifier,range:{start:e.startOffset,end:e.endOffset}}}))}function v(e,t){if(d=[],Object(s.dispatch)("core/annotations").__experimentalRemoveAnnotationsBySource("yoast"),0!==t.length){var n=Object(s.select)("core/block-editor").getBlocks();O(Object(a.flatMap)(n,(function(e){return Object(a.flatMap)(y(e.name),(function(n){return g(n,e,t)}))}))),b()}}function E(){var e=Object(s.select)("core/editor").getSelectedBlock(),t=Object(s.select)("yoast-seo/editor").getActiveMarker();if(e&&t){var n;n=e.clientId,Object(s.select)("core/annotations").__experimentalGetAnnotations().filter((function(e){return e.blockClientId===n&&"yoast"===e.source})).forEach((function(e){Object(s.dispatch)("core/annotations").__experimentalRemoveAnnotation(e.id)}));var r=Object(s.select)("yoast-seo/editor").getResultById(t);if(void 0!==r){var o=r.marks;O(Object(a.flatMap)(y(e.name),(function(t){return g(t,e,o)}))),b()}}}},,,function(e,t,n){"use strict";n.d(t,"a",(function(){return s}));var r,o,a=n(16);function i(){return(i=Object.assign||function(e){for(var t=1;t=4}(h)&&Object(a.createElement)(Q,null),Object(a.createElement)(M,{countryCode:u,setCountry:s,newRequest:o,keyphrase:r,setRequestFailed:f,setNoResultsFound:b,setRequestSucceeded:y,setRequestLimitReached:g,response:t,lastRequestKeyphrase:n})),function(e){var t=e.isPending,n=e.requestLimitReached,r=e.isSuccess,o=e.response,s=e.requestHasData;return t?Object(a.createElement)(d,null):n?Object(a.createElement)(m,null):!r&&function(e){return!Object(l.isEmpty)(e)&&"error"in e}(o)?Object(a.createElement)(Z,null):s?void 0:Object(a.createElement)("p",null,Object(i.__)("Sorry, there's no data available for that keyphrase/country combination.","wordpress-seo"))}(e),Object(a.createElement)(Y,{keyphrase:r,relatedKeyphrases:h,countryCode:u,renderAction:c,data:t}))}J.propTypes={keyphrase:c.a.string,relatedKeyphrases:c.a.array,renderAction:c.a.func,requestLimitReached:c.a.bool,countryCode:c.a.string.isRequired,setCountry:c.a.func.isRequired,newRequest:c.a.func.isRequired,setRequestSucceeded:c.a.func.isRequired,setRequestLimitReached:c.a.func.isRequired,setRequestFailed:c.a.func.isRequired,setNoResultsFound:c.a.func.isRequired,response:c.a.object,lastRequestKeyphrase:c.a.string},J.defaultProps={keyphrase:"",relatedKeyphrases:[],renderAction:null,requestLimitReached:!1,response:{},lastRequestKeyphrase:""},t.a=Object(o.compose)([Object(r.withSelect)((function(e){var t=e("yoast-seo/editor"),n=t.getFocusKeyphrase,r=t.getSEMrushSelectedCountry,o=t.getSEMrushRequestLimitReached,a=t.getSEMrushRequestResponse,i=t.getSEMrushRequestIsSuccess,s=t.getSEMrushIsRequestPending,c=t.getSEMrushRequestHasData,l=t.getSEMrushRequestKeyphrase;return{keyphrase:n(),countryCode:r(),requestLimitReached:o(),response:a(),isSuccess:i(),isPending:s(),requestHasData:c(),lastRequestKeyphrase:l()}})),Object(r.withDispatch)((function(e){var t=e("yoast-seo/editor"),n=t.setSEMrushChangeCountry,r=t.setSEMrushNewRequest,o=t.setSEMrushRequestSucceeded,a=t.setSEMrushRequestFailed,i=t.setSEMrushSetRequestLimitReached,s=t.setSEMrushNoResultsFound;return{setCountry:function(e){n(e)},newRequest:function(e,t){r(e,t)},setRequestSucceeded:function(e){o(e)},setRequestFailed:function(e){a(e)},setRequestLimitReached:function(){i()},setNoResultsFound:function(){s()}}}))])(J)},,function(e,t){e.exports=window.wp.blocks},,,function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=n(2);function o(e){return void 0===e.length?e:Object(r.flatten)(e).sort((function(e,t){return void 0===e.props.renderPriority?1:e.props.renderPriority-t.props.renderPriority}))}},,function(e,t,n){"use strict";var r,o,a,i=n(10),s=n.n(i),c=n(5),l=n.n(c),u=n(7),d=n.n(u),p=n(13),f=n.n(p),m=n(14),b=n.n(m),h=n(8),y=n.n(h),g=n(15),O=n.n(g),v=n(0),E=n(4),j=n(3),w=n(6),_=n(24),T=n(1),k=n.n(T),S=n(12),R=n.n(S),P=n(42),A=n(81),C=n(9),x=R.a.p(r||(r=O()(["\n\tcolor: ",";\n\tmargin: 0;\n\tpadding-right: 8px;\n"])),_.colors.$color_upsell_text),I=R.a.div(o||(o=O()(["\n\tfont-size: 1em;\n\tdisplay: flex;\n\tflex-direction: ",";\n\t",": 4px solid ",";\n\tmargin: 16px 0;\n\tpadding: 0 0 0 8px;\n\tmax-width: 600px;\n\n\t> "," {\n\t\tmargin-bottom: ",";\n\t}\n"])),(function(e){return"horizontal"===e.alignment?"row":"column"}),Object(C.getDirectionalStyle)("border-left","border-right"),_.colors.$color_pink_dark,x,(function(e){return"vertical"===e.alignment&&"16px"})),D=R()(w.SvgIcon)(a||(a=O()(["\n\tmargin: ",";\n\ttransform: ",";\n"])),Object(C.getDirectionalStyle)("0 0 0 4px","0 4px 0 0"),Object(C.getDirectionalStyle)("rotate(0deg)","rotate(180deg)")),N=Object(C.makeOutboundLink)(w.UpsellLinkButton),L=function(e){var t=e.alignment,n=e.url;return Object(v.createElement)(I,{alignment:t},Object(v.createElement)(x,null,Object(j.sprintf)( +/* translators: %s expands to Yoast SEO Premium */ +Object(j.__)("Did you know %s also analyzes the different word forms of your keyphrase, like plurals and past tenses?","wordpress-seo"),"Yoast SEO Premium")),Object(v.createElement)("div",null,Object(v.createElement)(N,{href:n,className:"UpsellLinkButton"},Object(j.sprintf)( +/* translators: %s expands to Premium */ +Object(j.__)("Go %s!","wordpress-seo"),"Premium"),Object(v.createElement)(D,{icon:"arrow-right",size:"8px",color:_.colors.$color_black}))))};L.propTypes={alignment:k.a.oneOf(["horizontal","vertical"]),url:k.a.string.isRequired},L.defaultProps={alignment:"vertical"};var M,F,q=L,B=n(28),U=n(51),K=n(68),H=n(37),W=n.n(H);var G=R.a.ul(M||(M=O()(['\n\tlist-style: none;\n\tmargin: 0 0 16px;\n\tpadding: 0;\n\n\tli {\n\t\tmargin: 5px 0 0 0;\n\t\tpadding-left: 16px;\n\t}\n\n\tspan[aria-hidden="true"]:before {\n\t\tmargin: 0 8px 0 -16px;\n\t\tfont-weight: bold;\n\t\tcontent: "+";\n\t}\n']))),V=R.a.small(F||(F=O()(["\n\tdisplay: block;\n"]))),Y=Object(C.makeOutboundLink)(),$=function(e){f()(o,e);var t,n,r=(t=o,n=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}(),function(){var e,r=y()(t);if(n){var o=y()(this).constructor;e=Reflect.construct(r,arguments,o)}else e=r.apply(this,arguments);return b()(this,e)});function o(e){return l()(this,o),r.call(this,e)}return d()(o,[{key:"createBenefitsList",value:function(e){return e.length>0&&Object(v.createElement)(G,{role:"list"},e.map((function(e,t){return Object(v.createElement)("li",{key:t},Object(v.createElement)("span",{"aria-hidden":"true"}),W()({mixedString:e.replace("","{{strong}}").replace("","{{/strong}}"),components:{strong:Object(v.createElement)("strong",null)}}))})))}},{key:"createInfoParagraphs",value:function(e){return e.map((function(e,t){return Object(v.createElement)("p",{key:t},e)}))}},{key:"render",value:function(){return Object(v.createElement)("div",null,this.createInfoParagraphs(this.props.infoParagraphs),this.createBenefitsList(this.props.benefits),Object(v.createElement)(Y,this.props.upsellButton,this.props.upsellButtonText,this.props.upsellButtonHasCaret&&Object(v.createElement)("span",{"aria-hidden":"true",className:"yoast-button-upsell__caret"})),Object(v.createElement)(V,{id:this.props.upsellButton["aria-describedby"]},this.props.upsellButtonLabel))}}]),o}(v.Component);$.propTypes={benefits:k.a.array,infoParagraphs:k.a.array,upsellButton:k.a.object,upsellButtonText:k.a.string.isRequired,upsellButtonLabel:k.a.string,upsellButtonHasCaret:k.a.bool},$.defaultProps={infoParagraphs:[],benefits:[],upsellButton:{href:"",className:"button button-primary"},upsellButtonLabel:"",upsellButtonHasCaret:!0};var z=$,Z=Object(C.makeOutboundLink)(),Q=function(e){var t=Object(j.sprintf)( +/* translators: %1$s expands to a 'Yoast SEO Premium' text linked to the yoast.com website. */ +Object(j.__)("Great news: you can, with %1$s!","wordpress-seo"),"{{link}}Yoast SEO Premium{{/link}}"),n=W()({mixedString:t,components:{link:Object(v.createElement)(Z,{href:e.link})}}),r=["".concat(Object(j.__)("Rank better with synonyms & related keyphrases","wordpress-seo"),""),Object(j.sprintf)( +/* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */ +Object(j.__)("%1$sNo more dead links%2$s: easy redirect manager","wordpress-seo"),"",""),"".concat(Object(j.__)("Superfast internal linking suggestions","wordpress-seo"),""),Object(j.sprintf)( +/* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */ +Object(j.__)("%1$sSocial media preview%2$s: Facebook & Twitter","wordpress-seo"),"",""),"".concat(Object(j.__)("24/7 email support","wordpress-seo"),""),"".concat(Object(j.__)("No ads!","wordpress-seo"),"")],o=Object(j.sprintf)( +/* translators: %s expands to 'Yoast SEO Premium'. */ +Object(j.__)("Other benefits of %s for you:","wordpress-seo"),"Yoast SEO Premium");return Object(v.createElement)(z,{infoParagraphs:[n,o],benefits:r,upsellButtonText:Object(j.sprintf)( +/* translators: %s expands to 'Yoast SEO Premium'. */ +Object(j.__)("Get %s","wordpress-seo"),"Yoast SEO Premium"),upsellButton:{href:e.buyLink,className:"yoast-button-upsell",rel:null},upsellButtonLabel:Object(j.__)("1 year free support and updates included!","wordpress-seo")})};Q.propTypes={link:k.a.string.isRequired,buyLink:k.a.string.isRequired};var X=Q,J=Object(C.makeOutboundLink)(),ee=function(e){var t=Object(j.sprintf)( +/* translators: %s expands to a 'Yoast SEO Premium' text linked to the yoast.com website. */ +Object(j.__)("Great news: you can, with %s!","wordpress-seo"),"{{link}}Yoast SEO Premium{{/link}}"),n=[Object(j.sprintf)( +/* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */ +Object(j.__)("%1$sNo more dead links%2$s: easy redirect manager","wordpress-seo"),"",""),"".concat(Object(j.__)("Superfast internal linking suggestions","wordpress-seo"),""),Object(j.sprintf)( +/* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */ +Object(j.__)("%1$sSocial media preview%2$s: Facebook & Twitter","wordpress-seo"),"",""),"".concat(Object(j.__)("24/7 email support","wordpress-seo"),""),"".concat(Object(j.__)("No ads!","wordpress-seo"),"")],r=W()({mixedString:t,components:{link:Object(v.createElement)(J,{href:e.link})}}),o=Object(j.sprintf)( +/* translators: %s expands to 'Yoast SEO Premium'. */ +Object(j.__)("Other benefits of %s for you:","wordpress-seo"),"Yoast SEO Premium");return Object(v.createElement)(z,{infoParagraphs:[r,o],benefits:n,upsellButtonText:Object(j.sprintf)( +/* translators: %s expands to 'Yoast SEO Premium'. */ +Object(j.__)("Get %s","wordpress-seo"),"Yoast SEO Premium"),upsellButton:{href:e.buyLink,className:"yoast-button-upsell",rel:null},upsellButtonLabel:Object(j.__)("1 year free support and updates included!","wordpress-seo")})};ee.propTypes={link:k.a.string.isRequired,buyLink:k.a.string.isRequired};var te,ne=ee,re=n(39),oe=n.n(re),ae=n(53),ie=R.a.button(te||(te=O()(["\n\t// Increase specificity to override WP rules.\n\t&& {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t}\n\n\t.yoast-svg-icon {\n\t\tmargin: 1px 7px 0 0;\n\t\tfill: currentColor;\n\t}\n"]))),se={open:Object(j.__)("Open","wordpress-seo"),heading:"",closeIconButton:Object(j.__)("Close","wordpress-seo"),closeButton:""},ce=function(e){var t=Object(v.useState)(!1),n=oe()(t,2),r=n[0],o=n[1],a=Object.assign({},se,e.labels),i=Object(v.useCallback)((function(){return o(!1)}),[]),s=Object(v.useCallback)((function(){return o(!0)}),[]);return Object(v.createElement)(v.Fragment,null,Object(v.createElement)(ie,{type:"button",onClick:s,className:"".concat(e.classes.openButton," yoast-modal__button-open")},e.openButtonIcon&&Object(v.createElement)(w.SvgIcon,{icon:e.openButtonIcon,size:"13px"}),a.open),r&&Object(v.createElement)(ae.a,{onRequestClose:i,className:e.className,title:a.heading},e.children))};ce.propTypes={openButtonIcon:k.a.string,labels:k.a.shape({open:k.a.string,modalAriaLabel:k.a.string.isRequired,heading:k.a.string,closeIconButton:k.a.string,closeButton:k.a.string}).isRequired,classes:k.a.shape({openButton:k.a.string,closeIconButton:k.a.string,closeButton:k.a.string}),className:k.a.string,children:k.a.any.isRequired},ce.defaultProps={className:ae.b,openButtonIcon:"",classes:{}};var le=ce,ue=n(96),de=n(50),pe=n(18);function fe(e){var t=e.location;return Object(v.createElement)(pe.Slot,{name:"yoast-synonyms-".concat(t)})}fe.propTypes={location:k.a.string.isRequired};var me,be=n(35);function he(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function ye(e){for(var t=1;t191&&e.push(Object(E.__)("Your keyphrase is too long. It can be a maximum of 191 characters.","wordpress-seo")),e}},{key:"render",value:function(){var e=this,t=this.validate();return Object(y.createElement)(K.LocationConsumer,null,(function(n){return Object(y.createElement)("div",{style:"sidebar"===n?{borderBottom:"1px solid #f0f0f0"}:{}},Object(y.createElement)(W,{location:n},Object(y.createElement)(k.KeywordInput,{id:"focus-keyword-input-".concat(n),onChange:e.props.onFocusKeywordChange,keyword:e.props.keyword,label:Object(E.__)("Focus keyphrase","wordpress-seo"),helpLink:a.renderHelpLink(),onBlurKeyword:e.props.onBlurKeyword,onFocusKeyword:e.props.onFocusKeyword,hasError:t.length>0,errorMessages:t}),e.props.isSEMrushIntegrationActive&&Object(y.createElement)(U,{location:n,keyphrase:e.props.keyword})),Object(y.createElement)(g.Slot,{name:"YoastAfterKeywordInput".concat(n.charAt(0).toUpperCase()+n.slice(1))}))}))}}],[{key:"renderHelpLink",value:function(){return Object(y.createElement)(H.a,{href:wpseoAdminL10n["shortlinks.focus_keyword_info"],className:"dashicons"},Object(y.createElement)("span",{className:"screen-reader-text"},Object(E.__)("Help on choosing the perfect focus keyphrase","wordpress-seo")))}}]),a}(y.Component);G.propTypes={keyword:w.a.string,onFocusKeywordChange:w.a.func.isRequired,onFocusKeyword:w.a.func.isRequired,onBlurKeyword:w.a.func.isRequired,isSEMrushIntegrationActive:w.a.bool,displayNoKeyphraseMessage:w.a.bool},G.defaultProps={keyword:"",isSEMrushIntegrationActive:!1,displayNoKeyphraseMessage:!1},t.a=Object(O.compose)([Object(v.withSelect)((function(e){var t=e("yoast-seo/editor"),n=t.getFocusKeyphrase,r=t.getSEMrushNoKeyphraseMessage;return{keyword:n(),displayNoKeyphraseMessage:r()}})),Object(v.withDispatch)((function(e){var t=e("yoast-seo/editor"),n=t.setFocusKeyword,r=t.setMarkerPauseStatus;return{onFocusKeywordChange:n,onFocusKeyword:function(){return r(!0)},onBlurKeyword:function(){return r(!1)}}}))])(G)},function(e,t,n){"use strict";var r,o,a,i=n(10),s=n.n(i),c=n(5),l=n.n(c),u=n(7),d=n.n(u),p=n(13),f=n.n(p),m=n(14),b=n.n(m),h=n(8),y=n.n(h),g=n(15),O=n.n(g),v=n(0),E=n(4),j=n(1),w=n.n(j),_=n(12),T=n.n(_),k=n(3),S=n(2),R=n(96),P=n(81),A=n(50),C=n(42),x=n(35),I=n(28),D=n(54),N=n(36);function L(e){var t=e.target,n=e.children;return Object(v.createElement)(N.a,{target:t},n)}function M(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function F(e){for(var t=1;t/g;function b(e,t,n,r,o){return{element:e,tokenStart:t,tokenLength:n,prevOffset:r,leadingTextStart:o,children:[]}}function h(){var e=r.length-o;0!==e&&a.push(r.substr(o,e))}function y(e){var t=e.element,n=e.tokenStart,o=e.tokenLength,a=e.prevOffset,s=e.children,c=i[i.length-1],l=r.substr(c.prevOffset,n-c.prevOffset);l&&c.children.push(l),c.children.push(f.cloneElement.apply(void 0,[t,null].concat(u()(s)))),c.prevOffset=a||n+o}function g(e){var t=function(){var e=m.exec(r);if(null===e)return["no-more-tokens"];var t=e.index,n=p()(e,4),o=n[0],a=n[1],i=n[2],s=n[3],c=o.length;return s?["self-closed",i,t,c]:a?["closer",i,t,c]:["opener",i,t,c]}(),n=p()(t,4),s=n[0],c=n[1],l=n[2],d=n[3],g=i.length,O=l>o?o:null;if(!e[c])return h(),!1;switch(s){case"no-more-tokens":if(0!==g){var v=i.pop(),E=v.leadingTextStart,j=v.tokenStart;a.push(r.substr(E,j))}return h(),!1;case"self-closed":return 0===g?(null!==O&&a.push(r.substr(O,l-O)),a.push(e[c]),o=l+d,!0):(y(b(e[c],l,d)),o=l+d,!0);case"opener":return i.push(b(e[c],l,d,l+d,O)),o=l+d,!0;case"closer":if(1===g)return function(e){var t=i.pop(),n=t.element,o=t.leadingTextStart,s=t.prevOffset,c=t.tokenStart,l=t.children,d=e?r.substr(s,e-s):r.substr(s);d&&l.push(d),null!==o&&a.push(r.substr(o,c-o)),a.push(f.cloneElement.apply(void 0,[n,null].concat(u()(l))))}(l),o=l+d,!0;var w=i.pop(),_=r.substr(w.prevOffset,l-w.prevOffset);w.children.push(_),w.prevOffset=l+d;var T=b(w.element,w.tokenStart,w.tokenLength,l+d);return T.children=w.children,y(T),o=l+d,!0;default:return h(),!1}}t.a=function(e,t){if(r=e,o=0,a=[],i=[],m.lastIndex=0,!function(e){var t="object"===c()(e),n=t&&Object.values(e);return t&&n.length&&n.every((function(e){return Object(f.isValidElement)(e)}))}(t))throw new TypeError("The conversionMap provided is not valid. It must be an object with values that are WPElements");do{}while(g(t));return f.createElement.apply(void 0,[f.Fragment,null].concat(u()(a)))}},,,function(e,t){e.exports=window.wp.annotations},,,,,,,,,,,,,function(e,t,n){"use strict";n.d(t,"a",(function(){return x}));var r=n(0),o=n(1),a=n.n(o),i=n(18),s=n(120),c=n(103);function l(e){var t=e.theme;return Object(r.createElement)(c.a,{theme:t,location:"metabox"},Object(r.createElement)(i.Slot,{name:"YoastMetabox"},(function(e){return Object(s.a)(e)})))}var u=n(4),d=n(3),p=n(124),f=n(161),m=n(160),b=n(125),h=n(126),y=n(122),g=n(51),O=n(32),v=n(128),E=n(163),j=n(162),w=function(e){var t=e.displayFacebook,n=e.displayTwitter;return Object(r.createElement)(r.Fragment,null,t&&Object(r.createElement)(g.a,{hasSeparator:!1 +/* Translators: %s expands to Facebook. */,title:Object(d.sprintf)(Object(d.__)("%s preview","wordpress-seo"),"Facebook"),initialIsOpen:!0},Object(r.createElement)(E.a,null)),n&&Object(r.createElement)(g.a +/* Translators: %s expands to Twitter. */,{title:Object(d.sprintf)(Object(d.__)("%s preview","wordpress-seo"),"Twitter"),hasSeparator:t,initialIsOpen:!0},Object(r.createElement)(j.a,null)))};w.propTypes={displayFacebook:a.a.bool.isRequired,displayTwitter:a.a.bool.isRequired};var _=w,T=Object(u.withSelect)((function(e){var t=(0,e("yoast-seo/editor").getPreferences)();return{displayFacebook:t.displayFacebook,displayTwitter:t.displayTwitter}}))(_),k=n(36);function S(e){var t=e.target;return Object(r.createElement)(k.a,{target:t},Object(r.createElement)(T,null))}S.propTypes={target:a.a.string.isRequired};var R=n(127),P=n(115);function A(e){var t=e.settings;return Object(r.createElement)(i.Fill,{name:"YoastMetabox"},Object(r.createElement)(O.a,{key:"warning",renderPriority:1},Object(r.createElement)(m.a,null)),t.isKeywordAnalysisActive&&Object(r.createElement)(O.a,{key:"keyword-input",renderPriority:8},Object(r.createElement)(b.a,{isSEMrushIntegrationActive:t.isSEMrushIntegrationActive}),!window.wpseoScriptData.metabox.isPremium&&Object(r.createElement)(i.Fill,{name:"YoastRelatedKeyphrases"},Object(r.createElement)(P.a,null))),Object(r.createElement)(O.a,{key:"google-preview",renderPriority:9},Object(r.createElement)(g.a,{id:"yoast-snippet-editor-metabox",title:Object(d.__)("Google preview","wordpress-seo"),initialIsOpen:!0},Object(r.createElement)(f.a,{hasPaperStyle:!1}))),t.isContentAnalysisActive&&Object(r.createElement)(O.a,{key:"readability-analysis",renderPriority:10},Object(r.createElement)(h.a,null)),t.isKeywordAnalysisActive&&Object(r.createElement)(O.a,{key:"seo-analysis",renderPriority:20},Object(r.createElement)(y.a,{shouldUpsell:t.shouldUpsell,shouldUpsellWordFormRecognition:t.isWordFormRecognitionActive})),t.isCornerstoneActive&&Object(r.createElement)(O.a,{key:"cornerstone",renderPriority:30},Object(r.createElement)(p.a,null)),t.displayAdvancedTab&&Object(r.createElement)(O.a,{key:"advanced",renderPriority:40},Object(r.createElement)(g.a,{id:"collapsible-advanced-settings",title:Object(d.__)("Advanced","wordpress-seo")},Object(r.createElement)(v.a,null))),t.displaySchemaSettings&&Object(r.createElement)(O.a,{key:"schema",renderPriority:50},Object(r.createElement)(R.a,null)),Object(r.createElement)(O.a,{key:"social",renderPriority:-1},Object(r.createElement)(S,{target:"wpseo-section-social"})))}A.propTypes={settings:a.a.object.isRequired};var C=Object(u.withSelect)((function(e,t){return{settings:(0,e("yoast-seo/editor").getPreferences)(),store:t.store}}))(A);function x(e){var t=e.target,n=e.store,o=e.theme;return Object(r.createElement)(k.a,{target:t},Object(r.createElement)(l,{store:n,theme:o}),Object(r.createElement)(C,{store:n,theme:o}))}x.propTypes={target:a.a.string.isRequired,store:a.a.object,theme:a.a.object}},,,,,,,,,,,,,function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(e,t){e.exports=window.wp.plugins},function(e,t){e.exports=window.wp.htmlEntities},function(e,t,n){"use strict";(function(e){n.d(t,"a",(function(){return O}));var r=n(10),o=n.n(r),a=n(5),i=n.n(a),s=n(7),c=n.n(s),l=n(2),u=n(23),d=n(4),p=n(17),f=n(43),m=n(40),b=n(108);function h(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function y(e){for(var t=1;t0);return n}},{key:"handleEditorChange",value:function(e){this._data.title!==e.title&&this._store.dispatch(Object(p.l)("title",e.title)),this._data.excerpt!==e.excerpt&&(this._store.dispatch(Object(p.l)("excerpt",e.excerpt)),this._store.dispatch(Object(p.l)("excerpt_only",e.excerpt_only))),this._data.slug!==e.slug&&this._store.dispatch(Object(p.k)({slug:e.slug})),this._data.snippetPreviewImageURL!==e.snippetPreviewImageURL&&this._store.dispatch(Object(p.k)({snippetPreviewImageURL:e.snippetPreviewImageURL})),this._data.contentImage!==e.contentImage&&this._store.dispatch(Object(f.c)(e.contentImage))}},{key:"reapplyMarkers",value:function(){var e=Object(d.select)("yoast-seo/editor"),t=e.getActiveMarker,n=e.getMarkerPauseStatus,r=t(),o=n();r&&!o&&Object(b.c)()}},{key:"refreshYoastSEO",value:function(){var e=this.collectGutenbergData();!this.isShallowEqual(this._data,e)&&(this.handleEditorChange(e),this._data=e,this._refresh())}},{key:"areNewAnalysisResultsAvailable",value:function(){var e=Object(d.select)("yoast-seo/editor"),t=e.getReadabilityResults(),n=e.getResultsForFocusKeyword();return(this._previousReadabilityResults!==t||this._previousSeoResults!==n)&&(this._previousReadabilityResults=t,this._previousSeoResults=n,!0)}},{key:"onNewAnalysisResultsAvailable",value:function(){this.reapplyMarkers()}},{key:"subscribeToGutenberg",value:function(){this.subscriber=Object(l.debounce)(this.refreshYoastSEO,500),Object(d.subscribe)(this.subscriber)}},{key:"subscribeToYoastSEO",value:function(){var e=this;this.yoastSubscriber=function(){e.areNewAnalysisResultsAvailable()&&e.onNewAnalysisResultsAvailable()},Object(d.subscribe)(this.yoastSubscriber)}},{key:"getData",value:function(){return this._data}}]),e}()}).call(this,n(205))},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(e,t,n){"use strict";n.r(t);var r,o=n(46),a=n.n(o),i=n(0),s=n(169),c=n(247),l=n(117),u=n(4),d=n(3),p=n(66),f=n(2),m=n(18),b=n(19),h=n(24),y=n(42),g=n(27),O=n.n(g),v=n(15),E=n.n(v),j=n(1),w=n.n(j),_=n(12),T=n.n(_).a.svg(r||(r=E()(["\n\twidth: ","px;\n\theight: ","px;\n\t&&& path {\n\t\tfill: ",";\n\t}\n\t&&& circle.yoast-icon-readability-score {\n\t\tfill: ",";\n\t\tdisplay: ",";\n\t}\n\t\n\t&&& circle.yoast-icon-seo-score {\n\t\tfill: ",";\n\t\tdisplay: ",";\n\t}\n"])),(function(e){return e.size}),(function(e){return e.size}),(function(e){return e.color}),(function(e){return e.readabilityScoreColor}),(function(e){return e.isContentAnalysisActive?"inline":"none"}),(function(e){return e.seoScoreColor}),(function(e){return e.isKeywordAnalysisActive?"inline":"none"})),k=function(e){return Object(i.createElement)(T,O()({},e,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 646.66 456.27"}),Object(i.createElement)("path",{d:"M73,405.26a68.53,68.53,0,0,1-12.82-4c-1-.42-2-.89-3-1.37-1.49-.72-3-1.56-4.77-2.56-1.5-.88-2.71-1.64-3.83-2.39-.9-.61-1.8-1.26-2.68-1.92q-2.64-2-5.08-4.19a68.26,68.26,0,0,1-8.4-9.17c-.92-1.2-1.68-2.25-2.35-3.24q-1.84-2.73-3.44-5.64a68.26,68.26,0,0,1-8.29-32.55V142.13a68.29,68.29,0,0,1,8.29-32.55,58.6,58.6,0,0,1,3.44-5.64,57.53,57.53,0,0,1,4-5.27A69.64,69.64,0,0,1,48.56,85.42,56.06,56.06,0,0,1,54.2,82,67.78,67.78,0,0,1,73,75.09,69.79,69.79,0,0,1,86.75,73.7H256.41L263,55.39H86.75A86.84,86.84,0,0,0,0,142.13V338.22A86.83,86.83,0,0,0,86.75,425H98.07V406.65H86.75A68.31,68.31,0,0,1,73,405.26ZM368.55,60.85l-1.41-.53L360.73,77.5l1.41.53a68.58,68.58,0,0,1,8.66,4,58.65,58.65,0,0,1,5.65,3.43A69.49,69.49,0,0,1,391,98.67c1.4,1.68,2.72,3.46,3.95,5.27s2.39,3.72,3.44,5.64a68.32,68.32,0,0,1,8.29,32.55V406.65H233.55l-.44.76c-3.07,5.37-6.26,10.48-9.49,15.19L222,425H425V142.13A87.19,87.19,0,0,0,368.55,60.85Z",fill:"#000001"}),Object(i.createElement)("path",{d:"M303.66,0l-96.8,268.87-47.58-149H101.1l72.72,186.78a73.61,73.61,0,0,1,0,53.73c-7.07,18.07-19.63,39.63-54.36,46l-1.56.29v49.57l2-.08c29-1.14,51.57-10.72,70.89-30.14,19.69-19.79,36.55-50.52,53-96.68L366.68,0Z",fill:"#000001"}),Object(i.createElement)("circle",{className:"yoast-icon-readability-score",cx:"561.26",cy:"142.43",r:"85.04",fill:"#000001",stroke:"#181716",strokeMiterlimit:"10",strokeWidth:"0.72"}),Object(i.createElement)("circle",{className:"yoast-icon-seo-score",cx:"561.26",cy:"341.96",r:"85.04",fill:"#000001",stroke:"#181716",strokeMiterlimit:"10",strokeWidth:"0.72"}))};k.propTypes={readabilityScoreColor:w.a.string,isContentAnalysisActive:w.a.bool,seoScoreColor:w.a.string,isKeywordAnalysisActive:w.a.bool,size:w.a.number,color:w.a.string},k.defaultProps={readabilityScoreColor:"#000000",isContentAnalysisActive:!1,seoScoreColor:"#000000",isKeywordAnalysisActive:!1,size:20,color:"#000001"};var S=k,R=Object(b.compose)([Object(u.withSelect)((function(e){var t,n,r=e("yoast-seo/editor"),o=Object(y.a)(r.getResultsForFocusKeyword().overallScore),a=Object(y.a)(r.getReadabilityResults().overallScore),i=r.getPreferences(),s=i.isKeywordAnalysisActive,c=i.isContentAnalysisActive;switch(a.className){case"good":t=h.colors.$color_good;break;case"ok":t=h.colors.$color_ok;break;case"bad":t=h.colors.$color_bad;break;default:t=h.colors.$color_score_icon}switch(o.className){case"good":n=h.colors.$color_good;break;case"ok":n=h.colors.$color_ok;break;case"bad":n=h.colors.$color_bad;break;default:n=h.colors.$color_score_icon}return{readabilityScoreColor:t,seoScoreColor:n,isKeywordAnalysisActive:s,isContentAnalysisActive:c}}))])(S),P=n(124),A=n(160),C=n(125),x=n(126),I=n(122),D=n(32),N=n(84),L=n(161),M=function(){return Object(i.createElement)(N.a,{title:Object(d.__)("Google preview","wordpress-seo"),id:"yoast-google-preview-modal"},Object(i.createElement)(L.a,{showCloseButton:!1,hasPaperStyle:!1}))},F=n(162),q=function(){return Object(i.createElement)(N.a,{title:Object(d.__)("Twitter preview","wordpress-seo"),id:"yoast-twitter-preview-modal"},Object(i.createElement)(F.a,null))},B=n(163),U=function(){return Object(i.createElement)(N.a,{title:Object(d.__)("Facebook preview","wordpress-seo"),id:"yoast-facebook-preview-modal"},Object(i.createElement)(B.a,null))},K=n(127),H=n(50),W=n(128);function G(e){var t=e.settings;return Object(i.createElement)(i.Fragment,null,Object(i.createElement)(m.Fill,{name:"YoastSidebar"},Object(i.createElement)(D.a,{key:"warning",renderPriority:1},Object(i.createElement)(A.a,null)),t.isKeywordAnalysisActive&&Object(i.createElement)(D.a,{key:"keyword-input",renderPriority:8},Object(i.createElement)(C.a,{isSEMrushIntegrationActive:t.isSEMrushIntegrationActive})),Object(i.createElement)(D.a,{key:"google-preview",renderPriority:23},Object(i.createElement)(M,null)),t.displayFacebook&&Object(i.createElement)(D.a,{key:"facebook-preview",renderPriority:24},Object(i.createElement)(U,null)),t.displayTwitter&&Object(i.createElement)(D.a,{key:"twitter-preview",renderPriority:25},Object(i.createElement)(q,null)),t.displaySchemaSettings&&Object(i.createElement)(D.a,{key:"schema",renderPriority:26},Object(i.createElement)(H.a,{title:Object(d.__)("Schema","wordpress-seo")},Object(i.createElement)(K.a,null))),t.displayAdvancedTab&&Object(i.createElement)(D.a,{key:"advanced",renderPriority:27},Object(i.createElement)(H.a,{title:Object(d.__)("Advanced","wordpress-seo")},Object(i.createElement)(W.a,null))),t.isContentAnalysisActive&&Object(i.createElement)(D.a,{key:"readability",renderPriority:10},Object(i.createElement)(x.a,null)),t.isKeywordAnalysisActive&&Object(i.createElement)(D.a,{key:"seo",renderPriority:20},Object(i.createElement)(I.a,{shouldUpsell:t.shouldUpsell,shouldUpsellWordFormRecognition:t.isWordFormRecognitionActive})),t.isCornerstoneActive&&Object(i.createElement)(D.a,{key:"cornerstone",renderPriority:30},Object(i.createElement)(P.a,null))))}G.propTypes={settings:w.a.object.isRequired};var V=Object(u.withSelect)((function(e,t){return{settings:(0,e("yoast-seo/editor").getPreferences)(),store:t.store}}))(G),Y=n(192),$=n(25),z=n(108),Z=n(120),Q=n(103);function X(e){var t=e.theme;return Object(i.createElement)(Q.a,{theme:t,location:"sidebar"},Object(i.createElement)(m.Slot,{name:"YoastSidebar"},(function(e){return Object(Z.a)(e)})))}var J=n(5),ee=n.n(J),te=n(7),ne=n.n(te),re=n(11),oe=n.n(re),ae=n(13),ie=n.n(ae),se=n(14),ce=n.n(se),le=n(8),ue=n.n(le),de=n(52),pe=n(248),fe=n(10),me=n.n(fe),be=n(39),he=n.n(be),ye=n(54),ge=n(176);function Oe(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function ve(e){for(var t=1;t","",""),{code:Object(i.createElement)("code",null),helplink:v}),j=Object(ge.a)(Object(d.sprintf)(Object(d.__)("This is a sponsored link or advert (mark as %1$ssponsored%2$s)%3$s","wordpress-seo"),"","",""),{code:Object(i.createElement)("code",null),helplink:v}),w=[{id:"opensInNewTab",title:Object(d.__)("Open in new tab","wordpress-seo")},{id:"noFollow",title:E},{id:"sponsored",title:j}],_=window.wp.blockEditor.__experimentalLinkControl;return Object(i.createElement)(m.Popover,{key:l,anchorRef:g,focusOnMount:!!r&&"firstElement",onClose:c,position:"bottom center"},Object(i.createElement)(_,{value:O,onChange:function(e){e=ve(ve({},h),e);var n=O.url===e.url&&O.opensInNewTab!==e.opensInNewTab||O.noFollow!==e.noFollow||O.sponsored!==e.sponsored;n&&!0===e.sponsored&&!0!==O.sponsored&&(e.noFollow=!0),n&&!1===e.noFollow&&!1!==O.noFollow&&(e.sponsored=!1);var r=n&&void 0===e.url;if(y(r?e:void 0),!r){var i=Object(de.prependHTTP)(e.url),l=function(e){var t=e.noFollow,n=e.sponsored,r={type:"core/link",attributes:{url:e.url}},o=[];return e.opensInNewWindow&&(r.attributes.target="_blank",o.push("noreferrer noopener")),n&&(o.push("sponsored"),o.push("nofollow")),t&&o.push("nofollow"),o.length>0&&(o=Object(f.uniq)(o),r.attributes.rel=o.join(" ")),r}({url:i,type:e.type,id:void 0!==e.id&&null!==e.id?String(e.id):void 0,opensInNewWindow:e.opensInNewTab,noFollow:e.noFollow,sponsored:e.sponsored});if(Object(p.isCollapsed)(o)&&!t){var u=e.title||i,m=Object(p.applyFormat)(Object(p.create)({text:u}),l,0,u.length);a(Object(p.insert)(o,m))}else{var b=Object(p.applyFormat)(o,l);b.start=b.end,b.activeFormats=[],a(b)}n||c(),function(e){if(!e)return!1;var t=e.trim();if(!t)return!1;if(/^\S+:/.test(t)){var n=Object(de.getProtocol)(t);if(!Object(de.isValidProtocol)(n))return!1;if(Object(f.startsWith)(n,"http")&&!/^https?:\/\/[^\/\s]/i.test(t))return!1;var r=Object(de.getAuthority)(t);if(!Object(de.isValidAuthority)(r))return!1;var o=Object(de.getPath)(t);if(o&&!Object(de.isValidPath)(o))return!1;var a=Object(de.getQueryString)(t);if(a&&!Object(de.isValidQueryString)(a))return!1;var i=Object(de.getFragment)(t);if(i&&!Object(de.isValidFragment)(i))return!1}return!(Object(f.startsWith)(t,"#")&&!Object(de.isValidFragment)(t))}(i)?s(t?Object(d.__)("Link edited.","wordpress-seo"):Object(d.__)("Link inserted.","wordpress-seo"),"assertive"):s(Object(d.__)("Warning: the link has been inserted but may have errors. Please test it.","wordpress-seo"),"assertive")}},forceIsEditingLink:r,settings:w}))}));var je=Object(d.__)("Link","wordpress-seo"),we={name:"core/link",title:je,tagName:"a",className:null,attributes:{url:"href",target:"target",rel:"rel"},replaces:"core/link",__unstablePasteRule:function(e,t){var n=t.html,r=t.plainText;if(Object(p.isCollapsed)(e))return e;var o=(n||r).replace(/<[^>]+>/g,"").trim();return Object(de.isURL)(o)?(window.console.log("Created link:\n\n",o),Object(p.applyFormat)(e,{type:"core/link",attributes:{url:Object(pe.decodeEntities)(o)}})):e},edit:Object(m.withSpokenMessages)(function(e){ie()(o,e);var t,n,r=(t=o,n=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}(),function(){var e,r=ue()(t);if(n){var o=ue()(this).constructor;e=Reflect.construct(r,arguments,o)}else e=r.apply(this,arguments);return ce()(this,e)});function o(){var e;return ee()(this,o),(e=r.apply(this,arguments)).addLink=e.addLink.bind(oe()(e)),e.stopAddingLink=e.stopAddingLink.bind(oe()(e)),e.onRemoveFormat=e.onRemoveFormat.bind(oe()(e)),e.state={addingLink:!1},e}return ne()(o,[{key:"addLink",value:function(){var e=this.props,t=e.value,n=e.onChange,r=Object(p.getTextContent)(Object(p.slice)(t));r&&Object(de.isURL)(r)?n(Object(p.applyFormat)(t,{type:"core/link",attributes:{url:r}})):r&&Object(de.isEmail)(r)?n(Object(p.applyFormat)(t,{type:"core/link",attributes:{url:"mailto:".concat(r)}})):this.setState({addingLink:!0})}},{key:"stopAddingLink",value:function(){this.setState({addingLink:!1}),this.props.onFocus()}},{key:"onRemoveFormat",value:function(){var e=this.props,t=e.value,n=e.onChange,r=e.speak;n(Object(p.removeFormat)(t,"core/link")),r(Object(d.__)("Link removed.","wordpress-seo"),"assertive")}},{key:"render",value:function(){var e=this.props,t=e.isActive,n=e.activeAttributes,r=e.value,o=e.onChange,a=window.wp.blockEditor,s=a.RichTextToolbarButton,c=a.RichTextShortcut;return Object(i.createElement)(i.Fragment,null,Object(i.createElement)(c,{type:"primary",character:"k",onUse:this.addLink}),Object(i.createElement)(c,{type:"primaryShift",character:"k",onUse:this.onRemoveFormat}),t&&Object(i.createElement)(s,{name:"link",icon:"editor-unlink",title:Object(d.__)("Unlink","wordpress-seo"),onClick:this.onRemoveFormat,isActive:t,shortcutType:"primaryShift",shortcutCharacter:"k"}),!t&&Object(i.createElement)(s,{name:"link",icon:"admin-links",title:je,onClick:this.addLink,isActive:t,shortcutType:"primary",shortcutCharacter:"k"}),(this.state.addingLink||t)&&Object(i.createElement)(Ee,{addingLink:this.state.addingLink,stopAddingLink:this.stopAddingLink,isActive:t,activeAttributes:n,value:r,onChange:o}))}}]),o}(i.Component))},_e=n(6),Te=n(35);function ke(e){var t=e.score,n=e.label,r=e.scoreValue;return Object(i.createElement)("div",null,Object(i.createElement)(_e.SvgIcon,Object(Te.getIconForScore)(t)),Object(i.createElement)("span",null," ",n," ",r&&Object(i.createElement)("strong",null,r)))}function Se(e){var t=e.checklist,n=e.onClick,r=t.every((function(e){return"good"===e.score}));return Object(i.createElement)(i.Fragment,null,t.map((function(e){return Object(i.createElement)(ke,O()({key:e.label},e))})),Object(i.createElement)("br",null),!r&&Object(i.createElement)(_e.Button,{onClick:n},Object(d.__)("Improve your post with Yoast SEO","wordpress-seo")))}function Re(e){var t,n=e.checklist,r=e.onClick;return t=n.every((function(e){return"good"===e.score}))?Object(d.__)("We've analyzed your post. Everything looks good. Well done!","wordpress-seo"):Object(d.__)("We've analyzed your post. There is still room for improvement!","wordpress-seo"),Object(i.createElement)(i.Fragment,null,Object(i.createElement)("p",null,t),Object(i.createElement)(Se,{checklist:n,onClick:r}))}function Pe(e,t){if(t.getPreferences().isKeywordAnalysisActive){var n=Object(y.a)(t.getReadabilityResults().overallScore);e.push({label:Object(d.__)("Readability analysis:","wordpress-seo"),score:n.className,scoreValue:n.screenReaderReadabilityText})}}function Ae(e,t){if(t.getPreferences().isContentAnalysisActive){var n=Object(y.a)(t.getResultsForFocusKeyword().overallScore);e.push({label:Object(d.__)("SEO analysis:","wordpress-seo"),score:n.className,scoreValue:n.screenReaderReadabilityText})}}function Ce(e,t,n){if(n.getBlocks().some((function(e){return!0===e.attributes["is-yoast-schema-block"]}))){var r=t.getSchemaBlocksValidationResults(),o=Object.values(r);if(o&&o.length>0){var a=o.every((function(e){return e.result<=0}));e.push({label:Object(d.__)("Schema analysis:","wordpress-seo"),score:a?"good":"bad",scoreValue:a?Object(d.__)("Good","wordpress-seo"):Object(d.__)("Needs improvement","wordpress-seo")})}}}ke.propTypes={score:j.string.isRequired,label:j.string.isRequired,scoreValue:j.string},ke.defaultProps={scoreValue:""},Se.propTypes={checklist:w.a.array.isRequired,onClick:w.a.func.isRequired},Re.propTypes={checklist:w.a.array.isRequired,onClick:w.a.func.isRequired};var xe,Ie,De,Ne=Object(b.compose)([Object(u.withSelect)((function(e){var t=e("yoast-seo/editor"),n=e("yoast-seo/schema-blocks"),r=e("core/block-editor"),o=[];return function(e,t){t.getFocusKeyphrase()||e.push({label:Object(d.__)("No focus keyword was entered","wordpress-seo"),score:"bad"})}(o,t),Pe(o,t),Ae(o,t),Ce(o,n,r),{checklist:o}})),Object(u.withDispatch)((function(e){var t=e("core/edit-post"),n=t.closePublishSidebar,r=t.openGeneralSidebar;return{onClick:function(){n(),r("yoast-seo/seo-sidebar")}}}))])(Re),Le=Object(b.compose)([Object(u.withSelect)((function(e){var t=e("yoast-seo/editor"),n=e("yoast-seo/schema-blocks"),r=e("core/block-editor"),o=[];return Pe(o,t),Ae(o,t),Ce(o,n,r),{checklist:o}})),Object(u.withDispatch)((function(e){var t=e("core/edit-post").openGeneralSidebar;return{onClick:function(){t("yoast-seo/seo-sidebar")}}}))])(Se),Me=n(16);function Fe(){return(Fe=Object.assign||function(e){for(var t=1;t2&&void 0!==arguments[2]?arguments[2]:"",a="string"==typeof t?Object(r.decodeHTML)(t):t;return{type:s,name:e,value:a,label:n}}function f(e){return{type:l,wordsToHighlight:e}}function b(e){return{type:i,name:e}}function h(){return{type:c,time:(new Date).getMilliseconds()}}},function(e,t){e.exports=window.wp.components},function(e,t){e.exports=window.wp.compose},function(e,t,n){"use strict";n.d(t,"a",(function(){return a}));var r=n(2);function a(){return Object(r.get)(window,"wpseoScriptData.metabox",{intl:{},isRtl:!1})}},,function(e,t){e.exports=window.yoast.components},function(e,t){e.exports=window.yoast.analysis},function(e,t){e.exports=window.yoast.styleGuide},,function(e,t){e.exports=window.regeneratorRuntime},function(e,t){function n(){return e.exports=n=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:"",n=e.getIdentifier(),a={score:e.score,rating:r.interpreters.scoreToRating(e.score),hasMarks:e.hasMarks(),marker:e.getMarker(),id:n,text:e.text,markerId:t.length>0?"".concat(t,":").concat(n):n};return"ok"===a.rating&&(a.rating="OK"),a}function s(e,t){switch(e.rating){case"error":t.errorsResults.push(e);break;case"feedback":t.considerationsResults.push(e);break;case"bad":t.problemsResults.push(e);break;case"OK":t.improvementsResults.push(e);break;case"good":t.goodResults.push(e)}return t}function i(e){var t={icon:"seo-score-none",color:a.colors.$color_grey_disabled};switch(e){case"loading":t={icon:"loading-spinner",color:a.colors.$color_green_medium_light};break;case"good":t={icon:"seo-score-good",color:a.colors.$color_green_medium};break;case"ok":t={icon:"seo-score-ok",color:a.colors.$color_ok};break;case"bad":t={icon:"seo-score-bad",color:a.colors.$color_red}}return t}function c(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n={errorsResults:[],problemsResults:[],improvementsResults:[],goodResults:[],considerationsResults:[]};if(!e)return n;for(var r=0;r "+c);if("componentClose"===p.type)throw new Error("Missing opening component token: `"+p.value+"`");if("componentOpen"===p.type){s=n[p.value],l=d;break}b.push(n[p.value])}else b.push(p.value);return s&&(u=function(e,t){var n,r,a=t[e],o=0;for(r=e+1;r1&&void 0!==arguments[1]?arguments[1]:"_";return e.replace(/\s/g,t)}function g(e){return{name:"cf_"+y(e),label:c(e+" (custom field)")}}function v(e){var t=y(e);return{name:"ct_"+t,label:c(e+" (custom taxonomy)"),descriptionName:"ct_desc_"+t,descriptionLabel:c(e+" description (custom taxonomy)")}}function O(e,t){return e.custom_taxonomies?(Object(o.forEach)(e.custom_taxonomies,(function(e,n){var r=v(n),a=r.name,o=r.label,s=r.descriptionName,c=r.descriptionLabel;t.dispatch(Object(i.l)(a,e.name,o)),t.dispatch(Object(i.l)(s,e.description,c))})),Object(o.omit)(u({},e),"custom_taxonomies")):e}function j(e,t){return e.custom_fields?(Object(o.forEach)(e.custom_fields,(function(e,n){var r=g(n),a=r.name,o=r.label;t.dispatch(Object(i.l)(a,e,o))})),Object(o.omit)(u({},e),"custom_fields")):e}function w(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:156;return(e=(e=Object(s.stripTags)(e)).trim()).length<=t?e:(e=e.substring(0,t)).substring(0,e.lastIndexOf(" "))}var k=function(e){var t=Object(o.get)(window,["YoastSEO","app","pluggable"],!1);if(!t||!Object(o.get)(window,["YoastSEO","app","pluggable","loaded"],!1))return function(e){var t=Object(o.get)(window,["YoastSEO","wp","replaceVarsPlugin","replaceVariables"],o.identity);return{url:e.url,title:p(t(e.title)),description:p(t(e.description))}}(e);var n=t._applyModifications.bind(t);return{url:e.url,title:p(n("data_page_title",e.title)),description:p(n("data_meta_desc",e.description))}}},,function(e,t,n){"use strict";n.d(t,"a",(function(){return s}));var r=n(3),a=n(23),o=n(2);function s(e){return Object(o.isNil)(e)||(e/=10),function(e){switch(e){case"feedback":return{className:"na",screenReaderText:Object(r.__)("Feedback","wordpress-seo"),screenReaderReadabilityText:""};case"bad":return{className:"bad",screenReaderText:Object(r.__)("Needs improvement","wordpress-seo"),screenReaderReadabilityText:Object(r.__)("Needs improvement","wordpress-seo")};case"ok":return{className:"ok",screenReaderText:Object(r.__)("OK SEO score","wordpress-seo"),screenReaderReadabilityText:Object(r.__)("OK","wordpress-seo")};case"good":return{className:"good",screenReaderText:Object(r.__)("Good SEO score","wordpress-seo"),screenReaderReadabilityText:Object(r.__)("Good","wordpress-seo")};default:return{className:"loading",screenReaderText:"",screenReaderReadabilityText:""}}}(a.interpreters.scoreToRating(e))}},function(e,t,n){"use strict";n.d(t,"b",(function(){return r})),n.d(t,"a",(function(){return a})),n.d(t,"d",(function(){return o})),n.d(t,"c",(function(){return s}));var r="SET_SETTINGS",a="SET_CONTENT_IMAGE",o=function(e){return{type:r,settings:e}},s=function(e){return{type:a,src:e}}},,function(e,t,n){"use strict";n.d(t,"a",(function(){return r})),n.d(t,"b",(function(){return a}));var r="WPSEO_SET_MARKER_STATUS",a=function(e){return{type:r,marksButtonStatus:e}}},function(e,t,n){var r=n(102);e.exports=function(e,t){if(null==e)return{};var n,a,o=r(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}},function(e,t){function n(e,t,n,r,a,o,s){try{var i=e[o](s),c=i.value}catch(e){return void n(e)}i.done?t(c):Promise.resolve(c).then(r,a)}e.exports=function(e){return function(){var t=this,r=arguments;return new Promise((function(a,o){var s=e.apply(t,r);function i(e){n(s,a,o,i,c,"next",e)}function c(e){n(s,a,o,i,c,"throw",e)}i(void 0)}))}}},,,function(e,t,n){"use strict";var r=n(39),a=n.n(r),o=n(0),s=n(6),i=n(1),c=n.n(i),l=function(e){var t=Object(o.useState)(!1),n=a()(t,2),r=n[0],i=n[1],c=e.prefixIcon;return Object(o.createElement)("div",{className:"yoast components-panel__body ".concat(r?"is-opened":"")},Object(o.createElement)("h2",{className:"components-panel__body-title"},Object(o.createElement)("button",{onClick:function(){i(!r)},className:"components-button components-panel__body-toggle"},Object(o.createElement)("span",{className:"yoast-icon-span",style:{fill:"".concat(c&&c.color||"")}},c&&Object(o.createElement)(s.SvgIcon,{icon:c.icon,color:c.color,size:c.size})),Object(o.createElement)("span",{className:"yoast-title-container"},Object(o.createElement)("div",{className:"yoast-title"},e.title),Object(o.createElement)("div",{className:"yoast-subtitle"},e.subTitle)),Object(o.createElement)("span",{className:"yoast-chevron","aria-hidden":"true"}))),r&&e.children)};t.a=l,l.propTypes={title:c.a.string.isRequired,children:c.a.oneOfType([c.a.node,c.a.arrayOf(c.a.node)]).isRequired,prefixIcon:c.a.object,subTitle:c.a.string},l.defaultProps={prefixIcon:null,subTitle:""}},function(e,t,n){"use strict";var r,a=n(27),o=n.n(a),s=n(15),i=n.n(s),c=n(0),l=n(6),u=n(12),p=n.n(u)()(l.Collapsible)(r||(r=i()(['\n\th2 > button {\n\t\tpadding-left: 24px;\n\t\tpadding-top: 16px;\n\n\t\t&:hover {\n\t\t\tbackground-color: #f0f0f0;\n\t\t}\n\t}\n\n\tdiv[class^="collapsible_content"] {\n\t\tpadding: 24px 0;\n\t\tmargin: 0 24px;\n\t\tborder-top: 1px solid rgba(0,0,0,0.2);\n\t}\n\n'])));t.a=function(e){return Object(c.createElement)(p,o()({hasPadding:!0,hasSeparator:!0},e))}},function(e,t){e.exports=window.wp.url},function(e,t,n){"use strict";n.d(t,"b",(function(){return p}));var r=n(27),a=n.n(r),o=n(46),s=n.n(o),i=n(0),c=n(1),l=n.n(c),u=n(18),p="yoast yoast-gutenberg-modal",d=function(e){var t=e.title,n=e.className,r=e.showYoastIcon,o=e.additionalClassName,c=s()(e,["title","className","showYoastIcon","additionalClassName"]),l=r?Object(i.createElement)("span",{className:"yoast-icon"}):null;return Object(i.createElement)(u.Modal,a()({title:t,className:"".concat(n," ").concat(o),icon:l},c),e.children)};d.propTypes={title:l.a.string,className:l.a.string,showYoastIcon:l.a.bool,children:l.a.oneOfType([l.a.node,l.a.arrayOf(l.a.node)]),additionalClassName:l.a.string},d.defaultProps={title:"Yoast SEO",className:p,showYoastIcon:!0,children:null,additionalClassName:""},t.a=d},function(e,t,n){"use strict";var r,a=n(15),o=n.n(a),s=n(24),i=n(9),c=n(12),l=n.n(c),u=Object(i.makeOutboundLink)(l.a.a(r||(r=o()(["\n\tdisplay: inline-block;\n\tposition: relative;\n\toutline: none;\n\ttext-decoration: none;\n\tborder-radius: 100%;\n\twidth: 24px;\n\theight: 24px;\n\tmargin: -4px 0;\n\tvertical-align: middle;\n\n\tcolor: ",";\n\t\n\t&:hover,\n\t&:focus {\n\t\tcolor: ",";\t\n\t}\n\t\n\t// Overwrite the default blue active color for links.\n\t&:active {\n\t\tcolor: ",';\t\n\t}\n\n\t&::before {\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\tpadding: 2px;\n\t\tcontent: "\f223";\n\t}\n'],["\n\tdisplay: inline-block;\n\tposition: relative;\n\toutline: none;\n\ttext-decoration: none;\n\tborder-radius: 100%;\n\twidth: 24px;\n\theight: 24px;\n\tmargin: -4px 0;\n\tvertical-align: middle;\n\n\tcolor: ",";\n\t\n\t&:hover,\n\t&:focus {\n\t\tcolor: ",";\t\n\t}\n\t\n\t// Overwrite the default blue active color for links.\n\t&:active {\n\t\tcolor: ",';\t\n\t}\n\n\t&::before {\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\tpadding: 2px;\n\t\tcontent: "\\f223";\n\t}\n'])),s.colors.$color_help_text,s.colors.$color_snippet_focus,s.colors.$color_help_text));t.a=u},,,function(e,t,n){"use strict";n.d(t,"a",(function(){return u}));var r=n(10),a=n.n(r),o=n(19),s=n(0),i=n(28);function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function l(e){for(var t=1;t0?"".concat(this.props.keywordKey,":").concat(e):e;n===this.props.activeMarker?(this.props.setActiveMarker(null),this.props.setMarkerPauseStatus(!1),this.removeMarkers()):(this.props.setActiveMarker(n),t())}},{key:"removeMarkers",value:function(){window.YoastSEO.analysis.applyMarks(new j.Paper("",{}),[])}},{key:"render",value:function(){var e=this.state.mappedResults,t=e.errorsResults,n=e.improvementsResults,r=e.goodResults,a=e.considerationsResults,o=e.problemsResults;return Object(y.createElement)(y.Fragment,null,Object(y.createElement)(O.ContentAnalysis,{errorsResults:t,problemsResults:o,improvementsResults:n,considerationsResults:a,goodResults:r,activeMarker:this.props.activeMarker,onMarkButtonClick:this.handleMarkButtonClick,marksButtonClassName:this.props.marksButtonClassName,marksButtonStatus:this.props.marksButtonStatus,headingLevel:3,keywordKey:this.props.keywordKey}))}}]),a}(y.Component);k.propTypes={results:v.a.array,marksButtonClassName:v.a.string,marksButtonStatus:v.a.string,setActiveMarker:v.a.func.isRequired,setMarkerPauseStatus:v.a.func.isRequired,activeMarker:v.a.string,keywordKey:v.a.string},k.defaultProps={results:null,marksButtonStatus:"enabled",marksButtonClassName:"",activeMarker:null,keywordKey:""};var E=k;t.a=Object(a.compose)([Object(r.withSelect)((function(e){return{activeMarker:(0,e("yoast-seo/editor").getActiveMarker)()}})),Object(r.withDispatch)((function(e){var t=e("yoast-seo/editor");return{setActiveMarker:t.setActiveMarker,setMarkerPauseStatus:t.setMarkerPauseStatus}}))])(E)},,function(e,t){e.exports=window.yoast.featureFlag},,function(e,t,n){"use strict";n.d(t,"b",(function(){return E}));var r=n(10),a=n.n(r),o=n(5),s=n.n(o),i=n(7),c=n.n(i),l=n(11),u=n.n(l),p=n(13),d=n.n(p),m=n(14),f=n.n(m),b=n(8),h=n.n(b),y=n(0),g=n(3),v=n(6),O=n(1),j=n.n(O),w=n(62);var k=function(e){d()(o,e);var t,n,r=(t=o,n=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}(),function(){var e,r=h()(t);if(n){var a=h()(this).constructor;e=Reflect.construct(r,arguments,a)}else e=r.apply(this,arguments);return f()(this,e)});function o(e){var t;return s()(this,o),(t=r.call(this,e)).initialPageType=e.pageType.value,t.initialArticleType=e.articleType?e.articleType.value:"None",t.state={schema_page_type:t.initialPageType,schema_article_type:t.initialArticleType},t.handleOptionFocus=t.handleOptionFocus.bind(u()(t)),t}return c()(o,[{key:"shouldShowAlert",value:function(){return this.state.schema_page_type!==this.initialPageType||this.state.schema_article_type!==this.initialArticleType}},{key:"handleOptionFocus",value:function(e,t){this.setState(a()({},e,t))}},{key:"render",value:function(){return Object(y.createElement)(y.Fragment,null,Object(y.createElement)(v.FieldGroup,{label:Object(g.__)("Schema settings","wordpress-seo"),linkTo:"https://yoa.st/404",linkText:Object(g.__)("Learn more about the schema settings","wordpress-seo"),description:Object(g.sprintf)( +/* translators: %1$s expands to an indexable object's name, e.g. Posts or Pages. */ +Object(g.__)("Choose how your %1$s should be described by default in your site's schema.org markup. You can change these settings for individual %1$s.","wordpress-seo"),this.props.postTypeName)}),this.shouldShowAlert()&&Object(y.createElement)(v.Alert,{type:"warning"},Object(g.sprintf)( +/* translators: %1$s expands to an indexable object's name, e.g. Posts or Pages. */ +Object(g._n)("Upon saving, this setting will apply to all of your %1$s. %1$s that are manually configured will be left untouched.","Upon saving, these settings will apply to all of your %1$s. %1$s that are manually configured will be left untouched.",this.props.articleType?2:1,"wordpress-seo"),this.props.postTypeName)),Object(y.createElement)(v.Select,{id:"schema-page-type-".concat(this.props.postType),name:"schema_page_type",options:this.props.pageTypeOptions,label:Object(g.__)("Default Page type","wordpress-seo"),onChange:this.props.pageType.onChange,selected:this.props.pageType.value,onOptionFocus:this.handleOptionFocus}),this.props.articleType&&Object(y.createElement)(v.Select,{id:"schema-article-type-".concat(this.props.postType),name:"schema_article_type",options:this.props.articleTypeOptions,label:Object(g.__)("Default Article type","wordpress-seo"),onChange:this.props.articleType.onChange,onOptionFocus:this.handleOptionFocus,selected:this.props.articleType.value}))}}]),o}(y.Component),E=j.a.arrayOf(j.a.shape({name:j.a.string,value:j.a.string}));k.propTypes={postType:j.a.string.isRequired,postTypeName:j.a.string.isRequired,pageType:w.b.isRequired,articleType:w.b,pageTypeOptions:E.isRequired,articleTypeOptions:E.isRequired},k.defaultProps={articleType:null},t.a=Object(w.a)((function(e){return[{name:"pageType",fieldId:e.pageTypeFieldId},{name:"articleType",fieldId:e.articleTypeFieldId}]}))(k)},,function(e,t){e.exports=function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t=0||(a[n]=e[n]);return a}},function(e,t,n){"use strict";var r=n(0),a=n(1),o=n.n(a),s=n(12),i=n(28),c=function(e){var t=e.theme,n=e.location,a=e.children;return Object(r.createElement)(i.LocationProvider,{value:n},Object(r.createElement)(s.ThemeProvider,{theme:t},a))};c.propTypes={theme:o.a.object.isRequired,location:o.a.oneOf(["sidebar","metabox","modal"]).isRequired,children:o.a.element.isRequired},t.a=c},,,,,,,,function(e,t,n){"use strict";n.d(t,"a",(function(){return i}));var r,a,o=n(16);function s(){return(s=Object.assign||function(e){for(var t=1;t=4}(h)&&Object(o.createElement)(J,null),Object(o.createElement)(D,{countryCode:u,setCountry:i,newRequest:a,keyphrase:r,setRequestFailed:m,setNoResultsFound:b,setRequestSucceeded:y,setRequestLimitReached:g,response:t,lastRequestKeyphrase:n})),function(e){var t=e.isPending,n=e.requestLimitReached,r=e.isSuccess,a=e.response,i=e.requestHasData;return t?Object(o.createElement)(p,null):n?Object(o.createElement)(f,null):!r&&function(e){return!Object(l.isEmpty)(e)&&"error"in e}(a)?Object(o.createElement)(Z,null):i?void 0:Object(o.createElement)("p",null,Object(s.__)("Sorry, there's no data available for that keyphrase/country combination.","wordpress-seo"))}(e),Object(o.createElement)(W,{keyphrase:r,relatedKeyphrases:h,countryCode:u,renderAction:c,data:t}))}Q.propTypes={keyphrase:c.a.string,relatedKeyphrases:c.a.array,renderAction:c.a.func,requestLimitReached:c.a.bool,countryCode:c.a.string.isRequired,setCountry:c.a.func.isRequired,newRequest:c.a.func.isRequired,setRequestSucceeded:c.a.func.isRequired,setRequestLimitReached:c.a.func.isRequired,setRequestFailed:c.a.func.isRequired,setNoResultsFound:c.a.func.isRequired,response:c.a.object,lastRequestKeyphrase:c.a.string},Q.defaultProps={keyphrase:"",relatedKeyphrases:[],renderAction:null,requestLimitReached:!1,response:{},lastRequestKeyphrase:""},t.a=Object(a.compose)([Object(r.withSelect)((function(e){var t=e("yoast-seo/editor"),n=t.getFocusKeyphrase,r=t.getSEMrushSelectedCountry,a=t.getSEMrushRequestLimitReached,o=t.getSEMrushRequestResponse,s=t.getSEMrushRequestIsSuccess,i=t.getSEMrushIsRequestPending,c=t.getSEMrushRequestHasData,l=t.getSEMrushRequestKeyphrase;return{keyphrase:n(),countryCode:r(),requestLimitReached:a(),response:o(),isSuccess:s(),isPending:i(),requestHasData:c(),lastRequestKeyphrase:l()}})),Object(r.withDispatch)((function(e){var t=e("yoast-seo/editor"),n=t.setSEMrushChangeCountry,r=t.setSEMrushNewRequest,a=t.setSEMrushRequestSucceeded,o=t.setSEMrushRequestFailed,s=t.setSEMrushSetRequestLimitReached,i=t.setSEMrushNoResultsFound;return{setCountry:function(e){n(e)},newRequest:function(e,t){r(e,t)},setRequestSucceeded:function(e){a(e)},setRequestFailed:function(e){o(e)},setRequestLimitReached:function(){s()},setNoResultsFound:function(){i()}}}))])(Q)},,,,,function(e,t,n){"use strict";n.d(t,"a",(function(){return a}));var r=n(2);function a(e){return void 0===e.length?e:Object(r.flatten)(e).sort((function(e,t){return void 0===e.props.renderPriority?1:e.props.renderPriority-t.props.renderPriority}))}},,function(e,t,n){"use strict";var r,a,o,s=n(10),i=n.n(s),c=n(5),l=n.n(c),u=n(7),p=n.n(u),d=n(13),m=n.n(d),f=n(14),b=n.n(f),h=n(8),y=n.n(h),g=n(15),v=n.n(g),O=n(0),j=n(4),w=n(3),k=n(6),E=n(24),_=n(1),T=n.n(_),R=n(12),S=n.n(R),x=n(42),C=n(81),P=n(9),I=S.a.p(r||(r=v()(["\n\tcolor: ",";\n\tmargin: 0;\n\tpadding-right: 8px;\n"])),E.colors.$color_upsell_text),A=S.a.div(a||(a=v()(["\n\tfont-size: 1em;\n\tdisplay: flex;\n\tflex-direction: ",";\n\t",": 4px solid ",";\n\tmargin: 16px 0;\n\tpadding: 0 0 0 8px;\n\tmax-width: 600px;\n\n\t> "," {\n\t\tmargin-bottom: ",";\n\t}\n"])),(function(e){return"horizontal"===e.alignment?"row":"column"}),Object(P.getDirectionalStyle)("border-left","border-right"),E.colors.$color_pink_dark,I,(function(e){return"vertical"===e.alignment&&"16px"})),L=S()(k.SvgIcon)(o||(o=v()(["\n\tmargin: ",";\n\ttransform: ",";\n"])),Object(P.getDirectionalStyle)("0 0 0 4px","0 4px 0 0"),Object(P.getDirectionalStyle)("rotate(0deg)","rotate(180deg)")),N=Object(P.makeOutboundLink)(k.UpsellLinkButton),q=function(e){var t=e.alignment,n=e.url;return Object(O.createElement)(A,{alignment:t},Object(O.createElement)(I,null,Object(w.sprintf)( +/* translators: %s expands to Yoast SEO Premium */ +Object(w.__)("Did you know %s also analyzes the different word forms of your keyphrase, like plurals and past tenses?","wordpress-seo"),"Yoast SEO Premium")),Object(O.createElement)("div",null,Object(O.createElement)(N,{href:n,className:"UpsellLinkButton"},Object(w.sprintf)( +/* translators: %s expands to Premium */ +Object(w.__)("Go %s!","wordpress-seo"),"Premium"),Object(O.createElement)(L,{icon:"arrow-right",size:"8px",color:E.colors.$color_black}))))};q.propTypes={alignment:T.a.oneOf(["horizontal","vertical"]),url:T.a.string.isRequired},q.defaultProps={alignment:"vertical"};var D,M,F=q,B=n(28),K=n(51),U=n(68),H=n(37),Y=n.n(H);var V=S.a.ul(D||(D=v()(['\n\tlist-style: none;\n\tmargin: 0 0 16px;\n\tpadding: 0;\n\n\tli {\n\t\tmargin: 5px 0 0 0;\n\t\tpadding-left: 16px;\n\t}\n\n\tspan[aria-hidden="true"]:before {\n\t\tmargin: 0 8px 0 -16px;\n\t\tfont-weight: bold;\n\t\tcontent: "+";\n\t}\n']))),z=S.a.small(M||(M=v()(["\n\tdisplay: block;\n"]))),W=Object(P.makeOutboundLink)(),G=function(e){m()(a,e);var t,n,r=(t=a,n=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}(),function(){var e,r=y()(t);if(n){var a=y()(this).constructor;e=Reflect.construct(r,arguments,a)}else e=r.apply(this,arguments);return b()(this,e)});function a(e){return l()(this,a),r.call(this,e)}return p()(a,[{key:"createBenefitsList",value:function(e){return e.length>0&&Object(O.createElement)(V,{role:"list"},e.map((function(e,t){return Object(O.createElement)("li",{key:t},Object(O.createElement)("span",{"aria-hidden":"true"}),Y()({mixedString:e.replace("","{{strong}}").replace("","{{/strong}}"),components:{strong:Object(O.createElement)("strong",null)}}))})))}},{key:"createInfoParagraphs",value:function(e){return e.map((function(e,t){return Object(O.createElement)("p",{key:t},e)}))}},{key:"render",value:function(){return Object(O.createElement)("div",null,this.createInfoParagraphs(this.props.infoParagraphs),this.createBenefitsList(this.props.benefits),Object(O.createElement)(W,this.props.upsellButton,this.props.upsellButtonText,this.props.upsellButtonHasCaret&&Object(O.createElement)("span",{"aria-hidden":"true",className:"yoast-button-upsell__caret"})),Object(O.createElement)(z,{id:this.props.upsellButton["aria-describedby"]},this.props.upsellButtonLabel))}}]),a}(O.Component);G.propTypes={benefits:T.a.array,infoParagraphs:T.a.array,upsellButton:T.a.object,upsellButtonText:T.a.string.isRequired,upsellButtonLabel:T.a.string,upsellButtonHasCaret:T.a.bool},G.defaultProps={infoParagraphs:[],benefits:[],upsellButton:{href:"",className:"button button-primary"},upsellButtonLabel:"",upsellButtonHasCaret:!0};var $=G,Z=Object(P.makeOutboundLink)(),J=function(e){var t=Object(w.sprintf)( +/* translators: %1$s expands to a 'Yoast SEO Premium' text linked to the yoast.com website. */ +Object(w.__)("Great news: you can, with %1$s!","wordpress-seo"),"{{link}}Yoast SEO Premium{{/link}}"),n=Y()({mixedString:t,components:{link:Object(O.createElement)(Z,{href:e.link})}}),r=["".concat(Object(w.__)("Rank better with synonyms & related keyphrases","wordpress-seo"),""),Object(w.sprintf)( +/* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */ +Object(w.__)("%1$sNo more dead links%2$s: easy redirect manager","wordpress-seo"),"",""),"".concat(Object(w.__)("Superfast internal linking suggestions","wordpress-seo"),""),Object(w.sprintf)( +/* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */ +Object(w.__)("%1$sSocial media preview%2$s: Facebook & Twitter","wordpress-seo"),"",""),"".concat(Object(w.__)("24/7 email support","wordpress-seo"),""),"".concat(Object(w.__)("No ads!","wordpress-seo"),"")],a=Object(w.sprintf)( +/* translators: %s expands to 'Yoast SEO Premium'. */ +Object(w.__)("Other benefits of %s for you:","wordpress-seo"),"Yoast SEO Premium");return Object(O.createElement)($,{infoParagraphs:[n,a],benefits:r,upsellButtonText:Object(w.sprintf)( +/* translators: %s expands to 'Yoast SEO Premium'. */ +Object(w.__)("Get %s","wordpress-seo"),"Yoast SEO Premium"),upsellButton:{href:e.buyLink,className:"yoast-button-upsell",rel:null},upsellButtonLabel:Object(w.__)("1 year free support and updates included!","wordpress-seo")})};J.propTypes={link:T.a.string.isRequired,buyLink:T.a.string.isRequired};var X=J,Q=Object(P.makeOutboundLink)(),ee=function(e){var t=Object(w.sprintf)( +/* translators: %s expands to a 'Yoast SEO Premium' text linked to the yoast.com website. */ +Object(w.__)("Great news: you can, with %s!","wordpress-seo"),"{{link}}Yoast SEO Premium{{/link}}"),n=[Object(w.sprintf)( +/* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */ +Object(w.__)("%1$sNo more dead links%2$s: easy redirect manager","wordpress-seo"),"",""),"".concat(Object(w.__)("Superfast internal linking suggestions","wordpress-seo"),""),Object(w.sprintf)( +/* translators: %1$s expands to a 'strong' start tag, %2$s to a 'strong' end tag. */ +Object(w.__)("%1$sSocial media preview%2$s: Facebook & Twitter","wordpress-seo"),"",""),"".concat(Object(w.__)("24/7 email support","wordpress-seo"),""),"".concat(Object(w.__)("No ads!","wordpress-seo"),"")],r=Y()({mixedString:t,components:{link:Object(O.createElement)(Q,{href:e.link})}}),a=Object(w.sprintf)( +/* translators: %s expands to 'Yoast SEO Premium'. */ +Object(w.__)("Other benefits of %s for you:","wordpress-seo"),"Yoast SEO Premium");return Object(O.createElement)($,{infoParagraphs:[r,a],benefits:n,upsellButtonText:Object(w.sprintf)( +/* translators: %s expands to 'Yoast SEO Premium'. */ +Object(w.__)("Get %s","wordpress-seo"),"Yoast SEO Premium"),upsellButton:{href:e.buyLink,className:"yoast-button-upsell",rel:null},upsellButtonLabel:Object(w.__)("1 year free support and updates included!","wordpress-seo")})};ee.propTypes={link:T.a.string.isRequired,buyLink:T.a.string.isRequired};var te,ne=ee,re=n(39),ae=n.n(re),oe=n(53),se=S.a.button(te||(te=v()(["\n\t// Increase specificity to override WP rules.\n\t&& {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t}\n\n\t.yoast-svg-icon {\n\t\tmargin: 1px 7px 0 0;\n\t\tfill: currentColor;\n\t}\n"]))),ie={open:Object(w.__)("Open","wordpress-seo"),heading:"",closeIconButton:Object(w.__)("Close","wordpress-seo"),closeButton:""},ce=function(e){var t=Object(O.useState)(!1),n=ae()(t,2),r=n[0],a=n[1],o=Object.assign({},ie,e.labels),s=Object(O.useCallback)((function(){return a(!1)}),[]),i=Object(O.useCallback)((function(){return a(!0)}),[]);return Object(O.createElement)(O.Fragment,null,Object(O.createElement)(se,{type:"button",onClick:i,className:"".concat(e.classes.openButton," yoast-modal__button-open")},e.openButtonIcon&&Object(O.createElement)(k.SvgIcon,{icon:e.openButtonIcon,size:"13px"}),o.open),r&&Object(O.createElement)(oe.a,{onRequestClose:s,className:e.className,title:o.heading},e.children))};ce.propTypes={openButtonIcon:T.a.string,labels:T.a.shape({open:T.a.string,modalAriaLabel:T.a.string.isRequired,heading:T.a.string,closeIconButton:T.a.string,closeButton:T.a.string}).isRequired,classes:T.a.shape({openButton:T.a.string,closeIconButton:T.a.string,closeButton:T.a.string}),className:T.a.string,children:T.a.any.isRequired},ce.defaultProps={className:oe.b,openButtonIcon:"",classes:{}};var le=ce,ue=n(96),pe=n(50),de=n(18);function me(e){var t=e.location;return Object(O.createElement)(de.Slot,{name:"yoast-synonyms-".concat(t)})}me.propTypes={location:T.a.string.isRequired};var fe,be=n(35);function he(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function ye(e){for(var t=1;t191&&e.push(Object(j.__)("Your keyphrase is too long. It can be a maximum of 191 characters.","wordpress-seo")),e}},{key:"render",value:function(){var e=this,t=this.validate();return Object(y.createElement)(U.LocationConsumer,null,(function(n){return Object(y.createElement)("div",{style:"sidebar"===n?{borderBottom:"1px solid #f0f0f0"}:{}},Object(y.createElement)(Y,{location:n},Object(y.createElement)(T.KeywordInput,{id:"focus-keyword-input-".concat(n),onChange:e.props.onFocusKeywordChange,keyword:e.props.keyword,label:Object(j.__)("Focus keyphrase","wordpress-seo"),helpLink:o.renderHelpLink(),onBlurKeyword:e.props.onBlurKeyword,onFocusKeyword:e.props.onFocusKeyword,hasError:t.length>0,errorMessages:t}),e.props.isSEMrushIntegrationActive&&Object(y.createElement)(K,{location:n,keyphrase:e.props.keyword})),Object(y.createElement)(g.Slot,{name:"YoastAfterKeywordInput".concat(n.charAt(0).toUpperCase()+n.slice(1))}))}))}}],[{key:"renderHelpLink",value:function(){return Object(y.createElement)(H.a,{href:wpseoAdminL10n["shortlinks.focus_keyword_info"],className:"dashicons"},Object(y.createElement)("span",{className:"screen-reader-text"},Object(j.__)("Help on choosing the perfect focus keyphrase","wordpress-seo")))}}]),o}(y.Component);V.propTypes={keyword:k.a.string,onFocusKeywordChange:k.a.func.isRequired,onFocusKeyword:k.a.func.isRequired,onBlurKeyword:k.a.func.isRequired,isSEMrushIntegrationActive:k.a.bool,displayNoKeyphraseMessage:k.a.bool},V.defaultProps={keyword:"",isSEMrushIntegrationActive:!1,displayNoKeyphraseMessage:!1},t.a=Object(v.compose)([Object(O.withSelect)((function(e){var t=e("yoast-seo/editor"),n=t.getFocusKeyphrase,r=t.getSEMrushNoKeyphraseMessage;return{keyword:n(),displayNoKeyphraseMessage:r()}})),Object(O.withDispatch)((function(e){var t=e("yoast-seo/editor"),n=t.setFocusKeyword,r=t.setMarkerPauseStatus;return{onFocusKeywordChange:n,onFocusKeyword:function(){return r(!0)},onBlurKeyword:function(){return r(!1)}}}))])(V)},function(e,t,n){"use strict";var r,a,o,s=n(10),i=n.n(s),c=n(5),l=n.n(c),u=n(7),p=n.n(u),d=n(13),m=n.n(d),f=n(14),b=n.n(f),h=n(8),y=n.n(h),g=n(15),v=n.n(g),O=n(0),j=n(4),w=n(1),k=n.n(w),E=n(12),_=n.n(E),T=n(3),R=n(2),S=n(96),x=n(81),C=n(50),P=n(42),I=n(35),A=n(28),L=n(54),N=n(36);function q(e){var t=e.target,n=e.children;return Object(O.createElement)(N.a,{target:t},n)}function D(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function M(e){for(var t=1;t2&&void 0!==arguments[2]?arguments[2]:"content";s()(this,e),this._refresh=t,this._store=n,this._initialData={},this._previousData={},this._tinyMceId=r,this.updateReplacementData=this.updateReplacementData.bind(this),this.refreshYoastSEO=this.refreshYoastSEO.bind(this)}return c()(e,[{key:"initialize",value:function(e){this._initialData=this.getInitialData(e),Object(C.fillReplacementVariables)(this._initialData,this._store),this.subscribeToElements(),this.subscribeToStore(),this.subscribeToSnippetPreviewImage()}},{key:"subscribeToSnippetPreviewImage",value:function(){var e=this;if(!Object(R.isUndefined)(wp.media)&&!Object(R.isUndefined)(wp.media.featuredImage)){N("#postimagediv").on("click","#remove-post-thumbnail",(function(){e.featuredImageIsSet=!1,e.setImageInSnippetPreview(e.getContentImage())}));var t=wp.media.featuredImage.frame();t.on("select",(function(){var n=t.state().get("selection").first().attributes.url;n&&(e.featuredImageIsSet=!0,e.setImageInSnippetPreview(n))})),P.addEventHandler(this._tinyMceId,["init"],(function(){var t=e.getContentImage(),n=e.getFeaturedImage()||t||null;e._store.dispatch(Object(x.c)(t)),e.setImageInSnippetPreview(n)})),P.addEventHandler(this._tinyMceId,["change"],Object(R.debounce)((function(){if(!e.featuredImageIsSet){var t=e.getContentImage();e._store.dispatch(Object(x.c)(t)),e.setImageInSnippetPreview(t)}}),1e3))}}},{key:"getFeaturedImage",value:function(){var e=N("#set-post-thumbnail img").attr("src");return e?(this.featuredImageIsSet=!0,e):(this.featuredImageIsSet=!1,null)}},{key:"setImageInSnippetPreview",value:function(e){this._store.dispatch(Object(S.k)({snippetPreviewImageURL:e}))}},{key:"getContentImage",value:function(){if(this.featuredImageIsSet)return"";var e=this.getContent(),t=T.a.languageProcessing.imageInText(e),n="";if(0===t.length)return n;do{var r=t.shift(),a=(r=N(r)).prop("src");a&&(n=a)}while(""===n&&t.length>0);return n}},{key:"getTitle",value:function(){var e=document.getElementById("title");return e&&e.value||""}},{key:"getExcerpt",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=document.getElementById("excerpt"),n=t&&t.value||"";return""!==n||!1===e?n:Object(C.excerptFromContent)(this.getContent())}},{key:"getSlug",value:function(){var e="",t=document.getElementById("new-post-slug");return t?e=t.value:null!==document.getElementById("editable-post-name-full")&&(e=document.getElementById("editable-post-name-full").textContent),e}},{key:"getContent",value:function(){var e=this._tinyMceId;return L(P.getContentTinyMce(e))}},{key:"subscribeToElements",value:function(){this.subscribeToInputElement("title","title"),this.subscribeToInputElement("excerpt","excerpt"),this.subscribeToInputElement("excerpt","excerpt_only")}},{key:"subscribeToInputElement",value:function(e,t){var n=this,r=document.getElementById(e);r&&r.addEventListener("input",(function(e){n.updateReplacementData(e,t)}))}},{key:"updateReplacementData",value:function(e,t){var n=e.target.value;"excerpt"===t&&""===n&&(n=this.getExcerpt()),this._initialData[t]=n,this._store.dispatch(Object(S.l)(t,n))}},{key:"isShallowEqual",value:function(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(var n in e)if(e.hasOwnProperty(n)&&(!(n in t)||e[n]!==t[n]))return!1;return!0}},{key:"refreshYoastSEO",value:function(){var e=this.getData();!this.isShallowEqual(this._previousData,e)&&(this.handleEditorChange(e),this._previousData=e,window.YoastSEO&&window.YoastSEO.app&&window.YoastSEO.app.refresh())}},{key:"handleEditorChange",value:function(e){this._previousData.excerpt!==e.excerpt&&(this._store.dispatch(Object(S.l)("excerpt",e.excerpt)),this._store.dispatch(Object(S.l)("excerpt_only",e.excerpt_only))),this._previousData.snippetPreviewImageURL!==e.snippetPreviewImageURL&&this.setImageInSnippetPreview(e.snippetPreviewImageURL)}},{key:"subscribeToStore",value:function(){this.subscriber=Object(R.debounce)(this.refreshYoastSEO,500),this._store.subscribe(this.subscriber)}},{key:"getInitialData",value:function(e){return e=Object(C.mapCustomFields)(e,this._store),A(A({},e=Object(C.mapCustomTaxonomies)(e,this._store)),{},{title:this.getTitle(),excerpt:this.getExcerpt(),excerpt_only:this.getExcerpt(!1),slug:this.getSlug(),content:this.getContent()})}},{key:"getData",value:function(){return A(A({},this._store.getState().snippetEditor.data),{},{content:this.getContent(),excerpt:this.getExcerpt(),excerpt_only:this.getExcerpt(!1)})}}]),e}();window.yoast=window.yoast||{},window.yoast.initEditorIntegration=function(e){window.YoastSEO=window.YoastSEO||{},window.YoastSEO._registerReactComponent=w,function(e){var t=Object(g.a)();O=Object(b.createRef)();var n={isRtl:t.isRtl};Object(b.render)(Object(b.createElement)(h.SlotFillProvider,null,Object(b.createElement)(y.a,{target:"wpseo-metabox-root",store:e,theme:n}),Object(b.createElement)(j,{ref:O})),document.getElementById("wpseo-metabox-root")),v.forEach((function(e){O.current.registerComponent(e.key,e.Component)}))}(e)},window.yoast.EditorData=q}]); \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/js/dist/commons-720.min.js b/wp-content/plugins/wordpress-seo/js/dist/commons-720.min.js deleted file mode 100644 index 8fc1b803..00000000 --- a/wp-content/plugins/wordpress-seo/js/dist/commons-720.min.js +++ /dev/null @@ -1,34 +0,0 @@ -!function(e){function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n=window.yoastWebpackJsonp;window.yoastWebpackJsonp=function(r,a,i){for(var l,u,c,s=0,f=[];sF.length&&F.push(e)}function d(e,t,n,o){var a=void 0===e?"undefined":v(e);"undefined"!==a&&"boolean"!==a||(e=null);var i=!1;if(null===e)i=!0;else switch(a){case"string":case"number":i=!0;break;case"object":switch(e.$$typeof){case x:case T:case S:case E:i=!0}}if(i)return n(o,e,""===t?"."+h(e,0):t),1;if(i=0,t=""===t?".":t+":",Array.isArray(e))for(var l=0;lthis.eventPool.length&&this.eventPool.push(e)}function V(e){e.eventPool=[],e.getPooled=H,e.release=z}function B(e,t,n,r){return U.call(this,e,t,n,r)}function W(e,t,n,r){return U.call(this,e,t,n,r)}function K(e,t){switch(e){case"topKeyUp":return-1!==hr.indexOf(t.keyCode);case"topKeyDown":return 229!==t.keyCode;case"topKeyPress":case"topMouseDown":case"topBlur":return!0;default:return!1}}function $(e){return e=e.detail,"object"===(void 0===e?"undefined":bn(e))&&"data"in e?e.data:null}function q(e,t){switch(e){case"topCompositionEnd":return $(t);case"topKeyPress":return 32!==t.which?null:(Tr=!0,wr);case"topTextInput":return e=t.data,e===wr&&Tr?null:e;default:return null}}function Q(e,t){if(Sr)return"topCompositionEnd"===e||!mr&&K(e,t)?(e=L(),fr._root=null,fr._startText=null,fr._fallbackText=null,Sr=!1,e):null;switch(e){case"topPaste":return null;case"topKeyPress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1Br.length&&Br.push(e)}}}function Me(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n["ms"+e]="MS"+t,n["O"+e]="o"+t.toLowerCase(),n}function De(e){if(Qr[e])return Qr[e];if(!qr[e])return e;var t,n=qr[e];for(t in n)if(n.hasOwnProperty(t)&&t in Gr)return Qr[e]=n[t];return""}function Re(e){return Object.prototype.hasOwnProperty.call(e,Jr)||(e[Jr]=Zr++,Xr[e[Jr]]={}),Xr[e[Jr]]}function Fe(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function Le(e,t){var n=Fe(e);e=0;for(var r;n;){if(3===n.nodeType){if(r=e+n.textContent.length,e<=t&&r>=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=Fe(n)}}function je(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&"text"===e.type||"textarea"===t||"true"===e.contentEditable)}function Ue(e,t){if(ao||null==no||no!==Sn())return null;var n=no;return"selectionStart"in n&&je(n)?n={start:n.selectionStart,end:n.selectionEnd}:window.getSelection?(n=window.getSelection(),n={anchorNode:n.anchorNode,anchorOffset:n.anchorOffset,focusNode:n.focusNode,focusOffset:n.focusOffset}):n=void 0,oo&&En(oo,n)?null:(oo=n,e=U.getPooled(to.select,ro,e,t),e.type="select",e.target=no,D(e),e)}function He(e,t,n,r){return U.call(this,e,t,n,r)}function ze(e,t,n,r){return U.call(this,e,t,n,r)}function Ve(e,t,n,r){return U.call(this,e,t,n,r)}function Be(e){var t=e.keyCode;return"charCode"in e?0===(e=e.charCode)&&13===t&&(e=13):e=t,32<=e||13===e?e:0}function We(e,t,n,r){return U.call(this,e,t,n,r)}function Ke(e,t,n,r){return U.call(this,e,t,n,r)}function $e(e,t,n,r){return U.call(this,e,t,n,r)}function qe(e,t,n,r){return U.call(this,e,t,n,r)}function Qe(e,t,n,r){return U.call(this,e,t,n,r)}function Ge(e){0>ho||(e.current=po[ho],po[ho]=null,ho--)}function Ye(e,t){ho++,po[ho]=e.current,e.current=t}function Xe(e){return Je(e)?go:mo.current}function Ze(e,t){var n=e.type.contextTypes;if(!n)return Nn;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var o,a={};for(o in n)a[o]=t[o];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=a),a}function Je(e){return 2===e.tag&&null!=e.type.childContextTypes}function et(e){Je(e)&&(Ge(yo,e),Ge(mo,e))}function tt(e,t,n){null!=mo.cursor&&r("168"),Ye(mo,t,e),Ye(yo,n,e)}function nt(e,t){var n=e.stateNode,o=e.type.childContextTypes;if("function"!=typeof n.getChildContext)return t;n=n.getChildContext();for(var a in n)a in o||r("108",ke(e)||"Unknown",a);return wn({},t,n)}function rt(e){if(!Je(e))return!1;var t=e.stateNode;return t=t&&t.__reactInternalMemoizedMergedChildContext||Nn,go=mo.current,Ye(mo,t,e),Ye(yo,yo.current,e),!0}function ot(e,t){var n=e.stateNode;if(n||r("169"),t){var o=nt(e,go);n.__reactInternalMemoizedMergedChildContext=o,Ge(yo,e),Ge(mo,e),Ye(mo,o,e)}else Ge(yo,e);Ye(yo,t,e)}function at(e,t,n){this.tag=e,this.key=t,this.stateNode=this.type=null,this.sibling=this.child=this.return=null,this.index=0,this.memoizedState=this.updateQueue=this.memoizedProps=this.pendingProps=this.ref=null,this.internalContextTag=n,this.effectTag=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.expirationTime=0,this.alternate=null}function it(e,t,n){var r=e.alternate;return null===r?(r=new at(e.tag,e.key,e.internalContextTag),r.type=e.type,r.stateNode=e.stateNode,r.alternate=e,e.alternate=r):(r.effectTag=0,r.nextEffect=null,r.firstEffect=null,r.lastEffect=null),r.expirationTime=n,r.pendingProps=t,r.child=e.child,r.memoizedProps=e.memoizedProps,r.memoizedState=e.memoizedState,r.updateQueue=e.updateQueue,r.sibling=e.sibling,r.index=e.index,r.ref=e.ref,r}function lt(e,t,n){var o=void 0,a=e.type,i=e.key;return"function"==typeof a?(o=a.prototype&&a.prototype.isReactComponent?new at(2,i,t):new at(0,i,t),o.type=a,o.pendingProps=e.props):"string"==typeof a?(o=new at(5,i,t),o.type=a,o.pendingProps=e.props):"object"===(void 0===a?"undefined":bn(a))&&null!==a&&"number"==typeof a.tag?(o=a,o.pendingProps=e.props):r("130",null==a?a:void 0===a?"undefined":bn(a),""),o.expirationTime=n,o}function ut(e,t,n,r){return t=new at(10,r,t),t.pendingProps=e,t.expirationTime=n,t}function ct(e,t,n){return t=new at(6,null,t),t.pendingProps=e,t.expirationTime=n,t}function st(e,t,n){return t=new at(7,e.key,t),t.type=e.handler,t.pendingProps=e,t.expirationTime=n,t}function ft(e,t,n){return e=new at(9,null,t),e.expirationTime=n,e}function pt(e,t,n){return t=new at(4,e.key,t),t.pendingProps=e.children||[],t.expirationTime=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function dt(e){return function(t){try{return e(t)}catch(e){}}}function ht(e){if("undefined"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__)return!1;var t=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(t.isDisabled||!t.supportsFiber)return!0;try{var n=t.inject(e);vo=dt(function(e){return t.onCommitFiberRoot(n,e)}),bo=dt(function(e){return t.onCommitFiberUnmount(n,e)})}catch(e){}return!0}function mt(e){"function"==typeof vo&&vo(e)}function yt(e){"function"==typeof bo&&bo(e)}function gt(e){return{baseState:e,expirationTime:0,first:null,last:null,callbackList:null,hasForceUpdate:!1,isInitialized:!1}}function vt(e,t){null===e.last?e.first=e.last=t:(e.last.next=t,e.last=t),(0===e.expirationTime||e.expirationTime>t.expirationTime)&&(e.expirationTime=t.expirationTime)}function bt(e,t){var n=e.alternate,r=e.updateQueue;null===r&&(r=e.updateQueue=gt(null)),null!==n?null===(e=n.updateQueue)&&(e=n.updateQueue=gt(null)):e=null,e=e!==r?e:null,null===e?vt(r,t):null===r.last||null===e.last?(vt(r,t),vt(e,t)):(vt(r,t),e.last=t)}function Ct(e,t,n,r){return e=e.partialState,"function"==typeof e?e.call(t,n,r):e}function kt(e,t,n,r,o,a){null!==e&&e.updateQueue===n&&(n=t.updateQueue={baseState:n.baseState,expirationTime:n.expirationTime,first:n.first,last:n.last,isInitialized:n.isInitialized,callbackList:null,hasForceUpdate:!1}),n.expirationTime=0,n.isInitialized?e=n.baseState:(e=n.baseState=t.memoizedState,n.isInitialized=!0);for(var i=!0,l=n.first,u=!1;null!==l;){var c=l.expirationTime;if(c>a){var s=n.expirationTime;(0===s||s>c)&&(n.expirationTime=c),u||(u=!0,n.baseState=e)}else u||(n.first=l.next,null===n.first&&(n.last=null)),l.isReplace?(e=Ct(l,r,e,o),i=!0):(c=Ct(l,r,e,o))&&(e=i?wn({},e,c):wn(e,c),i=!1),l.isForced&&(n.hasForceUpdate=!0),null!==l.callback&&(c=n.callbackList,null===c&&(c=n.callbackList=[]),c.push(l));l=l.next}return null!==n.callbackList?t.effectTag|=32:null!==n.first||n.hasForceUpdate||(t.updateQueue=null),u||(n.baseState=e),e}function wt(e,t){var n=e.callbackList;if(null!==n)for(e.callbackList=null,e=0;ep?(d=f,f=null):d=f.sibling;var g=m(r,f,l[p],u);if(null===g){null===f&&(f=d);break}e&&f&&null===g.alternate&&t(r,f),a=i(g,a,p),null===s?c=g:s.sibling=g,s=g,f=d}if(p===l.length)return n(r,f),c;if(null===f){for(;pd?(g=p,p=null):g=p.sibling;var b=m(a,p,v.value,c);if(null===b){p||(p=g);break}e&&p&&null===b.alternate&&t(a,p),l=i(b,l,d),null===f?s=b:f.sibling=b,f=b,p=g}if(v.done)return n(a,p),s;if(null===p){for(;!v.done;d++,v=u.next())null!==(v=h(a,v.value,c))&&(l=i(v,l,d),null===f?s=v:f.sibling=v,f=v);return s}for(p=o(a,p);!v.done;d++,v=u.next())null!==(v=y(p,a,d,v.value,c))&&(e&&null!==v.alternate&&p.delete(null===v.key?d:v.key),l=i(v,l,d),null===f?s=v:f.sibling=v,f=v);return e&&p.forEach(function(e){return t(a,e)}),s}return function(e,o,i,u){"object"===(void 0===i?"undefined":bn(i))&&null!==i&&i.type===So&&null===i.key&&(i=i.props.children);var c="object"===(void 0===i?"undefined":bn(i))&&null!==i;if(c)switch(i.$$typeof){case ko:e:{var s=i.key;for(c=o;null!==c;){if(c.key===s){if(10===c.tag?i.type===So:c.type===i.type){n(e,c.sibling),o=a(c,i.type===So?i.props.children:i.props,u),o.ref=St(c,i),o.return=e,e=o;break e}n(e,c);break}t(e,c),c=c.sibling}i.type===So?(o=ut(i.props.children,e.internalContextTag,u,i.key),o.return=e,e=o):(u=lt(i,e.internalContextTag,u),u.ref=St(o,i),u.return=e,e=u)}return l(e);case wo:e:{for(c=i.key;null!==o;){if(o.key===c){if(7===o.tag){n(e,o.sibling),o=a(o,i,u),o.return=e,e=o;break e}n(e,o);break}t(e,o),o=o.sibling}o=st(i,e.internalContextTag,u),o.return=e,e=o}return l(e);case xo:e:{if(null!==o){if(9===o.tag){n(e,o.sibling),o=a(o,null,u),o.type=i.value,o.return=e,e=o;break e}n(e,o)}o=ft(i,e.internalContextTag,u),o.type=i.value,o.return=e,e=o}return l(e);case To:e:{for(c=i.key;null!==o;){if(o.key===c){if(4===o.tag&&o.stateNode.containerInfo===i.containerInfo&&o.stateNode.implementation===i.implementation){n(e,o.sibling),o=a(o,i.children||[],u),o.return=e,e=o;break e}n(e,o);break}t(e,o),o=o.sibling}o=pt(i,e.internalContextTag,u),o.return=e,e=o}return l(e)}if("string"==typeof i||"number"==typeof i)return i=""+i,null!==o&&6===o.tag?(n(e,o.sibling),o=a(o,i,u)):(n(e,o),o=ct(i,e.internalContextTag,u)),o.return=e,e=o,l(e);if(Po(i))return g(e,o,i,u);if(Tt(i))return v(e,o,i,u);if(c&&Et(e,i),void 0===i)switch(e.tag){case 2:case 1:u=e.type,r("152",u.displayName||u.name||"Component")}return n(e,o)}}function Ot(e,t,n,o,a){function i(e,t,n){var r=t.expirationTime;t.child=null===e?No(t,null,n,r):Oo(t,e.child,n,r)}function l(e,t){var n=t.ref;null===n||e&&e.ref===n||(t.effectTag|=128)}function u(e,t,n,r){if(l(e,t),!n)return r&&ot(t,!1),s(e,t);n=t.stateNode,Vr.current=t;var o=n.render();return t.effectTag|=1,i(e,t,o),t.memoizedState=n.state,t.memoizedProps=n.props,r&&ot(t,!0),t.child}function c(e){var t=e.stateNode;t.pendingContext?tt(e,t.pendingContext,t.pendingContext!==t.context):t.context&&tt(e,t.context,!1),y(e,t.containerInfo)}function s(e,t){if(null!==e&&t.child!==e.child&&r("153"),null!==t.child){e=t.child;var n=it(e,e.pendingProps,e.expirationTime);for(t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,n=n.sibling=it(e,e.pendingProps,e.expirationTime),n.return=t;n.sibling=null}return t.child}function f(e,t){switch(t.tag){case 3:c(t);break;case 2:rt(t);break;case 4:y(t,t.stateNode.containerInfo)}return null}var p=e.shouldSetTextContent,d=e.useSyncScheduling,h=e.shouldDeprioritizeSubtree,m=t.pushHostContext,y=t.pushHostContainer,g=n.enterHydrationState,v=n.resetHydrationState,b=n.tryToClaimNextHydratableInstance;e=xt(o,a,function(e,t){e.memoizedProps=t},function(e,t){e.memoizedState=t});var C=e.adoptClassInstance,k=e.constructClassInstance,w=e.mountClassInstance,x=e.updateClassInstance;return{beginWork:function(e,t,n){if(0===t.expirationTime||t.expirationTime>n)return f(e,t);switch(t.tag){case 0:null!==e&&r("155");var o=t.type,a=t.pendingProps,T=Xe(t);return T=Ze(t,T),o=o(a,T),t.effectTag|=1,"object"===(void 0===o?"undefined":bn(o))&&null!==o&&"function"==typeof o.render?(t.tag=2,a=rt(t),C(t,o),w(t,n),t=u(e,t,!0,a)):(t.tag=1,i(e,t,o),t.memoizedProps=a,t=t.child),t;case 1:e:{if(a=t.type,n=t.pendingProps,o=t.memoizedProps,yo.current)null===n&&(n=o);else if(null===n||o===n){t=s(e,t);break e}o=Xe(t),o=Ze(t,o),a=a(n,o),t.effectTag|=1,i(e,t,a),t.memoizedProps=n,t=t.child}return t;case 2:return a=rt(t),o=void 0,null===e?t.stateNode?r("153"):(k(t,t.pendingProps),w(t,n),o=!0):o=x(e,t,n),u(e,t,o,a);case 3:return c(t),a=t.updateQueue,null!==a?(o=t.memoizedState,a=kt(e,t,a,null,null,n),o===a?(v(),t=s(e,t)):(o=a.element,T=t.stateNode,(null===e||null===e.child)&&T.hydrate&&g(t)?(t.effectTag|=2,t.child=No(t,null,o,n)):(v(),i(e,t,o)),t.memoizedState=a,t=t.child)):(v(),t=s(e,t)),t;case 5:m(t),null===e&&b(t),a=t.type;var S=t.memoizedProps;return o=t.pendingProps,null===o&&null===(o=S)&&r("154"),T=null!==e?e.memoizedProps:null,yo.current||null!==o&&S!==o?(S=o.children,p(a,o)?S=null:T&&p(a,T)&&(t.effectTag|=16),l(e,t),2147483647!==n&&!d&&h(a,o)?(t.expirationTime=2147483647,t=null):(i(e,t,S),t.memoizedProps=o,t=t.child)):t=s(e,t),t;case 6:return null===e&&b(t),e=t.pendingProps,null===e&&(e=t.memoizedProps),t.memoizedProps=e,null;case 8:t.tag=7;case 7:return a=t.pendingProps,yo.current?null===a&&null===(a=e&&e.memoizedProps)&&r("154"):null!==a&&t.memoizedProps!==a||(a=t.memoizedProps),o=a.children,t.stateNode=null===e?No(t,t.stateNode,o,n):Oo(t,t.stateNode,o,n),t.memoizedProps=a,t.stateNode;case 9:return null;case 4:e:{if(y(t,t.stateNode.containerInfo),a=t.pendingProps,yo.current)null===a&&null==(a=e&&e.memoizedProps)&&r("154");else if(null===a||t.memoizedProps===a){t=s(e,t);break e}null===e?t.child=Oo(t,null,a,n):i(e,t,a),t.memoizedProps=a,t=t.child}return t;case 10:e:{if(n=t.pendingProps,yo.current)null===n&&(n=t.memoizedProps);else if(null===n||t.memoizedProps===n){t=s(e,t);break e}i(e,t,n),t.memoizedProps=n,t=t.child}return t;default:r("156")}},beginFailedWork:function(e,t,n){switch(t.tag){case 2:rt(t);break;case 3:c(t);break;default:r("157")}return t.effectTag|=64,null===e?t.child=null:t.child!==e.child&&(t.child=e.child),0===t.expirationTime||t.expirationTime>n?f(e,t):(t.firstEffect=null,t.lastEffect=null,t.child=null===e?No(t,null,null,n):Oo(t,e.child,null,n),2===t.tag&&(e=t.stateNode,t.memoizedProps=e.props,t.memoizedState=e.state),t.child)}}}function Nt(e,t,n){function o(e){e.effectTag|=4}var a=e.createInstance,i=e.createTextInstance,l=e.appendInitialChild,u=e.finalizeInitialChildren,c=e.prepareUpdate,s=e.persistence,f=t.getRootHostContainer,p=t.popHostContext,d=t.getHostContext,h=t.popHostContainer,m=n.prepareToHydrateHostInstance,y=n.prepareToHydrateHostTextInstance,g=n.popHydrationState,v=void 0,b=void 0,C=void 0;return e.mutation?(v=function(){},b=function(e,t,n){(t.updateQueue=n)&&o(t)},C=function(e,t,n,r){n!==r&&o(t)}):r(s?"235":"236"),{completeWork:function(e,t,n){var s=t.pendingProps;switch(null===s?s=t.memoizedProps:2147483647===t.expirationTime&&2147483647!==n||(t.pendingProps=null),t.tag){case 1:return null;case 2:return et(t),null;case 3:return h(t),Ge(yo,t),Ge(mo,t),s=t.stateNode,s.pendingContext&&(s.context=s.pendingContext,s.pendingContext=null),null!==e&&null!==e.child||(g(t),t.effectTag&=-3),v(t),null;case 5:p(t),n=f();var k=t.type;if(null!==e&&null!=t.stateNode){var w=e.memoizedProps,x=t.stateNode,T=d();x=c(x,k,w,s,n,T),b(e,t,x,k,w,s,n),e.ref!==t.ref&&(t.effectTag|=128)}else{if(!s)return null===t.stateNode&&r("166"),null;if(e=d(),g(t))m(t,n,e)&&o(t);else{e=a(k,s,n,e,t);e:for(w=t.child;null!==w;){if(5===w.tag||6===w.tag)l(e,w.stateNode);else if(4!==w.tag&&null!==w.child){w.child.return=w,w=w.child;continue}if(w===t)break;for(;null===w.sibling;){if(null===w.return||w.return===t)break e;w=w.return}w.sibling.return=w.return,w=w.sibling}u(e,k,s,n)&&o(t),t.stateNode=e}null!==t.ref&&(t.effectTag|=128)}return null;case 6:if(e&&null!=t.stateNode)C(e,t,e.memoizedProps,s);else{if("string"!=typeof s)return null===t.stateNode&&r("166"),null;e=f(),n=d(),g(t)?y(t)&&o(t):t.stateNode=i(s,e,n,t)}return null;case 7:(s=t.memoizedProps)||r("165"),t.tag=8,k=[];e:for((w=t.stateNode)&&(w.return=t);null!==w;){if(5===w.tag||6===w.tag||4===w.tag)r("247");else if(9===w.tag)k.push(w.type);else if(null!==w.child){w.child.return=w,w=w.child;continue}for(;null===w.sibling;){if(null===w.return||w.return===t)break e;w=w.return}w.sibling.return=w.return,w=w.sibling}return w=s.handler,s=w(s.props,k),t.child=Oo(t,null!==e?e.child:null,s,n),t.child;case 8:return t.tag=7,null;case 9:case 10:return null;case 4:return h(t),v(t),null;case 0:r("167");default:r("156")}}}}function It(e,t){function n(e){var n=e.ref;if(null!==n)try{n(null)}catch(n){t(e,n)}}function o(e){switch("function"==typeof yt&&yt(e),e.tag){case 2:n(e);var r=e.stateNode;if("function"==typeof r.componentWillUnmount)try{r.props=e.memoizedProps,r.state=e.memoizedState,r.componentWillUnmount()}catch(n){t(e,n)}break;case 5:n(e);break;case 7:a(e.stateNode);break;case 4:c&&l(e)}}function a(e){for(var t=e;;)if(o(t),null===t.child||c&&4===t.tag){if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return;t=t.return}t.sibling.return=t.return,t=t.sibling}else t.child.return=t,t=t.child}function i(e){return 5===e.tag||3===e.tag||4===e.tag}function l(e){for(var t=e,n=!1,i=void 0,l=void 0;;){if(!n){n=t.return;e:for(;;){switch(null===n&&r("160"),n.tag){case 5:i=n.stateNode,l=!1;break e;case 3:case 4:i=n.stateNode.containerInfo,l=!0;break e}n=n.return}n=!0}if(5===t.tag||6===t.tag)a(t),l?b(i,t.stateNode):v(i,t.stateNode);else if(4===t.tag?i=t.stateNode.containerInfo:o(t),null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return;t=t.return,4===t.tag&&(n=!1)}t.sibling.return=t.return,t=t.sibling}}var u=e.getPublicInstance,c=e.mutation;e=e.persistence,c||r(e?"235":"236");var s=c.commitMount,f=c.commitUpdate,p=c.resetTextContent,d=c.commitTextUpdate,h=c.appendChild,m=c.appendChildToContainer,y=c.insertBefore,g=c.insertInContainerBefore,v=c.removeChild,b=c.removeChildFromContainer;return{commitResetTextContent:function(e){p(e.stateNode)},commitPlacement:function(e){e:{for(var t=e.return;null!==t;){if(i(t)){var n=t;break e}t=t.return}r("160"),n=void 0}var o=t=void 0;switch(n.tag){case 5:t=n.stateNode,o=!1;break;case 3:case 4:t=n.stateNode.containerInfo,o=!0;break;default:r("161")}16&n.effectTag&&(p(t),n.effectTag&=-17);e:t:for(n=e;;){for(;null===n.sibling;){if(null===n.return||i(n.return)){n=null;break e}n=n.return}for(n.sibling.return=n.return,n=n.sibling;5!==n.tag&&6!==n.tag;){if(2&n.effectTag)continue t;if(null===n.child||4===n.tag)continue t;n.child.return=n,n=n.child}if(!(2&n.effectTag)){n=n.stateNode;break e}}for(var a=e;;){if(5===a.tag||6===a.tag)n?o?g(t,a.stateNode,n):y(t,a.stateNode,n):o?m(t,a.stateNode):h(t,a.stateNode);else if(4!==a.tag&&null!==a.child){a.child.return=a,a=a.child;continue}if(a===e)break;for(;null===a.sibling;){if(null===a.return||a.return===e)return;a=a.return}a.sibling.return=a.return,a=a.sibling}},commitDeletion:function(e){l(e),e.return=null,e.child=null,e.alternate&&(e.alternate.child=null,e.alternate.return=null)},commitWork:function(e,t){switch(t.tag){case 2:break;case 5:var n=t.stateNode;if(null!=n){var o=t.memoizedProps;e=null!==e?e.memoizedProps:o;var a=t.type,i=t.updateQueue;t.updateQueue=null,null!==i&&f(n,i,a,e,o,t)}break;case 6:null===t.stateNode&&r("162"),n=t.memoizedProps,d(t.stateNode,null!==e?e.memoizedProps:n,n);break;case 3:break;default:r("163")}},commitLifeCycles:function(e,t){switch(t.tag){case 2:var n=t.stateNode;if(4&t.effectTag)if(null===e)n.props=t.memoizedProps,n.state=t.memoizedState,n.componentDidMount();else{var o=e.memoizedProps;e=e.memoizedState,n.props=t.memoizedProps,n.state=t.memoizedState,n.componentDidUpdate(o,e)}t=t.updateQueue,null!==t&&wt(t,n);break;case 3:n=t.updateQueue,null!==n&&wt(n,null!==t.child?t.child.stateNode:null);break;case 5:n=t.stateNode,null===e&&4&t.effectTag&&s(n,t.type,t.memoizedProps,t);break;case 6:case 4:break;default:r("163")}},commitAttachRef:function(e){var t=e.ref;if(null!==t){var n=e.stateNode;switch(e.tag){case 5:t(u(n));break;default:t(n)}}},commitDetachRef:function(e){null!==(e=e.ref)&&e(null)}}}function _t(e){function t(e){return e===Io&&r("174"),e}var n=e.getChildHostContext,o=e.getRootHostContext,a={current:Io},i={current:Io},l={current:Io};return{getHostContext:function(){return t(a.current)},getRootHostContainer:function(){return t(l.current)},popHostContainer:function(e){Ge(a,e),Ge(i,e),Ge(l,e)},popHostContext:function(e){i.current===e&&(Ge(a,e),Ge(i,e))},pushHostContainer:function(e,t){Ye(l,t,e),t=o(t),Ye(i,e,e),Ye(a,t,e)},pushHostContext:function(e){var r=t(l.current),o=t(a.current);r=n(o,e.type,r),o!==r&&(Ye(i,e,e),Ye(a,r,e))},resetHostContainer:function(){a.current=Io,l.current=Io}}}function At(e){function t(e,t){var n=new at(5,null,0);n.type="DELETED",n.stateNode=t,n.return=e,n.effectTag=8,null!==e.lastEffect?(e.lastEffect.nextEffect=n,e.lastEffect=n):e.firstEffect=e.lastEffect=n}function n(e,t){switch(e.tag){case 5:return null!==(t=i(t,e.type,e.pendingProps))&&(e.stateNode=t,!0);case 6:return null!==(t=l(t,e.pendingProps))&&(e.stateNode=t,!0);default:return!1}}function o(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag;)e=e.return;p=e}var a=e.shouldSetTextContent;if(!(e=e.hydration))return{enterHydrationState:function(){return!1},resetHydrationState:function(){},tryToClaimNextHydratableInstance:function(){},prepareToHydrateHostInstance:function(){r("175")},prepareToHydrateHostTextInstance:function(){r("176")},popHydrationState:function(){return!1}};var i=e.canHydrateInstance,l=e.canHydrateTextInstance,u=e.getNextHydratableSibling,c=e.getFirstHydratableChild,s=e.hydrateInstance,f=e.hydrateTextInstance,p=null,d=null,h=!1;return{enterHydrationState:function(e){return d=c(e.stateNode.containerInfo),p=e,h=!0},resetHydrationState:function(){d=p=null,h=!1},tryToClaimNextHydratableInstance:function(e){if(h){var r=d;if(r){if(!n(e,r)){if(!(r=u(r))||!n(e,r))return e.effectTag|=2,h=!1,void(p=e);t(p,d)}p=e,d=c(r)}else e.effectTag|=2,h=!1,p=e}},prepareToHydrateHostInstance:function(e,t,n){return t=s(e.stateNode,e.type,e.memoizedProps,t,n,e),e.updateQueue=t,null!==t},prepareToHydrateHostTextInstance:function(e){return f(e.stateNode,e.memoizedProps,e)},popHydrationState:function(e){if(e!==p)return!1;if(!h)return o(e),h=!0,!1;var n=e.type;if(5!==e.tag||"head"!==n&&"body"!==n&&!a(n,e.memoizedProps))for(n=d;n;)t(e,n),n=u(n);return o(e),d=p?u(e.stateNode):null,!0}}}function Mt(e){function t(e){ae=G=!0;var t=e.stateNode;if(t.current===e&&r("177"),t.isReadyForCommit=!1,Vr.current=null,1i.expirationTime)&&(a=i.expirationTime),i=i.sibling;o.expirationTime=a}if(null!==t)return t;if(null!==n&&(null===n.firstEffect&&(n.firstEffect=e.firstEffect),null!==e.lastEffect&&(null!==n.lastEffect&&(n.lastEffect.nextEffect=e.firstEffect),n.lastEffect=e.lastEffect),1e))if(Z<=q)for(;null!==Y;)Y=c(Y)?a(Y):o(Y);else for(;null!==Y&&!w();)Y=c(Y)?a(Y):o(Y)}else if(!(0===Z||Z>e))if(Z<=q)for(;null!==Y;)Y=o(Y);else for(;null!==Y&&!w();)Y=o(Y)}function l(e,t){if(G&&r("243"),G=!0,e.isReadyForCommit=!1,e!==X||t!==Z||null===Y){for(;-1t)&&(e.expirationTime=t),null!==e.alternate&&(0===e.alternate.expirationTime||e.alternate.expirationTime>t)&&(e.alternate.expirationTime=t),null===e.return){if(3!==e.tag)break;var n=e.stateNode;!G&&n===X&&tCe&&r("185"),null===o.nextScheduledRoot)o.remainingExpirationTime=a,null===ue?(le=ue=o,o.nextScheduledRoot=o):(ue=ue.nextScheduledRoot=o,ue.nextScheduledRoot=le);else{var i=o.remainingExpirationTime;(0===i||ace)return;V(se)}var t=H()-$;ce=e,se=z(b,{timeout:10*(e-2)-t})}function v(){var e=0,t=null;if(null!==ue)for(var n=ue,o=le;null!==o;){var a=o.remainingExpirationTime;if(0===a){if((null===n||null===ue)&&r("244"),o===o.nextScheduledRoot){le=ue=o.nextScheduledRoot=null;break}if(o===le)le=a=o.nextScheduledRoot,ue.nextScheduledRoot=a,o.nextScheduledRoot=null;else{if(o===ue){ue=n,ue.nextScheduledRoot=le,o.nextScheduledRoot=null;break}n.nextScheduledRoot=o.nextScheduledRoot,o.nextScheduledRoot=null}o=n.nextScheduledRoot}else{if((0===e||axe)&&(he=!0)}function x(e){null===pe&&r("246"),pe.remainingExpirationTime=0,me||(me=!0,ye=e)}var T=_t(e),S=At(e),E=T.popHostContainer,P=T.popHostContext,O=T.resetHostContainer,N=Ot(e,T,S,d,p),I=N.beginWork,_=N.beginFailedWork,A=Nt(e,T,S).completeWork;T=It(e,u);var M=T.commitResetTextContent,D=T.commitPlacement,R=T.commitDeletion,F=T.commitWork,L=T.commitLifeCycles,j=T.commitAttachRef,U=T.commitDetachRef,H=e.now,z=e.scheduleDeferredCallback,V=e.cancelDeferredCallback,B=e.useSyncScheduling,W=e.prepareForCommit,K=e.resetAfterCommit,$=H(),q=2,Q=0,G=!1,Y=null,X=null,Z=0,J=null,ee=null,te=null,ne=null,re=null,oe=!1,ae=!1,ie=!1,le=null,ue=null,ce=0,se=-1,fe=!1,pe=null,de=0,he=!1,me=!1,ye=null,ge=null,ve=!1,be=!1,Ce=1e3,we=0,xe=1;return{computeAsyncExpiration:f,computeExpirationForFiber:p,scheduleWork:d,batchedUpdates:function(e,t){var n=ve;ve=!0;try{return e(t)}finally{(ve=n)||fe||C(1,null)}},unbatchedUpdates:function(e){if(ve&&!be){be=!0;try{return e()}finally{be=!1}}return e()},flushSync:function(e){var t=ve;ve=!0;try{e:{var n=Q;Q=1;try{var o=e();break e}finally{Q=n}o=void 0}return o}finally{ve=t,fe&&r("187"),C(1,null)}},deferredUpdates:function(e){var t=Q;Q=f();try{return e()}finally{Q=t}}}}function Dt(e){function t(e){return e=Ee(e),null===e?null:e.stateNode}var n=e.getPublicInstance;e=Mt(e);var o=e.computeAsyncExpiration,a=e.computeExpirationForFiber,i=e.scheduleWork;return{createContainer:function(e,t){var n=new at(3,null,0);return e={current:n,containerInfo:e,pendingChildren:null,remainingExpirationTime:0,isReadyForCommit:!1,finishedWork:null,context:null,pendingContext:null,hydrate:t,nextScheduledRoot:null},n.stateNode=e},updateContainer:function(e,t,n,l){var u=t.current;if(n){n=n._reactInternalFiber;var c;e:{for(2===we(n)&&2===n.tag||r("170"),c=n;3!==c.tag;){if(Je(c)){c=c.stateNode.__reactInternalMemoizedMergedChildContext;break e}(c=c.return)||r("171")}c=c.stateNode.context}n=Je(n)?nt(n,c):c}else n=Nn;null===t.context?t.context=n:t.pendingContext=n,t=l,t=void 0===t?null:t,l=null!=e&&null!=e.type&&null!=e.type.prototype&&!0===e.type.prototype.unstable_isAsyncReactComponent?o():a(u),bt(u,{expirationTime:l,partialState:{element:e},callback:t,isReplace:!1,isForced:!1,nextCallback:null,next:null}),i(u,l)},batchedUpdates:e.batchedUpdates,unbatchedUpdates:e.unbatchedUpdates,deferredUpdates:e.deferredUpdates,flushSync:e.flushSync,getPublicRootInstance:function(e){if(e=e.current,!e.child)return null;switch(e.child.tag){case 5:return n(e.child.stateNode);default:return e.child.stateNode}},findHostInstance:t,findHostInstanceWithNoPortals:function(e){return e=Pe(e),null===e?null:e.stateNode},injectIntoDevTools:function(e){var n=e.findFiberByHostInstance;return ht(wn({},e,{findHostInstanceByFiber:function(e){return t(e)},findFiberByHostInstance:function(e){return n?n(e):null}}))}}}function Rt(e,t,n){var r=3n||r.hasOverloadedBooleanValue&&!1===n?Ut(e,t):r.mustUseProperty?e[r.propertyName]=n:(t=r.attributeName,(o=r.attributeNamespace)?e.setAttributeNS(o,t,""+n):r.hasBooleanValue||r.hasOverloadedBooleanValue&&!0===n?e.setAttribute(t,""):e.setAttribute(t,""+n))}else jt(e,t,a(t,n)?n:null)}function jt(e,t,n){Ft(t)&&(null==n?e.removeAttribute(t):e.setAttribute(t,""+n))}function Ut(e,t){var n=i(t);n?(t=n.mutationMethod)?t(e,void 0):n.mustUseProperty?e[n.propertyName]=!n.hasBooleanValue&&"":e.removeAttribute(n.attributeName):e.removeAttribute(t)}function Ht(e,t){var n=t.value,r=t.checked;return wn({type:void 0,step:void 0,min:void 0,max:void 0},t,{defaultChecked:void 0,defaultValue:void 0,value:null!=n?n:e._wrapperState.initialValue,checked:null!=r?r:e._wrapperState.initialChecked})}function zt(e,t){var n=t.defaultValue;e._wrapperState={initialChecked:null!=t.checked?t.checked:t.defaultChecked,initialValue:null!=t.value?t.value:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function Vt(e,t){null!=(t=t.checked)&&Lt(e,"checked",t)}function Bt(e,t){Vt(e,t);var n=t.value;null!=n?0===n&&""===e.value?e.value="0":"number"===t.type?(t=parseFloat(e.value)||0,(n!=t||n==t&&e.value!=n)&&(e.value=""+n)):e.value!==""+n&&(e.value=""+n):(null==t.value&&null!=t.defaultValue&&e.defaultValue!==""+t.defaultValue&&(e.defaultValue=""+t.defaultValue),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked))}function Wt(e,t){switch(t.type){case"submit":case"reset":break;case"color":case"date":case"datetime":case"datetime-local":case"month":case"time":case"week":e.value="",e.value=e.defaultValue;break;default:e.value=e.value}t=e.name,""!==t&&(e.name=""),e.defaultChecked=!e.defaultChecked,e.defaultChecked=!e.defaultChecked,""!==t&&(e.name=t)}function Kt(e){var t="";return Cn.Children.forEach(e,function(e){null==e||"string"!=typeof e&&"number"!=typeof e||(t+=e)}),t}function $t(e,t){return e=wn({children:void 0},t),(t=Kt(t.children))&&(e.children=t),e}function qt(e,t,n,r){if(e=e.options,t){t={};for(var o=0;o=t.length||r("93"),t=t[0]),n=""+t),null==n&&(n="")),e._wrapperState={initialValue:""+n}}function Xt(e,t){var n=t.value;null!=n&&(n=""+n,n!==e.value&&(e.value=n),null==t.defaultValue&&(e.defaultValue=n)),null!=t.defaultValue&&(e.defaultValue=t.defaultValue)}function Zt(e){var t=e.textContent;t===e._wrapperState.initialValue&&(e.value=t)}function Jt(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function en(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?Jt(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}function tn(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}function nn(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),o=n,a=t[n];o=null==a||"boolean"==typeof a||""===a?"":r||"number"!=typeof a||0===a||ea.hasOwnProperty(o)&&ea[o]?(""+a).trim():a+"px","float"===n&&(n="cssFloat"),r?e.setProperty(n,o):e[n]=o}}function rn(e,t,n){t&&(na[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML)&&r("137",e,n()),null!=t.dangerouslySetInnerHTML&&(null!=t.children&&r("60"),"object"===bn(t.dangerouslySetInnerHTML)&&"__html"in t.dangerouslySetInnerHTML||r("61")),null!=t.style&&"object"!==bn(t.style)&&r("62",n()))}function on(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}function an(e,t){e=9===e.nodeType||11===e.nodeType?e:e.ownerDocument;var n=Re(e);t=Xn[t];for(var r=0;r<\/script>",e=e.removeChild(e.firstChild)):e="string"==typeof t.is?n.createElement(e,{is:t.is}):n.createElement(e):e=n.createElementNS(r,e),e}function un(e,t){return(9===t.nodeType?t:t.ownerDocument).createTextNode(e)}function cn(e,t,n,r){var o=on(t,n);switch(t){case"iframe":case"object":Ie("topLoad","load",e);var a=n;break;case"video":case"audio":for(a in aa)aa.hasOwnProperty(a)&&Ie(a,aa[a],e);a=n;break;case"source":Ie("topError","error",e),a=n;break;case"img":case"image":Ie("topError","error",e),Ie("topLoad","load",e),a=n;break;case"form":Ie("topReset","reset",e),Ie("topSubmit","submit",e),a=n;break;case"details":Ie("topToggle","toggle",e),a=n;break;case"input":zt(e,n),a=Ht(e,n),Ie("topInvalid","invalid",e),an(r,"onChange");break;case"option":a=$t(e,n);break;case"select":Qt(e,n),a=wn({},n,{value:void 0}),Ie("topInvalid","invalid",e),an(r,"onChange");break;case"textarea":Yt(e,n),a=Gt(e,n),Ie("topInvalid","invalid",e),an(r,"onChange");break;default:a=n}rn(t,a,oa);var i,l=a;for(i in l)if(l.hasOwnProperty(i)){var u=l[i];"style"===i?nn(e,u,oa):"dangerouslySetInnerHTML"===i?null!=(u=u?u.__html:void 0)&&Jo(e,u):"children"===i?"string"==typeof u?("textarea"!==t||""!==u)&&tn(e,u):"number"==typeof u&&tn(e,""+u):"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&"autoFocus"!==i&&(Yn.hasOwnProperty(i)?null!=u&&an(r,i):o?jt(e,i,u):null!=u&&Lt(e,i,u))}switch(t){case"input":ae(e),Wt(e,n);break;case"textarea":ae(e),Zt(e,n);break;case"option":null!=n.value&&e.setAttribute("value",n.value);break;case"select":e.multiple=!!n.multiple,t=n.value,null!=t?qt(e,!!n.multiple,t,!1):null!=n.defaultValue&&qt(e,!!n.multiple,n.defaultValue,!0);break;default:"function"==typeof a.onClick&&(e.onclick=xn)}}function sn(e,t,n,r,o){var a=null;switch(t){case"input":n=Ht(e,n),r=Ht(e,r),a=[];break;case"option":n=$t(e,n),r=$t(e,r),a=[];break;case"select":n=wn({},n,{value:void 0}),r=wn({},r,{value:void 0}),a=[];break;case"textarea":n=Gt(e,n),r=Gt(e,r),a=[];break;default:"function"!=typeof n.onClick&&"function"==typeof r.onClick&&(e.onclick=xn)}rn(t,r,oa);var i,l;e=null;for(i in n)if(!r.hasOwnProperty(i)&&n.hasOwnProperty(i)&&null!=n[i])if("style"===i)for(l in t=n[i])t.hasOwnProperty(l)&&(e||(e={}),e[l]="");else"dangerouslySetInnerHTML"!==i&&"children"!==i&&"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&"autoFocus"!==i&&(Yn.hasOwnProperty(i)?a||(a=[]):(a=a||[]).push(i,null));for(i in r){var u=r[i];if(t=null!=n?n[i]:void 0,r.hasOwnProperty(i)&&u!==t&&(null!=u||null!=t))if("style"===i)if(t){for(l in t)!t.hasOwnProperty(l)||u&&u.hasOwnProperty(l)||(e||(e={}),e[l]="");for(l in u)u.hasOwnProperty(l)&&t[l]!==u[l]&&(e||(e={}),e[l]=u[l])}else e||(a||(a=[]),a.push(i,e)),e=u;else"dangerouslySetInnerHTML"===i?(u=u?u.__html:void 0,t=t?t.__html:void 0,null!=u&&t!==u&&(a=a||[]).push(i,""+u)):"children"===i?t===u||"string"!=typeof u&&"number"!=typeof u||(a=a||[]).push(i,""+u):"suppressContentEditableWarning"!==i&&"suppressHydrationWarning"!==i&&(Yn.hasOwnProperty(i)?(null!=u&&an(o,i),a||t===u||(a=[])):(a=a||[]).push(i,u))}return e&&(a=a||[]).push("style",e),a}function fn(e,t,n,r,o){"input"===n&&"radio"===o.type&&null!=o.name&&Vt(e,o),on(n,r),r=on(n,o);for(var a=0;a=u.hasBooleanValue+u.hasNumericValue+u.hasOverloadedBooleanValue||r("50",l),i.hasOwnProperty(l)&&(u.attributeName=i[l]),a.hasOwnProperty(l)&&(u.attributeNamespace=a[l]),e.hasOwnProperty(l)&&(u.mutationMethod=e[l]),An[l]=u}}},An={},Mn=_n,Dn=Mn.MUST_USE_PROPERTY,Rn=Mn.HAS_BOOLEAN_VALUE,Fn=Mn.HAS_NUMERIC_VALUE,Ln=Mn.HAS_POSITIVE_NUMERIC_VALUE,jn=Mn.HAS_OVERLOADED_BOOLEAN_VALUE,Un=Mn.HAS_STRING_BOOLEAN_VALUE,Hn={Properties:{allowFullScreen:Rn,async:Rn,autoFocus:Rn,autoPlay:Rn,capture:jn,checked:Dn|Rn,cols:Ln,contentEditable:Un,controls:Rn,default:Rn,defer:Rn,disabled:Rn,download:jn,draggable:Un,formNoValidate:Rn,hidden:Rn,loop:Rn,multiple:Dn|Rn,muted:Dn|Rn,noValidate:Rn,open:Rn,playsInline:Rn,readOnly:Rn,required:Rn,reversed:Rn,rows:Ln,rowSpan:Fn,scoped:Rn,seamless:Rn,selected:Dn|Rn,size:Ln,start:Fn,span:Ln,spellCheck:Un,style:0,tabIndex:0,itemScope:Rn,acceptCharset:0,className:0,htmlFor:0,httpEquiv:0,value:Un},DOMAttributeNames:{acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMMutationMethods:{value:function(e,t){if(null==t)return e.removeAttribute("value");"number"!==e.type||!1===e.hasAttribute("value")?e.setAttribute("value",""+t):e.validity&&!e.validity.badInput&&e.ownerDocument.activeElement!==e&&e.setAttribute("value",""+t)}}},zn=Mn.HAS_STRING_BOOLEAN_VALUE,Vn={xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace"},Bn={Properties:{autoReverse:zn,externalResourcesRequired:zn,preserveAlpha:zn},DOMAttributeNames:{autoReverse:"autoReverse",externalResourcesRequired:"externalResourcesRequired",preserveAlpha:"preserveAlpha"},DOMAttributeNamespaces:{xlinkActuate:Vn.xlink,xlinkArcrole:Vn.xlink,xlinkHref:Vn.xlink,xlinkRole:Vn.xlink,xlinkShow:Vn.xlink,xlinkTitle:Vn.xlink,xlinkType:Vn.xlink,xmlBase:Vn.xml,xmlLang:Vn.xml,xmlSpace:Vn.xml}},Wn=/[\-\:]([a-z])/g;"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode x-height xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xmlns:xlink xml:lang xml:space".split(" ").forEach(function(e){var t=e.replace(Wn,l);Bn.Properties[t]=0,Bn.DOMAttributeNames[t]=e}),Mn.injectDOMPropertyConfig(Hn),Mn.injectDOMPropertyConfig(Bn);var Kn={_caughtError:null,_hasCaughtError:!1,_rethrowError:null,_hasRethrowError:!1,injection:{injectErrorUtils:function(e){"function"!=typeof e.invokeGuardedCallback&&r("197"),u=e.invokeGuardedCallback}},invokeGuardedCallback:function(e,t,n,r,o,a,i,l,c){u.apply(Kn,arguments)},invokeGuardedCallbackAndCatchFirstError:function(e,t,n,r,o,a,i,l,u){if(Kn.invokeGuardedCallback.apply(this,arguments),Kn.hasCaughtError()){var c=Kn.clearCaughtError();Kn._hasRethrowError||(Kn._hasRethrowError=!0,Kn._rethrowError=c)}},rethrowCaughtError:function(){return c.apply(Kn,arguments)},hasCaughtError:function(){return Kn._hasCaughtError},clearCaughtError:function(){if(Kn._hasCaughtError){var e=Kn._caughtError;return Kn._caughtError=null,Kn._hasCaughtError=!1,e}r("198")}},$n=null,qn={},Qn=[],Gn={},Yn={},Xn={},Zn=Object.freeze({plugins:Qn,eventNameDispatchConfigs:Gn,registrationNameModules:Yn,registrationNameDependencies:Xn,possibleRegistrationNames:null,injectEventPluginOrder:p,injectEventPluginsByName:d}),Jn=null,er=null,tr=null,nr=null,rr={injectEventPluginOrder:p,injectEventPluginsByName:d},or=Object.freeze({injection:rr,getListener:C,extractEvents:k,enqueueEvents:w,processEventQueue:x}),ar=Math.random().toString(36).slice(2),ir="__reactInternalInstance$"+ar,lr="__reactEventHandlers$"+ar,ur=Object.freeze({precacheFiberNode:function(e,t){t[ir]=e},getClosestInstanceFromNode:T,getInstanceFromNode:function(e){return e=e[ir],!e||5!==e.tag&&6!==e.tag?null:e},getNodeFromInstance:S,getFiberCurrentPropsFromNode:E,updateFiberProps:function(e,t){e[lr]=t}}),cr=Object.freeze({accumulateTwoPhaseDispatches:D,accumulateTwoPhaseDispatchesSkipTarget:function(e){y(e,_)},accumulateEnterLeaveDispatches:R,accumulateDirectDispatches:function(e){y(e,M)}}),sr=null,fr={_root:null,_startText:null,_fallbackText:null},pr="dispatchConfig _targetInst nativeEvent isDefaultPrevented isPropagationStopped _dispatchListeners _dispatchInstances".split(" "),dr={type:null,target:null,currentTarget:xn.thatReturnsNull,eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(e){return e.timeStamp||Date.now()},defaultPrevented:null,isTrusted:null};wn(U.prototype,{preventDefault:function(){this.defaultPrevented=!0;var e=this.nativeEvent;e&&(e.preventDefault?e.preventDefault():"unknown"!=typeof e.returnValue&&(e.returnValue=!1),this.isDefaultPrevented=xn.thatReturnsTrue)},stopPropagation:function(){var e=this.nativeEvent;e&&(e.stopPropagation?e.stopPropagation():"unknown"!=typeof e.cancelBubble&&(e.cancelBubble=!0),this.isPropagationStopped=xn.thatReturnsTrue)},persist:function(){this.isPersistent=xn.thatReturnsTrue},isPersistent:xn.thatReturnsFalse,destructor:function(){var e,t=this.constructor.Interface;for(e in t)this[e]=null;for(t=0;t=parseInt(vr.version(),10))}var br,Cr=gr,kr=kn.canUseDOM&&(!mr||yr&&8=yr),wr=String.fromCharCode(32),xr={beforeInput:{phasedRegistrationNames:{bubbled:"onBeforeInput",captured:"onBeforeInputCapture"},dependencies:["topCompositionEnd","topKeyPress","topTextInput","topPaste"]},compositionEnd:{phasedRegistrationNames:{bubbled:"onCompositionEnd",captured:"onCompositionEndCapture"},dependencies:"topBlur topCompositionEnd topKeyDown topKeyPress topKeyUp topMouseDown".split(" ")},compositionStart:{phasedRegistrationNames:{bubbled:"onCompositionStart",captured:"onCompositionStartCapture"},dependencies:"topBlur topCompositionStart topKeyDown topKeyPress topKeyUp topMouseDown".split(" ")},compositionUpdate:{phasedRegistrationNames:{bubbled:"onCompositionUpdate",captured:"onCompositionUpdateCapture"},dependencies:"topBlur topCompositionUpdate topKeyDown topKeyPress topKeyUp topMouseDown".split(" ")}},Tr=!1,Sr=!1,Er={eventTypes:xr,extractEvents:function(e,t,n,r){var o;if(mr)e:{switch(e){case"topCompositionStart":var a=xr.compositionStart;break e;case"topCompositionEnd":a=xr.compositionEnd;break e;case"topCompositionUpdate":a=xr.compositionUpdate;break e}a=void 0}else Sr?K(e,n)&&(a=xr.compositionEnd):"topKeyDown"===e&&229===n.keyCode&&(a=xr.compositionStart);return a?(kr&&(Sr||a!==xr.compositionStart?a===xr.compositionEnd&&Sr&&(o=L()):(fr._root=r,fr._startText=j(),Sr=!0)),a=B.getPooled(a,t,n,r),o?a.data=o:null!==(o=$(n))&&(a.data=o),D(a),o=a):o=null,(e=Cr?q(e,n):Q(e,n))?(t=W.getPooled(xr.beforeInput,t,n,r),t.data=e,D(t)):t=null,[o,t]}},Pr=null,Or=null,Nr=null,Ir={injectFiberControlledHostComponent:function(e){Pr=e}},_r=Object.freeze({injection:Ir,enqueueStateRestore:Y,restoreStateIfNeeded:X}),Ar=!1,Mr={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};kn.canUseDOM&&(br=document.implementation&&document.implementation.hasFeature&&!0!==document.implementation.hasFeature("",""));var Dr={change:{phasedRegistrationNames:{bubbled:"onChange",captured:"onChangeCapture"},dependencies:"topBlur topChange topClick topFocus topInput topKeyDown topKeyUp topSelectionChange".split(" ")}},Rr=null,Fr=null,Lr=!1;kn.canUseDOM&&(Lr=ne("input")&&(!document.documentMode||9=document.documentMode,to={select:{phasedRegistrationNames:{bubbled:"onSelect",captured:"onSelectCapture"},dependencies:"topBlur topContextMenu topFocus topKeyDown topKeyUp topMouseDown topMouseUp topSelectionChange".split(" ")}},no=null,ro=null,oo=null,ao=!1,io={eventTypes:to,extractEvents:function(e,t,n,r){var o,a=r.window===r?r.document:9===r.nodeType?r:r.ownerDocument;if(!(o=!a)){e:{a=Re(a),o=Xn.onSelect;for(var i=0;i=Bo-e){if(!(-1!==zo&&zo<=e))return void(Vo||(Vo=!0,requestAnimationFrame(qo)));jo.didTimeout=!0}else jo.didTimeout=!1;zo=-1,e=Uo,Uo=null,null!==e&&e(jo)}},!1);var qo=function(e){Vo=!1;var t=e-Bo+Ko;tt&&(t=8),Ko=t"+t+"",t=Zo.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}}),ea={animationIterationCount:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},ta=["Webkit","ms","Moz","O"];Object.keys(ea).forEach(function(e){ta.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),ea[t]=ea[e]})});var na=wn({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0}),ra=Xo.html,oa=xn.thatReturns(""),aa={topAbort:"abort",topCanPlay:"canplay",topCanPlayThrough:"canplaythrough",topDurationChange:"durationchange",topEmptied:"emptied",topEncrypted:"encrypted",topEnded:"ended",topError:"error",topLoadedData:"loadeddata",topLoadedMetadata:"loadedmetadata",topLoadStart:"loadstart",topPause:"pause",topPlay:"play",topPlaying:"playing",topProgress:"progress",topRateChange:"ratechange",topSeeked:"seeked",topSeeking:"seeking",topStalled:"stalled",topSuspend:"suspend",topTimeUpdate:"timeupdate",topVolumeChange:"volumechange",topWaiting:"waiting"},ia=Object.freeze({createElement:ln,createTextNode:un,setInitialProperties:cn,diffProperties:sn,updateProperties:fn,diffHydratedProperties:pn,diffHydratedText:dn,warnForUnmatchedText:function(){},warnForDeletedHydratableElement:function(){},warnForDeletedHydratableText:function(){},warnForInsertedHydratedElement:function(){},warnForInsertedHydratedText:function(){},restoreControlledState:function(e,t,n){switch(t){case"input":if(Bt(e,n),t=n.name,"radio"===n.type&&null!=t){for(n=e;n.parentNode;)n=n.parentNode;for(n=n.querySelectorAll("input[name="+JSON.stringify(""+t)+'][type="radio"]'),t=0;tr&&(o=r,r=e,e=o),o=Le(n,e);var a=Le(n,r);if(o&&a&&(1!==t.rangeCount||t.anchorNode!==o.node||t.anchorOffset!==o.offset||t.focusNode!==a.node||t.focusOffset!==a.offset)){var i=document.createRange();i.setStart(o.node,o.offset),t.removeAllRanges(),e>r?(t.addRange(i),t.extend(a.node,a.offset)):(i.setEnd(a.node,a.offset),t.addRange(i))}}for(t=[],e=n;e=e.parentNode;)1===e.nodeType&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(On(n),n=0;n - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ -var o=n(1031);e.exports=function(e){var t,n;return!1!==r(e)&&("function"==typeof(t=e.constructor)&&(n=t.prototype,!1!==r(n)&&!1!==n.hasOwnProperty("isPrototypeOf")))}},1031:function(e,t,n){"use strict";/*! - * isobject - * - * Copyright (c) 2014-2017, Jon Schlinkert. - * Released under the MIT License. - */ -var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};e.exports=function(e){return null!=e&&"object"===(void 0===e?"undefined":r(e))&&!1===Array.isArray(e)}},1032:function(e,t,n){"use strict";var r,o,a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};!function(i){"object"===a(t)&&void 0!==e?e.exports=i(null):(r=i(null),void 0!==(o="function"==typeof r?r.call(t,n,t,e):r)&&(e.exports=o))}(function e(t){function n(e,t,o,u,f){for(var p,d,h=0,g=0,v=0,b=0,C=0,k=0,w=0,x=0,T=0,S=0,E=0,I=0,_=0,A=0,M=0,D=0,R=0,L=0,j=0,U=o.length,H=U-1,oe="",_e="",Ae="",Fe="",je="",Ue="";M0&&(_e=_e.replace(y,"")),_e.trim().length>0)){switch(w){case te:case J:case W:case Z:case X:break;default:_e+=o.charAt(M)}w=W}if(1===R)switch(w){case $:case K:case W:case ce:case ue:case q:case Q:case ie:R=0;case J:case Z:case X:case te:break;default:for(R=0,j=M,C=w,M--,w=W;j0&&(++M,w=C);case $:j=U}}switch(w){case $:for(_e=_e.trim(),C=_e.charCodeAt(0),E=1,j=++M;M0&&(_e=_e.replace(y,"")),k=_e.charCodeAt(1)){case Te:case ve:case be:case re:p=t;break;default:p=Re}if(Ae=n(t,p,Ae,k,f+1),j=Ae.length,De>0&&0===j&&(j=_e.length),Le>0&&(p=r(Re,_e,L),d=s(We,Ae,p,t,Pe,Ee,j,k,f,u),_e=p.join(""),void 0!==d&&0===(j=(Ae=d.trim()).length)&&(k=0,Ae="")),j>0)switch(k){case be:_e=_e.replace(F,l);case Te:case ve:case re:Ae=_e+"{"+Ae+"}";break;case ge:_e=_e.replace(P,"$1 $2"+($e>0?qe:"")),Ae=_e+"{"+Ae+"}",Ae=1===Ie||2===Ie&&i("@"+Ae,3)?"@"+z+Ae+"@"+Ae:"@"+Ae;break;default:Ae=_e+Ae,u===Se&&(Fe+=Ae,Ae="")}else Ae="";break;default:Ae=n(t,r(t,_e,L),Ae,u,f+1)}je+=Ae,I=0,R=0,A=0,D=0,L=0,_=0,_e="",Ae="",w=o.charCodeAt(++M);break;case K:case W:if(_e=(D>0?_e.replace(y,""):_e).trim(),(j=_e.length)>1)switch(0===A&&((C=_e.charCodeAt(0))===re||C>96&&C<123)&&(j=(_e=_e.replace(" ",":")).length),Le>0&&void 0!==(d=s(Ve,_e,t,e,Pe,Ee,Fe.length,u,f,u))&&0===(j=(_e=d.trim()).length)&&(_e="\0\0"),C=_e.charCodeAt(0),k=_e.charCodeAt(1),C+k){case he:break;case we:case xe:Ue+=_e+o.charAt(M);break;default:if(_e.charCodeAt(j-1)===le)break;Fe+=a(_e,C,k,_e.charCodeAt(2))}I=0,R=0,A=0,D=0,L=0,_e="",w=o.charCodeAt(++M)}}switch(w){case Z:case X:if(g+b+v+h+Me===0)switch(S){case Q:case ue:case ce:case ee:case de:case fe:case ae:case pe:case se:case re:case le:case ie:case W:case $:case K:break;default:A>0&&(R=1)}g===se?g=0:Ne+I===0&&(D=1,_e+="\0"),Le*Ke>0&&s(ze,_e,t,e,Pe,Ee,Fe.length,u,f,u),Ee=1,Pe++;break;case W:case K:if(g+b+v+h===0){Ee++;break}default:switch(Ee++,oe=o.charAt(M),w){case J:case te:if(b+h+g===0)switch(x){case ie:case le:case J:case te:oe="";break;default:w!==te&&(oe=" ")}break;case he:oe="\\0";break;case me:oe="\\f";break;case ye:oe="\\v";break;case ne:b+g+h===0&&Ne>0&&(L=1,D=1,oe="\f"+oe);break;case 108:if(b+g+h+Oe===0&&A>0)switch(M-A){case 2:x===Ce&&o.charCodeAt(M-3)===le&&(Oe=x);case 8:T===ke&&(Oe=T)}break;case le:b+g+h===0&&(A=M);break;case ie:g+v+b+h===0&&(D=1,oe+="\r");break;case ce:case ue:0===g&&(b=b===w?0:0===b?w:b);break;case G:b+g+v===0&&h++;break;case Y:b+g+v===0&&h--;break;case Q:b+g+h===0&&v--;break;case q:if(b+g+h===0){if(0===I)switch(2*x+3*T){case 533:break;default:E=0,I=1}v++}break;case ee:g+v+b+h+A+_===0&&(_=1);break;case ae:case se:if(b+h+v>0)break;switch(g){case 0:switch(2*w+3*o.charCodeAt(M+1)){case 235:g=se;break;case 220:j=M,g=ae}break;case ae:w===se&&x===ae&&(33===o.charCodeAt(j+2)&&(Fe+=o.substring(j,M+1)),oe="",g=0)}}if(0===g){if(Ne+b+h+_===0&&u!==ge&&w!==W)switch(w){case ie:case de:case fe:case pe:case Q:case q:if(0===I){switch(x){case J:case te:case X:case Z:oe+="\0";break;default:oe="\0"+oe+(w===ie?"":"\0")}D=1}else switch(w){case q:I=++E;break;case Q:0==(I=--E)&&(D=1,oe+="\0")}break;case J:case te:switch(x){case he:case $:case K:case W:case ie:case me:case J:case te:case X:case Z:break;default:0===I&&(D=1,oe+="\0")}}_e+=oe,w!==te&&w!==J&&(S=w)}}T=x,x=w,M++}if(j=Fe.length,De>0&&0===j&&0===je.length&&0===t[0].length==!1&&(u!==ve||1===t.length&&(Ne>0?Qe:Ge)===t[0])&&(j=t.join(",").length+2),j>0){if(p=0===Ne&&u!==ge?c(t):t,Le>0&&void 0!==(d=s(Be,Fe,p,e,Pe,Ee,j,u,f,u))&&0===(Fe=d).length)return Ue+Fe+je;if(Fe=p.join(",")+"{"+Fe+"}",Ie*Oe!=0){switch(2!==Ie||i(Fe,2)||(Oe=0),Oe){case ke:Fe=Fe.replace(N,":"+V+"$1")+Fe;break;case Ce:Fe=Fe.replace(O,"::"+z+"input-$1")+Fe.replace(O,"::"+V+"$1")+Fe.replace(O,":"+B+"input-$1")+Fe}Oe=0}}return Ue+Fe+je}function r(e,t,n){var r=t.trim().split(x),a=r,i=r.length,l=e.length;switch(l){case 0:case 1:for(var u=0,c=0===l?"":e[0]+" ";u0&&Ne>0)return o.replace(S,"$1").replace(T,"$1"+Ge);break;default:return e.trim()+o.replace(T,"$1"+e.trim())}default:if(n*Ne>0&&o.indexOf("\f")>0)return o.replace(T,(e.charCodeAt(0)===le?"":"$1")+e.trim())}return e+o}function a(e,t,n,r){var o,l=0,c=e+";",s=2*t+3*n+4*r;if(944===s)return u(c);if(0===Ie||2===Ie&&!i(c,1))return c;switch(s){case 1015:return 97===c.charCodeAt(10)?z+c+c:c;case 951:return 116===c.charCodeAt(3)?z+c+c:c;case 963:return 110===c.charCodeAt(5)?z+c+c:c;case 1009:if(100!==c.charCodeAt(4))break;case 969:case 942:return z+c+c;case 978:return z+c+V+c+c;case 1019:case 983:return z+c+V+c+B+c+c;case 883:return c.charCodeAt(8)===re?z+c+c:c;case 932:if(c.charCodeAt(4)===re)switch(c.charCodeAt(5)){case 103:return z+"box-"+c.replace("-grow","")+z+c+B+c.replace("grow","positive")+c;case 115:return z+c+B+c.replace("shrink","negative")+c;case 98:return z+c+B+c.replace("basis","preferred-size")+c}return z+c+B+c+c;case 964:return z+c+B+"flex-"+c+c;case 1023:if(99!==c.charCodeAt(8))break;return o=c.substring(c.indexOf(":",15)).replace("flex-","").replace("space-between","justify"),z+"box-pack"+o+z+c+B+"flex-pack"+o+c;case 1005:return v.test(c)?c.replace(g,":"+z)+c.replace(g,":"+V)+c:c;case 1e3:switch(o=c.substring(13).trim(),l=o.indexOf("-")+1,o.charCodeAt(0)+o.charCodeAt(l)){case 226:o=c.replace(R,"tb");break;case 232:o=c.replace(R,"tb-rl");break;case 220:o=c.replace(R,"lr");break;default:return c}return z+c+B+o+c;case 1017:if(-1===c.indexOf("sticky",9))return c;case 975:switch(l=(c=e).length-10,o=(33===c.charCodeAt(l)?c.substring(0,l):c).substring(e.indexOf(":",7)+1).trim(),s=o.charCodeAt(0)+(0|o.charCodeAt(7))){case 203:if(o.charCodeAt(8)<111)break;case 115:c=c.replace(o,z+o)+";"+c;break;case 207:case 102:c=c.replace(o,z+(s>102?"inline-":"")+"box")+";"+c.replace(o,z+o)+";"+c.replace(o,B+o+"box")+";"+c}return c+";";case 938:if(c.charCodeAt(5)===re)switch(c.charCodeAt(6)){case 105:return o=c.replace("-items",""),z+c+z+"box-"+o+B+"flex-"+o+c;case 115:return z+c+B+"flex-item-"+c.replace(j,"")+c;default:return z+c+B+"flex-line-pack"+c.replace("align-content","").replace(j,"")+c}break;case 973:case 989:if(c.charCodeAt(3)!==re||122===c.charCodeAt(4))break;case 931:case 953:if(!0===H.test(e))return 115===(o=e.substring(e.indexOf(":")+1)).charCodeAt(0)?a(e.replace("stretch","fill-available"),t,n,r).replace(":fill-available",":stretch"):c.replace(o,z+o)+c.replace(o,V+o.replace("fill-",""))+c;break;case 962:if(c=z+c+(102===c.charCodeAt(5)?B+c:"")+c,n+r===211&&105===c.charCodeAt(13)&&c.indexOf("transform",10)>0)return c.substring(0,c.indexOf(";",27)+1).replace(b,"$1"+z+"$2")+c}return c}function i(e,t){var n=e.indexOf(1===t?":":"{"),r=e.substring(0,3!==t?n:10),o=e.substring(n+1,e.length-1);return je(2!==t?r:r.replace(U,"$1"),o,t)}function l(e,t){var n=a(t,t.charCodeAt(0),t.charCodeAt(1),t.charCodeAt(2));return n!==t+";"?n.replace(L," or ($1)").substring(4):"("+t+")"}function u(e){var t=e.length,n=e.indexOf(":",9)+1,r=e.substring(0,n).trim(),o=e.substring(n,t-1).trim();switch(e.charCodeAt(9)*$e){case 0:break;case re:if(110!==e.charCodeAt(10))break;default:for(var a=o.split((o="",C)),l=0,n=0,t=a.length;lee&&s<90||s>96&&s<123||s===oe||s===re&&u.charCodeAt(1)!==re))switch(isNaN(parseFloat(u))+(-1!==u.indexOf("("))){case 1:switch(u){case"infinite":case"alternate":case"backwards":case"running":case"normal":case"forwards":case"both":case"none":case"linear":case"ease":case"ease-in":case"ease-out":case"ease-in-out":case"paused":case"reverse":case"alternate-reverse":case"inherit":case"initial":case"unset":case"step-start":case"step-end":break;default:u+=qe}}c[n++]=u}o+=(0===l?"":",")+c.join(" ")}}return o=r+o+";",1===Ie||2===Ie&&i(o,1)?z+o+o:o}function c(e){for(var t,n,r=0,o=e.length,a=Array(o);r1)){if(s=l.charCodeAt(l.length-1),f=n.charCodeAt(0),t="",0!==u)switch(s){case ae:case de:case fe:case pe:case te:case q:break;default:t=" "}switch(f){case ne:n=t+Qe;case de:case fe:case pe:case te:case Q:case q:break;case G:n=t+n+Qe;break;case le:switch(2*n.charCodeAt(1)+3*n.charCodeAt(2)){case 530:if(_e>0){n=t+n.substring(8,c-1);break}default:(u<1||i[u-1].length<1)&&(n=t+Qe+n)}break;case ie:t="";default:n=c>1&&n.indexOf(":")>0?t+n.replace(D,"$1"+Qe+"$2"):t+n+Qe}l+=n}a[r]=l.replace(y,"").trim()}return a}function s(e,t,n,r,o,a,i,l,u,c){for(var s,f=0,p=t;f0&&(qe=o.replace(E,a===G?"":"-")),a=1,1===Ne?Ge=o:Qe=o;var i,l=[Ge];Le>0&&void 0!==(i=s(He,r,l,l,Pe,Ee,0,0,0,0))&&"string"==typeof i&&(r=i);var u=n(Re,l,r,0,0);return Le>0&&void 0!==(i=s(Ue,u,l,l,Pe,Ee,u.length,0,0,0))&&"string"!=typeof(u=i)&&(a=0),qe="",Ge="",Qe="",Oe=0,Pe=1,Ee=1,Ae*a==0?u:f(u)}var m=/^\0+/g,y=/[\0\r\f]/g,g=/: */g,v=/zoo|gra/,b=/([,: ])(transform)/g,C=/,+\s*(?![^(]*[)])/g,k=/ +\s*(?![^(]*[)])/g,w=/ *[\0] */g,x=/,\r+?/g,T=/([\t\r\n ])*\f?&/g,S=/:global\(((?:[^\(\)\[\]]*|\[.*\]|\([^\(\)]*\))*)\)/g,E=/\W+/g,P=/@(k\w+)\s*(\S*)\s*/,O=/::(place)/g,N=/:(read-only)/g,I=/\s+(?=[{\];=:>])/g,_=/([[}=:>])\s+/g,A=/(\{[^{]+?);(?=\})/g,M=/\s{2,}/g,D=/([^\(])(:+) */g,R=/[svh]\w+-[tblr]{2}/,F=/\(\s*(.*)\s*\)/g,L=/([\s\S]*?);/g,j=/-self|flex-/g,U=/[^]*?(:[rp][el]a[\w-]+)[^]*/,H=/stretch|:\s*\w+\-(?:conte|avail)/,z="-webkit-",V="-moz-",B="-ms-",W=59,K=125,$=123,q=40,Q=41,G=91,Y=93,X=10,Z=13,J=9,ee=64,te=32,ne=38,re=45,oe=95,ae=42,ie=44,le=58,ue=39,ce=34,se=47,fe=62,pe=43,de=126,he=0,me=12,ye=11,ge=107,ve=109,be=115,Ce=112,ke=111,we=169,xe=163,Te=100,Se=112,Ee=1,Pe=1,Oe=0,Ne=1,Ie=1,_e=1,Ae=0,Me=0,De=0,Re=[],Fe=[],Le=0,je=null,Ue=-2,He=-1,ze=0,Ve=1,Be=2,We=3,Ke=0,$e=1,qe="",Qe="",Ge="";return h.use=p,h.set=d,void 0!==t&&d(t),h})},1033:function(e,t,n){"use strict";"function"==typeof Symbol&&Symbol.iterator;e.exports=n(1034)()},1034:function(e,t,n){"use strict";var r=n(43),o=n(73),a=n(1035);e.exports=function(){function e(e,t,n,r,i,l){l!==a&&o(!1,"Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types")}function t(){return e}e.isRequired=e;var n={array:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t};return n.checkPropTypes=r,n.PropTypes=n,n}},1035:function(e,t,n){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},1036:function(e,t,n){"use strict";var r={childContextTypes:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,arguments:!0,arity:!0},a="function"==typeof Object.getOwnPropertySymbols;e.exports=function(e,t,n){if("string"!=typeof t){var i=Object.getOwnPropertyNames(t);a&&(i=i.concat(Object.getOwnPropertySymbols(t)));for(var l=0;l=4;){var i=f(e,a);i=d(i,n),i^=i>>>24,i=d(i,n),r=d(r,n),r^=i,a+=4,o-=4}switch(o){case 3:r^=p(e,a),r^=e.charCodeAt(a+2)<<16,r=d(r,n);break;case 2:r^=p(e,a),r=d(r,n);break;case 1:r^=e.charCodeAt(a),r=d(r,n)}return r^=r>>>13,r=d(r,n),(r^=r>>>15)>>>0}function f(e,t){return e.charCodeAt(t++)+(e.charCodeAt(t++)<<8)+(e.charCodeAt(t++)<<16)+(e.charCodeAt(t)<<24)}function p(e,t){return e.charCodeAt(t++)+(e.charCodeAt(t++)<<8)}function d(e,t){return e|=0,t|=0,(65535&e)*t+(((e>>>16)*t&65535)<<16)|0}Object.defineProperty(t,"__esModule",{value:!0}),t.StyleSheetManager=t.ServerStyleSheet=t.withTheme=t.ThemeProvider=t.injectGlobal=t.keyframes=t.css=void 0;var h,m="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},y=n(1030),g=r(y),v=n(1032),b=r(v),C=n(0),k=r(C),w=n(1033),x=r(w),T=n(1036),S=r(T),E=/([A-Z])/g,P=o,O=P,N=/^ms-/,I=a,_=function e(t,n){var r=Object.keys(t).filter(function(e){var n=t[e];return void 0!==n&&null!==n&&!1!==n&&""!==n}).map(function(n){return(0,g.default)(t[n])?e(t[n],n):I(n)+": "+t[n]+";"}).join(" ");return n?n+" {\n "+r+"\n}":r},A=function e(t,n){return t.reduce(function(t,r){return void 0===r||null===r||!1===r||""===r?t:Array.isArray(r)?[].concat(t,e(r,n)):r.hasOwnProperty("styledComponentId")?[].concat(t,["."+r.styledComponentId]):"function"==typeof r?n?t.concat.apply(t,e([r(n)],n)):t.concat(r):t.concat((0,g.default)(r)?_(r):r.toString())},[])},M=new b.default({global:!1,cascade:!0,keyframe:!1,prefix:!0,compress:!1,semicolon:!0}),D=function(e,t,n){var r=e.join("").replace(/^\s*\/\/.*$/gm,""),o=t&&n?n+" "+t+" { "+r+" }":r;return M(n||!t?"":t,o)},R="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""),F=R.length,L=function(e){var t="",n=void 0;for(n=e;n>F;n=Math.floor(n/F))t=R[n%F]+t;return R[n%F]+t},j=function(e,t){return t.reduce(function(t,n,r){return t.concat(n,e[r+1])},[e[0]])},U=function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n},Q=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==(void 0===t?"undefined":m(t))&&"function"!=typeof t?e:t},G=function(){function e(t,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";B(this,e),this.el=t,this.isLocal=n,this.ready=!1;var o=z(r);this.size=o.length,this.components=o.reduce(function(e,t){return e[t.componentId]=t,e},{})}return e.prototype.isFull=function(){return this.size>=40},e.prototype.addComponent=function(e){this.ready||this.replaceElement();var t={componentId:e,textNode:document.createTextNode("")};this.el.appendChild(t.textNode),this.size+=1,this.components[e]=t},e.prototype.inject=function(e,t,n){this.ready||this.replaceElement();var r=this.components[e];if(""===r.textNode.data&&r.textNode.appendData("\n/* sc-component-id: "+e+" */\n"),r.textNode.appendData(t),n){var o=this.el.getAttribute(X);this.el.setAttribute(X,o?o+" "+n:n)}var a=V();a&&this.el.setAttribute("nonce",a)},e.prototype.toHTML=function(){return this.el.outerHTML},e.prototype.toReactElement=function(){throw new Error("BrowserTag doesn't implement toReactElement!")},e.prototype.clone=function(){throw new Error("BrowserTag cannot be cloned!")},e.prototype.replaceElement=function(){var e=this;if(this.ready=!0,0!==this.size){var t=this.el.cloneNode();if(t.appendChild(document.createTextNode("\n")),Object.keys(this.components).forEach(function(n){var r=e.components[n];r.textNode=document.createTextNode(r.cssFromDOM),t.appendChild(r.textNode)}),!this.el.parentNode)throw new Error("Trying to replace an element that wasn't mounted!");this.el.parentNode.replaceChild(t,this.el),this.el=t}},e}(),Y={create:function(){for(var e=[],t={},n=document.querySelectorAll("["+X+"]"),r=n.length,o=0;o");return document.head.appendChild(t),new G(t,e)},e,t)}},X="data-styled-components",Z="data-styled-components-is-local",J="__styled-components-stylesheet__",ee=null,te=[],ne=function(){function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};B(this,e),this.hashes={},this.deferredInjections={},this.stylesCacheable="undefined"!=typeof document,this.tagConstructor=t,this.tags=n,this.names=r,this.constructComponentTagMap()}return e.prototype.constructComponentTagMap=function(){var e=this;this.componentTags={},this.tags.forEach(function(t){Object.keys(t.components).forEach(function(n){e.componentTags[n]=t})})},e.prototype.getName=function(e){return this.hashes[e.toString()]},e.prototype.alreadyInjected=function(e,t){return!!this.names[t]&&(this.hashes[e.toString()]=t,!0)},e.prototype.hasInjectedComponent=function(e){return!!this.componentTags[e]},e.prototype.deferredInject=function(e,t,n){this===ee&&te.forEach(function(r){r.deferredInject(e,t,n)}),this.getOrCreateTag(e,t),this.deferredInjections[e]=n},e.prototype.inject=function(e,t,n,r,o){this===ee&&te.forEach(function(r){r.inject(e,t,n)});var a=this.getOrCreateTag(e,t),i=this.deferredInjections[e];i&&(a.inject(e,i),delete this.deferredInjections[e]),a.inject(e,n,o),r&&o&&(this.hashes[r.toString()]=o)},e.prototype.toHTML=function(){return this.tags.map(function(e){return e.toHTML()}).join("")},e.prototype.toReactElements=function(){return this.tags.map(function(e,t){return e.toReactElement("sc-"+t)})},e.prototype.getOrCreateTag=function(e,t){var n=this.componentTags[e];if(n)return n;var r=this.tags[this.tags.length-1],o=!r||r.isFull()||r.isLocal!==t?this.createNewTag(t):r;return this.componentTags[e]=o,o.addComponent(e),o},e.prototype.createNewTag=function(e){var t=this.tagConstructor(e);return this.tags.push(t),t},e.reset=function(t){ee=e.create(t)},e.create=function(){return((arguments.length>0&&void 0!==arguments[0]?arguments[0]:"undefined"==typeof document)?le:Y).create()},e.clone=function(t){var n=new e(t.tagConstructor,t.tags.map(function(e){return e.clone()}),K({},t.names));return n.hashes=K({},t.hashes),n.deferredInjections=K({},t.deferredInjections),te.push(n),n},W(e,null,[{key:"instance",get:function(){return ee||(ee=e.create())}}]),e}(),re=function(e){function t(){return B(this,t),Q(this,e.apply(this,arguments))}return $(t,e),t.prototype.getChildContext=function(){var e;return e={},e[J]=this.props.sheet,e},t.prototype.render=function(){return k.default.Children.only(this.props.children)},t}(C.Component);re.childContextTypes=(h={},h[J]=x.default.oneOfType([x.default.instanceOf(ne),x.default.instanceOf(le)]).isRequired,h),re.propTypes={sheet:x.default.oneOfType([x.default.instanceOf(ne),x.default.instanceOf(le)]).isRequired};var oe,ae,ie=function(){function e(t){B(this,e),this.isLocal=t,this.components={},this.size=0,this.names=[]}return e.prototype.isFull=function(){return!1},e.prototype.addComponent=function(e){this.components[e]={componentId:e,css:""},this.size+=1},e.prototype.concatenateCSS=function(){var e=this;return Object.keys(this.components).reduce(function(t,n){return t+e.components[n].css},"")},e.prototype.inject=function(e,t,n){var r=this.components[e];""===r.css&&(r.css="/* sc-component-id: "+e+" */\n"),r.css+=t.replace(/\n*$/,"\n"),n&&this.names.push(n)},e.prototype.toHTML=function(){var e=['type="text/css"',X+'="'+this.names.join(" ")+'"',Z+'="'+(this.isLocal?"true":"false")+'"'],t=V();return t&&e.push('nonce="'+t+'"'),""},e.prototype.toReactElement=function(e){var t,n=(t={},t[X]=this.names.join(" "),t[Z]=this.isLocal.toString(),t),r=V();return r&&(n.nonce=r),k.default.createElement("style",K({key:e,type:"text/css"},n,{dangerouslySetInnerHTML:{__html:this.concatenateCSS()}}))},e.prototype.clone=function(){var t=this,n=new e(this.isLocal);return n.names=[].concat(this.names),n.size=this.size,n.components=Object.keys(this.components).reduce(function(e,n){return e[n]=K({},t.components[n]),e},{}),n},e}(),le=function(){function e(){B(this,e),this.instance=ne.clone(ne.instance)}return e.prototype.collectStyles=function(e){if(this.closed)throw new Error("Can't collect styles once you've called getStyleTags!");return k.default.createElement(re,{sheet:this.instance},e)},e.prototype.getStyleTags=function(){return this.closed||(te.splice(te.indexOf(this.instance),1),this.closed=!0),this.instance.toHTML()},e.prototype.getStyleElement=function(){return this.closed||(te.splice(te.indexOf(this.instance),1),this.closed=!0),this.instance.toReactElements()},e.create=function(){return new ne(function(e){return new ie(e)})},e}(),ue=/^((?:s(?:uppressContentEditableWarn|croll|pac)|(?:shape|image|text)Render|(?:letter|word)Spac|vHang|hang)ing|(?:on(?:AnimationIteration|C(?:o(?:mposition(?:Update|Start|End)|ntextMenu|py)|anPlayThrough|anPlay|hange|lick|ut)|(?:(?:Duration|Volume|Rate)Chang|(?:MouseLea|(?:Touch|Mouse)Mo|DragLea)v|Paus)e|Loaded(?:Metad|D)ata|(?:Animation|Touch|Load|Drag)Start|(?:(?:T(?:ransition|ouch)|Animation)E|Suspe)nd|DoubleClick|(?:TouchCanc|Whe)el|(?:Mouse(?:Ent|Ov)e|Drag(?:Ent|Ov)e|Erro)r|TimeUpdate|(?:E(?:n(?:crypt|d)|mpti)|S(?:tall|eek))ed|MouseDown|P(?:rogress|laying)|(?:MouseOu|DragExi|S(?:elec|ubmi)|Rese|Inpu)t|KeyPress|DragEnd|Key(?:Down|Up)|(?:Wait|Seek)ing|(?:MouseU|Dro)p|Scroll|Paste|Focus|Abort|Drag|Play|Load|Blur)Captur|alignmentBaselin|(?:limitingConeAng|xlink(?:(?:Arcr|R)o|Tit)|s(?:urfaceSca|ty|ca)|unselectab|baseProfi|fontSty|(?:focus|dragg)ab|multip|profi|tit)l|d(?:ominantBaselin|efaultValu)|a(?:uto(?:Capitaliz|Revers|Sav)|dditiv)|(?:(?:formNoValid|xlinkActu|noValid|accumul|rot)a|autoComple|decelera)t|(?:(?:attribute|item)T|datat)yp|(?:attribute|glyph)Nam|playsInlin|(?:formE|e)ncTyp|(?:writing|input|edge)Mod|(?:xlinkTy|itemSco|keyTy|slo)p|(?:amplitu|mo)d|(?:xmlSpa|non)c|fillRul|(?:dateTi|na)m|r(?:esourc|ol)|xmlBas|wmod)e|(?:glyphOrientationHorizont|loc)al|(?:externalResourcesRequir|select|revers|mut)ed|c(?:o(?:lorInterpolationFilter|ntrol|ord)s|o(?:lor(?:Interpolation)?|ntent)|(?:ontentS(?:cript|tyle)Typ|o(?:ntentEditab|lorProfi)l|l(?:assNam|ipRul)|a(?:lcMod|ptur)|it)e|olorRendering|l(?:ipPathUnits|assID)|o(?:ntextMenu|ls)|h(?:eckedLink|a(?:llenge|rSet)|ildren|ecked)|ell(?:Spac|Padd)ing|(?:rossOrigi|olSpa)n|apHeight|lip(?:Path)?|ursor|[xy])|glyphOrientationVertical|d(?:angerouslySetInnerHTML|efaultChecked|ownload|isabled|isplay|[xy])|(?:s(?:trikethroughThickn|eaml)es|(?:und|ov)erlineThicknes|r(?:equiredExtension|adiu)|(?:requiredFeatur|tableValu|stitchTil|numOctav|filterR)e|key(?:(?:Splin|Tim)e|Param)|autoFocu|header|bia)s|(?:(?:st(?:rikethroughPosi|dDevia)|(?:und|ov)erlinePosi|(?:textDecor|elev)a|orienta)tio|(?:strokeLinejo|orig)i|formActio|zoomAndPa|onFocusI|directio|(?:vers|act)io|rowSpa|begi|ico)n|o(?:n(?:AnimationIteration|C(?:o(?:mposition(?:Update|Start|End)|ntextMenu|py)|anPlayThrough|anPlay|hange|lick|ut)|(?:(?:Duration|Volume|Rate)Chang|(?:MouseLea|(?:Touch|Mouse)Mo|DragLea)v|Paus)e|Loaded(?:Metad|D)ata|(?:Animation|Touch|Load|Drag)Start|(?:(?:T(?:ransition|ouch)|Animation)E|Suspe)nd|DoubleClick|(?:TouchCanc|Whe)el|(?:Mouse(?:Ent|Ov)e|Drag(?:Ent|Ov)e|Erro)r|TimeUpdate|(?:E(?:n(?:crypt|d)|mpti)|S(?:tall|eek))ed|MouseDown|P(?:rogress|laying)|(?:MouseOu|DragExi|S(?:elec|ubmi)|Rese|Inpu)t|KeyPress|DragEnd|Key(?:Down|Up)|(?:Wait|Seek)ing|(?:MouseU|Dro)p|Scroll|Paste|Focus|Abort|Drag|Play|Load|Blur)|rient)|p(?:reserveA(?:spectRatio|lpha)|ointsAt[X-Z]|anose1)|(?:patternContent|ma(?:sk(?:Content)?|rker)|primitive|gradient|pattern|filter)Units|(?:gradientT|patternT|t)ransform|(?:(?:allowTranspar|baseFrequ)enc|re(?:ferrerPolic|adOnl)|(?:(?:st(?:roke|op)O|floodO|fillO|o)pac|integr|secur)it|visibilit|fontFamil|accessKe|propert|summar)y|(?:strokeMiterlimi|(?:specularConsta|repeatCou|fontVaria)n|(?:(?:specularE|e)xpon|renderingInt|asc)en|d(?:iffuseConsta|esce)n|(?:fontSizeAdju|lengthAdju|manife)s|baselineShif|vectorEffec|(?:(?:mar(?:ker|gin)|x)H|accentH|fontW)eigh|a(?:utoCorrec|bou)|markerStar|onFocusOu|in(?:tercep|lis)|restar|forma|heigh|lis)t|(?:(?:st(?:rokeDasho|artO)|o)ffs|acceptChars|formTarg|viewTarg|srcS)et|(?:(?:enableBackgrou|markerE)n|s(?:p(?:readMetho|ee)|ee)|formMetho|m(?:arkerMi|etho)|preloa|kin)d|k(?:ernel(?:UnitLength|Matrix)|[1-4])|(?:[xy]ChannelSelect|lightingCol|textAnch|floodCol|stopCol|operat|htmlF)or|(?:allowFullScre|hidd)en|strokeDasharray|systemLanguage|(?:strokeLineca|itemPro|useMa|wra|loo)p|v(?:Mathematical|ert(?:Origin[XY]|AdvY)|alues|ocab)|(?:pointerEve|keyPoi)nts|unicodeRange|(?:(?:allowReord|placehold|frameBord|paintOrd|post|ord)e|repeatDu|d(?:efe|u))r|mathematical|(?:vI|i)deographic|h(?:oriz(?:Origin|Adv)X|ttpEquiv)|u(?:nicodeBidi|[12])|(?:fontStretc|hig)h|(?:(?:mar(?:ker|gin)W|strokeW)id|azimu)th|vAlphabetic|mediaGroup|spellCheck|(?:unitsPerE|optimu|fro)m|r(?:adioGroup|e(?:sults|f[XY]|l)|ows|[xy])|(?:xmlnsXl|valueL)ink|a(?:rabicForm|l(?:phabetic|t)|sync)|pathLength|(?:text|m(?:in|ax))Length|innerHTML|xlinkShow|(?:xlinkHr|glyphR)ef|r(?:e(?:quired|sult|f))?|o(?:verflow|pen)|(?:tabInde|(?:sand|b)bo|viewBo)x|(?:(?:href|xml|src)La|kerni)ng|f(?:o(?:ntSize|rm)|il(?:ter|l))|autoPlay|unicode|p(?:attern|oints)|t(?:arget[XY]|o)|i(?:temRef|n2|s)|divisor|d(?:efault|ata|ir)?|srcDoc|s(?:coped|te(?:m[hv]|p)|pan)|(?:width|size)s|(?:stri|la)ng|prefix|itemID|s(?:t(?:roke|art)|hape|cope|rc)|a(?:ccept|s)|t(?:arget|ype)|typeof|width|value|x(?:mlns)?|label|m(?:edia|a(?:sk|x)|in)|size|href|k(?:ey)?|end|low|x[12]|i[dn]|y[12]|g[12]|by|f[xy]|[yz])$/,ce=RegExp.prototype.test.bind(new RegExp("^(data|aria)-[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$")),se=function(e){return ue.test(e)||ce(e.toLowerCase())},fe=function(e,t,n){var r=n&&e.theme===n.theme;return e.theme&&!r?e.theme:t},pe=/[[\].#*$><+~=|^:(),"'`-]+/g,de=/(^-|-$)/g,he=function(e){function t(e){i=e;for(var t in o){var n=o[t];void 0!==n&&n(i)}}function n(e){var t=a;return o[t]=e,a+=1,e(i),t}function r(e){o[e]=void 0}var o={},a=0,i=e;return{publish:t,subscribe:n,unsubscribe:r}},me="__styled-components__",ye=me+"next__",ge=x.default.shape({getTheme:x.default.func,subscribe:x.default.func,unsubscribe:x.default.func}),ve=function(e){return"function"==typeof e},be=function(e){function t(){B(this,t);var n=Q(this,e.call(this));return n.unsubscribeToOuterId=-1,n.getTheme=n.getTheme.bind(n),n}return $(t,e),t.prototype.componentWillMount=function(){var e=this,t=this.context[ye];void 0!==t&&(this.unsubscribeToOuterId=t.subscribe(function(t){e.outerTheme=t})),this.broadcast=he(this.getTheme())},t.prototype.getChildContext=function(){var e,t=this;return K({},this.context,(e={},e[ye]={getTheme:this.getTheme,subscribe:this.broadcast.subscribe,unsubscribe:this.broadcast.unsubscribe},e[me]=function(e){var n=t.broadcast.subscribe(e);return function(){return t.broadcast.unsubscribe(n)}},e))},t.prototype.componentWillReceiveProps=function(e){this.props.theme!==e.theme&&this.broadcast.publish(this.getTheme(e.theme))},t.prototype.componentWillUnmount=function(){-1!==this.unsubscribeToOuterId&&this.context[ye].unsubscribe(this.unsubscribeToOuterId)},t.prototype.getTheme=function(e){var t=e||this.props.theme;if(ve(t)){return t(this.outerTheme)}if(!(0,g.default)(t))throw new Error("[ThemeProvider] Please make your theme prop a plain object");return K({},this.outerTheme,t)},t.prototype.render=function(){return this.props.children?k.default.Children.only(this.props.children):null},t}(C.Component);be.childContextTypes=(oe={},oe[me]=x.default.func,oe[ye]=ge,oe),be.contextTypes=(ae={},ae[ye]=ge,ae);var Ce={},ke=function e(t,n){for(var r=0;r2&&void 0!==arguments[2]?arguments[2]:{},a=function(t){for(var a=arguments.length,i=Array(a>1?a-1:0),l=1;l1?o-1:0),i=1;i1?r-1:0),a=1;a "+s);if("componentClose"===f.type)throw new Error("Missing opening component token: `"+f.value+"`");if("componentOpen"===f.type){a=n[f.value],c=p;break}y.push(n[f.value])}else y.push(f.value);return a&&(l=function(e,t){var n,r,o=t[e],i=0;for(r=e+1;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}},,,,,,,,,,,,,,,function(e,t,n){"use strict";n.r(t),n.d(t,"setTextdomainL10n",(function(){return i})),n.d(t,"setYoastComponentsL10n",(function(){return a})),n.d(t,"setWordPressSeoL10n",(function(){return u}));var r=n(3),o=n(2);function i(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"wpseoYoastJSL10n",n=Object(o.get)(window,[t,e,"locale_data",e],!1);!1===n?Object(r.setLocaleData)({"":{}},e):Object(r.setLocaleData)(n,e)}function a(){i("yoast-components")}function u(){i("wordpress-seo")}},,,,,,,,,function(e,t){function n(t,r){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,r)}e.exports=n},,,,,,,,,,,,,,,,,,,,,,,,function(e,t,n){"use strict";function r(e){return function(){return e}}var o=function(){};o.thatReturns=r,o.thatReturnsFalse=r(!1),o.thatReturnsTrue=r(!0),o.thatReturnsNull=r(null),o.thatReturnsThis=function(){return this},o.thatReturnsArgument=function(e){return e},e.exports=o},,,,,,,,function(e,t){e.exports=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}},,,,,function(e,t){var n=e.exports={version:"2.6.12"};"number"==typeof __e&&(__e=n)},,,,,,,,,,,,function(e,t,n){var r=n(212)("wks"),o=n(197),i=n(143).Symbol,a="function"==typeof i;(e.exports=function(e){return r[e]||(r[e]=a&&i[e]||(a?i:o)("Symbol."+e))}).store=r},,,,,,,,,,,function(e,t,n){"use strict";var r=n(16),o="function"==typeof Symbol&&Symbol.for&&Symbol.for("react.element")||60103,i=n(94),a=n(131),u=n(132),s="function"==typeof Symbol&&Symbol.iterator;function c(e,t){return e&&"object"==typeof e&&null!=e.key?(n=e.key,r={"=":"=0",":":"=2"},"$"+(""+n).replace(/[=:]/g,(function(e){return r[e]}))):t.toString(36);var n,r}var l=/\/+/g;function f(e){return(""+e).replace(l,"$&/")}var p,d,h=y,y=function(e){if(this.instancePool.length){var t=this.instancePool.pop();return this.call(t,e),t}return new this(e)};function v(e,t,n,r){this.result=e,this.keyPrefix=t,this.func=n,this.context=r,this.count=0}function m(e,t,n){var o,a,u=e.result,s=e.keyPrefix,c=e.func,l=e.context,p=c.call(l,t,e.count++);Array.isArray(p)?b(p,u,n,i.thatReturnsArgument):null!=p&&(r.isValidElement(p)&&(o=p,a=s+(!p.key||t&&t.key===p.key?"":f(p.key)+"/")+n,p=r.cloneElement(o,{key:a},void 0!==o.props?o.props.children:void 0)),u.push(p))}function b(e,t,n,r,i){var u="";null!=n&&(u=f(n)+"/");var l=v.getPooled(t,u,r,i);!function(e,t,n){null==e||function e(t,n,r,i){var u,l=typeof t;if("undefined"!==l&&"boolean"!==l||(t=null),null===t||"string"===l||"number"===l||"object"===l&&t.$$typeof===o)return r(i,t,""===n?"."+c(t,0):n),1;var f=0,p=""===n?".":n+":";if(Array.isArray(t))for(var d=0;d=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}},,,,,function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r,o=(r=n(262))&&r.__esModule?r:{default:r};t.default=o.default},,,,,,function(e,t,n){var r=n(144),o=n(180);e.exports=n(145)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){var r=n(172);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,n){var r=n(231),o=n(209);e.exports=function(e){return r(o(e))}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={easeOutFunction:"cubic-bezier(0.23, 1, 0.32, 1)",easeInOutFunction:"cubic-bezier(0.445, 0.05, 0.55, 0.95)",easeOut:function(e,t,n,r){if(r=r||this.easeOutFunction,t&&"[object Array]"===Object.prototype.toString.call(t)){for(var o="",i=0;i0?r:n)(e)}},function(e,t,n){var r=n(212)("keys"),o=n(197);e.exports=function(e){return r[e]||(r[e]=o(e))}},function(e,t,n){var r=n(107),o=n(143),i=o["__core-js_shared__"]||(o["__core-js_shared__"]={});(e.exports=function(e,t){return i[e]||(i[e]=void 0!==t?t:{})})("versions",[]).push({version:r.version,mode:n(196)?"pure":"global",copyright:"© 2020 Denis Pushkarev (zloirock.ru)"})},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t){t.f=Object.getOwnPropertySymbols},function(e,t,n){var r=n(171),o=n(280),i=n(213),a=n(211)("IE_PROTO"),u=function(){},s=function(){var e,t=n(229)("iframe"),r=i.length;for(t.style.display="none",n(281).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("', + ( $this->ask_consent ) ? 'wpseoHelpScoutBeaconConsent' : 'wpseoHelpScoutBeacon', + \esc_html( $this->pages_ids[ $this->page ] ), + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaping done in format_json_encode. + WPSEO_Utils::format_json_encode( (array) $this->get_session_data() ) + ); + } + + /** + * Checks if the current page is a page containing the beacon. + * + * @return bool + */ + private function is_beacon_page() { + $return = false; + if ( ! empty( $this->page ) && $GLOBALS['pagenow'] === 'admin.php' && isset( $this->pages_ids[ $this->page ] ) ) { + $return = true; + } + + /** + * Filter: 'wpseo_helpscout_show_beacon' - Allows overriding whether we show the HelpScout beacon. + * + * @api bool - Whether we show the beacon or not. + */ + return \apply_filters( 'wpseo_helpscout_show_beacon', $return ); + } + + /** + * Retrieves the identifying data. + * + * @return string The data to pass as identifying data. + */ + protected function get_session_data() { + $current_user = \wp_get_current_user(); + + // Do not make these strings translatable! They are for our support agents, the user won't see them! + $data = [ + 'name' => \trim( $current_user->user_firstname . ' ' . $current_user->user_lastname ), + 'email' => $current_user->user_email, + 'WordPress Version' => $this->get_wordpress_version(), + 'Server' => $this->get_server_info(), + 'Theme' => $this->get_theme_info(), + 'Plugins' => $this->get_active_plugins(), + ]; + + if ( ! empty( $this->products ) ) { + $addon_manager = new WPSEO_Addon_Manager(); + foreach ( $this->products as $product ) { + $subscription = $addon_manager->get_subscription( $product ); + + if ( ! $subscription ) { + continue; + } + + $data[ $subscription->product->name ] = $this->get_product_info( $subscription ); + } + } + + return WPSEO_Utils::format_json_encode( $data ); + } + + /** + * Returns basic info about the server software. + * + * @return string + */ + private function get_server_info() { + $server_tracking_data = new WPSEO_Tracking_Server_Data(); + $server_data = $server_tracking_data->get(); + $server_data = $server_data['server']; + + $fields_to_use = [ + 'IP' => 'ip', + 'Hostname' => 'Hostname', + 'OS' => 'os', + 'PHP' => 'PhpVersion', + 'CURL' => 'CurlVersion', + ]; + + $server_data['CurlVersion'] = $server_data['CurlVersion']['version'] . '(SSL Support' . $server_data['CurlVersion']['sslSupport'] . ')'; + + $server_info = ''; + + foreach ( $fields_to_use as $label => $field_to_use ) { + if ( isset( $server_data[ $field_to_use ] ) ) { + $server_info .= \sprintf( '', \esc_html( $label ), \esc_html( $server_data[ $field_to_use ] ) ); + } + } + + $server_info .= '
    %1$s%2$s
    '; + + 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 = ''; + $product_info .= ''; + $product_info .= ''; + $product_info .= '
    Version' . $plugin->product->version . '
    Expiration date' . $plugin->expiry_date . '
    '; + + 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( + '%2$s 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( '
    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 .= ' '; + } + + $active_plugins .= \sprintf( + '%2$s v%3$s', + \esc_attr( $plugin_data['PluginURI'] ), + \esc_html( $plugin_data['Name'] ), + \esc_html( $plugin_data['Version'] ) + ); + } + + return $active_plugins; + } + + /** + * Returns the conditionals based on which this integration should be active. + * + * @return array The array of conditionals. + */ + public static function get_conditionals() { + return [ Admin_Conditional::class ]; + } + + /** + * Allows filtering of the HelpScout settings. Hooked to admin_head to prevent timing issues, not too early, not too late. + */ + protected function filter_settings() { + /** + * Filter: 'wpseo_helpscout_beacon_settings' - Allows overriding the HelpScout beacon settings. + * + * @api string - The HelpScout beacon settings. + */ + $filterable_helpscout_setting = [ + 'products' => $this->products, + 'pages_ids' => $this->pages_ids, + ]; + + $helpscout_settings = \apply_filters( 'wpseo_helpscout_beacon_settings', $filterable_helpscout_setting ); + + $this->products = $helpscout_settings['products']; + $this->pages_ids = $helpscout_settings['pages_ids']; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/admin/indexing-notification-integration.php b/wp-content/plugins/wordpress-seo/src/integrations/admin/indexing-notification-integration.php new file mode 100644 index 00000000..a0b5adfa --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/admin/indexing-notification-integration.php @@ -0,0 +1,276 @@ +notification_center = $notification_center; + $this->product_helper = $product_helper; + $this->page_helper = $page_helper; + $this->short_link_helper = $short_link_helper; + $this->notification_helper = $notification_helper; + $this->indexing_helper = $indexing_helper; + $this->addon_manager = $addon_manager; + $this->environment_helper = $environment_helper; + } + + /** + * Initializes the integration. + * + * Adds hooks and jobs to cleanup or add the notification when necessary. + * + * @return void + */ + public function register_hooks() { + if ( $this->page_helper->get_current_yoast_seo_page() === 'wpseo_dashboard' ) { + \add_action( 'admin_init', [ $this, 'maybe_cleanup_notification' ] ); + } + + if ( $this->indexing_helper->has_reason() ) { + \add_action( 'admin_init', [ $this, 'maybe_create_notification' ] ); + } + + \add_action( self::NOTIFICATION_ID, [ $this, 'maybe_create_notification' ] ); + } + + /** + * Returns the conditionals based on which this loadable should be active. + * + * @return array The conditionals. + */ + public static function get_conditionals() { + return [ + Admin_Conditional::class, + ]; + } + + /** + * Checks whether the notification should be shown and adds + * it to the notification center if this is the case. + */ + public function maybe_create_notification() { + if ( ! $this->should_show_notification() ) { + return; + } + + if ( ! $this->notification_center->get_notification_by_id( self::NOTIFICATION_ID ) ) { + $notification = $this->notification(); + $this->notification_helper->restore_notification( $notification ); + $this->notification_center->add_notification( $notification ); + } + } + + /** + * Checks whether the notification should not be shown anymore and removes + * it from the notification center if this is the case. + */ + public function maybe_cleanup_notification() { + $notification = $this->notification_center->get_notification_by_id( self::NOTIFICATION_ID ); + + if ( $notification === null ) { + return; + } + + if ( $this->should_show_notification() ) { + return; + } + + $this->notification_center->remove_notification_by_id( self::NOTIFICATION_ID ); + } + + /** + * Checks whether the notification should be shown. + * + * @return bool If the notification should be shown. + */ + protected function should_show_notification() { + if ( ! $this->environment_helper->is_production_mode() ) { + return false; + } + // Don't show a notification if the indexing has already been started earlier. + if ( $this->indexing_helper->get_started() > 0 ) { + return false; + } + + // Never show a notification when nothing should be indexed. + return $this->indexing_helper->get_filtered_unindexed_count() > 0; + } + + /** + * Returns an instance of the notification. + * + * @return Yoast_Notification The notification to show. + */ + protected function notification() { + $reason = $this->indexing_helper->get_reason(); + + $presenter = $this->get_presenter( $reason ); + + return new Yoast_Notification( + $presenter, + [ + 'type' => Yoast_Notification::WARNING, + 'id' => self::NOTIFICATION_ID, + 'capabilities' => 'wpseo_manage_options', + 'priority' => 0.8, + ] + ); + } + + /** + * Gets the presenter to use to show the notification. + * + * @param string $reason The reason for the notification. + * + * @return Indexing_Failed_Notification_Presenter|Indexing_Notification_Presenter + */ + protected function get_presenter( $reason ) { + if ( $reason === Indexing_Reasons::REASON_INDEXING_FAILED ) { + $presenter = new Indexing_Failed_Notification_Presenter( $this->product_helper, $this->short_link_helper, $this->addon_manager ); + } + else { + $total_unindexed = $this->indexing_helper->get_filtered_unindexed_count(); + $presenter = new Indexing_Notification_Presenter( $this->short_link_helper, $total_unindexed, $reason ); + } + + return $presenter; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/admin/indexing-tool-integration.php b/wp-content/plugins/wordpress-seo/src/integrations/admin/indexing-tool-integration.php new file mode 100644 index 00000000..96708b3b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/admin/indexing-tool-integration.php @@ -0,0 +1,238 @@ +asset_manager = $asset_manager; + $this->indexable_helper = $indexable_helper; + $this->short_link_helper = $short_link_helper; + $this->indexing_helper = $indexing_helper; + $this->addon_manager = $addon_manager; + $this->product_helper = $product_helper; + } + + /** + * Register hooks. + */ + public function register_hooks() { + \add_action( 'wpseo_tools_overview_list_items', [ $this, 'render_indexing_list_item' ], 10 ); + \add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ], 10 ); + } + + /** + * Enqueues the required scripts. + * + * @return void + */ + public function enqueue_scripts() { + $this->asset_manager->enqueue_script( 'indexation' ); + $this->asset_manager->enqueue_style( 'admin-css' ); + $this->asset_manager->enqueue_style( 'monorepo' ); + + $data = [ + 'disabled' => ! $this->indexable_helper->should_index_indexables(), + 'amount' => $this->indexing_helper->get_filtered_unindexed_count(), + 'firstTime' => ( $this->indexing_helper->is_initial_indexing() === true ), + 'errorMessage' => $this->render_indexing_error(), + 'restApi' => [ + 'root' => \esc_url_raw( \rest_url() ), + 'endpoints' => $this->get_endpoints(), + 'nonce' => \wp_create_nonce( 'wp_rest' ), + ], + ]; + + /** + * Filter: 'wpseo_indexing_data' Filter to adapt the data used in the indexing process. + * + * @param array $data The indexing data to adapt. + */ + $data = \apply_filters( 'wpseo_indexing_data', $data ); + + $this->asset_manager->localize_script( 'indexation', 'yoastIndexingData', $data ); + } + + /** + * The error to show if optimization failed. + * + * @return string The error to show if optimization failed. + */ + protected function render_indexing_error() { + $presenter = new Indexing_Error_Presenter( + $this->short_link_helper, + $this->product_helper, + $this->addon_manager + ); + + return $presenter->present(); + } + + /** + * Determines if the site has a valid Premium subscription. + * + * @return bool If the site has a valid Premium subscription. + */ + protected function has_valid_premium_subscription() { + return $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG ); + } + + /** + * Renders the indexing list item. + * + * @return void + */ + public function render_indexing_list_item() { + if ( \current_user_can( 'manage_options' ) ) { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- The output is correctly escaped in the presenter. + echo new Indexing_List_Item_Presenter( $this->short_link_helper ); + } + } + + /** + * Retrieves a list of the endpoints to use. + * + * @return array The endpoints. + */ + protected function get_endpoints() { + $endpoints = [ + 'prepare' => Indexing_Route::FULL_PREPARE_ROUTE, + 'terms' => Indexing_Route::FULL_TERMS_ROUTE, + 'posts' => Indexing_Route::FULL_POSTS_ROUTE, + 'archives' => Indexing_Route::FULL_POST_TYPE_ARCHIVES_ROUTE, + 'general' => Indexing_Route::FULL_GENERAL_ROUTE, + 'indexablesComplete' => Indexing_Route::FULL_INDEXABLES_COMPLETE_ROUTE, + 'post_link' => Indexing_Route::FULL_POST_LINKS_INDEXING_ROUTE, + 'term_link' => Indexing_Route::FULL_TERM_LINKS_INDEXING_ROUTE, + ]; + + $endpoints = \apply_filters( 'wpseo_indexing_endpoints', $endpoints ); + + $endpoints['complete'] = Indexing_Route::FULL_COMPLETE_ROUTE; + + return $endpoints; + } + + /** + * Returns the total number of unindexed objects. + * + * @deprecated 15.3 + * @codeCoverageIgnore + * + * @param int $unindexed_count The total number of unindexed indexables. + * + * @return int The total number of unindexed objects. + */ + public function get_unindexed_indexables_count( $unindexed_count = 0 ) { + \_deprecated_function( __METHOD__, 'WPSEO 15.3' ); + + return $this->indexing_helper->get_unindexed_count(); + } + + /** + * Returns the total number of unindexed objects and applies a filter for third party integrations. + * + * @deprecated 15.3 + * @codeCoverageIgnore + * + * @param int $unindexed_count The total number of unindexed objects. + * + * @return int The total number of unindexed objects. + */ + public function get_unindexed_count( $unindexed_count = 0 ) { + \_deprecated_function( __METHOD__, 'WPSEO 15.3' ); + + return $this->indexing_helper->get_filtered_unindexed_count(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/admin/link-count-columns-integration.php b/wp-content/plugins/wordpress-seo/src/integrations/admin/link-count-columns-integration.php new file mode 100644 index 00000000..a4b2c6df --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/admin/link-count-columns-integration.php @@ -0,0 +1,252 @@ +post_type_helper = $post_type_helper; + $this->wpdb = $wpdb; + $this->post_link_indexing_action = $post_link_indexing_action; + $this->admin_columns_cache = $admin_columns_cache; + } + + /** + * {@inheritDoc} + */ + public function register_hooks() { + \add_filter( 'posts_clauses', [ $this, 'order_by_links' ], 1, 2 ); + \add_filter( 'posts_clauses', [ $this, 'order_by_linked' ], 1, 2 ); + + \add_filter( 'admin_init', [ $this, 'register_init_hooks' ] ); + + // Adds a filter to exclude the attachments from the link count. + \add_filter( 'wpseo_link_count_post_types', [ 'WPSEO_Post_Type', 'filter_attachment_post_type' ] ); + } + + /** + * Register hooks that need to be registered after `init` due to all post types not yet being registered. + */ + public function register_init_hooks() { + $public_post_types = \apply_filters( 'wpseo_link_count_post_types', $this->post_type_helper->get_accessible_post_types() ); + + if ( ! \is_array( $public_post_types ) || empty( $public_post_types ) ) { + return; + } + + foreach ( $public_post_types as $post_type ) { + \add_filter( 'manage_' . $post_type . '_posts_columns', [ $this, 'add_post_columns' ] ); + \add_action( 'manage_' . $post_type . '_posts_custom_column', [ $this, 'column_content' ], 10, 2 ); + \add_filter( 'manage_edit-' . $post_type . '_sortable_columns', [ $this, 'column_sort' ] ); + } + } + + /** + * Adds the columns for the post overview. + * + * @param array $columns Array with columns. + * + * @return array The extended array with columns. + */ + public function add_post_columns( $columns ) { + if ( ! \is_array( $columns ) ) { + return $columns; + } + + $columns[ 'wpseo-' . self::COLUMN_LINKS ] = \sprintf( + '%2$s', + \esc_attr__( 'Number of outgoing internal links in this post. See "Yoast Columns" text in the help tab for more info.', 'wordpress-seo' ), + \esc_html__( 'Outgoing internal links', 'wordpress-seo' ) + ); + + if ( $this->post_link_indexing_action->get_total_unindexed() === 0 ) { + $columns[ 'wpseo-' . self::COLUMN_LINKED ] = \sprintf( + '%2$s', + \esc_attr__( 'Number of internal links linking to this post. See "Yoast Columns" text in the help tab for more info.', 'wordpress-seo' ), + \esc_html__( 'Received internal links', 'wordpress-seo' ) + ); + } + + return $columns; + } + + /** + * Modifies the query pieces to allow ordering column by links to post. + * + * @param array $pieces Array of Query pieces. + * @param WP_Query $query The Query on which to apply. + * + * @return array + */ + public function order_by_linked( $pieces, $query ) { + if ( $query->get( 'orderby' ) !== 'wpseo-' . self::COLUMN_LINKED ) { + return $pieces; + } + + return $this->build_sort_query_pieces( $pieces, $query, 'incoming_link_count' ); + } + + /** + * Modifies the query pieces to allow ordering column by links to post. + * + * @param array $pieces Array of Query pieces. + * @param WP_Query $query The Query on which to apply. + * + * @return array + */ + public function order_by_links( $pieces, $query ) { + if ( $query->get( 'orderby' ) !== 'wpseo-' . self::COLUMN_LINKS ) { + return $pieces; + } + + return $this->build_sort_query_pieces( $pieces, $query, 'link_count' ); + } + + /** + * Builds the pieces for a sorting query. + * + * @param array $pieces Array of Query pieces. + * @param WP_Query $query The Query on which to apply. + * @param string $field The field in the table to JOIN on. + * + * @return array Modified Query pieces. + */ + protected function build_sort_query_pieces( $pieces, $query, $field ) { + // We only want our code to run in the main WP query. + if ( ! $query->is_main_query() ) { + return $pieces; + } + + // Get the order query variable - ASC or DESC. + $order = \strtoupper( $query->get( 'order' ) ); + + // Make sure the order setting qualifies. If not, set default as ASC. + if ( ! \in_array( $order, [ 'ASC', 'DESC' ], true ) ) { + $order = 'ASC'; + } + + $table = Model::get_table_name( 'Indexable' ); + + $pieces['join'] .= " LEFT JOIN $table AS yoast_indexable ON yoast_indexable.object_id = {$this->wpdb->posts}.ID AND yoast_indexable.object_type = 'post' "; + $pieces['orderby'] = "yoast_indexable.$field $order, FIELD( {$this->wpdb->posts}.post_status, 'publish' ) $order, {$pieces['orderby']}"; + + return $pieces; + } + + /** + * Displays the column content for the given column. + * + * @param string $column_name Column to display the content for. + * @param int $post_id Post to display the column content for. + */ + public function column_content( $column_name, $post_id ) { + $indexable = $this->admin_columns_cache->get_indexable( $post_id ); + // Nothing to output if we don't have the value. + if ( $indexable === false ) { + return; + } + + switch ( $column_name ) { + case 'wpseo-' . self::COLUMN_LINKS: + echo (int) $indexable->link_count; + return; + case 'wpseo-' . self::COLUMN_LINKED: + if ( \get_post_status( $post_id ) === 'publish' ) { + echo (int) $indexable->incoming_link_count; + } + } + } + + /** + * Sets the sortable columns. + * + * @param array $columns Array with sortable columns. + * + * @return array The extended array with sortable columns. + */ + public function column_sort( array $columns ) { + $columns[ 'wpseo-' . self::COLUMN_LINKS ] = 'wpseo-' . self::COLUMN_LINKS; + $columns[ 'wpseo-' . self::COLUMN_LINKED ] = 'wpseo-' . self::COLUMN_LINKED; + + return $columns; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/admin/menu-badge-integration.php b/wp-content/plugins/wordpress-seo/src/integrations/admin/menu-badge-integration.php new file mode 100644 index 00000000..7d4c6e43 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/admin/menu-badge-integration.php @@ -0,0 +1,38 @@ +migration_status = $migration_status; + } + + /** + * {@inheritDoc} + */ + public function register_hooks() { + if ( $this->migration_status->get_error( 'free' ) === false ) { + return; + } + + \add_action( 'admin_notices', [ $this, 'render_migration_error' ] ); + } + + /** + * Renders the migration error. + * + * @return void + */ + public function render_migration_error() { + // phpcs:ignore WordPress.Security.EscapeOutput -- The Migration_Error_Presenter already escapes it's output. + echo new Migration_Error_Presenter( $this->migration_status->get_error( 'free' ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/admin/social-templates-integration.php b/wp-content/plugins/wordpress-seo/src/integrations/admin/social-templates-integration.php new file mode 100644 index 00000000..a415c83f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/admin/social-templates-integration.php @@ -0,0 +1,262 @@ +recommended_replace_vars ) ) { + $this->recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars(); + } + + return $this->recommended_replace_vars; + } + + /** + * Returns the editor specific replacements variables object, creating it if needed. + * + * @return \WPSEO_Admin_Editor_Specific_Replace_Vars + */ + protected function get_admin_editor_specific_replace_vars() { + if ( is_null( $this->editor_specific_replace_vars ) ) { + $this->editor_specific_replace_vars = new WPSEO_Admin_Editor_Specific_Replace_Vars(); + } + + return $this->editor_specific_replace_vars; + } + + /** + * Build a set of social fields for the author archives in the Search Appearance section. + * + * @param Yoast_Form $yform The form builder. + */ + public function social_author_archives( $yform ) { + $identifier = 'author-wpseo'; + $page_type_recommended = $this->get_admin_recommended_replace_vars()->determine_for_archive( 'author' ); + $page_type_specific = $this->get_admin_editor_specific_replace_vars()->determine_for_archive( 'author' ); + + $this->build_social_fields( $yform, $identifier, $page_type_recommended, $page_type_specific ); + } + + /** + * Build a set of social fields for the date archives in the Search Appearance section. + * + * @param Yoast_Form $yform The form builder. + */ + public function social_date_archives( $yform ) { + $identifier = 'archive-wpseo'; + $page_type_recommended = $this->get_admin_recommended_replace_vars()->determine_for_archive( 'date' ); + $page_type_specific = $this->get_admin_editor_specific_replace_vars()->determine_for_archive( 'date' ); + + $this->build_social_fields( $yform, $identifier, $page_type_recommended, $page_type_specific ); + } + + /** + * Build a set of social fields for the post types in the Search Appearance section. + * + * @param Yoast_Form $yform The form builder. + * @param string $post_type_name The name of the current post_type that gets the social fields added. + */ + public function social_post_type( $yform, $post_type_name ) { + if ( $post_type_name === 'attachment' ) { + return; + } + + $page_type_recommended = $this->get_admin_recommended_replace_vars()->determine_for_post_type( $post_type_name ); + $page_type_specific = $this->get_admin_editor_specific_replace_vars()->determine_for_post_type( $post_type_name ); + + $this->build_social_fields( $yform, $post_type_name, $page_type_recommended, $page_type_specific ); + } + + /** + * Build a set of social fields for the post types archives in the Search Appearance section. + * + * @param Yoast_Form $yform The form builder. + * @param string $post_type_name The name of the current post_type that gets the social fields added. + */ + public function social_post_types_archive( $yform, $post_type_name ) { + $identifier = 'ptarchive-' . $post_type_name; + $page_type_recommended = $this->get_admin_recommended_replace_vars()->determine_for_archive( $post_type_name ); + $page_type_specific = $this->get_admin_editor_specific_replace_vars()->determine_for_archive( $post_type_name ); + + $this->build_social_fields( $yform, $identifier, $page_type_recommended, $page_type_specific ); + } + + /** + * Build a set of social fields for the taxonomies in the Search Appearance section. + * + * @param Yoast_Form $yform The form builder. + * @param WP_Taxonomy $taxonomy The taxonomy that gets the social fields added. + */ + public function social_taxonomies( $yform, $taxonomy ) { + $identifier = 'tax-' . $taxonomy->name; + $page_type_recommended = $this->get_admin_recommended_replace_vars()->determine_for_term( $taxonomy->name ); + $page_type_specific = $this->get_admin_editor_specific_replace_vars()->determine_for_term( $taxonomy->name ); + + $this->build_social_fields( $yform, $identifier, $page_type_recommended, $page_type_specific ); + } + + /** + * Build a set of social fields for the Search Appearance section. + * + * @param Yoast_Form $yform The form builder. + * @param string $identifier A page-wide unique identifier for data storage and unique DOM elements. + * @param string $page_type_recommended Recommended type of page for a list of replaceable variables. + * @param string $page_type_specific Editor specific type of page for a list of replaceable variables. + */ + protected function build_social_fields( Yoast_Form $yform, $identifier, $page_type_recommended, $page_type_specific ) { + $image_url_field_id = 'social-image-url-' . $identifier; + $image_id_field_id = 'social-image-id-' . $identifier; + $is_premium = YoastSEO()->helpers->product->is_premium(); + $is_premium_16_5_or_up = defined( '\WPSEO_PREMIUM_VERSION' ) && \version_compare( \WPSEO_PREMIUM_VERSION, '16.5-RC0', '>=' ); + $is_form_enabled = $is_premium && $is_premium_16_5_or_up; + + $section_class = 'yoast-settings-section'; + + if ( ! $is_form_enabled ) { + $section_class .= ' yoast-settings-section-disabled'; + } + + \printf( '
    ', \esc_attr( $section_class ) ); + + echo ''; + + $yform->hidden( $image_url_field_id, $image_url_field_id ); + $yform->hidden( $image_id_field_id, $image_id_field_id ); + \printf( + '
    ', + \esc_attr( 'yoast-social-' . $identifier . '-image-select' ), + \esc_attr( $image_url_field_id ), + \esc_attr( $image_id_field_id ), + \esc_attr( ! $is_form_enabled ), + true + ); + + $editor = new WPSEO_Replacevar_Editor( + $yform, + [ + 'title' => 'social-title-' . $identifier, + 'description' => 'social-description-' . $identifier, + 'page_type_recommended' => $page_type_recommended, + 'page_type_specific' => $page_type_specific, + 'paper_style' => false, + 'label_title' => \__( 'Social title', 'wordpress-seo' ), + 'label_description' => \__( 'Social description', 'wordpress-seo' ), + 'description_placeholder' => \__( 'Modify your social description by editing it right here.', 'wordpress-seo' ), + 'is_disabled' => ! $is_form_enabled, + ] + ); + $editor->render(); + + if ( $is_premium && ! $is_premium_16_5_or_up ) { + echo '
    '; + + $unlock_alert = \sprintf( + /* translators: %s expands to 'Yoast SEO Premium'. */ + \esc_html__( 'To unlock this feature please update %s to the latest version.', 'wordpress-seo' ), + 'Yoast SEO Premium' + ); + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output escaped above. + echo new Alert_Presenter( $unlock_alert ); + + echo '
    '; + } + + if ( ! $is_premium ) { + $wpseo_page = filter_input( INPUT_GET, 'page' ); + + echo ''; + } + + echo '
    '; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/admin/workouts-integration.php b/wp-content/plugins/wordpress-seo/src/integrations/admin/workouts-integration.php new file mode 100644 index 00000000..2c6b0cda --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/admin/workouts-integration.php @@ -0,0 +1,100 @@ +admin_asset_manager = $admin_asset_manager; + $this->shortlinker = $shortlinker; + } + + /** + * {@inheritDoc} + */ + public function register_hooks() { + add_filter( 'wpseo_submenu_pages', [ $this, 'add_submenu_page' ], 8 ); + add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] ); + } + + /** + * Adds the workouts submenu page. + * + * @param array $submenu_pages The Yoast SEO submenu pages. + * + * @return array the filtered submenu pages. + */ + public function add_submenu_page( $submenu_pages ) { + // this inserts the workouts menu page at the correct place in the array without overriding that position. + $submenu_pages[] = [ + 'wpseo_dashboard', + '', + \__( 'Workouts', 'wordpress-seo' ) . ' ', + 'edit_others_posts', + 'wpseo_workouts', + [ $this, 'render' ], + ]; + + return $submenu_pages; + } + + /** + * Enqueue the workouts app. + */ + public function enqueue_assets() { + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Date is not processed or saved. + if ( ! isset( $_GET['page'] ) || $_GET['page'] !== 'wpseo_workouts' ) { + return; + } + + $this->admin_asset_manager->enqueue_style( 'workouts' ); + } + + /** + * Renders the target for the React to mount to. + */ + public function render() { + $cornerstone_guide = $this->shortlinker->build_shortlink( 'https://yoa.st/4f1' ); + $cornerstone_upsell = $this->shortlinker->build_shortlink( 'https://yoa.st/4f2' ); + require_once WPSEO_PATH . 'admin/views/workouts.php'; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/alerts/abstract-dismissable-alert.php b/wp-content/plugins/wordpress-seo/src/integrations/alerts/abstract-dismissable-alert.php new file mode 100644 index 00000000..73c02ad8 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/alerts/abstract-dismissable-alert.php @@ -0,0 +1,45 @@ +alert_identifier; + + return $allowed_dismissable_alerts; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/blocks/abstract-dynamic-block.php b/wp-content/plugins/wordpress-seo/src/integrations/blocks/abstract-dynamic-block.php new file mode 100644 index 00000000..4352fb1f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/blocks/abstract-dynamic-block.php @@ -0,0 +1,70 @@ +block_name, + [ + 'editor_script' => $this->script, + 'render_callback' => [ $this, 'present' ], + 'attributes' => [ + 'className' => [ + 'default' => '', + 'type' => 'string', + ], + ], + ] + ); + } + + /** + * Presents the block output. This is abstract because in the loop we need to be able to build the data for the + * presenter in the last moment. + * + * @param array $attributes The block attributes. + * + * @return string The block output. + */ + abstract public function present( $attributes ); +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/blocks/block-categories.php b/wp-content/plugins/wordpress-seo/src/integrations/blocks/block-categories.php new file mode 100644 index 00000000..c14a7590 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/blocks/block-categories.php @@ -0,0 +1,77 @@ +wordpress_helper = $wordpress_helper; + } + + /** + * {@inheritDoc} + */ + public static function get_conditionals() { + return []; + } + + /** + * {@inheritDoc} + */ + public function register_hooks() { + $wordpress_version = $this->wordpress_helper->get_wordpress_version(); + + // The 'block_categories' filter has been deprecated in WordPress 5.8 and replaced by 'block_categories_all'. + if ( \version_compare( $wordpress_version, '5.8-beta0', '<' ) ) { + \add_filter( 'block_categories', [ $this, 'add_block_categories' ] ); + } + else { + \add_filter( 'block_categories_all', [ $this, 'add_block_categories' ] ); + } + } + + /** + * Adds Yoast block categories. + * + * @param array $categories The categories. + * @return array The filtered categories. + */ + public function add_block_categories( $categories ) { + $categories[] = [ + 'slug' => 'yoast-structured-data-blocks', + 'title' => \sprintf( + /* translators: %1$s expands to Yoast. */ + \__( '%1$s Structured Data Blocks', 'wordpress-seo' ), + 'Yoast' + ), + ]; + $categories[] = [ + 'slug' => 'yoast-internal-linking-blocks', + 'title' => \sprintf( + /* translators: %1$s expands to Yoast. */ + \__( '%1$s Internal Linking Blocks', 'wordpress-seo' ), + 'Yoast' + ), + ]; + + return $categories; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/blocks/breadcrumbs-block.php b/wp-content/plugins/wordpress-seo/src/integrations/blocks/breadcrumbs-block.php new file mode 100644 index 00000000..4ba11d77 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/blocks/breadcrumbs-block.php @@ -0,0 +1,124 @@ +context_memoizer = $context_memoizer; + $this->replace_vars = $replace_vars; + $this->helpers = $helpers; + $this->indexable_repository = $indexable_repository; + $this->request_helper = $request_helper; + } + + /** + * Presents the breadcrumbs output for the current page or the available post_id. + * + * @param array $attributes The block attributes. + * + * @return string The block output. + */ + public function present( $attributes ) { + $presenter = new Breadcrumbs_Presenter(); + // $this->context_memoizer->for_current_page only works on the frontend. To render the right breadcrumb in the + // editor, we need the repository. + if ( $this->request_helper->is_rest_request() || \is_admin() ) { + $post_id = \get_the_ID(); + if ( $post_id ) { + $indexable = $this->indexable_repository->find_by_id_and_type( $post_id, 'post' ); + $context = $this->context_memoizer->get( $indexable, 'Post_Type' ); + } + } + if ( ! isset( $context ) ) { + $context = $this->context_memoizer->for_current_page(); + } + + /** This filter is documented in src/integrations/front-end-integration.php */ + $presentation = \apply_filters( 'wpseo_frontend_presentation', $context->presentation, $context ); + $presenter->presentation = $presentation; + $presenter->replace_vars = $this->replace_vars; + $presenter->helpers = $this->helpers; + $class_name = 'yoast-breadcrumbs'; + + if ( ! empty( $attributes['className'] ) ) { + $class_name .= ' ' . \esc_attr( $attributes['className'] ); + } + + return '
    ' . $presenter->present() . '
    '; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/blocks/structured-data-blocks.php b/wp-content/plugins/wordpress-seo/src/integrations/blocks/structured-data-blocks.php new file mode 100644 index 00000000..b44d42ab --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/blocks/structured-data-blocks.php @@ -0,0 +1,59 @@ +asset_manager = $asset_manager; + } + + /** + * Registers hooks for Structured Data Blocks with WordPress. + */ + public function register_hooks() { + \add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_block_editor_assets' ] ); + } + + /** + * Enqueue Gutenberg block assets for backend editor. + */ + public function enqueue_block_editor_assets() { + /** + * Filter: 'wpseo_enable_structured_data_blocks' - Allows disabling Yoast's schema blocks entirely. + * + * @api bool If false, our structured data blocks won't show. + */ + if ( ! \apply_filters( 'wpseo_enable_structured_data_blocks', true ) ) { + return; + } + + $this->asset_manager->enqueue_script( 'structured-data-blocks' ); + $this->asset_manager->enqueue_style( 'structured-data-blocks' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/breadcrumbs-integration.php b/wp-content/plugins/wordpress-seo/src/integrations/breadcrumbs-integration.php new file mode 100644 index 00000000..19fe369e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/breadcrumbs-integration.php @@ -0,0 +1,80 @@ +context_memoizer = $context_memoizer; + $this->presenter = new Breadcrumbs_Presenter(); + $this->presenter->helpers = $helpers; + $this->presenter->replace_vars = $replace_vars; + } + + /** + * Returns the conditionals based in which this loadable should be active. + * + * @return array The array of conditionals. + */ + public static function get_conditionals() { + return []; + } + + /** + * Registers the `wpseo_breadcrumb` shortcode. + * + * @codeCoverageIgnore + */ + public function register_hooks() { + \add_shortcode( 'wpseo_breadcrumb', [ $this, 'render' ] ); + } + + /** + * Renders the breadcrumbs. + * + * @return string The rendered breadcrumbs. + */ + public function render() { + $context = $this->context_memoizer->for_current_page(); + + /** This filter is documented in src/integrations/front-end-integration.php */ + $presentation = \apply_filters( 'wpseo_frontend_presentation', $context->presentation, $context ); + + $this->presenter->presentation = $presentation; + + return $this->presenter->present(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/cleanup-integration.php b/wp-content/plugins/wordpress-seo/src/integrations/cleanup-integration.php new file mode 100644 index 00000000..f92a7b31 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/cleanup-integration.php @@ -0,0 +1,316 @@ +reset_cleanup(); + + $cleanups = $this->get_cleanup_tasks(); + $limit = $this->get_limit(); + + foreach ( $cleanups as $name => $action ) { + $items_cleaned = $action( $limit ); + + if ( $items_cleaned === false ) { + return; + } + + if ( $items_cleaned < $limit ) { + continue; + } + + // There are more items to delete for the current cleanup job, start a cronjob at the specified job. + $this->start_cron_job( $name ); + return; + } + } + + /** + * Returns an array of cleanup tasks. + * + * @return Closure[] The cleanup tasks. + */ + protected function get_cleanup_tasks() { + return \array_merge( + [ + 'clean_indexables_with_object_type_and_object_sub_type_shop_order' => function( $limit ) { + return $this->clean_indexables_with_object_type_and_object_sub_type( 'post', 'shop_order', $limit ); + }, + 'clean_indexables_by_post_status_auto-draft' => function( $limit ) { + return $this->clean_indexables_with_post_status( 'auto-draft', $limit ); + }, + ], + $this->get_additional_tasks(), + [ + /* These should always be the last ones to be called. */ + 'clean_orphaned_content_indexable_hierarchy' => function( $limit ) { + return $this->cleanup_orphaned_from_table( 'Indexable_Hierarchy', 'indexable_id', $limit ); + }, + 'clean_orphaned_content_seo_links_indexable_id' => function( $limit ) { + return $this->cleanup_orphaned_from_table( 'SEO_Links', 'indexable_id', $limit ); + }, + 'clean_orphaned_content_seo_links_target_indexable_id' => function( $limit ) { + return $this->cleanup_orphaned_from_table( 'SEO_Links', 'target_indexable_id', $limit ); + }, + ] + ); + } + + /** + * Gets additional tasks from the 'wpseo_cleanup_tasks' filter. + * + * @return Closure[] Associative array of cleanup functions. + */ + private function get_additional_tasks() { + + /** + * Filter: Adds the possibility to add addition cleanup functions. + * + * @api array Associative array with unique keys. Value should be a cleanup function that receives a limit. + */ + $additional_tasks = \apply_filters( 'wpseo_cleanup_tasks', [] ); + + if ( ! is_array( $additional_tasks ) ) { + return []; + } + + foreach ( $additional_tasks as $key => $value ) { + if ( is_int( $key ) ) { + return []; + } + if ( ( ! is_object( $value ) ) || ! ( $value instanceof Closure ) ) { + return []; + } + } + + return $additional_tasks; + } + + /** + * Gets the deletion limit for cleanups. + * + * @return int The limit for the amount of entities to be cleaned. + */ + private function get_limit() { + /** + * Filter: Adds the possibility to limit the number of items that are deleted from the database on cleanup. + * + * @api int $limit Maximum number of indexables to be cleaned up per query. + */ + $limit = \apply_filters( 'wpseo_cron_query_limit_size', 1000 ); + + if ( ! \is_int( $limit ) ) { + $limit = 1000; + } + + return \abs( $limit ); + } + + /** + * Resets and stops the cleanup integration. + * + * @return void + */ + public function reset_cleanup() { + \delete_option( self::CURRENT_TASK_OPTION ); + \wp_unschedule_hook( self::CRON_HOOK ); + } + + /** + * Starts the cleanup cron job. + * + * @param string $task_name The task name of the next cleanup task to run. + * + * @return void + */ + private function start_cron_job( $task_name ) { + \update_option( self::CURRENT_TASK_OPTION, $task_name ); + \wp_schedule_event( + ( \time() + HOUR_IN_SECONDS ), + 'hourly', + self::CRON_HOOK + ); + } + + /** + * The callback that is called for the cleanup cron job. + * + * @return void + */ + public function run_cleanup_cron() { + $current_task_name = \get_option( self::CURRENT_TASK_OPTION ); + + if ( $current_task_name === false ) { + $this->reset_cleanup(); + return; + } + + $limit = $this->get_limit(); + $tasks = $this->get_cleanup_tasks(); + + // The task may have been added by a filter that has been removed, in that case just start over. + if ( ! isset( $tasks[ $current_task_name ] ) ) { + $current_task_name = \key( $tasks ); + } + + $current_task = \current( $tasks ); + while ( $current_task !== false ) { + // Skip the tasks that have already been done. + if ( \key( $tasks ) !== $current_task_name ) { + $current_task = \next( $tasks ); + continue; + } + + // Call the cleanup callback function that accompanies the current task. + $items_cleaned = $current_task( $limit ); + + if ( $items_cleaned === false ) { + $this->reset_cleanup(); + return; + } + + if ( $items_cleaned === 0 ) { + // Check if we are finished with all tasks. + if ( \next( $tasks ) === false ) { + $this->reset_cleanup(); + return; + } + + // Continue with the next task next time the cron job is run. + \update_option( self::CURRENT_TASK_OPTION, \key( $tasks ) ); + return; + } + // There were items deleted for the current task, continue with the same task next cron call. + return; + } + } + + /** + * Deletes rows from the indexable table depending on the object_type and object_sub_type. + * + * @param string $object_type The object type to query. + * @param string $object_sub_type The object subtype to query. + * @param int $limit The limit we'll apply to the delete query. + * + * @return int|bool The number of rows that was deleted or false if the query failed. + */ + protected function clean_indexables_with_object_type_and_object_sub_type( $object_type, $object_sub_type, $limit ) { + global $wpdb; + + $indexable_table = Model::get_table_name( 'Indexable' ); + + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. + $sql = $wpdb->prepare( "DELETE FROM $indexable_table WHERE object_type = %s AND object_sub_type = %s ORDER BY id LIMIT %d", $object_type, $object_sub_type, $limit ); + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: Already prepared. + return $wpdb->query( $sql ); + } + + /** + * Deletes rows from the indexable table depending on the post_status. + * + * @param string $post_status The post status to query. + * @param int $limit The limit we'll apply to the delete query. + * + * @return int|bool The number of rows that was deleted or false if the query failed. + */ + protected function clean_indexables_with_post_status( $post_status, $limit ) { + global $wpdb; + + $indexable_table = Model::get_table_name( 'Indexable' ); + + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. + $sql = $wpdb->prepare( "DELETE FROM $indexable_table WHERE object_type = 'post' AND post_status = %s ORDER BY id LIMIT %d", $post_status, $limit ); + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: Already prepared. + return $wpdb->query( $sql ); + } + + /** + * Cleans orphaned rows from a yoast table. + * + * @param string $table The table to clean up. + * @param string $column The table column the cleanup will rely on. + * @param int $limit The limit we'll apply to the queries. + * + * @return int|bool The number of deleted rows, false if the query fails. + */ + protected function cleanup_orphaned_from_table( $table, $column, $limit ) { + global $wpdb; + + $table = Model::get_table_name( $table ); + $indexable_table = Model::get_table_name( 'Indexable' ); + + // Warning: If this query is changed, make sure to update the query in cleanup_orphaned_from_table in Premium as well. + // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input. + $query = $wpdb->prepare( + " + SELECT table_to_clean.{$column} + FROM {$table} table_to_clean + LEFT JOIN {$indexable_table} AS indexable_table + ON table_to_clean.{$column} = indexable_table.id + WHERE indexable_table.id IS NULL + AND table_to_clean.{$column} IS NOT NULL + LIMIT %d", + $limit + ); + // phpcs:enable + + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: Already prepared. + $orphans = $wpdb->get_col( $query ); + + if ( empty( $orphans ) ) { + return 0; + } + + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Reason: Already prepared. + return $wpdb->query( "DELETE FROM $table WHERE {$column} IN( " . implode( ',', $orphans ) . ' )' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/duplicate-post-integration.php b/wp-content/plugins/wordpress-seo/src/integrations/duplicate-post-integration.php new file mode 100644 index 00000000..09dd6744 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/duplicate-post-integration.php @@ -0,0 +1,36 @@ + 'hidden', + 'title' => 'estimated-reading-time-minutes', + ]; + } + + return $field_defs; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/exclude-oembed-cache-post-type.php b/wp-content/plugins/wordpress-seo/src/integrations/exclude-oembed-cache-post-type.php new file mode 100644 index 00000000..811ae2ab --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/exclude-oembed-cache-post-type.php @@ -0,0 +1,34 @@ +asset_manager = $asset_manager; + $this->feature_flags = $feature_flags; + } + + /** + * Returns the conditionals based on which this loadable should be active. + * + * @return string[] The conditionals based on which this loadable should be active. + */ + public static function get_conditionals() { + return [ Admin_Conditional::class ]; + } + + /** + * Initializes the integration. + * + * @return void + */ + public function register_hooks() { + \add_action( 'admin_init', [ $this, 'add_feature_flags' ] ); + } + + /** + * Gathers all the feature flags and injects them into the JavaScript. + * + * @return void + */ + public function add_feature_flags() { + $enabled_features = $this->get_enabled_features(); + // Localize under both names for BC. + $this->asset_manager->localize_script( 'feature-flag-package', 'wpseoFeatureFlags', $enabled_features ); + $this->asset_manager->localize_script( 'feature-flag-package', 'wpseoFeaturesL10n', $enabled_features ); + } + + /** + * Returns an array of all enabled feature flags. + * + * @return string[] The array of enabled features. + */ + public function get_enabled_features() { + $enabled_features = []; + foreach ( $this->feature_flags as $feature_flag ) { + if ( $feature_flag->is_met() ) { + $enabled_features[] = $feature_flag->get_feature_name(); + } + } + + return $this->filter_enabled_features( $enabled_features ); + } + + /** + * Runs the list of enabled feature flags through a filter. + * + * @param string[] $enabled_features The list of currently enabled feature flags. + * + * @return string[] The (possibly adapted) list of enabled features. + */ + protected function filter_enabled_features( $enabled_features ) { + /** + * Filters the list of currently enabled feature flags. + * + * @param string[] $enabled_features The current list of enabled feature flags. + */ + $filtered_enabled_features = \apply_filters( 'wpseo_enable_feature', $enabled_features ); + + if ( ! \is_array( $filtered_enabled_features ) ) { + $filtered_enabled_features = $enabled_features; + } + + return $filtered_enabled_features; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/front-end-integration.php b/wp-content/plugins/wordpress-seo/src/integrations/front-end-integration.php new file mode 100644 index 00000000..dbd32280 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/front-end-integration.php @@ -0,0 +1,453 @@ +container = $service_container; + $this->context_memoizer = $context_memoizer; + $this->options = $options; + $this->request = $request; + $this->helpers = $helpers; + $this->replace_vars = $replace_vars; + } + + /** + * Registers the appropriate hooks to show the SEO metadata on the frontend. + * + * Removes some actions to remove metadata that WordPress shows on the frontend, + * to avoid duplicate and/or mismatched metadata. + */ + public function register_hooks() { + \add_action( 'wp_head', [ $this, 'call_wpseo_head' ], 1 ); + // Filter the title for compatibility with other plugins and themes. + \add_filter( 'wp_title', [ $this, 'filter_title' ], 15 ); + + // Removes our robots presenter from the list when wp_robots is handling this. + \add_filter( 'wpseo_frontend_presenter_classes', [ $this, 'filter_robots_presenter' ] ); + + \add_action( 'wpseo_head', [ $this, 'present_head' ], -9999 ); + + \remove_action( 'wp_head', 'rel_canonical' ); + \remove_action( 'wp_head', 'index_rel_link' ); + \remove_action( 'wp_head', 'start_post_rel_link' ); + \remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head' ); + \remove_action( 'wp_head', 'noindex', 1 ); + \remove_action( 'wp_head', '_wp_render_title_tag', 1 ); + \remove_action( 'wp_head', 'gutenberg_render_title_tag', 1 ); + } + + /** + * Filters the title, mainly used for compatibility reasons. + * + * @return string + */ + public function filter_title() { + $context = $this->context_memoizer->for_current_page(); + + $title_presenter = new Title_Presenter(); + + /** This filter is documented in src/integrations/front-end-integration.php */ + $title_presenter->presentation = \apply_filters( 'wpseo_frontend_presentation', $context->presentation, $context ); + $title_presenter->replace_vars = $this->replace_vars; + $title_presenter->helpers = $this->helpers; + + return \esc_html( $title_presenter->get() ); + } + + /** + * Filters our robots presenter, but only when wp_robots is attached to the wp_head action. + * + * @param array $presenters The presenters for current page. + * + * @return array The filtered presenters. + */ + public function filter_robots_presenter( $presenters ) { + if ( ! \function_exists( 'wp_robots' ) ) { + return $presenters; + } + + if ( ! \has_action( 'wp_head', 'wp_robots' ) ) { + return $presenters; + } + + if ( $this->request->is_rest_request() ) { + return $presenters; + } + + return \array_diff( $presenters, [ 'Yoast\\WP\\SEO\\Presenters\\Robots_Presenter' ] ); + } + + /** + * Presents the head in the front-end. Resets wp_query if it's not the main query. + * + * @codeCoverageIgnore It just calls a WordPress function. + */ + public function call_wpseo_head() { + global $wp_query; + + $old_wp_query = $wp_query; + // phpcs:ignore WordPress.WP.DiscouragedFunctions.wp_reset_query_wp_reset_query -- Reason: The recommended function, wp_reset_postdata, doesn't reset wp_query. + \wp_reset_query(); + + \do_action( 'wpseo_head' ); + + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Reason: we have to restore the query. + $GLOBALS['wp_query'] = $old_wp_query; + } + + /** + * Echoes all applicable presenters for a page. + */ + public function present_head() { + $context = $this->context_memoizer->for_current_page(); + $presenters = $this->get_presenters( $context->page_type, $context ); + + /** + * Filter 'wpseo_frontend_presentation' - Allow filtering the presentation used to output our meta values. + * + * @api Indexable_Presention The indexable presentation. + */ + $presentation = \apply_filters( 'wpseo_frontend_presentation', $context->presentation, $context ); + + echo \PHP_EOL; + foreach ( $presenters as $presenter ) { + $presenter->presentation = $presentation; + $presenter->helpers = $this->helpers; + $presenter->replace_vars = $this->replace_vars; + + $output = $presenter->present(); + if ( ! empty( $output ) ) { + // phpcs:ignore WordPress.Security.EscapeOutput -- Presenters are responsible for correctly escaping their output. + echo "\t" . $output . \PHP_EOL; + } + } + echo \PHP_EOL . \PHP_EOL; + } + + /** + * Returns all presenters for this page. + * + * @param string $page_type The page type. + * @param Meta_Tags_Context $context The meta tags context for the current page. + * + * @return Abstract_Indexable_Presenter[] The presenters. + */ + public function get_presenters( $page_type, $context = null ) { + if ( \is_null( $context ) ) { + $context = $this->context_memoizer->for_current_page(); + } + + $needed_presenters = $this->get_needed_presenters( $page_type ); + + $callback = static function( $presenter ) { + if ( ! \class_exists( $presenter ) ) { + return null; + } + return new $presenter(); + }; + $presenters = \array_filter( \array_map( $callback, $needed_presenters ) ); + + /** + * Filter 'wpseo_frontend_presenters' - Allow filtering the presenter instances in or out of the request. + * + * @param $presenters array The presenters. + * @param Meta_Tags_Context The meta tags context for the current page. + * + * @api Abstract_Indexable_Presenter[] List of presenter instances. + */ + $presenter_instances = \apply_filters( 'wpseo_frontend_presenters', $presenters, $context ); + + if ( ! \is_array( $presenter_instances ) ) { + $presenter_instances = $presenters; + } + + $is_presenter_callback = static function ( $presenter_instance ) { + return $presenter_instance instanceof Abstract_Indexable_Presenter; + }; + $presenter_instances = \array_filter( $presenter_instances, $is_presenter_callback ); + + return \array_merge( + [ new Marker_Open_Presenter() ], + $presenter_instances, + [ new Marker_Close_Presenter() ] + ); + } + + /** + * Generate the array of presenters we need for the current request. + * + * @param string $page_type The page type we're retrieving presenters for. + * + * @return string[] The presenters. + */ + private function get_needed_presenters( $page_type ) { + $presenters = $this->get_presenters_for_page_type( $page_type ); + + if ( ! \get_theme_support( 'title-tag' ) && ! $this->options->get( 'forcerewritetitle', false ) ) { + // Remove the title presenter if the theme is hardcoded to output a title tag so we don't have two title tags. + $presenters = \array_diff( $presenters, [ 'Title' ] ); + } + + $callback = static function ( $presenter ) { + return "Yoast\WP\SEO\Presenters\\{$presenter}_Presenter"; + }; + $presenters = \array_map( $callback, $presenters ); + + /** + * Filter 'wpseo_frontend_presenter_classes' - Allow filtering presenters in or out of the request. + * + * @api array List of presenters. + */ + $presenters = \apply_filters( 'wpseo_frontend_presenter_classes', $presenters ); + + return $presenters; + } + + /** + * Filters the presenters based on the page type. + * + * @param string $page_type The page type. + * + * @return string[] The presenters. + */ + private function get_presenters_for_page_type( $page_type ) { + if ( $page_type === 'Error_Page' ) { + $presenters = $this->base_presenters; + if ( $this->options->get( 'opengraph' ) === true ) { + $presenters = \array_merge( $presenters, $this->open_graph_error_presenters ); + } + return \array_merge( $presenters, $this->closing_presenters ); + } + + $presenters = $this->get_all_presenters(); + if ( \in_array( $page_type, [ 'Static_Home_Page', 'Home_Page' ], true ) ) { + $presenters = \array_merge( $presenters, $this->webmaster_verification_presenters ); + } + + // Filter out the presenters only needed for singular pages on non-singular pages. + if ( ! \in_array( $page_type, [ 'Post_Type', 'Static_Home_Page' ], true ) ) { + $presenters = \array_diff( $presenters, $this->singular_presenters ); + } + + return $presenters; + } + + /** + * Returns a list of all available presenters based on settings. + * + * @return string[] The presenters. + */ + private function get_all_presenters() { + $presenters = \array_merge( $this->base_presenters, $this->indexing_directive_presenters ); + if ( $this->options->get( 'opengraph' ) === true ) { + $presenters = \array_merge( $presenters, $this->open_graph_presenters ); + } + if ( $this->options->get( 'twitter' ) === true && \apply_filters( 'wpseo_output_twitter_card', true ) !== false ) { + $presenters = \array_merge( $presenters, $this->twitter_card_presenters ); + } + if ( $this->options->get( 'enable_enhanced_slack_sharing' ) === true && \apply_filters( 'wpseo_output_enhanced_slack_data', true ) !== false ) { + $presenters = \array_merge( $presenters, $this->slack_presenters ); + } + + return \array_merge( $presenters, $this->closing_presenters ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/front-end/backwards-compatibility.php b/wp-content/plugins/wordpress-seo/src/integrations/front-end/backwards-compatibility.php new file mode 100644 index 00000000..dd139722 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/front-end/backwards-compatibility.php @@ -0,0 +1,72 @@ +options = $options; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + if ( $this->options->get( 'opengraph' ) === true ) { + \add_action( 'wpseo_head', [ $this, 'call_wpseo_opengraph' ], 30 ); + } + if ( $this->options->get( 'twitter' ) === true && \apply_filters( 'wpseo_output_twitter_card', true ) !== false ) { + \add_action( 'wpseo_head', [ $this, 'call_wpseo_twitter' ], 40 ); + } + } + + /** + * Calls the old wpseo_opengraph action. + * + * @return void + */ + public function call_wpseo_opengraph() { + \do_action_deprecated( 'wpseo_opengraph', [], '14.0', 'wpseo_frontend_presenters' ); + } + + /** + * Calls the old wpseo_twitter action. + * + * @return void + */ + public function call_wpseo_twitter() { + \do_action_deprecated( 'wpseo_twitter', [], '14.0', 'wpseo_frontend_presenters' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/front-end/category-term-description.php b/wp-content/plugins/wordpress-seo/src/integrations/front-end/category-term-description.php new file mode 100644 index 00000000..a4a9038f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/front-end/category-term-description.php @@ -0,0 +1,51 @@ +redirect = $redirect; + $this->robots = $robots; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + if ( $this->clean_reply_to_com() ) { + \add_filter( 'comment_reply_link', [ $this, 'remove_reply_to_com' ] ); + \add_action( 'template_redirect', [ $this, 'replytocom_redirect' ], 1 ); + } + + // When users view a reply to a comment, this URL parameter is set. These should never be indexed separately. + if ( $this->has_replytocom_parameter() ) { + \add_filter( 'wpseo_robots_array', [ $this->robots, 'set_robots_no_index' ] ); + } + } + + /** + * Checks if the url contains the ?replytocom query parameter. + * + * @codeCoverageIgnore Wraps the filter input. + * + * @return string The value of replytocom. + */ + protected function has_replytocom_parameter() { + return \filter_input( \INPUT_GET, 'replytocom' ); + } + + /** + * Removes the ?replytocom variable from the link, replacing it with a #comment- anchor. + * + * @todo Should this function also allow for relative urls ? + * + * @param string $link The comment link as a string. + * + * @return string The modified link. + */ + public function remove_reply_to_com( $link ) { + return \preg_replace( '`href=(["\'])(?:.*(?:\?|&|&)replytocom=(\d+)#respond)`', 'href=$1#comment-$2', $link ); + } + + /** + * Redirects out the ?replytocom variables. + * + * @return bool True when redirect has been done. + */ + public function replytocom_redirect() { + if ( isset( $_GET['replytocom'] ) && \is_singular() ) { + $url = \get_permalink( $GLOBALS['post']->ID ); + $hash = \sanitize_text_field( \wp_unslash( $_GET['replytocom'] ) ); + $query_string = ''; + if ( isset( $_SERVER['QUERY_STRING'] ) ) { + $query_string = \remove_query_arg( 'replytocom', \sanitize_text_field( \wp_unslash( $_SERVER['QUERY_STRING'] ) ) ); + } + if ( ! empty( $query_string ) ) { + $url .= '?' . $query_string; + } + $url .= '#comment-' . $hash; + + $this->redirect->do_safe_redirect( $url, 301 ); + + return true; + } + + return false; + } + + /** + * Checks whether we can allow the feature that removes ?replytocom query parameters. + * + * @codeCoverageIgnore It just wraps a call to a filter. + * + * @return bool True to remove, false not to remove. + */ + private function clean_reply_to_com() { + /** + * Filter: 'wpseo_remove_reply_to_com' - Allow disabling the feature that removes ?replytocom query parameters. + * + * @param bool $return True to remove, false not to remove. + */ + return (bool) \apply_filters( 'wpseo_remove_reply_to_com', true ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/front-end/force-rewrite-title.php b/wp-content/plugins/wordpress-seo/src/integrations/front-end/force-rewrite-title.php new file mode 100644 index 00000000..48afd395 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/front-end/force-rewrite-title.php @@ -0,0 +1,177 @@ +options = $options; + $this->wp_query = $wp_query; + } + + /** + * Returns the conditionals based in which this loadable should be active. + * + * @return array + */ + public static function get_conditionals() { + return [ Front_End_Conditional::class ]; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @codeCoverageIgnore + * + * @return void + */ + public function register_hooks() { + // When the option is disabled. + if ( ! $this->options->get( 'forcerewritetitle', false ) ) { + return; + } + + // For WordPress versions below 4.4. + if ( \current_theme_supports( 'title-tag' ) ) { + return; + } + + \add_action( 'template_redirect', [ $this, 'force_rewrite_output_buffer' ], 99999 ); + \add_action( 'wp_footer', [ $this, 'flush_cache' ], -1 ); + } + + /** + * Used in the force rewrite functionality this retrieves the output, replaces the title with the proper SEO + * title and then flushes the output. + * + * @return bool + */ + public function flush_cache() { + if ( $this->ob_started !== true ) { + return false; + } + + $content = $this->get_buffered_output(); + + $old_wp_query = $this->wp_query->get_query(); + + \wp_reset_query(); + + // When the file has the debug mark. + if ( \preg_match( '/(?\'before\'.*)(?\'after\'.*)/is', $content, $matches ) ) { + $content = $this->replace_titles_from_content( $content, $matches ); + + unset( $matches ); + } + + // phpcs:ignore WordPress.WP.GlobalVariablesOverride -- The query gets reset here with the original query. + $GLOBALS['wp_query'] = $old_wp_query; + + // phpcs:ignore WordPress.Security.EscapeOutput -- The output should already have been escaped, we are only filtering it. + echo $content; + + return true; + } + + /** + * Starts the output buffer so it can later be fixed by flush_cache(). + */ + public function force_rewrite_output_buffer() { + $this->ob_started = true; + $this->start_output_buffering(); + } + + /** + * Replaces the titles from the parts that contains a title. + * + * @param string $content The content to remove the titles from. + * @param array $parts_with_title The parts containing a title. + * + * @return string The modified content. + */ + protected function replace_titles_from_content( $content, $parts_with_title ) { + if ( isset( $parts_with_title['before'] ) && \is_string( $parts_with_title['before'] ) ) { + $content = $this->replace_title( $parts_with_title['before'], $content ); + } + + if ( isset( $parts_with_title['after'] ) ) { + $content = $this->replace_title( $parts_with_title['after'], $content ); + } + + return $content; + } + + /** + * Removes the title from the part that contains the title and put this modified part back + * into the content. + * + * @param string $part_with_title The part with the title that needs to be replaced. + * @param string $content The entire content. + * + * @return string The altered content. + */ + protected function replace_title( $part_with_title, $content ) { + $part_without_title = \preg_replace( '//i', '', $part_with_title ); + + return \str_replace( $part_with_title, $part_without_title, $content ); + } + + /** + * Starts the output buffering. + * + * @codeCoverageIgnore + */ + protected function start_output_buffering() { + \ob_start(); + } + + /** + * Retrieves the buffered output. + * + * @codeCoverageIgnore + * + * @return false|string The buffered output. + */ + protected function get_buffered_output() { + return \ob_get_clean(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/front-end/handle-404.php b/wp-content/plugins/wordpress-seo/src/integrations/front-end/handle-404.php new file mode 100644 index 00000000..2ef0fb7c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/front-end/handle-404.php @@ -0,0 +1,122 @@ +query_wrapper = $query_wrapper; + } + + /** + * Handles the 404 status code. + * + * @param bool $handled Whether we've handled the request. + * + * @return bool True if it's 404. + */ + public function handle_404( $handled ) { + if ( ! $this->is_feed_404() ) { + return $handled; + } + + $this->set_404(); + $this->set_headers(); + + \add_filter( 'old_slug_redirect_url', '__return_false' ); + \add_filter( 'redirect_canonical', '__return_false' ); + + return true; + } + + /** + * If there are no posts in a feed, make it 404 instead of sending an empty RSS feed. + * + * @return bool True if it's 404. + */ + protected function is_feed_404() { + if ( ! \is_feed() ) { + return false; + } + + $wp_query = $this->query_wrapper->get_query(); + + // Don't 404 if the query contains post(s) or an object. + if ( $wp_query->posts || $wp_query->get_queried_object() ) { + return false; + } + + // Don't 404 if it isn't archive or singular. + if ( ! $wp_query->is_archive() && ! $wp_query->is_singular() ) { + return false; + } + + return true; + } + + /** + * Sets the 404 status code. + */ + protected function set_404() { + $wp_query = $this->query_wrapper->get_query(); + $wp_query->is_feed = false; + $wp_query->set_404(); + $this->query_wrapper->set_query( $wp_query ); + } + + /** + * Sets the headers for http. + * + * @codeCoverageIgnore + */ + protected function set_headers() { + // Overwrite Content-Type header. + if ( ! \headers_sent() ) { + \header( 'Content-Type: ' . \get_option( 'html_type' ) . '; charset=' . \get_option( 'blog_charset' ) ); + } + + \status_header( 404 ); + \nocache_headers(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/front-end/indexing-controls.php b/wp-content/plugins/wordpress-seo/src/integrations/front-end/indexing-controls.php new file mode 100644 index 00000000..a60b15ec --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/front-end/indexing-controls.php @@ -0,0 +1,109 @@ +robots = $robots; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @codeCoverageIgnore + * + * @return void + */ + public function register_hooks() { + // The option `blog_public` is set in Settings > Reading > Search Engine Visibility. + if ( (string) \get_option( 'blog_public' ) === '0' ) { + \add_filter( 'wpseo_robots_array', [ $this->robots, 'set_robots_no_index' ] ); + } + + \add_action( 'template_redirect', [ $this, 'noindex_robots' ] ); + \add_filter( 'loginout', [ $this, 'nofollow_link' ] ); + \add_filter( 'register', [ $this, 'nofollow_link' ] ); + + // Remove actions that we will handle through our wpseo_head call, and probably change the output of. + \remove_action( 'wp_head', 'rel_canonical' ); + \remove_action( 'wp_head', 'index_rel_link' ); + \remove_action( 'wp_head', 'start_post_rel_link' ); + \remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head' ); + \remove_action( 'wp_head', 'noindex', 1 ); + } + + /** + * Sends a Robots HTTP header preventing URL from being indexed in the search results while allowing search engines + * to follow the links in the object at the URL. + * + * @return bool Boolean indicating whether the noindex header was sent. + */ + public function noindex_robots() { + if ( ! \is_robots() ) { + return false; + } + + return $this->set_robots_header(); + } + + /** + * Adds rel="nofollow" to a link, only used for login / registration links. + * + * @param string $input The link element as a string. + * + * @return string + */ + public function nofollow_link( $input ) { + return \str_replace( 'meta = $meta; + } + + /** + * Callback function to pass to the oEmbed's response data that will enable + * support for using the image and title set by the WordPress SEO plugin's fields. This + * address the concern where some social channels/subscribed use oEmebed data over Open Graph data + * if both are present. + * + * @link https://developer.wordpress.org/reference/hooks/oembed_response_data/ for hook info. + * + * @param array $data The oEmbed data. + * @param WP_Post $post The current Post object. + * + * @return array An array of oEmbed data with modified values where appropriate. + */ + public function set_oembed_data( $data, $post ) { + // Data to be returned. + $this->data = $data; + $this->post_id = $post->ID; + + $this->set_title(); + $this->set_description(); + $this->set_image(); + + return $this->data; + } + + /** + * Sets the OpenGraph title if configured. + */ + protected function set_title() { + $opengraph_title = $this->meta->for_post( $this->post_id )->open_graph_title; + + if ( ! empty( $opengraph_title ) ) { + $this->data['title'] = $opengraph_title; + } + } + + /** + * Sets the OpenGraph description if configured. + */ + protected function set_description() { + $opengraph_description = $this->meta->for_post( $this->post_id )->open_graph_description; + + if ( ! empty( $opengraph_description ) ) { + $this->data['description'] = $opengraph_description; + } + } + + /** + * Sets the image if it has been configured. + */ + protected function set_image() { + $images = $this->meta->for_post( $this->post_id )->open_graph_images; + $image = \reset( $images ); + + if ( empty( $image ) ) { + return; + } + + if ( ! isset( $image['url'] ) ) { + return; + } + + $this->data['thumbnail_url'] = $image['url']; + + if ( isset( $image['width'] ) ) { + $this->data['thumbnail_width'] = $image['width']; + } + + if ( isset( $image['height'] ) ) { + $this->data['thumbnail_height'] = $image['height']; + } + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/front-end/redirects.php b/wp-content/plugins/wordpress-seo/src/integrations/front-end/redirects.php new file mode 100644 index 00000000..cc46fcd2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/front-end/redirects.php @@ -0,0 +1,179 @@ +options = $options; + $this->meta = $meta; + $this->current_page = $current_page; + $this->redirect = $redirect; + } + + /** + * Returns the conditionals based in which this loadable should be active. + * + * @return array + */ + public static function get_conditionals() { + return [ Front_End_Conditional::class ]; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_action( 'wp', [ $this, 'archive_redirect' ] ); + \add_action( 'wp', [ $this, 'page_redirect' ], 99 ); + \add_action( 'template_redirect', [ $this, 'attachment_redirect' ], 1 ); + } + + /** + * When certain archives are disabled, this redirects those to the homepage. + */ + public function archive_redirect() { + if ( $this->need_archive_redirect() ) { + $this->redirect->do_safe_redirect( \get_bloginfo( 'url' ), 301 ); + } + } + + /** + * Based on the redirect meta value, this function determines whether it should redirect the current post / page. + */ + public function page_redirect() { + if ( ! $this->current_page->is_simple_page() ) { + return; + } + + $post = \get_post(); + if ( ! \is_object( $post ) ) { + return; + } + + $redirect = $this->meta->get_value( 'redirect', $post->ID ); + if ( $redirect === '' ) { + return; + } + + $this->redirect->do_safe_redirect( $redirect, 301 ); + } + + /** + * If the option to disable attachment URLs is checked, this performs the redirect to the attachment. + */ + public function attachment_redirect() { + if ( ! $this->current_page->is_attachment() ) { + return; + } + + if ( $this->options->get( 'disable-attachment', false ) === false ) { + return; + } + + $url = $this->get_attachment_url(); + if ( empty( $url ) ) { + return; + } + + $this->redirect->do_unsafe_redirect( $url, 301 ); + } + + /** + * Checks if certain archive pages are disabled to determine if a archive redirect is needed. + * + * @codeCoverageIgnore + * + * @return bool Whether or not to redirect an archive page. + */ + protected function need_archive_redirect() { + if ( $this->options->get( 'disable-date', false ) && $this->current_page->is_date_archive() ) { + return true; + } + + if ( $this->options->get( 'disable-author', false ) && $this->current_page->is_author_archive() ) { + return true; + } + + if ( $this->options->get( 'disable-post_format', false ) && $this->current_page->is_post_format_archive() ) { + return true; + } + + return false; + } + + /** + * Retrieves the attachment url for the current page. + * + * @codeCoverageIgnore It wraps WordPress functions. + * + * @return string The attachment url. + */ + protected function get_attachment_url() { + /** + * Allows the developer to change the target redirection URL for attachments. + * + * @api string $attachment_url The attachment URL for the queried object. + * @api object $queried_object The queried object. + * + * @since 7.5.3 + */ + return \apply_filters( + 'wpseo_attachment_redirect_url', + \wp_get_attachment_url( \get_queried_object_id() ), + \get_queried_object() + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/front-end/rss-footer-embed.php b/wp-content/plugins/wordpress-seo/src/integrations/front-end/rss-footer-embed.php new file mode 100644 index 00000000..631e0bfd --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/front-end/rss-footer-embed.php @@ -0,0 +1,197 @@ +options = $options; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_filter( 'the_content_feed', [ $this, 'embed_rssfooter' ] ); + \add_filter( 'the_excerpt_rss', [ $this, 'embed_rssfooter_excerpt' ] ); + } + + /** + * Adds the RSS footer (or header) to the full RSS feed item. + * + * @param string $content Feed item content. + * + * @return string + */ + public function embed_rssfooter( $content ) { + if ( ! $this->include_rss_footer( 'full' ) ) { + return $content; + } + + return $this->embed_rss( $content ); + } + + /** + * Adds the RSS footer (or header) to the excerpt RSS feed item. + * + * @param string $content Feed item excerpt. + * + * @return string + */ + public function embed_rssfooter_excerpt( $content ) { + if ( ! $this->include_rss_footer( 'excerpt' ) ) { + return $content; + } + + return $this->embed_rss( \wpautop( $content ) ); + } + + /** + * Checks if the RSS footer should included. + * + * @param string $context The context of the RSS content. + * + * @return bool Whether or not the RSS footer should included. + */ + protected function include_rss_footer( $context ) { + if ( ! \is_feed() ) { + return false; + } + + /** + * Filter: 'wpseo_include_rss_footer' - Allow the RSS footer to be dynamically shown/hidden. + * + * @api boolean $show_embed Indicates if the RSS footer should be shown or not. + * + * @param string $context The context of the RSS content - 'full' or 'excerpt'. + */ + if ( ! \apply_filters( 'wpseo_include_rss_footer', true, $context ) ) { + return false; + } + + return $this->is_configured(); + } + + /** + * Checks if the RSS feed fields are configured. + * + * @return bool True when one of the fields has a value. + */ + protected function is_configured() { + return ( $this->options->get( 'rssbefore', '' ) !== '' || $this->options->get( 'rssafter', '' ) ); + } + + /** + * Adds the RSS footer and/or header to an RSS feed item. + * + * @param string $content Feed item content. + * + * @return string The content to add. + */ + protected function embed_rss( $content ) { + $before = $this->rss_replace_vars( $this->options->get( 'rssbefore', '' ) ); + $after = $this->rss_replace_vars( $this->options->get( 'rssafter', '' ) ); + $content = $before . $content . $after; + + return $content; + } + + /** + * Replaces the possible RSS variables with their actual values. + * + * @param string $content The RSS content that should have the variables replaced. + * + * @return string + */ + protected function rss_replace_vars( $content ) { + if ( $content === '' ) { + return $content; + } + + $replace_vars = $this->get_replace_vars( $this->get_link_template(), \get_post() ); + + $content = \stripslashes( \trim( $content ) ); + $content = \str_ireplace( \array_keys( $replace_vars ), \array_values( $replace_vars ), $content ); + + return \wpautop( $content ); + } + + /** + * Retrieves the replacement variables. + * + * @codeCoverageIgnore It just contains too much WordPress functions. + * + * @param string $link_template The link template. + * @param mixed $post The post to use. + * + * @return array The replacement variables. + */ + protected function get_replace_vars( $link_template, $post ) { + $author_link = ''; + if ( \is_object( $post ) ) { + $author_link = \sprintf( $link_template, \esc_url( \get_author_posts_url( $post->post_author ) ), \esc_html( \get_the_author() ) ); + } + + return [ + '%%AUTHORLINK%%' => $author_link, + '%%POSTLINK%%' => \sprintf( $link_template, \esc_url( \get_permalink() ), \esc_html( \get_the_title() ) ), + '%%BLOGLINK%%' => \sprintf( $link_template, \esc_url( \get_bloginfo( 'url' ) ), \esc_html( \get_bloginfo( 'name' ) ) ), + '%%BLOGDESCLINK%%' => \sprintf( $link_template, \esc_url( \get_bloginfo( 'url' ) ), \esc_html( \get_bloginfo( 'name' ) ) . ' - ' . \esc_html( \get_bloginfo( 'description' ) ) ), + ]; + } + + /** + * Retrieves the link template. + * + * @return string The link template. + */ + protected function get_link_template() { + /** + * Filter: 'nofollow_rss_links' - Allow the developer to determine whether or not to follow the links in + * the bits Yoast SEO adds to the RSS feed, defaults to true. + * + * @api bool $unsigned Whether or not to follow the links in RSS feed, defaults to true. + * + * @since 1.4.20 + */ + if ( \apply_filters( 'nofollow_rss_links', true ) ) { + return '%2$s'; + } + + return '%2$s'; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/front-end/schema-accessibility-feature.php b/wp-content/plugins/wordpress-seo/src/integrations/front-end/schema-accessibility-feature.php new file mode 100644 index 00000000..3d921651 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/front-end/schema-accessibility-feature.php @@ -0,0 +1,80 @@ +is_needed() ) { + return $piece; + } + } + + return $this->add_accessibility_feature( $piece, $context ); + } + + /** + * Adds the accessibility feature to a schema graph piece. + * + * @param array $piece The schema piece. + * @param Meta_Tags_Context $context The context. + * + * @return array The graph piece. + */ + public function add_accessibility_feature( $piece, $context ) { + if ( empty( $context->blocks['yoast-seo/table-of-contents'] ) ) { + return $piece; + } + + if ( isset( $piece['accessibilityFeature'] ) ) { + $piece['accessibilityFeature'][] = 'tableOfContents'; + } + else { + $piece['accessibilityFeature'] = [ + 'tableOfContents', + ]; + } + return $piece; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/front-end/theme-titles.php b/wp-content/plugins/wordpress-seo/src/integrations/front-end/theme-titles.php new file mode 100644 index 00000000..cfe6427b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/front-end/theme-titles.php @@ -0,0 +1,57 @@ +context_memoizer = $context_memoizer; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + /** + * Allow control of the `wp_robots` filter by prioritizing our hook 10 less than max. + * Use the `wpseo_robots` filter to filter the Yoast robots output, instead of WordPress core. + */ + \add_filter( 'wp_robots', [ $this, 'add_robots' ], ( \PHP_INT_MAX - 10 ) ); + } + + /** + * Returns the conditionals based on which this loadable should be active. + * + * @return array The conditionals. + */ + public static function get_conditionals() { + return [ + Front_End_Conditional::class, + WP_Robots_Conditional::class, + ]; + } + + /** + * Adds our robots tag value to the WordPress robots tag output. + * + * @param array $robots The current robots data. + * + * @return array The robots data. + */ + public function add_robots( $robots ) { + if ( ! \is_array( $robots ) ) { + return $this->get_robots_value(); + } + + $merged_robots = \array_merge( $robots, $this->get_robots_value() ); + $filtered_robots = $this->enforce_robots_congruence( $merged_robots ); + $sorted_robots = $this->sort_robots( $filtered_robots ); + + // Filter all falsy-null robot values. + return \array_filter( $sorted_robots ); + } + + /** + * Retrieves the robots key-value pairs. + * + * @return array The robots key-value pairs. + */ + protected function get_robots_value() { + $context = $this->context_memoizer->for_current_page(); + + $robots_presenter = new Robots_Presenter(); + $robots_presenter->presentation = $context->presentation; + return $this->format_robots( $robots_presenter->get() ); + } + + /** + * Formats our robots fields, to match the pattern WordPress is using. + * + * Our format: `[ 'index' => 'noindex', 'max-image-preview' => 'max-image-preview:large', ... ]` + * WordPress format: `[ 'noindex' => true, 'max-image-preview' => 'large', ... ]` + * + * @param array $robots Our robots value. + * + * @return array The formatted robots. + */ + protected function format_robots( $robots ) { + foreach ( $robots as $key => $value ) { + // When the entry represents for example: max-image-preview:large. + $colon_position = \strpos( $value, ':' ); + if ( $colon_position !== false ) { + $robots[ $key ] = \substr( $value, ( $colon_position + 1 ) ); + + continue; + } + + // When index => noindex, we want a separate noindex as entry in array. + if ( \strpos( $value, 'no' ) === 0 ) { + $robots[ $key ] = false; + $robots[ $value ] = true; + + continue; + } + + // When the key is equal to the value, just make its value a boolean. + if ( $key === $value ) { + $robots[ $key ] = true; + } + } + + return $robots; + } + + /** + * Ensures all other possible robots values are congruent with nofollow and or noindex. + * + * WordPress might add some robot values again. + * When the page is set to noindex we want to filter out these values. + * + * @param array $robots The robots. + * + * @return array The filtered robots. + */ + protected function enforce_robots_congruence( $robots ) { + if ( ! empty( $robots['nofollow'] ) ) { + $robots['follow'] = null; + } + if ( ! empty( $robots['noarchive'] ) ) { + $robots['archive'] = null; + } + if ( ! empty( $robots['noimageindex'] ) ) { + $robots['imageindex'] = null; + + // `max-image-preview` should set be to `none` when `noimageindex` is present. + // Using `isset` rather than `! empty` here so that in the rare case of `max-image-preview` + // being equal to an empty string due to filtering, its value would still be set to `none`. + if ( isset( $robots['max-image-preview'] ) ) { + $robots['max-image-preview'] = 'none'; + } + } + if ( ! empty( $robots['nosnippet'] ) ) { + $robots['snippet'] = null; + } + if ( ! empty( $robots['noindex'] ) ) { + $robots['index'] = null; + $robots['imageindex'] = null; + $robots['noimageindex'] = null; + $robots['archive'] = null; + $robots['noarchive'] = null; + $robots['snippet'] = null; + $robots['nosnippet'] = null; + $robots['max-snippet'] = null; + $robots['max-image-preview'] = null; + $robots['max-video-preview'] = null; + } + + return $robots; + } + + /** + * Sorts the robots array. + * + * @param array $robots The robots array. + * + * @return array The sorted robots array. + */ + protected function sort_robots( $robots ) { + \uksort( + $robots, + static function ( $a, $b ) { + $order = [ + 'index' => 0, + 'noindex' => 1, + 'follow' => 2, + 'nofollow' => 3, + ]; + $ai = isset( $order[ $a ] ) ? $order[ $a ] : 4; + $bi = isset( $order[ $b ] ) ? $order[ $b ] : 4; + + return ( $ai - $bi ); + } + ); + + return $robots; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/integration-interface.php b/wp-content/plugins/wordpress-seo/src/integrations/integration-interface.php new file mode 100644 index 00000000..82145d4a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/integration-interface.php @@ -0,0 +1,22 @@ +get_primary_category( $post ); + if ( $primary_category !== false && $primary_category !== $category->cat_ID ) { + $category = \get_category( $primary_category ); + } + + return $category; + } + + /** + * Get the id of the primary category. + * + * @codeCoverageIgnore It justs wraps a dependency. + * + * @param WP_Post $post The post in question. + * + * @return int Primary category id. + */ + protected function get_primary_category( $post ) { + $primary_term = new WPSEO_Primary_Term( 'category', $post->ID ); + + return $primary_term->get_primary_term(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/schema-blocks.php b/wp-content/plugins/wordpress-seo/src/integrations/schema-blocks.php new file mode 100644 index 00000000..a17e040f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/schema-blocks.php @@ -0,0 +1,164 @@ +asset_manager = $asset_manager; + $this->blocks_conditional = $blocks_conditional; + $this->short_link_helper = $short_link_helper; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_action( 'enqueue_block_editor_assets', [ $this, 'load' ] ); + \add_action( 'enqueue_block_editor_assets', [ $this, 'load_translations' ] ); + \add_action( 'admin_enqueue_scripts', [ $this, 'output' ] ); + } + + /** + * Registers a schema template. + * + * @param string $template The template to be registered. + * If starting with a / is assumed to be an absolute path. + * If not starting with a / is assumed to be relative to WPSEO_PATH. + * + * @return void + */ + public function register_template( $template ) { + if ( \substr( $template, 0, 1 ) !== '/' ) { + $template = \WPSEO_PATH . '/' . $template; + } + + $this->templates[] = $template; + } + + /** + * Loads all schema block templates and the required JS library for them. + * + * @return void + */ + public function load() { + $this->asset_manager->enqueue_script( 'schema-blocks' ); + $this->asset_manager->enqueue_style( 'schema-blocks' ); + + $this->asset_manager->localize_script( + 'schema-blocks', + 'yoastSchemaBlocks', + [ + 'requiredLink' => $this->short_link_helper->build( 'https://yoa.st/required-fields' ), + 'recommendedLink' => $this->short_link_helper->build( 'https://yoa.st/recommended-fields' ), + ] + ); + } + + /** + * Outputs the set templates. + */ + public function output() { + if ( ! $this->asset_manager->is_script_enqueued( 'schema-blocks' ) ) { + return; + } + + $templates = []; + + // When the schema blocks feature flag is enabled, use the registered templates. + if ( $this->blocks_conditional->is_met() ) { + $templates = $this->templates; + } + + /** + * Filter: 'wpseo_load_schema_templates' - Allow adding additional schema templates. + * + * @param array $templates The templates to filter. + */ + $templates = \apply_filters( 'wpseo_load_schema_templates', $templates ); + if ( ! \is_array( $templates ) || empty( $templates ) ) { + return; + } + + foreach ( $templates as $template ) { + if ( ! \file_exists( $template ) ) { + continue; + } + // `.schema` and other suffixes become Schema (root) templates. + $type = ( \substr( $template, -10 ) === '.block.php' ) ? 'block' : 'schema'; + echo ''; + } + } + + /** + * Loads the translations and localizes the schema-blocks script file. + */ + public function load_translations() { + $yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_L10n(); + $yoast_components_l10n->localize_script( 'schema-blocks' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/third-party/amp.php b/wp-content/plugins/wordpress-seo/src/integrations/third-party/amp.php new file mode 100644 index 00000000..f9c7ae79 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/third-party/amp.php @@ -0,0 +1,61 @@ +front_end = $front_end; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_action( 'amp_post_template_head', [ $this, 'remove_amp_meta_output' ], 0 ); + \add_action( 'amp_post_template_head', [ $this->front_end, 'call_wpseo_head' ], 9 ); + } + + /** + * Removes amp meta output. + * + * @return void + */ + public function remove_amp_meta_output() { + \remove_action( 'amp_post_template_head', 'amp_post_template_add_title' ); + \remove_action( 'amp_post_template_head', 'amp_post_template_add_canonical' ); + \remove_action( 'amp_post_template_head', 'amp_print_schemaorg_metadata' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/third-party/bbpress.php b/wp-content/plugins/wordpress-seo/src/integrations/third-party/bbpress.php new file mode 100644 index 00000000..cc41fd03 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/third-party/bbpress.php @@ -0,0 +1,62 @@ +options = $options; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + if ( $this->options->get( 'breadcrumbs-enable' ) !== true ) { + return; + } + + /** + * If breadcrumbs are active (which they supposedly are if the users has enabled this settings, + * there's no reason to have bbPress breadcrumbs as well. + * + * {@internal The class itself is only loaded when the template tag is encountered + * via the template tag function in the wpseo-functions.php file.}} + */ + \add_filter( 'bbp_get_breadcrumb', '__return_false' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/third-party/elementor.php b/wp-content/plugins/wordpress-seo/src/integrations/third-party/elementor.php new file mode 100644 index 00000000..1c2f5755 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/third-party/elementor.php @@ -0,0 +1,717 @@ +asset_manager = $asset_manager; + $this->options = $options; + $this->capability = $capability; + + $this->seo_analysis = new WPSEO_Metabox_Analysis_SEO(); + $this->readability_analysis = new WPSEO_Metabox_Analysis_Readability(); + $this->social_is_enabled = $this->options->get( 'opengraph', false ) || $this->options->get( 'twitter', false ); + $this->is_advanced_metadata_enabled = $this->capability->current_user_can( 'wpseo_edit_advanced_metadata' ) || $this->options->get( 'disableadvanced_meta' ) === false; + $this->estimated_reading_time_conditional = $estimated_reading_time_conditional; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_action( 'wp_ajax_wpseo_elementor_save', [ $this, 'save_postdata' ] ); + + // We need to delay the post type lookup to give other plugins a chance to register custom post types. + \add_action( 'init', [ $this, 'register_elementor_hooks' ], \PHP_INT_MAX ); + } + + /** + * Registers our Elementor hooks. + */ + public function register_elementor_hooks() { + if ( ! $this->display_metabox( $this->get_metabox_post()->post_type ) ) { + return; + } + + \add_action( 'elementor/editor/before_enqueue_scripts', [ $this, 'init' ] ); + + // We are too late for elementor/init. We should see if we can be on time, or else this workaround works (we do always get the "else" though). + if ( ! \did_action( 'elementor/init' ) ) { + \add_action( 'elementor/init', [ $this, 'add_yoast_panel_tab' ] ); + } + else { + $this->add_yoast_panel_tab(); + } + \add_action( 'elementor/documents/register_controls', [ $this, 'register_document_controls' ] ); + } + + /** + * Initializes the integration. + * + * @return void + */ + public function init() { + $this->asset_manager->register_assets(); + $this->enqueue(); + $this->render_hidden_fields(); + } + + /** + * Register a panel tab slug, in order to allow adding controls to this tab. + */ + public function add_yoast_panel_tab() { + Controls_Manager::add_tab( $this::YOAST_TAB, \__( 'Yoast SEO', 'wordpress-seo' ) ); + } + + /** + * Register additional document controls. + * + * @param PageBase $document The PageBase document. + */ + public function register_document_controls( $document ) { + // PageBase is the base class for documents like `post` `page` and etc. + if ( ! $document instanceof PageBase || ! $document::get_property( 'has_elements' ) ) { + return; + } + + // This is needed to get the tab to appear, but will be overwritten in the JavaScript. + $document->start_controls_section( + 'yoast_temporary_section', + [ + 'label' => \__( 'Yoast SEO', 'wordpress-seo' ), + 'tab' => self::YOAST_TAB, + ] + ); + + $document->end_controls_section(); + } + + // Below is mostly copied from `class-metabox.php`. That constructor has side-effects we do not need. + + /** + * Determines whether the metabox should be shown for the passed identifier. + * + * By default the check is done for post types, but can also be used for taxonomies. + * + * @param string|null $identifier The identifier to check. + * @param string $type The type of object to check. Defaults to post_type. + * + * @return bool Whether or not the metabox should be displayed. + */ + public function display_metabox( $identifier = null, $type = 'post_type' ) { + return WPSEO_Utils::is_metabox_active( $identifier, $type ); + } + + /** + * Saves the WP SEO metadata for posts. + * + * Outputs JSON via wp_send_json then stops code execution. + * + * {@internal $_POST parameters are validated via sanitize_post_meta().}} + * + * @return void + */ + public function save_postdata() { + global $post; + + $post_id = \filter_input( \INPUT_POST, 'post_id', \FILTER_SANITIZE_NUMBER_INT ); + + if ( ! \current_user_can( 'manage_options' ) ) { + \wp_send_json_error( 'Unauthorized', 401 ); + } + + \check_ajax_referer( 'wpseo_elementor_save', '_wpseo_elementor_nonce' ); + + // Bail if this is a multisite installation and the site has been switched. + if ( \is_multisite() && \ms_is_switched() ) { + \wp_send_json_error( 'Switched multisite', 409 ); + } + + \clean_post_cache( $post_id ); + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- To setup the post we need to do this explicitly. + $post = \get_post( $post_id ); + + if ( ! \is_object( $post ) ) { + // Non-existent post. + \wp_send_json_error( 'Post not found', 400 ); + } + + \do_action( 'wpseo_save_compare_data', $post ); + + // Initialize meta, amongst other things it registers sanitization. + WPSEO_Meta::init(); + + $social_fields = []; + if ( $this->social_is_enabled ) { + $social_fields = WPSEO_Meta::get_meta_field_defs( 'social', $post->post_type ); + } + + // The below methods use the global post so make sure it is setup. + \setup_postdata( $post ); + $meta_boxes = \apply_filters( 'wpseo_save_metaboxes', [] ); + $meta_boxes = \array_merge( + $meta_boxes, + WPSEO_Meta::get_meta_field_defs( 'general', $post->post_type ), + WPSEO_Meta::get_meta_field_defs( 'advanced', $post->post_type ), + $social_fields, + WPSEO_Meta::get_meta_field_defs( 'schema', $post->post_type ) + ); + + foreach ( $meta_boxes as $key => $meta_box ) { + // If analysis is disabled remove that analysis score value from the DB. + if ( $this->is_meta_value_disabled( $key ) ) { + WPSEO_Meta::delete( $key, $post_id ); + continue; + } + + $data = null; + $field_name = WPSEO_Meta::$form_prefix . $key; + + if ( $meta_box['type'] === 'checkbox' ) { + $data = isset( $_POST[ $field_name ] ) ? 'on' : 'off'; + } + else { + if ( isset( $_POST[ $field_name ] ) ) { + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Reason: Sanitized through sanitize_post_meta. + $data = \wp_unslash( $_POST[ $field_name ] ); + + // For multi-select. + if ( \is_array( $data ) ) { + $data = \array_map( [ 'WPSEO_Utils', 'sanitize_text_field' ], $data ); + } + + if ( \is_string( $data ) ) { + $data = ( $key !== 'canonical' ) ? WPSEO_Utils::sanitize_text_field( $data ) : WPSEO_Utils::sanitize_url( $data ); + } + } + + // Reset options when no entry is present with multiselect - only applies to `meta-robots-adv` currently. + if ( ! isset( $_POST[ $field_name ] ) && ( $meta_box['type'] === 'multiselect' ) ) { + $data = []; + } + } + + if ( $data !== null ) { + WPSEO_Meta::set_value( $key, $data, $post_id ); + } + } + + // Saving the WP post to save the slug. + $slug = \filter_input( \INPUT_POST, WPSEO_Meta::$form_prefix . 'slug', \FILTER_SANITIZE_STRING ); + if ( $post->post_name !== $slug ) { + $post_array = $post->to_array(); + $post_array['post_name'] = $slug; + + $save_successful = \wp_insert_post( $post_array ); + if ( \is_wp_error( $save_successful ) ) { + \wp_send_json_error( 'Slug not saved', 400 ); + } + + // Update the post object to ensure we have the actual slug. + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Updating the post is needed to get the current slug. + $post = \get_post( $post_id ); + if ( ! \is_object( $post ) ) { + \wp_send_json_error( 'Updated slug not found', 400 ); + } + } + + \do_action( 'wpseo_saved_postdata' ); + + // Output the slug, because it is processed by WP and we need the actual slug again. + \wp_send_json_success( [ 'slug' => $post->post_name ] ); + } + + /** + * Determines if the given meta value key is disabled. + * + * @param string $key The key of the meta value. + * + * @return bool Whether the given meta value key is disabled. + */ + public function is_meta_value_disabled( $key ) { + if ( $key === 'linkdex' && ! $this->seo_analysis->is_enabled() ) { + return true; + } + + if ( $key === 'content_score' && ! $this->readability_analysis->is_enabled() ) { + return true; + } + + return false; + } + + /** + * Enqueues all the needed JS and CSS. + * + * @return void + */ + public function enqueue() { + $post_id = \get_queried_object_id(); + if ( empty( $post_id ) ) { + $post_id = \sanitize_text_field( \filter_input( \INPUT_GET, 'post' ) ); + } + + if ( $post_id !== 0 ) { + // Enqueue files needed for upload functionality. + \wp_enqueue_media( [ 'post' => $post_id ] ); + } + + $this->asset_manager->enqueue_style( 'admin-global' ); + $this->asset_manager->enqueue_style( 'metabox-css' ); + $this->asset_manager->enqueue_style( 'scoring' ); + $this->asset_manager->enqueue_style( 'select2' ); + $this->asset_manager->enqueue_style( 'monorepo' ); + $this->asset_manager->enqueue_style( 'admin-css' ); + $this->asset_manager->enqueue_style( 'elementor' ); + + $this->asset_manager->enqueue_script( 'elementor' ); + + $yoast_components_l10n = new WPSEO_Admin_Asset_Yoast_Components_L10n(); + $yoast_components_l10n->localize_script( 'elementor' ); + + $this->asset_manager->localize_script( 'elementor', 'wpseoAdminL10n', WPSEO_Utils::get_admin_l10n() ); + $this->asset_manager->localize_script( 'elementor', 'wpseoFeaturesL10n', WPSEO_Utils::retrieve_enabled_features() ); + + $plugins_script_data = [ + 'replaceVars' => [ + 'no_parent_text' => \__( '(no parent)', 'wordpress-seo' ), + 'replace_vars' => $this->get_replace_vars(), + 'recommended_replace_vars' => $this->get_recommended_replace_vars(), + 'scope' => $this->determine_scope(), + 'has_taxonomies' => $this->current_post_type_has_taxonomies(), + ], + 'shortcodes' => [ + 'wpseo_filter_shortcodes_nonce' => \wp_create_nonce( 'wpseo-filter-shortcodes' ), + 'wpseo_shortcode_tags' => $this->get_valid_shortcode_tags(), + ], + ]; + + $worker_script_data = [ + 'url' => YoastSEO()->helpers->asset->get_asset_url( 'yoast-seo-analysis-worker' ), + 'dependencies' => YoastSEO()->helpers->asset->get_dependency_urls_by_handle( 'yoast-seo-analysis-worker' ), + 'keywords_assessment_url' => YoastSEO()->helpers->asset->get_asset_url( 'yoast-seo-used-keywords-assessment' ), + 'log_level' => WPSEO_Utils::get_analysis_worker_log_level(), + // We need to make the feature flags separately available inside of the analysis web worker. + 'enabled_features' => WPSEO_Utils::retrieve_enabled_features(), + ]; + + $alert_dismissal_action = \YoastSEO()->classes->get( Alert_Dismissal_Action::class ); + $dismissed_alerts = $alert_dismissal_action->all_dismissed(); + + $script_data = [ + 'media' => [ 'choose_image' => \__( 'Use Image', 'wordpress-seo' ) ], + 'metabox' => $this->get_metabox_script_data(), + 'userLanguageCode' => WPSEO_Language_Utils::get_language( \get_user_locale() ), + 'isPost' => true, + 'isBlockEditor' => WP_Screen::get()->is_block_editor(), + 'isElementorEditor' => true, + 'analysis' => [ + 'plugins' => $plugins_script_data, + 'worker' => $worker_script_data, + 'estimatedReadingTimeEnabled' => $this->estimated_reading_time_conditional->is_met(), + ], + 'dismissedAlerts' => $dismissed_alerts, + ]; + + if ( \post_type_supports( $this->get_metabox_post()->post_type, 'thumbnail' ) ) { + $this->asset_manager->enqueue_style( 'featured-image' ); + + $script_data['featuredImage'] = [ + 'featured_image_notice' => \__( 'SEO issue: The featured image should be at least 200 by 200 pixels to be picked up by Facebook and other social media sites.', 'wordpress-seo' ), + ]; + } + + $this->asset_manager->localize_script( 'elementor', 'wpseoScriptData', $script_data ); + $this->asset_manager->enqueue_user_language_script(); + } + + /** + * Renders the metabox hidden fields. + * + * @return void + */ + protected function render_hidden_fields() { + // Wrap in a form with an action and post_id for the submit. + \printf( + '
    ', + \esc_url( \admin_url( 'admin-ajax.php' ) ), + \esc_attr( $this->get_metabox_post()->ID ) + ); + + \wp_nonce_field( 'wpseo_elementor_save', '_wpseo_elementor_nonce' ); + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Meta_Fields_Presenter->present is considered safe. + echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'general' ); + + if ( $this->is_advanced_metadata_enabled ) { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Meta_Fields_Presenter->present is considered safe. + echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'advanced' ); + } + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Meta_Fields_Presenter->present is considered safe. + echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'schema', $this->get_metabox_post()->post_type ); + + if ( $this->social_is_enabled ) { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Reason: Meta_Fields_Presenter->present is considered safe. + echo new Meta_Fields_Presenter( $this->get_metabox_post(), 'social' ); + } + + \printf( + '', + \esc_attr( WPSEO_Meta::$form_prefix . 'slug' ), + \esc_attr( $this->get_metabox_post()->post_name ) + ); + + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Output should be escaped in the filter. + echo \apply_filters( 'wpseo_elementor_hidden_fields', '' ); + + echo '
    '; + } + + /** + * Returns post in metabox context. + * + * @return WP_Post|null + */ + protected function get_metabox_post() { + if ( $this->post !== null ) { + return $this->post; + } + + $post = \filter_input( \INPUT_GET, 'post' ); + if ( ! empty( $post ) ) { + $post_id = (int) WPSEO_Utils::validate_int( $post ); + + $this->post = \get_post( $post_id ); + + return $this->post; + } + + if ( isset( $GLOBALS['post'] ) ) { + $this->post = $GLOBALS['post']; + + return $this->post; + } + + return null; + } + + /** + * Passes variables to js for use with the post-scraper. + * + * @return array + */ + protected function get_metabox_script_data() { + $permalink = ''; + + if ( \is_object( $this->get_metabox_post() ) ) { + $permalink = \get_sample_permalink( $this->get_metabox_post()->ID ); + $permalink = $permalink[0]; + } + + $post_formatter = new WPSEO_Metabox_Formatter( + new WPSEO_Post_Metabox_Formatter( $this->get_metabox_post(), [], $permalink ) + ); + + $values = $post_formatter->get_values(); + + /** This filter is documented in admin/filters/class-cornerstone-filter.php. */ + $post_types = \apply_filters( 'wpseo_cornerstone_post_types', \YoastSEO()->helpers->post_type->get_accessible_post_types() ); + if ( $values['cornerstoneActive'] && ! \in_array( $this->get_metabox_post()->post_type, $post_types, true ) ) { + $values['cornerstoneActive'] = false; + } + + return $values; + } + + /** + * Prepares the replace vars for localization. + * + * @return array Replace vars. + */ + protected function get_replace_vars() { + $cached_replacement_vars = []; + + $vars_to_cache = [ + 'date', + 'id', + 'sitename', + 'sitedesc', + 'sep', + 'page', + 'currentyear', + 'tag', + 'category', + 'primary_category', + 'pt_single', + 'pt_plural', + 'modified', + 'name', + 'user_description', + 'pagetotal', + 'pagenumber', + ]; + + foreach ( $vars_to_cache as $var ) { + $cached_replacement_vars[ $var ] = \wpseo_replace_vars( '%%' . $var . '%%', $this->get_metabox_post() ); + } + + // Merge custom replace variables with the WordPress ones. + return \array_merge( $cached_replacement_vars, $this->get_custom_replace_vars( $this->get_metabox_post() ) ); + } + + /** + * Prepares the recommended replace vars for localization. + * + * @return array Recommended replacement variables. + */ + protected function get_recommended_replace_vars() { + $recommended_replace_vars = new WPSEO_Admin_Recommended_Replace_Vars(); + + // What is recommended depends on the current context. + $post_type = $recommended_replace_vars->determine_for_post( $this->get_metabox_post() ); + + return $recommended_replace_vars->get_recommended_replacevars_for( $post_type ); + } + + /** + * Gets the custom replace variables for custom taxonomies and fields. + * + * @param WP_Post $post The post to check for custom taxonomies and fields. + * + * @return array Array containing all the replacement variables. + */ + protected function get_custom_replace_vars( $post ) { + return [ + 'custom_fields' => $this->get_custom_fields_replace_vars( $post ), + 'custom_taxonomies' => $this->get_custom_taxonomies_replace_vars( $post ), + ]; + } + + /** + * Gets the custom replace variables for custom taxonomies. + * + * @param WP_Post $post The post to check for custom taxonomies. + * + * @return array Array containing all the replacement variables. + */ + protected function get_custom_taxonomies_replace_vars( $post ) { + $taxonomies = \get_object_taxonomies( $post, 'objects' ); + $custom_replace_vars = []; + + foreach ( $taxonomies as $taxonomy_name => $taxonomy ) { + + if ( \is_string( $taxonomy ) ) { // If attachment, see https://core.trac.wordpress.org/ticket/37368 . + $taxonomy_name = $taxonomy; + $taxonomy = \get_taxonomy( $taxonomy_name ); + } + + if ( $taxonomy->_builtin && $taxonomy->public ) { + continue; + } + + $custom_replace_vars[ $taxonomy_name ] = [ + 'name' => $taxonomy->name, + 'description' => $taxonomy->description, + ]; + } + + return $custom_replace_vars; + } + + /** + * Gets the custom replace variables for custom fields. + * + * @param WP_Post $post The post to check for custom fields. + * + * @return array Array containing all the replacement variables. + */ + protected function get_custom_fields_replace_vars( $post ) { + $custom_replace_vars = []; + + // If no post object is passed, return the empty custom_replace_vars array. + if ( ! \is_object( $post ) ) { + return $custom_replace_vars; + } + + $custom_fields = \get_post_custom( $post->ID ); + + foreach ( $custom_fields as $custom_field_name => $custom_field ) { + // Skip private custom fields. + if ( \substr( $custom_field_name, 0, 1 ) === '_' ) { + continue; + } + + // Skip custom field values that are serialized. + if ( \is_serialized( $custom_field[0] ) ) { + continue; + } + + $custom_replace_vars[ $custom_field_name ] = $custom_field[0]; + } + + return $custom_replace_vars; + } + + /** + * Determines the scope based on the post type. + * This can be used by the replacevar plugin to determine if a replacement needs to be executed. + * + * @return string String describing the current scope. + */ + protected function determine_scope() { + if ( $this->get_metabox_post()->post_type === 'page' ) { + return 'page'; + } + + return 'post'; + } + + /** + * Determines whether or not the current post type has registered taxonomies. + * + * @return bool Whether the current post type has taxonomies. + */ + protected function current_post_type_has_taxonomies() { + $post_taxonomies = \get_object_taxonomies( $this->get_metabox_post()->post_type ); + + return ! empty( $post_taxonomies ); + } + + /** + * Returns an array with shortcode tags for all registered shortcodes. + * + * @return array + */ + protected function get_valid_shortcode_tags() { + $shortcode_tags = []; + + foreach ( $GLOBALS['shortcode_tags'] as $tag => $description ) { + $shortcode_tags[] = $tag; + } + + return $shortcode_tags; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/third-party/exclude-elementor-post-types.php b/wp-content/plugins/wordpress-seo/src/integrations/third-party/exclude-elementor-post-types.php new file mode 100644 index 00000000..617d29c2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/third-party/exclude-elementor-post-types.php @@ -0,0 +1,36 @@ +front_end = $front_end; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_action( 'web_stories_enable_metadata', '__return_false' ); + \add_action( 'web_stories_enable_schemaorg_metadata', '__return_false' ); + \add_action( 'web_stories_enable_open_graph_metadata', '__return_false' ); + \add_action( 'web_stories_enable_twitter_metadata', '__return_false' ); + \remove_action( 'web_stories_story_head', 'rel_canonical' ); + \add_action( 'web_stories_story_head', [ $this->front_end, 'call_wpseo_head' ], 9 ); + \add_filter( 'wpseo_schema_article_post_types', [ $this, 'filter_schema_article_post_types' ] ); + \add_filter( 'wpseo_schema_article_type', [ $this, 'filter_schema_article_type' ], 10, 2 ); + \add_filter( 'wpseo_metadesc', [ $this, 'filter_meta_description' ], 10, 2 ); + } + + /** + * Adds web story post type to list of which post types to output Article schema for. + * + * @param string[] $post_types Array of post types. + * @return string[] Array of post types. + */ + public function filter_schema_article_post_types( $post_types ) { + $post_types[] = Google_Web_Stories\Story_Post_Type::POST_TYPE_SLUG; + return $post_types; + } + + /** + * Filters the meta description for stories. + * + * @param string $description The description sentence. + * @param Indexable_Presentation $presentation The presentation of an indexable. + * @return string The description sentence. + */ + public function filter_meta_description( $description, $presentation ) { + if ( $description || $presentation->model->object_sub_type !== Google_Web_Stories\Story_Post_Type::POST_TYPE_SLUG ) { + return $description; + } + + return \get_the_excerpt( $presentation->model->object_id ); + } + + /** + * Filters Article type for Web Stories. + * + * @param string|string[] $type The Article type. + * @param Indexable $indexable The indexable. + * @return string|string[] Article type. + */ + public function filter_schema_article_type( $type, $indexable ) { + if ( $indexable->object_sub_type !== Google_Web_Stories\Story_Post_Type::POST_TYPE_SLUG ) { + return $type; + } + + if ( \is_string( $type ) && $type === 'None' ) { + return 'Article'; + } + + return $type; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/third-party/woocommerce-permalinks.php b/wp-content/plugins/wordpress-seo/src/integrations/third-party/woocommerce-permalinks.php new file mode 100644 index 00000000..8f6e0455 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/third-party/woocommerce-permalinks.php @@ -0,0 +1,108 @@ +indexable_helper = $indexable_helper; + } + + /** + * Registers the hooks. + * + * @codeCoverageIgnore + */ + public function register_hooks() { + \add_filter( 'wpseo_post_types_reset_permalinks', [ $this, 'filter_product_from_post_types' ] ); + \add_action( 'update_option_woocommerce_permalinks', [ $this, 'reset_woocommerce_permalinks' ], 10, 2 ); + } + + /** + * Filters the product post type from the post type. + * + * @param array $post_types The post types to filter. + * + * @return array The filtered post types. + */ + public function filter_product_from_post_types( $post_types ) { + unset( $post_types['product'] ); + + return $post_types; + } + + /** + * Resets the indexables for WooCommerce based on the changed permalink fields. + * + * @param array $old The old value. + * @param array $new The new value. + */ + public function reset_woocommerce_permalinks( $old, $new ) { + $changed_options = \array_diff( $old, $new ); + + if ( \array_key_exists( 'product_base', $changed_options ) ) { + $this->indexable_helper->reset_permalink_indexables( 'post', 'product' ); + } + + if ( \array_key_exists( 'attribute_base', $changed_options ) ) { + $attribute_taxonomies = $this->get_attribute_taxonomies(); + + foreach ( $attribute_taxonomies as $attribute_name ) { + $this->indexable_helper->reset_permalink_indexables( 'term', $attribute_name ); + } + } + + if ( \array_key_exists( 'category_base', $changed_options ) ) { + $this->indexable_helper->reset_permalink_indexables( 'term', 'product_cat' ); + } + + if ( \array_key_exists( 'tag_base', $changed_options ) ) { + $this->indexable_helper->reset_permalink_indexables( 'term', 'product_tag' ); + } + } + + /** + * Retrieves the taxonomies based on the attributes. + * + * @return array The taxonomies. + */ + protected function get_attribute_taxonomies() { + $taxonomies = []; + foreach ( \wc_get_attribute_taxonomies() as $attribute_taxonomy ) { + $taxonomies[] = \wc_attribute_taxonomy_name( $attribute_taxonomy->attribute_name ); + } + + $taxonomies = \array_filter( $taxonomies ); + + return $taxonomies; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/third-party/woocommerce.php b/wp-content/plugins/wordpress-seo/src/integrations/third-party/woocommerce.php new file mode 100644 index 00000000..8efbe1be --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/third-party/woocommerce.php @@ -0,0 +1,366 @@ +options = $options; + $this->replace_vars = $replace_vars; + $this->context_memoizer = $context_memoizer; + $this->repository = $repository; + $this->pagination_helper = $pagination_helper; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_filter( 'wpseo_frontend_page_type_simple_page_id', [ $this, 'get_page_id' ] ); + \add_filter( 'wpseo_breadcrumb_indexables', [ $this, 'add_shop_to_breadcrumbs' ] ); + + \add_filter( 'wpseo_title', [ $this, 'title' ], 10, 2 ); + \add_filter( 'wpseo_metadesc', [ $this, 'description' ], 10, 2 ); + \add_filter( 'wpseo_canonical', [ $this, 'canonical' ], 10, 2 ); + \add_filter( 'wpseo_adjacent_rel_url', [ $this, 'adjacent_rel_url' ], 10, 3 ); + } + + /** + * Returns the correct canonical when WooCommerce is enabled. + * + * @param string $canonical The current canonical. + * @param Indexable_Presentation|null $presentation The indexable presentation. + * + * @return string The correct canonical. + */ + public function canonical( $canonical, $presentation = null ) { + if ( ! $this->is_shop_page() ) { + return $canonical; + } + + $url = $this->get_shop_paginated_link( 'curr', $presentation ); + + if ( $url ) { + return $url; + } + + return $canonical; + } + + /** + * Returns correct adjacent pages when WooCommerce is enabled. + * + * @param string $link The current link. + * @param string $rel Link relationship, prev or next. + * @param Indexable_Presentation|null $presentation The indexable presentation. + * + * @return string The correct link. + */ + public function adjacent_rel_url( $link, $rel, $presentation = null ) { + if ( ! $this->is_shop_page() ) { + return $link; + } + + if ( $rel !== 'next' && $rel !== 'prev' ) { + return $link; + } + + $url = $this->get_shop_paginated_link( $rel, $presentation ); + + if ( $url ) { + return $url; + } + + return $link; + } + + /** + * Adds a breadcrumb for the shop page. + * + * @param Indexable[] $indexables The array with indexables. + * + * @return Indexable[] The indexables to be shown in the breadcrumbs, with the shop page added. + */ + public function add_shop_to_breadcrumbs( $indexables ) { + $shop_page_id = $this->get_shop_page_id(); + + if ( $shop_page_id < 1 ) { + return $indexables; + } + + foreach ( $indexables as $index => $indexable ) { + if ( $indexable->object_type === 'post-type-archive' && $indexable->object_sub_type === 'product' ) { + $indexables[ $index ] = $this->repository->find_by_id_and_type( $shop_page_id, 'post' ); + } + } + + return $indexables; + } + + /** + * Returns the ID of the WooCommerce shop page when the currently opened page is the shop page. + * + * @param int $page_id The page id. + * + * @return int The Page ID of the shop. + */ + public function get_page_id( $page_id ) { + if ( ! $this->is_shop_page() ) { + return $page_id; + } + + return $this->get_shop_page_id(); + } + + /** + * Handles the title. + * + * @param string $title The title. + * @param Indexable_Presentation|null $presentation The indexable presentation. + * + * @return string The title to use. + */ + public function title( $title, $presentation = null ) { + $presentation = $this->ensure_presentation( $presentation ); + + if ( $presentation->model->title ) { + return $title; + } + + if ( ! $this->is_shop_page() ) { + return $title; + } + + if ( ! \is_archive() ) { + return $title; + } + + $shop_page_id = $this->get_shop_page_id(); + if ( $shop_page_id < 1 ) { + return $title; + } + + $product_template_title = $this->get_product_template( 'title-product', $shop_page_id ); + if ( $product_template_title ) { + return $product_template_title; + } + + return $title; + } + + /** + * Handles the meta description. + * + * @param string $description The title. + * @param Indexable_Presentation|null $presentation The indexable presentation. + * + * @return string The description to use. + */ + public function description( $description, $presentation = null ) { + $presentation = $this->ensure_presentation( $presentation ); + + if ( $presentation->model->description ) { + return $description; + } + + if ( ! $this->is_shop_page() ) { + return $description; + } + + if ( ! \is_archive() ) { + return $description; + } + + $shop_page_id = $this->get_shop_page_id(); + if ( $shop_page_id < 1 ) { + return $description; + } + + $product_template_description = $this->get_product_template( 'metadesc-product', $shop_page_id ); + if ( $product_template_description ) { + return $product_template_description; + } + + return $description; + } + + /** + * Checks if the current page is a WooCommerce shop page. + * + * @return bool True when the page is a shop page. + */ + protected function is_shop_page() { + if ( ! \is_shop() ) { + return false; + } + + if ( \is_search() ) { + return false; + } + + return true; + } + + /** + * Uses template for the given option name and replace the replacement variables on it. + * + * @param string $option_name The option name to get the template for. + * @param string $shop_page_id The page id to retrieve template for. + * + * @return string The rendered value. + */ + protected function get_product_template( $option_name, $shop_page_id ) { + $template = $this->options->get( $option_name ); + $page = \get_post( $shop_page_id ); + + return $this->replace_vars->replace( $template, $page ); + } + + /** + * Returns the id of the set WooCommerce shop page. + * + * @return int The ID of the set page. + */ + protected function get_shop_page_id() { + if ( ! \function_exists( 'wc_get_page_id' ) ) { + return -1; + } + + return \wc_get_page_id( 'shop' ); + } + + /** + * Get paginated link for shop page. + * + * @param string $rel Link relationship, prev or next or curr. + * @param Indexable_Presentation|null $presentation The indexable presentation. + * + * @return string|null The link. + */ + protected function get_shop_paginated_link( $rel, $presentation = null ) { + $presentation = $this->ensure_presentation( $presentation ); + + $permalink = $presentation->get_permalink(); + if ( ! $permalink ) { + return null; + } + + $current_page = \max( 1, $this->pagination_helper->get_current_archive_page_number() ); + + if ( $rel === 'curr' && $current_page === 1 ) { + return $permalink; + } + + if ( $rel === 'curr' && $current_page > 1 ) { + return $this->pagination_helper->get_paginated_url( $permalink, $current_page ); + } + + if ( $rel === 'prev' && $current_page === 2 ) { + return $permalink; + } + + if ( $rel === 'prev' && $current_page > 2 ) { + return $this->pagination_helper->get_paginated_url( $permalink, ( $current_page - 1 ) ); + } + + if ( $rel === 'next' && $current_page < $this->pagination_helper->get_number_of_archive_pages() ) { + return $this->pagination_helper->get_paginated_url( $permalink, ( $current_page + 1 ) ); + } + + return null; + } + + /** + * Ensures a presentation is available. + * + * @param Indexable_Presentation $presentation The indexable presentation. + * + * @return Indexable_Presentation The presentation, taken from the current page if the input was invalid. + */ + protected function ensure_presentation( $presentation ) { + if ( \is_a( $presentation, Indexable_Presentation::class ) ) { + return $presentation; + } + + $context = $this->context_memoizer->for_current_page(); + + return $context->presentation; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/third-party/wpml-wpseo-notification.php b/wp-content/plugins/wordpress-seo/src/integrations/third-party/wpml-wpseo-notification.php new file mode 100644 index 00000000..59441f73 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/third-party/wpml-wpseo-notification.php @@ -0,0 +1,120 @@ +short_link_helper = $short_link_helper; + $this->notification_center = $notification_center; + $this->wpml_wpseo_conditional = $wpml_wpseo_conditional; + } + + /** + * Initializes the integration. + * + * @return void + */ + public function register_hooks() { + \add_action( 'admin_notices', [ $this, 'notify_not_installed' ] ); + } + + /** + * Returns the conditionals based in which this loadable should be active. + * + * This integration should only be active when WPML is installed and activated. + * + * @return array The conditionals. + */ + public static function get_conditionals() { + return [ WPML_Conditional::class ]; + } + + /** + * Notify the user that the Yoast SEO Multilingual plugin is not installed + * (when the WPML plugin is installed). + * + * Remove the notification again when it is installed. + * + * @return void + */ + public function notify_not_installed() { + if ( ! $this->wpml_wpseo_conditional->is_met() ) { + $this->notification_center->add_notification( $this->get_notification() ); + return; + } + $this->notification_center->remove_notification_by_id( self::NOTIFICATION_ID ); + } + + /** + * Generates the notification to show to the user when WPML is installed, + * but the Yoast SEO Multilingual plugin is not. + * + * @return Yoast_Notification The notification. + */ + protected function get_notification() { + return new Yoast_Notification( + \sprintf( + /* translators: %1$s expands to an opening anchor tag, %2$s expands to an closing anchor tag. */ + \__( 'We notice that you have installed WPML. To make sure your canonical URLs are set correctly, %1$sinstall and activate the Yoast SEO Multilingual add-on%2$s as well!', 'wordpress-seo' ), + '', + '' + ), + [ + 'id' => self::NOTIFICATION_ID, + 'type' => Yoast_Notification::WARNING, + ] + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/third-party/wpml.php b/wp-content/plugins/wordpress-seo/src/integrations/third-party/wpml.php new file mode 100644 index 00000000..e70a919c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/third-party/wpml.php @@ -0,0 +1,66 @@ +are_auto_updates_enabled( self::WPSEO_FREE_PLUGIN_ID, $auto_updated_plugins ) ) { + return \sprintf( + '%s', + \sprintf( + /* Translators: %1$s resolves to Yoast SEO. */ + \esc_html__( 'Auto-updates are enabled based on this setting for %1$s.', 'wordpress-seo' ), + 'Yoast SEO' + ) + ); + } + + return \sprintf( + '%s', + \sprintf( + /* Translators: %1$s resolves to Yoast SEO. */ + \esc_html__( 'Auto-updates are disabled based on this setting for %1$s.', 'wordpress-seo' ), + 'Yoast SEO' + ) + ); + } + + /** + * Handles the situation where the auto_update_plugins option did not previously exist. + * + * @param string $option The name of the option that is being created. + * @param array|mixed $value The new (and first) value of the option that is being created. + */ + public function call_toggle_auto_updates_with_empty_array( $option, $value ) { + if ( $option !== 'auto_update_plugins' ) { + return; + } + + $this->toggle_auto_updates_for_add_ons( $option, $value, [] ); + } + + /** + * Enables premium auto updates when free are enabled and the other way around. + * + * @param string $option The name of the option that has been updated. + * @param array $new_value The new value of the `auto_update_plugins` option. + * @param array $old_value The old value of the `auto_update_plugins` option. + * + * @return void + */ + public function toggle_auto_updates_for_add_ons( $option, $new_value, $old_value ) { + if ( $option !== 'auto_update_plugins' ) { + // If future versions of WordPress change this filter's behavior, our behavior should stay consistent. + return; + } + + if ( ! \is_array( $old_value ) || ! \is_array( $new_value ) ) { + return; + } + + $auto_updates_are_enabled = $this->are_auto_updates_enabled( self::WPSEO_FREE_PLUGIN_ID, $new_value ); + $auto_updates_were_enabled = $this->are_auto_updates_enabled( self::WPSEO_FREE_PLUGIN_ID, $old_value ); + + if ( $auto_updates_are_enabled === $auto_updates_were_enabled ) { + // Auto-updates for Yoast SEO have stayed the same, so have neither been enabled or disabled. + return; + } + + $auto_updates_have_been_enabled = $auto_updates_are_enabled && ! $auto_updates_were_enabled; + + if ( $auto_updates_have_been_enabled ) { + $this->enable_auto_updates_for_addons( $new_value ); + } + else { + $this->disable_auto_updates_for_addons( $new_value ); + } + } + + /** + * Enables auto-updates for all addons. + * + * @param string[] $auto_updated_plugins The current list of auto-updated plugins. + */ + protected function enable_auto_updates_for_addons( $auto_updated_plugins ) { + $plugins = \array_merge( $auto_updated_plugins, self::ADD_ON_PLUGIN_FILES ); + \update_site_option( 'auto_update_plugins', $plugins ); + } + + /** + * Disables auto-updates for all addons. + * + * @param string[] $auto_updated_plugins The current list of auto-updated plugins. + */ + protected function disable_auto_updates_for_addons( $auto_updated_plugins ) { + $plugins = \array_values( \array_diff( $auto_updated_plugins, self::ADD_ON_PLUGIN_FILES ) ); + \update_site_option( 'auto_update_plugins', $plugins ); + } + + /** + * Checks whether auto updates for a plugin are enabled. + * + * @param string $plugin_id The plugin ID. + * @param array $auto_updated_plugins The array of auto updated plugins. + * + * @return bool Whether auto updates for a plugin are enabled. + */ + protected function are_auto_updates_enabled( $plugin_id, $auto_updated_plugins ) { + if ( $auto_updated_plugins === false || ! \is_array( $auto_updated_plugins ) ) { + return false; + } + + return \in_array( $plugin_id, $auto_updated_plugins, true ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/auto-update-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/auto-update-watcher.php new file mode 100644 index 00000000..ddb97abd --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/auto-update-watcher.php @@ -0,0 +1,204 @@ +notification_center = $notification_center; + $this->notification_helper = $notification_helper; + } + + /** + * Initializes the integration. + * + * On admin_init, it is checked whether the notification to auto-update Yoast SEO needs to be shown or removed. + * This is also done when major WP core updates are being enabled or disabled, + * and when automatic updates for Yoast SEO are being enabled or disabled. + * + * @return void + */ + public function register_hooks() { + \add_action( 'admin_init', [ $this, 'auto_update_notification_not_if_dismissed' ] ); + \add_action( 'update_site_option_auto_update_core_major', [ $this, 'auto_update_notification_even_if_dismissed' ] ); + \add_action( 'update_site_option_auto_update_plugins', [ $this, 'auto_update_notification_not_if_dismissed' ] ); + } + + /** + * Handles the Yoast SEO auto-update notification when the user toggles the auto-update setting for WordPress Core. + * + * If it should be shown, this will be done even if the notification has been dismissed in the past. + * + * @return void + */ + public function auto_update_notification_even_if_dismissed() { + if ( ! $this->should_show_notification() ) { + $this->save_dismissal_status(); + $this->maybe_remove_notification(); + + return; + } + + $this->maybe_create_notification(); + } + + /** + * Handles the Yoast SEO auto-update notification on all admin pages, + * as well as when the user toggles the Yoast SEO auto-update setting. + * + * If it should be shown, this will only be done if the notification has not been dismissed in the past. + * + * @return void + */ + public function auto_update_notification_not_if_dismissed() { + if ( ! $this->should_show_notification() ) { + $this->save_dismissal_status(); + $this->maybe_remove_notification(); + + return; + } + + $this->maybe_create_notification_if_not_dismissed(); + } + + /** + * Checks whether the Yoast SEO auto-update notification should be shown. + * + * @return bool Whether the notification should be shown. + */ + protected function should_show_notification() { + $core_updates_enabled = \get_site_option( 'auto_update_core_major' ) === 'enabled'; + $yoast_updates_enabled = $this->yoast_auto_updates_enabled(); + + return $core_updates_enabled && ! $yoast_updates_enabled; + } + + /** + * Saves the dismissal status of the notification in an option in wp_usermeta, if the notification gets dismissed. + * + * @return void + */ + protected function save_dismissal_status() { + // This option exists if the notification has been dismissed at some point. + $notification_dismissed = \get_user_option( 'wp_' . self::NOTIFICATION_ID ); + + // We wish to have its value in a different option, so we can still access it even when the notification gets removed. + if ( $notification_dismissed && ! \get_user_option( 'wp_' . self::NOTIFICATION_ID . '_dismissed' ) ) { + \update_user_option( \get_current_user_id(), self::NOTIFICATION_ID . '_dismissed', true ); + } + } + + /** + * Removes the notification from the notification center, if it exists. + * + * @return void + */ + protected function maybe_remove_notification() { + $this->notification_center->remove_notification_by_id( self::NOTIFICATION_ID ); + } + + /** + * Creates the notification if it doesn't exist already. + * + * @return void + */ + protected function maybe_create_notification() { + if ( ! $this->notification_center->get_notification_by_id( self::NOTIFICATION_ID ) ) { + $notification = $this->notification(); + $this->notification_helper->restore_notification( $notification ); + $this->notification_center->add_notification( $notification ); + } + } + + /** + * Creates the notification when Yoast SEO auto-updates are enabled, if it hasn't been dismissed in the past. + * + * @return void + */ + protected function maybe_create_notification_if_not_dismissed() { + $notification_dismissed = \get_user_option( 'wp_' . self::NOTIFICATION_ID . '_dismissed' ) === '1'; + $yoast_updates_enabled = $this->yoast_auto_updates_enabled(); + + if ( $notification_dismissed && ! $yoast_updates_enabled ) { + return; + } + + $this->maybe_create_notification(); + } + + /** + * Checks whether auto-updates are enabled for Yoast SEO. + * + * @return bool True if they are enabled, false if not. + */ + protected function yoast_auto_updates_enabled() { + $plugins_to_auto_update = \get_site_option( 'auto_update_plugins' ); + + // If no plugins are set to be automatically updated, it means that Yoast SEO isn't either. + if ( ! $plugins_to_auto_update ) { + return false; + } + + // Check if the Yoast SEO plugin file is in the array of plugins for which auto-updates are enabled. + return \in_array( 'wordpress-seo/wp-seo.php', $plugins_to_auto_update, true ); + } + + /** + * Returns an instance of the notification. + * + * @return Yoast_Notification The notification to show. + */ + protected function notification() { + $presenter = new Auto_Update_Notification_Presenter(); + + return new Yoast_Notification( + $presenter->present(), + [ + 'type' => Yoast_Notification::WARNING, + 'id' => self::NOTIFICATION_ID, + 'capabilities' => 'wpseo_manage_options', + 'priority' => 0.8, + ] + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-ancestor-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-ancestor-watcher.php new file mode 100644 index 00000000..52f21d6f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-ancestor-watcher.php @@ -0,0 +1,245 @@ +indexable_repository = $indexable_repository; + $this->indexable_hierarchy_builder = $indexable_hierarchy_builder; + $this->wpdb = $wpdb; + $this->indexable_hierarchy_repository = $indexable_hierarchy_repository; + $this->permalink_helper = $permalink_helper; + $this->post_type_helper = $post_type_helper; + } + + /** + * Registers the appropriate hooks. + */ + public function register_hooks() { + \add_action( 'wpseo_save_indexable', [ $this, 'reset_children' ], \PHP_INT_MAX, 2 ); + } + + /** + * Returns the conditionals based on which this loadable should be active. + * + * @return array + */ + public static function get_conditionals() { + return [ Migrations_Conditional::class ]; + } + + /** + * If an indexable's permalink has changed, updates its children in the hierarchy table and resets the children's permalink. + * + * @param Indexable $indexable The indexable. + * @param Indexable $indexable_before The old indexable. + * + * @return bool True if the children were reset. + */ + public function reset_children( $indexable, $indexable_before ) { + if ( ! \in_array( $indexable->object_type, [ 'post', 'term' ], true ) ) { + return false; + } + + if ( $indexable->permalink === $indexable_before->permalink ) { + return false; + } + + $child_indexable_ids = $this->indexable_hierarchy_repository->find_children( $indexable ); + $child_indexables = $this->indexable_repository->find_by_ids( $child_indexable_ids ); + + \array_walk( $child_indexables, [ $this, 'update_hierarchy_and_permalink' ] ); + + if ( $indexable->object_type === 'term' ) { + $child_indexables_for_term = $this->get_children_for_term( $indexable->object_id, $child_indexables ); + + \array_walk( $child_indexables_for_term, [ $this, 'update_hierarchy_and_permalink' ] ); + } + + return true; + } + + /** + * Finds all child indexables for the given term. + * + * @param int $term_id Term to fetch the indexable for. + * @param Indexable[] $child_indexables The already known child indexables. + * + * @return array The list of additional child indexables for a given term. + */ + public function get_children_for_term( $term_id, array $child_indexables ) { + // Finds object_ids (posts) for the term. + $post_object_ids = $this->get_object_ids_for_term( $term_id, $child_indexables ); + + // Removes the objects that are already present in the children. + $existing_post_indexables = \array_filter( + $child_indexables, + static function( $indexable ) { + return $indexable->object_type === 'post'; + } + ); + + $existing_post_object_ids = \wp_list_pluck( $existing_post_indexables, 'object_id' ); + $post_object_ids = \array_diff( $post_object_ids, $existing_post_object_ids ); + + // Finds the indexables for the fetched post_object_ids. + $post_indexables = $this->indexable_repository->find_by_multiple_ids_and_type( $post_object_ids, 'post', false ); + + // Finds the indexables for the posts that are attached to the term. + $post_indexable_ids = \wp_list_pluck( $post_indexables, 'id' ); + $additional_indexable_ids = $this->indexable_hierarchy_repository->find_children_by_ancestor_ids( $post_indexable_ids ); + + // Makes sure we only have indexable id's that we haven't fetched before. + $additional_indexable_ids = \array_diff( $additional_indexable_ids, $post_indexable_ids ); + + // Finds the additional indexables. + $additional_indexables = $this->indexable_repository->find_by_ids( $additional_indexable_ids ); + + // Merges all fetched indexables. + return \array_merge( $post_indexables, $additional_indexables ); + } + + /** + * Builds the hierarchy for a post. + * + * @deprecated 16.4 + * + * @codeCoverageIgnore + * + * @param int $object_id The post id. + * @param int $post_type The post type. + */ + public function build_post_hierarchy( $object_id, $post_type ) { + _deprecated_function( __METHOD__, '16.4', 'Primary_Category_Quick_Edit_Watcher::build_post_hierarchy' ); + } + + /** + * Updates the indexable hierarchy and indexable permalink. + * + * @param Indexable $indexable The indexable to update the hierarchy and permalink for. + */ + protected function update_hierarchy_and_permalink( $indexable ) { + $this->indexable_hierarchy_builder->build( $indexable ); + + $indexable->permalink = $this->permalink_helper->get_permalink_for_indexable( $indexable ); + $indexable->save(); + } + + /** + * Retrieves the object id's for a term based on the term-post relationship. + * + * @param int $term_id The term to get the object id's for. + * @param Indexable[] $child_indexables The child indexables. + * + * @return array List with object ids for the term. + */ + protected function get_object_ids_for_term( $term_id, $child_indexables ) { + $filter_terms = static function( $child ) { + return $child->object_type === 'term'; + }; + + $child_terms = \array_filter( $child_indexables, $filter_terms ); + $child_object_ids = \wp_list_pluck( $child_terms, 'object_id' ); + + // Get the term-taxonomy id's for the term and its children. + $term_taxonomy_ids = $this->wpdb->get_col( + $this->wpdb->prepare( + 'SELECT term_taxonomy_id + FROM ' . $this->wpdb->term_taxonomy . ' + WHERE term_id IN( ' . \implode( ', ', \array_fill( 0, ( \count( $child_object_ids ) + 1 ), '%s' ) ) . ' )', + $term_id, + ...$child_object_ids + ) + ); + + // In the case of faulty data having been saved the above query can return 0 results. + if ( empty( $term_taxonomy_ids ) ) { + return []; + } + + // Get the (post) object id's that are attached to the term. + return $this->wpdb->get_col( + $this->wpdb->prepare( + 'SELECT DISTINCT object_id + FROM ' . $this->wpdb->term_relationships . ' + WHERE term_taxonomy_id IN( ' . \implode( ', ', \array_fill( 0, \count( $term_taxonomy_ids ), '%s' ) ) . ' )', + ...$term_taxonomy_ids + ) + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-author-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-author-watcher.php new file mode 100644 index 00000000..564b01e3 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-author-watcher.php @@ -0,0 +1,88 @@ +repository = $repository; + $this->builder = $builder; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + */ + public function register_hooks() { + \add_action( 'user_register', [ $this, 'build_indexable' ], \PHP_INT_MAX ); + \add_action( 'profile_update', [ $this, 'build_indexable' ], \PHP_INT_MAX ); + \add_action( 'deleted_user', [ $this, 'delete_indexable' ] ); + } + + /** + * Deletes user meta. + * + * @param int $user_id User ID to delete the metadata of. + * + * @return void + */ + public function delete_indexable( $user_id ) { + $indexable = $this->repository->find_by_id_and_type( $user_id, 'user', false ); + + if ( ! $indexable ) { + return; + } + + $indexable->delete(); + } + + /** + * Saves user meta. + * + * @param int $user_id User ID. + * + * @return void + */ + public function build_indexable( $user_id ) { + $indexable = $this->repository->find_by_id_and_type( $user_id, 'user', false ); + $this->builder->build_for_id_and_type( $user_id, 'user', $indexable ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-category-permalink-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-category-permalink-watcher.php new file mode 100644 index 00000000..6e24a9bd --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-category-permalink-watcher.php @@ -0,0 +1,53 @@ +indexable_helper->reset_permalink_indexables( 'term', 'category', Indexing_Reasons::REASON_CATEGORY_BASE_PREFIX ); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-date-archive-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-date-archive-watcher.php new file mode 100644 index 00000000..9b77cb1f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-date-archive-watcher.php @@ -0,0 +1,94 @@ +repository = $repository; + $this->builder = $builder; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + */ + public function register_hooks() { + \add_action( 'update_option_wpseo_titles', [ $this, 'check_option' ], 10, 2 ); + } + + /** + * Checks if the date archive indexable needs to be rebuild based on option values. + * + * @param array $old_value The old value of the option. + * @param array $new_value The new value of the option. + * + * @return void + */ + public function check_option( $old_value, $new_value ) { + $relevant_keys = [ 'title-archive-wpseo', 'breadcrumbs-archiveprefix', 'metadesc-archive-wpseo', 'noindex-archive-wpseo' ]; + + foreach ( $relevant_keys as $key ) { + // If both values aren't set they haven't changed. + if ( ! isset( $old_value[ $key ] ) && ! isset( $new_value[ $key ] ) ) { + continue; + } + + // If the value was set but now isn't, is set but wasn't or is not the same it has changed. + if ( ! isset( $old_value[ $key ] ) || ! isset( $new_value[ $key ] ) || $old_value[ $key ] !== $new_value[ $key ] ) { + $this->build_indexable(); + return; + } + } + } + + /** + * Saves the date archive. + * + * @return void + */ + public function build_indexable() { + $indexable = $this->repository->find_for_date_archive( false ); + $this->builder->build_for_date_archive( $indexable ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-home-page-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-home-page-watcher.php new file mode 100644 index 00000000..d883e47b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-home-page-watcher.php @@ -0,0 +1,113 @@ +repository = $repository; + $this->builder = $builder; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + */ + public function register_hooks() { + \add_action( 'update_option_wpseo_titles', [ $this, 'check_option' ], 15, 3 ); + \add_action( 'update_option_wpseo_social', [ $this, 'check_option' ], 15, 3 ); + \add_action( 'update_option_blog_public', [ $this, 'build_indexable' ] ); + \add_action( 'update_option_blogdescription', [ $this, 'build_indexable' ] ); + } + + /** + * Checks if the home page indexable needs to be rebuild based on option values. + * + * @param array $old_value The old value of the option. + * @param array $new_value The new value of the option. + * @param string $option The name of the option. + * + * @return void + */ + public function check_option( $old_value, $new_value, $option ) { + $relevant_keys = [ + 'wpseo_titles' => [ + 'title-home-wpseo', + 'breadcrumbs-home', + 'metadesc-home-wpseo', + 'open_graph_frontpage_title', + 'open_graph_frontpage_desc', + 'open_graph_frontpage_image', + ], + ]; + + if ( ! isset( $relevant_keys[ $option ] ) ) { + return; + } + + foreach ( $relevant_keys[ $option ] as $key ) { + // If both values aren't set they haven't changed. + if ( ! isset( $old_value[ $key ] ) && ! isset( $new_value[ $key ] ) ) { + continue; + } + + // If the value was set but now isn't, is set but wasn't or is not the same it has changed. + if ( ! isset( $old_value[ $key ] ) || ! isset( $new_value[ $key ] ) || $old_value[ $key ] !== $new_value[ $key ] ) { + $this->build_indexable(); + return; + } + } + } + + /** + * Saves the home page. + * + * @return void + */ + public function build_indexable() { + $indexable = $this->repository->find_for_home_page( false ); + $this->builder->build_for_home_page( $indexable ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-homeurl-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-homeurl-watcher.php new file mode 100644 index 00000000..0677d18f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-homeurl-watcher.php @@ -0,0 +1,114 @@ +post_type = $post_type; + $this->options_helper = $options; + $this->indexable_helper = $indexable; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_action( 'update_option_home', [ $this, 'reset_permalinks' ] ); + \add_action( 'wpseo_permalink_structure_check', [ $this, 'force_reset_permalinks' ] ); + } + + /** + * Resets the permalinks for everything that is related to the permalink structure. + * + * @return void + */ + public function reset_permalinks() { + $this->indexable_helper->reset_permalink_indexables( null, null, Indexing_Reasons::REASON_HOME_URL_OPTION ); + + // Reset the home_url option. + $this->options_helper->set( 'home_url', \get_home_url() ); + } + + /** + * Resets the permalink indexables automatically, if necessary. + * + * @return bool Whether the request ran. + */ + public function force_reset_permalinks() { + if ( $this->should_reset_permalinks() ) { + $this->reset_permalinks(); + + if ( \defined( 'WP_CLI' ) && \WP_CLI ) { + WP_CLI::success( \__( 'All permalinks were successfully reset', 'wordpress-seo' ) ); + } + + return true; + } + + return false; + } + + /** + * Checks whether permalinks should be reset. + * + * @return bool Whether the permalinks should be reset. + */ + public function should_reset_permalinks() { + return \get_home_url() !== $this->options_helper->get( 'home_url' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-permalink-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-permalink-watcher.php new file mode 100644 index 00000000..d667ecb2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-permalink-watcher.php @@ -0,0 +1,291 @@ +post_type = $post_type; + $this->options_helper = $options; + $this->indexable_helper = $indexable; + $this->taxonomy_helper = $taxonomy_helper; + + $this->schedule_cron(); + } + + /** + * Registers the hooks. + * + * @return void + */ + public function register_hooks() { + \add_action( 'update_option_permalink_structure', [ $this, 'reset_permalinks' ] ); + \add_action( 'update_option_category_base', [ $this, 'reset_permalinks_term' ], 10, 3 ); + \add_action( 'update_option_tag_base', [ $this, 'reset_permalinks_term' ], 10, 3 ); + \add_action( 'wpseo_permalink_structure_check', [ $this, 'force_reset_permalinks' ] ); + \add_action( 'wpseo_deactivate', [ $this, 'unschedule_cron' ] ); + } + + /** + * Resets the permalinks for everything that is related to the permalink structure. + */ + public function reset_permalinks() { + + $post_types = $this->get_post_types(); + foreach ( $post_types as $post_type ) { + $this->reset_permalinks_post_type( $post_type ); + } + + $taxonomies = $this->get_taxonomies_for_post_types( $post_types ); + foreach ( $taxonomies as $taxonomy ) { + $this->indexable_helper->reset_permalink_indexables( 'term', $taxonomy ); + } + + $this->indexable_helper->reset_permalink_indexables( 'user' ); + $this->indexable_helper->reset_permalink_indexables( 'date-archive' ); + $this->indexable_helper->reset_permalink_indexables( 'system-page' ); + + // Always update `permalink_structure` in the wpseo option. + $this->options_helper->set( 'permalink_structure', \get_option( 'permalink_structure' ) ); + } + + /** + * Resets the permalink for the given post type. + * + * @param string $post_type The post type to reset. + */ + public function reset_permalinks_post_type( $post_type ) { + $this->indexable_helper->reset_permalink_indexables( 'post', $post_type ); + $this->indexable_helper->reset_permalink_indexables( 'post-type-archive', $post_type ); + } + + /** + * Resets the term indexables when the base has been changed. + * + * @param string $old Unused. The old option value. + * @param string $new Unused. The new option value. + * @param string $type The option name. + */ + public function reset_permalinks_term( $old, $new, $type ) { + $subtype = $type; + + $reason = Indexing_Reasons::REASON_PERMALINK_SETTINGS; + + // When the subtype contains _base, just strip it. + if ( \strstr( $subtype, '_base' ) ) { + $subtype = \substr( $type, 0, -5 ); + } + + if ( $subtype === 'tag' ) { + $subtype = 'post_tag'; + $reason = Indexing_Reasons::REASON_TAG_BASE_PREFIX; + } + + if ( $subtype === 'category' ) { + $reason = Indexing_Reasons::REASON_CATEGORY_BASE_PREFIX; + } + + $this->indexable_helper->reset_permalink_indexables( 'term', $subtype, $reason ); + } + + /** + * Resets the permalink indexables automatically, if necessary. + * + * @return bool Whether the reset request ran. + */ + public function force_reset_permalinks() { + if ( \get_option( 'tag_base' ) !== $this->options_helper->get( 'tag_base_url' ) ) { + $this->reset_permalinks_term( null, null, 'tag_base' ); + $this->options_helper->set( 'tag_base_url', \get_option( 'tag_base' ) ); + } + if ( \get_option( 'category_base' ) !== $this->options_helper->get( 'category_base_url' ) ) { + $this->reset_permalinks_term( null, null, 'category_base' ); + $this->options_helper->set( 'category_base_url', \get_option( 'category_base' ) ); + } + + if ( $this->should_reset_permalinks() ) { + $this->reset_permalinks(); + + return true; + } + + $this->reset_altered_custom_taxonomies(); + + return true; + } + + /** + * Checks whether the permalinks should be reset after `permalink_structure` has changed. + * + * @return bool Whether the permalinks should be reset. + */ + public function should_reset_permalinks() { + return \get_option( 'permalink_structure' ) !== $this->options_helper->get( 'permalink_structure' ); + } + + /** + * Resets custom taxonomies if their slugs have changed. + * + * @return void + */ + public function reset_altered_custom_taxonomies() { + $taxonomies = $this->taxonomy_helper->get_custom_taxonomies(); + $custom_taxonomy_bases = $this->options_helper->get( 'custom_taxonomy_slugs', [] ); + $new_taxonomy_bases = []; + + foreach ( $taxonomies as $taxonomy ) { + $taxonomy_slug = $this->taxonomy_helper->get_taxonomy_slug( $taxonomy ); + + $new_taxonomy_bases[ $taxonomy ] = $taxonomy_slug; + + if ( ! \array_key_exists( $taxonomy, $custom_taxonomy_bases ) ) { + continue; + } + + if ( $taxonomy_slug !== $custom_taxonomy_bases[ $taxonomy ] ) { + $this->indexable_helper->reset_permalink_indexables( 'term', $taxonomy ); + } + } + + $this->options_helper->set( 'custom_taxonomy_slugs', $new_taxonomy_bases ); + } + + /** + * Retrieves a list with the public post types. + * + * @return array The post types. + */ + protected function get_post_types() { + /** + * Filter: Gives the possibility to filter out post types. + * + * @param array $post_types The post type names. + * + * @return array The post types. + */ + $post_types = \apply_filters( 'wpseo_post_types_reset_permalinks', $this->post_type->get_public_post_types() ); + + return $post_types; + } + + /** + * Retrieves the taxonomies that belongs to the public post types. + * + * @param array $post_types The post types to get taxonomies for. + * + * @return array The retrieved taxonomies. + */ + protected function get_taxonomies_for_post_types( $post_types ) { + $taxonomies = []; + foreach ( $post_types as $post_type ) { + $taxonomies[] = \get_object_taxonomies( $post_type, 'names' ); + } + + $taxonomies = \array_merge( [], ...$taxonomies ); + $taxonomies = \array_unique( $taxonomies ); + + return $taxonomies; + } + + /** + * Schedules the WP-Cron job to check the permalink_structure status. + * + * @return void + */ + protected function schedule_cron() { + if ( \wp_next_scheduled( 'wpseo_permalink_structure_check' ) ) { + return; + } + + \wp_schedule_event( \time(), 'daily', 'wpseo_permalink_structure_check' ); + } + + /** + * Unschedules the WP-Cron job to check the permalink_structure status. + * + * @return void + */ + public function unschedule_cron() { + if ( ! \wp_next_scheduled( 'wpseo_permalink_structure_check' ) ) { + return; + } + + \wp_clear_scheduled_hook( 'wpseo_permalink_structure_check' ); + } + + /* ********************* DEPRECATED METHODS ********************* */ + + /** + * Resets the permalinks of the indexables. + * + * @deprecated 15.1 + * @codeCoverageIgnore + * + * @param string $type The type of the indexable. + * @param string|null $subtype The subtype. Can be null. + * @param string $reason The reason that the permalink has been changed. + */ + public function reset_permalink_indexables( $type, $subtype = null, $reason = Indexing_Reasons::REASON_PERMALINK_SETTINGS ) { + \_deprecated_function( __METHOD__, 'WPSEO 15.1', 'Indexable_Helper::reset_permalink_indexables' ); + + $this->indexable_helper->reset_permalink_indexables( $type, $subtype, $reason ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-post-meta-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-post-meta-watcher.php new file mode 100644 index 00000000..a4d94507 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-post-meta-watcher.php @@ -0,0 +1,109 @@ +post_watcher = $post_watcher; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + */ + public function register_hooks() { + // Register all posts whose meta have changed. + \add_action( 'added_post_meta', [ $this, 'add_post_id' ], 10, 3 ); + \add_action( 'updated_post_meta', [ $this, 'add_post_id' ], 10, 3 ); + \add_action( 'deleted_post_meta', [ $this, 'add_post_id' ], 10, 3 ); + + // Remove posts that get saved as they are handled by the Indexable_Post_Watcher. + \add_action( 'wp_insert_post', [ $this, 'remove_post_id' ] ); + \add_action( 'delete_post', [ $this, 'remove_post_id' ] ); + \add_action( 'edit_attachment', [ $this, 'remove_post_id' ] ); + \add_action( 'add_attachment', [ $this, 'remove_post_id' ] ); + \add_action( 'delete_attachment', [ $this, 'remove_post_id' ] ); + + // Update indexables of all registered posts. + \register_shutdown_function( [ $this, 'update_indexables' ] ); + } + + /** + * Adds a post id to the array of posts to update. + * + * @param int|string $meta_id The meta ID. + * @param int|string $post_id The post ID. + * @param string $meta_key The meta key. + * + * @return void + */ + public function add_post_id( $meta_id, $post_id, $meta_key ) { + // Only register changes to our own meta. + if ( \strpos( $meta_key, WPSEO_Meta::$meta_prefix ) !== 0 ) { + return; + } + + if ( ! \in_array( $post_id, $this->post_ids_to_update, true ) ) { + $this->post_ids_to_update[] = (int) $post_id; + } + } + + /** + * Removes a post id from the array of posts to update. + * + * @param int|string $post_id The post ID. + * + * @return void + */ + public function remove_post_id( $post_id ) { + $this->post_ids_to_update = \array_diff( $this->post_ids_to_update, [ (int) $post_id ] ); + } + + /** + * Updates all indexables changed during the request. + * + * @return void + */ + public function update_indexables() { + foreach ( $this->post_ids_to_update as $post_id ) { + $this->post_watcher->build_indexable( $post_id ); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-post-type-archive-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-post-type-archive-watcher.php new file mode 100644 index 00000000..83bc9625 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-post-type-archive-watcher.php @@ -0,0 +1,126 @@ +repository = $repository; + $this->builder = $builder; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + */ + public function register_hooks() { + \add_action( 'update_option_wpseo_titles', [ $this, 'check_option' ], 10, 2 ); + } + + /** + * Checks if the home page indexable needs to be rebuild based on option values. + * + * @param array $old_value The old value of the option. + * @param array $new_value The new value of the option. + * + * @return bool Whether or not the option has been saved. + */ + public function check_option( $old_value, $new_value ) { + $relevant_keys = [ 'title-ptarchive-', 'metadesc-ptarchive-', 'bctitle-ptarchive-', 'noindex-ptarchive-' ]; + + // If this is the first time saving the option, thus when value is false. + if ( $old_value === false ) { + $old_value = []; + } + + if ( ! \is_array( $old_value ) || ! \is_array( $new_value ) ) { + return false; + } + + $keys = \array_unique( \array_merge( \array_keys( $old_value ), \array_keys( $new_value ) ) ); + $post_types_rebuild = []; + + foreach ( $keys as $key ) { + $post_type = false; + // Check if it's a key relevant to post type archives. + foreach ( $relevant_keys as $relevant_key ) { + if ( \strpos( $key, $relevant_key ) === 0 ) { + $post_type = \substr( $key, \strlen( $relevant_key ) ); + break; + } + } + + // If it's not a relevant key or both values aren't set they haven't changed. + if ( $post_type === false || ( ! isset( $old_value[ $key ] ) && ! isset( $new_value[ $key ] ) ) ) { + continue; + } + + // If the value was set but now isn't, is set but wasn't or is not the same it has changed. + if ( + ! \in_array( $post_type, $post_types_rebuild, true ) + && ( + ! isset( $old_value[ $key ] ) + || ! isset( $new_value[ $key ] ) + || $old_value[ $key ] !== $new_value[ $key ] + ) + ) { + $this->build_indexable( $post_type ); + $post_types_rebuild[] = $post_type; + } + } + + return true; + } + + /** + * Saves the post type archive. + * + * @param string $post_type The post type. + * + * @return void + */ + public function build_indexable( $post_type ) { + $indexable = $this->repository->find_for_post_type_archive( $post_type, false ); + $this->builder->build_for_post_type_archive( $post_type, $indexable ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-post-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-post-watcher.php new file mode 100644 index 00000000..85b49e11 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-post-watcher.php @@ -0,0 +1,291 @@ +repository = $repository; + $this->builder = $builder; + $this->hierarchy_repository = $hierarchy_repository; + $this->link_builder = $link_builder; + $this->author_archive = $author_archive; + $this->post = $post; + $this->logger = $logger; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_action( 'wp_insert_post', [ $this, 'build_indexable' ], \PHP_INT_MAX ); + \add_action( 'delete_post', [ $this, 'delete_indexable' ] ); + \add_action( 'wpseo_save_indexable', [ $this, 'updated_indexable' ], \PHP_INT_MAX, 2 ); + + \add_action( 'edit_attachment', [ $this, 'build_indexable' ], \PHP_INT_MAX ); + \add_action( 'add_attachment', [ $this, 'build_indexable' ], \PHP_INT_MAX ); + \add_action( 'delete_attachment', [ $this, 'delete_indexable' ] ); + } + + /** + * Deletes the meta when a post is deleted. + * + * @param int $post_id Post ID. + * + * @return void + */ + public function delete_indexable( $post_id ) { + $indexable = $this->repository->find_by_id_and_type( $post_id, 'post', false ); + + // Only interested in post indexables. + if ( ! $indexable || $indexable->object_type !== 'post' ) { + return; + } + + if ( $indexable->is_public ) { + $this->update_relations( $this->post->get_post( $post_id ) ); + } + + $this->update_has_public_posts( $indexable ); + + $this->hierarchy_repository->clear_ancestors( $indexable->id ); + $this->link_builder->delete( $indexable ); + $indexable->delete(); + } + + /** + * Updates the relations when the post indexable is built. + * + * @param Indexable $updated_indexable The updated indexable. + * @param Indexable $old_indexable The old indexable. + */ + public function updated_indexable( $updated_indexable, $old_indexable ) { + // Only interested in post indexables. + if ( $updated_indexable->object_type !== 'post' ) { + return; + } + + $post = $this->post->get_post( $updated_indexable->object_id ); + + // When the indexable is public or has a change in its public state. + if ( $updated_indexable->is_public || $updated_indexable->is_public !== $old_indexable->is_public ) { + $this->update_relations( $post ); + } + + $this->update_has_public_posts( $updated_indexable ); + + $updated_indexable->save(); + } + + /** + * Saves post meta. + * + * @param int $post_id Post ID. + * + * @return void + */ + public function build_indexable( $post_id ) { + // Bail if this is a multisite installation and the site has been switched. + if ( $this->is_multisite_and_switched() ) { + return; + } + + try { + $indexable = $this->repository->find_by_id_and_type( $post_id, 'post', false ); + $indexable = $this->builder->build_for_id_and_type( $post_id, 'post', $indexable ); + + $post = $this->post->get_post( $post_id ); + + // Build links for this post. + if ( $post && $indexable && \in_array( $post->post_status, $this->post->get_public_post_statuses(), true ) ) { + $this->link_builder->build( $indexable, $post->post_content ); + // Save indexable to persist the updated link count. + $indexable->save(); + } + } catch ( Exception $exception ) { + $this->logger->log( LogLevel::ERROR, $exception->getMessage() ); + } + } + + /** + * Updates the has_public_posts when the post indexable is built. + * + * @param Indexable $indexable The indexable to check. + */ + protected function update_has_public_posts( $indexable ) { + // Update the author indexable's has public posts value. + try { + $author_indexable = $this->repository->find_by_id_and_type( $indexable->author_id, 'user' ); + $author_indexable->has_public_posts = $this->author_archive->author_has_public_posts( $author_indexable->object_id ); + $author_indexable->save(); + } catch ( Exception $exception ) { + $this->logger->log( LogLevel::ERROR, $exception->getMessage() ); + } + + // Update possible attachment's has public posts value. + $this->post->update_has_public_posts_on_attachments( $indexable->object_id, $indexable->is_public ); + } + + /** + * Updates the relations on post save or post status change. + * + * @param WP_Post $post The post that has been updated. + */ + protected function update_relations( $post ) { + $related_indexables = $this->get_related_indexables( $post ); + + $updated_at = \gmdate( 'Y-m-d H:i:s' ); + foreach ( $related_indexables as $indexable ) { + if ( ! $indexable->is_public ) { + continue; + } + + $indexable->updated_at = $updated_at; + $indexable->save(); + } + } + + /** + * Retrieves the related indexables for given post. + * + * @param WP_Post $post The post to get the indexables for. + * + * @return Indexable[] The indexables. + */ + protected function get_related_indexables( $post ) { + /** + * The related indexables. + * + * @var Indexable[] $related_indexables . + */ + $related_indexables = []; + $related_indexables[] = $this->repository->find_by_id_and_type( $post->post_author, 'user', false ); + $related_indexables[] = $this->repository->find_for_post_type_archive( $post->post_type, false ); + $related_indexables[] = $this->repository->find_for_home_page( false ); + + $taxonomies = \get_post_taxonomies( $post->ID ); + $taxonomies = \array_filter( $taxonomies, 'is_taxonomy_viewable' ); + foreach ( $taxonomies as $taxonomy ) { + $terms = \get_the_terms( $post->ID, $taxonomy ); + + if ( empty( $terms ) || \is_wp_error( $terms ) ) { + continue; + } + + foreach ( $terms as $term ) { + $related_indexables[] = $this->repository->find_by_id_and_type( $term->term_id, 'term', false ); + } + } + + return \array_filter( $related_indexables ); + } + + /** + * Tests if the site is multisite and switched. + * + * @return bool True when the site is multisite and switched + */ + protected function is_multisite_and_switched() { + return \is_multisite() && \ms_is_switched(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-static-home-page-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-static-home-page-watcher.php new file mode 100644 index 00000000..1ad96f0b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-static-home-page-watcher.php @@ -0,0 +1,91 @@ +repository = $repository; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + */ + public function register_hooks() { + \add_action( 'update_option_page_on_front', [ $this, 'update_static_homepage_permalink' ], 10, 2 ); + } + + /** + * Updates the new and previous homepage's permalink when the static home page is updated. + * + * @param string $old_value The previous homepage's ID. + * @param int $value The new homepage's ID. + */ + public function update_static_homepage_permalink( $old_value, $value ) { + if ( \is_string( $old_value ) ) { + $old_value = (int) $old_value; + } + + if ( $old_value === $value ) { + return; + } + + $this->update_permalink_for_page( $old_value ); + $this->update_permalink_for_page( $value ); + } + + /** + * Updates the permalink based on the selected homepage settings. + * + * @param int $page_id The page's id. + */ + private function update_permalink_for_page( $page_id ) { + if ( $page_id === 0 ) { + return; + } + + $indexable = $this->repository->find_by_id_and_type( $page_id, 'post', false ); + + if ( $indexable === false ) { + return; + } + + $indexable->permalink = \get_permalink( $page_id ); + + $indexable->save(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-system-page-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-system-page-watcher.php new file mode 100644 index 00000000..996c3d19 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-system-page-watcher.php @@ -0,0 +1,100 @@ +repository = $repository; + $this->builder = $builder; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + */ + public function register_hooks() { + \add_action( 'update_option_wpseo_titles', [ $this, 'check_option' ], 10, 2 ); + } + + /** + * Checks if the home page indexable needs to be rebuild based on option values. + * + * @param array $old_value The old value of the option. + * @param array $new_value The new value of the option. + * + * @return void + */ + public function check_option( $old_value, $new_value ) { + foreach ( Indexable_System_Page_Builder::OPTION_MAPPING as $type => $options ) { + foreach ( $options as $option ) { + // If both values aren't set they haven't changed. + if ( ! isset( $old_value[ $option ] ) && ! isset( $new_value[ $option ] ) ) { + return; + } + + // If the value was set but now isn't, is set but wasn't or is not the same it has changed. + if ( + ! isset( $old_value[ $option ] ) + || ! isset( $new_value[ $option ] ) + || $old_value[ $option ] !== $new_value[ $option ] + ) { + $this->build_indexable( $type ); + } + } + } + } + + /** + * Saves the search result. + * + * @param string $type The type of no index page. + * + * @return void + */ + public function build_indexable( $type ) { + $indexable = $this->repository->find_for_system_page( $type, false ); + $this->builder->build_for_system_page( $type, $indexable ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-term-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-term-watcher.php new file mode 100644 index 00000000..2814f5a6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/indexable-term-watcher.php @@ -0,0 +1,135 @@ +repository = $repository; + $this->builder = $builder; + $this->link_builder = $link_builder; + $this->site = $site; + } + + /** + * Registers the hooks. + * + * @return void + */ + public function register_hooks() { + \add_action( 'created_term', [ $this, 'build_indexable' ], \PHP_INT_MAX ); + \add_action( 'edited_term', [ $this, 'build_indexable' ], \PHP_INT_MAX ); + \add_action( 'delete_term', [ $this, 'delete_indexable' ], \PHP_INT_MAX ); + } + + /** + * Deletes a term from the index. + * + * @param int $term_id The Term ID to delete. + * + * @return void + */ + public function delete_indexable( $term_id ) { + $indexable = $this->repository->find_by_id_and_type( $term_id, 'term', false ); + + if ( ! $indexable ) { + return; + } + + $indexable->delete(); + } + + /** + * Update the taxonomy meta data on save. + * + * @param int $term_id ID of the term to save data for. + * + * @return void + */ + public function build_indexable( $term_id ) { + // Bail if this is a multisite installation and the site has been switched. + if ( $this->site->is_multisite_and_switched() ) { + return; + } + + $term = \get_term( $term_id ); + + if ( $term === null || \is_wp_error( $term ) ) { + return; + } + + if ( ! \is_taxonomy_viewable( $term->taxonomy ) ) { + return; + } + + $indexable = $this->repository->find_by_id_and_type( $term_id, 'term', false ); + + // If we haven't found an existing indexable, create it. Otherwise update it. + $indexable = $this->builder->build_for_id_and_type( $term_id, 'term', $indexable ); + + // Update links. + $this->link_builder->build( $indexable, $term->description ); + + $indexable->save(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/option-titles-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/option-titles-watcher.php new file mode 100644 index 00000000..9797d062 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/option-titles-watcher.php @@ -0,0 +1,128 @@ +get_relevant_keys(); + if ( empty( $relevant_keys ) ) { + return false; + } + + $post_types = []; + + foreach ( $relevant_keys as $post_type => $relevant_option ) { + // If both values aren't set they haven't changed. + if ( ! isset( $old_value[ $relevant_option ] ) && ! isset( $new_value[ $relevant_option ] ) ) { + continue; + } + + if ( $old_value[ $relevant_option ] !== $new_value[ $relevant_option ] ) { + $post_types[] = $post_type; + } + } + + return $this->delete_ancestors( $post_types ); + } + + /** + * Retrieves the relevant keys. + * + * @return array Array with the relevant keys. + */ + protected function get_relevant_keys() { + $post_types = \get_post_types( [ 'public' => true ], 'names' ); + if ( ! \is_array( $post_types ) || $post_types === [] ) { + return []; + } + + $relevant_keys = []; + foreach ( $post_types as $post_type ) { + $relevant_keys[ $post_type ] = 'post_types-' . $post_type . '-maintax'; + } + + return $relevant_keys; + } + + /** + * Removes the ancestors for given post types. + * + * @param array $post_types The post types to remove hierarchy for. + * + * @return bool True when delete query was successful. + */ + protected function delete_ancestors( $post_types ) { + if ( empty( $post_types ) ) { + return false; + } + + $wpdb = Wrapper::get_wpdb(); + $total = \count( $post_types ); + $hierarchy_table = Model::get_table_name( 'Indexable_Hierarchy' ); + $indexable_table = Model::get_table_name( 'Indexable' ); + + $result = $wpdb->query( + $wpdb->prepare( + " + DELETE FROM `$hierarchy_table` + WHERE indexable_id IN( + SELECT id + FROM `$indexable_table` + WHERE object_type = 'post' + AND object_sub_type IN( " . \implode( ', ', \array_fill( 0, $total, '%s' ) ) . ' ) + )', + $post_types + ) + ); + + return $result !== false; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/option-wpseo-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/option-wpseo-watcher.php new file mode 100644 index 00000000..b51ee163 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/option-wpseo-watcher.php @@ -0,0 +1,47 @@ +helpers->options->set( 'semrush_tokens', [] ); + return true; + } + return false; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/primary-category-quick-edit-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/primary-category-quick-edit-watcher.php new file mode 100644 index 00000000..da47603c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/primary-category-quick-edit-watcher.php @@ -0,0 +1,191 @@ +options_helper = $options_helper; + $this->primary_term_repository = $primary_term_repository; + $this->post_type_helper = $post_type_helper; + $this->indexable_repository = $indexable_repository; + $this->indexable_hierarchy_builder = $indexable_hierarchy_builder; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + * + * @return void + */ + public function register_hooks() { + \add_action( 'set_object_terms', [ $this, 'validate_primary_category' ], 10, 4 ); + } + + /** + * Returns the conditionals based on which this loadable should be active. + * + * @return array The conditionals. + */ + public static function get_conditionals() { + return [ Migrations_Conditional::class, Doing_Post_Quick_Edit_Save_Conditional::class ]; + } + + /** + * Validates if the current primary category is still present. If not just remove the post meta for it. + * + * @param int $object_id Object ID. + * @param array $terms Unused. An array of object terms. + * @param array $tt_ids An array of term taxonomy IDs. + * @param string $taxonomy Taxonomy slug. + */ + public function validate_primary_category( $object_id, $terms, $tt_ids, $taxonomy ) { + $post = \get_post( $object_id ); + if ( $post === null ) { + return; + } + + $main_taxonomy = $this->options_helper->get( 'post_types-' . $post->post_type . '-maintax' ); + if ( ! $main_taxonomy || $main_taxonomy === '0' ) { + return; + } + + if ( $main_taxonomy !== $taxonomy ) { + return; + } + + $primary_category = $this->get_primary_term_id( $post->ID, $main_taxonomy ); + if ( $primary_category === false ) { + return; + } + + // The primary category isn't removed. + if ( \in_array( (string) $primary_category, $tt_ids, true ) ) { + return; + } + + $this->remove_primary_term( $post->ID, $main_taxonomy ); + + // Rebuild the post hierarchy for this post now the primary term has been changed. + $this->build_post_hierarchy( $post ); + } + + /** + * Returns the primary term id of a post. + * + * @param int $post_id The post ID. + * @param string $main_taxonomy The main taxonomy. + * + * @return int|false The ID of the primary term, or `false` if the post ID is invalid. + */ + private function get_primary_term_id( $post_id, $main_taxonomy ) { + $primary_term = $this->primary_term_repository->find_by_post_id_and_taxonomy( $post_id, $main_taxonomy, false ); + + if ( $primary_term ) { + return $primary_term->term_id; + } + + return \get_post_meta( $post_id, WPSEO_Meta::$meta_prefix . 'primary_' . $main_taxonomy, true ); + } + + /** + * Removes the primary category. + * + * @param int $post_id The post id to set primary taxonomy for. + * @param string $main_taxonomy Name of the taxonomy that is set to be the primary one. + */ + private function remove_primary_term( $post_id, $main_taxonomy ) { + $primary_term = $this->primary_term_repository->find_by_post_id_and_taxonomy( $post_id, $main_taxonomy, false ); + if ( $primary_term ) { + $primary_term->delete(); + } + + // Remove it from the post meta. + \delete_post_meta( $post_id, WPSEO_Meta::$meta_prefix . 'primary_' . $main_taxonomy ); + } + + /** + * Builds the hierarchy for a post. + * + * @param \WP_Post $post The post. + */ + public function build_post_hierarchy( $post ) { + if ( $this->post_type_helper->is_excluded( $post->post_type ) ) { + return; + } + + $indexable = $this->indexable_repository->find_by_id_and_type( $post->ID, 'post' ); + + if ( $indexable instanceof Indexable ) { + $this->indexable_hierarchy_builder->build( $indexable ); + } + } +} +// phpcs:enable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded diff --git a/wp-content/plugins/wordpress-seo/src/integrations/watchers/primary-term-watcher.php b/wp-content/plugins/wordpress-seo/src/integrations/watchers/primary-term-watcher.php new file mode 100644 index 00000000..58d14e44 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/watchers/primary-term-watcher.php @@ -0,0 +1,144 @@ +repository = $repository; + $this->site = $site; + $this->primary_term = $primary_term; + $this->primary_term_builder = $primary_term_builder; + } + + /** + * Initializes the integration. + * + * This is the place to register hooks and filters. + */ + public function register_hooks() { + \add_action( 'save_post', [ $this, 'save_primary_terms' ], \PHP_INT_MAX ); + \add_action( 'delete_post', [ $this, 'delete_primary_terms' ] ); + } + + /** + * 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 ( $this->site->is_multisite_and_switched() ) { + return; + } + + $taxonomies = $this->primary_term->get_primary_term_taxonomies( $post_id ); + + foreach ( $taxonomies as $taxonomy ) { + $this->save_primary_term( $post_id, $taxonomy ); + } + + $this->primary_term_builder->build( $post_id ); + } + + /** + * Saves 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 ( $primary_term && \check_admin_referer( 'save-primary-term', WPSEO_Meta::$form_prefix . 'primary_' . $taxonomy->name . '_nonce' ) !== null ) { + $primary_term_object = new WPSEO_Primary_Term( $taxonomy->name, $post_id ); + $primary_term_object->set_primary_term( $primary_term ); + } + } + + /** + * Deletes primary terms for a post. + * + * @param int $post_id The post to delete the terms of. + * + * @return void + */ + public function delete_primary_terms( $post_id ) { + foreach ( $this->primary_term->get_primary_term_taxonomies( $post_id ) as $taxonomy ) { + $primary_term = $this->repository->find_by_post_id_and_taxonomy( $post_id, $taxonomy->name, false ); + + if ( ! $primary_term ) { + continue; + } + + $primary_term->delete(); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/src/integrations/xmlrpc.php b/wp-content/plugins/wordpress-seo/src/integrations/xmlrpc.php new file mode 100644 index 00000000..3e218ad4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/integrations/xmlrpc.php @@ -0,0 +1,48 @@ +container = $container; + } + + /** + * Registers an integration. + * + * @param string $class The class name of the integration to be loaded. + * + * @return void + */ + public function register_integration( $class ) { + $this->integrations[] = $class; + } + + /** + * Registers an initializer. + * + * @param string $class The class name of the initializer to be loaded. + * + * @return void + */ + public function register_initializer( $class ) { + $this->initializers[] = $class; + } + + /** + * Registers a route. + * + * @param string $class The class name of the route to be loaded. + * + * @return void + */ + public function register_route( $class ) { + $this->routes[] = $class; + } + + /** + * Registers a command. + * + * @param string $class The class name of the command to be loaded. + * + * @return void + */ + public function register_command( $class ) { + $this->commands[] = $class; + } + + /** + * Registers a migration. + * + * @param string $plugin The plugin the migration belongs to. + * @param string $version The version of the migration. + * @param string $class The class name of the migration to be loaded. + * + * @return void + */ + public function register_migration( $plugin, $version, $class ) { + if ( ! \array_key_exists( $plugin, $this->migrations ) ) { + $this->migrations[ $plugin ] = []; + } + + $this->migrations[ $plugin ][ $version ] = $class; + } + + /** + * Loads all registered classes if their conditionals are met. + * + * @return void + */ + public function load() { + $this->load_initializers(); + + if ( ! \did_action( 'init' ) ) { + \add_action( 'init', [ $this, 'load_integrations' ] ); + } + else { + $this->load_integrations(); + } + + \add_action( 'rest_api_init', [ $this, 'load_routes' ] ); + + if ( \defined( 'WP_CLI' ) && \WP_CLI ) { + $this->load_commands(); + } + } + + /** + * Returns all registered migrations. + * + * @param string $plugin The plugin to get the migrations for. + * + * @return string[]|false The registered migrations. False if no migrations were registered. + */ + public function get_migrations( $plugin ) { + if ( ! \array_key_exists( $plugin, $this->migrations ) ) { + return false; + } + + return $this->migrations[ $plugin ]; + } + + /** + * Loads all registered commands. + * + * @return void + */ + protected function load_commands() { + foreach ( $this->commands as $class ) { + $command = $this->container->get( $class ); + + WP_CLI::add_command( $class::get_namespace(), $command ); + } + } + + /** + * Loads all registered initializers if their conditionals are met. + * + * @return void + */ + protected function load_initializers() { + foreach ( $this->initializers as $class ) { + if ( ! $this->conditionals_are_met( $class ) ) { + continue; + } + + $this->container->get( $class )->initialize(); + } + } + + /** + * Loads all registered integrations if their conditionals are met. + * + * @return void + */ + public function load_integrations() { + foreach ( $this->integrations as $class ) { + if ( ! $this->conditionals_are_met( $class ) ) { + continue; + } + + $this->container->get( $class )->register_hooks(); + } + } + + /** + * Loads all registered routes if their conditionals are met. + * + * @return void + */ + public function load_routes() { + foreach ( $this->routes as $class ) { + if ( ! $this->conditionals_are_met( $class ) ) { + continue; + } + + $this->container->get( $class )->register_routes(); + } + } + + /** + * Checks if all conditionals of a given integration are met. + * + * @param Loadable_Interface $class The class name of the integration. + * + * @return bool Whether or not all conditionals of the integration are met. + */ + protected function conditionals_are_met( $class ) { + $conditionals = $class::get_conditionals(); + foreach ( $conditionals as $conditional ) { + if ( ! $this->container->get( $conditional )->is_met() ) { + return false; + } + } + + return true; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/loggers/logger.php b/wp-content/plugins/wordpress-seo/src/loggers/logger.php new file mode 100644 index 00000000..849f02ec --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/loggers/logger.php @@ -0,0 +1,51 @@ +wrapped_logger = new NullLogger(); + + /** + * Gives the possibility to set override the logger interface. + * + * @api \YoastSEO_Vendor\Psr\Log\LoggerInterface $logger Instance of NullLogger. + * + * @return LoggerInterface The logger object. + */ + $this->wrapped_logger = \apply_filters( 'wpseo_logger', $this->wrapped_logger ); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level The log level. + * @param string $message The log message. + * @param array $context The log context. + * + * @return void + */ + public function log( $level, $message, array $context = [] ) { + $this->wrapped_logger->log( $level, $message, $context ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/main.php b/wp-content/plugins/wordpress-seo/src/main.php new file mode 100644 index 00000000..698fb56d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/main.php @@ -0,0 +1,82 @@ +is_development() && \class_exists( '\Yoast\WP\SEO\Dependency_Injection\Container_Compiler' ) ) { + // Exception here is unhandled as it will only occur in development. + Container_Compiler::compile( + $this->is_development(), + __DIR__ . '/generated/container.php', + __DIR__ . '/../config/dependency-injection/services.php', + __DIR__ . '/../vendor/composer/autoload_classmap.php', + 'Yoast\WP\SEO\Generated' + ); + } + + if ( \file_exists( __DIR__ . '/generated/container.php' ) ) { + require_once __DIR__ . '/generated/container.php'; + + return new Cached_Container(); + } + + return null; + } + + /** + * {@inheritDoc} + */ + protected function get_name() { + return 'yoast-seo'; + } + + /** + * {@inheritDoc} + */ + protected function get_surfaces() { + return [ + 'classes' => Classes_Surface::class, + 'meta' => Meta_Surface::class, + 'helpers' => Helpers_Surface::class, + ]; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/memoizers/meta-tags-context-memoizer.php b/wp-content/plugins/wordpress-seo/src/memoizers/meta-tags-context-memoizer.php new file mode 100644 index 00000000..ed59196f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/memoizers/meta-tags-context-memoizer.php @@ -0,0 +1,171 @@ +blocks = $blocks; + $this->current_page = $current_page; + $this->repository = $repository; + $this->context_prototype = $context_prototype; + $this->presentation_memoizer = $presentation_memoizer; + } + + /** + * Gets the meta tags context for the current page. + * This function is memoized so every call will return the same result. + * + * @return Meta_Tags_Context The meta tags context. + */ + public function for_current_page() { + if ( ! isset( $this->cache['current_page'] ) ) { + // First reset the query to ensure we actually have the current page. + global $wp_query; + + $old_wp_query = $wp_query; + // phpcs:ignore WordPress.WP.DiscouragedFunctions.wp_reset_query_wp_reset_query -- Reason: The recommended function, wp_reset_postdata, doesn't reset wp_query. + \wp_reset_query(); + + $indexable = $this->repository->for_current_page(); + $page_type = $this->current_page->get_page_type(); + + if ( $page_type === 'Fallback' ) { + // Do not cache the context if it's a fallback page. + // The likely cause for this is that this function was called before the query was loaded. + $context = $this->get( $indexable, $page_type ); + + // Restore the previous query. + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Reason: we have to restore the query. + $GLOBALS['wp_query'] = $old_wp_query; + + return $context; + } + $this->cache['current_page'] = $this->get( $indexable, $page_type ); + + // Restore the previous query. + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Reason: we have to restore the query. + $GLOBALS['wp_query'] = $old_wp_query; + } + + return $this->cache['current_page']; + } + + /** + * Gets the meta tags context given an indexable. + * This function is memoized by the indexable so every call with the same indexable will yield the same result. + * + * @param Indexable $indexable The indexable. + * @param string $page_type The page type. + * + * @return Meta_Tags_Context The meta tags context. + */ + public function get( Indexable $indexable, $page_type ) { + if ( ! isset( $this->cache[ $indexable->id ] ) ) { + $blocks = []; + $post = null; + if ( $indexable->object_type === 'post' ) { + $post = \get_post( $indexable->object_id ); + $blocks = $this->blocks->get_all_blocks_from_content( $post->post_content ); + } + + $context = $this->context_prototype->of( + [ + 'indexable' => $indexable, + 'blocks' => $blocks, + 'post' => $post, + 'page_type' => $page_type, + ] + ); + + $context->presentation = $this->presentation_memoizer->get( $indexable, $context, $page_type ); + + $this->cache[ $indexable->id ] = $context; + } + + return $this->cache[ $indexable->id ]; + } + + /** + * Clears the memoization of either a specific indexable or all indexables. + * + * @param Indexable|int|string|null $indexable Optional. The indexable or indexable id to clear the memoization of. + */ + public function clear( $indexable = null ) { + if ( $indexable instanceof Indexable ) { + unset( $this->cache[ $indexable->id ] ); + return; + } + if ( $indexable !== null ) { + unset( $this->cache[ $indexable ] ); + return; + } + $this->cache = []; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/memoizers/presentation-memoizer.php b/wp-content/plugins/wordpress-seo/src/memoizers/presentation-memoizer.php new file mode 100644 index 00000000..b775e436 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/memoizers/presentation-memoizer.php @@ -0,0 +1,87 @@ +container = $service_container; + } + + /** + * Gets the presentation of an indexable for a specific page type. + * This function is memoized by the indexable so every call with the same indexable will yield the same result. + * + * @param Indexable $indexable The indexable to get a presentation of. + * @param Meta_Tags_Context $context The current meta tags context. + * @param string $page_type The page type. + * + * @return Indexable_Presentation The indexable presentation. + */ + public function get( Indexable $indexable, Meta_Tags_Context $context, $page_type ) { + if ( ! isset( $this->cache[ $indexable->id ] ) ) { + $presentation = $this->container->get( "Yoast\WP\SEO\Presentations\Indexable_{$page_type}_Presentation", ContainerInterface::NULL_ON_INVALID_REFERENCE ); + + if ( ! $presentation ) { + $presentation = $this->container->get( Indexable_Presentation::class ); + } + + $context->presentation = $presentation->of( + [ + 'model' => $indexable, + 'context' => $context, + ] + ); + + $this->cache[ $indexable->id ] = $context->presentation; + } + + return $this->cache[ $indexable->id ]; + } + + /** + * Clears the memoization of either a specific indexable or all indexables. + * + * @param Indexable|int|null $indexable Optional. The indexable or indexable id to clear the memoization of. + */ + public function clear( $indexable = null ) { + if ( $indexable instanceof Indexable ) { + unset( $this->cache[ $indexable->id ] ); + return; + } + if ( \is_int( $indexable ) ) { + unset( $this->cache[ $indexable ] ); + return; + } + if ( $indexable === null ) { + $this->cache = []; + } + } +} diff --git a/wp-content/plugins/wordpress-seo/src/models/indexable-extension.php b/wp-content/plugins/wordpress-seo/src/models/indexable-extension.php new file mode 100644 index 00000000..9c65405e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/models/indexable-extension.php @@ -0,0 +1,31 @@ +indexable === null ) { + $this->indexable = $this->belongs_to( 'Indexable', 'indexable_id', 'id' )->find_one(); + } + + return $this->indexable; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/models/indexable-hierarchy.php b/wp-content/plugins/wordpress-seo/src/models/indexable-hierarchy.php new file mode 100644 index 00000000..f465941f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/models/indexable-hierarchy.php @@ -0,0 +1,28 @@ +loaded_extensions[ $class_name ] ) { + $this->loaded_extensions[ $class_name ] = $this->has_one( $class_name, 'indexable_id', 'id' )->find_one(); + } + + return $this->loaded_extensions[ $class_name ]; + } + + /** + * Enhances the save method. + * + * @return bool True on success. + */ + public function save() { + if ( $this->permalink ) { + $this->sanitize_permalink(); + $this->permalink_hash = \strlen( $this->permalink ) . ':' . \md5( $this->permalink ); + } + if ( \strlen( $this->primary_focus_keyword ) > 191 ) { + $this->primary_focus_keyword = \mb_substr( $this->primary_focus_keyword, 0, 191, 'UTF-8' ); + } + + return parent::save(); + } + + /** + * Sanitizes the permalink. + * + * @return void + */ + protected function sanitize_permalink() { + if ( $this->permalink === 'unindexed' ) { + return; + } + + $permalink_structure = \get_option( 'permalink_structure' ); + $permalink_parts = \wp_parse_url( $this->permalink ); + + if ( ! isset( $permalink_parts['path'] ) ) { + $permalink_parts['path'] = '/'; + } + if ( \substr( $permalink_structure, -1, 1 ) === '/' && \strpos( \substr( $permalink_parts['path'], -5 ), '.' ) === false ) { + $permalink_parts['path'] = \trailingslashit( $permalink_parts['path'] ); + } + + $permalink = ''; + if ( isset( $permalink_parts['scheme'] ) ) { + $permalink .= $permalink_parts['scheme'] . '://'; + } + if ( isset( $permalink_parts['host'] ) ) { + $permalink .= $permalink_parts['host']; + } + if ( isset( $permalink_parts['port'] ) ) { + $permalink .= ':' . $permalink_parts['port']; + } + if ( isset( $permalink_parts['path'] ) ) { + $permalink .= $permalink_parts['path']; + } + if ( isset( $permalink_parts['query'] ) ) { + $permalink .= '?' . $permalink_parts['query']; + } + // We never set the fragment as the fragment is intended to be client-only. + $this->permalink = $permalink; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/models/primary-term.php b/wp-content/plugins/wordpress-seo/src/models/primary-term.php new file mode 100644 index 00000000..254c6289 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/models/primary-term.php @@ -0,0 +1,39 @@ +is_prototype() ) { + throw new Exception( 'Attempting to create a model presentation from another model presentation. Use the prototype presentation gained from DI instead.' ); + } + + // Clone self to allow stateful services that do benefit from DI. + $presentation = clone $this; + foreach ( $data as $key => $value ) { + $presentation->{$key} = $value; + } + $presentation->is_prototype = false; + return $presentation; + } + + /** + * Magic getter for lazy loading of generate functions. + * + * @param string $name The property to get. + * + * @return mixed The value if it could be generated. + * + * @throws Exception If there is no generator for the property. + */ + public function __get( $name ) { + if ( $this->is_prototype() ) { + throw new Exception( 'Attempting property access on prototype presentation. Use Presentation::of( $data ) to get a model presentation.' ); + } + $generator = "generate_$name"; + if ( \method_exists( $this, $generator ) ) { + $this->{$name} = $this->$generator(); + return $this->{$name}; + } + throw new Exception( "Property $name has no generator. Expected function $generator." ); + } + + /** + * Magic isset for ensuring methods that have a generator are recognised. + * + * @codeCoverageIgnore Wrapper method. + * + * @param string $name The property to get. + * + * @return bool Whether or not there is a generator for the requested property. + */ + public function __isset( $name ) { + return \method_exists( $this, "generate_$name" ); + } + + /** + * Returns `true` if this class is a prototype. + * + * @return bool If this class is a prototype or not. + * + * @codeCoverageIgnore Wrapper method. + */ + protected function is_prototype() { + return $this->is_prototype; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/archive-adjacent-trait.php b/wp-content/plugins/wordpress-seo/src/presentations/archive-adjacent-trait.php new file mode 100644 index 00000000..e78bb036 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/archive-adjacent-trait.php @@ -0,0 +1,72 @@ +pagination = $pagination; + } + + /** + * Generates the rel prev. + * + * @return string + */ + public function generate_rel_prev() { + if ( $this->pagination->is_rel_adjacent_disabled() ) { + return ''; + } + + $current_page = \max( 1, $this->pagination->get_current_archive_page_number() ); + // Check if there is a previous page. + if ( $current_page === 1 ) { + return ''; + } + // Check if the previous page is the first page. + if ( $current_page === 2 ) { + return $this->get_permalink(); + } + + return $this->pagination->get_paginated_url( $this->get_permalink(), ( $current_page - 1 ) ); + } + + /** + * Generates the rel next. + * + * @return string + */ + public function generate_rel_next() { + if ( $this->pagination->is_rel_adjacent_disabled() ) { + return ''; + } + + $current_page = \max( 1, $this->pagination->get_current_archive_page_number() ); + if ( $this->pagination->get_number_of_archive_pages() <= $current_page ) { + return ''; + } + + return $this->pagination->get_paginated_url( $this->get_permalink(), ( $current_page + 1 ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-author-archive-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-author-archive-presentation.php new file mode 100644 index 00000000..a235b5a6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-author-archive-presentation.php @@ -0,0 +1,175 @@ +post_type = $post_type; + $this->author_archive = $author_archive; + } + + /** + * Generates the canonical. + * + * @return string The canonical. + */ + public function generate_canonical() { + if ( $this->model->canonical ) { + return $this->model->canonical; + } + + $permalink = $this->get_permalink(); + + if ( ! $permalink ) { + return ''; + } + + $current_page = $this->pagination->get_current_archive_page_number(); + if ( $current_page > 1 ) { + return $this->pagination->get_paginated_url( $permalink, $current_page ); + } + + return $permalink; + } + + /** + * Generates the title. + * + * @return string The title. + */ + public function generate_title() { + if ( $this->model->title ) { + return $this->model->title; + } + + $option_titles_key = 'title-author-wpseo'; + $title = $this->options->get( $option_titles_key ); + if ( $title ) { + return $title; + } + + return $this->options->get_title_default( $option_titles_key ); + } + + /** + * Generates the meta description. + * + * @return string The meta description. + */ + public function generate_meta_description() { + if ( $this->model->description ) { + return $this->model->description; + } + + $option_titles_key = 'metadesc-author-wpseo'; + $description = $this->options->get( $option_titles_key ); + if ( $description ) { + return $description; + } + + return $this->options->get_title_default( $option_titles_key ); + } + + /** + * Generates the robots value. + * + * @return array The robots value. + */ + public function generate_robots() { + $robots = $this->get_base_robots(); + + // Global option: "Show author archives in search results". + if ( $this->options->get( 'noindex-author-wpseo', false ) ) { + $robots['index'] = 'noindex'; + return $this->filter_robots( $robots ); + } + + $current_author = \get_userdata( $this->model->object_id ); + + // Safety check. The call to `get_user_data` could return false (called in `get_queried_object`). + if ( $current_author === false ) { + $robots['index'] = 'noindex'; + return $this->filter_robots( $robots ); + } + + $author_archive_post_types = $this->author_archive->get_author_archive_post_types(); + + // Global option: "Show archives for authors without posts in search results". + if ( $this->options->get( 'noindex-author-noposts-wpseo', false ) && $this->user->count_posts( $current_author->ID, $author_archive_post_types ) === 0 ) { + $robots['index'] = 'noindex'; + return $this->filter_robots( $robots ); + } + + // User option: "Do not allow search engines to show this author's archives in search results". + if ( $this->user->get_meta( $current_author->ID, 'wpseo_noindex_author', true ) === 'on' ) { + $robots['index'] = 'noindex'; + return $this->filter_robots( $robots ); + } + + return $this->filter_robots( $robots ); + } + + /** + * Generates the Open Graph type. + * + * @return string The Open Graph type. + */ + public function generate_open_graph_type() { + return 'profile'; + } + + /** + * Generates the open graph images. + * + * @return array The open graph images. + */ + public function generate_open_graph_images() { + if ( $this->context->open_graph_enabled === false ) { + return []; + } + + return $this->open_graph_image_generator->generate_for_author_archive( $this->context ); + } + + /** + * Generates the source. + * + * @return array The source. + */ + public function generate_source() { + return [ 'post_author' => $this->model->object_id ]; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-date-archive-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-date-archive-presentation.php new file mode 100644 index 00000000..da2801b2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-date-archive-presentation.php @@ -0,0 +1,123 @@ +pagination = $pagination; + } + + /** + * Generates the canonical. + * + * @return string The canonical. + */ + public function generate_canonical() { + $canonical = $this->current_page->get_date_archive_permalink(); + + $current_page = $this->pagination->get_current_archive_page_number(); + if ( $current_page > 1 ) { + return $this->pagination->get_paginated_url( $canonical, $current_page ); + } + + return $canonical; + } + + /** + * Generates the robots value. + * + * @return array The robots value. + */ + public function generate_robots() { + $robots = $this->get_base_robots(); + + if ( $this->options->get( 'noindex-archive-wpseo', false ) ) { + $robots['index'] = 'noindex'; + } + + return $this->filter_robots( $robots ); + } + + /** + * Generates the title. + * + * @return string The title. + */ + public function generate_title() { + if ( $this->model->title ) { + return $this->model->title; + } + + return $this->options->get_title_default( 'title-archive-wpseo' ); + } + + /** + * Generates the rel prev. + * + * @return string The rel prev value. + */ + public function generate_rel_prev() { + if ( $this->pagination->is_rel_adjacent_disabled() ) { + return ''; + } + + $current_page = \max( 1, $this->pagination->get_current_archive_page_number() ); + // Check if there is a previous page. + if ( $current_page === 1 ) { + return ''; + } + // Check if the previous page is the first page. + if ( $current_page === 2 ) { + return $this->current_page->get_date_archive_permalink(); + } + + return $this->pagination->get_paginated_url( $this->current_page->get_date_archive_permalink(), ( $current_page - 1 ) ); + } + + /** + * Generates the rel next. + * + * @return string The rel prev next. + */ + public function generate_rel_next() { + if ( $this->pagination->is_rel_adjacent_disabled() ) { + return ''; + } + + $current_page = \max( 1, $this->pagination->get_current_archive_page_number() ); + if ( $this->pagination->get_number_of_archive_pages() <= $current_page ) { + return ''; + } + + return $this->pagination->get_paginated_url( $this->current_page->get_date_archive_permalink(), ( $current_page + 1 ) ); + } + + /** + * Generates the open graph url. + * + * @return string The open graph url. + */ + public function generate_open_graph_url() { + return $this->current_page->get_date_archive_permalink(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-error-page-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-error-page-presentation.php new file mode 100644 index 00000000..dcbee565 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-error-page-presentation.php @@ -0,0 +1,37 @@ +get_base_robots(); + + $robots['index'] = 'noindex'; + + return $this->filter_robots( $robots ); + } + + /** + * Generates the title. + * + * @return string The title. + */ + public function generate_title() { + if ( $this->model->title ) { + return $this->model->title; + } + + return $this->options->get_title_default( 'title-404-wpseo' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-home-page-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-home-page-presentation.php new file mode 100644 index 00000000..958e423d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-home-page-presentation.php @@ -0,0 +1,63 @@ +model->canonical ) { + return $this->model->canonical; + } + + $permalink = $this->get_permalink(); + + if ( ! $permalink ) { + return ''; + } + + $current_page = $this->pagination->get_current_archive_page_number(); + if ( $current_page > 1 ) { + return $this->pagination->get_paginated_url( $permalink, $current_page ); + } + + return $permalink; + } + + /** + * Generates the meta description. + * + * @return string The meta description. + */ + public function generate_meta_description() { + if ( $this->model->description ) { + return $this->model->description; + } + + return $this->options->get( 'metadesc-home-wpseo' ); + } + + /** + * Generates the title. + * + * @return string The title. + */ + public function generate_title() { + if ( $this->model->title ) { + return $this->model->title; + } + + return $this->options->get_title_default( 'title-home-wpseo' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-post-type-archive-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-post-type-archive-presentation.php new file mode 100644 index 00000000..790db931 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-post-type-archive-presentation.php @@ -0,0 +1,72 @@ +get_permalink(); + if ( ! $permalink ) { + return ''; + } + + $current_page = $this->pagination->get_current_archive_page_number(); + if ( $current_page > 1 ) { + return $this->pagination->get_paginated_url( $permalink, $current_page ); + } + + return $permalink; + } + + /** + * Generates the robots value. + * + * @return array The robots value. + */ + public function generate_robots() { + $robots = $this->get_base_robots(); + + if ( $this->options->get( 'noindex-ptarchive-' . $this->model->object_sub_type, false ) ) { + $robots['index'] = 'noindex'; + } + + return $this->filter_robots( $robots ); + } + + /** + * Generates the title. + * + * @return string The title. + */ + public function generate_title() { + if ( $this->model->title ) { + return $this->model->title; + } + + $post_type = $this->model->object_sub_type; + $title = $this->options->get_title_default( 'title-ptarchive-' . $post_type ); + + return $title; + } + + /** + * Generates the source. + * + * @return array The source. + */ + public function generate_source() { + return [ 'post_type' => $this->model->object_sub_type ]; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-post-type-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-post-type-presentation.php new file mode 100644 index 00000000..714320a5 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-post-type-presentation.php @@ -0,0 +1,420 @@ +post_type = $post_type; + $this->date = $date; + $this->pagination = $pagination; + $this->post = $post; + } + + /** + * Generates the canonical. + * + * @return string The canonical. + */ + public function generate_canonical() { + if ( $this->model->canonical ) { + return $this->model->canonical; + } + + $permalink = $this->get_permalink(); + + // Fix paginated pages canonical, but only if the page is truly paginated. + $current_page = $this->pagination->get_current_post_page_number(); + if ( $current_page > 1 ) { + $number_of_pages = $this->model->number_of_pages; + if ( $number_of_pages && $current_page <= $number_of_pages ) { + $permalink = $this->get_paginated_url( $permalink, $current_page ); + } + } + + return $this->url->ensure_absolute_url( $permalink ); + } + + /** + * Generates the rel prev. + * + * @return string The rel prev value. + */ + public function generate_rel_prev() { + if ( $this->model->number_of_pages === null ) { + return ''; + } + + if ( $this->pagination->is_rel_adjacent_disabled() ) { + return ''; + } + + $current_page = \max( 1, $this->pagination->get_current_post_page_number() ); + + // Check if there is a previous page. + if ( $current_page < 2 ) { + return ''; + } + + // Check if the previous page is the first page. + if ( $current_page === 2 ) { + return $this->model->permalink; + } + + return $this->get_paginated_url( $this->model->permalink, ( $current_page - 1 ) ); + } + + /** + * Generates the rel next. + * + * @return string The rel prev next. + */ + public function generate_rel_next() { + if ( $this->model->number_of_pages === null ) { + return ''; + } + + if ( $this->pagination->is_rel_adjacent_disabled() ) { + return ''; + } + + $current_page = \max( 1, $this->pagination->get_current_post_page_number() ); + if ( $this->model->number_of_pages <= $current_page ) { + return ''; + } + + return $this->get_paginated_url( $this->model->permalink, ( $current_page + 1 ) ); + } + + /** + * Generates the open graph title. + * + * @return string The open graph title. + */ + public function generate_title() { + if ( $this->model->title ) { + return $this->model->title; + } + + // Get SEO title as entered in Search appearance. + $post_type = $this->model->object_sub_type; + $title = $this->options->get( 'title-' . $this->model->object_sub_type ); + if ( $title ) { + return $title; + } + + // Get installation default title. + return $this->options->get_title_default( 'title-' . $post_type ); + } + + /** + * Generates the meta description. + * + * @return string The meta description. + */ + public function generate_meta_description() { + if ( $this->model->description ) { + return $this->model->description; + } + + return $this->options->get( 'metadesc-' . $this->model->object_sub_type ); + } + + /** + * Generates the open graph description. + * + * @return string The open graph description. + */ + public function generate_open_graph_description() { + if ( $this->model->open_graph_description ) { + $open_graph_description = $this->model->open_graph_description; + } + + if ( empty( $open_graph_description ) ) { + // The helper applies a filter, but we don't have a default value at this stage so we pass an empty string. + $open_graph_description = $this->values_helper->get_open_graph_description( '', $this->model->object_type, $this->model->object_sub_type ); + } + + if ( empty( $open_graph_description ) ) { + $open_graph_description = $this->meta_description; + } + + if ( empty( $open_graph_description ) ) { + $open_graph_description = $this->post->get_the_excerpt( $this->model->object_id ); + $open_graph_description = $this->post->strip_shortcodes( $open_graph_description ); + } + + return $open_graph_description; + } + + /** + * Generates the open graph images. + * + * @return array The open graph images. + */ + public function generate_open_graph_images() { + if ( \post_password_required() ) { + return []; + } + + return parent::generate_open_graph_images(); + } + + /** + * Generates the Open Graph type. + * + * @return string The Open Graph type. + */ + public function generate_open_graph_type() { + return 'article'; + } + + /** + * Generates the open graph article author. + * + * @return string The open graph article author. + */ + public function generate_open_graph_article_author() { + if ( $this->model->object_sub_type !== 'post' ) { + return ''; + } + + $post = $this->source; + + $open_graph_article_author = $this->user->get_the_author_meta( 'facebook', $post->post_author ); + + if ( $open_graph_article_author ) { + return $open_graph_article_author; + } + + return ''; + } + + /** + * Generates the open graph article publisher. + * + * @return string The open graph article publisher. + */ + public function generate_open_graph_article_publisher() { + $open_graph_article_publisher = $this->context->open_graph_publisher; + + if ( $open_graph_article_publisher ) { + return $open_graph_article_publisher; + } + + return ''; + } + + /** + * Generates the open graph article published time. + * + * @return string The open graph article published time. + */ + public function generate_open_graph_article_published_time() { + if ( $this->model->object_sub_type !== 'post' ) { + /** + * Filter: 'wpseo_opengraph_show_publish_date' - Allow showing publication date for other post types. + * + * @param string $post_type The current URL's post type. + * + * @api bool Whether or not to show publish date. + */ + if ( ! \apply_filters( 'wpseo_opengraph_show_publish_date', false, $this->post->get_post_type( $this->source ) ) ) { + return ''; + } + } + + return $this->date->format( $this->source->post_date_gmt ); + } + + /** + * Generates the open graph article modified time. + * + * @return string The open graph article modified time. + */ + public function generate_open_graph_article_modified_time() { + if ( $this->source->post_modified_gmt !== $this->source->post_date_gmt ) { + return $this->date->format( $this->source->post_modified_gmt ); + } + + return ''; + } + + /** + * Generates the source. + * + * @return array The source. + */ + public function generate_source() { + return \get_post( $this->model->object_id ); + } + + /** + * Generates the robots value. + * + * @return array The robots value. + */ + public function generate_robots() { + $robots = $this->get_base_robots(); + $robots = \array_merge( + $robots, + [ + 'imageindex' => ( $this->model->is_robots_noimageindex === true ) ? 'noimageindex' : null, + 'archive' => ( $this->model->is_robots_noarchive === true ) ? 'noarchive' : null, + 'snippet' => ( $this->model->is_robots_nosnippet === true ) ? 'nosnippet' : null, + ] + ); + + // No snippet means max snippet can be omitted. + if ( $this->model->is_robots_nosnippet === true ) { + $robots['max-snippet'] = null; + } + + // No image index means max image preview can be omitted. + if ( $this->model->is_robots_noimageindex === true ) { + $robots['max-image-preview'] = null; + } + + // When the post specific index is not set, look to the post status and default of the post type. + if ( $this->model->is_robots_noindex === null ) { + $post_status_private = \get_post_status( $this->model->object_id ) === 'private'; + $post_type_noindex = ! $this->post_type->is_indexable( $this->model->object_sub_type ); + + if ( $post_status_private || $post_type_noindex ) { + $robots['index'] = 'noindex'; + } + } + + return $this->filter_robots( $robots ); + } + + /** + * Generates the Twitter description. + * + * @return string The Twitter description. + */ + public function generate_twitter_description() { + $twitter_description = parent::generate_twitter_description(); + + if ( $twitter_description ) { + return $twitter_description; + } + + if ( $this->open_graph_description && $this->context->open_graph_enabled === true ) { + return ''; + } + + return $this->post->get_the_excerpt( $this->model->object_id ); + } + + /** + * Generates the Twitter image. + * + * @return string The Twitter image. + */ + public function generate_twitter_image() { + if ( \post_password_required() ) { + return ''; + } + + return parent::generate_twitter_image(); + } + + /** + * Generates the Twitter creator. + * + * @return string The Twitter creator. + */ + public function generate_twitter_creator() { + if ( $this->model->object_sub_type !== 'post' ) { + return ''; + } + + $twitter_creator = \ltrim( \trim( \get_the_author_meta( 'twitter', $this->source->post_author ) ), '@' ); + + /** + * Filter: 'wpseo_twitter_creator_account' - Allow changing the Twitter account as output in the Twitter card by Yoast SEO. + * + * @api string $twitter The twitter account name string. + */ + $twitter_creator = \apply_filters( 'wpseo_twitter_creator_account', $twitter_creator ); + + if ( \is_string( $twitter_creator ) && $twitter_creator !== '' ) { + return '@' . $twitter_creator; + } + + $site_twitter = $this->options->get( 'twitter_site', '' ); + if ( \is_string( $site_twitter ) && $site_twitter !== '' ) { + return '@' . $site_twitter; + } + + return ''; + } + + /** + * Wraps the get_paginated_url pagination helper method. + * + * @codeCoverageIgnore A wrapper method. + * + * @param string $url The un-paginated URL of the current archive. + * @param string $page The page number to add on to $url for the $link tag. + * + * @return string The paginated URL. + */ + protected function get_paginated_url( $url, $page ) { + return $this->pagination->get_paginated_url( $url, $page, false ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-presentation.php new file mode 100644 index 00000000..d19c532d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-presentation.php @@ -0,0 +1,785 @@ +schema_generator = $schema_generator; + $this->open_graph_locale_generator = $open_graph_locale_generator; + $this->open_graph_image_generator = $open_graph_image_generator; + $this->twitter_image_generator = $twitter_image_generator; + $this->breadcrumbs_generator = $breadcrumbs_generator; + } + + /** + * Used by dependency injection container to inject the helpers. + * + * @required + * + * @param Image_Helper $image The image helper. + * @param Options_Helper $options The options helper. + * @param Current_Page_Helper $current_page The current page helper. + * @param Url_Helper $url The URL helper. + * @param User_Helper $user The user helper. + * @param Indexable_Helper $indexable The indexable helper. + * @param Permalink_Helper $permalink The permalink helper. + * @param Values_Helper $values The values helper. + */ + public function set_helpers( + Image_Helper $image, + Options_Helper $options, + Current_Page_Helper $current_page, + Url_Helper $url, + User_Helper $user, + Indexable_Helper $indexable, + Permalink_Helper $permalink, + Values_Helper $values + ) { + $this->image = $image; + $this->options = $options; + $this->current_page = $current_page; + $this->url = $url; + $this->user = $user; + $this->indexable_helper = $indexable; + $this->permalink_helper = $permalink; + $this->values_helper = $values; + } + + /** + * Gets the permalink from the indexable or generates it if dynamic permalinks are enabled. + * + * @return string The permalink. + */ + public function get_permalink() { + if ( $this->indexable_helper->dynamic_permalinks_enabled() ) { + return $this->permalink_helper->get_permalink_for_indexable( $this->model ); + } + + return $this->model->permalink; + } + + /** + * Generates the title. + * + * @return string The title. + */ + public function generate_title() { + if ( $this->model->title ) { + return $this->model->title; + } + + return ''; + } + + /** + * Generates the meta description. + * + * @return string The meta description. + */ + public function generate_meta_description() { + if ( $this->model->description ) { + return $this->model->description; + } + + return ''; + } + + /** + * Generates the robots value. + * + * @return array The robots value. + */ + public function generate_robots() { + $robots = $this->get_base_robots(); + + return $this->filter_robots( $robots ); + } + + /** + * Gets the base robots value. + * + * @return array The base robots value. + */ + protected function get_base_robots() { + return [ + 'index' => ( $this->model->is_robots_noindex === true ) ? 'noindex' : 'index', + 'follow' => ( $this->model->is_robots_nofollow === true ) ? 'nofollow' : 'follow', + 'max-snippet' => 'max-snippet:-1', + 'max-image-preview' => 'max-image-preview:large', + 'max-video-preview' => 'max-video-preview:-1', + ]; + } + + /** + * Run the robots output content through the `wpseo_robots` filter. + * + * @param array $robots The meta robots values to filter. + * + * @return array The filtered meta robots values. + */ + protected function filter_robots( $robots ) { + // Remove values that are only listened to when indexing. + if ( $robots['index'] === 'noindex' ) { + $robots['imageindex'] = null; + $robots['archive'] = null; + $robots['snippet'] = null; + $robots['max-snippet'] = null; + $robots['max-image-preview'] = null; + $robots['max-video-preview'] = null; + } + + $robots_string = \implode( ', ', \array_filter( $robots ) ); + + /** + * Filter: 'wpseo_robots' - Allows filtering of the meta robots output of Yoast SEO. + * + * @api string $robots The meta robots directives to be echoed. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + */ + $robots_filtered = \apply_filters( 'wpseo_robots', $robots_string, $this ); + + // Convert the robots string back to an array. + if ( \is_string( $robots_filtered ) ) { + $robots_values = \explode( ', ', $robots_filtered ); + $robots_new = []; + + foreach ( $robots_values as $value ) { + $key = $value; + + // Change `noindex` to `index. + if ( \strpos( $key, 'no' ) === 0 ) { + $key = \substr( $value, 2 ); + } + // Change `max-snippet:-1` to `max-snippet`. + $colon_position = \strpos( $key, ':' ); + if ( $colon_position !== false ) { + $key = \substr( $value, 0, $colon_position ); + } + + $robots_new[ $key ] = $value; + } + + $robots = $robots_new; + } + + if ( ! $robots_filtered ) { + return []; + } + + /** + * Filter: 'wpseo_robots_array' - Allows filtering of the meta robots output array of Yoast SEO. + * + * @api array $robots The meta robots directives to be used. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + */ + return \apply_filters( 'wpseo_robots_array', \array_filter( $robots ), $this ); + } + + /** + * Generates the robots value for the googlebot tag. + * + * @deprecated 14.9 Values merged into the robots meta tag. + * @codeCoverageIgnore + * + * @return array The robots value with opt-in snippets. + */ + public function generate_googlebot() { + \_deprecated_function( __METHOD__, 'WPSEO 14.9' ); + + return []; + } + + /** + * Generates the value for the bingbot tag. + * + * @deprecated 14.9 Values merged into the robots meta tag. + * @codeCoverageIgnore + * + * @return array The robots value with opt-in snippets. + */ + public function generate_bingbot() { + \_deprecated_function( __METHOD__, 'WPSEO 14.9' ); + + return []; + } + + /** + * Generates the canonical. + * + * @return string The canonical. + */ + public function generate_canonical() { + if ( $this->model->canonical ) { + return $this->model->canonical; + } + + $permalink = $this->get_permalink(); + if ( $permalink ) { + return $permalink; + } + + return ''; + } + + /** + * Generates the rel prev. + * + * @return string The rel prev value. + */ + public function generate_rel_prev() { + return ''; + } + + /** + * Generates the rel next. + * + * @return string The rel prev next. + */ + public function generate_rel_next() { + return ''; + } + + /** + * Generates the Open Graph type. + * + * @return string The Open Graph type. + */ + public function generate_open_graph_type() { + return 'website'; + } + + /** + * Generates the open graph title. + * + * @return string The open graph title. + */ + public function generate_open_graph_title() { + if ( $this->model->open_graph_title ) { + $open_graph_title = $this->model->open_graph_title; + } + + if ( empty( $open_graph_title ) ) { + // The helper applies a filter, but we don't have a default value at this stage so we pass an empty string. + $open_graph_title = $this->values_helper->get_open_graph_title( '', $this->model->object_type, $this->model->object_sub_type ); + } + + if ( empty( $open_graph_title ) ) { + $open_graph_title = $this->title; + } + + return $open_graph_title; + } + + /** + * Generates the open graph description. + * + * @return string The open graph description. + */ + public function generate_open_graph_description() { + if ( $this->model->open_graph_description ) { + $open_graph_description = $this->model->open_graph_description; + } + + if ( empty( $open_graph_description ) ) { + // The helper applies a filter, but we don't have a default value at this stage so we pass an empty string. + $open_graph_description = $this->values_helper->get_open_graph_description( '', $this->model->object_type, $this->model->object_sub_type ); + } + + if ( empty( $open_graph_description ) ) { + $open_graph_description = $this->meta_description; + } + + return $open_graph_description; + } + + /** + * Generates the open graph images. + * + * @return array The open graph images. + */ + public function generate_open_graph_images() { + if ( $this->context->open_graph_enabled === false ) { + return []; + } + + return $this->open_graph_image_generator->generate( $this->context ); + } + + /** + * Generates the open graph image ID. + * + * @return string The open graph image ID. + */ + public function generate_open_graph_image_id() { + if ( $this->model->open_graph_image_id ) { + return $this->model->open_graph_image_id; + } + + return $this->values_helper->get_open_graph_image_id( 0, $this->model->object_type, $this->model->object_sub_type ); + } + + /** + * Generates the open graph image URL. + * + * @return string The open graph image URL. + */ + public function generate_open_graph_image() { + if ( $this->model->open_graph_image ) { + return $this->model->open_graph_image; + } + + return $this->values_helper->get_open_graph_image( '', $this->model->object_type, $this->model->object_sub_type ); + } + + /** + * Generates the open graph url. + * + * @return string The open graph url. + */ + public function generate_open_graph_url() { + if ( $this->model->canonical ) { + return $this->model->canonical; + } + + return $this->get_permalink(); + } + + /** + * Generates the open graph article publisher. + * + * @return string The open graph article publisher. + */ + public function generate_open_graph_article_publisher() { + return ''; + } + + /** + * Generates the open graph article author. + * + * @return string The open graph article author. + */ + public function generate_open_graph_article_author() { + return ''; + } + + /** + * Generates the open graph article published time. + * + * @return string The open graph article published time. + */ + public function generate_open_graph_article_published_time() { + return ''; + } + + /** + * Generates the open graph article modified time. + * + * @return string The open graph article modified time. + */ + public function generate_open_graph_article_modified_time() { + return ''; + } + + /** + * Generates the open graph locale. + * + * @return string The open graph locale. + */ + public function generate_open_graph_locale() { + return $this->open_graph_locale_generator->generate( $this->context ); + } + + /** + * Generates the open graph Facebook app ID. + * + * @deprecated 15.5 + * @codeCoverageIgnore + * + * @return string The open graph Facebook app ID. + */ + public function generate_open_graph_fb_app_id() { + return $this->options->get( 'fbadminapp', '' ); + } + + /** + * Generates the open graph site name. + * + * @return string The open graph site name. + */ + public function generate_open_graph_site_name() { + return $this->context->wordpress_site_name; + } + + /** + * Generates the Twitter card type. + * + * @return string The Twitter card type. + */ + public function generate_twitter_card() { + return $this->context->twitter_card; + } + + /** + * Generates the Twitter title. + * + * @return string The Twitter title. + */ + public function generate_twitter_title() { + if ( $this->model->twitter_title ) { + return $this->model->twitter_title; + } + + if ( $this->context->open_graph_enabled === true ) { + $social_template_title = $this->values_helper->get_open_graph_title( '', $this->model->object_type, $this->model->object_sub_type ); + $open_graph_title = $this->open_graph_title; + + // If the helper returns a value and it's different from the OG value in the indexable, + // output it in a twitter: tag. + if ( ! empty( $social_template_title ) && $social_template_title !== $open_graph_title ) { + return $social_template_title; + } + + // If the OG title is set, let og: tag take care of this. + if ( ! empty( $open_graph_title ) ) { + return ''; + } + } + + if ( $this->title ) { + return $this->title; + } + + return ''; + } + + /** + * Generates the Twitter description. + * + * @return string The Twitter description. + */ + public function generate_twitter_description() { + if ( $this->model->twitter_description ) { + return $this->model->twitter_description; + } + + if ( $this->context->open_graph_enabled === true ) { + $social_template_description = $this->values_helper->get_open_graph_description( '', $this->model->object_type, $this->model->object_sub_type ); + $open_graph_description = $this->open_graph_description; + + // If the helper returns a value and it's different from the OG value in the indexable, + // output it in a twitter: tag. + if ( ! empty( $social_template_description ) && $social_template_description !== $open_graph_description ) { + return $social_template_description; + } + + // If the OG description is set, let og: tag take care of this. + if ( ! empty( $open_graph_description ) ) { + return ''; + } + } + + if ( $this->meta_description ) { + return $this->meta_description; + } + + return ''; + } + + /** + * Generates the Twitter image. + * + * @return string The Twitter image. + */ + public function generate_twitter_image() { + $images = $this->twitter_image_generator->generate( $this->context ); + $image = \reset( $images ); + + // Use a user-defined Twitter image, if present. + if ( $image && $this->context->indexable->twitter_image_source === 'set-by-user' ) { + return $image['url']; + } + + // Let the Open Graph tags, if enabled, handle the rest of the fallback hierarchy. + if ( $this->context->open_graph_enabled === true && $this->open_graph_images ) { + return ''; + } + + // Set a Twitter tag with the featured image, or a prominent image from the content, if present. + if ( $image ) { + return $image['url']; + } + + return ''; + } + + /** + * Generates the Twitter creator. + * + * @return string The Twitter creator. + */ + public function generate_twitter_creator() { + return ''; + } + + /** + * Generates the Twitter site. + * + * @return string The Twitter site. + */ + public function generate_twitter_site() { + switch ( $this->context->site_represents ) { + case 'person': + $twitter = $this->user->get_the_author_meta( 'twitter', (int) $this->context->site_user_id ); + if ( empty( $twitter ) ) { + $twitter = $this->options->get( 'twitter_site' ); + } + break; + case 'company': + default: + $twitter = $this->options->get( 'twitter_site' ); + break; + } + + return $twitter; + } + + /** + * Generates the source. + * + * @return array The source. + */ + public function generate_source() { + return []; + } + + /** + * Generates the schema for the page. + * + * @return array The Schema object. + * + * @codeCoverageIgnore Wrapper method. + */ + public function generate_schema() { + return $this->schema_generator->generate( $this->context ); + } + + /** + * Generates the breadcrumbs for the page. + * + * @return array The breadcrumbs. + * + * @codeCoverageIgnore Wrapper method. + */ + public function generate_breadcrumbs() { + return $this->breadcrumbs_generator->generate( $this->context ); + } + + /** + * Generates the estimated reading time. + * + * @return int|null The estimated reading time. + * + * @codeCoverageIgnore Wrapper method. + */ + public function generate_estimated_reading_time_minutes() { + if ( $this->model->estimated_reading_time_minutes !== null ) { + return $this->model->estimated_reading_time_minutes; + } + + if ( $this->context->post === null ) { + return null; + } + + // 200 is the approximate estimated words per minute across languages. + $words_per_minute = 200; + $words = \str_word_count( \wp_strip_all_tags( $this->context->post->post_content ) ); + return (int) \round( $words / $words_per_minute ); + } + + /** + * Strips all nested dependencies from the debug info. + * + * @return array + */ + public function __debugInfo() { + return [ + 'model' => $this->model, + 'context' => $this->context, + ]; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-search-result-page-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-search-result-page-presentation.php new file mode 100644 index 00000000..d570ab9e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-search-result-page-presentation.php @@ -0,0 +1,71 @@ +get_base_robots(); + + $robots['index'] = 'noindex'; + + return $this->filter_robots( $robots ); + } + + /** + * Generates the title. + * + * @return string The title. + */ + public function generate_title() { + if ( $this->model->title ) { + return $this->model->title; + } + + return $this->options->get_title_default( 'title-search-wpseo' ); + } + + /** + * Generates the Twitter title. + * + * @return string The Twitter title. + */ + public function generate_twitter_title() { + return $this->title; + } + + /** + * Generates the Open Graph URL. + * + * @return string The Open Graph URL. + */ + public function generate_open_graph_url() { + $search_query = \get_search_query(); + + // Regex catches case when /search/page/N without search term is itself mistaken for search term. + if ( ! empty( $search_query ) && ! \preg_match( '|^page/\d+$|', $search_query ) ) { + return \get_search_link(); + } + + return ''; + } + + /** + * Generates the Open Graph type. + * + * @return string The Open Graph type. + */ + public function generate_open_graph_type() { + return 'article'; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-static-home-page-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-static-home-page-presentation.php new file mode 100644 index 00000000..45340bd7 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-static-home-page-presentation.php @@ -0,0 +1,32 @@ +pagination->get_paginated_url( $url, $page ); + } + + /** + * Generates the Open Graph type. + * + * @return string The Open Graph type. + */ + public function generate_open_graph_type() { + return 'website'; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-static-posts-page-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-static-posts-page-presentation.php new file mode 100644 index 00000000..9cbfa339 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-static-posts-page-presentation.php @@ -0,0 +1,51 @@ +model->canonical ) { + return $this->model->canonical; + } + + $current_page = $this->pagination->get_current_archive_page_number(); + $permalink = $this->get_permalink(); + + if ( $current_page > 1 ) { + return $this->pagination->get_paginated_url( $permalink, $current_page ); + } + + return $permalink; + } + + /** + * Generates the Open Graph URL. + * + * @return string The Open Graph URL. + */ + public function generate_open_graph_url() { + return $this->get_permalink(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presentations/indexable-term-archive-presentation.php b/wp-content/plugins/wordpress-seo/src/presentations/indexable-term-archive-presentation.php new file mode 100644 index 00000000..65f2d73f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presentations/indexable-term-archive-presentation.php @@ -0,0 +1,217 @@ +wp_query_wrapper = $wp_query_wrapper; + $this->taxonomy = $taxonomy; + } + + /** + * Generates the canonical. + * + * @return string The canonical. + */ + public function generate_canonical() { + if ( $this->is_multiple_terms_query() ) { + return ''; + } + + if ( $this->model->canonical ) { + return $this->model->canonical; + } + + $permalink = $this->get_permalink(); + if ( ! $permalink ) { + return ''; + } + + $current_page = $this->pagination->get_current_archive_page_number(); + if ( $current_page > 1 ) { + return $this->pagination->get_paginated_url( $permalink, $current_page ); + } + + return $permalink; + } + + /** + * Generates the meta description. + * + * @return string The meta description. + */ + public function generate_meta_description() { + if ( $this->model->description ) { + return $this->model->description; + } + + return $this->options->get( 'metadesc-tax-' . $this->model->object_sub_type ); + } + + /** + * Generates the source. + * + * @return array The source. + */ + public function generate_source() { + return \get_term( $this->model->object_id, $this->model->object_sub_type ); + } + + /** + * Generates the Open Graph description. + * + * @return string The Open Graph description. + */ + public function generate_open_graph_description() { + $open_graph_description = parent::generate_open_graph_description(); + if ( $open_graph_description ) { + return $open_graph_description; + } + + return $this->taxonomy->get_term_description( $this->model->object_id ); + } + + /** + * Generates the Twitter description. + * + * @return string The Twitter description. + */ + public function generate_twitter_description() { + $twitter_description = parent::generate_twitter_description(); + if ( $twitter_description ) { + return $twitter_description; + } + + if ( $this->open_graph_description && $this->context->open_graph_enabled === true ) { + return ''; + } + + return $this->taxonomy->get_term_description( $this->model->object_id ); + } + + /** + * Generates the robots value. + * + * @return array The robots value. + */ + public function generate_robots() { + $robots = $this->get_base_robots(); + + /** + * If its a multiple terms archive page return a noindex. + */ + if ( $this->current_page->is_multiple_terms_page() ) { + $robots['index'] = 'noindex'; + + return $this->filter_robots( $robots ); + } + + /** + * First we get the no index option for this taxonomy, because it can be overwritten the indexable value for + * this specific term. + */ + if ( ! $this->taxonomy->is_indexable( $this->source->taxonomy ) ) { + $robots['index'] = 'noindex'; + } + + /** + * Overwrite the index directive when there is a term specific directive set. + */ + if ( $this->model->is_robots_noindex !== null ) { + $robots['index'] = ( $this->model->is_robots_noindex ) ? 'noindex' : 'index'; + } + + return $this->filter_robots( $robots ); + } + + /** + * Generates the title. + * + * @return string The title. + */ + public function generate_title() { + if ( $this->model->title ) { + return $this->model->title; + } + + // Get the SEO title as entered in Search Appearance. + $title = $this->options->get( 'title-tax-' . $this->source->taxonomy ); + if ( $title ) { + return $title; + } + + // Get the installation default title. + $title = $this->options->get_title_default( 'title-tax-' . $this->source->taxonomy ); + + return $title; + } + + /** + * Generates the Open Graph type. + * + * @return string The Open Graph type. + */ + public function generate_open_graph_type() { + return 'article'; + } + + /** + * Checks if term archive query is for multiple terms (/term-1,term-2/ or /term-1+term-2/). + * + * @return bool Whether the query contains multiple terms. + */ + protected function is_multiple_terms_query() { + $query = $this->wp_query_wrapper->get_query(); + + if ( ! isset( $query->tax_query ) ) { + return false; + } + + $queried_terms = $query->tax_query->queried_terms; + + if ( empty( $queried_terms[ $this->source->taxonomy ]['terms'] ) ) { + return false; + } + + return \count( $queried_terms[ $this->source->taxonomy ]['terms'] ) > 1; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/abstract-indexable-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/abstract-indexable-presenter.php new file mode 100644 index 00000000..24897ac9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/abstract-indexable-presenter.php @@ -0,0 +1,80 @@ +key === 'NO KEY PROVIDED' ) { + return null; + } + return \str_replace( [ ':', ' ', '-' ], '_', $this->key ); + } + + /** + * Returns the metafield's property key. + * + * @return string The property key. + */ + public function get_key() { + return $this->key; + } + + /** + * Replace replacement variables in a string. + * + * @param string $string The string. + * + * @return string The string with replacement variables replaced. + */ + protected function replace_vars( $string ) { + return $this->replace_vars->replace( $string, $this->presentation->source ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/abstract-indexable-tag-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/abstract-indexable-tag-presenter.php new file mode 100644 index 00000000..5308d30a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/abstract-indexable-tag-presenter.php @@ -0,0 +1,68 @@ +'; + const META_NAME_CONTENT = ''; + const LINK_REL_HREF = ''; + const DEFAULT_TAG_FORMAT = self::META_NAME_CONTENT; + + /** + * The tag format including placeholders. + * + * @var string + */ + protected $tag_format = self::DEFAULT_TAG_FORMAT; + + /** + * The method of escaping to use. + * + * @var string + */ + protected $escaping = 'attribute'; + + /** + * Returns a tag in the head. + * + * @return string The tag. + */ + public function present() { + $value = $this->get(); + + if ( ! \is_string( $value ) || $value === '' ) { + return ''; + } + + /** + * There may be some classes that are derived from this class that do not use the $key property + * in their $tag_format string. In that case the key property will simply not be used. + */ + return \sprintf( $this->tag_format, $this->escape_value( $value ), $this->key ); + } + + /** + * Escaped the output. + * + * @param string $value The desired method of escaping; 'html', 'url' or 'attribute'. + * + * @return string The escaped value. + */ + protected function escape_value( $value ) { + switch ( $this->escaping ) { + case 'html': + return \esc_html( $value ); + case 'url': + return \esc_url( $value ); + case 'attribute': + default: + return \esc_attr( $value ); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/abstract-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/abstract-presenter.php new file mode 100644 index 00000000..05ea34e8 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/abstract-presenter.php @@ -0,0 +1,25 @@ +present(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/alert-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/alert-presenter.php new file mode 100644 index 00000000..c9f0670d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/alert-presenter.php @@ -0,0 +1,72 @@ +content = $content; + $this->type = $type; + + if ( ! $this->asset_manager ) { + $this->asset_manager = new WPSEO_Admin_Asset_Manager(); + } + + $this->asset_manager->enqueue_style( 'alert' ); + } + + /** + * Presents the Alert. + * + * @return string The styled Alert. + */ + public function present() { + $icon_file = 'images/alert-' . $this->type . '-icon.svg'; + + $out = '
    '; + $out .= ''; + $out .= ''; + $out .= ''; + + $out .= '' . $this->content . ''; + $out .= '
    '; + + return $out; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/auto-update-notification-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/auto-update-notification-presenter.php new file mode 100644 index 00000000..0ec75a74 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/auto-update-notification-presenter.php @@ -0,0 +1,53 @@ +'; + $notification_text .= $this->get_message(); + $notification_text .= '

    '; + + return $notification_text; + } + + /** + * Returns the message to show. + * + * @return string The message. + */ + protected function get_message() { + if ( \is_multisite() ) { + return \sprintf( + /* Translators: %1$s expands to 'Yoast SEO', %2$s to an opening anchor tag for a link leading to the Plugins page, and %3$s to a closing anchor tag. */ + \esc_html__( + 'We see that you enabled automatic updates for WordPress. We recommend that you do this for %1$s as well. This way we can guarantee that WordPress and %1$s will continue to run smoothly together. Please contact your network admin to enable auto-updates for %1$s.', + 'wordpress-seo' + ), + 'Yoast SEO' + ); + } + + return \sprintf( + /* Translators: %1$s expands to 'Yoast SEO', %2$s to an opening anchor tag for a link leading to the Plugins page, and %3$s to a closing anchor tag. */ + \esc_html__( + 'We see that you enabled automatic updates for WordPress. We recommend that you do this for %1$s as well. This way we can guarantee that WordPress and %1$s will continue to run smoothly together. %2$sGo to your plugins overview to enable auto-updates for %1$s.%3$s', + 'wordpress-seo' + ), + 'Yoast SEO', + '', + '' + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/badge-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/badge-presenter.php new file mode 100644 index 00000000..217eb997 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/badge-presenter.php @@ -0,0 +1,104 @@ +id = $id; + $this->link = $link; + $this->group = $group; + + if ( ! $badge_group_names instanceof Badge_Group_Names ) { + $badge_group_names = new Badge_Group_Names(); + } + $this->badge_group_names = $badge_group_names; + } + + /** + * Presents the New Badge. If a link has been passed, the badge is presented with the link. + * Otherwise a static badge is presented. + * + * @return string The styled New Badge. + */ + public function present() { + if ( ! $this->is_group_still_new() ) { + return ''; + } + + if ( $this->link !== '' ) { + return \sprintf( + '%3$s', + \esc_attr( $this->id ), + \esc_url( $this->link ), + \esc_html__( 'New', 'wordpress-seo' ) + ); + } + + return \sprintf( + '%2$s', + \esc_attr( $this->id ), + \esc_html__( 'New', 'wordpress-seo' ) + ); + } + + /** + * Check whether the new badge should be shown according to the group it is in. + * + * @return bool True if still new. + */ + public function is_group_still_new() { + // If there's no group configured, the new badge is always active. + if ( ! $this->group ) { + return true; + } + + return $this->badge_group_names->is_still_eligible_for_new_badge( $this->group ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/help-link-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/help-link-presenter.php new file mode 100644 index 00000000..72c5a32f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/help-link-presenter.php @@ -0,0 +1,85 @@ +link = $link; + $this->link_text = $link_text; + $this->opens_in_new_browser_tab = $opens_in_new_browser_tab; + + if ( ! $this->asset_manager ) { + $this->asset_manager = new WPSEO_Admin_Asset_Manager(); + } + + $this->asset_manager->enqueue_style( 'admin-global' ); + } + + /** + * Presents the Help link. + * + * @return string The styled Help link. + */ + public function present() { + if ( $this->link === '' || $this->link_text === '' ) { + return; + } + + $target_blank_attribute = ''; + $new_tab_message = ''; + + if ( $this->opens_in_new_browser_tab ) { + $target_blank_attribute = ' target="_blank"'; + $new_tab_message = ' ' . \__( '(Opens in a new browser tab)', 'wordpress-seo' ); + } + + return \sprintf( + '%3$s', + \esc_url( $this->link ), + $target_blank_attribute, + \esc_html( $this->link_text . $new_tab_message ) + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-error-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-error-presenter.php new file mode 100644 index 00000000..a59333cf --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-error-presenter.php @@ -0,0 +1,127 @@ +short_link_helper = $short_link_helper; + $this->product_helper = $product_helper; + $this->addon_manager = $addon_manager; + } + + /** + * Generates the first paragraph of the error message to show when indexing failed. + * + * The contents of the paragraph varies based on whether WordPress SEO Premium has a valid, activated subscription or not. + * + * @param bool $is_premium Whether WordPress SEO Premium is currently active. + * @param bool $has_valid_premium_subscription Whether WordPress SEO Premium currently has a valid subscription. + * + * @return string + */ + protected function generate_first_paragraph( $is_premium, $has_valid_premium_subscription ) { + $message = __( + 'Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please click the button again to re-start the process. ', + 'wordpress-seo' + ); + + if ( $is_premium ) { + if ( $has_valid_premium_subscription ) { + $message .= __( 'If the problem persists, please contact support.', 'wordpress-seo' ); + } + else { + $message = sprintf( + // translators: %1$s expands to an opening anchor tag for a link leading to the Premium installation page, %2$s expands to a closing anchor tag. + __( + 'Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please make sure to activate your subscription in MyYoast by completing %1$sthese steps%2$s.', + 'wordpress-seo' + ), + '', + '' + ); + } + } + + return $message; + } + + /** + * Generates the second paragraph of the error message to show when indexing failed. + * + * The error message varies based on whether WordPress SEO Premium has a valid, activated subscription or not. + * + * @param bool $is_premium Whether WordPress SEO Premium is currently active. + * @param bool $has_valid_premium_subscription Whether WordPress SEO Premium currently has a valid subscription. + * + * @return string The second paragraph of the error message. + */ + protected function generate_second_paragraph( $is_premium, $has_valid_premium_subscription ) { + return sprintf( + // translators: %1$s expands to an opening anchor tag for a link leading to the Premium installation page, %2$s expands to a closing anchor tag. + __( + 'Below are the technical details for the error. See %1$sthis page%2$s for a more detailed explanation.', + 'wordpress-seo' + ), + '', + '' + ); + } + + /** + * Presents the error message to show if SEO optimization failed. + * + * The error message varies based on whether WordPress SEO Premium has a valid, activated subscription or not. + * + * @return string The error message to show. + */ + public function present() { + $is_premium = $this->product_helper->is_premium(); + $has_valid_premium_subscription = $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG ); + + $output = '

    ' . $this->generate_first_paragraph( $is_premium, $has_valid_premium_subscription ) . '

    '; + $output .= '

    ' . $this->generate_second_paragraph( $is_premium, $has_valid_premium_subscription ) . '

    '; + + return $output; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-failed-notification-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-failed-notification-presenter.php new file mode 100644 index 00000000..4a707490 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-failed-notification-presenter.php @@ -0,0 +1,99 @@ +class_addon_manager = $class_addon_manager; + $this->short_link_helper = $short_link_helper; + $this->product_helper = $product_helper; + } + + /** + * Returns the notification as an HTML string. + * + * @return string The notification in an HTML string representation. + */ + public function present() { + $notification_text = \sprintf( + /* Translators: %1$s expands to an opening anchor tag for a link leading to the Yoast SEO tools page, %2$s expands to a closing anchor tag. */ + \esc_html__( + 'Something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please %1$sre-start the process%2$s.', + 'wordpress-seo' + ), + '', + '' + ); + + if ( $this->product_helper->is_premium() ) { + if ( $this->has_valid_premium_subscription() ) { + // Add a support message for premium customers. + $notification_text .= ' '; + $notification_text .= \esc_html__( 'If the problem persists, please contact support.', 'wordpress-seo' ); + } + else { + // premium plugin with inactive addon; overwrite the entire error message. + $notification_text = \sprintf( + /* Translators: %1$s expands to an opening anchor tag for a link leading to the Premium installation page, %2$s expands to a closing anchor tag. */ + \esc_html__( + 'Oops, something has gone wrong and we couldn\'t complete the optimization of your SEO data. Please make sure to activate your subscription in MyYoast by completing %1$sthese steps%2$s.', + 'wordpress-seo' + ), + '', + '' + ); + } + } + + return '

    ' . $notification_text . '

    '; + } + + /** + * Determines if the site has a valid Premium subscription. + * + * @return bool + */ + protected function has_valid_premium_subscription() { + return $this->class_addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-list-item-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-list-item-presenter.php new file mode 100644 index 00000000..09a0458e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-list-item-presenter.php @@ -0,0 +1,50 @@ +short_link_helper = $short_link_helper; + } + + /** + * Presents the list item for the tools menu. + * + * @return string The list item HTML. + */ + public function present() { + $output = \sprintf( '
  • %s
    ', \esc_html__( 'Optimize SEO Data', 'wordpress-seo' ) ); + $output .= \sprintf( + '%1$s %3$s', + \esc_html__( 'You can speed up your site and get insight into your internal linking structure by letting us perform a few optimizations to the way SEO data is stored. If you have a lot of content it might take a while, but trust us, it\'s worth it.', 'wordpress-seo' ), + \esc_url( $this->short_link_helper->get( 'https://yoa.st/3-z' ) ), + \esc_html__( 'Learn more about the benefits of optimized SEO data.', 'wordpress-seo' ) + ); + + $output .= '
    '; + $output .= '
  • '; + + return $output; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-notification-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-notification-presenter.php new file mode 100644 index 00000000..6bb24ef0 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/indexing-notification-presenter.php @@ -0,0 +1,138 @@ +short_link_helper = $short_link_helper; + $this->total_unindexed = $total_unindexed; + $this->reason = $reason; + } + + /** + * Returns the notification as an HTML string. + * + * @return string The HTML string representation of the notification. + */ + public function present() { + $notification_text = '

    ' . $this->get_message( $this->reason ) . '

    '; + $notification_text .= '

    ' . $this->get_time_estimate( $this->total_unindexed ) . '

    '; + $notification_text .= ''; + $notification_text .= \esc_html__( 'Start SEO data optimization', 'wordpress-seo' ); + $notification_text .= ''; + + return $notification_text; + } + + /** + * Determines the message to show in the indexing notification. + * + * @param string $reason The reason identifier. + * + * @return string The message to show in the notification. + */ + protected function get_message( $reason ) { + switch ( $reason ) { + case Indexing_Reasons::REASON_PERMALINK_SETTINGS: + $text = \esc_html__( 'Because of a change in your permalink structure, some of your SEO data needs to be reprocessed.', 'wordpress-seo' ); + break; + case Indexing_Reasons::REASON_HOME_URL_OPTION: + $text = \esc_html__( 'Because of a change in your home URL setting, some of your SEO data needs to be reprocessed.', 'wordpress-seo' ); + break; + case Indexing_Reasons::REASON_CATEGORY_BASE_PREFIX: + $text = \esc_html__( 'Because of a change in your category base setting, some of your SEO data needs to be reprocessed.', 'wordpress-seo' ); + break; + case Indexing_Reasons::REASON_TAG_BASE_PREFIX: + $text = \esc_html__( 'Because of a change in your tag base setting, some of your SEO data needs to be reprocessed.', 'wordpress-seo' ); + break; + default: + $text = \esc_html__( 'You can speed up your site and get insight into your internal linking structure by letting us perform a few optimizations to the way SEO data is stored. ', 'wordpress-seo' ); + } + + /** + * Filter: 'wpseo_indexables_indexation_alert' - Allow developers to filter the reason of the indexation + * + * @param string $text The text to show as reason. + * @param string $reason The reason value. + */ + return (string) \apply_filters( 'wpseo_indexables_indexation_alert', $text, $reason ); + } + + /** + * Creates a time estimate based on the total number on unindexed objects. + * + * @param int $total_unindexed The total number of unindexed objects. + * + * @return string The time estimate as a HTML string. + */ + protected function get_time_estimate( $total_unindexed ) { + if ( $total_unindexed < 400 ) { + return \esc_html__( 'We estimate this will take less than a minute.', 'wordpress-seo' ); + } + + if ( $total_unindexed < 2500 ) { + return \esc_html__( 'We estimate this will take a couple of minutes.', 'wordpress-seo' ); + } + + $estimate = \esc_html__( 'We estimate this could take a long time, due to the size of your site. As an alternative to waiting, you could:', 'wordpress-seo' ); + $estimate .= '
      '; + $estimate .= '
    • '; + $estimate .= \sprintf( + /* translators: 1: Expands to Yoast SEO */ + \esc_html__( 'Wait for a week or so, until %1$s automatically processes most of your content in the background.', 'wordpress-seo' ), + 'Yoast SEO' + ); + $estimate .= '
    • '; + $estimate .= '
    • '; + $estimate .= \sprintf( + /* translators: 1: Link to article about indexation command, 2: Anchor closing tag, 3: Link to WP CLI. */ + \esc_html__( '%1$sRun the indexation process on your server%2$s using %3$sWP CLI%2$s.', 'wordpress-seo' ), + '', + '', + '' + ); + + $estimate .= '
    • '; + $estimate .= '
    '; + + return $estimate; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/light-switch-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/light-switch-presenter.php new file mode 100644 index 00000000..b2af3b7d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/light-switch-presenter.php @@ -0,0 +1,159 @@ +var = $var; + $this->label = $label; + $this->buttons = $buttons; + $this->name = $name; + $this->value = $value; + $this->reverse = $reverse; + $this->help = $help; + $this->strong = $strong; + $this->disabled_attribute = $disabled_attribute; + } + + /** + * Presents the light switch toggle. + * + * @return string The light switch's HTML. + */ + public function present() { + if ( empty( $this->buttons ) ) { + $this->buttons = [ \__( 'Disabled', 'wordpress-seo' ), \__( 'Enabled', 'wordpress-seo' ) ]; + } + + list( $off_button, $on_button ) = $this->buttons; + + $class = 'switch-light switch-candy switch-yoast-seo'; + + if ( $this->reverse ) { + $class .= ' switch-yoast-seo-reverse'; + } + + $help_class = ! empty( $this->help ) ? ' switch-container__has-help' : ''; + $strong_class = ( $this->strong ) ? ' switch-light-visual-label__strong' : ''; + + $output = ''; + + return $output; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/meta-fields-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/meta-fields-presenter.php new file mode 100644 index 00000000..deb8f1dc --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/meta-fields-presenter.php @@ -0,0 +1,64 @@ +post = $post; + $this->meta_fields = WPSEO_Meta::get_meta_field_defs( $field_group, $post_type ); + } + + /** + * Presents the Meta Fields. + * + * @return string The styled Alert. + */ + public function present() { + $output = ''; + + foreach ( $this->meta_fields as $key => $meta_field ) { + $form_key = \esc_attr( WPSEO_Meta::$form_prefix . $key ); + $meta_value = WPSEO_Meta::get_value( $key, $this->post->ID ); + + $default = ''; + if ( isset( $meta_field['default'] ) ) { + $default = \sprintf( ' data-default="%s"', \esc_attr( $meta_field['default'] ) ); + } + + $output .= '' . "\n"; + } + + return $output; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/migration-error-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/migration-error-presenter.php new file mode 100644 index 00000000..9ef789fb --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/migration-error-presenter.php @@ -0,0 +1,71 @@ +migration_error = $migration_error; + } + + /** + * Presents the migration error that occurred. + * + * @return string The error HTML. + */ + public function present() { + $message = \sprintf( + /* translators: %s: Yoast SEO. */ + \esc_html__( '%s had problems creating the database tables needed to speed up your site.', 'wordpress-seo' ), + 'Yoast SEO' + ); + $support = \sprintf( + /* translators: %1$s: link to help article about solving table issue. %2$s: is anchor closing. */ + \esc_html__( 'Please read %1$sthis help article%2$s to find out how to resolve this problem.', 'wordpress-seo' ), + '', + '' + ); + $reassurance = \sprintf( + /* translators: %s: Yoast SEO. */ + \esc_html__( 'Your site will continue to work normally, but won\'t take full advantage of %s.', 'wordpress-seo' ), + 'Yoast SEO' + ); + + $debug_info = \sprintf( + '
    %1$s

    %2$s

    ', + \esc_html__( 'Show debug information', 'wordpress-seo' ), + \esc_html( $this->migration_error['message'] ) + ); + + return \sprintf( + '

    %1$s

    %2$s

    %3$s

    %4$s
    ', + $message, + $support, + $reassurance, + $debug_info + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/admin/premium-badge-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/admin/premium-badge-presenter.php new file mode 100644 index 00000000..0d6165b8 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/admin/premium-badge-presenter.php @@ -0,0 +1,60 @@ +id = $id; + $this->link = $link; + } + + /** + * Presents the Premium Badge. If a link has been passed, the badge is presented with the link. + * Otherwise a static badge is presented. + * + * @return string The styled Premium Badge. + */ + public function present() { + if ( $this->link !== '' ) { + return \sprintf( + '%3$s', + \esc_attr( $this->id ), + \esc_url( $this->link ), + 'Premium' // We don't want this string to be translatable. + ); + } + + return \sprintf( + '%2$s', + \esc_attr( $this->id ), + 'Premium' // We don't want this string to be translatable. + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/bingbot-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/bingbot-presenter.php new file mode 100644 index 00000000..c961dd75 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/bingbot-presenter.php @@ -0,0 +1,66 @@ +get() ); + $bingbot = $this->filter( $bingbot ); + + if ( \is_string( $bingbot ) && $bingbot !== '' ) { + return \sprintf( '', \esc_attr( $bingbot ) ); + } + + return ''; + } + + /** + * Gets the raw value of a presentation. + * + * @deprecated 14.9 Values merged into the robots meta tag. + * @codeCoverageIgnore + * + * @return array The raw value. + */ + public function get() { + \_deprecated_function( __METHOD__, 'WPSEO 14.9' ); + + return $this->presentation->bingbot; + } + + /** + * Run the bingbot output content through the `wpseo_bingbot` filter. + * + * @param string $bingbot The meta bingbot output to filter. + * + * @return string The filtered meta bingbot output. + */ + private function filter( $bingbot ) { + /** + * Filter: 'wpseo_bingbot' - Allows filtering of the meta bingbot output of Yoast SEO. + * + * @api string $bingbot The meta bingbot directives to be echoed. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + */ + return (string) \apply_filters( 'wpseo_bingbot', $bingbot, $this->presentation ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/breadcrumbs-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/breadcrumbs-presenter.php new file mode 100644 index 00000000..42f95dc1 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/breadcrumbs-presenter.php @@ -0,0 +1,265 @@ +get(); + if ( ! \is_array( $breadcrumbs ) || empty( $breadcrumbs ) ) { + return ''; + } + + $links = []; + $total = \count( $breadcrumbs ); + foreach ( $breadcrumbs as $index => $breadcrumb ) { + $links[ $index ] = $this->crumb_to_link( $breadcrumb, $index, $total ); + } + + // Removes any effectively empty links. + $links = \array_map( 'trim', $links ); + $links = \array_filter( $links ); + $output = \implode( $this->get_separator(), $links ); + + if ( empty( $output ) ) { + return ''; + } + + $output = '<' . $this->get_wrapper() . $this->get_id() . $this->get_class() . '>' . $output . 'get_wrapper() . '>'; + $output = $this->filter( $output ); + + $prefix = $this->helpers->options->get( 'breadcrumbs-prefix' ); + if ( $prefix !== '' ) { + $output = "\t" . $prefix . "\n" . $output; + } + + return $output; + } + + /** + * Gets the raw value of a presentation. + * + * @return array The raw value. + */ + public function get() { + return $this->presentation->breadcrumbs; + } + + /** + * Filters the output. + * + * @param string $output The HTML output. + * + * @return string The filtered output. + */ + protected function filter( $output ) { + /** + * Filter: 'wpseo_breadcrumb_output' - Allow changing the HTML output of the Yoast SEO breadcrumbs class. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + * + * @api string $output The HTML output. + */ + return \apply_filters( 'wpseo_breadcrumb_output', $output, $this->presentation ); + } + + /** + * Create a breadcrumb element string. + * + * @param array $breadcrumb Link info array containing the keys: + * 'text' => (string) link text. + * 'url' => (string) link url. + * (optional) 'title' => (string) link title attribute text. + * @param int $index Index for the current breadcrumb. + * @param int $total The total number of breadcrumbs. + * + * @return string The breadcrumb link. + */ + protected function crumb_to_link( $breadcrumb, $index, $total ) { + $link = ''; + + if ( ! isset( $breadcrumb['text'] ) || ! \is_string( $breadcrumb['text'] ) || empty( $breadcrumb['text'] ) ) { + return $link; + } + + $text = \trim( $breadcrumb['text'] ); + + if ( + $index < ( $total - 1 ) + && isset( $breadcrumb['url'] ) + && \is_string( $breadcrumb['url'] ) + && ! empty( $breadcrumb['url'] ) + ) { + // If it's not the last element and we have a url. + $link .= '<' . $this->get_element() . '>'; + $title_attr = isset( $breadcrumb['title'] ) ? ' title="' . \esc_attr( $breadcrumb['title'] ) . '"' : ''; + $link .= '' . $text . ''; + } + elseif ( $index === ( $total - 1 ) ) { + // If it's the last element. + $inner_elm = 'span'; + if ( $this->helpers->options->get( 'breadcrumbs-boldlast' ) === true ) { + $inner_elm = 'strong'; + } + + $link .= '<' . $inner_elm . ' class="breadcrumb_last" aria-current="page">' . $text . ''; + // This is the last element, now close all previous elements. + while ( $index > 0 ) { + $link .= 'get_element() . '>'; + --$index; + } + } + else { + // It's not the last element and has no url. + $link .= '' . $text . ''; + } + + /** + * Filter: 'wpseo_breadcrumb_single_link' - Allow changing of each link being put out by the Yoast SEO breadcrumbs class. + * + * @param array $link The link array. + * + * @api string $link_output The output string. + */ + return \apply_filters( 'wpseo_breadcrumb_single_link', $link, $breadcrumb ); + } + + /** + * Retrieves HTML ID attribute. + * + * @return string The id attribute. + */ + protected function get_id() { + if ( ! $this->id ) { + /** + * Filter: 'wpseo_breadcrumb_output_id' - Allow changing the HTML ID on the Yoast SEO breadcrumbs wrapper element. + * + * @api string $unsigned ID to add to the wrapper element. + */ + $this->id = \apply_filters( 'wpseo_breadcrumb_output_id', '' ); + if ( ! \is_string( $this->id ) ) { + return ''; + } + + if ( $this->id !== '' ) { + $this->id = ' id="' . \esc_attr( $this->id ) . '"'; + } + } + + return $this->id; + } + + /** + * Retrieves HTML Class attribute. + * + * @return string The class attribute. + */ + protected function get_class() { + if ( ! $this->class ) { + /** + * Filter: 'wpseo_breadcrumb_output_class' - Allow changing the HTML class on the Yoast SEO breadcrumbs wrapper element. + * + * @api string $unsigned Class to add to the wrapper element. + */ + $this->class = \apply_filters( 'wpseo_breadcrumb_output_class', '' ); + if ( ! \is_string( $this->class ) ) { + return ''; + } + + if ( $this->class !== '' ) { + $this->class = ' class="' . \esc_attr( $this->class ) . '"'; + } + } + + return $this->class; + } + + /** + * Retrieves the wrapper element name. + * + * @return string The wrapper element name. + */ + protected function get_wrapper() { + if ( ! $this->wrapper ) { + $this->wrapper = \apply_filters( 'wpseo_breadcrumb_output_wrapper', 'span' ); + $this->wrapper = \tag_escape( $this->wrapper ); + if ( ! \is_string( $this->wrapper ) || $this->wrapper === '' ) { + $this->wrapper = 'span'; + } + } + + return $this->wrapper; + } + + /** + * Retrieves the separator. + * + * @return string The separator. + */ + protected function get_separator() { + if ( ! $this->separator ) { + $this->separator = \apply_filters( 'wpseo_breadcrumb_separator', $this->helpers->options->get( 'breadcrumbs-sep' ) ); + $this->separator = ' ' . $this->separator . ' '; + } + + return $this->separator; + } + + /** + * Retrieves the crumb element name. + * + * @return string The element to use. + */ + protected function get_element() { + if ( ! $this->element ) { + $this->element = \esc_attr( \apply_filters( 'wpseo_breadcrumb_single_link_wrapper', 'span' ) ); + } + + return $this->element; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/canonical-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/canonical-presenter.php new file mode 100644 index 00000000..c948ebf5 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/canonical-presenter.php @@ -0,0 +1,52 @@ +presentation->robots, true ) ) { + return ''; + } + + /** + * Filter: 'wpseo_canonical' - Allow filtering of the canonical URL put out by Yoast SEO. + * + * @api string $canonical The canonical URL. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + */ + return \urldecode( (string) \trim( \apply_filters( 'wpseo_canonical', $this->presentation->canonical, $this->presentation ) ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/debug/marker-close-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/debug/marker-close-presenter.php new file mode 100644 index 00000000..355498a4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/debug/marker-close-presenter.php @@ -0,0 +1,41 @@ +', + \esc_html( $this->helpers->product->get_name() ) + ); + } + + /** + * Gets the raw value of a presentation. + * + * @return string The raw value. + */ + public function get() { + return ''; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/debug/marker-open-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/debug/marker-open-presenter.php new file mode 100644 index 00000000..177efcd3 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/debug/marker-open-presenter.php @@ -0,0 +1,65 @@ +helpers->product->is_premium() ) { + $version_info = $this->construct_version_info(); + } + + return \sprintf( + '', + \esc_html( $this->helpers->product->get_name() ), + $version_info + ); + } + + /** + * Gets the plugin version information, including the free version if Premium is used. + * + * @return string The constructed version information. + */ + private function construct_version_info() { + /** + * Filter: 'wpseo_hide_version' - can be used to hide the Yoast SEO version in the debug marker (only available in Yoast SEO Premium). + * + * @api bool + */ + if ( \apply_filters( 'wpseo_hide_version', false ) ) { + return ''; + } + + return 'v' . \WPSEO_PREMIUM_VERSION . ' (Yoast SEO v' . \WPSEO_VERSION . ')'; + } + + /** + * Gets the raw value of a presentation. + * + * @return string The raw value. + */ + public function get() { + return ''; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/googlebot-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/googlebot-presenter.php new file mode 100644 index 00000000..79e9a82b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/googlebot-presenter.php @@ -0,0 +1,66 @@ +get() ); + $googlebot = $this->filter( $googlebot ); + + if ( \is_string( $googlebot ) && $googlebot !== '' ) { + return \sprintf( '', \esc_attr( $googlebot ) ); + } + + return ''; + } + + /** + * Gets the raw value of a presentation. + * + * @deprecated 14.9 Values merged into the robots meta tag. + * @codeCoverageIgnore + * + * @return array The raw value. + */ + public function get() { + \_deprecated_function( __METHOD__, 'WPSEO 14.9' ); + + return $this->presentation->googlebot; + } + + /** + * Run the googlebot output content through the `wpseo_googlebot` filter. + * + * @param string $googlebot The meta googlebot output to filter. + * + * @return string The filtered meta googlebot output. + */ + private function filter( $googlebot ) { + /** + * Filter: 'wpseo_googlebot' - Allows filtering of the meta googlebot output of Yoast SEO. + * + * @api string $googlebot The meta googlebot directives to be echoed. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + */ + return (string) \apply_filters( 'wpseo_googlebot', $googlebot, $this->presentation ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/meta-description-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/meta-description-presenter.php new file mode 100644 index 00000000..abf742b3 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/meta-description-presenter.php @@ -0,0 +1,64 @@ +'; + } + + return ''; + } + + /** + * Run the meta description content through replace vars, the `wpseo_metadesc` filter and sanitization. + * + * @return string The filtered meta description. + */ + public function get() { + $meta_description = $this->replace_vars( $this->presentation->meta_description ); + + /** + * Filter: 'wpseo_metadesc' - Allow changing the Yoast SEO meta description sentence. + * + * @api string $meta_description The description sentence. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + */ + $meta_description = \apply_filters( 'wpseo_metadesc', $meta_description, $this->presentation ); + $meta_description = $this->helpers->string->strip_all_tags( \stripslashes( $meta_description ) ); + return \trim( $meta_description ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-author-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-author-presenter.php new file mode 100644 index 00000000..a3016ee1 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-author-presenter.php @@ -0,0 +1,42 @@ +presentation->open_graph_article_author, $this->presentation ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-modified-time-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-modified-time-presenter.php new file mode 100644 index 00000000..b5764ff6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-modified-time-presenter.php @@ -0,0 +1,35 @@ +presentation->open_graph_article_modified_time; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-published-time-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-published-time-presenter.php new file mode 100644 index 00000000..299f0020 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-published-time-presenter.php @@ -0,0 +1,36 @@ +presentation->open_graph_article_published_time; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-publisher-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-publisher-presenter.php new file mode 100644 index 00000000..a1ccd2ca --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/article-publisher-presenter.php @@ -0,0 +1,42 @@ +presentation->open_graph_article_publisher, $this->presentation ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/description-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/description-presenter.php new file mode 100644 index 00000000..170605c8 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/description-presenter.php @@ -0,0 +1,42 @@ +replace_vars( $this->presentation->open_graph_description ), $this->presentation ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/image-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/image-presenter.php new file mode 100644 index 00000000..b94786e4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/image-presenter.php @@ -0,0 +1,98 @@ + 'width', + 'height' => 'height', + 'mime-type' => 'type', + ]; + + /** + * Returns the image for a post. + * + * @return string The image tag. + */ + public function present() { + $images = $this->get(); + + if ( empty( $images ) ) { + return ''; + } + + $return = ''; + foreach ( $images as $image_index => $image_meta ) { + $image_url = $image_meta['url']; + + $return .= ''; + + foreach ( static::$image_tags as $key => $value ) { + if ( empty( $image_meta[ $key ] ) ) { + continue; + } + + $return .= \PHP_EOL . "\t" . ''; + } + } + + return $return; + } + + /** + * Gets the raw value of a presentation. + * + * @return array The raw value. + */ + public function get() { + $images = []; + + foreach ( $this->presentation->open_graph_images as $open_graph_image ) { + $images[] = $this->filter( $open_graph_image ); + } + + return \array_filter( $images ); + } + + /** + * Run the image content through the `wpseo_opengraph_image` filter. + * + * @param array $image The image. + * + * @return array The filtered image. + */ + protected function filter( $image ) { + /** + * Filter: 'wpseo_opengraph_image' - Allow changing the Open Graph image. + * + * @api string - The URL of the Open Graph image. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + */ + $image_url = \trim( \apply_filters( 'wpseo_opengraph_image', $image['url'], $this->presentation ) ); + if ( ! empty( $image_url ) && \is_string( $image_url ) ) { + $image['url'] = $image_url; + } + + return $image; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/locale-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/locale-presenter.php new file mode 100644 index 00000000..e808ae5a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/locale-presenter.php @@ -0,0 +1,42 @@ +presentation->open_graph_locale, $this->presentation ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/site-name-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/site-name-presenter.php new file mode 100644 index 00000000..cf5055f1 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/site-name-presenter.php @@ -0,0 +1,42 @@ +presentation->open_graph_site_name, $this->presentation ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/title-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/title-presenter.php new file mode 100644 index 00000000..e86da9c4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/title-presenter.php @@ -0,0 +1,44 @@ +replace_vars( $this->presentation->open_graph_title ); + /** + * Filter: 'wpseo_opengraph_title' - Allow changing the Yoast SEO generated title. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + * + * @api string $title The title. + */ + $title = (string) \trim( \apply_filters( 'wpseo_opengraph_title', $title, $this->presentation ) ); + return $this->helpers->string->strip_all_tags( $title ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/type-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/type-presenter.php new file mode 100644 index 00000000..d1deaf88 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/type-presenter.php @@ -0,0 +1,42 @@ +presentation->open_graph_type, $this->presentation ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/open-graph/url-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/url-presenter.php new file mode 100644 index 00000000..a4766f0c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/open-graph/url-presenter.php @@ -0,0 +1,49 @@ +presentation->open_graph_url, $this->presentation ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/rel-next-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/rel-next-presenter.php new file mode 100644 index 00000000..c45f32c1 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/rel-next-presenter.php @@ -0,0 +1,73 @@ +presentation->robots, true ) ) { + return ''; + } + + /** + * Filter: 'wpseo_adjacent_rel_url' - Allow filtering of the rel next URL put out by Yoast SEO. + * + * @api string $rel_next The rel next URL. + * + * @param string $rel Link relationship, prev or next. + * @param Indexable_Presentation $presentation The presentation of an indexable. + */ + return (string) \trim( \apply_filters( 'wpseo_adjacent_rel_url', $this->presentation->rel_next, 'next', $this->presentation ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/rel-prev-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/rel-prev-presenter.php new file mode 100644 index 00000000..a66ec3f3 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/rel-prev-presenter.php @@ -0,0 +1,72 @@ +presentation->robots, true ) ) { + return ''; + } + + /** + * Filter: 'wpseo_adjacent_rel_url' - Allow filtering of the rel prev URL put out by Yoast SEO. + * + * @api string $canonical The rel prev URL. + * + * @param string $rel Link relationship, prev or next. + */ + return (string) \trim( \apply_filters( 'wpseo_adjacent_rel_url', $this->presentation->rel_prev, 'prev', $this->presentation ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/robots-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/robots-presenter.php new file mode 100644 index 00000000..6e6ee6ce --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/robots-presenter.php @@ -0,0 +1,40 @@ +get() ); + + if ( \is_string( $robots ) && $robots !== '' ) { + return \sprintf( '', \esc_attr( $robots ) ); + } + + return ''; + } + + /** + * Gets the raw value of a presentation. + * + * @return array The raw value. + */ + public function get() { + return $this->presentation->robots; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/schema-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/schema-presenter.php new file mode 100644 index 00000000..c634667a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/schema-presenter.php @@ -0,0 +1,62 @@ + 'Please use the "wpseo_schema_*" filters to extend the Yoast SEO schema data - see the WPSEO_Schema class.', + ]; + + /** + * Filter: 'wpseo_json_ld_output' - Allows disabling Yoast's schema output entirely. + * + * @api mixed If false or an empty array is returned, disable our output. + */ + $return = \apply_filters( 'wpseo_json_ld_output', $deprecated_data, '' ); + if ( $return === [] || $return === false ) { + return ''; + } + + /** + * Action: 'wpseo_json_ld' - Output Schema before the main schema from Yoast SEO is output. + */ + \do_action( 'wpseo_json_ld' ); + + $schema = $this->get(); + if ( \is_array( $schema ) ) { + $output = WPSEO_Utils::format_json_encode( $schema ); + $output = \str_replace( "\n", \PHP_EOL . "\t", $output ); + return ''; + } + + return ''; + } + + /** + * Gets the raw value of a presentation. + * + * @return array The raw value. + */ + public function get() { + return $this->presentation->schema; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/slack/enhanced-data-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/slack/enhanced-data-presenter.php new file mode 100644 index 00000000..b9aed21e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/slack/enhanced-data-presenter.php @@ -0,0 +1,65 @@ +get(); + $twitter_tags = ''; + $i = 1; + foreach ( $enhanced_data as $label => $value ) { + $twitter_tags .= \sprintf( "\t" . '' . "\n", $i, $label ); + $twitter_tags .= \sprintf( "\t" . '' . "\n", $i, $value ); + ++$i; + } + return \trim( $twitter_tags ); + } + + /** + * Gets the enhanced data array. + * + * @return array The enhanced data array + */ + public function get() { + $data = []; + $author_id = $this->presentation->source->post_author; + $estimated_reading_time = $this->presentation->estimated_reading_time_minutes; + + if ( $this->presentation->model->object_sub_type === 'post' && $author_id ) { + $data[ \__( 'Written by', 'wordpress-seo' ) ] = \get_the_author_meta( 'display_name', $author_id ); + } + + if ( ! empty( $estimated_reading_time ) ) { + /* translators: %s expands to the reading time number, in minutes */ + $data[ \__( 'Est. reading time', 'wordpress-seo' ) ] = \sprintf( \_n( '%s minute', '%s minutes', $estimated_reading_time, 'default' ), $estimated_reading_time ); + } + + /** + * Filter: 'wpseo_enhanced_slack_data' - Allows filtering of the enhanced data for sharing on Slack. + * + * @api array $data The enhanced Slack sharing data. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + */ + return \apply_filters( 'wpseo_enhanced_slack_data', $data, $this->presentation ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/title-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/title-presenter.php new file mode 100644 index 00000000..6063497a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/title-presenter.php @@ -0,0 +1,80 @@ +%s'; + + /** + * The method of escaping to use. + * + * @var string + */ + protected $escaping = 'html'; + + /** + * Gets the raw value of a presentation. + * + * @return string The raw value. + */ + public function get() { + // This ensures backwards compatibility with other plugins using this filter as well. + \add_filter( 'pre_get_document_title', [ $this, 'get_title' ], 15 ); + $title = \wp_get_document_title(); + \remove_filter( 'pre_get_document_title', [ $this, 'get_title' ], 15 ); + return $title; + } + + /** + * Returns a tag in the head. + * + * @return string The tag. + */ + public function present() { + $value = $this->get(); + + if ( \is_string( $value ) && $value !== '' ) { + return \sprintf( $this->tag_format, $this->escape_value( $value ) ); + } + + return ''; + } + + /** + * Returns the presentation title. + * + * @return string The title. + */ + public function get_title() { + $title = $this->replace_vars( $this->presentation->title ); + + /** + * Filter: 'wpseo_title' - Allow changing the Yoast SEO generated title. + * + * @api string $title The title. + * + * @param Indexable_Presentation $presentation The presentation of an indexable. + */ + $title = \apply_filters( 'wpseo_title', $title, $this->presentation ); + $title = $this->helpers->string->strip_all_tags( $title ); + return \trim( $title ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/twitter/card-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/twitter/card-presenter.php new file mode 100644 index 00000000..3dc28c7a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/twitter/card-presenter.php @@ -0,0 +1,35 @@ +presentation->twitter_card, $this->presentation ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/twitter/creator-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/twitter/creator-presenter.php new file mode 100644 index 00000000..e84db71a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/twitter/creator-presenter.php @@ -0,0 +1,27 @@ +presentation->twitter_creator; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/twitter/description-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/twitter/description-presenter.php new file mode 100644 index 00000000..b7b72834 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/twitter/description-presenter.php @@ -0,0 +1,35 @@ +replace_vars( $this->presentation->twitter_description ), $this->presentation ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/twitter/image-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/twitter/image-presenter.php new file mode 100644 index 00000000..324622f2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/twitter/image-presenter.php @@ -0,0 +1,42 @@ +presentation->twitter_image, $this->presentation ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/twitter/site-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/twitter/site-presenter.php new file mode 100644 index 00000000..89ea6b19 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/twitter/site-presenter.php @@ -0,0 +1,60 @@ +presentation->twitter_site, $this->presentation ); + $twitter_site = $this->get_twitter_id( $twitter_site ); + + if ( ! \is_string( $twitter_site ) || $twitter_site === '' ) { + return ''; + } + + return '@' . $twitter_site; + } + + /** + * Checks if the given id is actually an id or a url and if url, distills the id from it. + * + * Solves issues with filters returning urls and theme's/other plugins also adding a user meta + * twitter field which expects url rather than an id (which is what we expect). + * + * @param string $id Twitter ID or url. + * + * @return string|bool Twitter ID or false if it failed to get a valid Twitter ID. + */ + private function get_twitter_id( $id ) { + if ( \preg_match( '`([A-Za-z0-9_]{1,25})$`', $id, $match ) ) { + return $match[1]; + } + + return false; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/twitter/title-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/twitter/title-presenter.php new file mode 100644 index 00000000..92afdd6b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/twitter/title-presenter.php @@ -0,0 +1,35 @@ +replace_vars( $this->presentation->twitter_title ), $this->presentation ) ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/url-list-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/url-list-presenter.php new file mode 100644 index 00000000..ed5f0b85 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/url-list-presenter.php @@ -0,0 +1,48 @@ +links = $links; + $this->class_name = $class_name; + } + + /** + * Presents the URL list. + * + * @return string The URL list. + */ + public function present() { + $output = ''; + return $output; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/webmaster/baidu-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/webmaster/baidu-presenter.php new file mode 100644 index 00000000..2447a245 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/webmaster/baidu-presenter.php @@ -0,0 +1,27 @@ +helpers->options->get( 'baiduverify', '' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/webmaster/bing-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/webmaster/bing-presenter.php new file mode 100644 index 00000000..395cd56b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/webmaster/bing-presenter.php @@ -0,0 +1,27 @@ +helpers->options->get( 'msverify', '' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/webmaster/google-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/webmaster/google-presenter.php new file mode 100644 index 00000000..dd3b8f01 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/webmaster/google-presenter.php @@ -0,0 +1,27 @@ +helpers->options->get( 'googleverify', '' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/webmaster/pinterest-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/webmaster/pinterest-presenter.php new file mode 100644 index 00000000..d41bfbd9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/webmaster/pinterest-presenter.php @@ -0,0 +1,27 @@ +helpers->options->get( 'pinterestverify', '' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/presenters/webmaster/yandex-presenter.php b/wp-content/plugins/wordpress-seo/src/presenters/webmaster/yandex-presenter.php new file mode 100644 index 00000000..34b7512c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/presenters/webmaster/yandex-presenter.php @@ -0,0 +1,27 @@ +helpers->options->get( 'yandexverify', '' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/repositories/indexable-hierarchy-repository.php b/wp-content/plugins/wordpress-seo/src/repositories/indexable-hierarchy-repository.php new file mode 100644 index 00000000..9c092295 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/repositories/indexable-hierarchy-repository.php @@ -0,0 +1,144 @@ +builder = $builder; + } + + /** + * Removes all ancestors for an indexable. + * + * @param int $indexable_id The indexable id. + * + * @return bool Whether or not the indexables were successfully deleted. + */ + public function clear_ancestors( $indexable_id ) { + return $this->query()->where( 'indexable_id', $indexable_id )->delete_many(); + } + + /** + * Adds an ancestor to an indexable. + * + * @param int $indexable_id The indexable id. + * @param int $ancestor_id The ancestor id. + * @param int $depth The depth. + * + * @return bool Whether or not the ancestor was added successfully. + */ + public function add_ancestor( $indexable_id, $ancestor_id, $depth ) { + $hierarchy = $this->query()->create( + [ + 'indexable_id' => $indexable_id, + 'ancestor_id' => $ancestor_id, + 'depth' => $depth, + 'blog_id' => \get_current_blog_id(), + ] + ); + + return $hierarchy->save(); + } + + /** + * Retrieves the ancestors. Create them when empty. + * + * @param Indexable $indexable The indexable to get the ancestors for. + * + * @return int[] The indexable id's of the ancestors in order of grandparent to child. + */ + public function find_ancestors( Indexable $indexable ) { + $ancestors = $this->query() + ->select( 'ancestor_id' ) + ->where( 'indexable_id', $indexable->id ) + ->order_by_desc( 'depth' ) + ->find_array(); + + if ( ! empty( $ancestors ) ) { + if ( \count( $ancestors ) === 1 && $ancestors[0]['ancestor_id'] === '0' ) { + return []; + } + return \wp_list_pluck( $ancestors, 'ancestor_id' ); + } + + $indexable = $this->builder->build( $indexable ); + + return \wp_list_pluck( $indexable->ancestors, 'id' ); + } + + /** + * Finds the children for a given indexable. + * + * @param Indexable $indexable The indexable to find the children for. + * + * @return array Array with indexable id's for the children. + */ + public function find_children( Indexable $indexable ) { + $children = $this->query() + ->select( 'indexable_id' ) + ->where( 'ancestor_id', $indexable->id ) + ->find_array(); + + if ( empty( $children ) ) { + return []; + } + + return \wp_list_pluck( $children, 'indexable_id' ); + } + + /** + * Starts a query for this repository. + * + * @return ORM + */ + public function query() { + return Model::of_type( 'Indexable_Hierarchy' ); + } + + /** + * Finds all the children by given ancestor id's. + * + * @param array $object_ids List of id's to get the children for. + * + * @return array List of indexable id's for the children. + */ + public function find_children_by_ancestor_ids( array $object_ids ) { + if ( empty( $object_ids ) ) { + return []; + } + + $children = $this->query() + ->select( 'indexable_id' ) + ->where_in( 'ancestor_id', $object_ids ) + ->find_array(); + + if ( empty( $children ) ) { + return []; + } + + return \wp_list_pluck( $children, 'indexable_id' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/repositories/indexable-repository.php b/wp-content/plugins/wordpress-seo/src/repositories/indexable-repository.php new file mode 100644 index 00000000..2354e7fa --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/repositories/indexable-repository.php @@ -0,0 +1,543 @@ +builder = $builder; + $this->current_page = $current_page; + $this->logger = $logger; + $this->hierarchy_repository = $hierarchy_repository; + $this->wpdb = $wpdb; + $this->permalink_helper = $permalink_helper; + } + + /** + * Starts a query for this repository. + * + * @return ORM + */ + public function query() { + return Model::of_type( 'Indexable' ); + } + + /** + * Attempts to find the indexable for the current WordPress page. Returns false if no indexable could be found. + * This may be the result of the indexable not existing or of being unable to determine what type of page the + * current page is. + * + * @return bool|Indexable The indexable, false if none could be found. + */ + public function for_current_page() { + $indexable = false; + + switch ( true ) { + case $this->current_page->is_simple_page(): + $indexable = $this->find_by_id_and_type( $this->current_page->get_simple_page_id(), 'post' ); + break; + case $this->current_page->is_home_static_page(): + $indexable = $this->find_by_id_and_type( $this->current_page->get_front_page_id(), 'post' ); + break; + case $this->current_page->is_home_posts_page(): + $indexable = $this->find_for_home_page(); + break; + case $this->current_page->is_term_archive(): + $indexable = $this->find_by_id_and_type( $this->current_page->get_term_id(), 'term' ); + break; + case $this->current_page->is_date_archive(): + $indexable = $this->find_for_date_archive(); + break; + case $this->current_page->is_search_result(): + $indexable = $this->find_for_system_page( 'search-result' ); + break; + case $this->current_page->is_post_type_archive(): + $indexable = $this->find_for_post_type_archive( $this->current_page->get_queried_post_type() ); + break; + case $this->current_page->is_author_archive(): + $indexable = $this->find_by_id_and_type( $this->current_page->get_author_id(), 'user' ); + break; + case $this->current_page->is_404(): + $indexable = $this->find_for_system_page( '404' ); + break; + } + + if ( $indexable === false ) { + return $this->query()->create( + [ + 'object_type' => 'unknown', + 'post_status' => 'unindexed', + ] + ); + } + + return $indexable; + } + + /** + * Retrieves an indexable by its permalink. + * + * @param string $permalink The indexable permalink. + * + * @return bool|Indexable The indexable, false if none could be found. + */ + public function find_by_permalink( $permalink ) { + $permalink_hash = \strlen( $permalink ) . ':' . \md5( $permalink ); + + // Find by both permalink_hash and permalink, permalink_hash is indexed so will be used first by the DB to optimize the query. + return $this->query() + ->where( 'permalink_hash', $permalink_hash ) + ->where( 'permalink', $permalink ) + ->find_one(); + } + + /** + * Retrieves all the indexable instances of a certain object type. + * + * @param string $object_type The object type. + * + * @return Indexable[] The array with all the indexable instances of a certain object type. + */ + public function find_all_with_type( $object_type ) { + /** + * The array with all the indexable instances of a certain object type. + * + * @var Indexable[] $indexables + */ + $indexables = $this + ->query() + ->where( 'object_type', $object_type ) + ->find_many(); + + return \array_map( [ $this, 'ensure_permalink' ], $indexables ); + } + + /** + * Retrieves all the indexable instances of a certain object subtype. + * + * @param string $object_type The object type. + * @param string $object_sub_type The object subtype. + * + * @return Indexable[] The array with all the indexable instances of a certain object subtype. + */ + public function find_all_with_type_and_sub_type( $object_type, $object_sub_type ) { + /** + * The array with all the indexable instances of a certain object type and subtype. + * + * @var Indexable[] $indexables + */ + $indexables = $this + ->query() + ->where( 'object_type', $object_type ) + ->where( 'object_sub_type', $object_sub_type ) + ->find_many(); + + return \array_map( [ $this, 'ensure_permalink' ], $indexables ); + } + + /** + * Retrieves the homepage indexable. + * + * @param bool $auto_create Optional. Create the indexable if it does not exist. + * + * @return bool|Indexable Instance of indexable. + */ + public function find_for_home_page( $auto_create = true ) { + $indexable = \wp_cache_get( 'home-page', 'yoast-seo-indexables' ); + if ( ! $indexable ) { + /** + * Indexable instance. + * + * @var Indexable $indexable + */ + $indexable = $this->query()->where( 'object_type', 'home-page' )->find_one(); + + if ( $auto_create && ! $indexable ) { + $indexable = $this->builder->build_for_home_page(); + } + + $indexable = $this->ensure_permalink( $indexable ); + + \wp_cache_set( 'home-page', $indexable, 'yoast-seo-indexables', ( 5 * \MINUTE_IN_SECONDS ) ); + } + + return $indexable; + } + + /** + * Retrieves the date archive indexable. + * + * @param bool $auto_create Optional. Create the indexable if it does not exist. + * + * @return bool|Indexable Instance of indexable. + */ + public function find_for_date_archive( $auto_create = true ) { + /** + * Indexable instance. + * + * @var Indexable $indexable + */ + $indexable = $this->query()->where( 'object_type', 'date-archive' )->find_one(); + + if ( $auto_create && ! $indexable ) { + $indexable = $this->builder->build_for_date_archive(); + } + + return $this->ensure_permalink( $indexable ); + } + + /** + * Retrieves an indexable for a post type archive. + * + * @param string $post_type The post type. + * @param bool $auto_create Optional. Create the indexable if it does not exist. + * + * @return bool|Indexable The indexable, false if none could be found. + */ + public function find_for_post_type_archive( $post_type, $auto_create = true ) { + /** + * Indexable instance. + * + * @var Indexable $indexable + */ + $indexable = $this->query() + ->where( 'object_type', 'post-type-archive' ) + ->where( 'object_sub_type', $post_type ) + ->find_one(); + + if ( $auto_create && ! $indexable ) { + $indexable = $this->builder->build_for_post_type_archive( $post_type ); + } + + return $this->ensure_permalink( $indexable ); + } + + /** + * Retrieves the indexable for a system page. + * + * @param string $object_sub_type The type of system page. + * @param bool $auto_create Optional. Create the indexable if it does not exist. + * + * @return bool|Indexable Instance of indexable. + */ + public function find_for_system_page( $object_sub_type, $auto_create = true ) { + /** + * Indexable instance. + * + * @var Indexable $indexable + */ + $indexable = $this->query() + ->where( 'object_type', 'system-page' ) + ->where( 'object_sub_type', $object_sub_type ) + ->find_one(); + + if ( $auto_create && ! $indexable ) { + $indexable = $this->builder->build_for_system_page( $object_sub_type ); + } + + return $this->ensure_permalink( $indexable ); + } + + /** + * Retrieves an indexable by its ID and type. + * + * @param int $object_id The indexable object ID. + * @param string $object_type The indexable object type. + * @param bool $auto_create Optional. Create the indexable if it does not exist. + * + * @return bool|Indexable Instance of indexable. + */ + public function find_by_id_and_type( $object_id, $object_type, $auto_create = true ) { + $indexable = $this->query() + ->where( 'object_id', $object_id ) + ->where( 'object_type', $object_type ) + ->find_one(); + + if ( $auto_create && ! $indexable ) { + $indexable = $this->builder->build_for_id_and_type( $object_id, $object_type ); + } + + return $this->ensure_permalink( $indexable ); + } + + /** + * Retrieves multiple indexables at once by their id's and type. + * + * @param int[] $object_ids The array of indexable object id's. + * @param string $object_type The indexable object type. + * @param bool $auto_create Optional. Create the indexable if it does not exist. + * + * @return Indexable[] An array of indexables. + */ + public function find_by_multiple_ids_and_type( $object_ids, $object_type, $auto_create = true ) { + if ( empty( $object_ids ) ) { + return []; + } + + /** + * Represents an array of indexable objects. + * + * @var Indexable[] $indexables + */ + $indexables = $this->query() + ->where_in( 'object_id', $object_ids ) + ->where( 'object_type', $object_type ) + ->find_many(); + + if ( $auto_create ) { + $indexables_available = []; + foreach ( $indexables as $indexable ) { + $indexables_available[] = $indexable->object_id; + } + + $indexables_to_create = \array_diff( $object_ids, $indexables_available ); + + foreach ( $indexables_to_create as $indexable_to_create ) { + $indexables[] = $this->builder->build_for_id_and_type( $indexable_to_create, $object_type ); + } + } + + return \array_map( [ $this, 'ensure_permalink' ], $indexables ); + } + + /** + * Finds the indexables by id's. + * + * @param array $indexable_ids The indexable id's. + * + * @return Indexable[] The found indexables. + */ + public function find_by_ids( array $indexable_ids ) { + if ( empty( $indexable_ids ) ) { + return []; + } + + $indexables = $this + ->query() + ->where_in( 'id', $indexable_ids ) + ->find_many(); + + return \array_map( [ $this, 'ensure_permalink' ], $indexables ); + } + + /** + * Returns all ancestors of a given indexable. + * + * @param Indexable $indexable The indexable to find the ancestors of. + * + * @return Indexable[] All ancestors of the given indexable. + */ + public function get_ancestors( Indexable $indexable ) { + // If we've already set ancestors on the indexable no need to get them again. + if ( \is_array( $indexable->ancestors ) && ! empty( $indexable->ancestors ) ) { + return \array_map( [ $this, 'ensure_permalink' ], $indexable->ancestors ); + } + + $indexable_ids = $this->hierarchy_repository->find_ancestors( $indexable ); + + // If we've set ancestors on the indexable because we had to build them to find them. + if ( \is_array( $indexable->ancestors ) && ! empty( $indexable->ancestors ) ) { + return \array_map( [ $this, 'ensure_permalink' ], $indexable->ancestors ); + } + + if ( empty( $indexable_ids ) ) { + return []; + } + + if ( $indexable_ids[0] === 0 && \count( $indexable_ids ) === 1 ) { + return []; + } + + $indexables = $this->query() + ->where_in( 'id', $indexable_ids ) + ->order_by_expr( 'FIELD(id,' . \implode( ',', $indexable_ids ) . ')' ) + ->find_many(); + + return \array_map( [ $this, 'ensure_permalink' ], $indexables ); + } + + /** + * Returns all subpages with a given post_parent. + * + * @param int $post_parent The post parent. + * @param array $exclude_ids The id's to exclude. + * + * @return Indexable[] array of indexables. + */ + public function get_subpages_by_post_parent( $post_parent, $exclude_ids = [] ) { + $query = $this->query() + ->where( 'post_parent', $post_parent ) + ->where( 'object_type', 'post' ) + ->where( 'post_status', 'publish' ); + + if ( ! empty( $exclude_ids ) ) { + $query->where_not_in( 'object_id', $exclude_ids ); + } + return $query->find_many(); + } + + /** + * Updates the incoming link count for an indexable without first fetching it. + * + * @param int $indexable_id The indexable id. + * @param int $count The incoming link count. + * + * @return bool Whether or not the update was succeful. + */ + public function update_incoming_link_count( $indexable_id, $count ) { + return (bool) $this->query() + ->set( 'incoming_link_count', $count ) + ->where( 'id', $indexable_id ) + ->update_many(); + } + + /** + * Ensures that the given indexable has a permalink. + * + * @param Indexable $indexable The indexable. + * + * @return bool|Indexable The indexable. + */ + public function ensure_permalink( $indexable ) { + if ( $indexable && $indexable->permalink === null ) { + $indexable->permalink = $this->permalink_helper->get_permalink_for_indexable( $indexable ); + + if ( $indexable->permalink === null && $indexable->post_status === 'unindexed' ) { + $indexable->permalink = 'unindexed'; + } + + // Only save if changed. + if ( $indexable->permalink !== null ) { + $indexable->save(); + } + } + return $indexable; + } + + /* ********************* DEPRECATED METHODS ********************* */ + + /** + * Returns all children of a given indexable. + * + * @deprecated 15.0 + * @codeCoverageIgnore + * + * @param Indexable $indexable The indexable to find the children of. + * + * @return Indexable[] All children of the given indexable. + */ + public function get_children( Indexable $indexable ) { + \_deprecated_function( __METHOD__, 'WPSEO 15.0' ); + + $indexable_ids = $this->hierarchy_repository->find_children( $indexable ); + + return $this->find_by_ids( $indexable_ids ); + } + + /** + * Resets the permalinks of the passed object type and subtype. + * + * @param string|null $type The type of the indexable. Can be null. + * @param string|null $subtype The subtype. Can be null. + * + * @return int|bool The number of permalinks changed if the query was succesful. False otherwise. + */ + public function reset_permalink( $type = null, $subtype = null ) { + $query = $this->query()->set( + [ + 'permalink' => null, + 'permalink_hash' => null, + ] + ); + + if ( $type !== null ) { + $query->where( 'object_type', $type ); + } + + if ( $type !== null && $subtype !== null ) { + $query->where( 'object_sub_type', $subtype ); + } + + return $query->update_many(); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/repositories/primary-term-repository.php b/wp-content/plugins/wordpress-seo/src/repositories/primary-term-repository.php new file mode 100644 index 00000000..244e34d6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/repositories/primary-term-repository.php @@ -0,0 +1,49 @@ +query() + ->where( 'post_id', $post_id ) + ->where( 'taxonomy', $taxonomy ) + ->find_one(); + + if ( $auto_create && ! $primary_term ) { + $primary_term = $this->query()->create(); + } + + return $primary_term; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/repositories/seo-links-repository.php b/wp-content/plugins/wordpress-seo/src/repositories/seo-links-repository.php new file mode 100644 index 00000000..37d345a0 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/repositories/seo-links-repository.php @@ -0,0 +1,144 @@ +query() + ->where( 'post_id', $post_id ) + ->find_many(); + } + + /** + * Finds all SEO Links by indexable ID. + * + * @param int $indexable_id The indexable ID. + * + * @return SEO_Links[] The SEO Links. + */ + public function find_all_by_indexable_id( $indexable_id ) { + return $this->query() + ->where( 'indexable_id', $indexable_id ) + ->find_many(); + } + + /** + * Clears all SEO Links by post ID. + * + * @param int $post_id The post ID. + * + * @return bool Whether or not the delete was succesfull. + */ + public function delete_all_by_post_id( $post_id ) { + return $this->query() + ->where( 'post_id', $post_id ) + ->delete_many(); + } + + /** + * Clears all SEO Links by post ID where the indexable id is null. + * + * @param int $post_id The post ID. + * + * @return bool Whether or not the delete was succesfull. + */ + public function delete_all_by_post_id_where_indexable_id_null( $post_id ) { + return $this->query() + ->where( 'post_id', $post_id ) + ->where_null( 'indexable_id' ) + ->delete_many(); + } + + /** + * Clears all SEO Links by indexable ID. + * + * @param int $indexable_id The indexable ID. + * + * @return bool Whether or not the delete was succesfull. + */ + public function delete_all_by_indexable_id( $indexable_id ) { + return $this->query() + ->where( 'indexable_id', $indexable_id ) + ->delete_many(); + } + + /** + * Returns incoming link counts for a number of posts. + * + * @param array $post_ids The post IDs. + * + * @return array An array of associative arrays, each containing a post id and incoming property. + */ + public function get_incoming_link_counts_for_post_ids( $post_ids ) { + return $this->query() + ->select_expr( 'COUNT( id )', 'incoming' ) + ->select( 'target_post_id', 'post_id' ) + ->where_in( 'target_post_id', $post_ids ) + ->group_by( 'target_post_id' ) + ->find_array(); + } + + /** + * Returns incoming link counts for a number of indexables. + * + * @param array $indexable_ids The indexable IDs. + * + * @return array An array of associative arrays, each containing a indexable id and incoming property. + */ + public function get_incoming_link_counts_for_indexable_ids( $indexable_ids ) { + return $this->query() + ->select_expr( 'COUNT( id )', 'incoming' ) + ->select( 'target_indexable_id' ) + ->where_in( 'target_indexable_id', $indexable_ids ) + ->group_by( 'target_indexable_id' ) + ->find_array(); + } + + /** + * Deletes all seo links for the given ids. + * + * @param int[] $ids The seo link ids. + * + * @return bool Whether or not the delete was succesfull. + */ + public function delete_many_by_id( $ids ) { + return $this->query() + ->where_in( 'id', $ids ) + ->delete_many(); + } + + /** + * Insert multiple seo links. + * + * @param SEO_Links[] $links The seo links to be inserted. + * + * @return bool Whether or not the insert was succesfull. + */ + public function insert_many( $links ) { + return $this->query() + ->insert_many( $links ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/repositories/seo-meta-repository.php b/wp-content/plugins/wordpress-seo/src/repositories/seo-meta-repository.php new file mode 100644 index 00000000..b749118a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/repositories/seo-meta-repository.php @@ -0,0 +1,35 @@ + $objects, + 'next_url' => $next_url, + ] + ); + } + + /** + * Runs an indexing action and returns the response. + * + * @param Indexation_Action_Interface $indexation_action The indexing action. + * @param string $url The url of the indexing route. + * + * @return WP_REST_Response The response. + */ + protected function run_indexation_action( Indexation_Action_Interface $indexation_action, $url ) { + $indexables = $indexation_action->index(); + + $next_url = false; + if ( \count( $indexables ) >= $indexation_action->get_limit() ) { + $next_url = \rest_url( $url ); + } + + return $this->respond_with( $indexables, $next_url ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/routes/alert-dismissal-route.php b/wp-content/plugins/wordpress-seo/src/routes/alert-dismissal-route.php new file mode 100644 index 00000000..d4ff184e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/routes/alert-dismissal-route.php @@ -0,0 +1,104 @@ +alert_dismissal_action = $alert_dismissal_action; + } + + /** + * Registers routes with WordPress. + * + * @return void + */ + public function register_routes() { + $dismiss_route_args = [ + 'methods' => 'POST', + 'callback' => [ $this, 'dismiss' ], + 'permission_callback' => [ $this, 'can_dismiss' ], + 'args' => [ + 'key' => [ + 'validate_callback' => [ $this->alert_dismissal_action, 'is_allowed' ], + 'required' => true, + ], + ], + ]; + + \register_rest_route( Main::API_V1_NAMESPACE, self::DISMISS_ROUTE, $dismiss_route_args ); + } + + /** + * Dismisses an alert. + * + * @param WP_REST_Request $request The request. This request should have a key param set. + * + * @return WP_REST_Response The response. + */ + public function dismiss( WP_REST_Request $request ) { + $success = $this->alert_dismissal_action->dismiss( $request['key'] ); + $status = $success === ( true ) ? 200 : 400; + + return new WP_REST_Response( + (object) [ + 'success' => $success, + 'status' => $status, + ], + $status + ); + } + + /** + * Whether or not the current user is allowed to dismiss alerts. + * + * @return bool Whether or not the current user is allowed to dismiss alerts. + */ + public function can_dismiss() { + return \current_user_can( 'edit_posts' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/routes/indexables-head-route.php b/wp-content/plugins/wordpress-seo/src/routes/indexables-head-route.php new file mode 100644 index 00000000..5f9ae161 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/routes/indexables-head-route.php @@ -0,0 +1,102 @@ +head_action = $head_action; + } + + /** + * Returns the conditionals based in which this loadable should be active. + * + * @return array + */ + public static function get_conditionals() { + return [ Headless_Rest_Endpoints_Enabled_Conditional::class ]; + } + + /** + * Registers routes with WordPress. + * + * @return void + */ + public function register_routes() { + $route_args = [ + 'methods' => 'GET', + 'callback' => [ $this, 'get_head' ], + 'permission_callback' => '__return_true', + 'args' => [ + 'url' => [ + 'validate_callback' => [ $this, 'is_valid_url' ], + 'required' => true, + ], + ], + ]; + \register_rest_route( Main::API_V1_NAMESPACE, self::HEAD_FOR_URL_ROUTE, $route_args ); + } + + /** + * Gets the head of a page for a given URL. + * + * @param WP_REST_Request $request The request. This request should have a url param set. + * + * @return WP_REST_Response The response. + */ + public function get_head( WP_REST_Request $request ) { + $url = \esc_url_raw( \utf8_uri_encode( $request['url'] ) ); + $data = $this->head_action->for_url( $url ); + + return new WP_REST_Response( $data, $data->status ); + } + + /** + * Checks if a url is a valid url. + * + * @param string $url The url to check. + * + * @return bool Whether or not the url is valid. + */ + public function is_valid_url( $url ) { + if ( \filter_var( \utf8_uri_encode( $url ), \FILTER_VALIDATE_URL ) === false ) { + return false; + } + return true; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/routes/indexing-route.php b/wp-content/plugins/wordpress-seo/src/routes/indexing-route.php new file mode 100644 index 00000000..f104090f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/routes/indexing-route.php @@ -0,0 +1,431 @@ +post_indexation_action = $post_indexation_action; + $this->term_indexation_action = $term_indexation_action; + $this->post_type_archive_indexation_action = $post_type_archive_indexation_action; + $this->general_indexation_action = $general_indexation_action; + $this->indexable_indexing_complete_action = $indexable_indexing_complete_action; + $this->indexing_complete_action = $indexing_complete_action; + $this->prepare_indexing_action = $prepare_indexing_action; + $this->post_link_indexing_action = $post_link_indexing_action; + $this->term_link_indexing_action = $term_link_indexing_action; + $this->options_helper = $options_helper; + $this->post_link_indexing_action = $post_link_indexing_action; + $this->term_link_indexing_action = $term_link_indexing_action; + $this->indexing_helper = $indexing_helper; + } + + /** + * Registers the routes used to index indexables. + */ + public function register_routes() { + $route_args = [ + 'methods' => 'POST', + 'callback' => [ $this, 'index_posts' ], + 'permission_callback' => [ $this, 'can_index' ], + ]; + \register_rest_route( Main::API_V1_NAMESPACE, self::POSTS_ROUTE, $route_args ); + + $route_args['callback'] = [ $this, 'index_terms' ]; + \register_rest_route( Main::API_V1_NAMESPACE, self::TERMS_ROUTE, $route_args ); + + $route_args['callback'] = [ $this, 'index_post_type_archives' ]; + \register_rest_route( Main::API_V1_NAMESPACE, self::POST_TYPE_ARCHIVES_ROUTE, $route_args ); + + $route_args['callback'] = [ $this, 'index_general' ]; + \register_rest_route( Main::API_V1_NAMESPACE, self::GENERAL_ROUTE, $route_args ); + + $route_args['callback'] = [ $this, 'prepare' ]; + \register_rest_route( Main::API_V1_NAMESPACE, self::PREPARE_ROUTE, $route_args ); + + $route_args['callback'] = [ $this, 'indexables_complete' ]; + \register_rest_route( Main::API_V1_NAMESPACE, self::INDEXABLES_COMPLETE_ROUTE, $route_args ); + + $route_args['callback'] = [ $this, 'complete' ]; + \register_rest_route( Main::API_V1_NAMESPACE, self::COMPLETE_ROUTE, $route_args ); + + $route_args['callback'] = [ $this, 'index_post_links' ]; + \register_rest_route( Main::API_V1_NAMESPACE, self::POST_LINKS_INDEXING_ROUTE, $route_args ); + + $route_args['callback'] = [ $this, 'index_term_links' ]; + \register_rest_route( Main::API_V1_NAMESPACE, self::TERM_LINKS_INDEXING_ROUTE, $route_args ); + } + + /** + * Indexes a number of unindexed posts. + * + * @return WP_REST_Response The response. + */ + public function index_posts() { + return $this->run_indexation_action( $this->post_indexation_action, self::FULL_POSTS_ROUTE ); + } + + /** + * Indexes a number of unindexed terms. + * + * @return WP_REST_Response The response. + */ + public function index_terms() { + return $this->run_indexation_action( $this->term_indexation_action, self::FULL_TERMS_ROUTE ); + } + + /** + * Indexes a number of unindexed post type archive pages. + * + * @return WP_REST_Response The response. + */ + public function index_post_type_archives() { + return $this->run_indexation_action( $this->post_type_archive_indexation_action, self::FULL_POST_TYPE_ARCHIVES_ROUTE ); + } + + /** + * Indexes a number of unindexed general items. + * + * @return WP_REST_Response The response. + */ + public function index_general() { + return $this->run_indexation_action( $this->general_indexation_action, self::FULL_GENERAL_ROUTE ); + } + + /** + * Indexes a number of posts for post links. + * + * @return WP_REST_Response The response. + */ + public function index_post_links() { + return $this->run_indexation_action( $this->post_link_indexing_action, self::FULL_POST_LINKS_INDEXING_ROUTE ); + } + + /** + * Indexes a number of terms for term links. + * + * @return WP_REST_Response The response. + */ + public function index_term_links() { + return $this->run_indexation_action( $this->term_link_indexing_action, self::FULL_TERM_LINKS_INDEXING_ROUTE ); + } + + /** + * Prepares the indexation. + * + * @return WP_REST_Response The response. + */ + public function prepare() { + $this->prepare_indexing_action->prepare(); + + return $this->respond_with( [], false ); + } + + /** + * Completes the indexable indexation. + * + * @return WP_REST_Response The response. + */ + public function indexables_complete() { + $this->indexable_indexing_complete_action->complete(); + + return $this->respond_with( [], false ); + } + + /** + * Completes the indexation. + * + * @return WP_REST_Response The response. + */ + public function complete() { + $this->indexing_complete_action->complete(); + + return $this->respond_with( [], false ); + } + + /** + * Whether or not the current user is allowed to index. + * + * @return bool Whether or not the current user is allowed to index. + */ + public function can_index() { + return \current_user_can( 'edit_posts' ); + } + + /** + * Runs an indexing action and returns the response. + * + * @param Indexation_Action_Interface $indexation_action The indexing action. + * @param string $url The url of the indexing route. + * + * @return WP_REST_Response|WP_Error The response, or an error when running the indexing action failed. + */ + protected function run_indexation_action( Indexation_Action_Interface $indexation_action, $url ) { + try { + return parent::run_indexation_action( $indexation_action, $url ); + } catch ( Exception $exception ) { + $this->indexing_helper->indexing_failed(); + + return new WP_Error( + 'wpseo_error_indexing', + $exception->getMessage(), + [ 'stackTrace' => $exception->getTraceAsString() ] + ); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/src/routes/route-interface.php b/wp-content/plugins/wordpress-seo/src/routes/route-interface.php new file mode 100644 index 00000000..12447ee9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/routes/route-interface.php @@ -0,0 +1,18 @@ +login_action = $login_action; + $this->options_action = $options_action; + $this->phrases_action = $phrases_action; + } + + /** + * Registers routes with WordPress. + * + * @return void + */ + public function register_routes() { + $authentication_route_args = [ + 'methods' => 'POST', + 'callback' => [ $this, 'authenticate' ], + 'permission_callback' => [ $this, 'can_use_semrush' ], + 'args' => [ + 'code' => [ + 'validate_callback' => [ $this, 'has_valid_code' ], + 'required' => true, + ], + ], + ]; + + \register_rest_route( Main::API_V1_NAMESPACE, self::AUTHENTICATION_ROUTE, $authentication_route_args ); + + $set_country_code_option_route_args = [ + 'methods' => 'POST', + 'callback' => [ $this, 'set_country_code_option' ], + 'permission_callback' => [ $this, 'can_use_semrush' ], + 'args' => [ + 'country_code' => [ + 'validate_callback' => [ $this, 'has_valid_country_code' ], + 'required' => true, + ], + ], + ]; + + \register_rest_route( Main::API_V1_NAMESPACE, self::COUNTRY_CODE_OPTION_ROUTE, $set_country_code_option_route_args ); + + $related_keyphrases_route_args = [ + 'methods' => 'GET', + 'callback' => [ $this, 'get_related_keyphrases' ], + 'permission_callback' => [ $this, 'can_use_semrush' ], + 'args' => [ + 'keyphrase' => [ + 'validate_callback' => [ $this, 'has_valid_keyphrase' ], + 'required' => true, + ], + 'country_code' => [ + 'required' => true, + ], + ], + ]; + + \register_rest_route( Main::API_V1_NAMESPACE, self::RELATED_KEYPHRASES_ROUTE, $related_keyphrases_route_args ); + } + + /** + * Authenticates with SEMrush. + * + * @param WP_REST_Request $request The request. This request should have a code param set. + * + * @return WP_REST_Response The response. + */ + public function authenticate( WP_REST_Request $request ) { + $data = $this + ->login_action + ->authenticate( $request['code'] ); + + return new WP_REST_Response( $data, $data->status ); + } + + /** + * Sets the SEMrush country code option. + * + * @param WP_REST_Request $request The request. This request should have a country code param set. + * + * @return WP_REST_Response The response. + */ + public function set_country_code_option( WP_REST_Request $request ) { + $data = $this + ->options_action + ->set_country_code( $request['country_code'] ); + + return new WP_REST_Response( $data, $data->status ); + } + + /** + * Checks if a valid code was returned. + * + * @param string $code The code to check. + * + * @return bool Whether or not the code is valid. + */ + public function has_valid_code( $code ) { + return $code !== ''; + } + + /** + * Checks if a valid keyphrase is provided. + * + * @param string $keyphrase The keyphrase to check. + * + * @return bool Whether or not the keyphrase is valid. + */ + public function has_valid_keyphrase( $keyphrase ) { + return \trim( $keyphrase ) !== ''; + } + + /** + * Gets the related keyphrases based on the passed keyphrase and database code. + * + * @param WP_REST_Request $request The request. This request should have a keyphrase and country_code param set. + * + * @return WP_REST_Response The response. + */ + public function get_related_keyphrases( WP_REST_Request $request ) { + $data = $this + ->phrases_action + ->get_related_keyphrases( + $request['keyphrase'], + $request['country_code'] + ); + + return new WP_REST_Response( $data, $data->status ); + } + + /** + * Checks if a valid country code was submitted. + * + * @param string $country_code The country code to check. + * + * @return bool Whether or not the country code is valid. + */ + public function has_valid_country_code( $country_code ) { + return ( $country_code !== '' && \preg_match( '/^[a-z]{2}$/', $country_code ) === 1 ); + } + + /** + * Whether or not the current user is allowed to edit post/pages and thus use the SEMrush integration. + * + * @return bool Whether or not the current user is allowed to use SEMrush. + */ + public function can_use_semrush() { + return \current_user_can( 'edit_posts' ) || \current_user_can( 'edit_pages' ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/routes/supported-features-route.php b/wp-content/plugins/wordpress-seo/src/routes/supported-features-route.php new file mode 100644 index 00000000..e9802eff --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/routes/supported-features-route.php @@ -0,0 +1,59 @@ + 'GET', + 'callback' => [ $this, 'get_supported_features' ], + 'permission_callback' => '__return_true', + ]; + + \register_rest_route( Main::API_V1_NAMESPACE, self::SUPPORTED_FEATURES_ROUTE, $supported_features_route ); + } + + /** + * Returns a list of features supported by this yoast seo installation. + * + * @return WP_REST_Response a list of features supported by this yoast seo installation. + */ + public function get_supported_features() { + return new WP_REST_Response( + [ + 'addon-installation' => 1, + ] + ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/routes/yoast-head-rest-field.php b/wp-content/plugins/wordpress-seo/src/routes/yoast-head-rest-field.php new file mode 100644 index 00000000..1bb9b0fb --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/routes/yoast-head-rest-field.php @@ -0,0 +1,225 @@ +post_type_helper = $post_type_helper; + $this->taxonomy_helper = $taxonomy_helper; + $this->post_helper = $post_helper; + $this->head_action = $head_action; + } + + /** + * Registers routes with WordPress. + * + * @return void + */ + public function register_routes() { + $public_post_types = $this->post_type_helper->get_public_post_types(); + + foreach ( $public_post_types as $post_type ) { + $this->register_rest_fields( $post_type, 'for_post' ); + } + + $public_taxonomies = $this->taxonomy_helper->get_public_taxonomies(); + + foreach ( $public_taxonomies as $taxonomy ) { + if ( $taxonomy === 'post_tag' ) { + $taxonomy = 'tag'; + } + $this->register_rest_fields( $taxonomy, 'for_term' ); + } + + $this->register_rest_fields( 'user', 'for_author' ); + $this->register_rest_fields( 'type', 'for_post_type_archive' ); + } + + /** + * Returns the head for a post. + * + * @param array $params The rest request params. + * @param string $format The desired output format. + * + * @return string|null The head. + */ + public function for_post( $params, $format = self::YOAST_HEAD_ATTRIBUTE_NAME ) { + if ( ! isset( $params['id'] ) ) { + return null; + } + + if ( ! $this->post_helper->is_post_indexable( $params['id'] ) ) { + return null; + } + $obj = $this->head_action->for_post( $params['id'] ); + + return $this->render_object( $obj, $format ); + } + + /** + * Returns the head for a term. + * + * @param array $params The rest request params. + * @param string $format The desired output format. + * + * @return string|null The head. + */ + public function for_term( $params, $format = self::YOAST_HEAD_ATTRIBUTE_NAME ) { + $obj = $this->head_action->for_term( $params['id'] ); + + return $this->render_object( $obj, $format ); + } + + /** + * Returns the head for an author. + * + * @param array $params The rest request params. + * @param string $format The desired output format. + * + * @return string|null The head. + */ + public function for_author( $params, $format = self::YOAST_HEAD_ATTRIBUTE_NAME ) { + $obj = $this->head_action->for_author( $params['id'] ); + + return $this->render_object( $obj, $format ); + } + + /** + * Returns the head for a post type archive. + * + * @param array $params The rest request params. + * @param string $format The desired output format. + * + * @return string|null The head. + */ + public function for_post_type_archive( $params, $format = self::YOAST_HEAD_ATTRIBUTE_NAME ) { + if ( $params['slug'] === 'post' ) { + $obj = $this->head_action->for_posts_page(); + } + elseif ( ! $this->post_type_helper->has_archive( $params['slug'] ) ) { + return null; + } + else { + $obj = $this->head_action->for_post_type_archive( $params['slug'] ); + } + + return $this->render_object( $obj, $format ); + } + + /** + * Registers the Yoast rest fields. + * + * @param string $object_type The object type. + * @param string $callback The function name of the callback. + * + * @return void + */ + protected function register_rest_fields( $object_type, $callback ) { + // Output metadata in page head meta tags. + \register_rest_field( $object_type, self::YOAST_HEAD_ATTRIBUTE_NAME, [ 'get_callback' => [ $this, $callback ] ] ); + // Output metadata in a json object in a head meta tag. + \register_rest_field( $object_type, self::YOAST_JSON_HEAD_ATTRIBUTE_NAME, [ 'get_callback' => [ $this, $callback ] ] ); + } + + /** + * Returns the correct property for the Yoast head. + * + * @param stdObject $head The Yoast head. + * @param string $format The format to return. + * + * @return string|array The output value. String if HTML was requested, array otherwise. + */ + protected function render_object( $head, $format = self::YOAST_HEAD_ATTRIBUTE_NAME ) { + if ( $head->status === 404 ) { + return null; + } + + switch ( $format ) { + case self::YOAST_HEAD_ATTRIBUTE_NAME: + return $head->html; + case self::YOAST_JSON_HEAD_ATTRIBUTE_NAME: + return $head->json; + } + + return null; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/assets/icons.php b/wp-content/plugins/wordpress-seo/src/schema-templates/assets/icons.php new file mode 100644 index 00000000..65348fd8 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/assets/icons.php @@ -0,0 +1,306 @@ +"; + + /** + * The default height and width of an icon. + */ + const SIZE_DEFAULT = 24; + + /** + * The height and width of an icon in a variation picker. + */ + const SIZE_VARIATION = 36; + + /** + * The Heroicons academic cap svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_academic_cap( $size = self::SIZE_DEFAULT ) { + return self::svg( + "" + . "" + . "", + $size + ); + } + + /** + * The Heroicons annotation svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_annotation( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons ban svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_ban( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons briefcase svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_briefcase( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons calendar svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_calendar( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons clipboard check svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_clipboard_check( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons clipboard copy svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_clipboard_copy( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons clipboard list svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_clipboard_list( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons clock svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_clock( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons currency dollar svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_currency_dollar( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons cursor_click svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_cursor_click( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons document text svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_document_text( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons globe svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_globe( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons identification svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_identification( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons location marker svg icon + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_location_marker( $size = self::SIZE_DEFAULT ) { + return self::svg( + "" + . "", + $size + ); + } + + /** + * The Heroicons office building svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_office_building( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons photograph svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_photograph( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons switch horizontal svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * @return string + */ + public static function heroicons_switch_horizontal( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons grid svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * + * @return string The generated icon. + */ + public static function heroicons_grid( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * The Heroicons book open svg icon. + * + * @param int $size The Height and Width of the SVG icon. + * + * @return string The generated icon. + */ + public static function heroicons_book_open( $size = self::SIZE_DEFAULT ) { + return self::svg( + "", + $size + ); + } + + /** + * Generates the SVG based on given path. + * + * @param string $path The path to generate svg for. + * @param int $svg_size The Height and Width of the SVG icon. + * + * @return string The generated icon svg. + */ + protected static function svg( $path, $svg_size = self::SIZE_DEFAULT ) { + $start = \str_replace( '%SIZE%', $svg_size, self::SVG_START_TAG ); + return $start . $path . ''; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/cooking-time.block.php b/wp-content/plugins/wordpress-seo/src/schema-templates/cooking-time.block.php new file mode 100644 index 00000000..09cbf669 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/cooking-time.block.php @@ -0,0 +1,15 @@ + +{{block name="yoast/cooking-time" title="" category="yoast-structured-data-blocks" parent=[ "yoast/recipe" ] description="" icon="" supports={"multiple": false} }} +
    + {{heading name="title" default-heading-level=3 tags=[ "h2", "h3", "h4", "h5", "h6", "strong" ] default="" }} + {{duration name="cooking-time" }} +
    diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/cooking-time.schema.php b/wp-content/plugins/wordpress-seo/src/schema-templates/cooking-time.schema.php new file mode 100644 index 00000000..bd704639 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/cooking-time.schema.php @@ -0,0 +1,3 @@ + +{{schema name="yoast/cooking-time" only-nested=true }} +{{attribute name="cooking-time-iso8601-duration" }} diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/image.schema.php b/wp-content/plugins/wordpress-seo/src/schema-templates/image.schema.php new file mode 100644 index 00000000..b03f6097 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/image.schema.php @@ -0,0 +1,10 @@ + +{{schema name="core/image" separate-in-graph=true }} +{ + "@type": "ImageObject", + "@id": {{block-id}}, + "url": {{attribute name="url" }}, + "width": {{attribute name="width" }}, + "height": {{attribute name="height" }}, + "caption": {{html name="caption" }} +} diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/preparation-time.block.php b/wp-content/plugins/wordpress-seo/src/schema-templates/preparation-time.block.php new file mode 100644 index 00000000..427cc423 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/preparation-time.block.php @@ -0,0 +1,15 @@ + +{{block name="yoast/preparation-time" title="" category="yoast-structured-data-blocks" parent=[ "yoast/recipe" ] description="" icon="" supports={"multiple": false} }} +
    + {{heading name="title" default-heading-level=3 tags=[ "h2", "h3", "h4", "h5", "h6", "strong" ] default="" }} + {{duration name="preparation-time" }} +
    diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/preparation-time.schema.php b/wp-content/plugins/wordpress-seo/src/schema-templates/preparation-time.schema.php new file mode 100644 index 00000000..7aea75f7 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/preparation-time.schema.php @@ -0,0 +1,3 @@ + +{{schema name="yoast/preparation-time" only-nested=true }} +{{attribute name="preparation-time-iso8601-duration" }} diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-description.block.php b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-description.block.php new file mode 100644 index 00000000..eaa0cc5f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-description.block.php @@ -0,0 +1,15 @@ + +{{block name="yoast/recipe-description" title="" category="yoast-structured-data-blocks" description="" icon="" supports={"multiple": false} }} +
    + {{rich-text name="description" required=true tag="p" keepPlaceholderOnFocus=true placeholder=""}} +
    diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-description.schema.php b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-description.schema.php new file mode 100644 index 00000000..8bcb675d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-description.schema.php @@ -0,0 +1,5 @@ + +{{schema name="yoast/recipe-description" only-nested=true}} +{ + "name": {{html name="description"}} +} diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-ingredients.block.php b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-ingredients.block.php new file mode 100644 index 00000000..fe77b80c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-ingredients.block.php @@ -0,0 +1,15 @@ + +{{block name="yoast/recipe-ingredients" title="" description="" icon="" category="yoast-structured-data-blocks" parent=[ "yoast/recipe" ] supports={"multiple": false} }} +
    + {{heading name="title" defaultHeadingLevel=3 placeholder="" default="" }} + {{rich-text name="ingredients" tag="ul" multiline="li" placeholder="" }} +
    diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-ingredients.schema.php b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-ingredients.schema.php new file mode 100644 index 00000000..67c0d158 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-ingredients.schema.php @@ -0,0 +1,3 @@ + +{{schema name="yoast/recipe-ingredients" only-nested=true }} +{{list name="ingredients" tag="li" allowed-tags=[ "h1","h2","h3","h4","h5","h6","br","a","p","b","strong","i","em" ] }} diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-instructions.block.php b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-instructions.block.php new file mode 100644 index 00000000..a343d99a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-instructions.block.php @@ -0,0 +1,16 @@ + + +{{block name="yoast/recipe-instructions" title="" description="" icon="" category="yoast-structured-data-blocks" parent=[ "yoast/recipe" ] supports={"multiple": false} }} +
    + {{heading name="title" defaultHeadingLevel=3 placeholder="" default="" }} + {{rich-text name="instructions" tag="ol" multiline="li" placeholder="" }} +
    diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-instructions.schema.php b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-instructions.schema.php new file mode 100644 index 00000000..f70f73f6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-instructions.schema.php @@ -0,0 +1,3 @@ + +{{schema name="yoast/recipe-instructions" only-nested=true}} +{{recipe-instructions name="instructions" tag="li" allowed-tags=[ "h1","h2","h3","h4","h5","h6","br","a","p","b","strong","i","em" ] }} diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-name.block.php b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-name.block.php new file mode 100644 index 00000000..af54fe58 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-name.block.php @@ -0,0 +1,10 @@ + +{{block name="yoast/recipe-name" title="Recipe name" category="yoast-structured-data-blocks" parent=[ "yoast/recipe" ] }} +{{heading name="name" defaultHeadingLevel=2 placeholder="" }} diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-name.schema.php b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-name.schema.php new file mode 100644 index 00000000..d350004e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe-name.schema.php @@ -0,0 +1,5 @@ + +{{schema name="yoast/recipe-name" only-nested=true}} +{ + "name": {{html name="name"}} +} diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/recipe.block.php b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe.block.php new file mode 100644 index 00000000..7979e2cd --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe.block.php @@ -0,0 +1,40 @@ + 'yoast/recipe-name' ], + [ 'name' => 'core/image' ], + [ 'name' => 'yoast/recipe-ingredients' ], + [ 'name' => 'yoast/recipe-instructions' ], +]; + +$yoast_seo_recommended_blocks = [ + [ 'name' => 'yoast/cooking-time' ], + [ 'name' => 'yoast/preparation-time' ], + [ 'name' => 'yoast/recipe-description' ], +]; + +// phpcs:disable WordPress.Security.EscapeOutput -- Reason: WPSEO_Utils::format_json_encode is safe. +?> +{{block name="yoast/recipe" title="" category="yoast-structured-data-blocks" keywords=[ "SEO", "Schema"] description="" supports={"multiple": false} }} +{{sidebar-input name="yield" output=false type="number" label="" }} +
    + {{inner-blocks template= required-blocks= recommended-blocks= appender="button" appenderLabel="" }} +
    diff --git a/wp-content/plugins/wordpress-seo/src/schema-templates/recipe.schema.php b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe.schema.php new file mode 100644 index 00000000..272ffabb --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/schema-templates/recipe.schema.php @@ -0,0 +1,20 @@ + +{{schema name="yoast/recipe"}} +{ + "@type": "Recipe", + "@id": "{{block-id}}", + "mainEntityOfPage": { + "@id": "%%main_schema_id%%" + }, + "image": {{inner-blocks-id allowed-blocks=[ "core/image" ] only-first=true null-when-empty=true }}, + "name": {{inner-blocks-html blocks={ "yoast/recipe-name": "name" } null-when-empty=true allowed-tags=[ "h1","h2","h3","h4","h5","h6","br","a","p","b","strong","i","em", "ul", "ol", "li" ] }}, + "author": { + "@id": "%%author_id%%" + }, + "description": {{inner-blocks-html blocks={ "yoast/recipe-description": "description" } null-when-empty=true allowed-tags=[ "h1","h2","h3","h4","h5","h6","br","a","p","b","strong","i","em" ] }}, + "cookTime": {{inner-blocks allowed-blocks=[ "yoast/cooking-time" ] only-first=true }}, + "prepTime": {{inner-blocks allowed-blocks=[ "yoast/preparation-time" ] only-first=true }}, + "recipeInstructions": {{inner-blocks allowed-blocks=[ "yoast/recipe-instructions" ] only-first=true }}, + "recipeIngredient": {{inner-blocks allowed-blocks=[ "yoast/recipe-ingredients" ] only-first=true }}, + "recipeYield": {{attribute name="yield" }} +} diff --git a/wp-content/plugins/wordpress-seo/src/surfaces/classes-surface.php b/wp-content/plugins/wordpress-seo/src/surfaces/classes-surface.php new file mode 100644 index 00000000..f1bdfe17 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/surfaces/classes-surface.php @@ -0,0 +1,33 @@ +container = $container; + } + + /** + * Returns the instance of a class. Handy for unhooking things. + * + * @param string $class The class to get the instance of. + * + * @return mixed The instance of the class. + */ + public function get( $class ) { + return $this->container->get( $class ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/surfaces/helpers-surface.php b/wp-content/plugins/wordpress-seo/src/surfaces/helpers-surface.php new file mode 100644 index 00000000..c0e7c063 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/surfaces/helpers-surface.php @@ -0,0 +1,110 @@ +container = $container; + $this->open_graph = $open_graph; + $this->schema = $schema; + $this->twitter = $twitter; + } + + /** + * Magic getter for getting helper classes. + * + * @param string $helper The helper to get. + * + * @return mixed The helper class. + */ + public function __get( $helper ) { + $helper = \implode( '_', \array_map( 'ucfirst', \explode( '_', $helper ) ) ); + $class = "Yoast\WP\SEO\Helpers\\{$helper}_Helper"; + return $this->container->get( $class ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/surfaces/meta-surface.php b/wp-content/plugins/wordpress-seo/src/surfaces/meta-surface.php new file mode 100644 index 00000000..00358815 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/surfaces/meta-surface.php @@ -0,0 +1,373 @@ +container = $container; + $this->context_memoizer = $context_memoizer; + $this->repository = $indexable_repository; + $this->wp_rewrite_wrapper = $wp_rewrite_wrapper; + $this->indexable_helper = $indexable_helper; + } + + /** + * Returns the meta tags context for the current page. + * + * @return Meta The meta values. + */ + public function for_current_page() { + return $this->build_meta( $this->context_memoizer->for_current_page() ); + } + + /** + * Returns the meta tags context for the home page. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_home_page() { + $front_page_id = \get_option( 'page_on_front' ); + if ( \get_option( 'show_on_front' ) === 'page' && $front_page_id !== 0 ) { + $indexable = $this->repository->find_by_id_and_type( $front_page_id, 'post' ); + + if ( ! $indexable ) { + return false; + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Static_Home_Page' ) ); + } + + $indexable = $this->repository->find_for_home_page(); + + if ( ! $indexable ) { + return false; + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Home_Page' ) ); + } + + /** + * Returns the meta tags context for the posts page. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_posts_page() { + $posts_page_id = (int) \get_option( 'page_for_posts' ); + if ( $posts_page_id !== 0 ) { + $indexable = $this->repository->find_by_id_and_type( $posts_page_id, 'post' ); + + if ( ! $indexable ) { + return false; + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Static_Posts_Page' ) ); + } + + $indexable = $this->repository->find_for_home_page(); + + if ( ! $indexable ) { + return false; + } + + + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Home_Page' ) ); + } + + /** + * Returns the meta tags context for a post type archive. + * + * @param string|null $post_type Optional. The post type to get the archive meta for. Defaults to the current post type. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_post_type_archive( $post_type = null ) { + if ( $post_type === null ) { + $post_type = \get_post_type(); + } + + $indexable = $this->repository->find_for_post_type_archive( $post_type ); + + if ( ! $indexable ) { + return false; + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type_Archive' ) ); + } + + /** + * Returns the meta tags context for the search result page. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_search_result() { + $indexable = $this->repository->find_for_system_page( 'search-result' ); + + if ( ! $indexable ) { + return false; + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Search_Result_Page' ) ); + } + + /** + * Returns the meta tags context for the search result page. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_404() { + $indexable = $this->repository->find_for_system_page( '404' ); + + if ( ! $indexable ) { + return false; + } + + + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Error_Page' ) ); + } + + /** + * Returns the meta tags context for a post. + * + * @param int $id The ID of the post. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_post( $id ) { + $indexable = $this->repository->find_by_id_and_type( $id, 'post' ); + + if ( ! $indexable ) { + return false; + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type' ) ); + } + + /** + * Returns the meta tags context for a number of posts. + * + * @param int[] $ids The IDs of the posts. + * + * @return Meta[]|false The meta values. False if none could be found. + */ + public function for_posts( $ids ) { + $indexables = $this->repository->find_by_multiple_ids_and_type( $ids, 'post' ); + + if ( empty( $indexables ) ) { + return false; + } + + return \array_map( + function( $indexable ) { + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Post_Type' ) ); + }, + $indexables + ); + } + + /** + * Returns the meta tags context for a term. + * + * @param int $id The ID of the term. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_term( $id ) { + $indexable = $this->repository->find_by_id_and_type( $id, 'term' ); + + if ( ! $indexable ) { + return false; + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Term_Archive' ) ); + } + + /** + * Returns the meta tags context for an author. + * + * @param int $id The ID of the author. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_author( $id ) { + $indexable = $this->repository->find_by_id_and_type( $id, 'user' ); + + if ( ! $indexable ) { + return false; + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, 'Author_Archive' ) ); + } + + /** + * Returns the meta for an indexable. + * + * @param Indexable $indexable The indexable. + * @param string|null $page_type Optional. The page type if already known. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_indexable( $indexable, $page_type = null ) { + if ( \is_null( $page_type ) ) { + $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, $page_type ) ); + } + + /** + * Returns the meta for an indexable. + * + * @param Indexable[] $indexables The indexables. + * @param string|null $page_type Optional. The page type if already known. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_indexables( $indexables, $page_type = null ) { + $closure = function( $indexable ) use ( $page_type ) { + $this_page_type = $page_type; + if ( \is_null( $this_page_type ) ) { + $this_page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, $this_page_type ) ); + }; + + return \array_map( $closure, $indexables ); + } + + /** + * Returns the meta tags context for a url. + * + * @param string $url The url of the page. Required to be relative to the site url. + * + * @return Meta|false The meta values. False if none could be found. + */ + public function for_url( $url ) { + $url_parts = \wp_parse_url( $url ); + $site_parts = \wp_parse_url( \site_url() ); + if ( $url_parts['host'] !== $site_parts['host'] ) { + return false; + } + // Ensure the scheme is consistent with values in the DB. + $url = $site_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path']; + + if ( $this->is_date_archive_url( $url ) ) { + $indexable = $this->repository->find_for_date_archive(); + } + else { + $indexable = $this->repository->find_by_permalink( $url ); + } + + // If we still don't have an indexable abort, the WP globals could be anything so we can't use the unknown indexable. + if ( ! $indexable ) { + return false; + } + $page_type = $this->indexable_helper->get_page_type_for_indexable( $indexable ); + + if ( $page_type === false ) { + return false; + } + + return $this->build_meta( $this->context_memoizer->get( $indexable, $page_type ) ); + } + + /** + * Checks if a given URL is a date archive URL. + * + * @param string $url The url. + * + * @return bool + */ + protected function is_date_archive_url( $url ) { + $path = \wp_parse_url( $url, \PHP_URL_PATH ); + $path = \ltrim( $path, '/' ); + + $wp_rewrite = $this->wp_rewrite_wrapper->get(); + $date_rewrite = $wp_rewrite->generate_rewrite_rules( $wp_rewrite->get_date_permastruct(), \EP_DATE ); + $date_rewrite = \apply_filters( 'date_rewrite_rules', $date_rewrite ); + + foreach ( (array) $date_rewrite as $match => $query ) { + if ( \preg_match( "#^$match#", $path ) ) { + return true; + } + } + + return false; + } + + /** + * Creates a new meta value object + * + * @param Meta_Tags_Context $context The meta tags context. + * + * @return Meta The meta value + */ + protected function build_meta( Meta_Tags_Context $context ) { + return new Meta( $context, $this->container ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/surfaces/open-graph-helpers-surface.php b/wp-content/plugins/wordpress-seo/src/surfaces/open-graph-helpers-surface.php new file mode 100644 index 00000000..8260bbdb --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/surfaces/open-graph-helpers-surface.php @@ -0,0 +1,45 @@ +container = $container; + } + + /** + * Magic getter for getting helper classes. + * + * @param string $helper The helper to get. + * + * @return mixed The helper class. + */ + public function __get( $helper ) { + $helper = \implode( '_', \array_map( 'ucfirst', \explode( '_', $helper ) ) ); + $class = "Yoast\WP\SEO\Helpers\Open_Graph\\{$helper}_Helper"; + return $this->container->get( $class ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/surfaces/schema-helpers-surface.php b/wp-content/plugins/wordpress-seo/src/surfaces/schema-helpers-surface.php new file mode 100644 index 00000000..b9c25f57 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/surfaces/schema-helpers-surface.php @@ -0,0 +1,60 @@ +container = $container; + } + + /** + * Magic getter for getting helper classes. + * + * @param string $helper The helper to get. + * + * @return mixed The helper class. + */ + public function __get( $helper ) { + if ( \in_array( $helper, $this->capitalized_helpers, true ) ) { + $helper = \strtoupper( $helper ); + } + $helper = \implode( '_', \array_map( 'ucfirst', \explode( '_', $helper ) ) ); + $class = "Yoast\WP\SEO\Helpers\Schema\\{$helper}_Helper"; + + return $this->container->get( $class ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/surfaces/twitter-helpers-surface.php b/wp-content/plugins/wordpress-seo/src/surfaces/twitter-helpers-surface.php new file mode 100644 index 00000000..4f919628 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/surfaces/twitter-helpers-surface.php @@ -0,0 +1,45 @@ +container = $container; + } + + /** + * Magic getter for getting helper classes. + * + * @param string $helper The helper to get. + * + * @return mixed The helper class. + */ + public function __get( $helper ) { + $helper = \implode( '_', \array_map( 'ucfirst', \explode( '_', $helper ) ) ); + $class = "Yoast\WP\SEO\Helpers\Twitter\\{$helper}_Helper"; + return $this->container->get( $class ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/surfaces/values/meta.php b/wp-content/plugins/wordpress-seo/src/surfaces/values/meta.php new file mode 100644 index 00000000..b5400923 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/surfaces/values/meta.php @@ -0,0 +1,287 @@ +container = $container; + $this->context = $context; + + $this->helpers = $this->container->get( Helpers_Surface::class ); + $this->replace_vars = $this->container->get( WPSEO_Replace_Vars::class ); + $this->front_end = $this->container->get( Front_End_Integration::class ); + } + + /** + * Returns the output as would be presented in the head. + * + * @return object The HTML and JSON presentation of the head metadata. + */ + public function get_head() { + $presenters = $this->get_presenters(); + + /** This filter is documented in src/integrations/front-end-integration.php */ + $presentation = \apply_filters( 'wpseo_frontend_presentation', $this->context->presentation, $this->context ); + + $html_output = ''; + $json_head_fields = []; + + foreach ( $presenters as $presenter ) { + $presenter->presentation = $presentation; + $presenter->replace_vars = $this->replace_vars; + $presenter->helpers = $this->helpers; + + $html_output .= $this->create_html_presentation( $presenter ); + $json_field = $this->create_json_field( $presenter ); + + // Only use the output of presenters that could successfully present their data. + if ( $json_field !== null && ! empty( $json_field->key ) ) { + $json_head_fields[ $json_field->key ] = $json_field->value; + } + } + $html_output = \trim( $html_output ); + + return (object) [ + 'html' => $html_output, + 'json' => $json_head_fields, + ]; + } + + /** + * Magic getter for presenting values through the appropriate presenter, if it exists. + * + * @param string $name The property to get. + * + * @return mixed The value, as presented by teh appropriate presenter. + * + * @throws Exception If an invalid property is accessed. + */ + public function __get( $name ) { + /** This filter is documented in src/integrations/front-end-integration.php */ + $presentation = \apply_filters( 'wpseo_frontend_presentation', $this->context->presentation, $this->context ); + + if ( ! isset( $presentation->{$name} ) ) { + if ( isset( $this->context->{$name} ) ) { + $this->{$name} = $this->context->{$name}; + return $this->{$name}; + } + return null; + } + + $presenter_namespace = 'Yoast\WP\SEO\Presenters\\'; + $parts = \explode( '_', $name ); + if ( $parts[0] === 'twitter' ) { + $presenter_namespace .= 'Twitter\\'; + $parts = \array_slice( $parts, 1 ); + } + elseif ( $parts[0] === 'open' && $parts[1] === 'graph' ) { + $presenter_namespace .= 'Open_Graph\\'; + $parts = \array_slice( $parts, 2 ); + } + + $presenter_class = $presenter_namespace . \implode( '_', \array_map( 'ucfirst', $parts ) ) . '_Presenter'; + + if ( \class_exists( $presenter_class ) ) { + /** + * The indexable presenter. + * + * @var Abstract_Indexable_Presenter + */ + $presenter = new $presenter_class(); + $presenter->presentation = $presentation; + $presenter->helpers = $this->helpers; + $presenter->replace_vars = $this->replace_vars; + $value = $presenter->get(); + } + else { + $value = $presentation->{$name}; + } + + $this->{$name} = $value; + return $this->{$name}; + } + + /** + * Magic isset for ensuring properties on the presentation are recognised. + * + * @param string $name The property to get. + * + * @return bool Whether or not the requested property exists. + */ + public function __isset( $name ) { + return isset( $this->context->presentation->{$name} ); + } + + /** + * Strips all nested dependencies from the debug info. + * + * @return array + */ + public function __debugInfo() { + return [ 'context' => $this->context ]; + } + + /** + * Returns all presenters. + * + * @return Abstract_Indexable_Presenter[] + */ + protected function get_presenters() { + $presenters = $this->front_end->get_presenters( $this->context->page_type, $this->context ); + + if ( $this->context->page_type === 'Date_Archive' ) { + /** + * Define a filter that removes objects of type Rel_Next_Presenter or Rel_Prev_Presenter from a list. + * + * @param $presenter The presenter to verify. + * + * @return bool True if the presenter is not a Rel_Next or Rel_Prev presenter. + */ + $callback = static function ( $presenter ) { + return ! \is_a( $presenter, Rel_Next_Presenter::class ) + && ! \is_a( $presenter, Rel_Prev_Presenter::class ); + }; + $presenters = \array_filter( $presenters, $callback ); + } + + return $presenters; + } + + /** + * Uses the presenter to create a line of HTML. + * + * @param Abstract_Indexable_Presenter $presenter The presenter. + * + * @return string + */ + protected function create_html_presentation( $presenter ) { + $presenter_output = $presenter->present(); + if ( ! empty( $presenter_output ) ) { + return $presenter_output . \PHP_EOL; + } + return ''; + } + + /** + * Converts a presenter's key and value to JSON. + * + * @param Abstract_Indexable_Presenter $presenter The presenter whose key and value are to be converted to JSON. + * + * @return object + */ + protected function create_json_field( $presenter ) { + if ( $presenter->get_key() === 'NO KEY PROVIDED' ) { + return null; + } + + $value = $presenter->get(); + if ( empty( $value ) ) { + return null; + } + + return (object) [ + 'key' => $presenter->escape_key(), + 'value' => $value, + ]; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/values/images.php b/wp-content/plugins/wordpress-seo/src/values/images.php new file mode 100644 index 00000000..3b3d4adc --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/values/images.php @@ -0,0 +1,151 @@ +image = $image; + $this->url = $url; + } + + /** + * Adds an image to the list by image ID. + * + * @param int $image_id The image ID to add. + * + * @return void + */ + public function add_image_by_id( $image_id ) { + $image = $this->image->get_attachment_image_source( $image_id, $this->image_size ); + if ( $image ) { + $this->add_image( $image ); + } + } + + /** + * Adds an image to the list by image ID. + * + * @param string $image_meta JSON encoded image meta. + * + * @return void + */ + public function add_image_by_meta( $image_meta ) { + $this->add_image( (array) \json_decode( $image_meta ) ); + } + + /** + * Return the images array. + * + * @return array The images. + */ + public function get_images() { + return $this->images; + } + + /** + * Check whether we have images or not. + * + * @return bool True if we have images, false if we don't. + */ + public function has_images() { + return ! empty( $this->images ); + } + + /** + * Adds an image based on a given URL. + * + * @param string $url The given URL. + * + * @return number|null Returns the found image ID if it exists. Otherwise -1. + * If the URL is empty we return null. + */ + public function add_image_by_url( $url ) { + if ( empty( $url ) ) { + return null; + } + + $image_id = $this->image->get_attachment_by_url( $url ); + + if ( $image_id ) { + $this->add_image_by_id( $image_id ); + + return $image_id; + } + + $this->add_image( $url ); + + return -1; + } + + /** + * Adds an image to the list of images. + * + * @param string|array $image Image array. + * + * @return void + */ + public function add_image( $image ) { + if ( \is_string( $image ) ) { + $image = [ 'url' => $image ]; + } + + if ( ! \is_array( $image ) || empty( $image['url'] ) || ! \is_string( $image['url'] ) ) { + return; + } + + if ( $this->url->is_relative( $image['url'] ) && $image['url'][0] === '/' ) { + $image['url'] = $this->url->build_absolute_url( $image['url'] ); + } + + if ( \array_key_exists( $image['url'], $this->images ) ) { + return; + } + + $this->images[ $image['url'] ] = $image; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/values/open-graph/images.php b/wp-content/plugins/wordpress-seo/src/values/open-graph/images.php new file mode 100644 index 00000000..b1dd12c3 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/values/open-graph/images.php @@ -0,0 +1,56 @@ +open_graph_image = $open_graph_image; + } + + /** + * Outputs the images. + * + * @codeCoverageIgnore - The method is empty, nothing to test. + * + * @return void + */ + public function show() {} + + /** + * Adds an image to the list by image ID. + * + * @param int $image_id The image ID to add. + * + * @return void + */ + public function add_image_by_id( $image_id ) { + $attachment = $this->open_graph_image->get_image_by_id( $image_id ); + + if ( $attachment ) { + $this->add_image( $attachment ); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/src/values/semrush/semrush-token.php b/wp-content/plugins/wordpress-seo/src/values/semrush/semrush-token.php new file mode 100644 index 00000000..d43b64ae --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/values/semrush/semrush-token.php @@ -0,0 +1,129 @@ +access_token = $access_token; + + if ( empty( $access_token ) ) { + throw new Empty_Property_Exception( 'refresh_token' ); + } + + $this->refresh_token = $refresh_token; + + if ( empty( $expires ) ) { + throw new Empty_Property_Exception( 'expires' ); + } + + $this->expires = $expires; + + if ( \is_null( $has_expired ) ) { + throw new Empty_Property_Exception( 'has_expired' ); + } + + $this->has_expired = $has_expired; + $this->created_at = $created_at; + } + + /** + * Creates a new instance based on the passed response. + * + * @param AccessTokenInterface $response The response object to create a new instance from. + * + * @return SEMrush_Token The token object. + * + * @throws Empty_Property_Exception Exception thrown if a token property is empty. + */ + public static function from_response( AccessTokenInterface $response ) { + return new self( + $response->getToken(), + $response->getRefreshToken(), + $response->getExpires(), + $response->hasExpired(), + \time() + ); + } + + /** + * Determines whether or not the token has expired. + * + * @return bool Whether or not the token has expired. + */ + public function has_expired() { + return ( \time() >= $this->expires ) || $this->has_expired === true; + } + + /** + * Converts the object to an array. + * + * @return array The converted object. + */ + public function to_array() { + return [ + 'access_token' => $this->access_token, + 'refresh_token' => $this->refresh_token, + 'expires' => $this->expires, + 'has_expired' => $this->has_expired(), + 'created_at' => $this->created_at, + ]; + } +} diff --git a/wp-content/plugins/wordpress-seo/src/wordpress/wrapper.php b/wp-content/plugins/wordpress-seo/src/wordpress/wrapper.php new file mode 100644 index 00000000..1677224e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/wordpress/wrapper.php @@ -0,0 +1,64 @@ +getHeaders() as $name => $values ) { + $headers[ $name ] = \implode( ',', $values ); + } + + $args = [ + 'method' => $request->getMethod(), + 'headers' => $headers, + 'body' => (string) $request->getBody(), + 'httpVersion' => $request->getProtocolVersion(), + ]; + + if ( isset( $options['verify'] ) && $options['verify'] === false ) { + $args['sslverify'] = false; + } + if ( isset( $options['timeout'] ) ) { + $args['timeout'] = ( $options['timeout'] * 1000 ); + } + + $raw_response = \wp_remote_request( $request->getUri(), $args ); + if ( \is_wp_error( $raw_response ) ) { + $exception = new Exception( $raw_response->get_error_message() ); + return new RejectedPromise( $exception ); + } + + $response = new Response( + $raw_response['response']['code'], + $raw_response['headers']->getAll(), + $raw_response['body'], + $args['httpVersion'], + $raw_response['response']['message'] + ); + + return new FulfilledPromise( $response ); + } +} diff --git a/wp-content/plugins/wordpress-seo/src/wrappers/wp-rewrite-wrapper.php b/wp-content/plugins/wordpress-seo/src/wrappers/wp-rewrite-wrapper.php new file mode 100644 index 00000000..e06d0a1f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/src/wrappers/wp-rewrite-wrapper.php @@ -0,0 +1,20 @@ +prefixDirsPsr4[$search])) { - $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); foreach ($this->prefixDirsPsr4[$search] as $dir) { - if (file_exists($file = $dir . $pathEnd)) { + $length = $this->prefixLengthsPsr4[$first][$search]; + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { return $file; } } diff --git a/wp-content/plugins/wordpress-seo/vendor/composer/ClassLoader52.php b/wp-content/plugins/wordpress-seo/vendor/composer/ClassLoader52.php deleted file mode 100644 index d721c7e7..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/composer/ClassLoader52.php +++ /dev/null @@ -1,271 +0,0 @@ - - * - Jordi Boggiano - */ - -class xrstf_Composer52_ClassLoader { - private $prefixes = array(); - private $fallbackDirs = array(); - private $useIncludePath = false; - private $classMap = array(); - private $classMapAuthoratative = false; - private $allowUnderscore = false; - - /** - * @param boolean $flag true to allow class names with a leading underscore, false to disable - */ - public function setAllowUnderscore($flag) { - $this->allowUnderscore = (boolean) $flag; - } - - /** - * @return array - */ - public function getPrefixes() { - return $this->prefixes; - } - - /** - * Turns off searching the prefix and fallback directories for classes - * that have not been registered with the class map. - * - * @param bool $classMapAuthoratative - */ - public function setClassMapAuthoritative($classMapAuthoratative) { - $this->classMapAuthoratative = $classMapAuthoratative; - } - - /** - * Should class lookup fail if not found in the current class map? - * - * @return bool - */ - public function getClassMapAuthoratative() { - return $this->classMapAuthoratative; - } - - /** - * @return array - */ - public function getFallbackDirs() { - return $this->fallbackDirs; - } - - /** - * @return array - */ - public function getClassMap() { - return $this->classMap; - } - - /** - * @param array $classMap class to filename map - */ - public function addClassMap(array $classMap) { - if ($this->classMap) { - $this->classMap = array_merge($this->classMap, $classMap); - } - else { - $this->classMap = $classMap; - } - } - - /** - * Registers a set of classes, merging with any others previously set. - * - * @param string $prefix the classes prefix - * @param array|string $paths the location(s) of the classes - * @param bool $prepend prepend the location(s) - */ - public function add($prefix, $paths, $prepend = false) { - if (!$prefix) { - if ($prepend) { - $this->fallbackDirs = array_merge( - (array) $paths, - $this->fallbackDirs - ); - } - else { - $this->fallbackDirs = array_merge( - $this->fallbackDirs, - (array) $paths - ); - } - - return; - } - - if (!isset($this->prefixes[$prefix])) { - $this->prefixes[$prefix] = (array) $paths; - return; - } - - if ($prepend) { - $this->prefixes[$prefix] = array_merge( - (array) $paths, - $this->prefixes[$prefix] - ); - } - else { - $this->prefixes[$prefix] = array_merge( - $this->prefixes[$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of classes, replacing any others previously set. - * - * @param string $prefix the classes prefix - * @param array|string $paths the location(s) of the classes - */ - public function set($prefix, $paths) { - if (!$prefix) { - $this->fallbackDirs = (array) $paths; - return; - } - - $this->prefixes[$prefix] = (array) $paths; - } - - /** - * Turns on searching the include path for class files. - * - * @param bool $useIncludePath - */ - public function setUseIncludePath($useIncludePath) { - $this->useIncludePath = $useIncludePath; - } - - /** - * Can be used to check if the autoloader uses the include path to check - * for classes. - * - * @return bool - */ - public function getUseIncludePath() { - return $this->useIncludePath; - } - - /** - * Registers this instance as an autoloader. - */ - public function register() { - spl_autoload_register(array($this, 'loadClass'), true); - } - - /** - * Unregisters this instance as an autoloader. - */ - public function unregister() { - spl_autoload_unregister(array($this, 'loadClass')); - } - - /** - * Loads the given class or interface. - * - * @param string $class the name of the class - * @return bool|null true, if loaded - */ - public function loadClass($class) { - if ($file = $this->findFile($class)) { - include $file; - return true; - } - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class the name of the class - * @return string|null the path, if found - */ - public function findFile($class) { - if ('\\' === $class[0]) { - $class = substr($class, 1); - } - - if (isset($this->classMap[$class])) { - return $this->classMap[$class]; - } - elseif ($this->classMapAuthoratative) { - return false; - } - - $classPath = $this->getClassPath($class); - - foreach ($this->prefixes as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { - return $dir.DIRECTORY_SEPARATOR.$classPath; - } - } - } - } - - foreach ($this->fallbackDirs as $dir) { - if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { - return $dir.DIRECTORY_SEPARATOR.$classPath; - } - } - - if ($this->useIncludePath && $file = self::resolveIncludePath($classPath)) { - return $file; - } - - return $this->classMap[$class] = false; - } - - private function getClassPath($class) { - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR; - $className = substr($class, $pos + 1); - } - else { - // PEAR-like class name - $classPath = null; - $className = $class; - } - - $className = str_replace('_', DIRECTORY_SEPARATOR, $className); - - // restore the prefix - if ($this->allowUnderscore && DIRECTORY_SEPARATOR === $className[0]) { - $className[0] = '_'; - } - - $classPath .= $className.'.php'; - - return $classPath; - } - - public static function resolveIncludePath($classPath) { - $paths = explode(PATH_SEPARATOR, get_include_path()); - - foreach ($paths as $path) { - $path = rtrim($path, '/\\'); - - if ($file = file_exists($path.DIRECTORY_SEPARATOR.$file)) { - return $file; - } - } - - return false; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_classmap.php b/wp-content/plugins/wordpress-seo/vendor/composer/autoload_classmap.php index 49db42b4..d56fc952 100644 --- a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_classmap.php +++ b/wp-content/plugins/wordpress-seo/vendor/composer/autoload_classmap.php @@ -16,6 +16,7 @@ return array( 'Composer\\Installers\\BonefishInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/BonefishInstaller.php', 'Composer\\Installers\\CakePHPInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/CakePHPInstaller.php', 'Composer\\Installers\\ChefInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ChefInstaller.php', + 'Composer\\Installers\\CiviCrmInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/CiviCrmInstaller.php', 'Composer\\Installers\\ClanCatsFrameworkInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php', 'Composer\\Installers\\CockpitInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/CockpitInstaller.php', 'Composer\\Installers\\CodeIgniterInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php', @@ -23,6 +24,7 @@ return array( 'Composer\\Installers\\CraftInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/CraftInstaller.php', 'Composer\\Installers\\CroogoInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/CroogoInstaller.php', 'Composer\\Installers\\DecibelInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/DecibelInstaller.php', + 'Composer\\Installers\\DframeInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/DframeInstaller.php', 'Composer\\Installers\\DokuWikiInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/DokuWikiInstaller.php', 'Composer\\Installers\\DolibarrInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/DolibarrInstaller.php', 'Composer\\Installers\\DrupalInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/DrupalInstaller.php', @@ -40,6 +42,7 @@ return array( 'Composer\\Installers\\JoomlaInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/JoomlaInstaller.php', 'Composer\\Installers\\KanboardInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/KanboardInstaller.php', 'Composer\\Installers\\KirbyInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/KirbyInstaller.php', + 'Composer\\Installers\\KnownInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/KnownInstaller.php', 'Composer\\Installers\\KodiCMSInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/KodiCMSInstaller.php', 'Composer\\Installers\\KohanaInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/KohanaInstaller.php', 'Composer\\Installers\\LanManagementSystemInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php', @@ -49,11 +52,14 @@ return array( 'Composer\\Installers\\MODULEWorkInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php', 'Composer\\Installers\\MODXEvoInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MODXEvoInstaller.php', 'Composer\\Installers\\MagentoInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MagentoInstaller.php', + 'Composer\\Installers\\MajimaInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MajimaInstaller.php', 'Composer\\Installers\\MakoInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MakoInstaller.php', + 'Composer\\Installers\\MantisBTInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MantisBTInstaller.php', 'Composer\\Installers\\MauticInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MauticInstaller.php', 'Composer\\Installers\\MayaInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MayaInstaller.php', 'Composer\\Installers\\MediaWikiInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MediaWikiInstaller.php', 'Composer\\Installers\\MicroweberInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MicroweberInstaller.php', + 'Composer\\Installers\\ModxInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ModxInstaller.php', 'Composer\\Installers\\MoodleInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/MoodleInstaller.php', 'Composer\\Installers\\OctoberInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/OctoberInstaller.php', 'Composer\\Installers\\OntoWikiInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/OntoWikiInstaller.php', @@ -69,17 +75,22 @@ return array( 'Composer\\Installers\\PortoInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/PortoInstaller.php', 'Composer\\Installers\\PrestashopInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/PrestashopInstaller.php', 'Composer\\Installers\\PuppetInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/PuppetInstaller.php', + 'Composer\\Installers\\PxcmsInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/PxcmsInstaller.php', 'Composer\\Installers\\RadPHPInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/RadPHPInstaller.php', 'Composer\\Installers\\ReIndexInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ReIndexInstaller.php', + 'Composer\\Installers\\Redaxo5Installer' => $vendorDir . '/composer/installers/src/Composer/Installers/Redaxo5Installer.php', 'Composer\\Installers\\RedaxoInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/RedaxoInstaller.php', 'Composer\\Installers\\RoundcubeInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/RoundcubeInstaller.php', 'Composer\\Installers\\SMFInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/SMFInstaller.php', 'Composer\\Installers\\ShopwareInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ShopwareInstaller.php', 'Composer\\Installers\\SilverStripeInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/SilverStripeInstaller.php', + 'Composer\\Installers\\SiteDirectInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/SiteDirectInstaller.php', 'Composer\\Installers\\SyDESInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/SyDESInstaller.php', + 'Composer\\Installers\\SyliusInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/SyliusInstaller.php', 'Composer\\Installers\\Symfony1Installer' => $vendorDir . '/composer/installers/src/Composer/Installers/Symfony1Installer.php', 'Composer\\Installers\\TYPO3CmsInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php', 'Composer\\Installers\\TYPO3FlowInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php', + 'Composer\\Installers\\TaoInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/TaoInstaller.php', 'Composer\\Installers\\TheliaInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/TheliaInstaller.php', 'Composer\\Installers\\TuskInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/TuskInstaller.php', 'Composer\\Installers\\UserFrostingInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/UserFrostingInstaller.php', @@ -92,29 +103,33 @@ return array( 'Composer\\Installers\\ZendInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ZendInstaller.php', 'Composer\\Installers\\ZikulaInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/ZikulaInstaller.php', 'WPSEO_Abstract_Capability_Manager' => $baseDir . '/admin/capabilities/class-abstract-capability-manager.php', + 'WPSEO_Abstract_Metabox_Tab_With_Sections' => $baseDir . '/admin/metabox/class-abstract-sectioned-metabox-tab.php', 'WPSEO_Abstract_Post_Filter' => $baseDir . '/admin/filters/class-abstract-post-filter.php', 'WPSEO_Abstract_Role_Manager' => $baseDir . '/admin/roles/class-abstract-role-manager.php', + 'WPSEO_Add_Keyword_Modal' => $baseDir . '/src/deprecated/admin/add-keyword-modal.php', + 'WPSEO_Addon_Manager' => $baseDir . '/inc/class-addon-manager.php', 'WPSEO_Admin' => $baseDir . '/admin/class-admin.php', 'WPSEO_Admin_Asset' => $baseDir . '/admin/class-asset.php', + 'WPSEO_Admin_Asset_Analysis_Worker_Location' => $baseDir . '/admin/class-admin-asset-analysis-worker-location.php', 'WPSEO_Admin_Asset_Dev_Server_Location' => $baseDir . '/admin/class-admin-asset-dev-server-location.php', 'WPSEO_Admin_Asset_Location' => $baseDir . '/admin/class-admin-asset-location.php', 'WPSEO_Admin_Asset_Manager' => $baseDir . '/admin/class-admin-asset-manager.php', 'WPSEO_Admin_Asset_SEO_Location' => $baseDir . '/admin/class-admin-asset-seo-location.php', - 'WPSEO_Admin_Banner' => $baseDir . '/admin/banner/class-admin-banner.php', - 'WPSEO_Admin_Banner_Renderer' => $baseDir . '/admin/banner/class-admin-banner-renderer.php', - 'WPSEO_Admin_Banner_Sidebar' => $baseDir . '/admin/banner/class-admin-banner-sidebar.php', - 'WPSEO_Admin_Banner_Sidebar_Renderer' => $baseDir . '/admin/banner/class-admin-banner-sidebar-renderer.php', - 'WPSEO_Admin_Banner_Spot' => $baseDir . '/admin/banner/class-admin-banner-spot.php', - 'WPSEO_Admin_Banner_Spot_Renderer' => $baseDir . '/admin/banner/class-admin-banner-spot-renderer.php', + 'WPSEO_Admin_Asset_Yoast_Components_L10n' => $baseDir . '/admin/class-admin-asset-yoast-components-l10n.php', + 'WPSEO_Admin_Bar_Menu' => $baseDir . '/inc/class-wpseo-admin-bar-menu.php', + 'WPSEO_Admin_Editor_Specific_Replace_Vars' => $baseDir . '/admin/class-admin-editor-specific-replace-vars.php', + 'WPSEO_Admin_Gutenberg_Compatibility_Notification' => $baseDir . '/admin/class-admin-gutenberg-compatibility-notification.php', 'WPSEO_Admin_Help_Panel' => $baseDir . '/admin/class-admin-help-panel.php', 'WPSEO_Admin_Init' => $baseDir . '/admin/class-admin-init.php', 'WPSEO_Admin_Menu' => $baseDir . '/admin/menu/class-admin-menu.php', 'WPSEO_Admin_Pages' => $baseDir . '/admin/class-config.php', + 'WPSEO_Admin_Recommended_Replace_Vars' => $baseDir . '/admin/class-admin-recommended-replace-vars.php', + 'WPSEO_Admin_Settings_Changed_Listener' => $baseDir . '/admin/admin-settings-changed-listener.php', 'WPSEO_Admin_User_Profile' => $baseDir . '/admin/class-admin-user-profile.php', 'WPSEO_Admin_Utils' => $baseDir . '/admin/class-admin-utils.php', - 'WPSEO_Advanced_Settings' => $baseDir . '/deprecated/class-wpseo-advanced-settings.php', 'WPSEO_Author_Sitemap_Provider' => $baseDir . '/inc/sitemaps/class-author-sitemap-provider.php', - 'WPSEO_Breadcrumbs' => $baseDir . '/frontend/class-breadcrumbs.php', + 'WPSEO_Base_Menu' => $baseDir . '/admin/menu/class-base-menu.php', + 'WPSEO_Breadcrumbs' => $baseDir . '/src/deprecated/frontend/breadcrumbs.php', 'WPSEO_Bulk_Description_List_Table' => $baseDir . '/admin/class-bulk-description-editor-list-table.php', 'WPSEO_Bulk_List_Table' => $baseDir . '/admin/class-bulk-editor-list-table.php', 'WPSEO_Bulk_Title_Editor_List_Table' => $baseDir . '/admin/class-bulk-title-editor-list-table.php', @@ -127,42 +142,37 @@ return array( 'WPSEO_Collection' => $baseDir . '/admin/interface-collection.php', 'WPSEO_Collector' => $baseDir . '/admin/class-collector.php', 'WPSEO_Config_Component' => $baseDir . '/admin/config-ui/components/interface-component.php', - 'WPSEO_Config_Component_Configuration_Choices' => $baseDir . '/admin/config-ui/components/class-component-configuration-choices.php', - 'WPSEO_Config_Component_Connect_Google_Search_Console' => $baseDir . '/admin/config-ui/components/class-component-connect-google-search-console.php', 'WPSEO_Config_Component_Mailchimp_Signup' => $baseDir . '/admin/config-ui/components/class-component-mailchimp-signup.php', 'WPSEO_Config_Component_Suggestions' => $baseDir . '/admin/config-ui/components/class-component-suggestions.php', 'WPSEO_Config_Factory_Post_Type' => $baseDir . '/admin/config-ui/factories/class-factory-post-type.php', 'WPSEO_Config_Field' => $baseDir . '/admin/config-ui/fields/class-field.php', 'WPSEO_Config_Field_Choice' => $baseDir . '/admin/config-ui/fields/class-field-choice.php', 'WPSEO_Config_Field_Choice_Post_Type' => $baseDir . '/admin/config-ui/fields/class-field-choice-post-type.php', + 'WPSEO_Config_Field_Company_Info_Missing' => $baseDir . '/admin/config-ui/fields/class-field-company-info-missing.php', 'WPSEO_Config_Field_Company_Logo' => $baseDir . '/admin/config-ui/fields/class-field-company-logo.php', 'WPSEO_Config_Field_Company_Name' => $baseDir . '/admin/config-ui/fields/class-field-company-name.php', 'WPSEO_Config_Field_Company_Or_Person' => $baseDir . '/admin/config-ui/fields/class-field-company-or-person.php', - 'WPSEO_Config_Field_Configuration_Choices' => $baseDir . '/admin/config-ui/fields/class-field-configuration-choices.php', - 'WPSEO_Config_Field_Connect_Google_Search_Console' => $baseDir . '/admin/config-ui/fields/class-field-connect-google-search-console.php', 'WPSEO_Config_Field_Environment' => $baseDir . '/admin/config-ui/fields/class-field-environment.php', - 'WPSEO_Config_Field_Google_Search_Console_Intro' => $baseDir . '/admin/config-ui/fields/class-field-google-search-console-intro.php', 'WPSEO_Config_Field_Mailchimp_Signup' => $baseDir . '/admin/config-ui/fields/class-field-mailchimp-signup.php', 'WPSEO_Config_Field_Multiple_Authors' => $baseDir . '/admin/config-ui/fields/class-field-multiple-authors.php', - 'WPSEO_Config_Field_Person_Name' => $baseDir . '/admin/config-ui/fields/class-field-person-name.php', + 'WPSEO_Config_Field_Person' => $baseDir . '/admin/config-ui/fields/class-field-person.php', 'WPSEO_Config_Field_Post_Type_Visibility' => $baseDir . '/admin/config-ui/fields/class-field-post-type-visibility.php', 'WPSEO_Config_Field_Profile_URL_Facebook' => $baseDir . '/admin/config-ui/fields/class-field-profile-url-facebook.php', - 'WPSEO_Config_Field_Profile_URL_GooglePlus' => $baseDir . '/admin/config-ui/fields/class-field-profile-url-googleplus.php', 'WPSEO_Config_Field_Profile_URL_Instagram' => $baseDir . '/admin/config-ui/fields/class-field-profile-url-instagram.php', 'WPSEO_Config_Field_Profile_URL_LinkedIn' => $baseDir . '/admin/config-ui/fields/class-field-profile-url-linkedin.php', 'WPSEO_Config_Field_Profile_URL_MySpace' => $baseDir . '/admin/config-ui/fields/class-field-profile-url-myspace.php', 'WPSEO_Config_Field_Profile_URL_Pinterest' => $baseDir . '/admin/config-ui/fields/class-field-profile-url-pinterest.php', 'WPSEO_Config_Field_Profile_URL_Twitter' => $baseDir . '/admin/config-ui/fields/class-field-profile-url-twitter.php', + 'WPSEO_Config_Field_Profile_URL_Wikipedia' => $baseDir . '/admin/config-ui/fields/class-field-profile-url-wikipedia.php', 'WPSEO_Config_Field_Profile_URL_YouTube' => $baseDir . '/admin/config-ui/fields/class-field-profile-url-youtube.php', 'WPSEO_Config_Field_Separator' => $baseDir . '/admin/config-ui/fields/class-field-separator.php', 'WPSEO_Config_Field_Site_Name' => $baseDir . '/admin/config-ui/fields/class-field-site-name.php', 'WPSEO_Config_Field_Site_Type' => $baseDir . '/admin/config-ui/fields/class-field-site-type.php', - 'WPSEO_Config_Field_Social_Profiles_Intro' => $baseDir . '/admin/config-ui/fields/class-field-social-profiles-intro.php', 'WPSEO_Config_Field_Success_Message' => $baseDir . '/admin/config-ui/fields/class-field-success-message.php', 'WPSEO_Config_Field_Suggestions' => $baseDir . '/admin/config-ui/fields/class-field-suggestions.php', 'WPSEO_Config_Field_Title_Intro' => $baseDir . '/admin/config-ui/fields/class-field-title-intro.php', - 'WPSEO_Config_Field_Upsell_Configuration_Service' => $baseDir . '/admin/config-ui/fields/class-field-upsell-configuration-service.php', - 'WPSEO_Config_Field_Upsell_Site_Review' => $baseDir . '/admin/config-ui/fields/class-field-upsell-site-review.php', + 'WPSEO_Config_Field_Tracking' => $baseDir . '/admin/config-ui/fields/class-field-tracking.php', + 'WPSEO_Config_Field_Tracking_Intro' => $baseDir . '/admin/config-ui/fields/class-field-tracking-intro.php', 'WPSEO_Configuration_Components' => $baseDir . '/admin/config-ui/class-configuration-components.php', 'WPSEO_Configuration_Endpoint' => $baseDir . '/admin/config-ui/class-configuration-endpoint.php', 'WPSEO_Configuration_Notifier' => $baseDir . '/admin/notifiers/class-configuration-notifier.php', @@ -172,108 +182,104 @@ return array( 'WPSEO_Configuration_Storage' => $baseDir . '/admin/config-ui/class-configuration-storage.php', 'WPSEO_Configuration_Structure' => $baseDir . '/admin/config-ui/class-configuration-structure.php', 'WPSEO_Configuration_Translations' => $baseDir . '/admin/config-ui/class-configuration-translations.php', - 'WPSEO_Cornerstone' => $baseDir . '/admin/class-cornerstone.php', - 'WPSEO_Cornerstone_Field' => $baseDir . '/admin/class-cornerstone-field.php', + 'WPSEO_Content_Images' => $baseDir . '/inc/class-wpseo-content-images.php', 'WPSEO_Cornerstone_Filter' => $baseDir . '/admin/filters/class-cornerstone-filter.php', + 'WPSEO_Custom_Fields' => $baseDir . '/inc/class-wpseo-custom-fields.php', + 'WPSEO_Custom_Taxonomies' => $baseDir . '/inc/class-wpseo-custom-taxonomies.php', 'WPSEO_Customizer' => $baseDir . '/admin/class-customizer.php', 'WPSEO_Database_Proxy' => $baseDir . '/admin/class-database-proxy.php', + 'WPSEO_Date_Helper' => $baseDir . '/inc/date-helper.php', + 'WPSEO_Deprecated_Graph_Piece' => $baseDir . '/src/deprecated/frontend/abstract-class-deprecated-schema-piece.php', + 'WPSEO_Dismissible_Notification' => $baseDir . '/admin/notifiers/dismissible-notification.php', 'WPSEO_Endpoint' => $baseDir . '/admin/endpoints/class-endpoint.php', - 'WPSEO_Endpoint_Ryte' => $baseDir . '/admin/endpoints/class-endpoint-ryte.php', + 'WPSEO_Endpoint_File_Size' => $baseDir . '/admin/endpoints/class-endpoint-file-size.php', + 'WPSEO_Endpoint_Ryte' => $baseDir . '/src/deprecated/admin/endpoints/class-endpoint-ryte.php', 'WPSEO_Endpoint_Statistics' => $baseDir . '/admin/endpoints/class-endpoint-statistics.php', 'WPSEO_Export' => $baseDir . '/admin/class-export.php', - 'WPSEO_Extension' => $baseDir . '/admin/class-extension.php', - 'WPSEO_Extension_Manager' => $baseDir . '/admin/class-extension-manager.php', - 'WPSEO_Extensions' => $baseDir . '/admin/class-extensions.php', + 'WPSEO_Expose_Shortlinks' => $baseDir . '/admin/class-expose-shortlinks.php', + 'WPSEO_Extension' => $baseDir . '/src/deprecated/admin/extension.php', + 'WPSEO_Extension_Manager' => $baseDir . '/src/deprecated/admin/extension-manager.php', + 'WPSEO_Extensions' => $baseDir . '/src/deprecated/admin/extensions.php', 'WPSEO_Features' => $baseDir . '/inc/class-wpseo-features.php', - 'WPSEO_Frontend' => $baseDir . '/frontend/class-frontend.php', - 'WPSEO_Frontend_Page_Type' => $baseDir . '/frontend/class-frontend-page-type.php', - 'WPSEO_Frontend_Primary_Category' => $baseDir . '/frontend/class-primary-category.php', + 'WPSEO_File_Size_Exception' => $baseDir . '/admin/exceptions/class-file-size-exception.php', + 'WPSEO_File_Size_Service' => $baseDir . '/admin/services/class-file-size.php', + 'WPSEO_Frontend' => $baseDir . '/src/deprecated/frontend/frontend.php', + 'WPSEO_Frontend_Page_Type' => $baseDir . '/src/deprecated/frontend/class-frontend-page-type.php', + 'WPSEO_Frontend_Primary_Category' => $baseDir . '/src/deprecated/frontend/class-primary-category.php', 'WPSEO_GSC' => $baseDir . '/admin/google_search_console/class-gsc.php', - 'WPSEO_GSC_Ajax' => $baseDir . '/admin/google_search_console/class-gsc-ajax.php', - 'WPSEO_GSC_Bulk_Action' => $baseDir . '/admin/google_search_console/class-gsc-bulk-action.php', - 'WPSEO_GSC_Category_Filters' => $baseDir . '/admin/google_search_console/class-gsc-category-filters.php', - 'WPSEO_GSC_Config' => $baseDir . '/admin/google_search_console/class-gsc-config.php', - 'WPSEO_GSC_Count' => $baseDir . '/admin/google_search_console/class-gsc-count.php', - 'WPSEO_GSC_Issue' => $baseDir . '/admin/google_search_console/class-gsc-issue.php', - 'WPSEO_GSC_Issues' => $baseDir . '/admin/google_search_console/class-gsc-issues.php', - 'WPSEO_GSC_Mapper' => $baseDir . '/admin/google_search_console/class-gsc-mapper.php', - 'WPSEO_GSC_Marker' => $baseDir . '/admin/google_search_console/class-gsc-marker.php', - 'WPSEO_GSC_Modal' => $baseDir . '/admin/google_search_console/class-gsc-modal.php', - 'WPSEO_GSC_Platform_Tabs' => $baseDir . '/admin/google_search_console/class-gsc-platform-tabs.php', - 'WPSEO_GSC_Service' => $baseDir . '/admin/google_search_console/class-gsc-service.php', - 'WPSEO_GSC_Settings' => $baseDir . '/admin/google_search_console/class-gsc-settings.php', - 'WPSEO_GSC_Table' => $baseDir . '/admin/google_search_console/class-gsc-table.php', - 'WPSEO_Help_Center' => $baseDir . '/admin/class-help-center.php', - 'WPSEO_Help_Center_Item' => $baseDir . '/admin/class-help-center-item.php', + 'WPSEO_Graph_Piece' => $baseDir . '/src/deprecated/frontend/schema/interface-wpseo-graph-piece.php', + 'WPSEO_Gutenberg_Compatibility' => $baseDir . '/admin/class-gutenberg-compatibility.php', + 'WPSEO_Handle_404' => $baseDir . '/src/deprecated/frontend/class-handle-404.php', + 'WPSEO_Health_Check' => $baseDir . '/inc/health-check.php', + 'WPSEO_Health_Check_Curl_Version' => $baseDir . '/inc/health-check-curl-version.php', + 'WPSEO_Health_Check_Default_Tagline' => $baseDir . '/inc/health-check-default-tagline.php', + 'WPSEO_Health_Check_Link_Table_Not_Accessible' => $baseDir . '/inc/health-check-links-table-not-accessible.php', + 'WPSEO_Health_Check_Page_Comments' => $baseDir . '/inc/health-check-page-comments.php', + 'WPSEO_Health_Check_Postname_Permalink' => $baseDir . '/inc/health-check-postname-permalink.php', + 'WPSEO_Health_Check_Ryte' => $baseDir . '/inc/health-check-ryte.php', + 'WPSEO_HelpScout' => $baseDir . '/admin/class-helpscout.php', + 'WPSEO_Image_Utils' => $baseDir . '/inc/class-wpseo-image-utils.php', 'WPSEO_Import_AIOSEO' => $baseDir . '/admin/import/plugins/class-import-aioseo.php', + 'WPSEO_Import_Greg_SEO' => $baseDir . '/admin/import/plugins/class-import-greg-high-performance-seo.php', 'WPSEO_Import_HeadSpace' => $baseDir . '/admin/import/plugins/class-import-headspace.php', 'WPSEO_Import_Jetpack_SEO' => $baseDir . '/admin/import/plugins/class-import-jetpack.php', + 'WPSEO_Import_Platinum_SEO' => $baseDir . '/admin/import/plugins/class-import-platinum-seo-pack.php', 'WPSEO_Import_Plugin' => $baseDir . '/admin/import/class-import-plugin.php', 'WPSEO_Import_Plugins_Detector' => $baseDir . '/admin/import/class-import-detector.php', + 'WPSEO_Import_Premium_SEO_Pack' => $baseDir . '/admin/import/plugins/class-import-premium-seo-pack.php', + 'WPSEO_Import_RankMath' => $baseDir . '/admin/import/plugins/class-import-rankmath.php', 'WPSEO_Import_SEOPressor' => $baseDir . '/admin/import/plugins/class-import-seopressor.php', + 'WPSEO_Import_SEO_Framework' => $baseDir . '/admin/import/plugins/class-import-seo-framework.php', 'WPSEO_Import_Settings' => $baseDir . '/admin/import/class-import-settings.php', + 'WPSEO_Import_Smartcrawl_SEO' => $baseDir . '/admin/import/plugins/class-import-smartcrawl.php', + 'WPSEO_Import_Squirrly' => $baseDir . '/admin/import/plugins/class-import-squirrly.php', 'WPSEO_Import_Status' => $baseDir . '/admin/import/class-import-status.php', 'WPSEO_Import_Ultimate_SEO' => $baseDir . '/admin/import/plugins/class-import-ultimate-seo.php', 'WPSEO_Import_WPSEO' => $baseDir . '/admin/import/plugins/class-import-wpseo.php', + 'WPSEO_Import_WP_Meta_SEO' => $baseDir . '/admin/import/plugins/class-import-wp-meta-seo.php', 'WPSEO_Import_WooThemes_SEO' => $baseDir . '/admin/import/plugins/class-import-woothemes-seo.php', 'WPSEO_Installable' => $baseDir . '/admin/interface-installable.php', 'WPSEO_Installation' => $baseDir . '/inc/class-wpseo-installation.php', - 'WPSEO_JSON_LD' => $baseDir . '/frontend/class-json-ld.php', + 'WPSEO_Keyword_Synonyms_Modal' => $baseDir . '/src/deprecated/admin/keyword-synonyms-modal.php', 'WPSEO_Language_Utils' => $baseDir . '/inc/language-utils.php', - 'WPSEO_License_Page_Manager' => $baseDir . '/admin/class-license-page-manager.php', - 'WPSEO_Link' => $baseDir . '/admin/links/class-link.php', - 'WPSEO_Link_Cleanup_Transient' => $baseDir . '/admin/links/class-link-cleanup-transient.php', - 'WPSEO_Link_Column_Count' => $baseDir . '/admin/links/class-link-column-count.php', - 'WPSEO_Link_Columns' => $baseDir . '/admin/links/class-link-columns.php', - 'WPSEO_Link_Compatibility_Notifier' => $baseDir . '/admin/links/class-link-compatibility-notifier.php', - 'WPSEO_Link_Content_Processor' => $baseDir . '/admin/links/class-link-content-processor.php', - 'WPSEO_Link_Extractor' => $baseDir . '/admin/links/class-link-extractor.php', - 'WPSEO_Link_Factory' => $baseDir . '/admin/links/class-link-factory.php', - 'WPSEO_Link_Filter' => $baseDir . '/admin/links/class-link-filter.php', - 'WPSEO_Link_Installer' => $baseDir . '/admin/links/class-link-installer.php', - 'WPSEO_Link_Internal_Lookup' => $baseDir . '/admin/links/class-link-internal-lookup.php', - 'WPSEO_Link_Notifier' => $baseDir . '/admin/links/class-link-notifier.php', - 'WPSEO_Link_Query' => $baseDir . '/admin/links/class-link-query.php', - 'WPSEO_Link_Reindex_Dashboard' => $baseDir . '/admin/links/class-link-reindex-dashboard.php', - 'WPSEO_Link_Reindex_Post_Endpoint' => $baseDir . '/admin/links/class-link-reindex-post-endpoint.php', - 'WPSEO_Link_Reindex_Post_Service' => $baseDir . '/admin/links/class-link-reindex-post-service.php', - 'WPSEO_Link_Storage' => $baseDir . '/admin/links/class-link-storage.php', - 'WPSEO_Link_Table_Accessible' => $baseDir . '/admin/links/class-link-table-accessible.php', - 'WPSEO_Link_Table_Accessible_Notifier' => $baseDir . '/admin/links/class-link-table-accessible-notifier.php', - 'WPSEO_Link_Type_Classifier' => $baseDir . '/admin/links/class-link-type-classifier.php', - 'WPSEO_Link_Utils' => $baseDir . '/admin/links/class-link-utils.php', - 'WPSEO_Link_Watcher' => $baseDir . '/admin/links/class-link-watcher.php', - 'WPSEO_Link_Watcher_Loader' => $baseDir . '/admin/links/class-link-watcher-loader.php', + 'WPSEO_License_Page_Manager' => $baseDir . '/src/deprecated/admin/license-page-manager.php', + 'WPSEO_Link_Compatibility_Notifier' => $baseDir . '/src/deprecated/admin/links/class-link-compatibility-notifier.php', + 'WPSEO_Link_Table_Accessible_Notifier' => $baseDir . '/src/deprecated/admin/links/class-link-table-accessible-notifier.php', 'WPSEO_Listener' => $baseDir . '/admin/listeners/class-listener.php', 'WPSEO_Menu' => $baseDir . '/admin/menu/class-menu.php', 'WPSEO_Meta' => $baseDir . '/inc/class-wpseo-meta.php', 'WPSEO_Meta_Columns' => $baseDir . '/admin/class-meta-columns.php', - 'WPSEO_Meta_Storage' => $baseDir . '/admin/class-meta-storage.php', - 'WPSEO_Meta_Table_Accessible' => $baseDir . '/admin/class-meta-table-accessible.php', 'WPSEO_Metabox' => $baseDir . '/admin/metabox/class-metabox.php', - 'WPSEO_Metabox_Add_Keyword_Tab' => $baseDir . '/admin/metabox/class-metabox-add-keyword-tab.php', - 'WPSEO_Metabox_Addon_Tab_Section' => $baseDir . '/admin/metabox/class-metabox-addon-section.php', 'WPSEO_Metabox_Analysis' => $baseDir . '/admin/metabox/interface-metabox-analysis.php', 'WPSEO_Metabox_Analysis_Readability' => $baseDir . '/admin/metabox/class-metabox-analysis-readability.php', 'WPSEO_Metabox_Analysis_SEO' => $baseDir . '/admin/metabox/class-metabox-analysis-seo.php', + 'WPSEO_Metabox_Collapsible' => $baseDir . '/admin/metabox/class-metabox-collapsible.php', + 'WPSEO_Metabox_Collapsibles_Sections' => $baseDir . '/admin/metabox/class-metabox-collapsibles-section.php', 'WPSEO_Metabox_Editor' => $baseDir . '/admin/metabox/class-metabox-editor.php', 'WPSEO_Metabox_Form_Tab' => $baseDir . '/admin/metabox/class-metabox-form-tab.php', 'WPSEO_Metabox_Formatter' => $baseDir . '/admin/formatter/class-metabox-formatter.php', 'WPSEO_Metabox_Formatter_Interface' => $baseDir . '/admin/formatter/interface-metabox-formatter.php', 'WPSEO_Metabox_Null_Tab' => $baseDir . '/admin/metabox/class-metabox-null-tab.php', 'WPSEO_Metabox_Section' => $baseDir . '/admin/metabox/interface-metabox-section.php', + 'WPSEO_Metabox_Section_Additional' => $baseDir . '/admin/metabox/class-metabox-section-additional.php', + 'WPSEO_Metabox_Section_React' => $baseDir . '/admin/metabox/class-metabox-section-react.php', + 'WPSEO_Metabox_Section_Readability' => $baseDir . '/admin/metabox/class-metabox-section-readability.php', 'WPSEO_Metabox_Tab' => $baseDir . '/admin/metabox/interface-metabox-tab.php', - 'WPSEO_Metabox_Tab_Section' => $baseDir . '/admin/metabox/class-metabox-tab-section.php', + 'WPSEO_Multiple_Keywords_Modal' => $baseDir . '/src/deprecated/admin/multiple-keywords-modal.php', + 'WPSEO_MyYoast_Api_Request' => $baseDir . '/inc/class-my-yoast-api-request.php', + 'WPSEO_MyYoast_Bad_Request_Exception' => $baseDir . '/inc/exceptions/class-myyoast-bad-request-exception.php', + 'WPSEO_MyYoast_Invalid_JSON_Exception' => $baseDir . '/inc/exceptions/class-myyoast-invalid-json-exception.php', + 'WPSEO_MyYoast_Proxy' => $baseDir . '/admin/class-my-yoast-proxy.php', 'WPSEO_Network_Admin_Menu' => $baseDir . '/admin/menu/class-network-admin-menu.php', - 'WPSEO_OnPage' => $baseDir . '/admin/onpage/class-onpage.php', - 'WPSEO_OnPage_Option' => $baseDir . '/admin/onpage/class-onpage-option.php', - 'WPSEO_OnPage_Request' => $baseDir . '/admin/onpage/class-onpage-request.php', - 'WPSEO_OpenGraph' => $baseDir . '/frontend/class-opengraph.php', - 'WPSEO_OpenGraph_Image' => $baseDir . '/frontend/class-opengraph-image.php', + 'WPSEO_Notification_Handler' => $baseDir . '/admin/notifiers/interface-notification-handler.php', + 'WPSEO_OnPage' => $baseDir . '/src/deprecated/admin/onpage/class-onpage.php', + 'WPSEO_OnPage_Option' => $baseDir . '/src/deprecated/admin/onpage/class-onpage-option.php', + 'WPSEO_OnPage_Request' => $baseDir . '/src/deprecated/admin/onpage/class-onpage-request.php', + 'WPSEO_OpenGraph' => $baseDir . '/src/deprecated/frontend/class-opengraph.php', + 'WPSEO_OpenGraph_Image' => $baseDir . '/src/deprecated/frontend/class-opengraph-image.php', + 'WPSEO_OpenGraph_OEmbed' => $baseDir . '/src/deprecated/frontend/class-opengraph-oembed.php', 'WPSEO_Option' => $baseDir . '/inc/options/class-wpseo-option.php', - 'WPSEO_Option_InternalLinks' => $baseDir . '/deprecated/class-wpseo-option-internallinks.php', 'WPSEO_Option_MS' => $baseDir . '/inc/options/class-wpseo-option-ms.php', - 'WPSEO_Option_Permalinks' => $baseDir . '/deprecated/class-wpseo-option-permalinks.php', 'WPSEO_Option_Social' => $baseDir . '/inc/options/class-wpseo-option-social.php', 'WPSEO_Option_Tab' => $baseDir . '/admin/class-option-tab.php', 'WPSEO_Option_Tabs' => $baseDir . '/admin/class-option-tabs.php', @@ -281,14 +287,14 @@ return array( 'WPSEO_Option_Titles' => $baseDir . '/inc/options/class-wpseo-option-titles.php', 'WPSEO_Option_Wpseo' => $baseDir . '/inc/options/class-wpseo-option-wpseo.php', 'WPSEO_Options' => $baseDir . '/inc/options/class-wpseo-options.php', - 'WPSEO_Options_Backfill' => $baseDir . '/inc/options/class-wpseo-options-backfill.php', + 'WPSEO_Paper_Presenter' => $baseDir . '/admin/class-paper-presenter.php', 'WPSEO_Plugin_Availability' => $baseDir . '/admin/class-plugin-availability.php', - 'WPSEO_Plugin_Compatibility' => $baseDir . '/admin/class-plugin-compatibility.php', 'WPSEO_Plugin_Conflict' => $baseDir . '/admin/class-plugin-conflict.php', 'WPSEO_Plugin_Importer' => $baseDir . '/admin/import/plugins/class-abstract-plugin-importer.php', 'WPSEO_Plugin_Importers' => $baseDir . '/admin/import/plugins/class-importers.php', 'WPSEO_Post_Metabox_Formatter' => $baseDir . '/admin/formatter/class-post-metabox-formatter.php', 'WPSEO_Post_Type' => $baseDir . '/inc/class-post-type.php', + 'WPSEO_Post_Type_Archive_Notification_Handler' => $baseDir . '/src/deprecated/admin/notifiers/class-post-type-archive-notification-handler.php', 'WPSEO_Post_Type_Sitemap_Provider' => $baseDir . '/inc/sitemaps/class-post-type-sitemap-provider.php', 'WPSEO_Premium_Popup' => $baseDir . '/admin/class-premium-popup.php', 'WPSEO_Premium_Upsell_Admin_Block' => $baseDir . '/admin/class-premium-upsell-admin-block.php', @@ -296,29 +302,50 @@ return array( 'WPSEO_Primary_Term_Admin' => $baseDir . '/admin/class-primary-term-admin.php', 'WPSEO_Product_Upsell_Notice' => $baseDir . '/admin/class-product-upsell-notice.php', 'WPSEO_Rank' => $baseDir . '/inc/class-wpseo-rank.php', - 'WPSEO_Recalculate' => $baseDir . '/admin/recalculate/class-recalculate.php', - 'WPSEO_Recalculate_Posts' => $baseDir . '/admin/recalculate/class-recalculate-posts.php', - 'WPSEO_Recalculate_Scores' => $baseDir . '/admin/class-recalculate-scores.php', - 'WPSEO_Recalculate_Scores_Ajax' => $baseDir . '/admin/ajax/class-recalculate-scores-ajax.php', - 'WPSEO_Recalculate_Terms' => $baseDir . '/admin/recalculate/class-recalculate-terms.php', + 'WPSEO_Recalculate' => $baseDir . '/src/deprecated/admin/recalculate/class-recalculate.php', + 'WPSEO_Recalculate_Posts' => $baseDir . '/src/deprecated/admin/recalculate/class-recalculate-posts.php', + 'WPSEO_Recalculate_Scores' => $baseDir . '/src/deprecated/admin/class-recalculate-scores.php', + 'WPSEO_Recalculate_Scores_Ajax' => $baseDir . '/src/deprecated/admin/ajax/class-recalculate-scores-ajax.php', + 'WPSEO_Recalculate_Terms' => $baseDir . '/src/deprecated/admin/recalculate/class-recalculate-terms.php', 'WPSEO_Register_Capabilities' => $baseDir . '/admin/capabilities/class-register-capabilities.php', 'WPSEO_Register_Roles' => $baseDir . '/admin/roles/class-register-roles.php', 'WPSEO_Remote_Request' => $baseDir . '/admin/class-remote-request.php', - 'WPSEO_Remove_Reply_To_Com' => $baseDir . '/frontend/class-remove-reply-to-com.php', 'WPSEO_Replace_Vars' => $baseDir . '/inc/class-wpseo-replace-vars.php', + 'WPSEO_Replacement_Variable' => $baseDir . '/inc/class-wpseo-replacement-variable.php', + 'WPSEO_Replacevar_Editor' => $baseDir . '/admin/menu/class-replacevar-editor.php', + 'WPSEO_Replacevar_Field' => $baseDir . '/admin/menu/class-replacevar-field.php', 'WPSEO_Rewrite' => $baseDir . '/inc/class-rewrite.php', 'WPSEO_Role_Manager' => $baseDir . '/admin/roles/class-role-manager.php', 'WPSEO_Role_Manager_Factory' => $baseDir . '/admin/roles/class-role-manager-factory.php', 'WPSEO_Role_Manager_VIP' => $baseDir . '/admin/roles/class-role-manager-vip.php', 'WPSEO_Role_Manager_WP' => $baseDir . '/admin/roles/class-role-manager-wp.php', - 'WPSEO_Ryte_Service' => $baseDir . '/admin/onpage/class-ryte-service.php', + 'WPSEO_Ryte' => $baseDir . '/admin/ryte/class-ryte.php', + 'WPSEO_Ryte_Option' => $baseDir . '/admin/ryte/class-ryte-option.php', + 'WPSEO_Ryte_Request' => $baseDir . '/admin/ryte/class-ryte-request.php', + 'WPSEO_Ryte_Service' => $baseDir . '/src/deprecated/admin/onpage/class-ryte-service.php', + 'WPSEO_Schema' => $baseDir . '/src/deprecated/frontend/schema/class-schema.php', + 'WPSEO_Schema_Article' => $baseDir . '/src/deprecated/frontend/schema/class-schema-article.php', + 'WPSEO_Schema_Author' => $baseDir . '/src/deprecated/frontend/schema/class-schema-author.php', + 'WPSEO_Schema_Breadcrumb' => $baseDir . '/src/deprecated/frontend/schema/class-schema-breadcrumb.php', + 'WPSEO_Schema_FAQ' => $baseDir . '/src/deprecated/frontend/schema/class-schema-faq.php', + 'WPSEO_Schema_FAQ_Question_List' => $baseDir . '/src/deprecated/frontend/schema/class-schema-faq-question-list.php', + 'WPSEO_Schema_FAQ_Questions' => $baseDir . '/src/deprecated/frontend/schema/class-schema-faq-questions.php', + 'WPSEO_Schema_HowTo' => $baseDir . '/src/deprecated/frontend/schema/class-schema-howto.php', + 'WPSEO_Schema_IDs' => $baseDir . '/src/deprecated/frontend/schema/class-schema-ids.php', + 'WPSEO_Schema_Image' => $baseDir . '/src/deprecated/frontend/schema/class-schema-image.php', + 'WPSEO_Schema_MainImage' => $baseDir . '/src/deprecated/frontend/schema/class-schema-main-image.php', + 'WPSEO_Schema_Organization' => $baseDir . '/src/deprecated/frontend/schema/class-schema-organization.php', + 'WPSEO_Schema_Person' => $baseDir . '/src/deprecated/frontend/schema/class-schema-person.php', + 'WPSEO_Schema_Person_Upgrade_Notification' => $baseDir . '/admin/class-schema-person-upgrade-notification.php', + 'WPSEO_Schema_Utils' => $baseDir . '/src/deprecated/frontend/schema/class-schema-utils.php', + 'WPSEO_Schema_WebPage' => $baseDir . '/src/deprecated/frontend/schema/class-schema-webpage.php', + 'WPSEO_Schema_Website' => $baseDir . '/src/deprecated/frontend/schema/class-schema-website.php', 'WPSEO_Shortcode_Filter' => $baseDir . '/admin/ajax/class-shortcode-filter.php', 'WPSEO_Shortlinker' => $baseDir . '/inc/class-wpseo-shortlinker.php', 'WPSEO_Sitemap_Cache_Data' => $baseDir . '/inc/sitemaps/class-sitemap-cache-data.php', 'WPSEO_Sitemap_Cache_Data_Interface' => $baseDir . '/inc/sitemaps/interface-sitemap-cache-data.php', 'WPSEO_Sitemap_Image_Parser' => $baseDir . '/inc/sitemaps/class-sitemap-image-parser.php', 'WPSEO_Sitemap_Provider' => $baseDir . '/inc/sitemaps/interface-sitemap-provider.php', - 'WPSEO_Sitemap_Timezone' => $baseDir . '/inc/sitemaps/class-sitemap-timezone.php', 'WPSEO_Sitemaps' => $baseDir . '/inc/sitemaps/class-sitemaps.php', 'WPSEO_Sitemaps_Admin' => $baseDir . '/inc/sitemaps/class-sitemaps-admin.php', 'WPSEO_Sitemaps_Cache' => $baseDir . '/inc/sitemaps/class-sitemaps-cache.php', @@ -326,85 +353,577 @@ return array( 'WPSEO_Sitemaps_Renderer' => $baseDir . '/inc/sitemaps/class-sitemaps-renderer.php', 'WPSEO_Sitemaps_Router' => $baseDir . '/inc/sitemaps/class-sitemaps-router.php', 'WPSEO_Slug_Change_Watcher' => $baseDir . '/admin/watchers/class-slug-change-watcher.php', - 'WPSEO_Social_Admin' => $baseDir . '/admin/class-social-admin.php', + 'WPSEO_Social_Admin' => $baseDir . '/src/deprecated/admin/class-social-admin.php', 'WPSEO_Statistic_Integration' => $baseDir . '/admin/statistics/class-statistics-integration.php', 'WPSEO_Statistics' => $baseDir . '/inc/class-wpseo-statistics.php', 'WPSEO_Statistics_Service' => $baseDir . '/admin/statistics/class-statistics-service.php', 'WPSEO_Submenu_Capability_Normalize' => $baseDir . '/admin/menu/class-submenu-capability-normalize.php', - 'WPSEO_Submenu_Hider' => $baseDir . '/deprecated/class-submenu-hider.php', 'WPSEO_Suggested_Plugins' => $baseDir . '/admin/class-suggested-plugins.php', 'WPSEO_Taxonomy' => $baseDir . '/admin/taxonomy/class-taxonomy.php', 'WPSEO_Taxonomy_Columns' => $baseDir . '/admin/taxonomy/class-taxonomy-columns.php', - 'WPSEO_Taxonomy_Content_Fields' => $baseDir . '/admin/taxonomy/class-taxonomy-content-fields.php', + 'WPSEO_Taxonomy_Content_Fields' => $baseDir . '/src/deprecated/admin/taxonomy/class-taxonomy-content-fields.php', 'WPSEO_Taxonomy_Fields' => $baseDir . '/admin/taxonomy/class-taxonomy-fields.php', 'WPSEO_Taxonomy_Fields_Presenter' => $baseDir . '/admin/taxonomy/class-taxonomy-fields-presenter.php', 'WPSEO_Taxonomy_Meta' => $baseDir . '/inc/options/class-wpseo-taxonomy-meta.php', 'WPSEO_Taxonomy_Metabox' => $baseDir . '/admin/taxonomy/class-taxonomy-metabox.php', - 'WPSEO_Taxonomy_Settings_Fields' => $baseDir . '/admin/taxonomy/class-taxonomy-settings-fields.php', + 'WPSEO_Taxonomy_Settings_Fields' => $baseDir . '/src/deprecated/admin/taxonomy/class-taxonomy-settings-fields.php', 'WPSEO_Taxonomy_Sitemap_Provider' => $baseDir . '/inc/sitemaps/class-taxonomy-sitemap-provider.php', - 'WPSEO_Taxonomy_Social_Fields' => $baseDir . '/admin/taxonomy/class-taxonomy-social-fields.php', + 'WPSEO_Taxonomy_Social_Fields' => $baseDir . '/src/deprecated/admin/taxonomy/class-taxonomy-social-fields.php', 'WPSEO_Term_Metabox_Formatter' => $baseDir . '/admin/formatter/class-term-metabox-formatter.php', 'WPSEO_Tracking' => $baseDir . '/admin/tracking/class-tracking.php', 'WPSEO_Tracking_Default_Data' => $baseDir . '/admin/tracking/class-tracking-default-data.php', 'WPSEO_Tracking_Plugin_Data' => $baseDir . '/admin/tracking/class-tracking-plugin-data.php', 'WPSEO_Tracking_Server_Data' => $baseDir . '/admin/tracking/class-tracking-server-data.php', + 'WPSEO_Tracking_Settings_Data' => $baseDir . '/admin/tracking/class-tracking-settings-data.php', 'WPSEO_Tracking_Theme_Data' => $baseDir . '/admin/tracking/class-tracking-theme-data.php', - 'WPSEO_Twitter' => $baseDir . '/frontend/class-twitter.php', + 'WPSEO_Twitter' => $baseDir . '/src/deprecated/frontend/class-twitter.php', 'WPSEO_Upgrade' => $baseDir . '/inc/class-upgrade.php', + 'WPSEO_Upgrade_History' => $baseDir . '/inc/class-upgrade-history.php', 'WPSEO_Utils' => $baseDir . '/inc/class-wpseo-utils.php', - 'WPSEO_WooCommerce_Shop_Page' => $baseDir . '/frontend/class-woocommerce-shop-page.php', + 'WPSEO_Validator' => $baseDir . '/src/deprecated/inc/class-wpseo-validator.php', + 'WPSEO_WooCommerce_Shop_Page' => $baseDir . '/src/deprecated/frontend/class-woocommerce-shop-page.php', + 'WPSEO_WordPress_AJAX_Integration' => $baseDir . '/inc/interface-wpseo-wordpress-ajax-integration.php', 'WPSEO_WordPress_Integration' => $baseDir . '/inc/interface-wpseo-wordpress-integration.php', 'WPSEO_Yoast_Columns' => $baseDir . '/admin/class-yoast-columns.php', - 'Whip_BasicMessage' => $vendorDir . '/yoast/whip/src/messages/Whip_BasicMessage.php', - 'Whip_Configuration' => $vendorDir . '/yoast/whip/src/Whip_Configuration.php', - 'Whip_DismissStorage' => $vendorDir . '/yoast/whip/src/interfaces/Whip_DismissStorage.php', - 'Whip_EmptyProperty' => $vendorDir . '/yoast/whip/src/exceptions/Whip_EmptyProperty.php', - 'Whip_Host' => $vendorDir . '/yoast/whip/src/Whip_Host.php', - 'Whip_HostMessage' => $vendorDir . '/yoast/whip/src/messages/Whip_HostMessage.php', - 'Whip_InvalidOperatorType' => $vendorDir . '/yoast/whip/src/exceptions/Whip_InvalidOperatorType.php', - 'Whip_InvalidType' => $vendorDir . '/yoast/whip/src/exceptions/Whip_InvalidType.php', - 'Whip_InvalidVersionComparisonString' => $vendorDir . '/yoast/whip/src/exceptions/Whip_InvalidVersionComparisonString.php', - 'Whip_InvalidVersionRequirementMessage' => $vendorDir . '/yoast/whip/src/messages/Whip_InvalidVersionRequirementMessage.php', - 'Whip_Listener' => $vendorDir . '/yoast/whip/src/interfaces/Whip_Listener.php', - 'Whip_Message' => $vendorDir . '/yoast/whip/src/interfaces/Whip_Message.php', - 'Whip_MessageDismisser' => $vendorDir . '/yoast/whip/src/Whip_MessageDismisser.php', - 'Whip_MessageFormatter' => $vendorDir . '/yoast/whip/src/Whip_MessageFormatter.php', - 'Whip_MessagePresenter' => $vendorDir . '/yoast/whip/src/interfaces/Whip_MessagePresenter.php', - 'Whip_MessagesManager' => $vendorDir . '/yoast/whip/src/Whip_MessagesManager.php', - 'Whip_NullMessage' => $vendorDir . '/yoast/whip/src/messages/Whip_NullMessage.php', - 'Whip_Requirement' => $vendorDir . '/yoast/whip/src/interfaces/Whip_Requirement.php', - 'Whip_RequirementsChecker' => $vendorDir . '/yoast/whip/src/Whip_RequirementsChecker.php', - 'Whip_UpgradePhpMessage' => $vendorDir . '/yoast/whip/src/messages/Whip_UpgradePhpMessage.php', - 'Whip_VersionDetector' => $vendorDir . '/yoast/whip/src/interfaces/Whip_VersionDetector.php', - 'Whip_VersionRequirement' => $vendorDir . '/yoast/whip/src/Whip_VersionRequirement.php', - 'Whip_WPDismissOption' => $vendorDir . '/yoast/whip/src/Whip_WPDismissOption.php', - 'Whip_WPMessageDismissListener' => $vendorDir . '/yoast/whip/src/Whip_WPMessageDismissListener.php', - 'Whip_WPMessagePresenter' => $vendorDir . '/yoast/whip/src/presenters/Whip_WPMessagePresenter.php', - 'Yoast_API_Request' => $vendorDir . '/yoast/license-manager/class-api-request.php', - 'Yoast_Alerts' => $baseDir . '/admin/class-yoast-alerts.php', - 'Yoast_Api_Libs' => $vendorDir . '/yoast/api-libs/class-api-libs.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Client' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Client.php', + 'YoastSEO_Vendor\\GuzzleHttp\\ClientInterface' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/ClientInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\CookieJar' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJar.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\CookieJarInterface' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\FileCookieJar' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\SessionCookieJar' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\SetCookie' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SetCookie.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\BadResponseException' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/BadResponseException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\ClientException' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/ClientException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\ConnectException' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/ConnectException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\GuzzleException' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/GuzzleException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\RequestException' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/RequestException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\SeekException' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/SeekException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\ServerException' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/ServerException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\TooManyRedirectsException' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\TransferException' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/TransferException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\HandlerStack' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/HandlerStack.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\CurlFactory' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlFactory.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\CurlFactoryInterface' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\CurlHandler' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlHandler.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\CurlMultiHandler' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\EasyHandle' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/EasyHandle.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\MockHandler' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/MockHandler.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\Proxy' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/Proxy.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\StreamHandler' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/StreamHandler.php', + 'YoastSEO_Vendor\\GuzzleHttp\\MessageFormatter' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/MessageFormatter.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Middleware' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Middleware.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Pool' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/Pool.php', + 'YoastSEO_Vendor\\GuzzleHttp\\PrepareBodyMiddleware' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\AggregateException' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/AggregateException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\CancellationException' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/CancellationException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\Coroutine' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/Coroutine.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\EachPromise' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/EachPromise.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\FulfilledPromise' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/FulfilledPromise.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\Promise' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/Promise.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\PromiseInterface' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/PromiseInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\PromisorInterface' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/PromisorInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\RejectedPromise' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/RejectedPromise.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\RejectionException' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/RejectionException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\TaskQueue' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/TaskQueue.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\TaskQueueInterface' => $baseDir . '/vendor_prefixed/guzzlehttp/promises/src/TaskQueueInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\AppendStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/AppendStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\BufferStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/BufferStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\CachingStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/CachingStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\DroppingStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/DroppingStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\FnStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/FnStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\InflateStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/InflateStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\LazyOpenStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/LazyOpenStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\LimitStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/LimitStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\MessageTrait' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/MessageTrait.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\MultipartStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/MultipartStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\NoSeekStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/NoSeekStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\PumpStream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/PumpStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\Request' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/Request.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\Response' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/Response.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\Rfc7230' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/Rfc7230.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\ServerRequest' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/ServerRequest.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\Stream' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/Stream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\StreamDecoratorTrait' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/StreamDecoratorTrait.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\StreamWrapper' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/StreamWrapper.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\UploadedFile' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/UploadedFile.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\Uri' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/Uri.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\UriNormalizer' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/UriNormalizer.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\UriResolver' => $baseDir . '/vendor_prefixed/guzzlehttp/psr7/src/UriResolver.php', + 'YoastSEO_Vendor\\GuzzleHttp\\RedirectMiddleware' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/RedirectMiddleware.php', + 'YoastSEO_Vendor\\GuzzleHttp\\RequestOptions' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/RequestOptions.php', + 'YoastSEO_Vendor\\GuzzleHttp\\RetryMiddleware' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/RetryMiddleware.php', + 'YoastSEO_Vendor\\GuzzleHttp\\TransferStats' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/TransferStats.php', + 'YoastSEO_Vendor\\GuzzleHttp\\UriTemplate' => $baseDir . '/vendor_prefixed/guzzlehttp/guzzle/src/UriTemplate.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AbstractGrant' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/AbstractGrant.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AuthorizationCode' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/AuthorizationCode.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\ClientCredentials' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/ClientCredentials.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\Exception\\InvalidGrantException' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\GrantFactory' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/GrantFactory.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\Password' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/Password.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\RefreshToken' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Grant/RefreshToken.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\OptionProvider\\HttpBasicAuthOptionProvider' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\OptionProvider\\OptionProviderInterface' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\OptionProvider\\PostAuthOptionProvider' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Provider\\AbstractProvider' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Provider/AbstractProvider.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Provider\\GenericProvider' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Provider/GenericProvider.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Provider\\GenericResourceOwner' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Provider/GenericResourceOwner.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Provider\\ResourceOwnerInterface' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Provider/ResourceOwnerInterface.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Token\\AccessToken' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Token/AccessToken.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Token\\AccessTokenInterface' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Token/AccessTokenInterface.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Token\\ResourceOwnerAccessTokenInterface' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\ArrayAccessorTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/ArrayAccessorTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\BearerAuthorizationTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\GuardedPropertyTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/GuardedPropertyTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\MacAuthorizationTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/MacAuthorizationTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\ProviderRedirectTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/ProviderRedirectTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\QueryBuilderTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/QueryBuilderTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequestFactory' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/RequestFactory.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequiredParameterTrait' => $baseDir . '/vendor_prefixed/league/oauth2-client/src/Tool/RequiredParameterTrait.php', + 'YoastSEO_Vendor\\Psr\\Container\\ContainerExceptionInterface' => $baseDir . '/vendor_prefixed/psr/container/src/ContainerExceptionInterface.php', + 'YoastSEO_Vendor\\Psr\\Container\\ContainerInterface' => $baseDir . '/vendor_prefixed/psr/container/src/ContainerInterface.php', + 'YoastSEO_Vendor\\Psr\\Container\\NotFoundExceptionInterface' => $baseDir . '/vendor_prefixed/psr/container/src/NotFoundExceptionInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\MessageInterface' => $baseDir . '/vendor_prefixed/psr/http-message/src/MessageInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\RequestInterface' => $baseDir . '/vendor_prefixed/psr/http-message/src/RequestInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\ResponseInterface' => $baseDir . '/vendor_prefixed/psr/http-message/src/ResponseInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\ServerRequestInterface' => $baseDir . '/vendor_prefixed/psr/http-message/src/ServerRequestInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\StreamInterface' => $baseDir . '/vendor_prefixed/psr/http-message/src/StreamInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\UploadedFileInterface' => $baseDir . '/vendor_prefixed/psr/http-message/src/UploadedFileInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\UriInterface' => $baseDir . '/vendor_prefixed/psr/http-message/src/UriInterface.php', + 'YoastSEO_Vendor\\Psr\\Log\\AbstractLogger' => $baseDir . '/vendor_prefixed/psr/log/Psr/Log/AbstractLogger.php', + 'YoastSEO_Vendor\\Psr\\Log\\InvalidArgumentException' => $baseDir . '/vendor_prefixed/psr/log/Psr/Log/InvalidArgumentException.php', + 'YoastSEO_Vendor\\Psr\\Log\\LogLevel' => $baseDir . '/vendor_prefixed/psr/log/Psr/Log/LogLevel.php', + 'YoastSEO_Vendor\\Psr\\Log\\LoggerAwareInterface' => $baseDir . '/vendor_prefixed/psr/log/Psr/Log/LoggerAwareInterface.php', + 'YoastSEO_Vendor\\Psr\\Log\\LoggerAwareTrait' => $baseDir . '/vendor_prefixed/psr/log/Psr/Log/LoggerAwareTrait.php', + 'YoastSEO_Vendor\\Psr\\Log\\LoggerInterface' => $baseDir . '/vendor_prefixed/psr/log/Psr/Log/LoggerInterface.php', + 'YoastSEO_Vendor\\Psr\\Log\\LoggerTrait' => $baseDir . '/vendor_prefixed/psr/log/Psr/Log/LoggerTrait.php', + 'YoastSEO_Vendor\\Psr\\Log\\NullLogger' => $baseDir . '/vendor_prefixed/psr/log/Psr/Log/NullLogger.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/Argument/RewindableGenerator.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Container' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/Container.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/ContainerInterface.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\EnvNotFoundException' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/Exception/EnvNotFoundException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\ExceptionInterface' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/Exception/ExceptionInterface.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/Exception/InvalidArgumentException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\LogicException' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/Exception/LogicException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterCircularReferenceException' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/Exception/RuntimeException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceCircularReferenceException' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/Exception/ServiceNotFoundException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ParameterBag\\EnvPlaceholderParameterBag' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ParameterBag\\FrozenParameterBag' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBag.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ResettableContainerInterface' => $baseDir . '/vendor_prefixed/symfony/dependency-injection/ResettableContainerInterface.php', + 'Yoast\\WP\\Lib\\Abstract_Main' => $baseDir . '/lib/abstract-main.php', + 'Yoast\\WP\\Lib\\Dependency_Injection\\Container_Registry' => $baseDir . '/lib/dependency-injection/container-registry.php', + 'Yoast\\WP\\Lib\\Migrations\\Adapter' => $baseDir . '/lib/migrations/adapter.php', + 'Yoast\\WP\\Lib\\Migrations\\Column' => $baseDir . '/lib/migrations/column.php', + 'Yoast\\WP\\Lib\\Migrations\\Constants' => $baseDir . '/lib/migrations/constants.php', + 'Yoast\\WP\\Lib\\Migrations\\Migration' => $baseDir . '/lib/migrations/migration.php', + 'Yoast\\WP\\Lib\\Migrations\\Table' => $baseDir . '/lib/migrations/table.php', + 'Yoast\\WP\\Lib\\Model' => $baseDir . '/lib/model.php', + 'Yoast\\WP\\Lib\\ORM' => $baseDir . '/lib/orm.php', + 'Yoast\\WP\\SEO\\Actions\\Addon_Installation\\Addon_Activate_Action' => $baseDir . '/src/actions/addon-installation/addon-activate-action.php', + 'Yoast\\WP\\SEO\\Actions\\Addon_Installation\\Addon_Install_Action' => $baseDir . '/src/actions/addon-installation/addon-install-action.php', + 'Yoast\\WP\\SEO\\Actions\\Alert_Dismissal_Action' => $baseDir . '/src/actions/alert-dismissal-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexables\\Indexable_Head_Action' => $baseDir . '/src/actions/indexables/indexable-head-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Abstract_Link_Indexing_Action' => $baseDir . '/src/deprecated/src/actions/indexation/abstract-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Complete_Indexation_Action' => $baseDir . '/src/deprecated/src/actions/indexation/indexable-complete-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_General_Indexation_Action' => $baseDir . '/src/deprecated/src/actions/indexation/indexable-general-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Post_Indexation_Action' => $baseDir . '/src/deprecated/src/actions/indexation/indexable-post-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Post_Type_Archive_Indexation_Action' => $baseDir . '/src/deprecated/src/actions/indexation/indexable-post-type-archive-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Prepare_Indexation_Action' => $baseDir . '/src/deprecated/src/actions/indexation/indexable-prepare-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Term_Indexation_Action' => $baseDir . '/src/deprecated/src/actions/indexation/indexable-term-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexation_Action_Interface' => $baseDir . '/src/deprecated/src/actions/indexation/indexation-action-interface.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Post_Link_Indexing_Action' => $baseDir . '/src/deprecated/src/actions/indexation/post-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Term_Link_Indexing_Action' => $baseDir . '/src/deprecated/src/actions/indexation/term-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Abstract_Indexing_Action' => $baseDir . '/src/actions/indexing/abstract-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Abstract_Link_Indexing_Action' => $baseDir . '/src/actions/indexing/abstract-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_General_Indexation_Action' => $baseDir . '/src/actions/indexing/indexable-general-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_Indexing_Complete_Action' => $baseDir . '/src/actions/indexing/indexable-indexing-complete-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_Post_Indexation_Action' => $baseDir . '/src/actions/indexing/indexable-post-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_Post_Type_Archive_Indexation_Action' => $baseDir . '/src/actions/indexing/indexable-post-type-archive-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_Prepare_Indexation_Action' => $baseDir . '/src/deprecated/src/actions/indexing/indexable-prepare-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_Term_Indexation_Action' => $baseDir . '/src/actions/indexing/indexable-term-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexation_Action_Interface' => $baseDir . '/src/actions/indexing/indexation-action-interface.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexing_Complete_Action' => $baseDir . '/src/actions/indexing/indexing-complete-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexing_Prepare_Action' => $baseDir . '/src/actions/indexing/indexing-prepare-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Limited_Indexing_Action_Interface' => $baseDir . '/src/actions/indexing/limited-indexing-action-interface.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Post_Link_Indexing_Action' => $baseDir . '/src/actions/indexing/post-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Term_Link_Indexing_Action' => $baseDir . '/src/actions/indexing/term-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\SEMrush\\SEMrush_Login_Action' => $baseDir . '/src/actions/semrush/semrush-login-action.php', + 'Yoast\\WP\\SEO\\Actions\\SEMrush\\SEMrush_Options_Action' => $baseDir . '/src/actions/semrush/semrush-options-action.php', + 'Yoast\\WP\\SEO\\Actions\\SEMrush\\SEMrush_Phrases_Action' => $baseDir . '/src/actions/semrush/semrush-phrases-action.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder' => $baseDir . '/src/builders/indexable-author-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Builder' => $baseDir . '/src/builders/indexable-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Date_Archive_Builder' => $baseDir . '/src/builders/indexable-date-archive-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Hierarchy_Builder' => $baseDir . '/src/builders/indexable-hierarchy-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Home_Page_Builder' => $baseDir . '/src/builders/indexable-home-page-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Link_Builder' => $baseDir . '/src/builders/indexable-link-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder' => $baseDir . '/src/builders/indexable-post-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Post_Type_Archive_Builder' => $baseDir . '/src/builders/indexable-post-type-archive-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Social_Image_Trait' => $baseDir . '/src/builders/indexable-social-image-trait.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_System_Page_Builder' => $baseDir . '/src/builders/indexable-system-page-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder' => $baseDir . '/src/builders/indexable-term-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Primary_Term_Builder' => $baseDir . '/src/builders/primary-term-builder.php', + 'Yoast\\WP\\SEO\\Commands\\Command_Interface' => $baseDir . '/src/commands/command-interface.php', + 'Yoast\\WP\\SEO\\Commands\\Index_Command' => $baseDir . '/src/commands/index-command.php', + 'Yoast\\WP\\SEO\\Conditionals\\Addon_Installation_Conditional' => $baseDir . '/src/conditionals/addon-installation-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin\\Doing_Post_Quick_Edit_Save_Conditional' => $baseDir . '/src/conditionals/admin/doing-post-quick-edit-save-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin\\Estimated_Reading_Time_Conditional' => $baseDir . '/src/conditionals/admin/estimated-reading-time-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin\\Licenses_Page_Conditional' => $baseDir . '/src/conditionals/admin/licenses-page-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin\\Post_Conditional' => $baseDir . '/src/conditionals/admin/post-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin\\Posts_Overview_Or_Ajax_Conditional' => $baseDir . '/src/conditionals/admin/posts-overview-or-ajax-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin_Conditional' => $baseDir . '/src/conditionals/admin-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Conditional' => $baseDir . '/src/conditionals/conditional-interface.php', + 'Yoast\\WP\\SEO\\Conditionals\\Development_Conditional' => $baseDir . '/src/conditionals/development-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Farsi_Support_Conditional' => $baseDir . '/src/deprecated/src/conditionals/farsi-support-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Feature_Flag_Conditional' => $baseDir . '/src/conditionals/feature-flag-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Front_End_Conditional' => $baseDir . '/src/conditionals/front-end-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Get_Request_Conditional' => $baseDir . '/src/conditionals/get-request-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Headless_Rest_Endpoints_Enabled_Conditional' => $baseDir . '/src/conditionals/headless-rest-endpoints-enabled-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Jetpack_Conditional' => $baseDir . '/src/conditionals/jetpack-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Migrations_Conditional' => $baseDir . '/src/conditionals/migrations-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\News_Conditional' => $baseDir . '/src/conditionals/news-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\No_Conditionals' => $baseDir . '/src/conditionals/no-conditionals-trait.php', + 'Yoast\\WP\\SEO\\Conditionals\\No_Tool_Selected_Conditional' => $baseDir . '/src/conditionals/no-tool-selected-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Norwegian_Readability_Conditional' => $baseDir . '/src/deprecated/src/conditionals/norwegian-readability-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Open_Graph_Conditional' => $baseDir . '/src/conditionals/open-graph-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Premium_Inactive_Conditional' => $baseDir . '/src/conditionals/premium-inactive-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Primary_Category_Conditional' => $baseDir . '/src/conditionals/primary-category-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\SEMrush_Enabled_Conditional' => $baseDir . '/src/conditionals/semrush-enabled-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Schema_Blocks_Conditional' => $baseDir . '/src/conditionals/schema-blocks-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Should_Index_Links_Conditional' => $baseDir . '/src/conditionals/should-index-links-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\The_Events_Calendar_Conditional' => $baseDir . '/src/conditionals/the-events-calendar-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Third_Party\\Elementor_Activated_Conditional' => $baseDir . '/src/conditionals/third-party/elementor-activated-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Third_Party\\Elementor_Edit_Conditional' => $baseDir . '/src/conditionals/third-party/elementor-edit-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Third_Party\\W3_Total_Cache_Conditional' => $baseDir . '/src/conditionals/third-party/w3-total-cache-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Third_Party\\WPML_Conditional' => $baseDir . '/src/conditionals/third-party/wpml-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Third_Party\\WPML_WPSEO_Conditional' => $baseDir . '/src/conditionals/third-party/wpml-wpseo-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\WP_Robots_Conditional' => $baseDir . '/src/conditionals/wp-robots-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Web_Stories_Conditional' => $baseDir . '/src/conditionals/web-stories-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\WooCommerce_Conditional' => $baseDir . '/src/conditionals/woocommerce-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\XMLRPC_Conditional' => $baseDir . '/src/conditionals/xmlrpc-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Yoast_Admin_And_Dashboard_Conditional' => $baseDir . '/src/conditionals/yoast-admin-and-dashboard-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Yoast_Tools_Page_Conditional' => $baseDir . '/src/conditionals/yoast-tools-page-conditional.php', + 'Yoast\\WP\\SEO\\Config\\Badge_Group_Names' => $baseDir . '/src/config/badge-group-names.php', + 'Yoast\\WP\\SEO\\Config\\Indexing_Reasons' => $baseDir . '/src/config/indexing-reasons.php', + 'Yoast\\WP\\SEO\\Config\\Migration_Status' => $baseDir . '/src/config/migration-status.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddCollationToTables' => $baseDir . '/src/config/migrations/20200408101900_AddCollationToTables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddColumnsToIndexables' => $baseDir . '/src/config/migrations/20200420073606_AddColumnsToIndexables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddEstimatedReadingTime' => $baseDir . '/src/config/migrations/20201202144329_AddEstimatedReadingTime.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddHasAncestorsColumn' => $baseDir . '/src/config/migrations/20200609154515_AddHasAncestorsColumn.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddIndexableObjectIdAndTypeIndex' => $baseDir . '/src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddIndexesForProminentWordsOnIndexables' => $baseDir . '/src/config/migrations/20200728095334_AddIndexesForProminentWordsOnIndexables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\BreadcrumbTitleAndHierarchyReset' => $baseDir . '/src/config/migrations/20200428123747_BreadcrumbTitleAndHierarchyReset.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ClearIndexableTables' => $baseDir . '/src/config/migrations/20200430150130_ClearIndexableTables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\CreateIndexableSubpagesIndex' => $baseDir . '/src/config/migrations/20200702141921_CreateIndexableSubpagesIndex.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\CreateSEOLinksTable' => $baseDir . '/src/config/migrations/20200617122511_CreateSEOLinksTable.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\DeleteDuplicateIndexables' => $baseDir . '/src/config/migrations/20200507054848_DeleteDuplicateIndexables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ExpandIndexableColumnLengths' => $baseDir . '/src/config/migrations/20200428194858_ExpandIndexableColumnLengths.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ExpandIndexableIDColumnLengths' => $baseDir . '/src/config/migrations/20201216124002_ExpandIndexableIDColumnLengths.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ExpandPrimaryTermIDColumnLengths' => $baseDir . '/src/config/migrations/20201216141134_ExpandPrimaryTermIDColumnLengths.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ReplacePermalinkHashIndex' => $baseDir . '/src/config/migrations/20200616130143_ReplacePermalinkHashIndex.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ResetIndexableHierarchyTable' => $baseDir . '/src/config/migrations/20200513133401_ResetIndexableHierarchyTable.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\TruncateIndexableTables' => $baseDir . '/src/config/migrations/20200429105310_TruncateIndexableTables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\WpYoastDropIndexableMetaTableIfExists' => $baseDir . '/src/config/migrations/20190529075038_WpYoastDropIndexableMetaTableIfExists.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\WpYoastIndexable' => $baseDir . '/src/config/migrations/20171228151840_WpYoastIndexable.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\WpYoastIndexableHierarchy' => $baseDir . '/src/config/migrations/20191011111109_WpYoastIndexableHierarchy.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\WpYoastPrimaryTerm' => $baseDir . '/src/config/migrations/20171228151841_WpYoastPrimaryTerm.php', + 'Yoast\\WP\\SEO\\Config\\Researcher_Languages' => $baseDir . '/src/config/researcher-languages.php', + 'Yoast\\WP\\SEO\\Config\\SEMrush_Client' => $baseDir . '/src/config/semrush-client.php', + 'Yoast\\WP\\SEO\\Config\\Schema_IDs' => $baseDir . '/src/config/schema-ids.php', + 'Yoast\\WP\\SEO\\Config\\Schema_Types' => $baseDir . '/src/config/schema-types.php', + 'Yoast\\WP\\SEO\\Context\\Meta_Tags_Context' => $baseDir . '/src/context/meta-tags-context.php', + 'Yoast\\WP\\SEO\\Exceptions\\Addon_Installation\\Addon_Activation_Error_Exception' => $baseDir . '/src/exceptions/addon-installation/addon-activation-error-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Addon_Installation\\Addon_Already_Installed_Exception' => $baseDir . '/src/exceptions/addon-installation/addon-already-installed-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Addon_Installation\\Addon_Installation_Error_Exception' => $baseDir . '/src/exceptions/addon-installation/addon-installation-error-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Addon_Installation\\User_Cannot_Activate_Plugins_Exception' => $baseDir . '/src/exceptions/addon-installation/user-cannot-activate-plugins-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Addon_Installation\\User_Cannot_Install_Plugins_Exception' => $baseDir . '/src/exceptions/addon-installation/user-cannot-install-plugins-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Indexable\\Indexable_Exception' => $baseDir . '/src/exceptions/indexable/indexable-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Indexable\\Invalid_Term_Exception' => $baseDir . '/src/exceptions/indexable/invalid-term-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Indexable\\Post_Not_Found_Exception' => $baseDir . '/src/exceptions/indexable/post-not-found-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Indexable\\Source_Exception' => $baseDir . '/src/exceptions/indexable/source-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Indexable\\Term_Not_Found_Exception' => $baseDir . '/src/exceptions/indexable/term-not-found-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Missing_Method' => $baseDir . '/src/exceptions/missing-method.php', + 'Yoast\\WP\\SEO\\Exceptions\\OAuth\\Authentication_Failed_Exception' => $baseDir . '/src/exceptions/oauth/authentication-failed-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\SEMrush\\Tokens\\Empty_Property_Exception' => $baseDir . '/src/exceptions/semrush/tokens/empty-property-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\SEMrush\\Tokens\\Empty_Token_Exception' => $baseDir . '/src/exceptions/semrush/tokens/empty-token-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\SEMrush\\Tokens\\Failed_Storage_Exception' => $baseDir . '/src/exceptions/semrush/tokens/failed-storage-exception.php', + 'Yoast\\WP\\SEO\\Generated\\Cached_Container' => $baseDir . '/src/generated/container.php', + 'Yoast\\WP\\SEO\\Generators\\Breadcrumbs_Generator' => $baseDir . '/src/generators/breadcrumbs-generator.php', + 'Yoast\\WP\\SEO\\Generators\\Generator_Interface' => $baseDir . '/src/generators/generator-interface.php', + 'Yoast\\WP\\SEO\\Generators\\Open_Graph_Image_Generator' => $baseDir . '/src/generators/open-graph-image-generator.php', + 'Yoast\\WP\\SEO\\Generators\\Open_Graph_Locale_Generator' => $baseDir . '/src/generators/open-graph-locale-generator.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Abstract_Schema_Piece' => $baseDir . '/src/generators/schema/abstract-schema-piece.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Article' => $baseDir . '/src/generators/schema/article.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Author' => $baseDir . '/src/generators/schema/author.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Breadcrumb' => $baseDir . '/src/generators/schema/breadcrumb.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\FAQ' => $baseDir . '/src/generators/schema/faq.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\HowTo' => $baseDir . '/src/generators/schema/howto.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Main_Image' => $baseDir . '/src/generators/schema/main-image.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Organization' => $baseDir . '/src/generators/schema/organization.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Person' => $baseDir . '/src/generators/schema/person.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Third_Party\\Events_Calendar_Schema' => $baseDir . '/src/generators/schema/third-party/events-calendar-schema.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\WebPage' => $baseDir . '/src/generators/schema/webpage.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Website' => $baseDir . '/src/generators/schema/website.php', + 'Yoast\\WP\\SEO\\Generators\\Schema_Generator' => $baseDir . '/src/generators/schema-generator.php', + 'Yoast\\WP\\SEO\\Generators\\Twitter_Image_Generator' => $baseDir . '/src/generators/twitter-image-generator.php', + 'Yoast\\WP\\SEO\\Helpers\\Asset_Helper' => $baseDir . '/src/helpers/asset-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Author_Archive_Helper' => $baseDir . '/src/helpers/author-archive-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Blocks_Helper' => $baseDir . '/src/helpers/blocks-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Capability_Helper' => $baseDir . '/src/helpers/capability-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Current_Page_Helper' => $baseDir . '/src/helpers/current-page-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Date_Helper' => $baseDir . '/src/helpers/date-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Environment_Helper' => $baseDir . '/src/helpers/environment-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Home_Url_Helper' => $baseDir . '/src/helpers/home-url-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Image_Helper' => $baseDir . '/src/helpers/image-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Indexable_Helper' => $baseDir . '/src/helpers/indexable-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Indexing_Helper' => $baseDir . '/src/helpers/indexing-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Input_Helper' => $baseDir . '/src/helpers/input-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Language_Helper' => $baseDir . '/src/helpers/language-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Meta_Helper' => $baseDir . '/src/helpers/meta-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Notification_Helper' => $baseDir . '/src/helpers/notification-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Open_Graph\\Image_Helper' => $baseDir . '/src/helpers/open-graph/image-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Open_Graph\\Values_Helper' => $baseDir . '/src/helpers/open-graph/values-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Options_Helper' => $baseDir . '/src/helpers/options-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Pagination_Helper' => $baseDir . '/src/helpers/pagination-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Permalink_Helper' => $baseDir . '/src/helpers/permalink-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Post_Helper' => $baseDir . '/src/helpers/post-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Post_Type_Helper' => $baseDir . '/src/helpers/post-type-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Primary_Term_Helper' => $baseDir . '/src/helpers/primary-term-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Product_Helper' => $baseDir . '/src/helpers/product-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Redirect_Helper' => $baseDir . '/src/helpers/redirect-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Request_Helper' => $baseDir . '/src/helpers/request-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Require_File_Helper' => $baseDir . '/src/helpers/require-file-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Robots_Helper' => $baseDir . '/src/helpers/robots-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\Article_Helper' => $baseDir . '/src/helpers/schema/article-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\HTML_Helper' => $baseDir . '/src/helpers/schema/html-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\ID_Helper' => $baseDir . '/src/helpers/schema/id-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\Image_Helper' => $baseDir . '/src/helpers/schema/image-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\Language_Helper' => $baseDir . '/src/helpers/schema/language-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\Replace_Vars_Helper' => $baseDir . '/src/helpers/schema/replace-vars-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Short_Link_Helper' => $baseDir . '/src/helpers/short-link-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Site_Helper' => $baseDir . '/src/helpers/site-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\String_Helper' => $baseDir . '/src/helpers/string-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Taxonomy_Helper' => $baseDir . '/src/helpers/taxonomy-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Twitter\\Image_Helper' => $baseDir . '/src/helpers/twitter/image-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Url_Helper' => $baseDir . '/src/helpers/url-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\User_Helper' => $baseDir . '/src/helpers/user-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Woocommerce_Helper' => $baseDir . '/src/helpers/woocommerce-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Wordpress_Helper' => $baseDir . '/src/helpers/wordpress-helper.php', + 'Yoast\\WP\\SEO\\Initializers\\Disable_Core_Sitemaps' => $baseDir . '/src/initializers/disable-core-sitemaps.php', + 'Yoast\\WP\\SEO\\Initializers\\Initializer_Interface' => $baseDir . '/src/initializers/initializer-interface.php', + 'Yoast\\WP\\SEO\\Initializers\\Migration_Runner' => $baseDir . '/src/initializers/migration-runner.php', + 'Yoast\\WP\\SEO\\Integrations\\Abstract_Exclude_Post_Type' => $baseDir . '/src/integrations/abstract-exclude-post-type.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Addon_Installation\\Dialog_Integration' => $baseDir . '/src/integrations/admin/addon-installation/dialog-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Addon_Installation\\Installation_Integration' => $baseDir . '/src/integrations/admin/addon-installation/installation-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Admin_Columns_Cache_Integration' => $baseDir . '/src/integrations/admin/admin-columns-cache-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Background_Indexing_Integration' => $baseDir . '/src/integrations/admin/background-indexing-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Cron_Integration' => $baseDir . '/src/integrations/admin/cron-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Disable_Concatenate_Scripts_Integration' => $baseDir . '/src/integrations/admin/disable-concatenate-scripts-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Fix_News_Dependencies_Integration' => $baseDir . '/src/integrations/admin/fix-news-dependencies-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\HelpScout_Beacon' => $baseDir . '/src/integrations/admin/helpscout-beacon.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration' => $baseDir . '/src/deprecated/src/integrations/admin/indexation-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexing_Notification_Integration' => $baseDir . '/src/integrations/admin/indexing-notification-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexing_Tool_Integration' => $baseDir . '/src/integrations/admin/indexing-tool-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Link_Count_Columns_Integration' => $baseDir . '/src/integrations/admin/link-count-columns-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Link_Count_Notification_Integration' => $baseDir . '/src/deprecated/src/integrations/admin/link-count-notification-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Link_Count_Tools_Integration' => $baseDir . '/src/deprecated/src/integrations/admin/link-count-tools-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Menu_Badge_Integration' => $baseDir . '/src/integrations/admin/menu-badge-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Migration_Error_Integration' => $baseDir . '/src/integrations/admin/migration-error-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Social_Templates_Integration' => $baseDir . '/src/integrations/admin/social-templates-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Workouts_Integration' => $baseDir . '/src/integrations/admin/workouts-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Alerts\\Abstract_Dismissable_Alert' => $baseDir . '/src/integrations/alerts/abstract-dismissable-alert.php', + 'Yoast\\WP\\SEO\\Integrations\\Blocks\\Breadcrumbs_Block' => $baseDir . '/src/integrations/blocks/breadcrumbs-block.php', + 'Yoast\\WP\\SEO\\Integrations\\Blocks\\Dynamic_Block' => $baseDir . '/src/integrations/blocks/abstract-dynamic-block.php', + 'Yoast\\WP\\SEO\\Integrations\\Blocks\\Internal_Linking_Category' => $baseDir . '/src/integrations/blocks/block-categories.php', + 'Yoast\\WP\\SEO\\Integrations\\Blocks\\Structured_Data_Blocks' => $baseDir . '/src/integrations/blocks/structured-data-blocks.php', + 'Yoast\\WP\\SEO\\Integrations\\Breadcrumbs_Integration' => $baseDir . '/src/integrations/breadcrumbs-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Cleanup_Integration' => $baseDir . '/src/integrations/cleanup-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Duplicate_Post_Integration' => $baseDir . '/src/integrations/duplicate-post-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Estimated_Reading_Time' => $baseDir . '/src/integrations/estimated-reading-time.php', + 'Yoast\\WP\\SEO\\Integrations\\Exclude_Oembed_Cache_Post_Type' => $baseDir . '/src/integrations/exclude-oembed-cache-post-type.php', + 'Yoast\\WP\\SEO\\Integrations\\Feature_Flag_Integration' => $baseDir . '/src/integrations/feature-flag-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Backwards_Compatibility' => $baseDir . '/src/integrations/front-end/backwards-compatibility.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Category_Term_Description' => $baseDir . '/src/integrations/front-end/category-term-description.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Comment_Link_Fixer' => $baseDir . '/src/integrations/front-end/comment-link-fixer.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Force_Rewrite_Title' => $baseDir . '/src/integrations/front-end/force-rewrite-title.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Handle_404' => $baseDir . '/src/integrations/front-end/handle-404.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Indexing_Controls' => $baseDir . '/src/integrations/front-end/indexing-controls.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Open_Graph_OEmbed' => $baseDir . '/src/integrations/front-end/open-graph-oembed.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\RSS_Footer_Embed' => $baseDir . '/src/integrations/front-end/rss-footer-embed.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Redirects' => $baseDir . '/src/integrations/front-end/redirects.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Schema_Accessibility_Feature' => $baseDir . '/src/integrations/front-end/schema-accessibility-feature.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Theme_Titles' => $baseDir . '/src/integrations/front-end/theme-titles.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\WP_Robots_Integration' => $baseDir . '/src/integrations/front-end/wp-robots-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End_Integration' => $baseDir . '/src/integrations/front-end-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Integration_Interface' => $baseDir . '/src/integrations/integration-interface.php', + 'Yoast\\WP\\SEO\\Integrations\\Primary_Category' => $baseDir . '/src/integrations/primary-category.php', + 'Yoast\\WP\\SEO\\Integrations\\Schema_Blocks' => $baseDir . '/src/integrations/schema-blocks.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\AMP' => $baseDir . '/src/integrations/third-party/amp.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\BbPress' => $baseDir . '/src/integrations/third-party/bbpress.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Elementor' => $baseDir . '/src/integrations/third-party/elementor.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Elementor_Exclude_Post_Types' => $baseDir . '/src/deprecated/src/integrations/third-party/elementor.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Exclude_Elementor_Post_Types' => $baseDir . '/src/integrations/third-party/exclude-elementor-post-types.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Exclude_WooCommerce_Post_Types' => $baseDir . '/src/integrations/third-party/exclude-woocommerce-post-types.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Jetpack' => $baseDir . '/src/integrations/third-party/jetpack.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\The_Events_Calendar' => $baseDir . '/src/integrations/third-party/the-events-calendar.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\W3_Total_Cache' => $baseDir . '/src/integrations/third-party/w3-total-cache.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\WPML' => $baseDir . '/src/integrations/third-party/wpml.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\WPML_WPSEO_Notification' => $baseDir . '/src/integrations/third-party/wpml-wpseo-notification.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Web_Stories' => $baseDir . '/src/integrations/third-party/web-stories.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\WooCommerce' => $baseDir . '/src/integrations/third-party/woocommerce.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Woocommerce_Permalinks' => $baseDir . '/src/integrations/third-party/woocommerce-permalinks.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Addon_Update_Watcher' => $baseDir . '/src/integrations/watchers/addon-update-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Auto_Update_Watcher' => $baseDir . '/src/integrations/watchers/auto-update-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Ancestor_Watcher' => $baseDir . '/src/integrations/watchers/indexable-ancestor-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Author_Watcher' => $baseDir . '/src/integrations/watchers/indexable-author-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Category_Permalink_Watcher' => $baseDir . '/src/integrations/watchers/indexable-category-permalink-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Date_Archive_Watcher' => $baseDir . '/src/integrations/watchers/indexable-date-archive-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_HomeUrl_Watcher' => $baseDir . '/src/integrations/watchers/indexable-homeurl-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Home_Page_Watcher' => $baseDir . '/src/integrations/watchers/indexable-home-page-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Permalink_Watcher' => $baseDir . '/src/integrations/watchers/indexable-permalink-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Post_Meta_Watcher' => $baseDir . '/src/integrations/watchers/indexable-post-meta-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Post_Type_Archive_Watcher' => $baseDir . '/src/integrations/watchers/indexable-post-type-archive-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Post_Watcher' => $baseDir . '/src/integrations/watchers/indexable-post-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Static_Home_Page_Watcher' => $baseDir . '/src/integrations/watchers/indexable-static-home-page-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_System_Page_Watcher' => $baseDir . '/src/integrations/watchers/indexable-system-page-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Term_Watcher' => $baseDir . '/src/integrations/watchers/indexable-term-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Option_Titles_Watcher' => $baseDir . '/src/integrations/watchers/option-titles-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Option_Wpseo_Watcher' => $baseDir . '/src/integrations/watchers/option-wpseo-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Category_Quick_Edit_Watcher' => $baseDir . '/src/integrations/watchers/primary-category-quick-edit-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher' => $baseDir . '/src/integrations/watchers/primary-term-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\XMLRPC' => $baseDir . '/src/integrations/xmlrpc.php', + 'Yoast\\WP\\SEO\\Loadable_Interface' => $baseDir . '/src/loadable-interface.php', + 'Yoast\\WP\\SEO\\Loader' => $baseDir . '/src/loader.php', + 'Yoast\\WP\\SEO\\Loggers\\Logger' => $baseDir . '/src/loggers/logger.php', + 'Yoast\\WP\\SEO\\Main' => $baseDir . '/src/main.php', + 'Yoast\\WP\\SEO\\Memoizers\\Meta_Tags_Context_Memoizer' => $baseDir . '/src/memoizers/meta-tags-context-memoizer.php', + 'Yoast\\WP\\SEO\\Memoizers\\Presentation_Memoizer' => $baseDir . '/src/memoizers/presentation-memoizer.php', + 'Yoast\\WP\\SEO\\Models\\Indexable' => $baseDir . '/src/models/indexable.php', + 'Yoast\\WP\\SEO\\Models\\Indexable_Extension' => $baseDir . '/src/models/indexable-extension.php', + 'Yoast\\WP\\SEO\\Models\\Indexable_Hierarchy' => $baseDir . '/src/models/indexable-hierarchy.php', + 'Yoast\\WP\\SEO\\Models\\Primary_Term' => $baseDir . '/src/models/primary-term.php', + 'Yoast\\WP\\SEO\\Models\\SEO_Links' => $baseDir . '/src/models/seo-links.php', + 'Yoast\\WP\\SEO\\Models\\SEO_Meta' => $baseDir . '/src/models/seo-meta.php', + 'Yoast\\WP\\SEO\\Presentations\\Abstract_Presentation' => $baseDir . '/src/presentations/abstract-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Archive_Adjacent' => $baseDir . '/src/presentations/archive-adjacent-trait.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Author_Archive_Presentation' => $baseDir . '/src/presentations/indexable-author-archive-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Date_Archive_Presentation' => $baseDir . '/src/presentations/indexable-date-archive-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Error_Page_Presentation' => $baseDir . '/src/presentations/indexable-error-page-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Home_Page_Presentation' => $baseDir . '/src/presentations/indexable-home-page-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Post_Type_Archive_Presentation' => $baseDir . '/src/presentations/indexable-post-type-archive-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Post_Type_Presentation' => $baseDir . '/src/presentations/indexable-post-type-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Presentation' => $baseDir . '/src/presentations/indexable-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Search_Result_Page_Presentation' => $baseDir . '/src/presentations/indexable-search-result-page-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Static_Home_Page_Presentation' => $baseDir . '/src/presentations/indexable-static-home-page-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Static_Posts_Page_Presentation' => $baseDir . '/src/presentations/indexable-static-posts-page-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Term_Archive_Presentation' => $baseDir . '/src/presentations/indexable-term-archive-presentation.php', + 'Yoast\\WP\\SEO\\Presenters\\Abstract_Indexable_Presenter' => $baseDir . '/src/presenters/abstract-indexable-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Abstract_Indexable_Tag_Presenter' => $baseDir . '/src/presenters/abstract-indexable-tag-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Abstract_Presenter' => $baseDir . '/src/presenters/abstract-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Alert_Presenter' => $baseDir . '/src/presenters/admin/alert-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Auto_Update_Notification_Presenter' => $baseDir . '/src/presenters/admin/auto-update-notification-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Badge_Presenter' => $baseDir . '/src/presenters/admin/badge-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Help_Link_Presenter' => $baseDir . '/src/presenters/admin/help-link-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexation_List_Item_Presenter' => $baseDir . '/src/deprecated/src/presenters/admin/indexation-list-item-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexation_Modal_Presenter' => $baseDir . '/src/deprecated/src/presenters/admin/indexation-modal-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexation_Permalink_Warning_Presenter' => $baseDir . '/src/deprecated/src/presenters/admin/indexation-permalink-warning-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexation_Warning_Presenter' => $baseDir . '/src/deprecated/src/presenters/admin/indexation-warning-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexing_Error_Presenter' => $baseDir . '/src/presenters/admin/indexing-error-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexing_Failed_Notification_Presenter' => $baseDir . '/src/presenters/admin/indexing-failed-notification-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexing_List_Item_Presenter' => $baseDir . '/src/presenters/admin/indexing-list-item-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexing_Notification_Presenter' => $baseDir . '/src/presenters/admin/indexing-notification-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Light_Switch_Presenter' => $baseDir . '/src/presenters/admin/light-switch-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Link_Count_Indexing_List_Item_Presenter' => $baseDir . '/src/deprecated/src/presenters/admin/link-count-indexing-list-item-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Link_Count_Indexing_Modal_Presenter' => $baseDir . '/src/deprecated/src/presenters/admin/link-count-indexing-modal-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Meta_Fields_Presenter' => $baseDir . '/src/presenters/admin/meta-fields-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Migration_Error_Presenter' => $baseDir . '/src/presenters/admin/migration-error-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Premium_Badge_Presenter' => $baseDir . '/src/presenters/admin/premium-badge-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Bingbot_Presenter' => $baseDir . '/src/presenters/bingbot-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Breadcrumbs_Presenter' => $baseDir . '/src/presenters/breadcrumbs-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Canonical_Presenter' => $baseDir . '/src/presenters/canonical-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Debug\\Marker_Close_Presenter' => $baseDir . '/src/presenters/debug/marker-close-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Debug\\Marker_Open_Presenter' => $baseDir . '/src/presenters/debug/marker-open-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Googlebot_Presenter' => $baseDir . '/src/presenters/googlebot-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Meta_Description_Presenter' => $baseDir . '/src/presenters/meta-description-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Article_Author_Presenter' => $baseDir . '/src/presenters/open-graph/article-author-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Article_Modified_Time_Presenter' => $baseDir . '/src/presenters/open-graph/article-modified-time-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Article_Published_Time_Presenter' => $baseDir . '/src/presenters/open-graph/article-published-time-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Article_Publisher_Presenter' => $baseDir . '/src/presenters/open-graph/article-publisher-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Description_Presenter' => $baseDir . '/src/presenters/open-graph/description-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\FB_App_ID_Presenter' => $baseDir . '/src/deprecated/src/presenters/open-graph/fb-app-id-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Image_Presenter' => $baseDir . '/src/presenters/open-graph/image-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Locale_Presenter' => $baseDir . '/src/presenters/open-graph/locale-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Site_Name_Presenter' => $baseDir . '/src/presenters/open-graph/site-name-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Title_Presenter' => $baseDir . '/src/presenters/open-graph/title-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Type_Presenter' => $baseDir . '/src/presenters/open-graph/type-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Url_Presenter' => $baseDir . '/src/presenters/open-graph/url-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Rel_Next_Presenter' => $baseDir . '/src/presenters/rel-next-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Rel_Prev_Presenter' => $baseDir . '/src/presenters/rel-prev-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Robots_Presenter' => $baseDir . '/src/presenters/robots-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Schema_Presenter' => $baseDir . '/src/presenters/schema-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Slack\\Enhanced_Data_Presenter' => $baseDir . '/src/presenters/slack/enhanced-data-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Title_Presenter' => $baseDir . '/src/presenters/title-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Card_Presenter' => $baseDir . '/src/presenters/twitter/card-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Creator_Presenter' => $baseDir . '/src/presenters/twitter/creator-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Description_Presenter' => $baseDir . '/src/presenters/twitter/description-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Image_Presenter' => $baseDir . '/src/presenters/twitter/image-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Site_Presenter' => $baseDir . '/src/presenters/twitter/site-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Title_Presenter' => $baseDir . '/src/presenters/twitter/title-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Url_List_Presenter' => $baseDir . '/src/presenters/url-list-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Webmaster\\Baidu_Presenter' => $baseDir . '/src/presenters/webmaster/baidu-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Webmaster\\Bing_Presenter' => $baseDir . '/src/presenters/webmaster/bing-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Webmaster\\Google_Presenter' => $baseDir . '/src/presenters/webmaster/google-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Webmaster\\Pinterest_Presenter' => $baseDir . '/src/presenters/webmaster/pinterest-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Webmaster\\Yandex_Presenter' => $baseDir . '/src/presenters/webmaster/yandex-presenter.php', + 'Yoast\\WP\\SEO\\Repositories\\Indexable_Hierarchy_Repository' => $baseDir . '/src/repositories/indexable-hierarchy-repository.php', + 'Yoast\\WP\\SEO\\Repositories\\Indexable_Repository' => $baseDir . '/src/repositories/indexable-repository.php', + 'Yoast\\WP\\SEO\\Repositories\\Primary_Term_Repository' => $baseDir . '/src/repositories/primary-term-repository.php', + 'Yoast\\WP\\SEO\\Repositories\\SEO_Links_Repository' => $baseDir . '/src/repositories/seo-links-repository.php', + 'Yoast\\WP\\SEO\\Repositories\\SEO_Meta_Repository' => $baseDir . '/src/repositories/seo-meta-repository.php', + 'Yoast\\WP\\SEO\\Routes\\Abstract_Indexation_Route' => $baseDir . '/src/routes/abstract-indexation-route.php', + 'Yoast\\WP\\SEO\\Routes\\Alert_Dismissal_Route' => $baseDir . '/src/routes/alert-dismissal-route.php', + 'Yoast\\WP\\SEO\\Routes\\Indexables_Head_Route' => $baseDir . '/src/routes/indexables-head-route.php', + 'Yoast\\WP\\SEO\\Routes\\Indexing_Route' => $baseDir . '/src/routes/indexing-route.php', + 'Yoast\\WP\\SEO\\Routes\\Route_Interface' => $baseDir . '/src/routes/route-interface.php', + 'Yoast\\WP\\SEO\\Routes\\SEMrush_Route' => $baseDir . '/src/routes/semrush-route.php', + 'Yoast\\WP\\SEO\\Routes\\Supported_Features_Route' => $baseDir . '/src/routes/supported-features-route.php', + 'Yoast\\WP\\SEO\\Routes\\Yoast_Head_REST_Field' => $baseDir . '/src/routes/yoast-head-rest-field.php', + 'Yoast\\WP\\SEO\\Schema_Templates\\Assets\\Icons' => $baseDir . '/src/schema-templates/assets/icons.php', + 'Yoast\\WP\\SEO\\Surfaces\\Classes_Surface' => $baseDir . '/src/surfaces/classes-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Helpers_Surface' => $baseDir . '/src/surfaces/helpers-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Meta_Surface' => $baseDir . '/src/surfaces/meta-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Open_Graph_Helpers_Surface' => $baseDir . '/src/surfaces/open-graph-helpers-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Schema_Helpers_Surface' => $baseDir . '/src/surfaces/schema-helpers-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Twitter_Helpers_Surface' => $baseDir . '/src/surfaces/twitter-helpers-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Values\\Meta' => $baseDir . '/src/surfaces/values/meta.php', + 'Yoast\\WP\\SEO\\Values\\Images' => $baseDir . '/src/values/images.php', + 'Yoast\\WP\\SEO\\Values\\Open_Graph\\Images' => $baseDir . '/src/values/open-graph/images.php', + 'Yoast\\WP\\SEO\\Values\\SEMrush\\SEMrush_Token' => $baseDir . '/src/values/semrush/semrush-token.php', + 'Yoast\\WP\\SEO\\WordPress\\Wrapper' => $baseDir . '/src/wordpress/wrapper.php', + 'Yoast\\WP\\SEO\\Wrappers\\WP_Query_Wrapper' => $baseDir . '/src/wrappers/wp-query-wrapper.php', + 'Yoast\\WP\\SEO\\Wrappers\\WP_Remote_Handler' => $baseDir . '/src/wrappers/wp-remote-handler.php', + 'Yoast\\WP\\SEO\\Wrappers\\WP_Rewrite_Wrapper' => $baseDir . '/src/wrappers/wp-rewrite-wrapper.php', 'Yoast_Dashboard_Widget' => $baseDir . '/admin/class-yoast-dashboard-widget.php', 'Yoast_Dismissable_Notice_Ajax' => $baseDir . '/admin/ajax/class-yoast-dismissable-notice.php', + 'Yoast_Feature_Toggle' => $baseDir . '/admin/views/class-yoast-feature-toggle.php', + 'Yoast_Feature_Toggles' => $baseDir . '/admin/views/class-yoast-feature-toggles.php', 'Yoast_Form' => $baseDir . '/admin/class-yoast-form.php', 'Yoast_Form_Element' => $baseDir . '/admin/views/interface-yoast-form-element.php', - 'Yoast_Form_Fieldset' => $baseDir . '/admin/views/class-yoast-form-fieldset.php', - 'Yoast_I18n_WordPressOrg_v3' => $vendorDir . '/yoast/i18n-module/src/i18n-module-wordpressorg.php', - 'Yoast_I18n_v3' => $vendorDir . '/yoast/i18n-module/src/i18n-module.php', + 'Yoast_I18n_WordPressOrg_v3' => $vendorDir . '/yoast/i18n-module/src/i18n-wordpressorg-v3.php', + 'Yoast_I18n_v3' => $vendorDir . '/yoast/i18n-module/src/i18n-v3.php', 'Yoast_Input_Select' => $baseDir . '/admin/views/class-yoast-input-select.php', - 'Yoast_License_Manager' => $vendorDir . '/yoast/license-manager/class-license-manager.php', + 'Yoast_Input_Validation' => $baseDir . '/admin/class-yoast-input-validation.php', + 'Yoast_Integration_Toggles' => $baseDir . '/admin/views/class-yoast-integration-toggles.php', + 'Yoast_Network_Admin' => $baseDir . '/admin/class-yoast-network-admin.php', + 'Yoast_Network_Settings_API' => $baseDir . '/admin/class-yoast-network-settings-api.php', 'Yoast_Notification' => $baseDir . '/admin/class-yoast-notification.php', 'Yoast_Notification_Center' => $baseDir . '/admin/class-yoast-notification-center.php', - 'Yoast_OnPage_Ajax' => $baseDir . '/admin/ajax/class-yoast-onpage-ajax.php', + 'Yoast_Notifications' => $baseDir . '/admin/class-yoast-notifications.php', + 'Yoast_OnPage_Ajax' => $baseDir . '/src/deprecated/admin/ajax/class-yoast-onpage-ajax.php', 'Yoast_Plugin_Conflict' => $baseDir . '/admin/class-yoast-plugin-conflict.php', 'Yoast_Plugin_Conflict_Ajax' => $baseDir . '/admin/ajax/class-yoast-plugin-conflict-ajax.php', - 'Yoast_Plugin_License_Manager' => $vendorDir . '/yoast/license-manager/class-plugin-license-manager.php', - 'Yoast_Plugin_Update_Manager' => $vendorDir . '/yoast/license-manager/class-plugin-update-manager.php', - 'Yoast_Product' => $vendorDir . '/yoast/license-manager/class-product.php', - 'Yoast_Theme_License_Manager' => $vendorDir . '/yoast/license-manager/class-theme-license-manager.php', - 'Yoast_Theme_Update_Manager' => $vendorDir . '/yoast/license-manager/class-theme-update-manager.php', - 'Yoast_Update_Manager' => $vendorDir . '/yoast/license-manager/class-update-manager.php', 'Yoast_View_Utils' => $baseDir . '/admin/views/class-view-utils.php', - 'iYoast_License_Manager' => $vendorDir . '/yoast/license-manager/class-license-manager.php', - 'xrstf\\Composer52\\AutoloadGenerator' => $vendorDir . '/xrstf/composer-php52/lib/xrstf/Composer52/AutoloadGenerator.php', - 'xrstf\\Composer52\\Generator' => $vendorDir . '/xrstf/composer-php52/lib/xrstf/Composer52/Generator.php', ); diff --git a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_files.php b/wp-content/plugins/wordpress-seo/vendor/composer/autoload_files.php deleted file mode 100644 index b9d0df5d..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_files.php +++ /dev/null @@ -1,10 +0,0 @@ - $vendorDir . '/yoast/whip/src/facades/wordpress.php', -); diff --git a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_namespaces.php b/wp-content/plugins/wordpress-seo/vendor/composer/autoload_namespaces.php index 420e8467..b7fc0125 100644 --- a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_namespaces.php +++ b/wp-content/plugins/wordpress-seo/vendor/composer/autoload_namespaces.php @@ -6,5 +6,4 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - 'xrstf\\Composer52' => array($vendorDir . '/xrstf/composer-php52/lib'), ); diff --git a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_real.php b/wp-content/plugins/wordpress-seo/vendor/composer/autoload_real.php index fe068a4c..f6f32a5a 100644 --- a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_real.php +++ b/wp-content/plugins/wordpress-seo/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInite65e71171c1a5e9e7f808031e878a5e0 +class ComposerAutoloaderInit91ec1988dfabfb54a53c085331eb54a0 { private static $loader; @@ -19,15 +19,15 @@ class ComposerAutoloaderInite65e71171c1a5e9e7f808031e878a5e0 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInite65e71171c1a5e9e7f808031e878a5e0', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit91ec1988dfabfb54a53c085331eb54a0', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInite65e71171c1a5e9e7f808031e878a5e0', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit91ec1988dfabfb54a53c085331eb54a0', 'loadClassLoader')); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); if ($useStaticLoader) { require_once __DIR__ . '/autoload_static.php'; - call_user_func(\Composer\Autoload\ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0::getInitializer($loader)); + call_user_func(\Composer\Autoload\ComposerStaticInit91ec1988dfabfb54a53c085331eb54a0::getInitializer($loader)); } else { $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { @@ -47,24 +47,6 @@ class ComposerAutoloaderInite65e71171c1a5e9e7f808031e878a5e0 $loader->register(true); - if ($useStaticLoader) { - $includeFiles = Composer\Autoload\ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0::$files; - } else { - $includeFiles = require __DIR__ . '/autoload_files.php'; - } - foreach ($includeFiles as $fileIdentifier => $file) { - composerRequiree65e71171c1a5e9e7f808031e878a5e0($fileIdentifier, $file); - } - return $loader; } } - -function composerRequiree65e71171c1a5e9e7f808031e878a5e0($fileIdentifier, $file) -{ - if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { - require $file; - - $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_real_52.php b/wp-content/plugins/wordpress-seo/vendor/composer/autoload_real_52.php deleted file mode 100644 index 41609e0f..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_real_52.php +++ /dev/null @@ -1,46 +0,0 @@ - $path) { - $loader->add($namespace, $path); - } - - $classMap = require $dir.'/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - - $loader->register(true); - - require $vendorDir . '/yoast/whip/src/facades/wordpress.php'; - - return $loader; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_static.php b/wp-content/plugins/wordpress-seo/vendor/composer/autoload_static.php index 0b1d094e..d36089fd 100644 --- a/wp-content/plugins/wordpress-seo/vendor/composer/autoload_static.php +++ b/wp-content/plugins/wordpress-seo/vendor/composer/autoload_static.php @@ -4,12 +4,8 @@ namespace Composer\Autoload; -class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 +class ComposerStaticInit91ec1988dfabfb54a53c085331eb54a0 { - public static $files = array ( - '995b589e693a50f54393aa31ee1c3763' => __DIR__ . '/..' . '/yoast/whip/src/facades/wordpress.php', - ); - public static $prefixLengthsPsr4 = array ( 'C' => array ( @@ -24,16 +20,6 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 ), ); - public static $prefixesPsr0 = array ( - 'x' => - array ( - 'xrstf\\Composer52' => - array ( - 0 => __DIR__ . '/..' . '/xrstf/composer-php52/lib', - ), - ), - ); - public static $classMap = array ( 'Composer\\Installers\\AglInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AglInstaller.php', 'Composer\\Installers\\AimeosInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AimeosInstaller.php', @@ -45,6 +31,7 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'Composer\\Installers\\BonefishInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/BonefishInstaller.php', 'Composer\\Installers\\CakePHPInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/CakePHPInstaller.php', 'Composer\\Installers\\ChefInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ChefInstaller.php', + 'Composer\\Installers\\CiviCrmInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/CiviCrmInstaller.php', 'Composer\\Installers\\ClanCatsFrameworkInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php', 'Composer\\Installers\\CockpitInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/CockpitInstaller.php', 'Composer\\Installers\\CodeIgniterInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php', @@ -52,6 +39,7 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'Composer\\Installers\\CraftInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/CraftInstaller.php', 'Composer\\Installers\\CroogoInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/CroogoInstaller.php', 'Composer\\Installers\\DecibelInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/DecibelInstaller.php', + 'Composer\\Installers\\DframeInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/DframeInstaller.php', 'Composer\\Installers\\DokuWikiInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/DokuWikiInstaller.php', 'Composer\\Installers\\DolibarrInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/DolibarrInstaller.php', 'Composer\\Installers\\DrupalInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/DrupalInstaller.php', @@ -69,6 +57,7 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'Composer\\Installers\\JoomlaInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/JoomlaInstaller.php', 'Composer\\Installers\\KanboardInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/KanboardInstaller.php', 'Composer\\Installers\\KirbyInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/KirbyInstaller.php', + 'Composer\\Installers\\KnownInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/KnownInstaller.php', 'Composer\\Installers\\KodiCMSInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/KodiCMSInstaller.php', 'Composer\\Installers\\KohanaInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/KohanaInstaller.php', 'Composer\\Installers\\LanManagementSystemInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php', @@ -78,11 +67,14 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'Composer\\Installers\\MODULEWorkInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php', 'Composer\\Installers\\MODXEvoInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MODXEvoInstaller.php', 'Composer\\Installers\\MagentoInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MagentoInstaller.php', + 'Composer\\Installers\\MajimaInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MajimaInstaller.php', 'Composer\\Installers\\MakoInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MakoInstaller.php', + 'Composer\\Installers\\MantisBTInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MantisBTInstaller.php', 'Composer\\Installers\\MauticInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MauticInstaller.php', 'Composer\\Installers\\MayaInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MayaInstaller.php', 'Composer\\Installers\\MediaWikiInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MediaWikiInstaller.php', 'Composer\\Installers\\MicroweberInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MicroweberInstaller.php', + 'Composer\\Installers\\ModxInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ModxInstaller.php', 'Composer\\Installers\\MoodleInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/MoodleInstaller.php', 'Composer\\Installers\\OctoberInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/OctoberInstaller.php', 'Composer\\Installers\\OntoWikiInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/OntoWikiInstaller.php', @@ -98,17 +90,22 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'Composer\\Installers\\PortoInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/PortoInstaller.php', 'Composer\\Installers\\PrestashopInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/PrestashopInstaller.php', 'Composer\\Installers\\PuppetInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/PuppetInstaller.php', + 'Composer\\Installers\\PxcmsInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/PxcmsInstaller.php', 'Composer\\Installers\\RadPHPInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/RadPHPInstaller.php', 'Composer\\Installers\\ReIndexInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ReIndexInstaller.php', + 'Composer\\Installers\\Redaxo5Installer' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/Redaxo5Installer.php', 'Composer\\Installers\\RedaxoInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/RedaxoInstaller.php', 'Composer\\Installers\\RoundcubeInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/RoundcubeInstaller.php', 'Composer\\Installers\\SMFInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/SMFInstaller.php', 'Composer\\Installers\\ShopwareInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ShopwareInstaller.php', 'Composer\\Installers\\SilverStripeInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/SilverStripeInstaller.php', + 'Composer\\Installers\\SiteDirectInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/SiteDirectInstaller.php', 'Composer\\Installers\\SyDESInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/SyDESInstaller.php', + 'Composer\\Installers\\SyliusInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/SyliusInstaller.php', 'Composer\\Installers\\Symfony1Installer' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/Symfony1Installer.php', 'Composer\\Installers\\TYPO3CmsInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php', 'Composer\\Installers\\TYPO3FlowInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php', + 'Composer\\Installers\\TaoInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/TaoInstaller.php', 'Composer\\Installers\\TheliaInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/TheliaInstaller.php', 'Composer\\Installers\\TuskInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/TuskInstaller.php', 'Composer\\Installers\\UserFrostingInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/UserFrostingInstaller.php', @@ -121,29 +118,33 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'Composer\\Installers\\ZendInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ZendInstaller.php', 'Composer\\Installers\\ZikulaInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/ZikulaInstaller.php', 'WPSEO_Abstract_Capability_Manager' => __DIR__ . '/../..' . '/admin/capabilities/class-abstract-capability-manager.php', + 'WPSEO_Abstract_Metabox_Tab_With_Sections' => __DIR__ . '/../..' . '/admin/metabox/class-abstract-sectioned-metabox-tab.php', 'WPSEO_Abstract_Post_Filter' => __DIR__ . '/../..' . '/admin/filters/class-abstract-post-filter.php', 'WPSEO_Abstract_Role_Manager' => __DIR__ . '/../..' . '/admin/roles/class-abstract-role-manager.php', + 'WPSEO_Add_Keyword_Modal' => __DIR__ . '/../..' . '/src/deprecated/admin/add-keyword-modal.php', + 'WPSEO_Addon_Manager' => __DIR__ . '/../..' . '/inc/class-addon-manager.php', 'WPSEO_Admin' => __DIR__ . '/../..' . '/admin/class-admin.php', 'WPSEO_Admin_Asset' => __DIR__ . '/../..' . '/admin/class-asset.php', + 'WPSEO_Admin_Asset_Analysis_Worker_Location' => __DIR__ . '/../..' . '/admin/class-admin-asset-analysis-worker-location.php', 'WPSEO_Admin_Asset_Dev_Server_Location' => __DIR__ . '/../..' . '/admin/class-admin-asset-dev-server-location.php', 'WPSEO_Admin_Asset_Location' => __DIR__ . '/../..' . '/admin/class-admin-asset-location.php', 'WPSEO_Admin_Asset_Manager' => __DIR__ . '/../..' . '/admin/class-admin-asset-manager.php', 'WPSEO_Admin_Asset_SEO_Location' => __DIR__ . '/../..' . '/admin/class-admin-asset-seo-location.php', - 'WPSEO_Admin_Banner' => __DIR__ . '/../..' . '/admin/banner/class-admin-banner.php', - 'WPSEO_Admin_Banner_Renderer' => __DIR__ . '/../..' . '/admin/banner/class-admin-banner-renderer.php', - 'WPSEO_Admin_Banner_Sidebar' => __DIR__ . '/../..' . '/admin/banner/class-admin-banner-sidebar.php', - 'WPSEO_Admin_Banner_Sidebar_Renderer' => __DIR__ . '/../..' . '/admin/banner/class-admin-banner-sidebar-renderer.php', - 'WPSEO_Admin_Banner_Spot' => __DIR__ . '/../..' . '/admin/banner/class-admin-banner-spot.php', - 'WPSEO_Admin_Banner_Spot_Renderer' => __DIR__ . '/../..' . '/admin/banner/class-admin-banner-spot-renderer.php', + 'WPSEO_Admin_Asset_Yoast_Components_L10n' => __DIR__ . '/../..' . '/admin/class-admin-asset-yoast-components-l10n.php', + 'WPSEO_Admin_Bar_Menu' => __DIR__ . '/../..' . '/inc/class-wpseo-admin-bar-menu.php', + 'WPSEO_Admin_Editor_Specific_Replace_Vars' => __DIR__ . '/../..' . '/admin/class-admin-editor-specific-replace-vars.php', + 'WPSEO_Admin_Gutenberg_Compatibility_Notification' => __DIR__ . '/../..' . '/admin/class-admin-gutenberg-compatibility-notification.php', 'WPSEO_Admin_Help_Panel' => __DIR__ . '/../..' . '/admin/class-admin-help-panel.php', 'WPSEO_Admin_Init' => __DIR__ . '/../..' . '/admin/class-admin-init.php', 'WPSEO_Admin_Menu' => __DIR__ . '/../..' . '/admin/menu/class-admin-menu.php', 'WPSEO_Admin_Pages' => __DIR__ . '/../..' . '/admin/class-config.php', + 'WPSEO_Admin_Recommended_Replace_Vars' => __DIR__ . '/../..' . '/admin/class-admin-recommended-replace-vars.php', + 'WPSEO_Admin_Settings_Changed_Listener' => __DIR__ . '/../..' . '/admin/admin-settings-changed-listener.php', 'WPSEO_Admin_User_Profile' => __DIR__ . '/../..' . '/admin/class-admin-user-profile.php', 'WPSEO_Admin_Utils' => __DIR__ . '/../..' . '/admin/class-admin-utils.php', - 'WPSEO_Advanced_Settings' => __DIR__ . '/../..' . '/deprecated/class-wpseo-advanced-settings.php', 'WPSEO_Author_Sitemap_Provider' => __DIR__ . '/../..' . '/inc/sitemaps/class-author-sitemap-provider.php', - 'WPSEO_Breadcrumbs' => __DIR__ . '/../..' . '/frontend/class-breadcrumbs.php', + 'WPSEO_Base_Menu' => __DIR__ . '/../..' . '/admin/menu/class-base-menu.php', + 'WPSEO_Breadcrumbs' => __DIR__ . '/../..' . '/src/deprecated/frontend/breadcrumbs.php', 'WPSEO_Bulk_Description_List_Table' => __DIR__ . '/../..' . '/admin/class-bulk-description-editor-list-table.php', 'WPSEO_Bulk_List_Table' => __DIR__ . '/../..' . '/admin/class-bulk-editor-list-table.php', 'WPSEO_Bulk_Title_Editor_List_Table' => __DIR__ . '/../..' . '/admin/class-bulk-title-editor-list-table.php', @@ -156,42 +157,37 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'WPSEO_Collection' => __DIR__ . '/../..' . '/admin/interface-collection.php', 'WPSEO_Collector' => __DIR__ . '/../..' . '/admin/class-collector.php', 'WPSEO_Config_Component' => __DIR__ . '/../..' . '/admin/config-ui/components/interface-component.php', - 'WPSEO_Config_Component_Configuration_Choices' => __DIR__ . '/../..' . '/admin/config-ui/components/class-component-configuration-choices.php', - 'WPSEO_Config_Component_Connect_Google_Search_Console' => __DIR__ . '/../..' . '/admin/config-ui/components/class-component-connect-google-search-console.php', 'WPSEO_Config_Component_Mailchimp_Signup' => __DIR__ . '/../..' . '/admin/config-ui/components/class-component-mailchimp-signup.php', 'WPSEO_Config_Component_Suggestions' => __DIR__ . '/../..' . '/admin/config-ui/components/class-component-suggestions.php', 'WPSEO_Config_Factory_Post_Type' => __DIR__ . '/../..' . '/admin/config-ui/factories/class-factory-post-type.php', 'WPSEO_Config_Field' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field.php', 'WPSEO_Config_Field_Choice' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-choice.php', 'WPSEO_Config_Field_Choice_Post_Type' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-choice-post-type.php', + 'WPSEO_Config_Field_Company_Info_Missing' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-company-info-missing.php', 'WPSEO_Config_Field_Company_Logo' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-company-logo.php', 'WPSEO_Config_Field_Company_Name' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-company-name.php', 'WPSEO_Config_Field_Company_Or_Person' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-company-or-person.php', - 'WPSEO_Config_Field_Configuration_Choices' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-configuration-choices.php', - 'WPSEO_Config_Field_Connect_Google_Search_Console' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-connect-google-search-console.php', 'WPSEO_Config_Field_Environment' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-environment.php', - 'WPSEO_Config_Field_Google_Search_Console_Intro' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-google-search-console-intro.php', 'WPSEO_Config_Field_Mailchimp_Signup' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-mailchimp-signup.php', 'WPSEO_Config_Field_Multiple_Authors' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-multiple-authors.php', - 'WPSEO_Config_Field_Person_Name' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-person-name.php', + 'WPSEO_Config_Field_Person' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-person.php', 'WPSEO_Config_Field_Post_Type_Visibility' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-post-type-visibility.php', 'WPSEO_Config_Field_Profile_URL_Facebook' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-profile-url-facebook.php', - 'WPSEO_Config_Field_Profile_URL_GooglePlus' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-profile-url-googleplus.php', 'WPSEO_Config_Field_Profile_URL_Instagram' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-profile-url-instagram.php', 'WPSEO_Config_Field_Profile_URL_LinkedIn' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-profile-url-linkedin.php', 'WPSEO_Config_Field_Profile_URL_MySpace' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-profile-url-myspace.php', 'WPSEO_Config_Field_Profile_URL_Pinterest' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-profile-url-pinterest.php', 'WPSEO_Config_Field_Profile_URL_Twitter' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-profile-url-twitter.php', + 'WPSEO_Config_Field_Profile_URL_Wikipedia' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-profile-url-wikipedia.php', 'WPSEO_Config_Field_Profile_URL_YouTube' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-profile-url-youtube.php', 'WPSEO_Config_Field_Separator' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-separator.php', 'WPSEO_Config_Field_Site_Name' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-site-name.php', 'WPSEO_Config_Field_Site_Type' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-site-type.php', - 'WPSEO_Config_Field_Social_Profiles_Intro' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-social-profiles-intro.php', 'WPSEO_Config_Field_Success_Message' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-success-message.php', 'WPSEO_Config_Field_Suggestions' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-suggestions.php', 'WPSEO_Config_Field_Title_Intro' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-title-intro.php', - 'WPSEO_Config_Field_Upsell_Configuration_Service' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-upsell-configuration-service.php', - 'WPSEO_Config_Field_Upsell_Site_Review' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-upsell-site-review.php', + 'WPSEO_Config_Field_Tracking' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-tracking.php', + 'WPSEO_Config_Field_Tracking_Intro' => __DIR__ . '/../..' . '/admin/config-ui/fields/class-field-tracking-intro.php', 'WPSEO_Configuration_Components' => __DIR__ . '/../..' . '/admin/config-ui/class-configuration-components.php', 'WPSEO_Configuration_Endpoint' => __DIR__ . '/../..' . '/admin/config-ui/class-configuration-endpoint.php', 'WPSEO_Configuration_Notifier' => __DIR__ . '/../..' . '/admin/notifiers/class-configuration-notifier.php', @@ -201,108 +197,104 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'WPSEO_Configuration_Storage' => __DIR__ . '/../..' . '/admin/config-ui/class-configuration-storage.php', 'WPSEO_Configuration_Structure' => __DIR__ . '/../..' . '/admin/config-ui/class-configuration-structure.php', 'WPSEO_Configuration_Translations' => __DIR__ . '/../..' . '/admin/config-ui/class-configuration-translations.php', - 'WPSEO_Cornerstone' => __DIR__ . '/../..' . '/admin/class-cornerstone.php', - 'WPSEO_Cornerstone_Field' => __DIR__ . '/../..' . '/admin/class-cornerstone-field.php', + 'WPSEO_Content_Images' => __DIR__ . '/../..' . '/inc/class-wpseo-content-images.php', 'WPSEO_Cornerstone_Filter' => __DIR__ . '/../..' . '/admin/filters/class-cornerstone-filter.php', + 'WPSEO_Custom_Fields' => __DIR__ . '/../..' . '/inc/class-wpseo-custom-fields.php', + 'WPSEO_Custom_Taxonomies' => __DIR__ . '/../..' . '/inc/class-wpseo-custom-taxonomies.php', 'WPSEO_Customizer' => __DIR__ . '/../..' . '/admin/class-customizer.php', 'WPSEO_Database_Proxy' => __DIR__ . '/../..' . '/admin/class-database-proxy.php', + 'WPSEO_Date_Helper' => __DIR__ . '/../..' . '/inc/date-helper.php', + 'WPSEO_Deprecated_Graph_Piece' => __DIR__ . '/../..' . '/src/deprecated/frontend/abstract-class-deprecated-schema-piece.php', + 'WPSEO_Dismissible_Notification' => __DIR__ . '/../..' . '/admin/notifiers/dismissible-notification.php', 'WPSEO_Endpoint' => __DIR__ . '/../..' . '/admin/endpoints/class-endpoint.php', - 'WPSEO_Endpoint_Ryte' => __DIR__ . '/../..' . '/admin/endpoints/class-endpoint-ryte.php', + 'WPSEO_Endpoint_File_Size' => __DIR__ . '/../..' . '/admin/endpoints/class-endpoint-file-size.php', + 'WPSEO_Endpoint_Ryte' => __DIR__ . '/../..' . '/src/deprecated/admin/endpoints/class-endpoint-ryte.php', 'WPSEO_Endpoint_Statistics' => __DIR__ . '/../..' . '/admin/endpoints/class-endpoint-statistics.php', 'WPSEO_Export' => __DIR__ . '/../..' . '/admin/class-export.php', - 'WPSEO_Extension' => __DIR__ . '/../..' . '/admin/class-extension.php', - 'WPSEO_Extension_Manager' => __DIR__ . '/../..' . '/admin/class-extension-manager.php', - 'WPSEO_Extensions' => __DIR__ . '/../..' . '/admin/class-extensions.php', + 'WPSEO_Expose_Shortlinks' => __DIR__ . '/../..' . '/admin/class-expose-shortlinks.php', + 'WPSEO_Extension' => __DIR__ . '/../..' . '/src/deprecated/admin/extension.php', + 'WPSEO_Extension_Manager' => __DIR__ . '/../..' . '/src/deprecated/admin/extension-manager.php', + 'WPSEO_Extensions' => __DIR__ . '/../..' . '/src/deprecated/admin/extensions.php', 'WPSEO_Features' => __DIR__ . '/../..' . '/inc/class-wpseo-features.php', - 'WPSEO_Frontend' => __DIR__ . '/../..' . '/frontend/class-frontend.php', - 'WPSEO_Frontend_Page_Type' => __DIR__ . '/../..' . '/frontend/class-frontend-page-type.php', - 'WPSEO_Frontend_Primary_Category' => __DIR__ . '/../..' . '/frontend/class-primary-category.php', + 'WPSEO_File_Size_Exception' => __DIR__ . '/../..' . '/admin/exceptions/class-file-size-exception.php', + 'WPSEO_File_Size_Service' => __DIR__ . '/../..' . '/admin/services/class-file-size.php', + 'WPSEO_Frontend' => __DIR__ . '/../..' . '/src/deprecated/frontend/frontend.php', + 'WPSEO_Frontend_Page_Type' => __DIR__ . '/../..' . '/src/deprecated/frontend/class-frontend-page-type.php', + 'WPSEO_Frontend_Primary_Category' => __DIR__ . '/../..' . '/src/deprecated/frontend/class-primary-category.php', 'WPSEO_GSC' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc.php', - 'WPSEO_GSC_Ajax' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-ajax.php', - 'WPSEO_GSC_Bulk_Action' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-bulk-action.php', - 'WPSEO_GSC_Category_Filters' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-category-filters.php', - 'WPSEO_GSC_Config' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-config.php', - 'WPSEO_GSC_Count' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-count.php', - 'WPSEO_GSC_Issue' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-issue.php', - 'WPSEO_GSC_Issues' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-issues.php', - 'WPSEO_GSC_Mapper' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-mapper.php', - 'WPSEO_GSC_Marker' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-marker.php', - 'WPSEO_GSC_Modal' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-modal.php', - 'WPSEO_GSC_Platform_Tabs' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-platform-tabs.php', - 'WPSEO_GSC_Service' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-service.php', - 'WPSEO_GSC_Settings' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-settings.php', - 'WPSEO_GSC_Table' => __DIR__ . '/../..' . '/admin/google_search_console/class-gsc-table.php', - 'WPSEO_Help_Center' => __DIR__ . '/../..' . '/admin/class-help-center.php', - 'WPSEO_Help_Center_Item' => __DIR__ . '/../..' . '/admin/class-help-center-item.php', + 'WPSEO_Graph_Piece' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/interface-wpseo-graph-piece.php', + 'WPSEO_Gutenberg_Compatibility' => __DIR__ . '/../..' . '/admin/class-gutenberg-compatibility.php', + 'WPSEO_Handle_404' => __DIR__ . '/../..' . '/src/deprecated/frontend/class-handle-404.php', + 'WPSEO_Health_Check' => __DIR__ . '/../..' . '/inc/health-check.php', + 'WPSEO_Health_Check_Curl_Version' => __DIR__ . '/../..' . '/inc/health-check-curl-version.php', + 'WPSEO_Health_Check_Default_Tagline' => __DIR__ . '/../..' . '/inc/health-check-default-tagline.php', + 'WPSEO_Health_Check_Link_Table_Not_Accessible' => __DIR__ . '/../..' . '/inc/health-check-links-table-not-accessible.php', + 'WPSEO_Health_Check_Page_Comments' => __DIR__ . '/../..' . '/inc/health-check-page-comments.php', + 'WPSEO_Health_Check_Postname_Permalink' => __DIR__ . '/../..' . '/inc/health-check-postname-permalink.php', + 'WPSEO_Health_Check_Ryte' => __DIR__ . '/../..' . '/inc/health-check-ryte.php', + 'WPSEO_HelpScout' => __DIR__ . '/../..' . '/admin/class-helpscout.php', + 'WPSEO_Image_Utils' => __DIR__ . '/../..' . '/inc/class-wpseo-image-utils.php', 'WPSEO_Import_AIOSEO' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-aioseo.php', + 'WPSEO_Import_Greg_SEO' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-greg-high-performance-seo.php', 'WPSEO_Import_HeadSpace' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-headspace.php', 'WPSEO_Import_Jetpack_SEO' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-jetpack.php', + 'WPSEO_Import_Platinum_SEO' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-platinum-seo-pack.php', 'WPSEO_Import_Plugin' => __DIR__ . '/../..' . '/admin/import/class-import-plugin.php', 'WPSEO_Import_Plugins_Detector' => __DIR__ . '/../..' . '/admin/import/class-import-detector.php', + 'WPSEO_Import_Premium_SEO_Pack' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-premium-seo-pack.php', + 'WPSEO_Import_RankMath' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-rankmath.php', 'WPSEO_Import_SEOPressor' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-seopressor.php', + 'WPSEO_Import_SEO_Framework' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-seo-framework.php', 'WPSEO_Import_Settings' => __DIR__ . '/../..' . '/admin/import/class-import-settings.php', + 'WPSEO_Import_Smartcrawl_SEO' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-smartcrawl.php', + 'WPSEO_Import_Squirrly' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-squirrly.php', 'WPSEO_Import_Status' => __DIR__ . '/../..' . '/admin/import/class-import-status.php', 'WPSEO_Import_Ultimate_SEO' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-ultimate-seo.php', 'WPSEO_Import_WPSEO' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-wpseo.php', + 'WPSEO_Import_WP_Meta_SEO' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-wp-meta-seo.php', 'WPSEO_Import_WooThemes_SEO' => __DIR__ . '/../..' . '/admin/import/plugins/class-import-woothemes-seo.php', 'WPSEO_Installable' => __DIR__ . '/../..' . '/admin/interface-installable.php', 'WPSEO_Installation' => __DIR__ . '/../..' . '/inc/class-wpseo-installation.php', - 'WPSEO_JSON_LD' => __DIR__ . '/../..' . '/frontend/class-json-ld.php', + 'WPSEO_Keyword_Synonyms_Modal' => __DIR__ . '/../..' . '/src/deprecated/admin/keyword-synonyms-modal.php', 'WPSEO_Language_Utils' => __DIR__ . '/../..' . '/inc/language-utils.php', - 'WPSEO_License_Page_Manager' => __DIR__ . '/../..' . '/admin/class-license-page-manager.php', - 'WPSEO_Link' => __DIR__ . '/../..' . '/admin/links/class-link.php', - 'WPSEO_Link_Cleanup_Transient' => __DIR__ . '/../..' . '/admin/links/class-link-cleanup-transient.php', - 'WPSEO_Link_Column_Count' => __DIR__ . '/../..' . '/admin/links/class-link-column-count.php', - 'WPSEO_Link_Columns' => __DIR__ . '/../..' . '/admin/links/class-link-columns.php', - 'WPSEO_Link_Compatibility_Notifier' => __DIR__ . '/../..' . '/admin/links/class-link-compatibility-notifier.php', - 'WPSEO_Link_Content_Processor' => __DIR__ . '/../..' . '/admin/links/class-link-content-processor.php', - 'WPSEO_Link_Extractor' => __DIR__ . '/../..' . '/admin/links/class-link-extractor.php', - 'WPSEO_Link_Factory' => __DIR__ . '/../..' . '/admin/links/class-link-factory.php', - 'WPSEO_Link_Filter' => __DIR__ . '/../..' . '/admin/links/class-link-filter.php', - 'WPSEO_Link_Installer' => __DIR__ . '/../..' . '/admin/links/class-link-installer.php', - 'WPSEO_Link_Internal_Lookup' => __DIR__ . '/../..' . '/admin/links/class-link-internal-lookup.php', - 'WPSEO_Link_Notifier' => __DIR__ . '/../..' . '/admin/links/class-link-notifier.php', - 'WPSEO_Link_Query' => __DIR__ . '/../..' . '/admin/links/class-link-query.php', - 'WPSEO_Link_Reindex_Dashboard' => __DIR__ . '/../..' . '/admin/links/class-link-reindex-dashboard.php', - 'WPSEO_Link_Reindex_Post_Endpoint' => __DIR__ . '/../..' . '/admin/links/class-link-reindex-post-endpoint.php', - 'WPSEO_Link_Reindex_Post_Service' => __DIR__ . '/../..' . '/admin/links/class-link-reindex-post-service.php', - 'WPSEO_Link_Storage' => __DIR__ . '/../..' . '/admin/links/class-link-storage.php', - 'WPSEO_Link_Table_Accessible' => __DIR__ . '/../..' . '/admin/links/class-link-table-accessible.php', - 'WPSEO_Link_Table_Accessible_Notifier' => __DIR__ . '/../..' . '/admin/links/class-link-table-accessible-notifier.php', - 'WPSEO_Link_Type_Classifier' => __DIR__ . '/../..' . '/admin/links/class-link-type-classifier.php', - 'WPSEO_Link_Utils' => __DIR__ . '/../..' . '/admin/links/class-link-utils.php', - 'WPSEO_Link_Watcher' => __DIR__ . '/../..' . '/admin/links/class-link-watcher.php', - 'WPSEO_Link_Watcher_Loader' => __DIR__ . '/../..' . '/admin/links/class-link-watcher-loader.php', + 'WPSEO_License_Page_Manager' => __DIR__ . '/../..' . '/src/deprecated/admin/license-page-manager.php', + 'WPSEO_Link_Compatibility_Notifier' => __DIR__ . '/../..' . '/src/deprecated/admin/links/class-link-compatibility-notifier.php', + 'WPSEO_Link_Table_Accessible_Notifier' => __DIR__ . '/../..' . '/src/deprecated/admin/links/class-link-table-accessible-notifier.php', 'WPSEO_Listener' => __DIR__ . '/../..' . '/admin/listeners/class-listener.php', 'WPSEO_Menu' => __DIR__ . '/../..' . '/admin/menu/class-menu.php', 'WPSEO_Meta' => __DIR__ . '/../..' . '/inc/class-wpseo-meta.php', 'WPSEO_Meta_Columns' => __DIR__ . '/../..' . '/admin/class-meta-columns.php', - 'WPSEO_Meta_Storage' => __DIR__ . '/../..' . '/admin/class-meta-storage.php', - 'WPSEO_Meta_Table_Accessible' => __DIR__ . '/../..' . '/admin/class-meta-table-accessible.php', 'WPSEO_Metabox' => __DIR__ . '/../..' . '/admin/metabox/class-metabox.php', - 'WPSEO_Metabox_Add_Keyword_Tab' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-add-keyword-tab.php', - 'WPSEO_Metabox_Addon_Tab_Section' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-addon-section.php', 'WPSEO_Metabox_Analysis' => __DIR__ . '/../..' . '/admin/metabox/interface-metabox-analysis.php', 'WPSEO_Metabox_Analysis_Readability' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-analysis-readability.php', 'WPSEO_Metabox_Analysis_SEO' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-analysis-seo.php', + 'WPSEO_Metabox_Collapsible' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-collapsible.php', + 'WPSEO_Metabox_Collapsibles_Sections' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-collapsibles-section.php', 'WPSEO_Metabox_Editor' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-editor.php', 'WPSEO_Metabox_Form_Tab' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-form-tab.php', 'WPSEO_Metabox_Formatter' => __DIR__ . '/../..' . '/admin/formatter/class-metabox-formatter.php', 'WPSEO_Metabox_Formatter_Interface' => __DIR__ . '/../..' . '/admin/formatter/interface-metabox-formatter.php', 'WPSEO_Metabox_Null_Tab' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-null-tab.php', 'WPSEO_Metabox_Section' => __DIR__ . '/../..' . '/admin/metabox/interface-metabox-section.php', + 'WPSEO_Metabox_Section_Additional' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-section-additional.php', + 'WPSEO_Metabox_Section_React' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-section-react.php', + 'WPSEO_Metabox_Section_Readability' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-section-readability.php', 'WPSEO_Metabox_Tab' => __DIR__ . '/../..' . '/admin/metabox/interface-metabox-tab.php', - 'WPSEO_Metabox_Tab_Section' => __DIR__ . '/../..' . '/admin/metabox/class-metabox-tab-section.php', + 'WPSEO_Multiple_Keywords_Modal' => __DIR__ . '/../..' . '/src/deprecated/admin/multiple-keywords-modal.php', + 'WPSEO_MyYoast_Api_Request' => __DIR__ . '/../..' . '/inc/class-my-yoast-api-request.php', + 'WPSEO_MyYoast_Bad_Request_Exception' => __DIR__ . '/../..' . '/inc/exceptions/class-myyoast-bad-request-exception.php', + 'WPSEO_MyYoast_Invalid_JSON_Exception' => __DIR__ . '/../..' . '/inc/exceptions/class-myyoast-invalid-json-exception.php', + 'WPSEO_MyYoast_Proxy' => __DIR__ . '/../..' . '/admin/class-my-yoast-proxy.php', 'WPSEO_Network_Admin_Menu' => __DIR__ . '/../..' . '/admin/menu/class-network-admin-menu.php', - 'WPSEO_OnPage' => __DIR__ . '/../..' . '/admin/onpage/class-onpage.php', - 'WPSEO_OnPage_Option' => __DIR__ . '/../..' . '/admin/onpage/class-onpage-option.php', - 'WPSEO_OnPage_Request' => __DIR__ . '/../..' . '/admin/onpage/class-onpage-request.php', - 'WPSEO_OpenGraph' => __DIR__ . '/../..' . '/frontend/class-opengraph.php', - 'WPSEO_OpenGraph_Image' => __DIR__ . '/../..' . '/frontend/class-opengraph-image.php', + 'WPSEO_Notification_Handler' => __DIR__ . '/../..' . '/admin/notifiers/interface-notification-handler.php', + 'WPSEO_OnPage' => __DIR__ . '/../..' . '/src/deprecated/admin/onpage/class-onpage.php', + 'WPSEO_OnPage_Option' => __DIR__ . '/../..' . '/src/deprecated/admin/onpage/class-onpage-option.php', + 'WPSEO_OnPage_Request' => __DIR__ . '/../..' . '/src/deprecated/admin/onpage/class-onpage-request.php', + 'WPSEO_OpenGraph' => __DIR__ . '/../..' . '/src/deprecated/frontend/class-opengraph.php', + 'WPSEO_OpenGraph_Image' => __DIR__ . '/../..' . '/src/deprecated/frontend/class-opengraph-image.php', + 'WPSEO_OpenGraph_OEmbed' => __DIR__ . '/../..' . '/src/deprecated/frontend/class-opengraph-oembed.php', 'WPSEO_Option' => __DIR__ . '/../..' . '/inc/options/class-wpseo-option.php', - 'WPSEO_Option_InternalLinks' => __DIR__ . '/../..' . '/deprecated/class-wpseo-option-internallinks.php', 'WPSEO_Option_MS' => __DIR__ . '/../..' . '/inc/options/class-wpseo-option-ms.php', - 'WPSEO_Option_Permalinks' => __DIR__ . '/../..' . '/deprecated/class-wpseo-option-permalinks.php', 'WPSEO_Option_Social' => __DIR__ . '/../..' . '/inc/options/class-wpseo-option-social.php', 'WPSEO_Option_Tab' => __DIR__ . '/../..' . '/admin/class-option-tab.php', 'WPSEO_Option_Tabs' => __DIR__ . '/../..' . '/admin/class-option-tabs.php', @@ -310,14 +302,14 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'WPSEO_Option_Titles' => __DIR__ . '/../..' . '/inc/options/class-wpseo-option-titles.php', 'WPSEO_Option_Wpseo' => __DIR__ . '/../..' . '/inc/options/class-wpseo-option-wpseo.php', 'WPSEO_Options' => __DIR__ . '/../..' . '/inc/options/class-wpseo-options.php', - 'WPSEO_Options_Backfill' => __DIR__ . '/../..' . '/inc/options/class-wpseo-options-backfill.php', + 'WPSEO_Paper_Presenter' => __DIR__ . '/../..' . '/admin/class-paper-presenter.php', 'WPSEO_Plugin_Availability' => __DIR__ . '/../..' . '/admin/class-plugin-availability.php', - 'WPSEO_Plugin_Compatibility' => __DIR__ . '/../..' . '/admin/class-plugin-compatibility.php', 'WPSEO_Plugin_Conflict' => __DIR__ . '/../..' . '/admin/class-plugin-conflict.php', 'WPSEO_Plugin_Importer' => __DIR__ . '/../..' . '/admin/import/plugins/class-abstract-plugin-importer.php', 'WPSEO_Plugin_Importers' => __DIR__ . '/../..' . '/admin/import/plugins/class-importers.php', 'WPSEO_Post_Metabox_Formatter' => __DIR__ . '/../..' . '/admin/formatter/class-post-metabox-formatter.php', 'WPSEO_Post_Type' => __DIR__ . '/../..' . '/inc/class-post-type.php', + 'WPSEO_Post_Type_Archive_Notification_Handler' => __DIR__ . '/../..' . '/src/deprecated/admin/notifiers/class-post-type-archive-notification-handler.php', 'WPSEO_Post_Type_Sitemap_Provider' => __DIR__ . '/../..' . '/inc/sitemaps/class-post-type-sitemap-provider.php', 'WPSEO_Premium_Popup' => __DIR__ . '/../..' . '/admin/class-premium-popup.php', 'WPSEO_Premium_Upsell_Admin_Block' => __DIR__ . '/../..' . '/admin/class-premium-upsell-admin-block.php', @@ -325,29 +317,50 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'WPSEO_Primary_Term_Admin' => __DIR__ . '/../..' . '/admin/class-primary-term-admin.php', 'WPSEO_Product_Upsell_Notice' => __DIR__ . '/../..' . '/admin/class-product-upsell-notice.php', 'WPSEO_Rank' => __DIR__ . '/../..' . '/inc/class-wpseo-rank.php', - 'WPSEO_Recalculate' => __DIR__ . '/../..' . '/admin/recalculate/class-recalculate.php', - 'WPSEO_Recalculate_Posts' => __DIR__ . '/../..' . '/admin/recalculate/class-recalculate-posts.php', - 'WPSEO_Recalculate_Scores' => __DIR__ . '/../..' . '/admin/class-recalculate-scores.php', - 'WPSEO_Recalculate_Scores_Ajax' => __DIR__ . '/../..' . '/admin/ajax/class-recalculate-scores-ajax.php', - 'WPSEO_Recalculate_Terms' => __DIR__ . '/../..' . '/admin/recalculate/class-recalculate-terms.php', + 'WPSEO_Recalculate' => __DIR__ . '/../..' . '/src/deprecated/admin/recalculate/class-recalculate.php', + 'WPSEO_Recalculate_Posts' => __DIR__ . '/../..' . '/src/deprecated/admin/recalculate/class-recalculate-posts.php', + 'WPSEO_Recalculate_Scores' => __DIR__ . '/../..' . '/src/deprecated/admin/class-recalculate-scores.php', + 'WPSEO_Recalculate_Scores_Ajax' => __DIR__ . '/../..' . '/src/deprecated/admin/ajax/class-recalculate-scores-ajax.php', + 'WPSEO_Recalculate_Terms' => __DIR__ . '/../..' . '/src/deprecated/admin/recalculate/class-recalculate-terms.php', 'WPSEO_Register_Capabilities' => __DIR__ . '/../..' . '/admin/capabilities/class-register-capabilities.php', 'WPSEO_Register_Roles' => __DIR__ . '/../..' . '/admin/roles/class-register-roles.php', 'WPSEO_Remote_Request' => __DIR__ . '/../..' . '/admin/class-remote-request.php', - 'WPSEO_Remove_Reply_To_Com' => __DIR__ . '/../..' . '/frontend/class-remove-reply-to-com.php', 'WPSEO_Replace_Vars' => __DIR__ . '/../..' . '/inc/class-wpseo-replace-vars.php', + 'WPSEO_Replacement_Variable' => __DIR__ . '/../..' . '/inc/class-wpseo-replacement-variable.php', + 'WPSEO_Replacevar_Editor' => __DIR__ . '/../..' . '/admin/menu/class-replacevar-editor.php', + 'WPSEO_Replacevar_Field' => __DIR__ . '/../..' . '/admin/menu/class-replacevar-field.php', 'WPSEO_Rewrite' => __DIR__ . '/../..' . '/inc/class-rewrite.php', 'WPSEO_Role_Manager' => __DIR__ . '/../..' . '/admin/roles/class-role-manager.php', 'WPSEO_Role_Manager_Factory' => __DIR__ . '/../..' . '/admin/roles/class-role-manager-factory.php', 'WPSEO_Role_Manager_VIP' => __DIR__ . '/../..' . '/admin/roles/class-role-manager-vip.php', 'WPSEO_Role_Manager_WP' => __DIR__ . '/../..' . '/admin/roles/class-role-manager-wp.php', - 'WPSEO_Ryte_Service' => __DIR__ . '/../..' . '/admin/onpage/class-ryte-service.php', + 'WPSEO_Ryte' => __DIR__ . '/../..' . '/admin/ryte/class-ryte.php', + 'WPSEO_Ryte_Option' => __DIR__ . '/../..' . '/admin/ryte/class-ryte-option.php', + 'WPSEO_Ryte_Request' => __DIR__ . '/../..' . '/admin/ryte/class-ryte-request.php', + 'WPSEO_Ryte_Service' => __DIR__ . '/../..' . '/src/deprecated/admin/onpage/class-ryte-service.php', + 'WPSEO_Schema' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema.php', + 'WPSEO_Schema_Article' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-article.php', + 'WPSEO_Schema_Author' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-author.php', + 'WPSEO_Schema_Breadcrumb' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-breadcrumb.php', + 'WPSEO_Schema_FAQ' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-faq.php', + 'WPSEO_Schema_FAQ_Question_List' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-faq-question-list.php', + 'WPSEO_Schema_FAQ_Questions' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-faq-questions.php', + 'WPSEO_Schema_HowTo' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-howto.php', + 'WPSEO_Schema_IDs' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-ids.php', + 'WPSEO_Schema_Image' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-image.php', + 'WPSEO_Schema_MainImage' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-main-image.php', + 'WPSEO_Schema_Organization' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-organization.php', + 'WPSEO_Schema_Person' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-person.php', + 'WPSEO_Schema_Person_Upgrade_Notification' => __DIR__ . '/../..' . '/admin/class-schema-person-upgrade-notification.php', + 'WPSEO_Schema_Utils' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-utils.php', + 'WPSEO_Schema_WebPage' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-webpage.php', + 'WPSEO_Schema_Website' => __DIR__ . '/../..' . '/src/deprecated/frontend/schema/class-schema-website.php', 'WPSEO_Shortcode_Filter' => __DIR__ . '/../..' . '/admin/ajax/class-shortcode-filter.php', 'WPSEO_Shortlinker' => __DIR__ . '/../..' . '/inc/class-wpseo-shortlinker.php', 'WPSEO_Sitemap_Cache_Data' => __DIR__ . '/../..' . '/inc/sitemaps/class-sitemap-cache-data.php', 'WPSEO_Sitemap_Cache_Data_Interface' => __DIR__ . '/../..' . '/inc/sitemaps/interface-sitemap-cache-data.php', 'WPSEO_Sitemap_Image_Parser' => __DIR__ . '/../..' . '/inc/sitemaps/class-sitemap-image-parser.php', 'WPSEO_Sitemap_Provider' => __DIR__ . '/../..' . '/inc/sitemaps/interface-sitemap-provider.php', - 'WPSEO_Sitemap_Timezone' => __DIR__ . '/../..' . '/inc/sitemaps/class-sitemap-timezone.php', 'WPSEO_Sitemaps' => __DIR__ . '/../..' . '/inc/sitemaps/class-sitemaps.php', 'WPSEO_Sitemaps_Admin' => __DIR__ . '/../..' . '/inc/sitemaps/class-sitemaps-admin.php', 'WPSEO_Sitemaps_Cache' => __DIR__ . '/../..' . '/inc/sitemaps/class-sitemaps-cache.php', @@ -355,96 +368,587 @@ class ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0 'WPSEO_Sitemaps_Renderer' => __DIR__ . '/../..' . '/inc/sitemaps/class-sitemaps-renderer.php', 'WPSEO_Sitemaps_Router' => __DIR__ . '/../..' . '/inc/sitemaps/class-sitemaps-router.php', 'WPSEO_Slug_Change_Watcher' => __DIR__ . '/../..' . '/admin/watchers/class-slug-change-watcher.php', - 'WPSEO_Social_Admin' => __DIR__ . '/../..' . '/admin/class-social-admin.php', + 'WPSEO_Social_Admin' => __DIR__ . '/../..' . '/src/deprecated/admin/class-social-admin.php', 'WPSEO_Statistic_Integration' => __DIR__ . '/../..' . '/admin/statistics/class-statistics-integration.php', 'WPSEO_Statistics' => __DIR__ . '/../..' . '/inc/class-wpseo-statistics.php', 'WPSEO_Statistics_Service' => __DIR__ . '/../..' . '/admin/statistics/class-statistics-service.php', 'WPSEO_Submenu_Capability_Normalize' => __DIR__ . '/../..' . '/admin/menu/class-submenu-capability-normalize.php', - 'WPSEO_Submenu_Hider' => __DIR__ . '/../..' . '/deprecated/class-submenu-hider.php', 'WPSEO_Suggested_Plugins' => __DIR__ . '/../..' . '/admin/class-suggested-plugins.php', 'WPSEO_Taxonomy' => __DIR__ . '/../..' . '/admin/taxonomy/class-taxonomy.php', 'WPSEO_Taxonomy_Columns' => __DIR__ . '/../..' . '/admin/taxonomy/class-taxonomy-columns.php', - 'WPSEO_Taxonomy_Content_Fields' => __DIR__ . '/../..' . '/admin/taxonomy/class-taxonomy-content-fields.php', + 'WPSEO_Taxonomy_Content_Fields' => __DIR__ . '/../..' . '/src/deprecated/admin/taxonomy/class-taxonomy-content-fields.php', 'WPSEO_Taxonomy_Fields' => __DIR__ . '/../..' . '/admin/taxonomy/class-taxonomy-fields.php', 'WPSEO_Taxonomy_Fields_Presenter' => __DIR__ . '/../..' . '/admin/taxonomy/class-taxonomy-fields-presenter.php', 'WPSEO_Taxonomy_Meta' => __DIR__ . '/../..' . '/inc/options/class-wpseo-taxonomy-meta.php', 'WPSEO_Taxonomy_Metabox' => __DIR__ . '/../..' . '/admin/taxonomy/class-taxonomy-metabox.php', - 'WPSEO_Taxonomy_Settings_Fields' => __DIR__ . '/../..' . '/admin/taxonomy/class-taxonomy-settings-fields.php', + 'WPSEO_Taxonomy_Settings_Fields' => __DIR__ . '/../..' . '/src/deprecated/admin/taxonomy/class-taxonomy-settings-fields.php', 'WPSEO_Taxonomy_Sitemap_Provider' => __DIR__ . '/../..' . '/inc/sitemaps/class-taxonomy-sitemap-provider.php', - 'WPSEO_Taxonomy_Social_Fields' => __DIR__ . '/../..' . '/admin/taxonomy/class-taxonomy-social-fields.php', + 'WPSEO_Taxonomy_Social_Fields' => __DIR__ . '/../..' . '/src/deprecated/admin/taxonomy/class-taxonomy-social-fields.php', 'WPSEO_Term_Metabox_Formatter' => __DIR__ . '/../..' . '/admin/formatter/class-term-metabox-formatter.php', 'WPSEO_Tracking' => __DIR__ . '/../..' . '/admin/tracking/class-tracking.php', 'WPSEO_Tracking_Default_Data' => __DIR__ . '/../..' . '/admin/tracking/class-tracking-default-data.php', 'WPSEO_Tracking_Plugin_Data' => __DIR__ . '/../..' . '/admin/tracking/class-tracking-plugin-data.php', 'WPSEO_Tracking_Server_Data' => __DIR__ . '/../..' . '/admin/tracking/class-tracking-server-data.php', + 'WPSEO_Tracking_Settings_Data' => __DIR__ . '/../..' . '/admin/tracking/class-tracking-settings-data.php', 'WPSEO_Tracking_Theme_Data' => __DIR__ . '/../..' . '/admin/tracking/class-tracking-theme-data.php', - 'WPSEO_Twitter' => __DIR__ . '/../..' . '/frontend/class-twitter.php', + 'WPSEO_Twitter' => __DIR__ . '/../..' . '/src/deprecated/frontend/class-twitter.php', 'WPSEO_Upgrade' => __DIR__ . '/../..' . '/inc/class-upgrade.php', + 'WPSEO_Upgrade_History' => __DIR__ . '/../..' . '/inc/class-upgrade-history.php', 'WPSEO_Utils' => __DIR__ . '/../..' . '/inc/class-wpseo-utils.php', - 'WPSEO_WooCommerce_Shop_Page' => __DIR__ . '/../..' . '/frontend/class-woocommerce-shop-page.php', + 'WPSEO_Validator' => __DIR__ . '/../..' . '/src/deprecated/inc/class-wpseo-validator.php', + 'WPSEO_WooCommerce_Shop_Page' => __DIR__ . '/../..' . '/src/deprecated/frontend/class-woocommerce-shop-page.php', + 'WPSEO_WordPress_AJAX_Integration' => __DIR__ . '/../..' . '/inc/interface-wpseo-wordpress-ajax-integration.php', 'WPSEO_WordPress_Integration' => __DIR__ . '/../..' . '/inc/interface-wpseo-wordpress-integration.php', 'WPSEO_Yoast_Columns' => __DIR__ . '/../..' . '/admin/class-yoast-columns.php', - 'Whip_BasicMessage' => __DIR__ . '/..' . '/yoast/whip/src/messages/Whip_BasicMessage.php', - 'Whip_Configuration' => __DIR__ . '/..' . '/yoast/whip/src/Whip_Configuration.php', - 'Whip_DismissStorage' => __DIR__ . '/..' . '/yoast/whip/src/interfaces/Whip_DismissStorage.php', - 'Whip_EmptyProperty' => __DIR__ . '/..' . '/yoast/whip/src/exceptions/Whip_EmptyProperty.php', - 'Whip_Host' => __DIR__ . '/..' . '/yoast/whip/src/Whip_Host.php', - 'Whip_HostMessage' => __DIR__ . '/..' . '/yoast/whip/src/messages/Whip_HostMessage.php', - 'Whip_InvalidOperatorType' => __DIR__ . '/..' . '/yoast/whip/src/exceptions/Whip_InvalidOperatorType.php', - 'Whip_InvalidType' => __DIR__ . '/..' . '/yoast/whip/src/exceptions/Whip_InvalidType.php', - 'Whip_InvalidVersionComparisonString' => __DIR__ . '/..' . '/yoast/whip/src/exceptions/Whip_InvalidVersionComparisonString.php', - 'Whip_InvalidVersionRequirementMessage' => __DIR__ . '/..' . '/yoast/whip/src/messages/Whip_InvalidVersionRequirementMessage.php', - 'Whip_Listener' => __DIR__ . '/..' . '/yoast/whip/src/interfaces/Whip_Listener.php', - 'Whip_Message' => __DIR__ . '/..' . '/yoast/whip/src/interfaces/Whip_Message.php', - 'Whip_MessageDismisser' => __DIR__ . '/..' . '/yoast/whip/src/Whip_MessageDismisser.php', - 'Whip_MessageFormatter' => __DIR__ . '/..' . '/yoast/whip/src/Whip_MessageFormatter.php', - 'Whip_MessagePresenter' => __DIR__ . '/..' . '/yoast/whip/src/interfaces/Whip_MessagePresenter.php', - 'Whip_MessagesManager' => __DIR__ . '/..' . '/yoast/whip/src/Whip_MessagesManager.php', - 'Whip_NullMessage' => __DIR__ . '/..' . '/yoast/whip/src/messages/Whip_NullMessage.php', - 'Whip_Requirement' => __DIR__ . '/..' . '/yoast/whip/src/interfaces/Whip_Requirement.php', - 'Whip_RequirementsChecker' => __DIR__ . '/..' . '/yoast/whip/src/Whip_RequirementsChecker.php', - 'Whip_UpgradePhpMessage' => __DIR__ . '/..' . '/yoast/whip/src/messages/Whip_UpgradePhpMessage.php', - 'Whip_VersionDetector' => __DIR__ . '/..' . '/yoast/whip/src/interfaces/Whip_VersionDetector.php', - 'Whip_VersionRequirement' => __DIR__ . '/..' . '/yoast/whip/src/Whip_VersionRequirement.php', - 'Whip_WPDismissOption' => __DIR__ . '/..' . '/yoast/whip/src/Whip_WPDismissOption.php', - 'Whip_WPMessageDismissListener' => __DIR__ . '/..' . '/yoast/whip/src/Whip_WPMessageDismissListener.php', - 'Whip_WPMessagePresenter' => __DIR__ . '/..' . '/yoast/whip/src/presenters/Whip_WPMessagePresenter.php', - 'Yoast_API_Request' => __DIR__ . '/..' . '/yoast/license-manager/class-api-request.php', - 'Yoast_Alerts' => __DIR__ . '/../..' . '/admin/class-yoast-alerts.php', - 'Yoast_Api_Libs' => __DIR__ . '/..' . '/yoast/api-libs/class-api-libs.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Client' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Client.php', + 'YoastSEO_Vendor\\GuzzleHttp\\ClientInterface' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/ClientInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\CookieJar' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJar.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\CookieJarInterface' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\FileCookieJar' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\SessionCookieJar' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Cookie\\SetCookie' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SetCookie.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\BadResponseException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/BadResponseException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\ClientException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/ClientException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\ConnectException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/ConnectException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\GuzzleException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/GuzzleException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\RequestException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/RequestException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\SeekException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/SeekException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\ServerException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/ServerException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\TooManyRedirectsException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Exception\\TransferException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Exception/TransferException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\HandlerStack' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/HandlerStack.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\CurlFactory' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlFactory.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\CurlFactoryInterface' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\CurlHandler' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlHandler.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\CurlMultiHandler' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\EasyHandle' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/EasyHandle.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\MockHandler' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/MockHandler.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\Proxy' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/Proxy.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Handler\\StreamHandler' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Handler/StreamHandler.php', + 'YoastSEO_Vendor\\GuzzleHttp\\MessageFormatter' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/MessageFormatter.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Middleware' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Middleware.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Pool' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/Pool.php', + 'YoastSEO_Vendor\\GuzzleHttp\\PrepareBodyMiddleware' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\AggregateException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/AggregateException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\CancellationException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/CancellationException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\Coroutine' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/Coroutine.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\EachPromise' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/EachPromise.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\FulfilledPromise' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/FulfilledPromise.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\Promise' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/Promise.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\PromiseInterface' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/PromiseInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\PromisorInterface' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/PromisorInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\RejectedPromise' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/RejectedPromise.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\RejectionException' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/RejectionException.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\TaskQueue' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/TaskQueue.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Promise\\TaskQueueInterface' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/promises/src/TaskQueueInterface.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\AppendStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/AppendStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\BufferStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/BufferStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\CachingStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/CachingStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\DroppingStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/DroppingStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\FnStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/FnStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\InflateStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/InflateStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\LazyOpenStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/LazyOpenStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\LimitStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/LimitStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\MessageTrait' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/MessageTrait.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\MultipartStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/MultipartStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\NoSeekStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/NoSeekStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\PumpStream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/PumpStream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\Request' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/Request.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\Response' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/Response.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\Rfc7230' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/Rfc7230.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\ServerRequest' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/ServerRequest.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\Stream' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/Stream.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\StreamDecoratorTrait' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/StreamDecoratorTrait.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\StreamWrapper' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/StreamWrapper.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\UploadedFile' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/UploadedFile.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\Uri' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/Uri.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\UriNormalizer' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/UriNormalizer.php', + 'YoastSEO_Vendor\\GuzzleHttp\\Psr7\\UriResolver' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/psr7/src/UriResolver.php', + 'YoastSEO_Vendor\\GuzzleHttp\\RedirectMiddleware' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/RedirectMiddleware.php', + 'YoastSEO_Vendor\\GuzzleHttp\\RequestOptions' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/RequestOptions.php', + 'YoastSEO_Vendor\\GuzzleHttp\\RetryMiddleware' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/RetryMiddleware.php', + 'YoastSEO_Vendor\\GuzzleHttp\\TransferStats' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/TransferStats.php', + 'YoastSEO_Vendor\\GuzzleHttp\\UriTemplate' => __DIR__ . '/../..' . '/vendor_prefixed/guzzlehttp/guzzle/src/UriTemplate.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AbstractGrant' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/AbstractGrant.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\AuthorizationCode' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/AuthorizationCode.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\ClientCredentials' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/ClientCredentials.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\Exception\\InvalidGrantException' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\GrantFactory' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/GrantFactory.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\Password' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/Password.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\RefreshToken' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Grant/RefreshToken.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\OptionProvider\\HttpBasicAuthOptionProvider' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\OptionProvider\\OptionProviderInterface' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\OptionProvider\\PostAuthOptionProvider' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Provider\\AbstractProvider' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Provider/AbstractProvider.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Provider\\Exception\\IdentityProviderException' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Provider\\GenericProvider' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Provider/GenericProvider.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Provider\\GenericResourceOwner' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Provider/GenericResourceOwner.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Provider\\ResourceOwnerInterface' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Provider/ResourceOwnerInterface.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Token\\AccessToken' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Token/AccessToken.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Token\\AccessTokenInterface' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Token/AccessTokenInterface.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Token\\ResourceOwnerAccessTokenInterface' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\ArrayAccessorTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/ArrayAccessorTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\BearerAuthorizationTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\GuardedPropertyTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/GuardedPropertyTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\MacAuthorizationTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/MacAuthorizationTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\ProviderRedirectTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/ProviderRedirectTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\QueryBuilderTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/QueryBuilderTrait.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequestFactory' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/RequestFactory.php', + 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Tool\\RequiredParameterTrait' => __DIR__ . '/../..' . '/vendor_prefixed/league/oauth2-client/src/Tool/RequiredParameterTrait.php', + 'YoastSEO_Vendor\\Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/container/src/ContainerExceptionInterface.php', + 'YoastSEO_Vendor\\Psr\\Container\\ContainerInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/container/src/ContainerInterface.php', + 'YoastSEO_Vendor\\Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/container/src/NotFoundExceptionInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/http-message/src/MessageInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/http-message/src/RequestInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/http-message/src/ResponseInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/http-message/src/ServerRequestInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/http-message/src/StreamInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/http-message/src/UploadedFileInterface.php', + 'YoastSEO_Vendor\\Psr\\Http\\Message\\UriInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/http-message/src/UriInterface.php', + 'YoastSEO_Vendor\\Psr\\Log\\AbstractLogger' => __DIR__ . '/../..' . '/vendor_prefixed/psr/log/Psr/Log/AbstractLogger.php', + 'YoastSEO_Vendor\\Psr\\Log\\InvalidArgumentException' => __DIR__ . '/../..' . '/vendor_prefixed/psr/log/Psr/Log/InvalidArgumentException.php', + 'YoastSEO_Vendor\\Psr\\Log\\LogLevel' => __DIR__ . '/../..' . '/vendor_prefixed/psr/log/Psr/Log/LogLevel.php', + 'YoastSEO_Vendor\\Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/log/Psr/Log/LoggerAwareInterface.php', + 'YoastSEO_Vendor\\Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/../..' . '/vendor_prefixed/psr/log/Psr/Log/LoggerAwareTrait.php', + 'YoastSEO_Vendor\\Psr\\Log\\LoggerInterface' => __DIR__ . '/../..' . '/vendor_prefixed/psr/log/Psr/Log/LoggerInterface.php', + 'YoastSEO_Vendor\\Psr\\Log\\LoggerTrait' => __DIR__ . '/../..' . '/vendor_prefixed/psr/log/Psr/Log/LoggerTrait.php', + 'YoastSEO_Vendor\\Psr\\Log\\NullLogger' => __DIR__ . '/../..' . '/vendor_prefixed/psr/log/Psr/Log/NullLogger.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Argument\\RewindableGenerator' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/Argument/RewindableGenerator.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Container' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/Container.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/ContainerInterface.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\EnvNotFoundException' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/Exception/EnvNotFoundException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\ExceptionInterface' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/Exception/ExceptionInterface.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\InvalidArgumentException' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/Exception/InvalidArgumentException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\LogicException' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/Exception/LogicException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\ParameterCircularReferenceException' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\RuntimeException' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/Exception/RuntimeException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceCircularReferenceException' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\Exception\\ServiceNotFoundException' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/Exception/ServiceNotFoundException.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ParameterBag\\EnvPlaceholderParameterBag' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ParameterBag\\FrozenParameterBag' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBag.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBagInterface' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php', + 'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ResettableContainerInterface' => __DIR__ . '/../..' . '/vendor_prefixed/symfony/dependency-injection/ResettableContainerInterface.php', + 'Yoast\\WP\\Lib\\Abstract_Main' => __DIR__ . '/../..' . '/lib/abstract-main.php', + 'Yoast\\WP\\Lib\\Dependency_Injection\\Container_Registry' => __DIR__ . '/../..' . '/lib/dependency-injection/container-registry.php', + 'Yoast\\WP\\Lib\\Migrations\\Adapter' => __DIR__ . '/../..' . '/lib/migrations/adapter.php', + 'Yoast\\WP\\Lib\\Migrations\\Column' => __DIR__ . '/../..' . '/lib/migrations/column.php', + 'Yoast\\WP\\Lib\\Migrations\\Constants' => __DIR__ . '/../..' . '/lib/migrations/constants.php', + 'Yoast\\WP\\Lib\\Migrations\\Migration' => __DIR__ . '/../..' . '/lib/migrations/migration.php', + 'Yoast\\WP\\Lib\\Migrations\\Table' => __DIR__ . '/../..' . '/lib/migrations/table.php', + 'Yoast\\WP\\Lib\\Model' => __DIR__ . '/../..' . '/lib/model.php', + 'Yoast\\WP\\Lib\\ORM' => __DIR__ . '/../..' . '/lib/orm.php', + 'Yoast\\WP\\SEO\\Actions\\Addon_Installation\\Addon_Activate_Action' => __DIR__ . '/../..' . '/src/actions/addon-installation/addon-activate-action.php', + 'Yoast\\WP\\SEO\\Actions\\Addon_Installation\\Addon_Install_Action' => __DIR__ . '/../..' . '/src/actions/addon-installation/addon-install-action.php', + 'Yoast\\WP\\SEO\\Actions\\Alert_Dismissal_Action' => __DIR__ . '/../..' . '/src/actions/alert-dismissal-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexables\\Indexable_Head_Action' => __DIR__ . '/../..' . '/src/actions/indexables/indexable-head-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Abstract_Link_Indexing_Action' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexation/abstract-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Complete_Indexation_Action' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexation/indexable-complete-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_General_Indexation_Action' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexation/indexable-general-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Post_Indexation_Action' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexation/indexable-post-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Post_Type_Archive_Indexation_Action' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexation/indexable-post-type-archive-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Prepare_Indexation_Action' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexation/indexable-prepare-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexable_Term_Indexation_Action' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexation/indexable-term-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Indexation_Action_Interface' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexation/indexation-action-interface.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Post_Link_Indexing_Action' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexation/post-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexation\\Term_Link_Indexing_Action' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexation/term-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Abstract_Indexing_Action' => __DIR__ . '/../..' . '/src/actions/indexing/abstract-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Abstract_Link_Indexing_Action' => __DIR__ . '/../..' . '/src/actions/indexing/abstract-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_General_Indexation_Action' => __DIR__ . '/../..' . '/src/actions/indexing/indexable-general-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_Indexing_Complete_Action' => __DIR__ . '/../..' . '/src/actions/indexing/indexable-indexing-complete-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_Post_Indexation_Action' => __DIR__ . '/../..' . '/src/actions/indexing/indexable-post-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_Post_Type_Archive_Indexation_Action' => __DIR__ . '/../..' . '/src/actions/indexing/indexable-post-type-archive-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_Prepare_Indexation_Action' => __DIR__ . '/../..' . '/src/deprecated/src/actions/indexing/indexable-prepare-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexable_Term_Indexation_Action' => __DIR__ . '/../..' . '/src/actions/indexing/indexable-term-indexation-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexation_Action_Interface' => __DIR__ . '/../..' . '/src/actions/indexing/indexation-action-interface.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexing_Complete_Action' => __DIR__ . '/../..' . '/src/actions/indexing/indexing-complete-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Indexing_Prepare_Action' => __DIR__ . '/../..' . '/src/actions/indexing/indexing-prepare-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Limited_Indexing_Action_Interface' => __DIR__ . '/../..' . '/src/actions/indexing/limited-indexing-action-interface.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Post_Link_Indexing_Action' => __DIR__ . '/../..' . '/src/actions/indexing/post-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\Indexing\\Term_Link_Indexing_Action' => __DIR__ . '/../..' . '/src/actions/indexing/term-link-indexing-action.php', + 'Yoast\\WP\\SEO\\Actions\\SEMrush\\SEMrush_Login_Action' => __DIR__ . '/../..' . '/src/actions/semrush/semrush-login-action.php', + 'Yoast\\WP\\SEO\\Actions\\SEMrush\\SEMrush_Options_Action' => __DIR__ . '/../..' . '/src/actions/semrush/semrush-options-action.php', + 'Yoast\\WP\\SEO\\Actions\\SEMrush\\SEMrush_Phrases_Action' => __DIR__ . '/../..' . '/src/actions/semrush/semrush-phrases-action.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder' => __DIR__ . '/../..' . '/src/builders/indexable-author-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Builder' => __DIR__ . '/../..' . '/src/builders/indexable-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Date_Archive_Builder' => __DIR__ . '/../..' . '/src/builders/indexable-date-archive-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Hierarchy_Builder' => __DIR__ . '/../..' . '/src/builders/indexable-hierarchy-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Home_Page_Builder' => __DIR__ . '/../..' . '/src/builders/indexable-home-page-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Link_Builder' => __DIR__ . '/../..' . '/src/builders/indexable-link-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder' => __DIR__ . '/../..' . '/src/builders/indexable-post-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Post_Type_Archive_Builder' => __DIR__ . '/../..' . '/src/builders/indexable-post-type-archive-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Social_Image_Trait' => __DIR__ . '/../..' . '/src/builders/indexable-social-image-trait.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_System_Page_Builder' => __DIR__ . '/../..' . '/src/builders/indexable-system-page-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder' => __DIR__ . '/../..' . '/src/builders/indexable-term-builder.php', + 'Yoast\\WP\\SEO\\Builders\\Primary_Term_Builder' => __DIR__ . '/../..' . '/src/builders/primary-term-builder.php', + 'Yoast\\WP\\SEO\\Commands\\Command_Interface' => __DIR__ . '/../..' . '/src/commands/command-interface.php', + 'Yoast\\WP\\SEO\\Commands\\Index_Command' => __DIR__ . '/../..' . '/src/commands/index-command.php', + 'Yoast\\WP\\SEO\\Conditionals\\Addon_Installation_Conditional' => __DIR__ . '/../..' . '/src/conditionals/addon-installation-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin\\Doing_Post_Quick_Edit_Save_Conditional' => __DIR__ . '/../..' . '/src/conditionals/admin/doing-post-quick-edit-save-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin\\Estimated_Reading_Time_Conditional' => __DIR__ . '/../..' . '/src/conditionals/admin/estimated-reading-time-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin\\Licenses_Page_Conditional' => __DIR__ . '/../..' . '/src/conditionals/admin/licenses-page-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin\\Post_Conditional' => __DIR__ . '/../..' . '/src/conditionals/admin/post-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin\\Posts_Overview_Or_Ajax_Conditional' => __DIR__ . '/../..' . '/src/conditionals/admin/posts-overview-or-ajax-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Admin_Conditional' => __DIR__ . '/../..' . '/src/conditionals/admin-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Conditional' => __DIR__ . '/../..' . '/src/conditionals/conditional-interface.php', + 'Yoast\\WP\\SEO\\Conditionals\\Development_Conditional' => __DIR__ . '/../..' . '/src/conditionals/development-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Farsi_Support_Conditional' => __DIR__ . '/../..' . '/src/deprecated/src/conditionals/farsi-support-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Feature_Flag_Conditional' => __DIR__ . '/../..' . '/src/conditionals/feature-flag-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Front_End_Conditional' => __DIR__ . '/../..' . '/src/conditionals/front-end-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Get_Request_Conditional' => __DIR__ . '/../..' . '/src/conditionals/get-request-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Headless_Rest_Endpoints_Enabled_Conditional' => __DIR__ . '/../..' . '/src/conditionals/headless-rest-endpoints-enabled-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Jetpack_Conditional' => __DIR__ . '/../..' . '/src/conditionals/jetpack-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Migrations_Conditional' => __DIR__ . '/../..' . '/src/conditionals/migrations-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\News_Conditional' => __DIR__ . '/../..' . '/src/conditionals/news-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\No_Conditionals' => __DIR__ . '/../..' . '/src/conditionals/no-conditionals-trait.php', + 'Yoast\\WP\\SEO\\Conditionals\\No_Tool_Selected_Conditional' => __DIR__ . '/../..' . '/src/conditionals/no-tool-selected-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Norwegian_Readability_Conditional' => __DIR__ . '/../..' . '/src/deprecated/src/conditionals/norwegian-readability-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Open_Graph_Conditional' => __DIR__ . '/../..' . '/src/conditionals/open-graph-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Premium_Inactive_Conditional' => __DIR__ . '/../..' . '/src/conditionals/premium-inactive-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Primary_Category_Conditional' => __DIR__ . '/../..' . '/src/conditionals/primary-category-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\SEMrush_Enabled_Conditional' => __DIR__ . '/../..' . '/src/conditionals/semrush-enabled-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Schema_Blocks_Conditional' => __DIR__ . '/../..' . '/src/conditionals/schema-blocks-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Should_Index_Links_Conditional' => __DIR__ . '/../..' . '/src/conditionals/should-index-links-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\The_Events_Calendar_Conditional' => __DIR__ . '/../..' . '/src/conditionals/the-events-calendar-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Third_Party\\Elementor_Activated_Conditional' => __DIR__ . '/../..' . '/src/conditionals/third-party/elementor-activated-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Third_Party\\Elementor_Edit_Conditional' => __DIR__ . '/../..' . '/src/conditionals/third-party/elementor-edit-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Third_Party\\W3_Total_Cache_Conditional' => __DIR__ . '/../..' . '/src/conditionals/third-party/w3-total-cache-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Third_Party\\WPML_Conditional' => __DIR__ . '/../..' . '/src/conditionals/third-party/wpml-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Third_Party\\WPML_WPSEO_Conditional' => __DIR__ . '/../..' . '/src/conditionals/third-party/wpml-wpseo-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\WP_Robots_Conditional' => __DIR__ . '/../..' . '/src/conditionals/wp-robots-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Web_Stories_Conditional' => __DIR__ . '/../..' . '/src/conditionals/web-stories-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\WooCommerce_Conditional' => __DIR__ . '/../..' . '/src/conditionals/woocommerce-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\XMLRPC_Conditional' => __DIR__ . '/../..' . '/src/conditionals/xmlrpc-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Yoast_Admin_And_Dashboard_Conditional' => __DIR__ . '/../..' . '/src/conditionals/yoast-admin-and-dashboard-conditional.php', + 'Yoast\\WP\\SEO\\Conditionals\\Yoast_Tools_Page_Conditional' => __DIR__ . '/../..' . '/src/conditionals/yoast-tools-page-conditional.php', + 'Yoast\\WP\\SEO\\Config\\Badge_Group_Names' => __DIR__ . '/../..' . '/src/config/badge-group-names.php', + 'Yoast\\WP\\SEO\\Config\\Indexing_Reasons' => __DIR__ . '/../..' . '/src/config/indexing-reasons.php', + 'Yoast\\WP\\SEO\\Config\\Migration_Status' => __DIR__ . '/../..' . '/src/config/migration-status.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddCollationToTables' => __DIR__ . '/../..' . '/src/config/migrations/20200408101900_AddCollationToTables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddColumnsToIndexables' => __DIR__ . '/../..' . '/src/config/migrations/20200420073606_AddColumnsToIndexables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddEstimatedReadingTime' => __DIR__ . '/../..' . '/src/config/migrations/20201202144329_AddEstimatedReadingTime.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddHasAncestorsColumn' => __DIR__ . '/../..' . '/src/config/migrations/20200609154515_AddHasAncestorsColumn.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddIndexableObjectIdAndTypeIndex' => __DIR__ . '/../..' . '/src/config/migrations/20200430075614_AddIndexableObjectIdAndTypeIndex.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\AddIndexesForProminentWordsOnIndexables' => __DIR__ . '/../..' . '/src/config/migrations/20200728095334_AddIndexesForProminentWordsOnIndexables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\BreadcrumbTitleAndHierarchyReset' => __DIR__ . '/../..' . '/src/config/migrations/20200428123747_BreadcrumbTitleAndHierarchyReset.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ClearIndexableTables' => __DIR__ . '/../..' . '/src/config/migrations/20200430150130_ClearIndexableTables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\CreateIndexableSubpagesIndex' => __DIR__ . '/../..' . '/src/config/migrations/20200702141921_CreateIndexableSubpagesIndex.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\CreateSEOLinksTable' => __DIR__ . '/../..' . '/src/config/migrations/20200617122511_CreateSEOLinksTable.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\DeleteDuplicateIndexables' => __DIR__ . '/../..' . '/src/config/migrations/20200507054848_DeleteDuplicateIndexables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ExpandIndexableColumnLengths' => __DIR__ . '/../..' . '/src/config/migrations/20200428194858_ExpandIndexableColumnLengths.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ExpandIndexableIDColumnLengths' => __DIR__ . '/../..' . '/src/config/migrations/20201216124002_ExpandIndexableIDColumnLengths.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ExpandPrimaryTermIDColumnLengths' => __DIR__ . '/../..' . '/src/config/migrations/20201216141134_ExpandPrimaryTermIDColumnLengths.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ReplacePermalinkHashIndex' => __DIR__ . '/../..' . '/src/config/migrations/20200616130143_ReplacePermalinkHashIndex.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\ResetIndexableHierarchyTable' => __DIR__ . '/../..' . '/src/config/migrations/20200513133401_ResetIndexableHierarchyTable.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\TruncateIndexableTables' => __DIR__ . '/../..' . '/src/config/migrations/20200429105310_TruncateIndexableTables.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\WpYoastDropIndexableMetaTableIfExists' => __DIR__ . '/../..' . '/src/config/migrations/20190529075038_WpYoastDropIndexableMetaTableIfExists.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\WpYoastIndexable' => __DIR__ . '/../..' . '/src/config/migrations/20171228151840_WpYoastIndexable.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\WpYoastIndexableHierarchy' => __DIR__ . '/../..' . '/src/config/migrations/20191011111109_WpYoastIndexableHierarchy.php', + 'Yoast\\WP\\SEO\\Config\\Migrations\\WpYoastPrimaryTerm' => __DIR__ . '/../..' . '/src/config/migrations/20171228151841_WpYoastPrimaryTerm.php', + 'Yoast\\WP\\SEO\\Config\\Researcher_Languages' => __DIR__ . '/../..' . '/src/config/researcher-languages.php', + 'Yoast\\WP\\SEO\\Config\\SEMrush_Client' => __DIR__ . '/../..' . '/src/config/semrush-client.php', + 'Yoast\\WP\\SEO\\Config\\Schema_IDs' => __DIR__ . '/../..' . '/src/config/schema-ids.php', + 'Yoast\\WP\\SEO\\Config\\Schema_Types' => __DIR__ . '/../..' . '/src/config/schema-types.php', + 'Yoast\\WP\\SEO\\Context\\Meta_Tags_Context' => __DIR__ . '/../..' . '/src/context/meta-tags-context.php', + 'Yoast\\WP\\SEO\\Exceptions\\Addon_Installation\\Addon_Activation_Error_Exception' => __DIR__ . '/../..' . '/src/exceptions/addon-installation/addon-activation-error-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Addon_Installation\\Addon_Already_Installed_Exception' => __DIR__ . '/../..' . '/src/exceptions/addon-installation/addon-already-installed-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Addon_Installation\\Addon_Installation_Error_Exception' => __DIR__ . '/../..' . '/src/exceptions/addon-installation/addon-installation-error-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Addon_Installation\\User_Cannot_Activate_Plugins_Exception' => __DIR__ . '/../..' . '/src/exceptions/addon-installation/user-cannot-activate-plugins-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Addon_Installation\\User_Cannot_Install_Plugins_Exception' => __DIR__ . '/../..' . '/src/exceptions/addon-installation/user-cannot-install-plugins-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Indexable\\Indexable_Exception' => __DIR__ . '/../..' . '/src/exceptions/indexable/indexable-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Indexable\\Invalid_Term_Exception' => __DIR__ . '/../..' . '/src/exceptions/indexable/invalid-term-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Indexable\\Post_Not_Found_Exception' => __DIR__ . '/../..' . '/src/exceptions/indexable/post-not-found-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Indexable\\Source_Exception' => __DIR__ . '/../..' . '/src/exceptions/indexable/source-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Indexable\\Term_Not_Found_Exception' => __DIR__ . '/../..' . '/src/exceptions/indexable/term-not-found-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\Missing_Method' => __DIR__ . '/../..' . '/src/exceptions/missing-method.php', + 'Yoast\\WP\\SEO\\Exceptions\\OAuth\\Authentication_Failed_Exception' => __DIR__ . '/../..' . '/src/exceptions/oauth/authentication-failed-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\SEMrush\\Tokens\\Empty_Property_Exception' => __DIR__ . '/../..' . '/src/exceptions/semrush/tokens/empty-property-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\SEMrush\\Tokens\\Empty_Token_Exception' => __DIR__ . '/../..' . '/src/exceptions/semrush/tokens/empty-token-exception.php', + 'Yoast\\WP\\SEO\\Exceptions\\SEMrush\\Tokens\\Failed_Storage_Exception' => __DIR__ . '/../..' . '/src/exceptions/semrush/tokens/failed-storage-exception.php', + 'Yoast\\WP\\SEO\\Generated\\Cached_Container' => __DIR__ . '/../..' . '/src/generated/container.php', + 'Yoast\\WP\\SEO\\Generators\\Breadcrumbs_Generator' => __DIR__ . '/../..' . '/src/generators/breadcrumbs-generator.php', + 'Yoast\\WP\\SEO\\Generators\\Generator_Interface' => __DIR__ . '/../..' . '/src/generators/generator-interface.php', + 'Yoast\\WP\\SEO\\Generators\\Open_Graph_Image_Generator' => __DIR__ . '/../..' . '/src/generators/open-graph-image-generator.php', + 'Yoast\\WP\\SEO\\Generators\\Open_Graph_Locale_Generator' => __DIR__ . '/../..' . '/src/generators/open-graph-locale-generator.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Abstract_Schema_Piece' => __DIR__ . '/../..' . '/src/generators/schema/abstract-schema-piece.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Article' => __DIR__ . '/../..' . '/src/generators/schema/article.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Author' => __DIR__ . '/../..' . '/src/generators/schema/author.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Breadcrumb' => __DIR__ . '/../..' . '/src/generators/schema/breadcrumb.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\FAQ' => __DIR__ . '/../..' . '/src/generators/schema/faq.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\HowTo' => __DIR__ . '/../..' . '/src/generators/schema/howto.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Main_Image' => __DIR__ . '/../..' . '/src/generators/schema/main-image.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Organization' => __DIR__ . '/../..' . '/src/generators/schema/organization.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Person' => __DIR__ . '/../..' . '/src/generators/schema/person.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Third_Party\\Events_Calendar_Schema' => __DIR__ . '/../..' . '/src/generators/schema/third-party/events-calendar-schema.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\WebPage' => __DIR__ . '/../..' . '/src/generators/schema/webpage.php', + 'Yoast\\WP\\SEO\\Generators\\Schema\\Website' => __DIR__ . '/../..' . '/src/generators/schema/website.php', + 'Yoast\\WP\\SEO\\Generators\\Schema_Generator' => __DIR__ . '/../..' . '/src/generators/schema-generator.php', + 'Yoast\\WP\\SEO\\Generators\\Twitter_Image_Generator' => __DIR__ . '/../..' . '/src/generators/twitter-image-generator.php', + 'Yoast\\WP\\SEO\\Helpers\\Asset_Helper' => __DIR__ . '/../..' . '/src/helpers/asset-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Author_Archive_Helper' => __DIR__ . '/../..' . '/src/helpers/author-archive-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Blocks_Helper' => __DIR__ . '/../..' . '/src/helpers/blocks-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Capability_Helper' => __DIR__ . '/../..' . '/src/helpers/capability-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Current_Page_Helper' => __DIR__ . '/../..' . '/src/helpers/current-page-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Date_Helper' => __DIR__ . '/../..' . '/src/helpers/date-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Environment_Helper' => __DIR__ . '/../..' . '/src/helpers/environment-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Home_Url_Helper' => __DIR__ . '/../..' . '/src/helpers/home-url-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Image_Helper' => __DIR__ . '/../..' . '/src/helpers/image-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Indexable_Helper' => __DIR__ . '/../..' . '/src/helpers/indexable-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Indexing_Helper' => __DIR__ . '/../..' . '/src/helpers/indexing-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Input_Helper' => __DIR__ . '/../..' . '/src/helpers/input-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Language_Helper' => __DIR__ . '/../..' . '/src/helpers/language-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Meta_Helper' => __DIR__ . '/../..' . '/src/helpers/meta-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Notification_Helper' => __DIR__ . '/../..' . '/src/helpers/notification-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Open_Graph\\Image_Helper' => __DIR__ . '/../..' . '/src/helpers/open-graph/image-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Open_Graph\\Values_Helper' => __DIR__ . '/../..' . '/src/helpers/open-graph/values-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Options_Helper' => __DIR__ . '/../..' . '/src/helpers/options-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Pagination_Helper' => __DIR__ . '/../..' . '/src/helpers/pagination-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Permalink_Helper' => __DIR__ . '/../..' . '/src/helpers/permalink-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Post_Helper' => __DIR__ . '/../..' . '/src/helpers/post-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Post_Type_Helper' => __DIR__ . '/../..' . '/src/helpers/post-type-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Primary_Term_Helper' => __DIR__ . '/../..' . '/src/helpers/primary-term-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Product_Helper' => __DIR__ . '/../..' . '/src/helpers/product-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Redirect_Helper' => __DIR__ . '/../..' . '/src/helpers/redirect-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Request_Helper' => __DIR__ . '/../..' . '/src/helpers/request-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Require_File_Helper' => __DIR__ . '/../..' . '/src/helpers/require-file-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Robots_Helper' => __DIR__ . '/../..' . '/src/helpers/robots-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\Article_Helper' => __DIR__ . '/../..' . '/src/helpers/schema/article-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\HTML_Helper' => __DIR__ . '/../..' . '/src/helpers/schema/html-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\ID_Helper' => __DIR__ . '/../..' . '/src/helpers/schema/id-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\Image_Helper' => __DIR__ . '/../..' . '/src/helpers/schema/image-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\Language_Helper' => __DIR__ . '/../..' . '/src/helpers/schema/language-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Schema\\Replace_Vars_Helper' => __DIR__ . '/../..' . '/src/helpers/schema/replace-vars-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Short_Link_Helper' => __DIR__ . '/../..' . '/src/helpers/short-link-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Site_Helper' => __DIR__ . '/../..' . '/src/helpers/site-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\String_Helper' => __DIR__ . '/../..' . '/src/helpers/string-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Taxonomy_Helper' => __DIR__ . '/../..' . '/src/helpers/taxonomy-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Twitter\\Image_Helper' => __DIR__ . '/../..' . '/src/helpers/twitter/image-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Url_Helper' => __DIR__ . '/../..' . '/src/helpers/url-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\User_Helper' => __DIR__ . '/../..' . '/src/helpers/user-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Woocommerce_Helper' => __DIR__ . '/../..' . '/src/helpers/woocommerce-helper.php', + 'Yoast\\WP\\SEO\\Helpers\\Wordpress_Helper' => __DIR__ . '/../..' . '/src/helpers/wordpress-helper.php', + 'Yoast\\WP\\SEO\\Initializers\\Disable_Core_Sitemaps' => __DIR__ . '/../..' . '/src/initializers/disable-core-sitemaps.php', + 'Yoast\\WP\\SEO\\Initializers\\Initializer_Interface' => __DIR__ . '/../..' . '/src/initializers/initializer-interface.php', + 'Yoast\\WP\\SEO\\Initializers\\Migration_Runner' => __DIR__ . '/../..' . '/src/initializers/migration-runner.php', + 'Yoast\\WP\\SEO\\Integrations\\Abstract_Exclude_Post_Type' => __DIR__ . '/../..' . '/src/integrations/abstract-exclude-post-type.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Addon_Installation\\Dialog_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/addon-installation/dialog-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Addon_Installation\\Installation_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/addon-installation/installation-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Admin_Columns_Cache_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/admin-columns-cache-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Background_Indexing_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/background-indexing-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Cron_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/cron-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Disable_Concatenate_Scripts_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/disable-concatenate-scripts-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Fix_News_Dependencies_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/fix-news-dependencies-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\HelpScout_Beacon' => __DIR__ . '/../..' . '/src/integrations/admin/helpscout-beacon.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexation_Integration' => __DIR__ . '/../..' . '/src/deprecated/src/integrations/admin/indexation-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexing_Notification_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/indexing-notification-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Indexing_Tool_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/indexing-tool-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Link_Count_Columns_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/link-count-columns-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Link_Count_Notification_Integration' => __DIR__ . '/../..' . '/src/deprecated/src/integrations/admin/link-count-notification-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Link_Count_Tools_Integration' => __DIR__ . '/../..' . '/src/deprecated/src/integrations/admin/link-count-tools-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Menu_Badge_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/menu-badge-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Migration_Error_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/migration-error-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Social_Templates_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/social-templates-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Admin\\Workouts_Integration' => __DIR__ . '/../..' . '/src/integrations/admin/workouts-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Alerts\\Abstract_Dismissable_Alert' => __DIR__ . '/../..' . '/src/integrations/alerts/abstract-dismissable-alert.php', + 'Yoast\\WP\\SEO\\Integrations\\Blocks\\Breadcrumbs_Block' => __DIR__ . '/../..' . '/src/integrations/blocks/breadcrumbs-block.php', + 'Yoast\\WP\\SEO\\Integrations\\Blocks\\Dynamic_Block' => __DIR__ . '/../..' . '/src/integrations/blocks/abstract-dynamic-block.php', + 'Yoast\\WP\\SEO\\Integrations\\Blocks\\Internal_Linking_Category' => __DIR__ . '/../..' . '/src/integrations/blocks/block-categories.php', + 'Yoast\\WP\\SEO\\Integrations\\Blocks\\Structured_Data_Blocks' => __DIR__ . '/../..' . '/src/integrations/blocks/structured-data-blocks.php', + 'Yoast\\WP\\SEO\\Integrations\\Breadcrumbs_Integration' => __DIR__ . '/../..' . '/src/integrations/breadcrumbs-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Cleanup_Integration' => __DIR__ . '/../..' . '/src/integrations/cleanup-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Duplicate_Post_Integration' => __DIR__ . '/../..' . '/src/integrations/duplicate-post-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Estimated_Reading_Time' => __DIR__ . '/../..' . '/src/integrations/estimated-reading-time.php', + 'Yoast\\WP\\SEO\\Integrations\\Exclude_Oembed_Cache_Post_Type' => __DIR__ . '/../..' . '/src/integrations/exclude-oembed-cache-post-type.php', + 'Yoast\\WP\\SEO\\Integrations\\Feature_Flag_Integration' => __DIR__ . '/../..' . '/src/integrations/feature-flag-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Backwards_Compatibility' => __DIR__ . '/../..' . '/src/integrations/front-end/backwards-compatibility.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Category_Term_Description' => __DIR__ . '/../..' . '/src/integrations/front-end/category-term-description.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Comment_Link_Fixer' => __DIR__ . '/../..' . '/src/integrations/front-end/comment-link-fixer.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Force_Rewrite_Title' => __DIR__ . '/../..' . '/src/integrations/front-end/force-rewrite-title.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Handle_404' => __DIR__ . '/../..' . '/src/integrations/front-end/handle-404.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Indexing_Controls' => __DIR__ . '/../..' . '/src/integrations/front-end/indexing-controls.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Open_Graph_OEmbed' => __DIR__ . '/../..' . '/src/integrations/front-end/open-graph-oembed.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\RSS_Footer_Embed' => __DIR__ . '/../..' . '/src/integrations/front-end/rss-footer-embed.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Redirects' => __DIR__ . '/../..' . '/src/integrations/front-end/redirects.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Schema_Accessibility_Feature' => __DIR__ . '/../..' . '/src/integrations/front-end/schema-accessibility-feature.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\Theme_Titles' => __DIR__ . '/../..' . '/src/integrations/front-end/theme-titles.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End\\WP_Robots_Integration' => __DIR__ . '/../..' . '/src/integrations/front-end/wp-robots-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Front_End_Integration' => __DIR__ . '/../..' . '/src/integrations/front-end-integration.php', + 'Yoast\\WP\\SEO\\Integrations\\Integration_Interface' => __DIR__ . '/../..' . '/src/integrations/integration-interface.php', + 'Yoast\\WP\\SEO\\Integrations\\Primary_Category' => __DIR__ . '/../..' . '/src/integrations/primary-category.php', + 'Yoast\\WP\\SEO\\Integrations\\Schema_Blocks' => __DIR__ . '/../..' . '/src/integrations/schema-blocks.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\AMP' => __DIR__ . '/../..' . '/src/integrations/third-party/amp.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\BbPress' => __DIR__ . '/../..' . '/src/integrations/third-party/bbpress.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Elementor' => __DIR__ . '/../..' . '/src/integrations/third-party/elementor.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Elementor_Exclude_Post_Types' => __DIR__ . '/../..' . '/src/deprecated/src/integrations/third-party/elementor.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Exclude_Elementor_Post_Types' => __DIR__ . '/../..' . '/src/integrations/third-party/exclude-elementor-post-types.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Exclude_WooCommerce_Post_Types' => __DIR__ . '/../..' . '/src/integrations/third-party/exclude-woocommerce-post-types.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Jetpack' => __DIR__ . '/../..' . '/src/integrations/third-party/jetpack.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\The_Events_Calendar' => __DIR__ . '/../..' . '/src/integrations/third-party/the-events-calendar.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\W3_Total_Cache' => __DIR__ . '/../..' . '/src/integrations/third-party/w3-total-cache.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\WPML' => __DIR__ . '/../..' . '/src/integrations/third-party/wpml.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\WPML_WPSEO_Notification' => __DIR__ . '/../..' . '/src/integrations/third-party/wpml-wpseo-notification.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Web_Stories' => __DIR__ . '/../..' . '/src/integrations/third-party/web-stories.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\WooCommerce' => __DIR__ . '/../..' . '/src/integrations/third-party/woocommerce.php', + 'Yoast\\WP\\SEO\\Integrations\\Third_Party\\Woocommerce_Permalinks' => __DIR__ . '/../..' . '/src/integrations/third-party/woocommerce-permalinks.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Addon_Update_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/addon-update-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Auto_Update_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/auto-update-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Ancestor_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-ancestor-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Author_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-author-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Category_Permalink_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-category-permalink-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Date_Archive_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-date-archive-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_HomeUrl_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-homeurl-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Home_Page_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-home-page-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Permalink_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-permalink-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Post_Meta_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-post-meta-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Post_Type_Archive_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-post-type-archive-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Post_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-post-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Static_Home_Page_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-static-home-page-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_System_Page_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-system-page-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Indexable_Term_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/indexable-term-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Option_Titles_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/option-titles-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Option_Wpseo_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/option-wpseo-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Category_Quick_Edit_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/primary-category-quick-edit-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\Watchers\\Primary_Term_Watcher' => __DIR__ . '/../..' . '/src/integrations/watchers/primary-term-watcher.php', + 'Yoast\\WP\\SEO\\Integrations\\XMLRPC' => __DIR__ . '/../..' . '/src/integrations/xmlrpc.php', + 'Yoast\\WP\\SEO\\Loadable_Interface' => __DIR__ . '/../..' . '/src/loadable-interface.php', + 'Yoast\\WP\\SEO\\Loader' => __DIR__ . '/../..' . '/src/loader.php', + 'Yoast\\WP\\SEO\\Loggers\\Logger' => __DIR__ . '/../..' . '/src/loggers/logger.php', + 'Yoast\\WP\\SEO\\Main' => __DIR__ . '/../..' . '/src/main.php', + 'Yoast\\WP\\SEO\\Memoizers\\Meta_Tags_Context_Memoizer' => __DIR__ . '/../..' . '/src/memoizers/meta-tags-context-memoizer.php', + 'Yoast\\WP\\SEO\\Memoizers\\Presentation_Memoizer' => __DIR__ . '/../..' . '/src/memoizers/presentation-memoizer.php', + 'Yoast\\WP\\SEO\\Models\\Indexable' => __DIR__ . '/../..' . '/src/models/indexable.php', + 'Yoast\\WP\\SEO\\Models\\Indexable_Extension' => __DIR__ . '/../..' . '/src/models/indexable-extension.php', + 'Yoast\\WP\\SEO\\Models\\Indexable_Hierarchy' => __DIR__ . '/../..' . '/src/models/indexable-hierarchy.php', + 'Yoast\\WP\\SEO\\Models\\Primary_Term' => __DIR__ . '/../..' . '/src/models/primary-term.php', + 'Yoast\\WP\\SEO\\Models\\SEO_Links' => __DIR__ . '/../..' . '/src/models/seo-links.php', + 'Yoast\\WP\\SEO\\Models\\SEO_Meta' => __DIR__ . '/../..' . '/src/models/seo-meta.php', + 'Yoast\\WP\\SEO\\Presentations\\Abstract_Presentation' => __DIR__ . '/../..' . '/src/presentations/abstract-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Archive_Adjacent' => __DIR__ . '/../..' . '/src/presentations/archive-adjacent-trait.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Author_Archive_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-author-archive-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Date_Archive_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-date-archive-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Error_Page_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-error-page-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Home_Page_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-home-page-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Post_Type_Archive_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-post-type-archive-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Post_Type_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-post-type-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Search_Result_Page_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-search-result-page-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Static_Home_Page_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-static-home-page-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Static_Posts_Page_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-static-posts-page-presentation.php', + 'Yoast\\WP\\SEO\\Presentations\\Indexable_Term_Archive_Presentation' => __DIR__ . '/../..' . '/src/presentations/indexable-term-archive-presentation.php', + 'Yoast\\WP\\SEO\\Presenters\\Abstract_Indexable_Presenter' => __DIR__ . '/../..' . '/src/presenters/abstract-indexable-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Abstract_Indexable_Tag_Presenter' => __DIR__ . '/../..' . '/src/presenters/abstract-indexable-tag-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Abstract_Presenter' => __DIR__ . '/../..' . '/src/presenters/abstract-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Alert_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/alert-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Auto_Update_Notification_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/auto-update-notification-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Badge_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/badge-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Help_Link_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/help-link-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexation_List_Item_Presenter' => __DIR__ . '/../..' . '/src/deprecated/src/presenters/admin/indexation-list-item-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexation_Modal_Presenter' => __DIR__ . '/../..' . '/src/deprecated/src/presenters/admin/indexation-modal-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexation_Permalink_Warning_Presenter' => __DIR__ . '/../..' . '/src/deprecated/src/presenters/admin/indexation-permalink-warning-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexation_Warning_Presenter' => __DIR__ . '/../..' . '/src/deprecated/src/presenters/admin/indexation-warning-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexing_Error_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/indexing-error-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexing_Failed_Notification_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/indexing-failed-notification-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexing_List_Item_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/indexing-list-item-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Indexing_Notification_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/indexing-notification-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Light_Switch_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/light-switch-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Link_Count_Indexing_List_Item_Presenter' => __DIR__ . '/../..' . '/src/deprecated/src/presenters/admin/link-count-indexing-list-item-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Link_Count_Indexing_Modal_Presenter' => __DIR__ . '/../..' . '/src/deprecated/src/presenters/admin/link-count-indexing-modal-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Meta_Fields_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/meta-fields-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Migration_Error_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/migration-error-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Admin\\Premium_Badge_Presenter' => __DIR__ . '/../..' . '/src/presenters/admin/premium-badge-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Bingbot_Presenter' => __DIR__ . '/../..' . '/src/presenters/bingbot-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Breadcrumbs_Presenter' => __DIR__ . '/../..' . '/src/presenters/breadcrumbs-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Canonical_Presenter' => __DIR__ . '/../..' . '/src/presenters/canonical-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Debug\\Marker_Close_Presenter' => __DIR__ . '/../..' . '/src/presenters/debug/marker-close-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Debug\\Marker_Open_Presenter' => __DIR__ . '/../..' . '/src/presenters/debug/marker-open-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Googlebot_Presenter' => __DIR__ . '/../..' . '/src/presenters/googlebot-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Meta_Description_Presenter' => __DIR__ . '/../..' . '/src/presenters/meta-description-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Article_Author_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/article-author-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Article_Modified_Time_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/article-modified-time-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Article_Published_Time_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/article-published-time-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Article_Publisher_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/article-publisher-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Description_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/description-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\FB_App_ID_Presenter' => __DIR__ . '/../..' . '/src/deprecated/src/presenters/open-graph/fb-app-id-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Image_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/image-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Locale_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/locale-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Site_Name_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/site-name-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Title_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/title-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Type_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/type-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Open_Graph\\Url_Presenter' => __DIR__ . '/../..' . '/src/presenters/open-graph/url-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Rel_Next_Presenter' => __DIR__ . '/../..' . '/src/presenters/rel-next-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Rel_Prev_Presenter' => __DIR__ . '/../..' . '/src/presenters/rel-prev-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Robots_Presenter' => __DIR__ . '/../..' . '/src/presenters/robots-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Schema_Presenter' => __DIR__ . '/../..' . '/src/presenters/schema-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Slack\\Enhanced_Data_Presenter' => __DIR__ . '/../..' . '/src/presenters/slack/enhanced-data-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Title_Presenter' => __DIR__ . '/../..' . '/src/presenters/title-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Card_Presenter' => __DIR__ . '/../..' . '/src/presenters/twitter/card-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Creator_Presenter' => __DIR__ . '/../..' . '/src/presenters/twitter/creator-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Description_Presenter' => __DIR__ . '/../..' . '/src/presenters/twitter/description-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Image_Presenter' => __DIR__ . '/../..' . '/src/presenters/twitter/image-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Site_Presenter' => __DIR__ . '/../..' . '/src/presenters/twitter/site-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Twitter\\Title_Presenter' => __DIR__ . '/../..' . '/src/presenters/twitter/title-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Url_List_Presenter' => __DIR__ . '/../..' . '/src/presenters/url-list-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Webmaster\\Baidu_Presenter' => __DIR__ . '/../..' . '/src/presenters/webmaster/baidu-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Webmaster\\Bing_Presenter' => __DIR__ . '/../..' . '/src/presenters/webmaster/bing-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Webmaster\\Google_Presenter' => __DIR__ . '/../..' . '/src/presenters/webmaster/google-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Webmaster\\Pinterest_Presenter' => __DIR__ . '/../..' . '/src/presenters/webmaster/pinterest-presenter.php', + 'Yoast\\WP\\SEO\\Presenters\\Webmaster\\Yandex_Presenter' => __DIR__ . '/../..' . '/src/presenters/webmaster/yandex-presenter.php', + 'Yoast\\WP\\SEO\\Repositories\\Indexable_Hierarchy_Repository' => __DIR__ . '/../..' . '/src/repositories/indexable-hierarchy-repository.php', + 'Yoast\\WP\\SEO\\Repositories\\Indexable_Repository' => __DIR__ . '/../..' . '/src/repositories/indexable-repository.php', + 'Yoast\\WP\\SEO\\Repositories\\Primary_Term_Repository' => __DIR__ . '/../..' . '/src/repositories/primary-term-repository.php', + 'Yoast\\WP\\SEO\\Repositories\\SEO_Links_Repository' => __DIR__ . '/../..' . '/src/repositories/seo-links-repository.php', + 'Yoast\\WP\\SEO\\Repositories\\SEO_Meta_Repository' => __DIR__ . '/../..' . '/src/repositories/seo-meta-repository.php', + 'Yoast\\WP\\SEO\\Routes\\Abstract_Indexation_Route' => __DIR__ . '/../..' . '/src/routes/abstract-indexation-route.php', + 'Yoast\\WP\\SEO\\Routes\\Alert_Dismissal_Route' => __DIR__ . '/../..' . '/src/routes/alert-dismissal-route.php', + 'Yoast\\WP\\SEO\\Routes\\Indexables_Head_Route' => __DIR__ . '/../..' . '/src/routes/indexables-head-route.php', + 'Yoast\\WP\\SEO\\Routes\\Indexing_Route' => __DIR__ . '/../..' . '/src/routes/indexing-route.php', + 'Yoast\\WP\\SEO\\Routes\\Route_Interface' => __DIR__ . '/../..' . '/src/routes/route-interface.php', + 'Yoast\\WP\\SEO\\Routes\\SEMrush_Route' => __DIR__ . '/../..' . '/src/routes/semrush-route.php', + 'Yoast\\WP\\SEO\\Routes\\Supported_Features_Route' => __DIR__ . '/../..' . '/src/routes/supported-features-route.php', + 'Yoast\\WP\\SEO\\Routes\\Yoast_Head_REST_Field' => __DIR__ . '/../..' . '/src/routes/yoast-head-rest-field.php', + 'Yoast\\WP\\SEO\\Schema_Templates\\Assets\\Icons' => __DIR__ . '/../..' . '/src/schema-templates/assets/icons.php', + 'Yoast\\WP\\SEO\\Surfaces\\Classes_Surface' => __DIR__ . '/../..' . '/src/surfaces/classes-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Helpers_Surface' => __DIR__ . '/../..' . '/src/surfaces/helpers-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Meta_Surface' => __DIR__ . '/../..' . '/src/surfaces/meta-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Open_Graph_Helpers_Surface' => __DIR__ . '/../..' . '/src/surfaces/open-graph-helpers-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Schema_Helpers_Surface' => __DIR__ . '/../..' . '/src/surfaces/schema-helpers-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Twitter_Helpers_Surface' => __DIR__ . '/../..' . '/src/surfaces/twitter-helpers-surface.php', + 'Yoast\\WP\\SEO\\Surfaces\\Values\\Meta' => __DIR__ . '/../..' . '/src/surfaces/values/meta.php', + 'Yoast\\WP\\SEO\\Values\\Images' => __DIR__ . '/../..' . '/src/values/images.php', + 'Yoast\\WP\\SEO\\Values\\Open_Graph\\Images' => __DIR__ . '/../..' . '/src/values/open-graph/images.php', + 'Yoast\\WP\\SEO\\Values\\SEMrush\\SEMrush_Token' => __DIR__ . '/../..' . '/src/values/semrush/semrush-token.php', + 'Yoast\\WP\\SEO\\WordPress\\Wrapper' => __DIR__ . '/../..' . '/src/wordpress/wrapper.php', + 'Yoast\\WP\\SEO\\Wrappers\\WP_Query_Wrapper' => __DIR__ . '/../..' . '/src/wrappers/wp-query-wrapper.php', + 'Yoast\\WP\\SEO\\Wrappers\\WP_Remote_Handler' => __DIR__ . '/../..' . '/src/wrappers/wp-remote-handler.php', + 'Yoast\\WP\\SEO\\Wrappers\\WP_Rewrite_Wrapper' => __DIR__ . '/../..' . '/src/wrappers/wp-rewrite-wrapper.php', 'Yoast_Dashboard_Widget' => __DIR__ . '/../..' . '/admin/class-yoast-dashboard-widget.php', 'Yoast_Dismissable_Notice_Ajax' => __DIR__ . '/../..' . '/admin/ajax/class-yoast-dismissable-notice.php', + 'Yoast_Feature_Toggle' => __DIR__ . '/../..' . '/admin/views/class-yoast-feature-toggle.php', + 'Yoast_Feature_Toggles' => __DIR__ . '/../..' . '/admin/views/class-yoast-feature-toggles.php', 'Yoast_Form' => __DIR__ . '/../..' . '/admin/class-yoast-form.php', 'Yoast_Form_Element' => __DIR__ . '/../..' . '/admin/views/interface-yoast-form-element.php', - 'Yoast_Form_Fieldset' => __DIR__ . '/../..' . '/admin/views/class-yoast-form-fieldset.php', - 'Yoast_I18n_WordPressOrg_v3' => __DIR__ . '/..' . '/yoast/i18n-module/src/i18n-module-wordpressorg.php', - 'Yoast_I18n_v3' => __DIR__ . '/..' . '/yoast/i18n-module/src/i18n-module.php', + 'Yoast_I18n_WordPressOrg_v3' => __DIR__ . '/..' . '/yoast/i18n-module/src/i18n-wordpressorg-v3.php', + 'Yoast_I18n_v3' => __DIR__ . '/..' . '/yoast/i18n-module/src/i18n-v3.php', 'Yoast_Input_Select' => __DIR__ . '/../..' . '/admin/views/class-yoast-input-select.php', - 'Yoast_License_Manager' => __DIR__ . '/..' . '/yoast/license-manager/class-license-manager.php', + 'Yoast_Input_Validation' => __DIR__ . '/../..' . '/admin/class-yoast-input-validation.php', + 'Yoast_Integration_Toggles' => __DIR__ . '/../..' . '/admin/views/class-yoast-integration-toggles.php', + 'Yoast_Network_Admin' => __DIR__ . '/../..' . '/admin/class-yoast-network-admin.php', + 'Yoast_Network_Settings_API' => __DIR__ . '/../..' . '/admin/class-yoast-network-settings-api.php', 'Yoast_Notification' => __DIR__ . '/../..' . '/admin/class-yoast-notification.php', 'Yoast_Notification_Center' => __DIR__ . '/../..' . '/admin/class-yoast-notification-center.php', - 'Yoast_OnPage_Ajax' => __DIR__ . '/../..' . '/admin/ajax/class-yoast-onpage-ajax.php', + 'Yoast_Notifications' => __DIR__ . '/../..' . '/admin/class-yoast-notifications.php', + 'Yoast_OnPage_Ajax' => __DIR__ . '/../..' . '/src/deprecated/admin/ajax/class-yoast-onpage-ajax.php', 'Yoast_Plugin_Conflict' => __DIR__ . '/../..' . '/admin/class-yoast-plugin-conflict.php', 'Yoast_Plugin_Conflict_Ajax' => __DIR__ . '/../..' . '/admin/ajax/class-yoast-plugin-conflict-ajax.php', - 'Yoast_Plugin_License_Manager' => __DIR__ . '/..' . '/yoast/license-manager/class-plugin-license-manager.php', - 'Yoast_Plugin_Update_Manager' => __DIR__ . '/..' . '/yoast/license-manager/class-plugin-update-manager.php', - 'Yoast_Product' => __DIR__ . '/..' . '/yoast/license-manager/class-product.php', - 'Yoast_Theme_License_Manager' => __DIR__ . '/..' . '/yoast/license-manager/class-theme-license-manager.php', - 'Yoast_Theme_Update_Manager' => __DIR__ . '/..' . '/yoast/license-manager/class-theme-update-manager.php', - 'Yoast_Update_Manager' => __DIR__ . '/..' . '/yoast/license-manager/class-update-manager.php', 'Yoast_View_Utils' => __DIR__ . '/../..' . '/admin/views/class-view-utils.php', - 'iYoast_License_Manager' => __DIR__ . '/..' . '/yoast/license-manager/class-license-manager.php', - 'xrstf\\Composer52\\AutoloadGenerator' => __DIR__ . '/..' . '/xrstf/composer-php52/lib/xrstf/Composer52/AutoloadGenerator.php', - 'xrstf\\Composer52\\Generator' => __DIR__ . '/..' . '/xrstf/composer-php52/lib/xrstf/Composer52/Generator.php', ); public static function getInitializer(ClassLoader $loader) { return \Closure::bind(function () use ($loader) { - $loader->prefixLengthsPsr4 = ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0::$prefixLengthsPsr4; - $loader->prefixDirsPsr4 = ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0::$prefixDirsPsr4; - $loader->prefixesPsr0 = ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0::$prefixesPsr0; - $loader->classMap = ComposerStaticInite65e71171c1a5e9e7f808031e878a5e0::$classMap; + $loader->prefixLengthsPsr4 = ComposerStaticInit91ec1988dfabfb54a53c085331eb54a0::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit91ec1988dfabfb54a53c085331eb54a0::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit91ec1988dfabfb54a53c085331eb54a0::$classMap; }, null, ClassLoader::class); } diff --git a/wp-content/plugins/wordpress-seo/vendor/xrstf/composer-php52/LICENSE b/wp-content/plugins/wordpress-seo/vendor/xrstf/composer-php52/LICENSE deleted file mode 100644 index 0e81028e..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/xrstf/composer-php52/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2013 Christoph Mewes - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/wp-content/plugins/wordpress-seo/vendor/xrstf/composer-php52/lib/xrstf/Composer52/AutoloadGenerator.php b/wp-content/plugins/wordpress-seo/vendor/xrstf/composer-php52/lib/xrstf/Composer52/AutoloadGenerator.php deleted file mode 100644 index 2e93e6f3..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/xrstf/composer-php52/lib/xrstf/Composer52/AutoloadGenerator.php +++ /dev/null @@ -1,346 +0,0 @@ - - * - Jordi Boggiano - */ - -namespace xrstf\Composer52; - -use Composer\Autoload\AutoloadGenerator as BaseGenerator; -use Composer\Autoload\ClassMapGenerator; -use Composer\Config; -use Composer\Installer\InstallationManager; -use Composer\Package\AliasPackage; -use Composer\Package\PackageInterface; -use Composer\Repository\InstalledRepositoryInterface; -use Composer\Util\Filesystem; - -class AutoloadGenerator extends BaseGenerator { - - /** - * @var bool - */ - private $classMapAuthoritative = false; - - public function __construct() { - // do nothing (but keep this constructor so we can build an instance without the need for an event dispatcher) - } - - /** - * Whether or not generated autoloader considers the class map - * authoritative. - * - * @param bool $classMapAuthoritative - */ - public function setClassMapAuthoritative($classMapAuthoritative) - { - $this->classMapAuthoritative = (boolean) $classMapAuthoritative; - } - - public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '') { - if ($this->classMapAuthoritative) { - // Force scanPsr0Packages when classmap is authoritative - $scanPsr0Packages = true; - } - - $filesystem = new Filesystem(); - $filesystem->ensureDirectoryExists($config->get('vendor-dir')); - - $cwd = getcwd(); - $basePath = $filesystem->normalizePath($cwd); - $vendorPath = $filesystem->normalizePath(realpath($config->get('vendor-dir'))); - $targetDir = $vendorPath.'/'.$targetDir; - $filesystem->ensureDirectoryExists($targetDir); - - $useGlobalIncludePath = (bool) $config->get('use-include-path'); - $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true'; - $classMapAuthoritative = $config->get('classmap-authoritative'); - - $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true); - $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true); - - $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true); - $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode); - - // add 5.2 compat - $vendorPathCode = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode); - $vendorPathToTargetDirCode = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathToTargetDirCode); - - $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages()); - $autoloads = $this->parseAutoloads($packageMap, $mainPackage); - - // add custom psr-0 autoloading if the root package has a target dir - $targetDirLoader = null; - $mainAutoload = $mainPackage->getAutoload(); - if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) { - $levels = count(explode('/', $filesystem->normalizePath($mainPackage->getTargetDir()))); - $prefixes = implode(', ', array_map(function ($prefix) { - return var_export($prefix, true); - }, array_keys($mainAutoload['psr-0']))); - - $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true); - - $targetDirLoader = <<isPHP53($functionFile)) { - $filesCode .= '// require '.$this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile)."; // disabled because of PHP 5.3 syntax\n"; - } - else { - $filesCode .= ' require '.$this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile).";\n"; - } - } - - if (!$suffix) { - $suffix = md5(uniqid('', true)); - } - - $includePathFile = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode); - - file_put_contents($vendorPath.'/autoload_52.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix)); - file_put_contents($targetDir.'/autoload_real_52.php', $this->getAutoloadRealFile(true, (bool) $includePathFile, $targetDirLoader, $filesCode, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader)); - - // use stream_copy_to_stream instead of copy - // to work around https://bugs.php.net/bug.php?id=64634 - $sourceLoader = fopen(__DIR__.'/ClassLoader.php', 'r'); - $targetLoader = fopen($targetDir.'/ClassLoader52.php', 'w+'); - stream_copy_to_stream($sourceLoader, $targetLoader); - fclose($sourceLoader); - fclose($targetLoader); - unset($sourceLoader, $targetLoader); - } - - protected function isPHP53($file) { - $tokens = token_get_all(file_get_contents($file)); - $php53 = array(T_DIR, T_GOTO, T_NAMESPACE, T_NS_C, T_NS_SEPARATOR, T_USE); - - // PHP 5.4+ - if (defined('T_TRAIT')) { - $php53[] = T_TRAIT; - $php53[] = T_TRAIT_C; - $php53[] = T_TRAIT_C; - } - - // PHP 5.5+ - if (defined('T_FINALLY')) { - $php53[] = T_FINALLY; - $php53[] = T_YIELD; - } - - foreach ($tokens as $token) { - if (is_array($token) && in_array($token[0], $php53)) { - return true; - } - } - - return false; - } - - protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode) { - $includePaths = array(); - - foreach ($packageMap as $item) { - list($package, $installPath) = $item; - - if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) { - $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir())); - } - - foreach ($package->getIncludePaths() as $includePath) { - $includePath = trim($includePath, '/'); - $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath; - } - } - - if (!$includePaths) { - return; - } - - $includePathsFile = <<getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n"; - } - - return $includePathsFile . ");\n"; - } - - protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix) { - return << $path) { - $loader->add($namespace, $path); - } - - -PSR0; - - if ($useClassMap) { - $file .= <<<'CLASSMAP' - $classMap = require $dir.'/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - - -CLASSMAP; - } - - if ($this->classMapAuthoritative) { - $file .= <<<'CLASSMAPAUTHORITATIVE' - $loader->setClassMapAuthoritative(true); - -CLASSMAPAUTHORITATIVE; - } - - if ($useGlobalIncludePath) { - $file .= <<<'INCLUDEPATH' - $loader->setUseIncludePath(true); - - -INCLUDEPATH; - } - - if ($targetDirLoader) { - $file .= <<register($prependAutoloader);{$filesCode} - - return \$loader; - } - -METHOD_FOOTER; - - $file .= $targetDirLoader; - - return $file . <<
    - * - Jordi Boggiano - */ - -class xrstf_Composer52_ClassLoader { - private $prefixes = array(); - private $fallbackDirs = array(); - private $useIncludePath = false; - private $classMap = array(); - private $classMapAuthoratative = false; - private $allowUnderscore = false; - - /** - * @param boolean $flag true to allow class names with a leading underscore, false to disable - */ - public function setAllowUnderscore($flag) { - $this->allowUnderscore = (boolean) $flag; - } - - /** - * @return array - */ - public function getPrefixes() { - return $this->prefixes; - } - - /** - * Turns off searching the prefix and fallback directories for classes - * that have not been registered with the class map. - * - * @param bool $classMapAuthoratative - */ - public function setClassMapAuthoritative($classMapAuthoratative) { - $this->classMapAuthoratative = $classMapAuthoratative; - } - - /** - * Should class lookup fail if not found in the current class map? - * - * @return bool - */ - public function getClassMapAuthoratative() { - return $this->classMapAuthoratative; - } - - /** - * @return array - */ - public function getFallbackDirs() { - return $this->fallbackDirs; - } - - /** - * @return array - */ - public function getClassMap() { - return $this->classMap; - } - - /** - * @param array $classMap class to filename map - */ - public function addClassMap(array $classMap) { - if ($this->classMap) { - $this->classMap = array_merge($this->classMap, $classMap); - } - else { - $this->classMap = $classMap; - } - } - - /** - * Registers a set of classes, merging with any others previously set. - * - * @param string $prefix the classes prefix - * @param array|string $paths the location(s) of the classes - * @param bool $prepend prepend the location(s) - */ - public function add($prefix, $paths, $prepend = false) { - if (!$prefix) { - if ($prepend) { - $this->fallbackDirs = array_merge( - (array) $paths, - $this->fallbackDirs - ); - } - else { - $this->fallbackDirs = array_merge( - $this->fallbackDirs, - (array) $paths - ); - } - - return; - } - - if (!isset($this->prefixes[$prefix])) { - $this->prefixes[$prefix] = (array) $paths; - return; - } - - if ($prepend) { - $this->prefixes[$prefix] = array_merge( - (array) $paths, - $this->prefixes[$prefix] - ); - } - else { - $this->prefixes[$prefix] = array_merge( - $this->prefixes[$prefix], - (array) $paths - ); - } - } - - /** - * Registers a set of classes, replacing any others previously set. - * - * @param string $prefix the classes prefix - * @param array|string $paths the location(s) of the classes - */ - public function set($prefix, $paths) { - if (!$prefix) { - $this->fallbackDirs = (array) $paths; - return; - } - - $this->prefixes[$prefix] = (array) $paths; - } - - /** - * Turns on searching the include path for class files. - * - * @param bool $useIncludePath - */ - public function setUseIncludePath($useIncludePath) { - $this->useIncludePath = $useIncludePath; - } - - /** - * Can be used to check if the autoloader uses the include path to check - * for classes. - * - * @return bool - */ - public function getUseIncludePath() { - return $this->useIncludePath; - } - - /** - * Registers this instance as an autoloader. - */ - public function register() { - spl_autoload_register(array($this, 'loadClass'), true); - } - - /** - * Unregisters this instance as an autoloader. - */ - public function unregister() { - spl_autoload_unregister(array($this, 'loadClass')); - } - - /** - * Loads the given class or interface. - * - * @param string $class the name of the class - * @return bool|null true, if loaded - */ - public function loadClass($class) { - if ($file = $this->findFile($class)) { - include $file; - return true; - } - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class the name of the class - * @return string|null the path, if found - */ - public function findFile($class) { - if ('\\' === $class[0]) { - $class = substr($class, 1); - } - - if (isset($this->classMap[$class])) { - return $this->classMap[$class]; - } - elseif ($this->classMapAuthoratative) { - return false; - } - - $classPath = $this->getClassPath($class); - - foreach ($this->prefixes as $prefix => $dirs) { - if (0 === strpos($class, $prefix)) { - foreach ($dirs as $dir) { - if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { - return $dir.DIRECTORY_SEPARATOR.$classPath; - } - } - } - } - - foreach ($this->fallbackDirs as $dir) { - if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { - return $dir.DIRECTORY_SEPARATOR.$classPath; - } - } - - if ($this->useIncludePath && $file = self::resolveIncludePath($classPath)) { - return $file; - } - - return $this->classMap[$class] = false; - } - - private function getClassPath($class) { - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR; - $className = substr($class, $pos + 1); - } - else { - // PEAR-like class name - $classPath = null; - $className = $class; - } - - $className = str_replace('_', DIRECTORY_SEPARATOR, $className); - - // restore the prefix - if ($this->allowUnderscore && DIRECTORY_SEPARATOR === $className[0]) { - $className[0] = '_'; - } - - $classPath .= $className.'.php'; - - return $classPath; - } - - public static function resolveIncludePath($classPath) { - $paths = explode(PATH_SEPARATOR, get_include_path()); - - foreach ($paths as $path) { - $path = rtrim($path, '/\\'); - - if ($file = file_exists($path.DIRECTORY_SEPARATOR.$file)) { - return $file; - } - } - - return false; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/xrstf/composer-php52/lib/xrstf/Composer52/Generator.php b/wp-content/plugins/wordpress-seo/vendor/xrstf/composer-php52/lib/xrstf/Composer52/Generator.php deleted file mode 100644 index 7c8af4de..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/xrstf/composer-php52/lib/xrstf/Composer52/Generator.php +++ /dev/null @@ -1,39 +0,0 @@ -getComposer(); - $installationManager = $composer->getInstallationManager(); - $repoManager = $composer->getRepositoryManager(); - $localRepo = $repoManager->getLocalRepository(); - $package = $composer->getPackage(); - $config = $composer->getConfig(); - - // We can't gain access to the Command's input object, so we have to look - // for -o / --optimize-autoloader ourselves. Sadly, neither getopt() works - // (always returns an empty array), nor does Symfony's Console Input, as - // it expects a full definition of the current command line and we can't - // provide that. - - $args = $_SERVER['argv']; - $optimize = in_array('-o', $args) || in_array('--optimize-autoloader', $args) || in_array('--optimize', $args); - - $suffix = $config->get('autoloader-suffix'); - - $generator = new AutoloadGenerator(); - $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize, $suffix); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/class-api-google-client.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/class-api-google-client.php deleted file mode 100644 index d8871e17..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/class-api-google-client.php +++ /dev/null @@ -1,269 +0,0 @@ -option_refresh_token = $option_prefix . '-refresh_token'; - $this->option_access_token = $option_prefix . '-access_token'; - - $this->api_url = $api_url; - - // Initialize the config to set all properties properly. - $this->init_config( $config ); - - // Let's get an access token if we've got a refresh token. - $this->refresh_tokens(); - } - - /** - * Authenticate the client. If $authorization_code is empty it will lead the user through the validation process of - * Google. If set it will be get the access token for current session and save the refresh_token for future use - * - * @param mixed $authorization_code - * - * @return bool - */ - public function authenticate_client( $authorization_code = null ) { - static $has_retried; - - // Authenticate client. - try { - $this->authenticate( $authorization_code ); - - // Get access response. - $response = $this->getAccessToken(); - - // Check if there is a response body. - if ( ! empty( $response ) ) { - $response = json_decode( $response ); - - if ( is_object( $response ) ) { - // Save the refresh token. - $this->save_refresh_token( $response->refresh_token ); - - return true; - } - } - } catch ( Yoast_Google_AuthException $exception ) { - // If there aren't any attempts before, try again and set attempts on true, to prevent further attempts. - if ( empty( $has_retried ) ) { - $has_retried = true; - - return $this->authenticate_client( $authorization_code ); - } - } - - return false; - } - - /** - * Doing a request to the API - * - * @param string $target_request_url - * @param bool $decode_response - * @param string $request_method - * - * @return array - */ - public function do_request( $target_request_url, $decode_response = false, $request_method = 'GET' ) { - // Get response. - $response = $this->getIo()->authenticatedRequest( - new Yoast_Google_HttpRequest( $this->api_url . $target_request_url, $request_method ) - ); - - // Storing the response code. - $this->http_response_code = $response->getResponseHttpCode(); - - if ( $decode_response ) { - return $this->decode_response( $response ); - } - - return $response; - } - - /** - * Decode the JSON response - * - * @param object $response - * @param int $accepted_response_code - * - * @return mixed - */ - public function decode_response( $response, $accepted_response_code = 200 ) { - if ( $accepted_response_code === $response->getResponseHttpCode() ) { - return json_decode( $response->getResponseBody() ); - } - } - - /** - * Getting the response code, saved from latest request to Google - * - * @return mixed - */ - public function get_http_response_code() { - return $this->http_response_code; - } - - /** - * Clears the options and revokes the token - */ - public function clear_data() { - $this->revokeToken(); - - delete_option( $this->option_access_token ); - delete_option( $this->option_refresh_token ); - } - - /** - * Check if user is authenticated - * - * @return bool - */ - public function is_authenticated() { - $has_refresh_token = ( $this->get_refresh_token() !== '' ); - $access_token_expired = $this->access_token_expired(); - - return $has_refresh_token && ! $access_token_expired; - } - - /** - * Initialize the config, will merge given config with default config to be sure all settings are available - * - * @param array $config - */ - protected function init_config( array $config ) { - if ( ! empty( $config['application_name'] ) ) { - $this->setApplicationName( $config['application_name'] ); - } - - if ( ! empty( $config['client_id'] ) ) { - $this->setClientId( $config['client_id'] ); - } - - if ( ! empty( $config['client_secret'] ) ) { - $this->setClientSecret( $config['client_secret'] ); - } - - // Set our settings. - $this->setRedirectUri( $config['redirect_uri'] ); - $this->setScopes( $config['scopes'] ); - $this->setAccessType( 'offline' ); - } - - /** - * Refreshing the tokens - */ - protected function refresh_tokens() { - if ( ( $refresh_token = $this->get_refresh_token() ) !== '' && $this->access_token_expired() ) { - try { - // Refresh the token. - $this->refreshToken( $refresh_token ); - - $response = $this->getAuth()->token; - - // Check response and if there is an access_token. - if ( ! empty( $response ) && ! empty ( $response['access_token'] ) ) { - $this->save_access_token( $response ); - } - } - catch ( Exception $e ) { - return false; - } - } - } - - /** - * Save the refresh token - * - * @param string $refresh_token - */ - protected function save_refresh_token( $refresh_token ) { - update_option( $this->option_refresh_token, trim( $refresh_token ) ); - } - - /** - * Return refresh token - * - * @return string - */ - protected function get_refresh_token() { - return get_option( $this->option_refresh_token, '' ); - } - - /** - * Saving the access token as an option for further use till it expires. - * - * @param array $response - */ - protected function save_access_token( $response ) { - update_option( - $this->option_access_token, - array( - 'refresh_token' => $this->get_refresh_token(), - 'access_token' => $response['access_token'], - 'expires' => current_time( 'timestamp' ) + $response['expires_in'], - 'expires_in' => $response['expires_in'], - 'created' => $response['created'], - ) - ); - - $this->setAccessToken( json_encode( $response ) ); - } - - /** - * Check if current access token is expired. - * - * @return bool - */ - private function access_token_expired() { - $access_token = $this->get_access_token(); - - if ( current_time( 'timestamp' ) >= $access_token['expires'] ) { - return true; - } - - $this->setAccessToken( json_encode( $access_token ) ); - } - - /** - * Getting the current access token from the options - * - * @return mixed - */ - private function get_access_token() { - return get_option( $this->option_access_token, array( 'access_token' => false, 'expires' => 0 ) ); - } - -} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/class-api-google.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/class-api-google.php deleted file mode 100644 index fe671f4d..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/class-api-google.php +++ /dev/null @@ -1,64 +0,0 @@ - 'google/Google_Client', - 'yoast_api_google_client' => 'class-api-google-client', - - // Requires in classes - 'yoast_google_auth' => 'google/auth/Google_Auth', - 'yoast_google_assertion' => 'google/auth/Google_AssertionCredentials', - 'yoast_google_signer' => 'google/auth/Google_Signer', - 'yoast_google_p12signer' => 'google/auth/Google_P12Signer', - 'yoast_google_authnone' => 'google/auth/Google_AuthNone', - 'yoast_google_oauth2' => 'google/auth/Google_OAuth2', - 'yoast_google_verifier' => 'google/auth/Google_Verifier', - 'yoast_google_loginticket' => 'google/auth/Google_LoginTicket', - 'yoast_google_pemverifier' => 'google/auth/Google_PemVerifier', - 'yoast_google_model' => 'google/service/Google_Model', - 'yoast_google_service' => 'google/service/Google_Service', - 'yoast_google_serviceresource' => 'google/service/Google_ServiceResource', - 'yoast_google_utils' => 'google/service/Google_Utils', - 'yoast_google_batchrequest' => 'google/service/Google_BatchRequest', - 'yoast_google_mediafileupload' => 'google/service/Google_MediaFileUpload', - 'yoast_google_uritemplate' => 'google/external/URITemplateParser', - 'yoast_google_cache' => 'google/cache/Google_Cache', - - // Requests - 'yoast_google_cacheparser' => 'google/io/Google_CacheParser', - 'yoast_google_io' => 'google/io/Google_IO', - 'yoast_google_httprequest' => 'google/io/Google_HttpRequest', - 'yoast_google_rest' => 'google/io/Google_REST', - - // Wordpress - 'yoast_google_wpio' => 'google/io/Google_WPIO', - 'yoast_google_wpcache' => 'google/cache/Google_WPCache', - ); - - if ( ! empty( $oauth_files[$class_name] ) ) { - if ( file_exists( $path . '/' . $oauth_files[$class_name] . '.php' ) ) { - require_once( $path . '/' . $oauth_files[$class_name] . '.php' ); - } - - } - - } - -} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/class-api-libs.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/class-api-libs.php deleted file mode 100644 index e17c7fba..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/class-api-libs.php +++ /dev/null @@ -1,49 +0,0 @@ -register_api_library() - * - Create folder 'oauth' - * - Create file 'class-api-oauth.php' - * - Class name should be 'Yoast_Api_Oauth' - */ -class Yoast_Api_Libs { - - /** - * Current version number of the API-libs - */ - const version = '2.0'; - - /** - * Check if minimal required version is met. - * - * @param string $minimal_required_version - * - * @throws Exception - */ - public function __construct( $minimal_required_version ) { - $this->load_google(); - - if ( ! version_compare( self::version, $minimal_required_version, '>=' )) { - throw new Exception( 'required_version' ); - } - } - - /** - * Loading the google api library which will set the autoloader - */ - private function load_google() { - if ( ! class_exists('Yoast_Api_Google', false) ) { - // Require the file - require_once dirname( __FILE__ ) . '/' . 'class-api-google.php'; - - // Initialize the Google API Class to set the autoloader - new Yoast_Api_Google(); - } - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/Google_Client.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/Google_Client.php deleted file mode 100644 index 95adba8f..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/Google_Client.php +++ /dev/null @@ -1,457 +0,0 @@ - - * @author Chirag Shah - */ -class Yoast_Google_Client { - /** - * @static - * @var Yoast_Google_Auth $auth - */ - static $auth; - - /** - * @static - * @var Yoast_Google_IO $io - */ - static $io; - - /** - * @static - * @var Yoast_Google_Cache $cache - */ - static $cache; - - /** - * @static - * @var boolean $useBatch - */ - static $useBatch = false; - - /** @var array $scopes */ - protected $scopes = array(); - - /** @var bool $useObjects */ - protected $useObjects = false; - - // definitions of services that are discovered. - protected $services = array(); - - // Used to track authenticated state, can't discover services after doing authenticate() - private $authenticated = false; - - public function __construct($config = array()) { - global $apiConfig; - $apiConfig = array_merge($apiConfig, $config); - self::$cache = new $apiConfig['cacheClass'](); - self::$auth = new $apiConfig['authClass'](); - self::$io = new $apiConfig['ioClass'](); - } - - /** - * Add a service - */ - public function addService($service, $version = false) { - global $apiConfig; - if ($this->authenticated) { - throw new Yoast_Google_Exception('Cant add services after having authenticated'); - } - $this->services[$service] = array(); - if (isset($apiConfig['services'][$service])) { - // Merge the service descriptor with the default values - $this->services[$service] = array_merge($this->services[$service], $apiConfig['services'][$service]); - } - } - - public function authenticate($code = null) { - $service = $this->prepareService(); - $this->authenticated = true; - return self::$auth->authenticate($service, $code); - } - - /** - * @return array - * @visible For Testing - */ - public function prepareService() { - $service = array(); - $scopes = array(); - if ($this->scopes) { - $scopes = $this->scopes; - } else { - foreach ($this->services as $key => $val) { - if (isset($val['scope'])) { - if (is_array($val['scope'])) { - $scopes = array_merge($val['scope'], $scopes); - } else { - $scopes[] = $val['scope']; - } - } else { - $scopes[] = 'https://www.googleapis.com/auth/' . $key; - } - unset($val['discoveryURI']); - unset($val['scope']); - $service = array_merge($service, $val); - } - } - $service['scope'] = implode(' ', $scopes); - return $service; - } - - /** - * Set the OAuth 2.0 access token using the string that resulted from calling authenticate() - * or Yoast_Google_Client#getAccessToken(). - * @param string $accessToken JSON encoded string containing in the following format: - * {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer", - * "expires_in":3600, "id_token":"TOKEN", "created":1320790426} - */ - public function setAccessToken($accessToken) { - if ($accessToken == null || 'null' == $accessToken) { - $accessToken = null; - } - self::$auth->setAccessToken($accessToken); - } - - /** - * Set the type of Auth class the client should use. - * @param string $authClassName - */ - public function setAuthClass($authClassName) { - self::$auth = new $authClassName(); - } - - /** - * Construct the OAuth 2.0 authorization request URI. - * @return string - */ - public function createAuthUrl() { - $service = $this->prepareService(); - return self::$auth->createAuthUrl($service['scope']); - } - - /** - * Get the OAuth 2.0 access token. - * @return string $accessToken JSON encoded string in the following format: - * {"access_token":"TOKEN", "refresh_token":"TOKEN", "token_type":"Bearer", - * "expires_in":3600,"id_token":"TOKEN", "created":1320790426} - */ - public function getAccessToken() { - $token = self::$auth->getAccessToken(); - return (null == $token || 'null' == $token) ? null : $token; - } - - /** - * Returns if the access_token is expired. - * @return bool Returns True if the access_token is expired. - */ - public function isAccessTokenExpired() { - return self::$auth->isAccessTokenExpired(); - } - - /** - * Set the developer key to use, these are obtained through the API Console. - * @see http://code.google.com/apis/console-help/#generatingdevkeys - * @param string $developerKey - */ - public function setDeveloperKey($developerKey) { - self::$auth->setDeveloperKey($developerKey); - } - - /** - * Set OAuth 2.0 "state" parameter to achieve per-request customization. - * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.1.2.2 - * @param string $state - */ - public function setState($state) { - self::$auth->setState($state); - } - - /** - * @param string $accessType Possible values for access_type include: - * {@code "offline"} to request offline access from the user. (This is the default value) - * {@code "online"} to request online access from the user. - */ - public function setAccessType($accessType) { - self::$auth->setAccessType($accessType); - } - - /** - * @param string $approvalPrompt Possible values for approval_prompt include: - * {@code "force"} to force the approval UI to appear. (This is the default value) - * {@code "auto"} to request auto-approval when possible. - */ - public function setApprovalPrompt($approvalPrompt) { - self::$auth->setApprovalPrompt($approvalPrompt); - } - - /** - * Set the application name, this is included in the User-Agent HTTP header. - * @param string $applicationName - */ - public function setApplicationName($applicationName) { - global $apiConfig; - $apiConfig['application_name'] = $applicationName; - } - - /** - * Set the OAuth 2.0 Client ID. - * @param string $clientId - */ - public function setClientId($clientId) { - global $apiConfig; - $apiConfig['oauth2_client_id'] = $clientId; - self::$auth->clientId = $clientId; - } - - /** - * Get the OAuth 2.0 Client ID. - */ - public function getClientId() { - return self::$auth->clientId; - } - - /** - * Set the OAuth 2.0 Client Secret. - * @param string $clientSecret - */ - public function setClientSecret($clientSecret) { - global $apiConfig; - $apiConfig['oauth2_client_secret'] = $clientSecret; - self::$auth->clientSecret = $clientSecret; - } - - /** - * Get the OAuth 2.0 Client Secret. - */ - public function getClientSecret() { - return self::$auth->clientSecret; - } - - /** - * Set the OAuth 2.0 Redirect URI. - * @param string $redirectUri - */ - public function setRedirectUri($redirectUri) { - global $apiConfig; - $apiConfig['oauth2_redirect_uri'] = $redirectUri; - self::$auth->redirectUri = $redirectUri; - } - - /** - * Get the OAuth 2.0 Redirect URI. - */ - public function getRedirectUri() { - return self::$auth->redirectUri; - } - - /** - * Fetches a fresh OAuth 2.0 access token with the given refresh token. - * @param string $refreshToken - * @return void - */ - public function refreshToken($refreshToken) { - self::$auth->refreshToken($refreshToken); - } - - /** - * Revoke an OAuth2 access token or refresh token. This method will revoke the current access - * token, if a token isn't provided. - * @throws Yoast_Google_AuthException - * @param string|null $token The token (access token or a refresh token) that should be revoked. - * @return boolean Returns True if the revocation was successful, otherwise False. - */ - public function revokeToken($token = null) { - self::$auth->revokeToken($token); - } - - /** - * Verify an id_token. This method will verify the current id_token, if one - * isn't provided. - * @throws Yoast_Google_AuthException - * @param string|null $token The token (id_token) that should be verified. - * @return Yoast_Google_LoginTicket Returns an apiLoginTicket if the verification was - * successful. - */ - public function verifyIdToken($token = null) { - return self::$auth->verifyIdToken($token); - } - - /** - * @param Yoast_Google_AssertionCredentials $creds - * @return void - */ - public function setAssertionCredentials(Yoast_Google_AssertionCredentials $creds) { - self::$auth->setAssertionCredentials($creds); - } - - /** - * This function allows you to overrule the automatically generated scopes, - * so that you can ask for more or less permission in the auth flow - * Set this before you call authenticate() though! - * @param array $scopes, ie: array('https://www.googleapis.com/auth/plus.me', 'https://www.googleapis.com/auth/moderator') - */ - public function setScopes($scopes) { - $this->scopes = is_string($scopes) ? explode(" ", $scopes) : $scopes; - } - - /** - * Returns the list of scopes set on the client - * @return array the list of scopes - * - */ - public function getScopes() { - return $this->scopes; - } - - /** - * If 'plus.login' is included in the list of requested scopes, you can use - * this method to define types of app activities that your app will write. - * You can find a list of available types here: - * @link https://developers.google.com/+/api/moment-types - * - * @param array $requestVisibleActions Array of app activity types - */ - public function setRequestVisibleActions($requestVisibleActions) { - self::$auth->requestVisibleActions = - join(" ", $requestVisibleActions); - } - - /** - * Declare if objects should be returned by the api service classes. - * - * @param boolean $useObjects True if objects should be returned by the service classes. - * False if associative arrays should be returned (default behavior). - * @experimental - */ - public function setUseObjects($useObjects) { - global $apiConfig; - $apiConfig['use_objects'] = $useObjects; - } - - /** - * Declare if objects should be returned by the api service classes. - * - * @param boolean $useBatch True if the experimental batch support should - * be enabled. Defaults to False. - * @experimental - */ - public function setUseBatch($useBatch) { - self::$useBatch = $useBatch; - } - - /** - * @static - * @return Yoast_Google_Auth the implementation of apiAuth. - */ - public static function getAuth() { - return Yoast_Google_Client::$auth; - } - - /** - * @static - * @return Yoast_Google_IO the implementation of apiIo. - */ - public static function getIo() { - return Yoast_Google_Client::$io; - } - - /** - * @return Yoast_Google_Cache the implementation of apiCache. - */ - public function getCache() { - return Yoast_Google_Client::$cache; - } -} - -// Exceptions that the Google PHP API Library can throw -class Yoast_Google_Exception extends Exception {} -class Yoast_Google_AuthException extends Yoast_Google_Exception {} -class Yoast_Google_CacheException extends Yoast_Google_Exception {} -class Yoast_Google_IOException extends Yoast_Google_Exception {} -class Yoast_Google_ServiceException extends Yoast_Google_Exception { - /** - * Optional list of errors returned in a JSON body of an HTTP error response. - */ - protected $errors = array(); - - /** - * Override default constructor to add ability to set $errors. - * - * @param string $message - * @param int $code - * @param Exception|null $previous - * @param [{string, string}] errors List of errors returned in an HTTP - * response. Defaults to []. - */ - public function __construct($message, $code = 0, Exception $previous = null, - $errors = array()) { - if(version_compare(PHP_VERSION, '5.3.0') >= 0) { - parent::__construct($message, $code, $previous); - } else { - parent::__construct($message, $code); - } - - $this->errors = $errors; - } - - /** - * An example of the possible errors returned. - * - * { - * "domain": "global", - * "reason": "authError", - * "message": "Invalid Credentials", - * "locationType": "header", - * "location": "Authorization", - * } - * - * @return [{string, string}] List of errors return in an HTTP response or []. - */ - public function getErrors() { - return $this->errors; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_AssertionCredentials.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_AssertionCredentials.php deleted file mode 100644 index 0ddac241..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_AssertionCredentials.php +++ /dev/null @@ -1,103 +0,0 @@ - - */ -class Yoast_Google_AssertionCredentials { - const MAX_TOKEN_LIFETIME_SECS = 3600; - - public $serviceAccountName; - public $scopes; - public $privateKey; - public $privateKeyPassword; - public $assertionType; - public $sub; - /** - * @deprecated - * @link http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06 - */ - public $prn; - - /** - * @param $serviceAccountName - * @param $scopes array List of scopes - * @param $privateKey - * @param string $privateKeyPassword - * @param string $assertionType - * @param bool|string $sub The email address of the user for which the - * application is requesting delegated access. - */ - public function __construct( - $serviceAccountName, - $scopes, - $privateKey, - $privateKeyPassword = 'notasecret', - $assertionType = 'http://oauth.net/grant_type/jwt/1.0/bearer', - $sub = false) { - $this->serviceAccountName = $serviceAccountName; - $this->scopes = is_string($scopes) ? $scopes : implode(' ', $scopes); - $this->privateKey = $privateKey; - $this->privateKeyPassword = $privateKeyPassword; - $this->assertionType = $assertionType; - $this->sub = $sub; - $this->prn = $sub; - } - - public function generateAssertion() { - $now = time(); - - $jwtParams = array( - 'aud' => Yoast_Google_OAuth2::OAUTH2_TOKEN_URI, - 'scope' => $this->scopes, - 'iat' => $now, - 'exp' => $now + self::MAX_TOKEN_LIFETIME_SECS, - 'iss' => $this->serviceAccountName, - ); - - if ($this->sub !== false) { - $jwtParams['sub'] = $this->sub; - } else if ($this->prn !== false) { - $jwtParams['prn'] = $this->prn; - } - - return $this->makeSignedJwt($jwtParams); - } - - /** - * Creates a signed JWT. - * @param array $payload - * @return string The signed JWT. - */ - private function makeSignedJwt($payload) { - $header = array('typ' => 'JWT', 'alg' => 'RS256'); - - $segments = array( - Yoast_Google_Utils::urlSafeB64Encode(json_encode($header)), - Yoast_Google_Utils::urlSafeB64Encode(json_encode($payload)) - ); - - $signingInput = implode('.', $segments); - $signer = new Yoast_Google_P12Signer($this->privateKey, $this->privateKeyPassword); - $signature = $signer->sign($signingInput); - $segments[] = Yoast_Google_Utils::urlSafeB64Encode($signature); - - return implode(".", $segments); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_Auth.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_Auth.php deleted file mode 100644 index 418efcf7..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_Auth.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - */ -abstract class Yoast_Google_Auth { - abstract public function authenticate($service); - abstract public function sign(Yoast_Google_HttpRequest $request); - abstract public function createAuthUrl($scope); - - abstract public function getAccessToken(); - abstract public function setAccessToken($accessToken); - abstract public function setDeveloperKey($developerKey); - abstract public function refreshToken($refreshToken); - abstract public function revokeToken(); -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_AuthNone.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_AuthNone.php deleted file mode 100644 index 389b4ac7..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_AuthNone.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @author Chirag Shah - */ -class Yoast_Google_AuthNone extends Yoast_Google_Auth { - public $key = null; - - public function __construct() { - global $apiConfig; - if (!empty($apiConfig['developer_key'])) { - $this->setDeveloperKey($apiConfig['developer_key']); - } - } - - public function setDeveloperKey($key) {$this->key = $key;} - public function authenticate($service) {/*noop*/} - public function setAccessToken($accessToken) {/* noop*/} - public function getAccessToken() {return null;} - public function createAuthUrl($scope) {return null;} - public function refreshToken($refreshToken) {/* noop*/} - public function revokeToken() {/* noop*/} - - public function sign(Yoast_Google_HttpRequest $request) { - if ($this->key) { - $request->setUrl($request->getUrl() . ((strpos($request->getUrl(), '?') === false) ? '?' : '&') - . 'key='.urlencode($this->key)); - } - return $request; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_LoginTicket.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_LoginTicket.php deleted file mode 100644 index 52e04d98..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_LoginTicket.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ -class Yoast_Google_LoginTicket { - const USER_ATTR = "id"; - - // Information from id token envelope. - private $envelope; - - // Information from id token payload. - private $payload; - - /** - * Creates a user based on the supplied token. - * - * @param string $envelope Header from a verified authentication token. - * @param string $payload Information from a verified authentication token. - */ - public function __construct($envelope, $payload) { - $this->envelope = $envelope; - $this->payload = $payload; - } - - /** - * Returns the numeric identifier for the user. - * @throws Yoast_Google_AuthException - * @return - */ - public function getUserId() { - if (array_key_exists(self::USER_ATTR, $this->payload)) { - return $this->payload[self::USER_ATTR]; - } - throw new Yoast_Google_AuthException("No user_id in token"); - } - - /** - * Returns attributes from the login ticket. This can contain - * various information about the user session. - * @return array - */ - public function getAttributes() { - return array("envelope" => $this->envelope, "payload" => $this->payload); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_OAuth2.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_OAuth2.php deleted file mode 100644 index 73a44ca0..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_OAuth2.php +++ /dev/null @@ -1,451 +0,0 @@ - - * @author Chirag Shah - * - */ -class Yoast_Google_OAuth2 extends Yoast_Google_Auth { - public $clientId; - public $clientSecret; - public $developerKey; - public $token; - public $redirectUri; - public $state; - public $accessType = 'offline'; - public $approvalPrompt = 'force'; - public $requestVisibleActions; - - /** @var Yoast_Google_AssertionCredentials $assertionCredentials */ - public $assertionCredentials; - - const OAUTH2_REVOKE_URI = 'https://accounts.google.com/o/oauth2/revoke'; - const OAUTH2_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token'; - const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth'; - const OAUTH2_FEDERATED_SIGNON_CERTS_URL = 'https://www.googleapis.com/oauth2/v1/certs'; - const CLOCK_SKEW_SECS = 300; // five minutes in seconds - const AUTH_TOKEN_LIFETIME_SECS = 300; // five minutes in seconds - const MAX_TOKEN_LIFETIME_SECS = 86400; // one day in seconds - - /** - * Instantiates the class, but does not initiate the login flow, leaving it - * to the discretion of the caller (which is done by calling authenticate()). - */ - public function __construct() { - global $apiConfig; - - if (! empty($apiConfig['developer_key'])) { - $this->developerKey = $apiConfig['developer_key']; - } - - if (! empty($apiConfig['oauth2_client_id'])) { - $this->clientId = $apiConfig['oauth2_client_id']; - } - - if (! empty($apiConfig['oauth2_client_secret'])) { - $this->clientSecret = $apiConfig['oauth2_client_secret']; - } - - if (! empty($apiConfig['oauth2_redirect_uri'])) { - $this->redirectUri = $apiConfig['oauth2_redirect_uri']; - } - - if (! empty($apiConfig['oauth2_access_type'])) { - $this->accessType = $apiConfig['oauth2_access_type']; - } - - if (! empty($apiConfig['oauth2_approval_prompt'])) { - $this->approvalPrompt = $apiConfig['oauth2_approval_prompt']; - } - - } - - /** - * @param $service - * @param string|null $code - * @throws Yoast_Google_AuthException - * @return string - */ - public function authenticate($service, $code = null) { - if (!$code && isset($_GET['code'])) { - $code = $_GET['code']; - } - - - if ($code) { - // We got here from the redirect from a successful authorization grant, fetch the access token - $request = Yoast_Google_Client::$io->makeRequest(new Yoast_Google_HttpRequest(self::OAUTH2_TOKEN_URI, 'POST', array(), array( - 'code' => $code, - 'grant_type' => 'authorization_code', - 'redirect_uri' => $this->redirectUri, - 'client_id' => $this->clientId, - 'client_secret' => $this->clientSecret - ))); - - - if ($request->getResponseHttpCode() == 200) { - $this->setAccessToken($request->getResponseBody()); - $this->token['created'] = time(); - return $this->getAccessToken(); - } else { - $response = $request->getResponseBody(); - $decodedResponse = json_decode($response, true); - if ($decodedResponse != null && $decodedResponse['error']) { - $response = $decodedResponse['error']; - } - throw new Yoast_Google_AuthException("Error fetching OAuth2 access token, message: '$response'", $request->getResponseHttpCode()); - } - } - - $authUrl = $this->createAuthUrl($service['scope']); - header('Location: ' . $authUrl); - return true; - } - - /** - * Create a URL to obtain user authorization. - * The authorization endpoint allows the user to first - * authenticate, and then grant/deny the access request. - * @param string $scope The scope is expressed as a list of space-delimited strings. - * @return string - */ - public function createAuthUrl($scope) { - $params = array( - 'response_type=code', - 'redirect_uri=' . urlencode($this->redirectUri), - 'client_id=' . urlencode($this->clientId), - 'scope=' . urlencode($scope), - 'access_type=' . urlencode($this->accessType), - 'approval_prompt=' . urlencode($this->approvalPrompt), - ); - - // if the list of scopes contains plus.login, add request_visible_actions - // to auth URL - if(strpos($scope, 'plus.login') && count($this->requestVisibleActions) > 0) { - $params[] = 'request_visible_actions=' . - urlencode($this->requestVisibleActions); - } - - if (isset($this->state)) { - $params[] = 'state=' . urlencode($this->state); - } - $params = implode('&', $params); - return self::OAUTH2_AUTH_URL . "?$params"; - } - - /** - * @param string $token - * @throws Yoast_Google_AuthException - */ - public function setAccessToken($token) { - $token = json_decode($token, true); - if ($token == null) { - throw new Yoast_Google_AuthException('Could not json decode the token'); - } - if (! isset($token['access_token'])) { - throw new Yoast_Google_AuthException("Invalid token format"); - } - $this->token = $token; - } - - public function getAccessToken() { - return json_encode($this->token); - } - - public function setDeveloperKey($developerKey) { - $this->developerKey = $developerKey; - } - - public function setState($state) { - $this->state = $state; - } - - public function setAccessType($accessType) { - $this->accessType = $accessType; - } - - public function setApprovalPrompt($approvalPrompt) { - $this->approvalPrompt = $approvalPrompt; - } - - public function setAssertionCredentials(Yoast_Google_AssertionCredentials $creds) { - $this->assertionCredentials = $creds; - } - - /** - * Include an accessToken in a given apiHttpRequest. - * @param Yoast_Google_HttpRequest $request - * @return Yoast_Google_HttpRequest - * @throws Yoast_Google_AuthException - */ - public function sign(Yoast_Google_HttpRequest $request) { - // add the developer key to the request before signing it - if ($this->developerKey) { - $requestUrl = $request->getUrl(); - $requestUrl .= (strpos($request->getUrl(), '?') === false) ? '?' : '&'; - $requestUrl .= 'key=' . urlencode($this->developerKey); - $request->setUrl($requestUrl); - } - - // Cannot sign the request without an OAuth access token. - if (null == $this->token && null == $this->assertionCredentials) { - return $request; - } - - // Check if the token is set to expire in the next 30 seconds - // (or has already expired). - if ($this->isAccessTokenExpired()) { - if ($this->assertionCredentials) { - $this->refreshTokenWithAssertion(); - } else { - if (! array_key_exists('refresh_token', $this->token)) { - throw new Yoast_Google_AuthException("The OAuth 2.0 access token has expired, " - . "and a refresh token is not available. Refresh tokens are not " - . "returned for responses that were auto-approved."); - } - $this->refreshToken($this->token['refresh_token']); - } - } - - // Add the OAuth2 header to the request - $request->setRequestHeaders( - array('Authorization' => 'Bearer ' . $this->token['access_token']) - ); - - return $request; - } - - /** - * Fetches a fresh access token with the given refresh token. - * @param string $refreshToken - * @return void - */ - public function refreshToken($refreshToken) { - $this->refreshTokenRequest(array( - 'client_id' => $this->clientId, - 'client_secret' => $this->clientSecret, - 'refresh_token' => $refreshToken, - 'grant_type' => 'refresh_token' - )); - } - - /** - * Fetches a fresh access token with a given assertion token. - * @param Yoast_Google_AssertionCredentials $assertionCredentials optional. - * @return void - */ - public function refreshTokenWithAssertion($assertionCredentials = null) { - if (!$assertionCredentials) { - $assertionCredentials = $this->assertionCredentials; - } - - $this->refreshTokenRequest(array( - 'grant_type' => 'assertion', - 'assertion_type' => $assertionCredentials->assertionType, - 'assertion' => $assertionCredentials->generateAssertion(), - )); - } - - private function refreshTokenRequest($params) { - $http = new Yoast_Google_HttpRequest(self::OAUTH2_TOKEN_URI, 'POST', array(), $params); - $request = Yoast_Google_Client::$io->makeRequest($http); - - $code = $request->getResponseHttpCode(); - $body = $request->getResponseBody(); - if (200 == $code) { - $token = json_decode($body, true); - if ($token == null) { - throw new Yoast_Google_AuthException("Could not json decode the access token"); - } - - if (! isset($token['access_token']) || ! isset($token['expires_in'])) { - throw new Yoast_Google_AuthException("Invalid token format"); - } - - $this->token['access_token'] = $token['access_token']; - $this->token['expires_in'] = $token['expires_in']; - $this->token['created'] = time(); - } else { - throw new Yoast_Google_AuthException("Error refreshing the OAuth2 token, message: '$body'", $code); - } - } - - /** - * Revoke an OAuth2 access token or refresh token. This method will revoke the current access - * token, if a token isn't provided. - * @throws Yoast_Google_AuthException - * @param string|null $token The token (access token or a refresh token) that should be revoked. - * @return boolean Returns True if the revocation was successful, otherwise False. - */ - public function revokeToken($token = null) { - if (!$token) { - $token = $this->token['access_token']; - } - $request = new Yoast_Google_HttpRequest(self::OAUTH2_REVOKE_URI, 'POST', array(), "token=$token"); - $response = Yoast_Google_Client::$io->makeRequest($request); - $code = $response->getResponseHttpCode(); - if ($code == 200) { - $this->token = null; - return true; - } - - return false; - } - - /** - * Returns if the access_token is expired. - * @return bool Returns True if the access_token is expired. - */ - public function isAccessTokenExpired() { - if (null == $this->token) { - return true; - } - - // If the token is set to expire in the next 30 seconds. - $expired = ($this->token['created'] - + ($this->token['expires_in'] - 30)) < time(); - - return $expired; - } - - // Gets federated sign-on certificates to use for verifying identity tokens. - // Returns certs as array structure, where keys are key ids, and values - // are PEM encoded certificates. - private function getFederatedSignOnCerts() { - // This relies on makeRequest caching certificate responses. - $request = Yoast_Google_Client::$io->makeRequest(new Yoast_Google_HttpRequest( - self::OAUTH2_FEDERATED_SIGNON_CERTS_URL)); - if ($request->getResponseHttpCode() == 200) { - $certs = json_decode($request->getResponseBody(), true); - if ($certs) { - return $certs; - } - } - throw new Yoast_Google_AuthException( - "Failed to retrieve verification certificates: '" . - $request->getResponseBody() . "'.", - $request->getResponseHttpCode()); - } - - /** - * Verifies an id token and returns the authenticated apiLoginTicket. - * Throws an exception if the id token is not valid. - * The audience parameter can be used to control which id tokens are - * accepted. By default, the id token must have been issued to this OAuth2 client. - * - * @param $id_token - * @param $audience - * @return Yoast_Google_LoginTicket - */ - public function verifyIdToken($id_token = null, $audience = null) { - if (!$id_token) { - $id_token = $this->token['id_token']; - } - - $certs = $this->getFederatedSignonCerts(); - if (!$audience) { - $audience = $this->clientId; - } - return $this->verifySignedJwtWithCerts($id_token, $certs, $audience); - } - - // Verifies the id token, returns the verified token contents. - // Visible for testing. - function verifySignedJwtWithCerts($jwt, $certs, $required_audience) { - $segments = explode(".", $jwt); - if (count($segments) != 3) { - throw new Yoast_Google_AuthException("Wrong number of segments in token: $jwt"); - } - $signed = $segments[0] . "." . $segments[1]; - $signature = Yoast_Google_Utils::urlSafeB64Decode($segments[2]); - - // Parse envelope. - $envelope = json_decode(Yoast_Google_Utils::urlSafeB64Decode($segments[0]), true); - if (!$envelope) { - throw new Yoast_Google_AuthException("Can't parse token envelope: " . $segments[0]); - } - - // Parse token - $json_body = Yoast_Google_Utils::urlSafeB64Decode($segments[1]); - $payload = json_decode($json_body, true); - if (!$payload) { - throw new Yoast_Google_AuthException("Can't parse token payload: " . $segments[1]); - } - - // Check signature - $verified = false; - foreach ($certs as $keyName => $pem) { - $public_key = new Yoast_Google_PemVerifier($pem); - if ($public_key->verify($signed, $signature)) { - $verified = true; - break; - } - } - - if (!$verified) { - throw new Yoast_Google_AuthException("Invalid token signature: $jwt"); - } - - // Check issued-at timestamp - $iat = 0; - if (array_key_exists("iat", $payload)) { - $iat = $payload["iat"]; - } - if (!$iat) { - throw new Yoast_Google_AuthException("No issue time in token: $json_body"); - } - $earliest = $iat - self::CLOCK_SKEW_SECS; - - // Check expiration timestamp - $now = time(); - $exp = 0; - if (array_key_exists("exp", $payload)) { - $exp = $payload["exp"]; - } - if (!$exp) { - throw new Yoast_Google_AuthException("No expiration time in token: $json_body"); - } - if ($exp >= $now + self::MAX_TOKEN_LIFETIME_SECS) { - throw new Yoast_Google_AuthException( - "Expiration time too far in future: $json_body"); - } - - $latest = $exp + self::CLOCK_SKEW_SECS; - if ($now < $earliest) { - throw new Yoast_Google_AuthException( - "Token used too early, $now < $earliest: $json_body"); - } - if ($now > $latest) { - throw new Yoast_Google_AuthException( - "Token used too late, $now > $latest: $json_body"); - } - - // TODO(beaton): check issuer field? - - // Check audience - $aud = $payload["aud"]; - if ($aud != $required_audience) { - throw new Yoast_Google_AuthException("Wrong recipient, $aud != $required_audience: $json_body"); - } - - // All good. - return new Yoast_Google_LoginTicket($envelope, $payload); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_P12Signer.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_P12Signer.php deleted file mode 100644 index dcec0241..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_P12Signer.php +++ /dev/null @@ -1,70 +0,0 @@ - - */ -class Yoast_Google_P12Signer extends Yoast_Google_Signer { - // OpenSSL private key resource - private $privateKey; - - // Creates a new signer from a .p12 file. - function __construct($p12, $password) { - if (!function_exists('openssl_x509_read')) { - throw new Exception( - 'The Google PHP API library needs the openssl PHP extension'); - } - - // This throws on error - $certs = array(); - if (!openssl_pkcs12_read($p12, $certs, $password)) { - throw new Yoast_Google_AuthException("Unable to parse the p12 file. " . - "Is this a .p12 file? Is the password correct? OpenSSL error: " . - openssl_error_string()); - } - // TODO(beaton): is this part of the contract for the openssl_pkcs12_read - // method? What happens if there are multiple private keys? Do we care? - if (!array_key_exists("pkey", $certs) || !$certs["pkey"]) { - throw new Yoast_Google_AuthException("No private key found in p12 file."); - } - $this->privateKey = openssl_pkey_get_private($certs["pkey"]); - if (!$this->privateKey) { - throw new Yoast_Google_AuthException("Unable to load private key in "); - } - } - - function __destruct() { - if ($this->privateKey) { - openssl_pkey_free($this->privateKey); - } - } - - function sign($data) { - if(version_compare(PHP_VERSION, '5.3.0') < 0) { - throw new Yoast_Google_AuthException( - "PHP 5.3.0 or higher is required to use service accounts."); - } - if (!openssl_sign($data, $signature, $this->privateKey, "sha256")) { - throw new Yoast_Google_AuthException("Unable to sign data"); - } - return $signature; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_PemVerifier.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_PemVerifier.php deleted file mode 100644 index f22d4b4f..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_PemVerifier.php +++ /dev/null @@ -1,66 +0,0 @@ - - */ -class Yoast_Google_PemVerifier extends Yoast_Google_Verifier { - private $publicKey; - - /** - * Constructs a verifier from the supplied PEM-encoded certificate. - * - * $pem: a PEM encoded certificate (not a file). - * @param $pem - * @throws Yoast_Google_AuthException - * @throws Yoast_Google_Exception - */ - function __construct($pem) { - if (!function_exists('openssl_x509_read')) { - throw new Yoast_Google_Exception('Google API PHP client needs the openssl PHP extension'); - } - $this->publicKey = openssl_x509_read($pem); - if (!$this->publicKey) { - throw new Yoast_Google_AuthException("Unable to parse PEM: $pem"); - } - } - - function __destruct() { - if ($this->publicKey) { - openssl_x509_free($this->publicKey); - } - } - - /** - * Verifies the signature on data. - * - * Returns true if the signature is valid, false otherwise. - * @param $data - * @param $signature - * @throws Yoast_Google_AuthException - * @return bool - */ - function verify($data, $signature) { - $status = openssl_verify($data, $signature, $this->publicKey, "sha256"); - if ($status === -1) { - throw new Yoast_Google_AuthException('Signature verification error: ' . openssl_error_string()); - } - return $status === 1; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_Signer.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_Signer.php deleted file mode 100644 index 5feb9836..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_Signer.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ -abstract class Yoast_Google_Signer { - /** - * Signs data, returns the signature as binary data. - */ - abstract public function sign($data); -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_Verifier.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_Verifier.php deleted file mode 100644 index 0a55a5aa..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/auth/Google_Verifier.php +++ /dev/null @@ -1,29 +0,0 @@ - - */ -abstract class Yoast_Google_Verifier { - /** - * Checks a signature, returns true if the signature is correct, - * false otherwise. - */ - abstract public function verify($data, $signature); -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/cache/Google_Cache.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/cache/Google_Cache.php deleted file mode 100644 index b5a93ef4..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/cache/Google_Cache.php +++ /dev/null @@ -1,52 +0,0 @@ - - */ -abstract class Yoast_Google_Cache { - - /** - * Retrieves the data for the given key, or false if they - * key is unknown or expired - * - * @param String $key The key who's data to retrieve - * @param boolean|int $expiration Expiration time in seconds - * - */ - abstract function get($key, $expiration = false); - - /** - * Store the key => $value set. The $value is serialized - * by this function so can be of any type - * - * @param string $key Key of the data - * @param string $value data - */ - abstract function set($key, $value); - - /** - * Removes the key/data pair for the given $key - * - * @param String $key - */ - abstract function delete($key); -} - - diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/cache/Google_WPCache.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/cache/Google_WPCache.php deleted file mode 100644 index a8a4a228..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/cache/Google_WPCache.php +++ /dev/null @@ -1,53 +0,0 @@ - $value set. The $value is serialized - * by this function so can be of any type - * - * @param string $key Key of the data - * @param string $value data - */ - public function set($key, $value) { - wp_cache_set( $key, $value ) ; - } - - /** - * Removes the key/data pair for the given $key - * - * @param String $key - */ - public function delete($key) { - wp_cache_delete( $key ); - } - - -} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/config.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/config.php deleted file mode 100644 index a8757fee..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/config.php +++ /dev/null @@ -1,83 +0,0 @@ - false, - - // The application_name is included in the User-Agent HTTP header. - 'application_name' => '', - - // OAuth2 Settings, you can get these keys at https://code.google.com/apis/console - 'oauth2_client_id' => '', - 'oauth2_client_secret' => '', - 'oauth2_redirect_uri' => '', - - // The developer key, you get this at https://code.google.com/apis/console - 'developer_key' => '', - - // Site name to show in the Google's OAuth 1 authentication screen. - 'site_name' => 'www.example.org', - - // Which Authentication, Storage and HTTP IO classes to use. - 'authClass' => 'Yoast_Google_OAuth2', - 'ioClass' => 'Yoast_Google_WPIO', - 'cacheClass' => 'Yoast_Google_WPCache', - - // Don't change these unless you're working against a special development or testing environment. - 'basePath' => 'https://www.googleapis.com', - - // IO Class dependent configuration, you only have to configure the values - // for the class that was configured as the ioClass above - 'ioFileCache_directory' => - (function_exists('sys_get_temp_dir') ? - sys_get_temp_dir() . '/Google_Client' : - '/tmp/Google_Client'), - - // Definition of service specific values like scopes, oauth token URLs, etc - /* - 'services' => array( - 'analytics' => array('scope' => 'https://www.googleapis.com/auth/analytics.readonly'), - 'calendar' => array( - 'scope' => array( - "https://www.googleapis.com/auth/calendar", - "https://www.googleapis.com/auth/calendar.readonly", - ) - ), - 'books' => array('scope' => 'https://www.googleapis.com/auth/books'), - 'latitude' => array( - 'scope' => array( - 'https://www.googleapis.com/auth/latitude.all.best', - 'https://www.googleapis.com/auth/latitude.all.city', - ) - ), - 'moderator' => array('scope' => 'https://www.googleapis.com/auth/moderator'), - 'oauth2' => array( - 'scope' => array( - 'https://www.googleapis.com/auth/userinfo.profile', - 'https://www.googleapis.com/auth/userinfo.email', - ) - ), - 'plus' => array('scope' => 'https://www.googleapis.com/auth/plus.login'), - 'siteVerification' => array('scope' => 'https://www.googleapis.com/auth/siteverification'), - 'tasks' => array('scope' => 'https://www.googleapis.com/auth/tasks'), - 'urlshortener' => array('scope' => 'https://www.googleapis.com/auth/urlshortener') - ) - */ -); diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/external/URITemplateParser.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/external/URITemplateParser.php deleted file mode 100644 index 594adbb1..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/external/URITemplateParser.php +++ /dev/null @@ -1,209 +0,0 @@ -template = $template; - } - - public function expand($data) { - // Modification to make this a bit more performant (since gettype is very slow) - if (! is_array($data)) { - $data = (array)$data; - } - /* - // Original code, which uses a slow gettype() statement, kept in place for if the assumption that is_array always works here is incorrect - switch (gettype($data)) { - case "boolean": - case "integer": - case "double": - case "string": - case "object": - $data = (array)$data; - break; - } -*/ - - // Resolve template vars - preg_match_all('/\{([^\}]*)\}/', $this->template, $em); - - foreach ($em[1] as $i => $bare_expression) { - preg_match('/^([\+\;\?\/\.]{1})?(.*)$/', $bare_expression, $lm); - $exp = new StdClass(); - $exp->expression = $em[0][$i]; - $exp->operator = $lm[1]; - $exp->variable_list = $lm[2]; - $exp->varspecs = explode(',', $exp->variable_list); - $exp->vars = array(); - foreach ($exp->varspecs as $varspec) { - preg_match('/^([a-zA-Z0-9_]+)([\*\+]{1})?([\:\^][0-9-]+)?(\=[^,]+)?$/', $varspec, $vm); - $var = new StdClass(); - $var->name = $vm[1]; - $var->modifier = isset($vm[2]) && $vm[2] ? $vm[2] : null; - $var->modifier = isset($vm[3]) && $vm[3] ? $vm[3] : $var->modifier; - $var->default = isset($vm[4]) ? substr($vm[4], 1) : null; - $exp->vars[] = $var; - } - - // Add processing flags - $exp->reserved = false; - $exp->prefix = ''; - $exp->delimiter = ','; - switch ($exp->operator) { - case '+': - $exp->reserved = 'true'; - break; - case ';': - $exp->prefix = ';'; - $exp->delimiter = ';'; - break; - case '?': - $exp->prefix = '?'; - $exp->delimiter = '&'; - break; - case '/': - $exp->prefix = '/'; - $exp->delimiter = '/'; - break; - case '.': - $exp->prefix = '.'; - $exp->delimiter = '.'; - break; - } - $expressions[] = $exp; - } - - // Expansion - $this->expansion = $this->template; - - foreach ($expressions as $exp) { - $part = $exp->prefix; - $exp->one_var_defined = false; - foreach ($exp->vars as $var) { - $val = ''; - if ($exp->one_var_defined && isset($data[$var->name])) { - $part .= $exp->delimiter; - } - // Variable present - if (isset($data[$var->name])) { - $exp->one_var_defined = true; - $var->data = $data[$var->name]; - - $val = self::val_from_var($var, $exp); - - // Variable missing - } else { - if ($var->default) { - $exp->one_var_defined = true; - $val = $var->default; - } - } - $part .= $val; - } - if (! $exp->one_var_defined) $part = ''; - $this->expansion = str_replace($exp->expression, $part, $this->expansion); - } - - return $this->expansion; - } - - private function val_from_var($var, $exp) { - $val = ''; - if (is_array($var->data)) { - $i = 0; - if ($exp->operator == '?' && ! $var->modifier) { - $val .= $var->name . '='; - } - foreach ($var->data as $k => $v) { - $del = $var->modifier ? $exp->delimiter : ','; - $ek = rawurlencode($k); - $ev = rawurlencode($v); - - // Array - if ($k !== $i) { - if ($var->modifier == '+') { - $val .= $var->name . '.'; - } - if ($exp->operator == '?' && $var->modifier || $exp->operator == ';' && $var->modifier == '*' || $exp->operator == ';' && $var->modifier == '+') { - $val .= $ek . '='; - } else { - $val .= $ek . $del; - } - - // List - } else { - if ($var->modifier == '+') { - if ($exp->operator == ';' && $var->modifier == '*' || $exp->operator == ';' && $var->modifier == '+' || $exp->operator == '?' && $var->modifier == '+') { - $val .= $var->name . '='; - } else { - $val .= $var->name . '.'; - } - } - } - $val .= $ev . $del; - $i ++; - } - $val = trim($val, $del); - - // Strings, numbers, etc. - } else { - if ($exp->operator == '?') { - $val = $var->name . (isset($var->data) ? '=' : ''); - } else if ($exp->operator == ';') { - $val = $var->name . ($var->data ? '=' : ''); - } - $val .= rawurlencode($var->data); - if ($exp->operator == '+') { - $val = str_replace(self::$reserved_pct, self::$reserved, $val); - } - } - return $val; - } - - public function match($uri) {} - - public function __toString() { - return $this->template; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_CacheParser.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_CacheParser.php deleted file mode 100644 index 3437a08d..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_CacheParser.php +++ /dev/null @@ -1,173 +0,0 @@ - - */ -class Yoast_Google_CacheParser { - public static $CACHEABLE_HTTP_METHODS = array('GET', 'HEAD'); - public static $CACHEABLE_STATUS_CODES = array('200', '203', '300', '301'); - - private function __construct() {} - - /** - * Check if an HTTP request can be cached by a private local cache. - * - * @static - * @param Yoast_Google_HttpRequest $resp - * @return bool True if the request is cacheable. - * False if the request is uncacheable. - */ - public static function isRequestCacheable (Yoast_Google_HttpRequest $resp) { - $method = $resp->getRequestMethod(); - if (! in_array($method, self::$CACHEABLE_HTTP_METHODS)) { - return false; - } - - // Don't cache authorized requests/responses. - // [rfc2616-14.8] When a shared cache receives a request containing an - // Authorization field, it MUST NOT return the corresponding response - // as a reply to any other request... - if ($resp->getRequestHeader("authorization")) { - return false; - } - - return true; - } - - /** - * Check if an HTTP response can be cached by a private local cache. - * - * @static - * @param Yoast_Google_HttpRequest $resp - * @return bool True if the response is cacheable. - * False if the response is un-cacheable. - */ - public static function isResponseCacheable (Yoast_Google_HttpRequest $resp) { - // First, check if the HTTP request was cacheable before inspecting the - // HTTP response. - if (false == self::isRequestCacheable($resp)) { - return false; - } - - $code = $resp->getResponseHttpCode(); - if (! in_array($code, self::$CACHEABLE_STATUS_CODES)) { - return false; - } - - // The resource is uncacheable if the resource is already expired and - // the resource doesn't have an ETag for revalidation. - $etag = $resp->getResponseHeader("etag"); - if (self::isExpired($resp) && $etag == false) { - return false; - } - - // [rfc2616-14.9.2] If [no-store is] sent in a response, a cache MUST NOT - // store any part of either this response or the request that elicited it. - $cacheControl = $resp->getParsedCacheControl(); - if (isset($cacheControl['no-store'])) { - return false; - } - - // Pragma: no-cache is an http request directive, but is occasionally - // used as a response header incorrectly. - $pragma = $resp->getResponseHeader('pragma'); - if ($pragma == 'no-cache' || strpos($pragma, 'no-cache') !== false) { - return false; - } - - // [rfc2616-14.44] Vary: * is extremely difficult to cache. "It implies that - // a cache cannot determine from the request headers of a subsequent request - // whether this response is the appropriate representation." - // Given this, we deem responses with the Vary header as uncacheable. - $vary = $resp->getResponseHeader('vary'); - if ($vary) { - return false; - } - - return true; - } - - /** - * @static - * @param Yoast_Google_HttpRequest $resp - * @return bool True if the HTTP response is considered to be expired. - * False if it is considered to be fresh. - */ - public static function isExpired(Yoast_Google_HttpRequest $resp) { - // HTTP/1.1 clients and caches MUST treat other invalid date formats, - // especially including the value “0”, as in the past. - $parsedExpires = false; - $responseHeaders = $resp->getResponseHeaders(); - if (isset($responseHeaders['expires'])) { - $rawExpires = $responseHeaders['expires']; - // Check for a malformed expires header first. - if (empty($rawExpires) || (is_numeric($rawExpires) && $rawExpires <= 0)) { - return true; - } - - // See if we can parse the expires header. - $parsedExpires = strtotime($rawExpires); - if (false == $parsedExpires || $parsedExpires <= 0) { - return true; - } - } - - // Calculate the freshness of an http response. - $freshnessLifetime = false; - $cacheControl = $resp->getParsedCacheControl(); - if (isset($cacheControl['max-age'])) { - $freshnessLifetime = $cacheControl['max-age']; - } - - $rawDate = $resp->getResponseHeader('date'); - $parsedDate = strtotime($rawDate); - - if (empty($rawDate) || false == $parsedDate) { - $parsedDate = time(); - } - if (false == $freshnessLifetime && isset($responseHeaders['expires'])) { - $freshnessLifetime = $parsedExpires - $parsedDate; - } - - if (false == $freshnessLifetime) { - return true; - } - - // Calculate the age of an http response. - $age = max(0, time() - $parsedDate); - if (isset($responseHeaders['age'])) { - $age = max($age, strtotime($responseHeaders['age'])); - } - - return $freshnessLifetime <= $age; - } - - /** - * Determine if a cache entry should be revalidated with by the origin. - * - * @param Yoast_Google_HttpRequest $response - * @return bool True if the entry is expired, else return false. - */ - public static function mustRevalidate(Yoast_Google_HttpRequest $response) { - // [13.3] When a cache has a stale entry that it would like to use as a - // response to a client's request, it first has to check with the origin - // server to see if its cached entry is still usable. - return self::isExpired($response); - } -} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_CurlIO.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_CurlIO.php deleted file mode 100644 index 5904e758..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_CurlIO.php +++ /dev/null @@ -1,196 +0,0 @@ - - * @author Chirag Shah - */ - -class Yoast_Google_CurlIO extends Yoast_Google_IO { - private static $ENTITY_HTTP_METHODS = array("POST" => null, "PUT" => null); - private static $HOP_BY_HOP = array( - 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', - 'te', 'trailers', 'transfer-encoding', 'upgrade'); - - private $curlParams = array ( - CURLOPT_RETURNTRANSFER => true, - CURLOPT_FOLLOWLOCATION => 0, - CURLOPT_FAILONERROR => false, - CURLOPT_SSL_VERIFYPEER => true, - CURLOPT_HEADER => true, - CURLOPT_VERBOSE => false, - ); - - /** - * Check for cURL availability. - */ - public function __construct() { - if (! function_exists('curl_init')) { - throw new Exception( - 'Google CurlIO client requires the CURL PHP extension'); - } - } - - /** - * Perform an authenticated / signed apiHttpRequest. - * This function takes the apiHttpRequest, calls apiAuth->sign on it - * (which can modify the request in what ever way fits the auth mechanism) - * and then calls apiCurlIO::makeRequest on the signed request - * - * @param Yoast_Google_HttpRequest $request - * @return Yoast_Google_HttpRequest The resulting HTTP response including the - * responseHttpCode, responseHeaders and responseBody. - */ - public function authenticatedRequest(Yoast_Google_HttpRequest $request) { - $request = Yoast_Google_Client::$auth->sign($request); - return $this->makeRequest($request); - } - - /** - * Execute a apiHttpRequest - * - * @param Yoast_Google_HttpRequest $request the http request to be executed - * @return Yoast_Google_HttpRequest http request with the response http code, response - * headers and response body filled in - * @throws Yoast_Google_IOException on curl or IO error - */ - public function makeRequest(Yoast_Google_HttpRequest $request) { - // First, check to see if we have a valid cached version. - $cached = $this->getCachedRequest($request); - if ($cached !== false) { - if (!$this->checkMustRevaliadateCachedRequest($cached, $request)) { - return $cached; - } - } - - if (array_key_exists($request->getRequestMethod(), - self::$ENTITY_HTTP_METHODS)) { - $request = $this->processEntityRequest($request); - } - - $ch = curl_init(); - curl_setopt_array($ch, $this->curlParams); - curl_setopt($ch, CURLOPT_URL, $request->getUrl()); - if ($request->getPostBody()) { - curl_setopt($ch, CURLOPT_POSTFIELDS, $request->getPostBody()); - } - - $requestHeaders = $request->getRequestHeaders(); - if ($requestHeaders && is_array($requestHeaders)) { - $parsed = array(); - foreach ($requestHeaders as $k => $v) { - $parsed[] = "$k: $v"; - } - curl_setopt($ch, CURLOPT_HTTPHEADER, $parsed); - } - - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request->getRequestMethod()); - curl_setopt($ch, CURLOPT_USERAGENT, $request->getUserAgent()); - $respData = curl_exec($ch); - - // Retry if certificates are missing. - if (curl_errno($ch) == CURLE_SSL_CACERT) { - error_log('SSL certificate problem, verify that the CA cert is OK.' - . ' Retrying with the CA cert bundle from google-api-php-client.'); - curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacerts.pem'); - $respData = curl_exec($ch); - } - - $respHeaderSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); - $respHttpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); - $curlErrorNum = curl_errno($ch); - $curlError = curl_error($ch); - curl_close($ch); - if ($curlErrorNum != CURLE_OK) { - throw new Yoast_Google_IOException("HTTP Error: ($respHttpCode) $curlError"); - } - - // Parse out the raw response into usable bits - list($responseHeaders, $responseBody) = - self::parseHttpResponse($respData, $respHeaderSize); - - if ($respHttpCode == 304 && $cached) { - // If the server responded NOT_MODIFIED, return the cached request. - $this->updateCachedRequest($cached, $responseHeaders); - return $cached; - } - - // Fill in the apiHttpRequest with the response values - $request->setResponseHttpCode($respHttpCode); - $request->setResponseHeaders($responseHeaders); - $request->setResponseBody($responseBody); - // Store the request in cache (the function checks to see if the request - // can actually be cached) - $this->setCachedRequest($request); - // And finally return it - return $request; - } - - /** - * Set options that update cURL's default behavior. - * The list of accepted options are: - * {@link http://php.net/manual/en/function.curl-setopt.php] - * - * @param array $optCurlParams Multiple options used by a cURL session. - */ - public function setOptions($optCurlParams) { - foreach ($optCurlParams as $key => $val) { - $this->curlParams[$key] = $val; - } - } - - /** - * @param $respData - * @param $headerSize - * @return array - */ - public static function parseHttpResponse($respData, $headerSize) { - if (stripos($respData, parent::CONNECTION_ESTABLISHED) !== false) { - $respData = str_ireplace(parent::CONNECTION_ESTABLISHED, '', $respData); - } - - if ($headerSize) { - $responseBody = substr($respData, $headerSize); - $responseHeaders = substr($respData, 0, $headerSize); - } else { - list($responseHeaders, $responseBody) = explode("\r\n\r\n", $respData, 2); - } - - $responseHeaders = self::parseResponseHeaders($responseHeaders); - return array($responseHeaders, $responseBody); - } - - public static function parseResponseHeaders($rawHeaders) { - $responseHeaders = array(); - - $responseHeaderLines = explode("\r\n", $rawHeaders); - foreach ($responseHeaderLines as $headerLine) { - if ($headerLine && strpos($headerLine, ':') !== false) { - list($header, $value) = explode(': ', $headerLine, 2); - $header = strtolower($header); - if (isset($responseHeaders[$header])) { - $responseHeaders[$header] .= "\n" . $value; - } else { - $responseHeaders[$header] = $value; - } - } - } - return $responseHeaders; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_HttpRequest.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_HttpRequest.php deleted file mode 100644 index 3c257dea..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_HttpRequest.php +++ /dev/null @@ -1,304 +0,0 @@ - - * @author Chirag Shah - * - */ -class Yoast_Google_HttpRequest { - const USER_AGENT_SUFFIX = "google-api-php-client/0.6.5"; - private $batchHeaders = array( - 'Content-Type' => 'application/http', - 'Content-Transfer-Encoding' => 'binary', - 'MIME-Version' => '1.0', - 'Content-Length' => '' - ); - - protected $url; - protected $requestMethod; - protected $requestHeaders; - protected $postBody; - protected $userAgent; - - protected $responseHttpCode; - protected $responseHeaders; - protected $responseBody; - - public $accessKey; - - public function __construct($url, $method = 'GET', $headers = array(), $postBody = null) { - $this->setUrl($url); - $this->setRequestMethod($method); - $this->setRequestHeaders($headers); - $this->setPostBody($postBody); - - global $apiConfig; - if (empty($apiConfig['application_name'])) { - $this->userAgent = self::USER_AGENT_SUFFIX; - } else { - $this->userAgent = $apiConfig['application_name'] . " " . self::USER_AGENT_SUFFIX; - } - } - - /** - * Misc function that returns the base url component of the $url - * used by the OAuth signing class to calculate the base string - * @return string The base url component of the $url. - * @see http://oauth.net/core/1.0a/#anchor13 - */ - public function getBaseUrl() { - if ($pos = strpos($this->url, '?')) { - return substr($this->url, 0, $pos); - } - return $this->url; - } - - /** - * Misc function that returns an array of the query parameters of the current - * url used by the OAuth signing class to calculate the signature - * @return array Query parameters in the query string. - */ - public function getQueryParams() { - if ($pos = strpos($this->url, '?')) { - $queryStr = substr($this->url, $pos + 1); - $params = array(); - parse_str($queryStr, $params); - return $params; - } - return array(); - } - - /** - * @return string HTTP Response Code. - */ - public function getResponseHttpCode() { - return (int) $this->responseHttpCode; - } - - /** - * @param int $responseHttpCode HTTP Response Code. - */ - public function setResponseHttpCode($responseHttpCode) { - $this->responseHttpCode = $responseHttpCode; - } - - /** - * @return $responseHeaders (array) HTTP Response Headers. - */ - public function getResponseHeaders() { - return $this->responseHeaders; - } - - /** - * @return string HTTP Response Body - */ - public function getResponseBody() { - return $this->responseBody; - } - - /** - * @param array $headers The HTTP response headers - * to be normalized. - */ - public function setResponseHeaders($headers) { - $headers = Yoast_Google_Utils::normalize($headers); - if ($this->responseHeaders) { - $headers = array_merge($this->responseHeaders, $headers); - } - - $this->responseHeaders = $headers; - } - - /** - * @param string $key - * @return array|boolean Returns the requested HTTP header or - * false if unavailable. - */ - public function getResponseHeader($key) { - return isset($this->responseHeaders[$key]) - ? $this->responseHeaders[$key] - : false; - } - - /** - * @param string $responseBody The HTTP response body. - */ - public function setResponseBody($responseBody) { - $this->responseBody = $responseBody; - } - - /** - * @return string $url The request URL. - */ - - public function getUrl() { - return $this->url; - } - - /** - * @return string $method HTTP Request Method. - */ - public function getRequestMethod() { - return $this->requestMethod; - } - - /** - * @return array $headers HTTP Request Headers. - */ - public function getRequestHeaders() { - return $this->requestHeaders; - } - - /** - * @param string $key - * @return array|boolean Returns the requested HTTP header or - * false if unavailable. - */ - public function getRequestHeader($key) { - return isset($this->requestHeaders[$key]) - ? $this->requestHeaders[$key] - : false; - } - - /** - * @return string $postBody HTTP Request Body. - */ - public function getPostBody() { - return $this->postBody; - } - - /** - * @param string $url the url to set - */ - public function setUrl($url) { - if (substr($url, 0, 4) == 'http') { - $this->url = $url; - } else { - // Force the path become relative. - if (substr($url, 0, 1) !== '/') { - $url = '/' . $url; - } - global $apiConfig; - $this->url = $apiConfig['basePath'] . $url; - } - } - - /** - * @param string $method Set he HTTP Method and normalize - * it to upper-case, as required by HTTP. - * - */ - public function setRequestMethod($method) { - $this->requestMethod = strtoupper($method); - } - - /** - * @param array $headers The HTTP request headers - * to be set and normalized. - */ - public function setRequestHeaders($headers) { - $headers = Yoast_Google_Utils::normalize($headers); - if ($this->requestHeaders) { - $headers = array_merge($this->requestHeaders, $headers); - } - $this->requestHeaders = $headers; - } - - /** - * @param string $postBody the postBody to set - */ - public function setPostBody($postBody) { - $this->postBody = $postBody; - } - - /** - * Set the User-Agent Header. - * @param string $userAgent The User-Agent. - */ - public function setUserAgent($userAgent) { - $this->userAgent = $userAgent; - } - - /** - * @return string The User-Agent. - */ - public function getUserAgent() { - return $this->userAgent; - } - - /** - * Returns a cache key depending on if this was an OAuth signed request - * in which case it will use the non-signed url and access key to make this - * cache key unique per authenticated user, else use the plain request url - * @return string The md5 hash of the request cache key. - */ - public function getCacheKey() { - $key = $this->getUrl(); - - if (isset($this->accessKey)) { - $key .= $this->accessKey; - } - - if (isset($this->requestHeaders['authorization'])) { - $key .= $this->requestHeaders['authorization']; - } - - return md5($key); - } - - public function getParsedCacheControl() { - $parsed = array(); - $rawCacheControl = $this->getResponseHeader('cache-control'); - if ($rawCacheControl) { - $rawCacheControl = str_replace(', ', '&', $rawCacheControl); - parse_str($rawCacheControl, $parsed); - } - - return $parsed; - } - - /** - * @param string $id - * @return string A string representation of the HTTP Request. - */ - public function toBatchString($id) { - $str = ''; - foreach($this->batchHeaders as $key => $val) { - $str .= $key . ': ' . $val . "\n"; - } - - $str .= "Content-ID: $id\n"; - $str .= "\n"; - - $path = parse_url($this->getUrl(), PHP_URL_PATH); - $str .= $this->getRequestMethod() . ' ' . $path . " HTTP/1.1\n"; - foreach($this->getRequestHeaders() as $key => $val) { - $str .= $key . ': ' . $val . "\n"; - } - - if ($this->getPostBody()) { - $str .= "\n"; - $str .= $this->getPostBody(); - } - - return $str; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_IO.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_IO.php deleted file mode 100644 index ee6698b0..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_IO.php +++ /dev/null @@ -1,156 +0,0 @@ - - */ -abstract class Yoast_Google_IO { - const CONNECTION_ESTABLISHED = "HTTP/1.0 200 Connection established\r\n\r\n"; - const FORM_URLENCODED = 'application/x-www-form-urlencoded'; - /** - * An utility function that first calls $this->auth->sign($request) and then executes makeRequest() - * on that signed request. Used for when a request should be authenticated - * @param Yoast_Google_HttpRequest $request - * @return Yoast_Google_HttpRequest $request - */ - abstract function authenticatedRequest(Yoast_Google_HttpRequest $request); - - /** - * Executes a apIHttpRequest and returns the resulting populated httpRequest - * @param Yoast_Google_HttpRequest $request - * @return Yoast_Google_HttpRequest $request - */ - abstract function makeRequest(Yoast_Google_HttpRequest $request); - - /** - * Set options that update the transport implementation's behavior. - * @param $options - */ - abstract function setOptions($options); - - /** - * @visible for testing. - * Cache the response to an HTTP request if it is cacheable. - * @param Yoast_Google_HttpRequest $request - * @return bool Returns true if the insertion was successful. - * Otherwise, return false. - */ - protected function setCachedRequest(Yoast_Google_HttpRequest $request) { - // Determine if the request is cacheable. - if (Yoast_Google_CacheParser::isResponseCacheable($request)) { - Yoast_Google_Client::$cache->set($request->getCacheKey(), $request); - return true; - } - - return false; - } - - /** - * @visible for testing. - * @param Yoast_Google_HttpRequest $request - * @return Yoast_Google_HttpRequest|bool Returns the cached object or - * false if the operation was unsuccessful. - */ - protected function getCachedRequest(Yoast_Google_HttpRequest $request) { - if (false == Yoast_Google_CacheParser::isRequestCacheable($request)) { - false; - } - - return Yoast_Google_Client::$cache->get($request->getCacheKey()); - } - - /** - * @visible for testing - * Process an http request that contains an enclosed entity. - * @param Yoast_Google_HttpRequest $request - * @return Yoast_Google_HttpRequest Processed request with the enclosed entity. - */ - protected function processEntityRequest(Yoast_Google_HttpRequest $request) { - $postBody = $request->getPostBody(); - $contentType = $request->getRequestHeader("content-type"); - - // Set the default content-type as application/x-www-form-urlencoded. - if (false == $contentType) { - $contentType = self::FORM_URLENCODED; - $request->setRequestHeaders(array('content-type' => $contentType)); - } - - // Force the payload to match the content-type asserted in the header. - if ($contentType == self::FORM_URLENCODED && is_array($postBody)) { - $postBody = http_build_query($postBody, '', '&'); - $request->setPostBody($postBody); - } - - // Make sure the content-length header is set. - if (!$postBody || is_string($postBody)) { - $postsLength = strlen($postBody); - $request->setRequestHeaders(array('content-length' => $postsLength)); - } - - return $request; - } - - /** - * Check if an already cached request must be revalidated, and if so update - * the request with the correct ETag headers. - * @param Yoast_Google_HttpRequest $cached A previously cached response. - * @param Yoast_Google_HttpRequest $request The outbound request. - * return bool If the cached object needs to be revalidated, false if it is - * still current and can be re-used. - */ - protected function checkMustRevaliadateCachedRequest($cached, $request) { - if (Yoast_Google_CacheParser::mustRevalidate($cached)) { - $addHeaders = array(); - if ($cached->getResponseHeader('etag')) { - // [13.3.4] If an entity tag has been provided by the origin server, - // we must use that entity tag in any cache-conditional request. - $addHeaders['If-None-Match'] = $cached->getResponseHeader('etag'); - } elseif ($cached->getResponseHeader('date')) { - $addHeaders['If-Modified-Since'] = $cached->getResponseHeader('date'); - } - - $request->setRequestHeaders($addHeaders); - return true; - } else { - return false; - } - } - - /** - * Update a cached request, using the headers from the last response. - * @param Yoast_Google_HttpRequest $cached A previously cached response. - * @param mixed Associative array of response headers from the last request. - */ - protected function updateCachedRequest($cached, $responseHeaders) { - if (isset($responseHeaders['connection'])) { - $hopByHop = array_merge( - self::$HOP_BY_HOP, - explode(',', $responseHeaders['connection']) - ); - - $endToEnd = array(); - foreach($hopByHop as $key) { - if (isset($responseHeaders[$key])) { - $endToEnd[$key] = $responseHeaders[$key]; - } - } - $cached->setResponseHeaders($endToEnd); - } - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_REST.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_REST.php deleted file mode 100644 index 4242df16..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_REST.php +++ /dev/null @@ -1,128 +0,0 @@ - - * @author Chirag Shah - */ -class Yoast_Google_REST { - /** - * Executes a apiServiceRequest using a RESTful call by transforming it into - * an apiHttpRequest, and executed via apiIO::authenticatedRequest(). - * - * @param Yoast_Google_HttpRequest $req - * @return array decoded result - * @throws Yoast_Google_ServiceException on server side error (ie: not authenticated, - * invalid or malformed post body, invalid url) - */ - static public function execute(Yoast_Google_HttpRequest $req) { - $httpRequest = Yoast_Google_Client::$io->makeRequest($req); - $decodedResponse = self::decodeHttpResponse($httpRequest); - $ret = isset($decodedResponse['data']) - ? $decodedResponse['data'] : $decodedResponse; - return $ret; - } - - - /** - * Decode an HTTP Response. - * @static - * @throws Yoast_Google_ServiceException - * @param Yoast_Google_HttpRequest $response The http response to be decoded. - * @return mixed|null - */ - public static function decodeHttpResponse($response) { - $code = $response->getResponseHttpCode(); - $body = $response->getResponseBody(); - $decoded = null; - - if ((intVal($code)) >= 300) { - $decoded = json_decode($body, true); - $err = 'Error calling ' . $response->getRequestMethod() . ' ' . $response->getUrl(); - if ($decoded != null && isset($decoded['error']['message']) && isset($decoded['error']['code'])) { - // if we're getting a json encoded error definition, use that instead of the raw response - // body for improved readability - $err .= ": ({$decoded['error']['code']}) {$decoded['error']['message']}"; - } else { - $err .= ": ($code) $body"; - } - - throw new Yoast_Google_ServiceException($err, $code, null, $decoded['error']['errors']); - } - - // Only attempt to decode the response, if the response code wasn't (204) 'no content' - if ($code != '204') { - $decoded = json_decode($body, true); - if ($decoded === null || $decoded === "") { - throw new Yoast_Google_ServiceException("Invalid json in service response: $body"); - } - } - return $decoded; - } - - /** - * Parse/expand request parameters and create a fully qualified - * request uri. - * @static - * @param string $servicePath - * @param string $restPath - * @param array $params - * @return string $requestUrl - */ - static function createRequestUri($servicePath, $restPath, $params) { - $requestUrl = $servicePath . $restPath; - $uriTemplateVars = array(); - $queryVars = array(); - foreach ($params as $paramName => $paramSpec) { - // Discovery v1.0 puts the canonical location under the 'location' field. - if (! isset($paramSpec['location'])) { - $paramSpec['location'] = $paramSpec['restParameterType']; - } - - if ($paramSpec['type'] == 'boolean') { - $paramSpec['value'] = ($paramSpec['value']) ? 'true' : 'false'; - } - if ($paramSpec['location'] == 'path') { - $uriTemplateVars[$paramName] = $paramSpec['value']; - } else { - if (isset($paramSpec['repeated']) && is_array($paramSpec['value'])) { - foreach ($paramSpec['value'] as $value) { - $queryVars[] = $paramName . '=' . rawurlencode($value); - } - } else { - $queryVars[] = $paramName . '=' . rawurlencode($paramSpec['value']); - } - } - } - - if (count($uriTemplateVars)) { - $uriTemplateParser = new URI_Template_Parser($requestUrl); - $requestUrl = $uriTemplateParser->expand($uriTemplateVars); - } - //FIXME work around for the the uri template lib which url encodes - // the @'s & confuses our servers. - $requestUrl = str_replace('%40', '@', $requestUrl); - - if (count($queryVars)) { - $requestUrl .= '?' . implode($queryVars, '&'); - } - - return $requestUrl; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_WPIO.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_WPIO.php deleted file mode 100644 index b88a55b3..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/Google_WPIO.php +++ /dev/null @@ -1,170 +0,0 @@ - null, "PUT" => null, "DELETE" => null ); - private static $HOP_BY_HOP = array( - 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', - 'te', 'trailers', 'transfer-encoding', 'upgrade' ); - - /** - * Perform an authenticated / signed apiHttpRequest. - * This function takes the apiHttpRequest, calls apiAuth->sign on it - * (which can modify the request in what ever way fits the auth mechanism) - * and then calls apiWPIO::makeRequest on the signed request - * - * @param Yoast_Google_HttpRequest $request - * - * @return Yoast_Google_HttpRequest The resulting HTTP response including the - * responseHttpCode, responseHeaders and responseBody. - */ - public function authenticatedRequest( Yoast_Google_HttpRequest $request ) { - $request = Yoast_Google_Client::$auth->sign( $request ); - - return $this->makeRequest( $request ); - } - - /** - * Execute a apiHttpRequest - * - * @param Yoast_Google_HttpRequest $request the http request to be executed - * - * @return Yoast_Google_HttpRequest http request with the response http code, response - * headers and response body filled in - */ - public function makeRequest( Yoast_Google_HttpRequest $request ) { - - // First, check to see if we have a valid cached version. - $cached = $this->getCachedRequest( $request ); - if ( $cached !== false ) { - if ( ! $this->checkMustRevaliadateCachedRequest( $cached, $request ) ) { - return $cached; - } - } - - if ( array_key_exists( $request->getRequestMethod(), self::$ENTITY_HTTP_METHODS ) ) { - $request = $this->processEntityRequest( $request ); - } - - $params = array( - 'user-agent' => $request->getUserAgent(), - 'timeout' => 30, - 'sslverify' => false, - ); - - $curl_version = $this->get_curl_version(); - if ( $curl_version !== false ) { - if ( version_compare( $curl_version, '7.19.0', '<=' ) && version_compare( $curl_version, '7.19.8', '>' ) ) { - add_filter( 'http_api_transports', array( $this, 'filter_curl_from_transports' ) ); - } - } - - if ( $request->getPostBody() ) { - $params['body'] = $request->getPostBody(); - } - - $requestHeaders = $request->getRequestHeaders(); - if ( $requestHeaders && is_array( $requestHeaders ) ) { - $params['headers'] = $requestHeaders; - } - - // There might be some problems with decompressing, so we prevent this by setting the param to false - $params['decompress'] = false; - - - switch ( $request->getRequestMethod() ) { - case 'POST' : - $response = wp_remote_post( $request->getUrl(), $params ); - break; - - case 'GET' : - $response = wp_remote_get( $request->getUrl(), $params ); - break; - case 'DELETE' : - $params['method'] = 'DELETE'; - $response = wp_remote_get( $request->getUrl(), $params ); - break; - } - - $responseBody = wp_remote_retrieve_body( $response ); - $respHttpCode = wp_remote_retrieve_response_code( $response ); - $responseHeaders = wp_remote_retrieve_headers( $response ); - - if ( $respHttpCode == 304 && $cached ) { - // If the server responded NOT_MODIFIED, return the cached request. - $this->updateCachedRequest( $cached, $responseHeaders ); - - return $cached; - } - - // Fill in the apiHttpRequest with the response values - $request->setResponseHttpCode( $respHttpCode ); - $request->setResponseHeaders( $responseHeaders ); - - $request->setResponseBody( $responseBody ); - // Store the request in cache (the function checks to see if the request - // can actually be cached) - $this->setCachedRequest( $request ); - - // And finally return it - return $request; - } - - /** - * Remove Curl from the transport - * - * @param $transports - * - * @return mixed - */ - public function filter_curl_from_transports( $transports ) { - unset( $transports['curl'] ); - - return $transports; - } - - /** - * Set options that update default behavior. - * - * @param array $optParams Multiple options used by a session. - */ - public function setOptions( $optParams ) { - - } - - /** - * Get the current curl verison if curl is installed - * - * @return bool|string - */ - public function get_curl_version() { - if ( function_exists( 'curl_version' ) ) { - $curl = curl_version(); - - if ( isset( $curl['version'] ) ) { - return $curl['version']; - } - } - - return false; - } - -} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/cacerts.pem b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/cacerts.pem deleted file mode 100644 index 79a49289..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/io/cacerts.pem +++ /dev/null @@ -1,738 +0,0 @@ -# Certifcate Authority certificates for validating SSL connections. -# -# This file contains PEM format certificates generated from -# http://mxr.mozilla.org/seamonkey/source/security/nss/lib/ckfw/builtins/certdata.txt -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is the Netscape security libraries. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1994-2000 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -Verisign/RSA Secure Server CA -============================= - ------BEGIN CERTIFICATE----- -MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD -VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0 -MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV -BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy -dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ -ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII -0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI -uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI -hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3 -YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc -1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA== ------END CERTIFICATE----- - -Thawte Personal Basic CA -======================== - ------BEGIN CERTIFICATE----- -MIIDITCCAoqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCByzELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFBlcnNvbmFsIEJhc2lj -IENBMSgwJgYJKoZIhvcNAQkBFhlwZXJzb25hbC1iYXNpY0B0aGF3dGUuY29tMB4X -DTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgcsxCzAJBgNVBAYTAlpBMRUw -EwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgGA1UE -ChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vy -dmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQZXJzb25hbCBCYXNpYyBD -QTEoMCYGCSqGSIb3DQEJARYZcGVyc29uYWwtYmFzaWNAdGhhd3RlLmNvbTCBnzAN -BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvLyTU23AUE+CFeZIlDWmWr5vQvoPR+53 -dXLdjUmbllegeNTKP1GzaQuRdhciB5dqxFGTS+CN7zeVoQxN2jSQHReJl+A1OFdK -wPQIcOk8RHtQfmGakOMj04gRRif1CwcOu93RfyAKiLlWCy4cgNrx454p7xS9CkT7 -G1sY0b8jkyECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQF -AAOBgQAt4plrsD16iddZopQBHyvdEktTwq1/qqcAXJFAVyVKOKqEcLnZgA+le1z7 -c8a914phXAPjLSeoF+CEhULcXpvGt7Jtu3Sv5D/Lp7ew4F2+eIMllNLbgQ95B21P -9DkVWlIBe94y1k049hJcBlDfBVu9FEuh3ym6O0GN92NWod8isQ== ------END CERTIFICATE----- - -Thawte Personal Premium CA -========================== - ------BEGIN CERTIFICATE----- -MIIDKTCCApKgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBzzELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEjMCEGA1UEAxMaVGhhd3RlIFBlcnNvbmFsIFByZW1p -dW0gQ0ExKjAoBgkqhkiG9w0BCQEWG3BlcnNvbmFsLXByZW1pdW1AdGhhd3RlLmNv -bTAeFw05NjAxMDEwMDAwMDBaFw0yMDEyMzEyMzU5NTlaMIHPMQswCQYDVQQGEwJa -QTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xGjAY -BgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9u -IFNlcnZpY2VzIERpdmlzaW9uMSMwIQYDVQQDExpUaGF3dGUgUGVyc29uYWwgUHJl -bWl1bSBDQTEqMCgGCSqGSIb3DQEJARYbcGVyc29uYWwtcHJlbWl1bUB0aGF3dGUu -Y29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJZtn4B0TPuYwu8KHvE0Vs -Bd/eJxZRNkERbGw77f4QfRKe5ZtCmv5gMcNmt3M6SK5O0DI3lIi1DbbZ8/JE2dWI -Et12TfIa/G8jHnrx2JhFTgcQ7xZC0EN1bUre4qrJMf8fAHB8Zs8QJQi6+u4A6UYD -ZicRFTuqW/KY3TZCstqIdQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG -SIb3DQEBBAUAA4GBAGk2ifc0KjNyL2071CKyuG+axTZmDhs8obF1Wub9NdP4qPIH -b4Vnjt4rueIXsDqg8A6iAJrf8xQVbrvIhVqYgPn/vnQdPfP+MCXRNzRn+qVxeTBh -KXLA4CxM+1bkOqhv5TJZUtt1KFBZDPgLGeSs2a+WjS9Q2wfD6h+rM+D1KzGJ ------END CERTIFICATE----- - -Thawte Personal Freemail CA -=========================== - ------BEGIN CERTIFICATE----- -MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD -VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT -ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt -YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu -Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT -AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa -MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp -b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG -cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh -d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY -DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E -rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq -uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN -BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP -MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa -/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei -gQ== ------END CERTIFICATE----- - -Thawte Server CA -================ - ------BEGIN CERTIFICATE----- -MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm -MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx -MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT -DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 -dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl -cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 -DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD -gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 -yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX -L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj -EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG -7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e -QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ -qdq5snUb9kLy78fyGPmJvKP/iiMucEc= ------END CERTIFICATE----- - -Thawte Premium Server CA -======================== - ------BEGIN CERTIFICATE----- -MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD -VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv -biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy -dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t -MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB -MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG -A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp -b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl -cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv -bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE -VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ -ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR -uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG -9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI -hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM -pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== ------END CERTIFICATE----- - -Equifax Secure CA -================= - ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy -dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 -MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx -dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f -BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A -cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ -MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm -aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw -ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj -IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y -7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh -1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 ------END CERTIFICATE----- - -Verisign Class 1 Public Primary Certification Authority -======================================================= - ------BEGIN CERTIFICATE----- -MIICPTCCAaYCEQDNun9W8N/kvFT+IqyzcqpVMA0GCSqGSIb3DQEBAgUAMF8xCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xh -c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05 -NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYD -VQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMSBQdWJsaWMgUHJp -bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOB -jQAwgYkCgYEA5Rm/baNWYS2ZSHH2Z965jeu3noaACpEO+jglr0aIguVzqKCbJF0N -H8xlbgyw0FaEGIeaBpsQoXPftFg5a27B9hXVqKg/qhIGjTGsf7A01480Z4gJzRQR -4k5FVmkfeAKA2txHkSm7NsljXMXg1y2He6G3MrB7MLoqLzGq7qNn2tsCAwEAATAN -BgkqhkiG9w0BAQIFAAOBgQBMP7iLxmjf7kMzDl3ppssHhE16M/+SG/Q2rdiVIjZo -EWx8QszznC7EBz8UsA9P/5CSdvnivErpj82ggAr3xSnxgiJduLHdgSOjeyUVRjB5 -FvjqBUuUfx3CHMjjt/QQQDwTw18fU+hI5Ia0e6E1sHslurjTjqs/OJ0ANACY89Fx -lA== ------END CERTIFICATE----- - -Verisign Class 2 Public Primary Certification Authority -======================================================= - ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh -YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7 -FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg -J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc -r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority -======================================================= - ------BEGIN CERTIFICATE----- -MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE -BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is -I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do -lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc -AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k ------END CERTIFICATE----- - -Verisign Class 1 Public Primary Certification Authority - G2 -============================================================ - ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK -VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm -Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J -h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul -uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 -DzFc6PLZ ------END CERTIFICATE----- - -Verisign Class 2 Public Primary Certification Authority - G2 -============================================================ - ------BEGIN CERTIFICATE----- -MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns -YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH -MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y -aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe -Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj -IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx -KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM -HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw -DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC -AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji -nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX -rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn -jBJ7xUS0rg== ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority - G2 -============================================================ - ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 -pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 -13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk -U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i -F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY -oJ2daZH9 ------END CERTIFICATE----- - -Verisign Class 4 Public Primary Certification Authority - G2 -============================================================ - ------BEGIN CERTIFICATE----- -MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh -c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy -MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp -emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X -DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw -FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg -UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo -YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 -MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM -HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK -qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID -AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj -cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y -cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP -T8qAkbYp ------END CERTIFICATE----- - -Verisign Class 1 Public Primary Certification Authority - G3 -============================================================ - ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 -nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO -8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV -ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb -PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 -6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr -n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a -qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 -wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 -ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs -pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 -E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== ------END CERTIFICATE----- - -Verisign Class 2 Public Primary Certification Authority - G3 -============================================================ - ------BEGIN CERTIFICATE----- -MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ -BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy -aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s -IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp -Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV -BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp -Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu -Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g -Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt -IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU -J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO -JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY -wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o -koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN -qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E -Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe -xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u -7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU -sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI -sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP -cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q ------END CERTIFICATE----- - -Verisign Class 3 Public Primary Certification Authority - G3 -============================================================ - ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b -N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t -KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu -kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm -CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ -Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu -imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te -2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe -DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p -F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt -TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- - -Verisign Class 4 Public Primary Certification Authority - G3 -============================================================ - ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 -GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ -+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd -U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm -NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY -ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ -ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 -CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq -g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm -fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c -2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ -bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== ------END CERTIFICATE----- - -Equifax Secure Global eBusiness CA -================================== - ------BEGIN CERTIFICATE----- -MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT -ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw -MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj -dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l -c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC -UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc -58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ -o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH -MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr -aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA -A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA -Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv -8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV ------END CERTIFICATE----- - -Equifax Secure eBusiness CA 1 -============================= - ------BEGIN CERTIFICATE----- -MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc -MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT -ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw -MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j -LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ -KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo -RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu -WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw -Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD -AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK -eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM -zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ -WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN -/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== ------END CERTIFICATE----- - -Equifax Secure eBusiness CA 2 -============================= - ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj -dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0 -NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD -VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G -vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/ -BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX -MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl -IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw -NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq -y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy -0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1 -E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN ------END CERTIFICATE----- - -Thawte Time Stamping CA -======================= - ------BEGIN CERTIFICATE----- -MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCWkEx -FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN -BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAd -BgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcwMTAxMDAwMDAwWhcN -MjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4g -Q2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsG -A1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1l -c3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYrWHhhRYZT -6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQa -Wt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL -8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB -Af8wDQYJKoZIhvcNAQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC -9RAIDb/LogWK0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQ -pgCed/r8zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZ -CayJSdM= ------END CERTIFICATE----- - -thawte Primary Root CA -====================== - ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB -qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV -BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw -NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j -LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG -A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs -W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta -3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk -6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 -Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J -NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP -r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU -DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz -YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 -/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ -LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 -jVaMaA== ------END CERTIFICATE----- - -VeriSign Class 3 Public Primary Certification Authority - G5 -============================================================ - ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- - -Entrust.net Secure Server Certification Authority -================================================= - ------BEGIN CERTIFICATE----- -MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC -VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u -ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc -KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u -ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 -MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE -ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j -b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF -bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg -U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA -A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ -I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 -wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC -AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb -oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 -BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p -dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk -MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp -b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu -dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 -MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi -E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa -MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI -hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN -95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd -2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= ------END CERTIFICATE----- - -Go Daddy Certification Authority Root Certificate Bundle -======================================================== - ------BEGIN CERTIFICATE----- -MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx -ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g -RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw -MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH -QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j -b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j -b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H -KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm -VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR -SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT -cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ -6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu -MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS -kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB -BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f -BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv -c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH -AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO -BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG -OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU -A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o -0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX -RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH -qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV -U+4= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh -bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu -Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g -QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe -BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoX -DTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBE -YWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC -ggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv -2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+q -N1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiO -r18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN -f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEH -U1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHU -TBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMb -VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwg -SW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlv -biBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEg -MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUw -AwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdv -ZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMu -Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUd -IAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv -bS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1 -QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4O -WBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0Vmsf -SxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 -IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz -BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y -aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG -9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy -NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y -azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs -YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw -Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl -cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY -dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 -WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS -v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v -UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu -IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC -W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd ------END CERTIFICATE----- - -GeoTrust Global CA -================== - ------BEGIN CERTIFICATE----- -MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT -MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0 -aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw -WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE -AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m -OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu -T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c -JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR -Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz -PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm -aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM -TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g -LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO -BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv -dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB -AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL -NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W -b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S ------END CERTIFICATE----- diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_BatchRequest.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_BatchRequest.php deleted file mode 100644 index 916e0627..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_BatchRequest.php +++ /dev/null @@ -1,110 +0,0 @@ - - */ -class Yoast_Google_BatchRequest { - /** @var string Multipart Boundary. */ - private $boundary; - - /** @var array service requests to be executed. */ - private $requests = array(); - - public function __construct($boundary = false) { - $boundary = (false == $boundary) ? mt_rand() : $boundary; - $this->boundary = str_replace('"', '', $boundary); - } - - public function add(Yoast_Google_HttpRequest $request, $key = false) { - if (false == $key) { - $key = mt_rand(); - } - - $this->requests[$key] = $request; - } - - public function execute() { - $body = ''; - - /** @var Yoast_Google_HttpRequest $req */ - foreach($this->requests as $key => $req) { - $body .= "--{$this->boundary}\n"; - $body .= $req->toBatchString($key) . "\n"; - } - - $body = rtrim($body); - $body .= "\n--{$this->boundary}--"; - - global $apiConfig; - $url = $apiConfig['basePath'] . '/batch'; - $httpRequest = new Yoast_Google_HttpRequest($url, 'POST'); - $httpRequest->setRequestHeaders(array( - 'Content-Type' => 'multipart/mixed; boundary=' . $this->boundary)); - - $httpRequest->setPostBody($body); - $response = Yoast_Google_Client::$io->makeRequest($httpRequest); - - $response = $this->parseResponse($response); - return $response; - } - - public function parseResponse(Yoast_Google_HttpRequest $response) { - $contentType = $response->getResponseHeader('content-type'); - $contentType = explode(';', $contentType); - $boundary = false; - foreach($contentType as $part) { - $part = (explode('=', $part, 2)); - if (isset($part[0]) && 'boundary' == trim($part[0])) { - $boundary = $part[1]; - } - } - - $body = $response->getResponseBody(); - if ($body) { - $body = str_replace("--$boundary--", "--$boundary", $body); - $parts = explode("--$boundary", $body); - $responses = array(); - - foreach($parts as $part) { - $part = trim($part); - if (!empty($part)) { - list($metaHeaders, $part) = explode("\r\n\r\n", $part, 2); - $metaHeaders = Yoast_Google_CurlIO::parseResponseHeaders($metaHeaders); - - $status = substr($part, 0, strpos($part, "\n")); - $status = explode(" ", $status); - $status = $status[1]; - - list($partHeaders, $partBody) = Yoast_Google_CurlIO::parseHttpResponse($part, false); - $response = new Yoast_Google_HttpRequest(""); - $response->setResponseHttpCode($status); - $response->setResponseHeaders($partHeaders); - $response->setResponseBody($partBody); - $response = Yoast_Google_REST::decodeHttpResponse($response); - - // Need content id. - $responses[$metaHeaders['content-id']] = $response; - } - } - - return $responses; - } - - return null; - } -} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_MediaFileUpload.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_MediaFileUpload.php deleted file mode 100644 index 421fbc70..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_MediaFileUpload.php +++ /dev/null @@ -1,262 +0,0 @@ - - * - */ -class Yoast_Google_MediaFileUpload { - const UPLOAD_MEDIA_TYPE = 'media'; - const UPLOAD_MULTIPART_TYPE = 'multipart'; - const UPLOAD_RESUMABLE_TYPE = 'resumable'; - - /** @var string $mimeType */ - public $mimeType; - - /** @var string $data */ - public $data; - - /** @var bool $resumable */ - public $resumable; - - /** @var int $chunkSize */ - public $chunkSize; - - /** @var int $size */ - public $size; - - /** @var string $resumeUri */ - public $resumeUri; - - /** @var int $progress */ - public $progress; - - /** - * @param $mimeType string - * @param $data string The bytes you want to upload. - * @param $resumable bool - * @param bool $chunkSize File will be uploaded in chunks of this many bytes. - * only used if resumable=True - */ - public function __construct($mimeType, $data, $resumable=false, $chunkSize=false) { - $this->mimeType = $mimeType; - $this->data = $data; - $this->size = strlen($this->data); - $this->resumable = $resumable; - if(!$chunkSize) { - $chunkSize = 256 * 1024; - } - $this->chunkSize = $chunkSize; - $this->progress = 0; - } - - public function setFileSize($size) { - $this->size = $size; - } - - /** - * @static - * @param $meta - * @param $params - * @return array|bool - */ - public static function process($meta, &$params) { - $payload = array(); - $meta = is_string($meta) ? json_decode($meta, true) : $meta; - $uploadType = self::getUploadType($meta, $payload, $params); - if (!$uploadType) { - // Process as a normal API request. - return false; - } - - // Process as a media upload request. - $params['uploadType'] = array( - 'type' => 'string', - 'location' => 'query', - 'value' => $uploadType, - ); - - $mimeType = isset($params['mimeType']) - ? $params['mimeType']['value'] - : false; - unset($params['mimeType']); - - if (!$mimeType) { - $mimeType = $payload['content-type']; - } - - if (isset($params['file'])) { - // This is a standard file upload with curl. - $file = $params['file']['value']; - unset($params['file']); - return self::processFileUpload($file, $mimeType); - } - - $data = isset($params['data']) - ? $params['data']['value'] - : false; - unset($params['data']); - - if (self::UPLOAD_RESUMABLE_TYPE == $uploadType) { - $payload['content-type'] = $mimeType; - $payload['postBody'] = is_string($meta) ? $meta : json_encode($meta); - - } elseif (self::UPLOAD_MEDIA_TYPE == $uploadType) { - // This is a simple media upload. - $payload['content-type'] = $mimeType; - $payload['postBody'] = $data; - } - - elseif (self::UPLOAD_MULTIPART_TYPE == $uploadType) { - // This is a multipart/related upload. - $boundary = isset($params['boundary']['value']) ? $params['boundary']['value'] : mt_rand(); - $boundary = str_replace('"', '', $boundary); - $payload['content-type'] = 'multipart/related; boundary=' . $boundary; - $related = "--$boundary\r\n"; - $related .= "Content-Type: application/json; charset=UTF-8\r\n"; - $related .= "\r\n" . json_encode($meta) . "\r\n"; - $related .= "--$boundary\r\n"; - $related .= "Content-Type: $mimeType\r\n"; - $related .= "Content-Transfer-Encoding: base64\r\n"; - $related .= "\r\n" . base64_encode($data) . "\r\n"; - $related .= "--$boundary--"; - $payload['postBody'] = $related; - } - - return $payload; - } - - /** - * Prepares a standard file upload via cURL. - * @param $file - * @param $mime - * @return array Includes the processed file name. - * @visible For testing. - */ - public static function processFileUpload($file, $mime) { - if (!$file) return array(); - if (substr($file, 0, 1) != '@') { - $file = '@' . $file; - } - - // This is a standard file upload with curl. - $params = array('postBody' => array('file' => $file)); - if ($mime) { - $params['content-type'] = $mime; - } - - return $params; - } - - /** - * Valid upload types: - * - resumable (UPLOAD_RESUMABLE_TYPE) - * - media (UPLOAD_MEDIA_TYPE) - * - multipart (UPLOAD_MULTIPART_TYPE) - * - none (false) - * @param $meta - * @param $payload - * @param $params - * @return bool|string - */ - public static function getUploadType($meta, &$payload, &$params) { - if (isset($params['mediaUpload']) - && get_class($params['mediaUpload']['value']) == 'Google_MediaFileUpload') { - $upload = $params['mediaUpload']['value']; - unset($params['mediaUpload']); - $payload['content-type'] = $upload->mimeType; - if (isset($upload->resumable) && $upload->resumable) { - return self::UPLOAD_RESUMABLE_TYPE; - } - } - - // Allow the developer to override the upload type. - if (isset($params['uploadType'])) { - return $params['uploadType']['value']; - } - - $data = isset($params['data']['value']) - ? $params['data']['value'] : false; - - if (false == $data && false == isset($params['file'])) { - // No upload data available. - return false; - } - - if (isset($params['file'])) { - return self::UPLOAD_MEDIA_TYPE; - } - - if (false == $meta) { - return self::UPLOAD_MEDIA_TYPE; - } - - return self::UPLOAD_MULTIPART_TYPE; - } - - - public function nextChunk(Yoast_Google_HttpRequest $req, $chunk=false) { - if (false == $this->resumeUri) { - $this->resumeUri = $this->getResumeUri($req); - } - - if (false == $chunk) { - $chunk = substr($this->data, $this->progress, $this->chunkSize); - } - - $lastBytePos = $this->progress + strlen($chunk) - 1; - $headers = array( - 'content-range' => "bytes $this->progress-$lastBytePos/$this->size", - 'content-type' => $req->getRequestHeader('content-type'), - 'content-length' => $this->chunkSize, - 'expect' => '', - ); - - $httpRequest = new Yoast_Google_HttpRequest($this->resumeUri, 'PUT', $headers, $chunk); - $response = Yoast_Google_Client::$io->authenticatedRequest($httpRequest); - $code = $response->getResponseHttpCode(); - if (308 == $code) { - $range = explode('-', $response->getResponseHeader('range')); - $this->progress = $range[1] + 1; - return false; - } else { - return Yoast_Google_REST::decodeHttpResponse($response); - } - } - - private function getResumeUri(Yoast_Google_HttpRequest $httpRequest) { - $result = null; - $body = $httpRequest->getPostBody(); - if ($body) { - $httpRequest->setRequestHeaders(array( - 'content-type' => 'application/json; charset=UTF-8', - 'content-length' => Yoast_Google_Utils::getStrLen($body), - 'x-upload-content-type' => $this->mimeType, - 'x-upload-content-length' => $this->size, - 'expect' => '', - )); - } - - $response = Yoast_Google_Client::$io->makeRequest($httpRequest); - $location = $response->getResponseHeader('location'); - $code = $response->getResponseHttpCode(); - if (200 == $code && true == $location) { - return $location; - } - throw new Yoast_Google_Exception("Failed to start the resumable upload"); - } -} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_Model.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_Model.php deleted file mode 100644 index e004e76d..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_Model.php +++ /dev/null @@ -1,115 +0,0 @@ - - * - */ -class Yoast_Google_Model { - public function __construct( /* polymorphic */ ) { - if (func_num_args() == 1 && is_array(func_get_arg(0))) { - // Initialize the model with the array's contents. - $array = func_get_arg(0); - $this->mapTypes($array); - } - } - - /** - * Initialize this object's properties from an array. - * - * @param array $array Used to seed this object's properties. - * @return void - */ - protected function mapTypes($array) { - foreach ($array as $key => $val) { - $this->$key = $val; - - $keyTypeName = "__$key" . 'Type'; - $keyDataType = "__$key" . 'DataType'; - if ($this->useObjects() && property_exists($this, $keyTypeName)) { - if ($this->isAssociativeArray($val)) { - if (isset($this->$keyDataType) && 'map' == $this->$keyDataType) { - foreach($val as $arrayKey => $arrayItem) { - $val[$arrayKey] = $this->createObjectFromName($keyTypeName, $arrayItem); - } - $this->$key = $val; - } else { - $this->$key = $this->createObjectFromName($keyTypeName, $val); - } - } else if (is_array($val)) { - $arrayObject = array(); - foreach ($val as $arrayIndex => $arrayItem) { - $arrayObject[$arrayIndex] = $this->createObjectFromName($keyTypeName, $arrayItem); - } - $this->$key = $arrayObject; - } - } - } - } - - /** - * Returns true only if the array is associative. - * @param array $array - * @return bool True if the array is associative. - */ - protected function isAssociativeArray($array) { - if (!is_array($array)) { - return false; - } - $keys = array_keys($array); - foreach($keys as $key) { - if (is_string($key)) { - return true; - } - } - return false; - } - - /** - * Given a variable name, discover its type. - * - * @param $name - * @param $item - * @return object The object from the item. - */ - private function createObjectFromName($name, $item) { - $type = $this->$name; - return new $type($item); - } - - protected function useObjects() { - global $apiConfig; - return (isset($apiConfig['use_objects']) && $apiConfig['use_objects']); - } - - /** - * Verify if $obj is an array. - * @throws Yoast_Google_Exception Thrown if $obj isn't an array. - * @param array $obj Items that should be validated. - * @param string $type Array items should be of this type. - * @param string $method Method expecting an array as an argument. - */ - public function assertIsArray($obj, $type, $method) { - if ($obj && !is_array($obj)) { - throw new Yoast_Google_Exception("Incorrect parameter type passed to $method(), expected an" - . " array containing items of type $type."); - } - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_Service.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_Service.php deleted file mode 100644 index a8b36a73..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_Service.php +++ /dev/null @@ -1,22 +0,0 @@ - - * @author Chirag Shah - * - */ -class Yoast_Google_ServiceResource { - // Valid query parameters that work, but don't appear in discovery. - private $stackParameters = array( - 'alt' => array('type' => 'string', 'location' => 'query'), - 'boundary' => array('type' => 'string', 'location' => 'query'), - 'fields' => array('type' => 'string', 'location' => 'query'), - 'trace' => array('type' => 'string', 'location' => 'query'), - 'userIp' => array('type' => 'string', 'location' => 'query'), - 'userip' => array('type' => 'string', 'location' => 'query'), - 'quotaUser' => array('type' => 'string', 'location' => 'query'), - 'file' => array('type' => 'complex', 'location' => 'body'), - 'data' => array('type' => 'string', 'location' => 'body'), - 'mimeType' => array('type' => 'string', 'location' => 'header'), - 'uploadType' => array('type' => 'string', 'location' => 'query'), - 'mediaUpload' => array('type' => 'complex', 'location' => 'query'), - ); - - /** @var Yoast_Google_Service $service */ - private $service; - - /** @var string $serviceName */ - private $serviceName; - - /** @var string $resourceName */ - private $resourceName; - - /** @var array $methods */ - private $methods; - - public function __construct($service, $serviceName, $resourceName, $resource) { - $this->service = $service; - $this->serviceName = $serviceName; - $this->resourceName = $resourceName; - $this->methods = isset($resource['methods']) ? $resource['methods'] : array($resourceName => $resource); - } - - /** - * @param $name - * @param $arguments - * @return Yoast_Google_HttpRequest|array - * @throws Yoast_Google_Exception - */ - public function __call($name, $arguments) { - if (! isset($this->methods[$name])) { - throw new Yoast_Google_Exception("Unknown function: {$this->serviceName}->{$this->resourceName}->{$name}()"); - } - $method = $this->methods[$name]; - $parameters = $arguments[0]; - - // postBody is a special case since it's not defined in the discovery document as parameter, but we abuse the param entry for storing it - $postBody = null; - if (isset($parameters['postBody'])) { - if (is_object($parameters['postBody'])) { - $this->stripNull($parameters['postBody']); - } - - // Some APIs require the postBody to be set under the data key. - if (is_array($parameters['postBody']) && 'latitude' == $this->serviceName) { - if (!isset($parameters['postBody']['data'])) { - $rawBody = $parameters['postBody']; - unset($parameters['postBody']); - $parameters['postBody']['data'] = $rawBody; - } - } - - $postBody = is_array($parameters['postBody']) || is_object($parameters['postBody']) - ? json_encode($parameters['postBody']) - : $parameters['postBody']; - unset($parameters['postBody']); - - if (isset($parameters['optParams'])) { - $optParams = $parameters['optParams']; - unset($parameters['optParams']); - $parameters = array_merge($parameters, $optParams); - } - } - - if (!isset($method['parameters'])) { - $method['parameters'] = array(); - } - - $method['parameters'] = array_merge($method['parameters'], $this->stackParameters); - foreach ($parameters as $key => $val) { - if ($key != 'postBody' && ! isset($method['parameters'][$key])) { - throw new Yoast_Google_Exception("($name) unknown parameter: '$key'"); - } - } - if (isset($method['parameters'])) { - foreach ($method['parameters'] as $paramName => $paramSpec) { - if (isset($paramSpec['required']) && $paramSpec['required'] && ! isset($parameters[$paramName])) { - throw new Yoast_Google_Exception("($name) missing required param: '$paramName'"); - } - if (isset($parameters[$paramName])) { - $value = $parameters[$paramName]; - $parameters[$paramName] = $paramSpec; - $parameters[$paramName]['value'] = $value; - unset($parameters[$paramName]['required']); - } else { - unset($parameters[$paramName]); - } - } - } - - // Discovery v1.0 puts the canonical method id under the 'id' field. - if (! isset($method['id'])) { - $method['id'] = $method['rpcMethod']; - } - - // Discovery v1.0 puts the canonical path under the 'path' field. - if (! isset($method['path'])) { - $method['path'] = $method['restPath']; - } - - $servicePath = $this->service->servicePath; - - // Process Media Request - $contentType = false; - if (isset($method['mediaUpload'])) { - $media = Yoast_Google_MediaFileUpload::process($postBody, $parameters); - if ($media) { - $contentType = isset($media['content-type']) ? $media['content-type']: null; - $postBody = isset($media['postBody']) ? $media['postBody'] : null; - $servicePath = $method['mediaUpload']['protocols']['simple']['path']; - $method['path'] = ''; - } - } - - $url = Yoast_Google_REST::createRequestUri($servicePath, $method['path'], $parameters); - $httpRequest = new Yoast_Google_HttpRequest($url, $method['httpMethod'], null, $postBody); - if ($postBody) { - $contentTypeHeader = array(); - if (isset($contentType) && $contentType) { - $contentTypeHeader['content-type'] = $contentType; - } else { - $contentTypeHeader['content-type'] = 'application/json; charset=UTF-8'; - $contentTypeHeader['content-length'] = Yoast_Google_Utils::getStrLen($postBody); - } - $httpRequest->setRequestHeaders($contentTypeHeader); - } - - $httpRequest = Yoast_Google_Client::$auth->sign($httpRequest); - if (Yoast_Google_Client::$useBatch) { - return $httpRequest; - } - - // Terminate immediately if this is a resumable request. - if (isset($parameters['uploadType']['value']) - && Yoast_Google_MediaFileUpload::UPLOAD_RESUMABLE_TYPE == $parameters['uploadType']['value']) { - $contentTypeHeader = array(); - if (isset($contentType) && $contentType) { - $contentTypeHeader['content-type'] = $contentType; - } - $httpRequest->setRequestHeaders($contentTypeHeader); - if ($postBody) { - $httpRequest->setPostBody($postBody); - } - return $httpRequest; - } - - return Yoast_Google_REST::execute($httpRequest); - } - - public function useObjects() { - global $apiConfig; - return (isset($apiConfig['use_objects']) && $apiConfig['use_objects']); - } - - protected function stripNull(&$o) { - $o = (array) $o; - foreach ($o as $k => $v) { - if ($v === null || strstr($k, "\0*\0__")) { - unset($o[$k]); - } - elseif (is_object($v) || is_array($v)) { - $this->stripNull($o[$k]); - } - } - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_Utils.php b/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_Utils.php deleted file mode 100644 index d560ca3b..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/api-libs/google/service/Google_Utils.php +++ /dev/null @@ -1,117 +0,0 @@ - - */ -class Yoast_Google_Utils { - public static function urlSafeB64Encode($data) { - $b64 = base64_encode($data); - $b64 = str_replace(array('+', '/', '\r', '\n', '='), - array('-', '_'), - $b64); - return $b64; - } - - public static function urlSafeB64Decode($b64) { - $b64 = str_replace(array('-', '_'), - array('+', '/'), - $b64); - return base64_decode($b64); - } - - /** - * Misc function used to count the number of bytes in a post body, in the world of multi-byte chars - * and the unpredictability of strlen/mb_strlen/sizeof, this is the only way to do that in a sane - * manner at the moment. - * - * This algorithm was originally developed for the - * Solar Framework by Paul M. Jones - * - * @link http://solarphp.com/ - * @link http://svn.solarphp.com/core/trunk/Solar/Json.php - * @link http://framework.zend.com/svn/framework/standard/trunk/library/Zend/Json/Decoder.php - * @param string $str - * @return int The number of bytes in a string. - */ - static public function getStrLen($str) { - $strlenVar = strlen($str); - $d = $ret = 0; - for ($count = 0; $count < $strlenVar; ++ $count) { - $ordinalValue = ord($str{$ret}); - switch (true) { - case (($ordinalValue >= 0x20) && ($ordinalValue <= 0x7F)): - // characters U-00000000 - U-0000007F (same as ASCII) - $ret ++; - break; - - case (($ordinalValue & 0xE0) == 0xC0): - // characters U-00000080 - U-000007FF, mask 110XXXXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $ret += 2; - break; - - case (($ordinalValue & 0xF0) == 0xE0): - // characters U-00000800 - U-0000FFFF, mask 1110XXXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $ret += 3; - break; - - case (($ordinalValue & 0xF8) == 0xF0): - // characters U-00010000 - U-001FFFFF, mask 11110XXX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $ret += 4; - break; - - case (($ordinalValue & 0xFC) == 0xF8): - // characters U-00200000 - U-03FFFFFF, mask 111110XX - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $ret += 5; - break; - - case (($ordinalValue & 0xFE) == 0xFC): - // characters U-04000000 - U-7FFFFFFF, mask 1111110X - // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $ret += 6; - break; - default: - $ret ++; - } - } - return $ret; - } - - /** - * Normalize all keys in an array to lower-case. - * @param array $arr - * @return array Normalized array. - */ - public static function normalize($arr) { - if (!is_array($arr)) { - return array(); - } - - $normalized = array(); - foreach ($arr as $key => $val) { - $normalized[strtolower($key)] = $val; - } - return $normalized; - } -} \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/CHANGELOG.md b/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/CHANGELOG.md index e387413a..261e47cf 100644 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/CHANGELOG.md +++ b/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## 3.1.1 + +### Fixed +- Reverts the capitalization of the class names. + +## 3.1.0 + +### Fixed +- Fixes a bug where a 'You're using WordPress in a language we don't support yet.' notice would be shown for formal and informal locales when the locale actually was supported. + ## 3.0.0 ### Added diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-module.php b/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-v3.php similarity index 75% rename from wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-module.php rename to wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-v3.php index ac502a12..973bb4a3 100644 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-module.php +++ b/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-v3.php @@ -1,47 +1,53 @@ $arg ) { @@ -176,7 +182,7 @@ class Yoast_I18n_v3 { } /** - * Check whether the promo should be hidden or not + * Check whether the promo should be hidden or not. * * @access private * @@ -210,7 +216,7 @@ class Yoast_I18n_v3 { } /** - * Generates a promo message + * Generates a promo message. * * @access private * @@ -223,18 +229,34 @@ class Yoast_I18n_v3 { $message = false; if ( $this->translation_exists && $this->translation_loaded && $this->percent_translated < 90 ) { + /* translators: 1: language name; 3: completion percentage; 4: link to translation platform. */ $message = __( 'As you can see, there is a translation of this plugin in %1$s. This translation is currently %3$d%% complete. We need your help to make it complete and to fix any errors. Please register at %4$s to help complete the translation to %1$s!', $this->textdomain ); - } else if ( ! $this->translation_loaded && $this->translation_exists ) { + } + elseif ( ! $this->translation_loaded && $this->translation_exists ) { + /* translators: 1: language name; 2: plugin name; 3: completion percentage; 4: link to translation platform. */ $message = __( 'You\'re using WordPress in %1$s. While %2$s has been translated to %1$s for %3$d%%, it\'s not been shipped with the plugin yet. You can help! Register at %4$s to help complete the translation to %1$s!', $this->textdomain ); - } else if ( ! $this->translation_exists ) { + } + elseif ( ! $this->translation_exists ) { + /* translators: 2: plugin name; 4: link to translation platform. */ $message = __( 'You\'re using WordPress in a language we don\'t support yet. We\'d love for %2$s to be translated in that language too, but unfortunately, it isn\'t right now. You can change that! Register at %4$s to help translate it!', $this->textdomain ); } - $registration_link = sprintf( '%2$s', esc_url( $this->register_url ), esc_html( $this->glotpress_name ) ); - $message = sprintf( $message, esc_html( $this->locale_name ), esc_html( $this->plugin_name ), $this->percent_translated, $registration_link ); + $registration_link = sprintf( + '%2$s', + esc_url( $this->register_url ), + esc_html( $this->glotpress_name ) + ); + + $message = sprintf( + esc_html( $message ), + esc_html( $this->locale_name ), + esc_html( $this->plugin_name ), + (int) $this->percent_translated, + $registration_link + ); if ( $message ) { - $message = '

    ' . $message . '

    ' . '

    ' . __( 'Register now »', $this->textdomain ) . '

    '; + $message = '

    ' . $message . '

    ' . esc_html__( 'Register now »', $this->textdomain ) . '

    '; } return $message; @@ -250,7 +272,7 @@ class Yoast_I18n_v3 { public function get_dismiss_i18n_message_button() { return 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', $this->textdomain ), + esc_html__( '%1$sPlease don\'t show me this notification anymore%2$s', $this->textdomain ), '', '' ); @@ -269,10 +291,12 @@ class Yoast_I18n_v3 { echo 'X'; echo '
    '; - echo '

    ' . sprintf( __( 'Translation of %s', $this->textdomain ), $this->plugin_name ) . '

    '; - if ( isset( $this->glotpress_logo ) && '' != $this->glotpress_logo ) { + /* translators: %s: plugin name. */ + echo '

    ' . sprintf( esc_html__( 'Translation of %s', $this->textdomain ), esc_html( $this->plugin_name ) ) . '

    '; + if ( isset( $this->glotpress_logo ) && is_string( $this->glotpress_logo ) && '' !== $this->glotpress_logo ) { echo '' . esc_attr( $this->glotpress_name ) . ''; } + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- correctly escaped in promo_message() method. echo $message; echo '
    '; echo '
    '; @@ -334,7 +358,7 @@ class Yoast_I18n_v3 { } /** - * Retrieve the translation details from Yoast Translate + * Retrieve the translation details from Yoast Translate. * * @access private * @@ -360,6 +384,11 @@ class Yoast_I18n_v3 { continue; } + // For informal and formal locales, we have to complete the locale code by concatenating the slug ('formal' or 'informal') to the xx_XX part. + if ( $set->slug !== 'default' && strtolower( $this->locale ) === strtolower( $set->wp_locale . '_' . $set->slug ) ) { + return $set; + } + if ( $this->locale === $set->wp_locale ) { return $set; } @@ -370,9 +399,9 @@ class Yoast_I18n_v3 { } /** - * Set the needed private variables based on the results from Yoast Translate + * Set the needed private variables based on the results from Yoast Translate. * - * @param object $set The translation set + * @param object $set The translation set. * * @access private */ @@ -380,7 +409,8 @@ class Yoast_I18n_v3 { if ( $this->translation_exists && is_object( $set ) ) { $this->locale_name = $set->name; $this->percent_translated = $set->percent_translated; - } else { + } + else { $this->locale_name = ''; $this->percent_translated = ''; } diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-module-wordpressorg.php b/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-wordpressorg-v3.php similarity index 79% rename from wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-module-wordpressorg.php rename to wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-wordpressorg-v3.php index 3cc4fe12..63e2b927 100644 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-module-wordpressorg.php +++ b/wp-content/plugins/wordpress-seo/vendor/yoast/i18n-module/src/i18n-wordpressorg-v3.php @@ -1,4 +1,9 @@ set_defaults( $args ); @@ -26,11 +33,11 @@ class Yoast_I18n_WordPressOrg_v3 { } /** - * Returns the i18n_promo message from the i18n_module. Returns en empty string if the promo shouldn't be shown. + * Returns the i18n_promo message from the i18n_module. * * @access public * - * @return string The i18n promo message. + * @return string The i18n promo message or an empty string if the promo shouldn't be shown. */ public function get_promo_message() { return $this->i18n->get_promo_message(); diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/CHANGELOG.md b/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/CHANGELOG.md deleted file mode 100644 index e516b9ee..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/CHANGELOG.md +++ /dev/null @@ -1,35 +0,0 @@ -# Change Log -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/) -and this project adheres to [Semantic Versioning](http://semver.org/). - -## [1.6.0] - 2017-08-22 - -### Added -- Added a way to overwrite the result of the license manager in the implementing plugin. This is done by applying `yoast-license-valid` and `yoast-show-license-notice` filters. - -### Fixed -- Fixed activation of licenses on multisites and on wpml installations. - -## [1.5.0] - 2017-02-28 -### Added -- Add a `custom_message` option to the response which will be shown as a custom message after the default message. -- Add a `custom_message_[locale]` option to the response which will be shown as a custom message only if the user locale is set to the locale in the message key. - -## [1.4.0] - 2016-11-11 -### Added -- Add a `get_extension_url` method to `Yoast_Product` to retrieve the URL where people can extend/upgrade their license. -- Add a `set_extension_url` method to `Yoast_Product` to set the URL where people can extend/upgrade their license. - -### Changed -- Removed development files from zip that GitHub generates by settings export-ignore for certain files in `.gitattributes`, props [Danny van Kooten](https://github.com/dannyvankooten). - -### Fixed -- Add missing gettext functions to several strings, props [Pedro Mendonça](https://github.com/pedro-mendonca) -- Improve text string for the new version notification, props [Xavi Ivars](https://github.com/xavivars) -- Fix alignment of license fields by setting WordPress classes that have certain default styles that align form elements correctly. - -## [1.3.0] - 2016-06-14 -### Fixed -- Fix issue where the transient would be overwritten for different products with different slugs. diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-api-request.php b/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-api-request.php deleted file mode 100644 index c8d3a656..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-api-request.php +++ /dev/null @@ -1,138 +0,0 @@ - 'GET', - 'timeout' => 10, - 'sslverify' => false, - 'headers' => array( - 'Accept-Encoding' => '*', - 'X-Yoast-EDD' => '1' - ) - ); - - /** - * @var boolean - */ - private $success = false; - - /** - * @var mixed - */ - private $response; - - /** - * @var string - */ - private $error_message = ''; - - /** - * Constructor - * - * @param string url - * @param array $args - */ - public function __construct( $url, array $args = array() ) { - - // set api url - $this->url = $url; - - // set request args (merge with defaults) - $this->args = wp_parse_args( $args, $this->args ); - - // fire the request - $this->success = $this->fire(); - } - - /** - * Fires the request, automatically called from constructor - * - * @return boolean - */ - private function fire() { - - // fire request to shop - $response = wp_remote_request( $this->url, $this->args ); - - // validate raw response - if( $this->validate_raw_response( $response ) === false ) { - return false; - } - - // decode the response - $this->response = json_decode( wp_remote_retrieve_body( $response ) ); - - // response should be an object - if( ! is_object( $this->response ) ) { - $this->error_message = 'No JSON object was returned.'; - return false; - } - - return true; - } - - /** - * @param object $response - * @return boolean - */ - private function validate_raw_response( $response ) { - - // make sure response came back okay - if( is_wp_error( $response ) ) { - $this->error_message = $response->get_error_message(); - return false; - } - - // check response code, should be 200 - $response_code = wp_remote_retrieve_response_code( $response ); - - if( false === strstr( $response_code, '200' ) ) { - - $response_message = wp_remote_retrieve_response_message( $response ); - $this->error_message = "{$response_code} {$response_message}"; - - return false; - } - - return true; - } - - /** - * Was a valid response returned? - * - * @return boolean - */ - public function is_valid() { - return ( $this->success === true ); - } - - /** - * @return string - */ - public function get_error_message() { - return $this->error_message; - } - - /** - * @return object - */ - public function get_response() { - return $this->response; - } - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-license-manager.php b/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-license-manager.php deleted file mode 100644 index d1eda1a8..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-license-manager.php +++ /dev/null @@ -1,781 +0,0 @@ -product = $product; - - // set prefix - $this->prefix = sanitize_title_with_dashes( $this->product->get_item_name() . '_', null, 'save' ); - - // maybe set license key from constant - $this->maybe_set_license_key_from_constant(); - } - - /** - * Setup hooks - * - */ - public function setup_hooks() { - - // show admin notice if license is not active - add_action( 'admin_notices', array( $this, 'display_admin_notices' ) ); - - // catch POST requests from license form - add_action( 'admin_init', array( $this, 'catch_post_request' ) ); - - // Adds the plugin to the active extensions. - add_filter( 'yoast-active-extensions', array( $this, 'set_active_extension' ) ); - - // setup item type (plugin|theme) specific hooks - $this->specific_hooks(); - - // setup the auto updater - $this->setup_auto_updater(); - } - - /** - * Checks if the license is valid and put it into the list with extensions. - * - * @param array $extensions The extensions used in Yoast SEO. - * - * @return array - */ - public function set_active_extension( $extensions ) { - if ( ! $this->license_is_valid() ) { - $this->set_license_key( 'yoast-dummy-license' ); - $this->activate_license(); - } - - if ( $this->license_is_valid() ) { - $extensions[] = $this->product->get_slug(); - } - - return $extensions; - } - - /** - * Display license specific admin notices, namely: - * - * - License for the product isn't activated - * - External requests are blocked through WP_HTTP_BLOCK_EXTERNAL - */ - public function display_admin_notices() { - - if ( ! current_user_can( 'manage_options' ) ) { - return; - } - - // show notice if license is invalid - if ( $this->show_license_notice() && ! $this->license_is_valid() ) { - if ( $this->get_license_key() == '' ) { - $message = __( 'Warning! You didn\'t set your %s license key yet, which means you\'re missing out on updates and support! Enter your license key or get a license here.' ); - } else { - $message = __( 'Warning! Your %s license is inactive which means you\'re missing out on updates and support! Activate your license or get a license here.' ); - } - ?> -
    -

    product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url(), $this->product->get_tracking_url( 'activate-license-notice' ) ); ?>

    -
    - product->get_api_url(), PHP_URL_HOST ); - - if ( ! defined( "WP_ACCESSIBLE_HOSTS" ) || stristr( WP_ACCESSIBLE_HOSTS, $host ) === false ) { - ?> -
    -

    Warning! You\'re blocking external requests which means you won\'t be able to get %s updates. Please add %s to %s.', $this->product->get_text_domain() ), $this->product->get_item_name(), '' . $host . '', 'WP_ACCESSIBLE_HOSTS' ); ?>

    -
    - prefix . 'license', 'license-notice', $message, $css_class ); - } - - /** - * Remotely activate License - * @return boolean True if the license is now activated, false if not - */ - public function activate_license() { - - $result = $this->call_license_api( 'activate' ); - - if ( $result ) { - - // show success notice if license is valid - if ( $result->license === 'valid' ) { - $success = true; - $message = $this->get_successful_activation_message( $result ); - } else { - $this->remote_license_activation_failed = true; - - $success = false; - $message = $this->get_unsuccessful_activation_message( $result ); - } - - // Append custom HTML message to default message. - $message .= $this->get_custom_message( $result ); - - if ( $this->show_license_notice() ) { - $this->set_notice( $message, $success ); - } - - $this->set_license_status( $result->license ); - } - - return $this->license_is_valid(); - } - - /** - * Remotely deactivate License - * @return boolean True if the license is now deactivated, false if not - */ - public function deactivate_license() { - - $result = $this->call_license_api( 'deactivate' ); - - if ( $result ) { - - // show notice if license is deactivated - if ( $result->license === 'deactivated' ) { - $success = true; - $message = sprintf( __( "Your %s license has been deactivated.", $this->product->get_text_domain() ), $this->product->get_item_name() ); - } else { - $success = false; - $message = sprintf( __( "Failed to deactivate your %s license.", $this->product->get_text_domain() ), $this->product->get_item_name() ); - } - - $message .= $this->get_custom_message( $result ); - - // Append custom HTML message to default message. - if ( $this->show_license_notice() ) { - $this->set_notice( $message, $success ); - } - - $this->set_license_status( $result->license ); - } - - return ( $this->get_license_status() === 'deactivated' ); - } - - /** - * Returns the home url with the following modifications: - * - * In case of a multisite setup we return the network_home_url. - * In case of no multisite setup we return the home_url while overriding the WPML filter. - */ - public function get_url() { - // Add a new filter to undo WPML's changing of home url. - add_filter( 'wpml_get_home_url', array( $this, 'wpml_get_home_url' ), 10, 2 ); - - // If the plugin is network activated, use the network home URL. - if ( $this->is_network_activated ) { - $url = network_home_url(); - } - - // Otherwise use the home URL for this specific site. - if ( ! $this->is_network_activated ) { - $url = home_url(); - } - - remove_filter( 'wpml_get_home_url', array( $this, 'wpml_get_home_url' ), 10 ); - - return $url; - } - - /** - * Returns the original URL instead of the language-enriched URL. - * This method gets automatically triggered by the wpml_get_home_url filter. - * - * @param string $home_url The url altered by WPML. Unused. - * @param string $url The url that isn't altered by WPML. - * - * @return string The original url. - */ - public function wpml_get_home_url( $home_url, $url ) { - return $url; - } - - /** - * @param string $action activate|deactivate - * - * @return mixed - */ - protected function call_license_api( $action ) { - - // don't make a request if license key is empty - if ( $this->get_license_key() === '' ) { - return false; - } - - // data to send in our API request - $api_params = array( - 'edd_action' => $action . '_license', - 'license' => $this->get_license_key(), - 'item_name' => urlencode( trim( $this->product->get_item_name() ) ), - 'url' => $this->get_url() - // grab the URL straight from the option to prevent filters from breaking it. - ); - - // create api request url - $url = add_query_arg( $api_params, $this->product->get_api_url() ); - - require_once dirname( __FILE__ ) . '/class-api-request.php'; - $request = new Yoast_API_Request( $url ); - - if ( $request->is_valid() !== true ) { - $this->set_notice( sprintf( __( "Request error: \"%s\" (%scommon license notices%s)", $this->product->get_text_domain() ), $request->get_error_message(), '', '' ), false ); - } - - // get response - return $request->get_response(); - } - - - /** - * Set the license status - * - * @param string $license_status - */ - public function set_license_status( $license_status ) { - $this->set_option( 'status', $license_status ); - } - - /** - * Get the license status - * - * @return string $license_status; - */ - public function get_license_status() { - $license_status = $this->get_option( 'status' ); - - return trim( $license_status ); - } - - /** - * Set the license key - * - * @param string $license_key - */ - public function set_license_key( $license_key ) { - $this->set_option( 'key', $license_key ); - } - - /** - * Gets the license key from constant or option - * - * @return string $license_key - */ - public function get_license_key() { - $license_key = $this->get_option( 'key' ); - - return trim( $license_key ); - } - - /** - * Gets the license expiry date - * - * @return string - */ - public function get_license_expiry_date() { - return $this->get_option( 'expiry_date' ); - } - - /** - * Stores the license expiry date - */ - public function set_license_expiry_date( $expiry_date ) { - $this->set_option( 'expiry_date', $expiry_date ); - } - - /** - * Checks whether the license status is active - * - * @return boolean True if license is active - */ - public function license_is_valid() { - return ( $this->get_license_status() === 'valid' ); - } - - /** - * Get all license related options - * - * @return array Array of license options - */ - protected function get_options() { - - // create option name - $option_name = $this->prefix . 'license'; - - // get array of options from db - if ( $this->is_network_activated ) { - $options = get_site_option( $option_name, array() ); - } else { - $options = get_option( $option_name, array() ); - } - - // setup array of defaults - $defaults = array( - 'key' => '', - 'status' => '', - 'expiry_date' => '' - ); - - // merge options with defaults - $this->options = wp_parse_args( $options, $defaults ); - - return $this->options; - } - - /** - * Set license related options - * - * @param array $options Array of new license options - */ - protected function set_options( array $options ) { - // create option name - $option_name = $this->prefix . 'license'; - - // update db - if ( $this->is_network_activated ) { - update_site_option( $option_name, $options ); - } else { - update_option( $option_name, $options ); - } - - } - - /** - * Gets a license related option - * - * @param string $name The option name - * - * @return mixed The option value - */ - protected function get_option( $name ) { - $options = $this->get_options(); - - return $options[ $name ]; - } - - /** - * Set a license related option - * - * @param string $name The option name - * @param mixed $value The option value - */ - protected function set_option( $name, $value ) { - // get options - $options = $this->get_options(); - - // update option - $options[ $name ] = $value; - - // save options - $this->set_options( $options ); - } - - public function show_license_form_heading() { - ?> -

    - product->get_text_domain() ), $this->product->get_item_name() ); ?> -     -

    - prefix . 'license_key'; - $nonce_name = $this->prefix . 'license_nonce'; - $action_name = $this->prefix . 'license_action'; - - $api_host_available = $this->get_api_availability(); - - $visible_license_key = $this->get_license_key(); - - // obfuscate license key - $obfuscate = ( strlen( $this->get_license_key() ) > 5 && ( $this->license_is_valid() || ! $this->remote_license_activation_failed ) ); - - if ( $obfuscate ) { - $visible_license_key = str_repeat( '*', strlen( $this->get_license_key() ) - 4 ) . substr( $this->get_license_key(), - 4 ); - } - - // make license key readonly when license key is valid or license is defined with a constant - $readonly = ( $this->license_is_valid() || $this->license_constant_is_defined ); - - require dirname( __FILE__ ) . '/views/form.php'; - - // enqueue script in the footer - add_action( 'admin_footer', array( $this, 'output_script' ), 99 ); - } - - /** - * Check if the license form has been submitted - */ - public function catch_post_request() { - - $name = $this->prefix . 'license_key'; - - // check if license key was posted and not empty - if ( ! isset( $_POST[ $name ] ) ) { - return; - } - - // run a quick security check - $nonce_name = $this->prefix . 'license_nonce'; - - if ( ! check_admin_referer( $nonce_name, $nonce_name ) ) { - return; - } - - // @TODO: check for user cap? - - // get key from posted value - $license_key = $_POST[ $name ]; - - // check if license key doesn't accidentally contain asterisks - if ( strstr( $license_key, '*' ) === false ) { - - // sanitize key - $license_key = trim( sanitize_key( $_POST[ $name ] ) ); - - // save license key - $this->set_license_key( $license_key ); - } - - // does user have an activated valid license - if ( ! $this->license_is_valid() ) { - - // try to auto-activate license - return $this->activate_license(); - - } - - $action_name = $this->prefix . 'license_action'; - - // was one of the action buttons clicked? - if ( isset( $_POST[ $action_name ] ) ) { - - $action = trim( $_POST[ $action_name ] ); - - switch ( $action ) { - case 'activate': - return $this->activate_license(); - - case 'deactivate': - return $this->deactivate_license(); - } - - } - - } - - /** - * Output the script containing the YoastLicenseManager JS Object - * - * This takes care of disabling the 'activate' and 'deactivate' buttons - */ - public function output_script() { - require_once dirname( __FILE__ ) . '/views/script.php'; - } - - /** - * Set the constant used to define the license - * - * @param string $license_constant_name The license constant name - */ - public function set_license_constant_name( $license_constant_name ) { - $this->license_constant_name = trim( $license_constant_name ); - $this->maybe_set_license_key_from_constant(); - } - - /** - * Get the API availability information - * - * @return array - */ - protected function get_api_availability() { - return array( - 'url' => $this->product->get_api_url(), - 'availability' => $this->check_api_host_availability(), - 'curl_version' => $this->get_curl_version(), - ); - } - - /** - * Check if the API host address is available from this server - * - * @return bool - */ - private function check_api_host_availability() { - $wp_http = new WP_Http(); - if ( $wp_http->block_request( $this->product->get_api_url() ) === false ) { - return true; - } - - return false; - } - - /** - * Get the current curl version, or false - * - * @return mixed - */ - protected function get_curl_version() { - if ( function_exists( 'curl_version' ) ) { - $curl_version = curl_version(); - - if ( isset( $curl_version['version'] ) ) { - return $curl_version['version']; - } - } - - return false; - } - - /** - * Maybe set license key from a defined constant - */ - private function maybe_set_license_key_from_constant() { - - if ( empty( $this->license_constant_name ) ) { - // generate license constant name - $this->set_license_constant_name( strtoupper( str_replace( array( - ' ', - '-' - ), '', sanitize_key( $this->product->get_item_name() ) ) ) . '_LICENSE' ); - } - - // set license key from constant - if ( defined( $this->license_constant_name ) ) { - - $license_constant_value = constant( $this->license_constant_name ); - - // update license key value with value of constant - if ( $this->get_license_key() !== $license_constant_value ) { - $this->set_license_key( $license_constant_value ); - } - - $this->license_constant_is_defined = true; - } - } - - /** - * Determine what message should be shown for a successful license activation - * - * @param Object $result Result of a request. - * - * @return string - */ - protected function get_successful_activation_message( $result ) { - // Get expiry date. - if ( isset( $result->expires ) ) { - $this->set_license_expiry_date( $result->expires ); - $expiry_date = strtotime( $result->expires ); - } else { - $expiry_date = false; - } - - // Always show that it was successful. - $message = sprintf( __( "Your %s license has been activated. ", $this->product->get_text_domain() ), $this->product->get_item_name() ); - - // Show a custom notice it is an unlimited license. - if ( $result->license_limit == 0 ) { - $message .= __( "You have an unlimited license. ", $this->product->get_text_domain() ); - } else { - $message .= sprintf( _n( "You have used %d/%d activation. ", "You have used %d/%d activations. ", $result->license_limit, $this->product->get_text_domain() ), $result->site_count, $result->license_limit ); - } - - // add upgrade notice if user has less than 3 activations left - if ( $result->license_limit > 0 && ( $result->license_limit - $result->site_count ) <= 3 ) { - $message .= sprintf( __( 'Did you know you can upgrade your license? ', $this->product->get_text_domain() ), $this->product->get_extension_url( 'license-nearing-limit-notice' ) ); - } - - if ( $expiry_date !== false && $expiry_date < strtotime( "+1 month" ) ) { - // Add extend notice if license is expiring in less than 1 month. - $days_left = round( ( $expiry_date - time() ) / 86400 ); - $message .= sprintf( _n( 'Your license is expiring in %d day, would you like to extend it? ', 'Your license is expiring in %d days, would you like to extend it? ', $days_left, $this->product->get_text_domain() ), $this->product->get_extension_url( 'license-expiring-notice' ), $days_left ); - } - - return $message; - } - - /** - * Determine what message should be shown for an unsuccessful activation - * - * @param Object $result Result of a request. - * - * @return string - */ - protected function get_unsuccessful_activation_message( $result ) { - // Default message if we cannot detect anything more specific. - $message = __( 'Failed to activate your license, your license key seems to be invalid.', $this->product->get_text_domain() ); - - if ( ! empty( $result->error ) ) { - switch ( $result->error ) { - // Show notice if user is at their activation limit. - case 'no_activations_left': - $message = sprintf( __( 'You\'ve reached your activation limit. You must upgrade your license to use it on this site.', $this->product->get_text_domain() ), $this->product->get_extension_url( 'license-at-limit-notice' ) ); - break; - - // Show notice if the license is expired. - case 'expired': - $message = sprintf( __( 'Your license has expired. You must extend your license in order to use it again.', $this->product->get_text_domain() ), $this->product->get_extension_url( 'license-expired-notice' ) ); - break; - } - } - - return $message; - } - - /** - * Get the locale for the current user - * - * @return string - */ - protected function get_user_locale() { - if ( function_exists( 'get_user_locale' ) ) { - return get_user_locale(); - } - - return get_locale(); - } - - /** - * Parse custom HTML message from response - * - * @param Object $result Result of the request. - * - * @return string - */ - protected function get_custom_message( $result ) { - $message = ''; - - // Allow for translated messages to be used. - $localizedDescription = 'custom_message_' . $this->get_user_locale(); - if ( ! empty( $result->{$localizedDescription} ) ) { - $message = $result->{$localizedDescription}; - } - - // Fall back to non-localized custom message if no locale has been provided. - if ( empty( $message ) && ! empty( $result->custom_message ) ) { - $message = $result->custom_message; - } - - // Make sure we limit the type of HTML elements to be displayed. - if ( ! empty( $message ) ) { - $message = wp_kses( $message, array( - 'a' => array( - 'href' => array(), - 'target' => array(), - 'title' => array() - ), - 'br' => array(), - ) ); - - // Make sure we are on a new line. - $message = '
    ' . $message; - } - - return $message; - } - - /** - * Returns true when a license notice should be shown. - * - * @return bool - */ - protected function show_license_notice() { - /** - * Filter: 'yoast-show-license-notice' - Show the license notice. - * - * @api bool $show True if notices should be shown. - */ - return ( bool ) apply_filters( 'yoast-show-license-notice', true ); - } - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-plugin-license-manager.php b/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-plugin-license-manager.php deleted file mode 100644 index df67ea32..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-plugin-license-manager.php +++ /dev/null @@ -1,95 +0,0 @@ -is_network_activated = is_plugin_active_for_network( $product->get_file() ); - } - } - - /** - * Setup auto updater for plugins - */ - public function setup_auto_updater() { - /** - * Filter: 'yoast-license-valid' - Perform action when license is valid or hook returns true. - * - * @api bool $is_valid True if the license is valid. - */ - if ( apply_filters( 'yoast-license-valid', $this->license_is_valid() ) ) { - // setup auto updater - require_once( dirname( __FILE__ ) . '/class-update-manager.php' ); - require_once( dirname( __FILE__ ) . '/class-plugin-update-manager.php' ); - new Yoast_Plugin_Update_Manager( $this->product, $this ); - } - } - - /** - * Setup hooks - */ - public function specific_hooks() { - - // deactivate the license remotely on plugin deactivation - register_deactivation_hook( $this->product->get_file(), array( $this, 'deactivate_license' ) ); - } - - /** - * Show a form where users can enter their license key - * Takes Multisites into account - * - * @param bool $embedded - * @return null - */ - public function show_license_form( $embedded = true ) { - - // For non-multisites, always show the license form - if( ! is_multisite() ) { - parent::show_license_form( $embedded ); - return; - } - - // Plugin is network activated - if( $this->is_network_activated ) { - - // We're on the network admin - if( is_network_admin() ) { - parent::show_license_form( $embedded ); - } else { - // We're not in the network admin area, show a notice - parent::show_license_form_heading(); - if ( is_super_admin() ) { - echo "

    " . sprintf( __( '%s is network activated, you can manage your license in the network admin license page.', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->product->get_license_page_url() ) . "

    "; - } else { - echo "

    " . sprintf( __( '%s is network activated, please contact your site administrator to manage the license.', $this->product->get_text_domain() ), $this->product->get_item_name() ) . "

    "; - } - - } - - } else { - - if( false == is_network_admin() ) { - parent::show_license_form( $embedded ); - } - - } - } - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-plugin-update-manager.php b/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-plugin-update-manager.php deleted file mode 100644 index b7c2551c..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-plugin-update-manager.php +++ /dev/null @@ -1,93 +0,0 @@ -setup_hooks(); - } - - /** - * Setup hooks - */ - private function setup_hooks() { - - // check for updates - add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'set_updates_available_data' ) ); - - // get correct plugin information (when viewing details) - add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 ); - } - - /** - * Check for updates and if so, add to "updates available" data - * - * @param object $data - * @return object $data - */ - public function set_updates_available_data( $data ) { - - if ( empty( $data ) ) { - return $data; - } - - // send of API request to check for updates - $remote_data = $this->get_remote_data(); - - // did we get a response? - if( $remote_data === false ) { - return $data; - } - - // compare local version with remote version - if ( version_compare( $this->product->get_version(), $remote_data->new_version, '<' ) ) { - - // remote version is newer, add to data - $data->response[ $this->product->get_file() ] = $remote_data; - - } - - return $data; - } - - /** - * Gets new plugin version details (view version x.x.x details) - * - * @uses api_request() - * - * @param object $data - * @param string $action - * @param object $args (optional) - * - * @return object $data - */ - public function plugins_api_filter( $data, $action = '', $args = null ) { - - // only do something if we're checking for our plugin - if ( $action !== 'plugin_information' || ! isset( $args->slug ) || $args->slug !== $this->product->get_slug() ) { - return $data; - } - - $api_response = $this->get_remote_data(); - - // did we get a response? - if ( $api_response === false ) { - return $data; - } - - // return api response - return $api_response; - } - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-product.php b/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-product.php deleted file mode 100644 index a072fa80..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-product.php +++ /dev/null @@ -1,323 +0,0 @@ -set_api_url( $api_url ); - $this->set_item_name( $item_name ); - $this->set_slug( $slug ); - $this->set_version( $version ); - $this->set_item_url( $item_url ); - $this->set_text_domain( $text_domain ); - $this->set_author( $author ); - $this->set_file( $file ); - $this->set_product_id( $product_id ); - $this->set_license_page_url( $license_page_url ); - } - - /** - * @param string $api_url - */ - public function set_api_url( $api_url ) { - $this->api_url = $api_url; - } - - /** - * @return string - */ - public function get_api_url() { - return $this->api_url; - } - - /** - * @param string $author - */ - public function set_author( $author ) { - $this->author = $author; - } - - /** - * @return string - */ - public function get_author() { - return $this->author; - } - - /** - * @param string $item_name - */ - public function set_item_name( $item_name ) { - $this->item_name = $item_name; - } - - /** - * @return string - */ - public function get_item_name() { - return $this->item_name; - } - - /** - * @param string $item_url - */ - public function set_item_url( $item_url ) { - if ( empty( $item_url ) ) { - $item_url = $this->api_url; - } - - $this->item_url = $item_url; - } - - /** - * @return string - */ - public function get_item_url() { - return $this->item_url; - } - - /** - * @param string $license_page_url - */ - public function set_license_page_url( $license_page_url ) { - - if ( is_admin() && is_multisite() ) { - - if ( ! function_exists( 'is_plugin_active_for_network' ) ) { - require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); - } - - if ( is_plugin_active_for_network( $this->get_file() ) ) { - $this->license_page_url = network_admin_url( $license_page_url ); - - return; - } - } - - $this->license_page_url = admin_url( $license_page_url ); - } - - /** - * @return string - */ - public function get_license_page_url() { - return $this->license_page_url; - } - - /** - * @param string $slug - */ - public function set_slug( $slug ) { - $this->slug = $slug; - } - - /** - * @return string - */ - public function get_slug() { - return $this->slug; - } - - /** - * Returns the dirname of the slug and limits it to 15 chars - * - * @return string - */ - public function get_transient_prefix() { - return substr( md5( $this->file ), 0, 15 ); - } - - /** - * @param string $text_domain - */ - public function set_text_domain( $text_domain ) { - $this->text_domain = $text_domain; - } - - /** - * @return string - */ - public function get_text_domain() { - return $this->text_domain; - } - - /** - * @param string $version - */ - public function set_version( $version ) { - $this->version = $version; - } - - /** - * @return string - */ - public function get_version() { - return $this->version; - } - - /** - * Returns the file path relative to the plugins folder - * - * @return string - */ - public function get_file() { - /* - * Fall back to the slug for BC reasons. - * - * We used to pass the file to the slug field, but this isn't supported with the shiny updates in WordPress. - * WordPress uses the slug in the HTML as an ID and a slash isn't a valid - */ - return empty( $this->file ) ? $this->slug : $this->file; - } - - /** - * Sets the file path relative to the plugins folder - * - * @param string $file Relative file path to the plugin. - */ - public function set_file( $file ) { - $this->file = $file; - } - - /** - * Return the Product ID - * - * @return int - */ - public function get_product_id() { - return $this->product_id; - } - - /** - * Set the product ID - * - * @param int $product_id Product ID to set. - */ - public function set_product_id( $product_id ) { - $this->product_id = (int) $product_id; - } - - /** - * Gets a Google Analytics Campaign url for this product - * - * @param string $link_identifier - * - * @return string The full URL - */ - public function get_tracking_url( $link_identifier = '' ) { - return $this->add_campaign_attributes( $this->get_item_url(), $link_identifier ); - } - - /** - * Returns the extension url if set, otherwise it will be the tracking url. - * - * @param string $link_identifier - * - * @return string - */ - public function get_extension_url( $link_identifier = '' ) { - if ( $this->extension_url ) { - return $this->add_campaign_attributes( $this->extension_url, $link_identifier ); - } - - return $this->get_tracking_url( $link_identifier ); - } - - /** - * Sets the extension url. - * - * @param string $extension_url - */ - public function set_extension_url( $extension_url ) { - $this->extension_url = $extension_url; - } - - private function add_campaign_attributes( $url, $link_identifier ) { - $tracking_vars = array( - 'utm_campaign' => $this->get_item_name() . ' licensing', - 'utm_medium' => 'link', - 'utm_source' => $this->get_item_name(), - 'utm_content' => $link_identifier - ); - - // URL encode tracking vars. - $tracking_vars = urlencode_deep( $tracking_vars ); - $query_string = build_query( $tracking_vars ); - - return $url . '#' . $query_string; - } - - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-update-manager.php b/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-update-manager.php deleted file mode 100644 index 01d0f6e1..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/class-update-manager.php +++ /dev/null @@ -1,224 +0,0 @@ -product = $product; - $this->license_manager = $license_manager; - - // generate transient names - $this->response_transient_key = $this->product->get_transient_prefix() . '-update-response'; - $this->request_failed_transient_key = $this->product->get_transient_prefix() . '-update-request-failed'; - - // maybe delete transient - $this->maybe_delete_transients(); - } - - /** - * Deletes the various transients - * If we're on the update-core.php?force-check=1 page - */ - private function maybe_delete_transients() { - global $pagenow; - - if ( $pagenow === 'update-core.php' && isset( $_GET['force-check'] ) ) { - delete_transient( $this->response_transient_key ); - delete_transient( $this->request_failed_transient_key ); - } - } - - /** - * If the update check returned a WP_Error, show it to the user - */ - public function show_update_error() { - - if ( $this->error_message === '' ) { - return; - } - - ?> -
    -

    %s', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->error_message ); ?>

    -
    - request_failed_transient_key ) !== false ) { - return false; - } - - // start request process - global $wp_version; - - // set a transient to prevent failed update checks on every page load - // this transient will be removed if a request succeeds - set_transient( $this->request_failed_transient_key, 'failed', 10800 ); - - // setup api parameters - $api_params = array( - 'edd_action' => 'get_version', - 'license' => $this->license_manager->get_license_key(), - 'item_name' => $this->product->get_item_name(), - 'wp_version' => $wp_version, - 'item_version' => $this->product->get_version(), - 'url' => $this->license_manager->get_url(), - 'slug' => $this->product->get_slug(), - ); - - // Add product ID from product if it is implemented. - if ( method_exists( $this->product, 'get_product_id' ) ) { - $product_id = $this->product->get_product_id(); - if ( $product_id > 0 ) { - $api_params['product_id'] = $this->product->get_product_id(); - } - } - - // setup request parameters - $request_params = array( - 'method' => 'POST', - 'body' => $api_params - ); - - require_once dirname( __FILE__ ) . '/class-api-request.php'; - $request = new Yoast_API_Request( $this->product->get_api_url(), $request_params ); - - if ( $request->is_valid() !== true ) { - - // show error message - $this->error_message = $request->get_error_message(); - add_action( 'admin_notices', array( $this, 'show_update_error' ) ); - - return false; - } - - // request succeeded, delete transient indicating a request failed - delete_transient( $this->request_failed_transient_key ); - - // decode response - $response = $request->get_response(); - - // check if response returned that a given site was inactive - if ( isset( $response->license_check ) && ! empty( $response->license_check ) && $response->license_check != 'valid' ) { - - // deactivate local license - $this->license_manager->set_license_status( 'invalid' ); - - // show notice to let the user know we deactivated his/her license - $this->error_message = __( "This site has not been activated properly on yoast.com and thus cannot check for future updates. Please activate your site with a valid license key.", $this->product->get_text_domain() ); - - /** - * Filter: 'yoast-show-license-notice' - Show the license notice. - * - * @api bool $show True if notices should be shown. - */ - if ( apply_filters( 'yoast-show-license-notice', true ) ) { - add_action( 'admin_notices', array( $this, 'show_update_error' ) ); - } - } - - $response->sections = maybe_unserialize( $response->sections ); - - // store response - set_transient( $this->response_transient_key, $response, 10800 ); - - return $response; - } - - /** - * Gets the remote product data (from the EDD API) - * - * - If it was previously fetched in the current requests, this gets it from the instance property - * - Next, it tries the 3-hour transient - * - Next, it calls the remote API and stores the result - * - * @return object - */ - protected function get_remote_data() { - - // always use property if it's set - if ( null !== $this->update_response ) { - return $this->update_response; - } - - // get cached remote data - $data = $this->get_cached_remote_data(); - - // if cache is empty or expired, call remote api - if ( $data === false ) { - $data = $this->call_remote_api(); - } - - $this->update_response = $data; - - return $data; - } - - /** - * Gets the remote product data from a 3-hour transient - * - * @return bool|mixed - */ - private function get_cached_remote_data() { - - $data = get_transient( $this->response_transient_key ); - - if ( $data ) { - return $data; - } - - return false; - } - - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/index.php b/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/index.php deleted file mode 100644 index 12c197f3..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/index.php +++ /dev/null @@ -1,2 +0,0 @@ -product; - -$this->show_license_form_heading(); - -if( $api_host_available['availability'] === false ){ - echo '

    ' . sprintf( __( 'We couldn\'t create a connection to our API to verify your license key(s). Please ask your hosting company to allow outgoing connections from your server to %s.', $product->get_text_domain() ), $api_host_available['url'] ) . '

    '; -} - -if( $api_host_available['curl_version'] !== false && version_compare( $api_host_available['curl_version'], '7.20.0', '<')){ - echo '

    ' . sprintf( __( 'Your server has an outdated version of the PHP module cURL (Version: %s). Please ask your hosting company to update this to a recent version of cURL. You can read more about that in our %sKnowledge base%s.', $product->get_text_domain() ), $api_host_available['curl_version'], '', '' ) . '

    '; -} - -// Output form tags if we're not embedded in another form -if( ! $embedded ) { - echo '
    '; -} - -wp_nonce_field( $nonce_name, $nonce_name ); ?> - - - - - - - - - - - - - - - - -
    get_text_domain() ); ?> - license_is_valid() ) { ?> - get_text_domain() ); ?>   -   get_text_domain() ); ?> - - get_text_domain() ); ?>   -   not receiving updates.', $product->get_text_domain() ); ?> - -
    get_text_domain() ); ?> - - license_is_valid() ) { ?> -   - get_text_domain() ); ?> - get_license_key() !== '') { ?> -   - get_text_domain() ); - } - - } ?> - -
    get_text_domain() ); ?> - /> - license_constant_is_defined ) { ?> -

    get_text_domain() ), '' . $this->license_constant_name . '' ); ?>

    - -
    - -license_is_valid() ) { - - $expiry_date = strtotime( $this->get_license_expiry_date() ); - - if( $expiry_date !== false ) { - echo '

    '; - - printf( __( 'Your %s license will expire on %s.', $product->get_text_domain() ), $product->get_item_name(), date('F jS Y', $expiry_date ) ); - - if( strtotime( '+3 months' ) > $expiry_date ) { - printf( ' ' . __('%sRenew your license now%s.', $product->get_text_domain() ), '', '' ); - } - - echo '

    '; - } -} - -// Only show a "Save Changes" button and end form if we're not embedded in another form. -if( ! $embedded ) { - - // only show "Save Changes" button if license is not activated and not defined with a constant - if( $readonly === false && $api_host_available['availability'] === true ) { - submit_button(); - } - - echo '
    '; -} - -$product = null; diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/views/index.php b/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/views/index.php deleted file mode 100644 index 12c197f3..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/license-manager/views/index.php +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/CHANGELOG.md b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/CHANGELOG.md deleted file mode 100644 index 061c690f..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/CHANGELOG.md +++ /dev/null @@ -1,34 +0,0 @@ -# Change Log -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/) -and this project adheres to [Semantic Versioning](http://semver.org/). - -## [1.1.0] -### Added -* Allow WordPress messages to be dismissed for a period of 4 weeks. - -## [1.0.1] -### Fixed -* Fix a missing link when the PHP message is switched to the WordPress.org hosting page. - -## [1.0.0] -### Changed -* Updated screenshot in README - -## [1.0.0-beta.2] - 2017-03-11 -### Added -* Complete PHP version message - -### Changed -* Refactor code architecture. -* Use PHP version constant instead of function. - -### Fixed -* Fix broken version reconciliation. - -## 1.0.0-beta.1 - 2017-02-21 -* Initial pre-release of whip. A package to nudge users to upgrade their software versions. - -[Unreleased]: https://github.com/yoast/whip/compare/1.0.0-beta.2...HEAD -[1.0.0-beta.2]: https://github.com/yoast/whip/compare/1.0.0-beta.1...1.0.0-beta.2 diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/LICENSE b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/LICENSE deleted file mode 100644 index 95846861..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Yoast - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/images/wp-message.png b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/images/wp-message.png deleted file mode 100644 index bc168d9e..00000000 Binary files a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/images/wp-message.png and /dev/null differ diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/phpunit.xml b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/phpunit.xml deleted file mode 100644 index 1a13c667..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/phpunit.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - ./tests/ - - - - - - ./src - - - diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_Configuration.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_Configuration.php deleted file mode 100644 index 4b6aa32f..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_Configuration.php +++ /dev/null @@ -1,54 +0,0 @@ -configuration = $configuration; - } - - /** - * Retrieves the configured version of a particular requirement. - * If the requirement does not exist, this returns -1. - * - * @param Whip_Requirement $requirement The requirement to check. - * - * @return int The version of the passed requirement that was detected. - */ - public function configuredVersion( Whip_Requirement $requirement ) { - if ( ! $this->hasRequirementConfigured( $requirement ) ) { - return -1; - } - - return $this->configuration[ $requirement->component() ]; - } - - /** - * Determines whether the passed requirement is present in the configuration. - * - * @param Whip_Requirement $requirement The requirement to check. - * - * @return bool Whether or not the requirement is present in the configuration. - */ - public function hasRequirementConfigured( Whip_Requirement $requirement ) { - return array_key_exists( $requirement->component(), $this->configuration ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_Host.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_Host.php deleted file mode 100644 index 2ae5ecb5..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_Host.php +++ /dev/null @@ -1,88 +0,0 @@ -currentTime = $currentTime; - $this->threshold = $threshold; - $this->storage = $storage; - } - - /** - * Saves the version number to the storage to indicate the message as being dismissed. - */ - public function dismiss() { - $this->storage->set( $this->currentTime ); - } - - /** - * Checks if the current time is lower than the stored time extended by the threshold. - * - * @return bool True when current time is lower than stored value + threshold. - */ - public function isDismissed() { - return ( $this->currentTime <= ( $this->storage->get() + $this->threshold ) ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_MessageFormatter.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_MessageFormatter.php deleted file mode 100644 index edf882dc..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_MessageFormatter.php +++ /dev/null @@ -1,37 +0,0 @@ -' . $toWrap . '
    '; - } - - /** - * Wraps a piece of text in HTML p tags - * - * @param string $toWrap The text to wrap. - * @return string The wrapped text. - */ - public static function paragraph( $toWrap ) { - return '

    ' . $toWrap . '

    '; - } - - /** - * Wraps a piece of text in HTML p and strong tags - * - * @param string $toWrap The text to wrap. - * @return string The wrapped text. - */ - public static function strongParagraph( $toWrap ) { - return self::paragraph( self::strong( $toWrap ) ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_MessagesManager.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_MessagesManager.php deleted file mode 100644 index 1d900bfd..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_MessagesManager.php +++ /dev/null @@ -1,83 +0,0 @@ - 0; - } - - /** - * Lists the messages that are currently available. - * - * @return array The messages that are currently set. - */ - public function listMessages() { - return $GLOBALS[ 'whip_messages' ]; - } - - /** - * Deletes all messages. - */ - public function deleteMessages() { - unset( $GLOBALS[ 'whip_messages' ] ); - } - - /** - * Gets the latest message. - * - * @return Whip_Message The message. Returns a NullMessage if none is found. - */ - public function getLatestMessage() { - if ( ! $this->hasMessages() ) { - return new Whip_NullMessage(); - } - - $messages = $this->sortByVersion( $this->listMessages() ); - - $this->deleteMessages(); - - return array_pop( $messages ); - } - - /** - * Sorts the list of messages based on the version number. - * - * @param array $messages The list of messages to sort. - * - * @return array The sorted list of messages. - */ - private function sortByVersion( array $messages ) { - uksort( $messages, 'version_compare' ); - - return $messages; - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_RequirementsChecker.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_RequirementsChecker.php deleted file mode 100644 index 17ceaef2..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_RequirementsChecker.php +++ /dev/null @@ -1,148 +0,0 @@ -requirements = array(); - $this->configuration = new Whip_Configuration( $configuration ); - $this->messageMananger = new Whip_MessagesManager(); - $this->textdomain = $textdomain; - } - - /** - * Adds a requirement to the list of requirements if it doesn't already exist. - * - * @param Whip_Requirement $requirement The requirement to add. - */ - public function addRequirement( Whip_Requirement $requirement ) { - // Only allow unique entries to ensure we're not checking specific combinations multiple times - if ( $this->requirementExistsForComponent( $requirement->component() ) ) { - return; - } - - $this->requirements[] = $requirement; - } - - /** - * Determines whether or not there are requirements available. - * - * @return bool Whether or not there are requirements. - */ - public function hasRequirements() { - return $this->totalRequirements() > 0; - } - - /** - * Gets the total amount of requirements. - * - * @return int The total amount of requirements. - */ - public function totalRequirements() { - return count( $this->requirements ); - } - - /** - * Determines whether or not a requirement exists for a particular component. - * - * @param string $component The component to check for. - * - * @return bool Whether or not the component has a requirement defined. - */ - public function requirementExistsForComponent( $component ) { - foreach ( $this->requirements as $requirement ) { - if ( $requirement->component() === $component ) { - return true; - } - } - - return false; - } - - /** - * Determines whether a requirement has been fulfilled. - * - * @param Whip_Requirement $requirement The requirement to check. - * - * @return bool Whether or not the requirement is fulfilled. - */ - private function requirementIsFulfilled( Whip_Requirement $requirement ) { - $available_version = $this->configuration->configuredVersion( $requirement ); - $required_version = $requirement->version(); - - if ( in_array( $requirement->operator(), array( '=', '==', '===' ), true ) ) { - return -1 !== version_compare( $available_version, $required_version ); - } - - return version_compare( $available_version, $required_version, $requirement->operator() ); - } - - /** - * Checks if all requirements are fulfilled and adds a message to the message manager if necessary. - */ - public function check() { - foreach ( $this->requirements as $requirement ) { - // Match against config - $requirement_fulfilled = $this->requirementIsFulfilled( $requirement ); - - if ( $requirement_fulfilled ) { - continue; - } - - $this->addMissingRequirementMessage( $requirement ); - } - } - - /** - * Adds a message to the message manager for requirements that cannot be fulfilled. - * - * @param Whip_Requirement $requirement The requirement that cannot be fulfilled. - */ - private function addMissingRequirementMessage( Whip_Requirement $requirement ) { - switch ( $requirement->component() ) { - case 'php': - $this->messageMananger->addMessage( new Whip_UpgradePhpMessage( $this->textdomain ) ); - break; - default: - $this->messageMananger->addMessage( new Whip_InvalidVersionRequirementMessage( $requirement, $this->configuration->configuredVersion( $requirement ) ) ); - break; - } - } - - /** - * Determines whether or not there are messages available. - * - * @return bool Whether or not there are messages to display. - */ - public function hasMessages() { - return $this->messageMananger->hasMessages(); - } - - /** - * Gets the most recent message from the message manager. - * - * @return Whip_Message The latest message. - */ - public function getMostRecentMessage() { - return $this->messageMananger->getLatestMessage(); - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_VersionRequirement.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_VersionRequirement.php deleted file mode 100644 index d12df827..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_VersionRequirement.php +++ /dev/null @@ -1,133 +0,0 @@ -validateParameters( $component, $version, $operator ); - - $this->component = $component; - $this->version = $version; - $this->operator = $operator; - } - - /** - * Gets the component name defined for the requirement. - * - * @return string The component name. - */ - public function component() { - return $this->component; - } - - /** - * Gets the components version defined for the requirement. - * - * @return string - */ - public function version() { - return $this->version; - } - - /** - * Returns the operator to use when comparing version numbers. - * - * @return string The comparison operator. - */ - public function operator() { - return $this->operator; - } - - /** - * Creates a new version requirement from a comparison string - * - * @throws Whip_InvalidVersionComparisonString When an invalid version comparison string is passed. - * -*@param string $component The component for this version requirement. - * @param string $comparisonString The comparison string for this version requirement. - * -*@returns Whip_VersionRequirement The parsed version requirement. - */ - public static function fromCompareString( $component, $comparisonString ) { - - $matcher = '(' . - '(>=?)' . // Matches >= and >. - '|' . - '(<=?)' . // Matches <= and <. - ')' . - '([^>=<\s]+)'; // Matches anything except >, <, =, and whitespace. - - if ( ! preg_match( '#' . $matcher . '#', $comparisonString, $match ) ) { - throw new Whip_InvalidVersionComparisonString( $comparisonString ); - } - - $version = $match[4]; - $operator = $match[1]; - - return new Whip_VersionRequirement( $component, $version, $operator ); - } - - /** - * Validates the parameters passed to the requirement. - * - * @param string $component The component name. - * @param string $version The component version. - * @param string $operator The operator to use when comparing version. - * - * @throws Whip_EmptyProperty - * @throws Whip_InvalidOperatorType - * @throws Whip_InvalidType - */ - private function validateParameters( $component, $version, $operator ) { - if ( empty( $component ) ) { - throw new Whip_EmptyProperty( 'Component' ); - } - - if ( !is_string( $component ) ) { - throw new Whip_InvalidType( 'Component', 'string', $component ); - } - - if ( empty( $version ) ) { - throw new Whip_EmptyProperty( 'Version' ); - } - - if ( !is_string( $version ) ) { - throw new Whip_InvalidType( 'Version', 'string', $version ); - } - - if ( empty( $operator ) ) { - throw new Whip_EmptyProperty( 'Operator' ); - } - - if ( !is_string( $operator ) ) { - throw new Whip_InvalidType( 'Operator', 'string', $operator ); - } - - if ( ! in_array( $operator, array( '=', '==', '===', '<', '>', '<=', '>=' ), true ) ) { - throw new Whip_InvalidOperatorType( $operator ); - } - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_WPDismissOption.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_WPDismissOption.php deleted file mode 100644 index c8f98b0f..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_WPDismissOption.php +++ /dev/null @@ -1,36 +0,0 @@ -optionName, $dismissedValue ); - } - - /** - * Returns the value of the whip_dismissed option. - * - * @return int Returns the value of the option or an empty string when not set. - */ - public function get() { - $dismissedOption = get_option( $this->optionName ); - if ( ! $dismissedOption ) { - return 0; - } - - return (int) $dismissedOption; - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_WPMessageDismissListener.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_WPMessageDismissListener.php deleted file mode 100644 index 01a3d874..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/Whip_WPMessageDismissListener.php +++ /dev/null @@ -1,51 +0,0 @@ -dismisser = $dismisser; - } - - /** - * Listens to a GET request to fetch the required attributes. - * - * @return void - */ - public function listen() { - $action = filter_input( INPUT_GET, 'action' ); - $nonce = filter_input( INPUT_GET, 'nonce' ); - - if ( $action === self::ACTION_NAME && wp_verify_nonce( $nonce, self::ACTION_NAME ) ) { - $this->dismisser->dismiss(); - } - } - - /** - * Creates an url for dismissing the notice. - * - * @return string The url for dismissing the message. - */ - public function getDismissURL() { - return sprintf( - admin_url( 'index.php?action=%1$s&nonce=%2$s' ), - self::ACTION_NAME, - wp_create_nonce( self::ACTION_NAME ) - ); - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/configs/default.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/configs/default.php deleted file mode 100644 index b83c8b18..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/configs/default.php +++ /dev/null @@ -1,5 +0,0 @@ - PHP_VERSION, -); diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/configs/version.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/configs/version.php deleted file mode 100644 index 9890dce9..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/configs/version.php +++ /dev/null @@ -1,3 +0,0 @@ -', '<=', '>=' ); - - /** - * InvalidOperatorType constructor. - * - * @param string $value - */ - public function __construct( $value ) { - parent::__construct( - sprintf( 'Invalid operator of %s used. Please use one of the following operators: %s', - $value, - implode( ', ', $this->validOperators ) - ) ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/exceptions/Whip_InvalidType.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/exceptions/Whip_InvalidType.php deleted file mode 100644 index 9801d91b..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/exceptions/Whip_InvalidType.php +++ /dev/null @@ -1,18 +0,0 @@ -=5.3. Passed version comparison string: %s', - $value - ) - ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/facades/wordpress.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/facades/wordpress.php deleted file mode 100644 index 524593a0..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/facades/wordpress.php +++ /dev/null @@ -1,36 +0,0 @@ - $versionComparison ) { - $checker->addRequirement( Whip_VersionRequirement::fromCompareString( $component, $versionComparison ) ); - } - - $checker->check(); - - if ( ! $checker->hasMessages() ) { - return; - } - - $dismissThreshold = WEEK_IN_SECONDS * 4; - $dismissMessage = __( 'Remind me again in 4 weeks.', 'wordpress' ); - - $dismisser = new Whip_MessageDismisser( time(), $dismissThreshold, new Whip_WPDismissOption() ); - - $presenter = new Whip_WPMessagePresenter( $checker->getMostRecentMessage(), $dismisser, $dismissMessage ); - $presenter->register_hooks(); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/interfaces/Whip_DismissStorage.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/interfaces/Whip_DismissStorage.php deleted file mode 100644 index e0716e15..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/interfaces/Whip_DismissStorage.php +++ /dev/null @@ -1,24 +0,0 @@ -validateParameters( $body ); - - $this->body = $body; - } - - /** - * @return string - */ - public function body() { - return $this->body; - } - - private function validateParameters( $body ) { - if ( empty( $body ) ) { - throw new Whip_EmptyProperty( 'Message body' ); - } - - if ( ! is_string( $body ) ) { - throw new Whip_InvalidType( 'Message body', "string", $body ); - } - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/messages/Whip_HostMessage.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/messages/Whip_HostMessage.php deleted file mode 100644 index a210058a..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/messages/Whip_HostMessage.php +++ /dev/null @@ -1,56 +0,0 @@ -textdomain = $textdomain; - $this->messageKey = $messageKey; - } - - /** - * Renders the message body. - * - * @return string The message body. - */ - public function body() { - $message = array(); - - $message[] = Whip_MessageFormatter::strong( $this->title() ) . '
    '; - $message[] = Whip_MessageFormatter::paragraph( Whip_Host::message( $this->messageKey, $this->filterKey ) ); - - return implode( $message, "\n" ); - } - - /** - * Renders the message title. - * - * @return string The message title. - */ - public function title() { - return sprintf( __( 'A message from %1$s', $this->textdomain ), Whip_Host::name() ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/messages/Whip_InvalidVersionRequirementMessage.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/messages/Whip_InvalidVersionRequirementMessage.php deleted file mode 100644 index 2db06295..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/messages/Whip_InvalidVersionRequirementMessage.php +++ /dev/null @@ -1,37 +0,0 @@ -requirement = $requirement; - $this->detected = $detected; - } - - /** - * @return string - */ - public function body() { - return sprintf( - 'Invalid version detected for %s. Found %s but expected %s.', - $this->requirement->component(), - $this->detected, - $this->requirement->version() - ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/messages/Whip_NullMessage.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/messages/Whip_NullMessage.php deleted file mode 100644 index 1fea0924..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/messages/Whip_NullMessage.php +++ /dev/null @@ -1,13 +0,0 @@ -textdomain = $textdomain; - } - - /** - * Composes the body of the message to display. - * - * @return string The message to display. - */ - public function body() { - $textdomain = $this->textdomain; - - $message = array(); - - $message[] = Whip_MessageFormatter::strongParagraph( __( 'Your site could be faster and more secure with a newer PHP version.', $textdomain ) ) . '
    '; - $message[] = Whip_MessageFormatter::paragraph( __( 'Hey, we\'ve noticed that you\'re running an outdated version of PHP. PHP is the programming language that WordPress and Yoast SEO are built on. The version that is currently used for your site is no longer supported. Newer versions of PHP are both faster and more secure. In fact, your version of PHP no longer receives security updates, which is why we\'re sending you to this notice.', $textdomain ) ); - $message[] = Whip_MessageFormatter::paragraph( __( 'Hosts have the ability to update your PHP version, but sometimes they don\'t dare to do that because they\'re afraid they\'ll break your site.', $textdomain ) ); - $message[] = Whip_MessageFormatter::strongParagraph( __( 'To which version should I update?', $textdomain ) ) . '
    '; - $message[] = Whip_MessageFormatter::paragraph( sprintf( __( 'You should update your PHP version to either 5.6 or to 7.0 or 7.1. On a normal WordPress site, switching to PHP 5.6 should never cause issues. We would however actually recommend you switch to PHP7. There are some plugins that are not ready for PHP7 though, so do some testing first. We have an article on how to test whether that\'s an option for you %1$shere%2$s. PHP7 is much faster than PHP 5.6. It\'s also the only PHP version still in active development and therefore the better option for your site in the long run.', $textdomain ), '', '' ) ); - - if ( Whip_Host::name() !== '' ) { - $hostMessage = new Whip_HostMessage( 'WHIP_MESSAGE_FROM_HOST_ABOUT_PHP', $textdomain ); - $message[] = $hostMessage->body(); - } - - $hostingPageUrl = Whip_Host::hostingPageUrl(); - - $message[] = Whip_MessageFormatter::strongParagraph( __( 'Can\'t update? Ask your host!', $textdomain ) ) . '
    '; - - if ( function_exists( 'apply_filters' ) && apply_filters( Whip_Host::HOSTING_PAGE_FILTER_KEY, false ) ) { - $message[] = Whip_MessageFormatter::paragraph( sprintf( __( 'If you cannot upgrade your PHP version yourself, you can send an email to your host. We have %1$sexamples here%2$s. If they don\'t want to upgrade your PHP version, we would suggest you switch hosts. Have a look at one of the recommended %3$sWordPress hosting partners%4$s.', $textdomain ), '', '', sprintf( '', esc_url( $hostingPageUrl ) ), '' ) ); - } else { - $message[] = Whip_MessageFormatter::paragraph( sprintf( __( 'If you cannot upgrade your PHP version yourself, you can send an email to your host. We have %1$sexamples here%2$s. If they don\'t want to upgrade your PHP version, we would suggest you switch hosts. Have a look at one of our recommended %3$sWordPress hosting partners%4$s, they\'ve all been vetted by our Yoast support team and provide all the features a modern host should provide.', $textdomain ), '', '', sprintf( '', esc_url( $hostingPageUrl ) ), '' ) ); - } - - return implode( $message, "\n" ); - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/presenters/Whip_WPMessagePresenter.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/presenters/Whip_WPMessagePresenter.php deleted file mode 100644 index 90e71a95..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/src/presenters/Whip_WPMessagePresenter.php +++ /dev/null @@ -1,83 +0,0 @@ -message = $message; - $this->dismisser = $dismisser; - $this->dismissMessage = $dismissMessage; - } - - /** - * Registers hooks to WordPress. This is a separate function so you can - * control when the hooks are registered. - * - */ - public function register_hooks() { - global $whip_admin_notices_added; - - if ( null === $whip_admin_notices_added || ! $whip_admin_notices_added ) { - add_action( 'admin_notices', array( $this, 'renderMessage' ) ); - $whip_admin_notices_added = true; - } - } - - /** - * Renders the messages present in the global to notices. - */ - public function renderMessage() { - $dismissListener = new Whip_WPMessageDismissListener( $this->dismisser ); - $dismissListener->listen(); - - if ( $this->dismisser->isDismissed() ) { - return; - } - - $dismissButton = sprintf( - '%1$s', - $this->dismissMessage, - $dismissListener->getDismissURL() - ); - - printf( '

    %1$s

    %2$s

    ', $this->kses( $this->message->body() ), $dismissButton ); - } - - /** - * Removes content from the message that we don't want to show. - * - * @param string $message The message to clean. - * - * @return string The cleaned message. - */ - public function kses( $message ) { - return wp_kses( $message, array( - 'a' => array( - 'href' => true, - 'target' => true, - ), - 'strong' => true, - 'p' => true, - 'ul' => true, - 'li' => true, - ) ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/ConfigurationTest.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/ConfigurationTest.php deleted file mode 100644 index 10f91e2a..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/ConfigurationTest.php +++ /dev/null @@ -1,62 +0,0 @@ - '5.6' ) ); - $requirement = $this->getMockBuilder( 'Whip_Requirement' ) - ->setMethods( array( 'component' ) ) - ->getMock(); - - $requirement - ->expects( $this->any() ) - ->method( 'component' ) - ->will( $this->returnValue( 'mysql' ) ); - - $this->assertEquals( -1, $configuration->configuredVersion( $requirement ) ); - } - - public function testItReturnsAnEntryIfRequirementIsFound() { - $configuration = new Whip_Configuration( array( 'php' => '5.6' ) ); - $requirement = $this->getMockBuilder( 'Whip_Requirement' ) - ->setMethods( array( 'component' ) ) - ->getMock(); - - $requirement - ->expects( $this->any() ) - ->method( 'component' ) - ->will( $this->returnValue( 'php' ) ); - - $this->assertEquals( '5.6', $configuration->configuredVersion( $requirement ) ); - } - - public function testIfRequirementIsConfigured() { - $configuration = new Whip_Configuration( array( 'php' => '5.6' ) ); - $requirement = $this->getMockBuilder( 'Whip_Requirement' ) - ->setMethods( array( 'component' ) ) - ->getMock(); - - $requirement - ->expects( $this->any() ) - ->method( 'component' ) - ->will( $this->returnValue( 'php' ) ); - - $falseRequirement = $this->getMockBuilder( 'Whip_Requirement' ) - ->setMethods( array( 'component' ) ) - ->getMock(); - - $falseRequirement - ->expects( $this->any() ) - ->method( 'component' ) - ->will( $this->returnValue( 'mysql' ) ); - - $this->assertTrue( $configuration->hasRequirementConfigured( $requirement ) ); - $this->assertFalse( $configuration->hasRequirementConfigured( $falseRequirement ) ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/MessageDismisserTest.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/MessageDismisserTest.php deleted file mode 100644 index d5b0931b..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/MessageDismisserTest.php +++ /dev/null @@ -1,86 +0,0 @@ -dismissed = $dismissedValue; - - return true; - } - - /** - * Returns the value. - * - * @return int - */ - public function get() { - return $this->dismissed; - } -} - -class MessageDismisserTest extends PHPUnit_Framework_TestCase { - - /** - * @covers Whip_MessageDismisser::__construct() - * @covers Whip_MessageDismisser::dismiss() - */ - public function testDismiss() { - $currentTime = time(); - $storage = new Whip_DismissStorageMock(); - $dismisser = new Whip_MessageDismisser( $currentTime, WEEK_IN_SECONDS * 4, $storage ); - - $this->assertEquals( 0, $storage->get() ); - - $dismisser->dismiss(); - - $this->assertEquals( $currentTime, $storage->get() ); - } - - /** - * @dataProvider versionNumbersProvider - * - * @param int $savedTime The saved time. - * @param int $currentTime The current time. - * @param bool $expected The expected value. - * - * @covers Whip_MessageDismisser::__construct() - * @covers Whip_MessageDismisser::isDismissed() - */ - public function testIsDismissibleWithVersions( $savedTime, $currentTime, $expected ) { - $storage = new Whip_DismissStorageMock(); - $storage->set( $savedTime ); - $dismisser = new Whip_MessageDismisser( $currentTime, WEEK_IN_SECONDS * 4, $storage ); - - $this->assertEquals( $expected, $dismisser->isDismissed() ); - } - - /** - * Provides array with test values. - * - * @return array - */ - public function versionNumbersProvider() { - return array( - array( strtotime( "-2weeks" ), time(), true ), - array( strtotime( "-4weeks" ), time(), true ), - array( strtotime( "-6weeks" ), time(), false ), - array( time(), time(), true ), - ); - } - -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/MessageTest.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/MessageTest.php deleted file mode 100644 index 1775724f..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/MessageTest.php +++ /dev/null @@ -1,23 +0,0 @@ -assertNotEmpty($message->body()); - } - - /** - * @expectedException Whip_EmptyProperty - */ - public function testMessageCannotBeEmpty() { - new Whip_BasicMessage( '' ); - } - - /** - * @expectedException Whip_InvalidType - */ - public function testMessageMustBeString() { - new Whip_BasicMessage( 123 ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/MessagesManagerTest.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/MessagesManagerTest.php deleted file mode 100644 index 0a9dae28..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/MessagesManagerTest.php +++ /dev/null @@ -1,14 +0,0 @@ -assertFalse( $manager->hasMessages() ); - - $GLOBALS['whip_messages'][] = 'I am a test message'; - - $this->assertTrue( $manager->hasMessages() ); - - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/RequirementsCheckerTest.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/RequirementsCheckerTest.php deleted file mode 100644 index 8be5e3f6..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/RequirementsCheckerTest.php +++ /dev/null @@ -1,144 +0,0 @@ -addRequirement( new Whip_VersionRequirement( 'php', '5.2' ) ); - - $this->assertTrue( $checker->hasRequirements() ); - $this->assertEquals( 1, $checker->totalRequirements() ); - } - - /** - * @requires PHP 7 - */ - public function testItThrowsAnTypeErrorWhenInvalidRequirementIsPassed() { - if ( version_compare( phpversion(), 7.0, '<' ) ) { - $this->markTestSkipped( 'Skipped due to incompatible PHP version.' ); - } - - $exceptionCaught = false; - - $checker = new Whip_RequirementsChecker(); - - try { - $checker->addRequirement( new stdClass() ); - } catch( Error $e ) { - $exceptionCaught = true; - } - - $this->assertTrue( $exceptionCaught ); - } - - public function testItThrowsAnTypeErrorWhenInvalidRequirementIsPassedInPHP5() { - if ( version_compare( phpversion(), 7.0, '>=' ) ) { - $this->markTestSkipped(); - } - - $exceptionCaught = false; - - $checker = new Whip_RequirementsChecker(); - - try { - $checker->addRequirement( new stdClass() ); - } catch( Exception $e ) { - $exceptionCaught = true; - } - - $this->assertTrue( $exceptionCaught ); - } - - public function testItOnlyContainsUniqueComponents() { - $checker = new Whip_RequirementsChecker(); - - $checker->addRequirement( new Whip_VersionRequirement( 'php', '5.2' ) ); - $checker->addRequirement( new Whip_VersionRequirement( 'mysql', '5.6' ) ); - - $this->assertTrue( $checker->hasRequirements() ); - $this->assertEquals( 2, $checker->totalRequirements() ); - - $checker->addRequirement( new Whip_VersionRequirement( 'php', '6' ) ); - - $this->assertEquals( 2, $checker->totalRequirements() ); - } - - public function testIfRequirementExists() { - $checker = new Whip_RequirementsChecker(); - - $checker->addRequirement( new Whip_VersionRequirement( 'php', '5.2' ) ); - $checker->addRequirement( new Whip_VersionRequirement( 'mysql', '5.6' ) ); - - $this->assertTrue( $checker->requirementExistsForComponent( 'php' ) ); - $this->assertFalse( $checker->requirementExistsForComponent( 'mongodb' ) ); - } - - public function testCheckIfRequirementIsFulfilled() { - $checker = new Whip_RequirementsChecker( array( 'php' => phpversion() ) ); - - $checker->addRequirement( new Whip_VersionRequirement( 'php', '5.2' ) ); - $checker->check(); - - $this->assertEmpty( $checker->getMostRecentMessage()->body() ); - } - - public function testCheckIfPHPRequirementIsNotFulfilled() { - $checker = new Whip_RequirementsChecker( array( 'php' => 4 ) ); - - $checker->addRequirement( new Whip_VersionRequirement( 'php', '5.6' ) ); - $checker->check(); - - $this->assertTrue( $checker->hasMessages() ); - - // Get the message. This will unset the global. - $recentMessage = $checker->getMostRecentMessage(); - - $this->assertNotEmpty( $recentMessage ); - $this->assertInternalType( 'string', $recentMessage->body() ); - $this->assertFalse( $checker->hasMessages() ); - $this->assertInstanceOf( 'Whip_UpgradePhpMessage', $recentMessage ); - } - - public function testCheckIfRequirementIsNotFulfilled() { - $checker = new Whip_RequirementsChecker( array( 'mysql' => 4 ) ); - - $checker->addRequirement( new Whip_VersionRequirement( 'mysql', '5.6' ) ); - $checker->check(); - - $this->assertTrue( $checker->hasMessages() ); - - // Get the message. This will unset the global. - $recentMessage = $checker->getMostRecentMessage(); - - $this->assertNotEmpty( $recentMessage ); - $this->assertFalse( $checker->hasMessages() ); - $this->assertInstanceOf( 'Whip_InvalidVersionRequirementMessage', $recentMessage ); - $this->assertStringStartsWith( 'Invalid version detected', $recentMessage->body() ); - } - - public function testCheckIfRequirementIsFulfilledWithSpecificComparison() { - $checker = new Whip_RequirementsChecker( array( 'php' => 4 ) ); - - $checker->addRequirement( new Whip_VersionRequirement( 'php', '5.2', '<' ) ); - $checker->check(); - - $this->assertFalse( $checker->hasMessages() ); - } - - public function testCheckIfRequirementIsNotFulfilledWithSpecificComparison() { - $checker = new Whip_RequirementsChecker( array( 'php' => 4 ) ); - - $checker->addRequirement( new Whip_VersionRequirement( 'php', '5.2', '>=' ) ); - $checker->check(); - - $this->assertTrue( $checker->hasMessages() ); - } -} diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/VersionRequirementTest.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/VersionRequirementTest.php deleted file mode 100644 index f0b5966b..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/VersionRequirementTest.php +++ /dev/null @@ -1,99 +0,0 @@ -assertNotEmpty($requirement->component()); - $this->assertNotEmpty($requirement->version()); - } - - /** - * @expectedException Whip_EmptyProperty - */ - public function testComponentCannotBeEmpty() { - new Whip_VersionRequirement( '', '5.2' ); - } - - /** - * @expectedException Whip_EmptyProperty - */ - public function testVersionCannotBeEmpty() { - new Whip_VersionRequirement( 'php', '' ); - } - - /** - * @expectedException Whip_InvalidType - */ - public function testComponentMustBeString() { - new Whip_VersionRequirement( 123, '5.2' ); - } - - /** - * @expectedException Whip_InvalidType - */ - public function testVersionMustBeString() { - new Whip_VersionRequirement( 'php', 123 ); - } - - /** - * @expectedException Whip_EmptyProperty - */ - public function testOperatorCannotBeEmpty() { - new Whip_VersionRequirement( 'php', '5.6', '' ); - } - - /** - * @expectedException Whip_InvalidType - */ - public function testOperatorMustBeString() { - new Whip_VersionRequirement( 'php', '5.2', 6 ); - } - - /** - * @expectedException Whip_InvalidOperatorType - */ - public function testOperatorMustBeValid() { - new Whip_VersionRequirement( 'php', '5.2', '->' ); - } - - public function testGettingComponentProperties() { - $requirement = new Whip_VersionRequirement( 'php', '5.6' ); - - $this->assertEquals( 'php', $requirement->component() ); - $this->assertEquals( '5.6', $requirement->version() ); - $this->assertEquals( '=', $requirement->operator() ); - } - - /** - * @dataProvider dataFromCompareString - */ - public function testFromCompareString( $expectation, $component, $compareString ) { - $requirement = Whip_VersionRequirement::fromCompareString( $component, $compareString ); - - $this->assertEquals( $expectation[0], $requirement->component() ); - $this->assertEquals( $expectation[1], $requirement->version() ); - $this->assertEquals( $expectation[2], $requirement->operator() ); - } - - public function dataFromCompareString() { - return array( - array( array( 'php', '5.5', '>' ), 'php', '>5.5' ), - array( array( 'php', '5.5', '>=' ), 'php', '>=5.5' ), - array( array( 'php', '5.5', '<' ), 'php', '<5.5' ), - array( array( 'php', '5.5', '<=' ), 'php', '<=5.5' ), - array( array( 'php', '7.3', '>' ), 'php', '>7.3' ), - array( array( 'php', '7.3', '>=' ), 'php', '>=7.3' ), - array( array( 'php', '7.3', '<' ), 'php', '<7.3' ), - array( array( 'php', '7.3', '<=' ), 'php', '<=7.3' ), - ); - } - - /** - * @expectedException Whip_InvalidVersionComparisonString - */ - public function testFromCompareStringException() { - Whip_VersionRequirement::fromCompareString( 'php', '> 2.3' ); - } -} - diff --git a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/bootstrap.php b/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/bootstrap.php deleted file mode 100644 index e9b85682..00000000 --- a/wp-content/plugins/wordpress-seo/vendor/yoast/whip/tests/bootstrap.php +++ /dev/null @@ -1,5 +0,0 @@ - 'http://www.foo.com/1.0/', + * 'timeout' => 0, + * 'allow_redirects' => false, + * 'proxy' => '192.168.16.1:10' + * ]); + * + * Client configuration settings include the following options: + * + * - handler: (callable) Function that transfers HTTP requests over the + * wire. The function is called with a Psr7\Http\Message\RequestInterface + * and array of transfer options, and must return a + * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a + * Psr7\Http\Message\ResponseInterface on success. "handler" is a + * constructor only option that cannot be overridden in per/request + * options. If no handler is provided, a default handler will be created + * that enables all of the request options below by attaching all of the + * default middleware to the handler. + * - base_uri: (string|UriInterface) Base URI of the client that is merged + * into relative URIs. Can be a string or instance of UriInterface. + * - **: any request option + * + * @param array $config Client configuration settings. + * + * @see \GuzzleHttp\RequestOptions for a list of available request options. + */ + public function __construct(array $config = []) + { + if (!isset($config['handler'])) { + $config['handler'] = \YoastSEO_Vendor\GuzzleHttp\HandlerStack::create(); + } elseif (!\is_callable($config['handler'])) { + throw new \InvalidArgumentException('handler must be a callable'); + } + // Convert the base_uri to a UriInterface + if (isset($config['base_uri'])) { + $config['base_uri'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\uri_for($config['base_uri']); + } + $this->configureDefaults($config); + } + public function __call($method, $args) + { + if (\count($args) < 1) { + throw new \InvalidArgumentException('Magic request methods require a URI and optional options array'); + } + $uri = $args[0]; + $opts = isset($args[1]) ? $args[1] : []; + return \substr($method, -5) === 'Async' ? $this->requestAsync(\substr($method, 0, -5), $uri, $opts) : $this->request($method, $uri, $opts); + } + public function sendAsync(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) + { + // Merge the base URI into the request URI if needed. + $options = $this->prepareDefaults($options); + return $this->transfer($request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')), $options); + } + public function send(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) + { + $options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true; + return $this->sendAsync($request, $options)->wait(); + } + public function requestAsync($method, $uri = '', array $options = []) + { + $options = $this->prepareDefaults($options); + // Remove request modifying parameter because it can be done up-front. + $headers = isset($options['headers']) ? $options['headers'] : []; + $body = isset($options['body']) ? $options['body'] : null; + $version = isset($options['version']) ? $options['version'] : '1.1'; + // Merge the URI into the base URI. + $uri = $this->buildUri($uri, $options); + if (\is_array($body)) { + $this->invalidBody(); + } + $request = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($method, $uri, $headers, $body, $version); + // Remove the option so that they are not doubly-applied. + unset($options['headers'], $options['body'], $options['version']); + return $this->transfer($request, $options); + } + public function request($method, $uri = '', array $options = []) + { + $options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true; + return $this->requestAsync($method, $uri, $options)->wait(); + } + public function getConfig($option = null) + { + return $option === null ? $this->config : (isset($this->config[$option]) ? $this->config[$option] : null); + } + private function buildUri($uri, array $config) + { + // for BC we accept null which would otherwise fail in uri_for + $uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\uri_for($uri === null ? '' : $uri); + if (isset($config['base_uri'])) { + $uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve(\YoastSEO_Vendor\GuzzleHttp\Psr7\uri_for($config['base_uri']), $uri); + } + return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri; + } + /** + * Configures the default options for a client. + * + * @param array $config + */ + private function configureDefaults(array $config) + { + $defaults = ['allow_redirects' => \YoastSEO_Vendor\GuzzleHttp\RedirectMiddleware::$defaultSettings, 'http_errors' => \true, 'decode_content' => \true, 'verify' => \true, 'cookies' => \false]; + // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set. + // We can only trust the HTTP_PROXY environment variable in a CLI + // process due to the fact that PHP has no reliable mechanism to + // get environment variables that start with "HTTP_". + if (\php_sapi_name() == 'cli' && \getenv('HTTP_PROXY')) { + $defaults['proxy']['http'] = \getenv('HTTP_PROXY'); + } + if ($proxy = \getenv('HTTPS_PROXY')) { + $defaults['proxy']['https'] = $proxy; + } + if ($noProxy = \getenv('NO_PROXY')) { + $cleanedNoProxy = \str_replace(' ', '', $noProxy); + $defaults['proxy']['no'] = \explode(',', $cleanedNoProxy); + } + $this->config = $config + $defaults; + if (!empty($config['cookies']) && $config['cookies'] === \true) { + $this->config['cookies'] = new \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar(); + } + // Add the default user-agent header. + if (!isset($this->config['headers'])) { + $this->config['headers'] = ['User-Agent' => default_user_agent()]; + } else { + // Add the User-Agent header if one was not already set. + foreach (\array_keys($this->config['headers']) as $name) { + if (\strtolower($name) === 'user-agent') { + return; + } + } + $this->config['headers']['User-Agent'] = default_user_agent(); + } + } + /** + * Merges default options into the array. + * + * @param array $options Options to modify by reference + * + * @return array + */ + private function prepareDefaults($options) + { + $defaults = $this->config; + if (!empty($defaults['headers'])) { + // Default headers are only added if they are not present. + $defaults['_conditional'] = $defaults['headers']; + unset($defaults['headers']); + } + // Special handling for headers is required as they are added as + // conditional headers and as headers passed to a request ctor. + if (\array_key_exists('headers', $options)) { + // Allows default headers to be unset. + if ($options['headers'] === null) { + $defaults['_conditional'] = null; + unset($options['headers']); + } elseif (!\is_array($options['headers'])) { + throw new \InvalidArgumentException('headers must be an array'); + } + } + // Shallow merge defaults underneath options. + $result = $options + $defaults; + // Remove null values. + foreach ($result as $k => $v) { + if ($v === null) { + unset($result[$k]); + } + } + return $result; + } + /** + * Transfers the given request and applies request options. + * + * The URI of the request is not modified and the request options are used + * as-is without merging in default options. + * + * @param RequestInterface $request + * @param array $options + * + * @return Promise\PromiseInterface + */ + private function transfer(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + // save_to -> sink + if (isset($options['save_to'])) { + $options['sink'] = $options['save_to']; + unset($options['save_to']); + } + // exceptions -> http_errors + if (isset($options['exceptions'])) { + $options['http_errors'] = $options['exceptions']; + unset($options['exceptions']); + } + $request = $this->applyOptions($request, $options); + $handler = $options['handler']; + try { + return \YoastSEO_Vendor\GuzzleHttp\Promise\promise_for($handler($request, $options)); + } catch (\Exception $e) { + return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($e); + } + } + /** + * Applies the array of request options to a request. + * + * @param RequestInterface $request + * @param array $options + * + * @return RequestInterface + */ + private function applyOptions(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options) + { + $modify = ['set_headers' => []]; + if (isset($options['headers'])) { + $modify['set_headers'] = $options['headers']; + unset($options['headers']); + } + if (isset($options['form_params'])) { + if (isset($options['multipart'])) { + throw new \InvalidArgumentException('You cannot use ' . 'form_params and multipart at the same time. Use the ' . 'form_params option if you want to send application/' . 'x-www-form-urlencoded requests, and the multipart ' . 'option to send multipart/form-data requests.'); + } + $options['body'] = \http_build_query($options['form_params'], '', '&'); + unset($options['form_params']); + // Ensure that we don't have the header in different case and set the new value. + $options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\_caseless_remove(['Content-Type'], $options['_conditional']); + $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded'; + } + if (isset($options['multipart'])) { + $options['body'] = new \YoastSEO_Vendor\GuzzleHttp\Psr7\MultipartStream($options['multipart']); + unset($options['multipart']); + } + if (isset($options['json'])) { + $options['body'] = \YoastSEO_Vendor\GuzzleHttp\json_encode($options['json']); + unset($options['json']); + // Ensure that we don't have the header in different case and set the new value. + $options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\_caseless_remove(['Content-Type'], $options['_conditional']); + $options['_conditional']['Content-Type'] = 'application/json'; + } + if (!empty($options['decode_content']) && $options['decode_content'] !== \true) { + // Ensure that we don't have the header in different case and set the new value. + $options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']); + $modify['set_headers']['Accept-Encoding'] = $options['decode_content']; + } + if (isset($options['body'])) { + if (\is_array($options['body'])) { + $this->invalidBody(); + } + $modify['body'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($options['body']); + unset($options['body']); + } + if (!empty($options['auth']) && \is_array($options['auth'])) { + $value = $options['auth']; + $type = isset($value[2]) ? \strtolower($value[2]) : 'basic'; + switch ($type) { + case 'basic': + // Ensure that we don't have the header in different case and set the new value. + $modify['set_headers'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\_caseless_remove(['Authorization'], $modify['set_headers']); + $modify['set_headers']['Authorization'] = 'Basic ' . \base64_encode("{$value[0]}:{$value[1]}"); + break; + case 'digest': + // @todo: Do not rely on curl + $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_DIGEST; + $options['curl'][\CURLOPT_USERPWD] = "{$value[0]}:{$value[1]}"; + break; + case 'ntlm': + $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM; + $options['curl'][\CURLOPT_USERPWD] = "{$value[0]}:{$value[1]}"; + break; + } + } + if (isset($options['query'])) { + $value = $options['query']; + if (\is_array($value)) { + $value = \http_build_query($value, null, '&', \PHP_QUERY_RFC3986); + } + if (!\is_string($value)) { + throw new \InvalidArgumentException('query must be a string or array'); + } + $modify['query'] = $value; + unset($options['query']); + } + // Ensure that sink is not an invalid value. + if (isset($options['sink'])) { + // TODO: Add more sink validation? + if (\is_bool($options['sink'])) { + throw new \InvalidArgumentException('sink must not be a boolean'); + } + } + $request = \YoastSEO_Vendor\GuzzleHttp\Psr7\modify_request($request, $modify); + if ($request->getBody() instanceof \YoastSEO_Vendor\GuzzleHttp\Psr7\MultipartStream) { + // Use a multipart/form-data POST if a Content-Type is not set. + // Ensure that we don't have the header in different case and set the new value. + $options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\_caseless_remove(['Content-Type'], $options['_conditional']); + $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' . $request->getBody()->getBoundary(); + } + // Merge in conditional headers if they are not present. + if (isset($options['_conditional'])) { + // Build up the changes so it's in a single clone of the message. + $modify = []; + foreach ($options['_conditional'] as $k => $v) { + if (!$request->hasHeader($k)) { + $modify['set_headers'][$k] = $v; + } + } + $request = \YoastSEO_Vendor\GuzzleHttp\Psr7\modify_request($request, $modify); + // Don't pass this internal value along to middleware/handlers. + unset($options['_conditional']); + } + return $request; + } + private function invalidBody() + { + throw new \InvalidArgumentException('Passing in the "body" request ' . 'option as an array to send a POST request has been deprecated. ' . 'Please use the "form_params" request option to send a ' . 'application/x-www-form-urlencoded request, or the "multipart" ' . 'request option to send a multipart/form-data request.'); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/ClientInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/ClientInterface.php new file mode 100644 index 00000000..b958f311 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/ClientInterface.php @@ -0,0 +1,79 @@ +strictMode = $strictMode; + foreach ($cookieArray as $cookie) { + if (!$cookie instanceof \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie) { + $cookie = new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie); + } + $this->setCookie($cookie); + } + } + /** + * Create a new Cookie jar from an associative array and domain. + * + * @param array $cookies Cookies to create the jar from + * @param string $domain Domain to set the cookies to + * + * @return self + */ + public static function fromArray(array $cookies, $domain) + { + $cookieJar = new self(); + foreach ($cookies as $name => $value) { + $cookieJar->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie(['Domain' => $domain, 'Name' => $name, 'Value' => $value, 'Discard' => \true])); + } + return $cookieJar; + } + /** + * @deprecated + */ + public static function getCookieValue($value) + { + return $value; + } + /** + * Evaluate if this cookie should be persisted to storage + * that survives between requests. + * + * @param SetCookie $cookie Being evaluated. + * @param bool $allowSessionCookies If we should persist session cookies + * @return bool + */ + public static function shouldPersist(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie, $allowSessionCookies = \false) + { + if ($cookie->getExpires() || $allowSessionCookies) { + if (!$cookie->getDiscard()) { + return \true; + } + } + return \false; + } + /** + * Finds and returns the cookie based on the name + * + * @param string $name cookie name to search for + * @return SetCookie|null cookie that was found or null if not found + */ + public function getCookieByName($name) + { + // don't allow a null name + if ($name === null) { + return null; + } + foreach ($this->cookies as $cookie) { + if ($cookie->getName() !== null && \strcasecmp($cookie->getName(), $name) === 0) { + return $cookie; + } + } + } + public function toArray() + { + return \array_map(function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) { + return $cookie->toArray(); + }, $this->getIterator()->getArrayCopy()); + } + public function clear($domain = null, $path = null, $name = null) + { + if (!$domain) { + $this->cookies = []; + return; + } elseif (!$path) { + $this->cookies = \array_filter($this->cookies, function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain) { + return !$cookie->matchesDomain($domain); + }); + } elseif (!$name) { + $this->cookies = \array_filter($this->cookies, function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain) { + return !($cookie->matchesPath($path) && $cookie->matchesDomain($domain)); + }); + } else { + $this->cookies = \array_filter($this->cookies, function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain, $name) { + return !($cookie->getName() == $name && $cookie->matchesPath($path) && $cookie->matchesDomain($domain)); + }); + } + } + public function clearSessionCookies() + { + $this->cookies = \array_filter($this->cookies, function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) { + return !$cookie->getDiscard() && $cookie->getExpires(); + }); + } + public function setCookie(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) + { + // If the name string is empty (but not 0), ignore the set-cookie + // string entirely. + $name = $cookie->getName(); + if (!$name && $name !== '0') { + return \false; + } + // Only allow cookies with set and valid domain, name, value + $result = $cookie->validate(); + if ($result !== \true) { + if ($this->strictMode) { + throw new \RuntimeException('Invalid cookie: ' . $result); + } else { + $this->removeCookieIfEmpty($cookie); + return \false; + } + } + // Resolve conflicts with previously set cookies + foreach ($this->cookies as $i => $c) { + // Two cookies are identical, when their path, and domain are + // identical. + if ($c->getPath() != $cookie->getPath() || $c->getDomain() != $cookie->getDomain() || $c->getName() != $cookie->getName()) { + continue; + } + // The previously set cookie is a discard cookie and this one is + // not so allow the new cookie to be set + if (!$cookie->getDiscard() && $c->getDiscard()) { + unset($this->cookies[$i]); + continue; + } + // If the new cookie's expiration is further into the future, then + // replace the old cookie + if ($cookie->getExpires() > $c->getExpires()) { + unset($this->cookies[$i]); + continue; + } + // If the value has changed, we better change it + if ($cookie->getValue() !== $c->getValue()) { + unset($this->cookies[$i]); + continue; + } + // The cookie exists, so no need to continue + return \false; + } + $this->cookies[] = $cookie; + return \true; + } + public function count() + { + return \count($this->cookies); + } + public function getIterator() + { + return new \ArrayIterator(\array_values($this->cookies)); + } + public function extractCookies(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) + { + if ($cookieHeader = $response->getHeader('Set-Cookie')) { + foreach ($cookieHeader as $cookie) { + $sc = \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie::fromString($cookie); + if (!$sc->getDomain()) { + $sc->setDomain($request->getUri()->getHost()); + } + if (0 !== \strpos($sc->getPath(), '/')) { + $sc->setPath($this->getCookiePathFromRequest($request)); + } + $this->setCookie($sc); + } + } + } + /** + * Computes cookie path following RFC 6265 section 5.1.4 + * + * @link https://tools.ietf.org/html/rfc6265#section-5.1.4 + * + * @param RequestInterface $request + * @return string + */ + private function getCookiePathFromRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) + { + $uriPath = $request->getUri()->getPath(); + if ('' === $uriPath) { + return '/'; + } + if (0 !== \strpos($uriPath, '/')) { + return '/'; + } + if ('/' === $uriPath) { + return '/'; + } + if (0 === ($lastSlashPos = \strrpos($uriPath, '/'))) { + return '/'; + } + return \substr($uriPath, 0, $lastSlashPos); + } + public function withCookieHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) + { + $values = []; + $uri = $request->getUri(); + $scheme = $uri->getScheme(); + $host = $uri->getHost(); + $path = $uri->getPath() ?: '/'; + foreach ($this->cookies as $cookie) { + if ($cookie->matchesPath($path) && $cookie->matchesDomain($host) && !$cookie->isExpired() && (!$cookie->getSecure() || $scheme === 'https')) { + $values[] = $cookie->getName() . '=' . $cookie->getValue(); + } + } + return $values ? $request->withHeader('Cookie', \implode('; ', $values)) : $request; + } + /** + * If a cookie already exists and the server asks to set it again with a + * null value, the cookie must be deleted. + * + * @param SetCookie $cookie + */ + private function removeCookieIfEmpty(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) + { + $cookieValue = $cookie->getValue(); + if ($cookieValue === null || $cookieValue === '') { + $this->clear($cookie->getDomain(), $cookie->getPath(), $cookie->getName()); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php new file mode 100644 index 00000000..c766f91a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php @@ -0,0 +1,76 @@ +filename = $cookieFile; + $this->storeSessionCookies = $storeSessionCookies; + if (\file_exists($cookieFile)) { + $this->load($cookieFile); + } + } + /** + * Saves the file when shutting down + */ + public function __destruct() + { + $this->save($this->filename); + } + /** + * Saves the cookies to a file. + * + * @param string $filename File to save + * @throws \RuntimeException if the file cannot be found or created + */ + public function save($filename) + { + $json = []; + foreach ($this as $cookie) { + /** @var SetCookie $cookie */ + if (\YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { + $json[] = $cookie->toArray(); + } + } + $jsonStr = \YoastSEO_Vendor\GuzzleHttp\json_encode($json); + if (\false === \file_put_contents($filename, $jsonStr)) { + throw new \RuntimeException("Unable to save file {$filename}"); + } + } + /** + * Load cookies from a JSON formatted file. + * + * Old cookies are kept unless overwritten by newly loaded ones. + * + * @param string $filename Cookie file to load. + * @throws \RuntimeException if the file cannot be loaded. + */ + public function load($filename) + { + $json = \file_get_contents($filename); + if (\false === $json) { + throw new \RuntimeException("Unable to load file {$filename}"); + } elseif ($json === '') { + return; + } + $data = \YoastSEO_Vendor\GuzzleHttp\json_decode($json, \true); + if (\is_array($data)) { + foreach (\json_decode($json, \true) as $cookie) { + $this->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie)); + } + } elseif (\strlen($data)) { + throw new \RuntimeException("Invalid cookie file: {$filename}"); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php new file mode 100644 index 00000000..000e7266 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php @@ -0,0 +1,66 @@ +sessionKey = $sessionKey; + $this->storeSessionCookies = $storeSessionCookies; + $this->load(); + } + /** + * Saves cookies to session when shutting down + */ + public function __destruct() + { + $this->save(); + } + /** + * Save cookies to the client session + */ + public function save() + { + $json = []; + foreach ($this as $cookie) { + /** @var SetCookie $cookie */ + if (\YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { + $json[] = $cookie->toArray(); + } + } + $_SESSION[$this->sessionKey] = \json_encode($json); + } + /** + * Load the contents of the client session into the data array + */ + protected function load() + { + if (!isset($_SESSION[$this->sessionKey])) { + return; + } + $data = \json_decode($_SESSION[$this->sessionKey], \true); + if (\is_array($data)) { + foreach ($data as $cookie) { + $this->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie)); + } + } elseif (\strlen($data)) { + throw new \RuntimeException("Invalid cookie data"); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SetCookie.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SetCookie.php new file mode 100644 index 00000000..5708c6be --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Cookie/SetCookie.php @@ -0,0 +1,343 @@ + null, 'Value' => null, 'Domain' => null, 'Path' => '/', 'Max-Age' => null, 'Expires' => null, 'Secure' => \false, 'Discard' => \false, 'HttpOnly' => \false]; + /** @var array Cookie data */ + private $data; + /** + * Create a new SetCookie object from a string + * + * @param string $cookie Set-Cookie header string + * + * @return self + */ + public static function fromString($cookie) + { + // Create the default return array + $data = self::$defaults; + // Explode the cookie string using a series of semicolons + $pieces = \array_filter(\array_map('trim', \explode(';', $cookie))); + // The name of the cookie (first kvp) must exist and include an equal sign. + if (empty($pieces[0]) || !\strpos($pieces[0], '=')) { + return new self($data); + } + // Add the cookie pieces into the parsed data array + foreach ($pieces as $part) { + $cookieParts = \explode('=', $part, 2); + $key = \trim($cookieParts[0]); + $value = isset($cookieParts[1]) ? \trim($cookieParts[1], " \n\r\t\0\v") : \true; + // Only check for non-cookies when cookies have been found + if (empty($data['Name'])) { + $data['Name'] = $key; + $data['Value'] = $value; + } else { + foreach (\array_keys(self::$defaults) as $search) { + if (!\strcasecmp($search, $key)) { + $data[$search] = $value; + continue 2; + } + } + $data[$key] = $value; + } + } + return new self($data); + } + /** + * @param array $data Array of cookie data provided by a Cookie parser + */ + public function __construct(array $data = []) + { + $this->data = \array_replace(self::$defaults, $data); + // Extract the Expires value and turn it into a UNIX timestamp if needed + if (!$this->getExpires() && $this->getMaxAge()) { + // Calculate the Expires date + $this->setExpires(\time() + $this->getMaxAge()); + } elseif ($this->getExpires() && !\is_numeric($this->getExpires())) { + $this->setExpires($this->getExpires()); + } + } + public function __toString() + { + $str = $this->data['Name'] . '=' . $this->data['Value'] . '; '; + foreach ($this->data as $k => $v) { + if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== \false) { + if ($k === 'Expires') { + $str .= 'Expires=' . \gmdate('D, d M Y H:i:s \\G\\M\\T', $v) . '; '; + } else { + $str .= ($v === \true ? $k : "{$k}={$v}") . '; '; + } + } + } + return \rtrim($str, '; '); + } + public function toArray() + { + return $this->data; + } + /** + * Get the cookie name + * + * @return string + */ + public function getName() + { + return $this->data['Name']; + } + /** + * Set the cookie name + * + * @param string $name Cookie name + */ + public function setName($name) + { + $this->data['Name'] = $name; + } + /** + * Get the cookie value + * + * @return string + */ + public function getValue() + { + return $this->data['Value']; + } + /** + * Set the cookie value + * + * @param string $value Cookie value + */ + public function setValue($value) + { + $this->data['Value'] = $value; + } + /** + * Get the domain + * + * @return string|null + */ + public function getDomain() + { + return $this->data['Domain']; + } + /** + * Set the domain of the cookie + * + * @param string $domain + */ + public function setDomain($domain) + { + $this->data['Domain'] = $domain; + } + /** + * Get the path + * + * @return string + */ + public function getPath() + { + return $this->data['Path']; + } + /** + * Set the path of the cookie + * + * @param string $path Path of the cookie + */ + public function setPath($path) + { + $this->data['Path'] = $path; + } + /** + * Maximum lifetime of the cookie in seconds + * + * @return int|null + */ + public function getMaxAge() + { + return $this->data['Max-Age']; + } + /** + * Set the max-age of the cookie + * + * @param int $maxAge Max age of the cookie in seconds + */ + public function setMaxAge($maxAge) + { + $this->data['Max-Age'] = $maxAge; + } + /** + * The UNIX timestamp when the cookie Expires + * + * @return mixed + */ + public function getExpires() + { + return $this->data['Expires']; + } + /** + * Set the unix timestamp for which the cookie will expire + * + * @param int $timestamp Unix timestamp + */ + public function setExpires($timestamp) + { + $this->data['Expires'] = \is_numeric($timestamp) ? (int) $timestamp : \strtotime($timestamp); + } + /** + * Get whether or not this is a secure cookie + * + * @return null|bool + */ + public function getSecure() + { + return $this->data['Secure']; + } + /** + * Set whether or not the cookie is secure + * + * @param bool $secure Set to true or false if secure + */ + public function setSecure($secure) + { + $this->data['Secure'] = $secure; + } + /** + * Get whether or not this is a session cookie + * + * @return null|bool + */ + public function getDiscard() + { + return $this->data['Discard']; + } + /** + * Set whether or not this is a session cookie + * + * @param bool $discard Set to true or false if this is a session cookie + */ + public function setDiscard($discard) + { + $this->data['Discard'] = $discard; + } + /** + * Get whether or not this is an HTTP only cookie + * + * @return bool + */ + public function getHttpOnly() + { + return $this->data['HttpOnly']; + } + /** + * Set whether or not this is an HTTP only cookie + * + * @param bool $httpOnly Set to true or false if this is HTTP only + */ + public function setHttpOnly($httpOnly) + { + $this->data['HttpOnly'] = $httpOnly; + } + /** + * Check if the cookie matches a path value. + * + * A request-path path-matches a given cookie-path if at least one of + * the following conditions holds: + * + * - The cookie-path and the request-path are identical. + * - The cookie-path is a prefix of the request-path, and the last + * character of the cookie-path is %x2F ("/"). + * - The cookie-path is a prefix of the request-path, and the first + * character of the request-path that is not included in the cookie- + * path is a %x2F ("/") character. + * + * @param string $requestPath Path to check against + * + * @return bool + */ + public function matchesPath($requestPath) + { + $cookiePath = $this->getPath(); + // Match on exact matches or when path is the default empty "/" + if ($cookiePath === '/' || $cookiePath == $requestPath) { + return \true; + } + // Ensure that the cookie-path is a prefix of the request path. + if (0 !== \strpos($requestPath, $cookiePath)) { + return \false; + } + // Match if the last character of the cookie-path is "/" + if (\substr($cookiePath, -1, 1) === '/') { + return \true; + } + // Match if the first character not included in cookie path is "/" + return \substr($requestPath, \strlen($cookiePath), 1) === '/'; + } + /** + * Check if the cookie matches a domain value + * + * @param string $domain Domain to check against + * + * @return bool + */ + public function matchesDomain($domain) + { + // Remove the leading '.' as per spec in RFC 6265. + // http://tools.ietf.org/html/rfc6265#section-5.2.3 + $cookieDomain = \ltrim($this->getDomain(), '.'); + // Domain not set or exact match. + if (!$cookieDomain || !\strcasecmp($domain, $cookieDomain)) { + return \true; + } + // Matching the subdomain according to RFC 6265. + // http://tools.ietf.org/html/rfc6265#section-5.1.3 + if (\filter_var($domain, \FILTER_VALIDATE_IP)) { + return \false; + } + return (bool) \preg_match('/\\.' . \preg_quote($cookieDomain, '/') . '$/', $domain); + } + /** + * Check if the cookie is expired + * + * @return bool + */ + public function isExpired() + { + return $this->getExpires() !== null && \time() > $this->getExpires(); + } + /** + * Check if the cookie is valid according to RFC 6265 + * + * @return bool|string Returns true if valid or an error message if invalid + */ + public function validate() + { + // Names must not be empty, but can be 0 + $name = $this->getName(); + if (empty($name) && !\is_numeric($name)) { + return 'The cookie name must not be empty'; + } + // Check if any of the invalid characters are present in the cookie name + if (\preg_match('/[\\x00-\\x20\\x22\\x28-\\x29\\x2c\\x2f\\x3a-\\x40\\x5c\\x7b\\x7d\\x7f]/', $name)) { + return 'Cookie name must not contain invalid characters: ASCII ' . 'Control characters (0-31;127), space, tab and the ' . 'following characters: ()<>@,;:\\"/?={}'; + } + // Value must not be empty, but can be 0 + $value = $this->getValue(); + if (empty($value) && !\is_numeric($value)) { + return 'The cookie value must not be empty'; + } + // Domains must not be empty, but can be 0 + // A "0" is not a valid internet domain, but may be used as server name + // in a private network. + $domain = $this->getDomain(); + if (empty($domain) && !\is_numeric($domain)) { + return 'The cookie domain must not be empty'; + } + return \true; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Exception/BadResponseException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Exception/BadResponseException.php new file mode 100644 index 00000000..0c16e489 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Exception/BadResponseException.php @@ -0,0 +1,19 @@ +getStatusCode() : 0; + parent::__construct($message, $code, $previous); + $this->request = $request; + $this->response = $response; + $this->handlerContext = $handlerContext; + } + /** + * Wrap non-RequestExceptions with a RequestException + * + * @param RequestInterface $request + * @param \Exception $e + * + * @return RequestException + */ + public static function wrapException(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \Exception $e) + { + return $e instanceof \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException ? $e : new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($e->getMessage(), $request, null, $e); + } + /** + * Factory method to create a new exception with a normalized error message + * + * @param RequestInterface $request Request + * @param ResponseInterface $response Response received + * @param \Exception $previous Previous exception + * @param array $ctx Optional handler context. + * + * @return self + */ + public static function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Exception $previous = null, array $ctx = []) + { + if (!$response) { + return new self('Error completing request', $request, null, $previous, $ctx); + } + $level = (int) \floor($response->getStatusCode() / 100); + if ($level === 4) { + $label = 'Client error'; + $className = \YoastSEO_Vendor\GuzzleHttp\Exception\ClientException::class; + } elseif ($level === 5) { + $label = 'Server error'; + $className = \YoastSEO_Vendor\GuzzleHttp\Exception\ServerException::class; + } else { + $label = 'Unsuccessful request'; + $className = __CLASS__; + } + $uri = $request->getUri(); + $uri = static::obfuscateUri($uri); + // Client Error: `GET /` resulted in a `404 Not Found` response: + // ... (truncated) + $message = \sprintf('%s: `%s %s` resulted in a `%s %s` response', $label, $request->getMethod(), $uri, $response->getStatusCode(), $response->getReasonPhrase()); + $summary = static::getResponseBodySummary($response); + if ($summary !== null) { + $message .= ":\n{$summary}\n"; + } + return new $className($message, $request, $response, $previous, $ctx); + } + /** + * Get a short summary of the response + * + * Will return `null` if the response is not printable. + * + * @param ResponseInterface $response + * + * @return string|null + */ + public static function getResponseBodySummary(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) + { + $body = $response->getBody(); + if (!$body->isSeekable()) { + return null; + } + $size = $body->getSize(); + if ($size === 0) { + return null; + } + $summary = $body->read(120); + $body->rewind(); + if ($size > 120) { + $summary .= ' (truncated...)'; + } + // Matches any printable character, including unicode characters: + // letters, marks, numbers, punctuation, spacing, and separators. + if (\preg_match('/[^\\pL\\pM\\pN\\pP\\pS\\pZ\\n\\r\\t]/', $summary)) { + return null; + } + return $summary; + } + /** + * Obfuscates URI if there is an username and a password present + * + * @param UriInterface $uri + * + * @return UriInterface + */ + private static function obfuscateUri($uri) + { + $userInfo = $uri->getUserInfo(); + if (\false !== ($pos = \strpos($userInfo, ':'))) { + return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***'); + } + return $uri; + } + /** + * Get the request that caused the exception + * + * @return RequestInterface + */ + public function getRequest() + { + return $this->request; + } + /** + * Get the associated response + * + * @return ResponseInterface|null + */ + public function getResponse() + { + return $this->response; + } + /** + * Check if a response was received + * + * @return bool + */ + public function hasResponse() + { + return $this->response !== null; + } + /** + * Get contextual information about the error from the underlying handler. + * + * The contents of this array will vary depending on which handler you are + * using. It may also be just an empty array. Relying on this data will + * couple you to a specific handler, but can give more debug information + * when needed. + * + * @return array + */ + public function getHandlerContext() + { + return $this->handlerContext; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Exception/SeekException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Exception/SeekException.php new file mode 100644 index 00000000..0869d9f1 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Exception/SeekException.php @@ -0,0 +1,25 @@ +stream = $stream; + $msg = $msg ?: 'Could not seek the stream to position ' . $pos; + parent::__construct($msg); + } + /** + * @return StreamInterface + */ + public function getStream() + { + return $this->stream; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Exception/ServerException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Exception/ServerException.php new file mode 100644 index 00000000..8a9fd9a6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Exception/ServerException.php @@ -0,0 +1,10 @@ +maxHandles = $maxHandles; + } + public function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + if (isset($options['curl']['body_as_string'])) { + $options['_body_as_string'] = $options['curl']['body_as_string']; + unset($options['curl']['body_as_string']); + } + $easy = new \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle(); + $easy->request = $request; + $easy->options = $options; + $conf = $this->getDefaultConf($easy); + $this->applyMethod($easy, $conf); + $this->applyHandlerOptions($easy, $conf); + $this->applyHeaders($easy, $conf); + unset($conf['_headers']); + // Add handler options from the request configuration options + if (isset($options['curl'])) { + $conf = \array_replace($conf, $options['curl']); + } + $conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy); + $easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init(); + \curl_setopt_array($easy->handle, $conf); + return $easy; + } + public function release(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) + { + $resource = $easy->handle; + unset($easy->handle); + if (\count($this->handles) >= $this->maxHandles) { + \curl_close($resource); + } else { + // Remove all callback functions as they can hold onto references + // and are not cleaned up by curl_reset. Using curl_setopt_array + // does not work for some reason, so removing each one + // individually. + \curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null); + \curl_setopt($resource, \CURLOPT_READFUNCTION, null); + \curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null); + \curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null); + \curl_reset($resource); + $this->handles[] = $resource; + } + } + /** + * Completes a cURL transaction, either returning a response promise or a + * rejected promise. + * + * @param callable $handler + * @param EasyHandle $easy + * @param CurlFactoryInterface $factory Dictates how the handle is released + * + * @return \GuzzleHttp\Promise\PromiseInterface + */ + public static function finish(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface $factory) + { + if (isset($easy->options['on_stats'])) { + self::invokeStats($easy); + } + if (!$easy->response || $easy->errno) { + return self::finishError($handler, $easy, $factory); + } + // Return the response if it is present and there is no error. + $factory->release($easy); + // Rewind the body of the response if possible. + $body = $easy->response->getBody(); + if ($body->isSeekable()) { + $body->rewind(); + } + return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($easy->response); + } + private static function invokeStats(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) + { + $curlStats = \curl_getinfo($easy->handle); + $stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($easy->request, $easy->response, $curlStats['total_time'], $easy->errno, $curlStats); + \call_user_func($easy->options['on_stats'], $stats); + } + private static function finishError(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface $factory) + { + // Get error information and release the handle to the factory. + $ctx = ['errno' => $easy->errno, 'error' => \curl_error($easy->handle)] + \curl_getinfo($easy->handle); + $factory->release($easy); + // Retry when nothing is present or when curl failed to rewind. + if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) { + return self::retryFailedRewind($handler, $easy, $ctx); + } + return self::createRejection($easy, $ctx); + } + private static function createRejection(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array $ctx) + { + static $connectionErrors = [\CURLE_OPERATION_TIMEOUTED => \true, \CURLE_COULDNT_RESOLVE_HOST => \true, \CURLE_COULDNT_CONNECT => \true, \CURLE_SSL_CONNECT_ERROR => \true, \CURLE_GOT_NOTHING => \true]; + // If an exception was encountered during the onHeaders event, then + // return a rejected promise that wraps that exception. + if ($easy->onHeadersException) { + return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered during the on_headers event', $easy->request, $easy->response, $easy->onHeadersException, $ctx)); + } + $message = \sprintf('cURL error %s: %s (%s)', $ctx['errno'], $ctx['error'], 'see http://curl.haxx.se/libcurl/c/libcurl-errors.html'); + // Create a connection exception if it was a specific error code. + $error = isset($connectionErrors[$easy->errno]) ? new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException($message, $easy->request, null, $ctx) : new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($message, $easy->request, $easy->response, null, $ctx); + return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($error); + } + private function getDefaultConf(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) + { + $conf = ['_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), \CURLOPT_RETURNTRANSFER => \false, \CURLOPT_HEADER => \false, \CURLOPT_CONNECTTIMEOUT => 150]; + if (\defined('CURLOPT_PROTOCOLS')) { + $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS; + } + $version = $easy->request->getProtocolVersion(); + if ($version == 1.1) { + $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1; + } elseif ($version == 2.0) { + $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0; + } else { + $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0; + } + return $conf; + } + private function applyMethod(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) + { + $body = $easy->request->getBody(); + $size = $body->getSize(); + if ($size === null || $size > 0) { + $this->applyBody($easy->request, $easy->options, $conf); + return; + } + $method = $easy->request->getMethod(); + if ($method === 'PUT' || $method === 'POST') { + // See http://tools.ietf.org/html/rfc7230#section-3.3.2 + if (!$easy->request->hasHeader('Content-Length')) { + $conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0'; + } + } elseif ($method === 'HEAD') { + $conf[\CURLOPT_NOBODY] = \true; + unset($conf[\CURLOPT_WRITEFUNCTION], $conf[\CURLOPT_READFUNCTION], $conf[\CURLOPT_FILE], $conf[\CURLOPT_INFILE]); + } + } + private function applyBody(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, array &$conf) + { + $size = $request->hasHeader('Content-Length') ? (int) $request->getHeaderLine('Content-Length') : null; + // Send the body as a string if the size is less than 1MB OR if the + // [curl][body_as_string] request value is set. + if ($size !== null && $size < 1000000 || !empty($options['_body_as_string'])) { + $conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody(); + // Don't duplicate the Content-Length header + $this->removeHeader('Content-Length', $conf); + $this->removeHeader('Transfer-Encoding', $conf); + } else { + $conf[\CURLOPT_UPLOAD] = \true; + if ($size !== null) { + $conf[\CURLOPT_INFILESIZE] = $size; + $this->removeHeader('Content-Length', $conf); + } + $body = $request->getBody(); + if ($body->isSeekable()) { + $body->rewind(); + } + $conf[\CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use($body) { + return $body->read($length); + }; + } + // If the Expect header is not present, prevent curl from adding it + if (!$request->hasHeader('Expect')) { + $conf[\CURLOPT_HTTPHEADER][] = 'Expect:'; + } + // cURL sometimes adds a content-type by default. Prevent this. + if (!$request->hasHeader('Content-Type')) { + $conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:'; + } + } + private function applyHeaders(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) + { + foreach ($conf['_headers'] as $name => $values) { + foreach ($values as $value) { + $value = (string) $value; + if ($value === '') { + // cURL requires a special format for empty headers. + // See https://github.com/guzzle/guzzle/issues/1882 for more details. + $conf[\CURLOPT_HTTPHEADER][] = "{$name};"; + } else { + $conf[\CURLOPT_HTTPHEADER][] = "{$name}: {$value}"; + } + } + } + // Remove the Accept header if one was not set + if (!$easy->request->hasHeader('Accept')) { + $conf[\CURLOPT_HTTPHEADER][] = 'Accept:'; + } + } + /** + * Remove a header from the options array. + * + * @param string $name Case-insensitive header to remove + * @param array $options Array of options to modify + */ + private function removeHeader($name, array &$options) + { + foreach (\array_keys($options['_headers']) as $key) { + if (!\strcasecmp($key, $name)) { + unset($options['_headers'][$key]); + return; + } + } + } + private function applyHandlerOptions(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) + { + $options = $easy->options; + if (isset($options['verify'])) { + if ($options['verify'] === \false) { + unset($conf[\CURLOPT_CAINFO]); + $conf[\CURLOPT_SSL_VERIFYHOST] = 0; + $conf[\CURLOPT_SSL_VERIFYPEER] = \false; + } else { + $conf[\CURLOPT_SSL_VERIFYHOST] = 2; + $conf[\CURLOPT_SSL_VERIFYPEER] = \true; + if (\is_string($options['verify'])) { + // Throw an error if the file/folder/link path is not valid or doesn't exist. + if (!\file_exists($options['verify'])) { + throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}"); + } + // If it's a directory or a link to a directory use CURLOPT_CAPATH. + // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO. + if (\is_dir($options['verify']) || \is_link($options['verify']) && \is_dir(\readlink($options['verify']))) { + $conf[\CURLOPT_CAPATH] = $options['verify']; + } else { + $conf[\CURLOPT_CAINFO] = $options['verify']; + } + } + } + } + if (!empty($options['decode_content'])) { + $accept = $easy->request->getHeaderLine('Accept-Encoding'); + if ($accept) { + $conf[\CURLOPT_ENCODING] = $accept; + } else { + $conf[\CURLOPT_ENCODING] = ''; + // Don't let curl send the header over the wire + $conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:'; + } + } + if (isset($options['sink'])) { + $sink = $options['sink']; + if (!\is_string($sink)) { + $sink = \YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($sink); + } elseif (!\is_dir(\dirname($sink))) { + // Ensure that the directory exists before failing in curl. + throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink)); + } else { + $sink = new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+'); + } + $easy->sink = $sink; + $conf[\CURLOPT_WRITEFUNCTION] = function ($ch, $write) use($sink) { + return $sink->write($write); + }; + } else { + // Use a default temp stream if no sink was set. + $conf[\CURLOPT_FILE] = \fopen('php://temp', 'w+'); + $easy->sink = \YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($conf[\CURLOPT_FILE]); + } + $timeoutRequiresNoSignal = \false; + if (isset($options['timeout'])) { + $timeoutRequiresNoSignal |= $options['timeout'] < 1; + $conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000; + } + // CURL default value is CURL_IPRESOLVE_WHATEVER + if (isset($options['force_ip_resolve'])) { + if ('v4' === $options['force_ip_resolve']) { + $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4; + } elseif ('v6' === $options['force_ip_resolve']) { + $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6; + } + } + if (isset($options['connect_timeout'])) { + $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1; + $conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000; + } + if ($timeoutRequiresNoSignal && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') { + $conf[\CURLOPT_NOSIGNAL] = \true; + } + if (isset($options['proxy'])) { + if (!\is_array($options['proxy'])) { + $conf[\CURLOPT_PROXY] = $options['proxy']; + } else { + $scheme = $easy->request->getUri()->getScheme(); + if (isset($options['proxy'][$scheme])) { + $host = $easy->request->getUri()->getHost(); + if (!isset($options['proxy']['no']) || !\YoastSEO_Vendor\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])) { + $conf[\CURLOPT_PROXY] = $options['proxy'][$scheme]; + } + } + } + } + if (isset($options['cert'])) { + $cert = $options['cert']; + if (\is_array($cert)) { + $conf[\CURLOPT_SSLCERTPASSWD] = $cert[1]; + $cert = $cert[0]; + } + if (!\file_exists($cert)) { + throw new \InvalidArgumentException("SSL certificate not found: {$cert}"); + } + $conf[\CURLOPT_SSLCERT] = $cert; + } + if (isset($options['ssl_key'])) { + $sslKey = $options['ssl_key']; + if (\is_array($sslKey)) { + $conf[\CURLOPT_SSLKEYPASSWD] = $sslKey[1]; + $sslKey = $sslKey[0]; + } + if (!\file_exists($sslKey)) { + throw new \InvalidArgumentException("SSL private key not found: {$sslKey}"); + } + $conf[\CURLOPT_SSLKEY] = $sslKey; + } + if (isset($options['progress'])) { + $progress = $options['progress']; + if (!\is_callable($progress)) { + throw new \InvalidArgumentException('progress client option must be callable'); + } + $conf[\CURLOPT_NOPROGRESS] = \false; + $conf[\CURLOPT_PROGRESSFUNCTION] = function () use($progress) { + $args = \func_get_args(); + // PHP 5.5 pushed the handle onto the start of the args + if (\is_resource($args[0])) { + \array_shift($args); + } + \call_user_func_array($progress, $args); + }; + } + if (!empty($options['debug'])) { + $conf[\CURLOPT_STDERR] = \YoastSEO_Vendor\GuzzleHttp\debug_resource($options['debug']); + $conf[\CURLOPT_VERBOSE] = \true; + } + } + /** + * This function ensures that a response was set on a transaction. If one + * was not set, then the request is retried if possible. This error + * typically means you are sending a payload, curl encountered a + * "Connection died, retrying a fresh connect" error, tried to rewind the + * stream, and then encountered a "necessary data rewind wasn't possible" + * error, causing the request to be sent through curl_multi_info_read() + * without an error status. + */ + private static function retryFailedRewind(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array $ctx) + { + try { + // Only rewind if the body has been read from. + $body = $easy->request->getBody(); + if ($body->tell() > 0) { + $body->rewind(); + } + } catch (\RuntimeException $e) { + $ctx['error'] = 'The connection unexpectedly failed without ' . 'providing an error. The request would have been retried, ' . 'but attempting to rewind the request body failed. ' . 'Exception: ' . $e; + return self::createRejection($easy, $ctx); + } + // Retry no more than 3 times before giving up. + if (!isset($easy->options['_curl_retries'])) { + $easy->options['_curl_retries'] = 1; + } elseif ($easy->options['_curl_retries'] == 2) { + $ctx['error'] = 'The cURL request was retried 3 times ' . 'and did not succeed. The most likely reason for the failure ' . 'is that cURL was unable to rewind the body of the request ' . 'and subsequent retries resulted in the same error. Turn on ' . 'the debug option to see what went wrong. See ' . 'https://bugs.php.net/bug.php?id=47204 for more information.'; + return self::createRejection($easy, $ctx); + } else { + $easy->options['_curl_retries']++; + } + return $handler($easy->request, $easy->options); + } + private function createHeaderFn(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) + { + if (isset($easy->options['on_headers'])) { + $onHeaders = $easy->options['on_headers']; + if (!\is_callable($onHeaders)) { + throw new \InvalidArgumentException('on_headers must be callable'); + } + } else { + $onHeaders = null; + } + return function ($ch, $h) use($onHeaders, $easy, &$startingResponse) { + $value = \trim($h); + if ($value === '') { + $startingResponse = \true; + $easy->createResponse(); + if ($onHeaders !== null) { + try { + $onHeaders($easy->response); + } catch (\Exception $e) { + // Associate the exception with the handle and trigger + // a curl header write error by returning 0. + $easy->onHeadersException = $e; + return -1; + } + } + } elseif ($startingResponse) { + $startingResponse = \false; + $easy->headers = [$value]; + } else { + $easy->headers[] = $value; + } + return \strlen($h); + }; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php new file mode 100644 index 00000000..0384e6c3 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php @@ -0,0 +1,26 @@ +factory = isset($options['handle_factory']) ? $options['handle_factory'] : new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory(3); + } + public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + if (isset($options['delay'])) { + \usleep($options['delay'] * 1000); + } + $easy = $this->factory->create($request, $options); + \curl_exec($easy->handle); + $easy->errno = \curl_errno($easy->handle); + return \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory::finish($this, $easy, $this->factory); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php new file mode 100644 index 00000000..fe783708 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php @@ -0,0 +1,160 @@ +factory = isset($options['handle_factory']) ? $options['handle_factory'] : new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory(50); + $this->selectTimeout = isset($options['select_timeout']) ? $options['select_timeout'] : 1; + } + public function __get($name) + { + if ($name === '_mh') { + return $this->_mh = \curl_multi_init(); + } + throw new \BadMethodCallException(); + } + public function __destruct() + { + if (isset($this->_mh)) { + \curl_multi_close($this->_mh); + unset($this->_mh); + } + } + public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + $easy = $this->factory->create($request, $options); + $id = (int) $easy->handle; + $promise = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$this, 'execute'], function () use($id) { + return $this->cancel($id); + }); + $this->addRequest(['easy' => $easy, 'deferred' => $promise]); + return $promise; + } + /** + * Ticks the curl event loop. + */ + public function tick() + { + // Add any delayed handles if needed. + if ($this->delays) { + $currentTime = \microtime(\true); + foreach ($this->delays as $id => $delay) { + if ($currentTime >= $delay) { + unset($this->delays[$id]); + \curl_multi_add_handle($this->_mh, $this->handles[$id]['easy']->handle); + } + } + } + // Step through the task queue which may add additional requests. + \YoastSEO_Vendor\GuzzleHttp\Promise\queue()->run(); + if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) { + // Perform a usleep if a select returns -1. + // See: https://bugs.php.net/bug.php?id=61141 + \usleep(250); + } + while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) { + } + $this->processMessages(); + } + /** + * Runs until all outstanding connections have completed. + */ + public function execute() + { + $queue = \YoastSEO_Vendor\GuzzleHttp\Promise\queue(); + while ($this->handles || !$queue->isEmpty()) { + // If there are no transfers, then sleep for the next delay + if (!$this->active && $this->delays) { + \usleep($this->timeToNext()); + } + $this->tick(); + } + } + private function addRequest(array $entry) + { + $easy = $entry['easy']; + $id = (int) $easy->handle; + $this->handles[$id] = $entry; + if (empty($easy->options['delay'])) { + \curl_multi_add_handle($this->_mh, $easy->handle); + } else { + $this->delays[$id] = \microtime(\true) + $easy->options['delay'] / 1000; + } + } + /** + * Cancels a handle from sending and removes references to it. + * + * @param int $id Handle ID to cancel and remove. + * + * @return bool True on success, false on failure. + */ + private function cancel($id) + { + // Cannot cancel if it has been processed. + if (!isset($this->handles[$id])) { + return \false; + } + $handle = $this->handles[$id]['easy']->handle; + unset($this->delays[$id], $this->handles[$id]); + \curl_multi_remove_handle($this->_mh, $handle); + \curl_close($handle); + return \true; + } + private function processMessages() + { + while ($done = \curl_multi_info_read($this->_mh)) { + $id = (int) $done['handle']; + \curl_multi_remove_handle($this->_mh, $done['handle']); + if (!isset($this->handles[$id])) { + // Probably was cancelled. + continue; + } + $entry = $this->handles[$id]; + unset($this->handles[$id], $this->delays[$id]); + $entry['easy']->errno = $done['result']; + $entry['deferred']->resolve(\YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory::finish($this, $entry['easy'], $this->factory)); + } + } + private function timeToNext() + { + $currentTime = \microtime(\true); + $nextTime = \PHP_INT_MAX; + foreach ($this->delays as $time) { + if ($time < $nextTime) { + $nextTime = $time; + } + } + return \max(0, $nextTime - $currentTime) * 1000000; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/EasyHandle.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/EasyHandle.php new file mode 100644 index 00000000..fd304640 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/EasyHandle.php @@ -0,0 +1,67 @@ +headers)) { + throw new \RuntimeException('No headers have been received'); + } + // HTTP-version SP status-code SP reason-phrase + $startLine = \explode(' ', \array_shift($this->headers), 3); + $headers = \YoastSEO_Vendor\GuzzleHttp\headers_from_lines($this->headers); + $normalizedKeys = \YoastSEO_Vendor\GuzzleHttp\normalize_header_keys($headers); + if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) { + $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; + unset($headers[$normalizedKeys['content-encoding']]); + if (isset($normalizedKeys['content-length'])) { + $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; + $bodyLength = (int) $this->sink->getSize(); + if ($bodyLength) { + $headers[$normalizedKeys['content-length']] = $bodyLength; + } else { + unset($headers[$normalizedKeys['content-length']]); + } + } + } + // Attach a response to the easy handle with the parsed headers. + $this->response = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($startLine[1], $headers, $this->sink, \substr($startLine[0], 5), isset($startLine[2]) ? (string) $startLine[2] : null); + } + public function __get($name) + { + $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: ' . $name; + throw new \BadMethodCallException($msg); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/MockHandler.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/MockHandler.php new file mode 100644 index 00000000..0f7825ac --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/MockHandler.php @@ -0,0 +1,152 @@ +onFulfilled = $onFulfilled; + $this->onRejected = $onRejected; + if ($queue) { + \call_user_func_array([$this, 'append'], $queue); + } + } + public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + if (!$this->queue) { + throw new \OutOfBoundsException('Mock queue is empty'); + } + if (isset($options['delay'])) { + \usleep($options['delay'] * 1000); + } + $this->lastRequest = $request; + $this->lastOptions = $options; + $response = \array_shift($this->queue); + if (isset($options['on_headers'])) { + if (!\is_callable($options['on_headers'])) { + throw new \InvalidArgumentException('on_headers must be callable'); + } + try { + $options['on_headers']($response); + } catch (\Exception $e) { + $msg = 'An error was encountered during the on_headers event'; + $response = new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($msg, $request, $response, $e); + } + } + if (\is_callable($response)) { + $response = \call_user_func($response, $request, $options); + } + $response = $response instanceof \Exception ? \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($response) : \YoastSEO_Vendor\GuzzleHttp\Promise\promise_for($response); + return $response->then(function ($value) use($request, $options) { + $this->invokeStats($request, $options, $value); + if ($this->onFulfilled) { + \call_user_func($this->onFulfilled, $value); + } + if (isset($options['sink'])) { + $contents = (string) $value->getBody(); + $sink = $options['sink']; + if (\is_resource($sink)) { + \fwrite($sink, $contents); + } elseif (\is_string($sink)) { + \file_put_contents($sink, $contents); + } elseif ($sink instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) { + $sink->write($contents); + } + } + return $value; + }, function ($reason) use($request, $options) { + $this->invokeStats($request, $options, null, $reason); + if ($this->onRejected) { + \call_user_func($this->onRejected, $reason); + } + return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($reason); + }); + } + /** + * Adds one or more variadic requests, exceptions, callables, or promises + * to the queue. + */ + public function append() + { + foreach (\func_get_args() as $value) { + if ($value instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface || $value instanceof \Exception || $value instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface || \is_callable($value)) { + $this->queue[] = $value; + } else { + throw new \InvalidArgumentException('Expected a response or ' . 'exception. Found ' . \YoastSEO_Vendor\GuzzleHttp\describe_type($value)); + } + } + } + /** + * Get the last received request. + * + * @return RequestInterface + */ + public function getLastRequest() + { + return $this->lastRequest; + } + /** + * Get the last received request options. + * + * @return array + */ + public function getLastOptions() + { + return $this->lastOptions; + } + /** + * Returns the number of remaining items in the queue. + * + * @return int + */ + public function count() + { + return \count($this->queue); + } + private function invokeStats(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, $reason = null) + { + if (isset($options['on_stats'])) { + $stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($request, $response, 0, $reason); + \call_user_func($options['on_stats'], $stats); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/Proxy.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/Proxy.php new file mode 100644 index 00000000..81789498 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Handler/Proxy.php @@ -0,0 +1,46 @@ +withoutHeader('Expect'); + // Append a content-length header if body size is zero to match + // cURL's behavior. + if (0 === $request->getBody()->getSize()) { + $request = $request->withHeader('Content-Length', 0); + } + return $this->createResponse($request, $options, $this->createStream($request, $options), $startTime); + } catch (\InvalidArgumentException $e) { + throw $e; + } catch (\Exception $e) { + // Determine if the error was a networking error. + $message = $e->getMessage(); + // This list can probably get more comprehensive. + if (\strpos($message, 'getaddrinfo') || \strpos($message, 'Connection refused') || \strpos($message, "couldn't connect to host") || \strpos($message, "connection attempt failed")) { + $e = new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException($e->getMessage(), $request, $e); + } + $e = \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException::wrapException($request, $e); + $this->invokeStats($options, $request, $startTime, null, $e); + return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($e); + } + } + private function invokeStats(array $options, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, $startTime, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, $error = null) + { + if (isset($options['on_stats'])) { + $stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($request, $response, \microtime(\true) - $startTime, $error, []); + \call_user_func($options['on_stats'], $stats); + } + } + private function createResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, $stream, $startTime) + { + $hdrs = $this->lastHeaders; + $this->lastHeaders = []; + $parts = \explode(' ', \array_shift($hdrs), 3); + $ver = \explode('/', $parts[0])[1]; + $status = $parts[1]; + $reason = isset($parts[2]) ? $parts[2] : null; + $headers = \YoastSEO_Vendor\GuzzleHttp\headers_from_lines($hdrs); + list($stream, $headers) = $this->checkDecode($options, $headers, $stream); + $stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($stream); + $sink = $stream; + if (\strcasecmp('HEAD', $request->getMethod())) { + $sink = $this->createSink($stream, $options); + } + $response = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($status, $headers, $sink, $ver, $reason); + if (isset($options['on_headers'])) { + try { + $options['on_headers']($response); + } catch (\Exception $e) { + $msg = 'An error was encountered during the on_headers event'; + $ex = new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($msg, $request, $response, $e); + return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($ex); + } + } + // Do not drain when the request is a HEAD request because they have + // no body. + if ($sink !== $stream) { + $this->drain($stream, $sink, $response->getHeaderLine('Content-Length')); + } + $this->invokeStats($options, $request, $startTime, $response, null); + return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($response); + } + private function createSink(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, array $options) + { + if (!empty($options['stream'])) { + return $stream; + } + $sink = isset($options['sink']) ? $options['sink'] : \fopen('php://temp', 'r+'); + return \is_string($sink) ? new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+') : \YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($sink); + } + private function checkDecode(array $options, array $headers, $stream) + { + // Automatically decode responses when instructed. + if (!empty($options['decode_content'])) { + $normalizedKeys = \YoastSEO_Vendor\GuzzleHttp\normalize_header_keys($headers); + if (isset($normalizedKeys['content-encoding'])) { + $encoding = $headers[$normalizedKeys['content-encoding']]; + if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') { + $stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\InflateStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\stream_for($stream)); + $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; + // Remove content-encoding header + unset($headers[$normalizedKeys['content-encoding']]); + // Fix content-length header + if (isset($normalizedKeys['content-length'])) { + $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; + $length = (int) $stream->getSize(); + if ($length === 0) { + unset($headers[$normalizedKeys['content-length']]); + } else { + $headers[$normalizedKeys['content-length']] = [$length]; + } + } + } + } + } + return [$stream, $headers]; + } + /** + * Drains the source stream into the "sink" client option. + * + * @param StreamInterface $source + * @param StreamInterface $sink + * @param string $contentLength Header specifying the amount of + * data to read. + * + * @return StreamInterface + * @throws \RuntimeException when the sink option is invalid. + */ + private function drain(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $sink, $contentLength) + { + // If a content-length header is provided, then stop reading once + // that number of bytes has been read. This can prevent infinitely + // reading from a stream when dealing with servers that do not honor + // Connection: Close headers. + \YoastSEO_Vendor\GuzzleHttp\Psr7\copy_to_stream($source, $sink, \strlen($contentLength) > 0 && (int) $contentLength > 0 ? (int) $contentLength : -1); + $sink->seek(0); + $source->close(); + return $sink; + } + /** + * Create a resource and check to ensure it was created successfully + * + * @param callable $callback Callable that returns stream resource + * + * @return resource + * @throws \RuntimeException on error + */ + private function createResource(callable $callback) + { + $errors = null; + \set_error_handler(function ($_, $msg, $file, $line) use(&$errors) { + $errors[] = ['message' => $msg, 'file' => $file, 'line' => $line]; + return \true; + }); + $resource = $callback(); + \restore_error_handler(); + if (!$resource) { + $message = 'Error creating resource: '; + foreach ($errors as $err) { + foreach ($err as $key => $value) { + $message .= "[{$key}] {$value}" . \PHP_EOL; + } + } + throw new \RuntimeException(\trim($message)); + } + return $resource; + } + private function createStream(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + static $methods; + if (!$methods) { + $methods = \array_flip(\get_class_methods(__CLASS__)); + } + // HTTP/1.1 streams using the PHP stream wrapper require a + // Connection: close header + if ($request->getProtocolVersion() == '1.1' && !$request->hasHeader('Connection')) { + $request = $request->withHeader('Connection', 'close'); + } + // Ensure SSL is verified by default + if (!isset($options['verify'])) { + $options['verify'] = \true; + } + $params = []; + $context = $this->getDefaultContext($request); + if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) { + throw new \InvalidArgumentException('on_headers must be callable'); + } + if (!empty($options)) { + foreach ($options as $key => $value) { + $method = "add_{$key}"; + if (isset($methods[$method])) { + $this->{$method}($request, $context, $value, $params); + } + } + } + if (isset($options['stream_context'])) { + if (!\is_array($options['stream_context'])) { + throw new \InvalidArgumentException('stream_context must be an array'); + } + $context = \array_replace_recursive($context, $options['stream_context']); + } + // Microsoft NTLM authentication only supported with curl handler + if (isset($options['auth']) && \is_array($options['auth']) && isset($options['auth'][2]) && 'ntlm' == $options['auth'][2]) { + throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler'); + } + $uri = $this->resolveHost($request, $options); + $context = $this->createResource(function () use($context, $params) { + return \stream_context_create($context, $params); + }); + return $this->createResource(function () use($uri, &$http_response_header, $context, $options) { + $resource = \fopen((string) $uri, 'r', null, $context); + $this->lastHeaders = $http_response_header; + if (isset($options['read_timeout'])) { + $readTimeout = $options['read_timeout']; + $sec = (int) $readTimeout; + $usec = ($readTimeout - $sec) * 100000; + \stream_set_timeout($resource, $sec, $usec); + } + return $resource; + }); + } + private function resolveHost(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + $uri = $request->getUri(); + if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) { + if ('v4' === $options['force_ip_resolve']) { + $records = \dns_get_record($uri->getHost(), \DNS_A); + if (!isset($records[0]['ip'])) { + throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request); + } + $uri = $uri->withHost($records[0]['ip']); + } elseif ('v6' === $options['force_ip_resolve']) { + $records = \dns_get_record($uri->getHost(), \DNS_AAAA); + if (!isset($records[0]['ipv6'])) { + throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request); + } + $uri = $uri->withHost('[' . $records[0]['ipv6'] . ']'); + } + } + return $uri; + } + private function getDefaultContext(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) + { + $headers = ''; + foreach ($request->getHeaders() as $name => $value) { + foreach ($value as $val) { + $headers .= "{$name}: {$val}\r\n"; + } + } + $context = ['http' => ['method' => $request->getMethod(), 'header' => $headers, 'protocol_version' => $request->getProtocolVersion(), 'ignore_errors' => \true, 'follow_location' => 0]]; + $body = (string) $request->getBody(); + if (!empty($body)) { + $context['http']['content'] = $body; + // Prevent the HTTP handler from adding a Content-Type header. + if (!$request->hasHeader('Content-Type')) { + $context['http']['header'] .= "Content-Type:\r\n"; + } + } + $context['http']['header'] = \rtrim($context['http']['header']); + return $context; + } + private function add_proxy(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params) + { + if (!\is_array($value)) { + $options['http']['proxy'] = $value; + } else { + $scheme = $request->getUri()->getScheme(); + if (isset($value[$scheme])) { + if (!isset($value['no']) || !\YoastSEO_Vendor\GuzzleHttp\is_host_in_noproxy($request->getUri()->getHost(), $value['no'])) { + $options['http']['proxy'] = $value[$scheme]; + } + } + } + } + private function add_timeout(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params) + { + if ($value > 0) { + $options['http']['timeout'] = $value; + } + } + private function add_verify(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params) + { + if ($value === \true) { + // PHP 5.6 or greater will find the system cert by default. When + // < 5.6, use the Guzzle bundled cacert. + if (\PHP_VERSION_ID < 50600) { + $options['ssl']['cafile'] = \YoastSEO_Vendor\GuzzleHttp\default_ca_bundle(); + } + } elseif (\is_string($value)) { + $options['ssl']['cafile'] = $value; + if (!\file_exists($value)) { + throw new \RuntimeException("SSL CA bundle not found: {$value}"); + } + } elseif ($value === \false) { + $options['ssl']['verify_peer'] = \false; + $options['ssl']['verify_peer_name'] = \false; + return; + } else { + throw new \InvalidArgumentException('Invalid verify request option'); + } + $options['ssl']['verify_peer'] = \true; + $options['ssl']['verify_peer_name'] = \true; + $options['ssl']['allow_self_signed'] = \false; + } + private function add_cert(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params) + { + if (\is_array($value)) { + $options['ssl']['passphrase'] = $value[1]; + $value = $value[0]; + } + if (!\file_exists($value)) { + throw new \RuntimeException("SSL certificate not found: {$value}"); + } + $options['ssl']['local_cert'] = $value; + } + private function add_progress(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params) + { + $this->addNotification($params, function ($code, $a, $b, $c, $transferred, $total) use($value) { + if ($code == \STREAM_NOTIFY_PROGRESS) { + $value($total, $transferred, null, null); + } + }); + } + private function add_debug(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, &$options, $value, &$params) + { + if ($value === \false) { + return; + } + static $map = [\STREAM_NOTIFY_CONNECT => 'CONNECT', \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', \STREAM_NOTIFY_PROGRESS => 'PROGRESS', \STREAM_NOTIFY_FAILURE => 'FAILURE', \STREAM_NOTIFY_COMPLETED => 'COMPLETED', \STREAM_NOTIFY_RESOLVE => 'RESOLVE']; + static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max']; + $value = \YoastSEO_Vendor\GuzzleHttp\debug_resource($value); + $ident = $request->getMethod() . ' ' . $request->getUri()->withFragment(''); + $this->addNotification($params, function () use($ident, $value, $map, $args) { + $passed = \func_get_args(); + $code = \array_shift($passed); + \fprintf($value, '<%s> [%s] ', $ident, $map[$code]); + foreach (\array_filter($passed) as $i => $v) { + \fwrite($value, $args[$i] . ': "' . $v . '" '); + } + \fwrite($value, "\n"); + }); + } + private function addNotification(array &$params, callable $notify) + { + // Wrap the existing function if needed. + if (!isset($params['notification'])) { + $params['notification'] = $notify; + } else { + $params['notification'] = $this->callArray([$params['notification'], $notify]); + } + } + private function callArray(array $functions) + { + return function () use($functions) { + $args = \func_get_args(); + foreach ($functions as $fn) { + \call_user_func_array($fn, $args); + } + }; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/HandlerStack.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/HandlerStack.php new file mode 100644 index 00000000..3d592dd3 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/HandlerStack.php @@ -0,0 +1,239 @@ +push(\YoastSEO_Vendor\GuzzleHttp\Middleware::httpErrors(), 'http_errors'); + $stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::redirect(), 'allow_redirects'); + $stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::cookies(), 'cookies'); + $stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::prepareBody(), 'prepare_body'); + return $stack; + } + /** + * @param callable $handler Underlying HTTP handler. + */ + public function __construct(callable $handler = null) + { + $this->handler = $handler; + } + /** + * Invokes the handler stack as a composed handler + * + * @param RequestInterface $request + * @param array $options + */ + public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + $handler = $this->resolve(); + return $handler($request, $options); + } + /** + * Dumps a string representation of the stack. + * + * @return string + */ + public function __toString() + { + $depth = 0; + $stack = []; + if ($this->handler) { + $stack[] = "0) Handler: " . $this->debugCallable($this->handler); + } + $result = ''; + foreach (\array_reverse($this->stack) as $tuple) { + $depth++; + $str = "{$depth}) Name: '{$tuple[1]}', "; + $str .= "Function: " . $this->debugCallable($tuple[0]); + $result = "> {$str}\n{$result}"; + $stack[] = $str; + } + foreach (\array_keys($stack) as $k) { + $result .= "< {$stack[$k]}\n"; + } + return $result; + } + /** + * Set the HTTP handler that actually returns a promise. + * + * @param callable $handler Accepts a request and array of options and + * returns a Promise. + */ + public function setHandler(callable $handler) + { + $this->handler = $handler; + $this->cached = null; + } + /** + * Returns true if the builder has a handler. + * + * @return bool + */ + public function hasHandler() + { + return (bool) $this->handler; + } + /** + * Unshift a middleware to the bottom of the stack. + * + * @param callable $middleware Middleware function + * @param string $name Name to register for this middleware. + */ + public function unshift(callable $middleware, $name = null) + { + \array_unshift($this->stack, [$middleware, $name]); + $this->cached = null; + } + /** + * Push a middleware to the top of the stack. + * + * @param callable $middleware Middleware function + * @param string $name Name to register for this middleware. + */ + public function push(callable $middleware, $name = '') + { + $this->stack[] = [$middleware, $name]; + $this->cached = null; + } + /** + * Add a middleware before another middleware by name. + * + * @param string $findName Middleware to find + * @param callable $middleware Middleware function + * @param string $withName Name to register for this middleware. + */ + public function before($findName, callable $middleware, $withName = '') + { + $this->splice($findName, $withName, $middleware, \true); + } + /** + * Add a middleware after another middleware by name. + * + * @param string $findName Middleware to find + * @param callable $middleware Middleware function + * @param string $withName Name to register for this middleware. + */ + public function after($findName, callable $middleware, $withName = '') + { + $this->splice($findName, $withName, $middleware, \false); + } + /** + * Remove a middleware by instance or name from the stack. + * + * @param callable|string $remove Middleware to remove by instance or name. + */ + public function remove($remove) + { + $this->cached = null; + $idx = \is_callable($remove) ? 0 : 1; + $this->stack = \array_values(\array_filter($this->stack, function ($tuple) use($idx, $remove) { + return $tuple[$idx] !== $remove; + })); + } + /** + * Compose the middleware and handler into a single callable function. + * + * @return callable + */ + public function resolve() + { + if (!$this->cached) { + if (!($prev = $this->handler)) { + throw new \LogicException('No handler has been specified'); + } + foreach (\array_reverse($this->stack) as $fn) { + $prev = $fn[0]($prev); + } + $this->cached = $prev; + } + return $this->cached; + } + /** + * @param $name + * @return int + */ + private function findByName($name) + { + foreach ($this->stack as $k => $v) { + if ($v[1] === $name) { + return $k; + } + } + throw new \InvalidArgumentException("Middleware not found: {$name}"); + } + /** + * Splices a function into the middleware list at a specific position. + * + * @param $findName + * @param $withName + * @param callable $middleware + * @param $before + */ + private function splice($findName, $withName, callable $middleware, $before) + { + $this->cached = null; + $idx = $this->findByName($findName); + $tuple = [$middleware, $withName]; + if ($before) { + if ($idx === 0) { + \array_unshift($this->stack, $tuple); + } else { + $replacement = [$tuple, $this->stack[$idx]]; + \array_splice($this->stack, $idx, 1, $replacement); + } + } elseif ($idx === \count($this->stack) - 1) { + $this->stack[] = $tuple; + } else { + $replacement = [$this->stack[$idx], $tuple]; + \array_splice($this->stack, $idx, 1, $replacement); + } + } + /** + * Provides a debug string for a given callable. + * + * @param array|callable $fn Function to write as a string. + * + * @return string + */ + private function debugCallable($fn) + { + if (\is_string($fn)) { + return "callable({$fn})"; + } + if (\is_array($fn)) { + return \is_string($fn[0]) ? "callable({$fn[0]}::{$fn[1]})" : "callable(['" . \get_class($fn[0]) . "', '{$fn[1]}'])"; + } + return 'callable(' . \spl_object_hash($fn) . ')'; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/MessageFormatter.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/MessageFormatter.php new file mode 100644 index 00000000..1b5f4b8c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/MessageFormatter.php @@ -0,0 +1,151 @@ +>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}"; + const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}'; + /** @var string Template used to format log messages */ + private $template; + /** + * @param string $template Log message template + */ + public function __construct($template = self::CLF) + { + $this->template = $template ?: self::CLF; + } + /** + * Returns a formatted message string. + * + * @param RequestInterface $request Request that was sent + * @param ResponseInterface $response Response that was received + * @param \Exception $error Exception that was received + * + * @return string + */ + public function format(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Exception $error = null) + { + $cache = []; + return \preg_replace_callback('/{\\s*([A-Za-z_\\-\\.0-9]+)\\s*}/', function (array $matches) use($request, $response, $error, &$cache) { + if (isset($cache[$matches[1]])) { + return $cache[$matches[1]]; + } + $result = ''; + switch ($matches[1]) { + case 'request': + $result = \YoastSEO_Vendor\GuzzleHttp\Psr7\str($request); + break; + case 'response': + $result = $response ? \YoastSEO_Vendor\GuzzleHttp\Psr7\str($response) : ''; + break; + case 'req_headers': + $result = \trim($request->getMethod() . ' ' . $request->getRequestTarget()) . ' HTTP/' . $request->getProtocolVersion() . "\r\n" . $this->headers($request); + break; + case 'res_headers': + $result = $response ? \sprintf('HTTP/%s %d %s', $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase()) . "\r\n" . $this->headers($response) : 'NULL'; + break; + case 'req_body': + $result = $request->getBody(); + break; + case 'res_body': + $result = $response ? $response->getBody() : 'NULL'; + break; + case 'ts': + case 'date_iso_8601': + $result = \gmdate('c'); + break; + case 'date_common_log': + $result = \date('d/M/Y:H:i:s O'); + break; + case 'method': + $result = $request->getMethod(); + break; + case 'version': + $result = $request->getProtocolVersion(); + break; + case 'uri': + case 'url': + $result = $request->getUri(); + break; + case 'target': + $result = $request->getRequestTarget(); + break; + case 'req_version': + $result = $request->getProtocolVersion(); + break; + case 'res_version': + $result = $response ? $response->getProtocolVersion() : 'NULL'; + break; + case 'host': + $result = $request->getHeaderLine('Host'); + break; + case 'hostname': + $result = \gethostname(); + break; + case 'code': + $result = $response ? $response->getStatusCode() : 'NULL'; + break; + case 'phrase': + $result = $response ? $response->getReasonPhrase() : 'NULL'; + break; + case 'error': + $result = $error ? $error->getMessage() : 'NULL'; + break; + default: + // handle prefixed dynamic headers + if (\strpos($matches[1], 'req_header_') === 0) { + $result = $request->getHeaderLine(\substr($matches[1], 11)); + } elseif (\strpos($matches[1], 'res_header_') === 0) { + $result = $response ? $response->getHeaderLine(\substr($matches[1], 11)) : 'NULL'; + } + } + $cache[$matches[1]] = $result; + return $result; + }, $this->template); + } + private function headers(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) + { + $result = ''; + foreach ($message->getHeaders() as $name => $values) { + $result .= $name . ': ' . \implode(', ', $values) . "\r\n"; + } + return \trim($result); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Middleware.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Middleware.php new file mode 100644 index 00000000..bdda796f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Middleware.php @@ -0,0 +1,222 @@ +withCookieHeader($request); + return $handler($request, $options)->then(function ($response) use($cookieJar, $request) { + $cookieJar->extractCookies($request, $response); + return $response; + }); + }; + }; + } + /** + * Middleware that throws exceptions for 4xx or 5xx responses when the + * "http_error" request option is set to true. + * + * @return callable Returns a function that accepts the next handler. + */ + public static function httpErrors() + { + return function (callable $handler) { + return function ($request, array $options) use($handler) { + if (empty($options['http_errors'])) { + return $handler($request, $options); + } + return $handler($request, $options)->then(function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($request, $handler) { + $code = $response->getStatusCode(); + if ($code < 400) { + return $response; + } + throw \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException::create($request, $response); + }); + }; + }; + } + /** + * Middleware that pushes history data to an ArrayAccess container. + * + * @param array|\ArrayAccess $container Container to hold the history (by reference). + * + * @return callable Returns a function that accepts the next handler. + * @throws \InvalidArgumentException if container is not an array or ArrayAccess. + */ + public static function history(&$container) + { + if (!\is_array($container) && !$container instanceof \ArrayAccess) { + throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess'); + } + return function (callable $handler) use(&$container) { + return function ($request, array $options) use($handler, &$container) { + return $handler($request, $options)->then(function ($value) use($request, &$container, $options) { + $container[] = ['request' => $request, 'response' => $value, 'error' => null, 'options' => $options]; + return $value; + }, function ($reason) use($request, &$container, $options) { + $container[] = ['request' => $request, 'response' => null, 'error' => $reason, 'options' => $options]; + return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($reason); + }); + }; + }; + } + /** + * Middleware that invokes a callback before and after sending a request. + * + * The provided listener cannot modify or alter the response. It simply + * "taps" into the chain to be notified before returning the promise. The + * before listener accepts a request and options array, and the after + * listener accepts a request, options array, and response promise. + * + * @param callable $before Function to invoke before forwarding the request. + * @param callable $after Function invoked after forwarding. + * + * @return callable Returns a function that accepts the next handler. + */ + public static function tap(callable $before = null, callable $after = null) + { + return function (callable $handler) use($before, $after) { + return function ($request, array $options) use($handler, $before, $after) { + if ($before) { + $before($request, $options); + } + $response = $handler($request, $options); + if ($after) { + $after($request, $options, $response); + } + return $response; + }; + }; + } + /** + * Middleware that handles request redirects. + * + * @return callable Returns a function that accepts the next handler. + */ + public static function redirect() + { + return function (callable $handler) { + return new \YoastSEO_Vendor\GuzzleHttp\RedirectMiddleware($handler); + }; + } + /** + * Middleware that retries requests based on the boolean result of + * invoking the provided "decider" function. + * + * If no delay function is provided, a simple implementation of exponential + * backoff will be utilized. + * + * @param callable $decider Function that accepts the number of retries, + * a request, [response], and [exception] and + * returns true if the request is to be retried. + * @param callable $delay Function that accepts the number of retries and + * returns the number of milliseconds to delay. + * + * @return callable Returns a function that accepts the next handler. + */ + public static function retry(callable $decider, callable $delay = null) + { + return function (callable $handler) use($decider, $delay) { + return new \YoastSEO_Vendor\GuzzleHttp\RetryMiddleware($decider, $handler, $delay); + }; + } + /** + * Middleware that logs requests, responses, and errors using a message + * formatter. + * + * @param LoggerInterface $logger Logs messages. + * @param MessageFormatter $formatter Formatter used to create message strings. + * @param string $logLevel Level at which to log requests. + * + * @return callable Returns a function that accepts the next handler. + */ + public static function log(\YoastSEO_Vendor\Psr\Log\LoggerInterface $logger, \YoastSEO_Vendor\GuzzleHttp\MessageFormatter $formatter, $logLevel = \YoastSEO_Vendor\Psr\Log\LogLevel::INFO) + { + return function (callable $handler) use($logger, $formatter, $logLevel) { + return function ($request, array $options) use($handler, $logger, $formatter, $logLevel) { + return $handler($request, $options)->then(function ($response) use($logger, $request, $formatter, $logLevel) { + $message = $formatter->format($request, $response); + $logger->log($logLevel, $message); + return $response; + }, function ($reason) use($logger, $request, $formatter) { + $response = $reason instanceof \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException ? $reason->getResponse() : null; + $message = $formatter->format($request, $response, $reason); + $logger->notice($message); + return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($reason); + }); + }; + }; + } + /** + * This middleware adds a default content-type if possible, a default + * content-length or transfer-encoding header, and the expect header. + * + * @return callable + */ + public static function prepareBody() + { + return function (callable $handler) { + return new \YoastSEO_Vendor\GuzzleHttp\PrepareBodyMiddleware($handler); + }; + } + /** + * Middleware that applies a map function to the request before passing to + * the next handler. + * + * @param callable $fn Function that accepts a RequestInterface and returns + * a RequestInterface. + * @return callable + */ + public static function mapRequest(callable $fn) + { + return function (callable $handler) use($fn) { + return function ($request, array $options) use($handler, $fn) { + return $handler($fn($request), $options); + }; + }; + } + /** + * Middleware that applies a map function to the resolved promise's + * response. + * + * @param callable $fn Function that accepts a ResponseInterface and + * returns a ResponseInterface. + * @return callable + */ + public static function mapResponse(callable $fn) + { + return function (callable $handler) use($fn) { + return function ($request, array $options) use($handler, $fn) { + return $handler($request, $options)->then($fn); + }; + }; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Pool.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Pool.php new file mode 100644 index 00000000..ab65249b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/Pool.php @@ -0,0 +1,106 @@ + $rfn) { + if ($rfn instanceof \YoastSEO_Vendor\Psr\Http\Message\RequestInterface) { + (yield $key => $client->sendAsync($rfn, $opts)); + } elseif (\is_callable($rfn)) { + (yield $key => $rfn($opts)); + } else { + throw new \InvalidArgumentException('Each value yielded by ' . 'the iterator must be a Psr7\\Http\\Message\\RequestInterface ' . 'or a callable that returns a promise that fulfills ' . 'with a Psr7\\Message\\Http\\ResponseInterface object.'); + } + } + }; + $this->each = new \YoastSEO_Vendor\GuzzleHttp\Promise\EachPromise($requests(), $config); + } + public function promise() + { + return $this->each->promise(); + } + /** + * Sends multiple requests concurrently and returns an array of responses + * and exceptions that uses the same ordering as the provided requests. + * + * IMPORTANT: This method keeps every request and response in memory, and + * as such, is NOT recommended when sending a large number or an + * indeterminate number of requests concurrently. + * + * @param ClientInterface $client Client used to send the requests + * @param array|\Iterator $requests Requests to send concurrently. + * @param array $options Passes through the options available in + * {@see GuzzleHttp\Pool::__construct} + * + * @return array Returns an array containing the response or an exception + * in the same order that the requests were sent. + * @throws \InvalidArgumentException if the event format is incorrect. + */ + public static function batch(\YoastSEO_Vendor\GuzzleHttp\ClientInterface $client, $requests, array $options = []) + { + $res = []; + self::cmpCallback($options, 'fulfilled', $res); + self::cmpCallback($options, 'rejected', $res); + $pool = new static($client, $requests, $options); + $pool->promise()->wait(); + \ksort($res); + return $res; + } + private static function cmpCallback(array &$options, $name, array &$results) + { + if (!isset($options[$name])) { + $options[$name] = function ($v, $k) use(&$results) { + $results[$k] = $v; + }; + } else { + $currentFn = $options[$name]; + $options[$name] = function ($v, $k) use(&$results, $currentFn) { + $currentFn($v, $k); + $results[$k] = $v; + }; + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php new file mode 100644 index 00000000..7c0b8953 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php @@ -0,0 +1,86 @@ +nextHandler = $nextHandler; + } + /** + * @param RequestInterface $request + * @param array $options + * + * @return PromiseInterface + */ + public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + $fn = $this->nextHandler; + // Don't do anything if the request has no body. + if ($request->getBody()->getSize() === 0) { + return $fn($request, $options); + } + $modify = []; + // Add a default content-type if possible. + if (!$request->hasHeader('Content-Type')) { + if ($uri = $request->getBody()->getMetadata('uri')) { + if ($type = \YoastSEO_Vendor\GuzzleHttp\Psr7\mimetype_from_filename($uri)) { + $modify['set_headers']['Content-Type'] = $type; + } + } + } + // Add a default content-length or transfer-encoding header. + if (!$request->hasHeader('Content-Length') && !$request->hasHeader('Transfer-Encoding')) { + $size = $request->getBody()->getSize(); + if ($size !== null) { + $modify['set_headers']['Content-Length'] = $size; + } else { + $modify['set_headers']['Transfer-Encoding'] = 'chunked'; + } + } + // Add the expect header if needed. + $this->addExpectHeader($request, $options, $modify); + return $fn(\YoastSEO_Vendor\GuzzleHttp\Psr7\modify_request($request, $modify), $options); + } + private function addExpectHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, array &$modify) + { + // Determine if the Expect header should be used + if ($request->hasHeader('Expect')) { + return; + } + $expect = isset($options['expect']) ? $options['expect'] : null; + // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0 + if ($expect === \false || $request->getProtocolVersion() < 1.1) { + return; + } + // The expect header is unconditionally enabled + if ($expect === \true) { + $modify['set_headers']['Expect'] = '100-Continue'; + return; + } + // By default, send the expect header when the payload is > 1mb + if ($expect === null) { + $expect = 1048576; + } + // Always add if the body cannot be rewound, the size cannot be + // determined, or the size is greater than the cutoff threshold + $body = $request->getBody(); + $size = $body->getSize(); + if ($size === null || $size >= (int) $expect || !$body->isSeekable()) { + $modify['set_headers']['Expect'] = '100-Continue'; + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/RedirectMiddleware.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/RedirectMiddleware.php new file mode 100644 index 00000000..041cac84 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/RedirectMiddleware.php @@ -0,0 +1,160 @@ + 5, 'protocols' => ['http', 'https'], 'strict' => \false, 'referer' => \false, 'track_redirects' => \false]; + /** @var callable */ + private $nextHandler; + /** + * @param callable $nextHandler Next handler to invoke. + */ + public function __construct(callable $nextHandler) + { + $this->nextHandler = $nextHandler; + } + /** + * @param RequestInterface $request + * @param array $options + * + * @return PromiseInterface + */ + public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + $fn = $this->nextHandler; + if (empty($options['allow_redirects'])) { + return $fn($request, $options); + } + if ($options['allow_redirects'] === \true) { + $options['allow_redirects'] = self::$defaultSettings; + } elseif (!\is_array($options['allow_redirects'])) { + throw new \InvalidArgumentException('allow_redirects must be true, false, or array'); + } else { + // Merge the default settings with the provided settings + $options['allow_redirects'] += self::$defaultSettings; + } + if (empty($options['allow_redirects']['max'])) { + return $fn($request, $options); + } + return $fn($request, $options)->then(function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($request, $options) { + return $this->checkRedirect($request, $options, $response); + }); + } + /** + * @param RequestInterface $request + * @param array $options + * @param ResponseInterface|PromiseInterface $response + * + * @return ResponseInterface|PromiseInterface + */ + public function checkRedirect(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) + { + if (\substr($response->getStatusCode(), 0, 1) != '3' || !$response->hasHeader('Location')) { + return $response; + } + $this->guardMax($request, $options); + $nextRequest = $this->modifyRequest($request, $options, $response); + if (isset($options['allow_redirects']['on_redirect'])) { + \call_user_func($options['allow_redirects']['on_redirect'], $request, $response, $nextRequest->getUri()); + } + /** @var PromiseInterface|ResponseInterface $promise */ + $promise = $this($nextRequest, $options); + // Add headers to be able to track history of redirects. + if (!empty($options['allow_redirects']['track_redirects'])) { + return $this->withTracking($promise, (string) $nextRequest->getUri(), $response->getStatusCode()); + } + return $promise; + } + private function withTracking(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise, $uri, $statusCode) + { + return $promise->then(function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($uri, $statusCode) { + // Note that we are pushing to the front of the list as this + // would be an earlier response than what is currently present + // in the history header. + $historyHeader = $response->getHeader(self::HISTORY_HEADER); + $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER); + \array_unshift($historyHeader, $uri); + \array_unshift($statusHeader, $statusCode); + return $response->withHeader(self::HISTORY_HEADER, $historyHeader)->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader); + }); + } + private function guardMax(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options) + { + $current = isset($options['__redirect_count']) ? $options['__redirect_count'] : 0; + $options['__redirect_count'] = $current + 1; + $max = $options['allow_redirects']['max']; + if ($options['__redirect_count'] > $max) { + throw new \YoastSEO_Vendor\GuzzleHttp\Exception\TooManyRedirectsException("Will not follow more than {$max} redirects", $request); + } + } + /** + * @param RequestInterface $request + * @param array $options + * @param ResponseInterface $response + * + * @return RequestInterface + */ + public function modifyRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) + { + // Request modifications to apply. + $modify = []; + $protocols = $options['allow_redirects']['protocols']; + // Use a GET request if this is an entity enclosing request and we are + // not forcing RFC compliance, but rather emulating what all browsers + // would do. + $statusCode = $response->getStatusCode(); + if ($statusCode == 303 || $statusCode <= 302 && $request->getBody() && !$options['allow_redirects']['strict']) { + $modify['method'] = 'GET'; + $modify['body'] = ''; + } + $modify['uri'] = $this->redirectUri($request, $response, $protocols); + \YoastSEO_Vendor\GuzzleHttp\Psr7\rewind_body($request); + // Add the Referer header if it is told to do so and only + // add the header if we are not redirecting from https to http. + if ($options['allow_redirects']['referer'] && $modify['uri']->getScheme() === $request->getUri()->getScheme()) { + $uri = $request->getUri()->withUserInfo('', ''); + $modify['set_headers']['Referer'] = (string) $uri; + } else { + $modify['remove_headers'][] = 'Referer'; + } + // Remove Authorization header if host is different. + if ($request->getUri()->getHost() !== $modify['uri']->getHost()) { + $modify['remove_headers'][] = 'Authorization'; + } + return \YoastSEO_Vendor\GuzzleHttp\Psr7\modify_request($request, $modify); + } + /** + * Set the appropriate URL on the request based on the location header + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @param array $protocols + * + * @return UriInterface + */ + private function redirectUri(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, array $protocols) + { + $location = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve($request->getUri(), new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($response->getHeaderLine('Location'))); + // Ensure that the redirect URI is allowed based on the protocols. + if (!\in_array($location->getScheme(), $protocols)) { + throw new \YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException(\sprintf('Redirect URI, %s, does not use one of the allowed redirect protocols: %s', $location, \implode(', ', $protocols)), $request, $response); + } + return $location; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/RequestOptions.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/RequestOptions.php new file mode 100644 index 00000000..e100bb1d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/RequestOptions.php @@ -0,0 +1,228 @@ +decider = $decider; + $this->nextHandler = $nextHandler; + $this->delay = $delay ?: __CLASS__ . '::exponentialDelay'; + } + /** + * Default exponential backoff delay function. + * + * @param $retries + * + * @return int + */ + public static function exponentialDelay($retries) + { + return (int) \pow(2, $retries - 1); + } + /** + * @param RequestInterface $request + * @param array $options + * + * @return PromiseInterface + */ + public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) + { + if (!isset($options['retries'])) { + $options['retries'] = 0; + } + $fn = $this->nextHandler; + return $fn($request, $options)->then($this->onFulfilled($request, $options), $this->onRejected($request, $options)); + } + private function onFulfilled(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $req, array $options) + { + return function ($value) use($req, $options) { + if (!\call_user_func($this->decider, $options['retries'], $req, $value, null)) { + return $value; + } + return $this->doRetry($req, $options, $value); + }; + } + private function onRejected(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $req, array $options) + { + return function ($reason) use($req, $options) { + if (!\call_user_func($this->decider, $options['retries'], $req, null, $reason)) { + return \YoastSEO_Vendor\GuzzleHttp\Promise\rejection_for($reason); + } + return $this->doRetry($req, $options); + }; + } + private function doRetry(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null) + { + $options['delay'] = \call_user_func($this->delay, ++$options['retries'], $response); + return $this($request, $options); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/TransferStats.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/TransferStats.php new file mode 100644 index 00000000..a3caa919 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/TransferStats.php @@ -0,0 +1,110 @@ +request = $request; + $this->response = $response; + $this->transferTime = $transferTime; + $this->handlerErrorData = $handlerErrorData; + $this->handlerStats = $handlerStats; + } + /** + * @return RequestInterface + */ + public function getRequest() + { + return $this->request; + } + /** + * Returns the response that was received (if any). + * + * @return ResponseInterface|null + */ + public function getResponse() + { + return $this->response; + } + /** + * Returns true if a response was received. + * + * @return bool + */ + public function hasResponse() + { + return $this->response !== null; + } + /** + * Gets handler specific error data. + * + * This might be an exception, a integer representing an error code, or + * anything else. Relying on this value assumes that you know what handler + * you are using. + * + * @return mixed + */ + public function getHandlerErrorData() + { + return $this->handlerErrorData; + } + /** + * Get the effective URI the request was sent to. + * + * @return UriInterface + */ + public function getEffectiveUri() + { + return $this->request->getUri(); + } + /** + * Get the estimated time the request was being transferred by the handler. + * + * @return float Time in seconds. + */ + public function getTransferTime() + { + return $this->transferTime; + } + /** + * Gets an array of all of the handler specific transfer data. + * + * @return array + */ + public function getHandlerStats() + { + return $this->handlerStats; + } + /** + * Get a specific handler statistic from the handler by name. + * + * @param string $stat Handler specific transfer stat to retrieve. + * + * @return mixed|null + */ + public function getHandlerStat($stat) + { + return isset($this->handlerStats[$stat]) ? $this->handlerStats[$stat] : null; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/UriTemplate.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/UriTemplate.php new file mode 100644 index 00000000..4e94678a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/UriTemplate.php @@ -0,0 +1,191 @@ + ['prefix' => '', 'joiner' => ',', 'query' => \false], '+' => ['prefix' => '', 'joiner' => ',', 'query' => \false], '#' => ['prefix' => '#', 'joiner' => ',', 'query' => \false], '.' => ['prefix' => '.', 'joiner' => '.', 'query' => \false], '/' => ['prefix' => '/', 'joiner' => '/', 'query' => \false], ';' => ['prefix' => ';', 'joiner' => ';', 'query' => \true], '?' => ['prefix' => '?', 'joiner' => '&', 'query' => \true], '&' => ['prefix' => '&', 'joiner' => '&', 'query' => \true]]; + /** @var array Delimiters */ + private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=']; + /** @var array Percent encoded delimiters */ + private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D', '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', '%3B', '%3D']; + public function expand($template, array $variables) + { + if (\false === \strpos($template, '{')) { + return $template; + } + $this->template = $template; + $this->variables = $variables; + return \preg_replace_callback('/\\{([^\\}]+)\\}/', [$this, 'expandMatch'], $this->template); + } + /** + * Parse an expression into parts + * + * @param string $expression Expression to parse + * + * @return array Returns an associative array of parts + */ + private function parseExpression($expression) + { + $result = []; + if (isset(self::$operatorHash[$expression[0]])) { + $result['operator'] = $expression[0]; + $expression = \substr($expression, 1); + } else { + $result['operator'] = ''; + } + foreach (\explode(',', $expression) as $value) { + $value = \trim($value); + $varspec = []; + if ($colonPos = \strpos($value, ':')) { + $varspec['value'] = \substr($value, 0, $colonPos); + $varspec['modifier'] = ':'; + $varspec['position'] = (int) \substr($value, $colonPos + 1); + } elseif (\substr($value, -1) === '*') { + $varspec['modifier'] = '*'; + $varspec['value'] = \substr($value, 0, -1); + } else { + $varspec['value'] = (string) $value; + $varspec['modifier'] = ''; + } + $result['values'][] = $varspec; + } + return $result; + } + /** + * Process an expansion + * + * @param array $matches Matches met in the preg_replace_callback + * + * @return string Returns the replacement string + */ + private function expandMatch(array $matches) + { + static $rfc1738to3986 = ['+' => '%20', '%7e' => '~']; + $replacements = []; + $parsed = self::parseExpression($matches[1]); + $prefix = self::$operatorHash[$parsed['operator']]['prefix']; + $joiner = self::$operatorHash[$parsed['operator']]['joiner']; + $useQuery = self::$operatorHash[$parsed['operator']]['query']; + foreach ($parsed['values'] as $value) { + if (!isset($this->variables[$value['value']])) { + continue; + } + $variable = $this->variables[$value['value']]; + $actuallyUseQuery = $useQuery; + $expanded = ''; + if (\is_array($variable)) { + $isAssoc = $this->isAssoc($variable); + $kvp = []; + foreach ($variable as $key => $var) { + if ($isAssoc) { + $key = \rawurlencode($key); + $isNestedArray = \is_array($var); + } else { + $isNestedArray = \false; + } + if (!$isNestedArray) { + $var = \rawurlencode($var); + if ($parsed['operator'] === '+' || $parsed['operator'] === '#') { + $var = $this->decodeReserved($var); + } + } + if ($value['modifier'] === '*') { + if ($isAssoc) { + if ($isNestedArray) { + // Nested arrays must allow for deeply nested + // structures. + $var = \strtr(\http_build_query([$key => $var]), $rfc1738to3986); + } else { + $var = $key . '=' . $var; + } + } elseif ($key > 0 && $actuallyUseQuery) { + $var = $value['value'] . '=' . $var; + } + } + $kvp[$key] = $var; + } + if (empty($variable)) { + $actuallyUseQuery = \false; + } elseif ($value['modifier'] === '*') { + $expanded = \implode($joiner, $kvp); + if ($isAssoc) { + // Don't prepend the value name when using the explode + // modifier with an associative array. + $actuallyUseQuery = \false; + } + } else { + if ($isAssoc) { + // When an associative array is encountered and the + // explode modifier is not set, then the result must be + // a comma separated list of keys followed by their + // respective values. + foreach ($kvp as $k => &$v) { + $v = $k . ',' . $v; + } + } + $expanded = \implode(',', $kvp); + } + } else { + if ($value['modifier'] === ':') { + $variable = \substr($variable, 0, $value['position']); + } + $expanded = \rawurlencode($variable); + if ($parsed['operator'] === '+' || $parsed['operator'] === '#') { + $expanded = $this->decodeReserved($expanded); + } + } + if ($actuallyUseQuery) { + if (!$expanded && $joiner !== '&') { + $expanded = $value['value']; + } else { + $expanded = $value['value'] . '=' . $expanded; + } + } + $replacements[] = $expanded; + } + $ret = \implode($joiner, $replacements); + if ($ret && $prefix) { + return $prefix . $ret; + } + return $ret; + } + /** + * Determines if an array is associative. + * + * This makes the assumption that input arrays are sequences or hashes. + * This assumption is a tradeoff for accuracy in favor of speed, but it + * should work in almost every case where input is supplied for a URI + * template. + * + * @param array $array Array to check + * + * @return bool + */ + private function isAssoc(array $array) + { + return $array && \array_keys($array)[0] !== 0; + } + /** + * Removes percent encoding on reserved characters (used with + and # + * modifiers). + * + * @param string $string String to fix + * + * @return string + */ + private function decodeReserved($string) + { + return \str_replace(self::$delimsPct, self::$delims, $string); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/functions.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/functions.php new file mode 100644 index 00000000..a686964b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/guzzle/src/functions.php @@ -0,0 +1,294 @@ +expand($template, $variables); +} +/** + * Debug function used to describe the provided value type and class. + * + * @param mixed $input + * + * @return string Returns a string containing the type of the variable and + * if a class is provided, the class name. + */ +function describe_type($input) +{ + switch (\gettype($input)) { + case 'object': + return 'object(' . \get_class($input) . ')'; + case 'array': + return 'array(' . \count($input) . ')'; + default: + \ob_start(); + \var_dump($input); + // normalize float vs double + return \str_replace('double(', 'float(', \rtrim(\ob_get_clean())); + } +} +/** + * Parses an array of header lines into an associative array of headers. + * + * @param array $lines Header lines array of strings in the following + * format: "Name: Value" + * @return array + */ +function headers_from_lines($lines) +{ + $headers = []; + foreach ($lines as $line) { + $parts = \explode(':', $line, 2); + $headers[\trim($parts[0])][] = isset($parts[1]) ? \trim($parts[1]) : null; + } + return $headers; +} +/** + * Returns a debug stream based on the provided variable. + * + * @param mixed $value Optional value + * + * @return resource + */ +function debug_resource($value = null) +{ + if (\is_resource($value)) { + return $value; + } elseif (\defined('STDOUT')) { + return \STDOUT; + } + return \fopen('php://output', 'w'); +} +/** + * Chooses and creates a default handler to use based on the environment. + * + * The returned handler is not wrapped by any default middlewares. + * + * @throws \RuntimeException if no viable Handler is available. + * @return callable Returns the best handler for the given system. + */ +function choose_handler() +{ + $handler = null; + if (\function_exists('curl_multi_exec') && \function_exists('curl_exec')) { + $handler = \YoastSEO_Vendor\GuzzleHttp\Handler\Proxy::wrapSync(new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlMultiHandler(), new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlHandler()); + } elseif (\function_exists('curl_exec')) { + $handler = new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlHandler(); + } elseif (\function_exists('curl_multi_exec')) { + $handler = new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlMultiHandler(); + } + if (\ini_get('allow_url_fopen')) { + $handler = $handler ? \YoastSEO_Vendor\GuzzleHttp\Handler\Proxy::wrapStreaming($handler, new \YoastSEO_Vendor\GuzzleHttp\Handler\StreamHandler()) : new \YoastSEO_Vendor\GuzzleHttp\Handler\StreamHandler(); + } elseif (!$handler) { + throw new \RuntimeException('GuzzleHttp requires cURL, the ' . 'allow_url_fopen ini setting, or a custom HTTP handler.'); + } + return $handler; +} +/** + * Get the default User-Agent string to use with Guzzle + * + * @return string + */ +function default_user_agent() +{ + static $defaultAgent = ''; + if (!$defaultAgent) { + $defaultAgent = 'GuzzleHttp/' . \YoastSEO_Vendor\GuzzleHttp\Client::VERSION; + if (\extension_loaded('curl') && \function_exists('curl_version')) { + $defaultAgent .= ' curl/' . \curl_version()['version']; + } + $defaultAgent .= ' PHP/' . \PHP_VERSION; + } + return $defaultAgent; +} +/** + * Returns the default cacert bundle for the current system. + * + * First, the openssl.cafile and curl.cainfo php.ini settings are checked. + * If those settings are not configured, then the common locations for + * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X + * and Windows are checked. If any of these file locations are found on + * disk, they will be utilized. + * + * Note: the result of this function is cached for subsequent calls. + * + * @return string + * @throws \RuntimeException if no bundle can be found. + */ +function default_ca_bundle() +{ + static $cached = null; + static $cafiles = [ + // Red Hat, CentOS, Fedora (provided by the ca-certificates package) + '/etc/pki/tls/certs/ca-bundle.crt', + // Ubuntu, Debian (provided by the ca-certificates package) + '/etc/ssl/certs/ca-certificates.crt', + // FreeBSD (provided by the ca_root_nss package) + '/usr/local/share/certs/ca-root-nss.crt', + // SLES 12 (provided by the ca-certificates package) + '/var/lib/ca-certificates/ca-bundle.pem', + // OS X provided by homebrew (using the default path) + '/usr/local/etc/openssl/cert.pem', + // Google app engine + '/etc/ca-certificates.crt', + // Windows? + 'C:\\windows\\system32\\curl-ca-bundle.crt', + 'C:\\windows\\curl-ca-bundle.crt', + ]; + if ($cached) { + return $cached; + } + if ($ca = \ini_get('openssl.cafile')) { + return $cached = $ca; + } + if ($ca = \ini_get('curl.cainfo')) { + return $cached = $ca; + } + foreach ($cafiles as $filename) { + if (\file_exists($filename)) { + return $cached = $filename; + } + } + throw new \RuntimeException(<<then(function ($v) { echo $v; }); + * + * @param callable $generatorFn Generator function to wrap into a promise. + * + * @return Promise + * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration + */ +final class Coroutine implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface +{ + /** + * @var PromiseInterface|null + */ + private $currentPromise; + /** + * @var Generator + */ + private $generator; + /** + * @var Promise + */ + private $result; + public function __construct(callable $generatorFn) + { + $this->generator = $generatorFn(); + $this->result = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(function () { + while (isset($this->currentPromise)) { + $this->currentPromise->wait(); + } + }); + $this->nextCoroutine($this->generator->current()); + } + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + return $this->result->then($onFulfilled, $onRejected); + } + public function otherwise(callable $onRejected) + { + return $this->result->otherwise($onRejected); + } + public function wait($unwrap = \true) + { + return $this->result->wait($unwrap); + } + public function getState() + { + return $this->result->getState(); + } + public function resolve($value) + { + $this->result->resolve($value); + } + public function reject($reason) + { + $this->result->reject($reason); + } + public function cancel() + { + $this->currentPromise->cancel(); + $this->result->cancel(); + } + private function nextCoroutine($yielded) + { + $this->currentPromise = promise_for($yielded)->then([$this, '_handleSuccess'], [$this, '_handleFailure']); + } + /** + * @internal + */ + public function _handleSuccess($value) + { + unset($this->currentPromise); + try { + $next = $this->generator->send($value); + if ($this->generator->valid()) { + $this->nextCoroutine($next); + } else { + $this->result->resolve($value); + } + } catch (\Exception $exception) { + $this->result->reject($exception); + } catch (\Throwable $throwable) { + $this->result->reject($throwable); + } + } + /** + * @internal + */ + public function _handleFailure($reason) + { + unset($this->currentPromise); + try { + $nextYield = $this->generator->throw(exception_for($reason)); + // The throw was caught, so keep iterating on the coroutine + $this->nextCoroutine($nextYield); + } catch (\Exception $exception) { + $this->result->reject($exception); + } catch (\Throwable $throwable) { + $this->result->reject($throwable); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/EachPromise.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/EachPromise.php new file mode 100644 index 00000000..619065eb --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/EachPromise.php @@ -0,0 +1,190 @@ +iterable = iter_for($iterable); + if (isset($config['concurrency'])) { + $this->concurrency = $config['concurrency']; + } + if (isset($config['fulfilled'])) { + $this->onFulfilled = $config['fulfilled']; + } + if (isset($config['rejected'])) { + $this->onRejected = $config['rejected']; + } + } + public function promise() + { + if ($this->aggregate) { + return $this->aggregate; + } + try { + $this->createPromise(); + $this->iterable->rewind(); + $this->refillPending(); + } catch (\Throwable $e) { + $this->aggregate->reject($e); + } catch (\Exception $e) { + $this->aggregate->reject($e); + } + return $this->aggregate; + } + private function createPromise() + { + $this->mutex = \false; + $this->aggregate = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(function () { + \reset($this->pending); + if (empty($this->pending) && !$this->iterable->valid()) { + $this->aggregate->resolve(null); + return; + } + // Consume a potentially fluctuating list of promises while + // ensuring that indexes are maintained (precluding array_shift). + while ($promise = \current($this->pending)) { + \next($this->pending); + $promise->wait(); + if ($this->aggregate->getState() !== \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::PENDING) { + return; + } + } + }); + // Clear the references when the promise is resolved. + $clearFn = function () { + $this->iterable = $this->concurrency = $this->pending = null; + $this->onFulfilled = $this->onRejected = null; + }; + $this->aggregate->then($clearFn, $clearFn); + } + private function refillPending() + { + if (!$this->concurrency) { + // Add all pending promises. + while ($this->addPending() && $this->advanceIterator()) { + } + return; + } + // Add only up to N pending promises. + $concurrency = \is_callable($this->concurrency) ? \call_user_func($this->concurrency, \count($this->pending)) : $this->concurrency; + $concurrency = \max($concurrency - \count($this->pending), 0); + // Concurrency may be set to 0 to disallow new promises. + if (!$concurrency) { + return; + } + // Add the first pending promise. + $this->addPending(); + // Note this is special handling for concurrency=1 so that we do + // not advance the iterator after adding the first promise. This + // helps work around issues with generators that might not have the + // next value to yield until promise callbacks are called. + while (--$concurrency && $this->advanceIterator() && $this->addPending()) { + } + } + private function addPending() + { + if (!$this->iterable || !$this->iterable->valid()) { + return \false; + } + $promise = promise_for($this->iterable->current()); + $idx = $this->iterable->key(); + $this->pending[$idx] = $promise->then(function ($value) use($idx) { + if ($this->onFulfilled) { + \call_user_func($this->onFulfilled, $value, $idx, $this->aggregate); + } + $this->step($idx); + }, function ($reason) use($idx) { + if ($this->onRejected) { + \call_user_func($this->onRejected, $reason, $idx, $this->aggregate); + } + $this->step($idx); + }); + return \true; + } + private function advanceIterator() + { + // Place a lock on the iterator so that we ensure to not recurse, + // preventing fatal generator errors. + if ($this->mutex) { + return \false; + } + $this->mutex = \true; + try { + $this->iterable->next(); + $this->mutex = \false; + return \true; + } catch (\Throwable $e) { + $this->aggregate->reject($e); + $this->mutex = \false; + return \false; + } catch (\Exception $e) { + $this->aggregate->reject($e); + $this->mutex = \false; + return \false; + } + } + private function step($idx) + { + // If the promise was already resolved, then ignore this step. + if ($this->aggregate->getState() !== \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::PENDING) { + return; + } + unset($this->pending[$idx]); + // Only refill pending promises if we are not locked, preventing the + // EachPromise to recursively invoke the provided iterator, which + // cause a fatal error: "Cannot resume an already running generator" + if ($this->advanceIterator() && !$this->checkIfFinished()) { + // Add more pending promises if possible. + $this->refillPending(); + } + } + private function checkIfFinished() + { + if (!$this->pending && !$this->iterable->valid()) { + // Resolve the promise if there's nothing left to do. + $this->aggregate->resolve(null); + return \true; + } + return \false; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/FulfilledPromise.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/FulfilledPromise.php new file mode 100644 index 00000000..836be482 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/FulfilledPromise.php @@ -0,0 +1,69 @@ +value = $value; + } + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + // Return itself if there is no onFulfilled function. + if (!$onFulfilled) { + return $this; + } + $queue = queue(); + $p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']); + $value = $this->value; + $queue->add(static function () use($p, $value, $onFulfilled) { + if ($p->getState() === self::PENDING) { + try { + $p->resolve($onFulfilled($value)); + } catch (\Throwable $e) { + $p->reject($e); + } catch (\Exception $e) { + $p->reject($e); + } + } + }); + return $p; + } + public function otherwise(callable $onRejected) + { + return $this->then(null, $onRejected); + } + public function wait($unwrap = \true, $defaultDelivery = null) + { + return $unwrap ? $this->value : null; + } + public function getState() + { + return self::FULFILLED; + } + public function resolve($value) + { + if ($value !== $this->value) { + throw new \LogicException("Cannot resolve a fulfilled promise"); + } + } + public function reject($reason) + { + throw new \LogicException("Cannot reject a fulfilled promise"); + } + public function cancel() + { + // pass + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/Promise.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/Promise.php new file mode 100644 index 00000000..14d2ed7d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/Promise.php @@ -0,0 +1,231 @@ +waitFn = $waitFn; + $this->cancelFn = $cancelFn; + } + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + if ($this->state === self::PENDING) { + $p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(null, [$this, 'cancel']); + $this->handlers[] = [$p, $onFulfilled, $onRejected]; + $p->waitList = $this->waitList; + $p->waitList[] = $this; + return $p; + } + // Return a fulfilled promise and immediately invoke any callbacks. + if ($this->state === self::FULFILLED) { + return $onFulfilled ? promise_for($this->result)->then($onFulfilled) : promise_for($this->result); + } + // It's either cancelled or rejected, so return a rejected promise + // and immediately invoke any callbacks. + $rejection = rejection_for($this->result); + return $onRejected ? $rejection->then(null, $onRejected) : $rejection; + } + public function otherwise(callable $onRejected) + { + return $this->then(null, $onRejected); + } + public function wait($unwrap = \true) + { + $this->waitIfPending(); + $inner = $this->result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface ? $this->result->wait($unwrap) : $this->result; + if ($unwrap) { + if ($this->result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface || $this->state === self::FULFILLED) { + return $inner; + } else { + // It's rejected so "unwrap" and throw an exception. + throw exception_for($inner); + } + } + } + public function getState() + { + return $this->state; + } + public function cancel() + { + if ($this->state !== self::PENDING) { + return; + } + $this->waitFn = $this->waitList = null; + if ($this->cancelFn) { + $fn = $this->cancelFn; + $this->cancelFn = null; + try { + $fn(); + } catch (\Throwable $e) { + $this->reject($e); + } catch (\Exception $e) { + $this->reject($e); + } + } + // Reject the promise only if it wasn't rejected in a then callback. + if ($this->state === self::PENDING) { + $this->reject(new \YoastSEO_Vendor\GuzzleHttp\Promise\CancellationException('Promise has been cancelled')); + } + } + public function resolve($value) + { + $this->settle(self::FULFILLED, $value); + } + public function reject($reason) + { + $this->settle(self::REJECTED, $reason); + } + private function settle($state, $value) + { + if ($this->state !== self::PENDING) { + // Ignore calls with the same resolution. + if ($state === $this->state && $value === $this->result) { + return; + } + throw $this->state === $state ? new \LogicException("The promise is already {$state}.") : new \LogicException("Cannot change a {$this->state} promise to {$state}"); + } + if ($value === $this) { + throw new \LogicException('Cannot fulfill or reject a promise with itself'); + } + // Clear out the state of the promise but stash the handlers. + $this->state = $state; + $this->result = $value; + $handlers = $this->handlers; + $this->handlers = null; + $this->waitList = $this->waitFn = null; + $this->cancelFn = null; + if (!$handlers) { + return; + } + // If the value was not a settled promise or a thenable, then resolve + // it in the task queue using the correct ID. + if (!\method_exists($value, 'then')) { + $id = $state === self::FULFILLED ? 1 : 2; + // It's a success, so resolve the handlers in the queue. + queue()->add(static function () use($id, $value, $handlers) { + foreach ($handlers as $handler) { + self::callHandler($id, $value, $handler); + } + }); + } elseif ($value instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\Promise && $value->getState() === self::PENDING) { + // We can just merge our handlers onto the next promise. + $value->handlers = \array_merge($value->handlers, $handlers); + } else { + // Resolve the handlers when the forwarded promise is resolved. + $value->then(static function ($value) use($handlers) { + foreach ($handlers as $handler) { + self::callHandler(1, $value, $handler); + } + }, static function ($reason) use($handlers) { + foreach ($handlers as $handler) { + self::callHandler(2, $reason, $handler); + } + }); + } + } + /** + * Call a stack of handlers using a specific callback index and value. + * + * @param int $index 1 (resolve) or 2 (reject). + * @param mixed $value Value to pass to the callback. + * @param array $handler Array of handler data (promise and callbacks). + * + * @return array Returns the next group to resolve. + */ + private static function callHandler($index, $value, array $handler) + { + /** @var PromiseInterface $promise */ + $promise = $handler[0]; + // The promise may have been cancelled or resolved before placing + // this thunk in the queue. + if ($promise->getState() !== self::PENDING) { + return; + } + try { + if (isset($handler[$index])) { + $promise->resolve($handler[$index]($value)); + } elseif ($index === 1) { + // Forward resolution values as-is. + $promise->resolve($value); + } else { + // Forward rejections down the chain. + $promise->reject($value); + } + } catch (\Throwable $reason) { + $promise->reject($reason); + } catch (\Exception $reason) { + $promise->reject($reason); + } + } + private function waitIfPending() + { + if ($this->state !== self::PENDING) { + return; + } elseif ($this->waitFn) { + $this->invokeWaitFn(); + } elseif ($this->waitList) { + $this->invokeWaitList(); + } else { + // If there's not wait function, then reject the promise. + $this->reject('Cannot wait on a promise that has ' . 'no internal wait function. You must provide a wait ' . 'function when constructing the promise to be able to ' . 'wait on a promise.'); + } + queue()->run(); + if ($this->state === self::PENDING) { + $this->reject('Invoking the wait callback did not resolve the promise'); + } + } + private function invokeWaitFn() + { + try { + $wfn = $this->waitFn; + $this->waitFn = null; + $wfn(\true); + } catch (\Exception $reason) { + if ($this->state === self::PENDING) { + // The promise has not been resolved yet, so reject the promise + // with the exception. + $this->reject($reason); + } else { + // The promise was already resolved, so there's a problem in + // the application. + throw $reason; + } + } + } + private function invokeWaitList() + { + $waitList = $this->waitList; + $this->waitList = null; + foreach ($waitList as $result) { + while (\true) { + $result->waitIfPending(); + if ($result->result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\Promise) { + $result = $result->result; + } else { + if ($result->result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) { + $result->result->wait(\false); + } + break; + } + } + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/PromiseInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/PromiseInterface.php new file mode 100644 index 00000000..29445bee --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/PromiseInterface.php @@ -0,0 +1,84 @@ +reason = $reason; + } + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + // If there's no onRejected callback then just return self. + if (!$onRejected) { + return $this; + } + $queue = queue(); + $reason = $this->reason; + $p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']); + $queue->add(static function () use($p, $reason, $onRejected) { + if ($p->getState() === self::PENDING) { + try { + // Return a resolved promise if onRejected does not throw. + $p->resolve($onRejected($reason)); + } catch (\Throwable $e) { + // onRejected threw, so return a rejected promise. + $p->reject($e); + } catch (\Exception $e) { + // onRejected threw, so return a rejected promise. + $p->reject($e); + } + } + }); + return $p; + } + public function otherwise(callable $onRejected) + { + return $this->then(null, $onRejected); + } + public function wait($unwrap = \true, $defaultDelivery = null) + { + if ($unwrap) { + throw exception_for($this->reason); + } + } + public function getState() + { + return self::REJECTED; + } + public function resolve($value) + { + throw new \LogicException("Cannot resolve a rejected promise"); + } + public function reject($reason) + { + if ($reason !== $this->reason) { + throw new \LogicException("Cannot reject a rejected promise"); + } + } + public function cancel() + { + // pass + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/RejectionException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/RejectionException.php new file mode 100644 index 00000000..159deb82 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/RejectionException.php @@ -0,0 +1,40 @@ +reason = $reason; + $message = 'The promise was rejected'; + if ($description) { + $message .= ' with reason: ' . $description; + } elseif (\is_string($reason) || \is_object($reason) && \method_exists($reason, '__toString')) { + $message .= ' with reason: ' . $this->reason; + } elseif ($reason instanceof \JsonSerializable) { + $message .= ' with reason: ' . \json_encode($this->reason, \JSON_PRETTY_PRINT); + } + parent::__construct($message); + } + /** + * Returns the rejection reason. + * + * @return mixed + */ + public function getReason() + { + return $this->reason; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/TaskQueue.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/TaskQueue.php new file mode 100644 index 00000000..a9d2a9f1 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/TaskQueue.php @@ -0,0 +1,62 @@ +run(); + */ +class TaskQueue implements \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface +{ + private $enableShutdown = \true; + private $queue = []; + public function __construct($withShutdown = \true) + { + if ($withShutdown) { + \register_shutdown_function(function () { + if ($this->enableShutdown) { + // Only run the tasks if an E_ERROR didn't occur. + $err = \error_get_last(); + if (!$err || $err['type'] ^ \E_ERROR) { + $this->run(); + } + } + }); + } + } + public function isEmpty() + { + return !$this->queue; + } + public function add(callable $task) + { + $this->queue[] = $task; + } + public function run() + { + /** @var callable $task */ + while ($task = \array_shift($this->queue)) { + $task(); + } + } + /** + * The task queue will be run and exhausted by default when the process + * exits IFF the exit is not the result of a PHP E_ERROR error. + * + * You can disable running the automatic shutdown of the queue by calling + * this function. If you disable the task queue shutdown process, then you + * MUST either run the task queue (as a result of running your event loop + * or manually using the run() method) or wait on each outstanding promise. + * + * Note: This shutdown will occur before any destructors are triggered. + */ + public function disableShutdown() + { + $this->enableShutdown = \false; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/TaskQueueInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/TaskQueueInterface.php new file mode 100644 index 00000000..1d4256c8 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/TaskQueueInterface.php @@ -0,0 +1,24 @@ + + * while ($eventLoop->isRunning()) { + * GuzzleHttp\Promise\queue()->run(); + * } + * + * + * @param TaskQueueInterface $assign Optionally specify a new queue instance. + * + * @return TaskQueueInterface + */ +function queue(\YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface $assign = null) +{ + static $queue; + if ($assign) { + $queue = $assign; + } elseif (!$queue) { + $queue = new \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueue(); + } + return $queue; +} +/** + * Adds a function to run in the task queue when it is next `run()` and returns + * a promise that is fulfilled or rejected with the result. + * + * @param callable $task Task function to run. + * + * @return PromiseInterface + */ +function task(callable $task) +{ + $queue = queue(); + $promise = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']); + $queue->add(function () use($task, $promise) { + try { + $promise->resolve($task()); + } catch (\Throwable $e) { + $promise->reject($e); + } catch (\Exception $e) { + $promise->reject($e); + } + }); + return $promise; +} +/** + * Creates a promise for a value if the value is not a promise. + * + * @param mixed $value Promise or value. + * + * @return PromiseInterface + */ +function promise_for($value) +{ + if ($value instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) { + return $value; + } + // Return a Guzzle promise that shadows the given promise. + if (\method_exists($value, 'then')) { + $wfn = \method_exists($value, 'wait') ? [$value, 'wait'] : null; + $cfn = \method_exists($value, 'cancel') ? [$value, 'cancel'] : null; + $promise = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise($wfn, $cfn); + $value->then([$promise, 'resolve'], [$promise, 'reject']); + return $promise; + } + return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($value); +} +/** + * Creates a rejected promise for a reason if the reason is not a promise. If + * the provided reason is a promise, then it is returned as-is. + * + * @param mixed $reason Promise or reason. + * + * @return PromiseInterface + */ +function rejection_for($reason) +{ + if ($reason instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) { + return $reason; + } + return new \YoastSEO_Vendor\GuzzleHttp\Promise\RejectedPromise($reason); +} +/** + * Create an exception for a rejected promise value. + * + * @param mixed $reason + * + * @return \Exception|\Throwable + */ +function exception_for($reason) +{ + return $reason instanceof \Exception || $reason instanceof \Throwable ? $reason : new \YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException($reason); +} +/** + * Returns an iterator for the given value. + * + * @param mixed $value + * + * @return \Iterator + */ +function iter_for($value) +{ + if ($value instanceof \Iterator) { + return $value; + } elseif (\is_array($value)) { + return new \ArrayIterator($value); + } else { + return new \ArrayIterator([$value]); + } +} +/** + * Synchronously waits on a promise to resolve and returns an inspection state + * array. + * + * Returns a state associative array containing a "state" key mapping to a + * valid promise state. If the state of the promise is "fulfilled", the array + * will contain a "value" key mapping to the fulfilled value of the promise. If + * the promise is rejected, the array will contain a "reason" key mapping to + * the rejection reason of the promise. + * + * @param PromiseInterface $promise Promise or value. + * + * @return array + */ +function inspect(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) +{ + try { + return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $promise->wait()]; + } catch (\YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException $e) { + return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e->getReason()]; + } catch (\Throwable $e) { + return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e]; + } catch (\Exception $e) { + return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e]; + } +} +/** + * Waits on all of the provided promises, but does not unwrap rejected promises + * as thrown exception. + * + * Returns an array of inspection state arrays. + * + * @param PromiseInterface[] $promises Traversable of promises to wait upon. + * + * @return array + * @see GuzzleHttp\Promise\inspect for the inspection state array format. + */ +function inspect_all($promises) +{ + $results = []; + foreach ($promises as $key => $promise) { + $results[$key] = inspect($promise); + } + return $results; +} +/** + * Waits on all of the provided promises and returns the fulfilled values. + * + * Returns an array that contains the value of each promise (in the same order + * the promises were provided). An exception is thrown if any of the promises + * are rejected. + * + * @param mixed $promises Iterable of PromiseInterface objects to wait on. + * + * @return array + * @throws \Exception on error + * @throws \Throwable on error in PHP >=7 + */ +function unwrap($promises) +{ + $results = []; + foreach ($promises as $key => $promise) { + $results[$key] = $promise->wait(); + } + return $results; +} +/** + * Given an array of promises, return a promise that is fulfilled when all the + * items in the array are fulfilled. + * + * The promise's fulfillment value is an array with fulfillment values at + * respective positions to the original array. If any promise in the array + * rejects, the returned promise is rejected with the rejection reason. + * + * @param mixed $promises Promises or values. + * + * @return PromiseInterface + */ +function all($promises) +{ + $results = []; + return \each($promises, function ($value, $idx) use(&$results) { + $results[$idx] = $value; + }, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\Promise $aggregate) { + $aggregate->reject($reason); + })->then(function () use(&$results) { + \ksort($results); + return $results; + }); +} +/** + * Initiate a competitive race between multiple promises or values (values will + * become immediately fulfilled promises). + * + * When count amount of promises have been fulfilled, the returned promise is + * fulfilled with an array that contains the fulfillment values of the winners + * in order of resolution. + * + * This prommise is rejected with a {@see GuzzleHttp\Promise\AggregateException} + * if the number of fulfilled promises is less than the desired $count. + * + * @param int $count Total number of promises. + * @param mixed $promises Promises or values. + * + * @return PromiseInterface + */ +function some($count, $promises) +{ + $results = []; + $rejections = []; + return \each($promises, function ($value, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $p) use(&$results, $count) { + if ($p->getState() !== \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::PENDING) { + return; + } + $results[$idx] = $value; + if (\count($results) >= $count) { + $p->resolve(null); + } + }, function ($reason) use(&$rejections) { + $rejections[] = $reason; + })->then(function () use(&$results, &$rejections, $count) { + if (\count($results) !== $count) { + throw new \YoastSEO_Vendor\GuzzleHttp\Promise\AggregateException('Not enough promises to fulfill count', $rejections); + } + \ksort($results); + return \array_values($results); + }); +} +/** + * Like some(), with 1 as count. However, if the promise fulfills, the + * fulfillment value is not an array of 1 but the value directly. + * + * @param mixed $promises Promises or values. + * + * @return PromiseInterface + */ +function any($promises) +{ + return some(1, $promises)->then(function ($values) { + return $values[0]; + }); +} +/** + * Returns a promise that is fulfilled when all of the provided promises have + * been fulfilled or rejected. + * + * The returned promise is fulfilled with an array of inspection state arrays. + * + * @param mixed $promises Promises or values. + * + * @return PromiseInterface + * @see GuzzleHttp\Promise\inspect for the inspection state array format. + */ +function settle($promises) +{ + $results = []; + return \each($promises, function ($value, $idx) use(&$results) { + $results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $value]; + }, function ($reason, $idx) use(&$results) { + $results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $reason]; + })->then(function () use(&$results) { + \ksort($results); + return $results; + }); +} +/** + * Given an iterator that yields promises or values, returns a promise that is + * fulfilled with a null value when the iterator has been consumed or the + * aggregate promise has been fulfilled or rejected. + * + * $onFulfilled is a function that accepts the fulfilled value, iterator + * index, and the aggregate promise. The callback can invoke any necessary side + * effects and choose to resolve or reject the aggregate promise if needed. + * + * $onRejected is a function that accepts the rejection reason, iterator + * index, and the aggregate promise. The callback can invoke any necessary side + * effects and choose to resolve or reject the aggregate promise if needed. + * + * @param mixed $iterable Iterator or array to iterate over. + * @param callable $onFulfilled + * @param callable $onRejected + * + * @return PromiseInterface + */ +function each($iterable, callable $onFulfilled = null, callable $onRejected = null) +{ + return (new \YoastSEO_Vendor\GuzzleHttp\Promise\EachPromise($iterable, ['fulfilled' => $onFulfilled, 'rejected' => $onRejected]))->promise(); +} +/** + * Like each, but only allows a certain number of outstanding promises at any + * given time. + * + * $concurrency may be an integer or a function that accepts the number of + * pending promises and returns a numeric concurrency limit value to allow for + * dynamic a concurrency size. + * + * @param mixed $iterable + * @param int|callable $concurrency + * @param callable $onFulfilled + * @param callable $onRejected + * + * @return PromiseInterface + */ +function each_limit($iterable, $concurrency, callable $onFulfilled = null, callable $onRejected = null) +{ + return (new \YoastSEO_Vendor\GuzzleHttp\Promise\EachPromise($iterable, ['fulfilled' => $onFulfilled, 'rejected' => $onRejected, 'concurrency' => $concurrency]))->promise(); +} +/** + * Like each_limit, but ensures that no promise in the given $iterable argument + * is rejected. If any promise is rejected, then the aggregate promise is + * rejected with the encountered rejection. + * + * @param mixed $iterable + * @param int|callable $concurrency + * @param callable $onFulfilled + * + * @return PromiseInterface + */ +function each_limit_all($iterable, $concurrency, callable $onFulfilled = null) +{ + return each_limit($iterable, $concurrency, $onFulfilled, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $aggregate) { + $aggregate->reject($reason); + }); +} +/** + * Returns true if a promise is fulfilled. + * + * @param PromiseInterface $promise + * + * @return bool + */ +function is_fulfilled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) +{ + return $promise->getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED; +} +/** + * Returns true if a promise is rejected. + * + * @param PromiseInterface $promise + * + * @return bool + */ +function is_rejected(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) +{ + return $promise->getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED; +} +/** + * Returns true if a promise is fulfilled or rejected. + * + * @param PromiseInterface $promise + * + * @return bool + */ +function is_settled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) +{ + return $promise->getState() !== \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::PENDING; +} +/** + * @see Coroutine + * + * @param callable $generatorFn + * + * @return PromiseInterface + */ +function coroutine(callable $generatorFn) +{ + return new \YoastSEO_Vendor\GuzzleHttp\Promise\Coroutine($generatorFn); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/functions_include.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/functions_include.php new file mode 100644 index 00000000..b0a22d15 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/promises/src/functions_include.php @@ -0,0 +1,8 @@ +addStream($stream); + } + } + public function __toString() + { + try { + $this->rewind(); + return $this->getContents(); + } catch (\Exception $e) { + return ''; + } + } + /** + * Add a stream to the AppendStream + * + * @param StreamInterface $stream Stream to append. Must be readable. + * + * @throws \InvalidArgumentException if the stream is not readable + */ + public function addStream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream) + { + if (!$stream->isReadable()) { + throw new \InvalidArgumentException('Each stream must be readable'); + } + // The stream is only seekable if all streams are seekable + if (!$stream->isSeekable()) { + $this->seekable = \false; + } + $this->streams[] = $stream; + } + public function getContents() + { + return copy_to_string($this); + } + /** + * Closes each attached stream. + * + * {@inheritdoc} + */ + public function close() + { + $this->pos = $this->current = 0; + $this->seekable = \true; + foreach ($this->streams as $stream) { + $stream->close(); + } + $this->streams = []; + } + /** + * Detaches each attached stream. + * + * Returns null as it's not clear which underlying stream resource to return. + * + * {@inheritdoc} + */ + public function detach() + { + $this->pos = $this->current = 0; + $this->seekable = \true; + foreach ($this->streams as $stream) { + $stream->detach(); + } + $this->streams = []; + } + public function tell() + { + return $this->pos; + } + /** + * Tries to calculate the size by adding the size of each stream. + * + * If any of the streams do not return a valid number, then the size of the + * append stream cannot be determined and null is returned. + * + * {@inheritdoc} + */ + public function getSize() + { + $size = 0; + foreach ($this->streams as $stream) { + $s = $stream->getSize(); + if ($s === null) { + return null; + } + $size += $s; + } + return $size; + } + public function eof() + { + return !$this->streams || $this->current >= \count($this->streams) - 1 && $this->streams[$this->current]->eof(); + } + public function rewind() + { + $this->seek(0); + } + /** + * Attempts to seek to the given position. Only supports SEEK_SET. + * + * {@inheritdoc} + */ + public function seek($offset, $whence = \SEEK_SET) + { + if (!$this->seekable) { + throw new \RuntimeException('This AppendStream is not seekable'); + } elseif ($whence !== \SEEK_SET) { + throw new \RuntimeException('The AppendStream can only seek with SEEK_SET'); + } + $this->pos = $this->current = 0; + // Rewind each stream + foreach ($this->streams as $i => $stream) { + try { + $stream->rewind(); + } catch (\Exception $e) { + throw new \RuntimeException('Unable to seek stream ' . $i . ' of the AppendStream', 0, $e); + } + } + // Seek to the actual position by reading from each stream + while ($this->pos < $offset && !$this->eof()) { + $result = $this->read(\min(8096, $offset - $this->pos)); + if ($result === '') { + break; + } + } + } + /** + * Reads from all of the appended streams until the length is met or EOF. + * + * {@inheritdoc} + */ + public function read($length) + { + $buffer = ''; + $total = \count($this->streams) - 1; + $remaining = $length; + $progressToNext = \false; + while ($remaining > 0) { + // Progress to the next stream if needed. + if ($progressToNext || $this->streams[$this->current]->eof()) { + $progressToNext = \false; + if ($this->current === $total) { + break; + } + $this->current++; + } + $result = $this->streams[$this->current]->read($remaining); + // Using a loose comparison here to match on '', false, and null + if ($result == null) { + $progressToNext = \true; + continue; + } + $buffer .= $result; + $remaining = $length - \strlen($buffer); + } + $this->pos += \strlen($buffer); + return $buffer; + } + public function isReadable() + { + return \true; + } + public function isWritable() + { + return \false; + } + public function isSeekable() + { + return $this->seekable; + } + public function write($string) + { + throw new \RuntimeException('Cannot write to an AppendStream'); + } + public function getMetadata($key = null) + { + return $key ? null : []; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/BufferStream.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/BufferStream.php new file mode 100644 index 00000000..c84a1c0e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/BufferStream.php @@ -0,0 +1,115 @@ +hwm = $hwm; + } + public function __toString() + { + return $this->getContents(); + } + public function getContents() + { + $buffer = $this->buffer; + $this->buffer = ''; + return $buffer; + } + public function close() + { + $this->buffer = ''; + } + public function detach() + { + $this->close(); + } + public function getSize() + { + return \strlen($this->buffer); + } + public function isReadable() + { + return \true; + } + public function isWritable() + { + return \true; + } + public function isSeekable() + { + return \false; + } + public function rewind() + { + $this->seek(0); + } + public function seek($offset, $whence = \SEEK_SET) + { + throw new \RuntimeException('Cannot seek a BufferStream'); + } + public function eof() + { + return \strlen($this->buffer) === 0; + } + public function tell() + { + throw new \RuntimeException('Cannot determine the position of a BufferStream'); + } + /** + * Reads data from the buffer. + */ + public function read($length) + { + $currentLength = \strlen($this->buffer); + if ($length >= $currentLength) { + // No need to slice the buffer because we don't have enough data. + $result = $this->buffer; + $this->buffer = ''; + } else { + // Slice up the result to provide a subset of the buffer. + $result = \substr($this->buffer, 0, $length); + $this->buffer = \substr($this->buffer, $length); + } + return $result; + } + /** + * Writes data to the buffer. + */ + public function write($string) + { + $this->buffer .= $string; + // TODO: What should happen here? + if (\strlen($this->buffer) >= $this->hwm) { + return \false; + } + return \strlen($string); + } + public function getMetadata($key = null) + { + if ($key == 'hwm') { + return $this->hwm; + } + return $key ? null : []; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/CachingStream.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/CachingStream.php new file mode 100644 index 00000000..779c7020 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/CachingStream.php @@ -0,0 +1,115 @@ +remoteStream = $stream; + $this->stream = $target ?: new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream(\fopen('php://temp', 'r+')); + } + public function getSize() + { + return \max($this->stream->getSize(), $this->remoteStream->getSize()); + } + public function rewind() + { + $this->seek(0); + } + public function seek($offset, $whence = \SEEK_SET) + { + if ($whence == \SEEK_SET) { + $byte = $offset; + } elseif ($whence == \SEEK_CUR) { + $byte = $offset + $this->tell(); + } elseif ($whence == \SEEK_END) { + $size = $this->remoteStream->getSize(); + if ($size === null) { + $size = $this->cacheEntireStream(); + } + $byte = $size + $offset; + } else { + throw new \InvalidArgumentException('Invalid whence'); + } + $diff = $byte - $this->stream->getSize(); + if ($diff > 0) { + // Read the remoteStream until we have read in at least the amount + // of bytes requested, or we reach the end of the file. + while ($diff > 0 && !$this->remoteStream->eof()) { + $this->read($diff); + $diff = $byte - $this->stream->getSize(); + } + } else { + // We can just do a normal seek since we've already seen this byte. + $this->stream->seek($byte); + } + } + public function read($length) + { + // Perform a regular read on any previously read data from the buffer + $data = $this->stream->read($length); + $remaining = $length - \strlen($data); + // More data was requested so read from the remote stream + if ($remaining) { + // If data was written to the buffer in a position that would have + // been filled from the remote stream, then we must skip bytes on + // the remote stream to emulate overwriting bytes from that + // position. This mimics the behavior of other PHP stream wrappers. + $remoteData = $this->remoteStream->read($remaining + $this->skipReadBytes); + if ($this->skipReadBytes) { + $len = \strlen($remoteData); + $remoteData = \substr($remoteData, $this->skipReadBytes); + $this->skipReadBytes = \max(0, $this->skipReadBytes - $len); + } + $data .= $remoteData; + $this->stream->write($remoteData); + } + return $data; + } + public function write($string) + { + // When appending to the end of the currently read stream, you'll want + // to skip bytes from being read from the remote stream to emulate + // other stream wrappers. Basically replacing bytes of data of a fixed + // length. + $overflow = \strlen($string) + $this->tell() - $this->remoteStream->tell(); + if ($overflow > 0) { + $this->skipReadBytes += $overflow; + } + return $this->stream->write($string); + } + public function eof() + { + return $this->stream->eof() && $this->remoteStream->eof(); + } + /** + * Close both the remote stream and buffer stream + */ + public function close() + { + $this->remoteStream->close() && $this->stream->close(); + } + private function cacheEntireStream() + { + $target = new \YoastSEO_Vendor\GuzzleHttp\Psr7\FnStream(['write' => 'strlen']); + copy_to_stream($this, $target); + return $this->tell(); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/DroppingStream.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/DroppingStream.php new file mode 100644 index 00000000..d4b04342 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/DroppingStream.php @@ -0,0 +1,36 @@ +stream = $stream; + $this->maxLength = $maxLength; + } + public function write($string) + { + $diff = $this->maxLength - $this->stream->getSize(); + // Begin returning 0 when the underlying stream is too large. + if ($diff <= 0) { + return 0; + } + // Write the stream or a subset of the stream if needed. + if (\strlen($string) < $diff) { + return $this->stream->write($string); + } + return $this->stream->write(\substr($string, 0, $diff)); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/FnStream.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/FnStream.php new file mode 100644 index 00000000..ecb87559 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/FnStream.php @@ -0,0 +1,132 @@ +methods = $methods; + // Create the functions on the class + foreach ($methods as $name => $fn) { + $this->{'_fn_' . $name} = $fn; + } + } + /** + * Lazily determine which methods are not implemented. + * @throws \BadMethodCallException + */ + public function __get($name) + { + throw new \BadMethodCallException(\str_replace('_fn_', '', $name) . '() is not implemented in the FnStream'); + } + /** + * The close method is called on the underlying stream only if possible. + */ + public function __destruct() + { + if (isset($this->_fn_close)) { + \call_user_func($this->_fn_close); + } + } + /** + * An unserialize would allow the __destruct to run when the unserialized value goes out of scope. + * @throws \LogicException + */ + public function __wakeup() + { + throw new \LogicException('FnStream should never be unserialized'); + } + /** + * Adds custom functionality to an underlying stream by intercepting + * specific method calls. + * + * @param StreamInterface $stream Stream to decorate + * @param array $methods Hash of method name to a closure + * + * @return FnStream + */ + public static function decorate(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, array $methods) + { + // If any of the required methods were not provided, then simply + // proxy to the decorated stream. + foreach (\array_diff(self::$slots, \array_keys($methods)) as $diff) { + $methods[$diff] = [$stream, $diff]; + } + return new self($methods); + } + public function __toString() + { + return \call_user_func($this->_fn___toString); + } + public function close() + { + return \call_user_func($this->_fn_close); + } + public function detach() + { + return \call_user_func($this->_fn_detach); + } + public function getSize() + { + return \call_user_func($this->_fn_getSize); + } + public function tell() + { + return \call_user_func($this->_fn_tell); + } + public function eof() + { + return \call_user_func($this->_fn_eof); + } + public function isSeekable() + { + return \call_user_func($this->_fn_isSeekable); + } + public function rewind() + { + \call_user_func($this->_fn_rewind); + } + public function seek($offset, $whence = \SEEK_SET) + { + \call_user_func($this->_fn_seek, $offset, $whence); + } + public function isWritable() + { + return \call_user_func($this->_fn_isWritable); + } + public function write($string) + { + return \call_user_func($this->_fn_write, $string); + } + public function isReadable() + { + return \call_user_func($this->_fn_isReadable); + } + public function read($length) + { + return \call_user_func($this->_fn_read, $length); + } + public function getContents() + { + return \call_user_func($this->_fn_getContents); + } + public function getMetadata($key = null) + { + return \call_user_func($this->_fn_getMetadata, $key); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/InflateStream.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/InflateStream.php new file mode 100644 index 00000000..d0fd482e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/InflateStream.php @@ -0,0 +1,48 @@ +read(10); + $filenameHeaderLength = $this->getLengthOfPossibleFilenameHeader($stream, $header); + // Skip the header, that is 10 + length of filename + 1 (nil) bytes + $stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\LimitStream($stream, -1, 10 + $filenameHeaderLength); + $resource = \YoastSEO_Vendor\GuzzleHttp\Psr7\StreamWrapper::getResource($stream); + \stream_filter_append($resource, 'zlib.inflate', \STREAM_FILTER_READ); + $this->stream = $stream->isSeekable() ? new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource) : new \YoastSEO_Vendor\GuzzleHttp\Psr7\NoSeekStream(new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource)); + } + /** + * @param StreamInterface $stream + * @param $header + * @return int + */ + private function getLengthOfPossibleFilenameHeader(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $header) + { + $filename_header_length = 0; + if (\substr(\bin2hex($header), 6, 2) === '08') { + // we have a filename, read until nil + $filename_header_length = 1; + while ($stream->read(1) !== \chr(0)) { + $filename_header_length++; + } + } + return $filename_header_length; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/LazyOpenStream.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/LazyOpenStream.php new file mode 100644 index 00000000..1318ee5d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/LazyOpenStream.php @@ -0,0 +1,35 @@ +filename = $filename; + $this->mode = $mode; + } + /** + * Creates the underlying stream lazily when required. + * + * @return StreamInterface + */ + protected function createStream() + { + return stream_for(try_fopen($this->filename, $this->mode)); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/LimitStream.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/LimitStream.php new file mode 100644 index 00000000..5af54c2d --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/LimitStream.php @@ -0,0 +1,128 @@ +stream = $stream; + $this->setLimit($limit); + $this->setOffset($offset); + } + public function eof() + { + // Always return true if the underlying stream is EOF + if ($this->stream->eof()) { + return \true; + } + // No limit and the underlying stream is not at EOF + if ($this->limit == -1) { + return \false; + } + return $this->stream->tell() >= $this->offset + $this->limit; + } + /** + * Returns the size of the limited subset of data + * {@inheritdoc} + */ + public function getSize() + { + if (null === ($length = $this->stream->getSize())) { + return null; + } elseif ($this->limit == -1) { + return $length - $this->offset; + } else { + return \min($this->limit, $length - $this->offset); + } + } + /** + * Allow for a bounded seek on the read limited stream + * {@inheritdoc} + */ + public function seek($offset, $whence = \SEEK_SET) + { + if ($whence !== \SEEK_SET || $offset < 0) { + throw new \RuntimeException(\sprintf('Cannot seek to offset % with whence %s', $offset, $whence)); + } + $offset += $this->offset; + if ($this->limit !== -1) { + if ($offset > $this->offset + $this->limit) { + $offset = $this->offset + $this->limit; + } + } + $this->stream->seek($offset); + } + /** + * Give a relative tell() + * {@inheritdoc} + */ + public function tell() + { + return $this->stream->tell() - $this->offset; + } + /** + * Set the offset to start limiting from + * + * @param int $offset Offset to seek to and begin byte limiting from + * + * @throws \RuntimeException if the stream cannot be seeked. + */ + public function setOffset($offset) + { + $current = $this->stream->tell(); + if ($current !== $offset) { + // If the stream cannot seek to the offset position, then read to it + if ($this->stream->isSeekable()) { + $this->stream->seek($offset); + } elseif ($current > $offset) { + throw new \RuntimeException("Could not seek to stream offset {$offset}"); + } else { + $this->stream->read($offset - $current); + } + } + $this->offset = $offset; + } + /** + * Set the limit of bytes that the decorator allows to be read from the + * stream. + * + * @param int $limit Number of bytes to allow to be read from the stream. + * Use -1 for no limit. + */ + public function setLimit($limit) + { + $this->limit = $limit; + } + public function read($length) + { + if ($this->limit == -1) { + return $this->stream->read($length); + } + // Check if the current position is less than the total allowed + // bytes + original offset + $remaining = $this->offset + $this->limit - $this->stream->tell(); + if ($remaining > 0) { + // Only return the amount of requested data, ensuring that the byte + // limit is not exceeded + return $this->stream->read(\min($remaining, $length)); + } + return ''; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/MessageTrait.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/MessageTrait.php new file mode 100644 index 00000000..1b334c65 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/MessageTrait.php @@ -0,0 +1,150 @@ + array of values */ + private $headers = []; + /** @var array Map of lowercase header name => original name at registration */ + private $headerNames = []; + /** @var string */ + private $protocol = '1.1'; + /** @var StreamInterface */ + private $stream; + public function getProtocolVersion() + { + return $this->protocol; + } + public function withProtocolVersion($version) + { + if ($this->protocol === $version) { + return $this; + } + $new = clone $this; + $new->protocol = $version; + return $new; + } + public function getHeaders() + { + return $this->headers; + } + public function hasHeader($header) + { + return isset($this->headerNames[\strtolower($header)]); + } + public function getHeader($header) + { + $header = \strtolower($header); + if (!isset($this->headerNames[$header])) { + return []; + } + $header = $this->headerNames[$header]; + return $this->headers[$header]; + } + public function getHeaderLine($header) + { + return \implode(', ', $this->getHeader($header)); + } + public function withHeader($header, $value) + { + if (!\is_array($value)) { + $value = [$value]; + } + $value = $this->trimHeaderValues($value); + $normalized = \strtolower($header); + $new = clone $this; + if (isset($new->headerNames[$normalized])) { + unset($new->headers[$new->headerNames[$normalized]]); + } + $new->headerNames[$normalized] = $header; + $new->headers[$header] = $value; + return $new; + } + public function withAddedHeader($header, $value) + { + if (!\is_array($value)) { + $value = [$value]; + } + $value = $this->trimHeaderValues($value); + $normalized = \strtolower($header); + $new = clone $this; + if (isset($new->headerNames[$normalized])) { + $header = $this->headerNames[$normalized]; + $new->headers[$header] = \array_merge($this->headers[$header], $value); + } else { + $new->headerNames[$normalized] = $header; + $new->headers[$header] = $value; + } + return $new; + } + public function withoutHeader($header) + { + $normalized = \strtolower($header); + if (!isset($this->headerNames[$normalized])) { + return $this; + } + $header = $this->headerNames[$normalized]; + $new = clone $this; + unset($new->headers[$header], $new->headerNames[$normalized]); + return $new; + } + public function getBody() + { + if (!$this->stream) { + $this->stream = stream_for(''); + } + return $this->stream; + } + public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body) + { + if ($body === $this->stream) { + return $this; + } + $new = clone $this; + $new->stream = $body; + return $new; + } + private function setHeaders(array $headers) + { + $this->headerNames = $this->headers = []; + foreach ($headers as $header => $value) { + if (!\is_array($value)) { + $value = [$value]; + } + $value = $this->trimHeaderValues($value); + $normalized = \strtolower($header); + if (isset($this->headerNames[$normalized])) { + $header = $this->headerNames[$normalized]; + $this->headers[$header] = \array_merge($this->headers[$header], $value); + } else { + $this->headerNames[$normalized] = $header; + $this->headers[$header] = $value; + } + } + } + /** + * Trims whitespace from the header values. + * + * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field. + * + * header-field = field-name ":" OWS field-value OWS + * OWS = *( SP / HTAB ) + * + * @param string[] $values Header values + * + * @return string[] Trimmed header values + * + * @see https://tools.ietf.org/html/rfc7230#section-3.2.4 + */ + private function trimHeaderValues(array $values) + { + return \array_map(function ($value) { + return \trim($value, " \t"); + }, $values); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/MultipartStream.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/MultipartStream.php new file mode 100644 index 00000000..9faf9c0e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/MultipartStream.php @@ -0,0 +1,123 @@ +boundary = $boundary ?: \sha1(\uniqid('', \true)); + $this->stream = $this->createStream($elements); + } + /** + * Get the boundary + * + * @return string + */ + public function getBoundary() + { + return $this->boundary; + } + public function isWritable() + { + return \false; + } + /** + * Get the headers needed before transferring the content of a POST file + */ + private function getHeaders(array $headers) + { + $str = ''; + foreach ($headers as $key => $value) { + $str .= "{$key}: {$value}\r\n"; + } + return "--{$this->boundary}\r\n" . \trim($str) . "\r\n\r\n"; + } + /** + * Create the aggregate stream that will be used to upload the POST data + */ + protected function createStream(array $elements) + { + $stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\AppendStream(); + foreach ($elements as $element) { + $this->addElement($stream, $element); + } + // Add the trailing boundary with CRLF + $stream->addStream(stream_for("--{$this->boundary}--\r\n")); + return $stream; + } + private function addElement(\YoastSEO_Vendor\GuzzleHttp\Psr7\AppendStream $stream, array $element) + { + foreach (['contents', 'name'] as $key) { + if (!\array_key_exists($key, $element)) { + throw new \InvalidArgumentException("A '{$key}' key is required"); + } + } + $element['contents'] = stream_for($element['contents']); + if (empty($element['filename'])) { + $uri = $element['contents']->getMetadata('uri'); + if (\substr($uri, 0, 6) !== 'php://') { + $element['filename'] = $uri; + } + } + list($body, $headers) = $this->createElement($element['name'], $element['contents'], isset($element['filename']) ? $element['filename'] : null, isset($element['headers']) ? $element['headers'] : []); + $stream->addStream(stream_for($this->getHeaders($headers))); + $stream->addStream($body); + $stream->addStream(stream_for("\r\n")); + } + /** + * @return array + */ + private function createElement($name, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $filename, array $headers) + { + // Set a default content-disposition header if one was no provided + $disposition = $this->getHeader($headers, 'content-disposition'); + if (!$disposition) { + $headers['Content-Disposition'] = $filename === '0' || $filename ? \sprintf('form-data; name="%s"; filename="%s"', $name, \basename($filename)) : "form-data; name=\"{$name}\""; + } + // Set a default content-length header if one was no provided + $length = $this->getHeader($headers, 'content-length'); + if (!$length) { + if ($length = $stream->getSize()) { + $headers['Content-Length'] = (string) $length; + } + } + // Set a default Content-Type if one was not supplied + $type = $this->getHeader($headers, 'content-type'); + if (!$type && ($filename === '0' || $filename)) { + if ($type = mimetype_from_filename($filename)) { + $headers['Content-Type'] = $type; + } + } + return [$stream, $headers]; + } + private function getHeader(array $headers, $key) + { + $lowercaseHeader = \strtolower($key); + foreach ($headers as $k => $v) { + if (\strtolower($k) === $lowercaseHeader) { + return $v; + } + } + return null; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/NoSeekStream.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/NoSeekStream.php new file mode 100644 index 00000000..b65e4963 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/NoSeekStream.php @@ -0,0 +1,20 @@ +source = $source; + $this->size = isset($options['size']) ? $options['size'] : null; + $this->metadata = isset($options['metadata']) ? $options['metadata'] : []; + $this->buffer = new \YoastSEO_Vendor\GuzzleHttp\Psr7\BufferStream(); + } + public function __toString() + { + try { + return copy_to_string($this); + } catch (\Exception $e) { + return ''; + } + } + public function close() + { + $this->detach(); + } + public function detach() + { + $this->tellPos = \false; + $this->source = null; + } + public function getSize() + { + return $this->size; + } + public function tell() + { + return $this->tellPos; + } + public function eof() + { + return !$this->source; + } + public function isSeekable() + { + return \false; + } + public function rewind() + { + $this->seek(0); + } + public function seek($offset, $whence = \SEEK_SET) + { + throw new \RuntimeException('Cannot seek a PumpStream'); + } + public function isWritable() + { + return \false; + } + public function write($string) + { + throw new \RuntimeException('Cannot write to a PumpStream'); + } + public function isReadable() + { + return \true; + } + public function read($length) + { + $data = $this->buffer->read($length); + $readLen = \strlen($data); + $this->tellPos += $readLen; + $remaining = $length - $readLen; + if ($remaining) { + $this->pump($remaining); + $data .= $this->buffer->read($remaining); + $this->tellPos += \strlen($data) - $readLen; + } + return $data; + } + public function getContents() + { + $result = ''; + while (!$this->eof()) { + $result .= $this->read(1000000); + } + return $result; + } + public function getMetadata($key = null) + { + if (!$key) { + return $this->metadata; + } + return isset($this->metadata[$key]) ? $this->metadata[$key] : null; + } + private function pump($length) + { + if ($this->source) { + do { + $data = \call_user_func($this->source, $length); + if ($data === \false || $data === null) { + $this->source = null; + return; + } + $this->buffer->write($data); + $length -= \strlen($data); + } while ($length > 0); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Request.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Request.php new file mode 100644 index 00000000..f339bcf9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Request.php @@ -0,0 +1,112 @@ +method = \strtoupper($method); + $this->uri = $uri; + $this->setHeaders($headers); + $this->protocol = $version; + if (!isset($this->headerNames['host'])) { + $this->updateHostFromUri(); + } + if ($body !== '' && $body !== null) { + $this->stream = stream_for($body); + } + } + public function getRequestTarget() + { + if ($this->requestTarget !== null) { + return $this->requestTarget; + } + $target = $this->uri->getPath(); + if ($target == '') { + $target = '/'; + } + if ($this->uri->getQuery() != '') { + $target .= '?' . $this->uri->getQuery(); + } + return $target; + } + public function withRequestTarget($requestTarget) + { + if (\preg_match('#\\s#', $requestTarget)) { + throw new \InvalidArgumentException('Invalid request target provided; cannot contain whitespace'); + } + $new = clone $this; + $new->requestTarget = $requestTarget; + return $new; + } + public function getMethod() + { + return $this->method; + } + public function withMethod($method) + { + $new = clone $this; + $new->method = \strtoupper($method); + return $new; + } + public function getUri() + { + return $this->uri; + } + public function withUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $preserveHost = \false) + { + if ($uri === $this->uri) { + return $this; + } + $new = clone $this; + $new->uri = $uri; + if (!$preserveHost || !isset($this->headerNames['host'])) { + $new->updateHostFromUri(); + } + return $new; + } + private function updateHostFromUri() + { + $host = $this->uri->getHost(); + if ($host == '') { + return; + } + if (($port = $this->uri->getPort()) !== null) { + $host .= ':' . $port; + } + if (isset($this->headerNames['host'])) { + $header = $this->headerNames['host']; + } else { + $header = 'Host'; + $this->headerNames['host'] = 'Host'; + } + // Ensure Host is the first header. + // See: http://tools.ietf.org/html/rfc7230#section-5.4 + $this->headers = [$header => [$host]] + $this->headers; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Response.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Response.php new file mode 100644 index 00000000..eb2f4ff2 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Response.php @@ -0,0 +1,61 @@ + 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-status', 208 => 'Already Reported', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 511 => 'Network Authentication Required']; + /** @var string */ + private $reasonPhrase = ''; + /** @var int */ + private $statusCode = 200; + /** + * @param int $status Status code + * @param array $headers Response headers + * @param string|null|resource|StreamInterface $body Response body + * @param string $version Protocol version + * @param string|null $reason Reason phrase (when empty a default will be used based on the status code) + */ + public function __construct($status = 200, array $headers = [], $body = null, $version = '1.1', $reason = null) + { + if (\filter_var($status, \FILTER_VALIDATE_INT) === \false) { + throw new \InvalidArgumentException('Status code must be an integer value.'); + } + $this->statusCode = (int) $status; + if ($body !== '' && $body !== null) { + $this->stream = stream_for($body); + } + $this->setHeaders($headers); + if ($reason == '' && isset(self::$phrases[$this->statusCode])) { + $this->reasonPhrase = self::$phrases[$this->statusCode]; + } else { + $this->reasonPhrase = (string) $reason; + } + $this->protocol = $version; + } + public function getStatusCode() + { + return $this->statusCode; + } + public function getReasonPhrase() + { + return $this->reasonPhrase; + } + public function withStatus($code, $reasonPhrase = '') + { + $new = clone $this; + $new->statusCode = (int) $code; + if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) { + $reasonPhrase = self::$phrases[$new->statusCode]; + } + $new->reasonPhrase = $reasonPhrase; + return $new; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Rfc7230.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Rfc7230.php new file mode 100644 index 00000000..1d04c255 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Rfc7230.php @@ -0,0 +1,18 @@ +@,;:\\\"/[\\]?={}\1- ]++):[ \t]*+((?:[ \t]*+[!-~€-ÿ]++)*+)[ \t]*+\r?\n)m"; + const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/ServerRequest.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/ServerRequest.php new file mode 100644 index 00000000..e885210a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/ServerRequest.php @@ -0,0 +1,302 @@ +serverParams = $serverParams; + parent::__construct($method, $uri, $headers, $body, $version); + } + /** + * Return an UploadedFile instance array. + * + * @param array $files A array which respect $_FILES structure + * @throws InvalidArgumentException for unrecognized values + * @return array + */ + public static function normalizeFiles(array $files) + { + $normalized = []; + foreach ($files as $key => $value) { + if ($value instanceof \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInterface) { + $normalized[$key] = $value; + } elseif (\is_array($value) && isset($value['tmp_name'])) { + $normalized[$key] = self::createUploadedFileFromSpec($value); + } elseif (\is_array($value)) { + $normalized[$key] = self::normalizeFiles($value); + continue; + } else { + throw new \InvalidArgumentException('Invalid value in files specification'); + } + } + return $normalized; + } + /** + * Create and return an UploadedFile instance from a $_FILES specification. + * + * If the specification represents an array of values, this method will + * delegate to normalizeNestedFileSpec() and return that return value. + * + * @param array $value $_FILES struct + * @return array|UploadedFileInterface + */ + private static function createUploadedFileFromSpec(array $value) + { + if (\is_array($value['tmp_name'])) { + return self::normalizeNestedFileSpec($value); + } + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile($value['tmp_name'], (int) $value['size'], (int) $value['error'], $value['name'], $value['type']); + } + /** + * Normalize an array of file specifications. + * + * Loops through all nested files and returns a normalized array of + * UploadedFileInterface instances. + * + * @param array $files + * @return UploadedFileInterface[] + */ + private static function normalizeNestedFileSpec(array $files = []) + { + $normalizedFiles = []; + foreach (\array_keys($files['tmp_name']) as $key) { + $spec = ['tmp_name' => $files['tmp_name'][$key], 'size' => $files['size'][$key], 'error' => $files['error'][$key], 'name' => $files['name'][$key], 'type' => $files['type'][$key]]; + $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec); + } + return $normalizedFiles; + } + /** + * Return a ServerRequest populated with superglobals: + * $_GET + * $_POST + * $_COOKIE + * $_FILES + * $_SERVER + * + * @return ServerRequestInterface + */ + public static function fromGlobals() + { + $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET'; + $headers = \getallheaders(); + $uri = self::getUriFromGlobals(); + $body = new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream('php://input', 'r+'); + $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? \str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1'; + $serverRequest = new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER); + return $serverRequest->withCookieParams($_COOKIE)->withQueryParams($_GET)->withParsedBody($_POST)->withUploadedFiles(self::normalizeFiles($_FILES)); + } + private static function extractHostAndPortFromAuthority($authority) + { + $uri = 'http://' . $authority; + $parts = \parse_url($uri); + if (\false === $parts) { + return [null, null]; + } + $host = isset($parts['host']) ? $parts['host'] : null; + $port = isset($parts['port']) ? $parts['port'] : null; + return [$host, $port]; + } + /** + * Get a Uri populated with values from $_SERVER. + * + * @return UriInterface + */ + public static function getUriFromGlobals() + { + $uri = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri(''); + $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); + $hasPort = \false; + if (isset($_SERVER['HTTP_HOST'])) { + list($host, $port) = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']); + if ($host !== null) { + $uri = $uri->withHost($host); + } + if ($port !== null) { + $hasPort = \true; + $uri = $uri->withPort($port); + } + } elseif (isset($_SERVER['SERVER_NAME'])) { + $uri = $uri->withHost($_SERVER['SERVER_NAME']); + } elseif (isset($_SERVER['SERVER_ADDR'])) { + $uri = $uri->withHost($_SERVER['SERVER_ADDR']); + } + if (!$hasPort && isset($_SERVER['SERVER_PORT'])) { + $uri = $uri->withPort($_SERVER['SERVER_PORT']); + } + $hasQuery = \false; + if (isset($_SERVER['REQUEST_URI'])) { + $requestUriParts = \explode('?', $_SERVER['REQUEST_URI'], 2); + $uri = $uri->withPath($requestUriParts[0]); + if (isset($requestUriParts[1])) { + $hasQuery = \true; + $uri = $uri->withQuery($requestUriParts[1]); + } + } + if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) { + $uri = $uri->withQuery($_SERVER['QUERY_STRING']); + } + return $uri; + } + /** + * {@inheritdoc} + */ + public function getServerParams() + { + return $this->serverParams; + } + /** + * {@inheritdoc} + */ + public function getUploadedFiles() + { + return $this->uploadedFiles; + } + /** + * {@inheritdoc} + */ + public function withUploadedFiles(array $uploadedFiles) + { + $new = clone $this; + $new->uploadedFiles = $uploadedFiles; + return $new; + } + /** + * {@inheritdoc} + */ + public function getCookieParams() + { + return $this->cookieParams; + } + /** + * {@inheritdoc} + */ + public function withCookieParams(array $cookies) + { + $new = clone $this; + $new->cookieParams = $cookies; + return $new; + } + /** + * {@inheritdoc} + */ + public function getQueryParams() + { + return $this->queryParams; + } + /** + * {@inheritdoc} + */ + public function withQueryParams(array $query) + { + $new = clone $this; + $new->queryParams = $query; + return $new; + } + /** + * {@inheritdoc} + */ + public function getParsedBody() + { + return $this->parsedBody; + } + /** + * {@inheritdoc} + */ + public function withParsedBody($data) + { + $new = clone $this; + $new->parsedBody = $data; + return $new; + } + /** + * {@inheritdoc} + */ + public function getAttributes() + { + return $this->attributes; + } + /** + * {@inheritdoc} + */ + public function getAttribute($attribute, $default = null) + { + if (\false === \array_key_exists($attribute, $this->attributes)) { + return $default; + } + return $this->attributes[$attribute]; + } + /** + * {@inheritdoc} + */ + public function withAttribute($attribute, $value) + { + $new = clone $this; + $new->attributes[$attribute] = $value; + return $new; + } + /** + * {@inheritdoc} + */ + public function withoutAttribute($attribute) + { + if (\false === \array_key_exists($attribute, $this->attributes)) { + return $this; + } + $new = clone $this; + unset($new->attributes[$attribute]); + return $new; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Stream.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Stream.php new file mode 100644 index 00000000..20173142 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Stream.php @@ -0,0 +1,212 @@ + ['r' => \true, 'w+' => \true, 'r+' => \true, 'x+' => \true, 'c+' => \true, 'rb' => \true, 'w+b' => \true, 'r+b' => \true, 'x+b' => \true, 'c+b' => \true, 'rt' => \true, 'w+t' => \true, 'r+t' => \true, 'x+t' => \true, 'c+t' => \true, 'a+' => \true, 'rb+' => \true], 'write' => ['w' => \true, 'w+' => \true, 'rw' => \true, 'r+' => \true, 'x+' => \true, 'c+' => \true, 'wb' => \true, 'w+b' => \true, 'r+b' => \true, 'rb+' => \true, 'x+b' => \true, 'c+b' => \true, 'w+t' => \true, 'r+t' => \true, 'x+t' => \true, 'c+t' => \true, 'a' => \true, 'a+' => \true]]; + /** + * This constructor accepts an associative array of options. + * + * - size: (int) If a read stream would otherwise have an indeterminate + * size, but the size is known due to foreknowledge, then you can + * provide that size, in bytes. + * - metadata: (array) Any additional metadata to return when the metadata + * of the stream is accessed. + * + * @param resource $stream Stream resource to wrap. + * @param array $options Associative array of options. + * + * @throws \InvalidArgumentException if the stream is not a stream resource + */ + public function __construct($stream, $options = []) + { + if (!\is_resource($stream)) { + throw new \InvalidArgumentException('Stream must be a resource'); + } + if (isset($options['size'])) { + $this->size = $options['size']; + } + $this->customMetadata = isset($options['metadata']) ? $options['metadata'] : []; + $this->stream = $stream; + $meta = \stream_get_meta_data($this->stream); + $this->seekable = $meta['seekable']; + $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]); + $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]); + $this->uri = $this->getMetadata('uri'); + } + /** + * Closes the stream when the destructed + */ + public function __destruct() + { + $this->close(); + } + public function __toString() + { + try { + $this->seek(0); + return (string) \stream_get_contents($this->stream); + } catch (\Exception $e) { + return ''; + } + } + public function getContents() + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + $contents = \stream_get_contents($this->stream); + if ($contents === \false) { + throw new \RuntimeException('Unable to read stream contents'); + } + return $contents; + } + public function close() + { + if (isset($this->stream)) { + if (\is_resource($this->stream)) { + \fclose($this->stream); + } + $this->detach(); + } + } + public function detach() + { + if (!isset($this->stream)) { + return null; + } + $result = $this->stream; + unset($this->stream); + $this->size = $this->uri = null; + $this->readable = $this->writable = $this->seekable = \false; + return $result; + } + public function getSize() + { + if ($this->size !== null) { + return $this->size; + } + if (!isset($this->stream)) { + return null; + } + // Clear the stat cache if the stream has a URI + if ($this->uri) { + \clearstatcache(\true, $this->uri); + } + $stats = \fstat($this->stream); + if (isset($stats['size'])) { + $this->size = $stats['size']; + return $this->size; + } + return null; + } + public function isReadable() + { + return $this->readable; + } + public function isWritable() + { + return $this->writable; + } + public function isSeekable() + { + return $this->seekable; + } + public function eof() + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + return \feof($this->stream); + } + public function tell() + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + $result = \ftell($this->stream); + if ($result === \false) { + throw new \RuntimeException('Unable to determine stream position'); + } + return $result; + } + public function rewind() + { + $this->seek(0); + } + public function seek($offset, $whence = \SEEK_SET) + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + if (!$this->seekable) { + throw new \RuntimeException('Stream is not seekable'); + } + if (\fseek($this->stream, $offset, $whence) === -1) { + throw new \RuntimeException('Unable to seek to stream position ' . $offset . ' with whence ' . \var_export($whence, \true)); + } + } + public function read($length) + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + if (!$this->readable) { + throw new \RuntimeException('Cannot read from non-readable stream'); + } + if ($length < 0) { + throw new \RuntimeException('Length parameter cannot be negative'); + } + if (0 === $length) { + return ''; + } + $string = \fread($this->stream, $length); + if (\false === $string) { + throw new \RuntimeException('Unable to read from stream'); + } + return $string; + } + public function write($string) + { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + if (!$this->writable) { + throw new \RuntimeException('Cannot write to a non-writable stream'); + } + // We can't know the size after writing anything + $this->size = null; + $result = \fwrite($this->stream, $string); + if ($result === \false) { + throw new \RuntimeException('Unable to write to stream'); + } + return $result; + } + public function getMetadata($key = null) + { + if (!isset($this->stream)) { + return $key ? null : []; + } elseif (!$key) { + return $this->customMetadata + \stream_get_meta_data($this->stream); + } elseif (isset($this->customMetadata[$key])) { + return $this->customMetadata[$key]; + } + $meta = \stream_get_meta_data($this->stream); + return isset($meta[$key]) ? $meta[$key] : null; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/StreamDecoratorTrait.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/StreamDecoratorTrait.php new file mode 100644 index 00000000..10acf3bc --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/StreamDecoratorTrait.php @@ -0,0 +1,128 @@ +stream = $stream; + } + /** + * Magic method used to create a new stream if streams are not added in + * the constructor of a decorator (e.g., LazyOpenStream). + * + * @param string $name Name of the property (allows "stream" only). + * + * @return StreamInterface + */ + public function __get($name) + { + if ($name == 'stream') { + $this->stream = $this->createStream(); + return $this->stream; + } + throw new \UnexpectedValueException("{$name} not found on class"); + } + public function __toString() + { + try { + if ($this->isSeekable()) { + $this->seek(0); + } + return $this->getContents(); + } catch (\Exception $e) { + // Really, PHP? https://bugs.php.net/bug.php?id=53648 + \trigger_error('StreamDecorator::__toString exception: ' . (string) $e, \E_USER_ERROR); + return ''; + } + } + public function getContents() + { + return copy_to_string($this); + } + /** + * Allow decorators to implement custom methods + * + * @param string $method Missing method name + * @param array $args Method arguments + * + * @return mixed + */ + public function __call($method, array $args) + { + $result = \call_user_func_array([$this->stream, $method], $args); + // Always return the wrapped object if the result is a return $this + return $result === $this->stream ? $this : $result; + } + public function close() + { + $this->stream->close(); + } + public function getMetadata($key = null) + { + return $this->stream->getMetadata($key); + } + public function detach() + { + return $this->stream->detach(); + } + public function getSize() + { + return $this->stream->getSize(); + } + public function eof() + { + return $this->stream->eof(); + } + public function tell() + { + return $this->stream->tell(); + } + public function isReadable() + { + return $this->stream->isReadable(); + } + public function isWritable() + { + return $this->stream->isWritable(); + } + public function isSeekable() + { + return $this->stream->isSeekable(); + } + public function rewind() + { + $this->seek(0); + } + public function seek($offset, $whence = \SEEK_SET) + { + $this->stream->seek($offset, $whence); + } + public function read($length) + { + return $this->stream->read($length); + } + public function write($string) + { + return $this->stream->write($string); + } + /** + * Implement in subclasses to dynamically create streams when requested. + * + * @return StreamInterface + * @throws \BadMethodCallException + */ + protected function createStream() + { + throw new \BadMethodCallException('Not implemented'); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/StreamWrapper.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/StreamWrapper.php new file mode 100644 index 00000000..f4109d50 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/StreamWrapper.php @@ -0,0 +1,102 @@ +isReadable()) { + $mode = $stream->isWritable() ? 'r+' : 'r'; + } elseif ($stream->isWritable()) { + $mode = 'w'; + } else { + throw new \InvalidArgumentException('The stream must be readable, ' . 'writable, or both.'); + } + return \fopen('guzzle://stream', $mode, null, self::createStreamContext($stream)); + } + /** + * Creates a stream context that can be used to open a stream as a php stream resource. + * + * @param StreamInterface $stream + * + * @return resource + */ + public static function createStreamContext(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream) + { + return \stream_context_create(['guzzle' => ['stream' => $stream]]); + } + /** + * Registers the stream wrapper if needed + */ + public static function register() + { + if (!\in_array('guzzle', \stream_get_wrappers())) { + \stream_wrapper_register('guzzle', __CLASS__); + } + } + public function stream_open($path, $mode, $options, &$opened_path) + { + $options = \stream_context_get_options($this->context); + if (!isset($options['guzzle']['stream'])) { + return \false; + } + $this->mode = $mode; + $this->stream = $options['guzzle']['stream']; + return \true; + } + public function stream_read($count) + { + return $this->stream->read($count); + } + public function stream_write($data) + { + return (int) $this->stream->write($data); + } + public function stream_tell() + { + return $this->stream->tell(); + } + public function stream_eof() + { + return $this->stream->eof(); + } + public function stream_seek($offset, $whence) + { + $this->stream->seek($offset, $whence); + return \true; + } + public function stream_cast($cast_as) + { + $stream = clone $this->stream; + return $stream->detach(); + } + public function stream_stat() + { + static $modeMap = ['r' => 33060, 'rb' => 33060, 'r+' => 33206, 'w' => 33188, 'wb' => 33188]; + return ['dev' => 0, 'ino' => 0, 'mode' => $modeMap[$this->mode], 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => $this->stream->getSize() ?: 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0]; + } + public function url_stat($path, $flags) + { + return ['dev' => 0, 'ino' => 0, 'mode' => 0, 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0]; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/UploadedFile.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/UploadedFile.php new file mode 100644 index 00000000..33be72ab --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/UploadedFile.php @@ -0,0 +1,244 @@ +setError($errorStatus); + $this->setSize($size); + $this->setClientFilename($clientFilename); + $this->setClientMediaType($clientMediaType); + if ($this->isOk()) { + $this->setStreamOrFile($streamOrFile); + } + } + /** + * Depending on the value set file or stream variable + * + * @param mixed $streamOrFile + * @throws InvalidArgumentException + */ + private function setStreamOrFile($streamOrFile) + { + if (\is_string($streamOrFile)) { + $this->file = $streamOrFile; + } elseif (\is_resource($streamOrFile)) { + $this->stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($streamOrFile); + } elseif ($streamOrFile instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) { + $this->stream = $streamOrFile; + } else { + throw new \InvalidArgumentException('Invalid stream or file provided for UploadedFile'); + } + } + /** + * @param int $error + * @throws InvalidArgumentException + */ + private function setError($error) + { + if (\false === \is_int($error)) { + throw new \InvalidArgumentException('Upload file error status must be an integer'); + } + if (\false === \in_array($error, \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile::$errors)) { + throw new \InvalidArgumentException('Invalid error status for UploadedFile'); + } + $this->error = $error; + } + /** + * @param int $size + * @throws InvalidArgumentException + */ + private function setSize($size) + { + if (\false === \is_int($size)) { + throw new \InvalidArgumentException('Upload file size must be an integer'); + } + $this->size = $size; + } + /** + * @param mixed $param + * @return boolean + */ + private function isStringOrNull($param) + { + return \in_array(\gettype($param), ['string', 'NULL']); + } + /** + * @param mixed $param + * @return boolean + */ + private function isStringNotEmpty($param) + { + return \is_string($param) && \false === empty($param); + } + /** + * @param string|null $clientFilename + * @throws InvalidArgumentException + */ + private function setClientFilename($clientFilename) + { + if (\false === $this->isStringOrNull($clientFilename)) { + throw new \InvalidArgumentException('Upload file client filename must be a string or null'); + } + $this->clientFilename = $clientFilename; + } + /** + * @param string|null $clientMediaType + * @throws InvalidArgumentException + */ + private function setClientMediaType($clientMediaType) + { + if (\false === $this->isStringOrNull($clientMediaType)) { + throw new \InvalidArgumentException('Upload file client media type must be a string or null'); + } + $this->clientMediaType = $clientMediaType; + } + /** + * Return true if there is no upload error + * + * @return boolean + */ + private function isOk() + { + return $this->error === \UPLOAD_ERR_OK; + } + /** + * @return boolean + */ + public function isMoved() + { + return $this->moved; + } + /** + * @throws RuntimeException if is moved or not ok + */ + private function validateActive() + { + if (\false === $this->isOk()) { + throw new \RuntimeException('Cannot retrieve stream due to upload error'); + } + if ($this->isMoved()) { + throw new \RuntimeException('Cannot retrieve stream after it has already been moved'); + } + } + /** + * {@inheritdoc} + * @throws RuntimeException if the upload was not successful. + */ + public function getStream() + { + $this->validateActive(); + if ($this->stream instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) { + return $this->stream; + } + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($this->file, 'r+'); + } + /** + * {@inheritdoc} + * + * @see http://php.net/is_uploaded_file + * @see http://php.net/move_uploaded_file + * @param string $targetPath Path to which to move the uploaded file. + * @throws RuntimeException if the upload was not successful. + * @throws InvalidArgumentException if the $path specified is invalid. + * @throws RuntimeException on any error during the move operation, or on + * the second or subsequent call to the method. + */ + public function moveTo($targetPath) + { + $this->validateActive(); + if (\false === $this->isStringNotEmpty($targetPath)) { + throw new \InvalidArgumentException('Invalid path provided for move operation; must be a non-empty string'); + } + if ($this->file) { + $this->moved = \php_sapi_name() == 'cli' ? \rename($this->file, $targetPath) : \move_uploaded_file($this->file, $targetPath); + } else { + copy_to_stream($this->getStream(), new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($targetPath, 'w')); + $this->moved = \true; + } + if (\false === $this->moved) { + throw new \RuntimeException(\sprintf('Uploaded file could not be moved to %s', $targetPath)); + } + } + /** + * {@inheritdoc} + * + * @return int|null The file size in bytes or null if unknown. + */ + public function getSize() + { + return $this->size; + } + /** + * {@inheritdoc} + * + * @see http://php.net/manual/en/features.file-upload.errors.php + * @return int One of PHP's UPLOAD_ERR_XXX constants. + */ + public function getError() + { + return $this->error; + } + /** + * {@inheritdoc} + * + * @return string|null The filename sent by the client or null if none + * was provided. + */ + public function getClientFilename() + { + return $this->clientFilename; + } + /** + * {@inheritdoc} + */ + public function getClientMediaType() + { + return $this->clientMediaType; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Uri.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Uri.php new file mode 100644 index 00000000..6d88872e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/Uri.php @@ -0,0 +1,584 @@ + 80, 'https' => 443, 'ftp' => 21, 'gopher' => 70, 'nntp' => 119, 'news' => 119, 'telnet' => 23, 'tn3270' => 23, 'imap' => 143, 'pop' => 110, 'ldap' => 389]; + private static $charUnreserved = 'a-zA-Z0-9_\\-\\.~'; + private static $charSubDelims = '!\\$&\'\\(\\)\\*\\+,;='; + private static $replaceQuery = ['=' => '%3D', '&' => '%26']; + /** @var string Uri scheme. */ + private $scheme = ''; + /** @var string Uri user info. */ + private $userInfo = ''; + /** @var string Uri host. */ + private $host = ''; + /** @var int|null Uri port. */ + private $port; + /** @var string Uri path. */ + private $path = ''; + /** @var string Uri query string. */ + private $query = ''; + /** @var string Uri fragment. */ + private $fragment = ''; + /** + * @param string $uri URI to parse + */ + public function __construct($uri = '') + { + // weak type check to also accept null until we can add scalar type hints + if ($uri != '') { + $parts = \parse_url($uri); + if ($parts === \false) { + throw new \InvalidArgumentException("Unable to parse URI: {$uri}"); + } + $this->applyParts($parts); + } + } + public function __toString() + { + return self::composeComponents($this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment); + } + /** + * Composes a URI reference string from its various components. + * + * Usually this method does not need to be called manually but instead is used indirectly via + * `Psr\Http\Message\UriInterface::__toString`. + * + * PSR-7 UriInterface treats an empty component the same as a missing component as + * getQuery(), getFragment() etc. always return a string. This explains the slight + * difference to RFC 3986 Section 5.3. + * + * Another adjustment is that the authority separator is added even when the authority is missing/empty + * for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with + * `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But + * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to + * that format). + * + * @param string $scheme + * @param string $authority + * @param string $path + * @param string $query + * @param string $fragment + * + * @return string + * + * @link https://tools.ietf.org/html/rfc3986#section-5.3 + */ + public static function composeComponents($scheme, $authority, $path, $query, $fragment) + { + $uri = ''; + // weak type checks to also accept null until we can add scalar type hints + if ($scheme != '') { + $uri .= $scheme . ':'; + } + if ($authority != '' || $scheme === 'file') { + $uri .= '//' . $authority; + } + $uri .= $path; + if ($query != '') { + $uri .= '?' . $query; + } + if ($fragment != '') { + $uri .= '#' . $fragment; + } + return $uri; + } + /** + * Whether the URI has the default port of the current scheme. + * + * `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used + * independently of the implementation. + * + * @param UriInterface $uri + * + * @return bool + */ + public static function isDefaultPort(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) + { + return $uri->getPort() === null || isset(self::$defaultPorts[$uri->getScheme()]) && $uri->getPort() === self::$defaultPorts[$uri->getScheme()]; + } + /** + * Whether the URI is absolute, i.e. it has a scheme. + * + * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true + * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative + * to another URI, the base URI. Relative references can be divided into several forms: + * - network-path references, e.g. '//example.com/path' + * - absolute-path references, e.g. '/path' + * - relative-path references, e.g. 'subpath' + * + * @param UriInterface $uri + * + * @return bool + * @see Uri::isNetworkPathReference + * @see Uri::isAbsolutePathReference + * @see Uri::isRelativePathReference + * @link https://tools.ietf.org/html/rfc3986#section-4 + */ + public static function isAbsolute(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) + { + return $uri->getScheme() !== ''; + } + /** + * Whether the URI is a network-path reference. + * + * A relative reference that begins with two slash characters is termed an network-path reference. + * + * @param UriInterface $uri + * + * @return bool + * @link https://tools.ietf.org/html/rfc3986#section-4.2 + */ + public static function isNetworkPathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) + { + return $uri->getScheme() === '' && $uri->getAuthority() !== ''; + } + /** + * Whether the URI is a absolute-path reference. + * + * A relative reference that begins with a single slash character is termed an absolute-path reference. + * + * @param UriInterface $uri + * + * @return bool + * @link https://tools.ietf.org/html/rfc3986#section-4.2 + */ + public static function isAbsolutePathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) + { + return $uri->getScheme() === '' && $uri->getAuthority() === '' && isset($uri->getPath()[0]) && $uri->getPath()[0] === '/'; + } + /** + * Whether the URI is a relative-path reference. + * + * A relative reference that does not begin with a slash character is termed a relative-path reference. + * + * @param UriInterface $uri + * + * @return bool + * @link https://tools.ietf.org/html/rfc3986#section-4.2 + */ + public static function isRelativePathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) + { + return $uri->getScheme() === '' && $uri->getAuthority() === '' && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/'); + } + /** + * Whether the URI is a same-document reference. + * + * A same-document reference refers to a URI that is, aside from its fragment + * component, identical to the base URI. When no base URI is given, only an empty + * URI reference (apart from its fragment) is considered a same-document reference. + * + * @param UriInterface $uri The URI to check + * @param UriInterface|null $base An optional base URI to compare against + * + * @return bool + * @link https://tools.ietf.org/html/rfc3986#section-4.4 + */ + public static function isSameDocumentReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $base = null) + { + if ($base !== null) { + $uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve($base, $uri); + return $uri->getScheme() === $base->getScheme() && $uri->getAuthority() === $base->getAuthority() && $uri->getPath() === $base->getPath() && $uri->getQuery() === $base->getQuery(); + } + return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === ''; + } + /** + * Removes dot segments from a path and returns the new path. + * + * @param string $path + * + * @return string + * + * @deprecated since version 1.4. Use UriResolver::removeDotSegments instead. + * @see UriResolver::removeDotSegments + */ + public static function removeDotSegments($path) + { + return \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::removeDotSegments($path); + } + /** + * Converts the relative URI into a new URI that is resolved against the base URI. + * + * @param UriInterface $base Base URI + * @param string|UriInterface $rel Relative URI + * + * @return UriInterface + * + * @deprecated since version 1.4. Use UriResolver::resolve instead. + * @see UriResolver::resolve + */ + public static function resolve(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, $rel) + { + if (!$rel instanceof \YoastSEO_Vendor\Psr\Http\Message\UriInterface) { + $rel = new self($rel); + } + return \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve($base, $rel); + } + /** + * Creates a new URI with a specific query string value removed. + * + * Any existing query string values that exactly match the provided key are + * removed. + * + * @param UriInterface $uri URI to use as a base. + * @param string $key Query string key to remove. + * + * @return UriInterface + */ + public static function withoutQueryValue(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $key) + { + $result = self::getFilteredQueryString($uri, [$key]); + return $uri->withQuery(\implode('&', $result)); + } + /** + * Creates a new URI with a specific query string value. + * + * Any existing query string values that exactly match the provided key are + * removed and replaced with the given key value pair. + * + * A value of null will set the query string key without a value, e.g. "key" + * instead of "key=value". + * + * @param UriInterface $uri URI to use as a base. + * @param string $key Key to set. + * @param string|null $value Value to set + * + * @return UriInterface + */ + public static function withQueryValue(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $key, $value) + { + $result = self::getFilteredQueryString($uri, [$key]); + $result[] = self::generateQueryString($key, $value); + return $uri->withQuery(\implode('&', $result)); + } + /** + * Creates a new URI with multiple specific query string values. + * + * It has the same behavior as withQueryValue() but for an associative array of key => value. + * + * @param UriInterface $uri URI to use as a base. + * @param array $keyValueArray Associative array of key and values + * + * @return UriInterface + */ + public static function withQueryValues(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $keyValueArray) + { + $result = self::getFilteredQueryString($uri, \array_keys($keyValueArray)); + foreach ($keyValueArray as $key => $value) { + $result[] = self::generateQueryString($key, $value); + } + return $uri->withQuery(\implode('&', $result)); + } + /** + * Creates a URI from a hash of `parse_url` components. + * + * @param array $parts + * + * @return UriInterface + * @link http://php.net/manual/en/function.parse-url.php + * + * @throws \InvalidArgumentException If the components do not form a valid URI. + */ + public static function fromParts(array $parts) + { + $uri = new self(); + $uri->applyParts($parts); + $uri->validateState(); + return $uri; + } + public function getScheme() + { + return $this->scheme; + } + public function getAuthority() + { + $authority = $this->host; + if ($this->userInfo !== '') { + $authority = $this->userInfo . '@' . $authority; + } + if ($this->port !== null) { + $authority .= ':' . $this->port; + } + return $authority; + } + public function getUserInfo() + { + return $this->userInfo; + } + public function getHost() + { + return $this->host; + } + public function getPort() + { + return $this->port; + } + public function getPath() + { + return $this->path; + } + public function getQuery() + { + return $this->query; + } + public function getFragment() + { + return $this->fragment; + } + public function withScheme($scheme) + { + $scheme = $this->filterScheme($scheme); + if ($this->scheme === $scheme) { + return $this; + } + $new = clone $this; + $new->scheme = $scheme; + $new->removeDefaultPort(); + $new->validateState(); + return $new; + } + public function withUserInfo($user, $password = null) + { + $info = $user; + if ($password != '') { + $info .= ':' . $password; + } + if ($this->userInfo === $info) { + return $this; + } + $new = clone $this; + $new->userInfo = $info; + $new->validateState(); + return $new; + } + public function withHost($host) + { + $host = $this->filterHost($host); + if ($this->host === $host) { + return $this; + } + $new = clone $this; + $new->host = $host; + $new->validateState(); + return $new; + } + public function withPort($port) + { + $port = $this->filterPort($port); + if ($this->port === $port) { + return $this; + } + $new = clone $this; + $new->port = $port; + $new->removeDefaultPort(); + $new->validateState(); + return $new; + } + public function withPath($path) + { + $path = $this->filterPath($path); + if ($this->path === $path) { + return $this; + } + $new = clone $this; + $new->path = $path; + $new->validateState(); + return $new; + } + public function withQuery($query) + { + $query = $this->filterQueryAndFragment($query); + if ($this->query === $query) { + return $this; + } + $new = clone $this; + $new->query = $query; + return $new; + } + public function withFragment($fragment) + { + $fragment = $this->filterQueryAndFragment($fragment); + if ($this->fragment === $fragment) { + return $this; + } + $new = clone $this; + $new->fragment = $fragment; + return $new; + } + /** + * Apply parse_url parts to a URI. + * + * @param array $parts Array of parse_url parts to apply. + */ + private function applyParts(array $parts) + { + $this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : ''; + $this->userInfo = isset($parts['user']) ? $parts['user'] : ''; + $this->host = isset($parts['host']) ? $this->filterHost($parts['host']) : ''; + $this->port = isset($parts['port']) ? $this->filterPort($parts['port']) : null; + $this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : ''; + $this->query = isset($parts['query']) ? $this->filterQueryAndFragment($parts['query']) : ''; + $this->fragment = isset($parts['fragment']) ? $this->filterQueryAndFragment($parts['fragment']) : ''; + if (isset($parts['pass'])) { + $this->userInfo .= ':' . $parts['pass']; + } + $this->removeDefaultPort(); + } + /** + * @param string $scheme + * + * @return string + * + * @throws \InvalidArgumentException If the scheme is invalid. + */ + private function filterScheme($scheme) + { + if (!\is_string($scheme)) { + throw new \InvalidArgumentException('Scheme must be a string'); + } + return \strtolower($scheme); + } + /** + * @param string $host + * + * @return string + * + * @throws \InvalidArgumentException If the host is invalid. + */ + private function filterHost($host) + { + if (!\is_string($host)) { + throw new \InvalidArgumentException('Host must be a string'); + } + return \strtolower($host); + } + /** + * @param int|null $port + * + * @return int|null + * + * @throws \InvalidArgumentException If the port is invalid. + */ + private function filterPort($port) + { + if ($port === null) { + return null; + } + $port = (int) $port; + if (1 > $port || 0xffff < $port) { + throw new \InvalidArgumentException(\sprintf('Invalid port: %d. Must be between 1 and 65535', $port)); + } + return $port; + } + /** + * @param UriInterface $uri + * @param array $keys + * + * @return array + */ + private static function getFilteredQueryString(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $keys) + { + $current = $uri->getQuery(); + if ($current === '') { + return []; + } + $decodedKeys = \array_map('rawurldecode', $keys); + return \array_filter(\explode('&', $current), function ($part) use($decodedKeys) { + return !\in_array(\rawurldecode(\explode('=', $part)[0]), $decodedKeys, \true); + }); + } + /** + * @param string $key + * @param string|null $value + * + * @return string + */ + private static function generateQueryString($key, $value) + { + // Query string separators ("=", "&") within the key or value need to be encoded + // (while preventing double-encoding) before setting the query string. All other + // chars that need percent-encoding will be encoded by withQuery(). + $queryString = \strtr($key, self::$replaceQuery); + if ($value !== null) { + $queryString .= '=' . \strtr($value, self::$replaceQuery); + } + return $queryString; + } + private function removeDefaultPort() + { + if ($this->port !== null && self::isDefaultPort($this)) { + $this->port = null; + } + } + /** + * Filters the path of a URI + * + * @param string $path + * + * @return string + * + * @throws \InvalidArgumentException If the path is invalid. + */ + private function filterPath($path) + { + if (!\is_string($path)) { + throw new \InvalidArgumentException('Path must be a string'); + } + return \preg_replace_callback('/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\\/]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $path); + } + /** + * Filters the query string or fragment of a URI. + * + * @param string $str + * + * @return string + * + * @throws \InvalidArgumentException If the query or fragment is invalid. + */ + private function filterQueryAndFragment($str) + { + if (!\is_string($str)) { + throw new \InvalidArgumentException('Query and fragment must be a string'); + } + return \preg_replace_callback('/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\\/\\?]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $str); + } + private function rawurlencodeMatchZero(array $match) + { + return \rawurlencode($match[0]); + } + private function validateState() + { + if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) { + $this->host = self::HTTP_DEFAULT_HOST; + } + if ($this->getAuthority() === '') { + if (0 === \strpos($this->path, '//')) { + throw new \InvalidArgumentException('The path of a URI without an authority must not start with two slashes "//"'); + } + if ($this->scheme === '' && \false !== \strpos(\explode('/', $this->path, 2)[0], ':')) { + throw new \InvalidArgumentException('A relative URI must not have a path beginning with a segment containing a colon'); + } + } elseif (isset($this->path[0]) && $this->path[0] !== '/') { + @\trigger_error('The path of a URI with an authority must start with a slash "/" or be empty. Automagically fixing the URI ' . 'by adding a leading slash to the path is deprecated since version 1.4 and will throw an exception instead.', \E_USER_DEPRECATED); + $this->path = '/' . $this->path; + //throw new \InvalidArgumentException('The path of a URI with an authority must start with a slash "/" or be empty'); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/UriNormalizer.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/UriNormalizer.php new file mode 100644 index 00000000..a2ce7317 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/UriNormalizer.php @@ -0,0 +1,179 @@ +getPath() === '' && ($uri->getScheme() === 'http' || $uri->getScheme() === 'https')) { + $uri = $uri->withPath('/'); + } + if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') { + $uri = $uri->withHost(''); + } + if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::isDefaultPort($uri)) { + $uri = $uri->withPort(null); + } + if ($flags & self::REMOVE_DOT_SEGMENTS && !\YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::isRelativePathReference($uri)) { + $uri = $uri->withPath(\YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::removeDotSegments($uri->getPath())); + } + if ($flags & self::REMOVE_DUPLICATE_SLASHES) { + $uri = $uri->withPath(\preg_replace('#//++#', '/', $uri->getPath())); + } + if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') { + $queryKeyValues = \explode('&', $uri->getQuery()); + \sort($queryKeyValues); + $uri = $uri->withQuery(\implode('&', $queryKeyValues)); + } + return $uri; + } + /** + * Whether two URIs can be considered equivalent. + * + * Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also + * accepts relative URI references and returns true when they are equivalent. This of course assumes they will be + * resolved against the same base URI. If this is not the case, determination of equivalence or difference of + * relative references does not mean anything. + * + * @param UriInterface $uri1 An URI to compare + * @param UriInterface $uri2 An URI to compare + * @param int $normalizations A bitmask of normalizations to apply, see constants + * + * @return bool + * @link https://tools.ietf.org/html/rfc3986#section-6.1 + */ + public static function isEquivalent(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri1, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS) + { + return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations); + } + private static function capitalizePercentEncoding(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) + { + $regex = '/(?:%[A-Fa-f0-9]{2})++/'; + $callback = function (array $match) { + return \strtoupper($match[0]); + }; + return $uri->withPath(\preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(\preg_replace_callback($regex, $callback, $uri->getQuery())); + } + private static function decodeUnreservedCharacters(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) + { + $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i'; + $callback = function (array $match) { + return \rawurldecode($match[0]); + }; + return $uri->withPath(\preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(\preg_replace_callback($regex, $callback, $uri->getQuery())); + } + private function __construct() + { + // cannot be instantiated + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/UriResolver.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/UriResolver.php new file mode 100644 index 00000000..129a0061 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/UriResolver.php @@ -0,0 +1,190 @@ +getScheme() != '') { + return $rel->withPath(self::removeDotSegments($rel->getPath())); + } + if ($rel->getAuthority() != '') { + $targetAuthority = $rel->getAuthority(); + $targetPath = self::removeDotSegments($rel->getPath()); + $targetQuery = $rel->getQuery(); + } else { + $targetAuthority = $base->getAuthority(); + if ($rel->getPath() === '') { + $targetPath = $base->getPath(); + $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery(); + } else { + if ($rel->getPath()[0] === '/') { + $targetPath = $rel->getPath(); + } else { + if ($targetAuthority != '' && $base->getPath() === '') { + $targetPath = '/' . $rel->getPath(); + } else { + $lastSlashPos = \strrpos($base->getPath(), '/'); + if ($lastSlashPos === \false) { + $targetPath = $rel->getPath(); + } else { + $targetPath = \substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath(); + } + } + } + $targetPath = self::removeDotSegments($targetPath); + $targetQuery = $rel->getQuery(); + } + } + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri(\YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::composeComponents($base->getScheme(), $targetAuthority, $targetPath, $targetQuery, $rel->getFragment())); + } + /** + * Returns the target URI as a relative reference from the base URI. + * + * This method is the counterpart to resolve(): + * + * (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target)) + * + * One use-case is to use the current request URI as base URI and then generate relative links in your documents + * to reduce the document size or offer self-contained downloadable document archives. + * + * $base = new Uri('http://example.com/a/b/'); + * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'. + * echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'. + * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'. + * echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'. + * + * This method also accepts a target that is already relative and will try to relativize it further. Only a + * relative-path reference will be returned as-is. + * + * echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well + * + * @param UriInterface $base Base URI + * @param UriInterface $target Target URI + * + * @return UriInterface The relative URI reference + */ + public static function relativize(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $target) + { + if ($target->getScheme() !== '' && ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')) { + return $target; + } + if (\YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::isRelativePathReference($target)) { + // As the target is already highly relative we return it as-is. It would be possible to resolve + // the target with `$target = self::resolve($base, $target);` and then try make it more relative + // by removing a duplicate query. But let's not do that automatically. + return $target; + } + if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) { + return $target->withScheme(''); + } + // We must remove the path before removing the authority because if the path starts with two slashes, the URI + // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also + // invalid. + $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost(''); + if ($base->getPath() !== $target->getPath()) { + return $emptyPathUri->withPath(self::getRelativePath($base, $target)); + } + if ($base->getQuery() === $target->getQuery()) { + // Only the target fragment is left. And it must be returned even if base and target fragment are the same. + return $emptyPathUri->withQuery(''); + } + // If the base URI has a query but the target has none, we cannot return an empty path reference as it would + // inherit the base query component when resolving. + if ($target->getQuery() === '') { + $segments = \explode('/', $target->getPath()); + $lastSegment = \end($segments); + return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment); + } + return $emptyPathUri; + } + private static function getRelativePath(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $target) + { + $sourceSegments = \explode('/', $base->getPath()); + $targetSegments = \explode('/', $target->getPath()); + \array_pop($sourceSegments); + $targetLastSegment = \array_pop($targetSegments); + foreach ($sourceSegments as $i => $segment) { + if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) { + unset($sourceSegments[$i], $targetSegments[$i]); + } else { + break; + } + } + $targetSegments[] = $targetLastSegment; + $relativePath = \str_repeat('../', \count($sourceSegments)) . \implode('/', $targetSegments); + // A reference to am empty last segment or an empty first sub-segment must be prefixed with "./". + // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used + // as the first segment of a relative-path reference, as it would be mistaken for a scheme name. + if ('' === $relativePath || \false !== \strpos(\explode('/', $relativePath, 2)[0], ':')) { + $relativePath = "./{$relativePath}"; + } elseif ('/' === $relativePath[0]) { + if ($base->getAuthority() != '' && $base->getPath() === '') { + // In this case an extra slash is added by resolve() automatically. So we must not add one here. + $relativePath = ".{$relativePath}"; + } else { + $relativePath = "./{$relativePath}"; + } + } + return $relativePath; + } + private function __construct() + { + // cannot be instantiated + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/functions.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/functions.php new file mode 100644 index 00000000..deb16450 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/functions.php @@ -0,0 +1,657 @@ +getMethod() . ' ' . $message->getRequestTarget()) . ' HTTP/' . $message->getProtocolVersion(); + if (!$message->hasHeader('host')) { + $msg .= "\r\nHost: " . $message->getUri()->getHost(); + } + } elseif ($message instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface) { + $msg = 'HTTP/' . $message->getProtocolVersion() . ' ' . $message->getStatusCode() . ' ' . $message->getReasonPhrase(); + } else { + throw new \InvalidArgumentException('Unknown message type'); + } + foreach ($message->getHeaders() as $name => $values) { + $msg .= "\r\n{$name}: " . \implode(', ', $values); + } + return "{$msg}\r\n\r\n" . $message->getBody(); +} +/** + * Returns a UriInterface for the given value. + * + * This function accepts a string or {@see Psr\Http\Message\UriInterface} and + * returns a UriInterface for the given value. If the value is already a + * `UriInterface`, it is returned as-is. + * + * @param string|UriInterface $uri + * + * @return UriInterface + * @throws \InvalidArgumentException + */ +function uri_for($uri) +{ + if ($uri instanceof \YoastSEO_Vendor\Psr\Http\Message\UriInterface) { + return $uri; + } elseif (\is_string($uri)) { + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($uri); + } + throw new \InvalidArgumentException('URI must be a string or UriInterface'); +} +/** + * Create a new stream based on the input type. + * + * Options is an associative array that can contain the following keys: + * - metadata: Array of custom metadata. + * - size: Size of the stream. + * + * @param resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource Entity body data + * @param array $options Additional options + * + * @return StreamInterface + * @throws \InvalidArgumentException if the $resource arg is not valid. + */ +function stream_for($resource = '', array $options = []) +{ + if (\is_scalar($resource)) { + $stream = \fopen('php://temp', 'r+'); + if ($resource !== '') { + \fwrite($stream, $resource); + \fseek($stream, 0); + } + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($stream, $options); + } + switch (\gettype($resource)) { + case 'resource': + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource, $options); + case 'object': + if ($resource instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) { + return $resource; + } elseif ($resource instanceof \Iterator) { + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\PumpStream(function () use($resource) { + if (!$resource->valid()) { + return \false; + } + $result = $resource->current(); + $resource->next(); + return $result; + }, $options); + } elseif (\method_exists($resource, '__toString')) { + return stream_for((string) $resource, $options); + } + break; + case 'NULL': + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream(\fopen('php://temp', 'r+'), $options); + } + if (\is_callable($resource)) { + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\PumpStream($resource, $options); + } + throw new \InvalidArgumentException('Invalid resource type: ' . \gettype($resource)); +} +/** + * Parse an array of header values containing ";" separated data into an + * array of associative arrays representing the header key value pair + * data of the header. When a parameter does not contain a value, but just + * contains a key, this function will inject a key with a '' string value. + * + * @param string|array $header Header to parse into components. + * + * @return array Returns the parsed header values. + */ +function parse_header($header) +{ + static $trimmed = "\"' \n\t\r"; + $params = $matches = []; + foreach (normalize_header($header) as $val) { + $part = []; + foreach (\preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) { + if (\preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) { + $m = $matches[0]; + if (isset($m[1])) { + $part[\trim($m[0], $trimmed)] = \trim($m[1], $trimmed); + } else { + $part[] = \trim($m[0], $trimmed); + } + } + } + if ($part) { + $params[] = $part; + } + } + return $params; +} +/** + * Converts an array of header values that may contain comma separated + * headers into an array of headers with no comma separated values. + * + * @param string|array $header Header to normalize. + * + * @return array Returns the normalized header field values. + */ +function normalize_header($header) +{ + if (!\is_array($header)) { + return \array_map('trim', \explode(',', $header)); + } + $result = []; + foreach ($header as $value) { + foreach ((array) $value as $v) { + if (\strpos($v, ',') === \false) { + $result[] = $v; + continue; + } + foreach (\preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $v) as $vv) { + $result[] = \trim($vv); + } + } + } + return $result; +} +/** + * Clone and modify a request with the given changes. + * + * The changes can be one of: + * - method: (string) Changes the HTTP method. + * - set_headers: (array) Sets the given headers. + * - remove_headers: (array) Remove the given headers. + * - body: (mixed) Sets the given body. + * - uri: (UriInterface) Set the URI. + * - query: (string) Set the query string value of the URI. + * - version: (string) Set the protocol version. + * + * @param RequestInterface $request Request to clone and modify. + * @param array $changes Changes to apply. + * + * @return RequestInterface + */ +function modify_request(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $changes) +{ + if (!$changes) { + return $request; + } + $headers = $request->getHeaders(); + if (!isset($changes['uri'])) { + $uri = $request->getUri(); + } else { + // Remove the host header if one is on the URI + if ($host = $changes['uri']->getHost()) { + $changes['set_headers']['Host'] = $host; + if ($port = $changes['uri']->getPort()) { + $standardPorts = ['http' => 80, 'https' => 443]; + $scheme = $changes['uri']->getScheme(); + if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) { + $changes['set_headers']['Host'] .= ':' . $port; + } + } + } + $uri = $changes['uri']; + } + if (!empty($changes['remove_headers'])) { + $headers = _caseless_remove($changes['remove_headers'], $headers); + } + if (!empty($changes['set_headers'])) { + $headers = _caseless_remove(\array_keys($changes['set_headers']), $headers); + $headers = $changes['set_headers'] + $headers; + } + if (isset($changes['query'])) { + $uri = $uri->withQuery($changes['query']); + } + if ($request instanceof \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface) { + return (new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest(isset($changes['method']) ? $changes['method'] : $request->getMethod(), $uri, $headers, isset($changes['body']) ? $changes['body'] : $request->getBody(), isset($changes['version']) ? $changes['version'] : $request->getProtocolVersion(), $request->getServerParams()))->withParsedBody($request->getParsedBody())->withQueryParams($request->getQueryParams())->withCookieParams($request->getCookieParams())->withUploadedFiles($request->getUploadedFiles()); + } + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request(isset($changes['method']) ? $changes['method'] : $request->getMethod(), $uri, $headers, isset($changes['body']) ? $changes['body'] : $request->getBody(), isset($changes['version']) ? $changes['version'] : $request->getProtocolVersion()); +} +/** + * Attempts to rewind a message body and throws an exception on failure. + * + * The body of the message will only be rewound if a call to `tell()` returns a + * value other than `0`. + * + * @param MessageInterface $message Message to rewind + * + * @throws \RuntimeException + */ +function rewind_body(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) +{ + $body = $message->getBody(); + if ($body->tell()) { + $body->rewind(); + } +} +/** + * Safely opens a PHP stream resource using a filename. + * + * When fopen fails, PHP normally raises a warning. This function adds an + * error handler that checks for errors and throws an exception instead. + * + * @param string $filename File to open + * @param string $mode Mode used to open the file + * + * @return resource + * @throws \RuntimeException if the file cannot be opened + */ +function try_fopen($filename, $mode) +{ + $ex = null; + \set_error_handler(function () use($filename, $mode, &$ex) { + $ex = new \RuntimeException(\sprintf('Unable to open %s using mode %s: %s', $filename, $mode, \func_get_args()[1])); + }); + $handle = \fopen($filename, $mode); + \restore_error_handler(); + if ($ex) { + /** @var $ex \RuntimeException */ + throw $ex; + } + return $handle; +} +/** + * Copy the contents of a stream into a string until the given number of + * bytes have been read. + * + * @param StreamInterface $stream Stream to read + * @param int $maxLen Maximum number of bytes to read. Pass -1 + * to read the entire stream. + * @return string + * @throws \RuntimeException on error. + */ +function copy_to_string(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $maxLen = -1) +{ + $buffer = ''; + if ($maxLen === -1) { + while (!$stream->eof()) { + $buf = $stream->read(1048576); + // Using a loose equality here to match on '' and false. + if ($buf == null) { + break; + } + $buffer .= $buf; + } + return $buffer; + } + $len = 0; + while (!$stream->eof() && $len < $maxLen) { + $buf = $stream->read($maxLen - $len); + // Using a loose equality here to match on '' and false. + if ($buf == null) { + break; + } + $buffer .= $buf; + $len = \strlen($buffer); + } + return $buffer; +} +/** + * Copy the contents of a stream into another stream until the given number + * of bytes have been read. + * + * @param StreamInterface $source Stream to read from + * @param StreamInterface $dest Stream to write to + * @param int $maxLen Maximum number of bytes to read. Pass -1 + * to read the entire stream. + * + * @throws \RuntimeException on error. + */ +function copy_to_stream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $dest, $maxLen = -1) +{ + $bufferSize = 8192; + if ($maxLen === -1) { + while (!$source->eof()) { + if (!$dest->write($source->read($bufferSize))) { + break; + } + } + } else { + $remaining = $maxLen; + while ($remaining > 0 && !$source->eof()) { + $buf = $source->read(\min($bufferSize, $remaining)); + $len = \strlen($buf); + if (!$len) { + break; + } + $remaining -= $len; + $dest->write($buf); + } + } +} +/** + * Calculate a hash of a Stream + * + * @param StreamInterface $stream Stream to calculate the hash for + * @param string $algo Hash algorithm (e.g. md5, crc32, etc) + * @param bool $rawOutput Whether or not to use raw output + * + * @return string Returns the hash of the stream + * @throws \RuntimeException on error. + */ +function hash(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $algo, $rawOutput = \false) +{ + $pos = $stream->tell(); + if ($pos > 0) { + $stream->rewind(); + } + $ctx = \hash_init($algo); + while (!$stream->eof()) { + \hash_update($ctx, $stream->read(1048576)); + } + $out = \hash_final($ctx, (bool) $rawOutput); + $stream->seek($pos); + return $out; +} +/** + * Read a line from the stream up to the maximum allowed buffer length + * + * @param StreamInterface $stream Stream to read from + * @param int $maxLength Maximum buffer length + * + * @return string + */ +function readline(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, $maxLength = null) +{ + $buffer = ''; + $size = 0; + while (!$stream->eof()) { + // Using a loose equality here to match on '' and false. + if (null == ($byte = $stream->read(1))) { + return $buffer; + } + $buffer .= $byte; + // Break when a new line is found or the max length - 1 is reached + if ($byte === "\n" || ++$size === $maxLength - 1) { + break; + } + } + return $buffer; +} +/** + * Parses a request message string into a request object. + * + * @param string $message Request message string. + * + * @return Request + */ +function parse_request($message) +{ + $data = _parse_message($message); + $matches = []; + if (!\preg_match('/^[\\S]+\\s+([a-zA-Z]+:\\/\\/|\\/).*/', $data['start-line'], $matches)) { + throw new \InvalidArgumentException('Invalid request string'); + } + $parts = \explode(' ', $data['start-line'], 3); + $version = isset($parts[2]) ? \explode('/', $parts[2])[1] : '1.1'; + $request = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($parts[0], $matches[1] === '/' ? _parse_request_uri($parts[1], $data['headers']) : $parts[1], $data['headers'], $data['body'], $version); + return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]); +} +/** + * Parses a response message string into a response object. + * + * @param string $message Response message string. + * + * @return Response + */ +function parse_response($message) +{ + $data = _parse_message($message); + // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space + // between status-code and reason-phrase is required. But browsers accept + // responses without space and reason as well. + if (!\preg_match('/^HTTP\\/.* [0-9]{3}( .*|$)/', $data['start-line'])) { + throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']); + } + $parts = \explode(' ', $data['start-line'], 3); + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($parts[1], $data['headers'], $data['body'], \explode('/', $parts[0])[1], isset($parts[2]) ? $parts[2] : null); +} +/** + * Parse a query string into an associative array. + * + * If multiple values are found for the same key, the value of that key + * value pair will become an array. This function does not parse nested + * PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will + * be parsed into ['foo[a]' => '1', 'foo[b]' => '2']). + * + * @param string $str Query string to parse + * @param int|bool $urlEncoding How the query string is encoded + * + * @return array + */ +function parse_query($str, $urlEncoding = \true) +{ + $result = []; + if ($str === '') { + return $result; + } + if ($urlEncoding === \true) { + $decoder = function ($value) { + return \rawurldecode(\str_replace('+', ' ', $value)); + }; + } elseif ($urlEncoding === \PHP_QUERY_RFC3986) { + $decoder = 'rawurldecode'; + } elseif ($urlEncoding === \PHP_QUERY_RFC1738) { + $decoder = 'urldecode'; + } else { + $decoder = function ($str) { + return $str; + }; + } + foreach (\explode('&', $str) as $kvp) { + $parts = \explode('=', $kvp, 2); + $key = $decoder($parts[0]); + $value = isset($parts[1]) ? $decoder($parts[1]) : null; + if (!isset($result[$key])) { + $result[$key] = $value; + } else { + if (!\is_array($result[$key])) { + $result[$key] = [$result[$key]]; + } + $result[$key][] = $value; + } + } + return $result; +} +/** + * Build a query string from an array of key value pairs. + * + * This function can use the return value of parse_query() to build a query + * string. This function does not modify the provided keys when an array is + * encountered (like http_build_query would). + * + * @param array $params Query string parameters. + * @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986 + * to encode using RFC3986, or PHP_QUERY_RFC1738 + * to encode using RFC1738. + * @return string + */ +function build_query(array $params, $encoding = \PHP_QUERY_RFC3986) +{ + if (!$params) { + return ''; + } + if ($encoding === \false) { + $encoder = function ($str) { + return $str; + }; + } elseif ($encoding === \PHP_QUERY_RFC3986) { + $encoder = 'rawurlencode'; + } elseif ($encoding === \PHP_QUERY_RFC1738) { + $encoder = 'urlencode'; + } else { + throw new \InvalidArgumentException('Invalid type'); + } + $qs = ''; + foreach ($params as $k => $v) { + $k = $encoder($k); + if (!\is_array($v)) { + $qs .= $k; + if ($v !== null) { + $qs .= '=' . $encoder($v); + } + $qs .= '&'; + } else { + foreach ($v as $vv) { + $qs .= $k; + if ($vv !== null) { + $qs .= '=' . $encoder($vv); + } + $qs .= '&'; + } + } + } + return $qs ? (string) \substr($qs, 0, -1) : ''; +} +/** + * Determines the mimetype of a file by looking at its extension. + * + * @param $filename + * + * @return null|string + */ +function mimetype_from_filename($filename) +{ + return mimetype_from_extension(\pathinfo($filename, \PATHINFO_EXTENSION)); +} +/** + * Maps a file extensions to a mimetype. + * + * @param $extension string The file extension. + * + * @return string|null + * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types + */ +function mimetype_from_extension($extension) +{ + static $mimetypes = ['3gp' => 'video/3gpp', '7z' => 'application/x-7z-compressed', 'aac' => 'audio/x-aac', 'ai' => 'application/postscript', 'aif' => 'audio/x-aiff', 'asc' => 'text/plain', 'asf' => 'video/x-ms-asf', 'atom' => 'application/atom+xml', 'avi' => 'video/x-msvideo', 'bmp' => 'image/bmp', 'bz2' => 'application/x-bzip2', 'cer' => 'application/pkix-cert', 'crl' => 'application/pkix-crl', 'crt' => 'application/x-x509-ca-cert', 'css' => 'text/css', 'csv' => 'text/csv', 'cu' => 'application/cu-seeme', 'deb' => 'application/x-debian-package', 'doc' => 'application/msword', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'dvi' => 'application/x-dvi', 'eot' => 'application/vnd.ms-fontobject', 'eps' => 'application/postscript', 'epub' => 'application/epub+zip', 'etx' => 'text/x-setext', 'flac' => 'audio/flac', 'flv' => 'video/x-flv', 'gif' => 'image/gif', 'gz' => 'application/gzip', 'htm' => 'text/html', 'html' => 'text/html', 'ico' => 'image/x-icon', 'ics' => 'text/calendar', 'ini' => 'text/plain', 'iso' => 'application/x-iso9660-image', 'jar' => 'application/java-archive', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', 'js' => 'text/javascript', 'json' => 'application/json', 'latex' => 'application/x-latex', 'log' => 'text/plain', 'm4a' => 'audio/mp4', 'm4v' => 'video/mp4', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mov' => 'video/quicktime', 'mkv' => 'video/x-matroska', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'mp4a' => 'audio/mp4', 'mp4v' => 'video/mp4', 'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpg' => 'video/mpeg', 'mpg4' => 'video/mp4', 'oga' => 'audio/ogg', 'ogg' => 'audio/ogg', 'ogv' => 'video/ogg', 'ogx' => 'application/ogg', 'pbm' => 'image/x-portable-bitmap', 'pdf' => 'application/pdf', 'pgm' => 'image/x-portable-graymap', 'png' => 'image/png', 'pnm' => 'image/x-portable-anymap', 'ppm' => 'image/x-portable-pixmap', 'ppt' => 'application/vnd.ms-powerpoint', 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'ps' => 'application/postscript', 'qt' => 'video/quicktime', 'rar' => 'application/x-rar-compressed', 'ras' => 'image/x-cmu-raster', 'rss' => 'application/rss+xml', 'rtf' => 'application/rtf', 'sgm' => 'text/sgml', 'sgml' => 'text/sgml', 'svg' => 'image/svg+xml', 'swf' => 'application/x-shockwave-flash', 'tar' => 'application/x-tar', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'torrent' => 'application/x-bittorrent', 'ttf' => 'application/x-font-ttf', 'txt' => 'text/plain', 'wav' => 'audio/x-wav', 'webm' => 'video/webm', 'wma' => 'audio/x-ms-wma', 'wmv' => 'video/x-ms-wmv', 'woff' => 'application/x-font-woff', 'wsdl' => 'application/wsdl+xml', 'xbm' => 'image/x-xbitmap', 'xls' => 'application/vnd.ms-excel', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xml' => 'application/xml', 'xpm' => 'image/x-xpixmap', 'xwd' => 'image/x-xwindowdump', 'yaml' => 'text/yaml', 'yml' => 'text/yaml', 'zip' => 'application/zip']; + $extension = \strtolower($extension); + return isset($mimetypes[$extension]) ? $mimetypes[$extension] : null; +} +/** + * Parses an HTTP message into an associative array. + * + * The array contains the "start-line" key containing the start line of + * the message, "headers" key containing an associative array of header + * array values, and a "body" key containing the body of the message. + * + * @param string $message HTTP request or response to parse. + * + * @return array + * @internal + */ +function _parse_message($message) +{ + if (!$message) { + throw new \InvalidArgumentException('Invalid message'); + } + $message = \ltrim($message, "\r\n"); + $messageParts = \preg_split("/\r?\n\r?\n/", $message, 2); + if ($messageParts === \false || \count($messageParts) !== 2) { + throw new \InvalidArgumentException('Invalid message: Missing header delimiter'); + } + list($rawHeaders, $body) = $messageParts; + $rawHeaders .= "\r\n"; + // Put back the delimiter we split previously + $headerParts = \preg_split("/\r?\n/", $rawHeaders, 2); + if ($headerParts === \false || \count($headerParts) !== 2) { + throw new \InvalidArgumentException('Invalid message: Missing status line'); + } + list($startLine, $rawHeaders) = $headerParts; + if (\preg_match("/(?:^HTTP\\/|^[A-Z]+ \\S+ HTTP\\/)(\\d+(?:\\.\\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') { + // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0 + $rawHeaders = \preg_replace(\YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders); + } + /** @var array[] $headerLines */ + $count = \preg_match_all(\YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, \PREG_SET_ORDER); + // If these aren't the same, then one line didn't match and there's an invalid header. + if ($count !== \substr_count($rawHeaders, "\n")) { + // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4 + if (\preg_match(\YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) { + throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding'); + } + throw new \InvalidArgumentException('Invalid header syntax'); + } + $headers = []; + foreach ($headerLines as $headerLine) { + $headers[$headerLine[1]][] = $headerLine[2]; + } + return ['start-line' => $startLine, 'headers' => $headers, 'body' => $body]; +} +/** + * Constructs a URI for an HTTP request message. + * + * @param string $path Path from the start-line + * @param array $headers Array of headers (each value an array). + * + * @return string + * @internal + */ +function _parse_request_uri($path, array $headers) +{ + $hostKey = \array_filter(\array_keys($headers), function ($k) { + return \strtolower($k) === 'host'; + }); + // If no host is found, then a full URI cannot be constructed. + if (!$hostKey) { + return $path; + } + $host = $headers[\reset($hostKey)][0]; + $scheme = \substr($host, -4) === ':443' ? 'https' : 'http'; + return $scheme . '://' . $host . '/' . \ltrim($path, '/'); +} +/** + * Get a short summary of the message body + * + * Will return `null` if the response is not printable. + * + * @param MessageInterface $message The message to get the body summary + * @param int $truncateAt The maximum allowed size of the summary + * + * @return null|string + */ +function get_message_body_summary(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message, $truncateAt = 120) +{ + $body = $message->getBody(); + if (!$body->isSeekable() || !$body->isReadable()) { + return null; + } + $size = $body->getSize(); + if ($size === 0) { + return null; + } + $summary = $body->read($truncateAt); + $body->rewind(); + if ($size > $truncateAt) { + $summary .= ' (truncated...)'; + } + // Matches any printable character, including unicode characters: + // letters, marks, numbers, punctuation, spacing, and separators. + if (\preg_match('/[^\\pL\\pM\\pN\\pP\\pS\\pZ\\n\\r\\t]/', $summary)) { + return null; + } + return $summary; +} +/** @internal */ +function _caseless_remove($keys, array $data) +{ + $result = []; + foreach ($keys as &$key) { + $key = \strtolower($key); + } + foreach ($data as $k => $v) { + if (!\in_array(\strtolower($k), $keys)) { + $result[$k] = $v; + } + } + return $result; +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/functions_include.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/functions_include.php new file mode 100644 index 00000000..d21cb559 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/guzzlehttp/psr7/src/functions_include.php @@ -0,0 +1,8 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; + +use YoastSEO_Vendor\League\OAuth2\Client\Tool\RequiredParameterTrait; +/** + * Represents a type of authorization grant. + * + * An authorization grant is a credential representing the resource + * owner's authorization (to access its protected resources) used by the + * client to obtain an access token. OAuth 2.0 defines four + * grant types -- authorization code, implicit, resource owner password + * credentials, and client credentials -- as well as an extensibility + * mechanism for defining additional types. + * + * @link http://tools.ietf.org/html/rfc6749#section-1.3 Authorization Grant (RFC 6749, §1.3) + */ +abstract class AbstractGrant +{ + use RequiredParameterTrait; + /** + * Returns the name of this grant, eg. 'grant_name', which is used as the + * grant type when encoding URL query parameters. + * + * @return string + */ + protected abstract function getName(); + /** + * Returns a list of all required request parameters. + * + * @return array + */ + protected abstract function getRequiredRequestParameters(); + /** + * Returns this grant's name as its string representation. This allows for + * string interpolation when building URL query parameters. + * + * @return string + */ + public function __toString() + { + return $this->getName(); + } + /** + * Prepares an access token request's parameters by checking that all + * required parameters are set, then merging with any given defaults. + * + * @param array $defaults + * @param array $options + * @return array + */ + public function prepareRequestParameters(array $defaults, array $options) + { + $defaults['grant_type'] = $this->getName(); + $required = $this->getRequiredRequestParameters(); + $provided = \array_merge($defaults, $options); + $this->checkRequiredParameters($required, $provided); + return $provided; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/AuthorizationCode.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/AuthorizationCode.php new file mode 100644 index 00000000..cec79b7b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/AuthorizationCode.php @@ -0,0 +1,38 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; + +/** + * Represents an authorization code grant. + * + * @link http://tools.ietf.org/html/rfc6749#section-1.3.1 Authorization Code (RFC 6749, §1.3.1) + */ +class AuthorizationCode extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant +{ + /** + * @inheritdoc + */ + protected function getName() + { + return 'authorization_code'; + } + /** + * @inheritdoc + */ + protected function getRequiredRequestParameters() + { + return ['code']; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/ClientCredentials.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/ClientCredentials.php new file mode 100644 index 00000000..57ce31f9 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/ClientCredentials.php @@ -0,0 +1,38 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; + +/** + * Represents a client credentials grant. + * + * @link http://tools.ietf.org/html/rfc6749#section-1.3.4 Client Credentials (RFC 6749, §1.3.4) + */ +class ClientCredentials extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant +{ + /** + * @inheritdoc + */ + protected function getName() + { + return 'client_credentials'; + } + /** + * @inheritdoc + */ + protected function getRequiredRequestParameters() + { + return []; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php new file mode 100644 index 00000000..6cad7118 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/Exception/InvalidGrantException.php @@ -0,0 +1,25 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Grant\Exception; + +use InvalidArgumentException; +/** + * Exception thrown if the grant does not extend from AbstractGrant. + * + * @see League\OAuth2\Client\Grant\AbstractGrant + */ +class InvalidGrantException extends \InvalidArgumentException +{ +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/GrantFactory.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/GrantFactory.php new file mode 100644 index 00000000..81f463df --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/GrantFactory.php @@ -0,0 +1,91 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; + +use YoastSEO_Vendor\League\OAuth2\Client\Grant\Exception\InvalidGrantException; +/** + * Represents a factory used when retrieving an authorization grant type. + */ +class GrantFactory +{ + /** + * @var array + */ + protected $registry = []; + /** + * Defines a grant singleton in the registry. + * + * @param string $name + * @param AbstractGrant $grant + * @return self + */ + public function setGrant($name, \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant $grant) + { + $this->registry[$name] = $grant; + return $this; + } + /** + * Returns a grant singleton by name. + * + * If the grant has not be registered, a default grant will be loaded. + * + * @param string $name + * @return AbstractGrant + */ + public function getGrant($name) + { + if (empty($this->registry[$name])) { + $this->registerDefaultGrant($name); + } + return $this->registry[$name]; + } + /** + * Registers a default grant singleton by name. + * + * @param string $name + * @return self + */ + protected function registerDefaultGrant($name) + { + // PascalCase the grant. E.g: 'authorization_code' becomes 'AuthorizationCode' + $class = \str_replace(' ', '', \ucwords(\str_replace(['-', '_'], ' ', $name))); + $class = 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\' . $class; + $this->checkGrant($class); + return $this->setGrant($name, new $class()); + } + /** + * Determines if a variable is a valid grant. + * + * @param mixed $class + * @return boolean + */ + public function isGrant($class) + { + return \is_subclass_of($class, \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant::class); + } + /** + * Checks if a variable is a valid grant. + * + * @throws InvalidGrantException + * @param mixed $class + * @return void + */ + public function checkGrant($class) + { + if (!$this->isGrant($class)) { + throw new \YoastSEO_Vendor\League\OAuth2\Client\Grant\Exception\InvalidGrantException(\sprintf('Grant "%s" must extend AbstractGrant', \is_object($class) ? \get_class($class) : $class)); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/Password.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/Password.php new file mode 100644 index 00000000..84e5920a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/Password.php @@ -0,0 +1,38 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; + +/** + * Represents a resource owner password credentials grant. + * + * @link http://tools.ietf.org/html/rfc6749#section-1.3.3 Resource Owner Password Credentials (RFC 6749, §1.3.3) + */ +class Password extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant +{ + /** + * @inheritdoc + */ + protected function getName() + { + return 'password'; + } + /** + * @inheritdoc + */ + protected function getRequiredRequestParameters() + { + return ['username', 'password']; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/RefreshToken.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/RefreshToken.php new file mode 100644 index 00000000..f5b149dc --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Grant/RefreshToken.php @@ -0,0 +1,38 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; + +/** + * Represents a refresh token grant. + * + * @link http://tools.ietf.org/html/rfc6749#section-6 Refreshing an Access Token (RFC 6749, §6) + */ +class RefreshToken extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant +{ + /** + * @inheritdoc + */ + protected function getName() + { + return 'refresh_token'; + } + /** + * @inheritdoc + */ + protected function getRequiredRequestParameters() + { + return ['refresh_token']; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php new file mode 100644 index 00000000..b5addc40 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.php @@ -0,0 +1,38 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\OptionProvider; + +use InvalidArgumentException; +/** + * Add http basic auth into access token request options + * @link https://tools.ietf.org/html/rfc6749#section-2.3.1 + */ +class HttpBasicAuthOptionProvider extends \YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\PostAuthOptionProvider +{ + /** + * @inheritdoc + */ + public function getAccessTokenOptions($method, array $params) + { + if (empty($params['client_id']) || empty($params['client_secret'])) { + throw new \InvalidArgumentException('clientId and clientSecret are required for http basic auth'); + } + $encodedCredentials = \base64_encode(\sprintf('%s:%s', $params['client_id'], $params['client_secret'])); + unset($params['client_id'], $params['client_secret']); + $options = parent::getAccessTokenOptions($method, $params); + $options['headers']['Authorization'] = 'Basic ' . $encodedCredentials; + return $options; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php new file mode 100644 index 00000000..8fc66e7e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/OptionProvider/OptionProviderInterface.php @@ -0,0 +1,30 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\OptionProvider; + +/** + * Interface for access token options provider + */ +interface OptionProviderInterface +{ + /** + * Builds request options used for requesting an access token. + * + * @param string $method + * @param array $params + * @return array + */ + public function getAccessTokenOptions($method, array $params); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php new file mode 100644 index 00000000..4813fd80 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/OptionProvider/PostAuthOptionProvider.php @@ -0,0 +1,46 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\OptionProvider; + +use YoastSEO_Vendor\League\OAuth2\Client\Provider\AbstractProvider; +use YoastSEO_Vendor\League\OAuth2\Client\Tool\QueryBuilderTrait; +/** + * Provide options for access token + */ +class PostAuthOptionProvider implements \YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\OptionProviderInterface +{ + use QueryBuilderTrait; + /** + * @inheritdoc + */ + public function getAccessTokenOptions($method, array $params) + { + $options = ['headers' => ['content-type' => 'application/x-www-form-urlencoded']]; + if ($method === \YoastSEO_Vendor\League\OAuth2\Client\Provider\AbstractProvider::METHOD_POST) { + $options['body'] = $this->getAccessTokenBody($params); + } + return $options; + } + /** + * Returns the request body for requesting an access token. + * + * @param array $params + * @return string + */ + protected function getAccessTokenBody(array $params) + { + return $this->buildQueryString($params); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/AbstractProvider.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/AbstractProvider.php new file mode 100644 index 00000000..bca3bae4 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/AbstractProvider.php @@ -0,0 +1,709 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Provider; + +use YoastSEO_Vendor\GuzzleHttp\Client as HttpClient; +use YoastSEO_Vendor\GuzzleHttp\ClientInterface as HttpClientInterface; +use YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException; +use YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant; +use YoastSEO_Vendor\League\OAuth2\Client\Grant\GrantFactory; +use YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\OptionProviderInterface; +use YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\PostAuthOptionProvider; +use YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException; +use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken; +use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface; +use YoastSEO_Vendor\League\OAuth2\Client\Tool\ArrayAccessorTrait; +use YoastSEO_Vendor\League\OAuth2\Client\Tool\GuardedPropertyTrait; +use YoastSEO_Vendor\League\OAuth2\Client\Tool\QueryBuilderTrait; +use YoastSEO_Vendor\League\OAuth2\Client\Tool\RequestFactory; +use YoastSEO_Vendor\Psr\Http\Message\RequestInterface; +use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface; +use UnexpectedValueException; +/** + * Represents a service provider (authorization server). + * + * @link http://tools.ietf.org/html/rfc6749#section-1.1 Roles (RFC 6749, §1.1) + */ +abstract class AbstractProvider +{ + use ArrayAccessorTrait; + use GuardedPropertyTrait; + use QueryBuilderTrait; + /** + * @var string Key used in a token response to identify the resource owner. + */ + const ACCESS_TOKEN_RESOURCE_OWNER_ID = null; + /** + * @var string HTTP method used to fetch access tokens. + */ + const METHOD_GET = 'GET'; + /** + * @var string HTTP method used to fetch access tokens. + */ + const METHOD_POST = 'POST'; + /** + * @var string + */ + protected $clientId; + /** + * @var string + */ + protected $clientSecret; + /** + * @var string + */ + protected $redirectUri; + /** + * @var string + */ + protected $state; + /** + * @var GrantFactory + */ + protected $grantFactory; + /** + * @var RequestFactory + */ + protected $requestFactory; + /** + * @var HttpClientInterface + */ + protected $httpClient; + /** + * @var OptionProviderInterface + */ + protected $optionProvider; + /** + * Constructs an OAuth 2.0 service provider. + * + * @param array $options An array of options to set on this provider. + * Options include `clientId`, `clientSecret`, `redirectUri`, and `state`. + * Individual providers may introduce more options, as needed. + * @param array $collaborators An array of collaborators that may be used to + * override this provider's default behavior. Collaborators include + * `grantFactory`, `requestFactory`, and `httpClient`. + * Individual providers may introduce more collaborators, as needed. + */ + public function __construct(array $options = [], array $collaborators = []) + { + // We'll let the GuardedPropertyTrait handle mass assignment of incoming + // options, skipping any blacklisted properties defined in the provider + $this->fillProperties($options); + if (empty($collaborators['grantFactory'])) { + $collaborators['grantFactory'] = new \YoastSEO_Vendor\League\OAuth2\Client\Grant\GrantFactory(); + } + $this->setGrantFactory($collaborators['grantFactory']); + if (empty($collaborators['requestFactory'])) { + $collaborators['requestFactory'] = new \YoastSEO_Vendor\League\OAuth2\Client\Tool\RequestFactory(); + } + $this->setRequestFactory($collaborators['requestFactory']); + if (empty($collaborators['httpClient'])) { + $client_options = $this->getAllowedClientOptions($options); + $collaborators['httpClient'] = new \YoastSEO_Vendor\GuzzleHttp\Client(\array_intersect_key($options, \array_flip($client_options))); + } + $this->setHttpClient($collaborators['httpClient']); + if (empty($collaborators['optionProvider'])) { + $collaborators['optionProvider'] = new \YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\PostAuthOptionProvider(); + } + $this->setOptionProvider($collaborators['optionProvider']); + } + /** + * Returns the list of options that can be passed to the HttpClient + * + * @param array $options An array of options to set on this provider. + * Options include `clientId`, `clientSecret`, `redirectUri`, and `state`. + * Individual providers may introduce more options, as needed. + * @return array The options to pass to the HttpClient constructor + */ + protected function getAllowedClientOptions(array $options) + { + $client_options = ['timeout', 'proxy']; + // Only allow turning off ssl verification if it's for a proxy + if (!empty($options['proxy'])) { + $client_options[] = 'verify'; + } + return $client_options; + } + /** + * Sets the grant factory instance. + * + * @param GrantFactory $factory + * @return self + */ + public function setGrantFactory(\YoastSEO_Vendor\League\OAuth2\Client\Grant\GrantFactory $factory) + { + $this->grantFactory = $factory; + return $this; + } + /** + * Returns the current grant factory instance. + * + * @return GrantFactory + */ + public function getGrantFactory() + { + return $this->grantFactory; + } + /** + * Sets the request factory instance. + * + * @param RequestFactory $factory + * @return self + */ + public function setRequestFactory(\YoastSEO_Vendor\League\OAuth2\Client\Tool\RequestFactory $factory) + { + $this->requestFactory = $factory; + return $this; + } + /** + * Returns the request factory instance. + * + * @return RequestFactory + */ + public function getRequestFactory() + { + return $this->requestFactory; + } + /** + * Sets the HTTP client instance. + * + * @param HttpClientInterface $client + * @return self + */ + public function setHttpClient(\YoastSEO_Vendor\GuzzleHttp\ClientInterface $client) + { + $this->httpClient = $client; + return $this; + } + /** + * Returns the HTTP client instance. + * + * @return HttpClientInterface + */ + public function getHttpClient() + { + return $this->httpClient; + } + /** + * Sets the option provider instance. + * + * @param OptionProviderInterface $provider + * @return self + */ + public function setOptionProvider(\YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\OptionProviderInterface $provider) + { + $this->optionProvider = $provider; + return $this; + } + /** + * Returns the option provider instance. + * + * @return OptionProviderInterface + */ + public function getOptionProvider() + { + return $this->optionProvider; + } + /** + * Returns the current value of the state parameter. + * + * This can be accessed by the redirect handler during authorization. + * + * @return string + */ + public function getState() + { + return $this->state; + } + /** + * Returns the base URL for authorizing a client. + * + * Eg. https://oauth.service.com/authorize + * + * @return string + */ + public abstract function getBaseAuthorizationUrl(); + /** + * Returns the base URL for requesting an access token. + * + * Eg. https://oauth.service.com/token + * + * @param array $params + * @return string + */ + public abstract function getBaseAccessTokenUrl(array $params); + /** + * Returns the URL for requesting the resource owner's details. + * + * @param AccessToken $token + * @return string + */ + public abstract function getResourceOwnerDetailsUrl(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token); + /** + * Returns a new random string to use as the state parameter in an + * authorization flow. + * + * @param int $length Length of the random string to be generated. + * @return string + */ + protected function getRandomState($length = 32) + { + // Converting bytes to hex will always double length. Hence, we can reduce + // the amount of bytes by half to produce the correct length. + return \bin2hex(\random_bytes($length / 2)); + } + /** + * Returns the default scopes used by this provider. + * + * This should only be the scopes that are required to request the details + * of the resource owner, rather than all the available scopes. + * + * @return array + */ + protected abstract function getDefaultScopes(); + /** + * Returns the string that should be used to separate scopes when building + * the URL for requesting an access token. + * + * @return string Scope separator, defaults to ',' + */ + protected function getScopeSeparator() + { + return ','; + } + /** + * Returns authorization parameters based on provided options. + * + * @param array $options + * @return array Authorization parameters + */ + protected function getAuthorizationParameters(array $options) + { + if (empty($options['state'])) { + $options['state'] = $this->getRandomState(); + } + if (empty($options['scope'])) { + $options['scope'] = $this->getDefaultScopes(); + } + $options += ['response_type' => 'code', 'approval_prompt' => 'auto']; + if (\is_array($options['scope'])) { + $separator = $this->getScopeSeparator(); + $options['scope'] = \implode($separator, $options['scope']); + } + // Store the state as it may need to be accessed later on. + $this->state = $options['state']; + // Business code layer might set a different redirect_uri parameter + // depending on the context, leave it as-is + if (!isset($options['redirect_uri'])) { + $options['redirect_uri'] = $this->redirectUri; + } + $options['client_id'] = $this->clientId; + return $options; + } + /** + * Builds the authorization URL's query string. + * + * @param array $params Query parameters + * @return string Query string + */ + protected function getAuthorizationQuery(array $params) + { + return $this->buildQueryString($params); + } + /** + * Builds the authorization URL. + * + * @param array $options + * @return string Authorization URL + */ + public function getAuthorizationUrl(array $options = []) + { + $base = $this->getBaseAuthorizationUrl(); + $params = $this->getAuthorizationParameters($options); + $query = $this->getAuthorizationQuery($params); + return $this->appendQuery($base, $query); + } + /** + * Redirects the client for authorization. + * + * @param array $options + * @param callable|null $redirectHandler + * @return mixed + */ + public function authorize(array $options = [], callable $redirectHandler = null) + { + $url = $this->getAuthorizationUrl($options); + if ($redirectHandler) { + return $redirectHandler($url, $this); + } + // @codeCoverageIgnoreStart + \header('Location: ' . $url); + exit; + // @codeCoverageIgnoreEnd + } + /** + * Appends a query string to a URL. + * + * @param string $url The URL to append the query to + * @param string $query The HTTP query string + * @return string The resulting URL + */ + protected function appendQuery($url, $query) + { + $query = \trim($query, '?&'); + if ($query) { + $glue = \strstr($url, '?') === \false ? '?' : '&'; + return $url . $glue . $query; + } + return $url; + } + /** + * Returns the method to use when requesting an access token. + * + * @return string HTTP method + */ + protected function getAccessTokenMethod() + { + return self::METHOD_POST; + } + /** + * Returns the key used in the access token response to identify the resource owner. + * + * @return string|null Resource owner identifier key + */ + protected function getAccessTokenResourceOwnerId() + { + return static::ACCESS_TOKEN_RESOURCE_OWNER_ID; + } + /** + * Builds the access token URL's query string. + * + * @param array $params Query parameters + * @return string Query string + */ + protected function getAccessTokenQuery(array $params) + { + return $this->buildQueryString($params); + } + /** + * Checks that a provided grant is valid, or attempts to produce one if the + * provided grant is a string. + * + * @param AbstractGrant|string $grant + * @return AbstractGrant + */ + protected function verifyGrant($grant) + { + if (\is_string($grant)) { + return $this->grantFactory->getGrant($grant); + } + $this->grantFactory->checkGrant($grant); + return $grant; + } + /** + * Returns the full URL to use when requesting an access token. + * + * @param array $params Query parameters + * @return string + */ + protected function getAccessTokenUrl(array $params) + { + $url = $this->getBaseAccessTokenUrl($params); + if ($this->getAccessTokenMethod() === self::METHOD_GET) { + $query = $this->getAccessTokenQuery($params); + return $this->appendQuery($url, $query); + } + return $url; + } + /** + * Returns a prepared request for requesting an access token. + * + * @param array $params Query string parameters + * @return RequestInterface + */ + protected function getAccessTokenRequest(array $params) + { + $method = $this->getAccessTokenMethod(); + $url = $this->getAccessTokenUrl($params); + $options = $this->optionProvider->getAccessTokenOptions($this->getAccessTokenMethod(), $params); + return $this->getRequest($method, $url, $options); + } + /** + * Requests an access token using a specified grant and option set. + * + * @param mixed $grant + * @param array $options + * @throws IdentityProviderException + * @return AccessTokenInterface + */ + public function getAccessToken($grant, array $options = []) + { + $grant = $this->verifyGrant($grant); + $params = ['client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'redirect_uri' => $this->redirectUri]; + $params = $grant->prepareRequestParameters($params, $options); + $request = $this->getAccessTokenRequest($params); + $response = $this->getParsedResponse($request); + if (\false === \is_array($response)) { + throw new \UnexpectedValueException('Invalid response received from Authorization Server. Expected JSON.'); + } + $prepared = $this->prepareAccessTokenResponse($response); + $token = $this->createAccessToken($prepared, $grant); + return $token; + } + /** + * Returns a PSR-7 request instance that is not authenticated. + * + * @param string $method + * @param string $url + * @param array $options + * @return RequestInterface + */ + public function getRequest($method, $url, array $options = []) + { + return $this->createRequest($method, $url, null, $options); + } + /** + * Returns an authenticated PSR-7 request instance. + * + * @param string $method + * @param string $url + * @param AccessTokenInterface|string $token + * @param array $options Any of "headers", "body", and "protocolVersion". + * @return RequestInterface + */ + public function getAuthenticatedRequest($method, $url, $token, array $options = []) + { + return $this->createRequest($method, $url, $token, $options); + } + /** + * Creates a PSR-7 request instance. + * + * @param string $method + * @param string $url + * @param AccessTokenInterface|string|null $token + * @param array $options + * @return RequestInterface + */ + protected function createRequest($method, $url, $token, array $options) + { + $defaults = ['headers' => $this->getHeaders($token)]; + $options = \array_merge_recursive($defaults, $options); + $factory = $this->getRequestFactory(); + return $factory->getRequestWithOptions($method, $url, $options); + } + /** + * Sends a request instance and returns a response instance. + * + * WARNING: This method does not attempt to catch exceptions caused by HTTP + * errors! It is recommended to wrap this method in a try/catch block. + * + * @param RequestInterface $request + * @return ResponseInterface + */ + public function getResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) + { + return $this->getHttpClient()->send($request); + } + /** + * Sends a request and returns the parsed response. + * + * @param RequestInterface $request + * @throws IdentityProviderException + * @return mixed + */ + public function getParsedResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) + { + try { + $response = $this->getResponse($request); + } catch (\YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException $e) { + $response = $e->getResponse(); + } + $parsed = $this->parseResponse($response); + $this->checkResponse($response, $parsed); + return $parsed; + } + /** + * Attempts to parse a JSON response. + * + * @param string $content JSON content from response body + * @return array Parsed JSON data + * @throws UnexpectedValueException if the content could not be parsed + */ + protected function parseJson($content) + { + $content = \json_decode($content, \true); + if (\json_last_error() !== \JSON_ERROR_NONE) { + throw new \UnexpectedValueException(\sprintf("Failed to parse JSON response: %s", \json_last_error_msg())); + } + return $content; + } + /** + * Returns the content type header of a response. + * + * @param ResponseInterface $response + * @return string Semi-colon separated join of content-type headers. + */ + protected function getContentType(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) + { + return \join(';', (array) $response->getHeader('content-type')); + } + /** + * Parses the response according to its content-type header. + * + * @throws UnexpectedValueException + * @param ResponseInterface $response + * @return array + */ + protected function parseResponse(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) + { + $content = (string) $response->getBody(); + $type = $this->getContentType($response); + if (\strpos($type, 'urlencoded') !== \false) { + \parse_str($content, $parsed); + return $parsed; + } + // Attempt to parse the string as JSON regardless of content type, + // since some providers use non-standard content types. Only throw an + // exception if the JSON could not be parsed when it was expected to. + try { + return $this->parseJson($content); + } catch (\UnexpectedValueException $e) { + if (\strpos($type, 'json') !== \false) { + throw $e; + } + if ($response->getStatusCode() == 500) { + throw new \UnexpectedValueException('An OAuth server error was encountered that did not contain a JSON body', 0, $e); + } + return $content; + } + } + /** + * Checks a provider response for errors. + * + * @throws IdentityProviderException + * @param ResponseInterface $response + * @param array|string $data Parsed response data + * @return void + */ + protected abstract function checkResponse(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, $data); + /** + * Prepares an parsed access token response for a grant. + * + * Custom mapping of expiration, etc should be done here. Always call the + * parent method when overloading this method. + * + * @param mixed $result + * @return array + */ + protected function prepareAccessTokenResponse(array $result) + { + if ($this->getAccessTokenResourceOwnerId() !== null) { + $result['resource_owner_id'] = $this->getValueByKey($result, $this->getAccessTokenResourceOwnerId()); + } + return $result; + } + /** + * Creates an access token from a response. + * + * The grant that was used to fetch the response can be used to provide + * additional context. + * + * @param array $response + * @param AbstractGrant $grant + * @return AccessTokenInterface + */ + protected function createAccessToken(array $response, \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant $grant) + { + return new \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken($response); + } + /** + * Generates a resource owner object from a successful resource owner + * details request. + * + * @param array $response + * @param AccessToken $token + * @return ResourceOwnerInterface + */ + protected abstract function createResourceOwner(array $response, \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token); + /** + * Requests and returns the resource owner of given access token. + * + * @param AccessToken $token + * @return ResourceOwnerInterface + */ + public function getResourceOwner(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token) + { + $response = $this->fetchResourceOwnerDetails($token); + return $this->createResourceOwner($response, $token); + } + /** + * Requests resource owner details. + * + * @param AccessToken $token + * @return mixed + */ + protected function fetchResourceOwnerDetails(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token) + { + $url = $this->getResourceOwnerDetailsUrl($token); + $request = $this->getAuthenticatedRequest(self::METHOD_GET, $url, $token); + $response = $this->getParsedResponse($request); + if (\false === \is_array($response)) { + throw new \UnexpectedValueException('Invalid response received from Authorization Server. Expected JSON.'); + } + return $response; + } + /** + * Returns the default headers used by this provider. + * + * Typically this is used to set 'Accept' or 'Content-Type' headers. + * + * @return array + */ + protected function getDefaultHeaders() + { + return []; + } + /** + * Returns the authorization headers used by this provider. + * + * Typically this is "Bearer" or "MAC". For more information see: + * http://tools.ietf.org/html/rfc6749#section-7.1 + * + * No default is provided, providers must overload this method to activate + * authorization headers. + * + * @param mixed|null $token Either a string or an access token instance + * @return array + */ + protected function getAuthorizationHeaders($token = null) + { + return []; + } + /** + * Returns all headers used by this provider for a request. + * + * The request will be authenticated if an access token is provided. + * + * @param mixed|null $token object or string + * @return array + */ + public function getHeaders($token = null) + { + if ($token) { + return \array_merge($this->getDefaultHeaders(), $this->getAuthorizationHeaders($token)); + } + return $this->getDefaultHeaders(); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php new file mode 100644 index 00000000..f4ed40a3 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/Exception/IdentityProviderException.php @@ -0,0 +1,45 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception; + +/** + * Exception thrown if the provider response contains errors. + */ +class IdentityProviderException extends \Exception +{ + /** + * @var mixed + */ + protected $response; + /** + * @param string $message + * @param int $code + * @param array|string $response The response body + */ + public function __construct($message, $code, $response) + { + $this->response = $response; + parent::__construct($message, $code); + } + /** + * Returns the exception's response body. + * + * @return array|string + */ + public function getResponseBody() + { + return $this->response; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/GenericProvider.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/GenericProvider.php new file mode 100644 index 00000000..39206e3e --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/GenericProvider.php @@ -0,0 +1,190 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Provider; + +use InvalidArgumentException; +use YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException; +use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken; +use YoastSEO_Vendor\League\OAuth2\Client\Tool\BearerAuthorizationTrait; +use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface; +/** + * Represents a generic service provider that may be used to interact with any + * OAuth 2.0 service provider, using Bearer token authentication. + */ +class GenericProvider extends \YoastSEO_Vendor\League\OAuth2\Client\Provider\AbstractProvider +{ + use BearerAuthorizationTrait; + /** + * @var string + */ + private $urlAuthorize; + /** + * @var string + */ + private $urlAccessToken; + /** + * @var string + */ + private $urlResourceOwnerDetails; + /** + * @var string + */ + private $accessTokenMethod; + /** + * @var string + */ + private $accessTokenResourceOwnerId; + /** + * @var array|null + */ + private $scopes = null; + /** + * @var string + */ + private $scopeSeparator; + /** + * @var string + */ + private $responseError = 'error'; + /** + * @var string + */ + private $responseCode; + /** + * @var string + */ + private $responseResourceOwnerId = 'id'; + /** + * @param array $options + * @param array $collaborators + */ + public function __construct(array $options = [], array $collaborators = []) + { + $this->assertRequiredOptions($options); + $possible = $this->getConfigurableOptions(); + $configured = \array_intersect_key($options, \array_flip($possible)); + foreach ($configured as $key => $value) { + $this->{$key} = $value; + } + // Remove all options that are only used locally + $options = \array_diff_key($options, $configured); + parent::__construct($options, $collaborators); + } + /** + * Returns all options that can be configured. + * + * @return array + */ + protected function getConfigurableOptions() + { + return \array_merge($this->getRequiredOptions(), ['accessTokenMethod', 'accessTokenResourceOwnerId', 'scopeSeparator', 'responseError', 'responseCode', 'responseResourceOwnerId', 'scopes']); + } + /** + * Returns all options that are required. + * + * @return array + */ + protected function getRequiredOptions() + { + return ['urlAuthorize', 'urlAccessToken', 'urlResourceOwnerDetails']; + } + /** + * Verifies that all required options have been passed. + * + * @param array $options + * @return void + * @throws InvalidArgumentException + */ + private function assertRequiredOptions(array $options) + { + $missing = \array_diff_key(\array_flip($this->getRequiredOptions()), $options); + if (!empty($missing)) { + throw new \InvalidArgumentException('Required options not defined: ' . \implode(', ', \array_keys($missing))); + } + } + /** + * @inheritdoc + */ + public function getBaseAuthorizationUrl() + { + return $this->urlAuthorize; + } + /** + * @inheritdoc + */ + public function getBaseAccessTokenUrl(array $params) + { + return $this->urlAccessToken; + } + /** + * @inheritdoc + */ + public function getResourceOwnerDetailsUrl(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token) + { + return $this->urlResourceOwnerDetails; + } + /** + * @inheritdoc + */ + public function getDefaultScopes() + { + return $this->scopes; + } + /** + * @inheritdoc + */ + protected function getAccessTokenMethod() + { + return $this->accessTokenMethod ?: parent::getAccessTokenMethod(); + } + /** + * @inheritdoc + */ + protected function getAccessTokenResourceOwnerId() + { + return $this->accessTokenResourceOwnerId ?: parent::getAccessTokenResourceOwnerId(); + } + /** + * @inheritdoc + */ + protected function getScopeSeparator() + { + return $this->scopeSeparator ?: parent::getScopeSeparator(); + } + /** + * @inheritdoc + */ + protected function checkResponse(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, $data) + { + if (!empty($data[$this->responseError])) { + $error = $data[$this->responseError]; + if (!\is_string($error)) { + $error = \var_export($error, \true); + } + $code = $this->responseCode && !empty($data[$this->responseCode]) ? $data[$this->responseCode] : 0; + if (!\is_int($code)) { + $code = \intval($code); + } + throw new \YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException($error, $code, $data); + } + } + /** + * @inheritdoc + */ + protected function createResourceOwner(array $response, \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token) + { + return new \YoastSEO_Vendor\League\OAuth2\Client\Provider\GenericResourceOwner($response, $this->responseResourceOwnerId); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/GenericResourceOwner.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/GenericResourceOwner.php new file mode 100644 index 00000000..08032401 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/GenericResourceOwner.php @@ -0,0 +1,57 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Provider; + +/** + * Represents a generic resource owner for use with the GenericProvider. + */ +class GenericResourceOwner implements \YoastSEO_Vendor\League\OAuth2\Client\Provider\ResourceOwnerInterface +{ + /** + * @var array + */ + protected $response; + /** + * @var string + */ + protected $resourceOwnerId; + /** + * @param array $response + * @param string $resourceOwnerId + */ + public function __construct(array $response, $resourceOwnerId) + { + $this->response = $response; + $this->resourceOwnerId = $resourceOwnerId; + } + /** + * Returns the identifier of the authorized resource owner. + * + * @return mixed + */ + public function getId() + { + return $this->response[$this->resourceOwnerId]; + } + /** + * Returns the raw resource owner response. + * + * @return array + */ + public function toArray() + { + return $this->response; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/ResourceOwnerInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/ResourceOwnerInterface.php new file mode 100644 index 00000000..d6717a58 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Provider/ResourceOwnerInterface.php @@ -0,0 +1,35 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Provider; + +/** + * Classes implementing `ResourceOwnerInterface` may be used to represent + * the resource owner authenticated with a service provider. + */ +interface ResourceOwnerInterface +{ + /** + * Returns the identifier of the authorized resource owner. + * + * @return mixed + */ + public function getId(); + /** + * Return all of the owner details available as an array. + * + * @return array + */ + public function toArray(); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Token/AccessToken.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Token/AccessToken.php new file mode 100644 index 00000000..79484e5a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Token/AccessToken.php @@ -0,0 +1,174 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Token; + +use InvalidArgumentException; +use RuntimeException; +/** + * Represents an access token. + * + * @link http://tools.ietf.org/html/rfc6749#section-1.4 Access Token (RFC 6749, §1.4) + */ +class AccessToken implements \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface, \YoastSEO_Vendor\League\OAuth2\Client\Token\ResourceOwnerAccessTokenInterface +{ + /** + * @var string + */ + protected $accessToken; + /** + * @var int + */ + protected $expires; + /** + * @var string + */ + protected $refreshToken; + /** + * @var string + */ + protected $resourceOwnerId; + /** + * @var array + */ + protected $values = []; + /** + * Constructs an access token. + * + * @param array $options An array of options returned by the service provider + * in the access token request. The `access_token` option is required. + * @throws InvalidArgumentException if `access_token` is not provided in `$options`. + */ + public function __construct(array $options = []) + { + if (empty($options['access_token'])) { + throw new \InvalidArgumentException('Required option not passed: "access_token"'); + } + $this->accessToken = $options['access_token']; + if (!empty($options['resource_owner_id'])) { + $this->resourceOwnerId = $options['resource_owner_id']; + } + if (!empty($options['refresh_token'])) { + $this->refreshToken = $options['refresh_token']; + } + // We need to know when the token expires. Show preference to + // 'expires_in' since it is defined in RFC6749 Section 5.1. + // Defer to 'expires' if it is provided instead. + if (isset($options['expires_in'])) { + if (!\is_numeric($options['expires_in'])) { + throw new \InvalidArgumentException('expires_in value must be an integer'); + } + $this->expires = $options['expires_in'] != 0 ? \time() + $options['expires_in'] : 0; + } elseif (!empty($options['expires'])) { + // Some providers supply the seconds until expiration rather than + // the exact timestamp. Take a best guess at which we received. + $expires = $options['expires']; + if (!$this->isExpirationTimestamp($expires)) { + $expires += \time(); + } + $this->expires = $expires; + } + // Capture any additional values that might exist in the token but are + // not part of the standard response. Vendors will sometimes pass + // additional user data this way. + $this->values = \array_diff_key($options, \array_flip(['access_token', 'resource_owner_id', 'refresh_token', 'expires_in', 'expires'])); + } + /** + * Check if a value is an expiration timestamp or second value. + * + * @param integer $value + * @return bool + */ + protected function isExpirationTimestamp($value) + { + // If the given value is larger than the original OAuth 2 draft date, + // assume that it is meant to be a (possible expired) timestamp. + $oauth2InceptionDate = 1349067600; + // 2012-10-01 + return $value > $oauth2InceptionDate; + } + /** + * @inheritdoc + */ + public function getToken() + { + return $this->accessToken; + } + /** + * @inheritdoc + */ + public function getRefreshToken() + { + return $this->refreshToken; + } + /** + * @inheritdoc + */ + public function getExpires() + { + return $this->expires; + } + /** + * @inheritdoc + */ + public function getResourceOwnerId() + { + return $this->resourceOwnerId; + } + /** + * @inheritdoc + */ + public function hasExpired() + { + $expires = $this->getExpires(); + if (empty($expires)) { + throw new \RuntimeException('"expires" is not set on the token'); + } + return $expires < \time(); + } + /** + * @inheritdoc + */ + public function getValues() + { + return $this->values; + } + /** + * @inheritdoc + */ + public function __toString() + { + return (string) $this->getToken(); + } + /** + * @inheritdoc + */ + public function jsonSerialize() + { + $parameters = $this->values; + if ($this->accessToken) { + $parameters['access_token'] = $this->accessToken; + } + if ($this->refreshToken) { + $parameters['refresh_token'] = $this->refreshToken; + } + if ($this->expires) { + $parameters['expires'] = $this->expires; + } + if ($this->resourceOwnerId) { + $parameters['resource_owner_id'] = $this->resourceOwnerId; + } + return $parameters; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Token/AccessTokenInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Token/AccessTokenInterface.php new file mode 100644 index 00000000..19f8fa2a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Token/AccessTokenInterface.php @@ -0,0 +1,65 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Token; + +use JsonSerializable; +use RuntimeException; +interface AccessTokenInterface extends \JsonSerializable +{ + /** + * Returns the access token string of this instance. + * + * @return string + */ + public function getToken(); + /** + * Returns the refresh token, if defined. + * + * @return string|null + */ + public function getRefreshToken(); + /** + * Returns the expiration timestamp, if defined. + * + * @return integer|null + */ + public function getExpires(); + /** + * Checks if this token has expired. + * + * @return boolean true if the token has expired, false otherwise. + * @throws RuntimeException if 'expires' is not set on the token. + */ + public function hasExpired(); + /** + * Returns additional vendor values stored in the token. + * + * @return array + */ + public function getValues(); + /** + * Returns a string representation of the access token + * + * @return string + */ + public function __toString(); + /** + * Returns an array of parameters to serialize when this is serialized with + * json_encode(). + * + * @return array + */ + public function jsonSerialize(); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php new file mode 100644 index 00000000..84ae8875 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.php @@ -0,0 +1,25 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Token; + +interface ResourceOwnerAccessTokenInterface extends \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface +{ + /** + * Returns the resource owner identifier, if defined. + * + * @return string|null + */ + public function getResourceOwnerId(); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/ArrayAccessorTrait.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/ArrayAccessorTrait.php new file mode 100644 index 00000000..8de856ff --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/ArrayAccessorTrait.php @@ -0,0 +1,47 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; + +/** + * Provides generic array navigation tools. + */ +trait ArrayAccessorTrait +{ + /** + * Returns a value by key using dot notation. + * + * @param array $data + * @param string $key + * @param mixed|null $default + * @return mixed + */ + private function getValueByKey(array $data, $key, $default = null) + { + if (!\is_string($key) || empty($key) || !\count($data)) { + return $default; + } + if (\strpos($key, '.') !== \false) { + $keys = \explode('.', $key); + foreach ($keys as $innerKey) { + if (!\is_array($data) || !\array_key_exists($innerKey, $data)) { + return $default; + } + $data = $data[$innerKey]; + } + return $data; + } + return \array_key_exists($key, $data) ? $data[$key] : $default; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php new file mode 100644 index 00000000..8fb7f76b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/BearerAuthorizationTrait.php @@ -0,0 +1,35 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; + +use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface; +/** + * Enables `Bearer` header authorization for providers. + * + * @link http://tools.ietf.org/html/rfc6750 Bearer Token Usage (RFC 6750) + */ +trait BearerAuthorizationTrait +{ + /** + * Returns authorization headers for the 'bearer' grant. + * + * @param AccessTokenInterface|string|null $token Either a string or an access token instance + * @return array + */ + protected function getAuthorizationHeaders($token = null) + { + return ['Authorization' => 'Bearer ' . $token]; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/GuardedPropertyTrait.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/GuardedPropertyTrait.php new file mode 100644 index 00000000..5de3b74c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/GuardedPropertyTrait.php @@ -0,0 +1,66 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; + +/** + * Provides support for blacklisting explicit properties from the + * mass assignment behavior. + */ +trait GuardedPropertyTrait +{ + /** + * The properties that aren't mass assignable. + * + * @var array + */ + protected $guarded = []; + /** + * Attempts to mass assign the given options to explicitly defined properties, + * skipping over any properties that are defined in the guarded array. + * + * @param array $options + * @return mixed + */ + protected function fillProperties(array $options = []) + { + if (isset($options['guarded'])) { + unset($options['guarded']); + } + foreach ($options as $option => $value) { + if (\property_exists($this, $option) && !$this->isGuarded($option)) { + $this->{$option} = $value; + } + } + } + /** + * Returns current guarded properties. + * + * @return array + */ + public function getGuarded() + { + return $this->guarded; + } + /** + * Determines if the given property is guarded. + * + * @param string $property + * @return bool + */ + public function isGuarded($property) + { + return \in_array($property, $this->getGuarded()); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/MacAuthorizationTrait.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/MacAuthorizationTrait.php new file mode 100644 index 00000000..a18a3156 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/MacAuthorizationTrait.php @@ -0,0 +1,76 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; + +use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken; +use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface; +/** + * Enables `MAC` header authorization for providers. + * + * @link http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-05 Message Authentication Code (MAC) Tokens + */ +trait MacAuthorizationTrait +{ + /** + * Returns the id of this token for MAC generation. + * + * @param AccessToken $token + * @return string + */ + protected abstract function getTokenId(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token); + /** + * Returns the MAC signature for the current request. + * + * @param string $id + * @param integer $ts + * @param string $nonce + * @return string + */ + protected abstract function getMacSignature($id, $ts, $nonce); + /** + * Returns a new random string to use as the state parameter in an + * authorization flow. + * + * @param int $length Length of the random string to be generated. + * @return string + */ + protected abstract function getRandomState($length = 32); + /** + * Returns the authorization headers for the 'mac' grant. + * + * @param AccessTokenInterface|string|null $token Either a string or an access token instance + * @return array + * @codeCoverageIgnore + * + * @todo This is currently untested and provided only as an example. If you + * complete the implementation, please create a pull request for + * https://github.com/thephpleague/oauth2-client + */ + protected function getAuthorizationHeaders($token = null) + { + if ($token === null) { + return []; + } + $ts = \time(); + $id = $this->getTokenId($token); + $nonce = $this->getRandomState(16); + $mac = $this->getMacSignature($id, $ts, $nonce); + $parts = []; + foreach (\compact('id', 'ts', 'nonce', 'mac') as $key => $value) { + $parts[] = \sprintf('%s="%s"', $key, $value); + } + return ['Authorization' => 'MAC ' . \implode(', ', $parts)]; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/ProviderRedirectTrait.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/ProviderRedirectTrait.php new file mode 100644 index 00000000..0888c971 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/ProviderRedirectTrait.php @@ -0,0 +1,105 @@ +redirectLimit) { + $attempts++; + $response = $this->getHttpClient()->send($request, ['allow_redirects' => \false]); + if ($this->isRedirect($response)) { + $redirectUrl = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($response->getHeader('Location')[0]); + $request = $request->withUri($redirectUrl); + } else { + break; + } + } + return $response; + } + /** + * Returns the HTTP client instance. + * + * @return GuzzleHttp\ClientInterface + */ + public abstract function getHttpClient(); + /** + * Retrieves current redirect limit. + * + * @return integer + */ + public function getRedirectLimit() + { + return $this->redirectLimit; + } + /** + * Determines if a given response is a redirect. + * + * @param ResponseInterface $response + * + * @return boolean + */ + protected function isRedirect(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) + { + $statusCode = $response->getStatusCode(); + return $statusCode > 300 && $statusCode < 400 && $response->hasHeader('Location'); + } + /** + * Sends a request instance and returns a response instance. + * + * WARNING: This method does not attempt to catch exceptions caused by HTTP + * errors! It is recommended to wrap this method in a try/catch block. + * + * @param RequestInterface $request + * @return ResponseInterface + */ + public function getResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) + { + try { + $response = $this->followRequestRedirects($request); + } catch (\YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException $e) { + $response = $e->getResponse(); + } + return $response; + } + /** + * Updates the redirect limit. + * + * @param integer $limit + * @return League\OAuth2\Client\Provider\AbstractProvider + * @throws InvalidArgumentException + */ + public function setRedirectLimit($limit) + { + if (!\is_int($limit)) { + throw new \InvalidArgumentException('redirectLimit must be an integer.'); + } + if ($limit < 1) { + throw new \InvalidArgumentException('redirectLimit must be greater than or equal to one.'); + } + $this->redirectLimit = $limit; + return $this; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/QueryBuilderTrait.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/QueryBuilderTrait.php new file mode 100644 index 00000000..5d27c31b --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/QueryBuilderTrait.php @@ -0,0 +1,33 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; + +/** + * Provides a standard way to generate query strings. + */ +trait QueryBuilderTrait +{ + /** + * Build a query string from an array. + * + * @param array $params + * + * @return string + */ + protected function buildQueryString(array $params) + { + return \http_build_query($params, null, '&', \PHP_QUERY_RFC3986); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/RequestFactory.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/RequestFactory.php new file mode 100644 index 00000000..efb7230c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/RequestFactory.php @@ -0,0 +1,67 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; + +use YoastSEO_Vendor\GuzzleHttp\Psr7\Request; +/** + * Used to produce PSR-7 Request instances. + * + * @link https://github.com/guzzle/guzzle/pull/1101 + */ +class RequestFactory +{ + /** + * Creates a PSR-7 Request instance. + * + * @param null|string $method HTTP method for the request. + * @param null|string $uri URI for the request. + * @param array $headers Headers for the message. + * @param string|resource|StreamInterface $body Message body. + * @param string $version HTTP protocol version. + * + * @return Request + */ + public function getRequest($method, $uri, array $headers = [], $body = null, $version = '1.1') + { + return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($method, $uri, $headers, $body, $version); + } + /** + * Parses simplified options. + * + * @param array $options Simplified options. + * + * @return array Extended options for use with getRequest. + */ + protected function parseOptions(array $options) + { + // Should match default values for getRequest + $defaults = ['headers' => [], 'body' => null, 'version' => '1.1']; + return \array_merge($defaults, $options); + } + /** + * Creates a request using a simplified array of options. + * + * @param null|string $method + * @param null|string $uri + * @param array $options + * + * @return Request + */ + public function getRequestWithOptions($method, $uri, array $options = []) + { + $options = $this->parseOptions($options); + return $this->getRequest($method, $uri, $options['headers'], $options['body'], $options['version']); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/RequiredParameterTrait.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/RequiredParameterTrait.php new file mode 100644 index 00000000..d5ba4258 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/league/oauth2-client/src/Tool/RequiredParameterTrait.php @@ -0,0 +1,51 @@ + + * @license http://opensource.org/licenses/MIT MIT + * @link http://thephpleague.com/oauth2-client/ Documentation + * @link https://packagist.org/packages/league/oauth2-client Packagist + * @link https://github.com/thephpleague/oauth2-client GitHub + */ +namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; + +use BadMethodCallException; +/** + * Provides functionality to check for required parameters. + */ +trait RequiredParameterTrait +{ + /** + * Checks for a required parameter in a hash. + * + * @throws BadMethodCallException + * @param string $name + * @param array $params + * @return void + */ + private function checkRequiredParameter($name, array $params) + { + if (!isset($params[$name])) { + throw new \BadMethodCallException(\sprintf('Required parameter not passed: "%s"', $name)); + } + } + /** + * Checks for multiple required parameters in a hash. + * + * @throws InvalidArgumentException + * @param array $names + * @param array $params + * @return void + */ + private function checkRequiredParameters(array $names, array $params) + { + foreach ($names as $name) { + $this->checkRequiredParameter($name, $params); + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/container/src/ContainerExceptionInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/container/src/ContainerExceptionInterface.php new file mode 100644 index 00000000..3b5fe22f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/container/src/ContainerExceptionInterface.php @@ -0,0 +1,13 @@ +getHeaders() as $name => $values) { + * echo $name . ": " . implode(", ", $values); + * } + * + * // Emit headers iteratively: + * foreach ($message->getHeaders() as $name => $values) { + * foreach ($values as $value) { + * header(sprintf('%s: %s', $name, $value), false); + * } + * } + * + * While header names are not case-sensitive, getHeaders() will preserve the + * exact case in which headers were originally specified. + * + * @return string[][] Returns an associative array of the message's headers. Each + * key MUST be a header name, and each value MUST be an array of strings + * for that header. + */ + public function getHeaders(); + /** + * Checks if a header exists by the given case-insensitive name. + * + * @param string $name Case-insensitive header field name. + * @return bool Returns true if any header names match the given header + * name using a case-insensitive string comparison. Returns false if + * no matching header name is found in the message. + */ + public function hasHeader($name); + /** + * Retrieves a message header value by the given case-insensitive name. + * + * This method returns an array of all the header values of the given + * case-insensitive header name. + * + * If the header does not appear in the message, this method MUST return an + * empty array. + * + * @param string $name Case-insensitive header field name. + * @return string[] An array of string values as provided for the given + * header. If the header does not appear in the message, this method MUST + * return an empty array. + */ + public function getHeader($name); + /** + * Retrieves a comma-separated string of the values for a single header. + * + * This method returns all of the header values of the given + * case-insensitive header name as a string concatenated together using + * a comma. + * + * NOTE: Not all header values may be appropriately represented using + * comma concatenation. For such headers, use getHeader() instead + * and supply your own delimiter when concatenating. + * + * If the header does not appear in the message, this method MUST return + * an empty string. + * + * @param string $name Case-insensitive header field name. + * @return string A string of values as provided for the given header + * concatenated together using a comma. If the header does not appear in + * the message, this method MUST return an empty string. + */ + public function getHeaderLine($name); + /** + * Return an instance with the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new and/or updated header and value. + * + * @param string $name Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withHeader($name, $value); + /** + * Return an instance with the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new header and/or value. + * + * @param string $name Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withAddedHeader($name, $value); + /** + * Return an instance without the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the named header. + * + * @param string $name Case-insensitive header field name to remove. + * @return static + */ + public function withoutHeader($name); + /** + * Gets the body of the message. + * + * @return StreamInterface Returns the body as a stream. + */ + public function getBody(); + /** + * Return an instance with the specified message body. + * + * The body MUST be a StreamInterface object. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * new body stream. + * + * @param StreamInterface $body Body. + * @return static + * @throws \InvalidArgumentException When the body is not valid. + */ + public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/http-message/src/RequestInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/http-message/src/RequestInterface.php new file mode 100644 index 00000000..e91ae893 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/http-message/src/RequestInterface.php @@ -0,0 +1,124 @@ +getQuery()` + * or from the `QUERY_STRING` server param. + * + * @return array + */ + public function getQueryParams(); + /** + * Return an instance with the specified query string arguments. + * + * These values SHOULD remain immutable over the course of the incoming + * request. They MAY be injected during instantiation, such as from PHP's + * $_GET superglobal, or MAY be derived from some other value such as the + * URI. In cases where the arguments are parsed from the URI, the data + * MUST be compatible with what PHP's parse_str() would return for + * purposes of how duplicate query parameters are handled, and how nested + * sets are handled. + * + * Setting query string arguments MUST NOT change the URI stored by the + * request, nor the values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated query string arguments. + * + * @param array $query Array of query string arguments, typically from + * $_GET. + * @return static + */ + public function withQueryParams(array $query); + /** + * Retrieve normalized file upload data. + * + * This method returns upload metadata in a normalized tree, with each leaf + * an instance of Psr\Http\Message\UploadedFileInterface. + * + * These values MAY be prepared from $_FILES or the message body during + * instantiation, or MAY be injected via withUploadedFiles(). + * + * @return array An array tree of UploadedFileInterface instances; an empty + * array MUST be returned if no data is present. + */ + public function getUploadedFiles(); + /** + * Create a new instance with the specified uploaded files. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param array $uploadedFiles An array tree of UploadedFileInterface instances. + * @return static + * @throws \InvalidArgumentException if an invalid structure is provided. + */ + public function withUploadedFiles(array $uploadedFiles); + /** + * Retrieve any parameters provided in the request body. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, this method MUST + * return the contents of $_POST. + * + * Otherwise, this method may return any results of deserializing + * the request body content; as parsing returns structured content, the + * potential types MUST be arrays or objects only. A null value indicates + * the absence of body content. + * + * @return null|array|object The deserialized body parameters, if any. + * These will typically be an array or object. + */ + public function getParsedBody(); + /** + * Return an instance with the specified body parameters. + * + * These MAY be injected during instantiation. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, use this method + * ONLY to inject the contents of $_POST. + * + * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of + * deserializing the request body content. Deserialization/parsing returns + * structured data, and, as such, this method ONLY accepts arrays or objects, + * or a null value if nothing was available to parse. + * + * As an example, if content negotiation determines that the request data + * is a JSON payload, this method could be used to create a request + * instance with the deserialized parameters. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param null|array|object $data The deserialized body data. This will + * typically be in an array or object. + * @return static + * @throws \InvalidArgumentException if an unsupported argument type is + * provided. + */ + public function withParsedBody($data); + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + * + * @return array Attributes derived from the request. + */ + public function getAttributes(); + /** + * Retrieve a single derived request attribute. + * + * Retrieves a single derived request attribute as described in + * getAttributes(). If the attribute has not been previously set, returns + * the default value as provided. + * + * This method obviates the need for a hasAttribute() method, as it allows + * specifying a default value to return if the attribute is not found. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $default Default value to return if the attribute does not exist. + * @return mixed + */ + public function getAttribute($name, $default = null); + /** + * Return an instance with the specified derived request attribute. + * + * This method allows setting a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $value The value of the attribute. + * @return static + */ + public function withAttribute($name, $value); + /** + * Return an instance that removes the specified derived request attribute. + * + * This method allows removing a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @return static + */ + public function withoutAttribute($name); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/http-message/src/StreamInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/http-message/src/StreamInterface.php new file mode 100644 index 00000000..a973dc3f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/http-message/src/StreamInterface.php @@ -0,0 +1,144 @@ + + * [user-info@]host[:port] + * + * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + * @return string The URI authority, in "[user-info@]host[:port]" format. + */ + public function getAuthority(); + /** + * Retrieve the user information component of the URI. + * + * If no user information is present, this method MUST return an empty + * string. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + * + * @return string The URI user information, in "username[:password]" format. + */ + public function getUserInfo(); + /** + * Retrieve the host component of the URI. + * + * If no host is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + * @return string The URI host. + */ + public function getHost(); + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + * + * @return null|int The URI port. + */ + public function getPort(); + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + * @return string The URI path. + */ + public function getPath(); + /** + * Retrieve the query string of the URI. + * + * If no query string is present, this method MUST return an empty string. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + * @return string The URI query string. + */ + public function getQuery(); + /** + * Retrieve the fragment component of the URI. + * + * If no fragment is present, this method MUST return an empty string. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + * @return string The URI fragment. + */ + public function getFragment(); + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * Implementations MUST support the schemes "http" and "https" case + * insensitively, and MAY accommodate other schemes if required. + * + * An empty scheme is equivalent to removing the scheme. + * + * @param string $scheme The scheme to use with the new instance. + * @return static A new instance with the specified scheme. + * @throws \InvalidArgumentException for invalid or unsupported schemes. + */ + public function withScheme($scheme); + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; an empty string for the user is equivalent to removing user + * information. + * + * @param string $user The user name to use for authority. + * @param null|string $password The password associated with $user. + * @return static A new instance with the specified user information. + */ + public function withUserInfo($user, $password = null); + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * An empty host value is equivalent to removing the host. + * + * @param string $host The hostname to use with the new instance. + * @return static A new instance with the specified host. + * @throws \InvalidArgumentException for invalid hostnames. + */ + public function withHost($host); + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * Implementations MUST raise an exception for ports outside the + * established TCP and UDP port ranges. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param null|int $port The port to use with the new instance; a null value + * removes the port information. + * @return static A new instance with the specified port. + * @throws \InvalidArgumentException for invalid ports. + */ + public function withPort($port); + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * If the path is intended to be domain-relative rather than path relative then + * it must begin with a slash ("/"). Paths not starting with a slash ("/") + * are assumed to be relative to some base path known to the application or + * consumer. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @param string $path The path to use with the new instance. + * @return static A new instance with the specified path. + * @throws \InvalidArgumentException for invalid paths. + */ + public function withPath($path); + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * An empty query string value is equivalent to removing the query string. + * + * @param string $query The query string to use with the new instance. + * @return static A new instance with the specified query string. + * @throws \InvalidArgumentException for invalid query strings. + */ + public function withQuery($query); + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * An empty fragment value is equivalent to removing the fragment. + * + * @param string $fragment The fragment to use with the new instance. + * @return static A new instance with the specified fragment. + */ + public function withFragment($fragment); + /** + * Return the string representation as a URI reference. + * + * Depending on which components of the URI are present, the resulting + * string is either a full URI or relative reference according to RFC 3986, + * Section 4.1. The method concatenates the various components of the URI, + * using the appropriate delimiters: + * + * - If a scheme is present, it MUST be suffixed by ":". + * - If an authority is present, it MUST be prefixed by "//". + * - The path can be concatenated without delimiters. But there are two + * cases where the path has to be adjusted to make the URI reference + * valid as PHP does not allow to throw an exception in __toString(): + * - If the path is rootless and an authority is present, the path MUST + * be prefixed by "/". + * - If the path is starting with more than one "/" and no authority is + * present, the starting slashes MUST be reduced to one. + * - If a query is present, it MUST be prefixed by "?". + * - If a fragment is present, it MUST be prefixed by "#". + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @return string + */ + public function __toString(); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/AbstractLogger.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/AbstractLogger.php new file mode 100644 index 00000000..6f8708fb --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/AbstractLogger.php @@ -0,0 +1,121 @@ +log(\YoastSEO_Vendor\Psr\Log\LogLevel::EMERGENCY, $message, $context); + } + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function alert($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ALERT, $message, $context); + } + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function critical($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::CRITICAL, $message, $context); + } + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function error($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ERROR, $message, $context); + } + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function warning($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::WARNING, $message, $context); + } + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function notice($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::NOTICE, $message, $context); + } + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function info($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::INFO, $message, $context); + } + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function debug($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::DEBUG, $message, $context); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/InvalidArgumentException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/InvalidArgumentException.php new file mode 100644 index 00000000..86a78ec6 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/InvalidArgumentException.php @@ -0,0 +1,7 @@ +logger = $logger; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/LoggerInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/LoggerInterface.php new file mode 100644 index 00000000..d1862e43 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/LoggerInterface.php @@ -0,0 +1,115 @@ +log(\YoastSEO_Vendor\Psr\Log\LogLevel::EMERGENCY, $message, $context); + } + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function alert($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ALERT, $message, $context); + } + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function critical($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::CRITICAL, $message, $context); + } + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function error($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ERROR, $message, $context); + } + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function warning($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::WARNING, $message, $context); + } + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function notice($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::NOTICE, $message, $context); + } + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function info($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::INFO, $message, $context); + } + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function debug($message, array $context = array()) + { + $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::DEBUG, $message, $context); + } + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * + * @return void + */ + public abstract function log($level, $message, array $context = array()); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/NullLogger.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/NullLogger.php new file mode 100644 index 00000000..5e87aa6c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/psr/log/Psr/Log/NullLogger.php @@ -0,0 +1,28 @@ +logger) { }` + * blocks. + */ +class NullLogger extends \YoastSEO_Vendor\Psr\Log\AbstractLogger +{ + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * + * @return void + */ + public function log($level, $message, array $context = array()) + { + // noop + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Argument/RewindableGenerator.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Argument/RewindableGenerator.php new file mode 100644 index 00000000..5d7d7bd7 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Argument/RewindableGenerator.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Argument; + +/** + * @internal + */ +class RewindableGenerator implements \IteratorAggregate, \Countable +{ + private $generator; + private $count; + /** + * @param int|callable $count + */ + public function __construct(callable $generator, $count) + { + $this->generator = $generator; + $this->count = $count; + } + public function getIterator() + { + $g = $this->generator; + return $g(); + } + public function count() + { + if (\is_callable($count = $this->count)) { + $this->count = $count(); + } + return $this->count; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Container.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Container.php new file mode 100644 index 00000000..e0ff052a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Container.php @@ -0,0 +1,465 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection; + +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; +/** + * Container is a dependency injection container. + * + * It gives access to object instances (services). + * Services and parameters are simple key/pair stores. + * The container can have four possible behaviors when a service + * does not exist (or is not initialized for the last case): + * + * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) + * * NULL_ON_INVALID_REFERENCE: Returns null + * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference + * (for instance, ignore a setter if the service does not exist) + * * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references + * + * @author Fabien Potencier + * @author Johannes M. Schmitt + */ +class Container implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ResettableContainerInterface +{ + protected $parameterBag; + protected $services = []; + protected $fileMap = []; + protected $methodMap = []; + protected $aliases = []; + protected $loading = []; + protected $resolving = []; + protected $syntheticIds = []; + /** + * @internal + */ + protected $privates = []; + /** + * @internal + */ + protected $normalizedIds = []; + private $underscoreMap = ['_' => '', '.' => '_', '\\' => '_']; + private $envCache = []; + private $compiled = \false; + private $getEnv; + public function __construct(\YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface $parameterBag = null) + { + $this->parameterBag = $parameterBag ?: new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag(); + } + /** + * Compiles the container. + * + * This method does two things: + * + * * Parameter values are resolved; + * * The parameter bag is frozen. + */ + public function compile() + { + $this->parameterBag->resolve(); + $this->parameterBag = new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag($this->parameterBag->all()); + $this->compiled = \true; + } + /** + * Returns true if the container is compiled. + * + * @return bool + */ + public function isCompiled() + { + return $this->compiled; + } + /** + * Returns true if the container parameter bag are frozen. + * + * @deprecated since version 3.3, to be removed in 4.0. + * + * @return bool true if the container parameter bag are frozen, false otherwise + */ + public function isFrozen() + { + @\trigger_error(\sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), \E_USER_DEPRECATED); + return $this->parameterBag instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; + } + /** + * Gets the service container parameter bag. + * + * @return ParameterBagInterface A ParameterBagInterface instance + */ + public function getParameterBag() + { + return $this->parameterBag; + } + /** + * Gets a parameter. + * + * @param string $name The parameter name + * + * @return mixed The parameter value + * + * @throws InvalidArgumentException if the parameter is not defined + */ + public function getParameter($name) + { + return $this->parameterBag->get($name); + } + /** + * Checks if a parameter exists. + * + * @param string $name The parameter name + * + * @return bool The presence of parameter in container + */ + public function hasParameter($name) + { + return $this->parameterBag->has($name); + } + /** + * Sets a parameter. + * + * @param string $name The parameter name + * @param mixed $value The parameter value + */ + public function setParameter($name, $value) + { + $this->parameterBag->set($name, $value); + } + /** + * Sets a service. + * + * Setting a synthetic service to null resets it: has() returns false and get() + * behaves in the same way as if the service was never created. + * + * @param string $id The service identifier + * @param object|null $service The service instance + */ + public function set($id, $service) + { + // Runs the internal initializer; used by the dumped container to include always-needed files + if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) { + $initialize = $this->privates['service_container']; + unset($this->privates['service_container']); + $initialize(); + } + $id = $this->normalizeId($id); + if ('service_container' === $id) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException('You cannot set service "service_container".'); + } + if (isset($this->privates[$id]) || !(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) { + if (!isset($this->privates[$id]) && !isset($this->getRemovedIds()[$id])) { + // no-op + } elseif (null === $service) { + @\trigger_error(\sprintf('The "%s" service is private, unsetting it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED); + unset($this->privates[$id]); + } else { + @\trigger_error(\sprintf('The "%s" service is private, replacing it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED); + } + } elseif (isset($this->services[$id])) { + if (null === $service) { + @\trigger_error(\sprintf('The "%s" service is already initialized, unsetting it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), \E_USER_DEPRECATED); + } else { + @\trigger_error(\sprintf('The "%s" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), \E_USER_DEPRECATED); + } + } + if (isset($this->aliases[$id])) { + unset($this->aliases[$id]); + } + if (null === $service) { + unset($this->services[$id]); + return; + } + $this->services[$id] = $service; + } + /** + * Returns true if the given service is defined. + * + * @param string $id The service identifier + * + * @return bool true if the service is defined, false otherwise + */ + public function has($id) + { + for ($i = 2;;) { + if (isset($this->privates[$id])) { + @\trigger_error(\sprintf('The "%s" service is private, checking for its existence is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED); + } + if (isset($this->aliases[$id])) { + $id = $this->aliases[$id]; + } + if (isset($this->services[$id])) { + return \true; + } + if ('service_container' === $id) { + return \true; + } + if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) { + return \true; + } + if (--$i && $id !== ($normalizedId = $this->normalizeId($id))) { + $id = $normalizedId; + continue; + } + // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, + // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) + if (!$this->methodMap && !$this instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerBuilder && __CLASS__ !== static::class && \method_exists($this, 'get' . \strtr($id, $this->underscoreMap) . 'Service')) { + @\trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED); + return \true; + } + return \false; + } + } + /** + * Gets a service. + * + * If a service is defined both through a set() method and + * with a get{$id}Service() method, the former has always precedence. + * + * @param string $id The service identifier + * @param int $invalidBehavior The behavior when the service does not exist + * + * @return object|null The associated service + * + * @throws ServiceCircularReferenceException When a circular reference is detected + * @throws ServiceNotFoundException When the service is not defined + * @throws \Exception if an exception has been thrown when the service has been resolved + * + * @see Reference + */ + public function get($id, $invalidBehavior = 1) + { + // Attempt to retrieve the service by checking first aliases then + // available services. Service IDs are case insensitive, however since + // this method can be called thousands of times during a request, avoid + // calling $this->normalizeId($id) unless necessary. + for ($i = 2;;) { + if (isset($this->privates[$id])) { + @\trigger_error(\sprintf('The "%s" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.', $id), \E_USER_DEPRECATED); + } + if (isset($this->aliases[$id])) { + $id = $this->aliases[$id]; + } + // Re-use shared service instance if it exists. + if (isset($this->services[$id])) { + return $this->services[$id]; + } + if ('service_container' === $id) { + return $this; + } + if (isset($this->loading[$id])) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException($id, \array_merge(\array_keys($this->loading), [$id])); + } + $this->loading[$id] = \true; + try { + if (isset($this->fileMap[$id])) { + return 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]); + } elseif (isset($this->methodMap[$id])) { + return 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}(); + } elseif (--$i && $id !== ($normalizedId = $this->normalizeId($id))) { + unset($this->loading[$id]); + $id = $normalizedId; + continue; + } elseif (!$this->methodMap && !$this instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerBuilder && __CLASS__ !== static::class && \method_exists($this, $method = 'get' . \strtr($id, $this->underscoreMap) . 'Service')) { + // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, + // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) + @\trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED); + return 4 === $invalidBehavior ? null : $this->{$method}(); + } + break; + } catch (\Exception $e) { + unset($this->services[$id]); + throw $e; + } finally { + unset($this->loading[$id]); + } + } + if (1 === $invalidBehavior) { + if (!$id) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id); + } + if (isset($this->syntheticIds[$id])) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id, null, null, [], \sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id)); + } + if (isset($this->getRemovedIds()[$id])) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id, null, null, [], \sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.', $id)); + } + $alternatives = []; + foreach ($this->getServiceIds() as $knownId) { + $lev = \levenshtein($id, $knownId); + if ($lev <= \strlen($id) / 3 || \false !== \strpos($knownId, $id)) { + $alternatives[] = $knownId; + } + } + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id, null, null, $alternatives); + } + } + /** + * Returns true if the given service has actually been initialized. + * + * @param string $id The service identifier + * + * @return bool true if service has already been initialized, false otherwise + */ + public function initialized($id) + { + $id = $this->normalizeId($id); + if (isset($this->privates[$id])) { + @\trigger_error(\sprintf('Checking for the initialization of the "%s" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.', $id), \E_USER_DEPRECATED); + } + if (isset($this->aliases[$id])) { + $id = $this->aliases[$id]; + } + if ('service_container' === $id) { + return \false; + } + return isset($this->services[$id]); + } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->services = []; + } + /** + * Gets all service ids. + * + * @return string[] An array of all defined service ids + */ + public function getServiceIds() + { + $ids = []; + if (!$this->methodMap && !$this instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerBuilder && __CLASS__ !== static::class) { + // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, + // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) + @\trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED); + foreach (\get_class_methods($this) as $method) { + if (\preg_match('/^get(.+)Service$/', $method, $match)) { + $ids[] = self::underscore($match[1]); + } + } + } + $ids[] = 'service_container'; + return \array_map('strval', \array_unique(\array_merge($ids, \array_keys($this->methodMap), \array_keys($this->fileMap), \array_keys($this->aliases), \array_keys($this->services)))); + } + /** + * Gets service ids that existed at compile time. + * + * @return array + */ + public function getRemovedIds() + { + return []; + } + /** + * Camelizes a string. + * + * @param string $id A string to camelize + * + * @return string The camelized string + */ + public static function camelize($id) + { + return \strtr(\ucwords(\strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']); + } + /** + * A string to underscore. + * + * @param string $id The string to underscore + * + * @return string The underscored string + */ + public static function underscore($id) + { + return \strtolower(\preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], \str_replace('_', '.', $id))); + } + /** + * Creates a service by requiring its factory file. + */ + protected function load($file) + { + return require $file; + } + /** + * Fetches a variable from the environment. + * + * @param string $name The name of the environment variable + * + * @return mixed The value to use for the provided environment variable name + * + * @throws EnvNotFoundException When the environment variable is not found and has no default value + */ + protected function getEnv($name) + { + if (isset($this->resolving[$envName = "env({$name})"])) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException(\array_keys($this->resolving)); + } + if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) { + return $this->envCache[$name]; + } + if (!$this->has($id = 'container.env_var_processors_locator')) { + $this->set($id, new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ServiceLocator([])); + } + if (!$this->getEnv) { + $this->getEnv = new \ReflectionMethod($this, __FUNCTION__); + $this->getEnv->setAccessible(\true); + $this->getEnv = $this->getEnv->getClosure($this); + } + $processors = $this->get($id); + if (\false !== ($i = \strpos($name, ':'))) { + $prefix = \substr($name, 0, $i); + $localName = \substr($name, 1 + $i); + } else { + $prefix = 'string'; + $localName = $name; + } + $processor = $processors->has($prefix) ? $processors->get($prefix) : new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\EnvVarProcessor($this); + $this->resolving[$envName] = \true; + try { + return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv); + } finally { + unset($this->resolving[$envName]); + } + } + /** + * Returns the case sensitive id used at registration time. + * + * @param string $id + * + * @return string + * + * @internal + */ + public function normalizeId($id) + { + if (!\is_string($id)) { + $id = (string) $id; + } + if (isset($this->normalizedIds[$normalizedId = \strtolower($id)])) { + $normalizedId = $this->normalizedIds[$normalizedId]; + if ($id !== $normalizedId) { + @\trigger_error(\sprintf('Service identifiers will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.3.', $id, $normalizedId), \E_USER_DEPRECATED); + } + } else { + $normalizedId = $this->normalizedIds[$normalizedId] = $id; + } + return $normalizedId; + } + private function __clone() + { + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ContainerInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ContainerInterface.php new file mode 100644 index 00000000..fc028a93 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ContainerInterface.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection; + +use YoastSEO_Vendor\Psr\Container\ContainerInterface as PsrContainerInterface; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +/** + * ContainerInterface is the interface implemented by service container classes. + * + * @author Fabien Potencier + * @author Johannes M. Schmitt + */ +interface ContainerInterface extends \YoastSEO_Vendor\Psr\Container\ContainerInterface +{ + const EXCEPTION_ON_INVALID_REFERENCE = 1; + const NULL_ON_INVALID_REFERENCE = 2; + const IGNORE_ON_INVALID_REFERENCE = 3; + const IGNORE_ON_UNINITIALIZED_REFERENCE = 4; + /** + * Sets a service. + * + * @param string $id The service identifier + * @param object|null $service The service instance + */ + public function set($id, $service); + /** + * Gets a service. + * + * @param string $id The service identifier + * @param int $invalidBehavior The behavior when the service does not exist + * + * @return object|null The associated service + * + * @throws ServiceCircularReferenceException When a circular reference is detected + * @throws ServiceNotFoundException When the service is not defined + * + * @see Reference + */ + public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE); + /** + * Returns true if the given service is defined. + * + * @param string $id The service identifier + * + * @return bool true if the service is defined, false otherwise + */ + public function has($id); + /** + * Check for whether or not a service has been initialized. + * + * @param string $id + * + * @return bool true if the service has been initialized, false otherwise + */ + public function initialized($id); + /** + * Gets a parameter. + * + * @param string $name The parameter name + * + * @return mixed The parameter value + * + * @throws InvalidArgumentException if the parameter is not defined + */ + public function getParameter($name); + /** + * Checks if a parameter exists. + * + * @param string $name The parameter name + * + * @return bool The presence of parameter in container + */ + public function hasParameter($name); + /** + * Sets a parameter. + * + * @param string $name The parameter name + * @param mixed $value The parameter value + */ + public function setParameter($name, $value); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/EnvNotFoundException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/EnvNotFoundException.php new file mode 100644 index 00000000..f453d9da --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/EnvNotFoundException.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; + +/** + * This exception is thrown when an environment variable is not found. + * + * @author Nicolas Grekas + */ +class EnvNotFoundException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException +{ + public function __construct($name) + { + parent::__construct(\sprintf('Environment variable not found: "%s".', $name)); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ExceptionInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ExceptionInterface.php new file mode 100644 index 00000000..3918357f --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ExceptionInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; + +use YoastSEO_Vendor\Psr\Container\ContainerExceptionInterface; +/** + * Base ExceptionInterface for Dependency Injection component. + * + * @author Fabien Potencier + * @author Bulat Shakirzyanov + */ +interface ExceptionInterface extends \YoastSEO_Vendor\Psr\Container\ContainerExceptionInterface +{ +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/InvalidArgumentException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/InvalidArgumentException.php new file mode 100644 index 00000000..9b32dd7a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/InvalidArgumentException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; + +/** + * Base InvalidArgumentException for Dependency Injection component. + * + * @author Bulat Shakirzyanov + */ +class InvalidArgumentException extends \InvalidArgumentException implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ExceptionInterface +{ +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/LogicException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/LogicException.php new file mode 100644 index 00000000..cec6f276 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/LogicException.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; + +/** + * Base LogicException for Dependency Injection component. + */ +class LogicException extends \LogicException implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ExceptionInterface +{ +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php new file mode 100644 index 00000000..eb166a7c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; + +/** + * This exception is thrown when a circular reference in a parameter is detected. + * + * @author Fabien Potencier + */ +class ParameterCircularReferenceException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException +{ + private $parameters; + public function __construct($parameters, \Exception $previous = null) + { + parent::__construct(\sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], \implode('" > "', $parameters), $parameters[0]), 0, $previous); + $this->parameters = $parameters; + } + public function getParameters() + { + return $this->parameters; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/RuntimeException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/RuntimeException.php new file mode 100644 index 00000000..f4ea1a6c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/RuntimeException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; + +/** + * Base RuntimeException for Dependency Injection component. + * + * @author Johannes M. Schmitt + */ +class RuntimeException extends \RuntimeException implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ExceptionInterface +{ +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php new file mode 100644 index 00000000..5aab8312 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; + +/** + * This exception is thrown when a circular reference is detected. + * + * @author Johannes M. Schmitt + */ +class ServiceCircularReferenceException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException +{ + private $serviceId; + private $path; + public function __construct($serviceId, array $path, \Exception $previous = null) + { + parent::__construct(\sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, \implode(' -> ', $path)), 0, $previous); + $this->serviceId = $serviceId; + $this->path = $path; + } + public function getServiceId() + { + return $this->serviceId; + } + public function getPath() + { + return $this->path; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ServiceNotFoundException.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ServiceNotFoundException.php new file mode 100644 index 00000000..77b7938a --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/Exception/ServiceNotFoundException.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; + +use YoastSEO_Vendor\Psr\Container\NotFoundExceptionInterface; +/** + * This exception is thrown when a non-existent service is requested. + * + * @author Johannes M. Schmitt + */ +class ServiceNotFoundException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException implements \YoastSEO_Vendor\Psr\Container\NotFoundExceptionInterface +{ + private $id; + private $sourceId; + private $alternatives; + public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = [], $msg = null) + { + if (null !== $msg) { + // no-op + } elseif (null === $sourceId) { + $msg = \sprintf('You have requested a non-existent service "%s".', $id); + } else { + $msg = \sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id); + } + if ($alternatives) { + if (1 == \count($alternatives)) { + $msg .= ' Did you mean this: "'; + } else { + $msg .= ' Did you mean one of these: "'; + } + $msg .= \implode('", "', $alternatives) . '"?'; + } + parent::__construct($msg, 0, $previous); + $this->id = $id; + $this->sourceId = $sourceId; + $this->alternatives = $alternatives; + } + public function getId() + { + return $this->id; + } + public function getSourceId() + { + return $this->sourceId; + } + public function getAlternatives() + { + return $this->alternatives; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php new file mode 100644 index 00000000..f9a4c669 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag; + +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException; +/** + * @author Nicolas Grekas + */ +class EnvPlaceholderParameterBag extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag +{ + private $envPlaceholders = []; + private $providedTypes = []; + /** + * {@inheritdoc} + */ + public function get($name) + { + if (0 === \strpos($name, 'env(') && ')' === \substr($name, -1) && 'env()' !== $name) { + $env = \substr($name, 4, -1); + if (isset($this->envPlaceholders[$env])) { + foreach ($this->envPlaceholders[$env] as $placeholder) { + return $placeholder; + // return first result + } + } + if (!\preg_match('/^(?:\\w++:)*+\\w++$/', $env)) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException(\sprintf('Invalid "%s" name: only "word" characters are allowed.', $name)); + } + if ($this->has($name)) { + $defaultValue = parent::get($name); + if (null !== $defaultValue && !\is_scalar($defaultValue)) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException(\sprintf('The default value of an env() parameter must be scalar or null, but "%s" given to "%s".', \gettype($defaultValue), $name)); + } + } + $uniqueName = \md5($name . \uniqid(\mt_rand(), \true)); + $placeholder = \sprintf('env_%s_%s', \str_replace(':', '_', $env), $uniqueName); + $this->envPlaceholders[$env][$placeholder] = $placeholder; + return $placeholder; + } + return parent::get($name); + } + /** + * Returns the map of env vars used in the resolved parameter values to their placeholders. + * + * @return string[][] A map of env var names to their placeholders + */ + public function getEnvPlaceholders() + { + return $this->envPlaceholders; + } + /** + * Merges the env placeholders of another EnvPlaceholderParameterBag. + */ + public function mergeEnvPlaceholders(self $bag) + { + if ($newPlaceholders = $bag->getEnvPlaceholders()) { + $this->envPlaceholders += $newPlaceholders; + foreach ($newPlaceholders as $env => $placeholders) { + $this->envPlaceholders[$env] += $placeholders; + } + } + } + /** + * Maps env prefixes to their corresponding PHP types. + */ + public function setProvidedTypes(array $providedTypes) + { + $this->providedTypes = $providedTypes; + } + /** + * Gets the PHP types corresponding to env() parameter prefixes. + * + * @return string[][] + */ + public function getProvidedTypes() + { + return $this->providedTypes; + } + /** + * {@inheritdoc} + */ + public function resolve() + { + if ($this->resolved) { + return; + } + parent::resolve(); + foreach ($this->envPlaceholders as $env => $placeholders) { + if (!$this->has($name = "env({$env})")) { + continue; + } + if (\is_numeric($default = $this->parameters[$name])) { + $this->parameters[$name] = (string) $default; + } elseif (null !== $default && !\is_scalar($default)) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException(\sprintf('The default value of env parameter "%s" must be scalar or null, "%s" given.', $env, \gettype($default))); + } + } + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php new file mode 100644 index 00000000..c2421c68 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/FrozenParameterBag.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag; + +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException; +/** + * Holds read-only parameters. + * + * @author Fabien Potencier + */ +class FrozenParameterBag extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag +{ + /** + * For performance reasons, the constructor assumes that + * all keys are already lowercased. + * + * This is always the case when used internally. + * + * @param array $parameters An array of parameters + */ + public function __construct(array $parameters = []) + { + $this->parameters = $parameters; + $this->resolved = \true; + } + /** + * {@inheritdoc} + */ + public function clear() + { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call clear() on a frozen ParameterBag.'); + } + /** + * {@inheritdoc} + */ + public function add(array $parameters) + { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call add() on a frozen ParameterBag.'); + } + /** + * {@inheritdoc} + */ + public function set($name, $value) + { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + /** + * {@inheritdoc} + */ + public function remove($name) + { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call remove() on a frozen ParameterBag.'); + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBag.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBag.php new file mode 100644 index 00000000..c7f8b712 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBag.php @@ -0,0 +1,263 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag; + +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException; +/** + * Holds parameters. + * + * @author Fabien Potencier + */ +class ParameterBag implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface +{ + protected $parameters = []; + protected $resolved = \false; + private $normalizedNames = []; + /** + * @param array $parameters An array of parameters + */ + public function __construct(array $parameters = []) + { + $this->add($parameters); + } + /** + * Clears all parameters. + */ + public function clear() + { + $this->parameters = []; + } + /** + * Adds parameters to the service container parameters. + * + * @param array $parameters An array of parameters + */ + public function add(array $parameters) + { + foreach ($parameters as $key => $value) { + $this->set($key, $value); + } + } + /** + * {@inheritdoc} + */ + public function all() + { + return $this->parameters; + } + /** + * {@inheritdoc} + */ + public function get($name) + { + $name = $this->normalizeName($name); + if (!\array_key_exists($name, $this->parameters)) { + if (!$name) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException($name); + } + $alternatives = []; + foreach ($this->parameters as $key => $parameterValue) { + $lev = \levenshtein($name, $key); + if ($lev <= \strlen($name) / 3 || \false !== \strpos($key, $name)) { + $alternatives[] = $key; + } + } + $nonNestedAlternative = null; + if (!\count($alternatives) && \false !== \strpos($name, '.')) { + $namePartsLength = \array_map('strlen', \explode('.', $name)); + $key = \substr($name, 0, -1 * (1 + \array_pop($namePartsLength))); + while (\count($namePartsLength)) { + if ($this->has($key)) { + if (\is_array($this->get($key))) { + $nonNestedAlternative = $key; + } + break; + } + $key = \substr($key, 0, -1 * (1 + \array_pop($namePartsLength))); + } + } + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative); + } + return $this->parameters[$name]; + } + /** + * Sets a service container parameter. + * + * @param string $name The parameter name + * @param mixed $value The parameter value + */ + public function set($name, $value) + { + $this->parameters[$this->normalizeName($name)] = $value; + } + /** + * {@inheritdoc} + */ + public function has($name) + { + return \array_key_exists($this->normalizeName($name), $this->parameters); + } + /** + * Removes a parameter. + * + * @param string $name The parameter name + */ + public function remove($name) + { + unset($this->parameters[$this->normalizeName($name)]); + } + /** + * {@inheritdoc} + */ + public function resolve() + { + if ($this->resolved) { + return; + } + $parameters = []; + foreach ($this->parameters as $key => $value) { + try { + $value = $this->resolveValue($value); + $parameters[$key] = $this->unescapeValue($value); + } catch (\YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException $e) { + $e->setSourceKey($key); + throw $e; + } + } + $this->parameters = $parameters; + $this->resolved = \true; + } + /** + * Replaces parameter placeholders (%name%) by their values. + * + * @param mixed $value A value + * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) + * + * @return mixed The resolved value + * + * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist + * @throws ParameterCircularReferenceException if a circular reference if detected + * @throws RuntimeException when a given parameter has a type problem + */ + public function resolveValue($value, array $resolving = []) + { + if (\is_array($value)) { + $args = []; + foreach ($value as $k => $v) { + $args[\is_string($k) ? $this->resolveValue($k, $resolving) : $k] = $this->resolveValue($v, $resolving); + } + return $args; + } + if (!\is_string($value) || 2 > \strlen($value)) { + return $value; + } + return $this->resolveString($value, $resolving); + } + /** + * Resolves parameters inside a string. + * + * @param string $value The string to resolve + * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) + * + * @return mixed The resolved string + * + * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist + * @throws ParameterCircularReferenceException if a circular reference if detected + * @throws RuntimeException when a given parameter has a type problem + */ + public function resolveString($value, array $resolving = []) + { + // we do this to deal with non string values (Boolean, integer, ...) + // as the preg_replace_callback throw an exception when trying + // a non-string in a parameter value + if (\preg_match('/^%([^%\\s]+)%$/', $value, $match)) { + $key = $match[1]; + $lcKey = \strtolower($key); + // strtolower() to be removed in 4.0 + if (isset($resolving[$lcKey])) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException(\array_keys($resolving)); + } + $resolving[$lcKey] = \true; + return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving); + } + return \preg_replace_callback('/%%|%([^%\\s]+)%/', function ($match) use($resolving, $value) { + // skip %% + if (!isset($match[1])) { + return '%%'; + } + $key = $match[1]; + $lcKey = \strtolower($key); + // strtolower() to be removed in 4.0 + if (isset($resolving[$lcKey])) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException(\array_keys($resolving)); + } + $resolved = $this->get($key); + if (!\is_string($resolved) && !\is_numeric($resolved)) { + throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException(\sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type "%s" inside string value "%s".', $key, \gettype($resolved), $value)); + } + $resolved = (string) $resolved; + $resolving[$lcKey] = \true; + return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving); + }, $value); + } + public function isResolved() + { + return $this->resolved; + } + /** + * {@inheritdoc} + */ + public function escapeValue($value) + { + if (\is_string($value)) { + return \str_replace('%', '%%', $value); + } + if (\is_array($value)) { + $result = []; + foreach ($value as $k => $v) { + $result[$k] = $this->escapeValue($v); + } + return $result; + } + return $value; + } + /** + * {@inheritdoc} + */ + public function unescapeValue($value) + { + if (\is_string($value)) { + return \str_replace('%%', '%', $value); + } + if (\is_array($value)) { + $result = []; + foreach ($value as $k => $v) { + $result[$k] = $this->unescapeValue($v); + } + return $result; + } + return $value; + } + private function normalizeName($name) + { + if (isset($this->normalizedNames[$normalizedName = \strtolower($name)])) { + $normalizedName = $this->normalizedNames[$normalizedName]; + if ((string) $name !== $normalizedName) { + @\trigger_error(\sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.4.', $name, $normalizedName), \E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedNames[$normalizedName] = (string) $name; + } + return $normalizedName; + } +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php new file mode 100644 index 00000000..60a0d98c --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ParameterBag/ParameterBagInterface.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag; + +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException; +use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; +/** + * ParameterBagInterface. + * + * @author Fabien Potencier + */ +interface ParameterBagInterface +{ + /** + * Clears all parameters. + * + * @throws LogicException if the ParameterBagInterface can not be cleared + */ + public function clear(); + /** + * Adds parameters to the service container parameters. + * + * @param array $parameters An array of parameters + * + * @throws LogicException if the parameter can not be added + */ + public function add(array $parameters); + /** + * Gets the service container parameters. + * + * @return array An array of parameters + */ + public function all(); + /** + * Gets a service container parameter. + * + * @param string $name The parameter name + * + * @return mixed The parameter value + * + * @throws ParameterNotFoundException if the parameter is not defined + */ + public function get($name); + /** + * Removes a parameter. + * + * @param string $name The parameter name + */ + public function remove($name); + /** + * Sets a service container parameter. + * + * @param string $name The parameter name + * @param mixed $value The parameter value + * + * @throws LogicException if the parameter can not be set + */ + public function set($name, $value); + /** + * Returns true if a parameter name is defined. + * + * @param string $name The parameter name + * + * @return bool true if the parameter name is defined, false otherwise + */ + public function has($name); + /** + * Replaces parameter placeholders (%name%) by their values for all parameters. + */ + public function resolve(); + /** + * Replaces parameter placeholders (%name%) by their values. + * + * @param mixed $value A value + * + * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist + */ + public function resolveValue($value); + /** + * Escape parameter placeholders %. + * + * @param mixed $value + * + * @return mixed + */ + public function escapeValue($value); + /** + * Unescape parameter placeholders %. + * + * @param mixed $value + * + * @return mixed + */ + public function unescapeValue($value); +} diff --git a/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ResettableContainerInterface.php b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ResettableContainerInterface.php new file mode 100644 index 00000000..44674925 --- /dev/null +++ b/wp-content/plugins/wordpress-seo/vendor_prefixed/symfony/dependency-injection/ResettableContainerInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection; + +/** + * ResettableContainerInterface defines additional resetting functionality + * for containers, allowing to release shared services when the container is + * not needed anymore. + * + * @author Christophe Coevoet + */ +interface ResettableContainerInterface extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface +{ + /** + * Resets shared services from the container. + * + * The container is not intended to be used again after being reset in a normal workflow. This method is + * meant as a way to release references for ref-counting. + * A subsequent call to ContainerInterface::get will recreate a new instance of the shared service. + */ + public function reset(); +} diff --git a/wp-content/plugins/wordpress-seo/wp-seo-main.php b/wp-content/plugins/wordpress-seo/wp-seo-main.php index e6acc146..47a22bb6 100644 --- a/wp-content/plugins/wordpress-seo/wp-seo-main.php +++ b/wp-content/plugins/wordpress-seo/wp-seo-main.php @@ -5,6 +5,8 @@ * @package WPSEO\Main */ +use Composer\Autoload\ClassLoader; + if ( ! function_exists( 'add_filter' ) ) { header( 'Status: 403 Forbidden' ); header( 'HTTP/1.1 403 Forbidden' ); @@ -15,7 +17,8 @@ if ( ! function_exists( 'add_filter' ) ) { * {@internal Nobody should be able to overrule the real version number as this can cause * serious issues with the options, so no if ( ! defined() ).}} */ -define( 'WPSEO_VERSION', '7.2' ); +define( 'WPSEO_VERSION', '17.2' ); + if ( ! defined( 'WPSEO_PATH' ) ) { define( 'WPSEO_PATH', plugin_dir_path( WPSEO_FILE ) ); @@ -25,10 +28,27 @@ if ( ! defined( 'WPSEO_BASENAME' ) ) { define( 'WPSEO_BASENAME', plugin_basename( WPSEO_FILE ) ); } +/* + * {@internal The prefix constants are used to build prefixed versions of dependencies. + * These should not be changed on run-time, thus missing the ! defined() check.}} + */ +define( 'YOAST_VENDOR_NS_PREFIX', 'YoastSEO_Vendor' ); +define( 'YOAST_VENDOR_DEFINE_PREFIX', 'YOASTSEO_VENDOR__' ); +define( 'YOAST_VENDOR_PREFIX_DIRECTORY', 'vendor_prefixed' ); + +define( 'YOAST_SEO_PHP_REQUIRED', '5.6' ); +define( 'YOAST_SEO_WP_TESTED', '5.8' ); +define( 'YOAST_SEO_WP_REQUIRED', '5.6' ); + +if ( ! defined( 'WPSEO_NAMESPACES' ) ) { + define( 'WPSEO_NAMESPACES', true ); +} + + /* ***************************** CLASS AUTOLOADING *************************** */ /** - * Auto load our class files + * Autoload our class files. * * @param string $class Class name. * @@ -38,11 +58,10 @@ function wpseo_auto_load( $class ) { static $classes = null; if ( $classes === null ) { - $classes = array( + $classes = [ 'wp_list_table' => ABSPATH . 'wp-admin/includes/class-wp-list-table.php', 'walker_category' => ABSPATH . 'wp-includes/category-template.php', - 'pclzip' => ABSPATH . 'wp-admin/includes/class-pclzip.php', - ); + ]; } $cn = strtolower( $class ); @@ -52,8 +71,10 @@ function wpseo_auto_load( $class ) { } } -if ( file_exists( WPSEO_PATH . 'vendor/autoload_52.php' ) ) { - require WPSEO_PATH . 'vendor/autoload_52.php'; +$yoast_autoload_file = WPSEO_PATH . 'vendor/autoload.php'; + +if ( is_readable( $yoast_autoload_file ) ) { + $yoast_autoloader = require $yoast_autoload_file; } elseif ( ! class_exists( 'WPSEO_Options' ) ) { // Still checking since might be site-level autoload R. add_action( 'admin_init', 'yoast_wpseo_missing_autoload', 1 ); @@ -64,21 +85,41 @@ elseif ( ! class_exists( 'WPSEO_Options' ) ) { // Still checking since might be if ( function_exists( 'spl_autoload_register' ) ) { spl_autoload_register( 'wpseo_auto_load' ); } +require_once WPSEO_PATH . 'src/functions.php'; /* ********************* DEFINES DEPENDING ON AUTOLOADED CODE ********************* */ /** - * Defaults to production, for safety + * Defaults to production, for safety. */ if ( ! defined( 'YOAST_ENVIRONMENT' ) ) { define( 'YOAST_ENVIRONMENT', 'production' ); } +if ( YOAST_ENVIRONMENT === 'development' && isset( $yoast_autoloader ) ) { + add_action( + 'plugins_loaded', + /** + * Reregisters the autoloader so that Yoast SEO is at the front. + * This prevents conflicts with the development versions of our addons. + * An anonymous function is used so we can use the autoloader variable. + * As this is only loaded in development removing this action is not a concern. + * + * @return void + */ + function() use ( $yoast_autoloader ) { + $yoast_autoloader->unregister(); + $yoast_autoloader->register( true ); + }, + 1 + ); +} + /** - * Only use minified assets when we are in a production environment + * Only use minified assets when we are in a production environment. */ if ( ! defined( 'WPSEO_CSSJS_SUFFIX' ) ) { - define( 'WPSEO_CSSJS_SUFFIX', ( 'development' !== YOAST_ENVIRONMENT ) ? '.min' : '' ); + define( 'WPSEO_CSSJS_SUFFIX', ( YOAST_ENVIRONMENT !== 'development' ) ? '.min' : '' ); } /* ***************************** PLUGIN (DE-)ACTIVATION *************************** */ @@ -93,7 +134,7 @@ function wpseo_activate( $networkwide = false ) { _wpseo_activate(); } else { - /* Multi-site network activation - activate the plugin for all blogs */ + /* Multi-site network activation - activate the plugin for all blogs. */ wpseo_network_activate_deactivate( true ); } } @@ -108,13 +149,13 @@ function wpseo_deactivate( $networkwide = false ) { _wpseo_deactivate(); } else { - /* Multi-site network activation - de-activate the plugin for all blogs */ + /* Multi-site network activation - de-activate the plugin for all blogs. */ wpseo_network_activate_deactivate( false ); } } /** - * Run network-wide (de-)activation of the plugin + * Run network-wide (de-)activation of the plugin. * * @param bool $activate True for plugin activation, false for de-activation. */ @@ -123,7 +164,7 @@ function wpseo_network_activate_deactivate( $activate = true ) { $network_blogs = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs WHERE site_id = %d", $wpdb->siteid ) ); - if ( is_array( $network_blogs ) && $network_blogs !== array() ) { + if ( is_array( $network_blogs ) && $network_blogs !== [] ) { foreach ( $network_blogs as $blog_id ) { switch_to_blog( $blog_id ); @@ -163,10 +204,20 @@ function _wpseo_activate() { delete_option( 'rewrite_rules' ); } else { - $wpseo_rewrite = new WPSEO_Rewrite(); - $wpseo_rewrite->schedule_flush(); + if ( WPSEO_Options::get( 'stripcategorybase' ) === true ) { + // Constructor has side effects so this registers all hooks. + $GLOBALS['wpseo_rewrite'] = new WPSEO_Rewrite(); + } + add_action( 'shutdown', 'flush_rewrite_rules' ); } + // Reset tracking to be disabled by default. + if ( ! YoastSEO()->helpers->product->is_premium() ) { + WPSEO_Options::set( 'tracking', false ); + } + + WPSEO_Options::set( 'indexing_reason', 'first_install' ); + do_action( 'wpseo_register_roles' ); WPSEO_Role_Manager_Factory::get()->add(); @@ -176,20 +227,13 @@ function _wpseo_activate() { // Clear cache so the changes are obvious. WPSEO_Utils::clear_cache(); - // Create the text link storage table. - $link_installer = new WPSEO_Link_Installer(); - $link_installer->install(); - - // Trigger reindex notification. - $notifier = new WPSEO_Link_Notifier(); - $notifier->manage_notification(); - // Schedule cronjob when it doesn't exists on activation. - $wpseo_onpage = new WPSEO_OnPage(); - $wpseo_onpage->activate_hooks(); + $wpseo_ryte = new WPSEO_Ryte(); + $wpseo_ryte->activate_hooks(); do_action( 'wpseo_activate' ); } + /** * On deactivation, flush the rewrite rules so XML sitemaps stop working. */ @@ -226,31 +270,34 @@ function _wpseo_deactivate() { * {@internal Unfortunately will fail if the plugin is in the must-use directory. * {@link https://core.trac.wordpress.org/ticket/24205} }} * - * @param int $blog_id Blog ID. + * @param int|WP_Site $blog_id Blog ID. */ function wpseo_on_activate_blog( $blog_id ) { if ( ! function_exists( 'is_plugin_active_for_network' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } - if ( is_plugin_active_for_network( plugin_basename( WPSEO_FILE ) ) ) { + if ( $blog_id instanceof WP_Site ) { + $blog_id = (int) $blog_id->blog_id; + } + + if ( is_plugin_active_for_network( WPSEO_BASENAME ) ) { switch_to_blog( $blog_id ); wpseo_activate( false ); restore_current_blog(); } } - /* ***************************** PLUGIN LOADING *************************** */ /** - * Load translations + * Load translations. */ function wpseo_load_textdomain() { $wpseo_path = str_replace( '\\', '/', WPSEO_PATH ); $mu_path = str_replace( '\\', '/', WPMU_PLUGIN_DIR ); - if ( false !== stripos( $wpseo_path, $mu_path ) ) { + if ( stripos( $wpseo_path, $mu_path ) !== false ) { load_muplugin_textdomain( 'wordpress-seo', dirname( WPSEO_BASENAME ) . '/languages/' ); } else { @@ -262,7 +309,7 @@ add_action( 'plugins_loaded', 'wpseo_load_textdomain' ); /** - * On plugins_loaded: load the minimum amount of essential files for this plugin + * On plugins_loaded: load the minimum amount of essential files for this plugin. */ function wpseo_init() { require_once WPSEO_PATH . 'inc/wpseo-functions.php'; @@ -273,6 +320,11 @@ function wpseo_init() { WPSEO_Meta::init(); if ( version_compare( WPSEO_Options::get( 'version', 1 ), WPSEO_VERSION, '<' ) ) { + if ( function_exists( 'opcache_reset' ) ) { + // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Prevent notices when opcache.restrict_api is set. + @opcache_reset(); + } + new WPSEO_Upgrade(); // Get a cleaned up version of the $options. } @@ -285,23 +337,23 @@ function wpseo_init() { $GLOBALS['wpseo_sitemaps'] = new WPSEO_Sitemaps(); } - if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) { + if ( ! wp_doing_ajax() ) { require_once WPSEO_PATH . 'inc/wpseo-non-ajax-functions.php'; } // Init it here because the filter must be present on the frontend as well or it won't work in the customizer. new WPSEO_Customizer(); - /* - * Initializes the link watcher for both the frontend and backend. - * Required to process scheduled items properly. - */ - $link_watcher = new WPSEO_Link_Watcher_Loader(); - $link_watcher->load(); + $integrations = []; + $integrations[] = new WPSEO_Slug_Change_Watcher(); + + foreach ( $integrations as $integration ) { + $integration->register_hooks(); + } // Loading Ryte integration. - $wpseo_onpage = new WPSEO_OnPage(); - $wpseo_onpage->register_hooks(); + $wpseo_ryte = new WPSEO_Ryte(); + $wpseo_ryte->register_hooks(); } /** @@ -317,54 +369,17 @@ function wpseo_init_rest_api() { $configuration_service = new WPSEO_Configuration_Service(); $configuration_service->initialize(); - $link_reindex_endpoint = new WPSEO_Link_Reindex_Post_Endpoint( new WPSEO_Link_Reindex_Post_Service() ); - $link_reindex_endpoint->register(); + $statistics_service = new WPSEO_Statistics_Service( new WPSEO_Statistics() ); - $statistics_service = new WPSEO_Statistics_Service( new WPSEO_Statistics() ); - $statistics_endpoint = new WPSEO_Endpoint_Statistics( $statistics_service ); - $statistics_endpoint->register(); + $endpoints = []; + $endpoints[] = new WPSEO_Endpoint_File_Size( new WPSEO_File_Size_Service() ); + $endpoints[] = new WPSEO_Endpoint_Statistics( $statistics_service ); - if ( WPSEO_OnPage::is_active() ) { - $ryte_endpoint_service = new WPSEO_Ryte_Service( new WPSEO_OnPage_Option() ); - $ryte_endpoint = new WPSEO_Endpoint_Ryte( $ryte_endpoint_service ); - $ryte_endpoint->register(); + foreach ( $endpoints as $endpoint ) { + $endpoint->register(); } } -/** - * Used to load the required files on the plugins_loaded hook, instead of immediately. - */ -function wpseo_frontend_init() { - add_action( 'init', 'initialize_wpseo_front' ); - - if ( WPSEO_Options::get( 'breadcrumbs-enable' ) === true ) { - /** - * If breadcrumbs are active (which they supposedly are if the users has enabled this settings, - * there's no reason to have bbPress breadcrumbs as well. - * - * {@internal The class itself is only loaded when the template tag is encountered - * via the template tag function in the wpseo-functions.php file.}} - */ - add_filter( 'bbp_get_breadcrumb', '__return_false' ); - } - - add_action( 'template_redirect', 'wpseo_frontend_head_init', 999 ); -} - -/** - * Instantiate the different social classes on the frontend - */ -function wpseo_frontend_head_init() { - if ( WPSEO_Options::get( 'twitter' ) === true ) { - add_action( 'wpseo_head', array( 'WPSEO_Twitter', 'get_instance' ), 40 ); - } - - if ( WPSEO_Options::get( 'opengraph' ) === true ) { - $GLOBALS['wpseo_og'] = new WPSEO_OpenGraph(); - } - -} - /** * Used to load the required files on the plugins_loaded hook, instead of immediately. */ @@ -372,6 +387,52 @@ function wpseo_admin_init() { new WPSEO_Admin_Init(); } +/** + * Initialize the WP-CLI integration. + * + * The WP-CLI integration needs PHP 5.3 support, which should be automatically + * enforced by the check for the WP_CLI constant. As WP-CLI itself only runs + * on PHP 5.3+, the constant should only be set when requirements are met. + */ +function wpseo_cli_init() { + if ( YoastSEO()->helpers->product->is_premium() ) { + WP_CLI::add_command( + 'yoast redirect list', + 'WPSEO_CLI_Redirect_List_Command', + [ 'before_invoke' => 'WPSEO_CLI_Premium_Requirement::enforce' ] + ); + + WP_CLI::add_command( + 'yoast redirect create', + 'WPSEO_CLI_Redirect_Create_Command', + [ 'before_invoke' => 'WPSEO_CLI_Premium_Requirement::enforce' ] + ); + + WP_CLI::add_command( + 'yoast redirect update', + 'WPSEO_CLI_Redirect_Update_Command', + [ 'before_invoke' => 'WPSEO_CLI_Premium_Requirement::enforce' ] + ); + + WP_CLI::add_command( + 'yoast redirect delete', + 'WPSEO_CLI_Redirect_Delete_Command', + [ 'before_invoke' => 'WPSEO_CLI_Premium_Requirement::enforce' ] + ); + + WP_CLI::add_command( + 'yoast redirect has', + 'WPSEO_CLI_Redirect_Has_Command', + [ 'before_invoke' => 'WPSEO_CLI_Premium_Requirement::enforce' ] + ); + + WP_CLI::add_command( + 'yoast redirect follow', + 'WPSEO_CLI_Redirect_Follow_Command', + [ 'before_invoke' => 'WPSEO_CLI_Premium_Requirement::enforce' ] + ); + } +} /* ***************************** BOOTSTRAP / HOOK INTO WP *************************** */ $spl_autoload_exists = function_exists( 'spl_autoload_register' ); @@ -391,9 +452,12 @@ if ( ! wp_installing() && ( $spl_autoload_exists && $filter_exists ) ) { if ( is_admin() ) { - new Yoast_Alerts(); + new Yoast_Notifications(); - if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { + $yoast_addon_manager = new WPSEO_Addon_Manager(); + $yoast_addon_manager->register_hooks(); + + if ( wp_doing_ajax() ) { require_once WPSEO_PATH . 'admin/ajax.php'; // Plugin conflict ajax hooks. @@ -407,17 +471,37 @@ if ( ! wp_installing() && ( $spl_autoload_exists && $filter_exists ) ) { add_action( 'plugins_loaded', 'wpseo_admin_init', 15 ); } } - else { - add_action( 'plugins_loaded', 'wpseo_frontend_init', 15 ); - } add_action( 'plugins_loaded', 'load_yoast_notifications' ); + + if ( defined( 'WP_CLI' ) && WP_CLI ) { + add_action( 'plugins_loaded', 'wpseo_cli_init', 20 ); + } + + add_action( 'init', [ 'WPSEO_Replace_Vars', 'setup_statics_once' ] ); + + // Initializes the Yoast indexables for the first time. + YoastSEO(); + + /** + * Action called when the Yoast SEO plugin file has loaded. + */ + do_action( 'wpseo_loaded' ); } // Activation and deactivation hook. register_activation_hook( WPSEO_FILE, 'wpseo_activate' ); register_deactivation_hook( WPSEO_FILE, 'wpseo_deactivate' ); -add_action( 'wpmu_new_blog', 'wpseo_on_activate_blog' ); + +// Wpmu_new_blog has been deprecated in 5.1 and replaced by wp_insert_site. +global $wp_version; +if ( version_compare( $wp_version, '5.1', '<' ) ) { + add_action( 'wpmu_new_blog', 'wpseo_on_activate_blog' ); +} +else { + add_action( 'wp_initialize_site', 'wpseo_on_activate_blog', 99 ); +} + add_action( 'activate_blog', 'wpseo_on_activate_blog' ); // Registers SEO capabilities. @@ -438,7 +522,7 @@ function load_yoast_notifications() { /** - * Throw an error if the PHP SPL extension is disabled (prevent white screens) and self-deactivate plugin + * Throw an error if the PHP SPL extension is disabled (prevent white screens) and self-deactivate plugin. * * @since 1.5.4 * @@ -453,7 +537,7 @@ function yoast_wpseo_missing_spl() { } /** - * Returns the notice in case of missing spl extension + * Returns the notice in case of missing spl extension. */ function yoast_wpseo_missing_spl_notice() { $message = esc_html__( 'The Standard PHP Library (SPL) extension seem to be unavailable. Please ask your web host to enable it.', 'wordpress-seo' ); @@ -461,7 +545,7 @@ function yoast_wpseo_missing_spl_notice() { } /** - * Throw an error if the Composer autoload is missing and self-deactivate plugin + * Throw an error if the Composer autoload is missing and self-deactivate plugin. * * @return void */ @@ -474,7 +558,7 @@ function yoast_wpseo_missing_autoload() { } /** - * Returns the notice in case of missing Composer autoload + * Returns the notice in case of missing Composer autoload. */ function yoast_wpseo_missing_autoload_notice() { /* translators: %1$s expands to Yoast SEO, %2$s / %3$s: links to the installation manual in the Readme for the Yoast SEO code repository on GitHub */ @@ -484,7 +568,7 @@ function yoast_wpseo_missing_autoload_notice() { } /** - * Throw an error if the filter extension is disabled (prevent white screens) and self-deactivate plugin + * Throw an error if the filter extension is disabled (prevent white screens) and self-deactivate plugin. * * @since 2.0 * @@ -499,7 +583,7 @@ function yoast_wpseo_missing_filter() { } /** - * Returns the notice in case of missing filter extension + * Returns the notice in case of missing filter extension. */ function yoast_wpseo_missing_filter_notice() { $message = esc_html__( 'The filter extension seem to be unavailable. Please ask your web host to enable it.', 'wordpress-seo' ); @@ -512,20 +596,50 @@ function yoast_wpseo_missing_filter_notice() { * @param string $message Message string. */ function yoast_wpseo_activation_failed_notice( $message ) { - echo '

    ' . esc_html__( 'Activation failed:', 'wordpress-seo' ) . ' ' . $message . '

    '; + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This function is only called in 3 places that are safe. + echo '

    ' . esc_html__( 'Activation failed:', 'wordpress-seo' ) . ' ' . strip_tags( $message, '' ) . '

    '; } /** - * The method will deactivate the plugin, but only once, done by the static $is_deactivated + * The method will deactivate the plugin, but only once, done by the static $is_deactivated. */ function yoast_wpseo_self_deactivate() { static $is_deactivated; if ( $is_deactivated === null ) { $is_deactivated = true; - deactivate_plugins( plugin_basename( WPSEO_FILE ) ); + deactivate_plugins( WPSEO_BASENAME ); if ( isset( $_GET['activate'] ) ) { unset( $_GET['activate'] ); } } } + +/* ********************* DEPRECATED METHODS ********************* */ + +/** + * Instantiate the different social classes on the frontend. + * + * @deprecated 14.0 + * @codeCoverageIgnore + */ +function wpseo_frontend_head_init() { + _deprecated_function( __METHOD__, 'WPSEO 14.0' ); +} + +/** + * Used to load the required files on the plugins_loaded hook, instead of immediately. + * + * @deprecated 14.0 + * @codeCoverageIgnore + */ +function wpseo_frontend_init() { + _deprecated_function( __METHOD__, 'WPSEO 14.0' ); +} + +/** + * Aliasses added in order to keep compatibility with Yoast SEO: Local. + */ +class_alias( '\Yoast\WP\SEO\Initializers\Initializer_Interface', '\Yoast\WP\SEO\WordPress\Initializer' ); +class_alias( '\Yoast\WP\SEO\Loadable_Interface', '\Yoast\WP\SEO\WordPress\Loadable' ); +class_alias( '\Yoast\WP\SEO\Integrations\Integration_Interface', '\Yoast\WP\SEO\WordPress\Integration' ); diff --git a/wp-content/plugins/wordpress-seo/wp-seo.php b/wp-content/plugins/wordpress-seo/wp-seo.php index d86696f5..07aab0b2 100644 --- a/wp-content/plugins/wordpress-seo/wp-seo.php +++ b/wp-content/plugins/wordpress-seo/wp-seo.php @@ -3,12 +3,12 @@ * Yoast SEO Plugin. * * @package WPSEO\Main - * @copyright Copyright (C) 2008-2016, Yoast BV - support@yoast.com + * @copyright Copyright (C) 2008-2021, Yoast BV - support@yoast.com * @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License, version 3 or higher * * @wordpress-plugin * Plugin Name: Yoast SEO - * Version: 7.2 + * Version: 17.2 * Plugin URI: https://yoa.st/1uj * Description: The first true all-in-one SEO solution for WordPress, including on-page content analysis, XML sitemaps and much more. * Author: Team Yoast @@ -16,6 +16,11 @@ * Text Domain: wordpress-seo * Domain Path: /languages/ * License: GPL v3 + * Requires at least: 5.6 + * Requires PHP: 5.6.20 + * + * WC requires at least: 3.0 + * WC tested up to: 5.6 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/wp-content/plugins/wordpress-seo/wpml-config.xml b/wp-content/plugins/wordpress-seo/wpml-config.xml index 7abce611..5bc612d2 100644 --- a/wp-content/plugins/wordpress-seo/wpml-config.xml +++ b/wp-content/plugins/wordpress-seo/wpml-config.xml @@ -10,7 +10,6 @@ _yoast_wpseo_canonical _yoast_wpseo_redirect _yoast_wpseo_opengraph-description - _yoast_wpseo_google-plus-description