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