WordPress.org

Make WordPress Core

Ticket #11861: 11861.mu.dropins.diff

File 11861.mu.dropins.diff, 17.3 KB (added by nacin, 4 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