Completed
Push — update/add-managed-wp-hosts ( cce2ba...80f1e5 )
by
unknown
20:15 queued 14:01
created

get_hosting_provider_by_known_constant()   B

Complexity

Conditions 9
Paths 8

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 8
nop 0
dl 0
loc 29
rs 8.0555
c 0
b 0
f 0
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\Constants;
11
12
/**
13
 * Utility functions to generate data synced to wpcom
14
 */
15
class Functions {
16
	const HTTPS_CHECK_OPTION_PREFIX = 'jetpack_sync_https_history_';
17
	const HTTPS_CHECK_HISTORY       = 5;
18
19
	/**
20
	 * Return array of Jetpack modules.
21
	 *
22
	 * @return array
23
	 */
24
	public static function get_modules() {
25
		require_once JETPACK__PLUGIN_DIR . 'class.jetpack-admin.php';
26
27
		return \Jetpack_Admin::init()->get_modules();
28
	}
29
30
	/**
31
	 * Return array of taxonomies registered on the site.
32
	 *
33
	 * @return array
34
	 */
35
	public static function get_taxonomies() {
36
		global $wp_taxonomies;
37
		$wp_taxonomies_without_callbacks = array();
38
		foreach ( $wp_taxonomies as $taxonomy_name => $taxonomy ) {
39
			$sanitized_taxonomy = self::sanitize_taxonomy( $taxonomy );
40
			if ( ! empty( $sanitized_taxonomy ) ) {
41
				$wp_taxonomies_without_callbacks[ $taxonomy_name ] = $sanitized_taxonomy;
42
			}
43
		}
44
		return $wp_taxonomies_without_callbacks;
45
	}
46
47
	/**
48
	 * Return array of registered shortcodes.
49
	 *
50
	 * @return array
51
	 */
52
	public static function get_shortcodes() {
53
		global $shortcode_tags;
54
		return array_keys( $shortcode_tags );
55
	}
56
57
	/**
58
	 * Removes any callback data since we will not be able to process it on our side anyways.
59
	 *
60
	 * @param \WP_Taxonomy $taxonomy \WP_Taxonomy item.
61
	 *
62
	 * @return mixed|null
63
	 */
64
	public static function sanitize_taxonomy( $taxonomy ) {
65
66
		// Lets clone the taxonomy object instead of modifing the global one.
67
		$cloned_taxonomy = json_decode( wp_json_encode( $taxonomy ) );
68
69
		// recursive taxonomies are no fun.
70
		if ( is_null( $cloned_taxonomy ) ) {
71
			return null;
72
		}
73
		// Remove any meta_box_cb if they are not the default wp ones.
74
		if ( isset( $cloned_taxonomy->meta_box_cb ) &&
75
			! in_array( $cloned_taxonomy->meta_box_cb, array( 'post_tags_meta_box', 'post_categories_meta_box' ), true ) ) {
76
			$cloned_taxonomy->meta_box_cb = null;
77
		}
78
		// Remove update call back.
79
		if ( isset( $cloned_taxonomy->update_count_callback ) &&
80
			! is_null( $cloned_taxonomy->update_count_callback ) ) {
81
			$cloned_taxonomy->update_count_callback = null;
82
		}
83
		// Remove rest_controller_class if it something other then the default.
84
		if ( isset( $cloned_taxonomy->rest_controller_class ) &&
85
			'WP_REST_Terms_Controller' !== $cloned_taxonomy->rest_controller_class ) {
86
			$cloned_taxonomy->rest_controller_class = null;
87
		}
88
		return $cloned_taxonomy;
89
	}
90
91
	/**
92
	 * Return array of registered post types.
93
	 *
94
	 * @return array
95
	 */
96
	public static function get_post_types() {
97
		global $wp_post_types;
98
99
		$post_types_without_callbacks = array();
100
		foreach ( $wp_post_types as $post_type_name => $post_type ) {
101
			$sanitized_post_type = self::sanitize_post_type( $post_type );
102
			if ( ! empty( $sanitized_post_type ) ) {
103
				$post_types_without_callbacks[ $post_type_name ] = $sanitized_post_type;
104
			}
105
		}
106
		return $post_types_without_callbacks;
107
	}
108
109
	/**
110
	 * Sanitizes by cloning post type object.
111
	 *
112
	 * @param object $post_type \WP_Post_Type.
113
	 *
114
	 * @return object
115
	 */
116
	public static function sanitize_post_type( $post_type ) {
117
		// Lets clone the post type object instead of modifing the global one.
118
		$sanitized_post_type = array();
119
		foreach ( Defaults::$default_post_type_attributes as $attribute_key => $default_value ) {
120
			if ( isset( $post_type->{ $attribute_key } ) ) {
121
				$sanitized_post_type[ $attribute_key ] = $post_type->{ $attribute_key };
122
			}
123
		}
124
		return (object) $sanitized_post_type;
125
	}
126
127
	/**
128
	 * Return information about a synced post type.
129
	 *
130
	 * @param array  $sanitized_post_type Array of args used in constructing \WP_Post_Type.
131
	 * @param string $post_type Post type name.
132
	 *
133
	 * @return object \WP_Post_Type
134
	 */
135
	public static function expand_synced_post_type( $sanitized_post_type, $post_type ) {
136
		$post_type        = sanitize_key( $post_type );
137
		$post_type_object = new \WP_Post_Type( $post_type, $sanitized_post_type );
138
		$post_type_object->add_supports();
139
		$post_type_object->add_rewrite_rules();
140
		$post_type_object->add_hooks();
141
		$post_type_object->register_taxonomies();
142
		return (object) $post_type_object;
143
	}
144
145
	/**
146
	 * Returns site's post_type_features.
147
	 *
148
	 * @return array
149
	 */
150
	public static function get_post_type_features() {
151
		global $_wp_post_type_features;
152
153
		return $_wp_post_type_features;
154
	}
155
156
	/**
157
	 * Return hosting provider.
158
	 *
159
	 * Uses a set of known constants, classes, or functions to help determine the hosting platform.
160
	 *
161
	 * @return string Hosting provider.
162
	 */
163
	public static function get_hosting_provider() {
164
		$hosting_provider = 'unknown';
165
166
		$hosting_provider_detection_methods = array(
167
			'get_hosting_provider_by_known_constant',
168
			'get_hosting_provider_by_known_class',
169
			'get_hosting_provider_by_known_function',
170
		);
171
172
		$functions = new Functions();
173
		foreach ( $hosting_provider_detection_methods as $method ) {
174
			$hosting_provider = call_user_func( array( $functions, $method ) );
175
			if ( false !== $hosting_provider ) {
176
				return $hosting_provider;
177
			}
178
		}
179
180
		return $hosting_provider;
181
	}
182
183
	/**
184
	 * Return a hosting provider using a set of known constants.
185
	 *
186
	 * @return mixed A host identifier string or false.
187
	 */
188
	public static function get_hosting_provider_by_known_constant() {
189
		$hosting_provider = false;
190
191
		switch ( true ) {
192
			case ( Constants::is_defined( 'GD_SYSTEM_PLUGIN_DIR' ) ):
193
				$hosting_provider = 'gd-managed-wp';
194
				break;
195
			case ( Constants::is_defined( 'MM_BASE_DIR' ) ):
196
				$hosting_provider = 'bh';
197
				break;
198
			case ( Constants::is_defined( 'PAGELYBIN' ) ):
199
				$hosting_provider = 'pagely';
200
				break;
201
			case ( Constants::is_defined( 'KINSTAMU_VERSION' ) ):
202
				$hosting_provider = 'kinsta';
203
				break;
204
			case ( Constants::is_defined( 'FLYWHEEL_CONFIG_DIR' ) ):
205
				$hosting_provider = 'flywheel';
206
				break;
207
			case ( Constants::is_defined( 'IS_PRESSABLE' ) ):
208
				$hosting_provider = 'pressable';
209
				break;
210
			case ( Constants::is_defined( 'VIP_GO_ENV' ) && false !== Constants::get_constant( 'VIP_GO_ENV' ) ):
211
				$hosting_provider = 'vip-go';
212
				break;
213
		}
214
215
		return $hosting_provider;
216
	}
217
218
	/**
219
	 * Return a hosting provider using a set of known classes.
220
	 *
221
	 * @return mixed A host identifier string or false.
222
	 */
223
	public static function get_hosting_provider_by_known_class() {
224
		$hosting_provider = false;
225
226
		switch ( true ) {
227
			case ( class_exists( '\\WPaaS\\Plugin' ) ):
228
				$hosting_provider = 'gd-managed-wp';
229
				break;
230
		}
231
232
		return $hosting_provider;
233
	}
234
235
	/**
236
	 * Return a hosting provider using a set of known functions.
237
	 *
238
	 * @return mixed A host identifier string or false.
239
	 */
240
	public static function get_hosting_provider_by_known_function() {
241
		$hosting_provider = false;
242
243
		switch ( true ) {
244
			case ( function_exists( 'is_wpe' ) || function_exists( 'is_wpe_snapshot' ) ):
245
				$hosting_provider = 'wpe';
246
				break;
247
		}
248
249
		return $hosting_provider;
250
	}
251
252
	/**
253
	 * Return array of allowed REST API post types.
254
	 *
255
	 * @return array Array of allowed post types.
256
	 */
257
	public static function rest_api_allowed_post_types() {
258
		/** This filter is already documented in class.json-api-endpoints.php */
259
		return apply_filters( 'rest_api_allowed_post_types', array( 'post', 'page', 'revision' ) );
260
	}
261
262
	/**
263
	 * Return array of allowed REST API public metadata.
264
	 *
265
	 * @return array Array of allowed metadata.
266
	 */
267
	public static function rest_api_allowed_public_metadata() {
268
		/** This filter is documented in json-endpoints/class.wpcom-json-api-post-endpoint.php */
269
		return apply_filters( 'rest_api_allowed_public_metadata', array() );
270
	}
271
272
	/**
273
	 * Finds out if a site is using a version control system.
274
	 *
275
	 * @return bool
276
	 **/
277
	public static function is_version_controlled() {
278
279
		if ( ! class_exists( 'WP_Automatic_Updater' ) ) {
280
			require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
281
		}
282
		$updater = new \WP_Automatic_Updater();
283
284
		return (bool) strval( $updater->is_vcs_checkout( ABSPATH ) );
285
	}
286
287
	/**
288
	 * Returns true if the site has file write access false otherwise.
289
	 *
290
	 * @return bool
291
	 **/
292
	public static function file_system_write_access() {
293
		if ( ! function_exists( 'get_filesystem_method' ) ) {
294
			require_once ABSPATH . 'wp-admin/includes/file.php';
295
		}
296
297
		require_once ABSPATH . 'wp-admin/includes/template.php';
298
299
		$filesystem_method = get_filesystem_method();
300
		if ( 'direct' === $filesystem_method ) {
301
			return true;
302
		}
303
304
		ob_start();
305
306
		if ( ! function_exists( 'request_filesystem_credentials' ) ) {
307
			require_once ABSPATH . 'wp-admin/includes/file.php';
308
		}
309
310
		$filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() );
311
		ob_end_clean();
312
		if ( $filesystem_credentials_are_stored ) {
313
			return true;
314
		}
315
316
		return false;
317
	}
