Completed
Push — master ( 6337a4...1e5684 )
by Zack
11s
created

GravityView_Compatibility   B

Complexity

Total Complexity 42

Size/Duplication

Total Lines 350
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 350
rs 8.295
c 0
b 0
f 0
wmc 42
lcom 3
cbo 1

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 1
A add_hooks() 0 6 1
A insert_admin_notices() 0 3 1
A getInstance() 0 6 2
A is_valid() 0 3 3
A is_valid_wordpress() 0 3 1
A is_valid_gravity_forms() 0 3 1
A is_valid_php() 0 3 1
A add_fallback_shortcode() 0 12 2
A get_notices() 0 3 1
A _shortcode_gf_notice() 0 17 3
B check_php() 0 30 3
A check_wordpress() 0 17 2
C check_gravityforms() 0 72 10
A check_gf_directory() 0 13 2
C get_plugin_status() 0 23 8

How to fix   Complexity   

Complex Class

Complex classes like GravityView_Compatibility 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 GravityView_Compatibility, and based on these observations, apply Extract Interface, too.

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 18 and the first side effect is on line 369.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Handle issues with plugin and version compatibility
4
 *
5
 * @package   GravityView
6
 * @license   GPL2+
7
 * @author    Katz Web Services, Inc.
8
 * @link      http://gravityview.co
9
 * @copyright Copyright 2015, Katz Web Services, Inc.
10
 *
11
 * @since 1.12
12
 */
13
14
/**
15
 * Handle GravityView compatibility notices and fallback shortcodes
16
 * @since 1.12
17
 */
18
class GravityView_Compatibility {
19
20
	/**
21
	 * @var GravityView_Compatibility
22
	 */
23
	static public $instance = null;
24
25
	/**
26
	 * @var bool Is Gravity Forms version valid and is Gravity Forms loaded?
27
	 */
28
	static public $valid_gravity_forms = false;
29
30
	/**
31
	 * @var bool Is the WordPress installation compatible?
32
	 */
33
	static public $valid_wordpress = false;
34
35
	/**
36
	 * @var bool Is the server's PHP version compatible?
37
	 */
38
	static public $valid_php = false;
39
40
	/**
41
	 * @var array Holder for notices to be displayed in frontend shortcodes if not valid GF
42
	 */
43
	static private $notices = array();
44
45
	function __construct() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
46
47
		self::$valid_gravity_forms = self::check_gravityforms();
48
49
		self::$valid_wordpress = self::check_wordpress();
50
51
		self::$valid_php = self::check_php();
52
53
		self::check_gf_directory();
54
55
		$this->add_hooks();
56
	}
57
58
	function add_hooks() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
59
60
		add_filter( 'gravityview/admin/notices', array( $this, 'insert_admin_notices' ) );
61
62
		$this->add_fallback_shortcode();
63
	}
64
65
	/**
66
	 * Add the compatibility notices to the other admin notices
67
	 * @param array $notices
68
	 *
69
	 * @return array
70
	 */
71
	function insert_admin_notices( $notices = array() ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
72
		return array_merge( $notices, self::$notices );
73
	}
74
75
	/**
76
	 * @return GravityView_Compatibility
77
	 */
78
	public static function getInstance() {
0 ignored issues
show
Coding Style introduced by
The function name getInstance is in camel caps, but expected get_instance instead as per the coding standard.
Loading history...
79
		if( self::$instance ) {
80
			return self::$instance;
81
		}
82
		return new self;
83
	}
84
85
	/**
86
	 * Is everything compatible with this version of GravityView?
87
	 * @return bool
88
	 */
89
	public static function is_valid() {
90
		return ( self::is_valid_gravity_forms() && self::is_valid_wordpress() && self::is_valid_php() );
91
	}
92
93
	/**
94
	 * Is the version of WordPress compatible?
95
	 * @since 1.12
96
	 */
97
	private static function is_valid_wordpress() {
98
		return self::$valid_wordpress;
99
	}
100
101
	/**
102
	 * @since 1.12
103
	 * @return bool
104
	 */
105
	private static function is_valid_gravity_forms() {
106
		return self::$valid_gravity_forms;
107
	}
108
109
	/**
110
	 * @since 1.12
111
	 * @return bool
112
	 */
113
	private static function is_valid_php() {
114
		return self::$valid_php;
115
	}
116
117
	/**
118
	 * @since 1.12
119
	 * @return bool
120
	 */
121
	private function add_fallback_shortcode() {
122
123
		// If Gravity Forms doesn't exist or is outdated, load the admin view class to
124
		// show the notice, but not load any post types or process shortcodes.
125
		// Without Gravity Forms, there is no GravityView. Beautiful, really.
126
		if( ! self::is_valid() ) {
127
128
			// If the plugin's not loaded, might as well hide the shortcode for people.
129
			add_shortcode( 'gravityview', array( $this, '_shortcode_gf_notice') );
0 ignored issues
show
introduced by
No space before closing parenthesis of array is bad style
Loading history...
130
131
		}
132
	}
133
134
	/**
135
	 * Get admin notices
136
	 * @since 1.12
137
	 * @return array
138
	 */
