PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.0.1
Jetpack – WP Security, Backup, Speed, & Growth v16.0.1
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 / jetpack_vendor / automattic / jetpack-sync / src / class-functions.php
jetpack / jetpack_vendor / automattic / jetpack-sync / src Last commit date
modules 3 weeks ago replicastore 3 months ago sync-queue 5 months ago class-actions.php 1 month ago class-activity-log-event.php 3 weeks ago class-data-settings.php 1 month ago class-dedicated-sender.php 7 months ago class-default-filter-settings.php 4 years ago class-defaults.php 2 days ago class-functions.php 1 month ago class-health.php 4 months ago class-json-deflate-array-codec.php 7 months ago class-listener.php 1 month ago class-lock.php 4 years ago class-main.php 2 months ago class-modules.php 1 year ago class-package-version.php 2 days ago class-queue-buffer.php 4 years ago class-queue.php 1 month ago class-replicastore.php 1 month ago class-rest-endpoints.php 4 months ago class-rest-sender.php 1 month ago class-sender.php 1 month ago class-server.php 4 months ago class-settings.php 3 months ago class-simple-codec.php 7 months ago class-users.php 3 months ago class-utils.php 4 years ago interface-codec.php 4 years ago interface-replicastore.php 1 month ago
class-functions.php
764 lines
1 <?php
2 /**
3 * Utility functions to generate data synced to wpcom
4 *
5 * @package automattic/jetpack-sync
6 */
7
8 namespace Automattic\Jetpack\Sync;
9
10 use Automattic\Jetpack\Connection\Manager;
11 use Automattic\Jetpack\Connection\Urls;
12 use Automattic\Jetpack\Constants;
13 use Automattic\Jetpack\Modules as Jetpack_Modules;
14
15 /**
16 * Utility functions to generate data synced to wpcom
17 */
18 class Functions {
19 const HTTPS_CHECK_OPTION_PREFIX = 'jetpack_sync_https_history_';
20 const HTTPS_CHECK_HISTORY = 5;
21
22 /**
23 * Return array of Jetpack modules.
24 *
25 * @return array
26 */
27 public static function get_modules() {
28 if ( defined( 'JETPACK__PLUGIN_DIR' ) ) {
29 require_once JETPACK__PLUGIN_DIR . 'class.jetpack-admin.php';
30
31 return \Jetpack_Admin::init()->get_modules();
32 }
33
34 return array();
35 }
36
37 /**
38 * Return array of taxonomies registered on the site.
39 *
40 * @return array
41 */
42 public static function get_taxonomies() {
43 global $wp_taxonomies;
44 $wp_taxonomies_without_callbacks = array();
45 foreach ( $wp_taxonomies as $taxonomy_name => $taxonomy ) {
46 $sanitized_taxonomy = self::sanitize_taxonomy( $taxonomy );
47 if ( ! empty( $sanitized_taxonomy ) ) {
48 $wp_taxonomies_without_callbacks[ $taxonomy_name ] = $sanitized_taxonomy;
49 }
50 }
51 return $wp_taxonomies_without_callbacks;
52 }
53
54 /**
55 * Return array of registered shortcodes.
56 *
57 * @return array
58 */
59 public static function get_shortcodes() {
60 global $shortcode_tags;
61 return array_keys( $shortcode_tags );
62 }
63
64 /**
65 * Removes any callback data since we will not be able to process it on our side anyways.
66 *
67 * @param \WP_Taxonomy $taxonomy \WP_Taxonomy item.
68 *
69 * @return mixed|null
70 */
71 public static function sanitize_taxonomy( $taxonomy ) {
72
73 // Lets clone the taxonomy object instead of modifing the global one.
74 $cloned_taxonomy = json_decode( wp_json_encode( $taxonomy, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) );
75
76 // recursive taxonomies are no fun.
77 if ( $cloned_taxonomy === null ) {
78 return null;
79 }
80 // Remove any meta_box_cb if they are not the default wp ones.
81 if ( isset( $cloned_taxonomy->meta_box_cb ) &&
82 ! in_array( $cloned_taxonomy->meta_box_cb, array( 'post_tags_meta_box', 'post_categories_meta_box' ), true ) ) {
83 $cloned_taxonomy->meta_box_cb = null;
84 }
85 // Remove update call back.
86 if ( isset( $cloned_taxonomy->update_count_callback ) &&
87 $cloned_taxonomy->update_count_callback !== null ) {
88 $cloned_taxonomy->update_count_callback = null;
89 }
90 // Remove rest_controller_class if it something other then the default.
91 if ( isset( $cloned_taxonomy->rest_controller_class ) &&
92 'WP_REST_Terms_Controller' !== $cloned_taxonomy->rest_controller_class ) {
93 $cloned_taxonomy->rest_controller_class = null;
94 }
95 return $cloned_taxonomy;
96 }
97
98 /**
99 * Return array of registered post types.
100 *
101 * @return array
102 */
103 public static function get_post_types() {
104 global $wp_post_types;
105
106 $post_types_without_callbacks = array();
107 foreach ( $wp_post_types as $post_type_name => $post_type ) {
108 $sanitized_post_type = self::sanitize_post_type( $post_type );
109 if ( ! empty( $sanitized_post_type ) ) {
110 $post_types_without_callbacks[ $post_type_name ] = $sanitized_post_type;
111 }
112 }
113 return $post_types_without_callbacks;
114 }
115
116 /**
117 * Sanitizes by cloning post type object.
118 *
119 * @param object $post_type \WP_Post_Type.
120 *
121 * @return object
122 */
123 public static function sanitize_post_type( $post_type ) {
124 // Lets clone the post type object instead of modifing the global one.
125 $sanitized_post_type = array();
126 foreach ( Defaults::$default_post_type_attributes as $attribute_key => $default_value ) {
127 if ( isset( $post_type->{ $attribute_key } ) ) {
128 $sanitized_post_type[ $attribute_key ] = $post_type->{ $attribute_key };
129 }
130 }
131 return (object) $sanitized_post_type;
132 }
133
134 /**
135 * Return information about a synced post type.
136 *
137 * @param array $sanitized_post_type Array of args used in constructing \WP_Post_Type.
138 * @param string $post_type Post type name.
139 *
140 * @return object \WP_Post_Type
141 */
142 public static function expand_synced_post_type( $sanitized_post_type, $post_type ) {
143 $post_type = sanitize_key( $post_type );
144 $post_type_object = new \WP_Post_Type( $post_type, $sanitized_post_type );
145 $post_type_object->add_supports();
146 $post_type_object->add_rewrite_rules();
147 $post_type_object->add_hooks();
148 $post_type_object->register_taxonomies();
149 return $post_type_object;
150 }
151
152 /**
153 * Returns site's post_type_features.
154 *
155 * @return array
156 */
157 public static function get_post_type_features() {
158 global $_wp_post_type_features;
159
160 return $_wp_post_type_features;
161 }
162
163 /**
164 * Return hosting provider.
165 *
166 * Uses a set of known constants, classes, or functions to help determine the hosting platform.
167 *
168 * @return string Hosting provider.
169 */
170 public static function get_hosting_provider() {
171 $hosting_provider_detection_methods = array(
172 'get_hosting_provider_by_known_constant',
173 'get_hosting_provider_by_known_class',
174 'get_hosting_provider_by_known_function',
175 );
176
177 $functions = new Functions();
178 foreach ( $hosting_provider_detection_methods as $method ) {
179 $hosting_provider = call_user_func( array( $functions, $method ) );
180 if ( false !== $hosting_provider ) {
181 return $hosting_provider;
182 }
183 }
184
185 return 'unknown';
186 }
187
188 /**
189 * Return a hosting provider using a set of known constants.
190 *
191 * @return mixed A host identifier string or false.
192 */
193 public function get_hosting_provider_by_known_constant() {
194 $hosting_provider_constants = array(
195 'GD_SYSTEM_PLUGIN_DIR' => 'gd-managed-wp',
196 'MM_BASE_DIR' => 'bh',
197 'PAGELYBIN' => 'pagely',
198 'KINSTAMU_VERSION' => 'kinsta',
199 'FLYWHEEL_CONFIG_DIR' => 'flywheel',
200 'IS_PRESSABLE' => 'pressable',
201 'VIP_GO_ENV' => 'vip-go',
202 );
203
204 foreach ( $hosting_provider_constants as $constant => $constant_value ) {
205 if ( Constants::is_defined( $constant ) ) {
206 if ( 'VIP_GO_ENV' === $constant && false === Constants::get_constant( 'VIP_GO_ENV' ) ) {
207 continue;
208 }
209 return $constant_value;
210 }
211 }
212
213 return false;
214 }
215
216 /**
217 * Return a hosting provider using a set of known classes.
218 *
219 * @return mixed A host identifier string or false.
220 */
221 public function get_hosting_provider_by_known_class() {
222 $hosting_provider = false;
223
224 switch ( true ) {
225 case ( class_exists( '\\WPaaS\\Plugin' ) ):
226 $hosting_provider = 'gd-managed-wp';
227 break;
228 }
229
230 return $hosting_provider;
231 }
232
233 /**
234 * Return a hosting provider using a set of known functions.
235 *
236 * @return mixed A host identifier string or false.
237 */
238 public function get_hosting_provider_by_known_function() {
239 $hosting_provider = false;
240
241 switch ( true ) {
242 case ( function_exists( 'is_wpe' ) || function_exists( 'is_wpe_snapshot' ) ):
243 $hosting_provider = 'wpe';
244 break;
245 }
246
247 return $hosting_provider;
248 }
249
250 /**
251 * Return array of allowed REST API post types.
252 *
253 * @return array Array of allowed post types.
254 */
255 public static function rest_api_allowed_post_types() {
256 /** This filter is already documented in class.json-api-endpoints.php */
257 return apply_filters( 'rest_api_allowed_post_types', array( 'post', 'page', 'revision' ) );
258 }
259
260 /**
261 * Return array of allowed REST API public metadata.
262 *
263 * @return array Array of allowed metadata.
264 */
265 public static function rest_api_allowed_public_metadata() {
266 /**
267 * Filters the meta keys accessible by the REST API.
268 *
269 * @see https://developer.wordpress.com/2013/04/26/custom-post-type-and-metadata-support-in-the-rest-api/
270 *
271 * @module json-api
272 *
273 * @since 1.6.3
274 * @since-jetpack 2.2.3
275 *
276 * @param array $whitelisted_meta Array of metadata that is accessible by the REST API.
277 */
278 return apply_filters( 'rest_api_allowed_public_metadata', array() );
279 }
280
281 /**
282 * Finds out if a site is using a version control system.
283 *
284 * @return bool
285 **/
286 public static function is_version_controlled() {
287
288 if ( ! class_exists( 'WP_Automatic_Updater' ) ) {
289 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
290 }
291 $updater = new \WP_Automatic_Updater();
292
293 return (bool) (string) $updater->is_vcs_checkout( ABSPATH );
294 }
295
296 /**
297 * Returns true if the site has file write access false otherwise.
298 *
299 * @return bool
300 **/
301 public static function file_system_write_access() {
302 if ( ! function_exists( 'get_filesystem_method' ) ) {
303 require_once ABSPATH . 'wp-admin/includes/file.php';
304 }
305
306 require_once ABSPATH . 'wp-admin/includes/template.php';
307
308 $filesystem_method = get_filesystem_method();
309 if ( 'direct' === $filesystem_method ) {
310 return true;
311 }
312
313 ob_start();
314
315 if ( ! function_exists( 'request_filesystem_credentials' ) ) {
316 require_once ABSPATH . 'wp-admin/includes/file.php';
317 }
318
319 $filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() );
320 ob_end_clean();
321 if ( $filesystem_credentials_are_stored ) {
322 return true;
323 }
324
325 return false;
326 }
327
328 /**
329 * Helper function that is used when getting home or siteurl values. Decides
330 * whether to get the raw or filtered value.
331 *
332 * @deprecated 1.23.1
333 *
334 * @param string $url_type URL to get, home or siteurl.
335 * @return string
336 */
337 public static function get_raw_or_filtered_url( $url_type ) {
338 _deprecated_function( __METHOD__, '1.23.1', '\\Automattic\\Jetpack\\Connection\\Urls::get_raw_or_filtered_url' );
339 return Urls::get_raw_or_filtered_url( $url_type );
340 }
341
342 /**
343 * Return the escaped home_url.
344 *
345 * @deprecated 1.23.1
346 *
347 * @return string
348 */
349 public static function home_url() {
350 _deprecated_function( __METHOD__, '1.23.1', '\\Automattic\\Jetpack\\Connection\\Urls::home_url' );
351 return Urls::home_url();
352 }
353
354 /**
355 * Return the escaped siteurl.
356 *
357 * @deprecated 1.23.1
358 *
359 * @return string
360 */
361 public static function site_url() {
362 _deprecated_function( __METHOD__, '1.23.1', '\\Automattic\\Jetpack\\Connection\\Urls::site_url' );
363 return Urls::site_url();
364 }
365
366 /**
367 * Return main site URL with a normalized protocol.
368 *
369 * @deprecated 1.23.1
370 *
371 * @return string
372 */
373 public static function main_network_site_url() {
374 _deprecated_function( __METHOD__, '1.23.1', '\\Automattic\\Jetpack\\Connection\\Urls::main_network_site_url' );
375 return Urls::main_network_site_url();
376 }
377
378 /**
379 * Return main site WordPress.com site ID.
380 *
381 * @return string
382 */
383 public static function main_network_site_wpcom_id() {
384 /**
385 * Return the current site WPCOM ID for single site installs
386 */
387 if ( ! is_multisite() ) {
388 return \Jetpack_Options::get_option( 'id' );
389 }
390
391 /**
392 * Return the main network site WPCOM ID for multi-site installs
393 */
394 $current_network = get_network();
395 switch_to_blog( $current_network->blog_id );
396 $wpcom_blog_id = \Jetpack_Options::get_option( 'id' );
397 restore_current_blog();
398 return $wpcom_blog_id;
399 }
400
401 /**
402 * Return URL with a normalized protocol.
403 *
404 * @deprecated 1.23.1
405 *
406 * @param string $callable Function name that was used to retrieve URL option.
407 * @param string $new_value URL Protocol to set URLs to.
408 * @return string Normalized URL.
409 */
410 public static function get_protocol_normalized_url( $callable, $new_value ) {
411 _deprecated_function( __METHOD__, '1.23.1', '\\Automattic\\Jetpack\\Connection\\Urls::get_protocol_normalized_url' );
412 return Urls::get_protocol_normalized_url( $callable, $new_value );
413 }
414
415 /**
416 * Return URL from option or PHP constant.
417 *
418 * @deprecated 1.23.1
419 *
420 * @param string $option_name (e.g. 'home').
421 *
422 * @return mixed|null URL.
423 */
424 public static function get_raw_url( $option_name ) {
425 _deprecated_function( __METHOD__, '1.23.1', '\\Automattic\\Jetpack\\Connection\\Urls::get_raw_url' );
426 return Urls::get_raw_url( $option_name );
427 }
428
429 /**
430 * Normalize domains by removing www unless declared in the site's option.
431 *
432 * @deprecated 1.23.1
433 *
434 * @param string $option Option value from the site.
435 * @param callable $url_function Function retrieving the URL to normalize.
436 * @return mixed|string URL.
437 */
438 public static function normalize_www_in_url( $option, $url_function ) {
439 _deprecated_function( __METHOD__, '1.23.1', '\\Automattic\\Jetpack\\Connection\\Urls::normalize_www_in_url' );
440 return Urls::normalize_www_in_url( $option, $url_function );
441 }
442
443 /**
444 * Return filtered value of get_plugins.
445 *
446 * @return mixed|void
447 */
448 public static function get_plugins() {
449 if ( ! function_exists( 'get_plugins' ) ) {
450 require_once ABSPATH . 'wp-admin/includes/plugin.php';
451 }
452
453 /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
454 return apply_filters( 'all_plugins', get_plugins() );
455 }
456
457 /**
458 * Get custom action link tags that the plugin is using
459 * Ref: https://codex.wordpress.org/Plugin_API/Filter_Reference/plugin_action_links_(plugin_file_name)
460 *
461 * @param string $plugin_file_singular Particular plugin.
462 * @return array of plugin action links (key: link name value: url)
463 */
464 public static function get_plugins_action_links( $plugin_file_singular = null ) {
465 // Some sites may have DOM disabled in PHP fail early.
466 if ( ! class_exists( 'DOMDocument' ) ) {
467 return array();
468 }
469 $plugins_action_links = get_option( 'jetpack_plugin_api_action_links', array() );
470 if ( ! empty( $plugins_action_links ) ) {
471 if ( $plugin_file_singular === null ) {
472 return $plugins_action_links;
473 }
474 return ( $plugins_action_links[ $plugin_file_singular ] ?? null );
475 }
476 return array();
477 }
478
479 /**
480 * Return the WP version as defined in the $wp_version global.
481 *
482 * @return string
483 */
484 public static function wp_version() {
485 global $wp_version;
486 return $wp_version;
487 }
488
489 /**
490 * Return site icon url used on the site.
491 *
492 * @param int $size Size of requested icon in pixels.
493 * @return mixed|string|void
494 */
495 public static function site_icon_url( $size = 512 ) {
496 $site_icon = get_site_icon_url( $size );
497 return $site_icon ? $site_icon : get_option( 'jetpack_site_icon_url' );
498 }
499
500 /**
501 * Return roles registered on the site.
502 *
503 * @return array
504 */
505 public static function roles() {
506 $wp_roles = wp_roles();
507 return $wp_roles->roles;
508 }
509
510 /**
511 * Determine time zone from WordPress' options "timezone_string"
512 * and "gmt_offset".
513 *
514 * 1. Check if `timezone_string` is set and return it.
515 * 2. Check if `gmt_offset` is set, formats UTC-offset from it and return it.
516 * 3. Default to "UTC+0" if nothing is set.
517 *
518 * Note: This function is specifically not using wp_timezone() to keep consistency with
519 * the existing formatting of the timezone string.
520 *
521 * @return string
522 */
523 public static function get_timezone() {
524 $timezone_string = get_option( 'timezone_string' );
525
526 if ( ! empty( $timezone_string ) ) {
527 return str_replace( '_', ' ', $timezone_string );
528 }
529
530 $gmt_offset = get_option( 'gmt_offset', 0 );
531
532 $formatted_gmt_offset = sprintf( '%+g', (float) $gmt_offset );
533
534 $formatted_gmt_offset = str_replace(
535 array( '.25', '.5', '.75' ),
536 array( ':15', ':30', ':45' ),
537 $formatted_gmt_offset
538 );
539
540 /* translators: %s is UTC offset, e.g. "+1" */
541 return sprintf( __( 'UTC%s', 'jetpack-sync' ), $formatted_gmt_offset );
542 }
543
544 /**
545 * Return list of paused themes.
546 *
547 * @return array|bool Array of paused themes or false if unsupported.
548 */
549 public static function get_paused_themes() {
550 $paused_themes = wp_paused_themes();
551 return $paused_themes->get_all();
552 }
553
554 /**
555 * Return list of paused plugins.
556 *
557 * @return array|bool Array of paused plugins or false if unsupported.
558 */
559 public static function get_paused_plugins() {
560 $paused_plugins = wp_paused_plugins();
561 return $paused_plugins->get_all();
562 }
563
564 /**
565 * Return the theme's supported features.
566 * Used for syncing the supported feature that we care about.
567 *
568 * @return array List of features that the theme supports.
569 */
570 public static function get_theme_support() {
571 global $_wp_theme_features;
572
573 $theme_support = array();
574 foreach ( Defaults::$default_theme_support_whitelist as $theme_feature ) {
575 $has_support = current_theme_supports( $theme_feature );
576 if ( $has_support ) {
577 $theme_support[ $theme_feature ] = $_wp_theme_features[ $theme_feature ];
578 }
579 }
580
581 return $theme_support;
582 }
583
584 /**
585 * Returns if the current theme is a Full Site Editing theme.
586 *
587 * @since 1.49.0 Uses wp_is_block_theme() instead of deprecated gutenberg_is_fse_theme().
588 *
589 * @return bool Theme is a Full Site Editing theme.
590 */
591 public static function get_is_fse_theme() {
592 return wp_is_block_theme();
593 }
594
595 /**
596 * Wraps data in a way so that we can distinguish between objects and array and also prevent object recursion.
597 *
598 * @since 1.21.0
599 *
600 * @param mixed $any Source data to be cleaned up.
601 * @param array $seen_nodes Built array of nodes.
602 *
603 * @return array
604 */
605 public static function json_wrap( &$any, $seen_nodes = array() ) {
606 if ( is_object( $any ) ) {
607 $input = get_object_vars( $any );
608
609 // WordPress 6.9 introduced lazy-loading of WP_User `roles`, `caps`, and `allcaps` properties.
610 // It also made said properties protected, so we need to access them and set them as keys manually.
611 if ( $any instanceof \WP_User ) {
612 $roles = $any->roles;
613 $caps = $any->caps;
614 $allcaps = $any->allcaps;
615 $input['roles'] = $roles;
616 $input['caps'] = $caps;
617 $input['allcaps'] = $allcaps;
618 }
619
620 $input['__o'] = 1;
621 } else {
622 $input = &$any;
623 }
624
625 if ( is_array( $input ) ) {
626 $seen_nodes[] = &$any;
627
628 $return = array();
629
630 foreach ( $input as $k => &$v ) {
631 if ( ( is_array( $v ) || is_object( $v ) ) ) {
632 if ( in_array( $v, $seen_nodes, true ) ) {
633 continue;
634 }
635 $return[ $k ] = self::json_wrap( $v, $seen_nodes );
636 } else {
637 $return[ $k ] = $v;
638 }
639 }
640
641 return $return;
642 }
643
644 return $any;
645 }
646
647 /**
648 * Return the list of installed themes
649 *
650 * @since 1.31.0
651 *
652 * @return array
653 */
654 public static function get_themes() {
655 $current_stylesheet = get_stylesheet();
656 $installed_themes = wp_get_themes();
657 $synced_headers = array( 'Name', 'ThemeURI', 'Author', 'Version', 'Template', 'Status', 'TextDomain', 'RequiresWP', 'RequiresPHP' );
658 $themes = array();
659 foreach ( $installed_themes as $stylesheet => $theme ) {
660 $themes[ $stylesheet ] = array();
661 foreach ( $synced_headers as $header ) {
662 $themes[ $stylesheet ][ $header ] = $theme->get( $header );
663 }
664 $themes[ $stylesheet ]['active'] = $stylesheet === $current_stylesheet;
665 if ( method_exists( $theme, 'is_block_theme' ) ) {
666 $themes[ $stylesheet ]['is_block_theme'] = $theme->is_block_theme();
667 }
668 }
669 /**
670 * Filters the output of Sync's get_theme callable
671 *
672 * @since 1.31.0
673 *
674 * @param array $themes The list of installed themes formatted in an array with a collection of information extracted from the Theme's headers
675 */
676 return apply_filters( 'jetpack_sync_get_themes_callable', $themes );
677 }
678
679 /**
680 * Return the list of active Jetpack modules.
681 *
682 * @since 1.34.0
683 *
684 * @return array
685 */
686 public static function get_active_modules() {
687 return ( new Jetpack_Modules() )->get_active();
688 }
689
690 /**
691 * Return a list of PHP modules that we want to track.
692 *
693 * @since 1.50.0
694 *
695 * @return array
696 */
697 public static function get_loaded_extensions() {
698 if ( function_exists( 'get_loaded_extensions' ) ) {
699 return get_loaded_extensions();
700 }
701
702 // If a hosting provider has blocked get_loaded_extensions for any reason,
703 // we check extensions manually.
704
705 $extensions_to_check = array(
706 'libxml' => array( 'class' => 'libXMLError' ),
707 'xml' => array( 'function' => 'xml_parse' ),
708 'dom' => array( 'class' => 'DOMDocument' ),
709 'xdebug' => array( 'function' => 'xdebug_break' ),
710 );
711
712 $enabled_extensions = array();
713 foreach ( $extensions_to_check as $extension_name => $extension ) {
714 if (
715 ( isset( $extension['function'] )
716 && function_exists( $extension['function'] ) )
717 || class_exists( $extension['class'] )
718 ) {
719 $enabled_extensions[] = $extension_name;
720 }
721 }
722
723 return $enabled_extensions;
724 }
725
726 /**
727 * Return the list of active connected Jetpack plugins.
728 *
729 * @since 3.2.0
730 *
731 * @return array
732 */
733 public static function get_jetpack_connection_active_plugins() {
734 return ( new Manager() )->get_connected_plugins();
735 }
736
737 /**
738 * Return the list of active sync modules.
739 *
740 * @since 3.6.0
741 *
742 * @return array
743 */
744 public static function get_jetpack_sync_active_modules() {
745
746 /** This filter is documented in projects/packages/sync/src/class-modules.php */
747 $modules = apply_filters( 'jetpack_sync_modules', Modules::DEFAULT_SYNC_MODULES );
748 $modules = array_unique( $modules );
749 $modules = array_map( 'wp_normalize_path', $modules );
750 return $modules;
751 }
752
753 /**
754 * Return the list of Jetpack package versions.
755 *
756 * @since 4.11.1
757 *
758 * @return array
759 */
760 public static function get_jetpack_package_versions() {
761 return apply_filters( 'jetpack_package_versions', array() );
762 }
763 }
764