318
319
	/**
320
	 * Helper function that is used when getting home or siteurl values. Decides
321
	 * whether to get the raw or filtered value.
322
	 *
323
	 * @param string $url_type URL to get, home or siteurl.
324
	 * @return string
325
	 */
326
	public static function get_raw_or_filtered_url( $url_type ) {
327
		$url_function = ( 'home' === $url_type )
328
			? 'home_url'
329
			: 'site_url';
330
331
		if (
332
			! Constants::is_defined( 'JETPACK_SYNC_USE_RAW_URL' ) ||
333
			Constants::get_constant( 'JETPACK_SYNC_USE_RAW_URL' )
334
		) {
335
			$scheme = is_ssl() ? 'https' : 'http';
336
			$url    = self::get_raw_url( $url_type );
337
			$url    = set_url_scheme( $url, $scheme );
338
		} else {
339
			$url = self::normalize_www_in_url( $url_type, $url_function );
340
		}
341
342
		return self::get_protocol_normalized_url( $url_function, $url );
343
	}
344
345
	/**
346
	 * Return the escaped home_url.
347
	 *
348
	 * @return string
349
	 */
350
	public static function home_url() {
351
		$url = self::get_raw_or_filtered_url( 'home' );
352
353
		/**
354
		 * Allows overriding of the home_url value that is synced back to WordPress.com.
355
		 *
356
		 * @since 5.2.0
357
		 *
358
		 * @param string $home_url
359
		 */
360
		return esc_url_raw( apply_filters( 'jetpack_sync_home_url', $url ) );
361
	}