139
	public static function get_notices() {
140
		return self::$notices;
141
	}
142
143
	/**
144
	 * @since 1.9.2 in gravityview.php
145
	 * @since 1.12
146
	 *
147
	 * @param array $atts
148
	 * @param null $content
149
	 * @param string $shortcode
150
	 *
151
	 * @return null|string NULL returned if user can't activate plugins. Notice shown with a warning that GF isn't supported.
152
	 */
153
	public function _shortcode_gf_notice( $atts = array(), $content = null, $shortcode = 'gravityview' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $atts is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $content is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $shortcode is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
154
155
		if( ! GVCommon::has_cap( 'activate_plugins' ) ) {
156
			return null;
157
		}
158
159
		$notices = self::get_notices();
160
161
		$message = '<div style="border:1px solid red; padding: 15px;"><p style="text-align:center;"><em>' . esc_html__( 'You are seeing this notice because you are an administrator. Other users of the site will see nothing.', 'gravityview') . '</em></p>';
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
162
		foreach( (array)$notices as $notice ) {
0 ignored issues
show
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
163
			$message .= wpautop( $notice['message'] );
164
		}
165
		$message .= '</div>';
166
167
		return $message;
168
169
	}
170
171
	/**
172
	 * Is the version of PHP compatible?
173
	 *
174
	 * @since 1.12
175
	 * @since 1.19.2 Shows a notice if it's compatible with future PHP version requirements
176
	 *
177
	 * @return boolean
178
	 */
179
	public static function check_php() {
180
181
		if( false === version_compare( phpversion(), GV_MIN_PHP_VERSION , '>=' ) ) {
182
183
			self::$notices['php_version'] = array(
184
				'class' => 'error',
185
				'message' => sprintf( __( "%sGravityView requires PHP Version %s or newer.%s \n\nYou're using Version %s. Please ask your host to upgrade your server's PHP.", 'gravityview' ), '<h3>', GV_MIN_PHP_VERSION, "</h3>\n\n", '<span style="font-family: Consolas, Courier, monospace;">'.phpversion().'</span>' ),
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'phpversion'
Loading history...
186
				'cap' => 'manage_options',
187
				'dismiss' => 'php_version',
188
			);
189
190
			return false;
191
		}
192
193
		if( false === version_compare( phpversion(), GV_FUTURE_MIN_PHP_VERSION , '>=' ) ) {
194
195
			// Show the notice on every update. Yes, annoying, but not as annoying as a plugin breaking.
196
			$key = sprintf('php_%s_%s', GV_FUTURE_MIN_PHP_VERSION, GravityView_Plugin::version );
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
197
198
			self::$notices[ $key ] = array(
199
				'class' => 'error',
200
				'message' => sprintf( __( "%sGravityView will soon require PHP Version %s.%s \n\nYou're using Version %s. Please ask your host to upgrade your server's PHP.", 'gravityview' ), '<h3>', GV_FUTURE_MIN_PHP_VERSION, "</h3>\n\n", '<span style="font-family: Consolas, Courier, monospace;">'.phpversion().'</span>' ),
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'phpversion'
Loading history...
201
				'cap' => 'manage_options',
202
				'dismiss' => $key,
203
			);
204
205
		}
206
207
		return true;
208
	}
209
210
	/**
211
	 * Is WordPress compatible?
212
	 *
213
	 * @since 1.12
214
	 * @return boolean
215
	 */
216
	public static function check_wordpress() {
217
		global $wp_version;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
218
219
		if( version_compare( $wp_version, GV_MIN_WP_VERSION ) <= 0 ) {
220
221
			self::$notices['wp_version'] = array(
222
				'class' => 'error',
223
				'message' => sprintf( __( "%sGravityView requires WordPress %s or newer.%s \n\nYou're using Version %s. Please upgrade your WordPress installation.", 'gravityview' ), '<h3>', GV_MIN_WP_VERSION, "</h3>\n\n", '<span style="font-family: Consolas, Courier, monospace;">'.$wp_version.'</span>' ),
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$wp_version'
Loading history...
224
			    'cap' => 'update_core',
225
				'dismiss' => 'wp_version',
226
			);
227
228
			return false;
229
		}
230
231
		return true;
232
	}
233
234
235
	/**
236
	 * Check if Gravity Forms plugin is active and show notice if not.
237
	 *
238
	 * @since 1.12
239
	 *
240
	 * @access public
241
	 * @return boolean True: checks have been passed; GV is fine to run; False: checks have failed, don't continue loading
242
	 */
