Completed
Push — try/sync-package ( 228b13 )
by Marin
07:37
created

Functions::is_version_controlled()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
namespace Automattic\Jetpack\Sync;
4
5
/*
6
 * Utility functions to generate data synced to wpcom
7
 */
8
9
class Functions {
10
	const HTTPS_CHECK_OPTION_PREFIX = 'jetpack_sync_https_history_';
11
	const HTTPS_CHECK_HISTORY       = 5;
12
13
	public static function get_modules() {
14
		require_once JETPACK__PLUGIN_DIR . 'class.jetpack-admin.php';
15
16
		return Jetpack_Admin::init()->get_modules();
17
	}
18
19
	public static function get_taxonomies() {
20
		global $wp_taxonomies;
21
		$wp_taxonomies_without_callbacks = array();
22
		foreach ( $wp_taxonomies as $taxonomy_name => $taxonomy ) {
23
			$sanitized_taxonomy = self::sanitize_taxonomy( $taxonomy );
24
			if ( ! empty( $sanitized_taxonomy ) ) {
25
				$wp_taxonomies_without_callbacks[ $taxonomy_name ] = $sanitized_taxonomy;
26
			} else {
27
				error_log( 'Jetpack: Encountered a recusive taxonomy:' . $taxonomy_name );
28
			}
29
		}
30
		return $wp_taxonomies_without_callbacks;
31
	}
32
33
	public static function get_shortcodes() {
34
		global $shortcode_tags;
35
		return array_keys( $shortcode_tags );
36
	}
37
38
	/**
39
	 * Removes any callback data since we will not be able to process it on our side anyways.
40
	 */
41
	public static function sanitize_taxonomy( $taxonomy ) {
42
43
		// Lets clone the taxonomy object instead of modifing the global one.
44
		$cloned_taxonomy = json_decode( wp_json_encode( $taxonomy ) );
45
46
		// recursive taxonomies are no fun.
47
		if ( is_null( $cloned_taxonomy ) ) {
48
			return null;
49
		}
50
		// Remove any meta_box_cb if they are not the default wp ones.
51
		if ( isset( $cloned_taxonomy->meta_box_cb ) &&
52
			 ! in_array( $cloned_taxonomy->meta_box_cb, array( 'post_tags_meta_box', 'post_categories_meta_box' ) ) ) {
53
			$cloned_taxonomy->meta_box_cb = null;
54
		}
55
		// Remove update call back
56
		if ( isset( $cloned_taxonomy->update_count_callback ) &&
57
			 ! is_null( $cloned_taxonomy->update_count_callback ) ) {
58
			$cloned_taxonomy->update_count_callback = null;
59
		}
60
		// Remove rest_controller_class if it something other then the default.
61
		if ( isset( $cloned_taxonomy->rest_controller_class ) &&
62
			 'WP_REST_Terms_Controller' !== $cloned_taxonomy->rest_controller_class ) {
63
			$cloned_taxonomy->rest_controller_class = null;
64
		}
65
		return $cloned_taxonomy;
66
	}
67
68
	public static function get_post_types() {
69
		global $wp_post_types;
70
71
		$post_types_without_callbacks = array();
72
		foreach ( $wp_post_types as $post_type_name => $post_type ) {
73
			$sanitized_post_type = self::sanitize_post_type( $post_type );
74
			if ( ! empty( $sanitized_post_type ) ) {
75
				$post_types_without_callbacks[ $post_type_name ] = $sanitized_post_type;
76
			} else {
77
				error_log( 'Jetpack: Encountered a recusive post_type:' . $post_type_name );
78
			}
79
		}
80
		return $post_types_without_callbacks;
81
	}
82
83
	public static function sanitize_post_type( $post_type ) {
84
		// Lets clone the post type object instead of modifing the global one.
85
		$sanitized_post_type = array();
86
		foreach ( Defaults::$default_post_type_attributes as $attribute_key => $default_value ) {
0 ignored issues
show
Bug introduced by
The property default_post_type_attributes cannot be accessed from this context as it is declared private in class Automattic\Jetpack\Sync\Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
87
			if ( isset( $post_type->{ $attribute_key } ) ) {
88
				$sanitized_post_type[ $attribute_key ] = $post_type->{ $attribute_key };
89
			}
90
		}
91
		return (object) $sanitized_post_type;
92
	}
93
94
	public static function expand_synced_post_type( $sanitized_post_type, $post_type ) {
95
		$post_type        = sanitize_key( $post_type );
96
		$post_type_object = new WP_Post_Type( $post_type, $sanitized_post_type );
97
		$post_type_object->add_supports();
98
		$post_type_object->add_rewrite_rules();
99
		$post_type_object->add_hooks();
100
		$post_type_object->register_taxonomies();
101
		return (object) $post_type_object;
102
	}
103
104
	public static function get_post_type_features() {
105
		global $_wp_post_type_features;
106
107
		return $_wp_post_type_features;
108
	}
109
110
	public static function get_hosting_provider() {
111
		if ( defined( 'GD_SYSTEM_PLUGIN_DIR' ) || class_exists( '\\WPaaS\\Plugin' ) ) {
112
			return 'gd-managed-wp';
113
		}
114
		if ( defined( 'MM_BASE_DIR' ) ) {
115
			return 'bh';
116
		}
117
		if ( defined( 'IS_PRESSABLE' ) ) {
118
			return 'pressable';
119
		}
120
		if ( function_exists( 'is_wpe' ) || function_exists( 'is_wpe_snapshot' ) ) {
121
			return 'wpe';
122
		}
123
		if ( defined( 'VIP_GO_ENV' ) && false !== VIP_GO_ENV ) {
124
			return 'vip-go';
125
		}
126
		return 'unknown';
127
	}
128
129
	public static function rest_api_allowed_post_types() {
130
		/** This filter is already documented in class.json-api-endpoints.php */
131
		return apply_filters( 'rest_api_allowed_post_types', array( 'post', 'page', 'revision' ) );
132
	}
133
134
	public static function rest_api_allowed_public_metadata() {
135
		/** This filter is documented in json-endpoints/class.wpcom-json-api-post-endpoint.php */
136
		return apply_filters( 'rest_api_allowed_public_metadata', array() );
137
	}
138
139
	/**
140
	 * Finds out if a site is using a version control system.
141
	 *
142
	 * @return bool
143
	 **/
144
	public static function is_version_controlled() {
145
146
		if ( ! class_exists( 'WP_Automatic_Updater' ) ) {
147
			require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
148
		}
149
		$updater = new WP_Automatic_Updater();
150
151
		return (bool) strval( $updater->is_vcs_checkout( $context = ABSPATH ) );
152
	}
153
154
	/**
155
	 * Returns true if the site has file write access false otherwise.
156
	 *
157
	 * @return bool
158
	 **/
159
	public static function file_system_write_access() {
160
		if ( ! function_exists( 'get_filesystem_method' ) ) {
161
			require_once ABSPATH . 'wp-admin/includes/file.php';
162
		}
163
164
		require_once ABSPATH . 'wp-admin/includes/template.php';
165
166
		$filesystem_method = get_filesystem_method();
167
		if ( 'direct' === $filesystem_method ) {
168
			return true;
169
		}
170
171
		ob_start();
172
173
		if ( ! function_exists( 'request_filesystem_credentials' ) ) {
174
			require_once ABSPATH . 'wp-admin/includes/file.php';
175
		}
176
177
		$filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() );
178
		ob_end_clean();
179
		if ( $filesystem_credentials_are_stored ) {
180
			return true;
181
		}
182
183
		return false;
184
	}
