' . esc_html( $item['description'] ) . '

'; endif; ?>
postmeta}` AS `postmeta` LEFT JOIN `{$bbp_db->posts}` AS `posts` ON `posts`.`ID` = `postmeta`.`post_id` WHERE `posts`.`post_type` = '{$tpt}' AND `postmeta`.`meta_key` = '_bbp_reply_count'"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 1, sprintf( $statement, $result ) ); } // Recalculate the meta key _bbp_reply_count for each topic $sql = "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `topics`.`ID` AS `post_id`, '_bbp_reply_count' AS `meta_key`, COUNT(`replies`.`ID`) As `meta_value` FROM `{$bbp_db->posts}` AS `topics` LEFT JOIN `{$bbp_db->posts}` as `replies` ON `replies`.`post_parent` = `topics`.`ID` AND `replies`.`post_status` = '{$pps}' AND `replies`.`post_type` = '{$rpt}' WHERE `topics`.`post_type` = '{$tpt}' AND `topics`.`post_status` IN ( '{$pps}', '{$cps}' ) GROUP BY `topics`.`ID`)"; if ( is_wp_error( $bbp_db->query( $sql ) ) ) { return array( 2, sprintf( $statement, $result ) ); } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Recount topic voices * * @since 2.0.0 bbPress (r2613) * * @return array An array of the status code and the message */ function bbp_admin_repair_topic_voice_count() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Counting the number of voices in each topic… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); $sql_delete = "DELETE FROM {$bbp_db->postmeta} WHERE meta_key IN ('_bbp_voice_count', '_bbp_engagement')"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 1, sprintf( $statement, $result ) ); } // Post types and status $tpt = bbp_get_topic_post_type(); $rpt = bbp_get_reply_post_type(); $pps = bbp_get_public_status_id(); $cps = bbp_get_closed_status_id(); $engagements_sql = $bbp_db->prepare( "INSERT INTO {$bbp_db->postmeta} (post_id, meta_key, meta_value) ( SELECT postmeta.meta_value, '_bbp_engagement', posts.post_author FROM {$bbp_db->posts} AS posts LEFT JOIN {$bbp_db->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_bbp_topic_id' WHERE posts.post_type IN (%s, %s) AND posts.post_status IN (%s, %s) GROUP BY postmeta.meta_value, posts.post_author)", $tpt, $rpt, $pps, $cps ); if ( is_wp_error( $bbp_db->query( $engagements_sql ) ) ) { return array( 2, sprintf( $statement, $result ) ); } $voice_count_sql = "INSERT INTO {$bbp_db->postmeta} (post_id, meta_key, meta_value) ( SELECT post_id, '_bbp_voice_count', COUNT(DISTINCT meta_value) FROM {$bbp_db->postmeta} WHERE meta_key = '_bbp_engagement' GROUP BY post_id)"; if ( is_wp_error( $bbp_db->query( $voice_count_sql ) ) ) { return array( 3, sprintf( $statement, $result ) ); } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Recount non-public replies per topic (pending/spammed/trashed) * * @since 2.0.0 bbPress (r2747) * * @return array An array of the status code and the message */ function bbp_admin_repair_topic_hidden_reply_count() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Counting the number of pending, spammed, and trashed replies in each topic… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); $sql_delete = "DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` = '_bbp_reply_count_hidden'"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 1, sprintf( $statement, $result ) ); } // Post types and status $rpt = bbp_get_reply_post_type(); $sta = bbp_get_non_public_topic_statuses(); // SQL $sql_status = "'" . implode( "','", $sta ) . "'"; $sql = "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) (SELECT `post_parent`, '_bbp_reply_count_hidden', COUNT(`post_status`) as `meta_value` FROM `{$bbp_db->posts}` WHERE `post_type` = '{$rpt}' AND `post_status` IN ({$sql_status}) GROUP BY `post_parent`)"; if ( is_wp_error( $bbp_db->query( $sql ) ) ) { return array( 2, sprintf( $statement, $result ) ); } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Recount forum topics * * @since 2.0.0 bbPress (r2613) * * @return array An array of the status code and the message */ function bbp_admin_repair_forum_topic_count() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Counting the number of topics in each forum… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); $sql_delete = "DELETE FROM {$bbp_db->postmeta} WHERE meta_key IN ( '_bbp_topic_count', '_bbp_total_topic_count', '_bbp_topic_count_hidden' )"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 1, sprintf( $statement, $result ) ); } $forums = get_posts( array( 'post_type' => bbp_get_forum_post_type(), 'numberposts' => -1 ) ); if ( ! empty( $forums ) ) { foreach ( $forums as $forum ) { bbp_update_forum_topic_count( $forum->ID ); bbp_update_forum_topic_count_hidden( $forum->ID ); } } else { return array( 2, sprintf( $statement, $result ) ); } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Recount topic in each topic-tag * * @since 2.6.0 bbPress (r6256) * * @return array An array of the status code and the message */ function bbp_admin_repair_topic_tag_count() { // Define variables $statement = esc_html__( 'Counting the number of topics in each topic-tag… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); $tax_id = bbp_get_topic_tag_tax_id(); $terms = get_terms( $tax_id, array( 'hide_empty' => false ) ); $tt_ids = wp_list_pluck( $terms, 'term_taxonomy_id' ); $ints = array_map( 'intval', $tt_ids ); $taxonomy = get_taxonomy( $tax_id ); // Bail if taxonomy does not exist if ( empty( $taxonomy ) ) { return array( 1, sprintf( $statement, $result ) ); } // Custom callback if ( ! empty( $taxonomy->update_count_callback ) ) { // Bail if callback is not callable if ( ! is_callable( $taxonomy->update_count_callback ) ) { return array( 1, sprintf( $statement, $result ) ); } call_user_func( $taxonomy->update_count_callback, $ints, $taxonomy ); // Generic callback fallback } else { _update_post_term_count( $ints, $taxonomy ); } // Bust the cache clean_term_cache( $ints, '', false ); return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Recount forum replies * * @since 2.0.0 bbPress (r2613) * * @return array An array of the status code and the message */ function bbp_admin_repair_forum_reply_count() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Counting the number of replies in each forum… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); // Post type $fpt = bbp_get_forum_post_type(); // Delete the meta keys _bbp_reply_count and _bbp_total_reply_count for each forum $sql_delete = "DELETE `postmeta` FROM `{$bbp_db->postmeta}` AS `postmeta` LEFT JOIN `{$bbp_db->posts}` AS `posts` ON `posts`.`ID` = `postmeta`.`post_id` WHERE `posts`.`post_type` = '{$fpt}' AND `postmeta`.`meta_key` = '_bbp_reply_count' OR `postmeta`.`meta_key` = '_bbp_total_reply_count'"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 1, sprintf( $statement, $result ) ); } // Recalculate the metas key _bbp_reply_count and _bbp_total_reply_count for each forum $forums = get_posts( array( 'post_type' => bbp_get_forum_post_type(), 'numberposts' => -1 ) ); if ( ! empty( $forums ) ) { foreach ( $forums as $forum ) { bbp_update_forum_reply_count( $forum->ID ); } } else { return array( 2, sprintf( $statement, $result ) ); } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Recount non-public forum replies * * @since 2.6.0 bbPress (r6922) * @since 2.6.0 bbPress (r6932) Rename to match the topic reply recount function * * @return array An array of the status code and the message */ function bbp_admin_repair_forum_hidden_reply_count() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Counting the number of pending, spammed, and trashed replies in each forum… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); // Post type $fpt = bbp_get_forum_post_type(); // Delete the meta keys _bbp_reply_count and _bbp_total_reply_count for each forum $sql_delete = "DELETE `postmeta` FROM `{$bbp_db->postmeta}` AS `postmeta` LEFT JOIN `{$bbp_db->posts}` AS `posts` ON `posts`.`ID` = `postmeta`.`post_id` WHERE `posts`.`post_type` = '{$fpt}' AND `postmeta`.`meta_key` = '_bbp_reply_count_hidden' OR `postmeta`.`meta_key` = '_bbp_total_reply_count_hidden'"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 1, sprintf( $statement, $result ) ); } // Recalculate the metas key _bbp_reply_count and _bbp_total_reply_count for each forum $forums = get_posts( array( 'post_type' => bbp_get_forum_post_type(), 'numberposts' => -1 ) ); if ( ! empty( $forums ) ) { foreach ( $forums as $forum ) { bbp_update_forum_reply_count_hidden( $forum->ID ); } } else { return array( 2, sprintf( $statement, $result ) ); } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Recount topics by the users * * @since 2.1.0 bbPress (r3889) * * @return array An array of the status code and the message */ function bbp_admin_repair_user_topic_count() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Counting the number of topics each user has created… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); $sql_select = "SELECT `post_author`, COUNT(DISTINCT `ID`) as `_count` FROM `{$bbp_db->posts}` WHERE `post_type` = '" . bbp_get_topic_post_type() . "' AND `post_status` = '" . bbp_get_public_status_id() . "' GROUP BY `post_author`"; $insert_rows = $bbp_db->get_results( $sql_select ); if ( is_wp_error( $insert_rows ) ) { return array( 1, sprintf( $statement, $result ) ); } $key = $bbp_db->prefix . '_bbp_topic_count'; $insert_values = array(); foreach ( $insert_rows as $insert_row ) { $insert_values[] = "('{$insert_row->post_author}', '{$key}', '{$insert_row->_count}')"; } if ( !count( $insert_values ) ) { return array( 2, sprintf( $statement, $result ) ); } $sql_delete = "DELETE FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 3, sprintf( $statement, $result ) ); } foreach ( array_chunk( $insert_values, 10000 ) as $chunk ) { $chunk = "\n" . implode( ",\n", $chunk ); $sql_insert = "INSERT INTO `{$bbp_db->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES {$chunk}"; if ( is_wp_error( $bbp_db->query( $sql_insert ) ) ) { return array( 4, sprintf( $statement, $result ) ); } } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Recount topic replied by the users * * @since 2.0.0 bbPress (r2613) * * @return array An array of the status code and the message */ function bbp_admin_repair_user_reply_count() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Counting the number of topics to which each user has replied… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); $sql_select = "SELECT `post_author`, COUNT(DISTINCT `ID`) as `_count` FROM `{$bbp_db->posts}` WHERE `post_type` = '" . bbp_get_reply_post_type() . "' AND `post_status` = '" . bbp_get_public_status_id() . "' GROUP BY `post_author`"; $insert_rows = $bbp_db->get_results( $sql_select ); if ( is_wp_error( $insert_rows ) ) { return array( 1, sprintf( $statement, $result ) ); } $key = $bbp_db->prefix . '_bbp_reply_count'; $insert_values = array(); foreach ( $insert_rows as $insert_row ) { $insert_values[] = "('{$insert_row->post_author}', '{$key}', '{$insert_row->_count}')"; } if ( !count( $insert_values ) ) { return array( 2, sprintf( $statement, $result ) ); } $sql_delete = "DELETE FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 3, sprintf( $statement, $result ) ); } foreach ( array_chunk( $insert_values, 10000 ) as $chunk ) { $chunk = "\n" . implode( ",\n", $chunk ); $sql_insert = "INSERT INTO `{$bbp_db->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES {$chunk}"; if ( is_wp_error( $bbp_db->query( $sql_insert ) ) ) { return array( 4, sprintf( $statement, $result ) ); } } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Repair user favorites * * @since 2.0.0 bbPress (r2613) * * @return array An array of the status code and the message */ function bbp_admin_repair_user_favorites() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Removing unpublished topics from user favorites… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); // Query for users with favorites $key = $bbp_db->prefix . '_bbp_favorites'; $users = $bbp_db->get_results( "SELECT `user_id`, `meta_value` AS `favorites` FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'" ); if ( is_wp_error( $users ) ) { return array( 1, sprintf( $statement, $result ) ); } $topics = $bbp_db->get_col( "SELECT `ID` FROM `{$bbp_db->posts}` WHERE `post_type` = '" . bbp_get_topic_post_type() . "' AND `post_status` = '" . bbp_get_public_status_id() . "'" ); if ( is_wp_error( $topics ) ) { return array( 2, sprintf( $statement, $result ) ); } $values = array(); foreach ( $users as $user ) { if ( empty( $user->favorites ) || ! is_string( $user->favorites ) ) { continue; } $favorites = array_intersect( $topics, explode( ',', $user->favorites ) ); if ( empty( $favorites ) || ! is_array( $favorites ) ) { continue; } $favorites_joined = implode( ',', $favorites ); $values[] = "('{$user->user_id}', '{$key}', '{$favorites_joined}')"; // Cleanup unset( $favorites, $favorites_joined ); } if ( !count( $values ) ) { $result = esc_html__( 'Nothing to remove!', 'bbpress' ); return array( 0, sprintf( $statement, $result ) ); } $sql_delete = "DELETE FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 4, sprintf( $statement, $result ) ); } foreach ( array_chunk( $values, 10000 ) as $chunk ) { $chunk = "\n" . implode( ",\n", $chunk ); $sql_insert = "INSERT INTO `{$bbp_db->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES {$chunk}"; if ( is_wp_error( $bbp_db->query( $sql_insert ) ) ) { return array( 5, sprintf( $statement, $result ) ); } } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Clean the user topic subscriptions * * @since 2.0.0 bbPress (r2668) * * @return array An array of the status code and the message */ function bbp_admin_repair_user_topic_subscriptions() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Removing trashed topics from user subscriptions… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); $key = $bbp_db->prefix . '_bbp_subscriptions'; $users = $bbp_db->get_results( "SELECT `user_id`, `meta_value` AS `subscriptions` FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'" ); if ( is_wp_error( $users ) ) { return array( 1, sprintf( $statement, $result ) ); } $topics = $bbp_db->get_col( "SELECT `ID` FROM `{$bbp_db->posts}` WHERE `post_type` = '" . bbp_get_topic_post_type() . "' AND `post_status` = '" . bbp_get_public_status_id() . "'" ); if ( is_wp_error( $topics ) ) { return array( 2, sprintf( $statement, $result ) ); } $values = array(); foreach ( $users as $user ) { if ( empty( $user->subscriptions ) || ! is_string( $user->subscriptions ) ) { continue; } $subscriptions = array_intersect( $topics, explode( ',', $user->subscriptions ) ); if ( empty( $subscriptions ) || ! is_array( $subscriptions ) ) { continue; } $subscriptions_joined = implode( ',', $subscriptions ); $values[] = "('{$user->user_id}', '{$key}', '{$subscriptions_joined}')"; // Cleanup unset( $subscriptions, $subscriptions_joined ); } if ( !count( $values ) ) { $result = esc_html__( 'Nothing to remove!', 'bbpress' ); return array( 0, sprintf( $statement, $result ) ); } $sql_delete = "DELETE FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 4, sprintf( $statement, $result ) ); } foreach ( array_chunk( $values, 10000 ) as $chunk ) { $chunk = "\n" . implode( ",\n", $chunk ); $sql_insert = "INSERT INTO `{$bbp_db->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES {$chunk}"; if ( is_wp_error( $bbp_db->query( $sql_insert ) ) ) { return array( 5, sprintf( $statement, $result ) ); } } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Clean the user forum subscriptions * * @since 2.5.0 bbPress (r5155) * * @return array An array of the status code and the message */ function bbp_admin_repair_user_forum_subscriptions() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Removing trashed forums from user subscriptions… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); $key = $bbp_db->prefix . '_bbp_forum_subscriptions'; $users = $bbp_db->get_results( "SELECT `user_id`, `meta_value` AS `subscriptions` FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'" ); if ( is_wp_error( $users ) ) { return array( 1, sprintf( $statement, $result ) ); } $forums = $bbp_db->get_col( "SELECT `ID` FROM `{$bbp_db->posts}` WHERE `post_type` = '" . bbp_get_forum_post_type() . "' AND `post_status` = '" . bbp_get_public_status_id() . "'" ); if ( is_wp_error( $forums ) ) { return array( 2, sprintf( $statement, $result ) ); } $values = array(); foreach ( $users as $user ) { if ( empty( $user->subscriptions ) || ! is_string( $user->subscriptions ) ) { continue; } $subscriptions = array_intersect( $forums, explode( ',', $user->subscriptions ) ); if ( empty( $subscriptions ) || ! is_array( $subscriptions ) ) { continue; } $subscriptions_joined = implode( ',', $subscriptions ); $values[] = "('{$user->user_id}', '{$key}', '{$subscriptions_joined}')"; // Cleanup unset( $subscriptions, $subscriptions_joined ); } if ( !count( $values ) ) { $result = esc_html__( 'Nothing to remove!', 'bbpress' ); return array( 0, sprintf( $statement, $result ) ); } $sql_delete = "DELETE FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'"; if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) { return array( 4, sprintf( $statement, $result ) ); } foreach ( array_chunk( $values, 10000 ) as $chunk ) { $chunk = "\n" . implode( ",\n", $chunk ); $sql_insert = "INSERT INTO `{$bbp_db->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES {$chunk}"; if ( is_wp_error( $bbp_db->query( $sql_insert ) ) ) { return array( 5, sprintf( $statement, $result ) ); } } return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * This repair tool will map each user of the current site to their respective * forums role. By default, Admins will be Key Masters, and every other role * will be the default role defined in Settings > Forums (Participant). * * @since 2.2.0 bbPress (r4340) */ function bbp_admin_repair_user_roles() { $statement = esc_html__( 'Remapping forum role for each user on this site… %s', 'bbpress' ); $changed = 0; $role_map = bbp_get_user_role_map(); $default_role = bbp_get_default_role(); // Bail if no role map exists if ( empty( $role_map ) ) { return array( 1, sprintf( $statement, esc_html__( 'Failed!', 'bbpress' ) ) ); } // Get non-forum roles $blog_roles = array_keys( bbp_get_blog_roles() ); // Iterate through each role... foreach ( $blog_roles as $role ) { // Reset the offset $offset = 0; // If no role map exists, give the default forum role (bbp-participant) $new_role = isset( $role_map[ $role ] ) ? $role_map[ $role ] : $default_role; // Get users of this site, limited to 1000 while ( $users = get_users( array( 'role' => $role, 'fields' => 'ID', 'number' => 1000, 'offset' => $offset ) ) ) { // Iterate through each user of $role and try to set it foreach ( (array) $users as $user_id ) { if ( bbp_set_user_role( $user_id, $new_role ) ) { ++$changed; // Keep a count to display at the end } } // Bump the offset for the next query iteration $offset = $offset + 1000; } } // Reset the offset $offset = 0; $bbp_db = bbp_db(); $cap_key = $bbp_db->get_blog_prefix() . 'capabilities'; // Users without roles should be granted the default role, but not on multi- // site installations where not all users get a role by default. if ( ! is_multisite() ) { // Get users with missing capabilities on this site, limited to 1000 while ( $users = get_users( array( 'meta_key' => $cap_key, 'meta_compare' => 'NOT EXISTS', 'fields' => 'ID', 'number' => 1000, 'offset' => $offset ) ) ) { // Iterate through each user of $role and try to set it foreach ( (array) $users as $user_id ) { if ( bbp_set_user_role( $user_id, $default_role ) ) { ++$changed; // Keep a count to display at the end } } // Bump the offset for the next query iteration $offset = $offset + 1000; } // On multisite, we'll look for users with an empty capabilities array. // These are users who basically have malformed caps, and we can fix that. } else { // Get users with empty capabilities on this site, limited to 1000 while ( $users = get_users( array( 'meta_key' => $cap_key, 'meta_value' => 'a:0:{}', 'fields' => 'ID', 'number' => 1000, 'offset' => $offset ) ) ) { // Iterate through each user of $role and try to set it foreach ( (array) $users as $user_id ) { if ( bbp_set_user_role( $user_id, $default_role ) ) { ++$changed; // Keep a count to display at the end } } // Bump the offset for the next query iteration $offset = $offset + 1000; } } $result = sprintf( esc_html__( 'Complete! %s users updated.', 'bbpress' ), bbp_number_format( $changed ) ); return array( 0, sprintf( $statement, $result ) ); } /** * Repair the last post in every topic and forum * * @since 2.0.0 bbPress (r3040) * * @return array An array of the status code and the message */ function bbp_admin_repair_freshness() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Recomputing latest post in every topic and forum… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); // First, delete everything. if ( is_wp_error( $bbp_db->query( "DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` IN ( '_bbp_last_reply_id', '_bbp_last_topic_id', '_bbp_last_active_id', '_bbp_last_active_time' )" ) ) ) { return array( 1, sprintf( $statement, $result ) ); } // Post types and status $fpt = bbp_get_forum_post_type(); $tpt = bbp_get_topic_post_type(); $rpt = bbp_get_reply_post_type(); $pps = bbp_get_public_status_id(); // Next, give all the topics with replies the ID their last reply. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `topic`.`ID`, '_bbp_last_reply_id', MAX( `reply`.`ID` ) FROM `{$bbp_db->posts}` AS `topic` INNER JOIN `{$bbp_db->posts}` AS `reply` ON `topic`.`ID` = `reply`.`post_parent` WHERE `reply`.`post_status` = '{$pps}' AND `topic`.`post_type` = '{$tpt}' AND `reply`.`post_type` = '{$rpt}' GROUP BY `topic`.`ID` )" ) ) ) { return array( 2, sprintf( $statement, $result ) ); } // For any remaining topics, give a reply ID of 0. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `ID`, '_bbp_last_reply_id', 0 FROM `{$bbp_db->posts}` AS `topic` LEFT JOIN `{$bbp_db->postmeta}` AS `reply` ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_reply_id' WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = '{$tpt}' )" ) ) ) { return array( 3, sprintf( $statement, $result ) ); } // Now we give all the forums with topics the ID their last topic. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `forum`.`ID`, '_bbp_last_topic_id', MAX( `topic`.`ID` ) FROM `{$bbp_db->posts}` AS `forum` INNER JOIN `{$bbp_db->posts}` AS `topic` ON `forum`.`ID` = `topic`.`post_parent` WHERE `topic`.`post_status` = '{$pps}' AND `forum`.`post_type` = '{$fpt}' AND `topic`.`post_type` = '{$tpt}' GROUP BY `forum`.`ID` )" ) ) ) { return array( 4, sprintf( $statement, $result ) ); } // For any remaining forums, give a topic ID of 0. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `ID`, '_bbp_last_topic_id', 0 FROM `{$bbp_db->posts}` AS `forum` LEFT JOIN `{$bbp_db->postmeta}` AS `topic` ON `forum`.`ID` = `topic`.`post_id` AND `topic`.`meta_key` = '_bbp_last_topic_id' WHERE `topic`.`meta_id` IS NULL AND `forum`.`post_type` = '{$fpt}' )" ) ) ) { return array( 5, sprintf( $statement, $result ) ); } // After that, we give all the topics with replies the ID their last reply (again, this time for a different reason). if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `topic`.`ID`, '_bbp_last_active_id', MAX( `reply`.`ID` ) FROM `{$bbp_db->posts}` AS `topic` INNER JOIN `{$bbp_db->posts}` AS `reply` ON `topic`.`ID` = `reply`.`post_parent` WHERE `reply`.`post_status` = '{$pps}' AND `topic`.`post_type` = '{$tpt}' AND `reply`.`post_type` = '{$rpt}' GROUP BY `topic`.`ID` )" ) ) ) { return array( 6, sprintf( $statement, $result ) ); } // For any remaining topics, give a reply ID of themself. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `ID`, '_bbp_last_active_id', `ID` FROM `{$bbp_db->posts}` AS `topic` LEFT JOIN `{$bbp_db->postmeta}` AS `reply` ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_active_id' WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = '{$tpt}' )" ) ) ) { return array( 7, sprintf( $statement, $result ) ); } // Give topics with replies their last update time. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `topic`.`ID`, '_bbp_last_active_time', MAX( `reply`.`post_date` ) FROM `{$bbp_db->posts}` AS `topic` INNER JOIN `{$bbp_db->posts}` AS `reply` ON `topic`.`ID` = `reply`.`post_parent` WHERE `reply`.`post_status` = '{$pps}' AND `topic`.`post_type` = '{$tpt}' AND `reply`.`post_type` = '{$rpt}' GROUP BY `topic`.`ID` )" ) ) ) { return array( 8, sprintf( $statement, $result ) ); } // Give topics without replies their last update time. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `ID`, '_bbp_last_active_time', `post_date` FROM `{$bbp_db->posts}` AS `topic` LEFT JOIN `{$bbp_db->postmeta}` AS `reply` ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_active_time' WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = '{$tpt}' )" ) ) ) { return array( 9, sprintf( $statement, $result ) ); } // Forums need to know what their last active item is as well. Now it gets a bit more complex to do in the database. $forums = $bbp_db->get_col( "SELECT `ID` FROM `{$bbp_db->posts}` WHERE `post_type` = '{$fpt}' and `post_status` != 'auto-draft'" ); if ( is_wp_error( $forums ) ) { return array( 10, sprintf( $statement, $result ) ); } // Loop through forums foreach ( $forums as $forum_id ) { if ( ! bbp_is_forum_category( $forum_id ) ) { bbp_update_forum( array( 'forum_id' => $forum_id ) ); } } // Loop through categories when forums are done foreach ( $forums as $forum_id ) { if ( bbp_is_forum_category( $forum_id ) ) { bbp_update_forum( array( 'forum_id' => $forum_id ) ); } } // Complete results return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Repair the relationship of sticky topics to the actual parent forum * * @since 2.3.0 bbPress (r4695) * * @return array An array of the status code and the message */ function bbp_admin_repair_sticky() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Repairing the sticky topic to the parent forum relationships… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); $forums = $bbp_db->get_col( "SELECT ID FROM `{$bbp_db->posts}` WHERE `post_type` = '" . bbp_get_forum_post_type() . "'" ); // Bail if no forums found if ( empty( $forums ) || is_wp_error( $forums ) ) { return array( 1, sprintf( $statement, $result ) ); } // Loop through forums and get their sticky topics foreach ( $forums as $forum ) { $forum_stickies[ $forum ] = get_post_meta( $forum, '_bbp_sticky_topics', true ); } // Cleanup unset( $forums, $forum ); // Loop through each forum with sticky topics foreach ( $forum_stickies as $forum_id => $stickies ) { // Skip if no stickies if ( empty( $stickies ) ) { continue; } // Loop through each sticky topic foreach ( $stickies as $id => $topic_id ) { // If the topic is not a super sticky, and the forum ID does not // match the topic's forum ID, unset the forum's sticky meta. if ( ! bbp_is_topic_super_sticky( $topic_id ) && ( $forum_id !== bbp_get_topic_forum_id( $topic_id ) ) ) { unset( $forum_stickies[ $forum_id ][ $id ] ); } } // Get sticky topic ID's, or use empty string $stickers = ! empty( $forum_stickies[ $forum_id ] ) ? array_values( $forum_stickies[ $forum_id ] ) : ''; // Update the forum's sticky topics meta update_post_meta( $forum_id, '_bbp_sticky_topics', $stickers ); } // Complete results return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Repair closed topics * * Closed topics that are missing the post-meta "_bbp_status" key value "publish" * result in unexpected behavior, primarily this would have only occurred if you * had imported forums from another forum package previous to bbPress v2.6, * https://bbpress.trac.wordpress.org/ticket/2577 * * @since 2.6.0 bbPress (r5668) * * @return array An array of the status code and the message */ function bbp_admin_repair_closed_topics() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Repairing closed topics… %s', 'bbpress' ); $result = esc_html__( 'No closed topics to repair.', 'bbpress' ); $changed = 0; // Results $query = "SELECT ID FROM `{$bbp_db->posts}` WHERE `post_type` = %s AND `post_status` = %s"; $prepare = $bbp_db->prepare( $query, bbp_get_topic_post_type(), bbp_get_closed_status_id() ); $closed_topics = $bbp_db->get_col( $prepare ); // Bail if no closed topics found if ( empty( $closed_topics ) || is_wp_error( $closed_topics ) ) { return array( 1, sprintf( $statement, $result ) ); } // Loop through each closed topic foreach ( $closed_topics as $closed_topic ) { // Check if the closed topic already has a postmeta _bbp_status value $topic_status = get_post_meta( $closed_topic, '_bbp_status', true ); // If we don't have a postmeta _bbp_status value if ( empty( $topic_status ) ) { update_post_meta( $closed_topic, '_bbp_status', 'publish' ); ++$changed; // Keep a count to display at the end } } // Cleanup unset( $closed_topics, $closed_topic, $topic_status ); // Complete results $result = sprintf( _n( 'Complete! %d closed topic repaired.', 'Complete! %d closed topics repaired.', $changed, 'bbpress' ), $changed ); return array( 0, sprintf( $statement, $result ) ); } /** * Repair the private and hidden forums * * @since 2.2.0 bbPress (r4104) * * @return array An array of the status code and the message */ function bbp_admin_repair_forum_visibility() { $statement = esc_html__( 'Recalculating forum visibility… %s', 'bbpress' ); // Bail if queries returned errors if ( ! bbp_repair_forum_visibility() ) { return array( 2, sprintf( $statement, esc_html__( 'Failed!', 'bbpress' ) ) ); // Complete results } else { return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } } /** * Repair the parent forum meta for each topic and reply * * @since 2.1.0 bbPress (r3876) * * @return array An array of the status code and the message */ function bbp_admin_repair_forum_meta() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Recalculating the forum for each post… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); // First, delete everything. if ( is_wp_error( $bbp_db->query( "DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` = '_bbp_forum_id'" ) ) ) { return array( 1, sprintf( $statement, $result ) ); } // Post types and status $tpt = bbp_get_topic_post_type(); $rpt = bbp_get_reply_post_type(); $fmt = bbp_get_forum_post_type(); // Next, give all the topics their parent forum id. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `topic`.`ID`, '_bbp_forum_id', `topic`.`post_parent` FROM `$bbp_db->posts` AS `topic` WHERE `topic`.`post_type` = '{$tpt}' GROUP BY `topic`.`ID` )" ) ) ) { return array( 2, sprintf( $statement, $result ) ); } // Next, give all the forums their parent forum id. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `forum`.`ID`, '_bbp_forum_id', `forum`.`post_parent` FROM `$bbp_db->posts` AS `forum` WHERE `forum`.`post_type` = '{$fmt}' GROUP BY `forum`.`ID` )" ) ) ) { return array( 2, sprintf( $statement, $result ) ); } // Next, give all the replies their parent forum id. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `reply`.`ID`, '_bbp_forum_id', `topic`.`post_parent` FROM `$bbp_db->posts` AS `reply` INNER JOIN `$bbp_db->posts` AS `topic` ON `reply`.`post_parent` = `topic`.`ID` WHERE `topic`.`post_type` = '{$tpt}' AND `reply`.`post_type` = '{$rpt}' GROUP BY `reply`.`ID` )" ) ) ) { return array( 3, sprintf( $statement, $result ) ); } // Complete results return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Repair the topic for each post * * @since 2.1.0 bbPress (r3876) * * @return array An array of the status code and the message */ function bbp_admin_repair_topic_meta() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Recalculating the topic for each post… %s', 'bbpress' ); $result = esc_html__( 'Failed!', 'bbpress' ); // First, delete everything. if ( is_wp_error( $bbp_db->query( "DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` = '_bbp_topic_id'" ) ) ) { return array( 1, sprintf( $statement, $result ) ); } // Post types and status $tpt = bbp_get_topic_post_type(); $rpt = bbp_get_reply_post_type(); // Next, give all the topics with replies the ID their last reply. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `topic`.`ID`, '_bbp_topic_id', `topic`.`ID` FROM `$bbp_db->posts` AS `topic` WHERE `topic`.`post_type` = '{$tpt}' GROUP BY `topic`.`ID` )" ) ) ) { return array( 3, sprintf( $statement, $result ) ); } // Next, give all the topics with replies the ID their last reply. if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) ( SELECT `reply`.`ID`, '_bbp_topic_id', `topic`.`ID` FROM `$bbp_db->posts` AS `reply` INNER JOIN `$bbp_db->posts` AS `topic` ON `reply`.`post_parent` = `topic`.`ID` WHERE `topic`.`post_type` = '{$tpt}' AND `reply`.`post_type` = '{$rpt}' GROUP BY `reply`.`ID` )" ) ) ) { return array( 4, sprintf( $statement, $result ) ); } // Complete results return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); } /** * Recalculate reply menu order * * @since 2.5.4 bbPress (r5367) * * @return array An array of the status code and the message */ function bbp_admin_repair_reply_menu_order() { // Define variables $bbp_db = bbp_db(); $statement = esc_html__( 'Recalculating reply menu order… %s', 'bbpress' ); $result = esc_html__( 'No reply positions to recalculate.', 'bbpress' ); // Delete cases where `_bbp_reply_to` was accidentally set to itself if ( is_wp_error( $bbp_db->query( "DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` = '_bbp_reply_to' AND `post_id` = `meta_value`" ) ) ) { return array( 1, sprintf( $statement, $result ) ); } // Post type $rpt = bbp_get_reply_post_type(); // Get an array of reply id's to update the menu oder for each reply $replies = $bbp_db->get_results( "SELECT `a`.`ID` FROM `{$bbp_db->posts}` AS `a` INNER JOIN ( SELECT `menu_order`, `post_parent` FROM `{$bbp_db->posts}` GROUP BY `menu_order`, `post_parent` HAVING COUNT( * ) >1 )`b` ON `a`.`menu_order` = `b`.`menu_order` AND `a`.`post_parent` = `b`.`post_parent` WHERE `post_type` = '{$rpt}'", OBJECT_K ); // Bail if no replies returned if ( empty( $replies ) ) { return array( 1, sprintf( $statement, $result ) ); } // Recalculate the menu order position for each reply foreach ( $replies as $reply ) { bbp_update_reply_position( $reply->ID ); } // Cleanup unset( $replies, $reply ); // Complete results return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) ); }