PluginProbe
bbPress / 2.1.3
bbPress v2.1.3
trunk 2.0 2.0-beta-1 2.0-beta-2b 2.0-beta-3 2.0-beta-3b 2.0-rc-2 2.0-rc-3 2.0-rc-4 2.0-rc-5 2.0.1 2.0.2 2.0.3 2.1 2.1-beta-1 2.1-rc1 2.1-rc2 2.1-rc3 2.1-rc4 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.2.2 All 71 releases
bbpress / bbp-admin / bbp-tools.php

bbp-tools.php in bbPress 2.1.3, at bbp-admin/bbp-tools.php

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