PluginProbe
bbPress / 2.1.1
bbPress v2.1.1
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.1, at bbp-admin/bbp-tools.php

986 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 // Complete results
731 $result = __( 'Complete!', 'bbpress' );
732 return array( 0, sprintf( $statement, $result ) );
733 }
734
735 /**
736 * Recaches the forum for each post
737 *
738 * @since bbPress (r3876)
739 *
740 * @uses wpdb::query() To run our recount sql queries
741 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
742 * @return array An array of the status code and the message
743 */
744 function bbp_admin_repair_forum_meta() {
745 global $wpdb;
746
747 $statement = __( 'Recalculating the forum for each post &hellip; %s', 'bbpress' );
748 $result = __( 'Failed!', 'bbpress' );
749
750 // First, delete everything.
751 if ( is_wp_error( $wpdb->query( "DELETE FROM `$wpdb->postmeta` WHERE `meta_key` = '_bbp_forum_id';" ) ) )
752 return array( 1, sprintf( $statement, $result ) );
753
754 // Next, give all the topics with replies the ID their last reply.
755 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
756 ( SELECT `forum`.`ID`, '_bbp_forum_id', `forum`.`post_parent`
757 FROM `$wpdb->posts`
758 AS `forum`
759 WHERE `forum`.`post_type` = 'forum'
760 GROUP BY `forum`.`ID` );" ) ) )
761 return array( 2, sprintf( $statement, $result ) );
762
763 // Next, give all the topics with replies the ID their last reply.
764 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
765 ( SELECT `topic`.`ID`, '_bbp_forum_id', `topic`.`post_parent`
766 FROM `$wpdb->posts`
767 AS `topic`
768 WHERE `topic`.`post_type` = 'topic'
769 GROUP BY `topic`.`ID` );" ) ) )
770 return array( 3, sprintf( $statement, $result ) );
771
772 // Next, give all the topics with replies the ID their last reply.
773 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
774 ( SELECT `reply`.`ID`, '_bbp_forum_id', `topic`.`post_parent`
775 FROM `$wpdb->posts`
776 AS `reply`
777 INNER JOIN `$wpdb->posts`
778 AS `topic`
779 ON `reply`.`post_parent` = `topic`.`ID`
780 WHERE `topic`.`post_type` = 'topic'
781 AND `reply`.`post_type` = 'reply'
782 GROUP BY `reply`.`ID` );" ) ) )
783 return array( 4, sprintf( $statement, $result ) );
784
785 // Complete results
786 $result = __( 'Complete!', 'bbpress' );
787 return array( 0, sprintf( $statement, $result ) );
788 }
789
790 /**
791 * Recaches the topic for each post
792 *
793 * @since bbPress (r3876)
794 *
795 * @uses wpdb::query() To run our recount sql queries
796 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
797 * @return array An array of the status code and the message
798 */
799 function bbp_admin_repair_topic_meta() {
800 global $wpdb;
801
802 $statement = __( 'Recalculating the topic for each post &hellip; %s', 'bbpress' );
803 $result = __( 'Failed!', 'bbpress' );
804
805 // First, delete everything.
806 if ( is_wp_error( $wpdb->query( "DELETE FROM `$wpdb->postmeta` WHERE `meta_key` = '_bbp_topic_id';" ) ) )
807 return array( 1, sprintf( $statement, $result ) );
808
809 // Next, give all the topics with replies the ID their last reply.
810 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
811 ( SELECT `topic`.`ID`, '_bbp_topic_id', `topic`.`ID`
812 FROM `$wpdb->posts`
813 AS `topic`
814 WHERE `topic`.`post_type` = 'topic'
815 GROUP BY `topic`.`ID` );" ) ) )
816 return array( 3, sprintf( $statement, $result ) );
817
818 // Next, give all the topics with replies the ID their last reply.
819 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
820 ( SELECT `reply`.`ID`, '_bbp_topic_id', `topic`.`ID`
821 FROM `$wpdb->posts`
822 AS `reply`
823 INNER JOIN `$wpdb->posts`
824 AS `topic`
825 ON `reply`.`post_parent` = `topic`.`ID`
826 WHERE `topic`.`post_type` = 'topic'
827 AND `reply`.`post_type` = 'reply'
828 GROUP BY `reply`.`ID` );" ) ) )
829 return array( 4, sprintf( $statement, $result ) );
830
831 // Complete results
832 $result = __( 'Complete!', 'bbpress' );
833 return array( 0, sprintf( $statement, $result ) );
834 }
835
836 /** Reset ********************************************************************/
837
838 /**
839 * Admin reset page
840 *
841 * @since bbPress (r2613)
842 *
843 * @uses check_admin_referer() To verify the nonce and the referer
844 * @uses do_action() Calls 'admin_notices' to display the notices
845 * @uses screen_icon() To display the screen icon
846 * @uses wp_nonce_field() To add a hidden nonce field
847 */
848 function bbp_admin_reset() {
849 ?>
850
851 <div class="wrap">
852
853 <?php screen_icon( 'tools' ); ?>
854
855 <h2 class="nav-tab-wrapper"><?php bbp_tools_admin_tabs( __( 'Reset Forums', 'bbpress' ) ); ?></h2>
856 <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>
857
858 <form class="settings" method="post" action="">
859 <table class="form-table">
860 <tbody>
861 <tr valign="top">
862 <th scope="row"><?php _e( 'The following data will be removed:', 'bbpress' ) ?></th>
863 <td>
864 <?php _e( 'All Forums', 'bbpress' ); ?><br />
865 <?php _e( 'All Topics', 'bbpress' ); ?><br />
866 <?php _e( 'All Replies', 'bbpress' ); ?><br />
867 <?php _e( 'All Topic Tags', 'bbpress' ); ?><br />
868 <?php _e( 'Related Meta Data', 'bbpress' ); ?><br />
869 <?php _e( 'Forum Settings', 'bbpress' ); ?><br />
870 <?php _e( 'Forum Activity', 'bbpress' ); ?><br />
871 <?php _e( 'Forum User Roles', 'bbpress' ); ?><br />
872 <?php _e( 'Importer Helper Data', 'bbpress' ); ?><br />
873 </td>
874 </tr>
875 <tr valign="top">
876 <th scope="row"><?php _e( 'Are you sure you want to do this?', 'bbpress' ) ?></th>
877 <td>
878 <fieldset>
879 <legend class="screen-reader-text"><span><?php _e( "Say it ain't so!", 'bbpress' ) ?></span></legend>
880 <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>
881 </fieldset>
882 </td>
883 </tr>
884 </tbody>
885 </table>
886
887 <fieldset class="submit">
888 <input class="button-primary" type="submit" name="submit" value="<?php _e( 'Reset bbPress', 'bbpress' ); ?>" />
889 <?php wp_nonce_field( 'bbpress-reset' ); ?>
890 </fieldset>
891 </form>
892 </div>
893
894 <?php
895 }
896
897 /**
898 * Handle the processing and feedback of the admin tools page
899 *
900 * @since bbPress (r2613)
901 *
902 * @uses check_admin_referer() To verify the nonce and the referer
903 * @uses wp_cache_flush() To flush the cache
904 */
905 function bbp_admin_reset_handler() {
906 if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) && !empty( $_POST['bbpress-are-you-sure'] ) ) {
907 check_admin_referer( 'bbpress-reset' );
908
909 global $wpdb;
910
911 // Stores messages
912 $messages = array();
913 $failed = __( 'Failed', 'bbpress' );
914 $success = __( 'Success!', 'bbpress' );
915
916 // Flush the cache; things are about to get ugly.
917 wp_cache_flush();
918
919 /** Posts *************************************************************/
920
921 $statement = __( 'Deleting Posts&hellip; %s', 'bbpress' );
922 $sql_posts = $wpdb->get_results( "SELECT `ID` FROM `{$wpdb->posts}` WHERE `post_type` IN ('forum', 'topic', 'reply')", OBJECT_K );
923 $sql_delete = "DELETE FROM `{$wpdb->posts}` WHERE `post_type` IN ('forum', 'topic', 'reply')";
924 $result = is_wp_error( $wpdb->query( $sql_delete ) ) ? $failed : $success;
925 $messages[] = sprintf( $statement, $result );
926
927
928 /** Post Meta *********************************************************/
929
930 if ( !empty( $sql_posts ) ) {
931 foreach( $sql_posts as $key => $value ) {
932 $sql_meta[] = $key;
933 }
934 $statement = __( 'Deleting Post Meta&hellip; %s', 'bbpress' );
935 $sql_meta = implode( "', '", $sql_meta );
936 $sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `post_id` IN ('{$sql_meta}');";
937 $result = is_wp_error( $wpdb->query( $sql_delete ) ) ? $failed : $success;
938 $messages[] = sprintf( $statement, $result );
939 }
940
941 /** Topic Tags ********************************************************/
942
943 // @todo
944
945 /** User Meta *********************************************************/
946
947 $statement = __( 'Deleting User Meta&hellip; %s', 'bbpress' );
948 $sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` LIKE '%%_bbp_%%';";
949 $result = is_wp_error( $wpdb->query( $sql_delete ) ) ? $failed : $success;
950 $messages[] = sprintf( $statement, $result );
951
952 /** Converter *********************************************************/
953
954 $statement = __( 'Deleting Conversion Table&hellip; %s', 'bbpress' );
955 $table_name = $wpdb->prefix . 'bbp_converter_translator';
956 if ( $wpdb->get_var( "SHOW TABLES LIKE '{$table_name}'" ) == $table_name ) {
957 $wpdb->query( "DROP TABLE {$table_name}" );
958 $result = $success;
959 } else {
960 $result = $failed;
961 }
962 $messages[] = sprintf( $statement, $result );
963
964 /** Options ***********************************************************/
965
966 $statement = __( 'Deleting Settings&hellip; %s', 'bbpress' );
967 $sql_delete = bbp_delete_options();
968 $messages[] = sprintf( $statement, $success );
969
970 /** Roles *************************************************************/
971
972 $statement = __( 'Deleting Roles and Capabilities&hellip; %s', 'bbpress' );
973 $sql_delete = bbp_remove_roles();
974 $sql_delete = bbp_remove_caps();
975 $messages[] = sprintf( $statement, $success );
976
977 /** Output ************************************************************/
978
979 if ( count( $messages ) ) {
980 foreach ( $messages as $message ) {
981 bbp_admin_tools_feedback( $message );
982 }
983 }
984 }
985 }
986