<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[35151] trunk/src/wp-admin: Include network-active plugins and inactive network-only plugins on the Plugins listing screen for individual sites on Multisite.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/35151">35151</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/35151","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>johnbillion</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2015-10-13 22:11:36 +0000 (Tue, 13 Oct 2015)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Include network-active plugins and inactive network-only plugins on the Plugins listing screen for individual sites on Multisite.

These plugins are only shown to users with the `manage_network_plugins` capability, which is Super Admins by default. This new feature lowers the blood pressure of Super Admins who may browse or search the Plugins listing screen of an individual site, having forgotten that a particular plugin is network-active. Showing inactive network-only plugins here also reduces friction when searching the Plugins listing screen on individual sites.

This change introduces a `show_network_active_plugins` filter which controls whether the network-active plugins and inactive network-only plugins are shown. This can be used to enable this functionality for regular site admininstrators, or, indeed, to disable this functionality for Super Admins.

Fixes <a href="https://core.trac.wordpress.org/ticket/20104">#20104</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpadmincsslisttablescss">trunk/src/wp-admin/css/list-tables.css</a></li>
<li><a href="#trunksrcwpadminincludesclasswppluginslisttablephp">trunk/src/wp-admin/includes/class-wp-plugins-list-table.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpadmincsslisttablescss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/list-tables.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/list-tables.css    2015-10-13 21:35:43 UTC (rev 35150)
+++ trunk/src/wp-admin/css/list-tables.css      2015-10-13 22:11:36 UTC (rev 35151)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -881,6 +881,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">        padding: 2px 0 0;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.row-actions .network_only,
+.row-actions .network_active {
+       color: #000;
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> tr:hover .row-actions,
</span><span class="cx" style="display: block; padding: 0 10px"> .mobile .row-actions,
</span><span class="cx" style="display: block; padding: 0 10px"> .row-actions.visible,
</span></span></pre></div>
<a id="trunksrcwpadminincludesclasswppluginslisttablephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/class-wp-plugins-list-table.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/class-wp-plugins-list-table.php       2015-10-13 21:35:43 UTC (rev 35150)
+++ trunk/src/wp-admin/includes/class-wp-plugins-list-table.php 2015-10-13 22:11:36 UTC (rev 35151)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -127,6 +127,24 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if ( ! $screen->in_admin( 'network' ) ) {
+                       $show = current_user_can( 'manage_network_plugins' );
+                       /**
+                        * Filter whether to display network-active plugins alongside plugins active for the current site.
+                        *
+                        * This also controls the display of inactive network-only plugins (plugins with
+                        * "Network: true" in the plugin header).
+                        *
+                        * Plugins cannot be network-activated or network-deactivated from this screen.
+                        *
+                        * @since 4.4.0
+                        *
+                        * @param bool $show Whether to show network-active plugins. Default is whether the current
+                        *                   user can manage network plugins (ie. a Super Admin).
+                        */
+                       $show_network_active = apply_filters( 'show_network_active_plugins', $show );
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 set_transient( 'plugin_slugs', array_keys( $plugins['all'] ), DAY_IN_SECONDS );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ( $screen->in_admin( 'network' ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -168,11 +186,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Filter into individual sections
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( is_multisite() && ! $screen->in_admin( 'network' ) && is_network_only_plugin( $plugin_file ) && ! is_plugin_active( $plugin_file ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // On the non-network screen, filter out network-only plugins as long as they're not individually activated
-                               unset( $plugins['all'][ $plugin_file ] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ( $show_network_active ) {
+                                       // On the non-network screen, show inactive network-only plugins if allowed
+                                       $plugins['inactive'][ $plugin_file ] = $plugin_data;
+                               } else {
+                                       // On the non-network screen, filter out network-only plugins as long as they're not individually active
+                                       unset( $plugins['all'][ $plugin_file ] );
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                         } elseif ( ! $screen->in_admin( 'network' ) && is_plugin_active_for_network( $plugin_file ) ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // On the non-network screen, filter out network activated plugins
-                               unset( $plugins['all'][ $plugin_file ] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ( $show_network_active ) {
+                                       // On the non-network screen, show network-active plugins if allowed
+                                       $plugins['active'][ $plugin_file ] = $plugin_data;
+                               } else {
+                                       // On the non-network screen, filter out network-active plugins
+                                       unset( $plugins['all'][ $plugin_file ] );
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                         } elseif ( ( ! $screen->in_admin( 'network' ) && is_plugin_active( $plugin_file ) )
</span><span class="cx" style="display: block; padding: 0 10px">                                || ( $screen->in_admin( 'network' ) && is_plugin_active_for_network( $plugin_file ) ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                // On the non-network screen, populate the active list with plugins that are individually activated
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -487,10 +515,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( $plugin_data['Description'] )
</span><span class="cx" style="display: block; padding: 0 10px">                                $description .= '<p>' . $plugin_data['Description'] . '</p>';
</span><span class="cx" style="display: block; padding: 0 10px">                } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ( $screen->in_admin( 'network' ) )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ( $screen->in_admin( 'network' ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $is_active = is_plugin_active_for_network( $plugin_file );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        else
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $restrict_network_active = false;
+                               $restrict_network_only = false;
+                       } else {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $is_active = is_plugin_active( $plugin_file );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                $restrict_network_active = ( is_multisite() && is_plugin_active_for_network( $plugin_file ) );
+                               $restrict_network_only = ( is_multisite() && is_network_only_plugin( $plugin_file ) && ! $is_active );
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( $screen->in_admin( 'network' ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                                if ( $is_active ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -509,7 +542,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                        } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ( $is_active ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ( $restrict_network_active ) {
+                                       $actions = array(
+                                               'network_active' => __( 'Network Active' ),
+                                       );
+                               } elseif ( $restrict_network_only ) {
+                                       $actions = array(
+                                               'network_only' => __( 'Network Only' ),
+                                       );
+                               } elseif ( $is_active ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         /* translators: %s: plugin name */
</span><span class="cx" style="display: block; padding: 0 10px">                                        $actions['deactivate'] = '<a href="' . wp_nonce_url( 'plugins.php?action=deactivate&amp;plugin=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'deactivate-plugin_' . $plugin_file ) . '" aria-label="' . esc_attr( sprintf( __( 'Deactivate %s' ), $plugin_data['Name'] ) ) . '">' . __( 'Deactivate' ) . '</a>';
</span><span class="cx" style="display: block; padding: 0 10px">                                } else {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -613,7 +654,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $class = $is_active ? 'active' : 'inactive';
</span><span class="cx" style="display: block; padding: 0 10px">                $checkbox_id =  "checkbox_" . md5($plugin_data['Name']);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( in_array( $status, array( 'mustuse', 'dropins' ) ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( $restrict_network_active || $restrict_network_only || in_array( $status, array( 'mustuse', 'dropins' ) ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         $checkbox = '';
</span><span class="cx" style="display: block; padding: 0 10px">                } else {
</span><span class="cx" style="display: block; padding: 0 10px">                        $checkbox = "<label class='screen-reader-text' for='" . $checkbox_id . "' >" . sprintf( __( 'Select %s' ), $plugin_data['Name'] ) . "</label>"
</span></span></pre>
</div>
</div>

</body>
</html>