From 75a3e484ec49a3ed9578be89a981074dc01086ae Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Fri, 22 Mar 2019 00:37:50 +0000 Subject: [PATCH] Plugins: Block plugin activation if it requires a higher version of PHP or WordPress. Introduce `validate_plugin_requirements()` for validating a plugin's WordPress and PHP version requirements. Introduce `wp_is_wp_compatible()` and `wp_is_php_compatible()` for checking compatibility with the current WordPress or PHP version. Props afragen, joyously, DrewAPicture, TimothyBlynJacobs, desrosj, flixos90, SergeyBiryukov. See #43992. Built from https://develop.svn.wordpress.org/trunk@44978 git-svn-id: http://core.svn.wordpress.org/trunk@44809 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/includes/plugin.php | 55 ++++++++++++++++++++++++++++++++++++ wp-includes/functions.php | 26 +++++++++++++++++ wp-includes/version.php | 2 +- 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/wp-admin/includes/plugin.php b/wp-admin/includes/plugin.php index f44b5aff02..f54717f804 100644 --- a/wp-admin/includes/plugin.php +++ b/wp-admin/includes/plugin.php @@ -597,6 +597,7 @@ function is_network_only_plugin( $plugin ) { * ensure that the success redirection will update the error redirection. * * @since 2.5.0 + * @since 5.2.0 Test for WordPress version and PHP version compatibility. * * @param string $plugin Path to the plugin file relative to the plugins directory. * @param string $redirect Optional. URL to redirect to. @@ -621,6 +622,11 @@ function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silen return $valid; } + $requirements = validate_plugin_requirements( $plugin ); + if ( is_wp_error( $requirements ) ) { + return $requirements; + } + if ( ( $network_wide && ! isset( $current[ $plugin ] ) ) || ( ! $network_wide && ! in_array( $plugin, $current ) ) ) { if ( ! empty( $redirect ) ) { wp_redirect( add_query_arg( '_error_nonce', wp_create_nonce( 'plugin-activation-error_' . $plugin ), $redirect ) ); // we'll override this later if the plugin can be included without fatal error @@ -1060,6 +1066,55 @@ function validate_plugin( $plugin ) { return 0; } +/** + * Validate the plugin requirements for WP version and PHP version. + * + * @since 5.2.0 + * + * @param string $plugin Path to the plugin file relative to the plugins directory. + * @return true|WP_Error True if requirements are met, WP_Error on failure. + */ +function validate_plugin_requirements( $plugin ) { + $readme_file = WP_PLUGIN_DIR . '/' . dirname( $plugin ) . '/readme.txt'; + + if ( file_exists( $readme_file ) ) { + $plugin_data = get_file_data( + $readme_file, + array( + 'requires' => 'Requires at least', + 'requires_php' => 'Requires PHP', + ), + 'plugin' + ); + } else { + return true; + } + + $plugin_data['wp_compatible'] = wp_is_wp_compatible( $plugin_data['requires'] ); + $plugin_data['php_compatible'] = wp_is_php_compatible( $plugin_data['requires_php'] ); + + $plugin_data = array_merge( $plugin_data, get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ) ); + + if ( ! $plugin_data['wp_compatible'] && ! $plugin_data['php_compatible'] ) { + return new WP_Error( 'plugin_wp_php_incompatible', sprintf( + /* translators: %s: plugin name */ + __( 'Error: Current WordPress and PHP versions do not meet minimum requirements for %s.' ), $plugin_data['Name'] ) + ); + } elseif ( ! $plugin_data['php_compatible'] ) { + return new WP_Error( 'plugin_php_incompatible', sprintf( + /* translators: %s: plugin name */ + __( 'Error: Current PHP version does not meet minimum requirements for %s.' ), $plugin_data['Name'] ) + ); + } elseif ( ! $plugin_data['wp_compatible'] ) { + return new WP_Error( 'plugin_wp_incompatible', sprintf( + /* translators: %s: plugin name */ + __( 'Error: Current WordPress version does not meet minimum requirements for %s.' ), $plugin_data['Name'] ) + ); + } + + return true; +} + /** * Whether the plugin can be uninstalled. * diff --git a/wp-includes/functions.php b/wp-includes/functions.php index 86cdabe7e0..b8a0a7db07 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -6897,3 +6897,29 @@ function wp_direct_php_update_button() { ); echo '

'; } + +/** + * Checks compatibility with the current WordPress version. + * + * @since 5.2.0 + * + * @param string $required Minimum required WordPress version. + * @return bool True if required version is compatible or empty, false if not. + */ +function wp_is_wp_compatible( $required ) { + $wp_version = get_bloginfo( 'version' ); + + return empty( $required ) || version_compare( $wp_version, $required, '>=' ); +} + +/** + * Checks compatibility with the current PHP version. + * + * @since 5.2.0 + * + * @param string $required Minimum required PHP version. + * @return bool True if required version is compatible or empty, false if not. + */ +function wp_is_php_compatible( $required ) { + return empty( $required ) || version_compare( phpversion(), $required, '>=' ); +} diff --git a/wp-includes/version.php b/wp-includes/version.php index 2c187b24f9..7438a5bf0f 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -13,7 +13,7 @@ * * @global string $wp_version */ -$wp_version = '5.2-alpha-44977'; +$wp_version = '5.2-alpha-44978'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.