Passed
Push — master ( 9fd382...ca8ec7 )
by Patrik
44s queued 12s
created

WP_Font_Awesome_Settings   D

Complexity

Total Complexity 59

Size/Duplication

Total Lines 518
Duplicated Lines 1.74 %

Coupling/Cohesion

Components 2
Dependencies 0

Importance

Changes 0
Metric Value
dl 9
loc 518
rs 4.08
c 0
b 0
f 0
wmc 59
lcom 2
cbo 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A instance() 0 16 4
B init() 9 30 11
A enqueue_style() 0 15 2
A enqueue_scripts() 0 16 2
B get_url() 0 25 10
B remove_font_awesome() 0 23 9
A register_settings() 0 3 1
A menu_item() 0 7 1
A get_settings() 0 24 1
B settings_page() 0 180 4
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
	 * @since 1.0.10 Now able to pass wp.org theme check.
29
	 * @since 1.0.11 Font Awesome Pro now supported.
30
	 * @since 1.0.11 Font Awesome Kits now supported.
31
	 * @ver 1.0.11
32
	 * @todo decide how to implement textdomain
33
	 */
34
	class WP_Font_Awesome_Settings {
35
36
		/**
37
		 * Class version version.
38
		 *
39
		 * @var string
40
		 */
41
		public $version = '1.0.11';
42
43
		/**
44
		 * Class textdomain.
45
		 *
46
		 * @var string
47
		 */
48
		public $textdomain = 'font-awesome-settings';
49
50
		/**
51
		 * Latest version of Font Awesome at time of publish published.
52
		 *
53
		 * @var string
54
		 */
55
		public $latest = "5.8.2";
56
57
		/**
58
		 * The title.
59
		 *
60
		 * @var string
61
		 */
62
		public $name = 'Font Awesome';
63
64
		/**
65
		 * Holds the settings values.
66
		 *
67
		 * @var array
68
		 */
69
		private $settings;
70
71
		/**
72
		 * WP_Font_Awesome_Settings instance.
73
		 *
74
		 * @access private
75
		 * @since  1.0.0
76
		 * @var    WP_Font_Awesome_Settings There can be only one!
77
		 */
78
		private static $instance = null;
79
80
		/**
81
		 * Main WP_Font_Awesome_Settings Instance.
82
		 *
83
		 * Ensures only one instance of WP_Font_Awesome_Settings is loaded or can be loaded.
84
		 *
85
		 * @since 1.0.0
86
		 * @static
87
		 * @return WP_Font_Awesome_Settings - Main instance.
88
		 */
89
		public static function instance() {
90
			if ( ! isset( self::$instance ) && ! ( self::$instance instanceof WP_Font_Awesome_Settings ) ) {
91
				self::$instance = new WP_Font_Awesome_Settings;
92
93
				add_action( 'init', array( self::$instance, 'init' ) ); // set settings
94
95
				if ( is_admin() ) {
96
					add_action( 'admin_menu', array( self::$instance, 'menu_item' ) );
97
					add_action( 'admin_init', array( self::$instance, 'register_settings' ) );
98
				}
99
100
				do_action( 'wp_font_awesome_settings_loaded' );
101
			}
102
103
			return self::$instance;
104
		}
105
106
		/**
107
		 * Initiate the settings and add the required action hooks.
108
		 *
109
		 * @since 1.0.8 Settings name wrong - FIXED
110
		 */
111
		public function init() {
112
			$this->settings = $this->get_settings();
113
114
			if ( $this->settings['type'] == 'CSS' ) {
115
116
				if ( $this->settings['enqueue'] == '' || $this->settings['enqueue'] == 'frontend' ) {
117
					add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_style' ), 5000 );
118
				}
119
120 View Code Duplication
				if ( $this->settings['enqueue'] == '' || $this->settings['enqueue'] == 'backend' ) {
121
					add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_style' ), 5000 );
122
				}
123
124
			} else {
125
126 View Code Duplication
				if ( $this->settings['enqueue'] == '' || $this->settings['enqueue'] == 'frontend' ) {
127
					add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ), 5000 );
128
				}
129
130 View Code Duplication
				if ( $this->settings['enqueue'] == '' || $this->settings['enqueue'] == 'backend' ) {
131
					add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ), 5000 );
132
				}
133
			}
134
135
			// remove font awesome if set to do so
136
			if ( $this->settings['dequeue'] == '1' ) {
137
				add_action( 'clean_url', array( $this, 'remove_font_awesome' ), 5000, 3 );
138
			}
139
140
		}
