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

937 lines 36.3 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-forum-topics', __( 'Count topics in each forum', 'bbpress' ), 'bbp_admin_repair_forum_topic_count' ),
163 15 => array( 'bbp-forum-replies', __( 'Count replies in each forum', 'bbpress' ), 'bbp_admin_repair_forum_reply_count' ),
164 20 => array( 'bbp-topic-replies', __( 'Count replies in each topic', 'bbpress' ), 'bbp_admin_repair_topic_reply_count' ),
165 25 => array( 'bbp-topic-voices', __( 'Count voices in each topic', 'bbpress' ), 'bbp_admin_repair_topic_voice_count' ),
166 30 => array( 'bbp-topic-hidden-replies', __( 'Count spammed & trashed replies in each topic', 'bbpress' ), 'bbp_admin_repair_topic_hidden_reply_count' ),
167 35 => array( 'bbp-user-replies', __( 'Count topics for each user', 'bbpress' ), 'bbp_admin_repair_user_topic_count' ),
168 35 => array( 'bbp-user-topics', __( 'Count replies for each user', 'bbpress' ), 'bbp_admin_repair_user_reply_count' ),
169 40 => array( 'bbp-user-favorites', __( 'Remove trashed topics from user favorites', 'bbpress' ), 'bbp_admin_repair_user_favorites' ),
170 45 => array( 'bbp-user-subscriptions', __( 'Remove trashed topics from user subscriptions', 'bbpress' ), 'bbp_admin_repair_user_subscriptions' ),
171 50 => array( 'bbp-sync-all-topics-forums', __( 'Recalculate last activity in each topic and forum', 'bbpress' ), 'bbp_admin_repair_freshness' )
172 );
173 ksort( $repair_list );
174
175 // DO NOT USE: Legacy filter
176 $repair_list = apply_filters( 'bbp_recount_list', $repair_list );
177
178 return (array) apply_filters( 'bbp_repair_list', $repair_list );
179 }
180
181 /**
182 * Recount topic replies
183 *
184 * @since bbPress (r2613)
185 *
186 * @uses bbp_get_reply_post_type() To get the reply post type
187 * @uses wpdb::query() To run our recount sql queries
188 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
189 * @return array An array of the status code and the message
190 */
191 function bbp_admin_repair_topic_reply_count() {
192 global $wpdb;
193
194 $statement = __( 'Counting the number of replies in each topic&hellip; %s', 'bbpress' );
195 $result = __( 'Failed!', 'bbpress' );
196
197 $sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `meta_key` = '_bbp_reply_count';";
198 if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
199 return array( 1, sprintf( $statement, $result ) );
200
201 // Post types and status
202 $tpt = bbp_get_topic_post_type();
203 $rpt = bbp_get_reply_post_type();
204 $pps = bbp_get_public_status_id();
205 $cps = bbp_get_closed_status_id();
206
207 $sql = "INSERT INTO `{$wpdb->postmeta}` (`post_id`, `meta_key`, `meta_value`) (
208 SELECT `topics`.`ID` AS `post_id`, '_bbp_reply_count' AS `meta_key`, COUNT(`replies`.`ID`) As `meta_value`
209 FROM `{$wpdb->posts}` AS `topics`
210 LEFT JOIN `{$wpdb->posts}` as `replies`
211 ON `replies`.`post_parent` = `topics`.`ID`
212 AND `replies`.`post_status` = '{$pps}'
213 AND `replies`.`post_type` = '{$rpt}'
214 WHERE `topics`.`post_type` = '{$tpt}'
215 AND `topics`.`post_status` IN ( '{$pps}', '{$cps}' )
216 GROUP BY `topics`.`ID`);";
217
218 if ( is_wp_error( $wpdb->query( $sql ) ) )
219 return array( 2, sprintf( $statement, $result ) );
220
221 $result = __( 'Complete!', 'bbpress' );
222 return array( 0, sprintf( $statement, $result ) );
223 }
224
225 /**
226 * Recount topic voices
227 *
228 * @since bbPress (r2613)
229 *
230 * @uses bbp_get_reply_post_type() To get the reply post type
231 * @uses wpdb::query() To run our recount sql queries
232 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
233 * @return array An array of the status code and the message
234 */
235 function bbp_admin_repair_topic_voice_count() {
236 global $wpdb;
237
238 $statement = __( 'Counting the number of voices in each topic&hellip; %s', 'bbpress' );
239 $result = __( 'Failed!', 'bbpress' );
240
241 $sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `meta_key` = '_bbp_voice_count';";
242 if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
243 return array( 1, sprintf( $statement, $result ) );
244
245 // Post types and status
246 $tpt = bbp_get_topic_post_type();
247 $rpt = bbp_get_reply_post_type();
248 $pps = bbp_get_public_status_id();
249 $cps = bbp_get_closed_status_id();
250
251 $sql = "INSERT INTO `{$wpdb->postmeta}` (`post_id`, `meta_key`, `meta_value`) (
252 SELECT `postmeta`.`meta_value`, '_bbp_voice_count', COUNT(DISTINCT `post_author`) as `meta_value`
253 FROM `{$wpdb->posts}` AS `posts`
254 LEFT JOIN `{$wpdb->postmeta}` AS `postmeta`
255 ON `posts`.`ID` = `postmeta`.`post_id`
256 AND `postmeta`.`meta_key` = '_bbp_topic_id'
257 WHERE `posts`.`post_type` IN ( '{$tpt}', '{$rpt}' )
258 AND `posts`.`post_status` IN ( '{$pps}', '{$cps}' )
259 AND `posts`.`post_author` != '0'
260 GROUP BY `postmeta`.`meta_value`);";
261
262 if ( is_wp_error( $wpdb->query( $sql ) ) )
263 return array( 2, sprintf( $statement, $result ) );
264
265 $result = __( 'Complete!', 'bbpress' );
266 return array( 0, sprintf( $statement, $result ) );
267 }
268
269 /**
270 * Recount topic hidden replies (spammed/trashed)
271 *
272 * @since bbPress (r2747)
273 *
274 * @uses wpdb::query() To run our recount sql queries
275 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
276 * @return array An array of the status code and the message
277 */
278 function bbp_admin_repair_topic_hidden_reply_count() {
279 global $wpdb;
280
281 $statement = __( 'Counting the number of spammed and trashed replies in each topic&hellip; %s', 'bbpress' );
282 $result = __( 'Failed!', 'bbpress' );
283
284 $sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `meta_key` = '_bbp_reply_count_hidden';";
285 if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
286 return array( 1, sprintf( $statement, $result ) );
287
288 $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`);";
289 if ( is_wp_error( $wpdb->query( $sql ) ) )
290 return array( 2, sprintf( $statement, $result ) );
291
292 $result = __( 'Complete!', 'bbpress' );
293 return array( 0, sprintf( $statement, $result ) );
294 }
295
296 /**
297 * Recount forum topics
298 *
299 * @since bbPress (r2613)
300 *
301 * @uses wpdb::query() To run our recount sql queries
302 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
303 * @uses bbp_get_forum_post_type() To get the forum post type
304 * @uses get_posts() To get the forums
305 * @uses bbp_update_forum_topic_count() To update the forum topic count
306 * @return array An array of the status code and the message
307 */
308 function bbp_admin_repair_forum_topic_count() {
309 global $wpdb;
310
311 $statement = __( 'Counting the number of topics in each forum&hellip; %s', 'bbpress' );
312 $result = __( 'Failed!', 'bbpress' );
313
314 $sql_delete = "DELETE FROM {$wpdb->postmeta} WHERE meta_key IN ( '_bbp_topic_count', '_bbp_total_topic_count' );";
315 if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
316 return array( 1, sprintf( $statement, $result ) );
317
318 $forums = get_posts( array( 'post_type' => bbp_get_forum_post_type(), 'numberposts' => -1 ) );
319 if ( !empty( $forums ) ) {
320 foreach( $forums as $forum ) {
321 bbp_update_forum_topic_count( $forum->ID );
322 }
323 } else {
324 return array( 2, sprintf( $statement, $result ) );
325 }
326
327 $result = __( 'Complete!', 'bbpress' );
328 return array( 0, sprintf( $statement, $result ) );
329 }
330
331 /**
332 * Recount forum replies
333 *
334 * @since bbPress (r2613)
335 *
336 * @uses wpdb::query() To run our recount sql queries
337 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
338 * @uses bbp_get_forum_post_type() To get the forum post type
339 * @uses get_posts() To get the forums
340 * @uses bbp_update_forum_reply_count() To update the forum reply count
341 * @return array An array of the status code and the message
342 */
343 function bbp_admin_repair_forum_reply_count() {
344 global $wpdb;
345
346 $statement = __( 'Counting the number of replies in each forum&hellip; %s', 'bbpress' );
347 $result = __( 'Failed!', 'bbpress' );
348
349 $sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `meta_key` IN ( '_bbp_reply_count', '_bbp_total_reply_count' );";
350 if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
351 return array( 1, sprintf( $statement, $result ) );
352
353 $forums = get_posts( array( 'post_type' => bbp_get_forum_post_type(), 'numberposts' => -1 ) );
354 if ( !empty( $forums ) ) {
355 foreach( $forums as $forum ) {
356 bbp_update_forum_reply_count( $forum->ID );
357 }
358 } else {
359 return array( 2, sprintf( $statement, $result ) );
360 }
361
362 $result = __( 'Complete!', 'bbpress' );
363 return array( 0, sprintf( $statement, $result ) );
364 }
365
366 /**
367 * Recount topics by the users
368 *
369 * @since bbPress (r3889)
370 *
371 * @uses bbp_get_reply_post_type() To get the reply post type
372 * @uses wpdb::query() To run our recount sql queries
373 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
374 * @return array An array of the status code and the message
375 */
376 function bbp_admin_repair_user_topic_count() {
377 global $wpdb;
378
379 $statement = __( 'Counting the number of topics each user has created&hellip; %s', 'bbpress' );
380 $result = __( 'Failed!', 'bbpress' );
381 $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`;";
382 $insert_rows = $wpdb->get_results( $sql_select );
383
384 if ( is_wp_error( $insert_rows ) )
385 return array( 1, sprintf( $statement, $result ) );
386
387 $key = $wpdb->prefix . '_bbp_topic_count';
388 $insert_values = array();
389 foreach ( $insert_rows as $insert_row )
390 $insert_values[] = "('{$insert_row->post_author}', '{$key}', '{$insert_row->_count}')";
391
392 if ( !count( $insert_values ) )
393 return array( 2, sprintf( $statement, $result ) );
394
395 $sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';";
396 if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
397 return array( 3, sprintf( $statement, $result ) );
398
399 $insert_values = array_chunk( $insert_values, 10000 );
400 foreach ( $insert_values as $chunk ) {
401 $chunk = "\n" . join( ",\n", $chunk );
402 $sql_insert = "INSERT INTO `{$wpdb->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES $chunk;";
403
404 if ( is_wp_error( $wpdb->query( $sql_insert ) ) ) {
405 return array( 4, sprintf( $statement, $result ) );
406 }
407 }
408
409 $result = __( 'Complete!', 'bbpress' );
410 return array( 0, sprintf( $statement, $result ) );
411 }
412
413 /**
414 * Recount topic replied by the users
415 *
416 * @since bbPress (r2613)
417 *
418 * @uses bbp_get_reply_post_type() To get the reply post type
419 * @uses wpdb::query() To run our recount sql queries
420 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
421 * @return array An array of the status code and the message
422 */
423 function bbp_admin_repair_user_reply_count() {
424 global $wpdb;
425
426 $statement = __( 'Counting the number of topics to which each user has replied&hellip; %s', 'bbpress' );
427 $result = __( 'Failed!', 'bbpress' );
428 $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`;";
429 $insert_rows = $wpdb->get_results( $sql_select );
430
431 if ( is_wp_error( $insert_rows ) )
432 return array( 1, sprintf( $statement, $result ) );
433
434 $key = $wpdb->prefix . '_bbp_reply_count';
435 $insert_values = array();
436 foreach ( $insert_rows as $insert_row )
437 $insert_values[] = "('{$insert_row->post_author}', '{$key}', '{$insert_row->_count}')";
438
439 if ( !count( $insert_values ) )
440 return array( 2, sprintf( $statement, $result ) );
441
442 $sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';";
443 if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
444 return array( 3, sprintf( $statement, $result ) );
445
446 $insert_values = array_chunk( $insert_values, 10000 );
447 foreach ( $insert_values as $chunk ) {
448 $chunk = "\n" . join( ",\n", $chunk );
449 $sql_insert = "INSERT INTO `{$wpdb->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES $chunk;";
450
451 if ( is_wp_error( $wpdb->query( $sql_insert ) ) ) {
452 return array( 4, sprintf( $statement, $result ) );
453 }
454 }
455
456 $result = __( 'Complete!', 'bbpress' );
457 return array( 0, sprintf( $statement, $result ) );
458 }
459
460 /**
461 * Clean the users' favorites
462 *
463 * @since bbPress (r2613)
464 *
465 * @uses bbp_get_topic_post_type() To get the topic post type
466 * @uses wpdb::query() To run our recount sql queries
467 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
468 * @return array An array of the status code and the message
469 */
470 function bbp_admin_repair_user_favorites() {
471 global $wpdb;
472
473 $statement = __( 'Removing trashed topics from user favorites&hellip; %s', 'bbpress' );
474 $result = __( 'Failed!', 'bbpress' );
475 $key = $wpdb->prefix . '_bbp_favorites';
476 $users = $wpdb->get_results( "SELECT `user_id`, `meta_value` AS `favorites` FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';" );
477
478 if ( is_wp_error( $users ) )
479 return array( 1, sprintf( $statement, $result ) );
480
481 $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() . "';" );
482
483 if ( is_wp_error( $topics ) )
484 return array( 2, sprintf( $statement, $result ) );
485
486 $values = array();
487 foreach ( $users as $user ) {
488 if ( empty( $user->favorites ) || !is_string( $user->favorites ) )
489 continue;
490
491 $favorites = array_intersect( $topics, (array) explode( ',', $user->favorites ) );
492 if ( empty( $favorites ) || !is_array( $favorites ) )
493 continue;
494
495 $favorites = join( ',', $favorites );
496 $values[] = "('{$user->user_id}', '{$key}, '{$favorites}')";
497 }
498
499 if ( !count( $values ) ) {
500 $result = __( 'Nothing to remove!', 'bbpress' );
501 return array( 0, sprintf( $statement, $result ) );
502 }
503
504 $sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';";
505 if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
506 return array( 4, sprintf( $statement, $result ) );
507
508 $values = array_chunk( $values, 10000 );
509 foreach ( $values as $chunk ) {
510 $chunk = "\n" . join( ",\n", $chunk );
511 $sql_insert = "INSERT INTO `$wpdb->usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES $chunk;";
512 if ( is_wp_error( $wpdb->query( $sql_insert ) ) )
513 return array( 5, sprintf( $statement, $result ) );
514 }
515
516 $result = __( 'Complete!', 'bbpress' );
517 return array( 0, sprintf( $statement, $result ) );
518 }
519
520 /**
521 * Clean the users' subscriptions
522 *
523 * @since bbPress (r2668)
524 *
525 * @uses bbp_get_topic_post_type() To get the topic post type
526 * @uses wpdb::query() To run our recount sql queries
527 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
528 * @return array An array of the status code and the message
529 */
530 function bbp_admin_repair_user_subscriptions() {
531 global $wpdb;
532
533 $statement = __( 'Removing trashed topics from user subscriptions&hellip; %s', 'bbpress' );
534 $result = __( 'Failed!', 'bbpress' );
535 $key = $wpdb->prefix . '_bbp_subscriptions';
536 $users = $wpdb->get_results( "SELECT `user_id`, `meta_value` AS `subscriptions` FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';" );
537
538 if ( is_wp_error( $users ) )
539 return array( 1, sprintf( $statement, $result ) );
540
541 $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() . "';" );
542 if ( is_wp_error( $topics ) )
543 return array( 2, sprintf( $statement, $result ) );
544
545 $values = array();
546 foreach ( $users as $user ) {
547 if ( empty( $user->subscriptions ) || !is_string( $user->subscriptions ) )
548 continue;
549
550 $subscriptions = array_intersect( $topics, (array) explode( ',', $user->subscriptions ) );
551 if ( empty( $subscriptions ) || !is_array( $subscriptions ) )
552 continue;
553
554 $subscriptions = join( ',', $subscriptions );
555 $values[] = "('{$user->user_id}', '{$key}', '{$subscriptions}')";
556 }
557
558 if ( !count( $values ) ) {
559 $result = __( 'Nothing to remove!', 'bbpress' );
560 return array( 0, sprintf( $statement, $result ) );
561 }
562
563 $sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` = '{$key}';";
564 if ( is_wp_error( $wpdb->query( $sql_delete ) ) )
565 return array( 4, sprintf( $statement, $result ) );
566
567 $values = array_chunk( $values, 10000 );
568 foreach ( $values as $chunk ) {
569 $chunk = "\n" . join( ",\n", $chunk );
570 $sql_insert = "INSERT INTO `{$wpdb->usermeta}` (`user_id`, `meta_key`, `meta_value`) VALUES $chunk;";
571 if ( is_wp_error( $wpdb->query( $sql_insert ) ) )
572 return array( 5, sprintf( $statement, $result ) );
573 }
574
575 $result = __( 'Complete!', 'bbpress' );
576 return array( 0, sprintf( $statement, $result ) );
577 }
578
579 /**
580 * Recaches the last post in every topic and forum
581 *
582 * @since bbPress (r3040)
583 *
584 * @uses wpdb::query() To run our recount sql queries
585 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
586 * @return array An array of the status code and the message
587 */
588 function bbp_admin_repair_freshness() {
589 global $wpdb;
590
591 $statement = __( 'Recomputing latest post in every topic and forum&hellip; %s', 'bbpress' );
592 $result = __( 'Failed!', 'bbpress' );
593
594 // First, delete everything.
595 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' );" ) ) )
596 return array( 1, sprintf( $statement, $result ) );
597
598 // Next, give all the topics with replies the ID their last reply.
599 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
600 ( SELECT `topic`.`ID`, '_bbp_last_reply_id', MAX( `reply`.`ID` )
601 FROM `$wpdb->posts` AS `topic` INNER JOIN `$wpdb->posts` AS `reply` ON `topic`.`ID` = `reply`.`post_parent`
602 WHERE `reply`.`post_status` IN ( '" . bbp_get_public_status_id() . "' ) AND `topic`.`post_type` = 'topic' AND `reply`.`post_type` = 'reply'
603 GROUP BY `topic`.`ID` );" ) ) )
604 return array( 2, sprintf( $statement, $result ) );
605
606 // For any remaining topics, give a reply ID of 0.
607 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
608 ( SELECT `ID`, '_bbp_last_reply_id', 0
609 FROM `$wpdb->posts` AS `topic` LEFT JOIN `$wpdb->postmeta` AS `reply`
610 ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_reply_id'
611 WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = 'topic' );" ) ) )
612 return array( 3, sprintf( $statement, $result ) );
613
614 // Now we give all the forums with topics the ID their last topic.
615 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
616 ( SELECT `forum`.`ID`, '_bbp_last_topic_id', `topic`.`ID`
617 FROM `$wpdb->posts` AS `forum` INNER JOIN `$wpdb->posts` AS `topic` ON `forum`.`ID` = `topic`.`post_parent`
618 WHERE `topic`.`post_status` IN ( '" . bbp_get_public_status_id() . "' ) AND `forum`.`post_type` = 'forum' AND `topic`.`post_type` = 'topic'
619 GROUP BY `forum`.`ID` );" ) ) )
620 return array( 4, sprintf( $statement, $result ) );
621
622 // For any remaining forums, give a topic ID of 0.
623 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
624 ( SELECT `ID`, '_bbp_last_topic_id', 0
625 FROM `$wpdb->posts` AS `forum` LEFT JOIN `$wpdb->postmeta` AS `topic`
626 ON `forum`.`ID` = `topic`.`post_id` AND `topic`.`meta_key` = '_bbp_last_topic_id'
627 WHERE `topic`.`meta_id` IS NULL AND `forum`.`post_type` = 'forum' );" ) ) )
628 return array( 5, sprintf( $statement, $result ) );
629
630 // After that, we give all the topics with replies the ID their last reply (again, this time for a different reason).
631 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
632 ( SELECT `topic`.`ID`, '_bbp_last_active_id', MAX( `reply`.`ID` )
633 FROM `$wpdb->posts` AS `topic` INNER JOIN `$wpdb->posts` AS `reply` ON `topic`.`ID` = `reply`.`post_parent`
634 WHERE `reply`.`post_status` IN ( '" . bbp_get_public_status_id() . "' ) AND `topic`.`post_type` = 'topic' AND `reply`.`post_type` = 'reply'
635 GROUP BY `topic`.`ID` );" ) ) )
636 return array( 6, sprintf( $statement, $result ) );
637
638 // For any remaining topics, give a reply ID of themself.
639 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
640 ( SELECT `ID`, '_bbp_last_active_id', `ID`
641 FROM `$wpdb->posts` AS `topic` LEFT JOIN `$wpdb->postmeta` AS `reply`
642 ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_active_id'
643 WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = 'topic' );" ) ) )
644 return array( 7, sprintf( $statement, $result ) );
645
646 // Give topics with replies their last update time.
647 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
648 ( SELECT `topic`.`ID`, '_bbp_last_active_time', MAX( `reply`.`post_date` )
649 FROM `$wpdb->posts` AS `topic` INNER JOIN `$wpdb->posts` AS `reply` ON `topic`.`ID` = `reply`.`post_parent`
650 WHERE `reply`.`post_status` IN ( '" . bbp_get_public_status_id() . "' ) AND `topic`.`post_type` = 'topic' AND `reply`.`post_type` = 'reply'
651 GROUP BY `topic`.`ID` );" ) ) )
652 return array( 8, sprintf( $statement, $result ) );
653
654 // Give topics without replies their last update time.
655 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
656 ( SELECT `ID`, '_bbp_last_active_time', `post_date`
657 FROM `$wpdb->posts` AS `topic` LEFT JOIN `$wpdb->postmeta` AS `reply`
658 ON `topic`.`ID` = `reply`.`post_id` AND `reply`.`meta_key` = '_bbp_last_active_time'
659 WHERE `reply`.`meta_id` IS NULL AND `topic`.`post_type` = 'topic' );" ) ) )
660 return array( 9, sprintf( $statement, $result ) );
661
662 // Forums need to know what their last active item is as well. Now it gets a bit more complex to do in the database.
663 $forums = $wpdb->get_col( "SELECT `ID` FROM `$wpdb->posts` WHERE `post_type` = 'forum' and `post_status` != 'auto-draft';" );
664 if ( is_wp_error( $forums ) )
665 return array( 10, sprintf( $statement, $result ) );
666
667 // Loop through forums
668 foreach ( $forums as $forum_id ) {
669 if ( !bbp_is_forum_category( $forum_id ) ) {
670 bbp_update_forum( array( 'forum_id' => $forum_id ) );
671 }
672 }
673
674 // Loop through categories when forums are done
675 foreach ( $forums as $forum_id ) {
676 if ( bbp_is_forum_category( $forum_id ) ) {
677 bbp_update_forum( array( 'forum_id' => $forum_id ) );
678 }
679 }
680
681 // Complete results
682 $result = __( 'Complete!', 'bbpress' );
683 return array( 0, sprintf( $statement, $result ) );
684 }
685
686 /**
687 * Recaches the forum for each post
688 *
689 * @since bbPress (r3876)
690 *
691 * @uses wpdb::query() To run our recount sql queries
692 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
693 * @return array An array of the status code and the message
694 */
695 function bbp_admin_repair_forum_meta() {
696 global $wpdb;
697
698 $statement = __( 'Recalculating the forum for each post &hellip; %s', 'bbpress' );
699 $result = __( 'Failed!', 'bbpress' );
700
701 // First, delete everything.
702 if ( is_wp_error( $wpdb->query( "DELETE FROM `$wpdb->postmeta` WHERE `meta_key` = '_bbp_forum_id';" ) ) )
703 return array( 1, sprintf( $statement, $result ) );
704
705 // Next, give all the topics with replies the ID their last reply.
706 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
707 ( SELECT `forum`.`ID`, '_bbp_forum_id', `forum`.`post_parent`
708 FROM `$wpdb->posts`
709 AS `forum`
710 WHERE `forum`.`post_type` = 'forum'
711 GROUP BY `forum`.`ID` );" ) ) )
712 return array( 2, sprintf( $statement, $result ) );
713
714 // Next, give all the topics with replies the ID their last reply.
715 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
716 ( SELECT `topic`.`ID`, '_bbp_forum_id', `topic`.`post_parent`
717 FROM `$wpdb->posts`
718 AS `topic`
719 WHERE `topic`.`post_type` = 'topic'
720 GROUP BY `topic`.`ID` );" ) ) )
721 return array( 3, sprintf( $statement, $result ) );
722
723 // Next, give all the topics with replies the ID their last reply.
724 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
725 ( SELECT `reply`.`ID`, '_bbp_forum_id', `topic`.`post_parent`
726 FROM `$wpdb->posts`
727 AS `reply`
728 INNER JOIN `$wpdb->posts`
729 AS `topic`
730 ON `reply`.`post_parent` = `topic`.`ID`
731 WHERE `topic`.`post_type` = 'topic'
732 AND `reply`.`post_type` = 'reply'
733 GROUP BY `reply`.`ID` );" ) ) )
734 return array( 4, sprintf( $statement, $result ) );
735
736 // Complete results
737 $result = __( 'Complete!', 'bbpress' );
738 return array( 0, sprintf( $statement, $result ) );
739 }
740
741 /**
742 * Recaches the topic for each post
743 *
744 * @since bbPress (r3876)
745 *
746 * @uses wpdb::query() To run our recount sql queries
747 * @uses is_wp_error() To check if the executed query returned {@link WP_Error}
748 * @return array An array of the status code and the message
749 */
750 function bbp_admin_repair_topic_meta() {
751 global $wpdb;
752
753 $statement = __( 'Recalculating the topic for each post &hellip; %s', 'bbpress' );
754 $result = __( 'Failed!', 'bbpress' );
755
756 // First, delete everything.
757 if ( is_wp_error( $wpdb->query( "DELETE FROM `$wpdb->postmeta` WHERE `meta_key` = '_bbp_topic_id';" ) ) )
758 return array( 1, sprintf( $statement, $result ) );
759
760 // Next, give all the topics with replies the ID their last reply.
761 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
762 ( SELECT `topic`.`ID`, '_bbp_topic_id', `topic`.`ID`
763 FROM `$wpdb->posts`
764 AS `topic`
765 WHERE `topic`.`post_type` = 'topic'
766 GROUP BY `topic`.`ID` );" ) ) )
767 return array( 3, sprintf( $statement, $result ) );
768
769 // Next, give all the topics with replies the ID their last reply.
770 if ( is_wp_error( $wpdb->query( "INSERT INTO `$wpdb->postmeta` (`post_id`, `meta_key`, `meta_value`)
771 ( SELECT `reply`.`ID`, '_bbp_topic_id', `topic`.`ID`
772 FROM `$wpdb->posts`
773 AS `reply`
774 INNER JOIN `$wpdb->posts`
775 AS `topic`
776 ON `reply`.`post_parent` = `topic`.`ID`
777 WHERE `topic`.`post_type` = 'topic'
778 AND `reply`.`post_type` = 'reply'
779 GROUP BY `reply`.`ID` );" ) ) )
780 return array( 4, sprintf( $statement, $result ) );
781
782 // Complete results
783 $result = __( 'Complete!', 'bbpress' );
784 return array( 0, sprintf( $statement, $result ) );
785 }
786
787 /** Reset ********************************************************************/
788
789 /**
790 * Admin reset page
791 *
792 * @since bbPress (r2613)
793 *
794 * @uses check_admin_referer() To verify the nonce and the referer
795 * @uses do_action() Calls 'admin_notices' to display the notices
796 * @uses screen_icon() To display the screen icon
797 * @uses wp_nonce_field() To add a hidden nonce field
798 */
799 function bbp_admin_reset() {
800 ?>
801
802 <div class="wrap">
803
804 <?php screen_icon( 'tools' ); ?>
805
806 <h2 class="nav-tab-wrapper"><?php bbp_tools_admin_tabs( __( 'Reset Forums', 'bbpress' ) ); ?></h2>
807 <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>
808
809 <form class="settings" method="post" action="">
810 <table class="form-table">
811 <tbody>
812 <tr valign="top">
813 <th scope="row"><?php _e( 'The following data will be removed:', 'bbpress' ) ?></th>
814 <td>
815 <?php _e( 'All Forums', 'bbpress' ); ?><br />
816 <?php _e( 'All Topics', 'bbpress' ); ?><br />
817 <?php _e( 'All Replies', 'bbpress' ); ?><br />
818 <?php _e( 'All Topic Tags', 'bbpress' ); ?><br />
819 <?php _e( 'Related Meta Data', 'bbpress' ); ?><br />
820 <?php _e( 'Forum Settings', 'bbpress' ); ?><br />
821 <?php _e( 'Forum Activity', 'bbpress' ); ?><br />
822 <?php _e( 'Forum User Roles', 'bbpress' ); ?><br />
823 <?php _e( 'Importer Helper Data', 'bbpress' ); ?><br />
824 </td>
825 </tr>
826 <tr valign="top">
827 <th scope="row"><?php _e( 'Are you sure you want to do this?', 'bbpress' ) ?></th>
828 <td>
829 <fieldset>
830 <legend class="screen-reader-text"><span><?php _e( "Say it ain't so!", 'bbpress' ) ?></span></legend>
831 <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>
832 </fieldset>
833 </td>
834 </tr>
835 </tbody>
836 </table>
837
838 <fieldset class="submit">
839 <input class="button-primary" type="submit" name="submit" value="<?php _e( 'Reset bbPress', 'bbpress' ); ?>" />
840 <?php wp_nonce_field( 'bbpress-reset' ); ?>
841 </fieldset>
842 </form>
843 </div>
844
845 <?php
846 }
847
848 /**
849 * Handle the processing and feedback of the admin tools page
850 *
851 * @since bbPress (r2613)
852 *
853 * @uses check_admin_referer() To verify the nonce and the referer
854 * @uses wp_cache_flush() To flush the cache
855 */
856 function bbp_admin_reset_handler() {
857 if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) && !empty( $_POST['bbpress-are-you-sure'] ) ) {
858 check_admin_referer( 'bbpress-reset' );
859
860 global $wpdb;
861
862 // Stores messages
863 $messages = array();
864 $failed = __( 'Failed', 'bbpress' );
865 $success = __( 'Success!', 'bbpress' );
866
867 // Flush the cache; things are about to get ugly.
868 wp_cache_flush();
869
870 /** Posts *************************************************************/
871
872 $statement = __( 'Deleting Posts&hellip; %s', 'bbpress' );
873 $sql_posts = $wpdb->get_results( "SELECT `ID` FROM `{$wpdb->posts}` WHERE `post_type` IN ('forum', 'topic', 'reply')", OBJECT_K );
874 $sql_delete = "DELETE FROM `{$wpdb->posts}` WHERE `post_type` IN ('forum', 'topic', 'reply')";
875 $result = is_wp_error( $wpdb->query( $sql_delete ) ) ? $failed : $success;
876 $messages[] = sprintf( $statement, $result );
877
878
879 /** Post Meta *********************************************************/
880
881 if ( !empty( $sql_posts ) ) {
882 foreach( $sql_posts as $key => $value ) {
883 $sql_meta[] = $key;
884 }
885 $statement = __( 'Deleting Post Meta&hellip; %s', 'bbpress' );
886 $sql_meta = implode( "', '", $sql_meta );
887 $sql_delete = "DELETE FROM `{$wpdb->postmeta}` WHERE `post_id` IN ('{$sql_meta}');";
888 $result = is_wp_error( $wpdb->query( $sql_delete ) ) ? $failed : $success;
889 $messages[] = sprintf( $statement, $result );
890 }
891
892 /** Topic Tags ********************************************************/
893
894 // @todo
895
896 /** User Meta *********************************************************/
897
898 $statement = __( 'Deleting User Meta&hellip; %s', 'bbpress' );
899 $sql_delete = "DELETE FROM `{$wpdb->usermeta}` WHERE `meta_key` LIKE '%%_bbp_%%';";
900 $result = is_wp_error( $wpdb->query( $sql_delete ) ) ? $failed : $success;
901 $messages[] = sprintf( $statement, $result );
902
903 /** Converter *********************************************************/
904
905 $statement = __( 'Deleting Conversion Table&hellip; %s', 'bbpress' );
906 $table_name = $wpdb->prefix . 'bbp_converter_translator';
907 if ( $wpdb->get_var( "SHOW TABLES LIKE '{$table_name}'" ) == $table_name ) {
908 $wpdb->query( "DROP TABLE {$table_name}" );
909 $result = $success;
910 } else {
911 $result = $failed;
912 }
913 $messages[] = sprintf( $statement, $result );
914
915 /** Options ***********************************************************/
916
917 $statement = __( 'Deleting Settings&hellip; %s', 'bbpress' );
918 $sql_delete = bbp_delete_options();
919 $messages[] = sprintf( $statement, $success );
920
921 /** Roles *************************************************************/
922
923 $statement = __( 'Deleting Roles and Capabilities&hellip; %s', 'bbpress' );
924 $sql_delete = bbp_remove_roles();
925 $sql_delete = bbp_remove_caps();
926 $messages[] = sprintf( $statement, $success );
927
928 /** Output ************************************************************/
929
930 if ( count( $messages ) ) {
931 foreach ( $messages as $message ) {
932 bbp_admin_tools_feedback( $message );
933 }
934 }
935 }
936 }
937