<!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… %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… %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… %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>