Passed
Push — master ( 1d60eb...03dff3 )
by Stiofan
06:44 queued 03:02
created

WP_Font_Awesome_Settings   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 429
Duplicated Lines 9.09 %

Coupling/Cohesion

Components 2
Dependencies 0

Importance

Changes 0
Metric Value
dl 39
loc 429
rs 6.96
c 0
b 0
f 0
wmc 53
lcom 2
cbo 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A instance() 0 16 4
B init() 9 30 11
A enqueue_style() 15 15 2
A enqueue_scripts() 15 15 2
A get_url() 0 13 5
B remove_font_awesome() 0 23 9
A register_settings() 0 3 1
A menu_item() 0 6 1
A get_settings() 0 22 1
B settings_page() 0 118 3
A validate_version_number() 0 10 2
A get_latest_version() 0 19 6
A get_latest_version_from_api() 0 12 6

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 WP_Font_Awesome_Settings 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 WP_Font_Awesome_Settings, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * A class for adjusting font awesome settings on WordPress
4
 *
5
 * This class can be added to any plugin or theme and will add a settings screen to WordPress to control Font Awesome settings.
6
 *
7
 * @link https://github.com/AyeCode/wp-font-awesome-settings
8
 *
9
 * @internal This file should not be edited directly but pulled from the github repo above.
10
 */
11
12
/**
13
 * Bail if we are not in WP.
14
 */
15
if ( ! defined( 'ABSPATH' ) ) {
16
	exit;
17
}
18
19
/**
20
 * Only add if the class does not already exist.
21
 */
22
if ( ! class_exists( 'WP_Font_Awesome_Settings' ) ) {
23
24
	/**
25
	 * A Class to be able to change settings for Font Awesome.
26
	 *
27
	 * Class WP_Font_Awesome_Settings
28
	 * @ver 1.0.7
29
	 * @todo decide how to implement textdomain
30
	 */
31
	class WP_Font_Awesome_Settings {
32
33
		/**
34
		 * Class version version.
35
		 *
36
		 * @var string
37
		 */
38
		public $version = '1.0.7';
39
40
		/**
41
		 * Latest version of Font Awesome at time of publish published.
42
		 *
43
		 * @var string
44
		 */
45
		public $latest = "5.5.0";
46
47
		/**
48
		 * The title.
49
		 *
50
		 * @var string
51
		 */
52
		public $name = 'Font Awesome';
53
54
		/**
55
		 * Holds the settings values.
56
		 *
57
		 * @var array
58
		 */
59
		private $settings;
60
61
		/**
62
		 * WP_Font_Awesome_Settings instance.
63
		 *
64
		 * @access private
65
		 * @since  1.0.0
66
		 * @var    WP_Font_Awesome_Settings There can be only one!
67
		 */
68
		private static $instance = null;
69
70
		/**
71
		 * Main WP_Font_Awesome_Settings Instance.
72
		 *
73
		 * Ensures only one instance of WP_Font_Awesome_Settings is loaded or can be loaded.
74
		 *
75
		 * @since 1.0.0
76
		 * @static
77
		 * @return WP_Font_Awesome_Settings - Main instance.
78
		 */
79
		public static function instance() {
80
			if ( ! isset( self::$instance ) && ! ( self::$instance instanceof WP_Font_Awesome_Settings ) ) {
81
				self::$instance = new WP_Font_Awesome_Settings;
82
83
				add_action( 'init', array( self::$instance, 'init' ) ); // set settings
84
85
				if ( is_admin() ) {
86
					add_action( 'admin_menu', array( self::$instance, 'menu_item' ) );
87
					add_action( 'admin_init', array( self::$instance, 'register_settings' ) );
88
				}
89
90
				do_action( 'wp_font_awesome_settings_loaded' );
91
			}
92
93
			return self::$instance;
94
		}
95
96
		/**
97
		 * Initiate the settings and add the required action hooks.
98
		 */
99
		public function init() {
100
			$this->settings = $this->get_settings();
101
102
			if ( $this->settings['type'] == 'CSS' ) {
103
104
				if ( $this->settings['enqueue'] == '' || $this->settings['frontend'] ) {
105
					add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_style' ), 5000 );//echo '###';exit;
106
				}
107
108 View Code Duplication
				if ( $this->settings['enqueue'] == '' || $this->settings['backend'] ) {
109
					add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_style' ), 5000 );
110
				}
111
112
			} else {
113
114 View Code Duplication
				if ( $this->settings['enqueue'] == '' || $this->settings['frontend'] ) {
115
					add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ), 5000 );//echo '###';exit;
116
				}
117
118 View Code Duplication
				if ( $this->settings['enqueue'] == '' || $this->settings['backend'] ) {
119
					add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 5000 );
120
				}
121
			}