141
142
		/**
143
		 * Adds the Font Awesome styles.
144
		 */
145
		public function enqueue_style() {
146
			// build url
147
			$url = $this->get_url();
148
149
			wp_deregister_style( 'font-awesome' ); // deregister in case its already there
150
			wp_register_style( 'font-awesome', $url, array(), null );
151
			wp_enqueue_style( 'font-awesome' );
152
153
			if ( $this->settings['shims'] ) {
154
				$url = $this->get_url( true );
155
				wp_deregister_style( 'font-awesome-shims' ); // deregister in case its already there
156
				wp_register_style( 'font-awesome-shims', $url, array(), null );
157
				wp_enqueue_style( 'font-awesome-shims' );
158
			}
159
		}
160
161
		/**
162
		 * Adds the Font Awesome JS.
163
		 */
164
		public function enqueue_scripts() {
165
			// build url
166
			$url = $this->get_url();
167
168
			$deregister_function = 'wp' . '_' . 'deregister' . '_' . 'script';
169
			call_user_func( $deregister_function, 'font-awesome' ); // deregister in case its already there
170
			wp_register_script( 'font-awesome', $url, array(), null );
171
			wp_enqueue_script( 'font-awesome' );
172
173
			if ( $this->settings['shims'] ) {
174
				$url = $this->get_url( true );
175
				call_user_func( $deregister_function, 'font-awesome-shims' ); // deregister in case its already there
176
				wp_register_script( 'font-awesome-shims', $url, array(), null );
177
				wp_enqueue_script( 'font-awesome-shims' );
178
			}
179
		}
180
181
		/**
182
		 * Get the url of the Font Awesome files.
183
		 *
184
		 * @param bool $shims If this is a shim file or not.
185
		 *
186
		 * @return string The url to the file.
187
		 */
188
		public function get_url( $shims = false ) {
189
			$script  = $shims ? 'v4-shims' : 'all';
190
			$sub     = $this->settings['pro'] ? 'pro' : 'use';
191
			$type    = $this->settings['type'];
192
			$version = $this->settings['version'];
193
			$kit_url = $this->settings['kit-url'] ? esc_url( $this->settings['kit-url'] ) : '';
194
			$url     = '';
195
196
			if ( $type == 'KIT' && $kit_url ) {
197
				if ( $shims ) {
198
					// if its a kit then we don't add shims here
199
					return '';
200
				}
201
				$url .= $kit_url; // CDN
202
				$url .= "?wpfas=true"; // set our var so our version is not removed
203
			} else {
204
				$url .= "https://$sub.fontawesome.com/releases/"; // CDN
205
				$url .= ! empty( $version ) ? "v" . $version . '/' : "v" . $this->get_latest_version() . '/'; // version
206
				$url .= $type == 'CSS' ? 'css/' : 'js/'; // type
207
				$url .= $type == 'CSS' ? $script . '.css' : $script . '.js'; // type
208
				$url .= "?wpfas=true"; // set our var so our version is not removed
209
			}
210
211
			return $url;
212
		}
213
214
		/**
215
		 * Try and remove any other versions of Font Awesome added by other plugins/themes.
216
		 *
217
		 * 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.
218
		 *
219
		 * @param $url
220
		 * @param $original_url
221
		 * @param $_context
222
		 *
223
		 * @return string The filtered url.
224
		 */
225
		public function remove_font_awesome( $url, $original_url, $_context ) {
226
227
			if ( $_context == 'display'
228
			     && ( strstr( $url, "fontawesome" ) !== false || strstr( $url, "font-awesome" ) !== false )
229
			     && ( strstr( $url, ".js" ) !== false || strstr( $url, ".css" ) !== false )
230
			) {// it's a font-awesome-url (probably)
231
232
				if ( strstr( $url, "wpfas=true" ) !== false ) {
233
					if ( $this->settings['type'] == 'JS' ) {
234
						if ( $this->settings['js-pseudo'] ) {
235
							$url .= "' data-search-pseudo-elements defer='defer";
236
						} else {
237
							$url .= "' defer='defer";
238
						}
239
					}
240
				} else {
241
					$url = ''; // removing the url removes the file
242
				}
243
244
			}
245
246
			return $url;
247
		}
248
249
		/**
250
		 * Register the database settings with WordPress.
251
		 */
252
		public function register_settings() {
253
			register_setting( 'wp-font-awesome-settings', 'wp-font-awesome-settings' );
254
		}
255
256
		/**
257
		 * Add the WordPress settings menu item.
258
		 * @since 1.0.10 Calling function name direct will fail theme check so we don't.
259
		 */
