diff --git a/wp-admin/includes/class-plugin-upgrader.php b/wp-admin/includes/class-plugin-upgrader.php index 97343fcf9d..091cfebc18 100644 --- a/wp-admin/includes/class-plugin-upgrader.php +++ b/wp-admin/includes/class-plugin-upgrader.php @@ -155,12 +155,6 @@ class Plugin_Upgrader extends WP_Upgrader { // Force refresh of plugin update information. wp_clean_plugins_cache( $parsed_args['clear_update_cache'] ); - $all_plugin_data = get_option( 'plugin_data', array() ); - $plugin_file = $this->new_plugin_data['file']; - unset( $this->new_plugin_data['file'] ); - $all_plugin_data[ $plugin_file ] = $this->new_plugin_data; - update_option( 'plugin_data', $all_plugin_data ); - if ( $parsed_args['overwrite_package'] ) { /** * Fires when the upgrader has successfully overwritten a currently installed @@ -488,16 +482,7 @@ class Plugin_Upgrader extends WP_Upgrader { foreach ( $files as $file ) { $info = get_plugin_data( $file, false, false ); if ( ! empty( $info['Name'] ) ) { - $basename = basename( $file ); - $dirname = basename( dirname( $file ) ); - - if ( '.' === $dirname ) { - $plugin_file = $basename; - } else { - $plugin_file = "$dirname/$basename"; - } - $this->new_plugin_data = ( $info ); - $this->new_plugin_data['file'] = $plugin_file; + $this->new_plugin_data = $info; break; } } diff --git a/wp-admin/includes/plugin-install.php b/wp-admin/includes/plugin-install.php index 2de2aabbc3..2399ffc807 100644 --- a/wp-admin/includes/plugin-install.php +++ b/wp-admin/includes/plugin-install.php @@ -927,7 +927,7 @@ function wp_get_plugin_action_button( $name, $data, $compatible_php, $compatible // Determine the status of plugin dependencies. $installed_plugins = get_plugins(); - $active_plugins = get_option( 'active_plugins' ); + $active_plugins = get_option( 'active_plugins', array() ); $plugin_dependencies_count = count( $requires_plugins ); $installed_plugin_dependencies_count = 0; $active_plugin_dependencies_count = 0; diff --git a/wp-admin/includes/plugin.php b/wp-admin/includes/plugin.php index fa3fa09f09..680f4a7728 100644 --- a/wp-admin/includes/plugin.php +++ b/wp-admin/includes/plugin.php @@ -333,7 +333,6 @@ function get_plugins( $plugin_folder = '' ) { return $wp_plugins; } - $new_plugin_data = array(); foreach ( $plugin_files as $plugin_file ) { if ( ! is_readable( "$plugin_root/$plugin_file" ) ) { continue; @@ -346,13 +345,6 @@ function get_plugins( $plugin_folder = '' ) { continue; } - $new_plugin_file = str_replace( - trailingslashit( WP_PLUGIN_DIR ), - '', - "$plugin_root/$plugin_file" - ); - - $new_plugin_data[ $new_plugin_file ] = $plugin_data; $wp_plugins[ plugin_basename( $plugin_file ) ] = $plugin_data; } @@ -361,10 +353,6 @@ function get_plugins( $plugin_folder = '' ) { $cache_plugins[ $plugin_folder ] = $wp_plugins; wp_cache_set( 'plugins', $cache_plugins, 'plugins' ); - if ( ! wp_installing() ) { - update_option( 'plugin_data', $new_plugin_data ); - } - return $wp_plugins; } @@ -975,7 +963,6 @@ function delete_plugins( $plugins, $deprecated = '' ) { $plugins_dir = trailingslashit( $plugins_dir ); $plugin_translations = wp_get_installed_translations( 'plugins' ); - $all_plugin_data = get_option( 'plugin_data', array() ); $errors = array(); @@ -1020,7 +1007,6 @@ function delete_plugins( $plugins, $deprecated = '' ) { $errors[] = $plugin_file; continue; } - unset( $all_plugin_data[ $plugin_file ] ); $plugin_slug = dirname( $plugin_file ); @@ -1069,7 +1055,6 @@ function delete_plugins( $plugins, $deprecated = '' ) { return new WP_Error( 'could_not_remove_plugin', sprintf( $message, implode( ', ', $errors ) ) ); } - update_option( 'plugin_data', $all_plugin_data ); return true; } @@ -1214,6 +1199,8 @@ function validate_plugin_requirements( $plugin ) { ); } + WP_Plugin_Dependencies::initialize(); + if ( WP_Plugin_Dependencies::has_unmet_dependencies( $plugin ) ) { $dependencies = WP_Plugin_Dependencies::get_dependencies( $plugin ); $unmet_dependencies = array(); diff --git a/wp-admin/plugin-install.php b/wp-admin/plugin-install.php index a8beb8249b..5c8be143bf 100644 --- a/wp-admin/plugin-install.php +++ b/wp-admin/plugin-install.php @@ -135,8 +135,8 @@ get_current_screen()->set_screen_reader_content( */ require_once ABSPATH . 'wp-admin/admin-header.php'; +WP_Plugin_Dependencies::initialize(); WP_Plugin_Dependencies::display_admin_notice_for_unmet_dependencies(); -WP_Plugin_Dependencies::display_admin_notice_for_deactivated_dependents(); WP_Plugin_Dependencies::display_admin_notice_for_circular_dependencies(); ?>
"> diff --git a/wp-admin/plugins.php b/wp-admin/plugins.php index 5c9f723283..e8f1074a71 100644 --- a/wp-admin/plugins.php +++ b/wp-admin/plugins.php @@ -40,6 +40,8 @@ $_SERVER['REQUEST_URI'] = remove_query_arg( $query_args_to_remove, $_SERVER['REQ wp_enqueue_script( 'updates' ); +WP_Plugin_Dependencies::initialize(); + if ( $action ) { switch ( $action ) { @@ -741,7 +743,6 @@ if ( isset( $_GET['error'] ) ) { ?> -

diff --git a/wp-includes/class-wp-plugin-dependencies.php b/wp-includes/class-wp-plugin-dependencies.php index d7332b4186..b0ad17faea 100644 --- a/wp-includes/class-wp-plugin-dependencies.php +++ b/wp-includes/class-wp-plugin-dependencies.php @@ -105,15 +105,25 @@ class WP_Plugin_Dependencies { protected static $circular_dependencies_slugs; /** - * Initializes by fetching plugin header and plugin API data, - * and deactivating dependents with unmet dependencies. + * Whether Plugin Dependencies have been initialized. + * + * @since 6.5.0 + * + * @var bool + */ + protected static $initialized = false; + + /** + * Initializes by fetching plugin header and plugin API data. * * @since 6.5.0 */ public static function initialize() { - self::read_dependencies_from_plugin_headers(); - self::get_dependency_api_data(); - self::deactivate_dependents_with_unmet_dependencies(); + if ( false === self::$initialized ) { + self::read_dependencies_from_plugin_headers(); + self::get_dependency_api_data(); + self::$initialized = true; + } } /** @@ -125,7 +135,7 @@ class WP_Plugin_Dependencies { * @return bool Whether the plugin has plugins that depend on it. */ public static function has_dependents( $plugin_file ) { - return in_array( self::convert_to_slug( $plugin_file ), self::$dependency_slugs, true ); + return in_array( self::convert_to_slug( $plugin_file ), (array) self::$dependency_slugs, true ); } /** @@ -172,7 +182,7 @@ class WP_Plugin_Dependencies { public static function get_dependents( $slug ) { $dependents = array(); - foreach ( self::$dependencies as $dependent => $dependencies ) { + foreach ( (array) self::$dependencies as $dependent => $dependencies ) { if ( in_array( $slug, $dependencies, true ) ) { $dependents[] = $dependent; } @@ -368,36 +378,6 @@ class WP_Plugin_Dependencies { } } - /** - * Displays an admin notice if dependencies have been deactivated. - * - * @since 6.5.0 - */ - public static function display_admin_notice_for_deactivated_dependents() { - /* - * Plugin deactivated if dependencies not met. - * Transient on a 10 second timeout. - */ - $deactivate_requires = get_site_transient( 'wp_plugin_dependencies_deactivated_plugins' ); - if ( ! empty( $deactivate_requires ) ) { - $deactivated_plugins = ''; - foreach ( $deactivate_requires as $deactivated ) { - $deactivated_plugins .= '
  • ' . esc_html( self::$plugins[ $deactivated ]['Name'] ) . '
  • '; - } - wp_admin_notice( - sprintf( - /* translators: 1: plugin names */ - __( 'The following plugin(s) have been deactivated due to uninstalled or inactive dependencies: %s' ), - "
      $deactivated_plugins
    " - ), - array( - 'type' => 'error', - 'dismissible' => true, - ) - ); - } - } - /** * Displays an admin notice if circular dependencies are installed. * @@ -543,14 +523,8 @@ class WP_Plugin_Dependencies { return self::$plugins; } - $all_plugin_data = get_option( 'plugin_data', array() ); - - if ( empty( $all_plugin_data ) ) { - require_once ABSPATH . '/wp-admin/includes/plugin.php'; - $all_plugin_data = get_plugins(); - } - - self::$plugins = $all_plugin_data; + require_once ABSPATH . '/wp-admin/includes/plugin.php'; + self::$plugins = get_plugins(); return self::$plugins; } @@ -620,83 +594,6 @@ class WP_Plugin_Dependencies { return $sanitized_slugs; } - /** - * Gets plugin filepaths for active plugins that depend on the dependency. - * - * Recurses for each dependent that is also a dependency. - * - * @param string $plugin_file The dependency's filepath, relative to the plugin directory. - * @return string[] An array of active dependent plugin filepaths, relative to the plugin directory. - */ - protected static function get_active_dependents_in_dependency_tree( $plugin_file ) { - $all_dependents = array(); - $dependents = self::get_dependents( self::convert_to_slug( $plugin_file ) ); - - if ( empty( $dependents ) ) { - return $all_dependents; - } - - require_once ABSPATH . '/wp-admin/includes/plugin.php'; - foreach ( $dependents as $dependent ) { - if ( is_plugin_active( $dependent ) ) { - $all_dependents[] = $dependent; - $all_dependents = array_merge( - $all_dependents, - self::get_active_dependents_in_dependency_tree( $dependent ) - ); - } - } - - return $all_dependents; - } - - /** - * Deactivates dependent plugins with unmet dependencies. - * - * @since 6.5.0 - */ - protected static function deactivate_dependents_with_unmet_dependencies() { - $dependents_to_deactivate = array(); - $circular_dependencies = array_reduce( - self::get_circular_dependencies(), - function ( $all_circular, $circular_pair ) { - return array_merge( $all_circular, $circular_pair ); - }, - array() - ); - - require_once ABSPATH . '/wp-admin/includes/plugin.php'; - foreach ( self::$dependencies as $dependent => $dependencies ) { - // Skip dependents that are no longer installed or aren't active. - if ( ! array_key_exists( $dependent, self::$plugins ) || is_plugin_inactive( $dependent ) ) { - continue; - } - - // Skip plugins within a circular dependency tree or plugins that have no unmet dependencies. - if ( in_array( $dependent, $circular_dependencies, true ) || ! self::has_unmet_dependencies( $dependent ) ) { - continue; - } - - $dependents_to_deactivate[] = $dependent; - - // Also add any plugins that rely on any of this plugin's dependents. - $dependents_to_deactivate = array_merge( - $dependents_to_deactivate, - self::get_active_dependents_in_dependency_tree( $dependent ) - ); - } - - // Bail early if there are no dependents to deactivate. - if ( empty( $dependents_to_deactivate ) ) { - return; - } - - $dependents_to_deactivate = array_unique( $dependents_to_deactivate ); - - deactivate_plugins( $dependents_to_deactivate ); - set_site_transient( 'wp_plugin_dependencies_deactivated_plugins', $dependents_to_deactivate, 10 ); - } - /** * Gets the filepath of installed dependencies. * If a dependency is not installed, the filepath defaults to false. @@ -710,6 +607,10 @@ class WP_Plugin_Dependencies { return self::$dependency_filepaths; } + if ( null === self::$dependency_slugs ) { + return array(); + } + self::$dependency_filepaths = array(); $plugin_dirnames = self::get_plugin_dirnames(); @@ -846,6 +747,10 @@ class WP_Plugin_Dependencies { return self::$circular_dependencies_pairs; } + if ( null === self::$dependencies ) { + return array(); + } + self::$circular_dependencies_slugs = array(); self::$circular_dependencies_pairs = array(); diff --git a/wp-includes/version.php b/wp-includes/version.php index 6f19168282..3e6b5c0542 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.5-beta1-57657'; +$wp_version = '6.5-beta1-57658'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. diff --git a/wp-settings.php b/wp-settings.php index 2772568dee..fe2aef2479 100644 --- a/wp-settings.php +++ b/wp-settings.php @@ -388,6 +388,7 @@ require ABSPATH . WPINC . '/script-modules.php'; require ABSPATH . WPINC . '/interactivity-api/class-wp-interactivity-api.php'; require ABSPATH . WPINC . '/interactivity-api/class-wp-interactivity-api-directives-processor.php'; require ABSPATH . WPINC . '/interactivity-api/interactivity-api.php'; +require ABSPATH . WPINC . '/class-wp-plugin-dependencies.php'; wp_script_modules()->add_hooks(); wp_interactivity()->add_hooks(); @@ -419,12 +420,6 @@ wp_plugin_directory_constants(); $GLOBALS['wp_plugin_paths'] = array(); -// Load and initialize WP_Plugin_Dependencies. -require_once ABSPATH . WPINC . '/class-wp-plugin-dependencies.php'; -if ( ! defined( 'WP_RUN_CORE_TESTS' ) ) { - WP_Plugin_Dependencies::initialize(); -} - // Load must-use plugins. foreach ( wp_get_mu_plugins() as $mu_plugin ) { $_wp_plugin_file = $mu_plugin; @@ -499,85 +494,7 @@ if ( ! is_multisite() && wp_is_fatal_error_handler_enabled() ) { } // Load active plugins. -$all_plugin_data = get_option( 'plugin_data', array() ); -$failed_plugins = array(); -$plugins_dir_strlen = strlen( trailingslashit( WP_PLUGIN_DIR ) ); foreach ( wp_get_active_and_valid_plugins() as $plugin ) { - $plugin_file = substr( $plugin, $plugins_dir_strlen ); - - /* - * Skip any plugins that have not been added to the 'plugin_data' option yet. - * - * Some plugin files may be added locally and activated, but will not yet be - * added to the 'plugin_data' option. This causes the 'active_plugins' option - * and the 'plugin_data' option to be temporarily out of sync until the next - * call to `get_plugins()`. - */ - if ( isset( $all_plugin_data[ $plugin_file ] ) ) { - $plugin_headers = $all_plugin_data[ $plugin_file ]; - $errors = array(); - $requirements = array( - 'requires' => ! empty( $plugin_headers['RequiresWP'] ) ? $plugin_headers['RequiresWP'] : '', - 'requires_php' => ! empty( $plugin_headers['RequiresPHP'] ) ? $plugin_headers['RequiresPHP'] : '', - ); - $compatible_wp = is_wp_version_compatible( $requirements['requires'] ); - $compatible_php = is_php_version_compatible( $requirements['requires_php'] ); - - $php_update_message = '

    ' . sprintf( - /* translators: %s: URL to Update PHP page. */ - __( 'Learn more about updating PHP.' ), - esc_url( wp_get_update_php_url() ) - ); - - $annotation = wp_get_update_php_annotation(); - - if ( $annotation ) { - $php_update_message .= '

    ' . $annotation . ''; - } - - if ( ! $compatible_wp && ! $compatible_php ) { - $errors[] = sprintf( - /* translators: 1: Current WordPress version, 2: Current PHP version, 3: Plugin name, 4: Required WordPress version, 5: Required PHP version. */ - _x( 'Error: Current versions of WordPress (%1$s) and PHP (%2$s) do not meet minimum requirements for %3$s. The plugin requires WordPress %4$s and PHP %5$s.', 'plugin' ), - get_bloginfo( 'version' ), - PHP_VERSION, - $plugin_headers['Name'], - $requirements['requires'], - $requirements['requires_php'] - ) . $php_update_message; - } elseif ( ! $compatible_php ) { - $errors[] = sprintf( - /* translators: 1: Current PHP version, 2: Plugin name, 3: Required PHP version. */ - _x( 'Error: Current PHP version (%1$s) does not meet minimum requirements for %2$s. The plugin requires PHP %3$s.', 'plugin' ), - PHP_VERSION, - $plugin_headers['Name'], - $requirements['requires_php'] - ) . $php_update_message; - } elseif ( ! $compatible_wp ) { - $errors[] = sprintf( - /* translators: 1: Current WordPress version, 2: Plugin name, 3: Required WordPress version. */ - _x( 'Error: Current WordPress version (%1$s) does not meet minimum requirements for %2$s. The plugin requires WordPress %3$s.', 'plugin' ), - get_bloginfo( 'version' ), - $plugin_headers['Name'], - $requirements['requires'] - ); - } - - if ( ! empty( $errors ) ) { - $failed_plugins[ $plugin_file ] = ''; - foreach ( $errors as $error ) { - $failed_plugins[ $plugin_file ] .= wp_get_admin_notice( - $error, - array( - 'type' => 'error', - 'dismissible' => true, - ) - ); - } - continue; - } - } - wp_register_plugin_realpath( $plugin ); $_wp_plugin_file = $plugin; @@ -595,20 +512,6 @@ foreach ( wp_get_active_and_valid_plugins() as $plugin ) { } unset( $plugin, $_wp_plugin_file ); -if ( ! empty( $failed_plugins ) ) { - add_action( - 'admin_notices', - function () use ( $failed_plugins ) { - global $pagenow; - - if ( 'index.php' === $pagenow || 'plugins.php' === $pagenow ) { - echo implode( '', $failed_plugins ); - } - } - ); -} -unset( $failed_plugins ); - // Load pluggable functions. require ABSPATH . WPINC . '/pluggable.php'; require ABSPATH . WPINC . '/pluggable-deprecated.php';