[ Index ]

PHP Cross Reference of BBPress

title

Body

[close]

/src/includes/admin/tools/ -> repair.php (source)

   1  <?php
   2  
   3  /**
   4   * bbPress Admin Repair Page
   5   *
   6   * @package bbPress
   7   * @subpackage Administration
   8   */
   9  
  10  // Exit if accessed directly
  11  defined( 'ABSPATH' ) || exit;
  12  
  13  /**
  14   * Admin repair page
  15   *
  16   * @since 2.0.0 bbPress (r2613) Converted from bbPress 1.2
  17   * @since 2.6.0 bbPress (r5885) Upgraded to list-table UI
  18   *
  19   * @todo Use a real list table
  20   *
  21   */
  22  function bbp_admin_repair_page() {
  23  
  24      // Get the registered repair tools
  25      $tools = bbp_admin_repair_list(); ?>
  26  
  27      <div class="wrap">
  28          <h1 class="wp-heading-inline"><?php esc_html_e( 'Forum Tools', 'bbpress' ); ?></h1>
  29          <hr class="wp-header-end">
  30          <h2 class="nav-tab-wrapper"><?php bbp_tools_admin_tabs( 'bbp-repair' ); ?></h2>
  31  
  32          <p><?php esc_html_e( 'bbPress keeps track of relationships between forums, topics, replies, topic-tags, favorites, subscriptions, 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>
  33          <p class="description"><?php esc_html_e( 'Some of these tools create substantial database overhead. Use caution when running more than 1 repair at a time.', 'bbpress' ); ?></p>
  34  
  35          <?php bbp_admin_repair_tool_overhead_filters(); ?>
  36  
  37          <form class="settings" method="get" action="">
  38  
  39              <?php bbp_admin_repair_list_search_form(); ?>
  40  
  41              <input type="hidden" name="page" value="bbp-repair" />
  42              <?php wp_nonce_field( 'bbpress-do-counts' ); ?>
  43  
  44              <div class="tablenav top">
  45                  <div class="alignleft actions bulkactions">
  46                      <label for="bulk-action-selector-top" class="screen-reader-text"><?php esc_html_e( 'Select bulk action', 'bbpress' ); ?></label>
  47                      <select name="action" id="bulk-action-selector-top">
  48                          <option value="" selected="selected"><?php esc_html_e( 'Bulk Actions', 'bbpress' ); ?></option>
  49                          <option value="run" class="hide-if-no-js"><?php esc_html_e( 'Run', 'bbpress' ); ?></option>
  50                      </select>
  51                      <input type="submit" id="doaction" class="button action" value="<?php esc_attr_e( 'Apply', 'bbpress' ); ?>">
  52                  </div>
  53                  <div class="alignleft actions">
  54  
  55                      <?php bbp_admin_repair_list_components_filter(); ?>
  56  
  57                      <input type="submit" name="filter_action" id="components-submit" class="button" value="<?php esc_html_e( 'Filter', 'bbpress' ); ?>">
  58                  </div>
  59                  <br class="clear">
  60              </div>
  61              <table class="wp-list-table widefat striped posts">
  62                  <thead>
  63                      <tr>
  64                          <td id="cb" class="manage-column column-cb check-column">
  65                              <label class="screen-reader-text" for="cb-select-all-1">
  66                                  <?php esc_html_e( 'Select All', 'bbpress' ); ?>
  67                              </label>
  68                              <input id="cb-select-all-1" type="checkbox">
  69                          </td>
  70                          <th scope="col" id="description" class="manage-column column-primary column-description"><?php esc_html_e( 'Description', 'bbpress' ); ?></th>
  71                          <th scope="col" id="components" class="manage-column column-components"><?php esc_html_e( 'Components', 'bbpress' ); ?></th>
  72                          <th scope="col" id="overhead" class="manage-column column-overhead"><?php esc_html_e( 'Overhead', 'bbpress' ); ?></th>
  73                      </tr>
  74                  </thead>
  75  
  76                  <tbody id="the-list">
  77  
  78                      <?php if ( ! empty( $tools ) ) : ?>
  79  
  80                          <?php foreach ( $tools as $item ) : ?>
  81  
  82                              <tr id="bbp-repair-tools" class="inactive">
  83                                  <th scope="row" class="check-column">
  84                                      <label class="screen-reader-text" for="<?php echo esc_attr( str_replace( '_', '-', $item['id'] ) ); ?>"></label>
  85                                      <input type="checkbox" name="checked[]" value="<?php echo esc_attr( $item['id'] ); ?>" id="<?php echo esc_attr( str_replace( '_', '-', $item['id'] ) ); ?>">
  86                                  </th>
  87                                  <td class="bbp-tool-title column-primary column-description" data-colname="<?php esc_html_e( 'Description', 'bbpress' ); ?>">
  88                                      <strong><?php echo esc_html( $item['title'] ); ?></strong><?php
  89  
  90                                          // Optional description
  91                                          if ( ! empty( $item['description'] ) ) :
  92                                              echo esc_html( $item['description'] );
  93                                          endif;
  94  
  95                                      ?><div class="row-actions hide-if-no-js">
  96                                          <span class="run">
  97                                              <a href="<?php bbp_admin_repair_tool_run_url( $item ); ?>" aria-label="<?php printf( esc_html__( 'Run %s', 'bbpress' ), $item['title'] ); ?>" id="<?php echo esc_attr( $item['id'] ); ?>" ><?php esc_html_e( 'Run', 'bbpress' ); ?></a>
  98                                          </span>
  99                                      </div>
 100                                      <button type="button" class="toggle-row">
 101                                          <span class="screen-reader-text"><?php esc_html_e( 'Show more details', 'bbpress' ); ?></span>
 102                                      </button>
 103                                  </td>
 104                                  <td class="column-components desc" data-colname="<?php esc_html_e( 'Components', 'bbpress' ); ?>">
 105                                      <div class="bbp-tool-overhead">
 106  
 107                                          <?php echo implode( ', ', bbp_get_admin_repair_tool_components( $item ) ); ?>
 108  
 109                                      </div>
 110                                  </td>
 111                                  <td class="column-overhead desc" data-colname="<?php esc_html_e( 'Overhead', 'bbpress' ); ?>">
 112                                      <div class="bbp-tool-overhead">
 113  
 114                                          <?php echo implode( ', ', bbp_get_admin_repair_tool_overhead( $item ) ); ?>
 115  
 116                                      </div>
 117                                  </td>
 118                              </tr>
 119  
 120                          <?php endforeach; ?>
 121  
 122                      <?php else : ?>
 123  
 124                          <tr>
 125                              <td colspan="4">
 126                                  <?php esc_html_e( 'No repair tools match this criteria.', 'bbpress' ); ?>
 127                              </td>
 128                          </tr>
 129  
 130                      <?php endif; ?>
 131  
 132                  </tbody>
 133                  <tfoot>
 134                      <tr>
 135                          <td class="manage-column column-cb check-column">
 136                              <label class="screen-reader-text" for="cb-select-all-2">
 137                                  <?php esc_html_e( 'Select All', 'bbpress' ); ?>
 138                              </label>
 139                              <input id="cb-select-all-2" type="checkbox">
 140                          </td>
 141                          <th scope="col" class="manage-column column-primary column-description"><?php esc_html_e( 'Description', 'bbpress' ); ?></th>
 142                          <th scope="col" class="manage-column column-components"><?php esc_html_e( 'Components', 'bbpress' ); ?></th>
 143                          <th scope="col" class="manage-column column-overhead"><?php esc_html_e( 'Overhead', 'bbpress' ); ?></th>
 144                      </tr>
 145                  </tfoot>
 146              </table>
 147              <div class="tablenav bottom">
 148                  <div class="alignleft actions bulkactions">
 149                      <label for="bulk-action-selector-bottom" class="screen-reader-text"><?php esc_html_e( 'Select bulk action', 'bbpress' ); ?></label>
 150                      <select name="action2" id="bulk-action-selector-bottom">
 151                          <option value="" selected="selected"><?php esc_html_e( 'Bulk Actions', 'bbpress' ); ?></option>
 152                          <option value="run" class="hide-if-no-js"><?php esc_html_e( 'Run', 'bbpress' ); ?></option>
 153                      </select>
 154                      <input type="submit" id="doaction2" class="button action" value="<?php esc_attr_e( 'Apply', 'bbpress' ); ?>">
 155                  </div>
 156              </div>
 157          </form>
 158      </div>
 159  
 160  <?php
 161  }
 162  
 163  /**
 164   * Recount topic replies
 165   *
 166   * @since 2.0.0 bbPress (r2613)
 167   *
 168   * @return array An array of the status code and the message
 169   */
 170  function bbp_admin_repair_topic_reply_count() {
 171  
 172      // Define variables
 173      $bbp_db    = bbp_db();
 174      $statement = esc_html__( 'Counting the number of replies in each topic&hellip; %s', 'bbpress' );
 175      $result    = esc_html__( 'Failed!', 'bbpress' );
 176  
 177      // Post types and status
 178      $tpt = bbp_get_topic_post_type();
 179      $rpt = bbp_get_reply_post_type();
 180      $pps = bbp_get_public_status_id();
 181      $cps = bbp_get_closed_status_id();
 182  
 183      // Delete the meta key _bbp_reply_count for each topic
 184      $sql_delete = "DELETE `postmeta` FROM `{$bbp_db->postmeta}` AS `postmeta`
 185                          LEFT JOIN `{$bbp_db->posts}` AS `posts` ON `posts`.`ID` = `postmeta`.`post_id`
 186                          WHERE `posts`.`post_type` = '{$tpt}'
 187                          AND `postmeta`.`meta_key` = '_bbp_reply_count'";
 188  
 189      if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) {
 190          return array( 1, sprintf( $statement, $result ) );
 191      }
 192  
 193      // Recalculate the meta key _bbp_reply_count for each topic
 194      $sql = "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) (
 195              SELECT `topics`.`ID` AS `post_id`, '_bbp_reply_count' AS `meta_key`, COUNT(`replies`.`ID`) As `meta_value`
 196                  FROM `{$bbp_db->posts}` AS `topics`
 197                      LEFT JOIN `{$bbp_db->posts}` as `replies`
 198                          ON  `replies`.`post_parent` = `topics`.`ID`
 199                          AND `replies`.`post_status` = '{$pps}'
 200                          AND `replies`.`post_type`   = '{$rpt}'
 201                  WHERE `topics`.`post_type` = '{$tpt}'
 202                      AND `topics`.`post_status` IN ( '{$pps}', '{$cps}' )
 203                  GROUP BY `topics`.`ID`)";
 204  
 205      if ( is_wp_error( $bbp_db->query( $sql ) ) ) {
 206          return array( 2, sprintf( $statement, $result ) );
 207      }
 208  
 209      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 210  }
 211  
 212  /**
 213   * Recount topic voices
 214   *
 215   * @since 2.0.0 bbPress (r2613)
 216   *
 217   * @return array An array of the status code and the message
 218   */
 219  function bbp_admin_repair_topic_voice_count() {
 220  
 221      // Define variables
 222      $bbp_db    = bbp_db();
 223      $statement = esc_html__( 'Counting the number of voices in each topic&hellip; %s', 'bbpress' );
 224      $result    = esc_html__( 'Failed!', 'bbpress' );
 225  
 226      $sql_delete = "DELETE FROM {$bbp_db->postmeta} WHERE meta_key IN ('_bbp_voice_count', '_bbp_engagement')";
 227      if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) {
 228          return array( 1, sprintf( $statement, $result ) );
 229      }
 230  
 231      // Post types and status
 232      $tpt = bbp_get_topic_post_type();
 233      $rpt = bbp_get_reply_post_type();
 234      $pps = bbp_get_public_status_id();
 235      $cps = bbp_get_closed_status_id();
 236  
 237      $engagements_sql = $bbp_db->prepare( "INSERT INTO {$bbp_db->postmeta} (post_id, meta_key, meta_value) (
 238          SELECT postmeta.meta_value, '_bbp_engagement', posts.post_author
 239              FROM {$bbp_db->posts} AS posts
 240              LEFT JOIN {$bbp_db->postmeta} AS postmeta
 241                  ON posts.ID = postmeta.post_id
 242                  AND postmeta.meta_key = '_bbp_topic_id'
 243              WHERE posts.post_type IN (%s, %s)
 244                  AND posts.post_status IN (%s, %s)
 245              GROUP BY postmeta.meta_value, posts.post_author)", $tpt, $rpt, $pps, $cps );
 246  
 247      if ( is_wp_error( $bbp_db->query( $engagements_sql ) ) ) {
 248          return array( 2, sprintf( $statement, $result ) );
 249      }
 250  
 251      $voice_count_sql = "INSERT INTO {$bbp_db->postmeta} (post_id, meta_key, meta_value) (
 252          SELECT post_id, '_bbp_voice_count', COUNT(DISTINCT meta_value)
 253              FROM {$bbp_db->postmeta}
 254              WHERE meta_key = '_bbp_engagement'
 255              GROUP BY post_id)";
 256  
 257      if ( is_wp_error( $bbp_db->query( $voice_count_sql ) ) ) {
 258          return array( 3, sprintf( $statement, $result ) );
 259      }
 260  
 261      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 262  }
 263  
 264  /**
 265   * Recount topic hidden replies (spammed/trashed)
 266   *
 267   * @since 2.0.0 bbPress (r2747)
 268   *
 269   * @return array An array of the status code and the message
 270   */
 271  function bbp_admin_repair_topic_hidden_reply_count() {
 272  
 273      // Define variables
 274      $bbp_db    = bbp_db();
 275      $statement = esc_html__( 'Counting the number of pending, spammed, and trashed replies in each topic&hellip; %s', 'bbpress' );
 276      $result    = esc_html__( 'Failed!', 'bbpress' );
 277  
 278      $sql_delete = "DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` = '_bbp_reply_count_hidden'";
 279      if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) {
 280          return array( 1, sprintf( $statement, $result ) );
 281      }
 282  
 283      // Post types and status
 284      $rpt = bbp_get_reply_post_type();
 285      $sta = bbp_get_non_public_topic_statuses();
 286  
 287      // SQL
 288      $sql_status = "'" . implode( "','", $sta ) . "'";
 289  
 290      $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`)";
 291      if ( is_wp_error( $bbp_db->query( $sql ) ) ) {
 292          return array( 2, sprintf( $statement, $result ) );
 293      }
 294  
 295      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 296  }
 297  
 298  /**
 299   * Recount forum topics
 300   *
 301   * @since 2.0.0 bbPress (r2613)
 302   *
 303   * @return array An array of the status code and the message
 304   */
 305  function bbp_admin_repair_forum_topic_count() {
 306  
 307      // Define variables
 308      $bbp_db    = bbp_db();
 309      $statement = esc_html__( 'Counting the number of topics in each forum&hellip; %s', 'bbpress' );
 310      $result    = esc_html__( 'Failed!', 'bbpress' );
 311  
 312      $sql_delete = "DELETE FROM {$bbp_db->postmeta} WHERE meta_key IN ( '_bbp_topic_count', '_bbp_total_topic_count', '_bbp_topic_count_hidden' )";
 313      if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) {
 314          return array( 1, sprintf( $statement, $result ) );
 315      }
 316  
 317      $forums = get_posts( array( 'post_type' => bbp_get_forum_post_type(), 'numberposts' => -1 ) );
 318      if ( ! empty( $forums ) ) {
 319          foreach ( $forums as $forum ) {
 320              bbp_update_forum_topic_count( $forum->ID );
 321              bbp_update_forum_topic_count_hidden( $forum->ID );
 322          }
 323      } else {
 324          return array( 2, sprintf( $statement, $result ) );
 325      }
 326  
 327      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 328  }
 329  
 330  /**
 331   * Recount topic in each topic-tag
 332   *
 333   * @since 2.6.0 bbPress (r6256)
 334   *
 335   * @return array An array of the status code and the message
 336   */
 337  function bbp_admin_repair_topic_tag_count() {
 338  
 339      // Define variables
 340      $statement = esc_html__( 'Counting the number of topics in each topic-tag&hellip; %s', 'bbpress' );
 341      $result    = esc_html__( 'Failed!', 'bbpress' );
 342      $tax_id    = bbp_get_topic_tag_tax_id();
 343      $terms     = get_terms( $tax_id, array( 'hide_empty' => false ) );
 344      $tt_ids    = wp_list_pluck( $terms, 'term_taxonomy_id' );
 345      $ints      = array_map( 'intval', $tt_ids );
 346      $taxonomy  = get_taxonomy( $tax_id );
 347  
 348      // Bail if taxonomy does not exist
 349      if ( empty( $taxonomy ) ) {
 350          return array( 1, sprintf( $statement, $result ) );
 351      }
 352  
 353      // Custom callback
 354      if ( ! empty( $taxonomy->update_count_callback ) ) {
 355  
 356          // Bail if callback is not callable
 357          if ( ! is_callable( $taxonomy->update_count_callback ) ) {
 358              return array( 1, sprintf( $statement, $result ) );
 359          }
 360  
 361          call_user_func( $taxonomy->update_count_callback, $ints, $taxonomy );
 362  
 363      // Generic callback fallback
 364      } else {
 365          _update_post_term_count( $ints, $taxonomy );
 366      }
 367  
 368      // Bust the cache
 369      clean_term_cache( $ints, '', false );
 370  
 371      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 372  }
 373  
 374  /**
 375   * Recount forum replies
 376   *
 377   * @since 2.0.0 bbPress (r2613)
 378   *
 379   * @return array An array of the status code and the message
 380   */
 381  function bbp_admin_repair_forum_reply_count() {
 382  
 383      // Define variables
 384      $bbp_db    = bbp_db();
 385      $statement = esc_html__( 'Counting the number of replies in each forum&hellip; %s', 'bbpress' );
 386      $result    = esc_html__( 'Failed!', 'bbpress' );
 387  
 388      // Post type
 389      $fpt = bbp_get_forum_post_type();
 390  
 391      // Delete the meta keys _bbp_reply_count and _bbp_total_reply_count for each forum
 392      $sql_delete = "DELETE `postmeta` FROM `{$bbp_db->postmeta}` AS `postmeta`
 393                          LEFT JOIN `{$bbp_db->posts}` AS `posts` ON `posts`.`ID` = `postmeta`.`post_id`
 394                          WHERE `posts`.`post_type` = '{$fpt}'
 395                          AND `postmeta`.`meta_key` = '_bbp_reply_count'
 396                          OR `postmeta`.`meta_key` = '_bbp_total_reply_count'";
 397  
 398      if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) {
 399           return array( 1, sprintf( $statement, $result ) );
 400      }
 401  
 402      // Recalculate the metas key _bbp_reply_count and _bbp_total_reply_count for each forum
 403      $forums = get_posts( array( 'post_type' => bbp_get_forum_post_type(), 'numberposts' => -1 ) );
 404      if ( ! empty( $forums ) ) {
 405          foreach ( $forums as $forum ) {
 406              bbp_update_forum_reply_count( $forum->ID );
 407          }
 408      } else {
 409          return array( 2, sprintf( $statement, $result ) );
 410      }
 411  
 412      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 413  }
 414  
 415  /**
 416   * Recount topics by the users
 417   *
 418   * @since 2.1.0 bbPress (r3889)
 419   *
 420   * @return array An array of the status code and the message
 421   */
 422  function bbp_admin_repair_user_topic_count() {
 423  
 424      // Define variables
 425      $bbp_db      = bbp_db();
 426      $statement   = esc_html__( 'Counting the number of topics each user has created&hellip; %s', 'bbpress' );
 427      $result      = esc_html__( 'Failed!', 'bbpress' );
 428  
 429      $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`";
 430      $insert_rows = $bbp_db->get_results( $sql_select );
 431  
 432      if ( is_wp_error( $insert_rows ) ) {
 433          return array( 1, sprintf( $statement, $result ) );
 434      }
 435  
 436      $key           = $bbp_db->prefix . '_bbp_topic_count';
 437      $insert_values = array();
 438      foreach ( $insert_rows as $insert_row ) {
 439          $insert_values[] = "('{$insert_row->post_author}', '{$key}', '{$insert_row->_count}')";
 440      }
 441  
 442      if ( !count( $insert_values ) ) {
 443          return array( 2, sprintf( $statement, $result ) );
 444      }
 445  
 446      $sql_delete = "DELETE FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'";
 447      if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) {
 448          return array( 3, sprintf( $statement, $result ) );
 449      }
 450  
 451      foreach ( array_chunk( $insert_values, 10000 ) as $chunk ) {
 452          $chunk = "\n" . implode( ",\n", $chunk );
 453          $sql_insert = "INSERT INTO `{$bbp_db->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES {$chunk}";
 454  
 455          if ( is_wp_error( $bbp_db->query( $sql_insert ) ) ) {
 456              return array( 4, sprintf( $statement, $result ) );
 457          }
 458      }
 459  
 460      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 461  }
 462  
 463  /**
 464   * Recount topic replied by the users
 465   *
 466   * @since 2.0.0 bbPress (r2613)
 467   *
 468   * @return array An array of the status code and the message
 469   */
 470  function bbp_admin_repair_user_reply_count() {
 471  
 472      // Define variables
 473      $bbp_db    = bbp_db();
 474      $statement   = esc_html__( 'Counting the number of topics to which each user has replied&hellip; %s', 'bbpress' );
 475      $result      = esc_html__( 'Failed!', 'bbpress' );
 476  
 477      $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`";
 478      $insert_rows = $bbp_db->get_results( $sql_select );
 479  
 480      if ( is_wp_error( $insert_rows ) ) {
 481          return array( 1, sprintf( $statement, $result ) );
 482      }
 483  
 484      $key           = $bbp_db->prefix . '_bbp_reply_count';
 485      $insert_values = array();
 486      foreach ( $insert_rows as $insert_row ) {
 487          $insert_values[] = "('{$insert_row->post_author}', '{$key}', '{$insert_row->_count}')";
 488      }
 489  
 490      if ( !count( $insert_values ) ) {
 491          return array( 2, sprintf( $statement, $result ) );
 492      }
 493  
 494      $sql_delete = "DELETE FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'";
 495      if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) {
 496          return array( 3, sprintf( $statement, $result ) );
 497      }
 498  
 499      foreach ( array_chunk( $insert_values, 10000 ) as $chunk ) {
 500          $chunk = "\n" . implode( ",\n", $chunk );
 501          $sql_insert = "INSERT INTO `{$bbp_db->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES {$chunk}";
 502  
 503          if ( is_wp_error( $bbp_db->query( $sql_insert ) ) ) {
 504              return array( 4, sprintf( $statement, $result ) );
 505          }
 506      }
 507  
 508      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 509  }
 510  
 511  /**
 512   * Repair user favorites
 513   *
 514   * @since 2.0.0 bbPress (r2613)
 515   *
 516   * @return array An array of the status code and the message
 517   */
 518  function bbp_admin_repair_user_favorites() {
 519  
 520      // Define variables
 521      $bbp_db    = bbp_db();
 522      $statement = esc_html__( 'Removing unpublished topics from user favorites&hellip; %s', 'bbpress' );
 523      $result    = esc_html__( 'Failed!', 'bbpress' );
 524  
 525      // Query for users with favorites
 526      $key       = $bbp_db->prefix . '_bbp_favorites';
 527      $users     = $bbp_db->get_results( "SELECT `user_id`, `meta_value` AS `favorites` FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'" );
 528  
 529      if ( is_wp_error( $users ) ) {
 530          return array( 1, sprintf( $statement, $result ) );
 531      }
 532  
 533      $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() . "'" );
 534  
 535      if ( is_wp_error( $topics ) ) {
 536          return array( 2, sprintf( $statement, $result ) );
 537      }
 538  
 539      $values = array();
 540      foreach ( $users as $user ) {
 541          if ( empty( $user->favorites ) || ! is_string( $user->favorites ) ) {
 542              continue;
 543          }
 544  
 545          $favorites = array_intersect( $topics, explode( ',', $user->favorites ) );
 546          if ( empty( $favorites ) || ! is_array( $favorites ) ) {
 547              continue;
 548          }
 549  
 550          $favorites_joined = implode( ',', $favorites );
 551          $values[]         = "('{$user->user_id}', '{$key}', '{$favorites_joined}')";
 552  
 553          // Cleanup
 554          unset( $favorites, $favorites_joined );
 555      }
 556  
 557      if ( !count( $values ) ) {
 558          $result = esc_html__( 'Nothing to remove!', 'bbpress' );
 559          return array( 0, sprintf( $statement, $result ) );
 560      }
 561  
 562      $sql_delete = "DELETE FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'";
 563      if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) {
 564          return array( 4, sprintf( $statement, $result ) );
 565      }
 566  
 567      foreach ( array_chunk( $values, 10000 ) as $chunk ) {
 568          $chunk = "\n" . implode( ",\n", $chunk );
 569          $sql_insert = "INSERT INTO `{$bbp_db->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES {$chunk}";
 570          if ( is_wp_error( $bbp_db->query( $sql_insert ) ) ) {
 571              return array( 5, sprintf( $statement, $result ) );
 572          }
 573      }
 574  
 575      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 576  }
 577  
 578  /**
 579   * Clean the user topic subscriptions
 580   *
 581   * @since 2.0.0 bbPress (r2668)
 582   *
 583   * @return array An array of the status code and the message
 584   */
 585  function bbp_admin_repair_user_topic_subscriptions() {
 586  
 587      // Define variables
 588      $bbp_db    = bbp_db();
 589      $statement = esc_html__( 'Removing trashed topics from user subscriptions&hellip; %s', 'bbpress' );
 590      $result    = esc_html__( 'Failed!', 'bbpress' );
 591  
 592      $key       = $bbp_db->prefix . '_bbp_subscriptions';
 593      $users     = $bbp_db->get_results( "SELECT `user_id`, `meta_value` AS `subscriptions` FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'" );
 594  
 595      if ( is_wp_error( $users ) ) {
 596          return array( 1, sprintf( $statement, $result ) );
 597      }
 598  
 599      $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() . "'" );
 600      if ( is_wp_error( $topics ) ) {
 601          return array( 2, sprintf( $statement, $result ) );
 602      }
 603  
 604      $values = array();
 605      foreach ( $users as $user ) {
 606          if ( empty( $user->subscriptions ) || ! is_string( $user->subscriptions ) ) {
 607              continue;
 608          }
 609  
 610          $subscriptions = array_intersect( $topics, explode( ',', $user->subscriptions ) );
 611          if ( empty( $subscriptions ) || ! is_array( $subscriptions ) ) {
 612              continue;
 613          }
 614  
 615          $subscriptions_joined = implode( ',', $subscriptions );
 616          $values[]             = "('{$user->user_id}', '{$key}', '{$subscriptions_joined}')";
 617  
 618          // Cleanup
 619          unset( $subscriptions, $subscriptions_joined );
 620      }
 621  
 622      if ( !count( $values ) ) {
 623          $result = esc_html__( 'Nothing to remove!', 'bbpress' );
 624          return array( 0, sprintf( $statement, $result ) );
 625      }
 626  
 627      $sql_delete = "DELETE FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'";
 628      if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) {
 629          return array( 4, sprintf( $statement, $result ) );
 630      }
 631  
 632      foreach ( array_chunk( $values, 10000 ) as $chunk ) {
 633          $chunk = "\n" . implode( ",\n", $chunk );
 634          $sql_insert = "INSERT INTO `{$bbp_db->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES {$chunk}";
 635          if ( is_wp_error( $bbp_db->query( $sql_insert ) ) ) {
 636              return array( 5, sprintf( $statement, $result ) );
 637          }
 638      }
 639  
 640      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 641  }
 642  
 643  /**
 644   * Clean the user forum subscriptions
 645   *
 646   * @since 2.5.0 bbPress (r5155)
 647   *
 648   * @return array An array of the status code and the message
 649   */
 650  function bbp_admin_repair_user_forum_subscriptions() {
 651  
 652      // Define variables
 653      $bbp_db    = bbp_db();
 654      $statement = esc_html__( 'Removing trashed forums from user subscriptions&hellip; %s', 'bbpress' );
 655      $result    = esc_html__( 'Failed!', 'bbpress' );
 656  
 657      $key       = $bbp_db->prefix . '_bbp_forum_subscriptions';
 658      $users     = $bbp_db->get_results( "SELECT `user_id`, `meta_value` AS `subscriptions` FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'" );
 659  
 660      if ( is_wp_error( $users ) ) {
 661          return array( 1, sprintf( $statement, $result ) );
 662      }
 663  
 664      $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() . "'" );
 665      if ( is_wp_error( $forums ) ) {
 666          return array( 2, sprintf( $statement, $result ) );
 667      }
 668  
 669      $values = array();
 670      foreach ( $users as $user ) {
 671          if ( empty( $user->subscriptions ) || ! is_string( $user->subscriptions ) ) {
 672              continue;
 673          }
 674  
 675          $subscriptions = array_intersect( $forums, explode( ',', $user->subscriptions ) );
 676          if ( empty( $subscriptions ) || ! is_array( $subscriptions ) ) {
 677              continue;
 678          }
 679  
 680          $subscriptions_joined = implode( ',', $subscriptions );
 681          $values[]             = "('{$user->user_id}', '{$key}', '{$subscriptions_joined}')";
 682  
 683          // Cleanup
 684          unset( $subscriptions, $subscriptions_joined );
 685      }
 686  
 687      if ( !count( $values ) ) {
 688          $result = esc_html__( 'Nothing to remove!', 'bbpress' );
 689          return array( 0, sprintf( $statement, $result ) );
 690      }
 691  
 692      $sql_delete = "DELETE FROM `{$bbp_db->usermeta}` WHERE `meta_key` = '{$key}'";
 693      if ( is_wp_error( $bbp_db->query( $sql_delete ) ) ) {
 694          return array( 4, sprintf( $statement, $result ) );
 695      }
 696  
 697      foreach ( array_chunk( $values, 10000 ) as $chunk ) {
 698          $chunk = "\n" . implode( ",\n", $chunk );
 699          $sql_insert = "INSERT INTO `{$bbp_db->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES {$chunk}";
 700          if ( is_wp_error( $bbp_db->query( $sql_insert ) ) ) {
 701              return array( 5, sprintf( $statement, $result ) );
 702          }
 703      }
 704  
 705      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 706  }
 707  
 708  /**
 709   * This repair tool will map each user of the current site to their respective
 710   * forums role. By default, Admins will be Key Masters, and every other role
 711   * will be the default role defined in Settings > Forums (Participant).
 712   *
 713   * @since 2.2.0 bbPress (r4340)
 714   */
 715  function bbp_admin_repair_user_roles() {
 716  
 717      $statement    = esc_html__( 'Remapping forum role for each user on this site&hellip; %s', 'bbpress' );
 718      $changed      = 0;
 719      $role_map     = bbp_get_user_role_map();
 720      $default_role = bbp_get_default_role();
 721  
 722      // Bail if no role map exists
 723      if ( empty( $role_map ) ) {
 724          return array( 1, sprintf( $statement, esc_html__( 'Failed!', 'bbpress' ) ) );
 725      }
 726  
 727      // Get non-forum roles
 728      $blog_roles = array_keys( bbp_get_blog_roles() );
 729  
 730      // Iterate through each role...
 731      foreach ( $blog_roles as $role ) {
 732  
 733          // Reset the offset
 734          $offset = 0;
 735  
 736          // If no role map exists, give the default forum role (bbp-participant)
 737          $new_role = isset( $role_map[ $role ] )
 738              ? $role_map[ $role ]
 739              : $default_role;
 740  
 741          // Get users of this site, limited to 1000
 742          while ( $users = get_users( array(
 743              'role'   => $role,
 744              'fields' => 'ID',
 745              'number' => 1000,
 746              'offset' => $offset
 747          ) ) ) {
 748  
 749              // Iterate through each user of $role and try to set it
 750              foreach ( (array) $users as $user_id ) {
 751                  if ( bbp_set_user_role( $user_id, $new_role ) ) {
 752                      ++$changed; // Keep a count to display at the end
 753                  }
 754              }
 755  
 756              // Bump the offset for the next query iteration
 757              $offset = $offset + 1000;
 758          }
 759      }
 760  
 761      // Reset the offset
 762      $offset  = 0;
 763      $bbp_db  = bbp_db();
 764      $cap_key = $bbp_db->get_blog_prefix() . 'capabilities';
 765  
 766      // Users without roles should be granted the default role, but not on multi-
 767      // site installations where not all users get a role by default.
 768      if ( ! is_multisite() ) {
 769  
 770          // Get users with missing capabilities on this site, limited to 1000
 771          while ( $users = get_users( array(
 772              'meta_key'     => $cap_key,
 773              'meta_compare' => 'NOT EXISTS',
 774              'fields'       => 'ID',
 775              'number'       => 1000,
 776              'offset'       => $offset
 777          ) ) ) {
 778  
 779              // Iterate through each user of $role and try to set it
 780              foreach ( (array) $users as $user_id ) {
 781                  if ( bbp_set_user_role( $user_id, $default_role ) ) {
 782                      ++$changed; // Keep a count to display at the end
 783                  }
 784              }
 785  
 786              // Bump the offset for the next query iteration
 787              $offset = $offset + 1000;
 788          }
 789  
 790      // On multisite, we'll look for users with an empty capabilities array.
 791      // These are users who basically have malformed caps, and we can fix that.
 792      } else {
 793  
 794          // Get users with empty capabilities on this site, limited to 1000
 795          while ( $users = get_users( array(
 796              'meta_key'   => $cap_key,
 797              'meta_value' => 'a:0:{}',
 798              'fields'     => 'ID',
 799              'number'     => 1000,
 800              'offset'     => $offset
 801          ) ) ) {
 802  
 803              // Iterate through each user of $role and try to set it
 804              foreach ( (array) $users as $user_id ) {
 805                  if ( bbp_set_user_role( $user_id, $default_role ) ) {
 806                      ++$changed; // Keep a count to display at the end
 807                  }
 808              }
 809  
 810              // Bump the offset for the next query iteration
 811              $offset = $offset + 1000;
 812          }
 813      }
 814  
 815      $result = sprintf( esc_html__( 'Complete! %s users updated.', 'bbpress' ), bbp_number_format( $changed ) );
 816  
 817      return array( 0, sprintf( $statement, $result ) );
 818  }
 819  
 820  /**
 821   * Repair the last post in every topic and forum
 822   *
 823   * @since 2.0.0 bbPress (r3040)
 824   *
 825   * @return array An array of the status code and the message
 826   */
 827  function bbp_admin_repair_freshness() {
 828  
 829      // Define variables
 830      $bbp_db    = bbp_db();
 831      $statement = esc_html__( 'Recomputing latest post in every topic and forum&hellip; %s', 'bbpress' );
 832      $result    = esc_html__( 'Failed!', 'bbpress' );
 833  
 834      // First, delete everything.
 835      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' )" ) ) ) {
 836          return array( 1, sprintf( $statement, $result ) );
 837      }
 838  
 839      // Post types and status
 840      $fpt = bbp_get_forum_post_type();
 841      $tpt = bbp_get_topic_post_type();
 842      $rpt = bbp_get_reply_post_type();
 843      $pps = bbp_get_public_status_id();
 844  
 845      // Next, give all the topics with replies the ID their last reply.
 846      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
 847              ( SELECT `topic`.`ID`, '_bbp_last_reply_id', MAX( `reply`.`ID` )
 848              FROM `{$bbp_db->posts}` AS `topic` INNER JOIN `{$bbp_db->posts}` AS `reply` ON `topic`.`ID` = `reply`.`post_parent`
 849              WHERE `reply`.`post_status` = '{$pps}' AND `topic`.`post_type` = '{$tpt}' AND `reply`.`post_type` = '{$rpt}'
 850              GROUP BY `topic`.`ID` )" ) ) ) {
 851          return array( 2, sprintf( $statement, $result ) );
 852      }
 853  
 854      // For any remaining topics, give a reply ID of 0.
 855      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
 856              ( SELECT `ID`, '_bbp_last_reply_id', 0
 857              FROM `{$bbp_db->posts}` AS `topic` LEFT JOIN `{$bbp_db->postmeta}` AS `reply`
 858              ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_reply_id'
 859              WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = '{$tpt}' )" ) ) ) {
 860          return array( 3, sprintf( $statement, $result ) );
 861      }
 862  
 863      // Now we give all the forums with topics the ID their last topic.
 864      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
 865              ( SELECT `forum`.`ID`, '_bbp_last_topic_id', MAX( `topic`.`ID` )
 866              FROM `{$bbp_db->posts}` AS `forum` INNER JOIN `{$bbp_db->posts}` AS `topic` ON `forum`.`ID` = `topic`.`post_parent`
 867              WHERE `topic`.`post_status` = '{$pps}' AND `forum`.`post_type` = '{$fpt}' AND `topic`.`post_type` = '{$tpt}'
 868              GROUP BY `forum`.`ID` )" ) ) ) {
 869          return array( 4, sprintf( $statement, $result ) );
 870      }
 871  
 872      // For any remaining forums, give a topic ID of 0.
 873      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
 874              ( SELECT `ID`, '_bbp_last_topic_id', 0
 875              FROM `{$bbp_db->posts}` AS `forum` LEFT JOIN `{$bbp_db->postmeta}` AS `topic`
 876              ON `forum`.`ID` = `topic`.`post_id` AND `topic`.`meta_key` = '_bbp_last_topic_id'
 877              WHERE `topic`.`meta_id` IS NULL AND `forum`.`post_type` = '{$fpt}' )" ) ) ) {
 878          return array( 5, sprintf( $statement, $result ) );
 879      }
 880  
 881      // After that, we give all the topics with replies the ID their last reply (again, this time for a different reason).
 882      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
 883              ( SELECT `topic`.`ID`, '_bbp_last_active_id', MAX( `reply`.`ID` )
 884              FROM `{$bbp_db->posts}` AS `topic` INNER JOIN `{$bbp_db->posts}` AS `reply` ON `topic`.`ID` = `reply`.`post_parent`
 885              WHERE `reply`.`post_status` = '{$pps}' AND `topic`.`post_type` = '{$tpt}' AND `reply`.`post_type` = '{$rpt}'
 886              GROUP BY `topic`.`ID` )" ) ) ) {
 887          return array( 6, sprintf( $statement, $result ) );
 888      }
 889  
 890      // For any remaining topics, give a reply ID of themself.
 891      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
 892              ( SELECT `ID`, '_bbp_last_active_id', `ID`
 893              FROM `{$bbp_db->posts}` AS `topic` LEFT JOIN `{$bbp_db->postmeta}` AS `reply`
 894              ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_active_id'
 895              WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = '{$tpt}' )" ) ) ) {
 896          return array( 7, sprintf( $statement, $result ) );
 897      }
 898  
 899      // Give topics with replies their last update time.
 900      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
 901              ( SELECT `topic`.`ID`, '_bbp_last_active_time', MAX( `reply`.`post_date` )
 902              FROM `{$bbp_db->posts}` AS `topic` INNER JOIN `{$bbp_db->posts}` AS `reply` ON `topic`.`ID` = `reply`.`post_parent`
 903              WHERE `reply`.`post_status` = '{$pps}' AND `topic`.`post_type` = '{$tpt}' AND `reply`.`post_type` = '{$rpt}'
 904              GROUP BY `topic`.`ID` )" ) ) ) {
 905          return array( 8, sprintf( $statement, $result ) );
 906      }
 907  
 908      // Give topics without replies their last update time.
 909      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
 910              ( SELECT `ID`, '_bbp_last_active_time', `post_date`
 911              FROM `{$bbp_db->posts}` AS `topic` LEFT JOIN `{$bbp_db->postmeta}` AS `reply`
 912              ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_active_time'
 913              WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = '{$tpt}' )" ) ) ) {
 914          return array( 9, sprintf( $statement, $result ) );
 915      }
 916  
 917      // Forums need to know what their last active item is as well. Now it gets a bit more complex to do in the database.
 918      $forums = $bbp_db->get_col( "SELECT `ID` FROM `{$bbp_db->posts}` WHERE `post_type` = '{$fpt}' and `post_status` != 'auto-draft'" );
 919      if ( is_wp_error( $forums ) ) {
 920          return array( 10, sprintf( $statement, $result ) );
 921      }
 922  
 923       // Loop through forums
 924       foreach ( $forums as $forum_id ) {
 925          if ( ! bbp_is_forum_category( $forum_id ) ) {
 926              bbp_update_forum( array( 'forum_id' => $forum_id ) );
 927          }
 928      }
 929  
 930      // Loop through categories when forums are done
 931      foreach ( $forums as $forum_id ) {
 932          if ( bbp_is_forum_category( $forum_id ) ) {
 933              bbp_update_forum( array( 'forum_id' => $forum_id ) );
 934          }
 935      }
 936  
 937      // Complete results
 938      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 939  }
 940  
 941  /**
 942   * Repair the relationship of sticky topics to the actual parent forum
 943   *
 944   * @since 2.3.0 bbPress (r4695)
 945   *
 946   * @return array An array of the status code and the message
 947   */
 948  function bbp_admin_repair_sticky() {
 949  
 950      // Define variables
 951      $bbp_db    = bbp_db();
 952      $statement = esc_html__( 'Repairing the sticky topic to the parent forum relationships&hellip; %s', 'bbpress' );
 953      $result    = esc_html__( 'Failed!', 'bbpress' );
 954  
 955      $forums    = $bbp_db->get_col( "SELECT ID FROM `{$bbp_db->posts}` WHERE `post_type` = '" . bbp_get_forum_post_type() . "'" );
 956  
 957      // Bail if no forums found
 958      if ( empty( $forums ) || is_wp_error( $forums ) ) {
 959          return array( 1, sprintf( $statement, $result ) );
 960      }
 961  
 962      // Loop through forums and get their sticky topics
 963      foreach ( $forums as $forum ) {
 964          $forum_stickies[ $forum ] = get_post_meta( $forum, '_bbp_sticky_topics', true );
 965      }
 966  
 967      // Cleanup
 968      unset( $forums, $forum );
 969  
 970      // Loop through each forum with sticky topics
 971      foreach ( $forum_stickies as $forum_id => $stickies ) {
 972  
 973          // Skip if no stickies
 974          if ( empty( $stickies ) ) {
 975              continue;
 976          }
 977  
 978          // Loop through each sticky topic
 979          foreach ( $stickies as $id => $topic_id ) {
 980  
 981              // If the topic is not a super sticky, and the forum ID does not
 982              // match the topic's forum ID, unset the forum's sticky meta.
 983              if ( ! bbp_is_topic_super_sticky( $topic_id ) && ( $forum_id !== bbp_get_topic_forum_id( $topic_id ) ) ) {
 984                  unset( $forum_stickies[ $forum_id ][ $id ] );
 985              }
 986          }
 987  
 988          // Get sticky topic ID's, or use empty string
 989          $stickers = ! empty( $forum_stickies[ $forum_id ] )
 990              ? array_values( $forum_stickies[ $forum_id ] )
 991              : '';
 992  
 993          // Update the forum's sticky topics meta
 994          update_post_meta( $forum_id, '_bbp_sticky_topics', $stickers );
 995      }
 996  
 997      // Complete results
 998      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
 999  }