362
363
	/**
364
	 * Return the escaped siteurl.
365
	 *
366
	 * @return string
367
	 */
368
	public static function site_url() {
369
		$url = self::get_raw_or_filtered_url( 'siteurl' );
370
371
		/**
372
		 * Allows overriding of the site_url value that is synced back to WordPress.com.
373
		 *
374
		 * @since 5.2.0
375
		 *
376
		 * @param string $site_url
377
		 */
378
		return esc_url_raw( apply_filters( 'jetpack_sync_site_url', $url ) );
379
	}
380
381
	/**
382
	 * Return main site URL with a normalized protocol.
383
	 *
384
	 * @return string
385
	 */
386
	public static function main_network_site_url() {
387
		return self::get_protocol_normalized_url( 'main_network_site_url', network_site_url() );
388
	}
389
390
	/**
391
	 * Return URL with a normalized protocol.
392
	 *
393
	 * @param callable $callable Function to retrieve URL option.
394
	 * @param string   $new_value URL Protocol to set URLs to.
395
	 * @return string Normalized URL.
396
	 */
397
	public static function get_protocol_normalized_url( $callable, $new_value ) {
398
		$option_key = self::HTTPS_CHECK_OPTION_PREFIX . $callable;
399
400
		$parsed_url = wp_parse_url( $new_value );
401
		if ( ! $parsed_url ) {
402
			return $new_value;
403
		}
404
		if ( array_key_exists( 'scheme', $parsed_url ) ) {
405
			$scheme = $parsed_url['scheme'];
406
		} else {
407
			$scheme = '';
408
		}
409
		$scheme_history   = get_option( $option_key, array() );
410
		$scheme_history[] = $scheme;
411
412
		// Limit length to self::HTTPS_CHECK_HISTORY.
413
		$scheme_history = array_slice( $scheme_history, ( self::HTTPS_CHECK_HISTORY * -1 ) );
414
415
		update_option( $option_key, $scheme_history );
416
417
		$forced_scheme = in_array( 'https', $scheme_history, true ) ? 'https' : 'http';
418
419
		return set_url_scheme( $new_value, $forced_scheme );
420
	}