260
		public function menu_item() {
261
			$menu_function = 'add' . '_' . 'options' . '_' . 'page'; // won't pass theme check if function name present in theme
262
			call_user_func( $menu_function, $this->name, $this->name, 'manage_options', 'wp-font-awesome-settings', array(
263
				$this,
264
				'settings_page'
265
			) );
266
		}
267
268
		/**
269
		 * Get the current Font Awesome output settings.
270
		 *
271
		 * @return array The array of settings.
272
		 */
273
		public function get_settings() {
274
275
			$db_settings = get_option( 'wp-font-awesome-settings' );
276
277
			$defaults = array(
278
				'type'      => 'CSS', // type to use, CSS or JS or KIT
279
				'version'   => '', // latest
280
				'enqueue'   => '', // front and backend
281
				'shims'     => '1', // default on for now, @todo maybe change to off in 2020
282
				'js-pseudo' => '0', // if the pseudo elements flag should be set (CPU intensive)
283
				'dequeue'   => '0', // if we should try to remove other versions added by other plugins/themes
284
				'pro'       => '0', // if pro CDN url should be used
285
				'kit-url'   => '', // the kit url
286
			);
287
288
			$settings = wp_parse_args( $db_settings, $defaults );
289
290
			/**
291
			 * Filter the Font Awesome settings.
292
			 *
293
			 * @todo if we add this filer people might use it and then it defeates the purpose of this class :/
294
			 */
295
			return $this->settings = apply_filters( 'wp-font-awesome-settings', $settings, $db_settings, $defaults );
296
		}
297
298
299
		/**
300
		 * The settings page html output.
301
		 */
