Issues (362)

includes/compatibility-check.php (4 issues)

1
<?php
2
3
if ( ! class_exists( 'MonsterInsights_Compatibility_Check' ) ) {
4
	/**
5
	 * Check PHP and WP compatibility
6
	 *
7
	 * @since 8.0.0
8
	 */
9
	class MonsterInsights_Compatibility_Check {
10
		/**
11
		 * Holds singleton instance
12
		 *
13
		 * @since 8.0.0
14
		 * @var MonsterInsights_Compatibility_Check
15
		 */
16
		private static $instance;
17
18
		/**
19
		 * Return Singleton instance
20
		 *
21
		 * @return MonsterInsights_Compatibility_Check
22
		 * @since 8.0.0
23
		 */
24
		public static function get_instance() {
25
			if ( empty( self::$instance ) ) {
26
				self::$instance = new self();
27
			}
28
29
			return self::$instance;
30
		}
31
32
		/**
33
		 * @since 8.0.0
34
		 * @var array {
35
		 *     PHP Version requirement and recommendation
36
		 *
37
		 * @type string $required Halt and deactivate plugin if PHP is under this version
38
		 * @type string $warning Display undismissable warning if PHP is under this version
39
		 * @type string $recommended Display undismissable warning if PHP is under this version
40
		 * }
41
		 */
42
		private $compatible_php_version = array(
43
			'required'    => '7.2',
44
			'warning'     => '7.0',
45
			'recommended' => false,
46
		);
47
48
		/**
49
		 * @since 8.0.0
50
		 * @var array {
51
		 *     WP Version requirement and recommendation
52
		 *
53
		 * @type string $required Halt and deactivate plugin if WP is under this version
54
		 * @type string $warning Display undismissable warning if WP is under this version
55
		 * @type string $recommended Display undismissable warning if WP is under this version
56
		 * }
57
		 */
58
		private $compatible_wp_version = array(
59
			'required'    => '5.6',
60
			'warning'     => '6.0',
61
			'recommended' => false,
62
		);
63
64
		/**
65
		 * Private constructor
66
		 *
67
		 * @since 8.0.0
68
		 */
69
		private function __construct() {
70
			add_filter( 'monsterinsights_compatible_php_version', array(
71
				$this,
72
				'filter_compatible_php_version'
73
			), 10, 1 );
74
			add_filter( 'monsterinsights_compatible_wp_version', array(
75
				$this,
76
				'filter_compatible_wp_version'
77
			), 10, 1 );
78
		}
79
80
		/**
81
		 * Return the strictest php compatibility versions
82
		 *
83
		 * @param array $version {
84
		 *     PHP Version requirement and recommendation
85
		 *
86
		 * @type string $required Halt and deactivate plugin if PHP is under this version
87
		 * @type string $warning Display undismissable warning if PHP is under this version
88
		 * @type string $recommended Display undismissable warning if PHP is under this version
89
		 * }
90
		 *
91
		 * @return array {
92
		 *     PHP Version requirement and recommendation
93
		 *
94
		 * @type string $required Halt and deactivate plugin if PHP is under this version
95
		 * @type string $warning Display undismissable warning if PHP is under this version
96
		 * @type string $recommended Display undismissable warning if PHP is under this version
97
		 * }
98
		 * @since 8.0.0
99
		 */
100
		public function filter_compatible_php_version( $version ) {
101
			if ( ! $version || version_compare( $version['required'], $this->compatible_php_version['required'], '<' ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $version of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
102
				return $this->compatible_php_version;
103
			}
104
105
			return $version;
106
		}
107
108
		/**
109
		 * Return the strictest WP compatibility versions
110
		 *
111
		 * @param array $version {
112
		 *     WP Version requirement and recommendation
113
		 *
114
		 * @type string $required Halt and deactivate plugin if WP is under this version
115
		 * @type string $warning Display undismissable warning if WP is under this version
116
		 * @type string $recommended Display undismissable warning if WP is under this version
117
		 * }
118
		 *
119
		 * @return array {
120
		 *     WP Version requirement and recommendation
121
		 *
122
		 * @type string $required Halt and deactivate plugin if WP is under this version
123
		 * @type string $warning Display undismissable warning if WP is under this version
124
		 * @type string $recommended Display undismissable warning if WP is under this version
125
		 * }
126
		 * @since 8.0.0
127
		 */
128
		public function filter_compatible_wp_version( $version ) {
129
			if ( ! $version || version_compare( $version['required'], $this->compatible_wp_version['required'], '<' ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $version of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
130
				return $this->compatible_wp_version;
131
			}
132
133
			return $version;
134
		}
135
136
		/**
137
		 * Return required, warning and recommended PHP versions
138
		 *
139
		 * @return array {
140
		 *     PHP Version requirement and recommendation
141
		 *
142
		 * @type string $required Halt and deactivate plugin if PHP is under this version
143
		 * @type string $warning Display undismissable warning if PHP is under this version
144
		 * @type string $recommended Display undismissable warning if PHP is under this version
145
		 * }
146
		 * @since 8.0.0
147
		 */
148
		public function get_compatible_php_version() {
149
			return apply_filters( 'monsterinsights_compatible_php_version', $this->compatible_php_version );
150
		}
151
152
		/**
153
		 * Check to see if PHP version meets the minimum required version
154
		 *
155
		 * @return bool
156
		 * @since 8.0.0
157
		 */
158
		public function is_php_compatible() {
159
			$compatible_php_version = $this->get_compatible_php_version();
160
161
			return empty( $compatible_php_version['required'] ) || version_compare( phpversion(), $compatible_php_version['required'], '>=' );
162
		}
163
164
		/**
165
		 * Return required, warning and recommended WP versions
166
		 *
167
		 * @return array {
168
		 *     WP Version requirement and recommendation
169
		 *
170
		 * @type string $required Halt and deactivate plugin if WP is under this version
171
		 * @type string $warning Display undismissable warning if WP is under this version
172
		 * @type string $recommended Display undismissable warning if WP is under this version
173
		 * }
174
		 * @since 8.0.0
175
		 */
176
		public function get_compatible_wp_version() {
177
			return apply_filters( 'monsterinsights_compatible_wp_version', $this->compatible_wp_version );
178
		}
179
180
		/**
181
		 * Check to see if WP version meets the minimum required version
182
		 *
183
		 * @return bool
184
		 * @since 8.0.0
185
		 */
186
		public function is_wp_compatible() {
187
			global $wp_version;
188
			$compatible_wp_version = $this->get_compatible_wp_version();
189
190
			return empty( $compatible_wp_version['required'] ) || version_compare( $wp_version, $compatible_wp_version['required'], '>=' );
191
		}
192
193
		/**
194
		 * Check to see if the main plugin or any other add-ons have displayed the required version notice
195
		 *
196
		 * @return bool
197
		 * @since 8.0.0
198
		 */
199
		private function is_notice_already_active() {
200
			return defined( 'MONSTERINSIGHTS_VERSION_NOTICE_ACTIVE' ) && MONSTERINSIGHTS_VERSION_NOTICE_ACTIVE;
201
		}
202
203
		/**
204
		 * Set global constant so that main plugin or other add-ons are aware that the version notice
205
		 * has been set for display already
206
		 *
207
		 * @return void
208
		 * @since 8.0.0
209
		 */
210
		private function set_notice_active() {
211
			if ( ! defined( 'MONSTERINSIGHTS_VERSION_NOTICE_ACTIVE' ) ) {
212
				define( 'MONSTERINSIGHTS_VERSION_NOTICE_ACTIVE', true );
213
			}
214
		}
215
216
		/**
217
		 * Display version notice in admin area if:
218
		 * 1. Minimum PHP and WP versions are not met
219
		 * 2. The notice has been displayed elsewhere (in case there are multiple add-ons)
220
		 *
221
		 * @return void
222
		 * @since 8.0.0
223
		 */
224
		public function maybe_display_notice() {
225
			if ( defined( 'MONSTERINSIGHTS_FORCE_ACTIVATION' ) && MONSTERINSIGHTS_FORCE_ACTIVATION ) {
0 ignored issues
show
The constant MONSTERINSIGHTS_FORCE_ACTIVATION was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
226
				return;
227
			}
228
229
			if ( $this->is_notice_already_active() ) {
230
				return;
231
			}
232
233
			if ( ! $this->is_php_compatible() ) {
234
				add_action( 'admin_notices', array( $this, 'display_php_notice' ) );
235
			}
236
237
			if ( ! $this->is_wp_compatible() ) {
238
				add_action( 'admin_notices', array( $this, 'display_wp_notice' ) );
239
			}
240
		}
241
242
		/**
243
		 * Deactivate plugin if minimum PHP and WP requirements are not met.
244
		 *
245
		 * @param $plugin
246
		 *
247
		 * @return void
248
		 * @since 8.0.0
249
		 */
250
		public function maybe_deactivate_plugin( $plugin ) {
251
			if ( defined( 'MONSTERINSIGHTS_FORCE_ACTIVATION' ) && MONSTERINSIGHTS_FORCE_ACTIVATION ) {
0 ignored issues
show
The constant MONSTERINSIGHTS_FORCE_ACTIVATION was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
252
				return;
253
			}
254
255
			$url                    = admin_url( 'plugins.php' );
256
			$compatible_php_version = $this->get_compatible_php_version();
257
			$compatible_wp_version  = $this->get_compatible_wp_version();
258
259
			if ( ! empty( $compatible_php_version['required'] ) && ! $this->is_php_compatible() ) {
260
				deactivate_plugins( $plugin );
261
				// Translators: HTML strong tag starts, PHP version number, HTML string tag end, plugins page Link tag starts with url and plugins page link tag ends.
262
				wp_die(
263
					sprintf( esc_html__( 'Sorry, but your current version of PHP does not meet the minimum required version %1$s%2$s%3$s or newer to run MonsterInsights properly. For information on how to upgrade your PHP version, contact your web host. %4$sClick here to return to the Dashboard%5$s.', 'google-analytics-for-wordpress' ),
264
						'<strong>',
265
						$compatible_php_version['required'], // phpcs:ignore
266
						'</strong>',
267
						'<a target="_blank" href="' . esc_url($url) . '">',
268
						'</a>'
269
					)
270
				);
271
			}
272
273
			if ( ! empty( $compatible_wp_version['required'] ) && ! $this->is_wp_compatible() ) {
274
				deactivate_plugins( plugin_basename( __FILE__ ) );
275
				// Translators: HTML strong tag starts, WP version number, HTML string tag end, plugins page Link tag starts with url and plugins page link tag ends.
276
				wp_die(
277
					sprintf(
278
						esc_html__( 'Sorry, but your WordPress version is not %1$s%2$s%3$s or newer. Please update your WordPress version and then activate MonsterInsights. For help on how to update your WordPress %4$sclick here%5$s.', 'google-analytics-for-wordpress' ),
279
						'<strong>',
280
						$compatible_wp_version['required'], // phpcs:ignore
281
						'</strong>',
282
						'<a target="_blank" href="' . esc_url($url) . '">',
283
						'</a>'
284
					)
285
				);
286
			}
287
		}
288
289
		/**
290
		 * Output a nag notice if the user has an out of date PHP version installed
291
		 *
292
		 * @return void
293
		 * @since 8.0.0
294
		 */
295
		public function display_php_notice() {
296
			$url = admin_url( 'plugins.php' );
297
			// Check for MS dashboard
298
			if ( is_network_admin() ) {
299
				$url = network_admin_url( 'plugins.php' );
300
			}
301
302
			$compatible_php_version = $this->get_compatible_php_version();
303
			if ( empty( $compatible_php_version['required'] ) ) {
304
				return;
305
			}
306
307
			$this->set_notice_active();
308
			?>
309
			<div class="error">
310
				<p>
311
					<?php
312
					// Translators: HTML strong tag starts, PHP version number, HTML string tag end, plugins page Link tag starts with url and plugins page link tag ends.
313
					echo sprintf(
314
						esc_html__( 'Sorry, but your current version of PHP does not meet the minimum required version %1$s%2$s%3$s or newer to run MonsterInsights properly. For information on how to upgrade your PHP version, contact your web host. %4$sClick here to return to the Dashboard%5$s.', 'google-analytics-for-wordpress' ),
315
						'<strong>',
316
						$compatible_php_version['required'], // phpcs:ignore
317
						'</strong>',
318
						'<a target="_blank" href="' . $url . '">', // phpcs:ignore
319
						'</a>' );
320
					?>
321
				</p>
322
			</div>
323
			<?php
324
		}
325
326
		/**
327
		 * Output a nag notice if the user has an out of date WP version installed
328
		 *
329
		 * @return void
330
		 * @since 8.0.0
331
		 */
332
		public function display_wp_notice() {
333
			$url = monsterinsights_get_url( 'notice', 'wrong-wp-version', 'https://www.wpbeginner.com/beginners-guide/ultimate-guide-to-upgrade-wordpress-for-beginners-infograph/' );
334
335
			$compatible_wp_version = $this->get_compatible_wp_version();
336
			if ( empty( $compatible_wp_version['required'] ) ) {
337
				return;
338
			}
339
340
			$this->set_notice_active();
341
			?>
342
			<div class="error">
343
				<p>
344
					<?php
345
					// Translators: Make version number bold and add a link to return to the plugins page.
346
					echo sprintf(
347
						esc_html__( 'Sorry, but your WordPress version is not %1$s%2$s%3$s or newer. Please update your WordPress version and then activate MonsterInsights. For help on how to update your WordPress %4$sclick here%5$s.', 'google-analytics-for-wordpress' ),
348
						'<strong>',
349
						$compatible_wp_version['required'], // phpcs:ignore
350
						'</strong>',
351
						'<a target="_blank" href="' . $url . '">', // phpcs:ignore
352
						'</a>'
353
					);
354
					?>
355
				</p>
356
			</div>
357
			<?php
358
		}
359
	}
360
}
361