PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.1.4
Jetpack – WP Security, Backup, Speed, & Growth v7.1.4
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 All 500 releases
jetpack / sync / class.jetpack-sync-functions.php
class.jetpack-sync-functions.php
407 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * Utility functions to generate data synced to wpcom
5 */
6
7 class Jetpack_Sync_Functions {
8 const HTTPS_CHECK_OPTION_PREFIX = 'jetpack_sync_https_history_';
9 const HTTPS_CHECK_HISTORY = 5;
10
11 public static function get_modules() {
12 require_once JETPACK__PLUGIN_DIR . 'class.jetpack-admin.php';
13
14 return Jetpack_Admin::init()->get_modules();
15 }
16
17 public static function get_taxonomies() {
18 global $wp_taxonomies;
19 $wp_taxonomies_without_callbacks = array();
20 foreach ( $wp_taxonomies as $taxonomy_name => $taxonomy ) {
21 $sanitized_taxonomy = self::sanitize_taxonomy( $taxonomy );
22 if ( ! empty( $sanitized_taxonomy ) ) {
23 $wp_taxonomies_without_callbacks[ $taxonomy_name ] = $sanitized_taxonomy;
24 } else {
25 error_log( 'Jetpack: Encountered a recusive taxonomy:' . $taxonomy_name );
26 }
27 }
28 return $wp_taxonomies_without_callbacks;
29 }
30
31 public static function get_shortcodes() {
32 global $shortcode_tags;
33 return array_keys( $shortcode_tags );
34 }
35
36 /**
37 * Removes any callback data since we will not be able to process it on our side anyways.
38 */
39 public static function sanitize_taxonomy( $taxonomy ) {
40
41 // Lets clone the taxonomy object instead of modifing the global one.
42 $cloned_taxonomy = json_decode( wp_json_encode( $taxonomy ) );
43
44 // recursive taxonomies are no fun.
45 if ( is_null( $cloned_taxonomy ) ) {
46 return null;
47 }
48 // Remove any meta_box_cb if they are not the default wp ones.
49 if ( isset( $cloned_taxonomy->meta_box_cb ) &&
50 ! in_array( $cloned_taxonomy->meta_box_cb, array( 'post_tags_meta_box', 'post_categories_meta_box' ) ) ) {
51 $cloned_taxonomy->meta_box_cb = null;
52 }
53 // Remove update call back
54 if ( isset( $cloned_taxonomy->update_count_callback ) &&
55 ! is_null( $cloned_taxonomy->update_count_callback ) ) {
56 $cloned_taxonomy->update_count_callback = null;
57 }
58 // Remove rest_controller_class if it something other then the default.
59 if ( isset( $cloned_taxonomy->rest_controller_class ) &&
60 'WP_REST_Terms_Controller' !== $cloned_taxonomy->rest_controller_class ) {
61 $cloned_taxonomy->rest_controller_class = null;
62 }
63 return $cloned_taxonomy;
64 }
65
66 public static function get_post_types() {
67 global $wp_post_types;
68
69 $post_types_without_callbacks = array();
70 foreach ( $wp_post_types as $post_type_name => $post_type ) {
71 $sanitized_post_type = self::sanitize_post_type( $post_type );
72 if ( ! empty( $sanitized_post_type ) ) {
73 $post_types_without_callbacks[ $post_type_name ] = $sanitized_post_type;
74 } else {
75 error_log( 'Jetpack: Encountered a recusive post_type:' . $post_type_name );
76 }
77 }
78 return $post_types_without_callbacks;
79 }
80
81 public static function sanitize_post_type( $post_type ) {
82 // Lets clone the post type object instead of modifing the global one.
83 $sanitized_post_type = array();
84 foreach ( Jetpack_Sync_Defaults::$default_post_type_attributes as $attribute_key => $default_value ) {
85 if ( isset( $post_type->{ $attribute_key } ) ) {
86 $sanitized_post_type[ $attribute_key ] = $post_type->{ $attribute_key };
87 }
88 }
89 return (object) $sanitized_post_type;
90 }
91
92 public static function expand_synced_post_type( $sanitized_post_type, $post_type ) {
93 $post_type = sanitize_key( $post_type );
94 $post_type_object = new WP_Post_Type( $post_type, $sanitized_post_type );
95 $post_type_object->add_supports();
96 $post_type_object->add_rewrite_rules();
97 $post_type_object->add_hooks();
98 $post_type_object->register_taxonomies();
99 return (object) $post_type_object;
100 }
101
102 public static function get_post_type_features() {
103 global $_wp_post_type_features;
104
105 return $_wp_post_type_features;
106 }
107
108 public static function get_hosting_provider() {
109 if ( defined( 'GD_SYSTEM_PLUGIN_DIR' ) || class_exists( '\\WPaaS\\Plugin' ) ) {
110 return 'gd-managed-wp';
111 }
112 if ( defined( 'MM_BASE_DIR' ) ) {
113 return 'bh';
114 }
115 if ( defined( 'IS_PRESSABLE' ) ) {
116 return 'pressable';
117 }
118 if ( function_exists( 'is_wpe' ) || function_exists( 'is_wpe_snapshot' ) ) {
119 return 'wpe';
120 }
121 if ( defined( 'VIP_GO_ENV' ) && false !== VIP_GO_ENV ) {
122 return 'vip-go';
123 }
124 return 'unknown';
125 }
126
127 public static function rest_api_allowed_post_types() {
128 /** This filter is already documented in class.json-api-endpoints.php */
129 return apply_filters( 'rest_api_allowed_post_types', array( 'post', 'page', 'revision' ) );
130 }
131
132 public static function rest_api_allowed_public_metadata() {
133 /** This filter is documented in json-endpoints/class.wpcom-json-api-post-endpoint.php */
134 return apply_filters( 'rest_api_allowed_public_metadata', array() );
135 }
136
137 /**
138 * Finds out if a site is using a version control system.
139 *
140 * @return bool
141 **/
142 public static function is_version_controlled() {
143
144 if ( ! class_exists( 'WP_Automatic_Updater' ) ) {
145 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
146 }
147 $updater = new WP_Automatic_Updater();
148
149 return (bool) strval( $updater->is_vcs_checkout( $context = ABSPATH ) );
150 }
151
152 /**
153 * Returns true if the site has file write access false otherwise.
154 *
155 * @return bool
156 **/
157 public static function file_system_write_access() {
158 if ( ! function_exists( 'get_filesystem_method' ) ) {
159 require_once ABSPATH . 'wp-admin/includes/file.php';
160 }
161
162 require_once ABSPATH . 'wp-admin/includes/template.php';
163
164 $filesystem_method = get_filesystem_method();
165 if ( 'direct' === $filesystem_method ) {
166 return true;
167 }
168
169 ob_start();
170
171 if ( ! function_exists( 'request_filesystem_credentials' ) ) {
172 require_once ABSPATH . 'wp-admin/includes/file.php';
173 }
174
175 $filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() );
176 ob_end_clean();
177 if ( $filesystem_credentials_are_stored ) {
178 return true;
179 }
180
181 return false;
182 }
183
184 /**
185 * Helper function that is used when getting home or siteurl values. Decides
186 * whether to get the raw or filtered value.
187 *
188 * @return string
189 */
190 public static function get_raw_or_filtered_url( $url_type ) {
191 $url_function = ( 'home' == $url_type )
192 ? 'home_url'
193 : 'site_url';
194
195 if (
196 ! Jetpack_Constants::is_defined( 'JETPACK_SYNC_USE_RAW_URL' ) ||
197 Jetpack_Constants::get_constant( 'JETPACK_SYNC_USE_RAW_URL' )
198 ) {
199 $scheme = is_ssl() ? 'https' : 'http';
200 $url = self::get_raw_url( $url_type );
201 $url = set_url_scheme( $url, $scheme );
202 } else {
203 $url = self::normalize_www_in_url( $url_type, $url_function );
204 }
205
206 return self::get_protocol_normalized_url( $url_function, $url );
207 }
208
209 public static function home_url() {
210 $url = self::get_raw_or_filtered_url( 'home' );
211
212 /**
213 * Allows overriding of the home_url value that is synced back to WordPress.com.
214 *
215 * @since 5.2.0
216 *
217 * @param string $home_url
218 */
219 return esc_url_raw( apply_filters( 'jetpack_sync_home_url', $url ) );
220 }
221
222 public static function site_url() {
223 $url = self::get_raw_or_filtered_url( 'siteurl' );
224
225 /**
226 * Allows overriding of the site_url value that is synced back to WordPress.com.
227 *
228 * @since 5.2.0
229 *
230 * @param string $site_url
231 */
232 return esc_url_raw( apply_filters( 'jetpack_sync_site_url', $url ) );
233 }
234
235 public static function main_network_site_url() {
236 return self::get_protocol_normalized_url( 'main_network_site_url', network_site_url() );
237 }
238
239 public static function get_protocol_normalized_url( $callable, $new_value ) {
240 $option_key = self::HTTPS_CHECK_OPTION_PREFIX . $callable;
241
242 $parsed_url = wp_parse_url( $new_value );
243 if ( ! $parsed_url ) {
244 return $new_value;
245 }
246 if ( array_key_exists( 'scheme', $parsed_url ) ) {
247 $scheme = $parsed_url['scheme'];
248 } else {
249 $scheme = '';
250 }
251 $scheme_history = get_option( $option_key, array() );
252 $scheme_history[] = $scheme;
253
254 // Limit length to self::HTTPS_CHECK_HISTORY
255 $scheme_history = array_slice( $scheme_history, ( self::HTTPS_CHECK_HISTORY * -1 ) );
256
257 update_option( $option_key, $scheme_history );
258
259 $forced_scheme = in_array( 'https', $scheme_history ) ? 'https' : 'http';
260
261 return set_url_scheme( $new_value, $forced_scheme );
262 }
263
264 public static function get_raw_url( $option_name ) {
265 $value = null;
266 $constant = ( 'home' == $option_name )
267 ? 'WP_HOME'
268 : 'WP_SITEURL';
269
270 // Since we disregard the constant for multisites in ms-default-filters.php,
271 // let's also use the db value if this is a multisite.
272 if ( ! is_multisite() && Jetpack_Constants::is_defined( $constant ) ) {
273 $value = Jetpack_Constants::get_constant( $constant );
274 } else {
275 // Let's get the option from the database so that we can bypass filters. This will help
276 // ensure that we get more uniform values.
277 $value = Jetpack_Options::get_raw_option( $option_name );
278 }
279
280 return $value;
281 }
282
283 public static function normalize_www_in_url( $option, $url_function ) {
284 $url = wp_parse_url( call_user_func( $url_function ) );
285 $option_url = wp_parse_url( get_option( $option ) );
286
287 if ( ! $option_url || ! $url ) {
288 return $url;
289 }
290
291 if ( $url['host'] === "www.{$option_url[ 'host' ]}" ) {
292 // remove www if not present in option URL
293 $url['host'] = $option_url['host'];
294 }
295 if ( $option_url['host'] === "www.{$url[ 'host' ]}" ) {
296 // add www if present in option URL
297 $url['host'] = $option_url['host'];
298 }
299
300 $normalized_url = "{$url['scheme']}://{$url['host']}";
301 if ( isset( $url['path'] ) ) {
302 $normalized_url .= "{$url['path']}";
303 }
304
305 if ( isset( $url['query'] ) ) {
306 $normalized_url .= "?{$url['query']}";
307 }
308
309 return $normalized_url;
310 }
311
312 public static function get_plugins() {
313 if ( ! function_exists( 'get_plugins' ) ) {
314 require_once ABSPATH . 'wp-admin/includes/plugin.php';
315 }
316
317 /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
318 return apply_filters( 'all_plugins', get_plugins() );
319 }
320
321 /**
322 * Get custom action link tags that the plugin is using
323 * Ref: https://codex.wordpress.org/Plugin_API/Filter_Reference/plugin_action_links_(plugin_file_name)
324 *
325 * @return array of plugin action links (key: link name value: url)
326 */
327 public static function get_plugins_action_links( $plugin_file_singular = null ) {
328 // Some sites may have DOM disabled in PHP fail early
329 if ( ! class_exists( 'DOMDocument' ) ) {
330 return array();
331 }
332 $plugins_action_links = get_option( 'jetpack_plugin_api_action_links', array() );
333 if ( ! empty( $plugins_action_links ) ) {
334 if ( is_null( $plugin_file_singular ) ) {
335 return $plugins_action_links;
336 }
337 return ( isset( $plugins_action_links[ $plugin_file_singular ] ) ? $plugins_action_links[ $plugin_file_singular ] : null );
338 }
339 return array();
340 }
341
342 public static function wp_version() {
343 global $wp_version;
344 return $wp_version;
345 }
346
347 public static function site_icon_url( $size = 512 ) {
348 if ( ! function_exists( 'get_site_icon_url' ) || ! has_site_icon() ) {
349 return get_option( 'jetpack_site_icon_url' );
350 }
351
352 return get_site_icon_url( $size );
353 }
354
355 public static function roles() {
356 $wp_roles = wp_roles();
357 return $wp_roles->roles;
358 }
359
360 /**
361 * Determine time zone from WordPress' options "timezone_string"
362 * and "gmt_offset".
363 *
364 * 1. Check if `timezone_string` is set and return it.
365 * 2. Check if `gmt_offset` is set, formats UTC-offset from it and return it.
366 * 3. Default to "UTC+0" if nothing is set.
367 *
368 * @return string
369 */
370 public static function get_timezone() {
371 $timezone_string = get_option( 'timezone_string' );
372
373 if ( ! empty( $timezone_string ) ) {
374 return str_replace( '_', ' ', $timezone_string );
375 }
376
377 $gmt_offset = get_option( 'gmt_offset', 0 );
378
379 $formatted_gmt_offset = sprintf( '%+g', floatval( $gmt_offset ) );
380
381 $formatted_gmt_offset = str_replace(
382 array( '.25', '.5', '.75' ),
383 array( ':15', ':30', ':45' ),
384 (string) $formatted_gmt_offset
385 );
386
387 /* translators: %s is UTC offset, e.g. "+1" */
388 return sprintf( __( 'UTC%s', 'jetpack' ), $formatted_gmt_offset );
389 }
390 // New in WP 5.1
391 public static function get_paused_themes() {
392 if ( function_exists( 'wp_paused_themes' ) ) {
393 $paused_themes = wp_paused_themes();
394 return $paused_themes->get_all();
395 }
396 return false;
397 }
398 // New in WP 5.1
399 public static function get_paused_plugins() {
400 if ( function_exists( 'wp_paused_plugins' ) ) {
401 $paused_plugins = wp_paused_plugins();
402 return $paused_plugins->get_all();
403 }
404 return false;
405 }
406 }
407