185
186
	/**
187
	 * Helper function that is used when getting home or siteurl values. Decides
188
	 * whether to get the raw or filtered value.
189
	 *
190
	 * @return string
191
	 */
192
	public static function get_raw_or_filtered_url( $url_type ) {
193
		$url_function = ( 'home' == $url_type )
194
			? 'home_url'
195
			: 'site_url';
196
197
		if (
198
			! Jetpack_Constants::is_defined( 'JETPACK_SYNC_USE_RAW_URL' ) ||
199
			Jetpack_Constants::get_constant( 'JETPACK_SYNC_USE_RAW_URL' )
200
		) {
201
			$scheme = is_ssl() ? 'https' : 'http';
202
			$url    = self::get_raw_url( $url_type );
203
			$url    = set_url_scheme( $url, $scheme );
204
		} else {
205
			$url = self::normalize_www_in_url( $url_type, $url_function );
206
		}
207
208
		return self::get_protocol_normalized_url( $url_function, $url );
209
	}
210
211
	public static function home_url() {
212
		$url = self::get_raw_or_filtered_url( 'home' );
213
214
		/**
215
		 * Allows overriding of the home_url value that is synced back to WordPress.com.
216
		 *
217
		 * @since 5.2.0
218
		 *
219
		 * @param string $home_url
220
		 */
221
		return esc_url_raw( apply_filters( 'jetpack_sync_home_url', $url ) );
222
	}
