/** * @covers ::bbp_approve_reply */ public function test_bbp_approve_reply() { // Create a forum. $f = $this->factory->forum->create(); // Create a topic. $t = $this->factory->topic->create(array('post_parent' => $f, 'topic_meta' => array('forum_id' => $f))); // Create some replies. $r1 = $this->factory->reply->create(array('post_parent' => $t, 'reply_meta' => array('forum_id' => $f, 'topic_id' => $t))); $reply_post_status = bbp_get_reply_status($r1); $this->assertSame('publish', $reply_post_status); $topic_reply_count = bbp_get_topic_reply_count($t); $this->assertSame('1', $topic_reply_count); $r2 = $this->factory->reply->create(array('post_parent' => $t, 'post_status' => bbp_get_pending_status_id(), 'reply_meta' => array('forum_id' => $f, 'topic_id' => $t))); $reply_post_status = bbp_get_reply_status($r2); $this->assertSame('pending', $reply_post_status); $topic_reply_count = bbp_get_topic_reply_count($t); $this->assertSame('1', $topic_reply_count); bbp_approve_reply($r2); $reply_post_status = bbp_get_reply_status($r2); $this->assertSame('publish', $reply_post_status); $topic_reply_count = bbp_get_topic_reply_count($t); $this->assertSame('2', $topic_reply_count); }
/** * Reply Row actions * * Remove the quick-edit action link under the reply title and add the * content and spam link * * @since 2.0.0 bbPress (r2577) * * @param array $actions Actions * @param array $reply Reply object * @uses bbp_get_reply_post_type() To get the reply post type * @uses bbp_reply_content() To output reply content * @uses bbp_get_reply_url() To get the reply link * @uses bbp_get_reply_title() To get the reply title * @uses current_user_can() To check if the current user can edit or * delete the reply * @uses bbp_is_reply_spam() To check if the reply is marked as spam * @uses get_post_type_object() To get the reply post type object * @uses add_query_arg() To add custom args to the url * @uses remove_query_arg() To remove custom args from the url * @uses wp_nonce_url() To nonce the url * @uses get_delete_post_link() To get the delete post link of the reply * @return array $actions Actions */ public function row_actions($actions, $reply) { if ($this->bail()) { return $actions; } unset($actions['inline hide-if-no-js']); // Reply view links to topic $actions['view'] = '<a href="' . esc_url(bbp_get_reply_url($reply->ID)) . '" title="' . esc_attr(sprintf(__('View “%s”', 'bbpress'), bbp_get_reply_title($reply->ID))) . '" rel="permalink">' . esc_html__('View', 'bbpress') . '</a>'; // User cannot view replies in trash if (bbp_get_trash_status_id() === $reply->post_status && !current_user_can('view_trash')) { unset($actions['view']); } // Only show the actions if the user is capable of viewing them if (current_user_can('moderate', $reply->ID)) { // Show the 'approve' link on pending posts only and 'unapprove' on published posts only $approve_uri = wp_nonce_url(add_query_arg(array('reply_id' => $reply->ID, 'action' => 'bbp_toggle_reply_approve'), remove_query_arg(array('bbp_reply_toggle_notice', 'reply_id', 'failed', 'super'))), 'approve-reply_' . $reply->ID); if (bbp_is_reply_published($reply->ID)) { $actions['unapproved'] = '<a href="' . esc_url($approve_uri) . '" title="' . esc_attr__('Unapprove this reply', 'bbpress') . '">' . _x('Unapprove', 'Unapprove reply', 'bbpress') . '</a>'; } elseif (!bbp_is_reply_private($reply->ID)) { $actions['approved'] = '<a href="' . esc_url($approve_uri) . '" title="' . esc_attr__('Approve this reply', 'bbpress') . '">' . _x('Approve', 'Approve reply', 'bbpress') . '</a>'; } // Show the 'spam' link on published and pending replies and 'not spam' on spammed replies if (in_array($reply->post_status, array(bbp_get_public_status_id(), bbp_get_pending_status_id(), bbp_get_spam_status_id()))) { $spam_uri = wp_nonce_url(add_query_arg(array('reply_id' => $reply->ID, 'action' => 'bbp_toggle_reply_spam'), remove_query_arg(array('bbp_reply_toggle_notice', 'reply_id', 'failed', 'super'))), 'spam-reply_' . $reply->ID); if (bbp_is_reply_spam($reply->ID)) { $actions['spam'] = '<a href="' . esc_url($spam_uri) . '" title="' . esc_attr__('Mark the reply as not spam', 'bbpress') . '">' . esc_html__('Not spam', 'bbpress') . '</a>'; } else { $actions['spam'] = '<a href="' . esc_url($spam_uri) . '" title="' . esc_attr__('Mark this reply as spam', 'bbpress') . '">' . esc_html__('Spam', 'bbpress') . '</a>'; } } } // Trash if (current_user_can('delete_reply', $reply->ID)) { if (bbp_get_trash_status_id() === $reply->post_status) { $post_type_object = get_post_type_object(bbp_get_reply_post_type()); $actions['untrash'] = "<a title='" . esc_attr__('Restore this item from the Trash', 'bbpress') . "' href='" . esc_url(add_query_arg(array('_wp_http_referer' => add_query_arg(array('post_type' => bbp_get_reply_post_type()), admin_url('edit.php'))), wp_nonce_url(admin_url(sprintf($post_type_object->_edit_link . '&action=untrash', $reply->ID)), 'untrash-' . $reply->post_type . '_' . $reply->ID))) . "'>" . esc_html__('Restore', 'bbpress') . "</a>"; } elseif (EMPTY_TRASH_DAYS) { $actions['trash'] = "<a class='submitdelete' title='" . esc_attr__('Move this item to the Trash', 'bbpress') . "' href='" . esc_url(add_query_arg(array('_wp_http_referer' => add_query_arg(array('post_type' => bbp_get_reply_post_type()), admin_url('edit.php'))), get_delete_post_link($reply->ID))) . "'>" . esc_html__('Trash', 'bbpress') . "</a>"; } if (bbp_get_trash_status_id() === $reply->post_status || !EMPTY_TRASH_DAYS) { $actions['delete'] = "<a class='submitdelete' title='" . esc_attr__('Delete this item permanently', 'bbpress') . "' href='" . esc_url(add_query_arg(array('_wp_http_referer' => add_query_arg(array('post_type' => bbp_get_reply_post_type()), admin_url('edit.php'))), get_delete_post_link($reply->ID, '', true))) . "'>" . esc_html__('Delete Permanently', 'bbpress') . "</a>"; } elseif (bbp_get_spam_status_id() === $reply->post_status) { unset($actions['trash']); } } return $actions; }
/** * Return admin links for topic. * * Move topic functionality is handled by the edit topic page. * * @param array $args This function supports these arguments: * - id: Optional. Topic id * - before: Before the links * - after: After the links * - sep: Links separator * - links: Topic admin links array * @uses current_user_can() To check if the current user can edit/delete * the topic * @uses bbp_get_topic_edit_link() To get the topic edit link * @uses bbp_get_topic_trash_link() To get the topic trash link * @uses bbp_get_topic_close_link() To get the topic close link * @uses bbp_get_topic_spam_link() To get the topic spam link * @uses bbp_get_topic_stick_link() To get the topic stick link * @uses bbp_get_topic_merge_link() To get the topic merge link * @uses bbp_get_topic_status() To get the topic status * @uses apply_filters() Calls 'bbp_get_topic_admin_links' with the * topic admin links and args * @return string Topic admin links */ function bbp_get_topic_admin_links($args = array()) { // Parse arguments against default values $r = bbp_parse_args($args, array('id' => bbp_get_topic_id(), 'before' => '<span class="bbp-admin-links">', 'after' => '</span>', 'sep' => ' | ', 'links' => array()), 'get_topic_admin_links'); if (empty($r['links'])) { $r['links'] = apply_filters('bbp_topic_admin_links', array('edit' => bbp_get_topic_edit_link($r), 'merge' => bbp_get_topic_merge_link($r), 'close' => bbp_get_topic_close_link($r), 'stick' => bbp_get_topic_stick_link($r), 'trash' => bbp_get_topic_trash_link($r), 'spam' => bbp_get_topic_spam_link($r), 'approve' => bbp_get_topic_approve_link($r), 'reply' => bbp_get_topic_reply_link($r)), $r['id']); } // See if links need to be unset $topic_status = bbp_get_topic_status($r['id']); if (in_array($topic_status, array(bbp_get_spam_status_id(), bbp_get_trash_status_id(), bbp_get_pending_status_id()))) { // Close link shouldn't be visible on trashed/spammed/pending topics unset($r['links']['close']); // Spam link shouldn't be visible on trashed topics if (bbp_get_trash_status_id() === $topic_status) { unset($r['links']['spam']); // Trash link shouldn't be visible on spam topics } elseif (bbp_get_spam_status_id() === $topic_status) { unset($r['links']['trash']); } } // Process the admin links $links = implode($r['sep'], array_filter($r['links'])); $retval = $r['before'] . $links . $r['after']; return apply_filters('bbp_get_topic_admin_links', $retval, $r, $args); }
/** * Return an associative array of available topic statuses * * @since bbPress (r5059) * * @return array */ function bbp_get_topic_statuses() { return apply_filters('bbp_get_topic_statuses', array(bbp_get_public_status_id() => _x('Open', 'Open the topic', 'bbpress'), bbp_get_closed_status_id() => _x('Closed', 'Close the topic', 'bbpress'), bbp_get_spam_status_id() => _x('Spam', 'Spam the topic', 'bbpress'), bbp_get_trash_status_id() => _x('Trash', 'Trash the topic', 'bbpress'), bbp_get_pending_status_id() => _x('Pending', 'Mark topic as pending', 'bbpress'))); }
/** * Trash all topics inside a forum * * @since bbPress (r3668) * * @param int $forum_id * @uses bbp_get_forum_id() To validate the forum ID * @uses bbp_is_forum() To make sure it's a forum * @uses bbp_get_public_status_id() To return public post status * @uses bbp_get_closed_status_id() To return closed post status * @uses bbp_get_pending_status_id() To return pending post status * @uses bbp_get_topic_post_type() To get the topic post type * @uses wp_trash_post() To trash the post * @uses update_post_meta() To update the forum meta of trashed topics * @return If forum is not valid */ function bbp_trash_forum_topics($forum_id = 0) { // Validate forum ID $forum_id = bbp_get_forum_id($forum_id); if (empty($forum_id)) { return; } // Allowed post statuses to pre-trash $post_stati = implode(',', array(bbp_get_public_status_id(), bbp_get_closed_status_id(), bbp_get_pending_status_id())); // Forum is being trashed, so its topics and replies are trashed too $topics = new WP_Query(array('suppress_filters' => true, 'post_type' => bbp_get_topic_post_type(), 'post_parent' => $forum_id, 'post_status' => $post_stati, 'posts_per_page' => -1, 'nopaging' => true, 'fields' => 'id=>parent')); // Loop through and trash child topics. Topic replies will get trashed by // the bbp_trash_topic() action. if (!empty($topics->posts)) { // Prevent debug notices $pre_trashed_topics = array(); // Loop through topics, trash them, and add them to array foreach ($topics->posts as $topic) { wp_trash_post($topic->ID, true); $pre_trashed_topics[] = $topic->ID; } // Set a post_meta entry of the topics that were trashed by this action. // This is so we can possibly untrash them, without untrashing topics // that were purposefully trashed before. update_post_meta($forum_id, '_bbp_pre_trashed_topics', $pre_trashed_topics); // Reset the $post global wp_reset_postdata(); } // Cleanup unset($topics); }
/** * Handles the front end edit reply submission * * @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_verify_nonce_request() To verify the nonce and check the request * @uses bbp_is_reply_anonymous() To check if the reply was by an anonymous user * @uses current_user_can() To check if the current user can edit that reply * @uses bbp_filter_anonymous_post_data() To filter anonymous data * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error} * @uses remove_filter() To remove kses filters if needed * @uses esc_attr() For sanitization * @uses apply_filters() Calls 'bbp_edit_reply_pre_title' with the title and * reply id * @uses apply_filters() Calls 'bbp_edit_reply_pre_content' with the content * reply id * @uses wp_set_post_terms() To set the topic tags * @uses bbp_has_errors() To get the {@link WP_Error} errors * @uses wp_save_post_revision() To save a reply revision * @uses bbp_update_reply_revision_log() To update the reply revision log * @uses wp_update_post() To update the reply * @uses bbp_get_reply_topic_id() To get the reply topic id * @uses bbp_get_topic_forum_id() To get the topic forum id * @uses bbp_get_reply_to() To get the reply to id * @uses do_action() Calls 'bbp_edit_reply' with the reply id, topic id, forum * id, anonymous data, reply author, bool true (for edit), * and the reply to id * @uses bbp_get_reply_url() To get the paginated url to the reply * @uses wp_safe_redirect() To redirect to the reply url * @uses bbPress::errors::get_error_message() To get the {@link WP_Error} error * message */ function bbp_edit_reply_handler($action = '') { // Bail if action is not bbp-edit-reply if ('bbp-edit-reply' !== $action) { return; } // Define local variable(s) $revisions_removed = false; $reply = $reply_id = $reply_author = $topic_id = $forum_id = $anonymous_data = 0; $reply_title = $reply_content = $reply_edit_reason = $terms = ''; /** Reply *****************************************************************/ // Reply id was not passed if (empty($_POST['bbp_reply_id'])) { bbp_add_error('bbp_edit_reply_id', __('<strong>ERROR</strong>: Reply ID not found.', 'bbpress')); return; // Reply id was passed } elseif (is_numeric($_POST['bbp_reply_id'])) { $reply_id = (int) $_POST['bbp_reply_id']; $reply = bbp_get_reply($reply_id); } // Nonce check if (!bbp_verify_nonce_request('bbp-edit-reply_' . $reply_id)) { bbp_add_error('bbp_edit_reply_nonce', __('<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress')); return; } // Reply does not exist if (empty($reply)) { bbp_add_error('bbp_edit_reply_not_found', __('<strong>ERROR</strong>: The reply you want to edit was not found.', 'bbpress')); return; // Reply exists } else { // Check users ability to create new reply if (!bbp_is_reply_anonymous($reply_id)) { // User cannot edit this reply if (!current_user_can('edit_reply', $reply_id)) { bbp_add_error('bbp_edit_reply_permissions', __('<strong>ERROR</strong>: You do not have permission to edit that reply.', 'bbpress')); return; } // Set reply author $reply_author = bbp_get_reply_author_id($reply_id); // It is an anonymous post } else { // Filter anonymous data $anonymous_data = bbp_filter_anonymous_post_data(); } } // Remove kses filters from title and content for capable users and if the nonce is verified if (current_user_can('unfiltered_html') && !empty($_POST['_bbp_unfiltered_html_reply']) && wp_create_nonce('bbp-unfiltered-html-reply_' . $reply_id) === $_POST['_bbp_unfiltered_html_reply']) { remove_filter('bbp_edit_reply_pre_title', 'wp_filter_kses'); remove_filter('bbp_edit_reply_pre_content', 'bbp_encode_bad', 10); remove_filter('bbp_edit_reply_pre_content', 'bbp_filter_kses', 30); } /** Reply Topic ***********************************************************/ $topic_id = bbp_get_reply_topic_id($reply_id); /** Topic Forum ***********************************************************/ $forum_id = bbp_get_topic_forum_id($topic_id); // Forum exists if (!empty($forum_id) && $forum_id !== bbp_get_reply_forum_id($reply_id)) { // Forum is a category if (bbp_is_forum_category($forum_id)) { bbp_add_error('bbp_edit_reply_forum_category', __('<strong>ERROR</strong>: This forum is a category. No replies can be created in this forum.', 'bbpress')); // Forum is not a category } else { // Forum is closed and user cannot access if (bbp_is_forum_closed($forum_id) && !current_user_can('edit_forum', $forum_id)) { bbp_add_error('bbp_edit_reply_forum_closed', __('<strong>ERROR</strong>: This forum has been closed to new replies.', 'bbpress')); } // Forum is private and user cannot access if (bbp_is_forum_private($forum_id)) { if (!current_user_can('read_private_forums')) { bbp_add_error('bbp_edit_reply_forum_private', __('<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new replies in it.', 'bbpress')); } // Forum is hidden and user cannot access } elseif (bbp_is_forum_hidden($forum_id)) { if (!current_user_can('read_hidden_forums')) { bbp_add_error('bbp_edit_reply_forum_hidden', __('<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new replies in it.', 'bbpress')); } } } } /** Reply Title ***********************************************************/ if (!empty($_POST['bbp_reply_title'])) { $reply_title = esc_attr(strip_tags($_POST['bbp_reply_title'])); } // Filter and sanitize $reply_title = apply_filters('bbp_edit_reply_pre_title', $reply_title, $reply_id); /** Reply Content *********************************************************/ if (!empty($_POST['bbp_reply_content'])) { $reply_content = $_POST['bbp_reply_content']; } // Filter and sanitize $reply_content = apply_filters('bbp_edit_reply_pre_content', $reply_content, $reply_id); // No reply content if (empty($reply_content)) { bbp_add_error('bbp_edit_reply_content', __('<strong>ERROR</strong>: Your reply cannot be empty.', 'bbpress')); } /** Reply Blacklist *******************************************************/ if (!bbp_check_for_blacklist($anonymous_data, $reply_author, $reply_title, $reply_content)) { bbp_add_error('bbp_reply_blacklist', __('<strong>ERROR</strong>: Your reply cannot be edited at this time.', 'bbpress')); } /** Reply Status **********************************************************/ // Maybe put into moderation if (!bbp_check_for_moderation($anonymous_data, $reply_author, $reply_title, $reply_content)) { // Set post status to pending if public if (bbp_get_public_status_id() === $reply->post_status) { $reply_status = bbp_get_pending_status_id(); } // Use existing post_status } else { $reply_status = $reply->post_status; } /** Reply To **************************************************************/ // Handle Reply To of the reply; $_REQUEST for non-JS submissions if (isset($_REQUEST['bbp_reply_to'])) { $reply_to = bbp_validate_reply_to($_REQUEST['bbp_reply_to']); } /** Topic Tags ************************************************************/ // Either replace terms if (bbp_allow_topic_tags() && current_user_can('assign_topic_tags') && !empty($_POST['bbp_topic_tags'])) { $terms = esc_attr(strip_tags($_POST['bbp_topic_tags'])); // ...or remove them. } elseif (isset($_POST['bbp_topic_tags'])) { $terms = ''; // Existing terms } else { $terms = bbp_get_topic_tag_names($topic_id); } /** Additional Actions (Before Save) **************************************/ do_action('bbp_edit_reply_pre_extras', $reply_id); // Bail if errors if (bbp_has_errors()) { return; } /** No Errors *************************************************************/ // Add the content of the form to $reply_data as an array // Just in time manipulation of reply data before being edited $reply_data = apply_filters('bbp_edit_reply_pre_insert', array('ID' => $reply_id, 'post_title' => $reply_title, 'post_content' => $reply_content, 'post_status' => $reply_status, 'post_parent' => $topic_id, 'post_author' => $reply_author, 'post_type' => bbp_get_reply_post_type())); // Toggle revisions to avoid duplicates if (post_type_supports(bbp_get_reply_post_type(), 'revisions')) { $revisions_removed = true; remove_post_type_support(bbp_get_reply_post_type(), 'revisions'); } // Insert topic $reply_id = wp_update_post($reply_data); // Toggle revisions back on if (true === $revisions_removed) { $revisions_removed = false; add_post_type_support(bbp_get_reply_post_type(), 'revisions'); } /** Topic Tags ************************************************************/ // Just in time manipulation of reply terms before being edited $terms = apply_filters('bbp_edit_reply_pre_set_terms', $terms, $topic_id, $reply_id); // Insert terms $terms = wp_set_post_terms($topic_id, $terms, bbp_get_topic_tag_tax_id(), false); // Term error if (is_wp_error($terms)) { bbp_add_error('bbp_reply_tags', __('<strong>ERROR</strong>: There was a problem adding the tags to the topic.', 'bbpress')); } /** Revisions *************************************************************/ // Revision Reason if (!empty($_POST['bbp_reply_edit_reason'])) { $reply_edit_reason = esc_attr(strip_tags($_POST['bbp_reply_edit_reason'])); } // Update revision log if (!empty($_POST['bbp_log_reply_edit']) && "1" === $_POST['bbp_log_reply_edit']) { $revision_id = wp_save_post_revision($reply_id); if (!empty($revision_id)) { bbp_update_reply_revision_log(array('reply_id' => $reply_id, 'revision_id' => $revision_id, 'author_id' => bbp_get_current_user_id(), 'reason' => $reply_edit_reason)); } } /** No Errors *************************************************************/ if (!empty($reply_id) && !is_wp_error($reply_id)) { // Update counts, etc... do_action('bbp_edit_reply', $reply_id, $topic_id, $forum_id, $anonymous_data, $reply_author, true, $reply_to); /** Additional Actions (After Save) ***********************************/ do_action('bbp_edit_reply_post_extras', $reply_id); /** Redirect **********************************************************/ // Redirect to $redirect_to = bbp_get_redirect_to(); // Get the reply URL $reply_url = bbp_get_reply_url($reply_id, $redirect_to); // Allow to be filtered $reply_url = apply_filters('bbp_edit_reply_redirect_to', $reply_url, $redirect_to); /** Successful Edit ***************************************************/ // Redirect back to new reply wp_safe_redirect($reply_url); // For good measure exit; /** Errors ****************************************************************/ } else { $append_error = is_wp_error($reply_id) && $reply_id->get_error_message() ? $reply_id->get_error_message() . ' ' : ''; bbp_add_error('bbp_reply_error', __('<strong>ERROR</strong>: The following problem(s) have been found with your reply:' . $append_error . 'Please try again.', 'bbpress')); } }
/** * @covers ::bbp_get_all_child_ids */ public function test_bbp_get_all_child_ids() { $f = $this->factory->forum->create(); // Test initial forum public child counts $count = count(bbp_get_all_child_ids($f, bbp_get_forum_post_type())); $this->assertSame(0, $count); $count = count(bbp_get_all_child_ids($f, bbp_get_topic_post_type())); $this->assertSame(0, $count); /* Sub-Forums *********************************************************/ $this->factory->forum->create_many(3, array('post_parent' => $f)); $this->factory->forum->create(array('post_parent' => $f, 'post_status' => bbp_get_private_status_id())); $count = count(bbp_get_all_child_ids($f, bbp_get_forum_post_type())); $this->assertSame(4, $count); $this->factory->forum->create_many(2, array('post_parent' => $f)); $count = count(bbp_get_all_child_ids($f, bbp_get_forum_post_type())); $this->assertSame(6, $count); /* Topics *************************************************************/ $t1 = $this->factory->topic->create_many(3, array('post_parent' => $f, 'topic_meta' => array('forum_id' => $f))); $this->factory->topic->create(array('post_parent' => $f, 'post_status' => bbp_get_spam_status_id(), 'topic_meta' => array('forum_id' => $f))); $count = count(bbp_get_all_child_ids($f, bbp_get_topic_post_type())); $this->assertSame(4, $count); $this->factory->topic->create_many(2, array('post_parent' => $f, 'topic_meta' => array('forum_id' => $f))); $count = count(bbp_get_all_child_ids($f, bbp_get_topic_post_type())); $this->assertSame(6, $count); $this->factory->topic->create(array('post_parent' => $f, 'post_status' => bbp_get_pending_status_id(), 'topic_meta' => array('forum_id' => $f))); $count = count(bbp_get_all_child_ids($f, bbp_get_topic_post_type())); $this->assertSame(7, $count); /* Replies ************************************************************/ $this->factory->reply->create_many(3, array('post_parent' => $t1[0], 'reply_meta' => array('forum_id' => $f, 'topic_id' => $t1[0]))); $this->factory->reply->create(array('post_parent' => $t1[0], 'post_status' => bbp_get_spam_status_id(), 'reply_meta' => array('forum_id' => $f, 'topic_id' => $t1[0]))); $count = count(bbp_get_all_child_ids($t1[0], bbp_get_reply_post_type())); $this->assertSame(4, $count); $this->factory->reply->create_many(2, array('post_parent' => $t1[0], 'reply_meta' => array('forum_id' => $f, 'topic_id' => $t1[0]))); $count = count(bbp_get_all_child_ids($t1[0], bbp_get_reply_post_type())); $this->assertSame(6, $count); $this->factory->reply->create(array('post_parent' => $t1[0], 'post_status' => bbp_get_pending_status_id(), 'reply_meta' => array('forum_id' => $f, 'topic_id' => $t1[0]))); $count = count(bbp_get_all_child_ids($t1[0], bbp_get_reply_post_type())); $this->assertSame(7, $count); }
/** * Unapproves a reply * * @since 2.6.0 bbPress (r5506) * * @param int $reply_id Reply id * @uses bbp_get_reply() To get the reply * @uses bbp_get_pending_status_id() To get the pending status id * @uses do_action() Calls 'bbp_unapprove_reply' with the reply id * @uses remove_action() To remove the auto save post revision action * @uses wp_update_post() To update the reply with the new status * @uses do_action() Calls 'bbp_unapproved_reply' with the reply id * @return mixed False or {@link WP_Error} on failure, reply id on success */ function bbp_unapprove_reply($reply_id = 0) { // Get reply $reply = bbp_get_reply($reply_id); if (empty($reply)) { return $reply; } // Bail if already pending if (bbp_get_pending_status_id() === $reply->post_status) { return false; } // Execute pre open code do_action('bbp_unapprove_reply', $reply_id); // Set pending status $reply->post_status = bbp_get_pending_status_id(); // No revisions remove_action('pre_post_update', 'wp_save_post_revision'); // Update reply $reply_id = wp_update_post($reply); // Execute post open code do_action('bbp_unapproved_reply', $reply_id); // Return reply_id return $reply_id; }
/** * Query the DB and get a the child id's of all children * * @since 2.0.0 bbPress (r3325) * * @param int $parent_id Parent id * @param string $post_type Post type. Defaults to 'post' * @uses wp_cache_get() To check if there is a cache of the children * @uses bbp_get_public_status_id() To get the public status id * @uses bbp_get_private_status_id() To get the private status id * @uses bbp_get_hidden_status_id() To get the hidden status id * @uses bbp_get_pending_status_id() To get the pending status id * @uses bbp_get_closed_status_id() To get the closed status id * @uses bbp_get_trash_status_id() To get the trash status id * @uses bbp_get_spam_status_id() To get the spam status id * @uses bbp_get_forum_post_type() To get the forum post type * @uses bbp_get_topic_post_type() To get the topic post type * @uses bbp_get_reply_post_type() To get the reply post type * @uses wpdb::prepare() To prepare the query * @uses wpdb::get_col() To get the result of the query in an array * @uses wp_cache_set() To set the cache for future use * @uses apply_filters() Calls 'bbp_get_all_child_ids' with the child ids, * parent id and post type * @return array The array of children */ function bbp_get_all_child_ids($parent_id = 0, $post_type = 'post') { // Bail if nothing passed if (empty($parent_id)) { return false; } // The ID of the cached query $cache_id = 'bbp_parent_all_' . $parent_id . '_type_' . $post_type . '_child_ids'; // Check for cache and set if needed $child_ids = wp_cache_get($cache_id, 'bbpress_posts'); if (false === $child_ids) { $post_status = array(bbp_get_public_status_id()); // Extra post statuses based on post type switch ($post_type) { // Forum case bbp_get_forum_post_type(): $post_status[] = bbp_get_private_status_id(); $post_status[] = bbp_get_hidden_status_id(); break; // Topic // Topic case bbp_get_topic_post_type(): $post_status[] = bbp_get_pending_status_id(); $post_status[] = bbp_get_closed_status_id(); $post_status[] = bbp_get_trash_status_id(); $post_status[] = bbp_get_spam_status_id(); break; // Reply // Reply case bbp_get_reply_post_type(): $post_status[] = bbp_get_pending_status_id(); $post_status[] = bbp_get_trash_status_id(); $post_status[] = bbp_get_spam_status_id(); break; } // Join post statuses together $post_status = "'" . implode("', '", $post_status) . "'"; $bbp_db = bbp_db(); $query = $bbp_db->prepare("SELECT ID FROM {$bbp_db->posts} WHERE post_parent = %d AND post_status IN ( {$post_status} ) AND post_type = '%s' ORDER BY ID DESC;", $parent_id, $post_type); $child_ids = (array) $bbp_db->get_col($query); wp_cache_set($cache_id, $child_ids, 'bbpress_posts'); } else { $child_ids = (array) $child_ids; } // Filter and return return (array) apply_filters('bbp_get_all_child_ids', $child_ids, $parent_id, $post_type); }
/** * Return admin links for reply * * @since 2.0.0 bbPress (r2667) * * @param array $args This function supports these arguments: * - id: Optional. Reply id * - before: HTML before the links. Defaults to * '<span class="bbp-admin-links">' * - after: HTML after the links. Defaults to '</span>' * - sep: Separator. Defaults to ' | ' * - links: Array of the links to display. By default, edit, trash, * spam, reply move, and topic split links are displayed * @uses bbp_is_topic() To check if it's the topic page * @uses bbp_is_reply() To check if it's the reply page * @uses bbp_get_reply_id() To get the reply id * @uses bbp_get_reply_edit_link() To get the reply edit link * @uses bbp_get_reply_trash_link() To get the reply trash link * @uses bbp_get_reply_spam_link() To get the reply spam link * @uses bbp_get_reply_move_link() To get the reply move link * @uses bbp_get_topic_split_link() To get the topic split link * @uses current_user_can() To check if the current user can edit or * delete the reply * @uses apply_filters() Calls 'bbp_get_reply_admin_links' with the * reply admin links and args * @return string Reply admin links */ function bbp_get_reply_admin_links($args = array()) { // Parse arguments against default values $r = bbp_parse_args($args, array('id' => 0, 'before' => '<span class="bbp-admin-links">', 'after' => '</span>', 'sep' => ' | ', 'links' => array()), 'get_reply_admin_links'); $r['id'] = bbp_get_reply_id($r['id']); // If post is a topic, return the topic admin links instead if (bbp_is_topic($r['id'])) { return bbp_get_topic_admin_links($args); } // If post is not a reply, return if (!bbp_is_reply($r['id'])) { return; } // If topic is trashed, do not show admin links if (bbp_is_topic_trash(bbp_get_reply_topic_id($r['id']))) { return; } // If no links were passed, default to the standard if (empty($r['links'])) { $r['links'] = apply_filters('bbp_reply_admin_links', array('edit' => bbp_get_reply_edit_link($r), 'move' => bbp_get_reply_move_link($r), 'split' => bbp_get_topic_split_link($r), 'trash' => bbp_get_reply_trash_link($r), 'spam' => bbp_get_reply_spam_link($r), 'approve' => bbp_get_reply_approve_link($r), 'reply' => bbp_get_reply_to_link($r)), $r['id']); } // See if links need to be unset $reply_status = bbp_get_reply_status($r['id']); if (in_array($reply_status, array(bbp_get_spam_status_id(), bbp_get_trash_status_id(), bbp_get_pending_status_id()))) { // Spam link shouldn't be visible on trashed topics if (bbp_get_trash_status_id() === $reply_status) { unset($r['links']['spam']); // Trash link shouldn't be visible on spam topics } elseif (bbp_get_spam_status_id() === $reply_status) { unset($r['links']['trash']); } } // Process the admin links $links = implode($r['sep'], array_filter($r['links'])); $retval = $r['before'] . $links . $r['after']; return apply_filters('bbp_get_reply_admin_links', $retval, $r, $args); }
/** * The main search loop. WordPress does the heavy lifting. * * @since 2.3.0 bbPress (r4579) * * @param array $args All the arguments supported by {@link WP_Query} * @uses bbp_get_view_all() Are we showing all results? * @uses bbp_get_public_status_id() To get the public status id * @uses bbp_get_closed_status_id() To get the closed status id * @uses bbp_get_spam_status_id() To get the spam status id * @uses bbp_get_trash_status_id() To get the trash status id * @uses bbp_get_forum_post_type() To get the forum post type * @uses bbp_get_topic_post_type() To get the topic post type * @uses bbp_get_reply_post_type() To get the reply post type * @uses bbp_get_replies_per_page() To get the replies per page option * @uses bbp_get_paged() To get the current page value * @uses bbp_get_search_terms() To get the search terms * @uses WP_Query To make query and get the search results * @uses bbp_use_pretty_urls() To check if the site is using pretty URLs * @uses bbp_get_search_url() To get the forum search url * @uses paginate_links() To paginate search results * @uses apply_filters() Calls 'bbp_has_search_results' with * bbPress::search_query::have_posts() * and bbPress::reply_query * @return object Multidimensional array of search information */ function bbp_has_search_results($args = array()) { /** Defaults **************************************************************/ $default_search_terms = bbp_get_search_terms(); $default_post_type = array(bbp_get_forum_post_type(), bbp_get_topic_post_type(), bbp_get_reply_post_type()); // Default query args $default = array('post_type' => $default_post_type, 'posts_per_page' => bbp_get_replies_per_page(), 'paged' => bbp_get_paged(), 'orderby' => 'date', 'order' => 'DESC', 'ignore_sticky_posts' => true); // Only set 's' if search terms exist // https://bbpress.trac.wordpress.org/ticket/2607 if (false !== $default_search_terms) { $default['s'] = $default_search_terms; } // What are the default allowed statuses (based on user caps) if (bbp_get_view_all()) { // Default view=all statuses $post_statuses = array(bbp_get_public_status_id(), bbp_get_closed_status_id(), bbp_get_spam_status_id(), bbp_get_trash_status_id(), bbp_get_pending_status_id()); // Add support for private status if (current_user_can('read_private_topics')) { $post_statuses[] = bbp_get_private_status_id(); } // Join post statuses together $default['post_status'] = implode(',', $post_statuses); // Lean on the 'perm' query var value of 'readable' to provide statuses } else { $default['perm'] = 'readable'; } /** Setup *****************************************************************/ // Parse arguments against default values $r = bbp_parse_args($args, $default, 'has_search_results'); // Get bbPress $bbp = bbpress(); // Only call the search query if 's' is not empty if (!empty($r['s'])) { $bbp->search_query = new WP_Query($r); } // Add pagination values to query object $bbp->search_query->posts_per_page = $r['posts_per_page']; $bbp->search_query->paged = $r['paged']; // Never home, regardless of what parse_query says $bbp->search_query->is_home = false; // Only add pagination is query returned results if (!empty($bbp->search_query->found_posts) && !empty($bbp->search_query->posts_per_page)) { // Array of arguments to add after pagination links $add_args = array(); // If pretty permalinks are enabled, make our pagination pretty if (bbp_use_pretty_urls()) { // Shortcode territory if (is_page() || is_single()) { $base = trailingslashit(get_permalink()); // Default search location } else { $base = trailingslashit(bbp_get_search_results_url()); } // Add pagination base $base = $base . user_trailingslashit(bbp_get_paged_slug() . '/%#%/'); // Unpretty permalinks } else { $base = add_query_arg('paged', '%#%'); } // Add args if (bbp_get_view_all()) { $add_args['view'] = 'all'; } // Add pagination to query object $bbp->search_query->pagination_links = paginate_links(apply_filters('bbp_search_results_pagination', array('base' => $base, 'format' => '', 'total' => ceil((int) $bbp->search_query->found_posts / (int) $r['posts_per_page']), 'current' => (int) $bbp->search_query->paged, 'prev_text' => is_rtl() ? '→' : '←', 'next_text' => is_rtl() ? '←' : '→', 'mid_size' => 1, 'add_args' => $add_args))); // Remove first page from pagination if (bbp_use_pretty_urls()) { $bbp->search_query->pagination_links = str_replace(bbp_get_paged_slug() . '/1/', '', $bbp->search_query->pagination_links); } else { $bbp->search_query->pagination_links = str_replace('&paged=1', '', $bbp->search_query->pagination_links); } } // Return object return apply_filters('bbp_has_search_results', $bbp->search_query->have_posts(), $bbp->search_query); }
/** * Unapproves a topic * * @since 2.6.0 bbPress (r5503) * * @param int $topic_id Topic id * @uses bbp_get_topic() To get the topic * @uses bbp_get_pending_status_id() To get the pending status id * @uses do_action() Calls 'bbp_unapprove_topic' with the topic id * @uses remove_action() To remove the auto save post revision action * @uses wp_update_post() To update the topic with the new status * @uses do_action() Calls 'bbp_unapproved_topic' with the topic id * @return mixed False or {@link WP_Error} on failure, topic id on success */ function bbp_unapprove_topic($topic_id = 0) { // Get topic $topic = bbp_get_topic($topic_id); if (empty($topic)) { return $topic; } // Bail if already pending if (bbp_get_pending_status_id() === $topic->post_status) { return false; } // Execute pre open code do_action('bbp_unapprove_topic', $topic_id); // Set pending status $topic->post_status = bbp_get_pending_status_id(); // No revisions remove_action('pre_post_update', 'wp_save_post_revision'); // Update topic $topic_id = wp_update_post($topic); // Execute post open code do_action('bbp_unapproved_topic', $topic_id); // Return topic_id return $topic_id; }
/** * @covers ::bbp_topic_voice_count * @covers ::bbp_get_topic_voice_count */ public function test_bbp_get_topic_voice_count_with_pending_reply() { $u = $this->factory->user->create_many(2); $f = $this->factory->forum->create(); $t = $this->factory->topic->create(array('post_parent' => $f, 'topic_meta' => array('forum_id' => $f))); $this->factory->reply->create(array('post_parent' => $t, 'post_author' => $u[0], 'reply_meta' => array('forum_id' => $f, 'topic_id' => $t))); $count = bbp_get_topic_voice_count($t, true); $this->assertSame(2, $count); $r2 = $this->factory->reply->create(array('post_parent' => $t, 'post_author' => $u[1], 'post_status' => bbp_get_pending_status_id(), 'reply_meta' => array('forum_id' => $f, 'topic_id' => $t))); $count = bbp_get_topic_voice_count($t, true); $this->assertSame(2, $count); bbp_approve_reply($r2); $count = bbp_get_topic_voice_count($t, true); $this->assertSame(3, $count); }
/** * Recount topic hidden replies (spammed/trashed) * * @since 2.0.0 bbPress (r2747) * * @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_get_trash_status_id() To get the trash status id * @uses bbp_get_spam_status_id() To get the spam status id * @uses bbp_get_pending_status_id() To get the pending status id * @return array An array of the status code and the message */ function bbp_admin_repair_topic_hidden_reply_count() { // Define variables $bbp_db = bbp_db(); $statement = __('Counting the number of pending, spammed, and trashed replies in each topic… %s', 'bbpress'); $result = __('Failed!', 'bbpress'); $sql_delete = "DELETE FROM `{$bbp_db->postmeta}` WHERE `meta_key` = '_bbp_reply_count_hidden';"; if (is_wp_error($bbp_db->query($sql_delete))) { return array(1, sprintf($statement, $result)); } // Post types and status $rpt = bbp_get_reply_post_type(); $tps = bbp_get_trash_status_id(); $sps = bbp_get_spam_status_id(); $pps = bbp_get_pending_status_id(); $sql = "INSERT INTO `{$bbp_db->postmeta}` (`post_id`, `meta_key`, `meta_value`) (SELECT `post_parent`, '_bbp_reply_count_hidden', COUNT(`post_status`) as `meta_value` FROM `{$bbp_db->posts}` WHERE `post_type` = '{$rpt}' AND `post_status` IN ( '{$tps}', '{$sps}', '{$pps}' ) GROUP BY `post_parent`);"; if (is_wp_error($bbp_db->query($sql))) { return array(2, sprintf($statement, $result)); } return array(0, sprintf($statement, __('Complete!', 'bbpress'))); }
/** * Handles the front end edit topic submission * * @uses bbPress:errors::add() To log various error messages * @uses bbp_get_topic() To get the topic * @uses bbp_verify_nonce_request() To verify the nonce and check the request * @uses bbp_is_topic_anonymous() To check if topic is by an anonymous user * @uses current_user_can() To check if the current user can edit the topic * @uses bbp_filter_anonymous_post_data() To filter anonymous data * @uses is_wp_error() To check if the value retrieved is a {@link WP_Error} * @uses esc_attr() For sanitization * @uses bbp_is_forum_category() To check if the forum is a category * @uses bbp_is_forum_closed() To check if the forum is closed * @uses bbp_is_forum_private() To check if the forum is private * @uses remove_filter() To remove 'wp_filter_kses' filters if needed * @uses apply_filters() Calls 'bbp_edit_topic_pre_title' with the title and * topic id * @uses apply_filters() Calls 'bbp_edit_topic_pre_content' with the content * and topic id * @uses bbPress::errors::get_error_codes() To get the {@link WP_Error} errors * @uses wp_save_post_revision() To save a topic revision * @uses bbp_update_topic_revision_log() To update the topic revision log * @uses bbp_stick_topic() To stick or super stick the topic * @uses bbp_unstick_topic() To unstick the topic * @uses wp_update_post() To update the topic * @uses do_action() Calls 'bbp_edit_topic' with the topic id, forum id, * anonymous data and reply author * @uses bbp_move_topic_handler() To handle movement of a topic from one forum * to another * @uses bbp_get_topic_permalink() To get the topic permalink * @uses wp_safe_redirect() To redirect to the topic link * @uses bbPress::errors::get_error_messages() To get the {@link WP_Error} error * messages */ function bbp_edit_topic_handler() { // Bail if not a POST action if ('POST' !== strtoupper($_SERVER['REQUEST_METHOD'])) { return; } // Bail if action is not bbp-edit-topic if (empty($_POST['action']) || 'bbp-edit-topic' !== $_POST['action']) { return; } // Define local variable(s) $topic = $topic_id = $forum_id = $anonymous_data = 0; $topic_title = $topic_content = $topic_edit_reason = ''; $terms = array(bbp_get_topic_tag_tax_id() => array()); /** Topic *****************************************************************/ // Topic id was not passed if (empty($_POST['bbp_topic_id'])) { bbp_add_error('bbp_edit_topic_id', __('<strong>ERROR</strong>: Topic ID not found.', 'bbpress')); return; // Topic id was passed } elseif (is_numeric($_POST['bbp_topic_id'])) { $topic_id = (int) $_POST['bbp_topic_id']; $topic = bbp_get_topic($topic_id); } // Topic does not exist if (empty($topic)) { bbp_add_error('bbp_edit_topic_not_found', __('<strong>ERROR</strong>: The topic you want to edit was not found.', 'bbpress')); return; // Topic exists } else { // Check users ability to create new topic if (!bbp_is_topic_anonymous($topic_id)) { // User cannot edit this topic if (!current_user_can('edit_topic', $topic_id)) { bbp_add_error('bbp_edit_topic_permissions', __('<strong>ERROR</strong>: You do not have permission to edit that topic.', 'bbpress')); } // It is an anonymous post } else { // Filter anonymous data $anonymous_data = bbp_filter_anonymous_post_data(array(), true); } } // Nonce check if (!bbp_verify_nonce_request('bbp-edit-topic_' . $topic_id)) { bbp_add_error('bbp_edit_topic_nonce', __('<strong>ERROR</strong>: Are you sure you wanted to do that?', 'bbpress')); return; } // Remove wp_filter_kses filters from title and content for capable users and if the nonce is verified if (current_user_can('unfiltered_html') && !empty($_POST['_bbp_unfiltered_html_topic']) && wp_create_nonce('bbp-unfiltered-html-topic_' . $topic_id) == $_POST['_bbp_unfiltered_html_topic']) { remove_filter('bbp_edit_topic_pre_title', 'wp_filter_kses'); remove_filter('bbp_edit_topic_pre_content', 'wp_filter_kses'); } /** Topic Forum ***********************************************************/ // Forum id was not passed if (empty($_POST['bbp_forum_id'])) { bbp_add_error('bbp_topic_forum_id', __('<strong>ERROR</strong>: Forum ID is missing.', 'bbpress')); // Forum id was passed } elseif (is_numeric($_POST['bbp_forum_id'])) { $forum_id = (int) $_POST['bbp_forum_id']; } // Current forum this topic is in $current_forum_id = bbp_get_topic_forum_id($topic_id); // Forum exists if (!empty($forum_id) && $forum_id !== $current_forum_id) { // Forum is a category if (bbp_is_forum_category($forum_id)) { bbp_add_error('bbp_edit_topic_forum_category', __('<strong>ERROR</strong>: This forum is a category. No topics can be created in it.', 'bbpress')); } // Forum is closed and user cannot access if (bbp_is_forum_closed($forum_id) && !current_user_can('edit_forum', $forum_id)) { bbp_add_error('bbp_edit_topic_forum_closed', __('<strong>ERROR</strong>: This forum has been closed to new topics.', 'bbpress')); } // Forum is private and user cannot access if (bbp_is_forum_private($forum_id) && !current_user_can('read_private_forums')) { bbp_add_error('bbp_edit_topic_forum_private', __('<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new topics in it.', 'bbpress')); } // Forum is hidden and user cannot access if (bbp_is_forum_hidden($forum_id) && !current_user_can('read_hidden_forums')) { bbp_add_error('bbp_edit_topic_forum_hidden', __('<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new topics in it.', 'bbpress')); } } /** Topic Title ***********************************************************/ if (!empty($_POST['bbp_topic_title'])) { $topic_title = esc_attr(strip_tags($_POST['bbp_topic_title'])); } // Filter and sanitize $topic_title = apply_filters('bbp_edit_topic_pre_title', $topic_title, $topic_id); // No topic title if (empty($topic_title)) { bbp_add_error('bbp_edit_topic_title', __('<strong>ERROR</strong>: Your topic needs a title.', 'bbpress')); } /** Topic Content *********************************************************/ if (!empty($_POST['bbp_topic_content'])) { $topic_content = $_POST['bbp_topic_content']; } // Filter and sanitize $topic_content = apply_filters('bbp_edit_topic_pre_content', $topic_content, $topic_id); // No topic content if (empty($topic_content)) { bbp_add_error('bbp_edit_topic_content', __('<strong>ERROR</strong>: Your topic cannot be empty.', 'bbpress')); } /** topic Blacklist *******************************************************/ if (!bbp_check_for_blacklist($anonymous_data, bbp_get_topic_author_id($topic_id), $topic_title, $topic_content)) { bbp_add_error('bbp_topic_blacklist', __('<strong>ERROR</strong>: Your topic cannot be edited at this time.', 'bbpress')); } /** Topic Moderation ******************************************************/ $post_status = bbp_get_public_status_id(); if (!bbp_check_for_moderation($anonymous_data, bbp_get_topic_author_id($topic_id), $topic_title, $topic_content)) { $post_status = bbp_get_pending_status_id(); } /** Topic Tags ************************************************************/ // Tags if (!empty($_POST['bbp_topic_tags'])) { // Escape tag input $terms = esc_attr(strip_tags($_POST['bbp_topic_tags'])); // Explode by comma if (strstr($terms, ',')) { $terms = explode(',', $terms); } // Add topic tag ID as main key $terms = array(bbp_get_topic_tag_tax_id() => $terms); } /** Additional Actions (Before Save) **************************************/ do_action('bbp_edit_topic_pre_extras', $topic_id); // Bail if errors if (bbp_has_errors()) { return; } /** No Errors *************************************************************/ // Add the content of the form to $topic_data as an array // Just in time manipulation of topic data before being edited $topic_data = apply_filters('bbp_edit_topic_pre_insert', array('ID' => $topic_id, 'post_title' => $topic_title, 'post_content' => $topic_content, 'post_status' => $post_status, 'post_parent' => $forum_id, 'post_author' => $topic->post_author, 'post_type' => bbp_get_topic_post_type(), 'tax_input' => $terms)); // Insert topic $topic_id = wp_update_post($topic_data); /** Stickies **************************************************************/ if (!empty($_POST['bbp_stick_topic']) && in_array($_POST['bbp_stick_topic'], array('stick', 'super', 'unstick'))) { // What's the dilly? switch ($_POST['bbp_stick_topic']) { // Sticky in forum case 'stick': bbp_stick_topic($topic_id); break; // Sticky in all forums // Sticky in all forums case 'super': bbp_stick_topic($topic_id, true); break; // Normal // Normal case 'unstick': default: bbp_unstick_topic($topic_id); break; } } /** Revisions *************************************************************/ // Revision Reason if (!empty($_POST['bbp_topic_edit_reason'])) { $topic_edit_reason = esc_attr(strip_tags($_POST['bbp_topic_edit_reason'])); } // Update revision log if (!empty($_POST['bbp_log_topic_edit']) && 1 == $_POST['bbp_log_topic_edit'] && ($revision_id = wp_save_post_revision($topic_id))) { bbp_update_topic_revision_log(array('topic_id' => $topic_id, 'revision_id' => $revision_id, 'author_id' => bbp_get_current_user_id(), 'reason' => $topic_edit_reason)); } /** No Errors *************************************************************/ if (!empty($topic_id) && !is_wp_error($topic_id)) { // Update counts, etc... do_action('bbp_edit_topic', $topic_id, $forum_id, $anonymous_data, $topic->post_author, true); // If the new forum id is not equal to the old forum id, run the // bbp_move_topic action and pass the topic's forum id as the // first arg and topic id as the second to update counts. if ($forum_id != $topic->post_parent) { bbp_move_topic_handler($topic_id, $topic->post_parent, $forum_id); } /** Additional Actions (After Save) ***********************************/ do_action('bbp_edit_topic_post_extras', $topic_id); /** Redirect **********************************************************/ // Redirect to $redirect_to = !empty($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : ''; // View all? $view_all = bbp_get_view_all(); // Get the topic URL $topic_url = bbp_get_topic_permalink($topic_id, $redirect_to); // Add view all? if (!empty($view_all)) { $topic_url = bbp_add_view_all($topic_url); } // Allow to be filtered $topic_url = apply_filters('bbp_edit_topic_redirect_to', $topic_url, $view_all, $redirect_to); /** Successful Edit ***************************************************/ // Redirect back to new topic wp_safe_redirect($topic_url); // For good measure exit; /** Errors ****************************************************************/ } else { $append_error = is_wp_error($topic_id) && $topic_id->get_error_message() ? $topic_id->get_error_message() . ' ' : ''; bbp_add_error('bbp_topic_error', __('<strong>ERROR</strong>: The following problem(s) have been found with your topic:' . $append_error . 'Please try again.', 'bbpress')); } }
/** * @covers ::bbp_forum_last_active_id * @covers ::bbp_get_forum_last_active_id */ public function test_bbp_get_forum_last_active_id_with_pending_reply() { $u = $this->factory->user->create_many(2); $c = $this->factory->forum->create(array('forum_meta' => array('forum_type' => 'category', 'status' => 'open'))); $f = $this->factory->forum->create(array('post_parent' => $c, 'forum_meta' => array('forum_id' => $c, 'forum_type' => 'forum', 'status' => 'open'))); // Get the forums last active id. $last_id = bbp_get_forum_last_active_id($f); $this->assertSame(0, $last_id); // Get the categories last active id. $last_id = bbp_get_forum_last_active_id($c); $this->assertSame(0, $last_id); bbp_update_forum_last_active_id($f); // Get the forums last active id. $last_id = bbp_get_forum_last_active_id($f); $this->assertSame(0, $last_id); // Get the categories last active id. $last_id = bbp_get_forum_last_active_id($c); $this->assertSame(0, $last_id); $t = $this->factory->topic->create(array('post_parent' => $f, 'topic_meta' => array('forum_id' => $f))); bbp_update_forum_last_active_id($f); // Get the forums last active id. $last_id = bbp_get_forum_last_active_id($f); $this->assertSame($t, $last_id); // Get the categories last active id. $last_id = bbp_get_forum_last_active_id($c); $this->assertSame($t, $last_id); $r1 = $this->factory->reply->create(array('post_parent' => $t, 'reply_meta' => array('forum_id' => $f, 'topic_id' => $t))); bbp_update_forum_last_active_id($f); // Get the forums last active id. $last_id = bbp_get_forum_last_active_id($f); $this->assertSame($r1, $last_id); // Get the categories last active id. $last_id = bbp_get_forum_last_active_id($c); $this->assertSame($r1, $last_id); $r2 = $this->factory->reply->create(array('post_parent' => $t, 'post_author' => $u[1], 'post_status' => bbp_get_pending_status_id(), 'reply_meta' => array('forum_id' => $f, 'topic_id' => $t))); // Get the forums last active id. $last_id = bbp_get_forum_last_active_id($f); $this->assertSame($r1, $last_id); // Get the categories last active id. $last_id = bbp_get_forum_last_active_id($c); $this->assertSame($r1, $last_id); bbp_approve_reply($r2); // Get the forums last active id. $last_id = bbp_get_forum_last_active_id($f); $this->assertSame($r2, $last_id); // Get the categories last active id. $last_id = bbp_get_forum_last_active_id($c); $this->assertSame($r2, $last_id); }
/** * Post new topic by email handler. * * For bbPress, the logic in this method is the same as {@link bbp_new_topic_handler()}. * It's duplicated because bbPress doesn't utilize hooks for verifying topics. * * @todo No fancy support for topic tags, subscriptions yet. Will probably need shortcodes. * * @param array $data { * An array of arguments. * * @type array $headers Email headers. * @type string $content The email body content. * @type string $subject The email subject line. * @type int $user_id The user ID who sent the email. * @type bool $is_html Whether the email content is HTML or not. * @type int $i The email message number. * } * @param array $params Parsed paramaters from the email address querystring. * See {@link BP_Reply_By_Email_Parser::get_parameters()}. * @return array|object Array of the parsed item on success. WP_Error object * on failure. */ private function post_new_topic($data, $params) { //private function post_new_topic( $connection, $i, $headers, $params, $body, $topic_author ) { /** SETUP DATA ***************************************************/ $i = $data['i']; $topic_author = $data['user_id']; $forum_id = $params[$this->forum_id_param]; /* current email is a bbPress new topic, let's proceed! */ // let RBE know that we're in the process of rendering a bbP new topic // BuddyPress group new topic if (!empty($params[$this->item_id_param])) { bp_rbe_log('Message #' . $i . ': this is a bbPress group forum new topic'); // bbPress } else { bp_rbe_log('Message #' . $i . ': this is a bbPress new topic'); } // other variables $anonymous_data = 0; /** GROUP PERMISSIONS ********************************************/ // posting from a BP group if (!empty($params[$this->item_id_param])) { global $bp; // set group ID and cache it in global for later use // $bp->rbe->temp->group_id gets passed to the set_group_id() method later on $group_id = $bp->rbe->temp->group_id = $params[$this->item_id_param]; // get all group member data for the user in one swoop! $group_member_data = bp_rbe_get_group_member_info($topic_author, $group_id); // user is not a member of the group anymore if (empty($group_member_data)) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'user_not_group_member' ); return new WP_Error('user_not_group_member', '', $data); } // user is banned from group if ((int) $group_member_data->is_banned == 1) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'user_banned_from_group' ); return new WP_Error('user_banned_from_group', '', $data); } // override groups_get_current_group() with our cached group ID add_filter('groups_get_current_group', array($this, 'set_group_id')); // temporarily add some GES filters here add_filter('bp_ass_activity_notification_subject', 'wp_specialchars_decode'); add_filter('bp_ass_activity_notification_content', 'wp_specialchars_decode'); } /** TOPIC / FORUM PERMISSIONS ************************************/ // Allow member to pass default cap checks. // The reason why we keep the user_can() checks below is b/c bbPress // plugins may disable cap access for a specific user if they have hooked into // the 'bbp_map_meta_caps' filter. add_filter('bbp_map_meta_caps', array($this, 'map_forum_meta_caps'), 5, 4); // User cannot create topics if (!user_can($topic_author, 'publish_topics')) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_topic_permissions' ); return new WP_Error('bbp_topic_permissions', '', $data); } // Forum is a category if (bbp_is_forum_category($forum_id)) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_edit_topic_forum_category' ); //bbp_add_error( 'bbp_edit_topic_forum_category', __( '<strong>ERROR</strong>: This forum is a category. No topics can be created in this forum.', 'bbpress' ) ); return new WP_Error('bbp_edit_topic_forum_category', '', $data); // Forum is not a category } else { // Forum is closed and user cannot access if (bbp_is_forum_closed($forum_id) && !user_can($topic_author, 'edit_forum')) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_edit_topic_forum_closed' ); //bbp_add_error( 'bbp_edit_topic_forum_closed', __( '<strong>ERROR</strong>: This forum has been closed to new topics.', 'bbpress' ) ); return new WP_Error('bbp_edit_topic_forum_closed', '', $data); } // Forum is private and user cannot access if (bbp_is_forum_private($forum_id)) { if (!user_can($topic_author, 'read_private_forums')) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_edit_topic_forum_private' ); //bbp_add_error( 'bbp_edit_topic_forum_private', __( '<strong>ERROR</strong>: This forum is private and you do not have the capability to read or create new topics in it.', 'bbpress' ) ); return new WP_Error('bbp_edit_topic_forum_private', '', $data); } } // Forum is hidden and user cannot access if (bbp_is_forum_hidden($forum_id)) { if (!user_can($topic_author, 'read_hidden_forums')) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_edit_topic_forum_hidden' ); //bbp_add_error( 'bbp_edit_topic_forum_hidden', __( '<strong>ERROR</strong>: This forum is hidden and you do not have the capability to read or create new topics in it.', 'bbpress' ) ); return new WP_Error('bbp_edit_topic_forum_hidden', '', $data); } } } /** UNFILTERED HTML **********************************************/ // Remove wp_filter_kses filters from title and content for capable users if (user_can($topic_author, 'unfiltered_html')) { remove_filter('bbp_new_topic_pre_title', 'wp_filter_kses'); remove_filter('bbp_new_topic_pre_content', 'wp_filter_kses'); } /** TOPIC DATA ***************************************************/ $topic_content = $data['content']; $topic_title = $data['subject']; bp_rbe_log('Message #' . $i . ': body contents - ' . $topic_content); bp_rbe_log('Subject - ' . $topic_title); if (empty($topic_content) || empty($topic_title)) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_new_forum_topic_empty' ); return new WP_Error('bbp_new_forum_topic_empty', '', $data); } // Filter and sanitize $topic_title = apply_filters('bbp_new_topic_pre_title', $topic_title); $topic_content = apply_filters('bbp_new_topic_pre_content', $topic_content); /** Topic Tags ****************************************************/ /* TODO if ( bbp_allow_topic_tags() ) { // Escape tag input $terms = esc_attr( strip_tags( $_POST['bbp_topic_tags'] ) ); // Explode by comma if ( strstr( $terms, ',' ) ) { $terms = explode( ',', $terms ); } // Add topic tag ID as main key $terms = array( bbp_get_topic_tag_tax_id() => $terms ); } */ /** TOPIC MODERATION *********************************************/ // Post Flooding if (!bbp_check_for_flood($anonymous_data, $topic_author)) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_topic_flood' ); //bbp_add_error( 'bbp_reply_flood', __( '<strong>ERROR</strong>: Slow down; you move too fast.', 'bbpress' ) ); return new WP_Error('bbp_topic_flood', '', $data); } // Topic Duplicate if (!bbp_check_for_duplicate(array('post_type' => bbp_get_topic_post_type(), 'post_author' => $topic_author, 'post_content' => $topic_content, 'anonymous_data' => $anonymous_data))) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_topic_duplicate' ); return new WP_Error('bbp_topic_duplicate', '', $data); } // Topic Blacklist if (!bbp_check_for_blacklist($anonymous_data, $topic_author, $topic_title, $topic_content)) { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_topic_blacklist' ); return new WP_Error('bbp_topic_blacklist', '', $data); } // Topic Status // Maybe put into moderation if (!bbp_check_for_moderation($anonymous_data, $topic_author, $topic_title, $topic_content)) { $topic_status = bbp_get_pending_status_id(); // Default } else { $topic_status = bbp_get_public_status_id(); } /** POSTING TIME! ************************************************/ // bbP hook before save do_action('bbp_new_topic_pre_extras', $forum_id); // Setup reply data $topic_data = apply_filters('bbp_new_topic_pre_insert', array('post_author' => $topic_author, 'post_title' => $topic_title, 'post_content' => $topic_content, 'post_status' => $topic_status, 'post_parent' => $forum_id, 'post_type' => bbp_get_topic_post_type(), 'comment_status' => 'closed')); // Insert topic $topic_id = wp_insert_post($topic_data); // Topic posted! if (!is_wp_error($topic_id)) { // more internal logging bp_rbe_log('Message #' . $i . ': bbPress topic successfully posted!'); // Problem posting } else { //do_action( 'bp_rbe_imap_no_match', $connection, $i, $headers, 'bbp_topic_error' ); return new WP_Error('bbp_topic_error', '', $data); } /** AFTER POSTING ************************************************/ // stuff that needs to happen after a bbP topic is posted occurs here... bbP // should preferably do the following at the 'bbp_new_reply' hook, until then // do what bbP does inline. // Trash Check //////////////////////////////////////////////////// // If the forum is trash, or the topic_status is switched to // trash, trash it properly if (get_post_field('post_status', $forum_id) == bbp_get_trash_status_id() || $topic_data['post_status'] == bbp_get_trash_status_id()) { // Trash the reply wp_trash_post($topic_id); } // Spam Check ///////////////////////////////////////////////////// // If reply or topic are spam, officially spam this reply if ($topic_data['post_status'] == bbp_get_spam_status_id()) { add_post_meta($topic_id, '_bbp_spam_meta_status', bbp_get_public_status_id()); } // Reply By Email ///////////////////////////////////////////////// // Add a RBE marker to the post's meta // Could potentially show that post was made via email on the frontend add_post_meta($topic_id, 'bp_rbe', 1); /** POST HOOKS ***************************************************/ // RBE Custom Hooks /////////////////////////////////////////////// // change activity action add_filter('bbp_before_record_activity_parse_args', array($this, 'change_activity_action')); // add RBE's special activity hook add_action('bp_activity_after_save', array($this, 'activity_rbe_hook')); // bbPress Topic Hooks //////////////////////////////////////////// do_action('bbp_new_topic', $topic_id, $forum_id, $anonymous_data, $topic_author); do_action('bbp_new_topic_post_extras', $topic_id); return array('bbp_topic_id' => $topic_id); }