Upgrade/Install: Introduce Plugin Dependencies.

Introduces a new "Requires Plugins" plugin header so that plugin developers can list the slugs of the plugins theirs depends on.

This will inform users of the requirements, and provide links to the WordPress.org Plugins Repository that they can click to install and activate the dependencies first.

Plugins whose requirements are not met cannot be installed or activated, and they will be deactivated automatically if their requirements become unmet.
Plugins that others rely on cannot be deactivated or deleted until their dependent plugins are deactivated or deleted.

In memory of Alex Mills and Alex King.
WordPress Remembers.

Props ahoereth, afragen, alanfuller, alexkingorg, amykamala, anonymized_10690803, apeatling, ashfame, atimmer, audrasjb, aristath, azaozz, batmoo, beaulebens, blobaugh, bobbingwide, boonebgorges, brianhenryie, chanthaboune, chrisdavidmiles, coolmann, costdev, courane01, danielbachhuber, davidperez, dd32, Denis-de-Bernardy, dingo_d, DJPaul, dougal, DrewAPicture, ethitter, filosofo, georgestephanis, giuseppemazzapica-1, goldenapples, griffinjt, hellofromTonya, husobj, ideag, jarednova, jbobich, jbrinley, jltallon, joedolson, johnciacia, johnjamesjacoby, joppuyo, jsmoriss, karmatosed, kebbet, knutsp, kraftbj, kraftner, kurtpayne, lkraav, logikal16, luisherranz, man4toman, markjaquith, matt, mbijon, megphillips91, mikeschinkel, mordauk, morehawes, mrwweb, mte90, mukesh27, mzaweb, nacin, norcross, nvwd, nwjames, obliviousharmony, ocean90, oglekler, paaljoachim, pauldewouters, pbaylies, pbiron, peterwilsoncc, Philipp15b, poena, pogidude, retlehs, rmccue, ryan, sabreuse, sc0ttkclark, scribu, sereedmedia, SergeyBiryukov, ShaneF, shidouhikari, soean, spacedmonkey, stephenh1988, swissspidy, taylorde, tazotodua, threadi, TimothyBlynJacobs, TJNowell, tollmanz, toscho, tropicalista, Viper007Bond, westi, whiteshadow, williamsba1, wpsmith, ZaneMatthew.
Fixes #22316.

git-svn-id: https://develop.svn.wordpress.org/trunk@57545 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Colin Stewart
2024-02-06 23:44:09 +00:00
parent 3eb7bd1b29
commit 2b08a77f5c
30 changed files with 4168 additions and 352 deletions
+108
View File
@@ -412,6 +412,12 @@ 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;
@@ -486,7 +492,91 @@ if ( ! is_multisite() && wp_is_fatal_error_handler_enabled() ) {
}
// Load active plugins.
$all_plugin_data = get_option( 'plugin_data', array() );
$failed_plugins = array();
$update_plugin_data = false;
foreach ( wp_get_active_and_valid_plugins() as $plugin ) {
$plugin_file = str_replace( trailingslashit( WP_PLUGIN_DIR ), '', $plugin );
if ( ! isset( $all_plugin_data[ $plugin_file ] ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
$all_plugin_data[ $plugin_file ] = get_plugin_data( WP_PLUGIN_DIR . "/$plugin_file" );
$update_plugin_data = true;
}
$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'] : '',
'requires_plugins' => ! empty( $plugin_headers['RequiresPlugins'] ) ? $plugin_headers['RequiresPlugins'] : '',
);
$compatible_wp = is_wp_version_compatible( $requirements['requires'] );
$compatible_php = is_php_version_compatible( $requirements['requires_php'] );
$dependencies_met = ! WP_Plugin_Dependencies::has_unmet_dependencies( $plugin_file );
$php_update_message = '</p><p>' . sprintf(
/* translators: %s: URL to Update PHP page. */
__( '<a href="%s">Learn more about updating PHP</a>.' ),
esc_url( wp_get_update_php_url() )
);
$annotation = wp_get_update_php_annotation();
if ( $annotation ) {
$php_update_message .= '</p><p><em>' . $annotation . '</em>';
}
if ( ! $dependencies_met ) {
$errors[] = sprintf(
/* translators: %s: The plugin's name. */
_x( '%s has unmet dependencies.', 'plugin' ),
$plugin_headers['Name']
);
}
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( '<strong>Error:</strong> 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( '<strong>Error:</strong> 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( '<strong>Error:</strong> 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;
@@ -504,6 +594,24 @@ foreach ( wp_get_active_and_valid_plugins() as $plugin ) {
}
unset( $plugin, $_wp_plugin_file );
if ( $update_plugin_data ) {
update_option( 'plugin_data', $all_plugin_data );
}
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';