PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / 2.6.1
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More v2.6.1
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.6.1, at classes/Plugin/Prerequisites.php

404 lines 10.2 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<string,array<string,mixed>>
23 */
24 public static $cache = [];
25
26 /**
27 * Array of checks to perform.
28 *
29 * @var array{type:string,version:string}[]
30 */
31 protected $checks = [];
32
33 /**
34 * Array of detected failures.
35 *
36 * @var array{type:string,version:string}[]
37 */
38 protected $failures = [];
39
40 /**
41 * Instantiate prerequisite checker.
42 *
43 * @param array{type:string,version:string}[] $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 * @return void
116 */
117 public function setup_notices() {
118 add_action( 'admin_notices', [ $this, 'render_notices' ] );
119 }
120
121 /**
122 * Handle individual checks by mapping them to methods.
123 *
124 * @param array{type:string,version:string} $check Requirement check arguments.
125 *
126 * @return bool
127 */
128 public function check_handler( $check ) {
129 return method_exists( $this, 'check_' . $check['type'] ) ? $this->{'check_' . $check['type']}( $check ) : false;
130 }
131
132 /**
133 * Report failure notice to the queue.
134 *
135 * @param array{type:string,version:string} $check_args Array of check arguments.
136 *
137 * @return void
138 */
139 public function report_failure( $check_args ) {
140 $this->failures[] = $check_args;
141 }
142
143 /**
144 * Get a list of failures.
145 *
146 * @return array{type:string,version:string}[]
147 */
148 public function get_failures() {
149 return $this->failures;
150 }
151
152 /**
153 * Check PHP version against args.
154 *
155 * @param array{type:string,version:string} $check_args Array of args.
156 *
157 * @return bool
158 */
159 public function check_php( $check_args ) {
160 if ( false === version_compare( phpversion(), $check_args['version'], '>=' ) ) {
161 $this->report_failure( $check_args );
162 return false;
163 }
164
165 return true;
166 }
167
168
169 /**
170 * Check PHP version against args.
171 *
172 * @param array{type:string,version:string} $check_args Array of args.
173 *
174 * @return bool
175 */
176 public function check_wp( $check_args ) {
177 global $wp_version;
178
179 if ( false === version_compare( $wp_version, $check_args['version'], '>=' ) ) {
180 $this->report_failure( $check_args );
181 return false;
182 }
183
184 return true;
185 }
186
187 /**
188 * Check plugin requirements.
189 *
190 * @param array{type:string,version:string,name:string,slug:string,version:string,check_installed:bool,dep_label:string} $check_args Array of args.
191 *
192 * @return bool
193 */
194 public function check_plugin( $check_args ) {
195 $active = $this->plugin_is_active( $check_args['slug'] );
196
197 /**
198 * The following checks are performed in this order for performance reasons.
199 *
200 * We start with most cached option, to least in hopes of a hit early.
201 *
202 * 1. If active and not checking version.
203 * 2. If active and outdated.
204 * 3. If not active and installed.
205 * 4. If not installed
206 */
207 if ( true === $active ) {
208 // If required version is set & plugin is active, check that first.
209 if ( ! empty( $check_args['version'] ) ) {
210 $version = $this->get_plugin_data( $check_args['slug'], 'Version' );
211
212 // If its higher than the required version, we can bail now > true.
213 if ( version_compare( $version, $check_args['version'], '>=' ) ) {
214 return true;
215 } else {
216 // If not updated, report the failure and bail > false.
217 $this->report_failure(
218 array_merge(
219 $check_args,
220 [
221 // Report not_updated status.
222 'not_updated' => true,
223 ]
224 )
225 );
226 return false;
227 }
228 } else {
229 // If the plugin is active, with no required version, were done > true.
230 return true;
231 }
232 }
233
234 if ( $check_args['check_installed'] ) {
235 // Check if installed, if so the plugin is not activated.
236 if ( $check_args['name'] === $this->get_plugin_data( $check_args['slug'], 'Name' ) ) {
237 $this->report_failure(
238 array_merge(
239 $check_args,
240 [
241 // Report not_activated status.
242 'not_activated' => true,
243 ]
244 )
245 );
246 } else {
247 $this->report_failure(
248 array_merge(
249 $check_args,
250 [
251 // Report not_installed status.
252 'not_installed' => true,
253 ]
254 )
255 );
256 }
257 }
258
259 return false;
260 }
261
262 /**
263 * Internally cached get_plugin_data/get_file_data wrapper.
264 *
265 * @param string $slug Plugins `folder/file.php` slug.
266 * @param string $header Specific plugin header needed.
267 * @return mixed
268 */
269 private function get_plugin_data( $slug, $header = null ) {
270 if ( ! isset( static::$cache['get_plugin_data'][ $slug ] ) ) {
271 $headers = \get_file_data( WP_PLUGIN_DIR . '/' . $slug, [
272 'Name' => 'Plugin Name',
273 'Version' => 'Version',
274 ], 'plugin' );
275
276 static::$cache['get_plugin_data'][ $slug ] = $headers;
277 }
278
279 $plugin_data = static::$cache['get_plugin_data'][ $slug ];
280
281 if ( empty( $header ) ) {
282 return $plugin_data;
283 }
284
285 return isset( $plugin_data[ $header ] ) ? $plugin_data[ $header ] : null;
286 }
287
288 /**
289 * Check if plugin is active.
290 *
291 * @param string $slug Slug to check for.
292 *
293 * @return bool
294 */
295 protected function plugin_is_active( $slug ) {
296 $active_plugins = \get_option( 'active_plugins', [] );
297
298 return in_array( $slug, $active_plugins, true );
299 }
300
301
302 /**
303 * Get php error message.
304 *
305 * @param array{type:string,version:string} $failed_check_args Check arguments.
306 *
307 * @return string
308 */
309 public function get_php_message( $failed_check_args ) {
310 /* translators: 1. Requirement name (WordPress|PHP)., 2. Version Number. */
311 $message = __( 'This plugin requires <b>%1$s %2$s</b> or higher in order to run.', 'content-control' );
312 return sprintf(
313 $message,
314 __( 'PHP', 'default' ),
315 $failed_check_args['version'] );
316 }
317
318 /**
319 * Get wp error message.
320 *
321 * @param array{type:string,version:string} $failed_check_args Check arguments.
322 *
323 * @return string
324 */
325 public function get_wp_message( $failed_check_args ) {
326 /* translators: 1. Requirement name (WordPress|PHP)., 2. Version Number. */
327 $message = __( 'This plugin requires <b>%1$s %2$s</b> or higher in order to run.', 'content-control' );
328 return sprintf(
329 $message,
330 __( 'WordPress', 'default' ),
331 $failed_check_args['version']
332 );
333 }
334
335 /**
336 * Get plugin error message.
337 *
338 * @param array{type:string,version:string,name:string,slug:string,version:string,check_installed:bool,dep_label:string,not_activated?:bool|null,not_updated?:bool|null} $failed_check_args Get helpful error message.
339 *
340 * @return string
341 */
342 public function get_plugin_message( $failed_check_args ) {
343 $slug = $failed_check_args['slug'];
344 // Without file path.
345 $short_slug = explode( '/', $slug );
346 $short_slug = $short_slug[0];
347 $name = $failed_check_args['name'];
348 $dep_label = $failed_check_args['dep_label'];
349
350 if ( isset( $failed_check_args['not_activated'] ) ) {
351 $url = esc_url( wp_nonce_url( admin_url( 'plugins.php?action=activate&plugin=' . $slug ), 'activate-plugin_' . $slug ) );
352 $link = '<a href="' . $url . '">' . __( 'activate it', 'content-control' ) . '</a>';
353
354 $text = sprintf(
355 /* translators: 1. Plugin Name, 2. Required Plugin Name, 4. `activate it` link. */
356 __( 'The plugin "%1$s" requires %2$s! Please %3$s to continue!', 'content-control' ),
357 $dep_label,
358 '<strong>' . $name . '</strong>',
359 $link
360 );
361 } elseif ( isset( $failed_check_args['not_updated'] ) ) {
362 $url = esc_url( wp_nonce_url( admin_url( 'update.php?action=upgrade-plugin&plugin=' . $slug ), 'upgrade-plugin_' . $slug ) );
363 $link = '<a href="' . $url . '">' . __( 'update it', 'content-control' ) . '</a>';
364
365 $text = sprintf(
366 /* translators: 1. Plugin Name, 2. Required Plugin Name, 3. Version number, 4. `update it` link. */
367 __( 'The plugin "%1$s" requires %2$s v%3$s or higher! Please %4$s to continue!', 'content-control' ),
368 $dep_label,
369 '<strong>' . $name . '</strong>',
370 '<strong>' . $failed_check_args['version'] . '</strong>',
371 $link
372 );
373 } else {
374 $url = esc_url( wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=' . $short_slug ), 'install-plugin_' . $short_slug ) );
375 $link = '<a href="' . $url . '">' . __( 'install it', 'content-control' ) . '</a>';
376
377 $text = sprintf(
378 /* translators: 1. Plugin Name, 2. Required Plugin Name, 3. `install it` link. */
379 __( 'The plugin "%1$s" requires %2$s! Please %3$s to continue!', 'content-control' ),
380 $dep_label,
381 '<strong>' . $name . '</strong>',
382 $link
383 );
384 }
385
386 return $text;
387 }
388
389 /**
390 * Render needed admin notices.
391 *
392 * @return void
393 */
394 public function render_notices() {
395 foreach ( $this->failures as $failure ) {
396 $class = 'notice notice-error';
397 $message = method_exists( $this, 'get_' . $failure['type'] . '_message' ) ? $this->{'get_' . $failure['type'] . '_message'}( $failure ) : false;
398
399 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
400 printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), $message );
401 }
402 }
403 }
404