243
	public static function check_gravityforms() {
244
245
		// Bypass other checks: if the class exists
246
		if( class_exists( 'GFCommon' ) ) {
247
248
			// and the version's right, we're good.
249
			if( true === version_compare( GFCommon::$version, GV_MIN_GF_VERSION, ">=" ) ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal >= does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
250
				return true;
251
			}
252
253
			// Or the version's wrong
254
			self::$notices['gf_version'] = array(
255
				'class' => 'error',
256
				'message' => sprintf( __( "%sGravityView requires Gravity Forms Version %s or newer.%s \n\nYou're using Version %s. Please update your Gravity Forms or purchase a license. %sGet Gravity Forms%s - starting at $39%s%s", 'gravityview' ), '<h3>', GV_MIN_GF_VERSION, "</h3>\n\n", '<span style="font-family: Consolas, Courier, monospace;">'.GFCommon::$version.'</span>', "\n\n".'<a href="http://katz.si/gravityforms" class="button button-secondary button-large button-hero">' , '<em>', '</em>', '</a>'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'GFCommon'
Loading history...
257
				'cap' => 'update_plugins',
258
				'dismiss' => 'gf_version',
259
			);
260
261
			return false;
262
		}
263
264
		$gf_status = self::get_plugin_status( 'gravityforms/gravityforms.php' );
265
266
		/**
267
		 * The plugin is activated and yet somehow GFCommon didn't get picked up...
268
		 * OR
269
		 * It's the Network Admin and we just don't know whether the sites have GF activated themselves.
270
		 */
271
		if( true === $gf_status || is_network_admin() ) {
272
			return true;
273
		}
274
275
		// If GFCommon doesn't exist, assume GF not active
276
		$return = false;
277
278
		switch( $gf_status ) {
279
			case 'inactive':
280
281
				// Required for multisite
282
				if( ! function_exists('wp_create_nonce') ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
283
					require_once ABSPATH . WPINC . '/pluggable.php';
284
				}
285
286
				// Otherwise, throws an error on activation & deactivation "Use of undefined constant LOGGED_IN_COOKIE"
287
				if( is_multisite() ) {
288
					wp_cookie_constants();
289
				}
290
291
				$return = false;
292
293
				$button = function_exists('is_network_admin') && is_network_admin() ? '<strong><a href="#gravity-forms">' : '<strong><a href="'. wp_nonce_url( admin_url( 'plugins.php?action=activate&plugin=gravityforms/gravityforms.php' ), 'activate-plugin_gravityforms/gravityforms.php') . '" class="button button-large">';
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
294
295
				self::$notices['gf_inactive'] = array(
296
					'class' => 'error',
297
					'message' => sprintf( __( '%sGravityView requires Gravity Forms to be active. %sActivate Gravity Forms%s to use the GravityView plugin.', 'gravityview' ), '<h3>', "</h3>\n\n". $button, '</a></strong>' ),
0 ignored issues
show
introduced by
Expected next thing to be a escaping function, not '$button'
Loading history...
298
					'cap' => 'activate_plugins',
299
					'dismiss' => 'gf_inactive',
300
				);
301
302
				break;
303
			default:
304
				self::$notices['gf_installed'] = array(
305
					'class' => 'error',
306
					'message' => sprintf( __( '%sGravityView requires Gravity Forms to be installed in order to run properly. %sGet Gravity Forms%s - starting at $39%s%s', 'gravityview' ), '<h3>', "</h3>\n\n".'<a href="http://katz.si/gravityforms" class="button button-secondary button-large button-hero">' , '<em>', '</em>', '</a>'),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
307
					'cap' => 'install_plugins',
308
					'dismiss' => 'gf_installed',
309
				);
310
				break;
311
		}
312
313
		return $return;
314
	}
315
316
	/**
317
	 * Check for potential conflicts and let users know about common issues.
318
	 *
319
	 * @return void
320
	 */
321
	private static function check_gf_directory() {
322
323
		if( class_exists( 'GFDirectory' ) ) {
324
			self::$notices['gf_directory'] = array(
325
				'class' => 'error is-dismissible',
326
				'title' => __('Potential Conflict', 'gravityview' ),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
327
				'message' => __( 'GravityView and Gravity Forms Directory are both active. This may cause problems. If you experience issues, disable the Gravity Forms Directory plugin.', 'gravityview' ),
328
				'dismiss' => 'gf_directory',
329
				'cap' => 'activate_plugins',
330
			);
331
		}
332
333
	}
334
335
	/**
336
	 * Check if specified plugin is active, inactive or not installed
337
	 *
338
	 * @access public
339
	 * @static
340
	 * @param string $location (default: '')
341
	 * @return boolean|string True: plugin is active; False: plugin file doesn't exist at path; 'inactive' it's inactive
342
	 */
343
	public static function get_plugin_status( $location = '' ) {
344
345
		if( ! function_exists('is_plugin_active') ) {
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
346
			include_once( ABSPATH . '/wp-admin/includes/plugin.php' );
347
		}
348
349
		if( is_network_admin() && is_plugin_active_for_network( $location ) ) {
350
			return true;
351
		}
352
353
		if( !is_network_admin() && is_plugin_active( $location ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
354
			return true;
355
		}
356
357
		if(
358
			!file_exists( trailingslashit( WP_PLUGIN_DIR ) . $location ) &&
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
359
			!file_exists( trailingslashit( WPMU_PLUGIN_DIR ) . $location )
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
360
		) {
361
			return false;
362
		}
363
364
		return 'inactive';
365
	}
366
367
}
368
369
GravityView_Compatibility::getInstance();
370