Make WordPress Core


Ignore:
Timestamp:
02/06/2024 11:44:09 PM (3 weeks ago)
Author:
costdev
Message:

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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/plugin.php

    r57337 r57545  
    4646 * @since 5.3.0 Added support for `Requires at least` and `Requires PHP` headers.
    4747 * @since 5.8.0 Added support for `Update URI` header.
     48 * @since 6.5.0 Added support for `Requires Plugins` header.
    4849 *
    4950 * @param string $plugin_file Absolute path to the main plugin file.
     
    5455 *     Plugin data. Values will be empty if not supplied by the plugin.
    5556 *
    56  *     @type string $Name        Name of the plugin. Should be unique.
    57  *     @type string $PluginURI   Plugin URI.
    58  *     @type string $Version     Plugin version.
    59  *     @type string $Description Plugin description.
    60  *     @type string $Author      Plugin author's name.
    61  *     @type string $AuthorURI   Plugin author's website address (if set).
    62  *     @type string $TextDomain  Plugin textdomain.
    63  *     @type string $DomainPath  Plugin's relative directory path to .mo files.
    64  *     @type bool   $Network     Whether the plugin can only be activated network-wide.
    65  *     @type string $RequiresWP  Minimum required version of WordPress.
    66  *     @type string $RequiresPHP Minimum required version of PHP.
    67  *     @type string $UpdateURI   ID of the plugin for update purposes, should be a URI.
    68  *     @type string $Title       Title of the plugin and link to the plugin's site (if set).
    69  *     @type string $AuthorName  Plugin author's name.
     57 *     @type string $Name            Name of the plugin. Should be unique.
     58 *     @type string $PluginURI       Plugin URI.
     59 *     @type string $Version         Plugin version.
     60 *     @type string $Description     Plugin description.
     61 *     @type string $Author          Plugin author's name.
     62 *     @type string $AuthorURI       Plugin author's website address (if set).
     63 *     @type string $TextDomain      Plugin textdomain.
     64 *     @type string $DomainPath      Plugin's relative directory path to .mo files.
     65 *     @type bool   $Network         Whether the plugin can only be activated network-wide.
     66 *     @type string $RequiresWP      Minimum required version of WordPress.
     67 *     @type string $RequiresPHP     Minimum required version of PHP.
     68 *     @type string $UpdateURI       ID of the plugin for update purposes, should be a URI.
     69 *     @type string $RequiresPlugins Comma separated list of dot org plugin slugs.
     70 *     @type string $Title           Title of the plugin and link to the plugin's site (if set).
     71 *     @type string $AuthorName      Plugin author's name.
    7072 * }
    7173 */
     
    7375
    7476    $default_headers = array(
    75         'Name'        => 'Plugin Name',
    76         'PluginURI'   => 'Plugin URI',
    77         'Version'     => 'Version',
    78         'Description' => 'Description',
    79         'Author'      => 'Author',
    80         'AuthorURI'   => 'Author URI',
    81         'TextDomain'  => 'Text Domain',
    82         'DomainPath'  => 'Domain Path',
    83         'Network'     => 'Network',
    84         'RequiresWP'  => 'Requires at least',
    85         'RequiresPHP' => 'Requires PHP',
    86         'UpdateURI'   => 'Update URI',
     77        'Name'            => 'Plugin Name',
     78        'PluginURI'       => 'Plugin URI',
     79        'Version'         => 'Version',
     80        'Description'     => 'Description',
     81        'Author'          => 'Author',
     82        'AuthorURI'       => 'Author URI',
     83        'TextDomain'      => 'Text Domain',
     84        'DomainPath'      => 'Domain Path',
     85        'Network'         => 'Network',
     86        'RequiresWP'      => 'Requires at least',
     87        'RequiresPHP'     => 'Requires PHP',
     88        'UpdateURI'       => 'Update URI',
     89        'RequiresPlugins' => 'Requires Plugins',
    8790        // Site Wide Only is deprecated in favor of Network.
    88         '_sitewide'   => 'Site Wide Only',
     91        '_sitewide'       => 'Site Wide Only',
    8992    );
    9093
     
    331334    }
    332335
     336    $new_plugin_data = array();
    333337    foreach ( $plugin_files as $plugin_file ) {
    334338        if ( ! is_readable( "$plugin_root/$plugin_file" ) ) {
     
    343347        }
    344348
     349        $new_plugin_file = str_replace(
     350            trailingslashit( WP_PLUGIN_DIR ),
     351            '',
     352            "$plugin_root/$plugin_file"
     353        );
     354
     355        $new_plugin_data[ $new_plugin_file ]           = $plugin_data;
    345356        $wp_plugins[ plugin_basename( $plugin_file ) ] = $plugin_data;
    346357    }
     
    350361    $cache_plugins[ $plugin_folder ] = $wp_plugins;
    351362    wp_cache_set( 'plugins', $cache_plugins, 'plugins' );
     363    update_option( 'plugin_data', $new_plugin_data );
    352364
    353365    return $wp_plugins;
     
    952964
    953965    $plugin_translations = wp_get_installed_translations( 'plugins' );
     966    $all_plugin_data     = get_option( 'plugin_data', array() );
    954967
    955968    $errors = array();
     
    9961009            continue;
    9971010        }
     1011        unset( $all_plugin_data[ $plugin_file ] );
    9981012
    9991013        $plugin_slug = dirname( $plugin_file );
     
    10441058        return new WP_Error( 'could_not_remove_plugin', sprintf( $message, implode( ', ', $errors ) ) );
    10451059    }
     1060    update_option( 'plugin_data', $all_plugin_data );
    10461061
    10471062    return true;
     
    11151130 * Validates the plugin requirements for WordPress version and PHP version.
    11161131 *
    1117  * Uses the information from `Requires at least` and `Requires PHP` headers
     1132 * Uses the information from `Requires at least`, `Requires PHP` and `Requires Plugins` headers
    11181133 * defined in the plugin's main PHP file.
    11191134 *
     
    11221137 *              main PHP file, with `readme.txt` as a fallback.
    11231138 * @since 5.8.0 Removed support for using `readme.txt` as a fallback.
     1139 * @since 6.5.0 Added support for the 'Requires Plugins' header.
    11241140 *
    11251141 * @param string $plugin Path to the plugin file relative to the plugins directory.
     
    11301146
    11311147    $requirements = array(
    1132         'requires'     => ! empty( $plugin_headers['RequiresWP'] ) ? $plugin_headers['RequiresWP'] : '',
    1133         'requires_php' => ! empty( $plugin_headers['RequiresPHP'] ) ? $plugin_headers['RequiresPHP'] : '',
     1148        'requires'         => ! empty( $plugin_headers['RequiresWP'] ) ? $plugin_headers['RequiresWP'] : '',
     1149        'requires_php'     => ! empty( $plugin_headers['RequiresPHP'] ) ? $plugin_headers['RequiresPHP'] : '',
     1150        'requires_plugins' => ! empty( $plugin_headers['RequiresPlugins'] ) ? $plugin_headers['RequiresPlugins'] : '',
    11341151    );
    11351152
     
    11861203    }
    11871204
     1205    if ( WP_Plugin_Dependencies::has_unmet_dependencies( $plugin ) ) {
     1206        $dependencies       = WP_Plugin_Dependencies::get_dependencies( $plugin );
     1207        $unmet_dependencies = array();
     1208
     1209        foreach ( $dependencies as $dependency ) {
     1210            $dependency_file = WP_Plugin_Dependencies::get_dependency_filepath( $dependency );
     1211
     1212            if ( false === $dependency_file ) {
     1213                $unmet_dependencies['not_installed'][] = $dependency;
     1214            } elseif ( is_plugin_inactive( $dependency_file ) ) {
     1215                $unmet_dependencies['inactive'][] = $dependency;
     1216            }
     1217        }
     1218
     1219        return new WP_Error(
     1220            'plugin_missing_dependencies',
     1221            '<p>' . sprintf(
     1222                /* translators: %s: Plugin name. */
     1223                _x( '<strong>Error:</strong> %s requires plugins that are not installed or activated.', 'plugin' ),
     1224                $plugin_headers['Name']
     1225            ) . '</p>',
     1226            $unmet_dependencies
     1227        );
     1228    }
     1229
    11881230    return true;
    11891231}
Note: See TracChangeset for help on using the changeset viewer.