diff options
Diffstat (limited to 'plugins/jetpack/_inc/lib')
5 files changed, 158 insertions, 103 deletions
diff --git a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-admin-page.php b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-admin-page.php index b4a86c16..ba2fefe8 100644 --- a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-admin-page.php +++ b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-admin-page.php @@ -21,15 +21,6 @@ abstract class Jetpack_Admin_Page { static $block_page_rendering_for_idc; /** - * Flag to know if we already checked the plan. - * - * @since 4.4.0 - * - * @var bool - */ - static $plan_checked = false; - - /** * Function called after admin_styles to load any additional needed styles. * * @since 4.3.0 @@ -172,7 +163,7 @@ abstract class Jetpack_Admin_Page { * * @param $page * - * @return bool|array + * @return array */ function check_plan_deactivate_modules( $page ) { if ( @@ -187,49 +178,43 @@ abstract class Jetpack_Admin_Page { 'jetpack_page_akismet-key-config' ) ) - || true === self::$plan_checked ) { return false; } - self::$plan_checked = true; - $previous = get_option( 'jetpack_active_plan', '' ); - $current = Jetpack_Core_Json_Api_Endpoints::site_data(); - if ( ! $current || is_wp_error( $current ) ) { - // If we can't get information about the current plan we don't do anything - self::$plan_checked = true; - return; - } + $current = Jetpack::get_active_plan(); $to_deactivate = array(); - if ( isset( $current->plan->product_slug ) ) { - if ( - empty( $previous ) - || ! isset( $previous['product_slug'] ) - || $previous['product_slug'] !== $current->plan->product_slug - ) { - $active = Jetpack::get_active_modules(); - switch ( $current->plan->product_slug ) { - case 'jetpack_free': - $to_deactivate = array( 'seo-tools', 'videopress', 'google-analytics', 'wordads', 'search' ); - break; - case 'jetpack_personal': - case 'jetpack_personal_monthly': - $to_deactivate = array( 'seo-tools', 'videopress', 'google-analytics', 'wordads', 'search' ); - break; - case 'jetpack_premium': - case 'jetpack_premium_monthly': - $to_deactivate = array( 'seo-tools', 'google-analytics', 'search' ); - break; - } - $to_deactivate = array_intersect( $active, $to_deactivate ); - if ( ! empty( $to_deactivate ) ) { - Jetpack::update_active_modules( array_filter( array_diff( $active, $to_deactivate ) ) ); + if ( isset( $current['product_slug'] ) ) { + $active = Jetpack::get_active_modules(); + switch ( $current['product_slug'] ) { + case 'jetpack_free': + $to_deactivate = array( 'seo-tools', 'videopress', 'google-analytics', 'wordads', 'search' ); + break; + case 'jetpack_personal': + case 'jetpack_personal_monthly': + $to_deactivate = array( 'seo-tools', 'videopress', 'google-analytics', 'wordads', 'search' ); + break; + case 'jetpack_premium': + case 'jetpack_premium_monthly': + $to_deactivate = array( 'seo-tools', 'google-analytics', 'search' ); + break; + } + $to_deactivate = array_intersect( $active, $to_deactivate ); + + $to_leave_enabled = array(); + foreach ( $to_deactivate as $feature ) { + if ( Jetpack::active_plan_supports( $feature ) ) { + $to_leave_enabled []= $feature; } } + $to_deactivate = array_diff( $to_deactivate, $to_leave_enabled ); + + if ( ! empty( $to_deactivate ) ) { + Jetpack::update_active_modules( array_filter( array_diff( $active, $to_deactivate ) ) ); + } } return array( - 'previous' => $previous, 'current' => $current, 'deactivate' => $to_deactivate ); diff --git a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php index 4047cfbc..6cd6b94c 100644 --- a/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php +++ b/plugins/jetpack/_inc/lib/admin-pages/class.jetpack-react-page.php @@ -147,21 +147,6 @@ class Jetpack_React_Page extends Jetpack_Admin_Page { } } - function get_i18n_data() { - - $i18n_json = JETPACK__PLUGIN_DIR . 'languages/json/jetpack-' . jetpack_get_user_locale() . '.json'; - - if ( is_file( $i18n_json ) && is_readable( $i18n_json ) ) { - $locale_data = @file_get_contents( $i18n_json ); - if ( $locale_data ) { - return $locale_data; - } - } - - // Return empty if we have nothing to return so it doesn't fail when parsed in JS - return '{}'; - } - /** * Gets array of any Jetpack notices that have been dismissed. * @@ -303,6 +288,7 @@ class Jetpack_React_Page extends Jetpack_Admin_Page { */ 'showPromotions' => apply_filters( 'jetpack_show_promotions', true ), 'isAtomicSite' => jetpack_is_atomic_site(), + 'plan' => Jetpack::get_active_plan(), ), 'themeData' => array( 'name' => $current_theme->get( 'Name' ), @@ -311,7 +297,7 @@ class Jetpack_React_Page extends Jetpack_Admin_Page { 'infinite-scroll' => current_theme_supports( 'infinite-scroll' ) || in_array( $current_theme->get_stylesheet(), $inf_scr_support_themes ), ), ), - 'locale' => $this->get_i18n_data(), + 'locale' => Jetpack::get_i18n_data_json(), 'localeSlug' => join( '-', explode( '_', jetpack_get_user_locale() ) ), 'jetpackStateNotices' => array( 'messageCode' => Jetpack::state( 'message' ), diff --git a/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php b/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php index 71bccc4c..8653d88b 100644 --- a/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php +++ b/plugins/jetpack/_inc/lib/class.core-rest-api-endpoints.php @@ -122,6 +122,13 @@ class Jetpack_Core_Json_Api_Endpoints { 'permission_callback' => __CLASS__ . '::get_user_connection_data_permission_callback', ) ); + // Set the connection owner + register_rest_route( 'jetpack/v4', '/connection/owner', array( + 'methods' => WP_REST_Server::EDITABLE, + 'callback' => __CLASS__ . '::set_connection_owner', + 'permission_callback' => __CLASS__ . '::set_connection_owner_permission_callback', + ) ); + // Current user: get or set tracking settings. register_rest_route( 'jetpack/v4', '/tracking/settings', array( array( @@ -374,39 +381,23 @@ class Jetpack_Core_Json_Api_Endpoints { } public static function get_plans( $request ) { - /** - * Filter to turn off caching of Jetpack plans - * - * @since 5.9.0 - * - * @param bool true Whether to cache Jetpack plans locally - */ - $use_cache = apply_filters( 'jetpack_cache_plans', true ); - - $data = $use_cache ? get_transient( 'jetpack_plans' ) : false; - - if ( false === $data ) { - $path = '/plans'; - // passing along from client to help geolocate currency - $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; // if we already have an list of forwarded ips, then just use that - if ( empty( $ip ) ) { - $ip = $_SERVER['HTTP_CLIENT_IP']; // another popular one for proxy servers - } - if ( empty( $ip ) ) { - $ip = $_SERVER['REMOTE_ADDR']; // if we don't have an ip by now, take the closest node's ip (likely directly connected client) - } - $request = Jetpack_Client::wpcom_json_api_request_as_blog( $path, '2', array( 'headers' => array( 'X-Forwarded-For' => $ip ) ), null, 'wpcom' ); - $body = wp_remote_retrieve_body( $request ); - if ( 200 === wp_remote_retrieve_response_code( $request ) ) { - $data = $body; - } else { - // something went wrong so we'll just return the response without caching - return $body; - } + $request = Jetpack_Client::wpcom_json_api_request_as_user( + '/plans?_locale=' . get_user_locale(), + '2', + array( + 'method' => 'GET', + 'headers' => array( + 'X-Forwarded-For' => Jetpack::current_user_ip( true ), + ), + ) + ); - if ( true === $use_cache ) { - set_transient( 'jetpack_plans', $data, DAY_IN_SECONDS ); - } + $body = wp_remote_retrieve_body( $request ); + if ( 200 === wp_remote_retrieve_response_code( $request ) ) { + $data = $body; + } else { + // something went wrong so we'll just return the response without caching + return $body; } return $data; @@ -575,6 +566,21 @@ class Jetpack_Core_Json_Api_Endpoints { } /** + * Check that user has permission to change the master user. + * + * @since 6.2.0 + * + * @return bool|WP_Error True if user is able to change master user. + */ + public static function set_connection_owner_permission_callback() { + if ( get_current_user_id() === Jetpack_Options::get_option( 'master_user' ) ) { + return true; + } + + return new WP_Error( 'invalid_user_permission_set_connection_owner', self::$user_permissions_error_msg, array( 'status' => self::rest_authorization_required_code() ) ); + } + + /** * Verify that a user can use the /connection/user endpoint. Has to be a registered user and be currently linked. * * @since 4.3.0 @@ -833,6 +839,64 @@ class Jetpack_Core_Json_Api_Endpoints { } /** + * Change the master user. + * + * @since 6.2.0 + * + * @param WP_REST_Request $request The request sent to the WP REST API. + * + * @return bool|WP_Error True if owner successfully changed. + */ + public static function set_connection_owner( $request ) { + if ( ! isset( $request['owner'] ) ) { + return new WP_Error( + 'invalid_param', + esc_html__( 'Invalid Parameter', 'jetpack' ), + array( 'status' => 400 ) + ); + } + + $new_owner_id = $request['owner']; + if ( ! user_can( $new_owner_id, 'administrator' ) ) { + return new WP_Error( + 'new_owner_not_admin', + esc_html__( 'New owner is not admin', 'jetpack' ), + array( 'status' => 400 ) + ); + } + + if ( $new_owner_id === get_current_user_id() ) { + return new WP_Error( + 'new_owner_is_current_user', + esc_html__( 'New owner is same as current user', 'jetpack' ), + array( 'status' => 400 ) + ); + } + + if ( ! Jetpack::is_user_connected( $new_owner_id ) ) { + return new WP_Error( + 'new_owner_not_connected', + esc_html__( 'New owner is not connected', 'jetpack' ), + array( 'status' => 400 ) + ); + } + + $updated = Jetpack_Options::update_option( 'master_user', $new_owner_id ); + if ( $updated ) { + return rest_ensure_response( + array( + 'code' => 'success' + ) + ); + } + return new WP_Error( + 'error_setting_new_owner', + esc_html__( 'Could not confirm new owner.', 'jetpack' ), + array( 'status' => 500 ) + ); + } + + /** * Unlinks current user from the WordPress.com Servers. * * @since 4.3.0 @@ -1660,7 +1724,7 @@ class Jetpack_Core_Json_Api_Endpoints { 'jp_group' => 'related-posts', ), 'show_thumbnails' => array( - 'description' => esc_html__( 'Use a large and visually striking layout', 'jetpack' ), + 'description' => esc_html__( 'Show a thumbnail image where available', 'jetpack' ), 'type' => 'boolean', 'default' => 0, 'validate_callback' => __CLASS__ . '::validate_boolean', diff --git a/plugins/jetpack/_inc/lib/class.media-summary.php b/plugins/jetpack/_inc/lib/class.media-summary.php index d129f5e6..cf1bc050 100644 --- a/plugins/jetpack/_inc/lib/class.media-summary.php +++ b/plugins/jetpack/_inc/lib/class.media-summary.php @@ -54,7 +54,7 @@ class Jetpack_Media_Summary { ); if ( empty( $post->post_password ) ) { - $return['excerpt'] = self::get_excerpt( $post->post_content, $post->post_excerpt, $args['max_words'], $args['max_chars'] ); + $return['excerpt'] = self::get_excerpt( $post->post_content, $post->post_excerpt, $args['max_words'], $args['max_chars'] , $post); $return['count']['word'] = self::get_word_count( $post->post_content ); $return['count']['word_remaining'] = self::get_word_remaining_count( $post->post_content, $return['excerpt'] ); $return['count']['link'] = self::get_link_count( $post->post_content ); @@ -298,22 +298,42 @@ class Jetpack_Media_Summary { ); } - static function get_excerpt( $post_content, $post_excerpt, $max_words = 16, $max_chars = 256 ) { + /** + * Retrieve an excerpt for the post summary. + * + * This function works around a suspected problem with Core. If resolved, this function should be simplified. + * @link https://github.com/Automattic/jetpack/pull/8510 + * @link https://core.trac.wordpress.org/ticket/42814 + * + * @param string $post_content The post's content. + * @param string $post_excerpt The post's excerpt. Empty if none was explicitly set. + * @param int $max_words Maximum number of words for the excerpt. Used on wp.com. Default 16. + * @param int $max_chars Maximum characters in the excerpt. Used on wp.com. Default 256. + * @param WP_Post $requested_post The post object. + * @return string Post excerpt. + **/ + static function get_excerpt( $post_content, $post_excerpt, $max_words = 16, $max_chars = 256, $requested_post = null ) { + global $post; + $original_post = $post; // Saving the global for later use. if ( function_exists( 'wpcom_enhanced_excerpt_extract_excerpt' ) ) { return self::clean_text( wpcom_enhanced_excerpt_extract_excerpt( array( - 'text' => $post_content, - 'excerpt_only' => true, - 'show_read_more' => false, - 'max_words' => $max_words, - 'max_chars' => $max_chars, + 'text' => $post_content, + 'excerpt_only' => true, + 'show_read_more' => false, + 'max_words' => $max_words, + 'max_chars' => $max_chars, 'read_more_threshold' => 25, ) ) ); - } else { - + } elseif ( $requested_post instanceof WP_Post ) { + $post = $requested_post; // setup_postdata does not set the global. + setup_postdata( $post ); /** This filter is documented in core/src/wp-includes/post-template.php */ - $post_excerpt = apply_filters( 'get_the_excerpt', $post_excerpt ); + $post_excerpt = apply_filters( 'get_the_excerpt', $post_excerpt, $post ); + $post = $original_post; // wp_reset_postdata uses the $post global. + wp_reset_postdata(); return self::clean_text( $post_excerpt ); } + return ''; } static function get_word_count( $post_content ) { diff --git a/plugins/jetpack/_inc/lib/markdown/extra.php b/plugins/jetpack/_inc/lib/markdown/extra.php index e54b4ab1..86778d2f 100644 --- a/plugins/jetpack/_inc/lib/markdown/extra.php +++ b/plugins/jetpack/_inc/lib/markdown/extra.php @@ -73,7 +73,7 @@ function Markdown($text) { * */ function jetpack_utf8_strlen( $text ) { - return preg_match_all( "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", $text, $m ); + return preg_match_all( "/[\\x00-\\xBF]|[\\xC0-\\xFF][\\x80-\\xBF]*/", $text, $m ); } # |