PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 6.2.2
Jetpack – WP Security, Backup, Speed, & Growth v6.2.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 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 All 501 releases
jetpack / sync / class.jetpack-sync-functions.php
class.jetpack-sync-functions.php
388 lines 11.6 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 * @return bool
140 **/
141 public static function is_version_controlled() {
142
143 if ( ! class_exists( 'WP_Automatic_Updater' ) ) {
144 require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
145 }
146 $updater = new WP_Automatic_Updater();
147
148 return (bool) strval( $updater->is_vcs_checkout( $context = ABSPATH ) );
149 }
150
151 /**
152 * Returns true if the site has file write access false otherwise.
153 * @return bool
154 **/
155 public static function file_system_write_access() {
156 if ( ! function_exists( 'get_filesystem_method' ) ) {
157 require_once( ABSPATH . 'wp-admin/includes/file.php' );
158 }
159
160 require_once( ABSPATH . 'wp-admin/includes/template.php' );
161
162 $filesystem_method = get_filesystem_method();
163 if ( 'direct' === $filesystem_method ) {
164 return true;
165 }
166
167 ob_start();
168
169 if ( ! function_exists( 'request_filesystem_credentials' ) ) {
170 require_once( ABSPATH . 'wp-admin/includes/file.php' );
171 }
172
173 $filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() );
174 ob_end_clean();
175 if ( $filesystem_credentials_are_stored ) {
176 return true;
177 }
178
179 return false;
180 }
181
182 /**
183 * Helper function that is used when getting home or siteurl values. Decides
184 * whether to get the raw or filtered value.
185 *
186 * @return string
187 */
188 public static function get_raw_or_filtered_url( $url_type ) {
189 $url_function = ( 'home' == $url_type )
190 ? 'home_url'
191 : 'site_url';
192
193 if (
194 ! Jetpack_Constants::is_defined( 'JETPACK_SYNC_USE_RAW_URL' ) ||
195 Jetpack_Constants::get_constant( 'JETPACK_SYNC_USE_RAW_URL' )
196 ) {
197 $scheme = is_ssl() ? 'https' : 'http';
198 $url = self::get_raw_url( $url_type );
199 $url = set_url_scheme( $url, $scheme );
200 } else {
201 $url = self::normalize_www_in_url( $url_type, $url_function );
202 }
203
204 return self::get_protocol_normalized_url( $url_function, $url );
205 }
206
207 public static function home_url() {
208 $url = self::get_raw_or_filtered_url( 'home' );
209
210 /**
211 * Allows overriding of the home_url value that is synced back to WordPress.com.
212 *
213 * @since 5.2
214 *
215 * @param string $home_url
216 */
217 return esc_url_raw( apply_filters( 'jetpack_sync_home_url', $url ) );
218 }
219
220 public static function site_url() {
221 $url = self::get_raw_or_filtered_url( 'siteurl' );
222
223 /**
224 * Allows overriding of the site_url value that is synced back to WordPress.com.
225 *
226 * @since 5.2
227 *
228 * @param string $site_url
229 */
230 return esc_url_raw( apply_filters( 'jetpack_sync_site_url', $url ) );
231 }
232
233 public static function main_network_site_url() {
234 return self::get_protocol_normalized_url( 'main_network_site_url', network_site_url() );
235 }
236
237 public static function get_protocol_normalized_url( $callable, $new_value ) {
238 $option_key = self::HTTPS_CHECK_OPTION_PREFIX . $callable;
239
240 $parsed_url = wp_parse_url( $new_value );
241 if ( ! $parsed_url ) {
242 return $new_value;
243 }
244 if ( array_key_exists ( 'scheme' , $parsed_url ) ) {
245 $scheme = $parsed_url['scheme'];
246 } else {
247 $scheme = '';
248 }
249 $scheme_history = get_option( $option_key, array() );
250 $scheme_history[] = $scheme;
251
252 // Limit length to self::HTTPS_CHECK_HISTORY
253 $scheme_history = array_slice( $scheme_history, ( self::HTTPS_CHECK_HISTORY * -1 ) );
254
255 update_option( $option_key, $scheme_history );
256
257 $forced_scheme = in_array( 'https', $scheme_history ) ? 'https' : 'http';
258
259 return set_url_scheme( $new_value, $forced_scheme );
260 }
261
262 public static function get_raw_url( $option_name ) {
263 $value = null;
264 $constant = ( 'home' == $option_name )
265 ? 'WP_HOME'
266 : 'WP_SITEURL';
267
268 // Since we disregard the constant for multisites in ms-default-filters.php,
269 // let's also use the db value if this is a multisite.
270 if ( ! is_multisite() && Jetpack_Constants::is_defined( $constant ) ) {
271 $value = Jetpack_Constants::get_constant( $constant );
272 } else {
273 // Let's get the option from the database so that we can bypass filters. This will help
274 // ensure that we get more uniform values.
275 $value = Jetpack_Options::get_raw_option( $option_name );
276 }
277
278 return $value;
279 }
280
281 public static function normalize_www_in_url( $option, $url_function ) {
282 $url = wp_parse_url( call_user_func( $url_function ) );
283 $option_url = wp_parse_url( get_option( $option ) );
284
285 if ( ! $option_url || ! $url ) {
286 return $url;
287 }
288
289 if ( $url[ 'host' ] === "www.{$option_url[ 'host' ]}" ) {
290 // remove www if not present in option URL
291 $url[ 'host' ] = $option_url[ 'host' ];
292 }
293 if ( $option_url[ 'host' ] === "www.{$url[ 'host' ]}" ) {
294 // add www if present in option URL
295 $url[ 'host' ] = $option_url[ 'host' ];
296 }
297
298 $normalized_url = "{$url['scheme']}://{$url['host']}";
299 if ( isset( $url['path'] ) ) {
300 $normalized_url .= "{$url['path']}";
301 }
302
303 if ( isset( $url['query'] ) ) {
304 $normalized_url .= "?{$url['query']}";
305 }
306
307 return $normalized_url;
308 }
309
310 public static function get_plugins() {
311 if ( ! function_exists( 'get_plugins' ) ) {
312 require_once ABSPATH . 'wp-admin/includes/plugin.php';
313 }
314
315 /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
316 return apply_filters( 'all_plugins', get_plugins() );
317 }
318
319 /**
320 * Get custom action link tags that the plugin is using
321 * Ref: https://codex.wordpress.org/Plugin_API/Filter_Reference/plugin_action_links_(plugin_file_name)
322 * @return array of plugin action links (key: link name value: url)
323 */
324 public static function get_plugins_action_links( $plugin_file_singular = null ) {
325 // Some sites may have DOM disabled in PHP fail early
326 if ( ! class_exists( 'DOMDocument' ) ) {
327 return array();
328 }
329 $plugins_action_links = get_option( 'jetpack_plugin_api_action_links', array() );
330 if ( ! empty( $plugins_action_links ) ) {
331 if ( is_null( $plugin_file_singular ) ) {
332 return $plugins_action_links;
333 }
334 return ( isset( $plugins_action_links[ $plugin_file_singular ] ) ? $plugins_action_links[ $plugin_file_singular ] : null );
335 }
336 return array();
337 }
338
339 public static function wp_version() {
340 global $wp_version;
341 return $wp_version;
342 }
343
344 public static function site_icon_url( $size = 512 ) {
345 if ( ! function_exists( 'get_site_icon_url' ) || ! has_site_icon() ) {
346 return get_option( 'jetpack_site_icon_url' );
347 }
348
349 return get_site_icon_url( $size );
350 }
351
352 public static function roles() {
353 $wp_roles = wp_roles();
354 return $wp_roles->roles;
355 }
356
357 /**
358 * Determine time zone from WordPress' options "timezone_string"
359 * and "gmt_offset".
360 *
361 * 1. Check if `timezone_string` is set and return it.
362 * 2. Check if `gmt_offset` is set, formats UTC-offset from it and return it.
363 * 3. Default to "UTC+0" if nothing is set.
364 *
365 * @return string
366 */
367 public static function get_timezone() {
368 $timezone_string = get_option( 'timezone_string' );
369
370 if ( ! empty( $timezone_string ) ) {
371 return str_replace( '_', ' ', $timezone_string );
372 }
373
374 $gmt_offset = get_option( 'gmt_offset', 0 );
375
376 $formatted_gmt_offset = sprintf( '%+g', floatval( $gmt_offset ) );
377
378 $formatted_gmt_offset = str_replace(
379 array( '.25', '.5', '.75' ),
380 array( ':15', ':30', ':45' ),
381 (string) $formatted_gmt_offset
382 );
383
384 /* translators: %s is UTC offset, e.g. "+1" */
385 return sprintf( __( 'UTC%s' ), $formatted_gmt_offset );
386 }
387 }
388