From 286d6723898b499817e501700c6244b56008ed97 Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Mon, 13 Apr 2020 15:26:37 +0000 Subject: [PATCH] Themes: Block theme activation if it requires a higher version of PHP or WordPress. Introduce `validate_theme_requirements()` for validating a theme's WordPress and PHP version requirements. Follow-up to [44978] and [45546] for plugins. Props afragen, audrasjb, SergeyBiryukov. See #43992. git-svn-id: https://develop.svn.wordpress.org/trunk@47573 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/theme.php | 77 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/wp-includes/theme.php b/src/wp-includes/theme.php index 197d99ebb3..03264225fe 100644 --- a/src/wp-includes/theme.php +++ b/src/wp-includes/theme.php @@ -733,6 +733,11 @@ function locale_stylesheet() { function switch_theme( $stylesheet ) { global $wp_theme_directories, $wp_customize, $sidebars_widgets; + $requirements = validate_theme_requirements( $stylesheet ); + if ( is_wp_error( $requirements ) ) { + wp_die( $requirements ); + } + $_sidebars_widgets = null; if ( 'wp_ajax_customize_save' === current_action() ) { $old_sidebars_widgets_data_setting = $wp_customize->get_setting( 'old_sidebars_widgets_data' ); @@ -880,6 +885,78 @@ function validate_current_theme() { return false; } +/** + * Validates the theme requirements for WordPress version and PHP version. + * + * Uses the information from `Requires at least` and `Requires PHP` headers + * defined in the theme's `style.css` file. + * + * If the headers are not present in the theme's stylesheet file, + * `readme.txt` is also checked as a fallback. + * + * @since 5.5.0 + * + * @param string $stylesheet Directory name for the theme. + * @return true|WP_Error True if requirements are met, WP_Error on failure. + */ +function validate_theme_requirements( $stylesheet ) { + $theme = wp_get_theme( $stylesheet ); + + $requirements = array( + 'requires' => ! empty( $theme->get( 'RequiresWP' ) ) ? $theme->get( 'RequiresWP' ) : '', + 'requires_php' => ! empty( $theme->get( 'RequiresPHP' ) ) ? $theme->get( 'RequiresPHP' ) : '', + ); + + $readme_file = $theme->theme_root . '/' . $stylesheet . '/readme.txt'; + + if ( file_exists( $readme_file ) ) { + $readme_headers = get_file_data( + $readme_file, + array( + 'requires' => 'Requires at least', + 'requires_php' => 'Requires PHP', + ), + 'theme' + ); + + $requirements = array_merge( $readme_headers, $requirements ); + } + + $compatible_wp = is_wp_version_compatible( $requirements['requires'] ); + $compatible_php = is_php_version_compatible( $requirements['requires_php'] ); + + if ( ! $compatible_wp && ! $compatible_php ) { + return new WP_Error( + 'theme_wp_php_incompatible', + sprintf( + /* translators: %s: Theme name. */ + _x( 'Error: Current WordPress and PHP versions do not meet minimum requirements for %s.', 'theme' ), + $theme->display( 'Name' ) + ) + ); + } elseif ( ! $compatible_php ) { + return new WP_Error( + 'theme_php_incompatible', + sprintf( + /* translators: %s: Theme name. */ + _x( 'Error: Current PHP version does not meet minimum requirements for %s.', 'theme' ), + $theme->display( 'Name' ) + ) + ); + } elseif ( ! $compatible_wp ) { + return new WP_Error( + 'theme_wp_incompatible', + sprintf( + /* translators: %s: Theme name. */ + _x( 'Error: Current WordPress version does not meet minimum requirements for %s.', 'theme' ), + $theme->display( 'Name' ) + ) + ); + } + + return true; +} + /** * Retrieve all theme modifications. *