diff --git a/wp-admin/includes/plugin.php b/wp-admin/includes/plugin.php index 9fe8ec402e..97b982aafa 100644 --- a/wp-admin/includes/plugin.php +++ b/wp-admin/includes/plugin.php @@ -265,6 +265,122 @@ function get_plugins($plugin_folder = '') { return $wp_plugins; } +/** + * Check the mu-plugins directory and retrieve all mu-plugin files with any plugin data. + * + * WordPress only includes mu-plugin files in the base mu-plugins directory (wp-content/mu-plugins). + * + * @since 3.0.0 + * @return array Key is the mu-plugin file path and the value is an array of the mu-plugin data. + */ +function get_mu_plugins() { + $wp_plugins = array(); + // Files in wp-content/mu-plugins directory + $plugin_files = array(); + + if ( ! is_dir( WPMU_PLUGIN_DIR ) ) + return $wp_plugins; + if ( $plugins_dir = @ opendir( WPMU_PLUGIN_DIR ) ) { + while ( ( $file = readdir( $plugins_dir ) ) !== false ) { + if ( substr( $file, -4 ) == '.php' ) + $plugin_files[] = $file; + } + } + + @closedir( $plugins_dir ); + + if ( !$plugins_dir || empty($plugin_files) ) + return $wp_plugins; + + foreach ( $plugin_files as $plugin_file ) { + if ( !is_readable( WPMU_PLUGIN_DIR . "/$plugin_file" ) ) + continue; + + $plugin_data = get_plugin_data( WPMU_PLUGIN_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. + + if ( empty ( $plugin_data['Name'] ) ) + $plugin_data['Name'] = $plugin_file; + + $wp_plugins[ $plugin_file ] = $plugin_data; + } + + if ( isset( $wp_plugins['index.php'] ) && filesize( WPMU_PLUGIN_DIR . '/index.php') <= 30 ) // silence is golden + unset( $wp_plugins['index.php'] ); + + uasort( $wp_plugins, create_function( '$a, $b', 'return strnatcasecmp( $a["Name"], $b["Name"] );' )); + + return $wp_plugins; +} + +/** + * Check the wp-content directory and retrieve all drop-ins with any plugin data. + * + * @since 3.0.0 + * @return array Key is the file path and the value is an array of the plugin data. + */ +function get_dropins() { + $dropins = array(); + $plugin_files = array(); + + $_dropins = _get_dropins(); + + // These exist in the wp-content directory + if ( $plugins_dir = @ opendir( WP_CONTENT_DIR ) ) { + while ( ( $file = readdir( $plugins_dir ) ) !== false ) { + if ( isset( $_dropins[ $file ] ) ) + $plugin_files[] = $file; + } + } + + @closedir( $plugins_dir ); + + if ( !$plugins_dir || empty($plugin_files) ) + return $dropins; + + foreach ( $plugin_files as $plugin_file ) { + if ( !is_readable( WP_CONTENT_DIR . "/$plugin_file" ) ) + continue; + $plugin_data = get_plugin_data( WP_CONTENT_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached. + if ( empty ( $plugin_data['Name'] ) ) + $plugin_data['Name'] = $plugin_file; + $dropins[ $plugin_file ] = $plugin_data; + } + + uksort( $dropins, create_function( '$a, $b', 'return strnatcasecmp( $a, $b );' )); + + return $dropins; +} + +/** + * Returns drop-ins that WordPress uses. + * + * Includes Multisite drop-ins only when is_multisite() + * + * @since 3.0.0 + * @return array Key is file name. The value is an array, with the first value the + * purpose of the drop-in and the second value the name of the constant that must be + * true for the drop-in to be used, or true if no constant is required. + */ +function _get_dropins() { + $dropins = array( + 'advanced-cache.php' => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ), // WP_CACHE + 'db.php' => array( __( 'Custom database class.' ), true ), // auto on load + 'db-error.php' => array( __( 'Custom database error message.' ), true ), // auto on error + 'install.php' => array( __( 'Custom install script.' ), true ), // auto on install + 'maintenance.php' => array( __( 'Custom maintenance message.' ), true ), // auto on maintenance + 'object-cache.php' => array( __( 'External object cache.' ), true ), // auto on load + ); + + if ( is_multisite() ) { + $dropins['sunrise.php' ] = array( __( 'Executed before Multisite is loaded.' ), 'SUNRISE' ); // SUNRISE + $dropins['blog-deleted.php' ] = array( __( 'Custom blog deleted message.' ), true ); // auto on deleted blog + $dropins['blog-inactive.php' ] = array( __( 'Custom blog inactive message.' ), true ); // auto on inactive blog + $dropins['blog-suspended.php'] = array( __( 'Custom blog suspended message.' ), true ); // auto on archived or spammed blog + } + + return $dropins; +} + /** * Check whether the plugin is active by checking the active_plugins list. * diff --git a/wp-admin/plugins.php b/wp-admin/plugins.php index d273275fb6..02dab63c2b 100644 --- a/wp-admin/plugins.php +++ b/wp-admin/plugins.php @@ -27,7 +27,7 @@ $default_status = get_user_option('plugins_last_view'); if ( empty($default_status) ) $default_status = 'all'; $status = isset($_REQUEST['plugin_status']) ? $_REQUEST['plugin_status'] : $default_status; -if ( !in_array($status, array('all', 'active', 'inactive', 'recent', 'upgrade', 'network', 'search')) ) +if ( !in_array($status, array('all', 'active', 'inactive', 'recent', 'upgrade', 'network', 'mustuse', 'dropins', 'search')) ) $status = 'all'; if ( $status != $default_status && 'search' != $status ) update_usermeta($current_user->ID, 'plugins_last_view', $status); @@ -365,6 +365,8 @@ $recent_plugins = array(); $recently_activated = get_option('recently_activated', array()); $upgrade_plugins = array(); $network_plugins = array(); +$mustuse_plugins = get_mu_plugins(); +$dropins_plugins = get_dropins(); set_transient( 'plugin_slugs', array_keys($all_plugins), 86400 ); @@ -376,12 +378,16 @@ if ( $recently_activated != get_option('recently_activated') ) //If array change update_option('recently_activated', $recently_activated); $current = get_site_transient( 'update_plugins' ); -foreach ( (array)$all_plugins as $plugin_file => $plugin_data) { - - // Translate, Apply Markup, Sanitize HTML - $plugin_data = _get_plugin_data_markup_translate($plugin_file, $plugin_data, false, true); - $all_plugins[ $plugin_file ] = $plugin_data; +foreach ( array( 'all_plugins', 'mustuse_plugins', 'dropins_plugins' ) as $plugin_array_name) { + foreach ( (array) $$plugin_array_name as $plugin_file => $plugin_data ) { + // Translate, Apply Markup, Sanitize HTML + $plugin_data = _get_plugin_data_markup_translate($plugin_file, $plugin_data, false, true); + $$plugin_array_name[ $plugin_file ] = $plugin_data; + } +} +unset( $plugin_array_name ); +foreach ( (array) $all_plugins as $plugin_file => $plugin_data) { // Filter into individual sections if ( is_plugin_active_for_network($plugin_file) && is_super_admin() ) { $network_plugins[ $plugin_file ] = $plugin_data; @@ -406,6 +412,8 @@ $total_active_plugins = count($active_plugins); $total_recent_plugins = count($recent_plugins); $total_upgrade_plugins = count($upgrade_plugins); $total_network_plugins = count($network_plugins); +$total_mustuse_plugins = count($mustuse_plugins); +$total_dropins_plugins = count($dropins_plugins); //Searching. if ( isset($_GET['s']) ) { @@ -469,11 +477,12 @@ $page_links_text = sprintf( '' . __( 'Displaying %s */ function print_plugins_table($plugins, $context = '') { global $page; + $checkbox = ! in_array( $context, array( 'mustuse', 'dropins' ) ) ? '' : ''; ?> - + @@ -481,7 +490,7 @@ function print_plugins_table($plugins, $context = '') { - + @@ -497,43 +506,72 @@ function print_plugins_table($plugins, $context = '') { } foreach ( (array)$plugins as $plugin_file => $plugin_data) { $actions = array(); - $is_active_for_network = is_plugin_active_for_network($plugin_file); - $is_active = $is_active_for_network || is_plugin_active( $plugin_file ); - - if ( $is_active_for_network && !is_super_admin() ) - continue; - - if ( $is_active ) { - if ( $is_active_for_network ) { - if ( is_super_admin() ) - $actions[] = '' . __('Network Deactivate') . ''; + if ( 'mustuse' == $context ) { + $is_active = true; + } elseif ( 'dropins' == $context ) { + $dropins = _get_dropins(); + $plugin_name = $plugin_file; + if ( $plugin_file != $plugin_data['Name'] ) + $plugin_name .= '
' . $plugin_data['Name']; + if ( true === ( $dropins[ $plugin_file ][1] ) ) { // Doesn't require a constant + $is_active = true; + $description = '

' . $dropins[ $plugin_file ][0] . '

'; + } elseif ( constant( $dropins[ $plugin_file ][1] ) ) { // Constant is true + $is_active = true; + $description = '

' . $dropins[ $plugin_file ][0] . '

'; } else { - $actions[] = '' . __('Deactivate') . ''; + $is_active = false; + $description = '' . $dropins[ $plugin_file ][0] . ' ' . __('Inactive:') . ' ' . sprintf( __( 'Requires %s in wp-config.php.' ), "define('" . $dropins[ $plugin_file ][1] . "', true);" ) . '

'; } + $description .= '

' . $plugin_data['Description'] . '

'; } else { + $is_active_for_network = is_plugin_active_for_network($plugin_file); + $is_active = $is_active_for_network || is_plugin_active( $plugin_file ); + if ( $is_active_for_network && !is_super_admin() ) + continue; + + if ( $is_active ) { + if ( $is_active_for_network ) { + if ( is_super_admin() ) + $actions[] = '' . __('Network Deactivate') . ''; + } else { + $actions[] = '' . __('Deactivate') . ''; + } + } else { + $actions[] = '' . __('Activate') . ''; + if ( is_multisite() && is_super_admin() ) + $actions[] = '' . __('Network Activate') . ''; + } + if ( is_multisite() && is_network_only_plugin( $plugin_file ) ) $actions[] = '' . __('Network Only') . ''; else $actions[] = '' . __('Activate') . ''; if ( is_multisite() && is_super_admin() ) $actions[] = '' . __('Network Activate') . ''; + + if ( !is_multisite() && current_user_can('edit_plugins') && is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) ) + $actions[] = '' . __('Edit') . ''; + + if ( ! $is_active && current_user_can('delete_plugins') ) + $actions[] = '' . __('Delete') . ''; + } - if ( !is_multisite() && current_user_can('edit_plugins') && is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) ) - $actions[] = '' . __('Edit') . ''; - - if ( ! $is_active && current_user_can('delete_plugins') ) - $actions[] = '' . __('Delete') . ''; - $actions = apply_filters( 'plugin_action_links', $actions, $plugin_file, $plugin_data, $context ); $actions = apply_filters( "plugin_action_links_$plugin_file", $actions, $plugin_file, $plugin_data, $context ); - $action_count = count($actions); + $class = $is_active ? 'active' : 'inactive'; + $checkbox = in_array( $context, array( 'mustuse', 'dropins' ) ) ? '' : ""; + if ( 'dropins' != $context ) { + $description = '

' . $plugin_data['Description'] . '

'; + $plugin_name = $plugin_data['Name']; + } echo " - - - + + + @@ -577,6 +615,8 @@ function print_plugins_table($plugins, $context = '') { * @param string $context */ function print_plugin_actions($context, $field_name = 'action' ) { + if ( in_array( $context, array( 'mustuse', 'dropins' ) ) ) + return; ?>
{$plugin_data['Name']}

{$plugin_data['Description']}

$checkbox$plugin_name$description