421
422
	/**
423
	 * Return URL from option or PHP constant.
424
	 *
425
	 * @param string $option_name (e.g. 'home').
426
	 *
427
	 * @return mixed|null URL.
428
	 */
429
	public static function get_raw_url( $option_name ) {
430
		$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...
431
		$constant = ( 'home' === $option_name )
432
			? 'WP_HOME'
433
			: 'WP_SITEURL';
434
435
		// Since we disregard the constant for multisites in ms-default-filters.php,
436
		// let's also use the db value if this is a multisite.
437
		if ( ! is_multisite() && Constants::is_defined( $constant ) ) {
438
			$value = Constants::get_constant( $constant );
439
		} else {
440
			// Let's get the option from the database so that we can bypass filters. This will help
441
			// ensure that we get more uniform values.
442
			$value = \Jetpack_Options::get_raw_option( $option_name );
443
		}
444
445
		return $value;
446
	}
447
448
	/**
449
	 * Normalize domains by removing www unless declared in the site's option.
450
	 *
451
	 * @param string   $option Option value from the site.
452
	 * @param callable $url_function Function retrieving the URL to normalize.
453
	 * @return mixed|string URL.
454
	 */
455
	public static function normalize_www_in_url( $option, $url_function ) {
456
		$url        = wp_parse_url( call_user_func( $url_function ) );
457
		$option_url = wp_parse_url( get_option( $option ) );
458
459
		if ( ! $option_url || ! $url ) {
460
			return $url;
461
		}
462
463 View Code Duplication
		if ( "www.{$option_url[ 'host' ]}" === $url['host'] ) {
464
			// remove www if not present in option URL.
465
			$url['host'] = $option_url['host'];
466
		}
467 View Code Duplication
		if ( "www.{$url[ 'host' ]}" === $option_url['host'] ) {
468
			// add www if present in option URL.
469
			$url['host'] = $option_url['host'];
470
		}
471
472
		$normalized_url = "{$url['scheme']}://{$url['host']}";
473
		if ( isset( $url['path'] ) ) {
474
			$normalized_url .= "{$url['path']}";
475
		}
476
477
		if ( isset( $url['query'] ) ) {
478
			$normalized_url .= "?{$url['query']}";
479
		}
480
481
		return $normalized_url;
482
	}
483
484
	/**
485
	 * Return filtered value of get_plugins.
486
	 *
487
	 * @return mixed|void
488
	 */
489
	public static function get_plugins() {
490
		if ( ! function_exists( 'get_plugins' ) ) {
491
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
492
		}
493
494
		/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
495
		return apply_filters( 'all_plugins', get_plugins() );
496
	}
