Completed
Push — renovate/gridicons-3.x ( c004c1...f8ccd4 )
by
unknown
284:06 queued 275:32
created

Functions   F

Complexity

Total Complexity 79

Size/Duplication

Total Lines 411
Duplicated Lines 1.95 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 79
lcom 1
cbo 4
dl 8
loc 411
rs 2.08
c 0
b 0
f 0

28 Methods

Rating   Name   Duplication   Size   Complexity  
A get_modules() 0 5 1
A get_taxonomies() 0 13 3
A get_shortcodes() 0 4 1
B sanitize_taxonomy() 0 26 8
A get_post_types() 0 14 3
A sanitize_post_type() 0 10 3
A expand_synced_post_type() 0 9 1
A get_post_type_features() 0 5 1
B get_hosting_provider() 0 18 9
A rest_api_allowed_post_types() 0 4 1
A rest_api_allowed_public_metadata() 0 4 1
A is_version_controlled() 0 9 2
A file_system_write_access() 0 26 5
A get_raw_or_filtered_url() 0 18 5
A home_url() 0 12 1
A site_url() 0 12 1
A main_network_site_url() 0 3 1
A get_protocol_normalized_url() 0 24 4
A get_raw_url() 0 18 4
B normalize_www_in_url() 8 28 7
A get_plugins() 0 8 2
A get_plugins_action_links() 0 14 5
A wp_version() 0 4 1
A site_icon_url() 0 4 2
A roles() 0 4 1
A get_timezone() 0 20 2
A get_paused_themes() 0 7 2
A get_paused_plugins() 0 7 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Functions often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Functions, and based on these observations, apply Extract Interface, too.

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