302
		public function settings_page() {
303
			if ( ! current_user_can( 'manage_options' ) ) {
304
				wp_die( __( 'You do not have sufficient permissions to access this page.', 'font-awesome-settings' ) );
305
			}
306
307
			// a hidden way to force the update of the verison number vai api instead of waiting the 48 hours
308
			if ( isset( $_REQUEST['force-version-check'] ) ) {
309
				$this->get_latest_version( $force_api = true );
310
			}
311
			?>
312
			<style>
313
				.wpfas-kit-show {
314
					display: none;
315
				}
316
317
				.wpfas-kit-set .wpfas-kit-hide {
318
					display: none;
319
				}
320
321
				.wpfas-kit-set .wpfas-kit-show {
322
					display: table-row;
323
				}
324
			</style>
325
			<div class="wrap">
326
				<h1><?php echo $this->name; ?></h1>
327
				<form method="post" action="options.php">
328
					<?php
329
					settings_fields( 'wp-font-awesome-settings' );
330
					do_settings_sections( 'wp-font-awesome-settings' );
331
					$kit_set = $this->settings['type'] == 'KIT' ? 'wpfas-kit-set' : '';
332
					?>
333
					<table class="form-table wpfas-table-settings <?php echo esc_attr( $kit_set ); ?>">
334
						<tr valign="top">
335
							<th scope="row"><label
336
									for="wpfas-type"><?php _e( 'Type', 'font-awesome-settings' ); ?></label></th>
337
							<td>
338
								<select name="wp-font-awesome-settings[type]" id="wpfas-type"
339
								        onchange="if(this.value=='KIT'){jQuery('.wpfas-table-settings').addClass('wpfas-kit-set');}else{jQuery('.wpfas-table-settings').removeClass('wpfas-kit-set');}">
340
									<option
341
										value="CSS" <?php selected( $this->settings['type'], 'CSS' ); ?>><?php _e( 'CSS (default)', 'font-awesome-settings' ); ?></option>
342
									<option value="JS" <?php selected( $this->settings['type'], 'JS' ); ?>>JS</option>
343
									<option
344
										value="KIT" <?php selected( $this->settings['type'], 'KIT' ); ?>><?php _e( 'Kits (settings managed on fontawesome.com)', 'font-awesome-settings' ); ?></option>
345
								</select>
346
							</td>
347
						</tr>
348
349
						<tr valign="top" class="wpfas-kit-show">
350
							<th scope="row"><label
351
									for="wpfas-kit-url"><?php _e( 'Kit URL', 'font-awesome-settings' ); ?></label></th>
352
							<td>
353
								<input class="regular-text" id="wpfas-kit-url" type="url"
354
								       name="wp-font-awesome-settings[kit-url]"
355
								       value="<?php echo esc_attr( $this->settings['kit-url'] ); ?>"
356
								       placeholder="https://kit.fontawesome.com/123abc.js"/>
357
								<span><?php
358
									echo sprintf(
359
										__( 'Requires a free account with Font Awesome. %sGet kit url%s', 'font-awesome-settings' ),
360
										'<a rel="noopener noreferrer" target="_blank" href="https://fontawesome.com/kits"><i class="fas fa-external-link-alt"></i>',
361
										'</a>'
362
									);
363
									?></span>
364
							</td>
365
						</tr>
366
367
						<tr valign="top" class="wpfas-kit-hide">
368
							<th scope="row"><label
369
									for="wpfas-version"><?php _e( 'Version', 'font-awesome-settings' ); ?></label></th>
370
							<td>
371
								<select name="wp-font-awesome-settings[version]" id="wpfas-version">
372
									<option
373
										value="" <?php selected( $this->settings['version'], '' ); ?>><?php echo sprintf( __( 'Latest - %s (default)', 'font-awesome-settings' ), $this->get_latest_version() ); ?>
374
									</option>
375
									<option value="5.6.0" <?php selected( $this->settings['version'], '5.6.0' ); ?>>
376
										5.6.0
377
									</option>
378
									<option value="5.5.0" <?php selected( $this->settings['version'], '5.5.0' ); ?>>
379
										5.5.0
380
									</option>
381
									<option value="5.4.0" <?php selected( $this->settings['version'], '5.4.0' ); ?>>
382
										5.4.0
383
									</option>
384
									<option value="5.3.0" <?php selected( $this->settings['version'], '5.3.0' ); ?>>
385
										5.3.0
386
									</option>
387
									<option value="5.2.0" <?php selected( $this->settings['version'], '5.2.0' ); ?>>
388
										5.2.0
389
									</option>
390
									<option value="5.1.0" <?php selected( $this->settings['version'], '5.1.0' ); ?>>
391
										5.1.0
392
									</option>
393
									<option value="4.7.0" <?php selected( $this->settings['version'], '4.7.0' ); ?>>
394
										4.7.1 (CSS only)
395
									</option>
396
								</select>
397
							</td>
398
						</tr>
399
400
						<tr valign="top">
401
							<th scope="row"><label
402
									for="wpfas-enqueue"><?php _e( 'Enqueue', 'font-awesome-settings' ); ?></label></th>
403
							<td>
404
								<select name="wp-font-awesome-settings[enqueue]" id="wpfas-enqueue">
405
									<option
406
										value="" <?php selected( $this->settings['enqueue'], '' ); ?>><?php _e( 'Frontend + Backend (default)', 'font-awesome-settings' ); ?></option>
407
									<option
408
										value="frontend" <?php selected( $this->settings['enqueue'], 'frontend' ); ?>><?php _e( 'Frontend', 'font-awesome-settings' ); ?></option>
409
									<option
410
										value="backend" <?php selected( $this->settings['enqueue'], 'backend' ); ?>><?php _e( 'Backend', 'font-awesome-settings' ); ?></option>
411
								</select>
412
							</td>
413
						</tr>
414
415
						<tr valign="top" class="wpfas-kit-hide">
416
							<th scope="row"><label
417
									for="wpfas-pro"><?php _e( 'Enable pro', 'font-awesome-settings' ); ?></label></th>
418
							<td>
419
								<input type="hidden" name="wp-font-awesome-settings[pro]" value="0"/>
420
								<input type="checkbox" name="wp-font-awesome-settings[pro]"
421
								       value="1" <?php checked( $this->settings['pro'], '1' ); ?> id="wpfas-pro"/>
422
								<span><?php
423
									echo sprintf(
424
										__( 'Requires a subscription. %sLearn more%s %sManage my allowed domains%s', 'font-awesome-settings' ),
425
										'<a rel="noopener noreferrer" target="_blank" href="https://fontawesome.com/pro"><i class="fas fa-external-link-alt"></i>',
426
										'</a>',
427
										'<a rel="noopener noreferrer" target="_blank" href="https://fontawesome.com/account/cdn"><i class="fas fa-external-link-alt"></i>',
428
										'</a>'
429
									);
430
									?></span>
431
							</td>
432
						</tr>
433
434
						<tr valign="top" class="wpfas-kit-hide">
435
							<th scope="row"><label
436
									for="wpfas-shims"><?php _e( 'Enable v4 shims compatibility', 'font-awesome-settings' ); ?></label>
437
							</th>
438
							<td>
439
								<input type="hidden" name="wp-font-awesome-settings[shims]" value="0"/>
440
								<input type="checkbox" name="wp-font-awesome-settings[shims]"
441
								       value="1" <?php checked( $this->settings['shims'], '1' ); ?> id="wpfas-shims"/>
442
								<span><?php _e( 'This enables v4 classes to work with v5, sort of like a band-aid until everyone has updated everything to v5.', 'font-awesome-settings' ); ?></span>
443
							</td>
444
						</tr>
445
446
						<tr valign="top" class="wpfas-kit-hide">
447
							<th scope="row"><label
448
									for="wpfas-js-pseudo"><?php _e( 'Enable JS pseudo elements (not recommended)', 'font-awesome-settings' ); ?></label>
449
							</th>
450
							<td>
451
								<input type="hidden" name="wp-font-awesome-settings[js-pseudo]" value="0"/>
452
								<input type="checkbox" name="wp-font-awesome-settings[js-pseudo]"
453
								       value="1" <?php checked( $this->settings['js-pseudo'], '1' ); ?>
454
								       id="wpfas-js-pseudo"/>
455
								<span><?php _e( 'Used only with the JS version, this will make pseudo-elements work but can be CPU intensive on some sites.', 'font-awesome-settings' ); ?></span>
456
							</td>
457
						</tr>
458
459
						<tr valign="top">
460
							<th scope="row"><label
461
									for="wpfas-dequeue"><?php _e( 'Dequeue', 'font-awesome-settings' ); ?></label></th>
462
							<td>
463
								<input type="hidden" name="wp-font-awesome-settings[dequeue]" value="0"/>
464
								<input type="checkbox" name="wp-font-awesome-settings[dequeue]"
465
								       value="1" <?php checked( $this->settings['dequeue'], '1' ); ?>
466
								       id="wpfas-dequeue"/>
467
								<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.', 'font-awesome-settings' ); ?></span>
468
							</td>
469
						</tr>
470
471
					</table>
472
					<?php
473
					submit_button();
474
					?>
475
				</form>
476
477
				<div id="wpfas-version"><?php echo $this->version; ?></div>
478
			</div>
479
480
			<?php
481
		}