223
224
	public static function site_url() {
225
		$url = self::get_raw_or_filtered_url( 'siteurl' );
226
227
		/**
228
		 * Allows overriding of the site_url value that is synced back to WordPress.com.
229
		 *
230
		 * @since 5.2.0
231
		 *
232
		 * @param string $site_url
233
		 */
234
		return esc_url_raw( apply_filters( 'jetpack_sync_site_url', $url ) );
235
	}
236
237
	public static function main_network_site_url() {
238
		return self::get_protocol_normalized_url( 'main_network_site_url', network_site_url() );
239
	}
240
241
	public static function get_protocol_normalized_url( $callable, $new_value ) {
242
		$option_key = self::HTTPS_CHECK_OPTION_PREFIX . $callable;
243
244
		$parsed_url = wp_parse_url( $new_value );
245
		if ( ! $parsed_url ) {
246
			return $new_value;
247
		}
248
		if ( array_key_exists( 'scheme', $parsed_url ) ) {
249
			$scheme = $parsed_url['scheme'];
250
		} else {
251
			$scheme = '';
252
		}
253
		$scheme_history   = get_option( $option_key, array() );
254
		$scheme_history[] = $scheme;
255
256
		// Limit length to self::HTTPS_CHECK_HISTORY
257
		$scheme_history = array_slice( $scheme_history, ( self::HTTPS_CHECK_HISTORY * -1 ) );
258
259
		update_option( $option_key, $scheme_history );
260
261
		$forced_scheme = in_array( 'https', $scheme_history ) ? 'https' : 'http';
262
263
		return set_url_scheme( $new_value, $forced_scheme );
264
	}
265
266
	public static function get_raw_url( $option_name ) {
267
		$value    = null;
0 ignored issues
show
Unused Code introduced by
$value is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
268
		$constant = ( 'home' == $option_name )
269
			? 'WP_HOME'
270
			: 'WP_SITEURL';
271
272
		// Since we disregard the constant for multisites in ms-default-filters.php,
273
		// let's also use the db value if this is a multisite.
274
		if ( ! is_multisite() && Jetpack_Constants::is_defined( $constant ) ) {
275
			$value = Jetpack_Constants::get_constant( $constant );
276
		} else {
277
			// Let's get the option from the database so that we can bypass filters. This will help
278
			// ensure that we get more uniform values.
279
			$value = Jetpack_Options::get_raw_option( $option_name );
280
		}
281
282
		return $value;
283
	}
284
285
	public static function normalize_www_in_url( $option, $url_function ) {
286
		$url        = wp_parse_url( call_user_func( $url_function ) );
287
		$option_url = wp_parse_url( get_option( $option ) );
288
289
		if ( ! $option_url || ! $url ) {
290
			return $url;
291
		}
292
293 View Code Duplication
		if ( $url['host'] === "www.{$option_url[ 'host' ]}" ) {
294
			// remove www if not present in option URL
295
			$url['host'] = $option_url['host'];
296
		}
297 View Code Duplication
		if ( $option_url['host'] === "www.{$url[ 'host' ]}" ) {
298
			// add www if present in option URL
299
			$url['host'] = $option_url['host'];
300
		}
301
302
		$normalized_url = "{$url['scheme']}://{$url['host']}";
303
		if ( isset( $url['path'] ) ) {
304
			$normalized_url .= "{$url['path']}";
305
		}
306
307
		if ( isset( $url['query'] ) ) {
308
			$normalized_url .= "?{$url['query']}";
309
		}
310
311
		return $normalized_url;
312
	}