122
123
			// remove font awesome if set to do so
124
			if ( $this->settings['dequeue'] == '1' ) {
125
				add_action( 'clean_url', array( $this, 'remove_font_awesome' ), 5000, 3 );
126
			}
127
128
		}
129
130
		/**
131
		 * Adds the Font Awesome styles.
132
		 */
133 View Code Duplication
		public function enqueue_style() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
134
			// build url
135
			$url = $this->get_url();
136
137
			wp_deregister_style( 'font-awesome' ); // deregister in case its already there
138
			wp_register_style( 'font-awesome', $url, array(), null );
139
			wp_enqueue_style( 'font-awesome' );
140
141
			if ( $this->settings['shims'] ) {
142
				$url = $this->get_url( true );
143
				wp_deregister_style( 'font-awesome-shims' ); // deregister in case its already there
144
				wp_register_style( 'font-awesome-shims', $url, array(), null );
145
				wp_enqueue_style( 'font-awesome-shims' );
146
			}
147
		}
148
149
		/**
150
		 * Adds the Font Awesome JS.
151
		 */
152 View Code Duplication
		public function enqueue_scripts() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
153
			// build url
154
			$url = $this->get_url();
155
156
			wp_deregister_script( 'font-awesome' ); // deregister in case its already there
157
			wp_register_script( 'font-awesome', $url, array(), null );
158
			wp_enqueue_script( 'font-awesome' );
159
160
			if ( $this->settings['shims'] ) {
161
				$url = $this->get_url( true );
162
				wp_deregister_script( 'font-awesome-shims' ); // deregister in case its already there
163
				wp_register_script( 'font-awesome-shims', $url, array(), null );
164
				wp_enqueue_script( 'font-awesome-shims' );
165
			}
166
		}
167
168
		/**
169
		 * Get the url of the Font Awesome files.
170
		 *
171
		 * @param bool $shims If this is a shim file or not.
172
		 *
173
		 * @return string The url to the file.
174
		 */
175
		public function get_url( $shims = false ) {
176
			$script  = $shims ? 'v4-shims' : 'all';
177
			$type    = $this->settings['type'];
178
			$version = $this->settings['version'];
179
180
			$url = "https://use.fontawesome.com/releases/"; // CDN
181
			$url .= ! empty( $version ) ? "v" . $version . '/' : "v" . $this->get_latest_version() . '/'; // version
182
			$url .= $type == 'CSS' ? 'css/' : 'js/'; // type
183
			$url .= $type == 'CSS' ? $script . '.css' : $script . '.js'; // type
184
			$url .= "?wpfas=true"; // set our var so our version is not removed
185
186
			return $url;
187
		}
188
189
		/**
190
		 * Try and remove any other versions of Font Awesome added by other plugins/themes.
191
		 *
192
		 * Uses the clean_url filter to try and remove any other Font Awesome files added, it can also add pseudo-elements flag for the JS version.
193
		 *
194
		 * @param $url
195
		 * @param $original_url
196
		 * @param $_context
197
		 *
198
		 * @return string The filtered url.
199
		 */
200
		public function remove_font_awesome( $url, $original_url, $_context ) {
201
202
			if ( $_context == 'display'
203
			     && ( strstr( $url, "fontawesome" ) !== false || strstr( $url, "font-awesome" ) !== false )
204
			     && ( strstr( $url, ".js" ) !== false || strstr( $url, ".css" ) !== false )
205
			) {// it's a font-awesome-url (probably)
206
207
				if ( strstr( $url, "wpfas=true" ) !== false ) {
208
					if ( $this->settings['type'] == 'JS' ) {
209
						if ( $this->settings['js-pseudo'] ) {
210
							$url .= "' data-search-pseudo-elements defer='defer";
211
						} else {
212
							$url .= "' defer='defer";
213
						}
214
					}
215
				} else {
216
					$url = ''; // removing the url removes the file
217
				}
218
219
			}
220
221
			return $url;
222
		}
223
224
		/**
225
		 * Register the database settings with WordPress.
226
		 */
227
		public function register_settings() {
228
			register_setting( 'wp-font-awesome-settings', 'wp-font-awesome-settings' );
229
		}
230
231
		/**
232
		 * Add the WordPress settings menu item.
233
		 */
234
		public function menu_item() {
235
			add_options_page( $this->name, $this->name, 'manage_options', 'wp-font-awesome-settings', array(
236
				$this,
237
				'settings_page'
238
			) );
239
		}
240
241
		/**
242
		 * Get the current Font Awesome output settings.
243
		 *
244
		 * @return array The array of settings.
245
		 */