482
483
		/**
484
		 * Check a version number is valid and if so return it or else return an empty string.
485
		 *
486
		 * @param $version string The version number to check.
487
		 *
488
		 * @since 1.0.6
489
		 *
490
		 * @return string Either a valid version number or an empty string.
491
		 */
492
		public function validate_version_number( $version ) {
493
494
			if ( version_compare( $version, '0.0.1', '>=' ) >= 0 ) {
495
				// valid
496
			} else {
497
				$version = '';// not validated
498
			}
499
500
			return $version;
501
		}
502
503
504
		/**
505
		 * Get the latest version of Font Awesome.
506
		 *
507
		 * 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.
508
		 *
509
		 * @since 1.0.7
510
		 * @return mixed|string The latest version number found.
511
		 */
512
		public function get_latest_version( $force_api = false ) {
513
			$latest_version = $this->latest;
514
515
			$cache = get_transient( 'wp-font-awesome-settings-version' );
516
517
			if ( $cache === false || $force_api ) { // its not set
518
				$api_ver = $this->get_latest_version_from_api();
519
				if ( version_compare( $api_ver, $this->latest, '>=' ) >= 0 ) {
520
					$latest_version = $api_ver;
521
					set_transient( 'wp-font-awesome-settings-version', $api_ver, 48 * HOUR_IN_SECONDS );
522
				}
523
			} elseif ( $this->validate_version_number( $cache ) ) {
524
				if ( version_compare( $cache, $this->latest, '>=' ) >= 0 ) {
525
					$latest_version = $cache;
526
				}
527
			}
528
529
			return $latest_version;
530
		}
531
532
		/**
533
		 * Get the latest Font Awesome version from the github API.
534
		 *
535
		 * @since 1.0.7
536
		 * @return string The latest version number or `0` on API fail.
537
		 */
538
		public function get_latest_version_from_api() {
539
			$version  = "0";
540
			$response = wp_remote_get( "https://api.github.com/repos/FortAwesome/Font-Awesome/releases/latest" );
541
			if ( ! is_wp_error( $response ) && is_array( $response ) ) {
542
				$api_response = json_decode( wp_remote_retrieve_body( $response ), true );
543
				if ( isset( $api_response['tag_name'] ) && version_compare( $api_response['tag_name'], $this->latest, '>=' ) >= 0 && empty( $api_response['prerelease'] ) ) {
544
					$version = $api_response['tag_name'];
545
				}
546
			}
547
548
			return $version;
549
		}
550
551
	}
552
553
	/**
554
	 * Run the class if found.
555
	 */
556
	WP_Font_Awesome_Settings::instance();
557
}