313
314
	public static function get_plugins() {
315
		if ( ! function_exists( 'get_plugins' ) ) {
316
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
317
		}
318
319
		/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
320
		return apply_filters( 'all_plugins', get_plugins() );
321
	}
322
323
	/**
324
	 * Get custom action link tags that the plugin is using
325
	 * Ref: https://codex.wordpress.org/Plugin_API/Filter_Reference/plugin_action_links_(plugin_file_name)
326
	 *
327
	 * @return array of plugin action links (key: link name value: url)
328
	 */
329
	public static function get_plugins_action_links( $plugin_file_singular = null ) {
330
		// Some sites may have DOM disabled in PHP fail early
331
		if ( ! class_exists( 'DOMDocument' ) ) {
332
			return array();
333
		}
334
		$plugins_action_links = get_option( 'jetpack_plugin_api_action_links', array() );
335
		if ( ! empty( $plugins_action_links ) ) {
336
			if ( is_null( $plugin_file_singular ) ) {
337
				return $plugins_action_links;
338
			}
339
			return ( isset( $plugins_action_links[ $plugin_file_singular ] ) ? $plugins_action_links[ $plugin_file_singular ] : null );
340
		}
341
		return array();
342
	}
343
344
	public static function wp_version() {
345
		global $wp_version;
346
		return $wp_version;
347
	}
348
349
	public static function site_icon_url( $size = 512 ) {
350
		$site_icon = get_site_icon_url( $size );
351
		return $site_icon ? $site_icon : get_option( 'jetpack_site_icon_url' );
352
	}
353
354
	public static function roles() {
355
		$wp_roles = wp_roles();
356
		return $wp_roles->roles;
357
	}
358
359
	/**
360
	 * Determine time zone from WordPress' options "timezone_string"
361
	 * and "gmt_offset".
362
	 *
363
	 * 1. Check if `timezone_string` is set and return it.
364
	 * 2. Check if `gmt_offset` is set, formats UTC-offset from it and return it.
365
	 * 3. Default to "UTC+0" if nothing is set.
366
	 *
367
	 * @return string
368
	 */
369
	public static function get_timezone() {
370
		$timezone_string = get_option( 'timezone_string' );
371
372
		if ( ! empty( $timezone_string ) ) {
373
			return str_replace( '_', ' ', $timezone_string );
374
		}
375
376
		$gmt_offset = get_option( 'gmt_offset', 0 );
377
378
		$formatted_gmt_offset = sprintf( '%+g', floatval( $gmt_offset ) );
379
380
		$formatted_gmt_offset = str_replace(
381
			array( '.25', '.5', '.75' ),
382
			array( ':15', ':30', ':45' ),
383
			(string) $formatted_gmt_offset
384
		);
385
386
		/* translators: %s is UTC offset, e.g. "+1" */
387
		return sprintf( __( 'UTC%s', 'jetpack' ), $formatted_gmt_offset );
388
	}
389
390
	/**
391
	 * Return list of paused themes.
392
	 *
393
	 * @todo Remove function_exists check when WP 5.2 is the minimum.
394
	 *
395
	 * @return array|bool Array of paused themes or false if unsupported.
396
	 */
397
	public static function get_paused_themes() {
398
		if ( function_exists( 'wp_paused_themes' ) ) {
399
			$paused_themes = wp_paused_themes();
400
			return $paused_themes->get_all();
401
		}
402
		return false;
403
	}
404
405
	/**
406
	 * Return list of paused plugins.
407
	 *
408
	 * @todo Remove function_exists check when WP 5.2 is the minimum.
409
	 *
410
	 * @return array|bool Array of paused plugins or false if unsupported.
411
	 */
412
	public static function get_paused_plugins() {
413
		if ( function_exists( 'wp_paused_plugins' ) ) {
414
			$paused_plugins = wp_paused_plugins();
415
			return $paused_plugins->get_all();
416
		}
417
		return false;
418
	}
419
}
420