<!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" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { 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 #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#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>
<title>[12903] trunk/wp-admin:
  Integrate sitewide plugin handling into activate_plugins(),
  deactivate_plugins(), and plugins.php.</title>
</head>
<body>

<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.wordpress.org/changeset/12903">12903</a></dd>
<dt>Author</dt> <dd>ryan</dd>
<dt>Date</dt> <dd>2010-01-29 21:45:32 +0000 (Fri, 29 Jan 2010)</dd>
</dl>

<h3>Log Message</h3>
<pre>Integrate sitewide plugin handling into activate_plugins(), deactivate_plugins(), and plugins.php. fixes <a href="http://trac.wordpress.org/ticket/11767">#11767</a> see <a href="http://trac.wordpress.org/ticket/11644">#11644</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadminincludesmsphp">trunk/wp-admin/includes/ms.php</a></li>
<li><a href="#trunkwpadminincludespluginphp">trunk/wp-admin/includes/plugin.php</a></li>
<li><a href="#trunkwpadminpluginsphp">trunk/wp-admin/plugins.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadminincludesmsphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/ms.php (12902 => 12903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/ms.php        2010-01-29 19:29:31 UTC (rev 12902)
+++ trunk/wp-admin/includes/ms.php        2010-01-29 21:45:32 UTC (rev 12903)
</span><span class="lines">@@ -742,280 +742,38 @@
</span><span class="cx"> add_filter( 'wp_insert_post_data', 'avoid_blog_page_permalink_collision', 10, 2 );
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * activate_sitewide_plugin()
- *
- * Activates a plugin site wide (for all blogs on an installation)
</del><ins>+ * @deprecated
</ins><span class="cx">  */
</span><span class="cx"> function activate_sitewide_plugin() {
</span><del>-        if ( !isset( $_GET['sitewide'] ) )
-                return false;
-
-        /* Add the plugin to the list of sitewide active plugins */
-        $active_sitewide_plugins = maybe_unserialize( get_site_option( 'active_sitewide_plugins' ) );
-
-        /* Add the activated plugin to the list */
-        $active_sitewide_plugins[ $_GET['plugin'] ] = time();
-
-        /* Write the updated option to the DB */
-        if ( !update_site_option( 'active_sitewide_plugins', $active_sitewide_plugins ) )
-                return false;
-
-        return true;
</del><ins>+        return false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-// @todo Throws warning if plugin is not set.  Kinda janky.
-//add_action( 'activate_' . $_GET['plugin'], 'activate_sitewide_plugin' );
-
</del><span class="cx"> /**
</span><del>- * deactivate_sitewide_plugin()
- *
- * Deactivates a plugin site wide (for all blogs on an installation)
</del><ins>+ * @deprecated
</ins><span class="cx">  */
</span><span class="cx"> function deactivate_sitewide_plugin( $plugin = false ) {
</span><del>-        if ( !$plugin )
-                $plugin = $_GET['plugin'];
-
-        /* Get the active sitewide plugins */
-        $active_sitewide_plugins = (array) maybe_unserialize( get_site_option( 'active_sitewide_plugins' ) );
-
-        /* Remove the plugin we are deactivating from the list of active sitewide plugins */
-        foreach ( $active_sitewide_plugins as $plugin_file =&gt; $activation_time ) {
-                if ( $plugin == $plugin_file )
-                        unset( $active_sitewide_plugins[ $plugin_file ] );
-        }
-
-        if ( !update_site_option( 'active_sitewide_plugins', $active_sitewide_plugins ) )
-                wp_redirect( 'plugins.php?error=true' );
-
-        return true;
</del><ins>+        return;
</ins><span class="cx"> }
</span><del>-// @todo Throws warning if plugin is not set.  Kinda janky.
-//add_action( 'deactivate_' . $_GET['plugin'], 'deactivate_sitewide_plugin' );
-add_action( 'deactivate_invalid_plugin', 'deactivate_sitewide_plugin' );
</del><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * add_sitewide_activate_row()
- *
- * Adds the &quot;Activate plugin site wide&quot; row for each plugin in the inactive plugins list.
</del><ins>+ * @deprecated is_network_only_plugin()
</ins><span class="cx">  */
</span><del>-function add_sitewide_activate_row( $file, $plugin_data, $context ) {
-        if ( !is_super_admin() )
-                return false;
-
-        if ( 'sitewide-active' == $context )
-                return false;
-
-        if ( is_plugin_active( $file ) )
-                return false;
-
-        echo '&lt;tr&gt;&lt;td colspan=&quot;5&quot; style=&quot;background: #f5f5f5; text-align: right;&quot;&gt;';
-
-        echo '&lt;a href=&quot;' . wp_nonce_url( admin_url( 'plugins.php?action=activate&amp;amp;sitewide=1&amp;amp;plugin=' . $file ), 'activate-plugin_' . $file ) . '&quot; title=&quot;' . __( 'Activate this plugin for all blogs across the entire network' ) . '&quot;&gt;&amp;uarr; ' . sprintf( __( 'Activate %s Site Wide' ), strip_tags( $plugin_data[&quot;Title&quot;] ) ) . '&lt;/a&gt;';
-        echo '&lt;/td&gt;&lt;/tr&gt;';
-}
-add_action( 'after_plugin_row', 'add_sitewide_activate_row', 9, 3 );
-
-/**
- * is_wpmu_sitewide_plugin()
- *
- * Checks for &quot;Site Wide Only: true&quot; in the plugin header to see if this should
- * be activated as a site wide MU plugin.
- */
</del><span class="cx"> function is_wpmu_sitewide_plugin( $file ) {
</span><del>-        /* Open the plugin file for reading to check if this is a ms-plugin. */
-        $fp = @fopen( WP_PLUGIN_DIR . '/' . $file, 'r' );
-
-        /* Pull only the first 8kiB of the file in. */
-        $plugin_data = @fread( $fp, 8192 );
-
-        /* PHP will close file handle, but we are good citizens. */
-        @fclose($fp);
-
-        if ( preg_match( '|Site Wide Only:(.*)true$|mi', $plugin_data ) )
-                return true;
-
-        return false;
</del><ins>+        return is_network_only_plugin( $file );
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> /**
</span><del>- * list_activate_sitewide_plugins()
- *
- * Lists all the plugins that have been activated site wide.
</del><ins>+ * @deprecated
</ins><span class="cx">  */
</span><del>-function list_activate_sitewide_plugins() {
-        $all_plugins = get_plugins();
-
-        if ( !is_super_admin() )
-                return false;
-
-        $active_sitewide_plugins = maybe_unserialize( get_site_option( 'active_sitewide_plugins') );
-        $context = 'sitewide-active';
-
-        if ( $active_sitewide_plugins ) {
-?&gt;
-                &lt;h3&gt;&lt;?php _e( 'Currently Active Site Wide Plugins' ) ?&gt;&lt;/h3&gt;
-
-                &lt;p&gt;&lt;?php _e( 'Plugins that appear in the list below are activate for all blogs across this installation.' ) ?&gt;&lt;/p&gt;
-
-                &lt;table class=&quot;widefat&quot; cellspacing=&quot;0&quot; id=&quot;&lt;?php echo $context ?&gt;-plugins-table&quot;&gt;
-                        &lt;thead&gt;
-                                &lt;tr&gt;
-                                        &lt;th scope=&quot;col&quot; class=&quot;manage-column check-column&quot;&gt;&amp;nbsp;&lt;/th&gt;
-                                        &lt;th scope=&quot;col&quot; class=&quot;manage-column&quot;&gt;&lt;?php _e('Plugin'); ?&gt;&lt;/th&gt;
-                                        &lt;th scope=&quot;col&quot; class=&quot;manage-column&quot;&gt;&lt;?php _e('Description'); ?&gt;&lt;/th&gt;
-                                &lt;/tr&gt;
-                        &lt;/thead&gt;
-
-                        &lt;tfoot&gt;
-                                &lt;tr&gt;
-                                        &lt;th scope=&quot;col&quot; class=&quot;manage-column check-column&quot;&gt;&amp;nbsp;&lt;/th&gt;
-                                        &lt;th scope=&quot;col&quot; class=&quot;manage-column&quot;&gt;&lt;?php _e('Plugin'); ?&gt;&lt;/th&gt;
-                                        &lt;th scope=&quot;col&quot; class=&quot;manage-column&quot;&gt;&lt;?php _e('Description'); ?&gt;&lt;/th&gt;
-                                &lt;/tr&gt;
-                        &lt;/tfoot&gt;
-
-                        &lt;tbody class=&quot;plugins&quot;&gt;
-                &lt;?php
-                        foreach ( (array) $active_sitewide_plugins as $plugin_file =&gt; $activated_time ) {
-                                $action_links = array();
-                                $action_links[] = '&lt;a href=&quot;' . wp_nonce_url( 'plugins.php?action=deactivate&amp;amp;sitewide=1&amp;amp;plugin=' . $plugin_file, 'deactivate-plugin_' . $plugin_file ) . '&quot; title=&quot;' . __('Deactivate this plugin site wide') . '&quot;&gt;' . __('Deactivate') . '&lt;/a&gt;';
-
-                                if ( current_user_can('edit_plugins') &amp;&amp; is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) )
-                                        $action_links[] = '&lt;a href=&quot;plugin-editor.php?file=' . $plugin_file . '&quot; title=&quot;' . __('Open this file in the Plugin Editor') . '&quot; class=&quot;edit&quot;&gt;' . __('Edit') . '&lt;/a&gt;';
-
-                                $action_links = apply_filters( 'plugin_action_links', $action_links, $plugin_file, $plugin_data, $context );
-                                $action_links = apply_filters( &quot;plugin_action_links_$plugin_file&quot;, $action_links, $plugin_file, $plugin_data, $context );
-
-                                $plugin_data = $all_plugins[$plugin_file];
-
-                                echo &quot;
-                        &lt;tr class='$context' style='background: #eef2ff;'&gt;
-                                &lt;th scope='row' class='check-column'&gt;&amp;nbsp;&lt;/th&gt;
-                                &lt;td class='plugin-title'&gt;&lt;strong&gt;{$plugin_data['Name']}&lt;/strong&gt;&lt;/td&gt;
-                                &lt;td class='desc'&gt;&lt;p&gt;{$plugin_data['Description']}&lt;/p&gt;&lt;/td&gt;
-                        &lt;/tr&gt;
-                        &lt;tr class='$context second' style='background: #eef2ff;'&gt;
-                                &lt;td&gt;&lt;/td&gt;
-                                &lt;td class='plugin-title'&gt;&quot;;
-                                echo '&lt;div class=&quot;row-actions-visible&quot;&gt;';
-                                foreach ( $action_links as $action =&gt; $link ) {
-                                        $sep = end($action_links) == $link ? '' : ' | ';
-                                        echo &quot;&lt;span class='$action'&gt;$link$sep&lt;/span&gt;&quot;;
-                                }
-                                echo &quot;&lt;/div&gt;&lt;/td&gt;
-                                &lt;td class='desc'&gt;&quot;;
-                                $plugin_meta = array();
-                                if ( !empty($plugin_data['Version']) )
-                                        $plugin_meta[] = sprintf(__('Version %s'), $plugin_data['Version']);
-                                if ( !empty($plugin_data['Author']) ) {
-                                        $author = $plugin_data['Author'];
-                                        if ( !empty($plugin_data['AuthorURI']) )
-                                                $author = '&lt;a href=&quot;' . $plugin_data['AuthorURI'] . '&quot; title=&quot;' . __( 'Visit author homepage' ) . '&quot;&gt;' . $plugin_data['Author'] . '&lt;/a&gt;';
-                                        $plugin_meta[] = sprintf( __('By %s'), $author );
-                                }
-                                if ( ! empty($plugin_data['PluginURI']) )
-                                        $plugin_meta[] = '&lt;a href=&quot;' . $plugin_data['PluginURI'] . '&quot; title=&quot;' . __( 'Visit plugin site' ) . '&quot;&gt;' . __('Visit plugin site') . '&lt;/a&gt;';
-
-                                $plugin_meta = apply_filters('plugin_row_meta', $plugin_meta, $plugin_file, $plugin_data, $context);
-                                echo implode(' | ', $plugin_meta);
-                                echo &quot;&lt;/td&gt;
-                        &lt;/tr&gt;\n&quot;;
-
-                                do_action( 'after_plugin_row', $plugin_file, $plugin_data, $context );
-                                do_action( &quot;after_plugin_row_$plugin_file&quot;, $plugin_file, $plugin_data, $context );
-                        }
-                ?&gt;
-                        &lt;/tbody&gt;
-                &lt;/table&gt;
-
-                &lt;p&gt;&lt;?php _e( 'Plugins that are enabled site wide can only be disabled by a site administrator.' ) ?&gt;&lt;/p&gt;
-
-&lt;?php
-        }
-}
-add_action( 'pre_current_active_plugins', 'list_activate_sitewide_plugins' );
-
-/**
- * sitewide_filter_inactive_plugins_list()
- *
- * Filters the inactive plugins list so that it doesn't include plugins that have
- * been activated site wide, and not for the specific blog.
- */
-function sitewide_filter_inactive_plugins_list( $inactive_plugins ) {
-        $active_sitewide_plugins = (array) maybe_unserialize( get_site_option('active_sitewide_plugins') );
-
-        foreach ( $active_sitewide_plugins as $sitewide_plugin =&gt; $activated_time ) {
-                unset( $inactive_plugins[ $sitewide_plugin ] );
-        }
-
-        /* Now unset any sitewide only plugins if the user is not a site admin */
-        if ( !is_super_admin() ) {
-                foreach ( $inactive_plugins as $plugin_name =&gt; $activated_time ) {
-                        if ( is_wpmu_sitewide_plugin( $plugin_name ) )
-                                unset( $inactive_plugins[ $plugin_name ] );
-                }
-        }
-
-        return $inactive_plugins;
-}
-add_filter( 'all_plugins', 'sitewide_filter_inactive_plugins_list' );
-
-/**
- * sitewide_filter_active_plugins_list()
- *
- * Filters the active plugins list so that it doesn't include plugins that have
- * been activated site wide instead of the specific blog.
- */
-function sitewide_filter_active_plugins_list( $active_plugins ) {
-        $active_sitewide_plugins = (array) maybe_unserialize( get_site_option('active_sitewide_plugins') );
-
-        foreach ( $active_sitewide_plugins as $sitewide_plugin =&gt; $activated_time ) {
-                unset( $active_plugins[ $sitewide_plugin ] );
-        }
-
-        return $active_plugins;
-}
-add_filter( 'all_plugins', 'sitewide_filter_active_plugins_list' );
-
-/**
- * check_is_wpmu_plugin_on_activate()
- *
- * When a plugin is activated, this will check if it should be activated site wide
- * only.
- */
</del><span class="cx"> function check_is_wpmu_plugin_on_activate() {
</span><del>-        /***
-         * On plugin activation on a blog level, check to see if this is actually a
-         * site wide MU plugin. If so, deactivate and activate it site wide.
-         */
-        if ( is_wpmu_sitewide_plugin( $_GET['plugin'] ) || isset( $_GET['sitewide'] ) ) {
-                deactivate_plugins( $_GET['plugin'], true );
-
-                /* Silently activate because the activate_* hook has already run. */
-                if ( is_super_admin() ) {
-                        $_GET['sitewide'] = true;
-                        activate_sitewide_plugin( $_GET['plugin'], true );
-                }
-        }
</del><ins>+        return;
</ins><span class="cx"> }
</span><del>-// @todo Throws warning if plugin is not set.  Kinda janky.
-//add_action( 'activate_' . $_GET['plugin'], 'check_is_wpmu_plugin_on_activate' );
</del><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * check_wpmu_plugins_on_bulk_activate()
</del><ins>+ * @deprecated
</ins><span class="cx">  */
</span><span class="cx"> function check_wpmu_plugins_on_bulk_activate( $plugins ) {
</span><del>-        if ( $plugins ) {
-                foreach ( $plugins as $plugin ) {
-                        if ( is_wpmu_sitewide_plugin( $plugin ) ) {
-                                deactivate_plugins( $plugin );
-
-                                if ( is_super_admin() )
-                                        activate_sitewide_plugin( $plugin );
-                        }
-                }
-        }
</del><ins>+        return;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function choose_primary_blog() {
</span></span></pre></div>
<a id="trunkwpadminincludespluginphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/plugin.php (12902 => 12903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/plugin.php        2010-01-29 19:29:31 UTC (rev 12902)
+++ trunk/wp-admin/includes/plugin.php        2010-01-29 21:45:32 UTC (rev 12903)
</span><span class="lines">@@ -263,6 +263,52 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Check whether the plugin is active for the entire network.
+ *
+ * @since 3.0.0
+ *
+ * @param string $plugin Base plugin path from plugins directory.
+ * @return bool True, if active for the network, otherwise false.
+ */
+function is_plugin_active_for_network( $plugin ){
+        if ( !is_multisite() )
+                return false;
+
+        $plugins = get_site_option( 'active_sitewide_plugins');
+        if ( isset($plugins[$plugin]) )
+                return true;
+
+        return false;
+}
+
+/**
+ * Checks for &quot;Site Wide Only: true&quot; in the plugin header to see if this should
+ * be activated as a network wide MU plugin.
+ *
+ * @since 3.0.0
+ *
+ * @todo Use API for getting arbitrary plugin headers.
+ *
+ * @param $file Plugin to check
+ * $return bool True if plugin is network only, false otherwise.
+ */
+function is_network_only_plugin( $file ) {
+        /* Open the plugin file for reading to check if this is a ms-plugin. */
+        $fp = @fopen( WP_PLUGIN_DIR . '/' . $file, 'r' );
+
+        /* Pull only the first 8kiB of the file in. */
+        $plugin_data = @fread( $fp, 8192 );
+
+        /* PHP will close file handle, but we are good citizens. */
+        @fclose($fp);
+
+        if ( preg_match( '|Site Wide Only:(.*)true$|mi', $plugin_data ) )
+                return true;
+
+        return false;
+}
+
+/**
</ins><span class="cx">  * Attempts activation of plugin in a &quot;sandbox&quot; and redirects on success.
</span><span class="cx">  *
</span><span class="cx">  * A plugin that is already activated will not attempt to be activated again.
</span><span class="lines">@@ -284,12 +330,19 @@
</span><span class="cx">  *
</span><span class="cx">  * @param string $plugin Plugin path to main plugin file with plugin data.
</span><span class="cx">  * @param string $redirect Optional. URL to redirect to.
</span><ins>+ * @param bool $network_wide Whether to enable the plugin for all sites in the network or just the current site.  Multisite only. Default is false.
</ins><span class="cx">  * @return WP_Error|null WP_Error on invalid file or null on success.
</span><span class="cx">  */
</span><del>-function activate_plugin( $plugin, $redirect = '' ) {
-        $current = get_option( 'active_plugins', array() );
</del><ins>+function activate_plugin( $plugin, $redirect = '', $network_wide = false) {
</ins><span class="cx">         $plugin  = plugin_basename( trim( $plugin ) );
</span><span class="cx"> 
</span><ins>+        if ( is_multisite() &amp;&amp; ( $network_wide || is_network_only_plugin($plugin) ) ) {
+                $network_wide = true;
+                $current = get_site_option( 'active_sitewide_plugins', array() );
+        } else {
+                $current = get_option( 'active_plugins', array() );
+        }
+
</ins><span class="cx">         $valid = validate_plugin($plugin);
</span><span class="cx">         if ( is_wp_error($valid) )
</span><span class="cx">                 return $valid;
</span><span class="lines">@@ -299,10 +352,15 @@
</span><span class="cx">                         wp_redirect(add_query_arg('_error_nonce', wp_create_nonce('plugin-activation-error_' . $plugin), $redirect)); // we'll override this later if the plugin can be included without fatal error
</span><span class="cx">                 ob_start();
</span><span class="cx">                 @include(WP_PLUGIN_DIR . '/' . $plugin);
</span><del>-                $current[] = $plugin;
-                sort($current);
</del><span class="cx">                 do_action( 'activate_plugin', trim( $plugin) );
</span><del>-                update_option('active_plugins', $current);
</del><ins>+                if ( $network_wide ) {
+                        $current[$plugin] = time();
+                        update_site_option( 'active_sitewide_plugins', $current );
+                } else {
+                        $current[] = $plugin;
+                        sort($current);
+                        update_option('active_plugins', $current);
+                }
</ins><span class="cx">                 do_action( 'activate_' . trim( $plugin ) );
</span><span class="cx">                 do_action( 'activated_plugin', trim( $plugin) );
</span><span class="cx">                 ob_end_clean();
</span><span class="lines">@@ -323,7 +381,9 @@
</span><span class="cx">  * @param bool $silent Optional, default is false. Prevent calling deactivate hook.
</span><span class="cx">  */
</span><span class="cx"> function deactivate_plugins( $plugins, $silent = false ) {
</span><ins>+        $network_current = get_site_option( 'active_sitewide_plugins', array() );
</ins><span class="cx">         $current = get_option( 'active_plugins', array() );
</span><ins>+        $do_blog = $do_network = false;
</ins><span class="cx"> 
</span><span class="cx">         foreach ( (array) $plugins as $plugin ) {
</span><span class="cx">                 $plugin = plugin_basename($plugin);
</span><span class="lines">@@ -332,10 +392,18 @@
</span><span class="cx">                 if ( ! $silent )
</span><span class="cx">                         do_action( 'deactivate_plugin', trim( $plugin ) );
</span><span class="cx"> 
</span><del>-                $key = array_search( $plugin, (array) $current );
</del><ins>+                if ( is_plugin_active_for_network($plugin) ) {
+                        // Deactivate network wide
+                        $do_network = true;
+                        unset($network_current[$plugin]);
+                } else {
+                        // Deactivate for this blog only
+                        $do_blog = true;
+                        $key = array_search( $plugin, (array) $current );
</ins><span class="cx"> 
</span><del>-                if ( false !== $key )
-                        array_splice( $current, $key, 1 );
</del><ins>+                        if ( false !== $key )
+                                array_splice( $current, $key, 1 );
+                }
</ins><span class="cx"> 
</span><span class="cx">                 //Used by Plugin updater to internally deactivate plugin, however, not to notify plugins of the fact to prevent plugin output.
</span><span class="cx">                 if ( ! $silent ) {
</span><span class="lines">@@ -344,7 +412,10 @@
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        update_option('active_plugins', $current);
</del><ins>+        if ( $do_blog )
+                update_option('active_plugins', $current);
+        if ( $do_network )
+                update_site_option( 'active_sitewide_plugins', $network_current );
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span></span></pre></div>
<a id="trunkwpadminpluginsphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/plugins.php (12902 => 12903)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/plugins.php        2010-01-29 19:29:31 UTC (rev 12902)
+++ trunk/wp-admin/plugins.php        2010-01-29 21:45:32 UTC (rev 12903)
</span><span class="lines">@@ -27,7 +27,7 @@
</span><span class="cx"> if ( empty($default_status) )
</span><span class="cx">         $default_status = 'all';
</span><span class="cx"> $status = isset($_REQUEST['plugin_status']) ? $_REQUEST['plugin_status'] : $default_status;
</span><del>-if ( !in_array($status, array('all', 'active', 'inactive', 'recent', 'upgrade', 'search')) )
</del><ins>+if ( !in_array($status, array('all', 'active', 'inactive', 'recent', 'upgrade', 'network', 'search')) )
</ins><span class="cx">         $status = 'all';
</span><span class="cx"> if ( $status != $default_status &amp;&amp; 'search' != $status )
</span><span class="cx">         update_usermeta($current_user-&gt;ID, 'plugins_last_view', $status);
</span><span class="lines">@@ -38,6 +38,10 @@
</span><span class="cx"> $_SERVER['REQUEST_URI'] = remove_query_arg(array('error', 'deleted', 'activate', 'activate-multi', 'deactivate', 'deactivate-multi', '_error_nonce'), $_SERVER['REQUEST_URI']);
</span><span class="cx"> 
</span><span class="cx"> if ( !empty($action) ) {
</span><ins>+        $network_wide = false;
+        if ( isset($_GET['networkwide']) &amp;&amp; is_multisite() &amp;&amp; is_super_admin() )
+                $network_wide = true;
+
</ins><span class="cx">         switch ( $action ) {
</span><span class="cx">                 case 'activate':
</span><span class="cx">                         if ( ! current_user_can('activate_plugins') )
</span><span class="lines">@@ -45,7 +49,7 @@
</span><span class="cx"> 
</span><span class="cx">                         check_admin_referer('activate-plugin_' . $plugin);
</span><span class="cx"> 
</span><del>-                        $result = activate_plugin($plugin, 'plugins.php?error=true&amp;plugin=' . $plugin);
</del><ins>+                        $result = activate_plugin($plugin, 'plugins.php?error=true&amp;plugin=' . $plugin, $network_wide);
</ins><span class="cx">                         if ( is_wp_error( $result ) )
</span><span class="cx">                                 wp_die($result);
</span><span class="cx"> 
</span><span class="lines">@@ -71,7 +75,7 @@
</span><span class="cx">                                 exit;
</span><span class="cx">                         }
</span><span class="cx"> 
</span><del>-                        activate_plugins($plugins, 'plugins.php?error=true');
</del><ins>+                        activate_plugins($plugins, 'plugins.php?error=true', $network_wide);
</ins><span class="cx"> 
</span><span class="cx">                         $recent = (array)get_option('recently_activated');
</span><span class="cx">                         foreach ( $plugins as $plugin =&gt; $time)
</span><span class="lines">@@ -340,6 +344,7 @@
</span><span class="cx"> $recent_plugins = array();
</span><span class="cx"> $recently_activated = get_option('recently_activated', array());
</span><span class="cx"> $upgrade_plugins = array();
</span><ins>+$network_plugins = array();
</ins><span class="cx"> 
</span><span class="cx"> set_transient( 'plugin_slugs', array_keys($all_plugins), 86400 );
</span><span class="cx"> 
</span><span class="lines">@@ -353,12 +358,14 @@
</span><span class="cx"> 
</span><span class="cx"> foreach ( (array)$all_plugins as $plugin_file =&gt; $plugin_data) {
</span><span class="cx"> 
</span><del>-        //Translate, Apply Markup, Sanitize HTML
</del><ins>+        // Translate, Apply Markup, Sanitize HTML
</ins><span class="cx">         $plugin_data = _get_plugin_data_markup_translate($plugin_file, $plugin_data, false, true);
</span><span class="cx">         $all_plugins[ $plugin_file ] = $plugin_data;
</span><span class="cx"> 
</span><del>-        //Filter into individual sections
-        if ( is_plugin_active($plugin_file) ) {
</del><ins>+        // Filter into individual sections
+        if ( is_plugin_active_for_network($plugin_file) &amp;&amp; is_super_admin() ) {
+                $network_plugins[ $plugin_file ] = $plugin_data;
+        } elseif ( is_plugin_active($plugin_file) ) {
</ins><span class="cx">                 $active_plugins[ $plugin_file ] = $plugin_data;
</span><span class="cx">         } else {
</span><span class="cx">                 if ( isset( $recently_activated[ $plugin_file ] ) ) // Was the plugin recently activated?
</span><span class="lines">@@ -378,6 +385,7 @@
</span><span class="cx"> $total_active_plugins = count($active_plugins);
</span><span class="cx"> $total_recent_plugins = count($recent_plugins);
</span><span class="cx"> $total_upgrade_plugins = count($upgrade_plugins);
</span><ins>+$total_network_plugins = count($network_plugins);
</ins><span class="cx"> 
</span><span class="cx"> //Searching.
</span><span class="cx"> if ( isset($_GET['s']) ) {
</span><span class="lines">@@ -408,7 +416,7 @@
</span><span class="cx"> 
</span><span class="cx"> $plugins = &amp;$$plugin_array_name;
</span><span class="cx"> 
</span><del>-//Paging.
</del><ins>+// Paging.
</ins><span class="cx"> $total_this_page = &quot;total_{$status}_plugins&quot;;
</span><span class="cx"> $total_this_page = $$total_this_page;
</span><span class="cx"> $plugins_per_page = (int) get_user_option( 'plugins_per_page' );
</span><span class="lines">@@ -470,13 +478,25 @@
</span><span class="cx">         foreach ( (array)$plugins as $plugin_file =&gt; $plugin_data) {
</span><span class="cx">                 $actions = array();
</span><span class="cx">                 $is_active = is_plugin_active($plugin_file);
</span><ins>+                $is_active_for_network = is_plugin_active_for_network($plugin_file);
</ins><span class="cx"> 
</span><del>-                if ( $is_active )
-                        $actions[] = '&lt;a href=&quot;' . wp_nonce_url('plugins.php?action=deactivate&amp;amp;plugin=' . $plugin_file . '&amp;amp;plugin_status=' . $context . '&amp;amp;paged=' . $page, 'deactivate-plugin_' . $plugin_file) . '&quot; title=&quot;' . __('Deactivate this plugin') . '&quot;&gt;' . __('Deactivate') . '&lt;/a&gt;';
-                else
</del><ins>+                if ( $is_active_for_network &amp;&amp; !is_super_admin() )
+                        continue;
+
+                if ( $is_active ) {
+                        if ( $is_active_for_network ) {
+                                if ( is_super_admin() )
+                                        $actions[] = '&lt;a href=&quot;' . wp_nonce_url('plugins.php?action=deactivate&amp;amp;networkwide=1&amp;amp;plugin=' . $plugin_file . '&amp;amp;plugin_status=' . $context . '&amp;amp;paged=' . $page, 'deactivate-plugin_' . $plugin_file) . '&quot; title=&quot;' . __('Deactivate this plugin') . '&quot;&gt;' . __('Network Deactivate') . '&lt;/a&gt;';
+                        } else {
+                                $actions[] = '&lt;a href=&quot;' . wp_nonce_url('plugins.php?action=deactivate&amp;amp;plugin=' . $plugin_file . '&amp;amp;plugin_status=' . $context . '&amp;amp;paged=' . $page, 'deactivate-plugin_' . $plugin_file) . '&quot; title=&quot;' . __('Deactivate this plugin') . '&quot;&gt;' . __('Deactivate') . '&lt;/a&gt;';
+                        }
+                } else {
</ins><span class="cx">                         $actions[] = '&lt;a href=&quot;' . wp_nonce_url('plugins.php?action=activate&amp;amp;plugin=' . $plugin_file . '&amp;amp;plugin_status=' . $context . '&amp;amp;paged=' . $page, 'activate-plugin_' . $plugin_file) . '&quot; title=&quot;' . __('Activate this plugin') . '&quot; class=&quot;edit&quot;&gt;' . __('Activate') . '&lt;/a&gt;';
</span><ins>+                        if ( is_multisite() &amp;&amp; is_super_admin() )
+                                $actions[] = '&lt;a href=&quot;' . wp_nonce_url('plugins.php?action=activate&amp;amp;networkwide=1&amp;amp;plugin=' . $plugin_file . '&amp;amp;plugin_status=' . $context . '&amp;amp;paged=' . $page, 'activate-plugin_' . $plugin_file) . '&quot; title=&quot;' . __('Activate this plugin for all sites in this network') . '&quot; class=&quot;edit&quot;&gt;' . __('Network Activate') . '&lt;/a&gt;';
+                }
</ins><span class="cx"> 
</span><del>-                if ( current_user_can('edit_plugins') &amp;&amp; is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) )
</del><ins>+                if ( !is_multisite() &amp;&amp; current_user_can('edit_plugins') &amp;&amp; is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) )
</ins><span class="cx">                         $actions[] = '&lt;a href=&quot;plugin-editor.php?file=' . $plugin_file . '&quot; title=&quot;' . __('Open this file in the Plugin Editor') . '&quot; class=&quot;edit&quot;&gt;' . __('Edit') . '&lt;/a&gt;';
</span><span class="cx"> 
</span><span class="cx">                 if ( ! $is_active &amp;&amp; current_user_can('delete_plugins') )
</span><span class="lines">@@ -592,6 +612,10 @@
</span><span class="cx">         $class = ( 'inactive' == $status ) ? ' class=&quot;current&quot;' : '';
</span><span class="cx">         $status_links[] = &quot;&lt;li&gt;&lt;a href='plugins.php?plugin_status=inactive' $class&gt;&quot; . sprintf( _n( 'Inactive &lt;span class=&quot;count&quot;&gt;(%s)&lt;/span&gt;', 'Inactive &lt;span class=&quot;count&quot;&gt;(%s)&lt;/span&gt;', $total_inactive_plugins ), number_format_i18n( $total_inactive_plugins ) ) . '&lt;/a&gt;';
</span><span class="cx"> }
</span><ins>+if ( ! empty($network_plugins) ) {
+        $class = ( 'network' == $status ) ? ' class=&quot;current&quot;' : '';
+        $status_links[] = &quot;&lt;li&gt;&lt;a href='plugins.php?plugin_status=network' $class&gt;&quot; . sprintf( _n( 'Network &lt;span class=&quot;count&quot;&gt;(%s)&lt;/span&gt;', 'Network &lt;span class=&quot;count&quot;&gt;(%s)&lt;/span&gt;', $total_network_plugins ), number_format_i18n( $total_network_plugins ) ) . '&lt;/a&gt;';
+}
</ins><span class="cx"> if ( ! empty($upgrade_plugins) ) {
</span><span class="cx">         $class = ( 'upgrade' == $status ) ? ' class=&quot;current&quot;' : '';
</span><span class="cx">         $status_links[] = &quot;&lt;li&gt;&lt;a href='plugins.php?plugin_status=upgrade' $class&gt;&quot; . sprintf( _n( 'Upgrade Available &lt;span class=&quot;count&quot;&gt;(%s)&lt;/span&gt;', 'Upgrade Available &lt;span class=&quot;count&quot;&gt;(%s)&lt;/span&gt;', $total_upgrade_plugins ), number_format_i18n( $total_upgrade_plugins ) ) . '&lt;/a&gt;';
</span></span></pre>
</div>
</div>

</body>
</html>