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


Generated: Sat Dec 7 01:00:51 2024 Cross-referenced by PHPXref 0.7.1