/** * Return the numeric position of a reply within a topic * * @since bbPress (r2984) * * @param int $reply_id Optional. Reply id * @param int $topic_id Optional. Topic id * @uses bbp_get_reply_id() To get the reply id * @uses bbp_get_reply_topic_id() Get the topic id of the reply id * @uses bbp_get_topic_reply_count() To get the topic reply count * @uses bbp_get_reply_post_type() To get the reply post type * @uses bbp_get_reply_position_raw() To get calculate the reply position * @uses bbp_update_reply_position() To update the reply position * @uses bbp_show_lead_topic() Bump the count if lead topic is included * @uses apply_filters() Calls 'bbp_get_reply_position' with the reply * position, reply id and topic id * @return int Reply position */ function bbp_get_reply_position($reply_id = 0, $topic_id = 0) { // Get required data $reply_id = bbp_get_reply_id($reply_id); $reply_position = get_post_field('menu_order', $reply_id); // Reply doesn't have a position so get the raw value if (empty($reply_position)) { $topic_id = !empty($topic_id) ? bbp_get_topic_id($topic_id) : bbp_get_reply_topic_id($reply_id); // Post is not the topic if ($reply_id !== $topic_id) { $reply_position = bbp_get_reply_position_raw($reply_id, $topic_id); // Update the reply position in the posts table so we'll never have // to hit the DB again. if (!empty($reply_position)) { bbp_update_reply_position($reply_id, $reply_position); } // Topic's position is always 0 } else { $reply_position = 0; } } // Bump the position by one if the lead topic is in the replies loop if (!bbp_show_lead_topic()) { $reply_position++; } return (int) apply_filters('bbp_get_reply_position', $reply_position, $reply_id, $topic_id); }
/** * Recalculate reply menu order * * @since 2.5.4 bbPress (r5367) * * @uses wpdb::query() To run our recount sql queries * @uses is_wp_error() To check if the executed query returned {@link WP_Error} * @uses bbp_get_reply_post_type() To get the reply post type * @uses bbp_update_reply_position() To update the reply position * @return array An array of the status code and the message */ function bbp_admin_repair_reply_menu_order() { // Define variables $bbp_db = bbp_db(); $statement = __('Recalculating reply menu order … %s', 'bbpress'); $result = __('No reply positions to recalculate!', 'bbpress'); // Delete cases where `_bbp_reply_to` was accidentally set to itself if (is_wp_error($bbp_db->query("DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` = '_bbp_reply_to' AND `post_id` = `meta_value`;"))) { return array(1, sprintf($statement, $result)); } // Post type $rpt = bbp_get_reply_post_type(); // Get an array of reply id's to update the menu oder for each reply $replies = $bbp_db->get_results("SELECT `a`.`ID` FROM `{$bbp_db->posts}` AS `a`\n\t\t\t\t\t\t\t\t\t\tINNER JOIN (\n\t\t\t\t\t\t\t\t\t\t\tSELECT `menu_order`, `post_parent`\n\t\t\t\t\t\t\t\t\t\t\tFROM `{$bbp_db->posts}`\n\t\t\t\t\t\t\t\t\t\t\tGROUP BY `menu_order`, `post_parent`\n\t\t\t\t\t\t\t\t\t\t\tHAVING COUNT( * ) >1\n\t\t\t\t\t\t\t\t\t\t)`b`\n\t\t\t\t\t\t\t\t\t\tON `a`.`menu_order` = `b`.`menu_order`\n\t\t\t\t\t\t\t\t\t\tAND `a`.`post_parent` = `b`.`post_parent`\n\t\t\t\t\t\t\t\t\t\tWHERE `post_type` = '{$rpt}';", OBJECT_K); // Bail if no replies returned if (empty($replies)) { return array(1, sprintf($statement, $result)); } // Recalculate the menu order position for each reply foreach ($replies as $reply) { bbp_update_reply_position($reply->ID); } // Cleanup unset($replies, $reply); // Flush the cache; things are about to get ugly. wp_cache_flush(); return array(0, sprintf($statement, __('Complete!', 'bbpress'))); }
/** * Split topic handler * * Handles the front end split topic submission * * @since 2.0.0 bbPress (r2756) * * @param string $action The requested action to compare this function to * @uses bbp_add_error() To add an error message * @uses bbp_get_reply() To get the reply * @uses bbp_get_topic() To get the topics * @uses bbp_verify_nonce_request() To verify the nonce and check the request * @uses current_user_can() To check if the current user can edit the topics * @uses bbp_get_topic_post_type() To get the topic post type * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error} * @uses do_action() Calls 'bbp_pre_split_topic' with the from reply id, source * and destination topic ids * @uses bbp_get_topic_subscribers() To get the source topic subscribers * @uses bbp_add_user_subscription() To add the user subscription * @uses bbp_get_topic_favoriters() To get the source topic favoriters * @uses bbp_add_user_favorite() To add the user favorite * @uses wp_get_post_terms() To get the source topic tags * @uses wp_set_post_terms() To set the topic tags * @uses bbp_get_reply_post_type() To get the reply post type * @uses wpdb::prepare() To prepare our sql query * @uses wpdb::get_results() To execute the sql query and get results * @uses wp_update_post() To update the replies * @uses bbp_update_reply_topic_id() To update the reply topic id * @uses bbp_get_topic_forum_id() To get the topic forum id * @uses bbp_update_reply_forum_id() To update the reply forum id * @uses do_action() Calls 'bbp_split_topic_reply' with the reply id and * destination topic id * @uses bbp_update_topic_last_reply_id() To update the topic last reply id * @uses bbp_update_topic_last_active_time() To update the topic last active meta * @uses do_action() Calls 'bbp_post_split_topic' with the destination and * source topic ids and source topic's forum id * @uses bbp_get_topic_permalink() To get the topic permalink * @uses bbp_redirect() To redirect to the topic link */ function bbp_split_topic_handler($action = '') { // Bail if action is not 'bbp-split-topic' if ('bbp-split-topic' !== $action) { return; } // Prevent debug notices $from_reply_id = $destination_topic_id = 0; $destination_topic_title = ''; $destination_topic = $from_reply = $source_topic = ''; $split_option = false; /** Split Reply ***********************************************************/ if (empty($_POST['bbp_reply_id'])) { bbp_add_error('bbp_split_topic_reply_id', __('<strong>ERROR</strong>: A reply ID is required.', 'bbpress')); } else { $from_reply_id = (int) $_POST['bbp_reply_id']; } $from_reply = bbp_get_reply($from_reply_id); // Reply exists if (empty($from_reply)) { bbp_add_error('bbp_split_topic_r_not_found', __('<strong>ERROR</strong>: The reply you want to split from was not found.', 'bbpress')); } /** Topic to Split ********************************************************/ // Get the topic being split $source_topic = bbp_get_topic($from_reply->post_parent); // No topic if (empty($source_topic)) { bbp_add_error('bbp_split_topic_source_not_found', __('<strong>ERROR</strong>: The topic you want to split was not found.', 'bbpress')); } // Nonce check failed if (!bbp_verify_nonce_request('bbp-split-topic_' . $source_topic->ID)) { bbp_add_error('bbp_split_topic_nonce', __('<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress')); return; } // Use cannot edit topic if (!current_user_can('edit_topic', $source_topic->ID)) { bbp_add_error('bbp_split_topic_source_permission', __('<strong>ERROR</strong>: You do not have permission to edit the source topic.', 'bbpress')); } // How to Split if (!empty($_POST['bbp_topic_split_option'])) { $split_option = sanitize_key($_POST['bbp_topic_split_option']); } // Invalid split option if (empty($split_option) || !in_array($split_option, array('existing', 'reply'))) { bbp_add_error('bbp_split_topic_option', __('<strong>ERROR</strong>: You need to choose a valid split option.', 'bbpress')); // Valid Split Option } else { // What kind of split switch ($split_option) { // Into an existing topic case 'existing': // Get destination topic id if (empty($_POST['bbp_destination_topic'])) { bbp_add_error('bbp_split_topic_destination_id', __('<strong>ERROR</strong>: A topic ID is required.', 'bbpress')); } else { $destination_topic_id = (int) $_POST['bbp_destination_topic']; } // Get the destination topic $destination_topic = bbp_get_topic($destination_topic_id); // No destination topic if (empty($destination_topic)) { bbp_add_error('bbp_split_topic_destination_not_found', __('<strong>ERROR</strong>: The topic you want to split to was not found.', 'bbpress')); } // User cannot edit the destination topic if (!current_user_can('edit_topic', $destination_topic->ID)) { bbp_add_error('bbp_split_topic_destination_permission', __('<strong>ERROR</strong>: You do not have permission to edit the destination topic.', 'bbpress')); } break; // Split at reply into a new topic // Split at reply into a new topic case 'reply': default: // User needs to be able to publish topics if (current_user_can('publish_topics')) { // Use the new title that was passed if (!empty($_POST['bbp_topic_split_destination_title'])) { $destination_topic_title = sanitize_text_field($_POST['bbp_topic_split_destination_title']); // Use the source topic title } else { $destination_topic_title = $source_topic->post_title; } // Update the topic $destination_topic_id = wp_update_post(array('ID' => $from_reply->ID, 'post_title' => $destination_topic_title, 'post_name' => false, 'post_type' => bbp_get_topic_post_type(), 'post_parent' => $source_topic->post_parent, 'menu_order' => 0, 'guid' => '')); $destination_topic = bbp_get_topic($destination_topic_id); // Make sure the new topic knows its a topic bbp_update_topic_topic_id($from_reply->ID); // Shouldn't happen if (false === $destination_topic_id || is_wp_error($destination_topic_id) || empty($destination_topic)) { bbp_add_error('bbp_split_topic_destination_reply', __('<strong>ERROR</strong>: There was a problem converting the reply into the topic. Please try again.', 'bbpress')); } // User cannot publish posts } else { bbp_add_error('bbp_split_topic_destination_permission', __('<strong>ERROR</strong>: You do not have permission to create new topics. The reply could not be converted into a topic.', 'bbpress')); } break; } } // Bail if there are errors if (bbp_has_errors()) { return; } /** No Errors - Do the Spit ***********************************************/ // Update counts, etc... do_action('bbp_pre_split_topic', $from_reply->ID, $source_topic->ID, $destination_topic->ID); /** Date Check ************************************************************/ // Check if the destination topic is older than the from reply if (strtotime($from_reply->post_date) < strtotime($destination_topic->post_date)) { // Set destination topic post_date to 1 second before from reply $destination_post_date = date('Y-m-d H:i:s', strtotime($from_reply->post_date) - 1); // Update destination topic wp_update_post(array('ID' => $destination_topic_id, 'post_date' => $destination_post_date, 'post_date_gmt' => get_gmt_from_date($destination_post_date))); } /** Subscriptions *********************************************************/ // Copy the subscribers if (!empty($_POST['bbp_topic_subscribers']) && "1" === $_POST['bbp_topic_subscribers'] && bbp_is_subscriptions_active()) { // Get the subscribers $subscribers = bbp_get_topic_subscribers($source_topic->ID); if (!empty($subscribers)) { // Add subscribers to new topic foreach ((array) $subscribers as $subscriber) { bbp_add_user_subscription($subscriber, $destination_topic->ID); } } } /** Favorites *************************************************************/ // Copy the favoriters if told to if (!empty($_POST['bbp_topic_favoriters']) && "1" === $_POST['bbp_topic_favoriters']) { // Get the favoriters $favoriters = bbp_get_topic_favoriters($source_topic->ID); if (!empty($favoriters)) { // Add the favoriters to new topic foreach ((array) $favoriters as $favoriter) { bbp_add_user_favorite($favoriter, $destination_topic->ID); } } } /** Tags ******************************************************************/ // Copy the tags if told to if (!empty($_POST['bbp_topic_tags']) && "1" === $_POST['bbp_topic_tags']) { // Get the source topic tags $source_topic_tags = wp_get_post_terms($source_topic->ID, bbp_get_topic_tag_tax_id(), array('fields' => 'names')); if (!empty($source_topic_tags)) { wp_set_post_terms($destination_topic->ID, $source_topic_tags, bbp_get_topic_tag_tax_id(), true); } } /** Split Replies *********************************************************/ // get_posts() is not used because it doesn't allow us to use '>=' // comparision without a filter. $bbp_db = bbp_db(); $query = $bbp_db->prepare("SELECT * FROM {$bbp_db->posts} WHERE {$bbp_db->posts}.post_date >= %s AND {$bbp_db->posts}.post_parent = %d AND {$bbp_db->posts}.post_type = %s ORDER BY {$bbp_db->posts}.post_date ASC", $from_reply->post_date, $source_topic->ID, bbp_get_reply_post_type()); $replies = (array) $bbp_db->get_results($query); // Make sure there are replies to loop through if (!empty($replies) && !is_wp_error($replies)) { // Save reply ids $reply_ids = array(); // Change the post_parent of each reply to the destination topic id foreach ($replies as $reply) { // Update the reply wp_update_post(array('ID' => $reply->ID, 'post_title' => '', 'post_name' => false, 'post_parent' => $destination_topic->ID, 'guid' => '')); // Gather reply ids $reply_ids[] = $reply->ID; // Adjust reply meta values bbp_update_reply_topic_id($reply->ID, $destination_topic->ID); bbp_update_reply_forum_id($reply->ID, bbp_get_topic_forum_id($destination_topic->ID)); // Adjust reply position bbp_update_reply_position($reply->ID); // Adjust reply to values $reply_to = bbp_get_reply_to($reply->ID); // Not a reply to a reply that moved over if (!in_array($reply_to, $reply_ids)) { bbp_update_reply_to($reply->ID, 0); } // New topic from reply can't be a reply to if ($from_reply->ID === $destination_topic->ID && $from_reply->ID === $reply_to) { bbp_update_reply_to($reply->ID, 0); } // Do additional actions per split reply do_action('bbp_split_topic_reply', $reply->ID, $destination_topic->ID); } // Remove reply to from new topic if ($from_reply->ID === $destination_topic->ID) { delete_post_meta($from_reply->ID, '_bbp_reply_to'); } // Set the last reply ID and freshness $last_reply_id = $reply->ID; $freshness = $reply->post_date; // Set the last reply ID and freshness to the from_reply } else { $last_reply_id = $from_reply->ID; $freshness = $from_reply->post_date; } // It is a new topic and we need to set some default metas to make // the topic display in bbp_has_topics() list if ('reply' === $split_option) { bbp_update_topic_last_reply_id($destination_topic->ID, $last_reply_id); bbp_update_topic_last_active_id($destination_topic->ID, $last_reply_id); bbp_update_topic_last_active_time($destination_topic->ID, $freshness); } // Update source topic ID last active bbp_update_topic_last_reply_id($source_topic->ID); bbp_update_topic_last_active_id($source_topic->ID); bbp_update_topic_last_active_time($source_topic->ID); /** Successful Split ******************************************************/ // Update counts, etc... do_action('bbp_post_split_topic', $from_reply->ID, $source_topic->ID, $destination_topic->ID); // Redirect back to the topic bbp_redirect(bbp_get_topic_permalink($destination_topic->ID)); }