← All changes
|
_inc/lib/admin-pages/class-jetpack-redux-state-helper.php
+473
-0
16.2-beta
→
16.3
View file →
| @@ -1,0 +1,473 @@ | ||
| 1 | +<?php | |
| 2 | +/** | |
| 3 | + * A utility class that generates the initial state for Redux in wp-admin. | |
| 4 | + * Modularized from `class.jetpack-react-page.php`. | |
| 5 | + * | |
| 6 | + * @package automattic/jetpack | |
| 7 | + */ | |
| 8 | + | |
| 9 | +use Automattic\Jetpack\Blaze; | |
| 10 | +use Automattic\Jetpack\Comments\Block_Editor; | |
| 11 | +use Automattic\Jetpack\Comments\Comments; | |
| 12 | +use Automattic\Jetpack\Connection\Manager as Connection_Manager; | |
| 13 | +use Automattic\Jetpack\Connection\Plugin_Storage as Connection_Plugin_Storage; | |
| 14 | +use Automattic\Jetpack\Connection\REST_Connector; | |
| 15 | +use Automattic\Jetpack\Constants; | |
| 16 | +use Automattic\Jetpack\Current_Plan as Jetpack_Plan; | |
| 17 | +use Automattic\Jetpack\Device_Detection\User_Agent_Info; | |
| 18 | +use Automattic\Jetpack\Identity_Crisis; | |
| 19 | +use Automattic\Jetpack\IP\Utils as IP_Utils; | |
| 20 | +use Automattic\Jetpack\Licensing; | |
| 21 | +use Automattic\Jetpack\Licensing\Endpoints as Licensing_Endpoints; | |
| 22 | +use Automattic\Jetpack\My_Jetpack\Initializer as My_Jetpack_Initializer; | |
| 23 | +use Automattic\Jetpack\Partner; | |
| 24 | +use Automattic\Jetpack\Publicize\Keyring_Helper; | |
| 25 | +use Automattic\Jetpack\Stats\Options as Stats_Options; | |
| 26 | +use Automattic\Jetpack\Status; | |
| 27 | +use Automattic\Jetpack\Status\Host; | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * Responsible for populating the initial Redux state. | |
| 31 | + */ | |
| 32 | +class Jetpack_Redux_State_Helper { | |
| 33 | + /** | |
| 34 | + * Generate minimal state for React to fetch its own data asynchronously after load | |
| 35 | + * This can improve user experience, reducing time spent on server requests before serving the page | |
| 36 | + * e.g. used by React Disconnect Dialog on plugins page where the full initial state is not needed | |
| 37 | + */ | |
| 38 | + public static function get_minimal_state() { | |
| 39 | + return array( | |
| 40 | + 'WP_API_root' => esc_url_raw( rest_url() ), | |
| 41 | + 'WP_API_nonce' => wp_create_nonce( 'wp_rest' ), | |
| 42 | + ); | |
| 43 | + } | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * Generate the state for the plugins page: the minimal state plus what the deactivation survey needs. | |
| 47 | + * | |
| 48 | + * @since 16.3 | |
| 49 | + * | |
| 50 | + * @return array | |
| 51 | + */ | |
| 52 | + public static function get_plugins_page_state() { | |
| 53 | + $state = self::get_minimal_state(); | |
| 54 | + | |
| 55 | + $connection = new Connection_Manager(); | |
| 56 | + | |
| 57 | + $state['pluginDeactivation'] = array( | |
| 58 | + 'siteId' => (int) Jetpack_Options::get_option( 'id' ), | |
| 59 | + 'hasConnectedUser' => $connection->has_connected_user(), | |
| 60 | + 'isCurrentUserConnected' => $connection->is_user_connected(), | |
| 61 | + ); | |
| 62 | + | |
| 63 | + return $state; | |
| 64 | + } | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * Generate the initial state array to be used by the Redux store. | |
| 68 | + */ | |
| 69 | + public static function get_initial_state() { | |
| 70 | + global $is_safari; | |
| 71 | + | |
| 72 | + // Load API endpoint base classes and endpoints for getting the module list fed into the JS Admin Page. | |
| 73 | + require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-xmlrpc-consumer-endpoint.php'; | |
| 74 | + require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php'; | |
| 75 | + require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php'; | |
| 76 | + | |
| 77 | + $module_list_endpoint = new Jetpack_Core_API_Module_List_Endpoint(); | |
| 78 | + $modules = $module_list_endpoint->get_modules(); | |
| 79 | + | |
| 80 | + // Preparing translated fields for JSON encoding by transforming all HTML entities to | |
| 81 | + // respective characters. | |
| 82 | + foreach ( $modules as $slug => $data ) { | |
| 83 | + $modules[ $slug ]['name'] = html_entity_decode( $data['name'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 ); | |
| 84 | + $modules[ $slug ]['description'] = html_entity_decode( $data['description'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 ); | |
| 85 | + $modules[ $slug ]['short_description'] = html_entity_decode( $data['short_description'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 ); | |
| 86 | + $modules[ $slug ]['long_description'] = html_entity_decode( $data['long_description'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 ); | |
| 87 | + } | |
| 88 | + | |
| 89 | + // "mock" a block module in order to get it searchable in the settings. | |
| 90 | + $modules['blocks']['module'] = 'blocks'; | |
| 91 | + $modules['blocks']['additional_search_queries'] = esc_html_x( 'blocks, block, gutenberg', 'Search terms', 'jetpack' ); | |
| 92 | + | |
| 93 | + // "mock" an Earn module in order to get it searchable in the settings. | |
| 94 | + $modules['earn']['module'] = 'earn'; | |
| 95 | + $modules['earn']['additional_search_queries'] = esc_html_x( 'earn, paypal, stripe, payments, pay', 'Search terms', 'jetpack' ); | |
| 96 | + | |
| 97 | + // Collecting roles that can view site stats. | |
| 98 | + $stats_roles = array(); | |
| 99 | + $enabled_roles = Stats_Options::get_option( 'roles' ); | |
| 100 | + | |
| 101 | + if ( ! function_exists( 'get_editable_roles' ) ) { | |
| 102 | + require_once ABSPATH . 'wp-admin/includes/user.php'; | |
| 103 | + } | |
| 104 | + foreach ( get_editable_roles() as $slug => $role ) { | |
| 105 | + $stats_roles[ $slug ] = array( | |
| 106 | + 'name' => translate_user_role( $role['name'] ), | |
| 107 | + 'canView' => is_array( $enabled_roles ) ? in_array( $slug, $enabled_roles, true ) : false, | |
| 108 | + ); | |
| 109 | + } | |
| 110 | + | |
| 111 | + // Get information about current theme. | |
| 112 | + $current_theme = wp_get_theme(); | |
| 113 | + | |
| 114 | + // Get all themes that Infinite Scroll provides support for natively. | |
| 115 | + $inf_scr_support_themes = array(); | |
| 116 | + foreach ( Jetpack::glob_php( JETPACK__PLUGIN_DIR . 'modules/infinite-scroll/themes' ) as $path ) { | |
| 117 | + if ( is_readable( $path ) ) { | |
| 118 | + $inf_scr_support_themes[] = basename( $path, '.php' ); | |
| 119 | + } | |
| 120 | + } | |
| 121 | + | |
| 122 | + // Get last post, to build the link to Customizer in the Related Posts module. | |
| 123 | + $last_post = get_posts( array( 'posts_per_page' => 1 ) ); | |
| 124 | + $last_post = isset( $last_post[0] ) && $last_post[0] instanceof WP_Post | |
| 125 | + ? get_permalink( $last_post[0]->ID ) | |
| 126 | + : get_home_url(); | |
| 127 | + | |
| 128 | + $current_user_data = jetpack_current_user_data(); | |
| 129 | + | |
| 130 | + /** | |
| 131 | + * Adds information to the `connectionStatus` API field that is unique to the Jetpack React dashboard. | |
| 132 | + */ | |
| 133 | + $connection_status = array( | |
| 134 | + 'isInIdentityCrisis' => Identity_Crisis::validate_sync_error_idc_option(), | |
| 135 | + 'sandboxDomain' => JETPACK__SANDBOX_DOMAIN, | |
| 136 | + | |
| 137 | + /** | |
| 138 | + * Filter to add connection errors | |
| 139 | + * Format: array( array( 'code' => '...', 'message' => '...', 'action' => '...' ), ... ) | |
| 140 | + * | |
| 141 | + * @since 8.7.0 | |
| 142 | + * | |
| 143 | + * @param array $errors Connection errors. | |
| 144 | + */ | |
| 145 | + 'errors' => apply_filters( 'react_connection_errors_initial_state', array() ), | |
| 146 | + ); | |
| 147 | + | |
| 148 | + $connection_status = array_merge( REST_Connector::connection_status( false ), $connection_status ); | |
| 149 | + | |
| 150 | + $block_availability = Jetpack_Gutenberg::get_cached_availability(); | |
| 151 | + | |
| 152 | + return array( | |
| 153 | + 'WP_API_root' => esc_url_raw( rest_url() ), | |
| 154 | + 'WP_API_nonce' => wp_create_nonce( 'wp_rest' ), | |
| 155 | + 'registrationNonce' => '', // Not used, keeping it for compatibility reasons, see https://github.com/Automattic/jetpack/pull/42076 | |
| 156 | + 'purchaseToken' => self::get_purchase_token(), | |
| 157 | + 'pluginBaseUrl' => plugins_url( '', JETPACK__PLUGIN_FILE ), | |
| 158 | + 'connectionStatus' => $connection_status, | |
| 159 | + 'connectedPlugins' => Connection_Plugin_Storage::get_all(), | |
| 160 | + 'connectUrl' => false == $current_user_data['isConnected'] // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual | |
| 161 | + ? Jetpack::init()->build_connect_url( true, false, false ) | |
| 162 | + : '', | |
| 163 | + 'dismissedNotices' => self::get_dismissed_jetpack_notices(), | |
| 164 | + 'isDevVersion' => Jetpack::is_development_version(), | |
| 165 | + 'currentVersion' => JETPACK__VERSION, | |
| 166 | + 'is_gutenberg_available' => true, | |
| 167 | + 'getModules' => $modules, | |
| 168 | + 'rawUrl' => ( new Status() )->get_site_suffix(), | |
| 169 | + 'adminUrl' => esc_url( admin_url() ), | |
| 170 | + 'siteTitle' => htmlspecialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), | |
| 171 | + 'stats' => array( | |
| 172 | + // data is populated asynchronously on page load. | |
| 173 | + 'data' => array( | |
| 174 | + 'general' => false, | |
| 175 | + 'day' => false, | |
| 176 | + 'week' => false, | |
| 177 | + 'month' => false, | |
| 178 | + ), | |
| 179 | + 'roles' => $stats_roles, | |
| 180 | + ), | |
| 181 | + 'aff' => Partner::init()->get_partner_code( Partner::AFFILIATE_CODE ), | |
| 182 | + 'partnerSubsidiaryId' => Partner::init()->get_partner_code( Partner::SUBSIDIARY_CODE ), | |
| 183 | + 'settings' => self::get_flattened_settings(), | |
| 184 | + 'userData' => array( | |
| 185 | + 'currentUser' => $current_user_data, | |
| 186 | + ), | |
| 187 | + 'siteData' => array( | |
| 188 | + 'blog_id' => Jetpack_Options::get_option( 'id', 0 ), | |
| 189 | + 'icon' => has_site_icon() | |
| 190 | + ? apply_filters( 'jetpack_photon_url', get_site_icon_url(), array( 'w' => 64 ) ) | |
| 191 | + : '', | |
| 192 | + 'representativeImage' => self::get_site_image(), | |
| 193 | + 'siteVisibleToSearchEngines' => '1' == get_option( 'blog_public' ), // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual | |
| 194 | + /** | |
| 195 | + * Whether promotions are visible or not. | |
| 196 | + * | |
| 197 | + * @since 4.8.0 | |
| 198 | + * | |
| 199 | + * @param bool $are_promotions_active Status of promotions visibility. True by default. | |
| 200 | + */ | |
| 201 | + 'showPromotions' => apply_filters( 'jetpack_show_promotions', true ), | |
| 202 | + 'plan' => Jetpack_Plan::get(), | |
| 203 | + 'showBackups' => Jetpack::show_backups_ui(), | |
| 204 | + 'showScan' => Jetpack::show_scan_ui(), | |
| 205 | + /** This filter is documented in my-jetpack/src/class-initializer.php */ | |
| 206 | + 'showMyJetpack' => My_Jetpack_Initializer::should_initialize(), | |
| 207 | + 'isMultisite' => is_multisite(), | |
| 208 | + 'dateFormat' => get_option( 'date_format' ), | |
| 209 | + 'isSharingBlockAvailable' => isset( $block_availability['sharing-buttons'] ) | |
| 210 | + && $block_availability['sharing-buttons']['available'], | |
| 211 | + 'isLikeBlockAvailable' => isset( $block_availability['like'] ) | |
| 212 | + && $block_availability['like']['available'], | |
| 213 | + // The rebuilt comment form is what offers blocks; the package may lag this file on a staged deploy. | |
| 214 | + 'isCommentBlocksAvailable' => class_exists( Block_Editor::class ) && Comments::is_enabled(), | |
| 215 | + ), | |
| 216 | + 'themeData' => array( | |
| 217 | + 'name' => $current_theme->get( 'Name' ), | |
| 218 | + 'stylesheet' => $current_theme->get_stylesheet(), | |
| 219 | + 'hasUpdate' => (bool) get_theme_update_available( $current_theme ), | |
| 220 | + 'isBlockTheme' => (bool) $current_theme->is_block_theme(), | |
| 221 | + 'support' => array( | |
| 222 | + 'infinite-scroll' => current_theme_supports( 'infinite-scroll' ) || in_array( $current_theme->get_stylesheet(), $inf_scr_support_themes, true ), | |
| 223 | + 'widgets' => current_theme_supports( 'widgets' ), | |
| 224 | + 'webfonts' => wp_theme_has_theme_json() | |
| 225 | + && ( function_exists( 'wp_register_webfont_provider' ) || function_exists( 'wp_register_webfonts' ) ), | |
| 226 | + ), | |
| 227 | + ), | |
| 228 | + 'jetpackStateNotices' => array( | |
| 229 | + 'messageCode' => Jetpack::state( 'message' ), | |
| 230 | + 'errorCode' => Jetpack::state( 'error' ), | |
| 231 | + 'errorDescription' => Jetpack::state( 'error_description' ), | |
| 232 | + ), | |
| 233 | + 'tracksUserData' => Jetpack_Tracks_Client::get_connected_user_tracks_identity(), | |
| 234 | + 'currentIp' => IP_Utils::get_ip(), | |
| 235 | + 'lastPostUrl' => esc_url( $last_post ), | |
| 236 | + 'externalServicesConnectUrls' => self::get_external_services_connect_urls(), | |
| 237 | + 'calypsoEnv' => ( new Host() )->get_calypso_env(), | |
| 238 | + 'isSafari' => $is_safari || User_Agent_Info::is_opera_desktop(), // @todo Rename isSafari everywhere. | |
| 239 | + 'doNotUseConnectionIframe' => Constants::is_true( 'JETPACK_SHOULD_NOT_USE_CONNECTION_IFRAME' ), | |
| 240 | + 'licensing' => array( | |
| 241 | + 'error' => Licensing::instance()->last_error(), | |
| 242 | + 'showLicensingUi' => Licensing::instance()->is_licensing_input_enabled(), | |
| 243 | + 'userCounts' => Licensing_Endpoints::get_user_license_counts(), | |
| 244 | + 'activationNoticeDismiss' => Licensing::instance()->get_license_activation_notice_dismiss(), | |
| 245 | + ), | |
| 246 | + 'useMyJetpackLicensingUI' => My_Jetpack_Initializer::is_licensing_ui_enabled(), | |
| 247 | + 'isOdysseyStatsEnabled' => Stats_Options::get_option( 'enable_odyssey_stats' ), | |
| 248 | + 'shouldInitializeBlaze' => Blaze::should_initialize(), | |
| 249 | + 'isBlazeDashboardEnabled' => Blaze::is_dashboard_enabled(), | |
| 250 | + // The composed AI gate chain (host, and the master where its rollout | |
| 251 | + // is active) — what the editor enforces, for settings UI that must | |
| 252 | + // not contradict it. | |
| 253 | + 'isAiEnabled' => Jetpack_AI_Settings::is_ai_enabled(), | |
| 254 | + // The AI SEO feature, gates folded in: controls that drive only its | |
| 255 | + // automatic half must follow it too. | |
| 256 | + 'isAiSeoEnabled' => Jetpack_AI_Settings::is_ai_seo_enabled(), | |
| 257 | + 'isSubscriptionSiteEnabled' => apply_filters( 'jetpack_subscription_site_enabled', false ), | |
| 258 | + 'newsletterDateExample' => gmdate( get_option( 'date_format' ), time() ), | |
| 259 | + 'subscriptionSiteEditSupported' => $current_theme->is_block_theme(), | |
| 260 | + | |
| 261 | + /* | |
| 262 | + * This filter is already documented in jetpack/modules/subscriptions.php. | |
| 263 | + * Defaults on for every site; hosts can opt out with the filter. | |
| 264 | + */ | |
| 265 | + 'isWpAdminSubscriberManagementEnabled' => apply_filters( | |
| 266 | + 'jetpack_wp_admin_subscriber_management_enabled', | |
| 267 | + true | |
| 268 | + ), | |
| 269 | + ); | |
| 270 | + } | |
| 271 | + | |
| 272 | + /** | |
| 273 | + * Gets array of any Jetpack notices that have been dismissed. | |
| 274 | + * | |
| 275 | + * @return mixed|void | |
| 276 | + */ | |
| 277 | + public static function get_dismissed_jetpack_notices() { | |
| 278 | + $jetpack_dismissed_notices = get_option( 'jetpack_dismissed_notices', array() ); | |
| 279 | + /** | |
| 280 | + * Array of notices that have been dismissed. | |
| 281 | + * | |
| 282 | + * @param array $jetpack_dismissed_notices If empty, will not show any Jetpack notices. | |
| 283 | + */ | |
| 284 | + $dismissed_notices = apply_filters( 'jetpack_dismissed_notices', $jetpack_dismissed_notices ); | |
| 285 | + return $dismissed_notices; | |
| 286 | + } | |
| 287 | + | |
| 288 | + /** | |
| 289 | + * Returns an array of modules and settings both as first class members of the object. | |
| 290 | + * | |
| 291 | + * @return array flattened settings with modules. | |
| 292 | + */ | |
| 293 | + public static function get_flattened_settings() { | |
| 294 | + $core_api_endpoint = new Jetpack_Core_API_Data(); | |
| 295 | + $settings = $core_api_endpoint->get_all_options(); | |
| 296 | + return $settings->data; | |
| 297 | + } | |
| 298 | + | |
| 299 | + /** | |
| 300 | + * Returns the release post content and image data as an associative array. | |
| 301 | + * | |
| 302 | + * The update modal that consumed this data has been removed, so there is nothing to return. | |
| 303 | + * | |
| 304 | + * @deprecated 16.2 | |
| 305 | + * | |
| 306 | + * @return null | |
| 307 | + */ | |
| 308 | + public static function get_update_modal_data() { | |
| 309 | + _deprecated_function( __METHOD__, 'jetpack-16.2' ); | |
| 310 | + return null; | |
| 311 | + } | |
| 312 | + | |
| 313 | + /** | |
| 314 | + * Temporarily allow post content to contain iframes, e.g. for videopress. | |
| 315 | + * | |
| 316 | + * Only ever used while sanitizing the release post for the removed update modal. | |
| 317 | + * | |
| 318 | + * @deprecated 16.2 | |
| 319 | + * | |
| 320 | + * @param string $tags The tags. | |
| 321 | + * @param string $context The context. | |
| 322 | + */ | |
| 323 | + public static function allow_post_embed_iframe( $tags, $context ) { | |
| 324 | + _deprecated_function( __METHOD__, 'jetpack-16.2' ); | |
| 325 | + | |
| 326 | + if ( 'post' === $context ) { | |
| 327 | + $tags['iframe'] = array( | |
| 328 | + 'src' => true, | |
| 329 | + 'height' => true, | |
| 330 | + 'width' => true, | |
| 331 | + 'frameborder' => true, | |
| 332 | + 'allowfullscreen' => true, | |
| 333 | + ); | |
| 334 | + } | |
| 335 | + | |
| 336 | + return $tags; | |
| 337 | + } | |
| 338 | + | |
| 339 | + /** | |
| 340 | + * Obtains the release post from the Jetpack release post blog. | |
| 341 | + * | |
| 342 | + * The release post blog has had no post tagged for a current Jetpack version since 2023, and the | |
| 343 | + * update modal that consumed this has been removed, so this no longer makes a remote request. | |
| 344 | + * | |
| 345 | + * @deprecated 16.2 | |
| 346 | + * | |
| 347 | + * @return null | |
| 348 | + */ | |
| 349 | + public static function get_release_post_data() { | |
| 350 | + _deprecated_function( __METHOD__, 'jetpack-16.2' ); | |
| 351 | + return null; | |
| 352 | + } | |
| 353 | + | |
| 354 | + /** | |
| 355 | + * Get external services connect URLs. | |
| 356 | + */ | |
| 357 | + public static function get_external_services_connect_urls() { | |
| 358 | + $connect_urls = array(); | |
| 359 | + foreach ( Keyring_Helper::SERVICES as $service_name => $service_info ) { | |
| 360 | + $connect_urls[ $service_name ] = Keyring_Helper::connect_url( $service_name, $service_info['for'] ); | |
| 361 | + } | |
| 362 | + return $connect_urls; | |
| 363 | + } | |
| 364 | + | |
| 365 | + /** | |
| 366 | + * Gets a purchase token that is used for Jetpack logged out visitor checkout. | |
| 367 | + * The purchase token should be appended to all CTA url's that lead to checkout. | |
| 368 | + * | |
| 369 | + * @since 9.8.0 | |
| 370 | + * @return string|boolean | |
| 371 | + */ | |
| 372 | + public static function get_purchase_token() { | |
| 373 | + if ( ! Jetpack::current_user_can_purchase() ) { | |
| 374 | + return false; | |
| 375 | + } | |
| 376 | + | |
| 377 | + $purchase_token = Jetpack_Options::get_option( 'purchase_token', false ); | |
| 378 | + | |
| 379 | + if ( $purchase_token ) { | |
| 380 | + return $purchase_token; | |
| 381 | + } | |
| 382 | + // If the purchase token is not saved in the options table yet, then add it. | |
| 383 | + Jetpack_Options::update_option( 'purchase_token', self::generate_purchase_token(), true ); | |
| 384 | + return Jetpack_Options::get_option( 'purchase_token', false ); | |
| 385 | + } | |
| 386 | + | |
| 387 | + /** | |
| 388 | + * Generates a purchase token that is used for Jetpack logged out visitor checkout. | |
| 389 | + * | |
| 390 | + * @since 9.8.0 | |
| 391 | + * @return string | |
| 392 | + */ | |
| 393 | + public static function generate_purchase_token() { | |
| 394 | + return wp_generate_password( 12, false ); | |
| 395 | + } | |
| 396 | + | |
| 397 | + /** | |
| 398 | + * Get a representative image for the site. | |
| 399 | + * | |
| 400 | + * @since 15.0 | |
| 401 | + * | |
| 402 | + * @return string | |
| 403 | + */ | |
| 404 | + public static function get_site_image(): string { | |
| 405 | + // Get the dynamic image generated for the Open Graph Meta tags. | |
| 406 | + require_once JETPACK__PLUGIN_DIR . 'functions.opengraph.php'; | |
| 407 | + return jetpack_og_get_fallback_social_image( 200, 200 )['src']; | |
| 408 | + } | |
| 409 | +} | |
| 410 | + | |
| 411 | +// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move these functions to some other file. | |
| 412 | + | |
| 413 | +/** | |
| 414 | + * Gather data about the current user. | |
| 415 | + * | |
| 416 | + * @since 4.1.0 | |
| 417 | + * | |
| 418 | + * @return array | |
| 419 | + */ | |
| 420 | +function jetpack_current_user_data() { | |
| 421 | + $jetpack_connection = new Connection_Manager( 'jetpack' ); | |
| 422 | + | |
| 423 | + $current_user = wp_get_current_user(); | |
| 424 | + $is_user_connected = $jetpack_connection->is_user_connected( $current_user->ID ); | |
| 425 | + $is_master_user = $is_user_connected && (int) $current_user->ID && (int) Jetpack_Options::get_option( 'master_user' ) === (int) $current_user->ID; | |
| 426 | + $dotcom_data = $jetpack_connection->get_connected_user_data(); | |
| 427 | + | |
| 428 | + // Add connected user gravatar to the returned dotcom_data. | |
| 429 | + // Probably we shouldn't do this when $dotcom_data is false, but we have been since 2016 so | |
| 430 | + // clients probably expect that by now. | |
| 431 | + if ( false === $dotcom_data ) { | |
| 432 | + $dotcom_data = array(); | |
| 433 | + } | |
| 434 | + $dotcom_data['avatar'] = ( ! empty( $dotcom_data['email'] ) ? | |
| 435 | + get_avatar_url( | |
| 436 | + $dotcom_data['email'], | |
| 437 | + array( | |
| 438 | + 'size' => 64, | |
| 439 | + 'default' => 'mysteryman', | |
| 440 | + ) | |
| 441 | + ) | |
| 442 | + : false ); | |
| 443 | + | |
| 444 | + $current_user_data = array( | |
| 445 | + 'isConnected' => $is_user_connected, | |
| 446 | + 'isMaster' => $is_master_user, | |
| 447 | + 'username' => $current_user->user_login, | |
| 448 | + 'displayName' => $current_user->display_name, | |
| 449 | + 'email' => $current_user->user_email, | |
| 450 | + 'id' => $current_user->ID, | |
| 451 | + 'wpcomUser' => $dotcom_data, | |
| 452 | + 'gravatar' => get_avatar_url( $current_user->ID ), | |
| 453 | + 'permissions' => array( | |
| 454 | + 'admin_page' => current_user_can( 'jetpack_admin_page' ), | |
| 455 | + 'connect' => current_user_can( 'jetpack_connect' ), | |
| 456 | + 'connect_user' => current_user_can( 'jetpack_connect_user' ), | |
| 457 | + 'disconnect' => current_user_can( 'jetpack_disconnect' ), | |
| 458 | + 'manage_modules' => current_user_can( 'jetpack_manage_modules' ), | |
| 459 | + 'network_admin' => current_user_can( 'jetpack_network_admin_page' ), | |
| 460 | + 'network_sites_page' => current_user_can( 'jetpack_network_sites_page' ), | |
| 461 | + 'edit_posts' => current_user_can( 'edit_posts' ), | |
| 462 | + 'publish_posts' => current_user_can( 'publish_posts' ), | |
| 463 | + 'manage_options' => current_user_can( 'manage_options' ), | |
| 464 | + 'view_stats' => current_user_can( 'view_stats' ), | |
| 465 | + 'manage_plugins' => current_user_can( 'install_plugins' ) | |
| 466 | + && current_user_can( 'activate_plugins' ) | |
| 467 | + && current_user_can( 'update_plugins' ) | |
| 468 | + && current_user_can( 'delete_plugins' ), | |
| 469 | + ), | |
| 470 | + ); | |
| 471 | + | |
| 472 | + return $current_user_data; | |
| 473 | +} | |