Completed
Push — develop ( faed85...5d0bd3 )
by Zack
04:39
created

GravityView_Compatibility::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 0
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
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 416.

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
	 *
88
	 * @deprecated
89
	 * @see \GV\Plugin::is_compatible() accessible via gravityview()->plugin->is_compatible()
90
	 *
91
	 * @return bool
92
	 */
93
	public static function is_valid() {
94
		if ( function_exists( 'gravityview' ) ) {
95
			return gravityview()->plugin->is_compatible();
96
		}
97
98
		return ( self::is_valid_gravity_forms() && self::is_valid_wordpress() && self::is_valid_php() );
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_Compatibilit...s_valid_gravity_forms() has been deprecated.

This method has been deprecated.

Loading history...
Deprecated Code introduced by
The method GravityView_Compatibility::is_valid_wordpress() has been deprecated.

This method has been deprecated.

Loading history...
Deprecated Code introduced by
The method GravityView_Compatibility::is_valid_php() has been deprecated.

This method has been deprecated.

Loading history...
99
	}
100
101
	/**
102
	 * Is the version of WordPress compatible?
103
	 * @since 1.12
104
	 *
105
	 * @deprecated
106
	 * @see \GV\Plugin::is_compatible_wordpress() accessible via gravityview()->plugin->is_compatible_wordpress()
107
	 */
108
	private static function is_valid_wordpress() {
109
		if ( function_exists( 'gravityview' ) ) {
110
			return gravityview()->plugin->is_compatible_wordpress();
111
		}
112
113
		return self::$valid_wordpress;
114
	}
115
116
	/**
117
	 * @since 1.12
118
	 *
119
	 * @deprecated
120
	 * @see \GV\Plugin::is_compatible_gravityforms() accessible via gravityview()->plugin->is_compatible_gravityforms()
121
	 *
122
	 * @return bool
123
	 */
124
	private static function is_valid_gravity_forms() {
125
		if ( function_exists( 'gravityview' ) ) {
126
			return gravityview()->plugin->is_compatible_gravityforms();
127
		}
128
129
		return self::$valid_gravity_forms;
130
	}
131
132
	/**
133
	 * @since 1.12
134
	 *
135
	 * @deprecated
136
	 * @see \GV\Plugin::is_compatible_php() accessible via gravityview()->plugin->is_compatible_php()
137
	 *
138
	 * @return bool
139
	 */
140
	private static function is_valid_php() {
141
		if ( function_exists( 'gravityview' ) ) {
142
			return gravityview()->plugin->is_compatible_php();
143
		}
144
145
		return self::$valid_php;
146
	}
147
148
	/**
149
	 * @since 1.12
150
	 * @return bool
151
	 */
152
	private function add_fallback_shortcode() {
153
154
		// If Gravity Forms doesn't exist or is outdated, load the admin view class to
155
		// show the notice, but not load any post types or process shortcodes.
156
		// Without Gravity Forms, there is no GravityView. Beautiful, really.
157
		if( ! self::is_valid() ) {
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_Compatibility::is_valid() has been deprecated.

This method has been deprecated.

Loading history...
158
159
			// If the plugin's not loaded, might as well hide the shortcode for people.
160
			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...
161
162
		}
163
	}
164
165
	/**
166
	 * Get admin notices
167
	 * @since 1.12
168
	 * @return array
169
	 */
170
	public static function get_notices() {
171
		return self::$notices;
172
	}
173
174
	/**
175
	 * @since 1.9.2 in gravityview.php
176
	 * @since 1.12
177
	 *
178
	 * @param array $atts
179
	 * @param null $content
180
	 * @param string $shortcode
181
	 *
182
	 * @return null|string NULL returned if user can't activate plugins. Notice shown with a warning that GF isn't supported.
183
	 */
184
	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...
185
186
		if( ! GVCommon::has_cap( 'activate_plugins' ) ) {
187
			return null;
188
		}
189
190
		$notices = self::get_notices();
191
192
		$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...
193
		foreach( (array)$notices as $notice ) {
0 ignored issues
show
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
194
			$message .= wpautop( $notice['message'] );
195
		}
196
		$message .= '</div>';
197
198
		return $message;
199
200
	}
201
202
	/**
203
	 * Is the version of PHP compatible?
204
	 *
205
	 * @since 1.12
206
	 * @since 1.19.2 Shows a notice if it's compatible with future PHP version requirements
207
	 *
208
	 * @return boolean
209
	 */
210
	public static function check_php() {
211
212
		if (
213
			( function_exists( 'gravityview' ) && ! gravityview()->plugin->is_compatible_php() )
214
			|| ( false === version_compare( phpversion(), GV_MIN_PHP_VERSION , '>=' ) )
215
		) {
216
217
			self::$notices['php_version'] = array(
218
				'class' => 'error',
219
				'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...
220
				'cap' => 'manage_options',
221
				'dismiss' => 'php_version',
222
			);
223
224
			return false;
225
		}
226
227
		if( false === version_compare( phpversion(), GV_FUTURE_MIN_PHP_VERSION , '>=' ) ) {
228
229
			// Show the notice on every update. Yes, annoying, but not as annoying as a plugin breaking.
230
			$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...
231
232
			self::$notices[ $key ] = array(
233
				'class' => 'error',
234
				'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...
235
				'cap' => 'manage_options',
236
				'dismiss' => $key,
237
			);
238
239
		}
240
241
		return true;
242
	}
243
244
	/**
245
	 * Is WordPress compatible?
246
	 *
247
	 * @since 1.12
248
	 * @return boolean
249
	 */