246
		public function get_settings() {
247
248
			$db_settings = get_option( 'wp-font-awesome-settings' );
249
250
			$defaults = array(
251
				'type'      => 'CSS', // type to use, CSS or JS
252
				'version'   => '', // latest
253
				'enqueue'   => '', // front and backend
254
				'shims'     => '1', // default on for now, @todo maybe change to off in 2020
255
				'js-pseudo' => '0', // if the pseudo elements flag should be set (CPU intensive)
256
				'dequeue'   => '0', // if we should try to remove other versions added by other plugins/themes
257
			);
258
259
			$settings = wp_parse_args( $db_settings, $defaults );
260
261
			/**
262
			 * Filter the Font Awesome settings.
263
			 *
264
			 * @todo if we add this filer people might use it and then it defeates the purpose of this class :/
265
			 */
266
			return $this->settings = apply_filters( 'wp-font-awesome-settings', $settings, $db_settings, $defaults );
267
		}
268
269
270
		/**
271
		 * The settings page html output.
272
		 */
273
		public function settings_page() {
274
			if ( ! current_user_can( 'manage_options' ) ) {
275
				wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
276
			}
277
278
			// a hidden way to force the update of the verison number vai api instead of waiting the 48 hours
279
			if(isset($_REQUEST['force-version-check'])){
280
				$this->get_latest_version($force_api = true);
281
			}
282
			?>
283
			<div class="wrap">
284
				<h1><?php echo $this->name; ?></h1>
285
				<form method="post" action="options.php">
286
					<?php
287
					settings_fields( 'wp-font-awesome-settings' );
288
					do_settings_sections( 'wp-font-awesome-settings' );
289
					?>
290
					<table class="form-table">
291
						<tr valign="top">
292
							<th scope="row"><label for="wpfas-type"><?php _e( 'Type' ); ?></label></th>
293
							<td>
294
								<select name="wp-font-awesome-settings[type]" id="wpfas-type">
295
									<option
296
										value="CSS" <?php selected( $this->settings['type'], 'CSS' ); ?>><?php _e( 'CSS (default)' ); ?></option>
297
									<option value="JS" <?php selected( $this->settings['type'], 'JS' ); ?>>JS</option>
298
								</select>
299
							</td>
300
						</tr>
301
302
						<tr valign="top">
303
							<th scope="row"><label for="wpfas-version"><?php _e( 'Version' ); ?></label></th>
304
							<td>
305
								<select name="wp-font-awesome-settings[version]" id="wpfas-version">
306
									<option
307
										value="" <?php selected( $this->settings['version'], '' ); ?>><?php echo sprintf( __( 'Latest - %s (default)' ), $this->get_latest_version() ); ?></option>
308
									<option value="5.5.0" <?php selected( $this->settings['version'], '5.5.0' ); ?>>
309
										5.5.0
310
									</option>
311
									<option value="5.4.0" <?php selected( $this->settings['version'], '5.4.0' ); ?>>
312
										5.4.0
313
									</option>
314
									<option value="5.3.0" <?php selected( $this->settings['version'], '5.3.0' ); ?>>
315
										5.3.0
316
									</option>
317
									<option value="5.2.0" <?php selected( $this->settings['version'], '5.2.0' ); ?>>
318
										5.2.0
319
									</option>
320
									<option value="5.1.0" <?php selected( $this->settings['version'], '5.1.0' ); ?>>
321
										5.1.0
322
									</option>
323
									<option value="4.7.0" <?php selected( $this->settings['version'], '4.7.0' ); ?>>
324
										4.7.1 (CSS only)
325
									</option>
326
								</select>
327
							</td>
328
						</tr>
329
330
						<tr valign="top">
331
							<th scope="row"><label for="wpfas-enqueue"><?php _e( 'Enqueue' ); ?></label></th>
332
							<td>
333
								<select name="wp-font-awesome-settings[enqueue]" id="wpfas-enqueue">
334
									<option
335
										value="" <?php selected( $this->settings['enqueue'], '' ); ?>><?php _e( 'Frontend + Backend (default)' ); ?></option>
336
									<option
337
										value="frontend" <?php selected( $this->settings['enqueue'], 'frontend' ); ?>><?php _e( 'Frontend' ); ?></option>
338
									<option
339
										value="backend" <?php selected( $this->settings['enqueue'], 'backend' ); ?>><?php _e( 'Backend' ); ?></option>
340
								</select>
341
							</td>
342
						</tr>
343
344
						<tr valign="top">
345
							<th scope="row"><label
346
									for="wpfas-shims"><?php _e( 'Enable v4 shims compatibility' ); ?></label></th>
347
							<td>
348
								<input type="hidden" name="wp-font-awesome-settings[shims]" value="0"/>
349
								<input type="checkbox" name="wp-font-awesome-settings[shims]"
350
								       value="1" <?php checked( $this->settings['shims'], '1' ); ?> id="wpfas-shims"/>
351
								<span><?php _e( 'This enables v4 classes to work with v5, sort of like a band-aid until everyone has updated everything to v5.' ); ?></span>
352
							</td>
353
						</tr>
354
355
						<tr valign="top">
356
							<th scope="row"><label
357
									for="wpfas-js-pseudo"><?php _e( 'Enable JS pseudo elements (not recommended)' ); ?></label>
358
							</th>
359
							<td>
360
								<input type="hidden" name="wp-font-awesome-settings[js-pseudo]" value="0"/>
361
								<input type="checkbox" name="wp-font-awesome-settings[js-pseudo]"
362
								       value="1" <?php checked( $this->settings['js-pseudo'], '1' ); ?>
363
								       id="wpfas-js-pseudo"/>
364
								<span><?php _e( 'Used only with the JS version, this will make pseudo-elements work but can be CPU intensive on some sites.' ); ?></span>
365
							</td>
366
						</tr>
367
368
						<tr valign="top">
369
							<th scope="row"><label for="wpfas-dequeue"><?php _e( 'Dequeue' ); ?></label></th>
370
							<td>
371
								<input type="hidden" name="wp-font-awesome-settings[dequeue]" value="0"/>
372
								<input type="checkbox" name="wp-font-awesome-settings[dequeue]"
373
								       value="1" <?php checked( $this->settings['dequeue'], '1' ); ?>
374
								       id="wpfas-dequeue"/>
375
								<span><?php _e( 'This will try to dequeue any other Font Awesome versions loaded by other sources if they are added with `font-awesome` or `fontawesome` in the name.' ); ?></span>
376
							</td>
377
						</tr>
378
379
380
					</table>
381
					<?php
382
					submit_button();
383
					?>
384
				</form>
385
386
				<div id="wpfas-version"><?php echo $this->version; ?></div>
387
			</div>
388
389
			<?php
390
		}