497
498
	/**
499
	 * Get custom action link tags that the plugin is using
500
	 * Ref: https://codex.wordpress.org/Plugin_API/Filter_Reference/plugin_action_links_(plugin_file_name)
501
	 *
502
	 * @param string $plugin_file_singular Particular plugin.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $plugin_file_singular not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
503
	 * @return array of plugin action links (key: link name value: url)
504
	 */
505
	public static function get_plugins_action_links( $plugin_file_singular = null ) {
506
		// Some sites may have DOM disabled in PHP fail early.
507
		if ( ! class_exists( 'DOMDocument' ) ) {
508
			return array();
509
		}
510
		$plugins_action_links = get_option( 'jetpack_plugin_api_action_links', array() );
511
		if ( ! empty( $plugins_action_links ) ) {
512
			if ( is_null( $plugin_file_singular ) ) {
513
				return $plugins_action_links;
514
			}
515
			return ( isset( $plugins_action_links[ $plugin_file_singular ] ) ? $plugins_action_links[ $plugin_file_singular ] : null );
516
		}
517
		return array();
518
	}
519
520
	/**
521
	 * Return the WP version as defined in the $wp_version global.
522
	 *
523
	 * @return string
524
	 */
525
	public static function wp_version() {
526
		global $wp_version;
527
		return $wp_version;
528
	}
529
530
	/**
531
	 * Return site icon url used on the site.
532
	 *
533
	 * @param int $size Size of requested icon in pixels.
534
	 * @return mixed|string|void
535
	 */
536
	public static function site_icon_url( $size = 512 ) {
537
		$site_icon = get_site_icon_url( $size );
538
		return $site_icon ? $site_icon : get_option( 'jetpack_site_icon_url' );
539
	}
540
541
	/**
542
	 * Return roles registered on the site.
543
	 *
544
	 * @return array
545
	 */
546
	public static function roles() {
547
		$wp_roles = wp_roles();
548
		return $wp_roles->roles;
549
	}
550
551
	/**
552
	 * Determine time zone from WordPress' options "timezone_string"
553
	 * and "gmt_offset".
554
	 *
555
	 * 1. Check if `timezone_string` is set and return it.
556
	 * 2. Check if `gmt_offset` is set, formats UTC-offset from it and return it.
557
	 * 3. Default to "UTC+0" if nothing is set.
558
	 *
559
	 * Note: This function is specifically not using wp_timezone() to keep consistency with
560
	 * the existing formatting of the timezone string.
561
	 *
562
	 * @return string
563
	 */
564
	public static function get_timezone() {
565
		$timezone_string = get_option( 'timezone_string' );
566
567
		if ( ! empty( $timezone_string ) ) {
568
			return str_replace( '_', ' ', $timezone_string );
569
		}
570
571
		$gmt_offset = get_option( 'gmt_offset', 0 );
572
573
		$formatted_gmt_offset = sprintf( '%+g', floatval( $gmt_offset ) );
574
575
		$formatted_gmt_offset = str_replace(
576
			array( '.25', '.5', '.75' ),
577
			array( ':15', ':30', ':45' ),
578
			(string) $formatted_gmt_offset
579
		);
580
581
		/* translators: %s is UTC offset, e.g. "+1" */
582
		return sprintf( __( 'UTC%s', 'jetpack' ), $formatted_gmt_offset );
583
	}
584
585
	/**
586
	 * Return list of paused themes.
587
	 *
588
	 * @todo Remove function_exists check when WP 5.2 is the minimum.
589
	 *
590
	 * @return array|bool Array of paused themes or false if unsupported.
591
	 */
592
	public static function get_paused_themes() {
593
		if ( function_exists( 'wp_paused_themes' ) ) {
594
			$paused_themes = wp_paused_themes();
595
			return $paused_themes->get_all();
596
		}
597
		return false;
598
	}
599
600
	/**
601
	 * Return list of paused plugins.
602
	 *
603
	 * @todo Remove function_exists check when WP 5.2 is the minimum.
604
	 *
605
	 * @return array|bool Array of paused plugins or false if unsupported.
606
	 */
607
	public static function get_paused_plugins() {
608
		if ( function_exists( 'wp_paused_plugins' ) ) {
609
			$paused_plugins = wp_paused_plugins();
610
			return $paused_plugins->get_all();
611
		}
612
		return false;
613
	}
614
}
615