Completed
Push — add/importer-stats ( c551c0...5337a5 )
by
unknown
07:23
created

get_calling_importer_class()   B

Complexity

Conditions 10
Paths 21

Size

Total Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
nc 21
nop 0
dl 0
loc 42
rs 7.6666
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 ) {
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 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...
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;
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...
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 View Code Duplication
		if ( $url['host'] === "www.{$option_url[ 'host' ]}" ) {
292
			// remove www if not present in option URL
293
			$url['host'] = $option_url['host'];
294
		}
295 View Code Duplication
		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
	/**
408
	 * Determine the class that extends `WP_Importer` which is responsible for
409
	 * the current action. Designed to be used within an action handler.
410
	 *
411
	 * @return string  The name of the calling class, or 'unknown'.
412
	 */
413
	public static function get_calling_importer_class() {
414
		// If WP_Importer doesn't exist, neither will any importer that extends it
415
		if ( ! class_exists( 'WP_Importer' ) ){
416
			return 'unknown';
417
		}
418
419
		$action = current_filter();
420
		$backtrace = wp_debug_backtrace_summary( null, 0, false );
421
422
		$do_action_pos = -1;
423
		for ( $i = 0; $i < count( $backtrace ); $i++ ) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
424
			// Find the location in the stack of the calling action
425
			if ( preg_match( "/^do_action\\(\'([^\']+)/", $backtrace[ $i ], $matches ) ) {
426
				if ( $matches[1] === $action ) {
427
					$do_action_pos = $i;
428
					break;
429
				}
430
			}
431
		}
432
433
		// if the action wasn't called, the calling class is unknown
434
		if ( -1 === $do_action_pos ) {
435
			return 'unknown';
436
		}
437
438
		// continue iterating the stack looking for a caller that extends WP_Importer
439
		for ( $i = $do_action_pos + 1; $i < count( $backtrace ); $i++ ) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
440
			// grab only class_name from the trace
441
			list( $class_name ) = explode( '->', $backtrace[ $i ] );
442
443
			// check if the class extends WP_Importer
444
			if ( class_exists( $class_name ) ) {
445
				$parents = class_parents( $class_name );
446
				if ( $parents && in_array( 'WP_Importer', $parents ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parents of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
447
					return $class_name;
448
				}
449
			}
450
		}
451
452
		// If we've exhausted the stack without a match, the calling class is unknown
453
		return 'unknown';
454
	}
455
}
456