PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / 2.0.2
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More v2.0.2
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 47 releases
content-control / classes / Plugin / Prerequisites.php

Prerequisites.php in Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More 2.0.2, at classes/Plugin/Prerequisites.php

400 lines 9.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Prerequisite handler.
4 *
5 * @package ContentControl\Utils
6 */
7
8 namespace ContentControl\Plugin;
9
10 defined( 'ABSPATH' ) || exit;
11
12 /**
13 * Prerequisite handler.
14 *
15 * @version 1.0.0
16 */
17 class Prerequisites {
18
19 /**
20 * Cache accessible across instances.
21 *
22 * @var array
23 */
24 public static $cache = [];
25
26 /**
27 * Array of checks to perform.
28 *
29 * @var array
30 */
31 protected $checks = [];
32
33 /**
34 * Array of detected failures.
35 *
36 * @var array
37 */
38 protected $failures = [];
39
40 /**
41 * Instantiate prerequisite checker.
42 *
43 * @param array $requirements Array of requirements.
44 */
45 public function __construct( $requirements = [] ) {
46 foreach ( $requirements as $arguments ) {
47 switch ( $arguments['type'] ) {
48 case 'php':
49 $this->checks[] = wp_parse_args(
50 $arguments,
51 [
52 'type' => 'php',
53 'version' => '5.6',
54 ]
55 );
56 break;
57 // phpcs:ignore WordPress.WP.CapitalPDangit.MisspelledInText
58 case 'wordpress':
59 case 'wp':
60 $this->checks[] = wp_parse_args(
61 $arguments,
62 [
63 'type' => 'wp',
64 'version' => '5.6',
65 ]
66 );
67 break;
68 case 'plugin':
69 $this->checks[] = wp_parse_args(
70 $arguments,
71 [
72 'type' => 'plugin',
73 'slug' => '',
74 'name' => '',
75 'version' => '',
76 'check_installed' => false,
77 'dep_label' => '',
78 ]
79 );
80 break;
81 default:
82 break;
83 }
84 }
85 }
86
87 /**
88 * Check requirements.
89 *
90 * @param boolean $return_on_fail Whether it should stop processing if one fails.
91 *
92 * @return bool
93 */
94 public function check( $return_on_fail = false ) {
95 $end_result = true;
96
97 foreach ( $this->checks as $check ) {
98 $result = $this->check_handler( $check );
99
100 if ( false === $result ) {
101 if ( true === $return_on_fail ) {
102 return false;
103 }
104
105 $end_result = false;
106 }
107 }
108
109 return $end_result;
110 }
111
112 /**
113 * Render notices when appropriate.
114 */
115 public function setup_notices() {
116 add_action( 'admin_notices', [ $this, 'render_notices' ] );
117 }
118
119 /**
120 * Handle individual checks by mapping them to methods.
121 *
122 * @param array $check Requirement check arguments.
123 *
124 * @return bool
125 */
126 public function check_handler( $check ) {
127 return method_exists( $this, 'check_' . $check['type'] ) ? $this->{'check_' . $check['type']}( $check ) : false;
128 }
129
130 /**
131 * Report failure notice to the queue.
132 *
133 * @param array $check_args Array of check arguments.
134 */
135 public function report_failure( $check_args ) {
136 $this->failures[] = $check_args;
137 }
138
139 /**
140 * Get a list of failures.
141 *
142 * @return array
143 */
144 public function get_failures() {
145 return $this->failures;
146 }
147
148 /**
149 * Check PHP version against args.
150 *
151 * @param array $check_args Array of args.
152 *
153 * @return bool
154 */
155 public function check_php( $check_args ) {
156 if ( false === version_compare( phpversion(), $check_args['version'], '>=' ) ) {
157 $this->report_failure( $check_args );
158 return false;
159 }
160
161 return true;
162 }
163
164
165 /**
166 * Check PHP version against args.
167 *
168 * @param array $check_args Array of args.
169 *
170 * @return bool
171 */
172 public function check_wp( $check_args ) {
173 global $wp_version;
174
175 if ( false === version_compare( $wp_version, $check_args['version'], '>=' ) ) {
176 $this->report_failure( $check_args );
177 return false;
178 }
179
180 return true;
181 }
182
183 /**
184 * Check plugin requirements.
185 *
186 * @param array $check_args Array of args.
187 *
188 * @return bool
189 */
190 public function check_plugin( $check_args ) {
191 $active = $this->plugin_is_active( $check_args['slug'] );
192
193 /**
194 * The following checks are performed in this order for performance reasons.
195 *
196 * We start with most cached option, to least in hopes of a hit early.
197 *
198 * 1. If active and not checking version.
199 * 2. If active and outdated.
200 * 3. If not active and installed.
201 * 4. If not installed
202 */
203 if ( true === $active ) {
204 // If required version is set & plugin is active, check that first.
205 if ( isset( $check_args['version'] ) ) {
206 $version = $this->get_plugin_data( $check_args['slug'], 'Version' );
207
208 // If its higher than the required version, we can bail now > true.
209 if ( version_compare( $version, $check_args['version'], '>=' ) ) {
210 return true;
211 } else {
212 // If not updated, report the failure and bail > false.
213 $this->report_failure(
214 array_merge(
215 $check_args,
216 [
217 // Report not_updated status.
218 'not_updated' => true,
219 ]
220 )
221 );
222 return false;
223 }
224 } else {
225 // If the plugin is active, with no required version, were done > true.
226 return true;
227 }
228 }
229
230 if ( $check_args['check_installed'] ) {
231 // Check if installed, if so the plugin is not activated.
232 if ( $check_args['name'] === $this->get_plugin_data( $check_args['slug'], 'Name' ) ) {
233 $this->report_failure(
234 array_merge(
235 $check_args,
236 [
237 // Report not_activated status.
238 'not_activated' => true,
239 ]
240 )
241 );
242 } else {
243 $this->report_failure(
244 array_merge(
245 $check_args,
246 [
247 // Report not_installed status.
248 'not_installed' => true,
249 ]
250 )
251 );
252 }
253 }
254
255 return false;
256 }
257
258 /**
259 * Internally cached get_plugin_data/get_file_data wrapper.
260 *
261 * @param string $slug Plugins `folder/file.php` slug.
262 * @param string $header Specific plugin header needed.
263 * @return mixed
264 */
265 private function get_plugin_data( $slug, $header = null ) {
266 if ( ! isset( static::$cache['get_plugin_data'][ $slug ] ) ) {
267 $headers = \get_file_data( WP_PLUGIN_DIR . '/' . $slug, [
268 'Name' => 'Plugin Name',
269 'Version' => 'Version',
270 ], 'plugin' );
271
272 static::$cache['get_plugin_data'][ $slug ] = $headers;
273 }
274
275 $plugin_data = static::$cache['get_plugin_data'][ $slug ];
276
277 if ( empty( $header ) ) {
278 return $plugin_data;
279 }
280
281 return isset( $plugin_data[ $header ] ) ? $plugin_data[ $header ] : null;
282 }
283
284 /**
285 * Check if plugin is active.
286 *
287 * @param string $slug Slug to check for.
288 *
289 * @return bool
290 */
291 protected function plugin_is_active( $slug ) {
292 $active_plugins = \get_option( 'active_plugins', [] );
293
294 return in_array( $slug, $active_plugins, true );
295 }
296
297
298 /**
299 * Get php error message.
300 *
301 * @param array $failed_check_args Check arguments.
302 *
303 * @return string
304 */
305 public function get_php_message( $failed_check_args ) {
306 /* translators: 1. Requirement name (WordPress|PHP)., 2. Version Number. */
307 $message = __( 'This plugin requires <b>%1$s %2$s</b> or higher in order to run.', 'content-control' );
308 return sprintf(
309 $message,
310 __( 'PHP', 'default' ),
311 $failed_check_args['version'] );
312 }
313
314 /**
315 * Get wp error message.
316 *
317 * @param array $failed_check_args Check arguments.
318 *
319 * @return string
320 */
321 public function get_wp_message( $failed_check_args ) {
322 /* translators: 1. Requirement name (WordPress|PHP)., 2. Version Number. */
323 $message = __( 'This plugin requires <b>%1$s %2$s</b> or higher in order to run.', 'content-control' );
324 return sprintf(
325 $message,
326 __( 'WordPress', 'default' ),
327 $failed_check_args['version']
328 );
329 }
330
331 /**
332 * Get plugin error message.
333 *
334 * @param array $failed_check_args Get helpful error message.
335 *
336 * @return string
337 */
338 public function get_plugin_message( $failed_check_args ) {
339 $slug = $failed_check_args['slug'];
340 // Without file path.
341 $short_slug = explode( '/', $slug );
342 $short_slug = $short_slug[0];
343 $name = $failed_check_args['name'];
344 $dep_label = $failed_check_args['dep_label'];
345
346 if ( isset( $failed_check_args['not_activated'] ) ) {
347 $url = esc_url( wp_nonce_url( admin_url( 'plugins.php?action=activate&plugin=' . $slug ), 'activate-plugin_' . $slug ) );
348 $link = '<a href="' . $url . '">' . __( 'activate it', 'content-control' ) . '</a>';
349
350 $text = sprintf(
351 /* translators: 1. Plugin Name, 2. Required Plugin Name, 4. `activate it` link. */
352 __( 'The plugin "%1$s" requires %2$s! Please %3$s to continue!', 'content-control' ),
353 $dep_label,
354 '<strong>' . $name . '</strong>',
355 $link
356 );
357 } elseif ( isset( $failed_check_args['not_updated'] ) ) {
358 $url = esc_url( wp_nonce_url( admin_url( 'update.php?action=upgrade-plugin&plugin=' . $slug ), 'upgrade-plugin_' . $slug ) );
359 $link = '<a href="' . $url . '">' . __( 'update it', 'content-control' ) . '</a>';
360
361 $text = sprintf(
362 /* translators: 1. Plugin Name, 2. Required Plugin Name, 3. Version number, 4. `update it` link. */
363 __( 'The plugin "%1$s" requires %2$s v%3$s or higher! Please %4$s to continue!', 'content-control' ),
364 $dep_label,
365 '<strong>' . $name . '</strong>',
366 '<strong>' . $failed_check_args['version'] . '</strong>',
367 $link
368 );
369 } else {
370 $url = esc_url( wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=' . $short_slug ), 'install-plugin_' . $short_slug ) );
371 $link = '<a href="' . $url . '">' . __( 'install it', 'content-control' ) . '</a>';
372
373 $text = sprintf(
374 /* translators: 1. Plugin Name, 2. Required Plugin Name, 3. `install it` link. */
375 __( 'The plugin "%1$s" requires %2$s! Please %3$s to continue!', 'content-control' ),
376 $dep_label,
377 '<strong>' . $name . '</strong>',
378 $link
379 );
380 }
381
382 return $text;
383 }
384
385 /**
386 * Render needed admin notices.
387 *
388 * @return void
389 */
390 public function render_notices() {
391 foreach ( $this->failures as $failure ) {
392 $class = 'notice notice-error';
393 $message = method_exists( $this, 'get_' . $failure['type'] . '_message' ) ? $this->{'get_' . $failure['type'] . '_message'}( $failure ) : false;
394
395 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
396 printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), $message );
397 }
398 }
399 }
400