<!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>[BuddyPress][8117] trunk/bp-core: Introduce BuddyPress Tools panel</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">
<dt>Revision</dt> <dd><a href="http://buddypress.trac.wordpress.org/changeset/8117">8117</a></dd>
<dt>Author</dt> <dd>boonebgorges</dd>
<dt>Date</dt> <dd>2014-03-12 21:26:35 +0000 (Wed, 12 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Introduce BuddyPress Tools panel

Modeled on the bbPress panel, the BuddyPress Tools panel contains a number of
tools for repairing BuddyPress data. In this first iteration, the following
actions are supported:

- Recalculate total_friend_count for each user
- Recalculate total_group_count for each user
- Recalculate total site members

On non-Multisite (or when BP is only activated on a single site), the menu
appears as Tools > BuddyPress. When BP is network-activated, we create a stub
Tools menu on the Network Admin to account for the fact that one is not
normally there. If WP ever introduces a menu like this, we can use it instead.

Fixes <a href="http://buddypress.trac.wordpress.org/ticket/5296">#5296</a>

Props cmmarslender, boonebgorges, imath</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkbpcoreadminbpcorefunctionsphp">trunk/bp-core/admin/bp-core-functions.php</a></li>
<li><a href="#trunkbpcoreadmincsscommoncss">trunk/bp-core/admin/css/common.css</a></li>
<li><a href="#trunkbpcorebpcoreadminphp">trunk/bp-core/bp-core-admin.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkbpcoreadminbpcoretoolsphp">trunk/bp-core/admin/bp-core-tools.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkbpcoreadminbpcorefunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-core/admin/bp-core-functions.php (8116 => 8117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-core/admin/bp-core-functions.php        2014-03-12 18:46:44 UTC (rev 8116)
+++ trunk/bp-core/admin/bp-core-functions.php   2014-03-12 21:26:35 UTC (rev 8117)
</span><span class="lines">@@ -74,11 +74,16 @@
</span><span class="cx">  * @since BuddyPress (1.6)
</span><span class="cx">  */
</span><span class="cx"> function bp_core_modify_admin_menu_highlight() {
</span><del>-       global $plugin_page, $submenu_file;
</del><ins>+        global $pagenow, $plugin_page, $submenu_file;
</ins><span class="cx"> 
</span><span class="cx">  // This tweaks the Settings subnav menu to show only one BuddyPress menu item
</span><span class="cx">  if ( ! in_array( $plugin_page, array( 'bp-activity', 'bp-general-settings', ) ) )
</span><span class="cx">          $submenu_file = 'bp-components';
</span><ins>+
+       // Network Admin > Tools
+       if ( in_array( $plugin_page, array( 'bp-tools', 'available-tools' ) ) ) {
+               $submenu_file = $plugin_page;
+       }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><span class="lines">@@ -388,7 +393,7 @@
</span><span class="cx">          '2' => array(
</span><span class="cx">                  'href' => bp_get_admin_url( add_query_arg( array( 'page' => 'bp-settings' ), 'admin.php' ) ),
</span><span class="cx">                  'name' => __( 'Settings', 'buddypress' )
</span><del>-               )
</del><ins>+                ),
</ins><span class="cx">   );
</span><span class="cx"> 
</span><span class="cx">  // If forums component is active, add additional tab
</span></span></pre></div>
<a id="trunkbpcoreadminbpcoretoolsphp"></a>
<div class="addfile"><h4>Added: trunk/bp-core/admin/bp-core-tools.php (0 => 8117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-core/admin/bp-core-tools.php                            (rev 0)
+++ trunk/bp-core/admin/bp-core-tools.php       2014-03-12 21:26:35 UTC (rev 8117)
</span><span class="lines">@@ -0,0 +1,329 @@
</span><ins>+<?php
+
+/**
+ * BuddyPress Tools panel
+ *
+ * @since BuddyPress (2.0.0)
+ */
+
+/**
+ * Render the BuddyPress Tools page.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_core_admin_tools() {
+       ?>
+       <div class="wrap">
+               <?php screen_icon( 'buddypress'); ?>
+
+               <h2><?php esc_html_e( 'BuddyPress Tools', 'buddypress' ) ?></h2>
+
+               <p>
+                       <?php esc_html_e( 'BuddyPress keeps track of various relationships between users, groups, and activity items. Occasionally these relationships become out of sync, most often after an import, update, or migration.', 'buddypress' ); ?>
+                       <?php esc_html_e( 'Use the tools below to manually recalculate these relationships.', 'buddypress' ); ?>
+               </p>
+               <p class="description"><?php esc_html_e( 'Some of these tools create substantial database overhead. Avoid running more than one repair job at a time.', 'buddypress' ); ?></p>
+
+               <form class="settings" method="post" action="">
+                       <table class="form-table">
+                               <tbody>
+                                       <tr valign="top">
+                                               <th scope="row"><?php esc_html_e( 'Data to Repair:', 'buddypress' ) ?></th>
+                                               <td>
+                                                       <fieldset>
+                                                               <legend class="screen-reader-text"><span><?php esc_html_e( 'Repair', 'buddypress' ) ?></span></legend>
+
+                                                               <?php foreach ( bp_admin_repair_list() as $item ) : ?>
+
+                                                                       <label><input type="checkbox" class="checkbox" name="<?php echo esc_attr( $item[0] ) . '" id="' . esc_attr( str_replace( '_', '-', $item[0] ) ); ?>" value="1" /> <?php echo esc_html( $item[1] ); ?></label><br />
+
+                                                               <?php endforeach; ?>
+
+                                                       </fieldset>
+                                               </td>
+                                       </tr>
+                               </tbody>
+                       </table>
+
+                       <fieldset class="submit">
+                               <input class="button-primary" type="submit" name="bp-tools-submit" value="<?php esc_attr_e( 'Repair Items', 'buddypress' ); ?>" />
+                               <?php wp_nonce_field( 'bp-do-counts' ); ?>
+                       </fieldset>
+               </form>
+       </div>
+       <?php
+}
+
+/**
+ * Handle the processing and feedback of the admin tools page.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_admin_repair_handler() {
+       if ( ! bp_is_post_request() ) {
+               return;
+       }
+
+       if ( empty( $_POST['bp-tools-submit'] ) ) {
+               return;
+       }
+
+       check_admin_referer( 'bp-do-counts' );
+
+       // Stores messages
+       $messages = array();
+
+       wp_cache_flush();
+
+       foreach ( (array) bp_admin_repair_list() as $item ) {
+               if ( isset( $item[2] ) && isset( $_POST[$item[0]] ) && 1 === absint( $_POST[$item[0]] ) && is_callable( $item[2] ) ) {
+                       $messages[] = call_user_func( $item[2] );
+               }
+       }
+
+       if ( count( $messages ) ) {
+               foreach ( $messages as $message ) {
+                       bp_admin_tools_feedback( $message[1] );
+               }
+       }
+}
+add_action( bp_core_admin_hook(), 'bp_admin_repair_handler' );
+
+/**
+ * Get the array of the repair list.
+ *
+ * @return array
+ */
+function bp_admin_repair_list() {
+       // Members:
+       // - member count
+       $repair_list = array(
+               20 => array(
+                       'bp-total-member-count',
+                       __( 'Count total members', 'buddypress' ),
+                       'bp_admin_repair_count_members',
+               ),
+       );
+
+       // Friends:
+       // - user friend count
+       if ( bp_is_active( 'friends' ) ) {
+               $repair_list[0] = array(
+                       'bp-user-friends',
+                       __( 'Count friends for each user', 'buddypress' ),
+                       'bp_admin_repair_friend_count',
+               );
+       }
+
+       // Groups:
+       // - user group count
+       if ( bp_is_active( 'groups' ) ) {
+               $repair_list[10] = array(
+                       'bp-group-count',
+                       __( 'Count groups for each user', 'buddypress' ),
+                       'bp_admin_repair_group_count',
+               );
+       }
+
+       ksort( $repair_list );
+
+       return (array) apply_filters( 'bp_repair_list', $repair_list );
+}
+
+/**
+ * Recalculate friend counts for each user.
+ *
+ * @since BuddyPress (2.0.0)
+ *
+ * @return array
+ */
+function bp_admin_repair_friend_count() {
+       global $wpdb, $bp;
+
+       if ( ! bp_is_active( 'friends' ) ) {
+               return;
+       }
+
+       $statement = __( 'Counting the number of friends for each user&hellip; %s', 'buddypress' );
+       $result    = __( 'Failed!', 'buddypress' );
+
+       $sql_delete = "DELETE FROM {$wpdb->usermeta} WHERE meta_key IN ( 'total_friend_count' );";
+       if ( is_wp_error( $wpdb->query( $sql_delete ) ) ) {
+               return array( 1, sprintf( $statement, $result ) );
+       }
+
+       // Walk through all users on the site
+       $total_users = $wpdb->get_row( "SELECT count(ID) as c FROM {$wpdb->users}" )->c;
+
+       $updated = array();
+       if ( $total_users > 0 ) {
+               $per_query = 500;
+               $offset = 0;
+               while ( $offset < $total_users ) {
+                       // Only bother updating counts for users who actually have friendships
+                       $friendships = $wpdb->get_results( $wpdb->prepare( "SELECT initiator_user_id, friend_user_id FROM {$bp->friends->table_name} WHERE is_confirmed = 1 AND ( ( initiator_user_id > %d AND initiator_user_id <= %d ) OR ( friend_user_id > %d AND friend_user_id <= %d ) )", $offset, $offset + $per_query, $offset, $offset + $per_query ) );
+
+                       // The previous query will turn up duplicates, so we
+                       // filter them here
+                       foreach ( $friendships as $friendship ) {
+                               if ( ! isset( $updated[ $friendship->initiator_user_id ] ) ) {
+                                       BP_Friends_Friendship::total_friend_count( $friendship->initiator_user_id );
+                                       $updated[ $friendship->initiator_user_id ] = 1;
+                               }
+
+                               if ( ! isset( $updated[ $friendship->friend_user_id ] ) ) {
+                                       BP_Friends_Friendship::total_friend_count( $friendship->friend_user_id );
+                                       $updated[ $friendship->friend_user_id ] = 1;
+                               }
+                       }
+
+                       $offset += $per_query;
+               }
+       } else {
+               return array( 2, sprintf( $statement, $result ) );
+       }
+
+       return array( 0, sprintf( $statement, __( 'Complete!', 'buddypress' ) ) );
+}
+
+/**
+ * Recalculate group counts for each user.
+ *
+ * @since BuddyPress (2.0.0)
+ *
+ * @return array
+ */
+function bp_admin_repair_group_count() {
+       global $wpdb, $bp;
+
+       if ( ! bp_is_active( 'groups' ) ) {
+               return;
+       }
+
+       $statement = __( 'Counting the number of groups for each user&hellip; %s', 'buddypress' );
+       $result    = __( 'Failed!', 'buddypress' );
+
+       $sql_delete = "DELETE FROM {$wpdb->usermeta} WHERE meta_key IN ( 'total_group_count' );";
+       if ( is_wp_error( $wpdb->query( $sql_delete ) ) ) {
+               return array( 1, sprintf( $statement, $result ) );
+       }
+
+       // Walk through all users on the site
+       $total_users = $wpdb->get_row( "SELECT count(ID) as c FROM {$wpdb->users}" )->c;
+
+       if ( $total_users > 0 ) {
+               $per_query = 500;
+               $offset = 0;
+               while ( $offset < $total_users ) {
+                       // But only bother to update counts for users that have groups
+                       $users = $wpdb->get_col( $wpdb->prepare( "SELECT user_id FROM {$bp->groups->table_name_members} WHERE is_confirmed = 1 AND is_banned = 0 AND user_id > %d AND user_id <= %d", $offset, $offset + $per_query ) );
+
+                       foreach ( $users as $user ) {
+                               BP_Groups_Member::refresh_total_group_count_for_user( $user );
+                       }
+
+                       $offset += $per_query;
+               }
+       } else {
+               return array( 2, sprintf( $statement, $result ) );
+       }
+
+       return array( 0, sprintf( $statement, __( 'Complete!', 'buddypress' ) ) );
+}
+
+/**
+ * Recalculate the total number of active site members.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_admin_repair_count_members() {
+       $statement = __( 'Counting the number of active members on the site&hellip; %s', 'buddypress' );
+       delete_transient( 'bp_active_member_count' );
+       bp_core_get_active_member_count();
+       return array( 0, sprintf( $statement, __( 'Complete!', 'buddypress' ) ) );
+}
+
+/**
+ * Assemble admin notices relating success/failure of repair processes.
+ *
+ * @since BuddyPress (2.0.0)
+ *
+ * @param string $message Feedback message.
+ * @param unknown $class Unused.
+ */
+function bp_admin_tools_feedback( $message, $class = false ) {
+       if ( is_string( $message ) ) {
+               $message = '<p>' . $message . '</p>';
+               $class = $class ? $class : 'updated';
+       } elseif ( is_wp_error( $message ) ) {
+               $errors = $message->get_error_messages();
+
+               switch ( count( $errors ) ) {
+                       case 0:
+                               return false;
+                               break;
+
+                       case 1:
+                               $message = '<p>' . $errors[0] . '</p>';
+                               break;
+
+                       default:
+                               $message = '<ul>' . "\n\t" . '<li>' . implode( '</li>' . "\n\t" . '<li>', $errors ) . '</li>' . "\n" . '</ul>';
+                               break;
+               }
+
+               $class = $class ? $class : 'error';
+       } else {
+               return false;
+       }
+
+       $message = '<div id="message" class="' . esc_attr( $class ) . '">' . $message . '</div>';
+       $message = str_replace( "'", "\'", $message );
+       $lambda  = create_function( '', "echo '$message';" );
+
+       add_action( 'admin_notices', $lambda );
+
+       return $lambda;
+}
+
+/**
+ * Render the Available Tools page.
+ *
+ * We register this page on Network Admin as a top-level home for our
+ * BuddyPress tools. This displays the default content.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_core_admin_available_tools_page() {
+       ?>
+       <div class="wrap">
+               <h2><?php esc_attr_e( 'Tools', 'buddypress' ) ?></h2>
+
+               <?php do_action( 'bp_network_tool_box' ); ?>
+
+       </div>
+       <?php
+}
+
+/**
+ * Render an introduction of BuddyPress tools on Available Tools page.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function bp_core_admin_available_tools_intro() {
+       $query_arg = array(
+               'page' => 'bp-tools'
+       );
+
+       $page = bp_core_do_network_admin() ? 'admin.php' : 'tools.php' ;
+       $url  = add_query_arg( $query_arg, bp_get_admin_url( $page ) );
+       ?>
+       <div class="tool-box">
+               <h3 class="title"><?php esc_html_e( 'BuddyPress Tools', 'buddypress' ) ?></h3>
+               <p>
+                       <?php esc_html_e( 'BuddyPress keeps track of various relationships between users, groups, and activity items. Occasionally these relationships become out of sync, most often after an import, update, or migration.', 'buddypress' ); ?>
+                       <?php printf( esc_html_x( 'Use the %s to repair these relationships.', 'buddypress tools intro', 'buddypress' ), '<a href="' . esc_url( $url ) . '">' . esc_html__( 'BuddyPress Tools', 'buddypress' ) . '</a>' ); ?>
+               </p>
+       </div>
+       <?php
+}
</ins></span></pre></div>
<a id="trunkbpcoreadmincsscommoncss"></a>
<div class="modfile"><h4>Modified: trunk/bp-core/admin/css/common.css (8116 => 8117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-core/admin/css/common.css       2014-03-12 18:46:44 UTC (rev 8116)
+++ trunk/bp-core/admin/css/common.css  2014-03-12 21:26:35 UTC (rev 8117)
</span><span class="lines">@@ -90,6 +90,12 @@
</span><span class="cx"> body.branch-3-7 ul#adminmenu li.toplevel_page_bp-groups_network.wp-has-current-submenu .wp-menu-image {
</span><span class="cx">  background-position: -61px -2px;
</span><span class="cx"> }
</span><ins>+
+/* Tools */
+#adminmenu .toplevel_page_network-tools div.wp-menu-image:before {
+    content: "";
+}
+
</ins><span class="cx"> th.column-gid {
</span><span class="cx">  width: 60px;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkbpcorebpcoreadminphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-core/bp-core-admin.php (8116 => 8117)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-core/bp-core-admin.php  2014-03-12 18:46:44 UTC (rev 8116)
+++ trunk/bp-core/bp-core-admin.php     2014-03-12 21:26:35 UTC (rev 8117)
</span><span class="lines">@@ -118,6 +118,7 @@
</span><span class="cx">          require( $this->admin_dir . 'bp-core-functions.php'  );
</span><span class="cx">          require( $this->admin_dir . 'bp-core-components.php' );
</span><span class="cx">          require( $this->admin_dir . 'bp-core-slugs.php'      );
</span><ins>+               require( $this->admin_dir . 'bp-core-tools.php'      );
</ins><span class="cx">   }
</span><span class="cx"> 
</span><span class="cx">  /**
</span><span class="lines">@@ -153,6 +154,10 @@
</span><span class="cx">          // Add a link to BuddyPress About page to the admin bar
</span><span class="cx">          add_action( 'admin_bar_menu', array( $this, 'admin_bar_about_link' ), 15 );
</span><span class="cx"> 
</span><ins>+               // Add a description of new BuddyPress tools in the available tools page
+               add_action( 'tool_box', 'bp_core_admin_available_tools_intro' );
+               add_action( 'bp_network_tool_box', 'bp_core_admin_available_tools_intro' );
+
</ins><span class="cx">           /** Filters ***********************************************************/
</span><span class="cx"> 
</span><span class="cx">          // Add link to settings page
</span><span class="lines">@@ -242,6 +247,42 @@
</span><span class="cx">                  'bp_core_admin_settings'
</span><span class="cx">          );
</span><span class="cx"> 
</span><ins>+               // For consistency with non-Multisite, we add a Tools menu in
+               // the Network Admin as a home for our Tools panel
+               if ( is_multisite() && bp_core_do_network_admin() ) {
+                       $tools_parent = 'network-tools';
+
+                       $hooks[] = add_menu_page(
+                               __( 'Tools', 'buddypress' ),
+                               __( 'Tools', 'buddypress' ),
+                               'manage_network_options',
+                               $tools_parent,
+                               'bp_core_tools_top_level_item',
+                               '',
+                               24 // just above Settings
+                       );
+
+                       $hooks[] = add_submenu_page(
+                               $tools_parent,
+                               __( 'Available Tools', 'buddypress' ),
+                               __( 'Available Tools', 'buddypress' ),
+                               'manage_network_options',
+                               'available-tools',
+                               'bp_core_admin_available_tools_page'
+                       );
+               } else {
+                       $tools_parent = 'tools.php';
+               }
+
+               $hooks[] = add_submenu_page(
+                       $tools_parent,
+                       __( 'BuddyPress Tools', 'buddypress' ),
+                       __( 'BuddyPress', 'buddypress' ),
+                       'manage_options',
+                       'bp-tools',
+                       'bp_core_admin_tools'
+               );
+
</ins><span class="cx">           // Fudge the highlighted subnav item when on a BuddyPress admin page
</span><span class="cx">          foreach( $hooks as $hook ) {
</span><span class="cx">                  add_action( "admin_head-$hook", 'bp_core_modify_admin_menu_highlight' );
</span><span class="lines">@@ -401,6 +442,9 @@
</span><span class="cx">          remove_submenu_page( $this->settings_page, 'bp-page-settings' );
</span><span class="cx">          remove_submenu_page( $this->settings_page, 'bp-settings'      );
</span><span class="cx"> 
</span><ins>+               // Network Admin Tools
+               remove_submenu_page( 'network-tools', 'network-tools' );
+
</ins><span class="cx">           // About and Credits pages
</span><span class="cx">          remove_submenu_page( 'index.php', 'bp-about'   );
</span><span class="cx">          remove_submenu_page( 'index.php', 'bp-credits' );
</span></span></pre>
</div>
</div>

</body>
</html>