WordPress.org

Make WordPress Core

Ticket #11861: 11861.mu.dropins.diff

File 11861.mu.dropins.diff, 17.3 KB (added by nacin, 8 years ago)

Exposes mu-plugins and drop-ins in admin area

  • wp-admin/plugins.php

     
    2727if ( empty($default_status) )
    2828        $default_status = 'all';
    2929$status = isset($_REQUEST['plugin_status']) ? $_REQUEST['plugin_status'] : $default_status;
    30 if ( !in_array($status, array('all', 'active', 'inactive', 'recent', 'upgrade', 'network', 'search')) )
     30if ( !in_array($status, array('all', 'active', 'inactive', 'recent', 'upgrade', 'network', 'mustuse', 'dropins', 'search')) )
    3131        $status = 'all';
    3232if ( $status != $default_status && 'search' != $status )
    3333        update_usermeta($current_user->ID, 'plugins_last_view', $status);
     
    345345$recently_activated = get_option('recently_activated', array());
    346346$upgrade_plugins = array();
    347347$network_plugins = array();
     348$mustuse_plugins = get_mu_plugins();
     349$dropins_plugins = get_dropins();
    348350
    349351set_transient( 'plugin_slugs', array_keys($all_plugins), 86400 );
    350352
     
    356358        update_option('recently_activated', $recently_activated);
    357359$current = get_site_transient( 'update_plugins' );
    358360
    359 foreach ( (array)$all_plugins as $plugin_file => $plugin_data) {
     361foreach ( array( 'all_plugins', 'mustuse_plugins', 'dropins_plugins' ) as $plugin_array_name) {
     362        foreach ( (array) $$plugin_array_name as $plugin_file => $plugin_data ) {
     363                // Translate, Apply Markup, Sanitize HTML
     364                $plugin_data = _get_plugin_data_markup_translate($plugin_file, $plugin_data, false, true);
     365                $$plugin_array_name[ $plugin_file ] = $plugin_data;
     366        }
     367}
     368unset( $plugin_array_name );
    360369
    361         // Translate, Apply Markup, Sanitize HTML
    362         $plugin_data = _get_plugin_data_markup_translate($plugin_file, $plugin_data, false, true);
    363         $all_plugins[ $plugin_file ] = $plugin_data;
    364 
     370foreach ( (array) $all_plugins as $plugin_file => $plugin_data) {
    365371        // Filter into individual sections
    366372        if ( is_plugin_active_for_network($plugin_file) && is_super_admin() ) {
    367373                $network_plugins[ $plugin_file ] = $plugin_data;
     
    386392$total_recent_plugins = count($recent_plugins);
    387393$total_upgrade_plugins = count($upgrade_plugins);
    388394$total_network_plugins = count($network_plugins);
     395$total_mustuse_plugins = count($mustuse_plugins);
     396$total_dropins_plugins = count($dropins_plugins);
    389397
    390398//Searching.
    391399if ( isset($_GET['s']) ) {
     
    449457 */
    450458function print_plugins_table($plugins, $context = '') {
    451459        global $page;
     460        $checkbox = ! in_array( $context, array( 'mustuse', 'dropins' ) ) ? '<input type="checkbox" />' : '';
    452461?>
    453462<table class="widefat" cellspacing="0" id="<?php echo $context ?>-plugins-table">
    454463        <thead>
    455464        <tr>
    456                 <th scope="col" class="manage-column check-column"><input type="checkbox" /></th>
     465                <th scope="col" class="manage-column check-column"><?php echo $checkbox; ?></th>
    457466                <th scope="col" class="manage-column"><?php _e('Plugin'); ?></th>
    458467                <th scope="col" class="manage-column"><?php _e('Description'); ?></th>
    459468        </tr>
     
    461470
    462471        <tfoot>
    463472        <tr>
    464                 <th scope="col" class="manage-column check-column"><input type="checkbox" /></th>
     473                <th scope="col" class="manage-column check-column"><?php echo $checkbox; ?></th>
    465474                <th scope="col" class="manage-column"><?php _e('Plugin'); ?></th>
    466475                <th scope="col" class="manage-column"><?php _e('Description'); ?></th>
    467476        </tr>
     
    477486        }
    478487        foreach ( (array)$plugins as $plugin_file => $plugin_data) {
    479488                $actions = array();
    480                 $is_active = is_plugin_active($plugin_file);
    481                 $is_active_for_network = is_plugin_active_for_network($plugin_file);
     489               
     490                if ( 'mustuse' == $context ) {
     491                        $is_active = true;
     492                        $actions = array();
     493                } elseif ( 'dropins' == $context ) {
     494                        $actions = array();
     495                        $dropins = _get_dropins();
     496                        $plugin_name = $plugin_file;
     497                        if ( $plugin_file != $plugin_data['Name'] )
     498                                $plugin_name .= '<br/>' . $plugin_data['Name'];
     499                        if ( true === ( $dropins[ $plugin_file ][1] ) ) { // Doesn't require a constant
     500                                $is_active = true;
     501                                $description = '<p><strong>' . $dropins[ $plugin_file ][0] . '</strong></p>';
     502                        } elseif ( constant( $dropins[ $plugin_file ][1] ) ) { // Constant is true
     503                                $is_active = true;
     504                                $description = '<p><strong>' . $dropins[ $plugin_file ][0] . '</strong></p>';
     505                        } else {
     506                                $is_active = false;
     507                                $description = '<strong>' . $dropins[ $plugin_file ][0] . ' <span class="attention">' . __('Inactive:') . '</span></strong> ' . sprintf( __( 'Requires <code>%s</code> in <code>wp-config.php</code>.' ), "define('" . $dropins[ $plugin_file ][1] . "', true);" ) . '</p>';
     508                        }
     509                        $description .= '<p>' . $plugin_data['Description'] . '</p>';
     510                } else {
     511                        $is_active = is_plugin_active( $plugin_file );
     512                        $is_active_for_network = is_plugin_active_for_network( $plugin_file );
    482513
    483                 if ( $is_active_for_network && !is_super_admin() )
    484                         continue;
     514                        if ( $is_active_for_network && !is_super_admin() )
     515                                continue;
    485516
    486                 if ( $is_active ) {
    487                         if ( $is_active_for_network ) {
    488                                 if ( is_super_admin() )
    489                                         $actions[] = '<a href="' . wp_nonce_url('plugins.php?action=deactivate&amp;networkwide=1&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page, 'deactivate-plugin_' . $plugin_file) . '" title="' . __('Deactivate this plugin') . '">' . __('Network Deactivate') . '</a>';
     517                        if ( $is_active ) {
     518                                if ( $is_active_for_network ) {
     519                                        if ( is_super_admin() )
     520                                                $actions[] = '<a href="' . wp_nonce_url('plugins.php?action=deactivate&amp;networkwide=1&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page, 'deactivate-plugin_' . $plugin_file) . '" title="' . __('Deactivate this plugin') . '">' . __('Network Deactivate') . '</a>';
     521                                } else {
     522                                        $actions[] = '<a href="' . wp_nonce_url('plugins.php?action=deactivate&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page, 'deactivate-plugin_' . $plugin_file) . '" title="' . __('Deactivate this plugin') . '">' . __('Deactivate') . '</a>';
     523                                }
    490524                        } else {
    491                                 $actions[] = '<a href="' . wp_nonce_url('plugins.php?action=deactivate&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page, 'deactivate-plugin_' . $plugin_file) . '" title="' . __('Deactivate this plugin') . '">' . __('Deactivate') . '</a>';
     525                                $actions[] = '<a href="' . wp_nonce_url('plugins.php?action=activate&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page, 'activate-plugin_' . $plugin_file) . '" title="' . __('Activate this plugin') . '" class="edit">' . __('Activate') . '</a>';
     526                                if ( is_multisite() && is_super_admin() )
     527                                        $actions[] = '<a href="' . wp_nonce_url('plugins.php?action=activate&amp;networkwide=1&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page, 'activate-plugin_' . $plugin_file) . '" title="' . __('Activate this plugin for all sites in this network') . '" class="edit">' . __('Network Activate') . '</a>';
    492528                        }
    493                 } else {
    494                         $actions[] = '<a href="' . wp_nonce_url('plugins.php?action=activate&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page, 'activate-plugin_' . $plugin_file) . '" title="' . __('Activate this plugin') . '" class="edit">' . __('Activate') . '</a>';
    495                         if ( is_multisite() && is_super_admin() )
    496                                 $actions[] = '<a href="' . wp_nonce_url('plugins.php?action=activate&amp;networkwide=1&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page, 'activate-plugin_' . $plugin_file) . '" title="' . __('Activate this plugin for all sites in this network') . '" class="edit">' . __('Network Activate') . '</a>';
    497                 }
    498529
    499                 if ( !is_multisite() && current_user_can('edit_plugins') && is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) )
    500                         $actions[] = '<a href="plugin-editor.php?file=' . $plugin_file . '" title="' . __('Open this file in the Plugin Editor') . '" class="edit">' . __('Edit') . '</a>';
     530                        if ( !is_multisite() && current_user_can('edit_plugins') && is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) )
     531                                $actions[] = '<a href="plugin-editor.php?file=' . $plugin_file . '" title="' . __('Open this file in the Plugin Editor') . '" class="edit">' . __('Edit') . '</a>';
    501532
    502                 if ( ! $is_active && current_user_can('delete_plugins') )
    503                         $actions[] = '<a href="' . wp_nonce_url('plugins.php?action=delete-selected&amp;checked[]=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page, 'bulk-manage-plugins') . '" title="' . __('Delete this plugin') . '" class="delete">' . __('Delete') . '</a>';
     533                        if ( ! $is_active && current_user_can('delete_plugins') )
     534                                $actions[] = '<a href="' . wp_nonce_url('plugins.php?action=delete-selected&amp;checked[]=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page, 'bulk-manage-plugins') . '" title="' . __('Delete this plugin') . '" class="delete">' . __('Delete') . '</a>';
    504535
     536                }
     537
    505538                $actions = apply_filters( 'plugin_action_links', $actions, $plugin_file, $plugin_data, $context );
    506539                $actions = apply_filters( "plugin_action_links_$plugin_file", $actions, $plugin_file, $plugin_data, $context );
    507                 $action_count = count($actions);
     540
    508541                $class = $is_active ? 'active' : 'inactive';
     542                $checkbox = in_array( $context, array( 'mustuse', 'dropins' ) ) ? '' : "<input type='checkbox' name='checked[]' value='" . esc_attr($plugin_file) . "' />";
     543                if ( 'dropins' != $context ) {
     544                        $description = '<p>' . $plugin_data['Description'] . '</p>';
     545                        $plugin_name = $plugin_data['Name'];
     546                }
    509547                echo "
    510548        <tr class='$class'>
    511                 <th scope='row' class='check-column'><input type='checkbox' name='checked[]' value='" . esc_attr($plugin_file) . "' /></th>
    512                 <td class='plugin-title'><strong>{$plugin_data['Name']}</strong></td>
    513                 <td class='desc'><p>{$plugin_data['Description']}</p></td>
     549                <th scope='row' class='check-column'>$checkbox</th>
     550                <td class='plugin-title'><strong>$plugin_name</strong></td>
     551                <td class='desc'>$description</td>
    514552        </tr>
    515553        <tr class='$class second'>
    516554                <td></td>
     
    554592 * @param string $context
    555593 */
    556594function print_plugin_actions($context, $field_name = 'action' ) {
     595        if ( in_array( $context, array( 'mustuse', 'dropins' ) ) )
     596                return;
    557597?>
    558598        <div class="alignleft actions">
    559599                <select name="<?php echo $field_name; ?>">
     
    616656        $class = ( 'network' == $status ) ? ' class="current"' : '';
    617657        $status_links[] = "<li><a href='plugins.php?plugin_status=network' $class>" . sprintf( _n( 'Network <span class="count">(%s)</span>', 'Network <span class="count">(%s)</span>', $total_network_plugins ), number_format_i18n( $total_network_plugins ) ) . '</a>';
    618658}
     659if ( ! empty($mustuse_plugins) ) {
     660        $class = ( 'mustuse' == $status ) ? ' class="current"' : '';
     661        $status_links[] = "<li><a href='plugins.php?plugin_status=mustuse' $class>" . sprintf( _n( 'Must-Use <span class="count">(%s)</span>', 'Must-Use <span class="count">(%s)</span>', $total_mustuse_plugins ), number_format_i18n( $total_mustuse_plugins ) ) . '</a>';
     662}
     663if ( ! empty($dropins_plugins) ) {
     664        $class = ( 'dropins' == $status ) ? ' class="current"' : '';
     665        $status_links[] = "<li><a href='plugins.php?plugin_status=dropins' $class>" . sprintf( _n( 'Drop-ins <span class="count">(%s)</span>', 'Drop-ins <span class="count">(%s)</span>', $total_dropins_plugins ), number_format_i18n( $total_dropins_plugins ) ) . '</a>';
     666}
    619667if ( ! empty($upgrade_plugins) ) {
    620668        $class = ( 'upgrade' == $status ) ? ' class="current"' : '';
    621669        $status_links[] = "<li><a href='plugins.php?plugin_status=upgrade' $class>" . sprintf( _n( 'Upgrade Available <span class="count">(%s)</span>', 'Upgrade Available <span class="count">(%s)</span>', $total_upgrade_plugins ), number_format_i18n( $total_upgrade_plugins ) ) . '</a>';
     
    630678?>
    631679</ul>
    632680
     681<?php
     682if ( 'mustuse' == $status )
     683        echo '<div class="clear"><p>' . __( 'Files in the <code>wp-content/mu-plugins</code> directory are executed automatically.' ) . '</p>';
     684elseif ( 'dropins' == $status )
     685        echo '<div class="clear"><p>' . __( 'Drop-ins are advanced plugins in the <code>wp-content</code> directory that replace WordPress functionality when present.' ) . '</p>';
     686
     687if ( ! in_array( $status, array( 'mustuse', 'dropins' ) ) || $page_links ) :
     688?>
    633689<div class="tablenav">
    634690<?php
    635691if ( $page_links )
     
    640696</div>
    641697<div class="clear"></div>
    642698<?php
    643         if ( $total_this_page > $plugins_per_page )
    644                 $plugins = array_slice($plugins, $start, $plugins_per_page);
     699endif;
    645700
    646         print_plugins_table($plugins, $status);
     701if ( $total_this_page > $plugins_per_page )
     702        $plugins = array_slice($plugins, $start, $plugins_per_page);
     703
     704print_plugins_table($plugins, $status);
     705
     706if ( ! in_array( $status, array( 'mustuse', 'dropins' ) ) || $page_links ) :
    647707?>
    648708<div class="tablenav">
    649709<?php
     
    653713print_plugin_actions($status, "action2");
    654714?>
    655715</div>
     716<?php endif; ?>
    656717</form>
    657718
    658719<?php if ( empty($all_plugins) ) : ?>
  • wp-admin/includes/plugin.php

     
    251251}
    252252
    253253/**
     254 * Check the mu-plugins directory and retrieve all mu-plugin files with any plugin data.
     255 *
     256 * WordPress only includes mu-plugin files in the base mu-plugins directory (wp-content/mu-plugins).
     257 *
     258 * @since 3.0.0
     259 * @return array Key is the mu-plugin file path and the value is an array of the mu-plugin data.
     260 */
     261function get_mu_plugins() {
     262        $wp_plugins = array();
     263        // Files in wp-content/mu-plugins directory
     264        $plugin_files = array();
     265
     266        if ( ! is_dir( WPMU_PLUGIN_DIR ) )
     267                return $wp_plugins;
     268        if ( $plugins_dir = @ opendir( WPMU_PLUGIN_DIR ) ) {
     269                while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
     270                        if ( substr( $file, -4 ) == '.php' )
     271                                $plugin_files[] = $file;
     272                }
     273        }
     274
     275        @closedir( $plugins_dir );
     276
     277        if ( !$plugins_dir || empty($plugin_files) )
     278                return $wp_plugins;
     279
     280        foreach ( $plugin_files as $plugin_file ) {
     281                if ( !is_readable( WPMU_PLUGIN_DIR . "/$plugin_file" ) )
     282                        continue;
     283
     284                $plugin_data = get_plugin_data( WPMU_PLUGIN_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached.
     285
     286                if ( empty ( $plugin_data['Name'] ) )
     287                        $plugin_data['Name'] = $plugin_file;
     288
     289                $wp_plugins[ $plugin_file ] = $plugin_data;
     290        }
     291
     292        if ( isset( $wp_plugins['index.php'] ) && filesize( WPMU_PLUGIN_DIR . '/index.php') <= 30 ) // silence is golden
     293                unset( $wp_plugins['index.php'] );
     294
     295        uasort( $wp_plugins, create_function( '$a, $b', 'return strnatcasecmp( $a["Name"], $b["Name"] );' ));
     296
     297        return $wp_plugins;
     298}
     299
     300/**
     301 * Check the wp-content directory and retrieve all drop-ins with any plugin data.
     302 *
     303 * @since 3.0.0
     304 * @return array Key is the file path and the value is an array of the plugin data.
     305 */
     306function get_dropins() {
     307        $dropins = array();
     308        $plugin_files = array();
     309
     310        $_dropins = _get_dropins();
     311
     312        // These exist in the wp-content directory
     313        if ( $plugins_dir = @ opendir( WP_CONTENT_DIR ) ) {
     314                while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
     315                        if ( isset( $_dropins[ $file ] ) )
     316                                $plugin_files[] = $file;
     317                        }
     318        }
     319
     320        @closedir( $plugins_dir );
     321
     322        if ( !$plugins_dir || empty($plugin_files) )
     323                        return $dropins;
     324
     325        foreach ( $plugin_files as $plugin_file ) {
     326                        if ( !is_readable( WP_CONTENT_DIR . "/$plugin_file" ) )
     327                                        continue;
     328                        $plugin_data = get_plugin_data( WP_CONTENT_DIR . "/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached.
     329                        if ( empty ( $plugin_data['Name'] ) )
     330                                $plugin_data['Name'] = $plugin_file;
     331                        $dropins[ $plugin_file ] = $plugin_data;
     332        }
     333
     334        uksort( $dropins, create_function( '$a, $b', 'return strnatcasecmp( $a, $b );' ));
     335
     336        return $dropins;
     337}
     338
     339/**
     340 * Returns drop-ins that WordPress uses.
     341 *
     342 * Includes Multisite drop-ins only when is_multisite()
     343 *
     344 * @since 3.0.0
     345 * @return array Key is file name. The value is an array, with the first value the
     346 *      purpose of the drop-in and the second value the name of the constant that must be
     347 *      true for the drop-in to be used, or true if no constant is required.
     348 */
     349function _get_dropins() {
     350        $dropins = array(
     351                'advanced-cache.php' => array( __( 'Advanced caching plugin.'       ), 'WP_CACHE' ), // WP_CACHE
     352                'db.php'             => array( __( 'Custom database class.'         ), true ), // auto on load
     353                'db-error.php'       => array( __( 'Custom database error message.' ), true ), // auto on error
     354                'install.php'        => array( __( 'Custom install script.'         ), true ), // auto on install
     355                'maintenance.php'    => array( __( 'Custom maintenance message.'    ), true ), // auto on maintenance
     356                'object-cache.php'   => array( __( 'External object cache.'         ), true ), // auto on load
     357        );
     358
     359        if ( is_multisite() ) {
     360                $dropins['sunrise.php'       ] = array( __( 'Executed before Multisite is loaded.' ), 'SUNRISE' ); // SUNRISE
     361                $dropins['blog-deleted.php'  ] = array( __( 'Custom blog deleted message.'   ), true ); // auto on deleted blog
     362                $dropins['blog-inactive.php' ] = array( __( 'Custom blog inactive message.'  ), true ); // auto on inactive blog
     363                $dropins['blog-suspended.php'] = array( __( 'Custom blog suspended message.' ), true ); // auto on archived or spammed blog
     364        }
     365
     366        return $dropins;
     367}
     368
     369/**
    254370 * Check whether the plugin is active by checking the active_plugins list.
    255371 *
    256372 * @since 2.5.0