1000  
1001  /**
1002   * Repair closed topics
1003   *
1004   * Closed topics that are missing the post-meta "_bbp_status" key value "publish"
1005   * result in unexpected behavior, primarily this would have only occurred if you
1006   * had imported forums from another forum package previous to bbPress v2.6,
1007   * https://bbpress.trac.wordpress.org/ticket/2577
1008   *
1009   * @since 2.6.0 bbPress (r5668)
1010   *
1011   * @return array An array of the status code and the message
1012   */
1013  function bbp_admin_repair_closed_topics() {
1014  
1015      // Define variables
1016      $bbp_db        = bbp_db();
1017      $statement     = esc_html__( 'Repairing closed topics&hellip; %s', 'bbpress' );
1018      $result        = esc_html__( 'No closed topics to repair.',        'bbpress' );
1019      $changed       = 0;
1020  
1021      // Results
1022      $query         = "SELECT ID FROM `{$bbp_db->posts}` WHERE `post_type` = %s AND `post_status` = %s";
1023      $prepare       = $bbp_db->prepare( $query, bbp_get_topic_post_type(), bbp_get_closed_status_id() );
1024      $closed_topics = $bbp_db->get_col( $prepare );
1025  
1026      // Bail if no closed topics found
1027      if ( empty( $closed_topics ) || is_wp_error( $closed_topics ) ) {
1028          return array( 1, sprintf( $statement, $result ) );
1029      }
1030  
1031      // Loop through each closed topic
1032      foreach ( $closed_topics as $closed_topic ) {
1033  
1034          // Check if the closed topic already has a postmeta _bbp_status value
1035          $topic_status = get_post_meta( $closed_topic, '_bbp_status', true );
1036  
1037          // If we don't have a postmeta _bbp_status value
1038          if( empty( $topic_status ) ) {
1039              update_post_meta( $closed_topic, '_bbp_status', 'publish' );
1040              ++$changed; // Keep a count to display at the end
1041          }
1042      }
1043  
1044      // Cleanup
1045      unset( $closed_topics, $closed_topic, $topic_status );
1046  
1047      // Complete results
1048      $result = sprintf( _n( 'Complete! %d closed topic repaired.', 'Complete! %d closed topics repaired.', $changed, 'bbpress' ), $changed );
1049  
1050      return array( 0, sprintf( $statement, $result ) );
1051  }
1052  
1053  /**
1054   * Repair the private and hidden forums
1055   *
1056   * @since 2.2.0 bbPress (r4104)
1057   *
1058   * @return array An array of the status code and the message
1059   */
1060  function bbp_admin_repair_forum_visibility() {
1061      $statement = esc_html__( 'Recalculating forum visibility&hellip; %s', 'bbpress' );
1062  
1063      // Bail if queries returned errors
1064      if ( ! bbp_repair_forum_visibility() ) {
1065          return array( 2, sprintf( $statement, esc_html__( 'Failed!',   'bbpress' ) ) );
1066  
1067      // Complete results
1068      } else {
1069          return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
1070      }
1071  }
1072  
1073  /**
1074   * Repair the parent forum meta for each topic and reply
1075   *
1076   * @since 2.1.0 bbPress (r3876)
1077   *
1078   * @return array An array of the status code and the message
1079   */
1080  function bbp_admin_repair_forum_meta() {
1081  
1082      // Define variables
1083      $bbp_db    = bbp_db();
1084      $statement = esc_html__( 'Recalculating the forum for each post&hellip; %s', 'bbpress' );
1085      $result    = esc_html__( 'Failed!', 'bbpress' );
1086  
1087      // First, delete everything.
1088      if ( is_wp_error( $bbp_db->query( "DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` = '_bbp_forum_id'" ) ) ) {
1089          return array( 1, sprintf( $statement, $result ) );
1090      }
1091  
1092      // Post types and status
1093      $tpt = bbp_get_topic_post_type();
1094      $rpt = bbp_get_reply_post_type();
1095  
1096      // Next, give all the topics their parent forum id.
1097      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
1098              ( SELECT `topic`.`ID`, '_bbp_forum_id', `topic`.`post_parent`
1099              FROM `$bbp_db->posts`
1100                  AS `topic`
1101              WHERE `topic`.`post_type` = '{$tpt}'
1102              GROUP BY `topic`.`ID` )" ) ) ) {
1103          return array( 2, sprintf( $statement, $result ) );
1104      }
1105  
1106      // Next, give all the replies their parent forum id.
1107      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
1108              ( SELECT `reply`.`ID`, '_bbp_forum_id', `topic`.`post_parent`
1109              FROM `$bbp_db->posts`
1110                  AS `reply`
1111              INNER JOIN `$bbp_db->posts`
1112                  AS `topic`
1113                  ON `reply`.`post_parent` = `topic`.`ID`
1114              WHERE `topic`.`post_type` = '{$tpt}'
1115                  AND `reply`.`post_type` = '{$rpt}'
1116              GROUP BY `reply`.`ID` )" ) ) ) {
1117          return array( 3, sprintf( $statement, $result ) );
1118      }
1119  
1120      // Complete results
1121      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
1122  }
1123  
1124  /**
1125   * Repair the topic for each post
1126   *
1127   * @since 2.1.0 bbPress (r3876)
1128   *
1129   * @return array An array of the status code and the message
1130   */
1131  function bbp_admin_repair_topic_meta() {
1132  
1133      // Define variables
1134      $bbp_db    = bbp_db();
1135      $statement = esc_html__( 'Recalculating the topic for each post&hellip; %s', 'bbpress' );
1136      $result    = esc_html__( 'Failed!', 'bbpress' );
1137  
1138      // First, delete everything.
1139      if ( is_wp_error( $bbp_db->query( "DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` = '_bbp_topic_id'" ) ) ) {
1140          return array( 1, sprintf( $statement, $result ) );
1141      }
1142  
1143      // Post types and status
1144      $tpt = bbp_get_topic_post_type();
1145      $rpt = bbp_get_reply_post_type();
1146  
1147      // Next, give all the topics with replies the ID their last reply.
1148      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
1149              ( SELECT `topic`.`ID`, '_bbp_topic_id', `topic`.`ID`
1150              FROM `$bbp_db->posts`
1151                  AS `topic`
1152              WHERE `topic`.`post_type` = '{$tpt}'
1153              GROUP BY `topic`.`ID` )" ) ) ) {
1154          return array( 3, sprintf( $statement, $result ) );
1155      }
1156  
1157      // Next, give all the topics with replies the ID their last reply.
1158      if ( is_wp_error( $bbp_db->query( "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`)
1159              ( SELECT `reply`.`ID`, '_bbp_topic_id', `topic`.`ID`
1160              FROM `$bbp_db->posts`
1161                  AS `reply`
1162              INNER JOIN `$bbp_db->posts`
1163                  AS `topic`
1164                  ON `reply`.`post_parent` = `topic`.`ID`
1165              WHERE `topic`.`post_type` = '{$tpt}'
1166                  AND `reply`.`post_type` = '{$rpt}'
1167              GROUP BY `reply`.`ID` )" ) ) ) {
1168          return array( 4, sprintf( $statement, $result ) );
1169      }
1170  
1171      // Complete results
1172      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
1173  }
1174  
1175  /**
1176   * Recalculate reply menu order
1177   *
1178   * @since 2.5.4 bbPress (r5367)
1179   *
1180   * @return array An array of the status code and the message
1181   */
1182  function bbp_admin_repair_reply_menu_order() {
1183  
1184      // Define variables
1185      $bbp_db    = bbp_db();
1186      $statement = esc_html__( 'Recalculating reply menu order&hellip; %s', 'bbpress' );
1187      $result    = esc_html__( 'No reply positions to recalculate.',         'bbpress' );
1188  
1189      // Delete cases where `_bbp_reply_to` was accidentally set to itself
1190      if ( is_wp_error( $bbp_db->query( "DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` = '_bbp_reply_to' AND `post_id` = `meta_value`" ) ) ) {
1191          return array( 1, sprintf( $statement, $result ) );
1192      }
1193  
1194      // Post type
1195      $rpt = bbp_get_reply_post_type();
1196  
1197      // Get an array of reply id's to update the menu oder for each reply
1198      $replies = $bbp_db->get_results( "SELECT `a`.`ID` FROM `{$bbp_db->posts}` AS `a`
1199                                          INNER JOIN (
1200                                              SELECT `menu_order`, `post_parent`
1201                                              FROM `{$bbp_db->posts}`
1202                                              GROUP BY `menu_order`, `post_parent`
1203                                              HAVING COUNT( * ) >1
1204                                          )`b`
1205                                          ON `a`.`menu_order` = `b`.`menu_order`
1206                                          AND `a`.`post_parent` = `b`.`post_parent`
1207                                          WHERE `post_type` = '{$rpt}'", OBJECT_K );
1208  
1209      // Bail if no replies returned
1210      if ( empty( $replies ) ) {
1211          return array( 1, sprintf( $statement, $result ) );
1212      }
1213  
1214      // Recalculate the menu order position for each reply
1215      foreach ( $replies as $reply ) {
1216          bbp_update_reply_position( $reply->ID );
1217      }
1218  
1219      // Cleanup
1220      unset( $replies, $reply );
1221  
1222      // Complete results
1223      return array( 0, sprintf( $statement, esc_html__( 'Complete!', 'bbpress' ) ) );
1224  }


Generated: Sat Sep 21 01:01:35 2019 Cross-referenced by PHPXref 0.7.1