web/wp-content/plugins/bbpress/includes/admin/tools.php
changeset 196 5e8dcbe22c24
child 204 09a1c134465b
equal deleted inserted replaced
195:c7c0fbc09788 196:5e8dcbe22c24
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * bbPress Admin Tools Page
       
     5  *
       
     6  * @package bbPress
       
     7  * @subpackage Administration
       
     8  */
       
     9 
       
    10 // Exit if accessed directly
       
    11 if ( !defined( 'ABSPATH' ) ) exit;
       
    12 
       
    13 /** Repair ********************************************************************/
       
    14 
       
    15 /**
       
    16  * Admin repair page
       
    17  *
       
    18  * @since bbPress (r2613)
       
    19  *
       
    20  * @uses bbp_admin_repair_list() To get the recount list
       
    21  * @uses check_admin_referer() To verify the nonce and the referer
       
    22  * @uses wp_cache_flush() To flush the cache
       
    23  * @uses do_action() Calls 'admin_notices' to display the notices
       
    24  * @uses screen_icon() To display the screen icon
       
    25  * @uses wp_nonce_field() To add a hidden nonce field
       
    26  */
       
    27 function bbp_admin_repair() {
       
    28 ?>
       
    29 
       
    30 	<div class="wrap">
       
    31 
       
    32 		<?php screen_icon( 'tools' ); ?>
       
    33 
       
    34 		<h2 class="nav-tab-wrapper"><?php bbp_tools_admin_tabs( __( 'Repair Forums', 'bbpress' ) ); ?></h2>
       
    35 
       
    36 		<p><?php _e( 'bbPress keeps track of relationships between forums, topics, replies, and topic tags, and users. Occasionally these relationships become out of sync, most often after an import or migration. Use the tools below to manually recalculate these relationships.', 'bbpress' ); ?></p>
       
    37 		<p class="description"><?php _e( 'Some of these tools create substantial database overhead. Avoid running more than 1 repair job at a time.', 'bbpress' ); ?></p>
       
    38 
       
    39 		<form class="settings" method="post" action="">
       
    40 			<table class="form-table">
       
    41 				<tbody>
       
    42 					<tr valign="top">
       
    43 						<th scope="row"><?php _e( 'Relationships to Repair:', 'bbpress' ) ?></th>
       
    44 						<td>
       
    45 							<fieldset>
       
    46 								<legend class="screen-reader-text"><span><?php _e( 'Repair', 'bbpress' ) ?></span></legend>
       
    47 
       
    48 								<?php foreach ( bbp_admin_repair_list() as $item ) : ?>
       
    49 
       
    50 									<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 />
       
    51 
       
    52 								<?php endforeach; ?>
       
    53 
       
    54 							</fieldset>
       
    55 						</td>
       
    56 					</tr>
       
    57 				</tbody>
       
    58 			</table>
       
    59 
       
    60 			<fieldset class="submit">
       
    61 				<input class="button-primary" type="submit" name="submit" value="<?php esc_attr_e( 'Repair Items', 'bbpress' ); ?>" />
       
    62 				<?php wp_nonce_field( 'bbpress-do-counts' ); ?>
       
    63 			</fieldset>
       
    64 		</form>
       
    65 	</div>
       
    66 
       
    67 <?php
       
    68 }
       
    69 
       
    70 /**
       
    71  * Handle the processing and feedback of the admin tools page
       
    72  *
       
    73  * @since bbPress (r2613)
       
    74  *
       
    75  * @uses bbp_admin_repair_list() To get the recount list
       
    76  * @uses check_admin_referer() To verify the nonce and the referer
       
    77  * @uses wp_cache_flush() To flush the cache
       
    78  * @uses do_action() Calls 'admin_notices' to display the notices
       
    79  */
       
    80 function bbp_admin_repair_handler() {
       
    81 
       
    82 	if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) ) {
       
    83 		check_admin_referer( 'bbpress-do-counts' );
       
    84 
       
    85 		// Stores messages
       
    86 		$messages = array();
       
    87 
       
    88 		wp_cache_flush();
       
    89 
       
    90 		foreach ( (array) bbp_admin_repair_list() as $item ) {
       
    91 			if ( isset( $item[2] ) && isset( $_POST[$item[0]] ) && 1 == $_POST[$item[0]] && is_callable( $item[2] ) ) {
       
    92 				$messages[] = call_user_func( $item[2] );
       
    93 			}
       
    94 		}
       
    95 
       
    96 		if ( count( $messages ) ) {
       
    97 			foreach ( $messages as $message ) {
       
    98 				bbp_admin_tools_feedback( $message[1] );
       
    99 			}
       
   100 		}
       
   101 	}
       
   102 }
       
   103 
       
   104 /**
       
   105  * Assemble the admin notices
       
   106  *
       
   107  * @since bbPress (r2613)
       
   108  *
       
   109  * @param string|WP_Error $message A message to be displayed or {@link WP_Error}
       
   110  * @param string $class Optional. A class to be added to the message div
       
   111  * @uses WP_Error::get_error_messages() To get the error messages of $message
       
   112  * @uses add_action() Adds the admin notice action with the message HTML
       
   113  * @return string The message HTML
       
   114  */
       
   115 function bbp_admin_tools_feedback( $message, $class = false ) {
       
   116 	if ( is_string( $message ) ) {
       
   117 		$message = '<p>' . $message . '</p>';
       
   118 		$class = $class ? $class : 'updated';
       
   119 	} elseif ( is_wp_error( $message ) ) {
       
   120 		$errors = $message->get_error_messages();
       
   121 
       
   122 		switch ( count( $errors ) ) {
       
   123 			case 0:
       
   124 				return false;
       
   125 				break;
       
   126 
       
   127 			case 1:
       
   128 				$message = '<p>' . $errors[0] . '</p>';
       
   129 				break;
       
   130 
       
   131 			default:
       
   132 				$message = '<ul>' . "\n\t" . '<li>' . join( '</li>' . "\n\t" . '<li>', $errors ) . '</li>' . "\n" . '</ul>';
       
   133 				break;
       
   134 		}
       
   135 
       
   136 		$class = $class ? $class : 'error';
       
   137 	} else {
       
   138 		return false;
       
   139 	}
       
   140 
       
   141 	$message = '<div id="message" class="' . esc_attr( $class ) . '">' . $message . '</div>';
       
   142 	$message = str_replace( "'", "\'", $message );
       
   143 	$lambda  = create_function( '', "echo '$message';" );
       
   144 
       
   145 	add_action( 'admin_notices', $lambda );
       
   146 
       
   147 	return $lambda;
       
   148 }
       
   149 
       
   150 /**
       
   151  * Get the array of the repair list
       
   152  *
       
   153  * @since bbPress (r2613)
       
   154  *
       
   155  * @uses apply_filters() Calls 'bbp_repair_list' with the list array
       
   156  * @return array Repair list of options
       
   157  */
       
   158 function bbp_admin_repair_list() {
       
   159 	$repair_list = array(
       
   160 		0  => array( 'bbp-sync-topic-meta',        __( 'Recalculate the parent topic for each post',          'bbpress' ), 'bbp_admin_repair_topic_meta'               ),
       
   161 		5  => array( 'bbp-sync-forum-meta',        __( 'Recalculate the parent forum for each post',          'bbpress' ), 'bbp_admin_repair_forum_meta'               ),
       
   162 		10 => array( 'bbp-sync-forum-visibility',  __( 'Recalculate private and hidden forums',               'bbpress' ), 'bbp_admin_repair_forum_visibility'         ),
       
   163 		15 => array( 'bbp-sync-all-topics-forums', __( 'Recalculate last activity in each topic and forum',   'bbpress' ), 'bbp_admin_repair_freshness'                ),
       
   164 		20 => array( 'bbp-group-forums',           __( 'Repair BuddyPress Group Forum relationships',         'bbpress' ), 'bbp_admin_repair_group_forum_relationship' ),
       
   165 		25 => array( 'bbp-forum-topics',           __( 'Count topics in each forum',                          'bbpress' ), 'bbp_admin_repair_forum_topic_count'        ),
       
   166 		30 => array( 'bbp-forum-replies',          __( 'Count replies in each forum',                         'bbpress' ), 'bbp_admin_repair_forum_reply_count'        ),
       
   167 		35 => array( 'bbp-topic-replies',          __( 'Count replies in each topic',                         'bbpress' ), 'bbp_admin_repair_topic_reply_count'        ),
       
   168 		40 => array( 'bbp-topic-voices',           __( 'Count voices in each topic',                          'bbpress' ), 'bbp_admin_repair_topic_voice_count'        ),
       
   169 		45 => array( 'bbp-topic-hidden-replies',   __( 'Count spammed & trashed replies in each topic',       'bbpress' ), 'bbp_admin_repair_topic_hidden_reply_count' ),
       
   170 		50 => array( 'bbp-user-replies',           __( 'Count topics for each user',                          'bbpress' ), 'bbp_admin_repair_user_topic_count'         ),
       
   171 		55 => array( 'bbp-user-topics',            __( 'Count replies for each user',                         'bbpress' ), 'bbp_admin_repair_user_reply_count'         ),
       
   172 		60 => array( 'bbp-user-favorites',         __( 'Remove trashed topics from user favorites',           'bbpress' ), 'bbp_admin_repair_user_favorites'           ),
       
   173 		65 => array( 'bbp-user-subscriptions',     __( 'Remove trashed topics from user subscriptions',       'bbpress' ), 'bbp_admin_repair_user_subscriptions'       ),
       
   174 		70 => array( 'bbp-user-role-map',          __( 'Remap existing users to default forum roles',         'bbpress' ), 'bbp_admin_repair_user_roles'               )
       
   175 	);
       
   176 	ksort( $repair_list );
       
   177 
       
   178 	return (array) apply_filters( 'bbp_repair_list', $repair_list );
       
   179 }
       
   180 
       
   181 /**
       
   182  * Recount topic replies
       
   183  *
       
   184  * @since bbPress (r2613)
       
   185  *
       
   186  * @uses bbp_get_reply_post_type() To get the reply post type
       
   187  * @uses wpdb::query() To run our recount sql queries
       
   188  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   189  * @return array An array of the status code and the message
       
   190  */
       
   191 function bbp_admin_repair_topic_reply_count() {
       
   192 	global $wpdb;
       
   193 
       
   194 	$statement = __( 'Counting the number of replies in each topic&hellip; %s', 'bbpress' );
       
   195 	$result    = __( 'Failed!', 'bbpress' );
       
   196 
       
   197 	$sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `meta_key` = '_bbp_reply_count';";
       
   198 	if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
       
   199 		return array( 1, sprintf( $statement, $result ) );
       
   200 
       
   201 	// Post types and status
       
   202 	$tpt = bbp_get_topic_post_type();
       
   203 	$rpt = bbp_get_reply_post_type();
       
   204 	$pps = bbp_get_public_status_id();
       
   205 	$cps = bbp_get_closed_status_id();
       
   206 
       
   207 	$sql = "INSERT INTO `{$wpdb->postmeta}` (`post_id`, `meta_key`, `meta_value`) (
       
   208 			SELECT `topics`.`ID` AS `post_id`, '_bbp_reply_count' AS `meta_key`, COUNT(`replies`.`ID`) As `meta_value`
       
   209 				FROM `{$wpdb->posts}` AS `topics`
       
   210 					LEFT JOIN `{$wpdb->posts}` as `replies`
       
   211 						ON  `replies`.`post_parent` = `topics`.`ID`
       
   212 						AND `replies`.`post_status` = '{$pps}'
       
   213 						AND `replies`.`post_type`   = '{$rpt}'
       
   214 				WHERE `topics`.`post_type` = '{$tpt}'
       
   215 					AND `topics`.`post_status` IN ( '{$pps}', '{$cps}' )
       
   216 				GROUP BY `topics`.`ID`);";
       
   217 
       
   218 	if ( is_wp_error( $wpdb->query( $sql ) ) )
       
   219 		return array( 2, sprintf( $statement, $result ) );
       
   220 
       
   221 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   222 }
       
   223 
       
   224 /**
       
   225  * Recount topic voices
       
   226  *
       
   227  * @since bbPress (r2613)
       
   228  *
       
   229  * @uses bbp_get_reply_post_type() To get the reply post type
       
   230  * @uses wpdb::query() To run our recount sql queries
       
   231  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   232  * @return array An array of the status code and the message
       
   233  */
       
   234 function bbp_admin_repair_topic_voice_count() {
       
   235 	global $wpdb;
       
   236 
       
   237 	$statement = __( 'Counting the number of voices in each topic&hellip; %s', 'bbpress' );
       
   238 	$result    = __( 'Failed!', 'bbpress' );
       
   239 
       
   240 	$sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `meta_key` = '_bbp_voice_count';";
       
   241 	if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
       
   242 		return array( 1, sprintf( $statement, $result ) );
       
   243 
       
   244 	// Post types and status
       
   245 	$tpt = bbp_get_topic_post_type();
       
   246 	$rpt = bbp_get_reply_post_type();
       
   247 	$pps = bbp_get_public_status_id();
       
   248 	$cps = bbp_get_closed_status_id();
       
   249 
       
   250 	$sql = "INSERT INTO `{$wpdb->postmeta}` (`post_id`, `meta_key`, `meta_value`) (
       
   251 			SELECT `postmeta`.`meta_value`, '_bbp_voice_count', COUNT(DISTINCT `post_author`) as `meta_value`
       
   252 				FROM `{$wpdb->posts}` AS `posts`
       
   253 				LEFT JOIN `{$wpdb->postmeta}` AS `postmeta`
       
   254 					ON `posts`.`ID` = `postmeta`.`post_id`
       
   255 					AND `postmeta`.`meta_key` = '_bbp_topic_id'
       
   256 				WHERE `posts`.`post_type` IN ( '{$tpt}', '{$rpt}' )
       
   257 					AND `posts`.`post_status` IN ( '{$pps}', '{$cps}' )
       
   258 					AND `posts`.`post_author` != '0'
       
   259 				GROUP BY `postmeta`.`meta_value`);";
       
   260 
       
   261 	if ( is_wp_error( $wpdb->query( $sql ) ) )
       
   262 		return array( 2, sprintf( $statement, $result ) );
       
   263 
       
   264 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   265 }
       
   266 
       
   267 /**
       
   268  * Recount topic hidden replies (spammed/trashed)
       
   269  *
       
   270  * @since bbPress (r2747)
       
   271  *
       
   272  * @uses wpdb::query() To run our recount sql queries
       
   273  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   274  * @return array An array of the status code and the message
       
   275  */
       
   276 function bbp_admin_repair_topic_hidden_reply_count() {
       
   277 	global $wpdb;
       
   278 
       
   279 	$statement = __( 'Counting the number of spammed and trashed replies in each topic&hellip; %s', 'bbpress' );
       
   280 	$result    = __( 'Failed!', 'bbpress' );
       
   281 
       
   282 	$sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `meta_key` = '_bbp_reply_count_hidden';";
       
   283 	if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
       
   284 		return array( 1, sprintf( $statement, $result ) );
       
   285 
       
   286 	$sql = "INSERT INTO `{$wpdb->postmeta}` (`post_id`, `meta_key`, `meta_value`) (SELECT `post_parent`, '_bbp_reply_count_hidden', COUNT(`post_status`) as `meta_value` FROM `{$wpdb->posts}` WHERE `post_type` = '" . bbp_get_reply_post_type() . "' AND `post_status` IN ( '" . join( "','", array( bbp_get_trash_status_id(), bbp_get_spam_status_id() ) ) . "') GROUP BY `post_parent`);";
       
   287 	if ( is_wp_error( $wpdb->query( $sql ) ) )
       
   288 		return array( 2, sprintf( $statement, $result ) );
       
   289 
       
   290 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   291 }
       
   292 
       
   293 /**
       
   294  * Repair group forum ID mappings after a bbPress 1.1 to bbPress 2.2 conversion
       
   295  *
       
   296  * @since bbPress (r4395)
       
   297  *
       
   298  * @global WPDB $wpdb
       
   299  * @return If a wp_error() occurs and no converted forums are found
       
   300  */
       
   301 function bbp_admin_repair_group_forum_relationship() {
       
   302 	global $wpdb;
       
   303 
       
   304 	$statement = __( 'Repairing BuddyPress group-forum relationships&hellip; %s', 'bbpress' );
       
   305 	$g_count     = 0;
       
   306 	$f_count     = 0;
       
   307 
       
   308 	// Copy the BuddyPress filter here, incase BuddyPress is not active
       
   309 	$prefix    = apply_filters( 'bp_core_get_table_prefix', $wpdb->base_prefix );
       
   310 	$tablename = $prefix . 'bp_groups_groupmeta';
       
   311 
       
   312 	// Get the converted forum IDs
       
   313 	$forum_ids = $wpdb->query( "SELECT `forum`.`ID`, `forummeta`.`meta_value`
       
   314 								FROM `{$wpdb->posts}` AS `forum`
       
   315 									LEFT JOIN `{$wpdb->postmeta}` AS `forummeta`
       
   316 										ON `forum`.`ID` = `forummeta`.`post_id`
       
   317 										AND `forummeta`.`meta_key` = '_bbp_old_forum_id'
       
   318 								WHERE `forum`.`post_type` = 'forum'
       
   319 								GROUP BY `forum`.`ID`;" );
       
   320 
       
   321 	// Bail if forum IDs returned an error
       
   322 	if ( is_wp_error( $forum_ids ) || empty( $wpdb->last_result ) )
       
   323 		return array( 2, sprintf( $statement, __( 'Failed!', 'bbpress' ) ) );
       
   324 
       
   325 	// Stash the last results
       
   326 	$results = $wpdb->last_result;
       
   327 
       
   328 	// Update each group forum
       
   329 	foreach ( $results as $group_forums ) {
       
   330 
       
   331 		// Only update if is a converted forum
       
   332 		if ( ! isset( $group_forums->meta_value ) )
       
   333 			continue;
       
   334 
       
   335 		// Attempt to update group meta
       
   336 		$updated = $wpdb->query( "UPDATE `{$tablename}` SET `meta_value` = '{$group_forums->ID}' WHERE `meta_key` = 'forum_id' AND `meta_value` = '{$group_forums->meta_value}';" );
       
   337 
       
   338 		// Bump the count
       
   339 		if ( !empty( $updated ) && ! is_wp_error( $updated ) ) {
       
   340 			++$g_count;
       
   341 		}
       
   342 
       
   343 		// Update group's forum metadata
       
   344 		$group_id = (int) $wpdb->get_var( "SELECT `group_id` FROM `{$tablename}` WHERE `meta_key` = 'forum_id' AND `meta_value` = '{$group_forums->ID}';" );
       
   345 		if ( !empty( $group_id ) ) {
       
   346 			update_post_meta( $group_forums->ID, '_bbp_group_ids', array( $group_id ) );
       
   347 			++$f_count;
       
   348 		}
       
   349 	}
       
   350 
       
   351 	// Make some logical guesses at the old group root forum
       
   352 	if ( function_exists( 'bp_forums_parent_forum_id' ) ) {
       
   353 		$old_default_forum_id = bp_forums_parent_forum_id();
       
   354 	} elseif ( defined( 'BP_FORUMS_PARENT_FORUM_ID' ) ) {
       
   355 		$old_default_forum_id = (int) BP_FORUMS_PARENT_FORUM_ID;
       
   356 	} else {
       
   357 		$old_default_forum_id = 1;
       
   358 	}
       
   359 
       
   360 	// Try to get the group root forum
       
   361 	$posts = get_posts( array(
       
   362 		'post_type'   => bbp_get_forum_post_type(),
       
   363 		'meta_key'    => '_bbp_old_forum_id',
       
   364 		'meta_value'  => $old_default_forum_id,
       
   365 		'numberposts' => 1
       
   366 	) );
       
   367 
       
   368 	// Found the group root forum
       
   369 	if ( ! empty( $posts ) ) {
       
   370 
       
   371 		// Rename 'Default Forum'  since it's now visible in sitewide forums
       
   372 		if ( 'Default Forum' == $posts[0]->post_title ) {
       
   373 			wp_update_post( array(
       
   374 				'ID'         => $posts[0]->ID,
       
   375 				'post_title' => __( 'Group Forums', 'bbpress' ),
       
   376 			) );
       
   377 		}
       
   378 
       
   379 		// Update the group forums root metadata
       
   380 		update_option( '_bbp_group_forums_root_id', $posts[0]->ID );
       
   381 	}
       
   382 
       
   383 	// Complete results
       
   384 	$result = sprintf( __( 'Complete! %s groups updated; %s forums updated.', 'bbpress' ), bbp_number_format( $g_count ), bbp_number_format( $f_count ) );
       
   385 	return array( 0, sprintf( $statement, $result ) );
       
   386 }
       
   387 
       
   388 /**
       
   389  * Recount forum topics
       
   390  *
       
   391  * @since bbPress (r2613)
       
   392  *
       
   393  * @uses wpdb::query() To run our recount sql queries
       
   394  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   395  * @uses bbp_get_forum_post_type() To get the forum post type
       
   396  * @uses get_posts() To get the forums
       
   397  * @uses bbp_update_forum_topic_count() To update the forum topic count
       
   398  * @return array An array of the status code and the message
       
   399  */
       
   400 function bbp_admin_repair_forum_topic_count() {
       
   401 	global $wpdb;
       
   402 
       
   403 	$statement = __( 'Counting the number of topics in each forum&hellip; %s', 'bbpress' );
       
   404 	$result    = __( 'Failed!', 'bbpress' );
       
   405 
       
   406 	$sql_delete = "DELETE FROM {$wpdb->postmeta} WHERE meta_key IN ( '_bbp_topic_count', '_bbp_total_topic_count' );";
       
   407 	if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
       
   408 		return array( 1, sprintf( $statement, $result ) );
       
   409 
       
   410 	$forums = get_posts( array( 'post_type' => bbp_get_forum_post_type(), 'numberposts' => -1 ) );
       
   411 	if ( !empty( $forums ) ) {
       
   412 		foreach( $forums as $forum ) {
       
   413 			bbp_update_forum_topic_count( $forum->ID );
       
   414 		}
       
   415 	} else {
       
   416 		return array( 2, sprintf( $statement, $result ) );
       
   417 	}
       
   418 
       
   419 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   420 }
       
   421 
       
   422 /**
       
   423  * Recount forum replies
       
   424  *
       
   425  * @since bbPress (r2613)
       
   426  *
       
   427  * @uses wpdb::query() To run our recount sql queries
       
   428  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   429  * @uses bbp_get_forum_post_type() To get the forum post type
       
   430  * @uses get_posts() To get the forums
       
   431  * @uses bbp_update_forum_reply_count() To update the forum reply count
       
   432  * @return array An array of the status code and the message
       
   433  */
       
   434 function bbp_admin_repair_forum_reply_count() {
       
   435 	global $wpdb;
       
   436 
       
   437 	$statement = __( 'Counting the number of replies in each forum&hellip; %s', 'bbpress' );
       
   438 	$result    = __( 'Failed!', 'bbpress' );
       
   439 
       
   440 	$sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `meta_key` IN ( '_bbp_reply_count', '_bbp_total_reply_count' );";
       
   441 	if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
       
   442 		return array( 1, sprintf( $statement, $result ) );
       
   443 
       
   444 	$forums = get_posts( array( 'post_type' => bbp_get_forum_post_type(), 'numberposts' => -1 ) );
       
   445 	if ( !empty( $forums ) ) {
       
   446 		foreach( $forums as $forum ) {
       
   447 			bbp_update_forum_reply_count( $forum->ID );
       
   448 		}
       
   449 	} else {
       
   450 		return array( 2, sprintf( $statement, $result ) );
       
   451 	}
       
   452 
       
   453 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   454 }
       
   455 
       
   456 /**
       
   457  * Recount topics by the users
       
   458  *
       
   459  * @since bbPress (r3889)
       
   460  *
       
   461  * @uses bbp_get_reply_post_type() To get the reply post type
       
   462  * @uses wpdb::query() To run our recount sql queries
       
   463  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   464  * @return array An array of the status code and the message
       
   465  */
       
   466 function bbp_admin_repair_user_topic_count() {
       
   467 	global $wpdb;
       
   468 
       
   469 	$statement   = __( 'Counting the number of topics each user has created&hellip; %s', 'bbpress' );
       
   470 	$result      = __( 'Failed!', 'bbpress' );
       
   471 	$sql_select  = "SELECT `post_author`, COUNT(DISTINCT `ID`) as `_count` FROM `{$wpdb->posts}` WHERE `post_type` = '" . bbp_get_topic_post_type() . "' AND `post_status` = '" . bbp_get_public_status_id() . "' GROUP BY `post_author`;";
       
   472 	$insert_rows = $wpdb->get_results( $sql_select );
       
   473 
       
   474 	if ( is_wp_error( $insert_rows ) )
       
   475 		return array( 1, sprintf( $statement, $result ) );
       
   476 
       
   477 	$key           = $wpdb->prefix . '_bbp_topic_count';
       
   478 	$insert_values = array();
       
   479 	foreach ( $insert_rows as $insert_row )
       
   480 		$insert_values[] = "('{$insert_row->post_author}', '{$key}', '{$insert_row->_count}')";
       
   481 
       
   482 	if ( !count( $insert_values ) )
       
   483 		return array( 2, sprintf( $statement, $result ) );
       
   484 
       
   485 	$sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';";
       
   486 	if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
       
   487 		return array( 3, sprintf( $statement, $result ) );
       
   488 
       
   489 	foreach ( array_chunk( $insert_values, 10000 ) as $chunk ) {
       
   490 		$chunk = "\n" . join( ",\n", $chunk );
       
   491 		$sql_insert = "INSERT INTO `{$wpdb->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES $chunk;";
       
   492 
       
   493 		if ( is_wp_error( $wpdb->query( $sql_insert ) ) ) {
       
   494 			return array( 4, sprintf( $statement, $result ) );
       
   495 		}
       
   496 	}
       
   497 
       
   498 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   499 }
       
   500 
       
   501 /**
       
   502  * Recount topic replied by the users
       
   503  *
       
   504  * @since bbPress (r2613)
       
   505  *
       
   506  * @uses bbp_get_reply_post_type() To get the reply post type
       
   507  * @uses wpdb::query() To run our recount sql queries
       
   508  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   509  * @return array An array of the status code and the message
       
   510  */
       
   511 function bbp_admin_repair_user_reply_count() {
       
   512 	global $wpdb;
       
   513 
       
   514 	$statement   = __( 'Counting the number of topics to which each user has replied&hellip; %s', 'bbpress' );
       
   515 	$result      = __( 'Failed!', 'bbpress' );
       
   516 	$sql_select  = "SELECT `post_author`, COUNT(DISTINCT `ID`) as `_count` FROM `{$wpdb->posts}` WHERE `post_type` = '" . bbp_get_reply_post_type() . "' AND `post_status` = '" . bbp_get_public_status_id() . "' GROUP BY `post_author`;";
       
   517 	$insert_rows = $wpdb->get_results( $sql_select );
       
   518 
       
   519 	if ( is_wp_error( $insert_rows ) )
       
   520 		return array( 1, sprintf( $statement, $result ) );
       
   521 
       
   522 	$key           = $wpdb->prefix . '_bbp_reply_count';
       
   523 	$insert_values = array();
       
   524 	foreach ( $insert_rows as $insert_row )
       
   525 		$insert_values[] = "('{$insert_row->post_author}', '{$key}', '{$insert_row->_count}')";
       
   526 
       
   527 	if ( !count( $insert_values ) )
       
   528 		return array( 2, sprintf( $statement, $result ) );
       
   529 
       
   530 	$sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';";
       
   531 	if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
       
   532 		return array( 3, sprintf( $statement, $result ) );
       
   533 
       
   534 	foreach ( array_chunk( $insert_values, 10000 ) as $chunk ) {
       
   535 		$chunk = "\n" . join( ",\n", $chunk );
       
   536 		$sql_insert = "INSERT INTO `{$wpdb->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES $chunk;";
       
   537 
       
   538 		if ( is_wp_error( $wpdb->query( $sql_insert ) ) ) {
       
   539 			return array( 4, sprintf( $statement, $result ) );
       
   540 		}
       
   541 	}
       
   542 
       
   543 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   544 }
       
   545 
       
   546 /**
       
   547  * Clean the users' favorites
       
   548  *
       
   549  * @since bbPress (r2613)
       
   550  *
       
   551  * @uses bbp_get_topic_post_type() To get the topic post type
       
   552  * @uses wpdb::query() To run our recount sql queries
       
   553  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   554  * @return array An array of the status code and the message
       
   555  */
       
   556 function bbp_admin_repair_user_favorites() {
       
   557 	global $wpdb;
       
   558 
       
   559 	$statement = __( 'Removing trashed topics from user favorites&hellip; %s', 'bbpress' );
       
   560 	$result    = __( 'Failed!', 'bbpress' );
       
   561 	$key       = $wpdb->prefix . '_bbp_favorites';
       
   562 	$users     = $wpdb->get_results( "SELECT `user_id`, `meta_value` AS `favorites` FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';" );
       
   563 
       
   564 	if ( is_wp_error( $users ) )
       
   565 		return array( 1, sprintf( $statement, $result ) );
       
   566 
       
   567 	$topics = $wpdb->get_col( "SELECT `ID` FROM `{$wpdb->posts}` WHERE `post_type` = '" . bbp_get_topic_post_type() . "' AND `post_status` = '" . bbp_get_public_status_id() . "';" );
       
   568 
       
   569 	if ( is_wp_error( $topics ) )
       
   570 		return array( 2, sprintf( $statement, $result ) );
       
   571 
       
   572 	$values = array();
       
   573 	foreach ( $users as $user ) {
       
   574 		if ( empty( $user->favorites ) || !is_string( $user->favorites ) )
       
   575 			continue;
       
   576 
       
   577 		$favorites = array_intersect( $topics, (array) explode( ',', $user->favorites ) );
       
   578 		if ( empty( $favorites ) || !is_array( $favorites ) )
       
   579 			continue;
       
   580 
       
   581 		$favorites_joined = join( ',', $favorites );
       
   582 		$values[]         = "('{$user->user_id}', '{$key}, '{$favorites_joined}')";
       
   583 
       
   584 		// Cleanup
       
   585 		unset( $favorites, $favorites_joined );
       
   586 	}
       
   587 
       
   588 	if ( !count( $values ) ) {
       
   589 		$result = __( 'Nothing to remove!', 'bbpress' );
       
   590 		return array( 0, sprintf( $statement, $result ) );
       
   591 	}
       
   592 
       
   593 	$sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';";
       
   594 	if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
       
   595 		return array( 4, sprintf( $statement, $result ) );
       
   596 
       
   597 	foreach ( array_chunk( $values, 10000 ) as $chunk ) {
       
   598 		$chunk = "\n" . join( ",\n", $chunk );
       
   599 		$sql_insert = "INSERT INTO `$wpdb->usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES $chunk;";
       
   600 		if ( is_wp_error( $wpdb->query( $sql_insert ) ) ) {
       
   601 			return array( 5, sprintf( $statement, $result ) );
       
   602 		}
       
   603 	}
       
   604 
       
   605 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   606 }
       
   607 
       
   608 /**
       
   609  * Clean the users' subscriptions
       
   610  *
       
   611  * @since bbPress (r2668)
       
   612  *
       
   613  * @uses bbp_get_topic_post_type() To get the topic post type
       
   614  * @uses wpdb::query() To run our recount sql queries
       
   615  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   616  * @return array An array of the status code and the message
       
   617  */
       
   618 function bbp_admin_repair_user_subscriptions() {
       
   619 	global $wpdb;
       
   620 
       
   621 	$statement = __( 'Removing trashed topics from user subscriptions&hellip; %s', 'bbpress' );
       
   622 	$result    = __( 'Failed!', 'bbpress' );
       
   623 	$key       = $wpdb->prefix . '_bbp_subscriptions';
       
   624 	$users     = $wpdb->get_results( "SELECT `user_id`, `meta_value` AS `subscriptions` FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';" );
       
   625 
       
   626 	if ( is_wp_error( $users ) )
       
   627 		return array( 1, sprintf( $statement, $result ) );
       
   628 
       
   629 	$topics = $wpdb->get_col( "SELECT `ID` FROM `{$wpdb->posts}` WHERE `post_type` = '" . bbp_get_topic_post_type() . "' AND `post_status` = '" . bbp_get_public_status_id() . "';" );
       
   630 	if ( is_wp_error( $topics ) )
       
   631 		return array( 2, sprintf( $statement, $result ) );
       
   632 
       
   633 	$values = array();
       
   634 	foreach ( $users as $user ) {
       
   635 		if ( empty( $user->subscriptions ) || !is_string( $user->subscriptions ) )
       
   636 			continue;
       
   637 
       
   638 		$subscriptions = array_intersect( $topics, (array) explode( ',', $user->subscriptions ) );
       
   639 		if ( empty( $subscriptions ) || !is_array( $subscriptions ) )
       
   640 			continue;
       
   641 
       
   642 		$subscriptions_joined = join( ',', $subscriptions );
       
   643 		$values[]             = "('{$user->user_id}', '{$key}', '{$subscriptions_joined}')";
       
   644 
       
   645 		// Cleanup
       
   646 		unset( $subscriptions, $subscriptions_joined );
       
   647 	}
       
   648 
       
   649 	if ( !count( $values ) ) {
       
   650 		$result = __( 'Nothing to remove!', 'bbpress' );
       
   651 		return array( 0, sprintf( $statement, $result ) );
       
   652 	}
       
   653 
       
   654 	$sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';";
       
   655 	if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
       
   656 		return array( 4, sprintf( $statement, $result ) );
       
   657 
       
   658 	foreach ( array_chunk( $values, 10000 ) as $chunk ) {
       
   659 		$chunk = "\n" . join( ",\n", $chunk );
       
   660 		$sql_insert = "INSERT INTO `{$wpdb->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES $chunk;";
       
   661 		if ( is_wp_error( $wpdb->query( $sql_insert ) ) ) {
       
   662 			return array( 5, sprintf( $statement, $result ) );
       
   663 		}
       
   664 	}
       
   665 
       
   666 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   667 }
       
   668 
       
   669 /**
       
   670  * This repair tool will map each user of the current site to their respective
       
   671  * forums role. By default, Admins will be Key Masters, and every other role
       
   672  * will be the default role defined in Settings > Forums (Participant).
       
   673  *
       
   674  * @since bbPress (r4340)
       
   675  *
       
   676  * @uses bbp_get_user_role_map() To get the map of user roles
       
   677  * @uses get_editable_roles() To get the current WordPress roles
       
   678  * @uses get_users() To get the users of each role (limited to ID field)
       
   679  * @uses bbp_set_user_role() To set each user's forums role
       
   680  */
       
   681 function bbp_admin_repair_user_roles() {
       
   682 
       
   683 	$statement    = __( 'Remapping forum role for each user on this site&hellip; %s', 'bbpress' );
       
   684 	$changed      = 0;
       
   685 	$role_map     = bbp_get_user_role_map();
       
   686 	$default_role = bbp_get_default_role();
       
   687 
       
   688 	// Bail if no role map exists
       
   689 	if ( empty( $role_map ) )
       
   690 		return array( 1, sprintf( $statement, __( 'Failed!', 'bbpress' ) ) );
       
   691 
       
   692 	// Iterate through each role...
       
   693 	foreach ( array_keys( get_editable_roles() ) as $role ) {
       
   694 
       
   695 		// Reset the offset
       
   696 		$offset = 0;
       
   697 
       
   698 		// If no role map exists, give the default forum role (bbp-participant)
       
   699 		$new_role = isset( $role_map[$role] ) ? $role_map[$role] : $default_role;
       
   700 			
       
   701 		// Get users of this site, limited to 1000
       
   702 		while ( $users = get_users( array(
       
   703 				'role'   => $role,
       
   704 				'fields' => 'ID',
       
   705 				'number' => 1000,
       
   706 				'offset' => $offset
       
   707 			) ) ) {
       
   708 
       
   709 			// Iterate through each user of $role and try to set it
       
   710 			foreach ( (array) $users as $user_id ) {
       
   711 				if ( bbp_set_user_role( $user_id, $new_role ) ) {
       
   712 					++$changed; // Keep a count to display at the end
       
   713 				}
       
   714 			}
       
   715 
       
   716 			// Bump the offset for the next query iteration
       
   717 			$offset = $offset + 1000;
       
   718 		}
       
   719 	}
       
   720 
       
   721 	$result = sprintf( __( 'Complete! %s users updated.', 'bbpress' ), bbp_number_format( $changed ) );
       
   722 	return array( 0, sprintf( $statement, $result ) );
       
   723 }
       
   724 
       
   725 /**
       
   726  * Recaches the last post in every topic and forum
       
   727  *
       
   728  * @since bbPress (r3040)
       
   729  *
       
   730  * @uses wpdb::query() To run our recount sql queries
       
   731  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   732  * @return array An array of the status code and the message
       
   733  */
       
   734 function bbp_admin_repair_freshness() {
       
   735 	global $wpdb;
       
   736 
       
   737 	$statement = __( 'Recomputing latest post in every topic and forum&hellip; %s', 'bbpress' );
       
   738 	$result    = __( 'Failed!', 'bbpress' );
       
   739 
       
   740 	// First, delete everything.
       
   741 	if ( is_wp_error( $wpdb->query( "DELETE FROM `$wpdb->postmeta` WHERE `meta_key` IN ( '_bbp_last_reply_id', '_bbp_last_topic_id', '_bbp_last_active_id', '_bbp_last_active_time' );" ) ) )
       
   742 		return array( 1, sprintf( $statement, $result ) );
       
   743 
       
   744 	// Next, give all the topics with replies the ID their last reply.
       
   745 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   746 			( SELECT `topic`.`ID`, '_bbp_last_reply_id', MAX( `reply`.`ID` )
       
   747 			FROM `$wpdb->posts` AS `topic` INNER JOIN `$wpdb->posts` AS `reply` ON `topic`.`ID` = `reply`.`post_parent`
       
   748 			WHERE `reply`.`post_status` IN ( '" . bbp_get_public_status_id() . "' ) AND `topic`.`post_type` = 'topic' AND `reply`.`post_type` = 'reply'
       
   749 			GROUP BY `topic`.`ID` );" ) ) )
       
   750 		return array( 2, sprintf( $statement, $result ) );
       
   751 
       
   752 	// For any remaining topics, give a reply ID of 0.
       
   753 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   754 			( SELECT `ID`, '_bbp_last_reply_id', 0
       
   755 			FROM `$wpdb->posts` AS `topic` LEFT JOIN `$wpdb->postmeta` AS `reply`
       
   756 			ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_reply_id'
       
   757 			WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = 'topic' );" ) ) )
       
   758 		return array( 3, sprintf( $statement, $result ) );
       
   759 
       
   760 	// Now we give all the forums with topics the ID their last topic.
       
   761 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   762 			( SELECT `forum`.`ID`, '_bbp_last_topic_id', `topic`.`ID`
       
   763 			FROM `$wpdb->posts` AS `forum` INNER JOIN `$wpdb->posts` AS `topic` ON `forum`.`ID` = `topic`.`post_parent`
       
   764 			WHERE `topic`.`post_status` IN ( '" . bbp_get_public_status_id() . "' ) AND `forum`.`post_type` = 'forum' AND `topic`.`post_type` = 'topic'
       
   765 			GROUP BY `forum`.`ID` );" ) ) )
       
   766 		return array( 4, sprintf( $statement, $result ) );
       
   767 
       
   768 	// For any remaining forums, give a topic ID of 0.
       
   769 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   770 			( SELECT `ID`, '_bbp_last_topic_id', 0
       
   771 			FROM `$wpdb->posts` AS `forum` LEFT JOIN `$wpdb->postmeta` AS `topic`
       
   772 			ON `forum`.`ID` = `topic`.`post_id` AND `topic`.`meta_key` = '_bbp_last_topic_id'
       
   773 			WHERE `topic`.`meta_id` IS NULL AND `forum`.`post_type` = 'forum' );" ) ) )
       
   774 		return array( 5, sprintf( $statement, $result ) );
       
   775 
       
   776 	// After that, we give all the topics with replies the ID their last reply (again, this time for a different reason).
       
   777 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   778 			( SELECT `topic`.`ID`, '_bbp_last_active_id', MAX( `reply`.`ID` )
       
   779 			FROM `$wpdb->posts` AS `topic` INNER JOIN `$wpdb->posts` AS `reply` ON `topic`.`ID` = `reply`.`post_parent`
       
   780 			WHERE `reply`.`post_status` IN ( '" . bbp_get_public_status_id() . "' ) AND `topic`.`post_type` = 'topic' AND `reply`.`post_type` = 'reply'
       
   781 			GROUP BY `topic`.`ID` );" ) ) )
       
   782 		return array( 6, sprintf( $statement, $result ) );
       
   783 
       
   784 	// For any remaining topics, give a reply ID of themself.
       
   785 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   786 			( SELECT `ID`, '_bbp_last_active_id', `ID`
       
   787 			FROM `$wpdb->posts` AS `topic` LEFT JOIN `$wpdb->postmeta` AS `reply`
       
   788 			ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_active_id'
       
   789 			WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = 'topic' );" ) ) )
       
   790 		return array( 7, sprintf( $statement, $result ) );
       
   791 
       
   792 	// Give topics with replies their last update time.
       
   793 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   794 			( SELECT `topic`.`ID`, '_bbp_last_active_time', MAX( `reply`.`post_date` )
       
   795 			FROM `$wpdb->posts` AS `topic` INNER JOIN `$wpdb->posts` AS `reply` ON `topic`.`ID` = `reply`.`post_parent`
       
   796 			WHERE `reply`.`post_status` IN ( '" . bbp_get_public_status_id() . "' ) AND `topic`.`post_type` = 'topic' AND `reply`.`post_type` = 'reply'
       
   797 			GROUP BY `topic`.`ID` );" ) ) )
       
   798 		return array( 8, sprintf( $statement, $result ) );
       
   799 
       
   800 	// Give topics without replies their last update time.
       
   801 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   802 			( SELECT `ID`, '_bbp_last_active_time', `post_date`
       
   803 			FROM `$wpdb->posts` AS `topic` LEFT JOIN `$wpdb->postmeta` AS `reply`
       
   804 			ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_active_time'
       
   805 			WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = 'topic' );" ) ) )
       
   806 		return array( 9, sprintf( $statement, $result ) );
       
   807 
       
   808 	// Forums need to know what their last active item is as well. Now it gets a bit more complex to do in the database.
       
   809 	$forums = $wpdb->get_col( "SELECT `ID` FROM `$wpdb->posts` WHERE `post_type` = 'forum' and `post_status` != 'auto-draft';" );
       
   810 	if ( is_wp_error( $forums ) )
       
   811 		return array( 10, sprintf( $statement, $result ) );
       
   812 
       
   813  	// Loop through forums
       
   814  	foreach ( $forums as $forum_id ) {
       
   815 		if ( !bbp_is_forum_category( $forum_id ) ) {
       
   816 			bbp_update_forum( array( 'forum_id' => $forum_id ) );
       
   817 		}
       
   818 	}
       
   819 
       
   820 	// Loop through categories when forums are done
       
   821 	foreach ( $forums as $forum_id ) {
       
   822 		if ( bbp_is_forum_category( $forum_id ) ) {
       
   823 			bbp_update_forum( array( 'forum_id' => $forum_id ) );
       
   824 		}
       
   825 	}
       
   826 
       
   827 	// Complete results
       
   828 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   829 }
       
   830 
       
   831 /**
       
   832  * Recaches the private and hidden forums
       
   833  *
       
   834  * @since bbPress (r4104)
       
   835  *
       
   836  * @uses delete_option() to delete private and hidden forum pointers
       
   837  * @uses WP_Query() To query post IDs
       
   838  * @uses is_wp_error() To return if error occurred
       
   839  * @uses update_option() To update the private and hidden post ID pointers
       
   840  * @return array An array of the status code and the message
       
   841  */
       
   842 function bbp_admin_repair_forum_visibility() {
       
   843 
       
   844 	$statement = __( 'Recalculating forum visibility &hellip; %s', 'bbpress' );
       
   845 	$result    = __( 'Failed!', 'bbpress' );
       
   846 
       
   847 	// First, delete everything.
       
   848 	delete_option( '_bbp_private_forums' );
       
   849 	delete_option( '_bbp_hidden_forums'  );
       
   850 
       
   851 	// Next, get all the private and hidden forums
       
   852 	$private_forums = new WP_Query( array(
       
   853 		'suppress_filters' => true,
       
   854 		'nopaging'         => true,
       
   855 		'post_type'        => bbp_get_forum_post_type(),
       
   856 		'post_status'      => bbp_get_private_status_id(),
       
   857 		'fields'           => 'ids'
       
   858 	) );
       
   859 	$hidden_forums = new WP_Query( array(
       
   860 		'suppress_filters' => true,
       
   861 		'nopaging'         => true,
       
   862 		'post_type'        => bbp_get_forum_post_type(),
       
   863 		'post_status'      => bbp_get_hidden_status_id(),
       
   864 		'fields'           => 'ids'
       
   865 	) );
       
   866 
       
   867 	// Bail if queries returned errors
       
   868 	if ( is_wp_error( $private_forums ) || is_wp_error( $hidden_forums ) )
       
   869 		return array( 2, sprintf( $statement, $result ) );
       
   870 
       
   871 	update_option( '_bbp_private_forums', $private_forums->posts ); // Private forums
       
   872 	update_option( '_bbp_hidden_forums',  $hidden_forums->posts  ); // Hidden forums
       
   873 
       
   874 	// Reset the $post global
       
   875 	wp_reset_postdata();
       
   876 
       
   877 	// Complete results
       
   878 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   879 }
       
   880 
       
   881 /**
       
   882  * Recaches the forum for each post
       
   883  *
       
   884  * @since bbPress (r3876)
       
   885  *
       
   886  * @uses wpdb::query() To run our recount sql queries
       
   887  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   888  * @return array An array of the status code and the message
       
   889  */
       
   890 function bbp_admin_repair_forum_meta() {
       
   891 	global $wpdb;
       
   892 
       
   893 	$statement = __( 'Recalculating the forum for each post &hellip; %s', 'bbpress' );
       
   894 	$result    = __( 'Failed!', 'bbpress' );
       
   895 
       
   896 	// First, delete everything.
       
   897 	if ( is_wp_error( $wpdb->query( "DELETE FROM `$wpdb->postmeta` WHERE `meta_key` = '_bbp_forum_id';" ) ) )
       
   898 		return array( 1, sprintf( $statement, $result ) );
       
   899 
       
   900 	// Next, give all the topics with replies the ID their last reply.
       
   901 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   902 			( SELECT `forum`.`ID`, '_bbp_forum_id', `forum`.`post_parent`
       
   903 			FROM `$wpdb->posts`
       
   904 				AS `forum`
       
   905 			WHERE `forum`.`post_type` = 'forum'
       
   906 			GROUP BY `forum`.`ID` );" ) ) )
       
   907 		return array( 2, sprintf( $statement, $result ) );
       
   908 
       
   909 	// Next, give all the topics with replies the ID their last reply.
       
   910 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   911 			( SELECT `topic`.`ID`, '_bbp_forum_id', `topic`.`post_parent`
       
   912 			FROM `$wpdb->posts`
       
   913 				AS `topic`
       
   914 			WHERE `topic`.`post_type` = 'topic'
       
   915 			GROUP BY `topic`.`ID` );" ) ) )
       
   916 		return array( 3, sprintf( $statement, $result ) );
       
   917 
       
   918 	// Next, give all the topics with replies the ID their last reply.
       
   919 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   920 			( SELECT `reply`.`ID`, '_bbp_forum_id', `topic`.`post_parent`
       
   921 			FROM `$wpdb->posts`
       
   922 				AS `reply`
       
   923 			INNER JOIN `$wpdb->posts`
       
   924 				AS `topic`
       
   925 				ON `reply`.`post_parent` = `topic`.`ID`
       
   926 			WHERE `topic`.`post_type` = 'topic'
       
   927 				AND `reply`.`post_type` = 'reply'
       
   928 			GROUP BY `reply`.`ID` );" ) ) )
       
   929 		return array( 4, sprintf( $statement, $result ) );
       
   930 
       
   931 	// Complete results
       
   932 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   933 }
       
   934 
       
   935 /**
       
   936  * Recaches the topic for each post
       
   937  *
       
   938  * @since bbPress (r3876)
       
   939  *
       
   940  * @uses wpdb::query() To run our recount sql queries
       
   941  * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
       
   942  * @return array An array of the status code and the message
       
   943  */
       
   944 function bbp_admin_repair_topic_meta() {
       
   945 	global $wpdb;
       
   946 
       
   947 	$statement = __( 'Recalculating the topic for each post &hellip; %s', 'bbpress' );
       
   948 	$result    = __( 'Failed!', 'bbpress' );
       
   949 
       
   950 	// First, delete everything.
       
   951 	if ( is_wp_error( $wpdb->query( "DELETE FROM `$wpdb->postmeta` WHERE `meta_key` = '_bbp_topic_id';" ) ) )
       
   952 		return array( 1, sprintf( $statement, $result ) );
       
   953 
       
   954 	// Next, give all the topics with replies the ID their last reply.
       
   955 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   956 			( SELECT `topic`.`ID`, '_bbp_topic_id', `topic`.`ID`
       
   957 			FROM `$wpdb->posts`
       
   958 				AS `topic`
       
   959 			WHERE `topic`.`post_type` = 'topic'
       
   960 			GROUP BY `topic`.`ID` );" ) ) )
       
   961 		return array( 3, sprintf( $statement, $result ) );
       
   962 
       
   963 	// Next, give all the topics with replies the ID their last reply.
       
   964 	if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
       
   965 			( SELECT `reply`.`ID`, '_bbp_topic_id', `topic`.`ID`
       
   966 			FROM `$wpdb->posts`
       
   967 				AS `reply`
       
   968 			INNER JOIN `$wpdb->posts`
       
   969 				AS `topic`
       
   970 				ON `reply`.`post_parent` = `topic`.`ID`
       
   971 			WHERE `topic`.`post_type` = 'topic'
       
   972 				AND `reply`.`post_type` = 'reply'
       
   973 			GROUP BY `reply`.`ID` );" ) ) )
       
   974 		return array( 4, sprintf( $statement, $result ) );
       
   975 
       
   976 	// Complete results
       
   977 	return array( 0, sprintf( $statement, __( 'Complete!', 'bbpress' ) ) );
       
   978 }
       
   979 
       
   980 /** Reset ********************************************************************/
       
   981 
       
   982 /**
       
   983  * Admin reset page
       
   984  *
       
   985  * @since bbPress (r2613)
       
   986  *
       
   987  * @uses check_admin_referer() To verify the nonce and the referer
       
   988  * @uses do_action() Calls 'admin_notices' to display the notices
       
   989  * @uses screen_icon() To display the screen icon
       
   990  * @uses wp_nonce_field() To add a hidden nonce field
       
   991  */
       
   992 function bbp_admin_reset() {
       
   993 ?>
       
   994 
       
   995 	<div class="wrap">
       
   996 
       
   997 		<?php screen_icon( 'tools' ); ?>
       
   998 
       
   999 		<h2 class="nav-tab-wrapper"><?php bbp_tools_admin_tabs( __( 'Reset Forums', 'bbpress' ) ); ?></h2>
       
  1000 		<p><?php _e( 'This will revert your forums back to a brand new installation. This process cannot be undone. <strong>Backup your database before proceeding</strong>.', 'bbpress' ); ?></p>
       
  1001 
       
  1002 		<form class="settings" method="post" action="">
       
  1003 			<table class="form-table">
       
  1004 				<tbody>
       
  1005 					<tr valign="top">
       
  1006 						<th scope="row"><?php _e( 'The following data will be removed:', 'bbpress' ) ?></th>
       
  1007 						<td>
       
  1008 							<?php _e( 'All Forums',           'bbpress' ); ?><br />
       
  1009 							<?php _e( 'All Topics',           'bbpress' ); ?><br />
       
  1010 							<?php _e( 'All Replies',          'bbpress' ); ?><br />
       
  1011 							<?php _e( 'All Topic Tags',       'bbpress' ); ?><br />
       
  1012 							<?php _e( 'Related Meta Data',    'bbpress' ); ?><br />
       
  1013 							<?php _e( 'Forum Settings',       'bbpress' ); ?><br />
       
  1014 							<?php _e( 'Forum Activity',       'bbpress' ); ?><br />
       
  1015 							<?php _e( 'Forum User Roles',     'bbpress' ); ?><br />
       
  1016 							<?php _e( 'Importer Helper Data', 'bbpress' ); ?><br />
       
  1017 						</td>
       
  1018 					</tr>
       
  1019 					<tr valign="top">
       
  1020 						<th scope="row"><?php _e( 'Are you sure you want to do this?', 'bbpress' ) ?></th>
       
  1021 						<td>
       
  1022 							<fieldset>
       
  1023 								<legend class="screen-reader-text"><span><?php _e( "Say it ain't so!", 'bbpress' ) ?></span></legend>
       
  1024 								<label><input type="checkbox" class="checkbox" name="bbpress-are-you-sure" id="bbpress-are-you-sure" value="1" /> <?php _e( 'This process cannot be undone.', 'bbpress' ); ?></label>
       
  1025 							</fieldset>
       
  1026 						</td>
       
  1027 					</tr>
       
  1028 				</tbody>
       
  1029 			</table>
       
  1030 
       
  1031 			<fieldset class="submit">
       
  1032 				<input class="button-primary" type="submit" name="submit" value="<?php esc_attr_e( 'Reset bbPress', 'bbpress' ); ?>" />
       
  1033 				<?php wp_nonce_field( 'bbpress-reset' ); ?>
       
  1034 			</fieldset>
       
  1035 		</form>
       
  1036 	</div>
       
  1037 
       
  1038 <?php
       
  1039 }
       
  1040 
       
  1041 /**
       
  1042  * Handle the processing and feedback of the admin tools page
       
  1043  *
       
  1044  * @since bbPress (r2613)
       
  1045  *
       
  1046  * @uses check_admin_referer() To verify the nonce and the referer
       
  1047  * @uses wp_cache_flush() To flush the cache
       
  1048  */
       
  1049 function bbp_admin_reset_handler() {
       
  1050 	if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) && !empty( $_POST['bbpress-are-you-sure'] ) ) {
       
  1051 		check_admin_referer( 'bbpress-reset' );
       
  1052 
       
  1053 		global $wpdb;
       
  1054 
       
  1055 		// Stores messages
       
  1056 		$messages = array();
       
  1057 		$failed   = __( 'Failed',   'bbpress' );
       
  1058 		$success  = __( 'Success!', 'bbpress' );
       
  1059 
       
  1060 		// Flush the cache; things are about to get ugly.
       
  1061 		wp_cache_flush();
       
  1062 
       
  1063 		/** Posts *************************************************************/
       
  1064 
       
  1065 		$statement  = __( 'Deleting Posts&hellip; %s', 'bbpress' );
       
  1066 		$sql_posts  = $wpdb->get_results( "SELECT `ID` FROM `{$wpdb->posts}` WHERE `post_type` IN ('forum', 'topic', 'reply')", OBJECT_K );
       
  1067 		$sql_delete = "DELETE FROM `{$wpdb->posts}` WHERE `post_type` IN ('forum', 'topic', 'reply')";
       
  1068 		$result     = is_wp_error( $wpdb->query( $sql_delete ) ) ? $failed : $success;
       
  1069 		$messages[] = sprintf( $statement, $result );
       
  1070 
       
  1071 
       
  1072 		/** Post Meta *********************************************************/
       
  1073 
       
  1074 		if ( !empty( $sql_posts ) ) {
       
  1075 			foreach( $sql_posts as $key => $value ) {
       
  1076 				$sql_meta[] = $key;
       
  1077 			}
       
  1078 			$statement  = __( 'Deleting Post Meta&hellip; %s', 'bbpress' );
       
  1079 			$sql_meta   = implode( "', '", $sql_meta );
       
  1080 			$sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `post_id` IN ('{$sql_meta}');";
       
  1081 			$result     = is_wp_error( $wpdb->query( $sql_delete ) ) ? $failed : $success;
       
  1082 			$messages[] = sprintf( $statement, $result );
       
  1083 		}
       
  1084 
       
  1085 		/** Topic Tags ********************************************************/
       
  1086 
       
  1087 		// @todo
       
  1088 
       
  1089 		/** User Meta *********************************************************/
       
  1090 
       
  1091 		$statement  = __( 'Deleting User Meta&hellip; %s', 'bbpress' );
       
  1092 		$sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` LIKE '%%_bbp_%%';";
       
  1093 		$result     = is_wp_error( $wpdb->query( $sql_delete ) ) ? $failed : $success;
       
  1094 		$messages[] = sprintf( $statement, $result );
       
  1095 
       
  1096 		/** Converter *********************************************************/
       
  1097 
       
  1098 		$statement  = __( 'Deleting Conversion Table&hellip; %s', 'bbpress' );
       
  1099 		$table_name = $wpdb->prefix . 'bbp_converter_translator';
       
  1100 		if ( $wpdb->get_var( "SHOW TABLES LIKE '{$table_name}'" ) == $table_name ) {
       
  1101 			$wpdb->query( "DROP TABLE {$table_name}" );
       
  1102 			$result = $success;
       
  1103 		} else {
       
  1104 			$result = $failed;
       
  1105 		}
       
  1106 		$messages[] = sprintf( $statement, $result );
       
  1107 
       
  1108 		/** Options ***********************************************************/
       
  1109 
       
  1110 		$statement  = __( 'Deleting Settings&hellip; %s', 'bbpress' );
       
  1111 		$sql_delete = bbp_delete_options();
       
  1112 		$messages[] = sprintf( $statement, $success );
       
  1113 
       
  1114 		/** Roles *************************************************************/
       
  1115 
       
  1116 		$statement  = __( 'Deleting Roles and Capabilities&hellip; %s', 'bbpress' );
       
  1117 		$sql_delete = bbp_remove_roles();
       
  1118 		$sql_delete = bbp_remove_caps();
       
  1119 		$messages[] = sprintf( $statement, $success );
       
  1120 
       
  1121 		/** Output ************************************************************/
       
  1122 
       
  1123 		if ( count( $messages ) ) {
       
  1124 			foreach ( $messages as $message ) {
       
  1125 				bbp_admin_tools_feedback( $message );
       
  1126 			}
       
  1127 		}
       
  1128 	}
       
  1129 }