391
392
		/**
393
		 * Check a version number is valid and if so return it or else return an empty string.
394
		 *
395
		 * @param $version string The version number to check.
396
		 * @since 1.0.6
397
		 *
398
		 * @return string Either a valid version number or an empty string.
399
		 */
400
		public function validate_version_number( $version ) {
401
402
			if ( version_compare( $version, '0.0.1', '>=' ) >= 0 ) {
403
				// valid
404
			} else {
405
				$version = '';// not validated
406
			}
407
408
			return $version;
409
		}
410
411
412
		/**
413
		 * Get the latest version of Font Awesome.
414
		 *
415
		 * We check for a cached bersion and if none we will check for a live version via API and then cache it for 48 hours.
416
		 *
417
		 * @since 1.0.7
418
		 * @return mixed|string The latest version number found.
419
		 */
420
		public function get_latest_version($force_api = false) {
421
			$latest_version = $this->latest;
422
423
			$cache = get_transient( 'wp-font-awesome-settings-version' );
424
425
			if ( $cache === false || $force_api) { // its not set
426
				$api_ver = $this->get_latest_version_from_api();
427
				if ( version_compare( $api_ver, $this->latest, '>=' ) >= 0 ) {
428
					$latest_version = $api_ver;
429
					set_transient( 'wp-font-awesome-settings-version', $api_ver, 48 * HOUR_IN_SECONDS );
430
				}
431
			} elseif ( $this->validate_version_number( $cache ) ) {
432
				if ( version_compare( $cache, $this->latest, '>=' ) >= 0 ) {
433
					$latest_version = $cache;
434
				}
435
			}
436
437
			return $latest_version;
438
		}
439
440
		/**
441
		 * Get the latest Font Awesome version from the github API.
442
		 *
443
		 * @since 1.0.7
444
		 * @return string The latest version number or `0` on API fail.
445
		 */
446
		public function get_latest_version_from_api() {
447
			$version  = "0";
448
			$response = wp_remote_get( "https://api.github.com/repos/FortAwesome/Font-Awesome/releases/latest" );
449
			if ( ! is_wp_error( $response ) && is_array( $response ) ) {
450
				$api_response = json_decode( wp_remote_retrieve_body( $response ), true );
451
				if ( isset( $api_response['tag_name'] ) && version_compare( $api_response['tag_name'], $this->latest, '>=' ) >= 0 && empty( $api_response['prerelease'] ) ) {
452
					$version = $api_response['tag_name'];
453
				}
454
			}
455
456
			return $version;
457
		}
458
459
	}
460
461
	/**
462
	 * Run the class if found.
463
	 */
464
	WP_Font_Awesome_Settings::instance();
465
}