PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 14.7.1
Jetpack – WP Security, Backup, Speed, & Growth v14.7.1
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / _inc / lib / admin-pages / class-jetpack-redux-state-helper.php
jetpack / _inc / lib / admin-pages Last commit date
class-jetpack-about-page.php 1 year ago class-jetpack-redux-state-helper.php 1 year ago class.jetpack-admin-page.php 1 year ago class.jetpack-landing-page.php 2 years ago class.jetpack-react-page.php 1 year ago class.jetpack-settings-page.php 3 years ago
class-jetpack-redux-state-helper.php
500 lines
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\Boost_Speed_Score\Speed_Score_History;
11 use Automattic\Jetpack\Connection\Manager as Connection_Manager;
12 use Automattic\Jetpack\Connection\Plugin_Storage as Connection_Plugin_Storage;
13 use Automattic\Jetpack\Connection\REST_Connector;
14 use Automattic\Jetpack\Constants;
15 use Automattic\Jetpack\Current_Plan as Jetpack_Plan;
16 use Automattic\Jetpack\Device_Detection\User_Agent_Info;
17 use Automattic\Jetpack\Identity_Crisis;
18 use Automattic\Jetpack\Image_CDN\Image_CDN_Core;
19 use Automattic\Jetpack\Image_CDN\Image_CDN_Image;
20 use Automattic\Jetpack\IP\Utils as IP_Utils;
21 use Automattic\Jetpack\Licensing;
22 use Automattic\Jetpack\Licensing\Endpoints as Licensing_Endpoints;
23 use Automattic\Jetpack\My_Jetpack\Initializer as My_Jetpack_Initializer;
24 use Automattic\Jetpack\My_Jetpack\Jetpack_Manage;
25 use Automattic\Jetpack\Partner;
26 use Automattic\Jetpack\Partner_Coupon as Jetpack_Partner_Coupon;
27 use Automattic\Jetpack\Publicize\Keyring_Helper;
28 use Automattic\Jetpack\Stats\Options as Stats_Options;
29 use Automattic\Jetpack\Status;
30 use Automattic\Jetpack\Status\Host;
31
32 /**
33 * Responsible for populating the initial Redux state.
34 */
35 class Jetpack_Redux_State_Helper {
36 /**
37 * Generate minimal state for React to fetch its own data asynchronously after load
38 * This can improve user experience, reducing time spent on server requests before serving the page
39 * e.g. used by React Disconnect Dialog on plugins page where the full initial state is not needed
40 */
41 public static function get_minimal_state() {
42 return array(
43 'WP_API_root' => esc_url_raw( rest_url() ),
44 'WP_API_nonce' => wp_create_nonce( 'wp_rest' ),
45 );
46 }
47
48 /**
49 * Generate the initial state array to be used by the Redux store.
50 */
51 public static function get_initial_state() {
52 global $is_safari;
53
54 // Load API endpoint base classes and endpoints for getting the module list fed into the JS Admin Page.
55 require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-xmlrpc-consumer-endpoint.php';
56 require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php';
57 require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-site-endpoints.php';
58
59 $module_list_endpoint = new Jetpack_Core_API_Module_List_Endpoint();
60 $modules = $module_list_endpoint->get_modules();
61
62 // Preparing translated fields for JSON encoding by transforming all HTML entities to
63 // respective characters.
64 foreach ( $modules as $slug => $data ) {
65 $modules[ $slug ]['name'] = html_entity_decode( $data['name'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );
66 $modules[ $slug ]['description'] = html_entity_decode( $data['description'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );
67 $modules[ $slug ]['short_description'] = html_entity_decode( $data['short_description'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );
68 $modules[ $slug ]['long_description'] = html_entity_decode( $data['long_description'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );
69 }
70
71 // "mock" a block module in order to get it searchable in the settings.
72 $modules['blocks']['module'] = 'blocks';
73 $modules['blocks']['additional_search_queries'] = esc_html_x( 'blocks, block, gutenberg', 'Search terms', 'jetpack' );
74
75 // "mock" an Earn module in order to get it searchable in the settings.
76 $modules['earn']['module'] = 'earn';
77 $modules['earn']['additional_search_queries'] = esc_html_x( 'earn, paypal, stripe, payments, pay', 'Search terms', 'jetpack' );
78
79 // Collecting roles that can view site stats.
80 $stats_roles = array();
81 $enabled_roles = Stats_Options::get_option( 'roles' );
82
83 if ( ! function_exists( 'get_editable_roles' ) ) {
84 require_once ABSPATH . 'wp-admin/includes/user.php';
85 }
86 foreach ( get_editable_roles() as $slug => $role ) {
87 $stats_roles[ $slug ] = array(
88 'name' => translate_user_role( $role['name'] ),
89 'canView' => is_array( $enabled_roles ) ? in_array( $slug, $enabled_roles, true ) : false,
90 );
91 }
92
93 // Get information about current theme.
94 $current_theme = wp_get_theme();
95
96 // Get all themes that Infinite Scroll provides support for natively.
97 $inf_scr_support_themes = array();
98 foreach ( Jetpack::glob_php( JETPACK__PLUGIN_DIR . 'modules/infinite-scroll/themes' ) as $path ) {
99 if ( is_readable( $path ) ) {
100 $inf_scr_support_themes[] = basename( $path, '.php' );
101 }
102 }
103
104 // Get last post, to build the link to Customizer in the Related Posts module.
105 $last_post = get_posts( array( 'posts_per_page' => 1 ) );
106 $last_post = isset( $last_post[0] ) && $last_post[0] instanceof WP_Post
107 ? get_permalink( $last_post[0]->ID )
108 : get_home_url();
109
110 $current_user_data = jetpack_current_user_data();
111
112 /**
113 * Adds information to the `connectionStatus` API field that is unique to the Jetpack React dashboard.
114 */
115 $connection_status = array(
116 'isInIdentityCrisis' => Identity_Crisis::validate_sync_error_idc_option(),
117 'sandboxDomain' => JETPACK__SANDBOX_DOMAIN,
118
119 /**
120 * Filter to add connection errors
121 * Format: array( array( 'code' => '...', 'message' => '...', 'action' => '...' ), ... )
122 *
123 * @since 8.7.0
124 *
125 * @param array $errors Connection errors.
126 */
127 'errors' => apply_filters( 'react_connection_errors_initial_state', array() ),
128 );
129
130 $connection_status = array_merge( REST_Connector::connection_status( false ), $connection_status );
131
132 $host = new Host();
133
134 $speed_score_history = new Speed_Score_History( wp_parse_url( get_site_url(), PHP_URL_HOST ) );
135
136 $block_availability = Jetpack_Gutenberg::get_cached_availability();
137
138 return array(
139 'WP_API_root' => esc_url_raw( rest_url() ),
140 'WP_API_nonce' => wp_create_nonce( 'wp_rest' ),
141 'registrationNonce' => '', // Not used, keeping it for compatibility reasons, see https://github.com/Automattic/jetpack/pull/42076
142 'purchaseToken' => self::get_purchase_token(),
143 'partnerCoupon' => Jetpack_Partner_Coupon::get_coupon(),
144 'pluginBaseUrl' => plugins_url( '', JETPACK__PLUGIN_FILE ),
145 'connectionStatus' => $connection_status,
146 'connectedPlugins' => Connection_Plugin_Storage::get_all(),
147 'connectUrl' => false == $current_user_data['isConnected'] // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
148 ? Jetpack::init()->build_connect_url( true, false, false )
149 : '',
150 'dismissedNotices' => self::get_dismissed_jetpack_notices(),
151 'isDevVersion' => Jetpack::is_development_version(),
152 'currentVersion' => JETPACK__VERSION,
153 'is_gutenberg_available' => true,
154 'getModules' => $modules,
155 'rawUrl' => ( new Status() )->get_site_suffix(),
156 'adminUrl' => esc_url( admin_url() ),
157 'siteTitle' => (string) htmlspecialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
158 'stats' => array(
159 // data is populated asynchronously on page load.
160 'data' => array(
161 'general' => false,
162 'day' => false,
163 'week' => false,
164 'month' => false,
165 ),
166 'roles' => $stats_roles,
167 ),
168 'aff' => Partner::init()->get_partner_code( Partner::AFFILIATE_CODE ),
169 'partnerSubsidiaryId' => Partner::init()->get_partner_code( Partner::SUBSIDIARY_CODE ),
170 'settings' => self::get_flattened_settings(),
171 'userData' => array(
172 'currentUser' => $current_user_data,
173 ),
174 'siteData' => array(
175 'blog_id' => Jetpack_Options::get_option( 'id', 0 ),
176 'icon' => has_site_icon()
177 ? apply_filters( 'jetpack_photon_url', get_site_icon_url(), array( 'w' => 64 ) )
178 : '',
179 'siteVisibleToSearchEngines' => '1' == get_option( 'blog_public' ), // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual
180 /**
181 * Whether promotions are visible or not.
182 *
183 * @since 4.8.0
184 *
185 * @param bool $are_promotions_active Status of promotions visibility. True by default.
186 */
187 'showPromotions' => apply_filters( 'jetpack_show_promotions', true ),
188 'isAtomicSite' => $host->is_woa_site(), // do not use - to be removed.
189 'isWoASite' => $host->is_woa_site(),
190 'isAtomicPlatform' => $host->is_atomic_platform(),
191 'plan' => Jetpack_Plan::get(),
192 'showBackups' => Jetpack::show_backups_ui(),
193 'showRecommendations' => Jetpack_Recommendations::is_enabled(),
194 /** This filter is documented in my-jetpack/src/class-initializer.php */
195 'showMyJetpack' => My_Jetpack_Initializer::should_initialize(),
196 'isMultisite' => is_multisite(),
197 'dateFormat' => get_option( 'date_format' ),
198 'latestBoostSpeedScores' => $speed_score_history->latest(),
199 'isSharingBlockAvailable' => (bool) isset( $block_availability['sharing-buttons'] )
200 && $block_availability['sharing-buttons']['available'],
201 ),
202 'themeData' => array(
203 'name' => $current_theme->get( 'Name' ),
204 'stylesheet' => $current_theme->get_stylesheet(),
205 'hasUpdate' => (bool) get_theme_update_available( $current_theme ),
206 'isBlockTheme' => (bool) $current_theme->is_block_theme(),
207 'support' => array(
208 'infinite-scroll' => current_theme_supports( 'infinite-scroll' ) || in_array( $current_theme->get_stylesheet(), $inf_scr_support_themes, true ),
209 'widgets' => current_theme_supports( 'widgets' ),
210 'webfonts' => wp_theme_has_theme_json()
211 && ( function_exists( 'wp_register_webfont_provider' ) || function_exists( 'wp_register_webfonts' ) ),
212 ),
213 ),
214 'jetpackStateNotices' => array(
215 'messageCode' => Jetpack::state( 'message' ),
216 'errorCode' => Jetpack::state( 'error' ),
217 'errorDescription' => Jetpack::state( 'error_description' ),
218 'messageContent' => Jetpack::state( 'display_update_modal' ) ? self::get_update_modal_data() : null,
219 ),
220 'tracksUserData' => Jetpack_Tracks_Client::get_connected_user_tracks_identity(),
221 'currentIp' => IP_Utils::get_ip(),
222 'lastPostUrl' => esc_url( $last_post ),
223 'externalServicesConnectUrls' => self::get_external_services_connect_urls(),
224 'calypsoEnv' => ( new Host() )->get_calypso_env(),
225 'products' => Jetpack::get_products_for_purchase(),
226 'recommendationsStep' => Jetpack_Core_Json_Api_Endpoints::get_recommendations_step()['step'],
227 'isSafari' => $is_safari || User_Agent_Info::is_opera_desktop(), // @todo Rename isSafari everywhere.
228 'doNotUseConnectionIframe' => Constants::is_true( 'JETPACK_SHOULD_NOT_USE_CONNECTION_IFRAME' ),
229 'licensing' => array(
230 'error' => Licensing::instance()->last_error(),
231 'showLicensingUi' => Licensing::instance()->is_licensing_input_enabled(),
232 'userCounts' => Licensing_Endpoints::get_user_license_counts(),
233 'activationNoticeDismiss' => Licensing::instance()->get_license_activation_notice_dismiss(),
234 ),
235 'jetpackManage' => array(
236 'isEnabled' => Jetpack_Manage::could_use_jp_manage(),
237 'isAgencyAccount' => Jetpack_Manage::is_agency_account(),
238 ),
239 'hasSeenWCConnectionModal' => Jetpack_Options::get_option( 'has_seen_wc_connection_modal', false ),
240 'newRecommendations' => Jetpack_Recommendations::get_new_conditional_recommendations(),
241 // Check if WooCommerce plugin is active (based on https://docs.woocommerce.com/document/create-a-plugin/).
242 'isWooCommerceActive' => in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', Jetpack::get_active_plugins() ), true ),
243 'useMyJetpackLicensingUI' => My_Jetpack_Initializer::is_licensing_ui_enabled(),
244 'isOdysseyStatsEnabled' => Stats_Options::get_option( 'enable_odyssey_stats' ),
245 'shouldInitializeBlaze' => Blaze::should_initialize(),
246 'isBlazeDashboardEnabled' => Blaze::is_dashboard_enabled(),
247 'isSubscriptionSiteEnabled' => apply_filters( 'jetpack_subscription_site_enabled', false ),
248 'newsletterDateExample' => gmdate( get_option( 'date_format' ), time() ),
249 'subscriptionSiteEditSupported' => $current_theme->is_block_theme(),
250 /* This filter is already documented in jetpack/modules/subscriptions.php */
251 'isWpAdminSubscriberManagementEnabled' => apply_filters( 'jetpack_wp_admin_subscriber_management_enabled', false ),
252 );
253 }
254
255 /**
256 * Gets array of any Jetpack notices that have been dismissed.
257 *
258 * @return mixed|void
259 */
260 public static function get_dismissed_jetpack_notices() {
261 $jetpack_dismissed_notices = get_option( 'jetpack_dismissed_notices', array() );
262 /**
263 * Array of notices that have been dismissed.
264 *
265 * @param array $jetpack_dismissed_notices If empty, will not show any Jetpack notices.
266 */
267 $dismissed_notices = apply_filters( 'jetpack_dismissed_notices', $jetpack_dismissed_notices );
268 return $dismissed_notices;
269 }
270
271 /**
272 * Returns an array of modules and settings both as first class members of the object.
273 *
274 * @return array flattened settings with modules.
275 */
276 public static function get_flattened_settings() {
277 $core_api_endpoint = new Jetpack_Core_API_Data();
278 $settings = $core_api_endpoint->get_all_options();
279 return $settings->data;
280 }
281
282 /**
283 * Returns the release post content and image data as an associative array.
284 * This data is used to create the update modal.
285 */
286 public static function get_update_modal_data() {
287 $post_data = self::get_release_post_data();
288
289 if ( ! isset( $post_data['posts'][0] ) ) {
290 return;
291 }
292
293 $post = $post_data['posts'][0];
294
295 if ( empty( $post['content'] ) ) {
296 return;
297 }
298
299 // This allows us to embed videopress videos into the release post.
300 add_filter( 'wp_kses_allowed_html', array( __CLASS__, 'allow_post_embed_iframe' ), 10, 2 );
301 $content = wp_kses_post( $post['content'] );
302 remove_filter( 'wp_kses_allowed_html', array( __CLASS__, 'allow_post_embed_iframe' ), 10 );
303
304 $post_title = isset( $post['title'] ) ? $post['title'] : null;
305 $title = wp_kses( $post_title, array() );
306
307 $post_thumbnail = isset( $post['post_thumbnail'] ) ? $post['post_thumbnail'] : null;
308 if ( ! empty( $post_thumbnail ) ) {
309 $photon_image = new Image_CDN_Image(
310 array(
311 'file' => Image_CDN_Core::cdn_url( $post_thumbnail['URL'] ),
312 'width' => $post_thumbnail['width'],
313 'height' => $post_thumbnail['height'],
314 ),
315 $post_thumbnail['mime_type']
316 );
317 $photon_image->resize(
318 array(
319 'width' => 600,
320 'height' => null,
321 'crop' => false,
322 )
323 );
324 $post_thumbnail_url = $photon_image->get_raw_filename();
325 } else {
326 $post_thumbnail_url = null;
327 }
328
329 $post_array = array(
330 'release_post_content' => $content,
331 'release_post_featured_image' => $post_thumbnail_url,
332 'release_post_title' => $title,
333 );
334
335 return $post_array;
336 }
337
338 /**
339 * Temporarily allow post content to contain iframes, e.g. for videopress.
340 *
341 * @param string $tags The tags.
342 * @param string $context The context.
343 */
344 public static function allow_post_embed_iframe( $tags, $context ) {
345 if ( 'post' === $context ) {
346 $tags['iframe'] = array(
347 'src' => true,
348 'height' => true,
349 'width' => true,
350 'frameborder' => true,
351 'allowfullscreen' => true,
352 );
353 }
354
355 return $tags;
356 }
357
358 /**
359 * Obtains the release post from the Jetpack release post blog. A release post will be displayed in the
360 * update modal when a post has a tag equal to the Jetpack version number.
361 *
362 * The response parameters for the post array can be found here:
363 * https://developer.wordpress.com/docs/api/1.1/get/sites/%24site/posts/%24post_ID/#apidoc-response
364 *
365 * @return array|null Returns an associative array containing the release post data at index ['posts'][0].
366 * Returns null if the release post data is not available.
367 */
368 public static function get_release_post_data() {
369 if ( Constants::is_defined( 'TESTING_IN_JETPACK' ) && Constants::get_constant( 'TESTING_IN_JETPACK' ) ) {
370 return null;
371 }
372
373 $release_post_src = add_query_arg(
374 array(
375 'order_by' => 'date',
376 'tag' => JETPACK__VERSION,
377 'number' => '1',
378 ),
379 'https://public-api.wordpress.com/rest/v1/sites/' . JETPACK__RELEASE_POST_BLOG_SLUG . '/posts'
380 );
381
382 $response = wp_remote_get( $release_post_src );
383
384 if ( ! is_array( $response ) ) {
385 return null;
386 }
387
388 return json_decode( wp_remote_retrieve_body( $response ), true );
389 }
390
391 /**
392 * Get external services connect URLs.
393 */
394 public static function get_external_services_connect_urls() {
395 $connect_urls = array();
396 // phpcs:disable
397 foreach ( Keyring_Helper::SERVICES as $service_name => $service_info ) {
398 // phpcs:enable
399 $connect_urls[ $service_name ] = Keyring_Helper::connect_url( $service_name, $service_info['for'] );
400 }
401 return $connect_urls;
402 }
403
404 /**
405 * Gets a purchase token that is used for Jetpack logged out visitor checkout.
406 * The purchase token should be appended to all CTA url's that lead to checkout.
407 *
408 * @since 9.8.0
409 * @return string|boolean
410 */
411 public static function get_purchase_token() {
412 if ( ! Jetpack::current_user_can_purchase() ) {
413 return false;
414 }
415
416 $purchase_token = Jetpack_Options::get_option( 'purchase_token', false );
417
418 if ( $purchase_token ) {
419 return $purchase_token;
420 }
421 // If the purchase token is not saved in the options table yet, then add it.
422 Jetpack_Options::update_option( 'purchase_token', self::generate_purchase_token(), true );
423 return Jetpack_Options::get_option( 'purchase_token', false );
424 }
425
426 /**
427 * Generates a purchase token that is used for Jetpack logged out visitor checkout.
428 *
429 * @since 9.8.0
430 * @return string
431 */
432 public static function generate_purchase_token() {
433 return wp_generate_password( 12, false );
434 }
435 }
436
437 // phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move these functions to some other file.
438
439 /**
440 * Gather data about the current user.
441 *
442 * @since 4.1.0
443 *
444 * @return array
445 */
446 function jetpack_current_user_data() {
447 $jetpack_connection = new Connection_Manager( 'jetpack' );
448
449 $current_user = wp_get_current_user();
450 $is_user_connected = $jetpack_connection->is_user_connected( $current_user->ID );
451 $is_master_user = $is_user_connected && (int) $current_user->ID && (int) Jetpack_Options::get_option( 'master_user' ) === (int) $current_user->ID;
452 $dotcom_data = $jetpack_connection->get_connected_user_data();
453
454 // Add connected user gravatar to the returned dotcom_data.
455 // Probably we shouldn't do this when $dotcom_data is false, but we have been since 2016 so
456 // clients probably expect that by now.
457 if ( false === $dotcom_data ) {
458 $dotcom_data = array();
459 }
460 $dotcom_data['avatar'] = ( ! empty( $dotcom_data['email'] ) ?
461 get_avatar_url(
462 $dotcom_data['email'],
463 array(
464 'size' => 64,
465 'default' => 'mysteryman',
466 )
467 )
468 : false );
469
470 $current_user_data = array(
471 'isConnected' => $is_user_connected,
472 'isMaster' => $is_master_user,
473 'username' => $current_user->user_login,
474 'displayName' => $current_user->display_name,
475 'email' => $current_user->user_email,
476 'id' => $current_user->ID,
477 'wpcomUser' => $dotcom_data,
478 'gravatar' => get_avatar_url( $current_user->ID ),
479 'permissions' => array(
480 'admin_page' => current_user_can( 'jetpack_admin_page' ),
481 'connect' => current_user_can( 'jetpack_connect' ),
482 'connect_user' => current_user_can( 'jetpack_connect_user' ),
483 'disconnect' => current_user_can( 'jetpack_disconnect' ),
484 'manage_modules' => current_user_can( 'jetpack_manage_modules' ),
485 'network_admin' => current_user_can( 'jetpack_network_admin_page' ),
486 'network_sites_page' => current_user_can( 'jetpack_network_sites_page' ),
487 'edit_posts' => current_user_can( 'edit_posts' ),
488 'publish_posts' => current_user_can( 'publish_posts' ),
489 'manage_options' => current_user_can( 'manage_options' ),
490 'view_stats' => current_user_can( 'view_stats' ),
491 'manage_plugins' => current_user_can( 'install_plugins' )
492 && current_user_can( 'activate_plugins' )
493 && current_user_can( 'update_plugins' )
494 && current_user_can( 'delete_plugins' ),
495 ),
496 );
497
498 return $current_user_data;
499 }
500