250
	public static function check_wordpress() {
251
		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...
252
253
		if (
254
			( function_exists( 'gravityview' ) && ! gravityview()->plugin->is_compatible_wordpress() )
255
			|| ( version_compare( $wp_version, GV_MIN_WP_VERSION ) <= 0 )
256
		) {
257
258
			self::$notices['wp_version'] = array(
259
				'class' => 'error',
260
				'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...
261
			    'cap' => 'update_core',
262
				'dismiss' => 'wp_version',
263
			);
264
265
			return false;
266
		}
267
268
		return true;
269
	}
270
271
272
	/**
273
	 * Check if Gravity Forms plugin is active and show notice if not.
274
	 *
275
	 * @since 1.12
276
	 *
277
	 * @access public
278
	 * @return boolean True: checks have been passed; GV is fine to run; False: checks have failed, don't continue loading
279
	 */
280
	public static function check_gravityforms() {
281
282
		// Bypass other checks: if the class exists
283
		if( class_exists( 'GFCommon' ) ) {
284
285
			// Does the version meet future requirements?
286
			if( true === version_compare( GFCommon::$version, GV_FUTURE_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...
287
				return true;
288
			}
289
290
			// Does it meet minimum requirements?
291
			if ( function_exists( 'gravityview' ) ) {
292
				$meets_minimum = gravityview()->plugin->is_compatible_gravityforms();
293
			} else {
294
				$meets_minimum = ( 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...
295
			}
296
297
			$class = $meets_minimum ? 'notice-warning' : 'error';
298
299
			// Show the notice even if the future version requirements aren't met
300
			self::$notices['gf_version'] = array(
301
				'class' => $class,
302
				'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_FUTURE_MIN_GF_VERSION, "</h3>\n\n", '<span style="font-family: Consolas, Courier, monospace;">'.GFCommon::$version.'</span>', "\n\n".'<a href="https://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...
303
				'cap' => 'update_plugins',
304
				'dismiss' => 'gf_version_' . GV_FUTURE_MIN_GF_VERSION,
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'GV_FUTURE_MIN_GF_VERSION'
Loading history...
305
			);
306
307
			// Return false if the plugin is not compatible, true if meets minimum
308
			return $meets_minimum;
309
		}
310
311
		$gf_status = self::get_plugin_status( 'gravityforms/gravityforms.php' );
312
313
		/**
314
		 * The plugin is activated and yet somehow GFCommon didn't get picked up...
315
		 * OR
316
		 * It's the Network Admin and we just don't know whether the sites have GF activated themselves.
317
		 */
318
		if( true === $gf_status || is_network_admin() ) {
319
			return true;
320
		}
321
322
		// If GFCommon doesn't exist, assume GF not active
323
		$return = false;
324
325
		switch( $gf_status ) {
326
			case 'inactive':
327
328
				// Required for multisite
329
				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...
330
					require_once ABSPATH . WPINC . '/pluggable.php';
331
				}
332
333
				// Otherwise, throws an error on activation & deactivation "Use of undefined constant LOGGED_IN_COOKIE"
334
				if( is_multisite() ) {
335
					wp_cookie_constants();
336
				}
337
338
				$return = false;
339
340
				$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...
341
342
				self::$notices['gf_inactive'] = array(
343
					'class' => 'error',
344
					'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...
345
					'cap' => 'activate_plugins',
346
					'dismiss' => 'gf_inactive',
347
				);
348
349
				break;
350
			default:
351
				self::$notices['gf_installed'] = array(
352
					'class' => 'error',
353
					'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...
354
					'cap' => 'install_plugins',
355
					'dismiss' => 'gf_installed',
356
				);
357
				break;
358
		}
359
360
		return $return;
361
	}
362
363
	/**
364
	 * Check for potential conflicts and let users know about common issues.
365
	 *
366
	 * @return void
367
	 */
368
	private static function check_gf_directory() {
369
370
		if( class_exists( 'GFDirectory' ) ) {
371
			self::$notices['gf_directory'] = array(
372
				'class' => 'error is-dismissible',
373
				'title' => __('Potential Conflict', 'gravityview' ),
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
374
				'message' => __( 'GravityView and Gravity Forms Directory are both active. This may cause problems. If you experience issues, disable the Gravity Forms Directory plugin.', 'gravityview' ),
375
				'dismiss' => 'gf_directory',
376
				'cap' => 'activate_plugins',
377
			);
378
		}
379
380
	}
381
382
	/**
383
	 * Check if specified plugin is active, inactive or not installed
384
	 *
385
	 * @access public
386
	 * @static
387
	 * @param string $location (default: '')
388
	 * @return boolean|string True: plugin is active; False: plugin file doesn't exist at path; 'inactive' it's inactive
389
	 */
390
	public static function get_plugin_status( $location = '' ) {
391
392
		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...
393
			include_once( ABSPATH . '/wp-admin/includes/plugin.php' );
394
		}
395
396
		if( is_network_admin() && is_plugin_active_for_network( $location ) ) {
397
			return true;
398
		}
399
400
		if( !is_network_admin() && is_plugin_active( $location ) ) {
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
401
			return true;
402
		}
403
404
		if(
405
			!file_exists( trailingslashit( WP_PLUGIN_DIR ) . $location ) &&
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
406
			!file_exists( trailingslashit( WPMU_PLUGIN_DIR ) . $location )
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
407
		) {
408
			return false;
409
		}
410
411
		return 'inactive';
412
	}
413
414
}
415
416
GravityView_Compatibility::getInstance();
417